summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/-ext-/arith_seq/test_arith_seq_beg_len_step.rb52
-rw-r--r--test/-ext-/bignum/test_big2str.rb38
-rw-r--r--test/-ext-/bignum/test_bigzero.rb20
-rw-r--r--test/-ext-/bignum/test_div.rb38
-rw-r--r--test/-ext-/bignum/test_mul.rb260
-rw-r--r--test/-ext-/bignum/test_pack.rb653
-rw-r--r--test/-ext-/bignum/test_str2big.rb52
-rw-r--r--test/-ext-/bug_reporter/test_bug_reporter.rb16
-rw-r--r--test/-ext-/debug/test_debug.rb2
-rw-r--r--test/-ext-/debug/test_profile_frames.rb89
-rw-r--r--test/-ext-/econv/test_append.rb23
-rw-r--r--test/-ext-/eval/test_eval.rb12
-rw-r--r--test/-ext-/float/test_nextafter.rb2
-rw-r--r--test/-ext-/funcall/test_funcall.rb11
-rw-r--r--test/-ext-/funcall/test_passing_block.rb5
-rw-r--r--test/-ext-/gvl/test_ubf_async_safe.rb2
-rw-r--r--test/-ext-/integer/test_my_integer.rb34
-rw-r--r--test/-ext-/iseq_load/test_iseq_load.rb8
-rw-r--r--test/-ext-/load/test_resolve_symbol.rb27
-rw-r--r--test/-ext-/load/test_stringify_symbols.rb35
-rw-r--r--test/-ext-/marshal/test_internal_ivar.rb2
-rw-r--r--test/-ext-/postponed_job/test_postponed_job.rb73
-rw-r--r--test/-ext-/required.rb10
-rw-r--r--test/-ext-/string/test_capacity.rb40
-rw-r--r--test/-ext-/string/test_cstr.rb6
-rw-r--r--test/-ext-/string/test_fstring.rb34
-rw-r--r--test/-ext-/string/test_rb_str_dup.rb6
-rw-r--r--test/-ext-/string/test_set_len.rb57
-rw-r--r--test/-ext-/string/test_too_many_dummy_encodings.rb15
-rw-r--r--test/-ext-/struct/test_data.rb18
-rw-r--r--test/-ext-/symbol/test_type.rb14
-rw-r--r--test/-ext-/test_abi.rb47
-rw-r--r--test/-ext-/test_bug-3571.rb4
-rw-r--r--test/-ext-/test_ensure_and_callcc.rb40
-rw-r--r--test/-ext-/test_random.rb26
-rw-r--r--test/-ext-/thread/helper.rb51
-rw-r--r--test/-ext-/thread/test_instrumentation_api.rb289
-rw-r--r--test/-ext-/thread/test_lock_native_thread.rb50
-rw-r--r--test/-ext-/thread_fd/test_thread_fd_close.rb1
-rw-r--r--test/-ext-/tracepoint/test_tracepoint.rb1
-rw-r--r--test/-ext-/wait/test_wait.rb16
-rw-r--r--test/.excludes-parsey/TestBugReporter.rb1
-rw-r--r--test/.excludes-parsey/TestM17N.rb1
-rw-r--r--test/.excludes-parsey/TestMixedUnicodeEscape.rb1
-rw-r--r--test/.excludes-parsey/TestRubyLiteral.rb1
-rw-r--r--test/.excludes-parsey/TestRubyOptions.rb10
-rw-r--r--test/.excludes/TestArray.rb (renamed from test/excludes/TestArray.rb)0
-rw-r--r--test/.excludes/TestArraySubclass.rb1
-rw-r--r--test/.excludes/TestException.rb (renamed from test/excludes/TestException.rb)0
-rw-r--r--test/.excludes/TestGem.rb4
-rw-r--r--test/.excludes/TestIO_Console.rb (renamed from test/excludes/TestIO_Console.rb)0
-rw-r--r--test/.excludes/TestISeq.rb (renamed from test/excludes/TestISeq.rb)0
-rw-r--r--test/.excludes/TestThread.rb18
-rw-r--r--test/.excludes/TestThreadQueue.rb9
-rw-r--r--test/.excludes/_appveyor/TestArray.rb (renamed from test/excludes/_appveyor/TestArray.rb)0
-rw-r--r--test/base64/test_base64.rb115
-rw-r--r--test/bigdecimal/helper.rb28
-rw-r--r--test/bigdecimal/test_bigdecimal.rb2120
-rw-r--r--test/bigdecimal/test_bigdecimal_util.rb126
-rw-r--r--test/bigdecimal/test_bigmath.rb81
-rw-r--r--test/bigdecimal/test_ractor.rb23
-rw-r--r--test/cgi/test_cgi_cookie.rb90
-rw-r--r--test/cgi/test_cgi_header.rb8
-rw-r--r--test/cgi/test_cgi_util.rb98
-rw-r--r--test/coverage/autostart.rb2
-rw-r--r--test/coverage/main.rb1
-rw-r--r--test/coverage/test_coverage.rb278
-rw-r--r--test/csv/helper.rb42
-rw-r--r--test/csv/interface/test_delegation.rb47
-rw-r--r--test/csv/interface/test_read.rb339
-rw-r--r--test/csv/interface/test_read_write.rb115
-rw-r--r--test/csv/interface/test_write.rb174
-rw-r--r--test/csv/line_endings.gzbin59 -> 0 bytes
-rw-r--r--test/csv/parse/test_column_separator.rb40
-rw-r--r--test/csv/parse/test_convert.rb110
-rw-r--r--test/csv/parse/test_each.rb23
-rw-r--r--test/csv/parse/test_general.rb259
-rw-r--r--test/csv/parse/test_header.rb335
-rw-r--r--test/csv/parse/test_invalid.rb39
-rw-r--r--test/csv/parse/test_liberal_parsing.rb160
-rw-r--r--test/csv/parse/test_quote_char_nil.rb93
-rw-r--r--test/csv/parse/test_rewind.rb40
-rw-r--r--test/csv/parse/test_row_separator.rb16
-rw-r--r--test/csv/parse/test_skip_lines.rb118
-rw-r--r--test/csv/parse/test_strip.rb83
-rw-r--r--test/csv/parse/test_unconverted_fields.rb117
-rw-r--r--test/csv/test_data_converters.rb106
-rw-r--r--test/csv/test_encodings.rb372
-rw-r--r--test/csv/test_features.rb359
-rw-r--r--test/csv/test_row.rb435
-rw-r--r--test/csv/test_table.rb620
-rw-r--r--test/csv/write/test_converters.rb53
-rw-r--r--test/csv/write/test_force_quotes.rb78
-rw-r--r--test/csv/write/test_general.rb246
-rw-r--r--test/csv/write/test_quote_empty.rb70
-rw-r--r--test/date/test_date.rb29
-rw-r--r--test/date/test_date_conv.rb17
-rw-r--r--test/date/test_date_parse.rb73
-rw-r--r--test/date/test_date_ractor.rb2
-rw-r--r--test/date/test_date_strftime.rb4
-rw-r--r--test/date/test_date_strptime.rb9
-rw-r--r--test/did_you_mean/core_ext/test_name_error_extension.rb27
-rw-r--r--test/did_you_mean/helper.rb14
-rw-r--r--test/did_you_mean/spell_checking/test_key_name_check.rb14
-rw-r--r--test/did_you_mean/spell_checking/test_method_name_check.rb38
-rw-r--r--test/did_you_mean/spell_checking/test_pattern_key_name_check.rb20
-rw-r--r--test/did_you_mean/spell_checking/test_require_path_check.rb6
-rw-r--r--test/did_you_mean/spell_checking/test_variable_name_check.rb36
-rw-r--r--test/did_you_mean/test_ractor_compatibility.rb117
-rw-r--r--test/did_you_mean/test_spell_checker.rb1
-rw-r--r--test/did_you_mean/test_verbose_formatter.rb23
-rw-r--r--test/digest/test_digest_extend.rb13
-rw-r--r--test/digest/test_ractor.rb6
-rw-r--r--test/drb/drbtest.rb394
-rw-r--r--test/drb/ignore_test_drb.rb14
-rw-r--r--test/drb/test_acl.rb207
-rw-r--r--test/drb/test_drb.rb370
-rw-r--r--test/drb/test_drbobject.rb69
-rw-r--r--test/drb/test_drbssl.rb72
-rw-r--r--test/drb/test_drbunix.rb60
-rw-r--r--test/drb/ut_array.rb17
-rw-r--r--test/drb/ut_array_drbssl.rb39
-rw-r--r--test/drb/ut_array_drbunix.rb17
-rw-r--r--test/drb/ut_drb.rb189
-rw-r--r--test/drb/ut_drb_drbssl.rb40
-rw-r--r--test/drb/ut_drb_drbunix.rb18
-rw-r--r--test/drb/ut_eq.rb37
-rw-r--r--test/drb/ut_large.rb62
-rw-r--r--test/drb/ut_port.rb16
-rw-r--r--test/drb/ut_safe1.rb17
-rw-r--r--test/drb/ut_timerholder.rb74
-rw-r--r--test/dtrace/helper.rb2
-rw-r--r--test/erb/test_erb.rb30
-rw-r--r--test/erb/test_erb_command.rb18
-rw-r--r--test/error_highlight/test_error_highlight.rb333
-rw-r--r--test/excludes/TestThread.rb2
-rw-r--r--test/fiber/autoload.rb3
-rw-r--r--test/fiber/scheduler.rb255
-rw-r--r--test/fiber/test_address_resolve.rb4
-rw-r--r--test/fiber/test_enumerator.rb16
-rw-r--r--test/fiber/test_io.rb163
-rw-r--r--test/fiber/test_io_buffer.rb199
-rw-r--r--test/fiber/test_mutex.rb24
-rw-r--r--test/fiber/test_process.rb42
-rw-r--r--test/fiber/test_queue.rb54
-rw-r--r--test/fiber/test_ractor.rb2
-rw-r--r--test/fiber/test_scheduler.rb79
-rw-r--r--test/fiber/test_storage.rb115
-rw-r--r--test/fiber/test_thread.rb22
-rw-r--r--test/fiddle/helper.rb10
-rw-r--r--test/fiddle/test_c_struct_entry.rb8
-rw-r--r--test/fiddle/test_closure.rb123
-rw-r--r--test/fiddle/test_cparser.rb40
-rw-r--r--test/fiddle/test_fiddle.rb41
-rw-r--r--test/fiddle/test_func.rb53
-rw-r--r--test/fiddle/test_function.rb34
-rw-r--r--test/fiddle/test_handle.rb10
-rw-r--r--test/fiddle/test_import.rb23
-rw-r--r--test/fiddle/test_pack.rb37
-rw-r--r--test/fiddle/test_pointer.rb19
-rw-r--r--test/fileutils/clobber.rb5
-rw-r--r--test/fileutils/test_dryrun.rb2
-rw-r--r--test/fileutils/test_fileutils.rb115
-rw-r--r--test/fileutils/test_nowrite.rb2
-rw-r--r--test/fileutils/test_verbose.rb2
-rw-r--r--test/fileutils/visibility_tests.rb5
-rw-r--r--test/io/console/test_io_console.rb66
-rw-r--r--test/io/console/test_ractor.rb34
-rw-r--r--test/io/nonblock/test_flush.rb2
-rw-r--r--test/io/wait/test_io_wait.rb37
-rw-r--r--test/io/wait/test_io_wait_uncommon.rb5
-rw-r--r--test/io/wait/test_ractor.rb7
-rw-r--r--test/irb/command/test_cd.rb65
-rw-r--r--test/irb/command/test_custom_command.rb194
-rw-r--r--test/irb/command/test_disable_irb.rb28
-rw-r--r--test/irb/command/test_force_exit.rb51
-rw-r--r--test/irb/command/test_help.rb75
-rw-r--r--test/irb/command/test_multi_irb_commands.rb50
-rw-r--r--test/irb/command/test_show_source.rb397
-rw-r--r--test/irb/helper.rb234
-rw-r--r--test/irb/test_cmd.rb529
-rw-r--r--test/irb/test_color.rb117
-rw-r--r--test/irb/test_color_printer.rb23
-rw-r--r--test/irb/test_command.rb958
-rw-r--r--test/irb/test_completion.rb346
-rw-r--r--test/irb/test_context.rb738
-rw-r--r--test/irb/test_debugger_integration.rb496
-rw-r--r--test/irb/test_eval_history.rb69
-rw-r--r--test/irb/test_evaluation.rb44
-rw-r--r--test/irb/test_helper_method.rb134
-rw-r--r--test/irb/test_history.rb407
-rw-r--r--test/irb/test_init.rb331
-rw-r--r--test/irb/test_input_method.rb195
-rw-r--r--test/irb/test_irb.rb936
-rw-r--r--test/irb/test_locale.rb118
-rw-r--r--test/irb/test_nesting_parser.rb338
-rw-r--r--test/irb/test_option.rb4
-rw-r--r--test/irb/test_raise_exception.rb74
-rw-r--r--test/irb/test_raise_no_backtrace_exception.rb54
-rw-r--r--test/irb/test_ruby_lex.rb768
-rw-r--r--test/irb/test_tracer.rb90
-rw-r--r--test/irb/test_type_completor.rb93
-rw-r--r--test/irb/test_workspace.rb10
-rw-r--r--test/irb/yamatanooroti/test_rendering.rb679
-rw-r--r--test/json/json_addition_test.rb8
-rw-r--r--test/json/json_common_interface_test.rb34
-rw-r--r--test/json/json_encoding_test.rb9
-rw-r--r--test/json/json_ext_parser_test.rb21
-rw-r--r--test/json/json_fixtures_test.rb2
-rwxr-xr-x[-rw-r--r--]test/json/json_generator_test.rb67
-rw-r--r--test/json/json_generic_object_test.rb4
-rw-r--r--test/json/json_parser_test.rb86
-rw-r--r--test/json/json_string_matching_test.rb2
-rw-r--r--test/json/ractor_test.rb8
-rw-r--r--test/lib/!Nothing_to_test.rb5
-rw-r--r--test/lib/jit_support.rb92
-rw-r--r--test/lib/parser_support.rb20
-rw-r--r--test/logger/test_formatter.rb35
-rw-r--r--test/logger/test_logdevice.rb3
-rw-r--r--test/logger/test_logger.rb15
-rw-r--r--test/logger/test_logperiod.rb83
-rw-r--r--test/logger/test_severity.rb32
-rw-r--r--test/mkmf/base.rb233
-rw-r--r--test/mkmf/test_config.rb62
-rw-r--r--test/mkmf/test_configuration.rb39
-rw-r--r--test/mkmf/test_constant.rb60
-rw-r--r--test/mkmf/test_convertible.rb48
-rw-r--r--test/mkmf/test_egrep_cpp.rb14
-rw-r--r--test/mkmf/test_find_executable.rb82
-rw-r--r--test/mkmf/test_flags.rb92
-rw-r--r--test/mkmf/test_framework.rb70
-rw-r--r--test/mkmf/test_have_func.rb18
-rw-r--r--test/mkmf/test_have_library.rb84
-rw-r--r--test/mkmf/test_have_macro.rb46
-rw-r--r--test/mkmf/test_have_var.rb17
-rw-r--r--test/mkmf/test_install.rb38
-rw-r--r--test/mkmf/test_libs.rb156
-rw-r--r--test/mkmf/test_mkmf.rb14
-rw-r--r--test/mkmf/test_pkg_config.rb66
-rw-r--r--test/mkmf/test_signedness.rb38
-rw-r--r--test/mkmf/test_sizeof.rb74
-rw-r--r--test/monitor/test_monitor.rb2
-rw-r--r--test/net/fixtures/Makefile6
-rw-r--r--test/net/fixtures/cacert.pem44
-rw-r--r--test/net/fixtures/server.crt99
-rw-r--r--test/net/fixtures/server.key55
-rw-r--r--test/net/http/test_http.rb182
-rw-r--r--test/net/http/test_http_request.rb5
-rw-r--r--test/net/http/test_httpheader.rb27
-rw-r--r--test/net/http/test_httpresponse.rb287
-rw-r--r--test/net/http/test_https.rb83
-rw-r--r--test/net/http/test_https_proxy.rb51
-rw-r--r--test/net/http/utils.rb357
-rw-r--r--test/net/protocol/test_protocol.rb37
-rw-r--r--test/nkf/test_kconv.rb82
-rw-r--r--test/nkf/test_nkf.rb23
-rw-r--r--test/objspace/test_objspace.rb370
-rw-r--r--test/objspace/test_ractor.rb17
-rw-r--r--test/open-uri/test_ftp.rb216
-rw-r--r--test/open-uri/test_open-uri.rb621
-rw-r--r--test/open-uri/test_proxy.rb174
-rw-r--r--test/open-uri/test_ssl.rb446
-rw-r--r--test/open-uri/utils.rb738
-rw-r--r--test/openssl/fixtures/pkey/dh1024.pem5
-rw-r--r--test/openssl/fixtures/pkey/dh2048_ffdhe2048.pem8
-rw-r--r--test/openssl/fixtures/pkey/dsa2048.pem15
-rw-r--r--test/openssl/fixtures/pkey/p256_too_large.pem5
-rw-r--r--test/openssl/fixtures/pkey/p384_invalid.pem6
-rw-r--r--test/openssl/test_asn1.rb24
-rw-r--r--test/openssl/test_bn.rb37
-rw-r--r--test/openssl/test_cipher.rb37
-rw-r--r--test/openssl/test_config.rb28
-rw-r--r--test/openssl/test_digest.rb24
-rw-r--r--test/openssl/test_engine.rb38
-rw-r--r--test/openssl/test_fips.rb40
-rw-r--r--test/openssl/test_hmac.rb8
-rw-r--r--test/openssl/test_ns_spki.rb8
-rw-r--r--test/openssl/test_ocsp.rb4
-rw-r--r--test/openssl/test_ossl.rb21
-rw-r--r--test/openssl/test_pair.rb46
-rw-r--r--test/openssl/test_pkcs12.rb326
-rw-r--r--test/openssl/test_pkcs7.rb21
-rw-r--r--test/openssl/test_pkey.rb86
-rw-r--r--test/openssl/test_pkey_dh.rb112
-rw-r--r--test/openssl/test_pkey_dsa.rb71
-rw-r--r--test/openssl/test_pkey_ec.rb159
-rw-r--r--test/openssl/test_pkey_rsa.rb388
-rw-r--r--test/openssl/test_provider.rb83
-rw-r--r--test/openssl/test_ssl.rb569
-rw-r--r--test/openssl/test_ssl_session.rb12
-rw-r--r--test/openssl/test_ts.rb20
-rw-r--r--test/openssl/test_x509attr.rb4
-rw-r--r--test/openssl/test_x509cert.rb36
-rw-r--r--test/openssl/test_x509crl.rb20
-rw-r--r--test/openssl/test_x509ext.rb37
-rw-r--r--test/openssl/test_x509req.rb30
-rw-r--r--test/openssl/ut_eof.rb4
-rw-r--r--test/openssl/utils.rb103
-rw-r--r--test/optparse/test_acceptable.rb9
-rw-r--r--test/optparse/test_autoconf.rb4
-rw-r--r--test/optparse/test_bash_completion.rb4
-rw-r--r--test/optparse/test_cclass.rb2
-rw-r--r--test/optparse/test_did_you_mean.rb22
-rw-r--r--test/optparse/test_getopts.rb20
-rw-r--r--test/optparse/test_kwargs.rb4
-rw-r--r--test/optparse/test_load.rb141
-rw-r--r--test/optparse/test_noarg.rb6
-rw-r--r--test/optparse/test_optarg.rb18
-rw-r--r--test/optparse/test_optparse.rb116
-rw-r--r--test/optparse/test_placearg.rb28
-rw-r--r--test/optparse/test_reqarg.rb16
-rw-r--r--test/optparse/test_summary.rb25
-rw-r--r--test/optparse/test_zsh_completion.rb4
-rw-r--r--test/ostruct/test_ostruct.rb38
-rw-r--r--test/pathname/test_pathname.rb31
-rw-r--r--test/prism/api/command_line_test.rb111
-rw-r--r--test/prism/api/dump_test.rb56
-rw-r--r--test/prism/api/lex_test.rb23
-rw-r--r--test/prism/api/parse_comments_test.rb33
-rw-r--r--test/prism/api/parse_stream_test.rb81
-rw-r--r--test/prism/api/parse_success_test.rb16
-rw-r--r--test/prism/api/parse_test.rb117
-rw-r--r--test/prism/bom_test.rb59
-rw-r--r--test/prism/encoding/encodings_test.rb101
-rw-r--r--test/prism/encoding/regular_expression_encoding_test.rb131
-rw-r--r--test/prism/encoding/string_encoding_test.rb136
-rw-r--r--test/prism/encoding/symbol_encoding_test.rb108
-rw-r--r--test/prism/errors/1_2_3.txt11
-rw-r--r--test/prism/errors/aliasing_global_variable_with_global_number_variable.txt3
-rw-r--r--test/prism/errors/aliasing_global_variable_with_non_global_variable.txt3
-rw-r--r--test/prism/errors/aliasing_non_global_variable_with_global_variable.txt3
-rw-r--r--test/prism/errors/alnum_delimiters.txt3
-rw-r--r--test/prism/errors/alnum_delimiters_2.txt3
-rw-r--r--test/prism/errors/alnum_delimiters_3.txt3
-rw-r--r--test/prism/errors/alnum_delimiters_4.txt3
-rw-r--r--test/prism/errors/alnum_delimiters_5.txt3
-rw-r--r--test/prism/errors/alnum_delimiters_6.txt3
-rw-r--r--test/prism/errors/alnum_delimiters_7.txt3
-rw-r--r--test/prism/errors/alnum_delimiters_8.txt3
-rw-r--r--test/prism/errors/alnum_delimiters_9.txt3
-rw-r--r--test/prism/errors/argument_after_ellipsis.txt3
-rw-r--r--test/prism/errors/argument_forwarding_only_effects_its_own_internals.txt3
-rw-r--r--test/prism/errors/argument_forwarding_when_parent_is_not_forwarding.txt3
-rw-r--r--test/prism/errors/arguments_after_block.txt3
-rw-r--r--test/prism/errors/arguments_binding_power_for_and.txt5
-rw-r--r--test/prism/errors/assign_to_numbered_parameter.txt11
-rw-r--r--test/prism/errors/bad_arguments.txt6
-rw-r--r--test/prism/errors/begin_at_toplevel.txt3
-rw-r--r--test/prism/errors/binary_range_with_left_unary_range.txt7
-rw-r--r--test/prism/errors/block_arg_and_block.txt3
-rw-r--r--test/prism/errors/block_beginning_with_brace_and_ending_with_end.txt6
-rw-r--r--test/prism/errors/break_1.txt4
-rw-r--r--test/prism/errors/break_1_2_3.txt8
-rw-r--r--test/prism/errors/call_with_block_and_write.txt4
-rw-r--r--test/prism/errors/call_with_block_operator_write.txt4
-rw-r--r--test/prism/errors/call_with_block_or_write.txt4
-rw-r--r--test/prism/errors/cannot_assign_to_a_reserved_numbered_parameter.txt14
-rw-r--r--test/prism/errors/case_without_clauses.txt4
-rw-r--r--test/prism/errors/case_without_when_clauses_errors_on_else_clause.txt5
-rw-r--r--test/prism/errors/check_value_expression.txt20
-rw-r--r--test/prism/errors/class_definition_in_method_body.txt3
-rw-r--r--test/prism/errors/class_definition_in_method_defs.txt7
-rw-r--r--test/prism/errors/class_name.txt3
-rw-r--r--test/prism/errors/command_call_in.txt7
-rw-r--r--test/prism/errors/command_calls.txt3
-rw-r--r--test/prism/errors/command_calls_10.txt3
-rw-r--r--test/prism/errors/command_calls_11.txt3
-rw-r--r--test/prism/errors/command_calls_12.txt3
-rw-r--r--test/prism/errors/command_calls_13.txt3
-rw-r--r--test/prism/errors/command_calls_14.txt3
-rw-r--r--test/prism/errors/command_calls_15.txt3
-rw-r--r--test/prism/errors/command_calls_16.txt3
-rw-r--r--test/prism/errors/command_calls_17.txt5
-rw-r--r--test/prism/errors/command_calls_18.txt3
-rw-r--r--test/prism/errors/command_calls_19.txt3
-rw-r--r--test/prism/errors/command_calls_2.txt6
-rw-r--r--test/prism/errors/command_calls_20.txt3
-rw-r--r--test/prism/errors/command_calls_21.txt5
-rw-r--r--test/prism/errors/command_calls_22.txt3
-rw-r--r--test/prism/errors/command_calls_23.txt3
-rw-r--r--test/prism/errors/command_calls_24.txt5
-rw-r--r--test/prism/errors/command_calls_25.txt8
-rw-r--r--test/prism/errors/command_calls_26.txt3
-rw-r--r--test/prism/errors/command_calls_27.txt3
-rw-r--r--test/prism/errors/command_calls_28.txt3
-rw-r--r--test/prism/errors/command_calls_29.txt3
-rw-r--r--test/prism/errors/command_calls_3.txt3
-rw-r--r--test/prism/errors/command_calls_30.txt3
-rw-r--r--test/prism/errors/command_calls_4.txt3
-rw-r--r--test/prism/errors/command_calls_5.txt3
-rw-r--r--test/prism/errors/command_calls_6.txt6
-rw-r--r--test/prism/errors/command_calls_7.txt6
-rw-r--r--test/prism/errors/command_calls_8.txt6
-rw-r--r--test/prism/errors/command_calls_9.txt6
-rw-r--r--test/prism/errors/conditional_predicate_closed.txt6
-rw-r--r--test/prism/errors/constant_assignment_in_method.txt3
-rw-r--r--test/prism/errors/constant_path_with_invalid_token_after.txt4
-rw-r--r--test/prism/errors/content_after_unterminated_heredoc.txt4
-rw-r--r--test/prism/errors/cr_without_lf_in_percent_expression.txt3
-rw-r--r--test/prism/errors/def_with_empty_expression_receiver.txt3
-rw-r--r--test/prism/errors/def_with_expression_receiver_and_no_identifier.txt4
-rw-r--r--test/prism/errors/def_with_multiple_statements_receiver.txt10
-rw-r--r--test/prism/errors/defining_numbered_parameter.txt3
-rw-r--r--test/prism/errors/defining_numbered_parameter_2.txt3
-rw-r--r--test/prism/errors/do_not_allow_characters_other_than_0_9_a_f_and_A_F_in_u_Unicode_character_notation.txt4
-rw-r--r--test/prism/errors/do_not_allow_forward_arguments_in_blocks.txt3
-rw-r--r--test/prism/errors/do_not_allow_forward_arguments_in_lambda_literals.txt3
-rw-r--r--test/prism/errors/do_not_allow_more_than_6_hexadecimal_digits_in_u_Unicode_character_notation.txt3
-rw-r--r--test/prism/errors/do_not_allow_multiple_codepoints_in_a_single_character_literal.txt3
-rw-r--r--test/prism/errors/do_not_allow_trailing_commas_in_lambda_parameters.txt3
-rw-r--r--test/prism/errors/do_not_allow_trailing_commas_in_method_parameters.txt3
-rw-r--r--test/prism/errors/dont_allow_return_inside_class_body.txt3
-rw-r--r--test/prism/errors/dont_allow_return_inside_module_body.txt3
-rw-r--r--test/prism/errors/dont_allow_return_inside_sclass_body.txt3
-rw-r--r--test/prism/errors/dont_allow_setting_to_back_and_nth_reference.txt7
-rw-r--r--test/prism/errors/double_arguments_forwarding.txt4
-rw-r--r--test/prism/errors/double_scope_numbered_parameters.txt3
-rw-r--r--test/prism/errors/double_splat_followed_by_splat_argument.txt3
-rw-r--r--test/prism/errors/duplicate_pattern_capture.txt17
-rw-r--r--test/prism/errors/duplicate_pattern_hash_key.txt4
-rw-r--r--test/prism/errors/duplicate_pattern_hash_key_2.txt3
-rw-r--r--test/prism/errors/duplicated_parameter_names.txt3
-rw-r--r--test/prism/errors/duplicated_parameter_names_2.txt3
-rw-r--r--test/prism/errors/duplicated_parameter_names_3.txt3
-rw-r--r--test/prism/errors/duplicated_parameter_names_4.txt3
-rw-r--r--test/prism/errors/duplicated_parameter_names_5.txt3
-rw-r--r--test/prism/errors/ellipsis_in_no_paren_call.txt3
-rw-r--r--test/prism/errors/for_loops_index_missing.txt5
-rw-r--r--test/prism/errors/for_loops_only_end.txt5
-rw-r--r--test/prism/errors/forwarding_arg_after_keyword_rest.txt3
-rw-r--r--test/prism/errors/forwarding_arg_and_block.txt3
-rw-r--r--test/prism/errors/incomplete_instance_var_string.txt4
-rw-r--r--test/prism/errors/index_call_with_block_and_write.txt5
-rw-r--r--test/prism/errors/index_call_with_block_operator_write.txt5
-rw-r--r--test/prism/errors/index_call_with_block_or_write.txt5
-rw-r--r--test/prism/errors/interpolated_regular_expression_with_unknown_regexp_options.txt3
-rw-r--r--test/prism/errors/invalid_global_variable_write.txt4
-rw-r--r--test/prism/errors/invalid_hex_escape.txt3
-rw-r--r--test/prism/errors/invalid_multi_target.txt3
-rw-r--r--test/prism/errors/invalid_multi_target_10.txt3
-rw-r--r--test/prism/errors/invalid_multi_target_11.txt3
-rw-r--r--test/prism/errors/invalid_multi_target_12.txt3
-rw-r--r--test/prism/errors/invalid_multi_target_13.txt3
-rw-r--r--test/prism/errors/invalid_multi_target_14.txt3
-rw-r--r--test/prism/errors/invalid_multi_target_15.txt3
-rw-r--r--test/prism/errors/invalid_multi_target_16.txt3
-rw-r--r--test/prism/errors/invalid_multi_target_17.txt3
-rw-r--r--test/prism/errors/invalid_multi_target_18.txt3
-rw-r--r--test/prism/errors/invalid_multi_target_19.txt3
-rw-r--r--test/prism/errors/invalid_multi_target_2.txt3
-rw-r--r--test/prism/errors/invalid_multi_target_20.txt3
-rw-r--r--test/prism/errors/invalid_multi_target_3.txt3
-rw-r--r--test/prism/errors/invalid_multi_target_4.txt3
-rw-r--r--test/prism/errors/invalid_multi_target_5.txt3
-rw-r--r--test/prism/errors/invalid_multi_target_6.txt3
-rw-r--r--test/prism/errors/invalid_multi_target_7.txt3
-rw-r--r--test/prism/errors/invalid_multi_target_8.txt4
-rw-r--r--test/prism/errors/invalid_multi_target_9.txt4
-rw-r--r--test/prism/errors/invalid_number_underscores.txt3
-rw-r--r--test/prism/errors/invalid_number_underscores_10.txt3
-rw-r--r--test/prism/errors/invalid_number_underscores_11.txt3
-rw-r--r--test/prism/errors/invalid_number_underscores_12.txt3
-rw-r--r--test/prism/errors/invalid_number_underscores_2.txt3
-rw-r--r--test/prism/errors/invalid_number_underscores_3.txt3
-rw-r--r--test/prism/errors/invalid_number_underscores_4.txt3
-rw-r--r--test/prism/errors/invalid_number_underscores_5.txt3
-rw-r--r--test/prism/errors/invalid_number_underscores_6.txt3
-rw-r--r--test/prism/errors/invalid_number_underscores_7.txt3
-rw-r--r--test/prism/errors/invalid_number_underscores_8.txt3
-rw-r--r--test/prism/errors/invalid_number_underscores_9.txt3
-rw-r--r--test/prism/errors/invalid_operator_write_dot.txt3
-rw-r--r--test/prism/errors/invalid_operator_write_fcall.txt3
-rw-r--r--test/prism/errors/it_with_ordinary_parameter.txt3
-rw-r--r--test/prism/errors/keywords_parameters_before_required_parameters.txt4
-rw-r--r--test/prism/errors/loop_conditional_is_closed.txt4
-rw-r--r--test/prism/errors/match_plus.txt7
-rw-r--r--test/prism/errors/method_parameters_after_arguments_forwarding.txt4
-rw-r--r--test/prism/errors/method_parameters_after_block.txt4
-rw-r--r--test/prism/errors/method_with_arguments_after_anonymous_block.txt4
-rw-r--r--test/prism/errors/missing_terminator_in_parentheses.txt3
-rw-r--r--test/prism/errors/module_definition_in_method_body.txt3
-rw-r--r--test/prism/errors/module_definition_in_method_body_within_block.txt7
-rw-r--r--test/prism/errors/module_definition_in_method_defs.txt7
-rw-r--r--test/prism/errors/module_name_recoverable.txt4
-rw-r--r--test/prism/errors/multiple_error_in_parameters_order.txt5
-rw-r--r--test/prism/errors/next_1.txt4
-rw-r--r--test/prism/errors/next_1_2_3.txt8
-rw-r--r--test/prism/errors/non_assoc_equality.txt19
-rw-r--r--test/prism/errors/non_assoc_range.txt4
-rw-r--r--test/prism/errors/numbered_parameters_in_block_arguments.txt3
-rw-r--r--test/prism/errors/optional_block_parameters_with_unary_operator.txt3
-rw-r--r--test/prism/errors/optional_block_parameters_with_unary_operator_2.txt3
-rw-r--r--test/prism/errors/optional_block_parameters_with_unary_operator_3.txt3
-rw-r--r--test/prism/errors/optional_block_parameters_with_unary_operator_4.txt3
-rw-r--r--test/prism/errors/parameter_name_ending_with_bang_or_question_mark.txt4
-rw-r--r--test/prism/errors/pre_execution_context.txt4
-rw-r--r--test/prism/errors/pre_execution_missing_brace.txt3
-rw-r--r--test/prism/errors/range_and_bin_op.txt4
-rw-r--r--test/prism/errors/range_and_bin_op_2.txt4
-rw-r--r--test/prism/errors/range_and_bin_op_3.txt3
-rw-r--r--test/prism/errors/range_and_bin_op_4.txt4
-rw-r--r--test/prism/errors/range_and_bin_op_5.txt5
-rw-r--r--test/prism/errors/range_and_bin_op_6.txt3
-rw-r--r--test/prism/errors/range_and_bin_op_7.txt3
-rw-r--r--test/prism/errors/range_and_bin_op_8.txt4
-rw-r--r--test/prism/errors/rational_number_with_exponential_portion.txt4
-rw-r--r--test/prism/errors/regexp_unicode_too_short.txt4
-rw-r--r--test/prism/errors/regular_expression_with_unknown_regexp_options.txt3
-rw-r--r--test/prism/errors/repeated_parameter_name_in_destructured_params.txt3
-rw-r--r--test/prism/errors/rest_keywords_parameters_before_required_parameters.txt4
-rw-r--r--test/prism/errors/return_1.txt3
-rw-r--r--test/prism/errors/return_1_2_3.txt7
-rw-r--r--test/prism/errors/returning_to_optional_parameters_multiple_times.txt4
-rw-r--r--test/prism/errors/semicolon_after_inheritance_operator.txt3
-rw-r--r--test/prism/errors/setter_method_cannot_be_defined_in_an_endless_method_definition.txt3
-rw-r--r--test/prism/errors/shadow_args_in_block.txt3
-rw-r--r--test/prism/errors/shadow_args_in_lambda.txt5
-rw-r--r--test/prism/errors/singleton_method_for_literals.txt39
-rw-r--r--test/prism/errors/splat_argument_after_keyword_argument.txt3
-rw-r--r--test/prism/errors/statement_at_non_statement.txt9
-rw-r--r--test/prism/errors/statement_operators.txt25
-rw-r--r--test/prism/errors/switching_to_named_arguments_twice.txt5
-rw-r--r--test/prism/errors/switching_to_optional_arguments_twice.txt5
-rw-r--r--test/prism/errors/symbol_in_hash.txt3
-rw-r--r--test/prism/errors/symbol_in_keyword_parameter.txt3
-rw-r--r--test/prism/errors/targeting_numbered_parameter.txt3
-rw-r--r--test/prism/errors/top_level_constant_starting_with_downcased_identifier.txt4
-rw-r--r--test/prism/errors/top_level_constant_with_downcased_identifier.txt4
-rw-r--r--test/prism/errors/trailing_comma_in_calls.txt3
-rw-r--r--test/prism/errors/unexpected_block.txt3
-rw-r--r--test/prism/errors/unterminated_W_list.txt3
-rw-r--r--test/prism/errors/unterminated_argument_expression.txt5
-rw-r--r--test/prism/errors/unterminated_embdoc.txt3
-rw-r--r--test/prism/errors/unterminated_embdoc_2.txt3
-rw-r--r--test/prism/errors/unterminated_empty_string.txt3
-rw-r--r--test/prism/errors/unterminated_global_variable.txt3
-rw-r--r--test/prism/errors/unterminated_global_variable_2.txt3
-rw-r--r--test/prism/errors/unterminated_i_list.txt3
-rw-r--r--test/prism/errors/unterminated_interpolated_string.txt3
-rw-r--r--test/prism/errors/unterminated_interpolated_symbol.txt3
-rw-r--r--test/prism/errors/unterminated_parenthesized_expression.txt4
-rw-r--r--test/prism/errors/unterminated_regular_expression.txt3
-rw-r--r--test/prism/errors/unterminated_regular_expression_with_heredoc.txt4
-rw-r--r--test/prism/errors/unterminated_s_symbol.txt3
-rw-r--r--test/prism/errors/unterminated_string.txt3
-rw-r--r--test/prism/errors/unterminated_unicode_brackets_should_be_a_syntax_error.txt3
-rw-r--r--test/prism/errors/unterminated_xstring.txt3
-rw-r--r--test/prism/errors/void_value_expression_in_arguments.txt17
-rw-r--r--test/prism/errors/void_value_expression_in_array.txt15
-rw-r--r--test/prism/errors/void_value_expression_in_assignment.txt9
-rw-r--r--test/prism/errors/void_value_expression_in_begin_statement.txt21
-rw-r--r--test/prism/errors/void_value_expression_in_binary_call.txt11
-rw-r--r--test/prism/errors/void_value_expression_in_call.txt11
-rw-r--r--test/prism/errors/void_value_expression_in_constant_path.txt5
-rw-r--r--test/prism/errors/void_value_expression_in_def.txt10
-rw-r--r--test/prism/errors/void_value_expression_in_expression.txt19
-rw-r--r--test/prism/errors/void_value_expression_in_hash.txt9
-rw-r--r--test/prism/errors/void_value_expression_in_modifier.txt13
-rw-r--r--test/prism/errors/void_value_expression_in_statement.txt26
-rw-r--r--test/prism/errors/void_value_expression_in_unary_call.txt5
-rw-r--r--test/prism/errors/while_endless_method.txt5
-rw-r--r--test/prism/errors/writing_numbered_parameter.txt3
-rw-r--r--test/prism/errors_test.rb101
-rw-r--r--test/prism/fixtures/alias.txt23
-rw-r--r--test/prism/fixtures/arithmetic.txt13
-rw-r--r--test/prism/fixtures/arrays.txt122
-rw-r--r--test/prism/fixtures/begin_ensure.txt21
-rw-r--r--test/prism/fixtures/begin_rescue.txt79
-rw-r--r--test/prism/fixtures/blocks.txt54
-rw-r--r--test/prism/fixtures/boolean_operators.txt5
-rw-r--r--test/prism/fixtures/booleans.txt3
-rw-r--r--test/prism/fixtures/break.txt29
-rw-r--r--test/prism/fixtures/case.txt55
-rw-r--r--test/prism/fixtures/classes.txt35
-rw-r--r--test/prism/fixtures/command_method_call.txt41
-rw-r--r--test/prism/fixtures/comments.txt24
-rw-r--r--test/prism/fixtures/constants.txt184
-rw-r--r--test/prism/fixtures/dash_heredocs.txt63
-rw-r--r--test/prism/fixtures/defined.txt10
-rw-r--r--test/prism/fixtures/dos_endings.txt20
-rw-r--r--test/prism/fixtures/dstring.txt29
-rw-r--r--test/prism/fixtures/dsym_str.txt2
-rw-r--r--test/prism/fixtures/embdoc_no_newline_at_end.txt2
-rw-r--r--test/prism/fixtures/emoji_method_calls.txt1
-rw-r--r--test/prism/fixtures/endless_methods.txt5
-rw-r--r--test/prism/fixtures/endless_range_in_conditional.txt3
-rw-r--r--test/prism/fixtures/for.txt19
-rw-r--r--test/prism/fixtures/global_variables.txt93
-rw-r--r--test/prism/fixtures/hashes.txt28
-rw-r--r--test/prism/fixtures/heredoc.txt2
-rw-r--r--test/prism/fixtures/heredoc_with_carriage_returns.txt2
-rw-r--r--test/prism/fixtures/heredoc_with_comment.txt3
-rw-r--r--test/prism/fixtures/heredoc_with_escaped_newline_at_start.txt7
-rw-r--r--test/prism/fixtures/heredoc_with_trailing_newline.txt2
-rw-r--r--test/prism/fixtures/heredocs_leading_whitespace.txt29
-rw-r--r--test/prism/fixtures/heredocs_nested.txt22
-rw-r--r--test/prism/fixtures/heredocs_with_ignored_newlines.txt14
-rw-r--r--test/prism/fixtures/heredocs_with_ignored_newlines_and_non_empty.txt4
-rw-r--r--test/prism/fixtures/if.txt42
-rw-r--r--test/prism/fixtures/indented_file_end.txt4
-rw-r--r--test/prism/fixtures/integer_operations.txt63
-rw-r--r--test/prism/fixtures/keyword_method_names.txt29
-rw-r--r--test/prism/fixtures/keywords.txt11
-rw-r--r--test/prism/fixtures/lambda.txt11
-rw-r--r--test/prism/fixtures/method_calls.txt156
-rw-r--r--test/prism/fixtures/methods.txt188
-rw-r--r--test/prism/fixtures/modules.txt18
-rw-r--r--test/prism/fixtures/multi_write.txt4
-rw-r--r--test/prism/fixtures/newline_terminated.txtbin0 -> 212 bytes
-rw-r--r--test/prism/fixtures/next.txt24
-rw-r--r--test/prism/fixtures/nils.txt13
-rw-r--r--test/prism/fixtures/non_alphanumeric_methods.txt105
-rw-r--r--test/prism/fixtures/not.txt37
-rw-r--r--test/prism/fixtures/numbers.txt67
-rw-r--r--test/prism/fixtures/patterns.txt220
-rw-r--r--test/prism/fixtures/procs.txt27
-rw-r--r--test/prism/fixtures/range_begin_open_exclusive.txt1
-rw-r--r--test/prism/fixtures/range_begin_open_inclusive.txt1
-rw-r--r--test/prism/fixtures/range_end_open_exclusive.txt1
-rw-r--r--test/prism/fixtures/range_end_open_inclusive.txt1
-rw-r--r--test/prism/fixtures/ranges.txt49
-rw-r--r--test/prism/fixtures/regex.txt48
-rw-r--r--test/prism/fixtures/regex_char_width.txt3
-rw-r--r--test/prism/fixtures/regex_escape_encoding.txt3
-rw-r--r--test/prism/fixtures/repeat_parameters.txt38
-rw-r--r--test/prism/fixtures/rescue.txt35
-rw-r--r--test/prism/fixtures/return.txt24
-rw-r--r--test/prism/fixtures/seattlerb/BEGIN.txt1
-rw-r--r--test/prism/fixtures/seattlerb/README.rdoc113
-rw-r--r--test/prism/fixtures/seattlerb/TestRubyParserShared.txt92
-rw-r--r--test/prism/fixtures/seattlerb/__ENCODING__.txt1
-rw-r--r--test/prism/fixtures/seattlerb/alias_gvar_backref.txt1
-rw-r--r--test/prism/fixtures/seattlerb/alias_resword.txt1
-rw-r--r--test/prism/fixtures/seattlerb/and_multi.txt3
-rw-r--r--test/prism/fixtures/seattlerb/aref_args_assocs.txt1
-rw-r--r--test/prism/fixtures/seattlerb/aref_args_lit_assocs.txt1
-rw-r--r--test/prism/fixtures/seattlerb/args_kw_block.txt1
-rw-r--r--test/prism/fixtures/seattlerb/array_line_breaks.txt4
-rw-r--r--test/prism/fixtures/seattlerb/array_lits_trailing_calls.txt3
-rw-r--r--test/prism/fixtures/seattlerb/assoc__bare.txt1
-rw-r--r--test/prism/fixtures/seattlerb/assoc_label.txt1
-rw-r--r--test/prism/fixtures/seattlerb/attr_asgn_colon_id.txt1
-rw-r--r--test/prism/fixtures/seattlerb/attrasgn_array_arg.txt1
-rw-r--r--test/prism/fixtures/seattlerb/attrasgn_array_lhs.txt1
-rw-r--r--test/prism/fixtures/seattlerb/attrasgn_primary_dot_constant.txt1
-rw-r--r--test/prism/fixtures/seattlerb/backticks_interpolation_line.txt1
-rw-r--r--test/prism/fixtures/seattlerb/bang_eq.txt1
-rw-r--r--test/prism/fixtures/seattlerb/bdot2.txt3
-rw-r--r--test/prism/fixtures/seattlerb/bdot3.txt3
-rw-r--r--test/prism/fixtures/seattlerb/begin_ensure_no_bodies.txt3
-rw-r--r--test/prism/fixtures/seattlerb/begin_rescue_else_ensure_bodies.txt9
-rw-r--r--test/prism/fixtures/seattlerb/begin_rescue_else_ensure_no_bodies.txt9
-rw-r--r--test/prism/fixtures/seattlerb/begin_rescue_ensure_no_bodies.txt4
-rw-r--r--test/prism/fixtures/seattlerb/block_arg__bare.txt1
-rw-r--r--test/prism/fixtures/seattlerb/block_arg_kwsplat.txt1
-rw-r--r--test/prism/fixtures/seattlerb/block_arg_opt_arg_block.txt1
-rw-r--r--test/prism/fixtures/seattlerb/block_arg_opt_splat.txt1
-rw-r--r--test/prism/fixtures/seattlerb/block_arg_opt_splat_arg_block_omfg.txt1
-rw-r--r--test/prism/fixtures/seattlerb/block_arg_optional.txt1
-rw-r--r--test/prism/fixtures/seattlerb/block_arg_scope.txt1
-rw-r--r--test/prism/fixtures/seattlerb/block_arg_scope2.txt1
-rw-r--r--test/prism/fixtures/seattlerb/block_arg_splat_arg.txt1
-rw-r--r--test/prism/fixtures/seattlerb/block_args_kwargs.txt1
-rw-r--r--test/prism/fixtures/seattlerb/block_args_no_kwargs.txt1
-rw-r--r--test/prism/fixtures/seattlerb/block_args_opt1.txt1
-rw-r--r--test/prism/fixtures/seattlerb/block_args_opt2.txt1
-rw-r--r--test/prism/fixtures/seattlerb/block_args_opt2_2.txt1
-rw-r--r--test/prism/fixtures/seattlerb/block_args_opt3.txt1
-rw-r--r--test/prism/fixtures/seattlerb/block_call_defn_call_block_call.txt4
-rw-r--r--test/prism/fixtures/seattlerb/block_call_dot_op2_brace_block.txt1
-rw-r--r--test/prism/fixtures/seattlerb/block_call_dot_op2_cmd_args_do_block.txt1
-rw-r--r--test/prism/fixtures/seattlerb/block_call_operation_colon.txt1
-rw-r--r--test/prism/fixtures/seattlerb/block_call_operation_dot.txt1
-rw-r--r--test/prism/fixtures/seattlerb/block_call_paren_call_block_call.txt2
-rw-r--r--test/prism/fixtures/seattlerb/block_command_operation_colon.txt1
-rw-r--r--test/prism/fixtures/seattlerb/block_command_operation_dot.txt1
-rw-r--r--test/prism/fixtures/seattlerb/block_decomp_anon_splat_arg.txt1
-rw-r--r--test/prism/fixtures/seattlerb/block_decomp_arg_splat.txt1
-rw-r--r--test/prism/fixtures/seattlerb/block_decomp_arg_splat_arg.txt1
-rw-r--r--test/prism/fixtures/seattlerb/block_decomp_splat.txt1
-rw-r--r--test/prism/fixtures/seattlerb/block_kw.txt1
-rw-r--r--test/prism/fixtures/seattlerb/block_kw__required.txt1
-rw-r--r--test/prism/fixtures/seattlerb/block_kwarg_lvar.txt1
-rw-r--r--test/prism/fixtures/seattlerb/block_kwarg_lvar_multiple.txt1
-rw-r--r--test/prism/fixtures/seattlerb/block_opt_arg.txt1
-rw-r--r--test/prism/fixtures/seattlerb/block_opt_splat.txt1
-rw-r--r--test/prism/fixtures/seattlerb/block_opt_splat_arg_block_omfg.txt1
-rw-r--r--test/prism/fixtures/seattlerb/block_optarg.txt1
-rw-r--r--test/prism/fixtures/seattlerb/block_paren_splat.txt1
-rw-r--r--test/prism/fixtures/seattlerb/block_reg_optarg.txt1
-rw-r--r--test/prism/fixtures/seattlerb/block_return.txt1
-rw-r--r--test/prism/fixtures/seattlerb/block_scope.txt1
-rw-r--r--test/prism/fixtures/seattlerb/block_splat_reg.txt1
-rw-r--r--test/prism/fixtures/seattlerb/bug169.txt1
-rw-r--r--test/prism/fixtures/seattlerb/bug179.txt1
-rw-r--r--test/prism/fixtures/seattlerb/bug190.txt1
-rw-r--r--test/prism/fixtures/seattlerb/bug191.txt3
-rw-r--r--test/prism/fixtures/seattlerb/bug202.txt2
-rw-r--r--test/prism/fixtures/seattlerb/bug236.txt3
-rw-r--r--test/prism/fixtures/seattlerb/bug290.txt3
-rw-r--r--test/prism/fixtures/seattlerb/bug_187.txt3
-rw-r--r--test/prism/fixtures/seattlerb/bug_215.txt1
-rw-r--r--test/prism/fixtures/seattlerb/bug_249.txt4
-rw-r--r--test/prism/fixtures/seattlerb/bug_and.txt4
-rw-r--r--test/prism/fixtures/seattlerb/bug_args__19.txt1
-rw-r--r--test/prism/fixtures/seattlerb/bug_args_masgn.txt1
-rw-r--r--test/prism/fixtures/seattlerb/bug_args_masgn2.txt1
-rw-r--r--test/prism/fixtures/seattlerb/bug_args_masgn_outer_parens__19.txt1
-rw-r--r--test/prism/fixtures/seattlerb/bug_call_arglist_parens.txt11
-rw-r--r--test/prism/fixtures/seattlerb/bug_case_when_regexp.txt1
-rw-r--r--test/prism/fixtures/seattlerb/bug_comma.txt1
-rw-r--r--test/prism/fixtures/seattlerb/bug_cond_pct.txt1
-rw-r--r--test/prism/fixtures/seattlerb/bug_hash_args.txt1
-rw-r--r--test/prism/fixtures/seattlerb/bug_hash_args_trailing_comma.txt1
-rw-r--r--test/prism/fixtures/seattlerb/bug_hash_interp_array.txt1
-rw-r--r--test/prism/fixtures/seattlerb/bug_masgn_right.txt1
-rw-r--r--test/prism/fixtures/seattlerb/bug_not_parens.txt1
-rw-r--r--test/prism/fixtures/seattlerb/bug_op_asgn_rescue.txt1
-rw-r--r--test/prism/fixtures/seattlerb/call_and.txt1
-rw-r--r--test/prism/fixtures/seattlerb/call_arg_assoc.txt1
-rw-r--r--test/prism/fixtures/seattlerb/call_arg_assoc_kwsplat.txt1
-rw-r--r--test/prism/fixtures/seattlerb/call_arg_kwsplat.txt1
-rw-r--r--test/prism/fixtures/seattlerb/call_args_assoc_quoted.txt5
-rw-r--r--test/prism/fixtures/seattlerb/call_args_assoc_trailing_comma.txt1
-rw-r--r--test/prism/fixtures/seattlerb/call_args_command.txt1
-rw-r--r--test/prism/fixtures/seattlerb/call_array_arg.txt1
-rw-r--r--test/prism/fixtures/seattlerb/call_array_block_call.txt1
-rw-r--r--test/prism/fixtures/seattlerb/call_array_lambda_block_call.txt2
-rw-r--r--test/prism/fixtures/seattlerb/call_array_lit_inline_hash.txt1
-rw-r--r--test/prism/fixtures/seattlerb/call_assoc.txt1
-rw-r--r--test/prism/fixtures/seattlerb/call_assoc_new.txt1
-rw-r--r--test/prism/fixtures/seattlerb/call_assoc_new_if_multiline.txt5
-rw-r--r--test/prism/fixtures/seattlerb/call_assoc_trailing_comma.txt1
-rw-r--r--test/prism/fixtures/seattlerb/call_bang_command_call.txt1
-rw-r--r--test/prism/fixtures/seattlerb/call_bang_squiggle.txt1
-rw-r--r--test/prism/fixtures/seattlerb/call_begin_call_block_call.txt3
-rw-r--r--test/prism/fixtures/seattlerb/call_block_arg_named.txt1
-rw-r--r--test/prism/fixtures/seattlerb/call_carat.txt1
-rw-r--r--test/prism/fixtures/seattlerb/call_colon2.txt1
-rw-r--r--test/prism/fixtures/seattlerb/call_colon_parens.txt1
-rw-r--r--test/prism/fixtures/seattlerb/call_div.txt1
-rw-r--r--test/prism/fixtures/seattlerb/call_dot_parens.txt1
-rw-r--r--test/prism/fixtures/seattlerb/call_env.txt1
-rw-r--r--test/prism/fixtures/seattlerb/call_eq3.txt1
-rw-r--r--test/prism/fixtures/seattlerb/call_gt.txt1
-rw-r--r--test/prism/fixtures/seattlerb/call_kwsplat.txt1
-rw-r--r--test/prism/fixtures/seattlerb/call_leading_dots.txt3
-rw-r--r--test/prism/fixtures/seattlerb/call_leading_dots_comment.txt4
-rw-r--r--test/prism/fixtures/seattlerb/call_lt.txt1
-rw-r--r--test/prism/fixtures/seattlerb/call_lte.txt1
-rw-r--r--test/prism/fixtures/seattlerb/call_not.txt1
-rw-r--r--test/prism/fixtures/seattlerb/call_pipe.txt1
-rw-r--r--test/prism/fixtures/seattlerb/call_rshift.txt1
-rw-r--r--test/prism/fixtures/seattlerb/call_self_brackets.txt1
-rw-r--r--test/prism/fixtures/seattlerb/call_spaceship.txt1
-rw-r--r--test/prism/fixtures/seattlerb/call_stabby_do_end_with_block.txt1
-rw-r--r--test/prism/fixtures/seattlerb/call_stabby_with_braces_block.txt1
-rw-r--r--test/prism/fixtures/seattlerb/call_star.txt1
-rw-r--r--test/prism/fixtures/seattlerb/call_star2.txt1
-rw-r--r--test/prism/fixtures/seattlerb/call_trailing_comma.txt1
-rw-r--r--test/prism/fixtures/seattlerb/call_trailing_dots.txt3
-rw-r--r--test/prism/fixtures/seattlerb/call_unary_bang.txt1
-rw-r--r--test/prism/fixtures/seattlerb/case_in.txt111
-rw-r--r--test/prism/fixtures/seattlerb/case_in_31.txt4
-rw-r--r--test/prism/fixtures/seattlerb/case_in_37.txt4
-rw-r--r--test/prism/fixtures/seattlerb/case_in_42.txt3
-rw-r--r--test/prism/fixtures/seattlerb/case_in_42_2.txt3
-rw-r--r--test/prism/fixtures/seattlerb/case_in_47.txt4
-rw-r--r--test/prism/fixtures/seattlerb/case_in_67.txt3
-rw-r--r--test/prism/fixtures/seattlerb/case_in_86.txt3
-rw-r--r--test/prism/fixtures/seattlerb/case_in_86_2.txt3
-rw-r--r--test/prism/fixtures/seattlerb/case_in_array_pat_const.txt4
-rw-r--r--test/prism/fixtures/seattlerb/case_in_array_pat_const2.txt4
-rw-r--r--test/prism/fixtures/seattlerb/case_in_array_pat_paren_assign.txt4
-rw-r--r--test/prism/fixtures/seattlerb/case_in_const.txt4
-rw-r--r--test/prism/fixtures/seattlerb/case_in_else.txt7
-rw-r--r--test/prism/fixtures/seattlerb/case_in_find.txt3
-rw-r--r--test/prism/fixtures/seattlerb/case_in_find_array.txt3
-rw-r--r--test/prism/fixtures/seattlerb/case_in_hash_pat.txt5
-rw-r--r--test/prism/fixtures/seattlerb/case_in_hash_pat_assign.txt4
-rw-r--r--test/prism/fixtures/seattlerb/case_in_hash_pat_paren_assign.txt4
-rw-r--r--test/prism/fixtures/seattlerb/case_in_hash_pat_paren_true.txt5
-rw-r--r--test/prism/fixtures/seattlerb/case_in_hash_pat_rest.txt3
-rw-r--r--test/prism/fixtures/seattlerb/case_in_hash_pat_rest_solo.txt3
-rw-r--r--test/prism/fixtures/seattlerb/case_in_if_unless_post_mod.txt6
-rw-r--r--test/prism/fixtures/seattlerb/case_in_multiple.txt6
-rw-r--r--test/prism/fixtures/seattlerb/case_in_or.txt5
-rw-r--r--test/prism/fixtures/seattlerb/class_comments.txt9
-rw-r--r--test/prism/fixtures/seattlerb/cond_unary_minus.txt1
-rw-r--r--test/prism/fixtures/seattlerb/const_2_op_asgn_or2.txt1
-rw-r--r--test/prism/fixtures/seattlerb/const_3_op_asgn_or.txt1
-rw-r--r--test/prism/fixtures/seattlerb/const_op_asgn_and1.txt1
-rw-r--r--test/prism/fixtures/seattlerb/const_op_asgn_and2.txt1
-rw-r--r--test/prism/fixtures/seattlerb/const_op_asgn_or.txt1
-rw-r--r--test/prism/fixtures/seattlerb/defined_eh_parens.txt1
-rw-r--r--test/prism/fixtures/seattlerb/defn_arg_asplat_arg.txt1
-rw-r--r--test/prism/fixtures/seattlerb/defn_arg_forward_args.txt1
-rw-r--r--test/prism/fixtures/seattlerb/defn_args_forward_args.txt1
-rw-r--r--test/prism/fixtures/seattlerb/defn_comments.txt5
-rw-r--r--test/prism/fixtures/seattlerb/defn_endless_command.txt1
-rw-r--r--test/prism/fixtures/seattlerb/defn_endless_command_rescue.txt1
-rw-r--r--test/prism/fixtures/seattlerb/defn_forward_args.txt1
-rw-r--r--test/prism/fixtures/seattlerb/defn_forward_args__no_parens.txt3
-rw-r--r--test/prism/fixtures/seattlerb/defn_kwarg_env.txt1
-rw-r--r--test/prism/fixtures/seattlerb/defn_kwarg_kwarg.txt1
-rw-r--r--test/prism/fixtures/seattlerb/defn_kwarg_kwsplat.txt1
-rw-r--r--test/prism/fixtures/seattlerb/defn_kwarg_kwsplat_anon.txt1
-rw-r--r--test/prism/fixtures/seattlerb/defn_kwarg_lvar.txt1
-rw-r--r--test/prism/fixtures/seattlerb/defn_kwarg_no_parens.txt2
-rw-r--r--test/prism/fixtures/seattlerb/defn_kwarg_val.txt1
-rw-r--r--test/prism/fixtures/seattlerb/defn_no_kwargs.txt1
-rw-r--r--test/prism/fixtures/seattlerb/defn_oneliner.txt1
-rw-r--r--test/prism/fixtures/seattlerb/defn_oneliner_eq2.txt3
-rw-r--r--test/prism/fixtures/seattlerb/defn_oneliner_noargs.txt1
-rw-r--r--test/prism/fixtures/seattlerb/defn_oneliner_noargs_parentheses.txt1
-rw-r--r--test/prism/fixtures/seattlerb/defn_oneliner_rescue.txt13
-rw-r--r--test/prism/fixtures/seattlerb/defn_opt_last_arg.txt2
-rw-r--r--test/prism/fixtures/seattlerb/defn_opt_reg.txt1
-rw-r--r--test/prism/fixtures/seattlerb/defn_opt_splat_arg.txt1
-rw-r--r--test/prism/fixtures/seattlerb/defn_powarg.txt1
-rw-r--r--test/prism/fixtures/seattlerb/defn_reg_opt_reg.txt1
-rw-r--r--test/prism/fixtures/seattlerb/defn_splat_arg.txt1
-rw-r--r--test/prism/fixtures/seattlerb/defn_unary_not.txt1
-rw-r--r--test/prism/fixtures/seattlerb/defns_reserved.txt1
-rw-r--r--test/prism/fixtures/seattlerb/defs_as_arg_with_do_block_inside.txt1
-rw-r--r--test/prism/fixtures/seattlerb/defs_comments.txt5
-rw-r--r--test/prism/fixtures/seattlerb/defs_endless_command.txt1
-rw-r--r--test/prism/fixtures/seattlerb/defs_endless_command_rescue.txt1
-rw-r--r--test/prism/fixtures/seattlerb/defs_kwarg.txt2
-rw-r--r--test/prism/fixtures/seattlerb/defs_oneliner.txt1
-rw-r--r--test/prism/fixtures/seattlerb/defs_oneliner_eq2.txt3
-rw-r--r--test/prism/fixtures/seattlerb/defs_oneliner_rescue.txt13
-rw-r--r--test/prism/fixtures/seattlerb/difficult0_.txt4
-rw-r--r--test/prism/fixtures/seattlerb/difficult1_line_numbers.txt13
-rw-r--r--test/prism/fixtures/seattlerb/difficult1_line_numbers2.txt8
-rw-r--r--test/prism/fixtures/seattlerb/difficult2_.txt2
-rw-r--r--test/prism/fixtures/seattlerb/difficult3_.txt1
-rw-r--r--test/prism/fixtures/seattlerb/difficult3_2.txt1
-rw-r--r--test/prism/fixtures/seattlerb/difficult3_3.txt1
-rw-r--r--test/prism/fixtures/seattlerb/difficult3_4.txt1
-rw-r--r--test/prism/fixtures/seattlerb/difficult3_5.txt1
-rw-r--r--test/prism/fixtures/seattlerb/difficult3__10.txt1
-rw-r--r--test/prism/fixtures/seattlerb/difficult3__11.txt1
-rw-r--r--test/prism/fixtures/seattlerb/difficult3__12.txt1
-rw-r--r--test/prism/fixtures/seattlerb/difficult3__6.txt1
-rw-r--r--test/prism/fixtures/seattlerb/difficult3__7.txt1
-rw-r--r--test/prism/fixtures/seattlerb/difficult3__8.txt1
-rw-r--r--test/prism/fixtures/seattlerb/difficult3__9.txt1
-rw-r--r--test/prism/fixtures/seattlerb/difficult4__leading_dots.txt2
-rw-r--r--test/prism/fixtures/seattlerb/difficult4__leading_dots2.txt2
-rw-r--r--test/prism/fixtures/seattlerb/difficult6_.txt1
-rw-r--r--test/prism/fixtures/seattlerb/difficult6__7.txt1
-rw-r--r--test/prism/fixtures/seattlerb/difficult6__8.txt1
-rw-r--r--test/prism/fixtures/seattlerb/difficult7_.txt5
-rw-r--r--test/prism/fixtures/seattlerb/do_bug.txt4
-rw-r--r--test/prism/fixtures/seattlerb/do_lambda.txt1
-rw-r--r--test/prism/fixtures/seattlerb/dot2_nil__26.txt1
-rw-r--r--test/prism/fixtures/seattlerb/dot3_nil__26.txt1
-rw-r--r--test/prism/fixtures/seattlerb/dstr_evstr.txt1
-rw-r--r--test/prism/fixtures/seattlerb/dstr_evstr_empty_end.txt1
-rw-r--r--test/prism/fixtures/seattlerb/dstr_lex_state.txt1
-rw-r--r--test/prism/fixtures/seattlerb/dstr_str.txt1
-rw-r--r--test/prism/fixtures/seattlerb/dsym_esc_to_sym.txt1
-rw-r--r--test/prism/fixtures/seattlerb/dsym_to_sym.txt3
-rw-r--r--test/prism/fixtures/seattlerb/eq_begin_line_numbers.txt6
-rw-r--r--test/prism/fixtures/seattlerb/eq_begin_why_wont_people_use_their_spacebar.txt3
-rw-r--r--test/prism/fixtures/seattlerb/evstr_evstr.txt1
-rw-r--r--test/prism/fixtures/seattlerb/evstr_str.txt1
-rw-r--r--test/prism/fixtures/seattlerb/expr_not_bang.txt1
-rw-r--r--test/prism/fixtures/seattlerb/f_kw.txt1
-rw-r--r--test/prism/fixtures/seattlerb/f_kw__required.txt1
-rw-r--r--test/prism/fixtures/seattlerb/flip2_env_lvar.txt1
-rw-r--r--test/prism/fixtures/seattlerb/float_with_if_modifier.txt1
-rw-r--r--test/prism/fixtures/seattlerb/heredoc__backslash_dos_format.txt5
-rw-r--r--test/prism/fixtures/seattlerb/heredoc_backslash_nl.txt8
-rw-r--r--test/prism/fixtures/seattlerb/heredoc_bad_hex_escape.txt3
-rw-r--r--test/prism/fixtures/seattlerb/heredoc_bad_oct_escape.txt5
-rw-r--r--test/prism/fixtures/seattlerb/heredoc_comma_arg.txt7
-rw-r--r--test/prism/fixtures/seattlerb/heredoc_lineno.txt7
-rw-r--r--test/prism/fixtures/seattlerb/heredoc_nested.txt7
-rw-r--r--test/prism/fixtures/seattlerb/heredoc_squiggly.txt7
-rw-r--r--test/prism/fixtures/seattlerb/heredoc_squiggly_blank_line_plus_interpolation.txt4
-rw-r--r--test/prism/fixtures/seattlerb/heredoc_squiggly_blank_lines.txt7
-rw-r--r--test/prism/fixtures/seattlerb/heredoc_squiggly_empty.txt2
-rw-r--r--test/prism/fixtures/seattlerb/heredoc_squiggly_interp.txt5
-rw-r--r--test/prism/fixtures/seattlerb/heredoc_squiggly_no_indent.txt3
-rw-r--r--test/prism/fixtures/seattlerb/heredoc_squiggly_tabs.txt6
-rw-r--r--test/prism/fixtures/seattlerb/heredoc_squiggly_tabs_extra.txt6
-rw-r--r--test/prism/fixtures/seattlerb/heredoc_squiggly_visually_blank_lines.txt7
-rw-r--r--test/prism/fixtures/seattlerb/heredoc_trailing_slash_continued_call.txt4
-rw-r--r--test/prism/fixtures/seattlerb/heredoc_unicode.txt4
-rw-r--r--test/prism/fixtures/seattlerb/heredoc_with_carriage_return_escapes.txt5
-rw-r--r--test/prism/fixtures/seattlerb/heredoc_with_carriage_return_escapes_windows.txt5
-rw-r--r--test/prism/fixtures/seattlerb/heredoc_with_extra_carriage_horrible_mix.txt4
-rw-r--r--test/prism/fixtures/seattlerb/heredoc_with_extra_carriage_returns.txt5
-rw-r--r--test/prism/fixtures/seattlerb/heredoc_with_extra_carriage_returns_windows.txt5
-rw-r--r--test/prism/fixtures/seattlerb/heredoc_with_interpolation_and_carriage_return_escapes.txt4
-rw-r--r--test/prism/fixtures/seattlerb/heredoc_with_interpolation_and_carriage_return_escapes_windows.txt4
-rw-r--r--test/prism/fixtures/seattlerb/heredoc_with_not_global_interpolation.txt3
-rw-r--r--test/prism/fixtures/seattlerb/heredoc_with_only_carriage_returns.txt6
-rw-r--r--test/prism/fixtures/seattlerb/heredoc_with_only_carriage_returns_windows.txt6
-rw-r--r--test/prism/fixtures/seattlerb/if_elsif.txt1
-rw-r--r--test/prism/fixtures/seattlerb/if_symbol.txt1
-rw-r--r--test/prism/fixtures/seattlerb/in_expr_no_case.txt1
-rw-r--r--test/prism/fixtures/seattlerb/index_0.txt1
-rw-r--r--test/prism/fixtures/seattlerb/index_0_opasgn.txt1
-rw-r--r--test/prism/fixtures/seattlerb/integer_with_if_modifier.txt1
-rw-r--r--test/prism/fixtures/seattlerb/interpolated_symbol_array_line_breaks.txt5
-rw-r--r--test/prism/fixtures/seattlerb/interpolated_word_array_line_breaks.txt5
-rw-r--r--test/prism/fixtures/seattlerb/iter_args_1.txt1
-rw-r--r--test/prism/fixtures/seattlerb/iter_args_10_1.txt1
-rw-r--r--test/prism/fixtures/seattlerb/iter_args_10_2.txt1
-rw-r--r--test/prism/fixtures/seattlerb/iter_args_11_1.txt1
-rw-r--r--test/prism/fixtures/seattlerb/iter_args_11_2.txt1
-rw-r--r--test/prism/fixtures/seattlerb/iter_args_2__19.txt1
-rw-r--r--test/prism/fixtures/seattlerb/iter_args_3.txt1
-rw-r--r--test/prism/fixtures/seattlerb/iter_args_4.txt1
-rw-r--r--test/prism/fixtures/seattlerb/iter_args_5.txt1
-rw-r--r--test/prism/fixtures/seattlerb/iter_args_6.txt1
-rw-r--r--test/prism/fixtures/seattlerb/iter_args_7_1.txt1
-rw-r--r--test/prism/fixtures/seattlerb/iter_args_7_2.txt1
-rw-r--r--test/prism/fixtures/seattlerb/iter_args_8_1.txt1
-rw-r--r--test/prism/fixtures/seattlerb/iter_args_8_2.txt1
-rw-r--r--test/prism/fixtures/seattlerb/iter_args_9_1.txt1
-rw-r--r--test/prism/fixtures/seattlerb/iter_args_9_2.txt1
-rw-r--r--test/prism/fixtures/seattlerb/iter_kwarg.txt1
-rw-r--r--test/prism/fixtures/seattlerb/iter_kwarg_kwsplat.txt1
-rw-r--r--test/prism/fixtures/seattlerb/label_vs_string.txt2
-rw-r--r--test/prism/fixtures/seattlerb/lambda_do_vs_brace.txt7
-rw-r--r--test/prism/fixtures/seattlerb/lasgn_arg_rescue_arg.txt1
-rw-r--r--test/prism/fixtures/seattlerb/lasgn_call_bracket_rescue_arg.txt1
-rw-r--r--test/prism/fixtures/seattlerb/lasgn_call_nobracket_rescue_arg.txt1
-rw-r--r--test/prism/fixtures/seattlerb/lasgn_command.txt1
-rw-r--r--test/prism/fixtures/seattlerb/lasgn_env.txt1
-rw-r--r--test/prism/fixtures/seattlerb/lasgn_ivar_env.txt1
-rw-r--r--test/prism/fixtures/seattlerb/lasgn_lasgn_command_call.txt1
-rw-r--r--test/prism/fixtures/seattlerb/lasgn_middle_splat.txt1
-rw-r--r--test/prism/fixtures/seattlerb/magic_encoding_comment.txt4
-rw-r--r--test/prism/fixtures/seattlerb/masgn_anon_splat_arg.txt1
-rw-r--r--test/prism/fixtures/seattlerb/masgn_arg_colon_arg.txt1
-rw-r--r--test/prism/fixtures/seattlerb/masgn_arg_ident.txt1
-rw-r--r--test/prism/fixtures/seattlerb/masgn_arg_splat_arg.txt1
-rw-r--r--test/prism/fixtures/seattlerb/masgn_colon2.txt1
-rw-r--r--test/prism/fixtures/seattlerb/masgn_colon3.txt1
-rw-r--r--test/prism/fixtures/seattlerb/masgn_command_call.txt1
-rw-r--r--test/prism/fixtures/seattlerb/masgn_double_paren.txt1
-rw-r--r--test/prism/fixtures/seattlerb/masgn_lhs_splat.txt1
-rw-r--r--test/prism/fixtures/seattlerb/masgn_paren.txt1
-rw-r--r--test/prism/fixtures/seattlerb/masgn_splat_arg.txt1
-rw-r--r--test/prism/fixtures/seattlerb/masgn_splat_arg_arg.txt1
-rw-r--r--test/prism/fixtures/seattlerb/masgn_star.txt1
-rw-r--r--test/prism/fixtures/seattlerb/masgn_var_star_var.txt1
-rw-r--r--test/prism/fixtures/seattlerb/messy_op_asgn_lineno.txt1
-rw-r--r--test/prism/fixtures/seattlerb/method_call_assoc_trailing_comma.txt1
-rw-r--r--test/prism/fixtures/seattlerb/method_call_trailing_comma.txt1
-rw-r--r--test/prism/fixtures/seattlerb/mlhs_back_anonsplat.txt1
-rw-r--r--test/prism/fixtures/seattlerb/mlhs_back_splat.txt1
-rw-r--r--test/prism/fixtures/seattlerb/mlhs_front_anonsplat.txt1
-rw-r--r--test/prism/fixtures/seattlerb/mlhs_front_splat.txt1
-rw-r--r--test/prism/fixtures/seattlerb/mlhs_keyword.txt1
-rw-r--r--test/prism/fixtures/seattlerb/mlhs_mid_anonsplat.txt1
-rw-r--r--test/prism/fixtures/seattlerb/mlhs_mid_splat.txt1
-rw-r--r--test/prism/fixtures/seattlerb/mlhs_rescue.txt1
-rw-r--r--test/prism/fixtures/seattlerb/module_comments.txt10
-rw-r--r--test/prism/fixtures/seattlerb/multiline_hash_declaration.txt8
-rw-r--r--test/prism/fixtures/seattlerb/non_interpolated_symbol_array_line_breaks.txt5
-rw-r--r--test/prism/fixtures/seattlerb/non_interpolated_word_array_line_breaks.txt5
-rw-r--r--test/prism/fixtures/seattlerb/op_asgn_command_call.txt1
-rw-r--r--test/prism/fixtures/seattlerb/op_asgn_dot_ident_command_call.txt1
-rw-r--r--test/prism/fixtures/seattlerb/op_asgn_index_command_call.txt1
-rw-r--r--test/prism/fixtures/seattlerb/op_asgn_primary_colon_const_command_call.txt1
-rw-r--r--test/prism/fixtures/seattlerb/op_asgn_primary_colon_identifier1.txt1
-rw-r--r--test/prism/fixtures/seattlerb/op_asgn_primary_colon_identifier_command_call.txt1
-rw-r--r--test/prism/fixtures/seattlerb/op_asgn_val_dot_ident_command_call.txt1
-rw-r--r--test/prism/fixtures/seattlerb/parse_def_special_name.txt1
-rw-r--r--test/prism/fixtures/seattlerb/parse_if_not_canonical.txt2
-rw-r--r--test/prism/fixtures/seattlerb/parse_if_not_noncanonical.txt2
-rw-r--r--test/prism/fixtures/seattlerb/parse_line_block.txt2
-rw-r--r--test/prism/fixtures/seattlerb/parse_line_block_inline_comment.txt3
-rw-r--r--test/prism/fixtures/seattlerb/parse_line_block_inline_comment_leading_newlines.txt7
-rw-r--r--test/prism/fixtures/seattlerb/parse_line_block_inline_multiline_comment.txt4
-rw-r--r--test/prism/fixtures/seattlerb/parse_line_call_ivar_arg_no_parens_line_break.txt2
-rw-r--r--test/prism/fixtures/seattlerb/parse_line_call_ivar_line_break_paren.txt2
-rw-r--r--test/prism/fixtures/seattlerb/parse_line_call_no_args.txt3
-rw-r--r--test/prism/fixtures/seattlerb/parse_line_defn_complex.txt5
-rw-r--r--test/prism/fixtures/seattlerb/parse_line_defn_no_parens.txt6
-rw-r--r--test/prism/fixtures/seattlerb/parse_line_defn_no_parens_args.txt2
-rw-r--r--test/prism/fixtures/seattlerb/parse_line_dot2.txt5
-rw-r--r--test/prism/fixtures/seattlerb/parse_line_dot2_open.txt3
-rw-r--r--test/prism/fixtures/seattlerb/parse_line_dot3.txt5
-rw-r--r--test/prism/fixtures/seattlerb/parse_line_dot3_open.txt3
-rw-r--r--test/prism/fixtures/seattlerb/parse_line_dstr_escaped_newline.txt3
-rw-r--r--test/prism/fixtures/seattlerb/parse_line_dstr_soft_newline.txt4
-rw-r--r--test/prism/fixtures/seattlerb/parse_line_evstr_after_break.txt2
-rw-r--r--test/prism/fixtures/seattlerb/parse_line_hash_lit.txt3
-rw-r--r--test/prism/fixtures/seattlerb/parse_line_heredoc.txt5
-rw-r--r--test/prism/fixtures/seattlerb/parse_line_heredoc_evstr.txt4
-rw-r--r--test/prism/fixtures/seattlerb/parse_line_heredoc_hardnewline.txt7
-rw-r--r--test/prism/fixtures/seattlerb/parse_line_heredoc_regexp_chars.txt5
-rw-r--r--test/prism/fixtures/seattlerb/parse_line_iter_call_no_parens.txt3
-rw-r--r--test/prism/fixtures/seattlerb/parse_line_iter_call_parens.txt3
-rw-r--r--test/prism/fixtures/seattlerb/parse_line_multiline_str.txt3
-rw-r--r--test/prism/fixtures/seattlerb/parse_line_multiline_str_literal_n.txt2
-rw-r--r--test/prism/fixtures/seattlerb/parse_line_newlines.txt3
-rw-r--r--test/prism/fixtures/seattlerb/parse_line_op_asgn.txt4
-rw-r--r--test/prism/fixtures/seattlerb/parse_line_postexe.txt3
-rw-r--r--test/prism/fixtures/seattlerb/parse_line_preexe.txt3
-rw-r--r--test/prism/fixtures/seattlerb/parse_line_rescue.txt8
-rw-r--r--test/prism/fixtures/seattlerb/parse_line_return.txt6
-rw-r--r--test/prism/fixtures/seattlerb/parse_line_str_with_newline_escape.txt1
-rw-r--r--test/prism/fixtures/seattlerb/parse_line_to_ary.txt3
-rw-r--r--test/prism/fixtures/seattlerb/parse_line_trailing_newlines.txt2
-rw-r--r--test/prism/fixtures/seattlerb/parse_opt_call_args_assocs_comma.txt1
-rw-r--r--test/prism/fixtures/seattlerb/parse_opt_call_args_lit_comma.txt1
-rw-r--r--test/prism/fixtures/seattlerb/parse_pattern_019.txt5
-rw-r--r--test/prism/fixtures/seattlerb/parse_pattern_044.txt5
-rw-r--r--test/prism/fixtures/seattlerb/parse_pattern_051.txt5
-rw-r--r--test/prism/fixtures/seattlerb/parse_pattern_058.txt5
-rw-r--r--test/prism/fixtures/seattlerb/parse_pattern_058_2.txt5
-rw-r--r--test/prism/fixtures/seattlerb/parse_pattern_069.txt5
-rw-r--r--test/prism/fixtures/seattlerb/parse_pattern_076.txt5
-rw-r--r--test/prism/fixtures/seattlerb/parse_until_not_canonical.txt3
-rw-r--r--test/prism/fixtures/seattlerb/parse_until_not_noncanonical.txt3
-rw-r--r--test/prism/fixtures/seattlerb/parse_while_not_canonical.txt3
-rw-r--r--test/prism/fixtures/seattlerb/parse_while_not_noncanonical.txt3
-rw-r--r--test/prism/fixtures/seattlerb/pctW_lineno.txt5
-rw-r--r--test/prism/fixtures/seattlerb/pct_Q_backslash_nl.txt2
-rw-r--r--test/prism/fixtures/seattlerb/pct_nl.txt3
-rw-r--r--test/prism/fixtures/seattlerb/pct_w_heredoc_interp_nested.txt4
-rw-r--r--test/prism/fixtures/seattlerb/pipe_semicolon.txt1
-rw-r--r--test/prism/fixtures/seattlerb/pipe_space.txt1
-rw-r--r--test/prism/fixtures/seattlerb/qWords_space.txt1
-rw-r--r--test/prism/fixtures/seattlerb/qsymbols.txt1
-rw-r--r--test/prism/fixtures/seattlerb/qsymbols_empty.txt1
-rw-r--r--test/prism/fixtures/seattlerb/qsymbols_empty_space.txt1
-rw-r--r--test/prism/fixtures/seattlerb/qsymbols_interp.txt1
-rw-r--r--test/prism/fixtures/seattlerb/quoted_symbol_hash_arg.txt1
-rw-r--r--test/prism/fixtures/seattlerb/quoted_symbol_keys.txt1
-rw-r--r--test/prism/fixtures/seattlerb/qw_escape.txt1
-rw-r--r--test/prism/fixtures/seattlerb/qw_escape_term.txt1
-rw-r--r--test/prism/fixtures/seattlerb/qwords_empty.txt1
-rw-r--r--test/prism/fixtures/seattlerb/read_escape_unicode_curlies.txt1
-rw-r--r--test/prism/fixtures/seattlerb/read_escape_unicode_h4.txt1
-rw-r--r--test/prism/fixtures/seattlerb/regexp.txt9
-rw-r--r--test/prism/fixtures/seattlerb/regexp_esc_C_slash.txt1
-rw-r--r--test/prism/fixtures/seattlerb/regexp_esc_u.txt1
-rw-r--r--test/prism/fixtures/seattlerb/regexp_escape_extended.txt1
-rw-r--r--test/prism/fixtures/seattlerb/regexp_unicode_curlies.txt3
-rw-r--r--test/prism/fixtures/seattlerb/required_kwarg_no_value.txt2
-rw-r--r--test/prism/fixtures/seattlerb/rescue_do_end_ensure_result.txt5
-rw-r--r--test/prism/fixtures/seattlerb/rescue_do_end_no_raise.txt9
-rw-r--r--test/prism/fixtures/seattlerb/rescue_do_end_raised.txt5
-rw-r--r--test/prism/fixtures/seattlerb/rescue_do_end_rescued.txt9
-rw-r--r--test/prism/fixtures/seattlerb/rescue_in_block.txt4
-rw-r--r--test/prism/fixtures/seattlerb/rescue_parens.txt1
-rw-r--r--test/prism/fixtures/seattlerb/return_call_assocs.txt11
-rw-r--r--test/prism/fixtures/seattlerb/rhs_asgn.txt1
-rw-r--r--test/prism/fixtures/seattlerb/ruby21_numbers.txt1
-rw-r--r--test/prism/fixtures/seattlerb/safe_attrasgn.txt1
-rw-r--r--test/prism/fixtures/seattlerb/safe_attrasgn_constant.txt1
-rw-r--r--test/prism/fixtures/seattlerb/safe_call.txt1
-rw-r--r--test/prism/fixtures/seattlerb/safe_call_after_newline.txt2
-rw-r--r--test/prism/fixtures/seattlerb/safe_call_dot_parens.txt1
-rw-r--r--test/prism/fixtures/seattlerb/safe_call_newline.txt2
-rw-r--r--test/prism/fixtures/seattlerb/safe_call_operator.txt1
-rw-r--r--test/prism/fixtures/seattlerb/safe_call_rhs_newline.txt2
-rw-r--r--test/prism/fixtures/seattlerb/safe_calls.txt1
-rw-r--r--test/prism/fixtures/seattlerb/safe_op_asgn.txt1
-rw-r--r--test/prism/fixtures/seattlerb/safe_op_asgn2.txt2
-rw-r--r--test/prism/fixtures/seattlerb/slashy_newlines_within_string.txt7
-rw-r--r--test/prism/fixtures/seattlerb/stabby_arg_no_paren.txt1
-rw-r--r--test/prism/fixtures/seattlerb/stabby_arg_opt_splat_arg_block_omfg.txt1
-rw-r--r--test/prism/fixtures/seattlerb/stabby_block_iter_call.txt4
-rw-r--r--test/prism/fixtures/seattlerb/stabby_block_iter_call_no_target_with_arg.txt4
-rw-r--r--test/prism/fixtures/seattlerb/stabby_block_kw.txt1
-rw-r--r--test/prism/fixtures/seattlerb/stabby_block_kw__required.txt1
-rw-r--r--test/prism/fixtures/seattlerb/stabby_proc_scope.txt1
-rw-r--r--test/prism/fixtures/seattlerb/str_backslashes.txt1
-rw-r--r--test/prism/fixtures/seattlerb/str_double_double_escaped_newline.txt1
-rw-r--r--test/prism/fixtures/seattlerb/str_double_escaped_newline.txt1
-rw-r--r--test/prism/fixtures/seattlerb/str_double_newline.txt2
-rw-r--r--test/prism/fixtures/seattlerb/str_evstr.txt1
-rw-r--r--test/prism/fixtures/seattlerb/str_evstr_escape.txt1
-rw-r--r--test/prism/fixtures/seattlerb/str_heredoc_interp.txt5
-rw-r--r--test/prism/fixtures/seattlerb/str_interp_ternary_or_label.txt1
-rw-r--r--test/prism/fixtures/seattlerb/str_lit_concat_bad_encodings.txt2
-rw-r--r--test/prism/fixtures/seattlerb/str_newline_hash_line_number.txt2
-rw-r--r--test/prism/fixtures/seattlerb/str_pct_Q_nested.txt1
-rw-r--r--test/prism/fixtures/seattlerb/str_pct_nested_nested.txt1
-rw-r--r--test/prism/fixtures/seattlerb/str_pct_q.txt1
-rw-r--r--test/prism/fixtures/seattlerb/str_single_double_escaped_newline.txt1
-rw-r--r--test/prism/fixtures/seattlerb/str_single_escaped_newline.txt1
-rw-r--r--test/prism/fixtures/seattlerb/str_single_newline.txt2
-rw-r--r--test/prism/fixtures/seattlerb/str_str.txt1
-rw-r--r--test/prism/fixtures/seattlerb/str_str_str.txt1
-rw-r--r--test/prism/fixtures/seattlerb/super_arg.txt1
-rw-r--r--test/prism/fixtures/seattlerb/symbol_empty.txt1
-rw-r--r--test/prism/fixtures/seattlerb/symbol_list.txt1
-rw-r--r--test/prism/fixtures/seattlerb/symbols.txt1
-rw-r--r--test/prism/fixtures/seattlerb/symbols_empty.txt1
-rw-r--r--test/prism/fixtures/seattlerb/symbols_empty_space.txt1
-rw-r--r--test/prism/fixtures/seattlerb/symbols_interp.txt1
-rw-r--r--test/prism/fixtures/seattlerb/thingy.txt3
-rw-r--r--test/prism/fixtures/seattlerb/uminus_float.txt1
-rw-r--r--test/prism/fixtures/seattlerb/unary_minus.txt1
-rw-r--r--test/prism/fixtures/seattlerb/unary_plus.txt1
-rw-r--r--test/prism/fixtures/seattlerb/unary_plus_on_literal.txt1
-rw-r--r--test/prism/fixtures/seattlerb/unary_tilde.txt1
-rw-r--r--test/prism/fixtures/seattlerb/utf8_bom.txt3
-rw-r--r--test/prism/fixtures/seattlerb/when_splat.txt1
-rw-r--r--test/prism/fixtures/seattlerb/words_interp.txt1
-rw-r--r--test/prism/fixtures/single_method_call_with_bang.txt1
-rw-r--r--test/prism/fixtures/single_quote_heredocs.txt3
-rw-r--r--test/prism/fixtures/spanning_heredoc.txt63
-rw-r--r--test/prism/fixtures/spanning_heredoc_newlines.txt23
-rw-r--r--test/prism/fixtures/strings.txt105
-rw-r--r--test/prism/fixtures/super.txt17
-rw-r--r--test/prism/fixtures/symbols.txt93
-rw-r--r--test/prism/fixtures/ternary_operator.txt15
-rw-r--r--test/prism/fixtures/tilde_heredocs.txt97
-rw-r--r--test/prism/fixtures/undef.txt17
-rw-r--r--test/prism/fixtures/unescaping.txt9
-rw-r--r--test/prism/fixtures/unless.txt14
-rw-r--r--test/prism/fixtures/unparser/LICENSE20
-rw-r--r--test/prism/fixtures/unparser/corpus/literal/alias.txt2
-rw-r--r--test/prism/fixtures/unparser/corpus/literal/assignment.txt53
-rw-r--r--test/prism/fixtures/unparser/corpus/literal/block.txt96
-rw-r--r--test/prism/fixtures/unparser/corpus/literal/case.txt37
-rw-r--r--test/prism/fixtures/unparser/corpus/literal/class.txt35
-rw-r--r--test/prism/fixtures/unparser/corpus/literal/def.txt134
-rw-r--r--test/prism/fixtures/unparser/corpus/literal/defined.txt3
-rw-r--r--test/prism/fixtures/unparser/corpus/literal/defs.txt40
-rw-r--r--test/prism/fixtures/unparser/corpus/literal/dstr.txt37
-rw-r--r--test/prism/fixtures/unparser/corpus/literal/empty.txt0
-rw-r--r--test/prism/fixtures/unparser/corpus/literal/empty_begin.txt1
-rw-r--r--test/prism/fixtures/unparser/corpus/literal/flipflop.txt10
-rw-r--r--test/prism/fixtures/unparser/corpus/literal/for.txt12
-rw-r--r--test/prism/fixtures/unparser/corpus/literal/hookexe.txt7
-rw-r--r--test/prism/fixtures/unparser/corpus/literal/if.txt36
-rw-r--r--test/prism/fixtures/unparser/corpus/literal/kwbegin.txt80
-rw-r--r--test/prism/fixtures/unparser/corpus/literal/lambda.txt13
-rw-r--r--test/prism/fixtures/unparser/corpus/literal/literal.txt91
-rw-r--r--test/prism/fixtures/unparser/corpus/literal/module.txt16
-rw-r--r--test/prism/fixtures/unparser/corpus/literal/opasgn.txt24
-rw-r--r--test/prism/fixtures/unparser/corpus/literal/pattern.txt41
-rw-r--r--test/prism/fixtures/unparser/corpus/literal/pragma.txt4
-rw-r--r--test/prism/fixtures/unparser/corpus/literal/range.txt4
-rw-r--r--test/prism/fixtures/unparser/corpus/literal/rescue.txt3
-rw-r--r--test/prism/fixtures/unparser/corpus/literal/send.txt84
-rw-r--r--test/prism/fixtures/unparser/corpus/literal/since/27.txt4
-rw-r--r--test/prism/fixtures/unparser/corpus/literal/since/30.txt4
-rw-r--r--test/prism/fixtures/unparser/corpus/literal/since/31.txt7
-rw-r--r--test/prism/fixtures/unparser/corpus/literal/since/32.txt11
-rw-r--r--test/prism/fixtures/unparser/corpus/literal/singletons.txt4
-rw-r--r--test/prism/fixtures/unparser/corpus/literal/super.txt21
-rw-r--r--test/prism/fixtures/unparser/corpus/literal/unary.txt9
-rw-r--r--test/prism/fixtures/unparser/corpus/literal/undef.txt2
-rw-r--r--test/prism/fixtures/unparser/corpus/literal/variables.txt10
-rw-r--r--test/prism/fixtures/unparser/corpus/literal/while.txt73
-rw-r--r--test/prism/fixtures/unparser/corpus/semantic/and.txt8
-rw-r--r--test/prism/fixtures/unparser/corpus/semantic/block.txt26
-rw-r--r--test/prism/fixtures/unparser/corpus/semantic/def.txt7
-rw-r--r--test/prism/fixtures/unparser/corpus/semantic/dstr.txt127
-rw-r--r--test/prism/fixtures/unparser/corpus/semantic/kwbegin.txt42
-rw-r--r--test/prism/fixtures/unparser/corpus/semantic/literal.txt14
-rw-r--r--test/prism/fixtures/unparser/corpus/semantic/opasgn.txt1
-rw-r--r--test/prism/fixtures/unparser/corpus/semantic/send.txt6
-rw-r--r--test/prism/fixtures/unparser/corpus/semantic/undef.txt2
-rw-r--r--test/prism/fixtures/unparser/corpus/semantic/while.txt25
-rw-r--r--test/prism/fixtures/until.txt13
-rw-r--r--test/prism/fixtures/variables.txt47
-rw-r--r--test/prism/fixtures/while.txt23
-rw-r--r--test/prism/fixtures/whitequark/LICENSE25
-rw-r--r--test/prism/fixtures/whitequark/__ENCODING__.txt1
-rw-r--r--test/prism/fixtures/whitequark/__ENCODING___legacy_.txt1
-rw-r--r--test/prism/fixtures/whitequark/alias.txt1
-rw-r--r--test/prism/fixtures/whitequark/alias_gvar.txt3
-rw-r--r--test/prism/fixtures/whitequark/ambiuous_quoted_label_in_ternary_operator.txt1
-rw-r--r--test/prism/fixtures/whitequark/and.txt3
-rw-r--r--test/prism/fixtures/whitequark/and_asgn.txt3
-rw-r--r--test/prism/fixtures/whitequark/and_or_masgn.txt3
-rw-r--r--test/prism/fixtures/whitequark/anonymous_blockarg.txt1
-rw-r--r--test/prism/fixtures/whitequark/arg.txt3
-rw-r--r--test/prism/fixtures/whitequark/arg_duplicate_ignored.txt3
-rw-r--r--test/prism/fixtures/whitequark/arg_label.txt6
-rw-r--r--test/prism/fixtures/whitequark/arg_scope.txt1
-rw-r--r--test/prism/fixtures/whitequark/args.txt63
-rw-r--r--test/prism/fixtures/whitequark/args_args_assocs.txt3
-rw-r--r--test/prism/fixtures/whitequark/args_args_assocs_comma.txt1
-rw-r--r--test/prism/fixtures/whitequark/args_args_comma.txt1
-rw-r--r--test/prism/fixtures/whitequark/args_args_star.txt3
-rw-r--r--test/prism/fixtures/whitequark/args_assocs_comma.txt1
-rw-r--r--test/prism/fixtures/whitequark/args_block_pass.txt1
-rw-r--r--test/prism/fixtures/whitequark/args_cmd.txt1
-rw-r--r--test/prism/fixtures/whitequark/args_star.txt3
-rw-r--r--test/prism/fixtures/whitequark/array_assocs.txt3
-rw-r--r--test/prism/fixtures/whitequark/array_plain.txt1
-rw-r--r--test/prism/fixtures/whitequark/array_splat.txt5
-rw-r--r--test/prism/fixtures/whitequark/array_symbols.txt1
-rw-r--r--test/prism/fixtures/whitequark/array_symbols_empty.txt3
-rw-r--r--test/prism/fixtures/whitequark/array_symbols_interp.txt3
-rw-r--r--test/prism/fixtures/whitequark/array_words.txt1
-rw-r--r--test/prism/fixtures/whitequark/array_words_empty.txt3
-rw-r--r--test/prism/fixtures/whitequark/array_words_interp.txt3
-rw-r--r--test/prism/fixtures/whitequark/asgn_cmd.txt3
-rw-r--r--test/prism/fixtures/whitequark/asgn_mrhs.txt5
-rw-r--r--test/prism/fixtures/whitequark/back_ref.txt1
-rw-r--r--test/prism/fixtures/whitequark/bang.txt1
-rw-r--r--test/prism/fixtures/whitequark/bang_cmd.txt1
-rw-r--r--test/prism/fixtures/whitequark/begin_cmdarg.txt1
-rw-r--r--test/prism/fixtures/whitequark/beginless_erange_after_newline.txt2
-rw-r--r--test/prism/fixtures/whitequark/beginless_irange_after_newline.txt2
-rw-r--r--test/prism/fixtures/whitequark/beginless_range.txt3
-rw-r--r--test/prism/fixtures/whitequark/blockarg.txt1
-rw-r--r--test/prism/fixtures/whitequark/blockargs.txt71
-rw-r--r--test/prism/fixtures/whitequark/bug_435.txt1
-rw-r--r--test/prism/fixtures/whitequark/bug_447.txt3
-rw-r--r--test/prism/fixtures/whitequark/bug_452.txt1
-rw-r--r--test/prism/fixtures/whitequark/bug_466.txt1
-rw-r--r--test/prism/fixtures/whitequark/bug_473.txt1
-rw-r--r--test/prism/fixtures/whitequark/bug_480.txt1
-rw-r--r--test/prism/fixtures/whitequark/bug_481.txt1
-rw-r--r--test/prism/fixtures/whitequark/bug_ascii_8bit_in_literal.txt2
-rw-r--r--test/prism/fixtures/whitequark/bug_cmd_string_lookahead.txt1
-rw-r--r--test/prism/fixtures/whitequark/bug_cmdarg.txt5
-rw-r--r--test/prism/fixtures/whitequark/bug_def_no_paren_eql_begin.txt4
-rw-r--r--test/prism/fixtures/whitequark/bug_do_block_in_call_args.txt1
-rw-r--r--test/prism/fixtures/whitequark/bug_do_block_in_cmdarg.txt1
-rw-r--r--test/prism/fixtures/whitequark/bug_do_block_in_hash_brace.txt9
-rw-r--r--test/prism/fixtures/whitequark/bug_heredoc_do.txt3
-rw-r--r--test/prism/fixtures/whitequark/bug_interp_single.txt3
-rw-r--r--test/prism/fixtures/whitequark/bug_lambda_leakage.txt1
-rw-r--r--test/prism/fixtures/whitequark/bug_regex_verification.txt1
-rw-r--r--test/prism/fixtures/whitequark/bug_rescue_empty_else.txt1
-rw-r--r--test/prism/fixtures/whitequark/bug_while_not_parens_do.txt1
-rw-r--r--test/prism/fixtures/whitequark/case_cond.txt1
-rw-r--r--test/prism/fixtures/whitequark/case_cond_else.txt1
-rw-r--r--test/prism/fixtures/whitequark/case_expr.txt1
-rw-r--r--test/prism/fixtures/whitequark/case_expr_else.txt1
-rw-r--r--test/prism/fixtures/whitequark/casgn_scoped.txt1
-rw-r--r--test/prism/fixtures/whitequark/casgn_toplevel.txt1
-rw-r--r--test/prism/fixtures/whitequark/casgn_unscoped.txt1
-rw-r--r--test/prism/fixtures/whitequark/character.txt1
-rw-r--r--test/prism/fixtures/whitequark/class.txt3
-rw-r--r--test/prism/fixtures/whitequark/class_super.txt1
-rw-r--r--test/prism/fixtures/whitequark/class_super_label.txt1
-rw-r--r--test/prism/fixtures/whitequark/comments_before_leading_dot__27.txt19
-rw-r--r--test/prism/fixtures/whitequark/complex.txt7
-rw-r--r--test/prism/fixtures/whitequark/cond_begin.txt1
-rw-r--r--test/prism/fixtures/whitequark/cond_begin_masgn.txt1
-rw-r--r--test/prism/fixtures/whitequark/cond_eflipflop.txt3
-rw-r--r--test/prism/fixtures/whitequark/cond_eflipflop_with_beginless_range.txt1
-rw-r--r--test/prism/fixtures/whitequark/cond_eflipflop_with_endless_range.txt1
-rw-r--r--test/prism/fixtures/whitequark/cond_iflipflop.txt3
-rw-r--r--test/prism/fixtures/whitequark/cond_iflipflop_with_beginless_range.txt1
-rw-r--r--test/prism/fixtures/whitequark/cond_iflipflop_with_endless_range.txt1
-rw-r--r--test/prism/fixtures/whitequark/cond_match_current_line.txt3
-rw-r--r--test/prism/fixtures/whitequark/const_op_asgn.txt9
-rw-r--r--test/prism/fixtures/whitequark/const_scoped.txt1
-rw-r--r--test/prism/fixtures/whitequark/const_toplevel.txt1
-rw-r--r--test/prism/fixtures/whitequark/const_unscoped.txt1
-rw-r--r--test/prism/fixtures/whitequark/cpath.txt3
-rw-r--r--test/prism/fixtures/whitequark/cvar.txt1
-rw-r--r--test/prism/fixtures/whitequark/cvasgn.txt1
-rw-r--r--test/prism/fixtures/whitequark/dedenting_heredoc.txt75
-rw-r--r--test/prism/fixtures/whitequark/dedenting_interpolating_heredoc_fake_line_continuation.txt4
-rw-r--r--test/prism/fixtures/whitequark/dedenting_non_interpolating_heredoc_line_continuation.txt4
-rw-r--r--test/prism/fixtures/whitequark/def.txt11
-rw-r--r--test/prism/fixtures/whitequark/defined.txt5
-rw-r--r--test/prism/fixtures/whitequark/defs.txt9
-rw-r--r--test/prism/fixtures/whitequark/empty_stmt.txt1
-rw-r--r--test/prism/fixtures/whitequark/endless_comparison_method.txt11
-rw-r--r--test/prism/fixtures/whitequark/endless_method.txt7
-rw-r--r--test/prism/fixtures/whitequark/endless_method_command_syntax.txt15
-rw-r--r--test/prism/fixtures/whitequark/endless_method_forwarded_args_legacy.txt1
-rw-r--r--test/prism/fixtures/whitequark/endless_method_with_rescue_mod.txt3
-rw-r--r--test/prism/fixtures/whitequark/endless_method_without_args.txt7
-rw-r--r--test/prism/fixtures/whitequark/ensure.txt1
-rw-r--r--test/prism/fixtures/whitequark/ensure_empty.txt1
-rw-r--r--test/prism/fixtures/whitequark/false.txt1
-rw-r--r--test/prism/fixtures/whitequark/float.txt3
-rw-r--r--test/prism/fixtures/whitequark/for.txt3
-rw-r--r--test/prism/fixtures/whitequark/for_mlhs.txt1
-rw-r--r--test/prism/fixtures/whitequark/forward_arg.txt1
-rw-r--r--test/prism/fixtures/whitequark/forward_arg_with_open_args.txt27
-rw-r--r--test/prism/fixtures/whitequark/forward_args_legacy.txt5
-rw-r--r--test/prism/fixtures/whitequark/forwarded_argument_with_kwrestarg.txt1
-rw-r--r--test/prism/fixtures/whitequark/forwarded_argument_with_restarg.txt1
-rw-r--r--test/prism/fixtures/whitequark/forwarded_kwrestarg.txt1
-rw-r--r--test/prism/fixtures/whitequark/forwarded_kwrestarg_with_additional_kwarg.txt1
-rw-r--r--test/prism/fixtures/whitequark/forwarded_restarg.txt1
-rw-r--r--test/prism/fixtures/whitequark/gvar.txt1
-rw-r--r--test/prism/fixtures/whitequark/gvasgn.txt1
-rw-r--r--test/prism/fixtures/whitequark/hash_empty.txt1
-rw-r--r--test/prism/fixtures/whitequark/hash_hashrocket.txt3
-rw-r--r--test/prism/fixtures/whitequark/hash_kwsplat.txt1
-rw-r--r--test/prism/fixtures/whitequark/hash_label.txt1
-rw-r--r--test/prism/fixtures/whitequark/hash_label_end.txt5
-rw-r--r--test/prism/fixtures/whitequark/hash_pair_value_omission.txt5
-rw-r--r--test/prism/fixtures/whitequark/heredoc.txt14
-rw-r--r--test/prism/fixtures/whitequark/if.txt3
-rw-r--r--test/prism/fixtures/whitequark/if_else.txt3
-rw-r--r--test/prism/fixtures/whitequark/if_elsif.txt1
-rw-r--r--test/prism/fixtures/whitequark/if_masgn__24.txt1
-rw-r--r--test/prism/fixtures/whitequark/if_mod.txt1
-rw-r--r--test/prism/fixtures/whitequark/if_nl_then.txt2
-rw-r--r--test/prism/fixtures/whitequark/int.txt5
-rw-r--r--test/prism/fixtures/whitequark/int___LINE__.txt1
-rw-r--r--test/prism/fixtures/whitequark/interp_digit_var.txt87
-rw-r--r--test/prism/fixtures/whitequark/ivar.txt1
-rw-r--r--test/prism/fixtures/whitequark/ivasgn.txt1
-rw-r--r--test/prism/fixtures/whitequark/keyword_argument_omission.txt1
-rw-r--r--test/prism/fixtures/whitequark/kwarg.txt1
-rw-r--r--test/prism/fixtures/whitequark/kwbegin_compstmt.txt1
-rw-r--r--test/prism/fixtures/whitequark/kwnilarg.txt5
-rw-r--r--test/prism/fixtures/whitequark/kwoptarg.txt1
-rw-r--r--test/prism/fixtures/whitequark/kwoptarg_with_kwrestarg_and_forwarded_args.txt1
-rw-r--r--test/prism/fixtures/whitequark/kwrestarg_named.txt1
-rw-r--r--test/prism/fixtures/whitequark/kwrestarg_unnamed.txt1
-rw-r--r--test/prism/fixtures/whitequark/lbrace_arg_after_command_args.txt1
-rw-r--r--test/prism/fixtures/whitequark/lparenarg_after_lvar__since_25.txt3
-rw-r--r--test/prism/fixtures/whitequark/lvar.txt1
-rw-r--r--test/prism/fixtures/whitequark/lvar_injecting_match.txt1
-rw-r--r--test/prism/fixtures/whitequark/lvasgn.txt1
-rw-r--r--test/prism/fixtures/whitequark/masgn.txt5
-rw-r--r--test/prism/fixtures/whitequark/masgn_attr.txt5
-rw-r--r--test/prism/fixtures/whitequark/masgn_cmd.txt1
-rw-r--r--test/prism/fixtures/whitequark/masgn_const.txt3
-rw-r--r--test/prism/fixtures/whitequark/masgn_nested.txt3
-rw-r--r--test/prism/fixtures/whitequark/masgn_splat.txt19
-rw-r--r--test/prism/fixtures/whitequark/method_definition_in_while_cond.txt7
-rw-r--r--test/prism/fixtures/whitequark/module.txt1
-rw-r--r--test/prism/fixtures/whitequark/multiple_pattern_matches.txt5
-rw-r--r--test/prism/fixtures/whitequark/newline_in_hash_argument.txt14
-rw-r--r--test/prism/fixtures/whitequark/nil.txt1
-rw-r--r--test/prism/fixtures/whitequark/nil_expression.txt3
-rw-r--r--test/prism/fixtures/whitequark/non_lvar_injecting_match.txt1
-rw-r--r--test/prism/fixtures/whitequark/not.txt5
-rw-r--r--test/prism/fixtures/whitequark/not_cmd.txt1
-rw-r--r--test/prism/fixtures/whitequark/not_masgn__24.txt1
-rw-r--r--test/prism/fixtures/whitequark/nth_ref.txt1
-rw-r--r--test/prism/fixtures/whitequark/numbered_args_after_27.txt7
-rw-r--r--test/prism/fixtures/whitequark/numparam_outside_block.txt9
-rw-r--r--test/prism/fixtures/whitequark/numparam_ruby_bug_19025.txt1
-rw-r--r--test/prism/fixtures/whitequark/op_asgn.txt5
-rw-r--r--test/prism/fixtures/whitequark/op_asgn_cmd.txt7
-rw-r--r--test/prism/fixtures/whitequark/op_asgn_index.txt1
-rw-r--r--test/prism/fixtures/whitequark/op_asgn_index_cmd.txt1
-rw-r--r--test/prism/fixtures/whitequark/optarg.txt3
-rw-r--r--test/prism/fixtures/whitequark/or.txt3
-rw-r--r--test/prism/fixtures/whitequark/or_asgn.txt3
-rw-r--r--test/prism/fixtures/whitequark/parser_bug_272.txt1
-rw-r--r--test/prism/fixtures/whitequark/parser_bug_490.txt5
-rw-r--r--test/prism/fixtures/whitequark/parser_bug_507.txt1
-rw-r--r--test/prism/fixtures/whitequark/parser_bug_518.txt2
-rw-r--r--test/prism/fixtures/whitequark/parser_bug_525.txt1
-rw-r--r--test/prism/fixtures/whitequark/parser_bug_604.txt1
-rw-r--r--test/prism/fixtures/whitequark/parser_bug_640.txt4
-rw-r--r--test/prism/fixtures/whitequark/parser_bug_645.txt1
-rw-r--r--test/prism/fixtures/whitequark/parser_bug_830.txt1
-rw-r--r--test/prism/fixtures/whitequark/parser_bug_989.txt3
-rw-r--r--test/prism/fixtures/whitequark/parser_drops_truncated_parts_of_squiggly_heredoc.txt3
-rw-r--r--test/prism/fixtures/whitequark/parser_slash_slash_n_escaping_in_literals.txt62
-rw-r--r--test/prism/fixtures/whitequark/pattern_matching__FILE__LINE_literals.txt4
-rw-r--r--test/prism/fixtures/whitequark/pattern_matching_blank_else.txt1
-rw-r--r--test/prism/fixtures/whitequark/pattern_matching_else.txt1
-rw-r--r--test/prism/fixtures/whitequark/pattern_matching_single_line.txt3
-rw-r--r--test/prism/fixtures/whitequark/pattern_matching_single_line_allowed_omission_of_parentheses.txt11
-rw-r--r--test/prism/fixtures/whitequark/postexe.txt1
-rw-r--r--test/prism/fixtures/whitequark/preexe.txt1
-rw-r--r--test/prism/fixtures/whitequark/procarg0.txt3
-rw-r--r--test/prism/fixtures/whitequark/range_exclusive.txt1
-rw-r--r--test/prism/fixtures/whitequark/range_inclusive.txt1
-rw-r--r--test/prism/fixtures/whitequark/rational.txt3
-rw-r--r--test/prism/fixtures/whitequark/regex_interp.txt1
-rw-r--r--test/prism/fixtures/whitequark/regex_plain.txt1
-rw-r--r--test/prism/fixtures/whitequark/resbody_list.txt1
-rw-r--r--test/prism/fixtures/whitequark/resbody_list_mrhs.txt1
-rw-r--r--test/prism/fixtures/whitequark/resbody_list_var.txt1
-rw-r--r--test/prism/fixtures/whitequark/resbody_var.txt3
-rw-r--r--test/prism/fixtures/whitequark/rescue.txt1
-rw-r--r--test/prism/fixtures/whitequark/rescue_else.txt1
-rw-r--r--test/prism/fixtures/whitequark/rescue_else_ensure.txt1
-rw-r--r--test/prism/fixtures/whitequark/rescue_ensure.txt1
-rw-r--r--test/prism/fixtures/whitequark/rescue_in_lambda_block.txt1
-rw-r--r--test/prism/fixtures/whitequark/rescue_mod.txt1
-rw-r--r--test/prism/fixtures/whitequark/rescue_mod_asgn.txt1
-rw-r--r--test/prism/fixtures/whitequark/rescue_mod_masgn.txt1
-rw-r--r--test/prism/fixtures/whitequark/rescue_mod_op_assign.txt1
-rw-r--r--test/prism/fixtures/whitequark/rescue_without_begin_end.txt1
-rw-r--r--test/prism/fixtures/whitequark/restarg_named.txt1
-rw-r--r--test/prism/fixtures/whitequark/restarg_unnamed.txt1
-rw-r--r--test/prism/fixtures/whitequark/return.txt7
-rw-r--r--test/prism/fixtures/whitequark/return_block.txt1
-rw-r--r--test/prism/fixtures/whitequark/ruby_bug_10279.txt1
-rw-r--r--test/prism/fixtures/whitequark/ruby_bug_10653.txt5
-rw-r--r--test/prism/fixtures/whitequark/ruby_bug_11107.txt1
-rw-r--r--test/prism/fixtures/whitequark/ruby_bug_11380.txt1
-rw-r--r--test/prism/fixtures/whitequark/ruby_bug_11873.txt23
-rw-r--r--test/prism/fixtures/whitequark/ruby_bug_11873_a.txt39
-rw-r--r--test/prism/fixtures/whitequark/ruby_bug_11873_b.txt1
-rw-r--r--test/prism/fixtures/whitequark/ruby_bug_11989.txt3
-rw-r--r--test/prism/fixtures/whitequark/ruby_bug_11990.txt3
-rw-r--r--test/prism/fixtures/whitequark/ruby_bug_12073.txt3
-rw-r--r--test/prism/fixtures/whitequark/ruby_bug_12402.txt27
-rw-r--r--test/prism/fixtures/whitequark/ruby_bug_12669.txt7
-rw-r--r--test/prism/fixtures/whitequark/ruby_bug_12686.txt1
-rw-r--r--test/prism/fixtures/whitequark/ruby_bug_13547.txt1
-rw-r--r--test/prism/fixtures/whitequark/ruby_bug_14690.txt1
-rw-r--r--test/prism/fixtures/whitequark/ruby_bug_15789.txt3
-rw-r--r--test/prism/fixtures/whitequark/ruby_bug_9669.txt8
-rw-r--r--test/prism/fixtures/whitequark/sclass.txt1
-rw-r--r--test/prism/fixtures/whitequark/self.txt1
-rw-r--r--test/prism/fixtures/whitequark/send_attr_asgn.txt7
-rw-r--r--test/prism/fixtures/whitequark/send_attr_asgn_conditional.txt1
-rw-r--r--test/prism/fixtures/whitequark/send_binary_op.txt41
-rw-r--r--test/prism/fixtures/whitequark/send_block_chain_cmd.txt13
-rw-r--r--test/prism/fixtures/whitequark/send_block_conditional.txt1
-rw-r--r--test/prism/fixtures/whitequark/send_call.txt3
-rw-r--r--test/prism/fixtures/whitequark/send_conditional.txt1
-rw-r--r--test/prism/fixtures/whitequark/send_index.txt1
-rw-r--r--test/prism/fixtures/whitequark/send_index_asgn.txt1
-rw-r--r--test/prism/fixtures/whitequark/send_index_asgn_legacy.txt1
-rw-r--r--test/prism/fixtures/whitequark/send_index_cmd.txt1
-rw-r--r--test/prism/fixtures/whitequark/send_index_legacy.txt1
-rw-r--r--test/prism/fixtures/whitequark/send_lambda.txt5
-rw-r--r--test/prism/fixtures/whitequark/send_lambda_args.txt3
-rw-r--r--test/prism/fixtures/whitequark/send_lambda_args_noparen.txt3
-rw-r--r--test/prism/fixtures/whitequark/send_lambda_args_shadow.txt1
-rw-r--r--test/prism/fixtures/whitequark/send_lambda_legacy.txt1
-rw-r--r--test/prism/fixtures/whitequark/send_op_asgn_conditional.txt1
-rw-r--r--test/prism/fixtures/whitequark/send_plain.txt5
-rw-r--r--test/prism/fixtures/whitequark/send_plain_cmd.txt5
-rw-r--r--test/prism/fixtures/whitequark/send_self.txt5
-rw-r--r--test/prism/fixtures/whitequark/send_self_block.txt7
-rw-r--r--test/prism/fixtures/whitequark/send_unary_op.txt5
-rw-r--r--test/prism/fixtures/whitequark/slash_newline_in_heredocs.txt13
-rw-r--r--test/prism/fixtures/whitequark/space_args_arg.txt1
-rw-r--r--test/prism/fixtures/whitequark/space_args_arg_block.txt5
-rw-r--r--test/prism/fixtures/whitequark/space_args_arg_call.txt1
-rw-r--r--test/prism/fixtures/whitequark/space_args_arg_newline.txt2
-rw-r--r--test/prism/fixtures/whitequark/space_args_block.txt1
-rw-r--r--test/prism/fixtures/whitequark/space_args_cmd.txt1
-rw-r--r--test/prism/fixtures/whitequark/string___FILE__.txt1
-rw-r--r--test/prism/fixtures/whitequark/string_concat.txt1
-rw-r--r--test/prism/fixtures/whitequark/string_dvar.txt1
-rw-r--r--test/prism/fixtures/whitequark/string_interp.txt1
-rw-r--r--test/prism/fixtures/whitequark/string_plain.txt3
-rw-r--r--test/prism/fixtures/whitequark/super.txt5
-rw-r--r--test/prism/fixtures/whitequark/super_block.txt3
-rw-r--r--test/prism/fixtures/whitequark/symbol_interp.txt1
-rw-r--r--test/prism/fixtures/whitequark/symbol_plain.txt3
-rw-r--r--test/prism/fixtures/whitequark/ternary.txt1
-rw-r--r--test/prism/fixtures/whitequark/ternary_ambiguous_symbol.txt1
-rw-r--r--test/prism/fixtures/whitequark/trailing_forward_arg.txt1
-rw-r--r--test/prism/fixtures/whitequark/true.txt1
-rw-r--r--test/prism/fixtures/whitequark/unary_num_pow_precedence.txt5
-rw-r--r--test/prism/fixtures/whitequark/undef.txt1
-rw-r--r--test/prism/fixtures/whitequark/unless.txt3
-rw-r--r--test/prism/fixtures/whitequark/unless_else.txt3
-rw-r--r--test/prism/fixtures/whitequark/unless_mod.txt1
-rw-r--r--test/prism/fixtures/whitequark/until.txt3
-rw-r--r--test/prism/fixtures/whitequark/until_mod.txt1
-rw-r--r--test/prism/fixtures/whitequark/until_post.txt1
-rw-r--r--test/prism/fixtures/whitequark/var_and_asgn.txt1
-rw-r--r--test/prism/fixtures/whitequark/var_op_asgn.txt7
-rw-r--r--test/prism/fixtures/whitequark/var_op_asgn_cmd.txt1
-rw-r--r--test/prism/fixtures/whitequark/var_or_asgn.txt1
-rw-r--r--test/prism/fixtures/whitequark/when_multi.txt1
-rw-r--r--test/prism/fixtures/whitequark/when_splat.txt1
-rw-r--r--test/prism/fixtures/whitequark/when_then.txt1
-rw-r--r--test/prism/fixtures/whitequark/while.txt3
-rw-r--r--test/prism/fixtures/whitequark/while_mod.txt1
-rw-r--r--test/prism/fixtures/whitequark/while_post.txt1
-rw-r--r--test/prism/fixtures/whitequark/xstring_interp.txt1
-rw-r--r--test/prism/fixtures/whitequark/xstring_plain.txt1
-rw-r--r--test/prism/fixtures/whitequark/zsuper.txt1
-rw-r--r--test/prism/fixtures/xstring.txt13
-rw-r--r--test/prism/fixtures/xstring_with_backslash.txt1
-rw-r--r--test/prism/fixtures/yield.txt7
-rw-r--r--test/prism/fixtures_test.rb21
-rw-r--r--test/prism/fuzzer_test.rb67
-rw-r--r--test/prism/heredoc_dedent_test.rb134
-rw-r--r--test/prism/lex_test.rb90
-rw-r--r--test/prism/library_symbols_test.rb104
-rw-r--r--test/prism/locals_test.rb238
-rw-r--r--test/prism/magic_comment_test.rb110
-rw-r--r--test/prism/newline_offsets_test.rb22
-rw-r--r--test/prism/newline_test.rb98
-rw-r--r--test/prism/onigmo_test.rb66
-rw-r--r--test/prism/regexp_test.rb261
-rw-r--r--test/prism/result/attribute_write_test.rb56
-rw-r--r--test/prism/result/breadth_first_search_test.rb18
-rw-r--r--test/prism/result/comments_test.rb138
-rw-r--r--test/prism/result/constant_path_node_test.rb91
-rw-r--r--test/prism/result/equality_test.rb22
-rw-r--r--test/prism/result/heredoc_test.rb19
-rw-r--r--test/prism/result/implicit_array_test.rb59
-rw-r--r--test/prism/result/index_write_test.rb89
-rw-r--r--test/prism/result/integer_base_flags_test.rb33
-rw-r--r--test/prism/result/integer_parse_test.rb41
-rw-r--r--test/prism/result/node_id_test.rb27
-rw-r--r--test/prism/result/numeric_value_test.rb21
-rw-r--r--test/prism/result/overlap_test.rb43
-rw-r--r--test/prism/result/regular_expression_options_test.rb25
-rw-r--r--test/prism/result/source_location_test.rb950
-rw-r--r--test/prism/result/static_inspect_test.rb89
-rw-r--r--test/prism/result/static_literals_test.rb92
-rw-r--r--test/prism/result/warnings_test.rb430
-rw-r--r--test/prism/ruby/compiler_test.rb31
-rw-r--r--test/prism/ruby/desugar_compiler_test.rb80
-rw-r--r--test/prism/ruby/dispatcher_test.rb46
-rw-r--r--test/prism/ruby/location_test.rb173
-rw-r--r--test/prism/ruby/parameters_signature_test.rb91
-rw-r--r--test/prism/ruby/parser_test.rb291
-rw-r--r--test/prism/ruby/pattern_test.rb132
-rw-r--r--test/prism/ruby/reflection_test.rb22
-rw-r--r--test/prism/ruby/ripper_test.rb62
-rw-r--r--test/prism/ruby/ruby_parser_test.rb127
-rw-r--r--test/prism/ruby/tunnel_test.rb26
-rw-r--r--test/prism/snippets_test.rb42
-rw-r--r--test/prism/test_helper.rb323
-rw-r--r--test/prism/unescape_test.rb240
-rw-r--r--test/prism/version_test.rb11
-rw-r--r--test/psych/helper.rb6
-rw-r--r--test/psych/test_array.rb16
-rw-r--r--test/psych/test_coder.rb6
-rw-r--r--test/psych/test_date_time.rb20
-rw-r--r--test/psych/test_encoding.rb11
-rw-r--r--test/psych/test_hash.rb64
-rw-r--r--test/psych/test_merge_keys.rb2
-rw-r--r--test/psych/test_numeric.rb20
-rw-r--r--test/psych/test_object.rb13
-rw-r--r--test/psych/test_object_references.rb8
-rw-r--r--test/psych/test_parser.rb31
-rw-r--r--test/psych/test_psych.rb33
-rw-r--r--test/psych/test_safe_load.rb31
-rw-r--r--test/psych/test_scalar_scanner.rb38
-rw-r--r--test/psych/test_set.rb7
-rw-r--r--test/psych/test_string.rb12
-rw-r--r--test/psych/test_yaml.rb904
-rw-r--r--test/psych/visitors/test_emitter.rb16
-rw-r--r--test/psych/visitors/test_to_ruby.rb2
-rw-r--r--test/psych/visitors/test_yaml_tree.rb8
-rw-r--r--test/racc/assets/cadenza.y170
-rw-r--r--test/racc/assets/cast.y926
-rw-r--r--test/racc/assets/chk.y126
-rw-r--r--test/racc/assets/conf.y16
-rw-r--r--test/racc/assets/csspool.y729
-rw-r--r--test/racc/assets/digraph.y29
-rw-r--r--test/racc/assets/echk.y118
-rw-r--r--test/racc/assets/edtf.y583
-rw-r--r--test/racc/assets/err.y60
-rw-r--r--test/racc/assets/error_recovery.y35
-rw-r--r--test/racc/assets/expect.y7
-rw-r--r--test/racc/assets/firstline.y4
-rw-r--r--test/racc/assets/huia.y318
-rw-r--r--test/racc/assets/ichk.y102
-rw-r--r--test/racc/assets/ifelse.y14
-rw-r--r--test/racc/assets/intp.y546
-rw-r--r--test/racc/assets/journey.y47
-rw-r--r--test/racc/assets/liquor.y313
-rw-r--r--test/racc/assets/machete.y423
-rw-r--r--test/racc/assets/macruby.y2197
-rw-r--r--test/racc/assets/mailp.y437
-rw-r--r--test/racc/assets/mediacloth.y599
-rw-r--r--test/racc/assets/mof.y649
-rw-r--r--test/racc/assets/namae.y302
-rw-r--r--test/racc/assets/nasl.y626
-rw-r--r--test/racc/assets/newsyn.y25
-rw-r--r--test/racc/assets/noend.y4
-rw-r--r--test/racc/assets/nokogiri-css.y255
-rw-r--r--test/racc/assets/nonass.y41
-rw-r--r--test/racc/assets/normal.y27
-rw-r--r--test/racc/assets/norule.y4
-rw-r--r--test/racc/assets/nullbug1.y25
-rw-r--r--test/racc/assets/nullbug2.y15
-rw-r--r--test/racc/assets/opal.y1807
-rw-r--r--test/racc/assets/opt.y123
-rw-r--r--test/racc/assets/percent.y35
-rw-r--r--test/racc/assets/php_serialization.y98
-rw-r--r--test/racc/assets/recv.y97
-rw-r--r--test/racc/assets/riml.y665
-rw-r--r--test/racc/assets/rrconf.y14
-rw-r--r--test/racc/assets/ruby18.y1943
-rw-r--r--test/racc/assets/ruby19.y2174
-rw-r--r--test/racc/assets/ruby20.y2350
-rw-r--r--test/racc/assets/ruby21.y2359
-rw-r--r--test/racc/assets/ruby22.y2381
-rw-r--r--test/racc/assets/scan.y72
-rw-r--r--test/racc/assets/syntax.y50
-rw-r--r--test/racc/assets/tp_plus.y622
-rw-r--r--test/racc/assets/twowaysql.y278
-rw-r--r--test/racc/assets/unterm.y5
-rw-r--r--test/racc/assets/useless.y12
-rw-r--r--test/racc/assets/yyerr.y46
-rw-r--r--test/racc/bench.y36
-rw-r--r--test/racc/case.rb110
-rw-r--r--test/racc/infini.y8
-rw-r--r--test/racc/regress/README.txt7
-rw-r--r--test/racc/regress/cadenza796
-rw-r--r--test/racc/regress/cast3945
-rw-r--r--test/racc/regress/csspool2314
-rw-r--r--test/racc/regress/edtf1794
-rw-r--r--test/racc/regress/huia1681
-rw-r--r--test/racc/regress/journey222
-rw-r--r--test/racc/regress/liquor885
-rw-r--r--test/racc/regress/machete833
-rw-r--r--test/racc/regress/mediacloth1463
-rw-r--r--test/racc/regress/mof1368
-rw-r--r--test/racc/regress/namae634
-rw-r--r--test/racc/regress/nasl2548
-rw-r--r--test/racc/regress/nokogiri-css836
-rw-r--r--test/racc/regress/opal10107
-rw-r--r--test/racc/regress/php_serialization336
-rw-r--r--test/racc/regress/riml4037
-rw-r--r--test/racc/regress/ruby189945
-rw-r--r--test/racc/regress/ruby2211180
-rw-r--r--test/racc/regress/tp_plus1933
-rw-r--r--test/racc/regress/twowaysql556
-rw-r--r--test/racc/scandata/brace7
-rw-r--r--test/racc/scandata/gvar1
-rw-r--r--test/racc/scandata/normal4
-rw-r--r--test/racc/scandata/percent18
-rw-r--r--test/racc/scandata/slash10
-rw-r--r--test/racc/src.intp34
-rw-r--r--test/racc/start.y20
-rw-r--r--test/racc/test_chk_y.rb52
-rw-r--r--test/racc/test_grammar_file_parser.rb15
-rw-r--r--test/racc/test_racc_command.rb339
-rw-r--r--test/racc/test_scan_y.rb52
-rw-r--r--test/racc/testscanner.rb51
-rw-r--r--test/rdoc/MarkdownTest_1.0.3/Markdown Documentation - Syntax.text2
-rw-r--r--test/rdoc/MarkdownTest_1.0.3/Tidiness.text (renamed from test/rdoc/MarkdownTest_1.0.3/Tidyness.text)0
-rw-r--r--test/rdoc/helper.rb6
-rw-r--r--test/rdoc/support/test_case.rb6
-rw-r--r--test/rdoc/support/text_formatter_test_case.rb1
-rw-r--r--test/rdoc/test_rdoc_alias.rb3
-rw-r--r--test/rdoc/test_rdoc_any_method.rb102
-rw-r--r--test/rdoc/test_rdoc_class_module.rb11
-rw-r--r--test/rdoc/test_rdoc_code_object.rb2
-rw-r--r--test/rdoc/test_rdoc_comment.rb9
-rw-r--r--test/rdoc/test_rdoc_constant.rb2
-rw-r--r--test/rdoc/test_rdoc_context.rb10
-rw-r--r--test/rdoc/test_rdoc_context_section.rb1
-rw-r--r--test/rdoc/test_rdoc_cross_reference.rb58
-rw-r--r--test/rdoc/test_rdoc_extend.rb11
-rw-r--r--test/rdoc/test_rdoc_generator_darkfish.rb109
-rw-r--r--test/rdoc/test_rdoc_generator_json_index.rb14
-rw-r--r--test/rdoc/test_rdoc_generator_markup.rb1
-rw-r--r--test/rdoc/test_rdoc_include.rb14
-rw-r--r--test/rdoc/test_rdoc_markdown.rb63
-rw-r--r--test/rdoc/test_rdoc_markdown_test.rb10
-rw-r--r--test/rdoc/test_rdoc_markup.rb1
-rw-r--r--test/rdoc/test_rdoc_markup_attribute_manager.rb3
-rw-r--r--test/rdoc/test_rdoc_markup_attributes.rb1
-rw-r--r--test/rdoc/test_rdoc_markup_document.rb1
-rw-r--r--test/rdoc/test_rdoc_markup_formatter.rb6
-rw-r--r--test/rdoc/test_rdoc_markup_hard_break.rb1
-rw-r--r--test/rdoc/test_rdoc_markup_heading.rb1
-rw-r--r--test/rdoc/test_rdoc_markup_include.rb1
-rw-r--r--test/rdoc/test_rdoc_markup_indented_paragraph.rb1
-rw-r--r--test/rdoc/test_rdoc_markup_paragraph.rb1
-rw-r--r--test/rdoc/test_rdoc_markup_raw.rb1
-rw-r--r--test/rdoc/test_rdoc_markup_to_ansi.rb1
-rw-r--r--test/rdoc/test_rdoc_markup_to_html.rb142
-rw-r--r--test/rdoc/test_rdoc_markup_to_html_crossref.rb21
-rw-r--r--test/rdoc/test_rdoc_markup_to_joined_paragraph.rb1
-rw-r--r--test/rdoc/test_rdoc_markup_to_label.rb1
-rw-r--r--test/rdoc/test_rdoc_markup_to_markdown.rb8
-rw-r--r--test/rdoc/test_rdoc_markup_to_rdoc.rb19
-rw-r--r--test/rdoc/test_rdoc_markup_to_table_of_contents.rb1
-rw-r--r--test/rdoc/test_rdoc_markup_to_tt_only.rb1
-rw-r--r--test/rdoc/test_rdoc_markup_verbatim.rb1
-rw-r--r--test/rdoc/test_rdoc_method_attr.rb3
-rw-r--r--test/rdoc/test_rdoc_normal_class.rb7
-rw-r--r--test/rdoc/test_rdoc_normal_module.rb3
-rw-r--r--test/rdoc/test_rdoc_options.rb108
-rw-r--r--test/rdoc/test_rdoc_parser.rb87
-rw-r--r--test/rdoc/test_rdoc_parser_c.rb310
-rw-r--r--test/rdoc/test_rdoc_parser_changelog.rb1
-rw-r--r--test/rdoc/test_rdoc_parser_markdown.rb1
-rw-r--r--test/rdoc/test_rdoc_parser_prism_ruby.rb1997
-rw-r--r--test/rdoc/test_rdoc_parser_rd.rb1
-rw-r--r--test/rdoc/test_rdoc_parser_ruby.rb62
-rw-r--r--test/rdoc/test_rdoc_parser_simple.rb1
-rw-r--r--test/rdoc/test_rdoc_rd.rb1
-rw-r--r--test/rdoc/test_rdoc_rd_block_parser.rb21
-rw-r--r--test/rdoc/test_rdoc_rd_inline.rb1
-rw-r--r--test/rdoc/test_rdoc_rdoc.rb59
-rw-r--r--test/rdoc/test_rdoc_require.rb3
-rw-r--r--test/rdoc/test_rdoc_ri_driver.rb51
-rw-r--r--test/rdoc/test_rdoc_ri_paths.rb1
-rw-r--r--test/rdoc/test_rdoc_rubygems_hook.rb10
-rw-r--r--test/rdoc/test_rdoc_single_class.rb1
-rw-r--r--test/rdoc/test_rdoc_stats.rb1
-rw-r--r--test/rdoc/test_rdoc_store.rb19
-rw-r--r--test/rdoc/test_rdoc_task.rb10
-rw-r--r--test/rdoc/test_rdoc_token_stream.rb53
-rw-r--r--test/rdoc/test_rdoc_top_level.rb7
-rw-r--r--test/rdoc/xref_data.rb30
-rw-r--r--test/rdoc/xref_test_case.rb9
-rw-r--r--test/readline/helper.rb29
-rw-r--r--test/readline/test_readline.rb930
-rw-r--r--test/readline/test_readline_history.rb292
-rw-r--r--test/reline/helper.rb132
-rw-r--r--test/reline/test_ansi_with_terminfo.rb112
-rw-r--r--test/reline/test_ansi_without_terminfo.rb77
-rw-r--r--test/reline/test_config.rb277
-rw-r--r--test/reline/test_face.rb257
-rw-r--r--test/reline/test_history.rb2
-rw-r--r--test/reline/test_key_actor_emacs.rb2060
-rw-r--r--test/reline/test_key_actor_vi.rb1344
-rw-r--r--test/reline/test_key_stroke.rb68
-rw-r--r--test/reline/test_line_editor.rb183
-rw-r--r--test/reline/test_macro.rb3
-rw-r--r--test/reline/test_reline.rb219
-rw-r--r--test/reline/test_reline_key.rb11
-rw-r--r--test/reline/test_string_processing.rb14
-rw-r--r--test/reline/test_terminfo.rb39
-rw-r--r--test/reline/test_unicode.rb67
-rw-r--r--test/reline/test_within_pipe.rb9
-rwxr-xr-xtest/reline/yamatanooroti/multiline_repl141
-rw-r--r--test/reline/yamatanooroti/termination_checker.rb38
-rw-r--r--test/reline/yamatanooroti/test_rendering.rb990
-rw-r--r--test/resolv/test_addr.rb4
-rw-r--r--test/resolv/test_dns.rb370
-rw-r--r--test/resolv/test_resource.rb76
-rw-r--r--test/resolv/test_svcb_https.rb231
-rw-r--r--test/rinda/test_rinda.rb894
-rw-r--r--test/rinda/test_tuplebag.rb173
-rw-r--r--test/ripper/assert_parse_files.rb25
-rw-r--r--test/ripper/dummyparser.rb53
-rw-r--r--test/ripper/test_lexer.rb288
-rw-r--r--test/ripper/test_parser_events.rb187
-rw-r--r--test/ripper/test_ripper.rb39
-rw-r--r--test/ripper/test_scanner_events.rb72
-rw-r--r--test/ripper/test_sexp.rb54
-rw-r--r--test/ruby/enc/test_case_comprehensive.rb4
-rw-r--r--test/ruby/enc/test_case_mapping.rb10
-rw-r--r--test/ruby/enc/test_case_options.rb12
-rw-r--r--test/ruby/enc/test_cesu8.rb4
-rw-r--r--test/ruby/enc/test_emoji_breaks.rb208
-rw-r--r--test/ruby/enc/test_grapheme_breaks.rb117
-rw-r--r--test/ruby/enc/test_regex_casefold.rb4
-rw-r--r--test/ruby/rjit/test_assembler.rb368
-rw-r--r--test/ruby/test_alias.rb39
-rw-r--r--test/ruby/test_allocation.rb842
-rw-r--r--test/ruby/test_argf.rb125
-rw-r--r--test/ruby/test_arity.rb43
-rw-r--r--test/ruby/test_array.rb186
-rw-r--r--test/ruby/test_assignment.rb108
-rw-r--r--test/ruby/test_ast.rb995
-rw-r--r--test/ruby/test_autoload.rb135
-rw-r--r--test/ruby/test_backtrace.rb89
-rw-r--r--test/ruby/test_beginendblock.rb14
-rw-r--r--test/ruby/test_bignum.rb19
-rw-r--r--test/ruby/test_call.rb1287
-rw-r--r--test/ruby/test_case.rb9
-rw-r--r--test/ruby/test_class.rb108
-rw-r--r--test/ruby/test_clone.rb53
-rw-r--r--test/ruby/test_comparable.rb10
-rw-r--r--test/ruby/test_compile_prism.rb2637
-rw-r--r--test/ruby/test_complex.rb207
-rw-r--r--test/ruby/test_complex2.rb2
-rw-r--r--test/ruby/test_complexrational.rb4
-rw-r--r--test/ruby/test_continuation.rb4
-rw-r--r--test/ruby/test_data.rb283
-rw-r--r--test/ruby/test_default_gems.rb21
-rw-r--r--test/ruby/test_defined.rb61
-rw-r--r--test/ruby/test_dir.rb216
-rw-r--r--test/ruby/test_dir_m17n.rb46
-rw-r--r--test/ruby/test_dup.rb110
-rw-r--r--test/ruby/test_econv.rb2
-rw-r--r--test/ruby/test_encoding.rb35
-rw-r--r--test/ruby/test_enum.rb47
-rw-r--r--test/ruby/test_enumerator.rb137
-rw-r--r--test/ruby/test_env.rb882
-rw-r--r--test/ruby/test_eval.rb83
-rw-r--r--test/ruby/test_exception.rb286
-rw-r--r--test/ruby/test_fiber.rb33
-rw-r--r--test/ruby/test_file.rb379
-rw-r--r--test/ruby/test_file_exhaustive.rb122
-rw-r--r--test/ruby/test_float.rb54
-rw-r--r--test/ruby/test_frozen.rb30
-rw-r--r--test/ruby/test_gc.rb536
-rw-r--r--test/ruby/test_gc_compact.rb380
-rw-r--r--test/ruby/test_hash.rb782
-rw-r--r--test/ruby/test_inlinecache.rb2
-rw-r--r--test/ruby/test_integer.rb150
-rw-r--r--test/ruby/test_integer_comb.rb23
-rw-r--r--test/ruby/test_io.rb370
-rw-r--r--test/ruby/test_io_buffer.rb575
-rw-r--r--test/ruby/test_io_m17n.rb114
-rw-r--r--test/ruby/test_io_timeout.rb58
-rw-r--r--test/ruby/test_iseq.rb336
-rw-r--r--test/ruby/test_iterator.rb16
-rw-r--r--test/ruby/test_jit.rb1259
-rw-r--r--test/ruby/test_jit_debug.rb17
-rw-r--r--test/ruby/test_keyword.rb422
-rw-r--r--test/ruby/test_lambda.rb26
-rw-r--r--test/ruby/test_lazy_enumerator.rb29
-rw-r--r--test/ruby/test_literal.rb68
-rw-r--r--test/ruby/test_m17n.rb104
-rw-r--r--test/ruby/test_marshal.rb121
-rw-r--r--test/ruby/test_math.rb10
-rw-r--r--test/ruby/test_method.rb374
-rw-r--r--test/ruby/test_mixed_unicode_escapes.rb2
-rw-r--r--test/ruby/test_module.rb227
-rw-r--r--test/ruby/test_nomethod_error.rb2
-rw-r--r--test/ruby/test_numeric.rb3
-rw-r--r--test/ruby/test_object.rb84
-rw-r--r--test/ruby/test_objectspace.rb65
-rw-r--r--test/ruby/test_optimization.rb222
-rw-r--r--test/ruby/test_pack.rb185
-rw-r--r--test/ruby/test_parse.rb610
-rw-r--r--test/ruby/test_pattern_matching.rb91
-rw-r--r--test/ruby/test_proc.rb217
-rw-r--r--test/ruby/test_process.rb530
-rw-r--r--test/ruby/test_rand.rb14
-rw-r--r--test/ruby/test_random_formatter.rb178
-rw-r--r--test/ruby/test_range.rb705
-rw-r--r--test/ruby/test_rational.rb2
-rw-r--r--test/ruby/test_refinement.rb385
-rw-r--r--test/ruby/test_regexp.rb775
-rw-r--r--test/ruby/test_require.rb176
-rw-r--r--test/ruby/test_require_lib.rb31
-rw-r--r--test/ruby/test_rubyoptions.rb429
-rw-r--r--test/ruby/test_rubyvm.rb59
-rw-r--r--test/ruby/test_rubyvm_jit.rb91
-rw-r--r--test/ruby/test_settracefunc.rb724
-rw-r--r--test/ruby/test_shapes.rb1040
-rw-r--r--test/ruby/test_signal.rb46
-rw-r--r--test/ruby/test_sleep.rb17
-rw-r--r--test/ruby/test_sprintf.rb43
-rw-r--r--test/ruby/test_stack.rb1
-rw-r--r--test/ruby/test_string.rb1356
-rw-r--r--test/ruby/test_string_memory.rb65
-rw-r--r--test/ruby/test_struct.rb69
-rw-r--r--test/ruby/test_super.rb94
-rw-r--r--test/ruby/test_symbol.rb24
-rw-r--r--test/ruby/test_syntax.rb548
-rw-r--r--test/ruby/test_system.rb13
-rw-r--r--test/ruby/test_thread.rb158
-rw-r--r--test/ruby/test_thread_cv.rb9
-rw-r--r--test/ruby/test_thread_queue.rb93
-rw-r--r--test/ruby/test_time.rb241
-rw-r--r--test/ruby/test_time_tz.rb38
-rw-r--r--test/ruby/test_transcode.rb535
-rw-r--r--test/ruby/test_undef.rb16
-rw-r--r--test/ruby/test_variable.rb130
-rw-r--r--test/ruby/test_vm_dump.rb13
-rw-r--r--test/ruby/test_warning.rb32
-rw-r--r--test/ruby/test_weakkeymap.rb159
-rw-r--r--test/ruby/test_weakmap.rb109
-rw-r--r--test/ruby/test_whileuntil.rb18
-rw-r--r--test/ruby/test_yjit.rb1842
-rw-r--r--test/ruby/test_yjit_exit_locations.rb96
-rw-r--r--test/rubygems/alternate_cert.pem28
-rw-r--r--test/rubygems/alternate_cert_32.pem30
-rw-r--r--test/rubygems/alternate_key.pem50
-rw-r--r--test/rubygems/bad_rake.rb1
-rw-r--r--test/rubygems/bundler_test_gem.rb424
-rw-r--r--test/rubygems/child_cert.pem31
-rw-r--r--test/rubygems/child_cert_32.pem31
-rw-r--r--test/rubygems/child_key.pem50
-rw-r--r--test/rubygems/data/excon-0.7.7.gemspec.rzbin0 -> 388 bytes
-rw-r--r--test/rubygems/data/null-type.gemspec.rzbin504 -> 0 bytes
-rw-r--r--test/rubygems/data/pry-0.4.7.gemspec.rzbin0 -> 433 bytes
-rw-r--r--test/rubygems/encrypted_private_key.pem52
-rw-r--r--test/rubygems/expired_cert.pem30
-rw-r--r--test/rubygems/fake_certlib/openssl.rb1
-rw-r--r--test/rubygems/future_cert.pem30
-rw-r--r--test/rubygems/future_cert_32.pem30
-rw-r--r--test/rubygems/good_rake.rb1
-rw-r--r--test/rubygems/grandchild_cert.pem31
-rw-r--r--test/rubygems/grandchild_cert_32.pem31
-rw-r--r--test/rubygems/grandchild_key.pem50
-rw-r--r--test/rubygems/helper.rb734
-rw-r--r--test/rubygems/installer_test_case.rb43
-rw-r--r--test/rubygems/invalid_issuer_cert.pem32
-rw-r--r--test/rubygems/invalid_issuer_cert_32.pem32
-rw-r--r--test/rubygems/invalid_key.pem50
-rw-r--r--test/rubygems/invalid_signer_cert.pem30
-rw-r--r--test/rubygems/invalid_signer_cert_32.pem30
-rw-r--r--test/rubygems/invalidchild_cert.pem31
-rw-r--r--test/rubygems/invalidchild_cert_32.pem31
-rw-r--r--test/rubygems/invalidchild_key.pem50
-rw-r--r--test/rubygems/mock_gem_ui.rb86
-rw-r--r--test/rubygems/multifactor_auth_utilities.rb111
-rw-r--r--test/rubygems/package/tar_test_case.rb72
-rw-r--r--test/rubygems/packages/Bluebie-legs-0.6.2.gembin0 -> 14336 bytes
-rw-r--r--test/rubygems/plugin/exception/rubygems_plugin.rb3
-rw-r--r--test/rubygems/plugin/load/rubygems_plugin.rb1
-rw-r--r--test/rubygems/plugin/scripterror/rubygems_plugin.rb4
-rw-r--r--test/rubygems/plugin/standarderror/rubygems_plugin.rb3
-rw-r--r--test/rubygems/private_ec_key.pem9
-rw-r--r--test/rubygems/private_key.pem50
-rw-r--r--test/rubygems/public_cert.pem32
-rw-r--r--test/rubygems/public_cert_32.pem30
-rw-r--r--test/rubygems/public_key.pem14
-rw-r--r--test/rubygems/rubygems/commands/crash_command.rb1
-rw-r--r--test/rubygems/rubygems_plugin.rb5
-rw-r--r--test/rubygems/simple_gem.rb3
-rw-r--r--test/rubygems/specifications/bar-0.0.2.gemspec2
-rw-r--r--test/rubygems/specifications/rubyforge-0.0.1.gemspec23
-rw-r--r--test/rubygems/test_bundled_ca.rb29
-rw-r--r--test/rubygems/test_config.rb13
-rw-r--r--test/rubygems/test_deprecate.rb17
-rw-r--r--test/rubygems/test_exit.rb12
-rw-r--r--test/rubygems/test_gem.rb1373
-rw-r--r--test/rubygems/test_gem_available_set.rb49
-rw-r--r--test/rubygems/test_gem_bundler_version_finder.rb79
-rw-r--r--test/rubygems/test_gem_ci_detector.rb32
-rw-r--r--test/rubygems/test_gem_command.rb118
-rw-r--r--test/rubygems/test_gem_command_manager.rb206
-rw-r--r--test/rubygems/test_gem_commands_build_command.rb146
-rw-r--r--test/rubygems/test_gem_commands_cert_command.rb323
-rw-r--r--test/rubygems/test_gem_commands_check_command.rb9
-rw-r--r--test/rubygems/test_gem_commands_cleanup_command.rb101
-rw-r--r--test/rubygems/test_gem_commands_contents_command.rb71
-rw-r--r--test/rubygems/test_gem_commands_dependency_command.rb73
-rw-r--r--test/rubygems/test_gem_commands_environment_command.rb96
-rw-r--r--test/rubygems/test_gem_commands_exec_command.rb859
-rw-r--r--test/rubygems/test_gem_commands_fetch_command.rb214
-rw-r--r--test/rubygems/test_gem_commands_generate_index_command.rb80
-rw-r--r--test/rubygems/test_gem_commands_help_command.rb29
-rw-r--r--test/rubygems/test_gem_commands_info_command.rb43
-rw-r--r--test/rubygems/test_gem_commands_install_command.rb443
-rw-r--r--test/rubygems/test_gem_commands_list_command.rb38
-rw-r--r--test/rubygems/test_gem_commands_lock_command.rb21
-rw-r--r--test/rubygems/test_gem_commands_mirror.rb7
-rw-r--r--test/rubygems/test_gem_commands_open_command.rb22
-rw-r--r--test/rubygems/test_gem_commands_outdated_command.rb19
-rw-r--r--test/rubygems/test_gem_commands_owner_command.rb309
-rw-r--r--test/rubygems/test_gem_commands_pristine_command.rb262
-rw-r--r--test/rubygems/test_gem_commands_push_command.rb287
-rw-r--r--test/rubygems/test_gem_commands_query_command.rb211
-rw-r--r--test/rubygems/test_gem_commands_rebuild_command.rb154
-rw-r--r--test/rubygems/test_gem_commands_search_command.rb5
-rw-r--r--test/rubygems/test_gem_commands_server_command.rb55
-rw-r--r--test/rubygems/test_gem_commands_setup_command.rb312
-rw-r--r--test/rubygems/test_gem_commands_signin_command.rb244
-rw-r--r--test/rubygems/test_gem_commands_signout_command.rb12
-rw-r--r--test/rubygems/test_gem_commands_sources_command.rb100
-rw-r--r--test/rubygems/test_gem_commands_specification_command.rb95
-rw-r--r--test/rubygems/test_gem_commands_stale_command.rb13
-rw-r--r--test/rubygems/test_gem_commands_uninstall_command.rb269
-rw-r--r--test/rubygems/test_gem_commands_unpack_command.rb69
-rw-r--r--test/rubygems/test_gem_commands_update_command.rb334
-rw-r--r--test/rubygems/test_gem_commands_which_command.rb25
-rw-r--r--test/rubygems/test_gem_commands_yank_command.rb215
-rw-r--r--test/rubygems/test_gem_config_file.rb332
-rw-r--r--test/rubygems/test_gem_console_ui.rb19
-rw-r--r--test/rubygems/test_gem_dependency.rb174
-rw-r--r--test/rubygems/test_gem_dependency_installer.rb530
-rw-r--r--test/rubygems/test_gem_dependency_list.rb107
-rw-r--r--test/rubygems/test_gem_dependency_resolution_error.rb19
-rw-r--r--test/rubygems/test_gem_doctor.rb53
-rw-r--r--test/rubygems/test_gem_ext_builder.rb290
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder.rb171
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder/custom_name/.gitignore1
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder/custom_name/custom_name.gemspec10
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.lock249
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.toml10
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/src/lib.rs27
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder/custom_name/lib/custom_name.rb3
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/.gitignore1
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock249
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.toml10
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/rust_ruby_example.gemspec10
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/src/lib.rs51
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder_link_flag_converter.rb34
-rw-r--r--test/rubygems/test_gem_ext_cargo_builder_unit.rb60
-rw-r--r--test/rubygems/test_gem_ext_cmake_builder.rb45
-rw-r--r--test/rubygems/test_gem_ext_configure_builder.rb29
-rw-r--r--test/rubygems/test_gem_ext_ext_conf_builder.rb112
-rw-r--r--test/rubygems/test_gem_ext_rake_builder.rb53
-rw-r--r--test/rubygems/test_gem_gem_runner.rb24
-rw-r--r--test/rubygems/test_gem_gemcutter_utilities.rb285
-rw-r--r--test/rubygems/test_gem_impossible_dependencies_error.rb9
-rw-r--r--test/rubygems/test_gem_indexer.rb357
-rw-r--r--test/rubygems/test_gem_install_update_options.rb58
-rw-r--r--test/rubygems/test_gem_installer.rb1142
-rw-r--r--test/rubygems/test_gem_local_remote_options.rb23
-rw-r--r--test/rubygems/test_gem_name_tuple.rb42
-rw-r--r--test/rubygems/test_gem_package.rb710
-rw-r--r--test/rubygems/test_gem_package_old.rb31
-rw-r--r--test/rubygems/test_gem_package_tar_header.rb137
-rw-r--r--test/rubygems/test_gem_package_tar_reader.rb81
-rw-r--r--test/rubygems/test_gem_package_tar_reader_entry.rb238
-rw-r--r--test/rubygems/test_gem_package_tar_writer.rb189
-rw-r--r--test/rubygems/test_gem_package_task.rb39
-rw-r--r--test/rubygems/test_gem_path_support.rb29
-rw-r--r--test/rubygems/test_gem_platform.rb576
-rw-r--r--test/rubygems/test_gem_rdoc.rb35
-rw-r--r--test/rubygems/test_gem_remote_fetcher.rb863
-rw-r--r--test/rubygems/test_gem_remote_fetcher_local_server.rb220
-rw-r--r--test/rubygems/test_gem_remote_fetcher_local_ssl_server.rb195
-rw-r--r--test/rubygems/test_gem_remote_fetcher_s3.rb233
-rw-r--r--test/rubygems/test_gem_request.rb223
-rw-r--r--test/rubygems/test_gem_request_connection_pools.rb65
-rw-r--r--test/rubygems/test_gem_request_set.rb251
-rw-r--r--test/rubygems/test_gem_request_set_gem_dependency_api.rb473
-rw-r--r--test/rubygems/test_gem_request_set_lockfile.rb173
-rw-r--r--test/rubygems/test_gem_request_set_lockfile_parser.rb133
-rw-r--r--test/rubygems/test_gem_request_set_lockfile_tokenizer.rb125
-rw-r--r--test/rubygems/test_gem_requirement.rb105
-rw-r--r--test/rubygems/test_gem_resolver.rb336
-rw-r--r--test/rubygems/test_gem_resolver_activation_request.rb21
-rw-r--r--test/rubygems/test_gem_resolver_api_set.rb114
-rw-r--r--test/rubygems/test_gem_resolver_api_specification.rb115
-rw-r--r--test/rubygems/test_gem_resolver_best_set.rb123
-rw-r--r--test/rubygems/test_gem_resolver_composed_set.rb3
-rw-r--r--test/rubygems/test_gem_resolver_conflict.rb31
-rw-r--r--test/rubygems/test_gem_resolver_dependency_request.rb55
-rw-r--r--test/rubygems/test_gem_resolver_git_set.rb43
-rw-r--r--test/rubygems/test_gem_resolver_git_specification.rb44
-rw-r--r--test/rubygems/test_gem_resolver_index_set.rb51
-rw-r--r--test/rubygems/test_gem_resolver_index_specification.rb36
-rw-r--r--test/rubygems/test_gem_resolver_installed_specification.rb11
-rw-r--r--test/rubygems/test_gem_resolver_installer_set.rb131
-rw-r--r--test/rubygems/test_gem_resolver_local_specification.rb15
-rw-r--r--test/rubygems/test_gem_resolver_lock_set.rb31
-rw-r--r--test/rubygems/test_gem_resolver_lock_specification.rb37
-rw-r--r--test/rubygems/test_gem_resolver_requirement_list.rb3
-rw-r--r--test/rubygems/test_gem_resolver_specification.rb19
-rw-r--r--test/rubygems/test_gem_resolver_vendor_set.rb13
-rw-r--r--test/rubygems/test_gem_resolver_vendor_specification.rb22
-rw-r--r--test/rubygems/test_gem_safe_marshal.rb416
-rw-r--r--test/rubygems/test_gem_safe_yaml.rb24
-rw-r--r--test/rubygems/test_gem_security.rb195
-rw-r--r--test/rubygems/test_gem_security_policy.rb178
-rw-r--r--test/rubygems/test_gem_security_signer.rb83
-rw-r--r--test/rubygems/test_gem_security_trust_dir.rb27
-rw-r--r--test/rubygems/test_gem_server.rb608
-rw-r--r--test/rubygems/test_gem_silent_ui.rb70
-rw-r--r--test/rubygems/test_gem_source.rb116
-rw-r--r--test/rubygems/test_gem_source_fetch_problem.rb19
-rw-r--r--test/rubygems/test_gem_source_git.rb144
-rw-r--r--test/rubygems/test_gem_source_installed.rb38
-rw-r--r--test/rubygems/test_gem_source_list.rb15
-rw-r--r--test/rubygems/test_gem_source_local.rb36
-rw-r--r--test/rubygems/test_gem_source_lock.rb67
-rw-r--r--test/rubygems/test_gem_source_specific_file.rb39
-rw-r--r--test/rubygems/test_gem_source_subpath_problem.rb19
-rw-r--r--test/rubygems/test_gem_source_vendor.rb27
-rw-r--r--test/rubygems/test_gem_spec_fetcher.rb159
-rw-r--r--test/rubygems/test_gem_specification.rb1932
-rw-r--r--test/rubygems/test_gem_stream_ui.rb89
-rw-r--r--test/rubygems/test_gem_stub_specification.rb83
-rw-r--r--test/rubygems/test_gem_text.rb3
-rw-r--r--test/rubygems/test_gem_uninstaller.rb400
-rw-r--r--test/rubygems/test_gem_unsatisfiable_dependency_error.rb7
-rw-r--r--test/rubygems/test_gem_update_suggestion.rb209
-rw-r--r--test/rubygems/test_gem_uri.rb10
-rw-r--r--test/rubygems/test_gem_uri_formatter.rb29
-rw-r--r--test/rubygems/test_gem_util.rb55
-rw-r--r--test/rubygems/test_gem_validator.rb16
-rw-r--r--test/rubygems/test_gem_version.rb50
-rw-r--r--test/rubygems/test_gem_version_option.rb67
-rw-r--r--test/rubygems/test_kernel.rb117
-rw-r--r--test/rubygems/test_project_sanity.rb37
-rw-r--r--test/rubygems/test_remote_fetch_error.rb17
-rw-r--r--test/rubygems/test_require.rb433
-rw-r--r--test/rubygems/test_rubygems.rb58
-rw-r--r--test/rubygems/test_webauthn_listener.rb143
-rw-r--r--test/rubygems/test_webauthn_listener_response.rb93
-rw-r--r--test/rubygems/test_webauthn_poller.rb134
-rw-r--r--test/rubygems/utilities.rb149
-rw-r--r--test/rubygems/wrong_key_cert.pem30
-rw-r--r--test/rubygems/wrong_key_cert_32.pem30
-rw-r--r--test/runner.rb9
-rw-r--r--test/set/fixtures/fake_sorted_set_gem/sorted_set.rb (renamed from test/fixtures/fake_sorted_set_gem/sorted_set.rb)0
-rw-r--r--test/set/test_set.rb892
-rw-r--r--test/set/test_sorted_set.rb (renamed from test/test_sorted_set.rb)0
-rw-r--r--test/socket/test_addrinfo.rb10
-rw-r--r--test/socket/test_basicsocket.rb2
-rw-r--r--test/socket/test_nonblock.rb12
-rw-r--r--test/socket/test_socket.rb287
-rw-r--r--test/socket/test_sockopt.rb2
-rw-r--r--test/socket/test_tcp.rb2
-rw-r--r--test/socket/test_udp.rb2
-rw-r--r--test/socket/test_unix.rb215
-rw-r--r--test/stringio/test_ractor.rb2
-rw-r--r--test/stringio/test_stringio.rb186
-rw-r--r--test/strscan/test_ractor.rb2
-rw-r--r--test/strscan/test_stringscanner.rb186
-rw-r--r--test/syslog/test_syslog_logger.rb588
-rw-r--r--test/test_abbrev.rb55
-rw-r--r--test/test_bundled_gems.rb35
-rw-r--r--test/test_delegate.rb9
-rw-r--r--test/test_extlibs.rb9
-rw-r--r--test/test_find.rb16
-rw-r--r--test/test_forwardable.rb2
-rw-r--r--test/test_ipaddr.rb171
-rw-r--r--test/test_mutex_m.rb58
-rw-r--r--test/test_observer.rb66
-rw-r--r--test/test_open3.rb5
-rw-r--r--test/test_pp.rb52
-rw-r--r--test/test_pstore.rb32
-rw-r--r--test/test_pty.rb30
-rw-r--r--test/test_rbconfig.rb9
-rw-r--r--test/test_securerandom.rb121
-rw-r--r--test/test_set.rb840
-rw-r--r--test/test_singleton.rb21
-rw-r--r--test/test_syslog.rb193
-rw-r--r--test/test_tempfile.rb118
-rw-r--r--test/test_time.rb9
-rw-r--r--test/test_timeout.rb167
-rw-r--r--test/test_tmpdir.rb42
-rw-r--r--test/test_trick.rb114
-rw-r--r--test/test_unicode_normalize.rb2
-rw-r--r--test/uri/test_common.rb141
-rw-r--r--test/uri/test_ftp.rb10
-rw-r--r--test/uri/test_generic.rb24
-rw-r--r--test/uri/test_http.rb35
-rw-r--r--test/uri/test_ldap.rb14
-rw-r--r--test/uri/test_parser.rb60
-rw-r--r--test/uri/test_ws.rb8
-rw-r--r--test/uri/test_wss.rb65
-rw-r--r--test/win32/test_registry.rb97
-rw-r--r--test/win32ole/available_ole.rb14
-rw-r--r--test/win32ole/err_in_callback.rb4
-rw-r--r--test/win32ole/test_err_in_callback.rb6
-rw-r--r--test/win32ole/test_folderitem2_invokeverb.rb2
-rw-r--r--test/win32ole/test_nil2vtempty.rb2
-rw-r--r--test/win32ole/test_propertyputref.rb2
-rw-r--r--test/win32ole/test_thread.rb2
-rw-r--r--test/win32ole/test_win32ole.rb45
-rw-r--r--test/win32ole/test_win32ole_event.rb75
-rw-r--r--test/win32ole/test_win32ole_method.rb48
-rw-r--r--test/win32ole/test_win32ole_method_event.rb12
-rw-r--r--test/win32ole/test_win32ole_param.rb42
-rw-r--r--test/win32ole/test_win32ole_param_event.rb4
-rw-r--r--test/win32ole/test_win32ole_record.rb60
-rw-r--r--test/win32ole/test_win32ole_type.rb67
-rw-r--r--test/win32ole/test_win32ole_type_event.rb6
-rw-r--r--test/win32ole/test_win32ole_typelib.rb66
-rw-r--r--test/win32ole/test_win32ole_variable.rb18
-rw-r--r--test/win32ole/test_win32ole_variant.rb310
-rw-r--r--test/win32ole/test_win32ole_variant_m.rb5
-rw-r--r--test/win32ole/test_win32ole_variant_outarg.rb8
-rw-r--r--test/win32ole/test_word.rb4
-rw-r--r--test/yaml/test_store.rb4
-rw-r--r--test/zlib/test_zlib.rb111
2146 files changed, 83796 insertions, 121282 deletions
diff --git a/test/-ext-/arith_seq/test_arith_seq_beg_len_step.rb b/test/-ext-/arith_seq/test_arith_seq_beg_len_step.rb
new file mode 100644
index 0000000000..4320c1f20d
--- /dev/null
+++ b/test/-ext-/arith_seq/test_arith_seq_beg_len_step.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: false
+require 'test/unit'
+
+class Test_ArithSeq < Test::Unit::TestCase
+ def test_beg_len_step
+ assert_separately([], <<-"end;") #do
+ require '-test-/arith_seq/beg_len_step'
+
+ r, = Enumerator::ArithmeticSequence.__beg_len_step__([1, 2, 3], 0, 0)
+ assert_equal(false, r)
+
+ r, = Enumerator::ArithmeticSequence.__beg_len_step__([1, 2, 3], 1, 0)
+ assert_equal(false, r)
+
+ r, = Enumerator::ArithmeticSequence.__beg_len_step__([1, 2, 3], 3, 0)
+ assert_equal(false, r)
+
+ r, = Enumerator::ArithmeticSequence.__beg_len_step__(1..3, 0, 0)
+ assert_equal(nil, r)
+
+ r = Enumerator::ArithmeticSequence.__beg_len_step__(1..3, 1, 0)
+ assert_equal([true, 1, 0, 1], r)
+
+ r = Enumerator::ArithmeticSequence.__beg_len_step__(1..3, 2, 0)
+ assert_equal([true, 1, 1, 1], r)
+
+ r = Enumerator::ArithmeticSequence.__beg_len_step__(1..3, 3, 0)
+ assert_equal([true, 1, 2, 1], r)
+
+ r = Enumerator::ArithmeticSequence.__beg_len_step__(1..3, 4, 0)
+ assert_equal([true, 1, 3, 1], r)
+
+ r = Enumerator::ArithmeticSequence.__beg_len_step__(1..3, 5, 0)
+ assert_equal([true, 1, 3, 1], r)
+
+ r = Enumerator::ArithmeticSequence.__beg_len_step__((-10..10).step(2), 24, 0)
+ assert_equal([true, 14, 0, 2], r)
+
+ r = Enumerator::ArithmeticSequence.__beg_len_step__((-10..10).step(3), 24, 0)
+ assert_equal([true, 14, 0, 3], r)
+
+ r = Enumerator::ArithmeticSequence.__beg_len_step__((-10..10).step(3), 22, 0)
+ assert_equal([true, 12, 0, 3], r)
+
+ r = Enumerator::ArithmeticSequence.__beg_len_step__((-10..10).step(-3), 22, 0)
+ assert_equal([true, 10, 3, -3], r)
+
+ r = Enumerator::ArithmeticSequence.__beg_len_step__(1..3, 0, 1)
+ assert_equal([true, 1, 3, 1], r)
+ end;
+ end
+end
diff --git a/test/-ext-/bignum/test_big2str.rb b/test/-ext-/bignum/test_big2str.rb
index f8d6320338..88e35a7294 100644
--- a/test/-ext-/bignum/test_big2str.rb
+++ b/test/-ext-/bignum/test_big2str.rb
@@ -2,29 +2,27 @@
require 'test/unit'
require "-test-/bignum"
-class Test_Bignum < Test::Unit::TestCase
- class TestBig2str < Test::Unit::TestCase
+class TestBignum_Big2str < Test::Unit::TestCase
- SIZEOF_BDIGIT = Bug::Bignum::SIZEOF_BDIGIT
- BITSPERDIG = Bug::Bignum::BITSPERDIG
- BDIGMAX = (1 << BITSPERDIG) - 1
+ SIZEOF_BDIGIT = Bug::Bignum::SIZEOF_BDIGIT
+ BITSPERDIG = Bug::Bignum::BITSPERDIG
+ BDIGMAX = (1 << BITSPERDIG) - 1
- def test_big2str_generic
- x = 10**1000
- assert_equal("1" + "0" * 1000, Bug::Bignum.big2str_generic(x, 10))
- end
-
- def test_big2str_poweroftwo
- e = BITSPERDIG*2
- x = 0b10**e
- assert_equal("1" + "0" * e, Bug::Bignum.big2str_poweroftwo(x, 2))
- end
+ def test_big2str_generic
+ x = 10**1000
+ assert_equal("1" + "0" * 1000, Bug::Bignum.big2str_generic(x, 10))
+ end
- def test_big2str_gmp
- x = 10**1000
- assert_equal("1" + "0" * 1000, Bug::Bignum.big2str_gmp(x, 10))
- rescue NotImplementedError
- end
+ def test_big2str_poweroftwo
+ e = BITSPERDIG*2
+ x = 0b10**e
+ assert_equal("1" + "0" * e, Bug::Bignum.big2str_poweroftwo(x, 2))
+ end
+ def test_big2str_gmp
+ x = 10**1000
+ assert_equal("1" + "0" * 1000, Bug::Bignum.big2str_gmp(x, 10))
+ rescue NotImplementedError
end
+
end
diff --git a/test/-ext-/bignum/test_bigzero.rb b/test/-ext-/bignum/test_bigzero.rb
index cf34964acd..6dfa3486c1 100644
--- a/test/-ext-/bignum/test_bigzero.rb
+++ b/test/-ext-/bignum/test_bigzero.rb
@@ -2,19 +2,17 @@
require 'test/unit'
require "-test-/bignum"
-class Test_Bignum < Test::Unit::TestCase
- class TestBigZero < Test::Unit::TestCase
- def test_equal_0
- bug8204 = '[ruby-core:53893] [Bug #8204]'
- (0..10).each do |i|
- assert_equal(0, Bug::Bignum.zero(i), "#{bug8204} Bignum.zero(#{i})")
- end
+class TestBignum_BigZero < Test::Unit::TestCase
+ def test_equal_0
+ bug8204 = '[ruby-core:53893] [Bug #8204]'
+ (0..10).each do |i|
+ assert_equal(0, Bug::Bignum.zero(i), "#{bug8204} Bignum.zero(#{i})")
end
+ end
- def test_zero?
- (0..10).each do |i|
- assert_equal(true, Bug::Bignum.zero(i).zero?)
- end
+ def test_zero?
+ (0..10).each do |i|
+ assert_equal(true, Bug::Bignum.zero(i).zero?)
end
end
end
diff --git a/test/-ext-/bignum/test_div.rb b/test/-ext-/bignum/test_div.rb
index e61fc2ced5..0c6f635ae8 100644
--- a/test/-ext-/bignum/test_div.rb
+++ b/test/-ext-/bignum/test_div.rb
@@ -2,28 +2,26 @@
require 'test/unit'
require "-test-/bignum"
-class Test_Bignum < Test::Unit::TestCase
- class TestDiv < Test::Unit::TestCase
+class TestBignum_Div < Test::Unit::TestCase
- SIZEOF_BDIGIT = Bug::Bignum::SIZEOF_BDIGIT
- BITSPERDIG = Bug::Bignum::BITSPERDIG
- BDIGMAX = (1 << BITSPERDIG) - 1
+ SIZEOF_BDIGIT = Bug::Bignum::SIZEOF_BDIGIT
+ BITSPERDIG = Bug::Bignum::BITSPERDIG
+ BDIGMAX = (1 << BITSPERDIG) - 1
- def test_divrem_normal
- x = (1 << (BITSPERDIG*2)) | (2 << BITSPERDIG) | 3
- y = (1 << BITSPERDIG) | 1
- q = (1 << BITSPERDIG) | 1
- r = 2
- assert_equal([q, r], Bug::Bignum.big_divrem_normal(x, y))
- end
+ def test_divrem_normal
+ x = (1 << (BITSPERDIG*2)) | (2 << BITSPERDIG) | 3
+ y = (1 << BITSPERDIG) | 1
+ q = (1 << BITSPERDIG) | 1
+ r = 2
+ assert_equal([q, r], Bug::Bignum.big_divrem_normal(x, y))
+ end
- def test_divrem_gmp
- x = (1 << (BITSPERDIG*2)) | (2 << BITSPERDIG) | 3
- y = (1 << BITSPERDIG) | 1
- q = (1 << BITSPERDIG) | 1
- r = 2
- assert_equal([q, r], Bug::Bignum.big_divrem_gmp(x, y))
- rescue NotImplementedError
- end
+ def test_divrem_gmp
+ x = (1 << (BITSPERDIG*2)) | (2 << BITSPERDIG) | 3
+ y = (1 << BITSPERDIG) | 1
+ q = (1 << BITSPERDIG) | 1
+ r = 2
+ assert_equal([q, r], Bug::Bignum.big_divrem_gmp(x, y))
+ rescue NotImplementedError
end
end
diff --git a/test/-ext-/bignum/test_mul.rb b/test/-ext-/bignum/test_mul.rb
index 7653a8e37a..95186bbf76 100644
--- a/test/-ext-/bignum/test_mul.rb
+++ b/test/-ext-/bignum/test_mul.rb
@@ -2,137 +2,135 @@
require 'test/unit'
require "-test-/bignum"
-class Test_Bignum < Test::Unit::TestCase
- class TestMul < Test::Unit::TestCase
-
- SIZEOF_BDIGIT = Bug::Bignum::SIZEOF_BDIGIT
- BITSPERDIG = Bug::Bignum::BITSPERDIG
- BDIGMAX = (1 << BITSPERDIG) - 1
-
- def test_mul_normal
- x = (1 << BITSPERDIG) | 1
- y = (1 << BITSPERDIG) | 1
- z = (1 << (BITSPERDIG*2)) | (2 << BITSPERDIG) | 1
- assert_equal(z, Bug::Bignum.big_mul_normal(x, y))
- end
-
- def test_mul_normal_zero_in_x
- x = (1 << (2*BITSPERDIG)) | 1
- y = (1 << BITSPERDIG) | 1
- z = (1 << (BITSPERDIG*3)) | (1 << (BITSPERDIG*2)) | (1 << BITSPERDIG) | 1
- assert_equal(z, Bug::Bignum.big_mul_normal(x, y))
- end
-
- def test_mul_normal_zero_in_y
- x = (1 << BITSPERDIG) | 1
- y = (1 << (2*BITSPERDIG)) | 1
- z = (1 << (BITSPERDIG*3)) | (1 << (BITSPERDIG*2)) | (1 << BITSPERDIG) | 1
- assert_equal(z, Bug::Bignum.big_mul_normal(x, y))
- end
-
- def test_mul_normal_max_max
- x = (1 << (2*BITSPERDIG)) - 1
- y = (1 << (2*BITSPERDIG)) - 1
- z = (1 << (4*BITSPERDIG)) - (1 << (2*BITSPERDIG+1)) + 1
- assert_equal(z, Bug::Bignum.big_mul_normal(x, y))
- end
-
- def test_sq_fast
- x = (1 << BITSPERDIG) | 1
- z = (1 << 2*BITSPERDIG) | (2 << BITSPERDIG) | 1
- assert_equal(z, Bug::Bignum.big_sq_fast(x))
- end
-
- def test_sq_fast_max2
- x = (BDIGMAX << BITSPERDIG) | BDIGMAX
- assert_equal(Bug::Bignum.big_mul_normal(x, x), Bug::Bignum.big_sq_fast(x))
- end
-
- def test_sq_fast_zero_in_middle
- x = (BDIGMAX << 2*BITSPERDIG) | BDIGMAX
- assert_equal(Bug::Bignum.big_mul_normal(x, x), Bug::Bignum.big_sq_fast(x))
- end
-
- def test_mul_balance
- x = (1 << BITSPERDIG) | 1
- y = (1 << BITSPERDIG) | 1
- z = (1 << (BITSPERDIG*2)) | (2 << BITSPERDIG) | 1
- assert_equal(z, Bug::Bignum.big_mul_balance(x, y))
- end
-
- def test_mul_balance_2x16
- x = (1 << BITSPERDIG) | 1
- y = (1 << BITSPERDIG*16) | 1
- assert_equal(Bug::Bignum.big_mul_normal(x, y), Bug::Bignum.big_mul_balance(x, y))
- end
-
- def test_mul_balance_2x17
- x = (1 << BITSPERDIG) | 1
- y = (1 << BITSPERDIG*17) | 1
- assert_equal(Bug::Bignum.big_mul_normal(x, y), Bug::Bignum.big_mul_balance(x, y))
- end
-
- def test_mul_karatsuba
- x = (1 << BITSPERDIG) | 1
- y = (1 << BITSPERDIG) | 1
- z = (1 << (BITSPERDIG*2)) | (2 << BITSPERDIG) | 1
- assert_equal(z, Bug::Bignum.big_mul_karatsuba(x, y))
- end
-
- def test_mul_karatsuba_odd_y
- x = (1 << BITSPERDIG) | 1
- y = (1 << (2*BITSPERDIG)) | 1
- assert_equal(Bug::Bignum.big_mul_normal(x, y), Bug::Bignum.big_mul_karatsuba(x, y))
- end
-
- def test_mul_karatsuba_odd_xy
- x = (1 << (2*BITSPERDIG)) | 1
- y = (1 << (2*BITSPERDIG)) | 1
- assert_equal(Bug::Bignum.big_mul_normal(x, y), Bug::Bignum.big_mul_karatsuba(x, y))
- end
-
- def test_mul_karatsuba_x1_gt_x0
- x = (2 << BITSPERDIG) | 1
- y = (1 << BITSPERDIG) | 2
- assert_equal(Bug::Bignum.big_mul_normal(x, y), Bug::Bignum.big_mul_karatsuba(x, y))
- end
-
- def test_mul_karatsuba_y1_gt_y0
- x = (1 << BITSPERDIG) | 2
- y = (2 << BITSPERDIG) | 1
- assert_equal(Bug::Bignum.big_mul_normal(x, y), Bug::Bignum.big_mul_karatsuba(x, y))
- end
-
- def test_mul_karatsuba_x1_gt_x0_and_y1_gt_y0
- x = (2 << BITSPERDIG) | 1
- y = (2 << BITSPERDIG) | 1
- assert_equal(Bug::Bignum.big_mul_normal(x, y), Bug::Bignum.big_mul_karatsuba(x, y))
- end
-
- def test_mul_karatsuba_carry2
- x = (1 << BITSPERDIG) | BDIGMAX
- y = (1 << BITSPERDIG) | BDIGMAX
- assert_equal(Bug::Bignum.big_mul_normal(x, y), Bug::Bignum.big_mul_karatsuba(x, y))
- end
-
- def test_mul_karatsuba_borrow
- x = (BDIGMAX << BITSPERDIG) | 1
- y = (BDIGMAX << BITSPERDIG) | 1
- assert_equal(Bug::Bignum.big_mul_normal(x, y), Bug::Bignum.big_mul_karatsuba(x, y))
- end
-
- def test_mul_toom3
- x = (1 << 2*BITSPERDIG) | (1 << BITSPERDIG) | 1
- y = (1 << 2*BITSPERDIG) | (1 << BITSPERDIG) | 1
- assert_equal(Bug::Bignum.big_mul_normal(x, y), Bug::Bignum.big_mul_toom3(x, y))
- end
-
- def test_mul_gmp
- x = (1 << 2*BITSPERDIG) | (1 << BITSPERDIG) | 1
- y = (1 << 2*BITSPERDIG) | (1 << BITSPERDIG) | 1
- assert_equal(Bug::Bignum.big_mul_normal(x, y), Bug::Bignum.big_mul_gmp(x, y))
- rescue NotImplementedError
- end
+class TestBignum_Mul < Test::Unit::TestCase
+ SIZEOF_BDIGIT = Bug::Bignum::SIZEOF_BDIGIT
+ BITSPERDIG = Bug::Bignum::BITSPERDIG
+ BDIGMAX = (1 << BITSPERDIG) - 1
+
+ def test_mul_normal
+ x = (1 << BITSPERDIG) | 1
+ y = (1 << BITSPERDIG) | 1
+ z = (1 << (BITSPERDIG*2)) | (2 << BITSPERDIG) | 1
+ assert_equal(z, Bug::Bignum.big_mul_normal(x, y))
+ end
+
+ def test_mul_normal_zero_in_x
+ x = (1 << (2*BITSPERDIG)) | 1
+ y = (1 << BITSPERDIG) | 1
+ z = (1 << (BITSPERDIG*3)) | (1 << (BITSPERDIG*2)) | (1 << BITSPERDIG) | 1
+ assert_equal(z, Bug::Bignum.big_mul_normal(x, y))
+ end
+
+ def test_mul_normal_zero_in_y
+ x = (1 << BITSPERDIG) | 1
+ y = (1 << (2*BITSPERDIG)) | 1
+ z = (1 << (BITSPERDIG*3)) | (1 << (BITSPERDIG*2)) | (1 << BITSPERDIG) | 1
+ assert_equal(z, Bug::Bignum.big_mul_normal(x, y))
+ end
+
+ def test_mul_normal_max_max
+ x = (1 << (2*BITSPERDIG)) - 1
+ y = (1 << (2*BITSPERDIG)) - 1
+ z = (1 << (4*BITSPERDIG)) - (1 << (2*BITSPERDIG+1)) + 1
+ assert_equal(z, Bug::Bignum.big_mul_normal(x, y))
+ end
+
+ def test_sq_fast
+ x = (1 << BITSPERDIG) | 1
+ z = (1 << 2*BITSPERDIG) | (2 << BITSPERDIG) | 1
+ assert_equal(z, Bug::Bignum.big_sq_fast(x))
+ end
+
+ def test_sq_fast_max2
+ x = (BDIGMAX << BITSPERDIG) | BDIGMAX
+ assert_equal(Bug::Bignum.big_mul_normal(x, x), Bug::Bignum.big_sq_fast(x))
+ end
+
+ def test_sq_fast_zero_in_middle
+ x = (BDIGMAX << 2*BITSPERDIG) | BDIGMAX
+ assert_equal(Bug::Bignum.big_mul_normal(x, x), Bug::Bignum.big_sq_fast(x))
+ end
+
+ def test_mul_balance
+ x = (1 << BITSPERDIG) | 1
+ y = (1 << BITSPERDIG) | 1
+ z = (1 << (BITSPERDIG*2)) | (2 << BITSPERDIG) | 1
+ assert_equal(z, Bug::Bignum.big_mul_balance(x, y))
+ end
+
+ def test_mul_balance_2x16
+ x = (1 << BITSPERDIG) | 1
+ y = (1 << BITSPERDIG*16) | 1
+ assert_equal(Bug::Bignum.big_mul_normal(x, y), Bug::Bignum.big_mul_balance(x, y))
+ end
+
+ def test_mul_balance_2x17
+ x = (1 << BITSPERDIG) | 1
+ y = (1 << BITSPERDIG*17) | 1
+ assert_equal(Bug::Bignum.big_mul_normal(x, y), Bug::Bignum.big_mul_balance(x, y))
+ end
+
+ def test_mul_karatsuba
+ x = (1 << BITSPERDIG) | 1
+ y = (1 << BITSPERDIG) | 1
+ z = (1 << (BITSPERDIG*2)) | (2 << BITSPERDIG) | 1
+ assert_equal(z, Bug::Bignum.big_mul_karatsuba(x, y))
+ end
+
+ def test_mul_karatsuba_odd_y
+ x = (1 << BITSPERDIG) | 1
+ y = (1 << (2*BITSPERDIG)) | 1
+ assert_equal(Bug::Bignum.big_mul_normal(x, y), Bug::Bignum.big_mul_karatsuba(x, y))
+ end
+
+ def test_mul_karatsuba_odd_xy
+ x = (1 << (2*BITSPERDIG)) | 1
+ y = (1 << (2*BITSPERDIG)) | 1
+ assert_equal(Bug::Bignum.big_mul_normal(x, y), Bug::Bignum.big_mul_karatsuba(x, y))
+ end
+
+ def test_mul_karatsuba_x1_gt_x0
+ x = (2 << BITSPERDIG) | 1
+ y = (1 << BITSPERDIG) | 2
+ assert_equal(Bug::Bignum.big_mul_normal(x, y), Bug::Bignum.big_mul_karatsuba(x, y))
+ end
+
+ def test_mul_karatsuba_y1_gt_y0
+ x = (1 << BITSPERDIG) | 2
+ y = (2 << BITSPERDIG) | 1
+ assert_equal(Bug::Bignum.big_mul_normal(x, y), Bug::Bignum.big_mul_karatsuba(x, y))
+ end
+
+ def test_mul_karatsuba_x1_gt_x0_and_y1_gt_y0
+ x = (2 << BITSPERDIG) | 1
+ y = (2 << BITSPERDIG) | 1
+ assert_equal(Bug::Bignum.big_mul_normal(x, y), Bug::Bignum.big_mul_karatsuba(x, y))
+ end
+
+ def test_mul_karatsuba_carry2
+ x = (1 << BITSPERDIG) | BDIGMAX
+ y = (1 << BITSPERDIG) | BDIGMAX
+ assert_equal(Bug::Bignum.big_mul_normal(x, y), Bug::Bignum.big_mul_karatsuba(x, y))
+ end
+
+ def test_mul_karatsuba_borrow
+ x = (BDIGMAX << BITSPERDIG) | 1
+ y = (BDIGMAX << BITSPERDIG) | 1
+ assert_equal(Bug::Bignum.big_mul_normal(x, y), Bug::Bignum.big_mul_karatsuba(x, y))
end
+
+ def test_mul_toom3
+ x = (1 << 2*BITSPERDIG) | (1 << BITSPERDIG) | 1
+ y = (1 << 2*BITSPERDIG) | (1 << BITSPERDIG) | 1
+ assert_equal(Bug::Bignum.big_mul_normal(x, y), Bug::Bignum.big_mul_toom3(x, y))
+ end
+
+ def test_mul_gmp
+ x = (1 << 2*BITSPERDIG) | (1 << BITSPERDIG) | 1
+ y = (1 << 2*BITSPERDIG) | (1 << BITSPERDIG) | 1
+ assert_equal(Bug::Bignum.big_mul_normal(x, y), Bug::Bignum.big_mul_gmp(x, y))
+ rescue NotImplementedError
+ end
+
end
diff --git a/test/-ext-/bignum/test_pack.rb b/test/-ext-/bignum/test_pack.rb
index d5605236f7..b7aea9ab68 100644
--- a/test/-ext-/bignum/test_pack.rb
+++ b/test/-ext-/bignum/test_pack.rb
@@ -4,348 +4,346 @@
require 'test/unit'
require "-test-/bignum"
-class Test_Bignum < Test::Unit::TestCase
- class TestPack < Test::Unit::TestCase
-
- MSWORD_FIRST = Bug::Bignum::INTEGER_PACK_MSWORD_FIRST
- LSWORD_FIRST = Bug::Bignum::INTEGER_PACK_LSWORD_FIRST
- MSBYTE_FIRST = Bug::Bignum::INTEGER_PACK_MSBYTE_FIRST
- LSBYTE_FIRST = Bug::Bignum::INTEGER_PACK_LSBYTE_FIRST
- NATIVE_BYTE_ORDER = Bug::Bignum::INTEGER_PACK_NATIVE_BYTE_ORDER
- TWOCOMP = Bug::Bignum::INTEGER_PACK_2COMP
- LITTLE_ENDIAN = Bug::Bignum::INTEGER_PACK_LITTLE_ENDIAN
- BIG_ENDIAN = Bug::Bignum::INTEGER_PACK_BIG_ENDIAN
- NEGATIVE = Bug::Bignum::INTEGER_PACK_NEGATIVE
- GENERIC = Bug::Bignum::INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION
-
- def test_pack_zero
- assert_equal([0, ""], Bug::Bignum.test_pack(0, 0, 1, 0, BIG_ENDIAN))
- end
-
- def test_pack_argument_check
- assert_raise(ArgumentError) { Bug::Bignum.test_pack_raw(0, "", 2, 1, 0, MSBYTE_FIRST) }
- assert_raise(ArgumentError) { Bug::Bignum.test_pack_raw(0, "", 0, 1, 0, MSWORD_FIRST) }
- assert_raise(ArgumentError) { Bug::Bignum.test_pack_raw(0, "", 0, 0, 0, BIG_ENDIAN) }
- assert_raise(ArgumentError) { Bug::Bignum.test_pack_raw(0, "", 0, 1, 8, BIG_ENDIAN) }
-
- # assume sizeof(ssize_t) == sizeof(intptr_t)
- assert_raise(ArgumentError) { Bug::Bignum.test_pack_raw(0, "", 1 << ([""].pack("p").length * 8 - 1), 0, BIG_ENDIAN) }
- end
-
- def test_pack_wordsize
- assert_equal([1, "\x01"], Bug::Bignum.test_pack(1, 1, 1, 0, BIG_ENDIAN))
- assert_equal([1, "\x00\x01"], Bug::Bignum.test_pack(1, 1, 2, 0, BIG_ENDIAN))
- assert_equal([1, "\x00\x00\x01"], Bug::Bignum.test_pack(1, 1, 3, 0, BIG_ENDIAN))
- assert_equal([1, "\x01"], Bug::Bignum.test_pack(1, 1, 1, 0, LITTLE_ENDIAN))
- assert_equal([1, "\x01\x00"], Bug::Bignum.test_pack(1, 1, 2, 0, LITTLE_ENDIAN))
- assert_equal([1, "\x01\x00\x00"], Bug::Bignum.test_pack(1, 1, 3, 0, LITTLE_ENDIAN))
- end
-
- def test_pack_fixed_buffer
- assert_equal([0, "\x00\x00"], Bug::Bignum.test_pack(0, 2, 1, 0, BIG_ENDIAN))
- assert_equal([1, "\x00\x01"], Bug::Bignum.test_pack(0x01, 2, 1, 0, BIG_ENDIAN))
- assert_equal([1, "\x02\x01"], Bug::Bignum.test_pack(0x0201, 2, 1, 0, BIG_ENDIAN))
- assert_equal([2, "\x02\x01"], Bug::Bignum.test_pack(0x030201, 2, 1, 0, BIG_ENDIAN))
- assert_equal([2, "\x02\x01"], Bug::Bignum.test_pack(0x04030201, 2, 1, 0, BIG_ENDIAN))
- assert_equal([0, "\x00\x00"], Bug::Bignum.test_pack(0, 2, 1, 0, LITTLE_ENDIAN))
- assert_equal([1, "\x01\x00"], Bug::Bignum.test_pack(0x01, 2, 1, 0, LITTLE_ENDIAN))
- assert_equal([1, "\x01\x02"], Bug::Bignum.test_pack(0x0201, 2, 1, 0, LITTLE_ENDIAN))
- assert_equal([2, "\x01\x02"], Bug::Bignum.test_pack(0x030201, 2, 1, 0, LITTLE_ENDIAN))
- assert_equal([2, "\x01\x02"], Bug::Bignum.test_pack(0x04030201, 2, 1, 0, LITTLE_ENDIAN))
- end
-
- def test_pack_wordorder_and_endian
- assert_equal([1, "\x12\x34\x56\x78"], Bug::Bignum.test_pack(0x12345678, 2, 2, 0, MSWORD_FIRST|MSBYTE_FIRST))
- assert_equal([1, "\x34\x12\x78\x56"], Bug::Bignum.test_pack(0x12345678, 2, 2, 0, MSWORD_FIRST|LSBYTE_FIRST))
- assert_equal([1, "\x56\x78\x12\x34"], Bug::Bignum.test_pack(0x12345678, 2, 2, 0, LSWORD_FIRST|MSBYTE_FIRST))
- assert_equal([1, "\x78\x56\x34\x12"], Bug::Bignum.test_pack(0x12345678, 2, 2, 0, LSWORD_FIRST|LSBYTE_FIRST))
- end
-
- def test_pack_native_endian
- assert_equal([1, [0x1234].pack("S!")], Bug::Bignum.test_pack(0x1234, 1, 2, 0, MSWORD_FIRST|NATIVE_BYTE_ORDER))
- end
-
- def test_pack_nail
- assert_equal([1, "\x01\x00\x00\x00\x01\x01"], Bug::Bignum.test_pack(0b100011, 6, 1, 7, BIG_ENDIAN))
- assert_equal([1, "\x01\x02\x03\x04\x05\x06\x07\x08"], Bug::Bignum.test_pack(0x12345678, 8, 1, 4, BIG_ENDIAN))
- assert_equal([1, "\x00\x12\x00\x34\x00\x56\x00\x78"], Bug::Bignum.test_pack(0x12345678, 4, 2, 8, BIG_ENDIAN))
- end
-
- def test_pack_overflow
- assert_equal([-2, "\x1"], Bug::Bignum.test_pack((-0x11), 1, 1, 4, BIG_ENDIAN))
- assert_equal([-2, "\x0"], Bug::Bignum.test_pack((-0x10), 1, 1, 4, BIG_ENDIAN))
- assert_equal([-1, "\xF"], Bug::Bignum.test_pack((-0x0F), 1, 1, 4, BIG_ENDIAN))
- assert_equal([+1, "\xF"], Bug::Bignum.test_pack((+0x0F), 1, 1, 4, BIG_ENDIAN))
- assert_equal([+2, "\x0"], Bug::Bignum.test_pack((+0x10), 1, 1, 4, BIG_ENDIAN))
- assert_equal([+2, "\x1"], Bug::Bignum.test_pack((+0x11), 1, 1, 4, BIG_ENDIAN))
-
- assert_equal([-2, "\x01"], Bug::Bignum.test_pack((-0x101), 1, 1, 0, BIG_ENDIAN))
- assert_equal([-2, "\x00"], Bug::Bignum.test_pack((-0x100), 1, 1, 0, BIG_ENDIAN))
- assert_equal([-1, "\xFF"], Bug::Bignum.test_pack((-0x0FF), 1, 1, 0, BIG_ENDIAN))
- assert_equal([+1, "\xFF"], Bug::Bignum.test_pack((+0x0FF), 1, 1, 0, BIG_ENDIAN))
- assert_equal([+2, "\x00"], Bug::Bignum.test_pack((+0x100), 1, 1, 0, BIG_ENDIAN))
- assert_equal([+2, "\x01"], Bug::Bignum.test_pack((+0x101), 1, 1, 0, BIG_ENDIAN))
-
- assert_equal([-2, "\x00\x00\x00\x00\x00\x00\x00\x01"], Bug::Bignum.test_pack((-0x10000000000000001), 2, 4, 0, BIG_ENDIAN))
- assert_equal([-2, "\x00\x00\x00\x00\x00\x00\x00\x00"], Bug::Bignum.test_pack((-0x10000000000000000), 2, 4, 0, BIG_ENDIAN))
- assert_equal([-1, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], Bug::Bignum.test_pack((-0x0FFFFFFFFFFFFFFFF), 2, 4, 0, BIG_ENDIAN))
- assert_equal([+1, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], Bug::Bignum.test_pack((+0x0FFFFFFFFFFFFFFFF), 2, 4, 0, BIG_ENDIAN))
- assert_equal([+2, "\x00\x00\x00\x00\x00\x00\x00\x00"], Bug::Bignum.test_pack((+0x10000000000000000), 2, 4, 0, BIG_ENDIAN))
- assert_equal([+2, "\x00\x00\x00\x00\x00\x00\x00\x01"], Bug::Bignum.test_pack((+0x10000000000000001), 2, 4, 0, BIG_ENDIAN))
-
- 1.upto(16) {|wordsize|
- 1.upto(20) {|numwords|
- w = numwords*wordsize
- n = 256**w
- assert_equal([-2, "\x00"*(w-1)+"\x01"], Bug::Bignum.test_pack((-n-1), numwords, wordsize, 0, BIG_ENDIAN))
- assert_equal([-2, "\x00"*w], Bug::Bignum.test_pack((-n ), numwords, wordsize, 0, BIG_ENDIAN))
- assert_equal([-1, "\xFF"*w], Bug::Bignum.test_pack((-n+1), numwords, wordsize, 0, BIG_ENDIAN))
- assert_equal([+1, "\xFF"*w], Bug::Bignum.test_pack((+n-1), numwords, wordsize, 0, BIG_ENDIAN))
- assert_equal([+2, "\x00"*w], Bug::Bignum.test_pack((+n ), numwords, wordsize, 0, BIG_ENDIAN))
- assert_equal([+2, "\x00"*(w-1)+"\x01"], Bug::Bignum.test_pack((+n+1), numwords, wordsize, 0, BIG_ENDIAN))
- }
- }
+class TestBignum_Pack < Test::Unit::TestCase
+
+ MSWORD_FIRST = Bug::Bignum::INTEGER_PACK_MSWORD_FIRST
+ LSWORD_FIRST = Bug::Bignum::INTEGER_PACK_LSWORD_FIRST
+ MSBYTE_FIRST = Bug::Bignum::INTEGER_PACK_MSBYTE_FIRST
+ LSBYTE_FIRST = Bug::Bignum::INTEGER_PACK_LSBYTE_FIRST
+ NATIVE_BYTE_ORDER = Bug::Bignum::INTEGER_PACK_NATIVE_BYTE_ORDER
+ TWOCOMP = Bug::Bignum::INTEGER_PACK_2COMP
+ LITTLE_ENDIAN = Bug::Bignum::INTEGER_PACK_LITTLE_ENDIAN
+ BIG_ENDIAN = Bug::Bignum::INTEGER_PACK_BIG_ENDIAN
+ NEGATIVE = Bug::Bignum::INTEGER_PACK_NEGATIVE
+ GENERIC = Bug::Bignum::INTEGER_PACK_FORCE_GENERIC_IMPLEMENTATION
+
+ def test_pack_zero
+ assert_equal([0, ""], Bug::Bignum.test_pack(0, 0, 1, 0, BIG_ENDIAN))
+ end
- 1.upto(16) {|wordsize|
- 1.upto(20) {|numwords|
- w = numwords*wordsize
- n = 256**w
- assert_equal([-2, "\x01"+"\x00"*(w-1)], Bug::Bignum.test_pack((-n-1), numwords, wordsize, 0, LITTLE_ENDIAN))
- assert_equal([-2, "\x00"*w], Bug::Bignum.test_pack((-n ), numwords, wordsize, 0, LITTLE_ENDIAN))
- assert_equal([-1, "\xFF"*w], Bug::Bignum.test_pack((-n+1), numwords, wordsize, 0, LITTLE_ENDIAN))
- assert_equal([+1, "\xFF"*w], Bug::Bignum.test_pack((+n-1), numwords, wordsize, 0, LITTLE_ENDIAN))
- assert_equal([+2, "\x00"*w], Bug::Bignum.test_pack((+n ), numwords, wordsize, 0, LITTLE_ENDIAN))
- assert_equal([+2, "\x01"+"\x00"*(w-1)], Bug::Bignum.test_pack((+n+1), numwords, wordsize, 0, LITTLE_ENDIAN))
- }
+ def test_pack_argument_check
+ assert_raise(ArgumentError) { Bug::Bignum.test_pack_raw(0, "", 2, 1, 0, MSBYTE_FIRST) }
+ assert_raise(ArgumentError) { Bug::Bignum.test_pack_raw(0, "", 0, 1, 0, MSWORD_FIRST) }
+ assert_raise(ArgumentError) { Bug::Bignum.test_pack_raw(0, "", 0, 0, 0, BIG_ENDIAN) }
+ assert_raise(ArgumentError) { Bug::Bignum.test_pack_raw(0, "", 0, 1, 8, BIG_ENDIAN) }
+
+ # assume sizeof(ssize_t) == sizeof(intptr_t)
+ assert_raise(ArgumentError) { Bug::Bignum.test_pack_raw(0, "", 1 << ([""].pack("p").length * 8 - 1), 0, BIG_ENDIAN) }
+ end
+
+ def test_pack_wordsize
+ assert_equal([1, "\x01"], Bug::Bignum.test_pack(1, 1, 1, 0, BIG_ENDIAN))
+ assert_equal([1, "\x00\x01"], Bug::Bignum.test_pack(1, 1, 2, 0, BIG_ENDIAN))
+ assert_equal([1, "\x00\x00\x01"], Bug::Bignum.test_pack(1, 1, 3, 0, BIG_ENDIAN))
+ assert_equal([1, "\x01"], Bug::Bignum.test_pack(1, 1, 1, 0, LITTLE_ENDIAN))
+ assert_equal([1, "\x01\x00"], Bug::Bignum.test_pack(1, 1, 2, 0, LITTLE_ENDIAN))
+ assert_equal([1, "\x01\x00\x00"], Bug::Bignum.test_pack(1, 1, 3, 0, LITTLE_ENDIAN))
+ end
+
+ def test_pack_fixed_buffer
+ assert_equal([0, "\x00\x00"], Bug::Bignum.test_pack(0, 2, 1, 0, BIG_ENDIAN))
+ assert_equal([1, "\x00\x01"], Bug::Bignum.test_pack(0x01, 2, 1, 0, BIG_ENDIAN))
+ assert_equal([1, "\x02\x01"], Bug::Bignum.test_pack(0x0201, 2, 1, 0, BIG_ENDIAN))
+ assert_equal([2, "\x02\x01"], Bug::Bignum.test_pack(0x030201, 2, 1, 0, BIG_ENDIAN))
+ assert_equal([2, "\x02\x01"], Bug::Bignum.test_pack(0x04030201, 2, 1, 0, BIG_ENDIAN))
+ assert_equal([0, "\x00\x00"], Bug::Bignum.test_pack(0, 2, 1, 0, LITTLE_ENDIAN))
+ assert_equal([1, "\x01\x00"], Bug::Bignum.test_pack(0x01, 2, 1, 0, LITTLE_ENDIAN))
+ assert_equal([1, "\x01\x02"], Bug::Bignum.test_pack(0x0201, 2, 1, 0, LITTLE_ENDIAN))
+ assert_equal([2, "\x01\x02"], Bug::Bignum.test_pack(0x030201, 2, 1, 0, LITTLE_ENDIAN))
+ assert_equal([2, "\x01\x02"], Bug::Bignum.test_pack(0x04030201, 2, 1, 0, LITTLE_ENDIAN))
+ end
+
+ def test_pack_wordorder_and_endian
+ assert_equal([1, "\x12\x34\x56\x78"], Bug::Bignum.test_pack(0x12345678, 2, 2, 0, MSWORD_FIRST|MSBYTE_FIRST))
+ assert_equal([1, "\x34\x12\x78\x56"], Bug::Bignum.test_pack(0x12345678, 2, 2, 0, MSWORD_FIRST|LSBYTE_FIRST))
+ assert_equal([1, "\x56\x78\x12\x34"], Bug::Bignum.test_pack(0x12345678, 2, 2, 0, LSWORD_FIRST|MSBYTE_FIRST))
+ assert_equal([1, "\x78\x56\x34\x12"], Bug::Bignum.test_pack(0x12345678, 2, 2, 0, LSWORD_FIRST|LSBYTE_FIRST))
+ end
+
+ def test_pack_native_endian
+ assert_equal([1, [0x1234].pack("S!")], Bug::Bignum.test_pack(0x1234, 1, 2, 0, MSWORD_FIRST|NATIVE_BYTE_ORDER))
+ end
+
+ def test_pack_nail
+ assert_equal([1, "\x01\x00\x00\x00\x01\x01"], Bug::Bignum.test_pack(0b100011, 6, 1, 7, BIG_ENDIAN))
+ assert_equal([1, "\x01\x02\x03\x04\x05\x06\x07\x08"], Bug::Bignum.test_pack(0x12345678, 8, 1, 4, BIG_ENDIAN))
+ assert_equal([1, "\x00\x12\x00\x34\x00\x56\x00\x78"], Bug::Bignum.test_pack(0x12345678, 4, 2, 8, BIG_ENDIAN))
+ end
+
+ def test_pack_overflow
+ assert_equal([-2, "\x1"], Bug::Bignum.test_pack((-0x11), 1, 1, 4, BIG_ENDIAN))
+ assert_equal([-2, "\x0"], Bug::Bignum.test_pack((-0x10), 1, 1, 4, BIG_ENDIAN))
+ assert_equal([-1, "\xF"], Bug::Bignum.test_pack((-0x0F), 1, 1, 4, BIG_ENDIAN))
+ assert_equal([+1, "\xF"], Bug::Bignum.test_pack((+0x0F), 1, 1, 4, BIG_ENDIAN))
+ assert_equal([+2, "\x0"], Bug::Bignum.test_pack((+0x10), 1, 1, 4, BIG_ENDIAN))
+ assert_equal([+2, "\x1"], Bug::Bignum.test_pack((+0x11), 1, 1, 4, BIG_ENDIAN))
+
+ assert_equal([-2, "\x01"], Bug::Bignum.test_pack((-0x101), 1, 1, 0, BIG_ENDIAN))
+ assert_equal([-2, "\x00"], Bug::Bignum.test_pack((-0x100), 1, 1, 0, BIG_ENDIAN))
+ assert_equal([-1, "\xFF"], Bug::Bignum.test_pack((-0x0FF), 1, 1, 0, BIG_ENDIAN))
+ assert_equal([+1, "\xFF"], Bug::Bignum.test_pack((+0x0FF), 1, 1, 0, BIG_ENDIAN))
+ assert_equal([+2, "\x00"], Bug::Bignum.test_pack((+0x100), 1, 1, 0, BIG_ENDIAN))
+ assert_equal([+2, "\x01"], Bug::Bignum.test_pack((+0x101), 1, 1, 0, BIG_ENDIAN))
+
+ assert_equal([-2, "\x00\x00\x00\x00\x00\x00\x00\x01"], Bug::Bignum.test_pack((-0x10000000000000001), 2, 4, 0, BIG_ENDIAN))
+ assert_equal([-2, "\x00\x00\x00\x00\x00\x00\x00\x00"], Bug::Bignum.test_pack((-0x10000000000000000), 2, 4, 0, BIG_ENDIAN))
+ assert_equal([-1, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], Bug::Bignum.test_pack((-0x0FFFFFFFFFFFFFFFF), 2, 4, 0, BIG_ENDIAN))
+ assert_equal([+1, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], Bug::Bignum.test_pack((+0x0FFFFFFFFFFFFFFFF), 2, 4, 0, BIG_ENDIAN))
+ assert_equal([+2, "\x00\x00\x00\x00\x00\x00\x00\x00"], Bug::Bignum.test_pack((+0x10000000000000000), 2, 4, 0, BIG_ENDIAN))
+ assert_equal([+2, "\x00\x00\x00\x00\x00\x00\x00\x01"], Bug::Bignum.test_pack((+0x10000000000000001), 2, 4, 0, BIG_ENDIAN))
+
+ 1.upto(16) {|wordsize|
+ 1.upto(20) {|numwords|
+ w = numwords*wordsize
+ n = 256**w
+ assert_equal([-2, "\x00"*(w-1)+"\x01"], Bug::Bignum.test_pack((-n-1), numwords, wordsize, 0, BIG_ENDIAN))
+ assert_equal([-2, "\x00"*w], Bug::Bignum.test_pack((-n ), numwords, wordsize, 0, BIG_ENDIAN))
+ assert_equal([-1, "\xFF"*w], Bug::Bignum.test_pack((-n+1), numwords, wordsize, 0, BIG_ENDIAN))
+ assert_equal([+1, "\xFF"*w], Bug::Bignum.test_pack((+n-1), numwords, wordsize, 0, BIG_ENDIAN))
+ assert_equal([+2, "\x00"*w], Bug::Bignum.test_pack((+n ), numwords, wordsize, 0, BIG_ENDIAN))
+ assert_equal([+2, "\x00"*(w-1)+"\x01"], Bug::Bignum.test_pack((+n+1), numwords, wordsize, 0, BIG_ENDIAN))
}
- end
-
- def test_pack_sign
- assert_equal([-1, "\x01"], Bug::Bignum.test_pack((-1), 1, 1, 0, BIG_ENDIAN))
- assert_equal([-1, "\x80\x70\x60\x50\x40\x30\x20\x10"], Bug::Bignum.test_pack((-0x8070605040302010), 8, 1, 0, BIG_ENDIAN))
- end
-
- def test_pack_orders
- [MSWORD_FIRST, LSWORD_FIRST].each {|word_order|
- [MSBYTE_FIRST, LSBYTE_FIRST, NATIVE_BYTE_ORDER].each {|byte_order|
- 1.upto(16) {|wordsize|
- 1.upto(20) {|numwords|
- w = numwords*wordsize
- n = 0;
- 0.upto(w) {|i|
- n |= ((i+1) % 256) << (i*8)
- }
- assert_equal(Bug::Bignum.test_pack(n, numwords, wordsize, 0, word_order|byte_order|GENERIC),
- Bug::Bignum.test_pack(n, numwords, wordsize, 0, word_order|byte_order),
- "#{'%#x' % n}.test_pack(#{numwords}, #{wordsize}, 0, #{'%#x' % (word_order|byte_order)})")
+ }
+
+ 1.upto(16) {|wordsize|
+ 1.upto(20) {|numwords|
+ w = numwords*wordsize
+ n = 256**w
+ assert_equal([-2, "\x01"+"\x00"*(w-1)], Bug::Bignum.test_pack((-n-1), numwords, wordsize, 0, LITTLE_ENDIAN))
+ assert_equal([-2, "\x00"*w], Bug::Bignum.test_pack((-n ), numwords, wordsize, 0, LITTLE_ENDIAN))
+ assert_equal([-1, "\xFF"*w], Bug::Bignum.test_pack((-n+1), numwords, wordsize, 0, LITTLE_ENDIAN))
+ assert_equal([+1, "\xFF"*w], Bug::Bignum.test_pack((+n-1), numwords, wordsize, 0, LITTLE_ENDIAN))
+ assert_equal([+2, "\x00"*w], Bug::Bignum.test_pack((+n ), numwords, wordsize, 0, LITTLE_ENDIAN))
+ assert_equal([+2, "\x01"+"\x00"*(w-1)], Bug::Bignum.test_pack((+n+1), numwords, wordsize, 0, LITTLE_ENDIAN))
+ }
+ }
+ end
+
+ def test_pack_sign
+ assert_equal([-1, "\x01"], Bug::Bignum.test_pack((-1), 1, 1, 0, BIG_ENDIAN))
+ assert_equal([-1, "\x80\x70\x60\x50\x40\x30\x20\x10"], Bug::Bignum.test_pack((-0x8070605040302010), 8, 1, 0, BIG_ENDIAN))
+ end
+
+ def test_pack_orders
+ [MSWORD_FIRST, LSWORD_FIRST].each {|word_order|
+ [MSBYTE_FIRST, LSBYTE_FIRST, NATIVE_BYTE_ORDER].each {|byte_order|
+ 1.upto(16) {|wordsize|
+ 1.upto(20) {|numwords|
+ w = numwords*wordsize
+ n = 0;
+ 0.upto(w) {|i|
+ n |= ((i+1) % 256) << (i*8)
}
+ assert_equal(Bug::Bignum.test_pack(n, numwords, wordsize, 0, word_order|byte_order|GENERIC),
+ Bug::Bignum.test_pack(n, numwords, wordsize, 0, word_order|byte_order),
+ "#{'%#x' % n}.test_pack(#{numwords}, #{wordsize}, 0, #{'%#x' % (word_order|byte_order)})")
}
}
}
- end
-
- def test_pack2comp_zero
- assert_equal([0, ""], Bug::Bignum.test_pack(0, 0, 1, 0, TWOCOMP|BIG_ENDIAN))
- end
-
- def test_pack2comp_emptybuf
- assert_equal([-2, ""], Bug::Bignum.test_pack((-3), 0, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([-2, ""], Bug::Bignum.test_pack((-2), 0, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([-1, ""], Bug::Bignum.test_pack((-1), 0, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([ 0, ""], Bug::Bignum.test_pack(0, 0, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([+2, ""], Bug::Bignum.test_pack(1, 0, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([+2, ""], Bug::Bignum.test_pack(2, 0, 1, 0, TWOCOMP|BIG_ENDIAN))
- end
-
- def test_pack2comp_nearly_zero
- assert_equal([-1, "\xFE"], Bug::Bignum.test_pack((-2), 1, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([-1, "\xFF"], Bug::Bignum.test_pack((-1), 1, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([ 0, "\x00"], Bug::Bignum.test_pack(0, 1, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([+1, "\x01"], Bug::Bignum.test_pack(1, 1, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([+1, "\x02"], Bug::Bignum.test_pack(2, 1, 1, 0, TWOCOMP|BIG_ENDIAN))
- end
-
- def test_pack2comp_overflow
- assert_equal([-2, "\xF"], Bug::Bignum.test_pack((-0x11), 1, 1, 4, TWOCOMP|BIG_ENDIAN))
- assert_equal([-1, "\x0"], Bug::Bignum.test_pack((-0x10), 1, 1, 4, TWOCOMP|BIG_ENDIAN))
- assert_equal([-1, "\x1"], Bug::Bignum.test_pack((-0x0F), 1, 1, 4, TWOCOMP|BIG_ENDIAN))
- assert_equal([+1, "\xF"], Bug::Bignum.test_pack((+0x0F), 1, 1, 4, TWOCOMP|BIG_ENDIAN))
- assert_equal([+2, "\x0"], Bug::Bignum.test_pack((+0x10), 1, 1, 4, TWOCOMP|BIG_ENDIAN))
- assert_equal([+2, "\x1"], Bug::Bignum.test_pack((+0x11), 1, 1, 4, TWOCOMP|BIG_ENDIAN))
-
- assert_equal([-2, "\xFF"], Bug::Bignum.test_pack((-0x101), 1, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([-1, "\x00"], Bug::Bignum.test_pack((-0x100), 1, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([-1, "\x01"], Bug::Bignum.test_pack((-0x0FF), 1, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([+1, "\xFF"], Bug::Bignum.test_pack((+0x0FF), 1, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([+2, "\x00"], Bug::Bignum.test_pack((+0x100), 1, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([+2, "\x01"], Bug::Bignum.test_pack((+0x101), 1, 1, 0, TWOCOMP|BIG_ENDIAN))
-
- assert_equal([-2, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], Bug::Bignum.test_pack((-0x10000000000000001), 2, 4, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([-1, "\x00\x00\x00\x00\x00\x00\x00\x00"], Bug::Bignum.test_pack((-0x10000000000000000), 2, 4, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([-1, "\x00\x00\x00\x00\x00\x00\x00\x01"], Bug::Bignum.test_pack((-0x0FFFFFFFFFFFFFFFF), 2, 4, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([+1, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], Bug::Bignum.test_pack((+0x0FFFFFFFFFFFFFFFF), 2, 4, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([+2, "\x00\x00\x00\x00\x00\x00\x00\x00"], Bug::Bignum.test_pack((+0x10000000000000000), 2, 4, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([+2, "\x00\x00\x00\x00\x00\x00\x00\x01"], Bug::Bignum.test_pack((+0x10000000000000001), 2, 4, 0, TWOCOMP|BIG_ENDIAN))
-
- 1.upto(16) {|wordsize|
- 1.upto(20) {|numwords|
- w = numwords*wordsize
- n = 256**w
- assert_equal([-2, "\xFF"*w ], Bug::Bignum.test_pack((-n-1), numwords, wordsize, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([-1, "\x00"*w], Bug::Bignum.test_pack((-n ), numwords, wordsize, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([-1, "\x00"*(w-1)+"\x01"], Bug::Bignum.test_pack((-n+1), numwords, wordsize, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([+1, "\xFF"*w], Bug::Bignum.test_pack((+n-1), numwords, wordsize, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([+2, "\x00"*w], Bug::Bignum.test_pack((+n ), numwords, wordsize, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal([+2, "\x00"*(w-1)+"\x01"], Bug::Bignum.test_pack((+n+1), numwords, wordsize, 0, TWOCOMP|BIG_ENDIAN))
- }
- }
+ }
+ end
- 1.upto(16) {|wordsize|
- 1.upto(20) {|numwords|
- w = numwords*wordsize
- n = 256**w
- assert_equal([-2, "\xFF"*w ], Bug::Bignum.test_pack((-n-1), numwords, wordsize, 0, TWOCOMP|LITTLE_ENDIAN))
- assert_equal([-1, "\x00"*w], Bug::Bignum.test_pack((-n ), numwords, wordsize, 0, TWOCOMP|LITTLE_ENDIAN))
- assert_equal([-1, "\x01"+"\x00"*(w-1)], Bug::Bignum.test_pack((-n+1), numwords, wordsize, 0, TWOCOMP|LITTLE_ENDIAN))
- assert_equal([+1, "\xFF"*w], Bug::Bignum.test_pack((+n-1), numwords, wordsize, 0, TWOCOMP|LITTLE_ENDIAN))
- assert_equal([+2, "\x00"*w], Bug::Bignum.test_pack((+n ), numwords, wordsize, 0, TWOCOMP|LITTLE_ENDIAN))
- assert_equal([+2, "\x01"+"\x00"*(w-1)], Bug::Bignum.test_pack((+n+1), numwords, wordsize, 0, TWOCOMP|LITTLE_ENDIAN))
- }
- }
+ def test_pack2comp_zero
+ assert_equal([0, ""], Bug::Bignum.test_pack(0, 0, 1, 0, TWOCOMP|BIG_ENDIAN))
+ end
- 2.upto(16) {|wordsize|
- w = wordsize
- b = 8*wordsize-1
- n = 2**b
- assert_equal([-2, "\x7F"+"\xFF"*(w-2)+"\xFF"], Bug::Bignum.test_pack((-n-1), 1, wordsize, 1, TWOCOMP|MSBYTE_FIRST))
- assert_equal([-1, "\x00"+"\x00"*(w-2)+"\x00"], Bug::Bignum.test_pack((-n ), 1, wordsize, 1, TWOCOMP|MSBYTE_FIRST))
- assert_equal([-1, "\x00"+"\x00"*(w-2)+"\x01"], Bug::Bignum.test_pack((-n+1), 1, wordsize, 1, TWOCOMP|MSBYTE_FIRST))
- assert_equal([+1, "\x7F"+"\xFF"*(w-2)+"\xFF"], Bug::Bignum.test_pack((+n-1), 1, wordsize, 1, TWOCOMP|MSBYTE_FIRST))
- assert_equal([+2, "\x00"+"\x00"*(w-2)+"\x00"], Bug::Bignum.test_pack((+n ), 1, wordsize, 1, TWOCOMP|MSBYTE_FIRST))
- assert_equal([+2, "\x00"+"\x00"*(w-2)+"\x01"], Bug::Bignum.test_pack((+n+1), 1, wordsize, 1, TWOCOMP|MSBYTE_FIRST))
- }
+ def test_pack2comp_emptybuf
+ assert_equal([-2, ""], Bug::Bignum.test_pack((-3), 0, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([-2, ""], Bug::Bignum.test_pack((-2), 0, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([-1, ""], Bug::Bignum.test_pack((-1), 0, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([ 0, ""], Bug::Bignum.test_pack(0, 0, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([+2, ""], Bug::Bignum.test_pack(1, 0, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([+2, ""], Bug::Bignum.test_pack(2, 0, 1, 0, TWOCOMP|BIG_ENDIAN))
+ end
- 2.upto(16) {|wordsize|
- w = wordsize
- b = 8*wordsize-1
- n = 2**b
- assert_equal([-2, "\xFF"+"\xFF"*(w-2)+"\x7F"], Bug::Bignum.test_pack((-n-1), 1, wordsize, 1, TWOCOMP|LSBYTE_FIRST))
- assert_equal([-1, "\x00"+"\x00"*(w-2)+"\x00"], Bug::Bignum.test_pack((-n ), 1, wordsize, 1, TWOCOMP|LSBYTE_FIRST))
- assert_equal([-1, "\x01"+"\x00"*(w-2)+"\x00"], Bug::Bignum.test_pack((-n+1), 1, wordsize, 1, TWOCOMP|LSBYTE_FIRST))
- assert_equal([+1, "\xFF"+"\xFF"*(w-2)+"\x7F"], Bug::Bignum.test_pack((+n-1), 1, wordsize, 1, TWOCOMP|LSBYTE_FIRST))
- assert_equal([+2, "\x00"+"\x00"*(w-2)+"\x00"], Bug::Bignum.test_pack((+n ), 1, wordsize, 1, TWOCOMP|LSBYTE_FIRST))
- assert_equal([+2, "\x01"+"\x00"*(w-2)+"\x00"], Bug::Bignum.test_pack((+n+1), 1, wordsize, 1, TWOCOMP|LSBYTE_FIRST))
+ def test_pack2comp_nearly_zero
+ assert_equal([-1, "\xFE"], Bug::Bignum.test_pack((-2), 1, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([-1, "\xFF"], Bug::Bignum.test_pack((-1), 1, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([ 0, "\x00"], Bug::Bignum.test_pack(0, 1, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([+1, "\x01"], Bug::Bignum.test_pack(1, 1, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([+1, "\x02"], Bug::Bignum.test_pack(2, 1, 1, 0, TWOCOMP|BIG_ENDIAN))
+ end
+
+ def test_pack2comp_overflow
+ assert_equal([-2, "\xF"], Bug::Bignum.test_pack((-0x11), 1, 1, 4, TWOCOMP|BIG_ENDIAN))
+ assert_equal([-1, "\x0"], Bug::Bignum.test_pack((-0x10), 1, 1, 4, TWOCOMP|BIG_ENDIAN))
+ assert_equal([-1, "\x1"], Bug::Bignum.test_pack((-0x0F), 1, 1, 4, TWOCOMP|BIG_ENDIAN))
+ assert_equal([+1, "\xF"], Bug::Bignum.test_pack((+0x0F), 1, 1, 4, TWOCOMP|BIG_ENDIAN))
+ assert_equal([+2, "\x0"], Bug::Bignum.test_pack((+0x10), 1, 1, 4, TWOCOMP|BIG_ENDIAN))
+ assert_equal([+2, "\x1"], Bug::Bignum.test_pack((+0x11), 1, 1, 4, TWOCOMP|BIG_ENDIAN))
+
+ assert_equal([-2, "\xFF"], Bug::Bignum.test_pack((-0x101), 1, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([-1, "\x00"], Bug::Bignum.test_pack((-0x100), 1, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([-1, "\x01"], Bug::Bignum.test_pack((-0x0FF), 1, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([+1, "\xFF"], Bug::Bignum.test_pack((+0x0FF), 1, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([+2, "\x00"], Bug::Bignum.test_pack((+0x100), 1, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([+2, "\x01"], Bug::Bignum.test_pack((+0x101), 1, 1, 0, TWOCOMP|BIG_ENDIAN))
+
+ assert_equal([-2, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], Bug::Bignum.test_pack((-0x10000000000000001), 2, 4, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([-1, "\x00\x00\x00\x00\x00\x00\x00\x00"], Bug::Bignum.test_pack((-0x10000000000000000), 2, 4, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([-1, "\x00\x00\x00\x00\x00\x00\x00\x01"], Bug::Bignum.test_pack((-0x0FFFFFFFFFFFFFFFF), 2, 4, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([+1, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"], Bug::Bignum.test_pack((+0x0FFFFFFFFFFFFFFFF), 2, 4, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([+2, "\x00\x00\x00\x00\x00\x00\x00\x00"], Bug::Bignum.test_pack((+0x10000000000000000), 2, 4, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([+2, "\x00\x00\x00\x00\x00\x00\x00\x01"], Bug::Bignum.test_pack((+0x10000000000000001), 2, 4, 0, TWOCOMP|BIG_ENDIAN))
+
+ 1.upto(16) {|wordsize|
+ 1.upto(20) {|numwords|
+ w = numwords*wordsize
+ n = 256**w
+ assert_equal([-2, "\xFF"*w ], Bug::Bignum.test_pack((-n-1), numwords, wordsize, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([-1, "\x00"*w], Bug::Bignum.test_pack((-n ), numwords, wordsize, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([-1, "\x00"*(w-1)+"\x01"], Bug::Bignum.test_pack((-n+1), numwords, wordsize, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([+1, "\xFF"*w], Bug::Bignum.test_pack((+n-1), numwords, wordsize, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([+2, "\x00"*w], Bug::Bignum.test_pack((+n ), numwords, wordsize, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal([+2, "\x00"*(w-1)+"\x01"], Bug::Bignum.test_pack((+n+1), numwords, wordsize, 0, TWOCOMP|BIG_ENDIAN))
}
+ }
+
+ 1.upto(16) {|wordsize|
+ 1.upto(20) {|numwords|
+ w = numwords*wordsize
+ n = 256**w
+ assert_equal([-2, "\xFF"*w ], Bug::Bignum.test_pack((-n-1), numwords, wordsize, 0, TWOCOMP|LITTLE_ENDIAN))
+ assert_equal([-1, "\x00"*w], Bug::Bignum.test_pack((-n ), numwords, wordsize, 0, TWOCOMP|LITTLE_ENDIAN))
+ assert_equal([-1, "\x01"+"\x00"*(w-1)], Bug::Bignum.test_pack((-n+1), numwords, wordsize, 0, TWOCOMP|LITTLE_ENDIAN))
+ assert_equal([+1, "\xFF"*w], Bug::Bignum.test_pack((+n-1), numwords, wordsize, 0, TWOCOMP|LITTLE_ENDIAN))
+ assert_equal([+2, "\x00"*w], Bug::Bignum.test_pack((+n ), numwords, wordsize, 0, TWOCOMP|LITTLE_ENDIAN))
+ assert_equal([+2, "\x01"+"\x00"*(w-1)], Bug::Bignum.test_pack((+n+1), numwords, wordsize, 0, TWOCOMP|LITTLE_ENDIAN))
+ }
+ }
+
+ 2.upto(16) {|wordsize|
+ w = wordsize
+ b = 8*wordsize-1
+ n = 2**b
+ assert_equal([-2, "\x7F"+"\xFF"*(w-2)+"\xFF"], Bug::Bignum.test_pack((-n-1), 1, wordsize, 1, TWOCOMP|MSBYTE_FIRST))
+ assert_equal([-1, "\x00"+"\x00"*(w-2)+"\x00"], Bug::Bignum.test_pack((-n ), 1, wordsize, 1, TWOCOMP|MSBYTE_FIRST))
+ assert_equal([-1, "\x00"+"\x00"*(w-2)+"\x01"], Bug::Bignum.test_pack((-n+1), 1, wordsize, 1, TWOCOMP|MSBYTE_FIRST))
+ assert_equal([+1, "\x7F"+"\xFF"*(w-2)+"\xFF"], Bug::Bignum.test_pack((+n-1), 1, wordsize, 1, TWOCOMP|MSBYTE_FIRST))
+ assert_equal([+2, "\x00"+"\x00"*(w-2)+"\x00"], Bug::Bignum.test_pack((+n ), 1, wordsize, 1, TWOCOMP|MSBYTE_FIRST))
+ assert_equal([+2, "\x00"+"\x00"*(w-2)+"\x01"], Bug::Bignum.test_pack((+n+1), 1, wordsize, 1, TWOCOMP|MSBYTE_FIRST))
+ }
+
+ 2.upto(16) {|wordsize|
+ w = wordsize
+ b = 8*wordsize-1
+ n = 2**b
+ assert_equal([-2, "\xFF"+"\xFF"*(w-2)+"\x7F"], Bug::Bignum.test_pack((-n-1), 1, wordsize, 1, TWOCOMP|LSBYTE_FIRST))
+ assert_equal([-1, "\x00"+"\x00"*(w-2)+"\x00"], Bug::Bignum.test_pack((-n ), 1, wordsize, 1, TWOCOMP|LSBYTE_FIRST))
+ assert_equal([-1, "\x01"+"\x00"*(w-2)+"\x00"], Bug::Bignum.test_pack((-n+1), 1, wordsize, 1, TWOCOMP|LSBYTE_FIRST))
+ assert_equal([+1, "\xFF"+"\xFF"*(w-2)+"\x7F"], Bug::Bignum.test_pack((+n-1), 1, wordsize, 1, TWOCOMP|LSBYTE_FIRST))
+ assert_equal([+2, "\x00"+"\x00"*(w-2)+"\x00"], Bug::Bignum.test_pack((+n ), 1, wordsize, 1, TWOCOMP|LSBYTE_FIRST))
+ assert_equal([+2, "\x01"+"\x00"*(w-2)+"\x00"], Bug::Bignum.test_pack((+n+1), 1, wordsize, 1, TWOCOMP|LSBYTE_FIRST))
+ }
+
+ end
+
+ def test_unpack_zero
+ assert_equal(0, Bug::Bignum.test_unpack("", 0, 1, 0, BIG_ENDIAN))
+ end
+
+ def test_unpack_argument_check
+ assert_raise(ArgumentError) { Bug::Bignum.test_unpack("x", 2, 1, 0, MSBYTE_FIRST) }
+ assert_raise(ArgumentError) { Bug::Bignum.test_unpack("x", 1, 1, 0, MSWORD_FIRST) }
+ assert_raise(ArgumentError) { Bug::Bignum.test_unpack("x", 1, 0, 0, BIG_ENDIAN) }
+ assert_raise(ArgumentError) { Bug::Bignum.test_unpack("x", 1, 1, 8, BIG_ENDIAN) }
+
+ # assume sizeof(ssize_t) == sizeof(intptr_t)
+ assert_raise(ArgumentError) { Bug::Bignum.test_unpack("x", 1, 1 << ([""].pack("p").length * 8 - 1), 0, BIG_ENDIAN) }
+ end
+
+ def test_unpack_wordsize
+ assert_equal(1, Bug::Bignum.test_unpack("\x01", 1, 1, 0, BIG_ENDIAN))
+ assert_equal(1, Bug::Bignum.test_unpack("\x00\x01", 1, 2, 0, BIG_ENDIAN))
+ assert_equal(1, Bug::Bignum.test_unpack("\x00\x00\x01", 1, 3, 0, BIG_ENDIAN))
+ assert_equal(1, Bug::Bignum.test_unpack("\x01", 1, 1, 0, LITTLE_ENDIAN))
+ assert_equal(1, Bug::Bignum.test_unpack("\x01\x00", 1, 2, 0, LITTLE_ENDIAN))
+ assert_equal(1, Bug::Bignum.test_unpack("\x01\x00\x00", 1, 3, 0, LITTLE_ENDIAN))
+ end
+
+ def test_unpack_wordorder_and_endian
+ assert_equal(0x01020304, Bug::Bignum.test_unpack("\x01\x02\x03\x04", 2, 2, 0, MSWORD_FIRST|MSBYTE_FIRST))
+ assert_equal(0x02010403, Bug::Bignum.test_unpack("\x01\x02\x03\x04", 2, 2, 0, MSWORD_FIRST|LSBYTE_FIRST))
+ assert_equal(0x03040102, Bug::Bignum.test_unpack("\x01\x02\x03\x04", 2, 2, 0, LSWORD_FIRST|MSBYTE_FIRST))
+ assert_equal(0x04030201, Bug::Bignum.test_unpack("\x01\x02\x03\x04", 2, 2, 0, LSWORD_FIRST|LSBYTE_FIRST))
+ end
+
+ def test_unpack_native_endian
+ assert_equal("\x12\x34".unpack("S!")[0], Bug::Bignum.test_unpack("\x12\x34", 1, 2, 0, MSWORD_FIRST|NATIVE_BYTE_ORDER))
+ end
+
+ def test_unpack_nail
+ assert_equal(0b100011, Bug::Bignum.test_unpack("\x01\x00\x00\x00\x01\x01", 6, 1, 7, BIG_ENDIAN))
+ assert_equal(0x12345678, Bug::Bignum.test_unpack("\x01\x02\x03\x04\x05\x06\x07\x08", 8, 1, 4, BIG_ENDIAN))
+ assert_equal(0x12345678, Bug::Bignum.test_unpack("\x00\x12\x00\x34\x00\x56\x00\x78", 4, 2, 8, BIG_ENDIAN))
+ end
+
+ def test_unpack_sign
+ assert_equal(-1, Bug::Bignum.test_unpack("\x01", 1, 1, 0, BIG_ENDIAN|NEGATIVE))
+ assert_equal(-0x8070605040302010, Bug::Bignum.test_unpack("\x80\x70\x60\x50\x40\x30\x20\x10", 8, 1, 0, BIG_ENDIAN|NEGATIVE))
+ end
- end
-
- def test_unpack_zero
- assert_equal(0, Bug::Bignum.test_unpack("", 0, 1, 0, BIG_ENDIAN))
- end
-
- def test_unpack_argument_check
- assert_raise(ArgumentError) { Bug::Bignum.test_unpack("x", 2, 1, 0, MSBYTE_FIRST) }
- assert_raise(ArgumentError) { Bug::Bignum.test_unpack("x", 1, 1, 0, MSWORD_FIRST) }
- assert_raise(ArgumentError) { Bug::Bignum.test_unpack("x", 1, 0, 0, BIG_ENDIAN) }
- assert_raise(ArgumentError) { Bug::Bignum.test_unpack("x", 1, 1, 8, BIG_ENDIAN) }
-
- # assume sizeof(ssize_t) == sizeof(intptr_t)
- assert_raise(ArgumentError) { Bug::Bignum.test_unpack("x", 1, 1 << ([""].pack("p").length * 8 - 1), 0, BIG_ENDIAN) }
- end
-
- def test_unpack_wordsize
- assert_equal(1, Bug::Bignum.test_unpack("\x01", 1, 1, 0, BIG_ENDIAN))
- assert_equal(1, Bug::Bignum.test_unpack("\x00\x01", 1, 2, 0, BIG_ENDIAN))
- assert_equal(1, Bug::Bignum.test_unpack("\x00\x00\x01", 1, 3, 0, BIG_ENDIAN))
- assert_equal(1, Bug::Bignum.test_unpack("\x01", 1, 1, 0, LITTLE_ENDIAN))
- assert_equal(1, Bug::Bignum.test_unpack("\x01\x00", 1, 2, 0, LITTLE_ENDIAN))
- assert_equal(1, Bug::Bignum.test_unpack("\x01\x00\x00", 1, 3, 0, LITTLE_ENDIAN))
- end
-
- def test_unpack_wordorder_and_endian
- assert_equal(0x01020304, Bug::Bignum.test_unpack("\x01\x02\x03\x04", 2, 2, 0, MSWORD_FIRST|MSBYTE_FIRST))
- assert_equal(0x02010403, Bug::Bignum.test_unpack("\x01\x02\x03\x04", 2, 2, 0, MSWORD_FIRST|LSBYTE_FIRST))
- assert_equal(0x03040102, Bug::Bignum.test_unpack("\x01\x02\x03\x04", 2, 2, 0, LSWORD_FIRST|MSBYTE_FIRST))
- assert_equal(0x04030201, Bug::Bignum.test_unpack("\x01\x02\x03\x04", 2, 2, 0, LSWORD_FIRST|LSBYTE_FIRST))
- end
-
- def test_unpack_native_endian
- assert_equal("\x12\x34".unpack("S!")[0], Bug::Bignum.test_unpack("\x12\x34", 1, 2, 0, MSWORD_FIRST|NATIVE_BYTE_ORDER))
- end
-
- def test_unpack_nail
- assert_equal(0b100011, Bug::Bignum.test_unpack("\x01\x00\x00\x00\x01\x01", 6, 1, 7, BIG_ENDIAN))
- assert_equal(0x12345678, Bug::Bignum.test_unpack("\x01\x02\x03\x04\x05\x06\x07\x08", 8, 1, 4, BIG_ENDIAN))
- assert_equal(0x12345678, Bug::Bignum.test_unpack("\x00\x12\x00\x34\x00\x56\x00\x78", 4, 2, 8, BIG_ENDIAN))
- end
-
- def test_unpack_sign
- assert_equal(-1, Bug::Bignum.test_unpack("\x01", 1, 1, 0, BIG_ENDIAN|NEGATIVE))
- assert_equal(-0x8070605040302010, Bug::Bignum.test_unpack("\x80\x70\x60\x50\x40\x30\x20\x10", 8, 1, 0, BIG_ENDIAN|NEGATIVE))
- end
-
- def test_unpack_orders
- [MSWORD_FIRST, LSWORD_FIRST].each {|word_order|
- [MSBYTE_FIRST, LSBYTE_FIRST, NATIVE_BYTE_ORDER].each {|byte_order|
- 1.upto(16) {|wordsize|
- 1.upto(20) {|numwords|
- w = numwords*wordsize
- ary = []
- 0.upto(w) {|i|
- ary << ((i+1) % 256);
- }
- str = ary.pack("C*")
- flags = word_order|byte_order
- assert_equal(Bug::Bignum.test_unpack(str, numwords, wordsize, 0, flags|GENERIC),
- Bug::Bignum.test_unpack(str, numwords, wordsize, 0, flags),
- "Bug::Bignum.test_unpack(#{str.dump}, #{numwords}, #{wordsize}, 0, #{'%#x' % flags})")
+ def test_unpack_orders
+ [MSWORD_FIRST, LSWORD_FIRST].each {|word_order|
+ [MSBYTE_FIRST, LSBYTE_FIRST, NATIVE_BYTE_ORDER].each {|byte_order|
+ 1.upto(16) {|wordsize|
+ 1.upto(20) {|numwords|
+ w = numwords*wordsize
+ ary = []
+ 0.upto(w) {|i|
+ ary << ((i+1) % 256);
}
+ str = ary.pack("C*")
+ flags = word_order|byte_order
+ assert_equal(Bug::Bignum.test_unpack(str, numwords, wordsize, 0, flags|GENERIC),
+ Bug::Bignum.test_unpack(str, numwords, wordsize, 0, flags),
+ "Bug::Bignum.test_unpack(#{str.dump}, #{numwords}, #{wordsize}, 0, #{'%#x' % flags})")
}
}
}
- end
-
- def test_unpack2comp_single_byte
- assert_equal(-128, Bug::Bignum.test_unpack("\x80", 1, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal( -2, Bug::Bignum.test_unpack("\xFE", 1, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal( -1, Bug::Bignum.test_unpack("\xFF", 1, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal( 0, Bug::Bignum.test_unpack("\x00", 1, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal( 1, Bug::Bignum.test_unpack("\x01", 1, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal( 2, Bug::Bignum.test_unpack("\x02", 1, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal( 127, Bug::Bignum.test_unpack("\x7F", 1, 1, 0, TWOCOMP|BIG_ENDIAN))
- end
-
- def test_unpack2comp_sequence_of_ff
- assert_equal(-1, Bug::Bignum.test_unpack("\xFF"*2, 2, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal(-1, Bug::Bignum.test_unpack("\xFF"*3, 3, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal(-1, Bug::Bignum.test_unpack("\xFF"*4, 4, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal(-1, Bug::Bignum.test_unpack("\xFF"*5, 5, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal(-1, Bug::Bignum.test_unpack("\xFF"*6, 6, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal(-1, Bug::Bignum.test_unpack("\xFF"*7, 7, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal(-1, Bug::Bignum.test_unpack("\xFF"*8, 8, 1, 0, TWOCOMP|BIG_ENDIAN))
- assert_equal(-1, Bug::Bignum.test_unpack("\xFF"*9, 9, 1, 0, TWOCOMP|BIG_ENDIAN))
- end
-
- def test_unpack2comp_negative_single_byte
- assert_equal(-256, Bug::Bignum.test_unpack("\x00", 1, 1, 0, TWOCOMP|BIG_ENDIAN|NEGATIVE))
- assert_equal(-255, Bug::Bignum.test_unpack("\x01", 1, 1, 0, TWOCOMP|BIG_ENDIAN|NEGATIVE))
- assert_equal(-254, Bug::Bignum.test_unpack("\x02", 1, 1, 0, TWOCOMP|BIG_ENDIAN|NEGATIVE))
- assert_equal(-129, Bug::Bignum.test_unpack("\x7F", 1, 1, 0, TWOCOMP|BIG_ENDIAN|NEGATIVE))
- assert_equal(-128, Bug::Bignum.test_unpack("\x80", 1, 1, 0, TWOCOMP|BIG_ENDIAN|NEGATIVE))
- assert_equal( -2, Bug::Bignum.test_unpack("\xFE", 1, 1, 0, TWOCOMP|BIG_ENDIAN|NEGATIVE))
- assert_equal( -1, Bug::Bignum.test_unpack("\xFF", 1, 1, 0, TWOCOMP|BIG_ENDIAN|NEGATIVE))
- end
-
- def test_unpack2comp_negative_zero
- 0.upto(100) {|n|
- str = "\x00"*n
- flags = TWOCOMP|BIG_ENDIAN|NEGATIVE
- assert_equal(-(256**n), Bug::Bignum.test_unpack(str, n, 1, 0, flags))
- flags = TWOCOMP|LITTLE_ENDIAN|NEGATIVE
- assert_equal(-(256**n), Bug::Bignum.test_unpack(str, n, 1, 0, flags),
- "Bug::Bignum.test_unpack(#{str.dump}, #{n}, 1, 0, #{'%#x' % flags})")
- }
- end
+ }
+ end
+
+ def test_unpack2comp_single_byte
+ assert_equal(-128, Bug::Bignum.test_unpack("\x80", 1, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal( -2, Bug::Bignum.test_unpack("\xFE", 1, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal( -1, Bug::Bignum.test_unpack("\xFF", 1, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal( 0, Bug::Bignum.test_unpack("\x00", 1, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal( 1, Bug::Bignum.test_unpack("\x01", 1, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal( 2, Bug::Bignum.test_unpack("\x02", 1, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal( 127, Bug::Bignum.test_unpack("\x7F", 1, 1, 0, TWOCOMP|BIG_ENDIAN))
+ end
+
+ def test_unpack2comp_sequence_of_ff
+ assert_equal(-1, Bug::Bignum.test_unpack("\xFF"*2, 2, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal(-1, Bug::Bignum.test_unpack("\xFF"*3, 3, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal(-1, Bug::Bignum.test_unpack("\xFF"*4, 4, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal(-1, Bug::Bignum.test_unpack("\xFF"*5, 5, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal(-1, Bug::Bignum.test_unpack("\xFF"*6, 6, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal(-1, Bug::Bignum.test_unpack("\xFF"*7, 7, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal(-1, Bug::Bignum.test_unpack("\xFF"*8, 8, 1, 0, TWOCOMP|BIG_ENDIAN))
+ assert_equal(-1, Bug::Bignum.test_unpack("\xFF"*9, 9, 1, 0, TWOCOMP|BIG_ENDIAN))
+ end
+
+ def test_unpack2comp_negative_single_byte
+ assert_equal(-256, Bug::Bignum.test_unpack("\x00", 1, 1, 0, TWOCOMP|BIG_ENDIAN|NEGATIVE))
+ assert_equal(-255, Bug::Bignum.test_unpack("\x01", 1, 1, 0, TWOCOMP|BIG_ENDIAN|NEGATIVE))
+ assert_equal(-254, Bug::Bignum.test_unpack("\x02", 1, 1, 0, TWOCOMP|BIG_ENDIAN|NEGATIVE))
+ assert_equal(-129, Bug::Bignum.test_unpack("\x7F", 1, 1, 0, TWOCOMP|BIG_ENDIAN|NEGATIVE))
+ assert_equal(-128, Bug::Bignum.test_unpack("\x80", 1, 1, 0, TWOCOMP|BIG_ENDIAN|NEGATIVE))
+ assert_equal( -2, Bug::Bignum.test_unpack("\xFE", 1, 1, 0, TWOCOMP|BIG_ENDIAN|NEGATIVE))
+ assert_equal( -1, Bug::Bignum.test_unpack("\xFF", 1, 1, 0, TWOCOMP|BIG_ENDIAN|NEGATIVE))
+ end
+
+ def test_unpack2comp_negative_zero
+ 0.upto(100) {|n|
+ str = "\x00"*n
+ flags = TWOCOMP|BIG_ENDIAN|NEGATIVE
+ assert_equal(-(256**n), Bug::Bignum.test_unpack(str, n, 1, 0, flags))
+ flags = TWOCOMP|LITTLE_ENDIAN|NEGATIVE
+ assert_equal(-(256**n), Bug::Bignum.test_unpack(str, n, 1, 0, flags),
+ "Bug::Bignum.test_unpack(#{str.dump}, #{n}, 1, 0, #{'%#x' % flags})")
+ }
end
def test_numbits_2comp
@@ -395,5 +393,4 @@ class Test_Bignum < Test::Unit::TestCase
assert_equal(5, Bug::Bignum.test_numbytes_2comp_with_sign(0x7fffffffff))
assert_equal(6, Bug::Bignum.test_numbytes_2comp_with_sign(0x8000000000))
end
-
end
diff --git a/test/-ext-/bignum/test_str2big.rb b/test/-ext-/bignum/test_str2big.rb
index d5bd72a85b..d27e4d23f7 100644
--- a/test/-ext-/bignum/test_str2big.rb
+++ b/test/-ext-/bignum/test_str2big.rb
@@ -2,37 +2,35 @@
require 'test/unit'
require "-test-/bignum"
-class Test_Bignum < Test::Unit::TestCase
- class TestStr2big < Test::Unit::TestCase
+class TestBignum_Str2big < Test::Unit::TestCase
- SIZEOF_BDIGIT = Bug::Bignum::SIZEOF_BDIGIT
- BITSPERDIG = Bug::Bignum::BITSPERDIG
- BDIGMAX = (1 << BITSPERDIG) - 1
+ SIZEOF_BDIGIT = Bug::Bignum::SIZEOF_BDIGIT
+ BITSPERDIG = Bug::Bignum::BITSPERDIG
+ BDIGMAX = (1 << BITSPERDIG) - 1
- def test_str2big_poweroftwo
- s = "1" + "0" * 1000
- n = 16 ** 1000
- assert_equal(n, Bug::Bignum.str2big_poweroftwo(s, 16, true))
- end
-
- def test_str2big_normal
- s = "1" + "0" * 1000
- n = 10 ** 1000
- assert_equal(n, Bug::Bignum.str2big_normal(s, 10, true))
- end
+ def test_str2big_poweroftwo
+ s = "1" + "0" * 1000
+ n = 16 ** 1000
+ assert_equal(n, Bug::Bignum.str2big_poweroftwo(s, 16, true))
+ end
- def test_str2big_karatsuba
- s = "1" + "0" * 1000
- n = 10 ** 1000
- assert_equal(n, Bug::Bignum.str2big_karatsuba(s, 10, true))
- end
+ def test_str2big_normal
+ s = "1" + "0" * 1000
+ n = 10 ** 1000
+ assert_equal(n, Bug::Bignum.str2big_normal(s, 10, true))
+ end
- def test_str2big_gmp
- s = "1" + "0" * 1000
- n = 10 ** 1000
- assert_equal(n, Bug::Bignum.str2big_gmp(s, 10, true))
- rescue NotImplementedError
- end
+ def test_str2big_karatsuba
+ s = "1" + "0" * 1000
+ n = 10 ** 1000
+ assert_equal(n, Bug::Bignum.str2big_karatsuba(s, 10, true))
+ end
+ def test_str2big_gmp
+ s = "1" + "0" * 1000
+ n = 10 ** 1000
+ assert_equal(n, Bug::Bignum.str2big_gmp(s, 10, true))
+ rescue NotImplementedError
end
+
end
diff --git a/test/-ext-/bug_reporter/test_bug_reporter.rb b/test/-ext-/bug_reporter/test_bug_reporter.rb
index ac6d92bb67..c7b2a5b370 100644
--- a/test/-ext-/bug_reporter/test_bug_reporter.rb
+++ b/test/-ext-/bug_reporter/test_bug_reporter.rb
@@ -1,13 +1,17 @@
# frozen_string_literal: false
require 'test/unit'
require 'tmpdir'
+require_relative '../../lib/jit_support'
+require_relative '../../lib/parser_support'
class TestBugReporter < Test::Unit::TestCase
def test_bug_reporter_add
- skip if ENV['RUBY_ON_BUG']
+ pend "macOS 15 beta is not working with this test" if macos?(15)
+ omit "flaky with RJIT" if JITSupport.rjit_enabled?
description = RUBY_DESCRIPTION
- description = description.sub(/\+JIT /, '') if defined?(RubyVM::JIT) && RubyVM::JIT.enabled?
+ description = description.sub(/\+PRISM /, '') unless ParserSupport.prism_enabled_in_subprocess?
+ description = description.sub(/\+RJIT /, '') unless JITSupport.rjit_force_enabled?
expected_stderr = [
:*,
/\[BUG\]\sSegmentation\sfault.*\n/,
@@ -18,9 +22,11 @@ class TestBugReporter < Test::Unit::TestCase
]
tmpdir = Dir.mktmpdir
- args = ["--disable-gems", "-r-test-/bug_reporter",
- "-C", tmpdir]
- stdin = "register_sample_bug_reporter(12345); Process.kill :SEGV, $$"
+ no_core = "Process.setrlimit(Process::RLIMIT_CORE, 0); " if defined?(Process.setrlimit) && defined?(Process::RLIMIT_CORE)
+ args = ["-r-test-/bug_reporter", "-C", tmpdir]
+ args.push("--yjit") if JITSupport.yjit_enabled? # We want the printed description to match this process's RUBY_DESCRIPTION
+ args.unshift({"RUBY_ON_BUG" => nil})
+ stdin = "#{no_core}register_sample_bug_reporter(12345); Process.kill :SEGV, $$"
assert_in_out_err(args, stdin, [], expected_stderr, encoding: "ASCII-8BIT")
ensure
FileUtils.rm_rf(tmpdir) if tmpdir
diff --git a/test/-ext-/debug/test_debug.rb b/test/-ext-/debug/test_debug.rb
index 8a351d74fa..b244eb41ea 100644
--- a/test/-ext-/debug/test_debug.rb
+++ b/test/-ext-/debug/test_debug.rb
@@ -29,7 +29,7 @@ class TestDebug < Test::Unit::TestCase
# check same location
assert_equal(loc.path, iseq.path, msg)
assert_equal(loc.absolute_path, iseq.absolute_path, msg)
- assert_equal(loc.label, iseq.label, msg)
+ #assert_equal(loc.label, iseq.label, msg)
assert_operator(loc.lineno, :>=, iseq.first_lineno, msg)
end
diff --git a/test/-ext-/debug/test_profile_frames.rb b/test/-ext-/debug/test_profile_frames.rb
index e0152247e7..bd819266df 100644
--- a/test/-ext-/debug/test_profile_frames.rb
+++ b/test/-ext-/debug/test_profile_frames.rb
@@ -14,6 +14,8 @@ class SampleClassForTestProfileFrames
end
class Sample2
+ EVAL_LINE = __LINE__ + 3
+
def baz(block)
instance_eval "def zab(block) block.call end"
[self, zab(block)]
@@ -37,6 +39,20 @@ class SampleClassForTestProfileFrames
end
end
+class SampleClassForTestProfileThreadFrames
+ def initialize(mutex)
+ @mutex = mutex
+ end
+
+ def foo(block)
+ bar(block)
+ end
+
+ def bar(block)
+ block.call
+ end
+end
+
class TestProfileFrames < Test::Unit::TestCase
def test_profile_frames
obj, frames = Fiber.new{
@@ -112,7 +128,7 @@ class TestProfileFrames < Test::Unit::TestCase
"SampleClassForTestProfileFrames#foo",
"TestProfileFrames#test_profile_frames",
]
- paths = [ nil, file=__FILE__, "(eval)", file, file, file, file, file, file, nil ]
+ paths = [ nil, file=__FILE__, "(eval at #{__FILE__}:#{SampleClassForTestProfileFrames::Sample2::EVAL_LINE})", file, file, file, file, file, file, nil ]
absolute_paths = [ "<cfunc>", file, nil, file, file, file, file, file, file, nil ]
assert_equal(labels.size, frames.size)
@@ -137,6 +153,73 @@ class TestProfileFrames < Test::Unit::TestCase
}
end
+ def test_profile_thread_frames
+ mutex = Mutex.new
+ th = Thread.new do
+ mutex.lock
+ Thread.stop
+ SampleClassForTestProfileThreadFrames.new(mutex).foo(lambda { mutex.unlock; loop { sleep(1) } } )
+ end
+
+ # ensure execution has reached SampleClassForTestProfileThreadFrames#bar before running profile_thread_frames
+ loop { break if th.status == "sleep"; sleep 0.1 }
+ th.run
+ mutex.lock # wait until SampleClassForTestProfileThreadFrames#bar has been called
+
+ frames = Bug::Debug.profile_thread_frames(th, 0, 10)
+
+ full_labels = [
+ "Kernel#sleep",
+ "TestProfileFrames#test_profile_thread_frames",
+ "Kernel#loop",
+ "TestProfileFrames#test_profile_thread_frames",
+ "SampleClassForTestProfileThreadFrames#bar",
+ "SampleClassForTestProfileThreadFrames#foo",
+ "TestProfileFrames#test_profile_thread_frames",
+ ]
+
+ frames.each.with_index do |frame, i|
+ assert_equal(full_labels[i], frame)
+ end
+
+ ensure
+ th.kill
+ th.join
+ end
+
+
+ def test_matches_backtrace_locations_main_thread
+ assert_equal(Thread.current, Thread.main)
+
+ # Keep these in the same line, so the backtraces match exactly
+ backtrace_locations, profile_frames = [Thread.current.backtrace_locations, Bug::Debug.profile_frames(0, 100)]
+
+ errmsg = "backtrace_locations:\n " + backtrace_locations.map.with_index{|loc, i| "#{i} #{loc}"}.join("\n ")
+ errmsg += "\n\nprofile_frames:\n " + profile_frames.map.with_index{|(path, absolute_path, _, base_label, _, _, _, _, _, full_label, lineno), i|
+ if lineno
+ "#{i} #{absolute_path}:#{lineno} // #{full_label}"
+ else
+ "#{i} #{absolute_path} #{full_label}"
+ end
+ }.join("\n ")
+ assert_equal(backtrace_locations.size, profile_frames.size, errmsg)
+
+ # The first entries are not going to match, since one is #backtrace_locations and the other #profile_frames
+ backtrace_locations.shift
+ profile_frames.shift
+
+ # The rest of the stack is expected to look the same...
+ backtrace_locations.zip(profile_frames).each.with_index do |(location, (path, absolute_path, _, base_label, _, _, _, _, _, _, lineno)), i|
+ next if absolute_path == "<cfunc>" # ...except for cfunc frames
+
+ err_msg = "#{i}th frame"
+ assert_equal(location.absolute_path, absolute_path, err_msg)
+ assert_equal(location.base_label, base_label, err_msg)
+ assert_equal(location.lineno, lineno, err_msg)
+ assert_equal(location.path, path, err_msg)
+ end
+ end
+
def test_ifunc_frame
bug11851 = '[ruby-core:72409] [Bug #11851]'
assert_ruby_status([], <<~'end;', bug11851) # do
@@ -153,4 +236,8 @@ class TestProfileFrames < Test::Unit::TestCase
a
end;
end
+
+ def test_start
+ assert_equal Bug::Debug.profile_frames(0, 10).tap(&:shift), Bug::Debug.profile_frames(1, 9)
+ end
end
diff --git a/test/-ext-/econv/test_append.rb b/test/-ext-/econv/test_append.rb
new file mode 100644
index 0000000000..f8c1d2add6
--- /dev/null
+++ b/test/-ext-/econv/test_append.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: false
+require 'test/unit'
+require "-test-/econv"
+
+class Test_EConvAppend < Test::Unit::TestCase
+ def test_econv_str_append_valid
+ ec = Bug::EConv.new("utf-8", "cp932")
+ dst = "\u3044".encode("cp932")
+ ret = ec.append("\u3042"*30, dst)
+ assert_same(dst, ret)
+ assert_not_predicate(dst, :ascii_only?)
+ assert_predicate(dst, :valid_encoding?)
+ end
+
+ def test_econv_str_append_broken
+ ec = Bug::EConv.new("utf-8", "cp932")
+ dst = ""
+ ret = ec.append("\u3042"*30, dst)
+ assert_same(dst, ret)
+ assert_not_predicate(dst, :ascii_only?)
+ assert_not_predicate(dst, :valid_encoding?)
+ end
+end
diff --git a/test/-ext-/eval/test_eval.rb b/test/-ext-/eval/test_eval.rb
new file mode 100644
index 0000000000..e37d301b2e
--- /dev/null
+++ b/test/-ext-/eval/test_eval.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: false
+require 'test/unit'
+require "-test-/eval"
+
+class EvalTest < Test::Unit::TestCase
+ def test_rb_eval_string
+ _a = 1
+ assert_equal [self, 1, __method__], rb_eval_string(%q{
+ [self, _a, __method__]
+ })
+ end
+end
diff --git a/test/-ext-/float/test_nextafter.rb b/test/-ext-/float/test_nextafter.rb
index e0a76935b1..ea8d7c7fc7 100644
--- a/test/-ext-/float/test_nextafter.rb
+++ b/test/-ext-/float/test_nextafter.rb
@@ -52,7 +52,7 @@ class TestFloatExt < Test::Unit::TestCase
"#{'%a' % v2} = Bug::Float.system_nextafter(#{'%a' % n1}, #{'%a' % n2})")
rescue Test::Unit::AssertionFailedError
if /aix/ =~ RUBY_PLATFORM
- skip "Known bug in nextafter(3) on AIX"
+ omit "Known bug in nextafter(3) on AIX"
end
raise $!
end
diff --git a/test/-ext-/funcall/test_funcall.rb b/test/-ext-/funcall/test_funcall.rb
deleted file mode 100644
index 01a03bf5ef..0000000000
--- a/test/-ext-/funcall/test_funcall.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-# frozen_string_literal: true
-require 'test/unit'
-
-class TestFuncall < Test::Unit::TestCase
- require '-test-/funcall'
-
- def test_funcall_extra_args
- assert_equal 'TestFuncall', TestFuncall.extra_args_name,
- '[ruby-core:85266] [Bug #14425]'
- end
-end
diff --git a/test/-ext-/funcall/test_passing_block.rb b/test/-ext-/funcall/test_passing_block.rb
index 71c9d905be..8964403494 100644
--- a/test/-ext-/funcall/test_passing_block.rb
+++ b/test/-ext-/funcall/test_passing_block.rb
@@ -9,6 +9,11 @@ class TestFuncall < Test::Unit::TestCase
end
require '-test-/funcall'
+ def test_funcall_extra_args
+ assert_equal 'TestFuncall', TestFuncall.extra_args_name,
+ '[ruby-core:85266] [Bug #14425]'
+ end
+
def test_with_funcall2
ok = nil
Relay.with_funcall2("feature#4504") {|arg| ok = arg || true}
diff --git a/test/-ext-/gvl/test_ubf_async_safe.rb b/test/-ext-/gvl/test_ubf_async_safe.rb
index fdaa4d418b..3261b42475 100644
--- a/test/-ext-/gvl/test_ubf_async_safe.rb
+++ b/test/-ext-/gvl/test_ubf_async_safe.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
class TestUbfAsyncSafe < Test::Unit::TestCase
def test_ubf_async_safe
- skip 'need fork for single-threaded test' unless Process.respond_to?(:fork)
+ omit 'need fork for single-threaded test' unless Process.respond_to?(:fork)
IO.pipe do |r, w|
pid = fork do
require '-test-/gvl/call_without_gvl'
diff --git a/test/-ext-/integer/test_my_integer.rb b/test/-ext-/integer/test_my_integer.rb
index 1b6f8489f8..0dfa234921 100644
--- a/test/-ext-/integer/test_my_integer.rb
+++ b/test/-ext-/integer/test_my_integer.rb
@@ -8,19 +8,13 @@ class Test_MyInteger < Test::Unit::TestCase
Bug::Integer::MyInteger.new.to_f
end
- begin
- Bug::Integer::MyInteger.class_eval do
- def to_f
- end
+ int = Class.new(Bug::Integer::MyInteger) do
+ def to_f
end
+ end
- assert_nothing_raised do
- Bug::Integer::MyInteger.new.to_f
- end
- ensure
- Bug::Integer::MyInteger.class_eval do
- remove_method :to_f
- end
+ assert_nothing_raised do
+ int.new.to_f
end
end
@@ -29,20 +23,14 @@ class Test_MyInteger < Test::Unit::TestCase
Bug::Integer::MyInteger.new <=> 0
end
- begin
- Bug::Integer::MyInteger.class_eval do
- def <=>(other)
- 0
- end
+ int = Class.new(Bug::Integer::MyInteger) do
+ def <=>(other)
+ 0
end
+ end
- assert_nothing_raised do
- Bug::Integer::MyInteger.new <=> 0
- end
- ensure
- Bug::Integer::MyInteger.class_eval do
- remove_method :<=>
- end
+ assert_nothing_raised do
+ int.new <=> 0
end
end
end
diff --git a/test/-ext-/iseq_load/test_iseq_load.rb b/test/-ext-/iseq_load/test_iseq_load.rb
index ffa6541c72..864ce1afbb 100644
--- a/test/-ext-/iseq_load/test_iseq_load.rb
+++ b/test/-ext-/iseq_load/test_iseq_load.rb
@@ -98,7 +98,7 @@ class TestIseqLoad < Test::Unit::TestCase
iseq = ISeq.iseq_load(a)
iseq.eval
assert_equal false, @next_broke
- skip "failing due to stack_max mismatch"
+ omit "failing due to stack_max mismatch"
assert_iseq_roundtrip(src)
end
@@ -121,8 +121,10 @@ class TestIseqLoad < Test::Unit::TestCase
iseq = ISeq.iseq_load(a)
iseq.eval
assert_equal false, test_break_ensure_def_method
- skip "failing due to exception entry sp mismatch"
+ omit "failing due to exception entry sp mismatch"
assert_iseq_roundtrip(src)
+ ensure
+ Object.undef_method(:test_break_ensure_def_method) rescue nil
end
def test_kwarg
@@ -137,7 +139,7 @@ class TestIseqLoad < Test::Unit::TestCase
# FIXME: still failing
def test_require_integration
- skip "iseq loader require integration tests still failing"
+ omit "iseq loader require integration tests still failing"
f = File.expand_path(__FILE__)
# $(top_srcdir)/test/ruby/test_....rb
3.times { f = File.dirname(f) }
diff --git a/test/-ext-/load/test_resolve_symbol.rb b/test/-ext-/load/test_resolve_symbol.rb
new file mode 100644
index 0000000000..471d3acebd
--- /dev/null
+++ b/test/-ext-/load/test_resolve_symbol.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+require 'test/unit'
+
+class Test_Load_ResolveSymbol < Test::Unit::TestCase
+ def test_load_resolve_symbol_resolver
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ feature = "Feature #20005"
+ assert_raise(LoadError, "resolve_symbol_target is not loaded") {
+ require '-test-/load/resolve_symbol_resolver'
+ }
+ require '-test-/load/resolve_symbol_target'
+ assert_nothing_raised(LoadError, "#{feature} resolver can be loaded") {
+ require '-test-/load/resolve_symbol_resolver'
+ }
+ assert_not_nil ResolveSymbolResolver
+ assert_equal "from target", ResolveSymbolResolver.any_method
+
+ assert_raise(LoadError, "tries to resolve missing feature name, and it should raise LoadError") {
+ ResolveSymbolResolver.try_resolve_fname
+ }
+ assert_raise(LoadError, "tries to resolve missing symbol name, and it should raise LoadError") {
+ ResolveSymbolResolver.try_resolve_sname
+ }
+ end;
+ end
+end
diff --git a/test/-ext-/load/test_stringify_symbols.rb b/test/-ext-/load/test_stringify_symbols.rb
new file mode 100644
index 0000000000..0d9736b591
--- /dev/null
+++ b/test/-ext-/load/test_stringify_symbols.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+require 'test/unit'
+
+class Test_Load_stringify_symbols < Test::Unit::TestCase
+ def test_load_stringify_symbol_required_extensions
+ require '-test-/load/stringify_symbols'
+ require '-test-/load/stringify_target'
+ r1 = StringifySymbols.stringify_symbol("-test-/load/stringify_target", "stt_any_method")
+ assert_not_nil r1
+ r2 = StringifySymbols.stringify_symbol("-test-/load/stringify_target.so", "stt_any_method")
+ assert_equal r1, r2, "resolved symbols should be equal even with or without .so suffix"
+ end
+
+ def test_load_stringify_symbol_statically_linked
+ require '-test-/load/stringify_symbols'
+ # "complex.so" is actually not a statically linked extension.
+ # But it is registered in $LOADED_FEATURES, so it can be a target of this test.
+ r1 = StringifySymbols.stringify_symbol("complex", "rb_complex_minus")
+ assert_not_nil r1
+ r2 = StringifySymbols.stringify_symbol("complex.so", "rb_complex_minus")
+ assert_equal r1, r2
+ end
+
+ def test_load_stringify_symbol_missing_target
+ require '-test-/load/stringify_symbols'
+ r1 = assert_nothing_raised {
+ StringifySymbols.stringify_symbol("something_missing", "unknown_method")
+ }
+ assert_nil r1
+ r2 = assert_nothing_raised {
+ StringifySymbols.stringify_symbol("complex.so", "unknown_method")
+ }
+ assert_nil r2
+ end
+end
diff --git a/test/-ext-/marshal/test_internal_ivar.rb b/test/-ext-/marshal/test_internal_ivar.rb
index a32138f6e8..faabe14ab2 100644
--- a/test/-ext-/marshal/test_internal_ivar.rb
+++ b/test/-ext-/marshal/test_internal_ivar.rb
@@ -11,7 +11,7 @@ module Bug::Marshal
assert_equal("hello", v.normal)
assert_equal("world", v.internal)
assert_equal("bye", v.encoding_short)
- dump = assert_warn(/instance variable `E' on class \S+ is not dumped/) {
+ dump = assert_warn(/instance variable 'E' on class \S+ is not dumped/) {
::Marshal.dump(v)
}
v = assert_nothing_raised {break ::Marshal.load(dump)}
diff --git a/test/-ext-/postponed_job/test_postponed_job.rb b/test/-ext-/postponed_job/test_postponed_job.rb
index 7dc28776d0..8c2b3e95d1 100644
--- a/test/-ext-/postponed_job/test_postponed_job.rb
+++ b/test/-ext-/postponed_job/test_postponed_job.rb
@@ -2,27 +2,70 @@
require 'test/unit'
require '-test-/postponed_job'
-module Bug
- def self.postponed_job_call_direct_wrapper(*args)
- postponed_job_call_direct(*args)
+class TestPostponed_job < Test::Unit::TestCase
+ def test_preregister_and_trigger
+ assert_separately([], __FILE__, __LINE__, <<-'RUBY')
+ require '-test-/postponed_job'
+ Bug.postponed_job_preregister_and_call_without_sleep(counters = [])
+ # i.e. rb_postponed_job_trigger performs coalescing
+ assert_equal([3], counters)
+
+ # i.e. rb_postponed_job_trigger resets after interrupts are checked
+ Bug.postponed_job_preregister_and_call_with_sleep(counters = [])
+ assert_equal([1, 2, 3], counters)
+ RUBY
end
- def self.postponed_job_register_wrapper(*args)
- postponed_job_register(*args)
+ def test_multiple_preregistration
+ assert_separately([], __FILE__, __LINE__, <<-'RUBY')
+ require '-test-/postponed_job'
+ handles = Bug.postponed_job_preregister_multiple_times
+ # i.e. rb_postponed_job_preregister returns the same handle if preregistered multiple times
+ assert_equal [handles[0]], handles.uniq
+ RUBY
end
-end
-class TestPostponed_job < Test::Unit::TestCase
- def test_register
- direct, registered = [], []
+ def test_multiple_preregistration_with_new_data
+ assert_separately([], __FILE__, __LINE__, <<-'RUBY')
+ require '-test-/postponed_job'
+ values = Bug.postponed_job_preregister_calls_with_last_argument
+ # i.e. the callback is called with the last argument it was preregistered with
+ assert_equal [3, 4], values
+ RUBY
+ end
- Bug.postponed_job_call_direct_wrapper(direct)
- Bug.postponed_job_register_wrapper(registered)
+ def test_legacy_register
+ assert_separately([], __FILE__, __LINE__, <<-'RUBY')
+ require '-test-/postponed_job'
+ direct, registered = [], []
- assert_equal([0], direct)
- assert_equal([3], registered)
+ Bug.postponed_job_call_direct(direct)
+ Bug.postponed_job_register(registered)
+
+ assert_equal([0], direct)
+ assert_equal([3], registered)
+
+ Bug.postponed_job_register_one(ary = [])
+ assert_equal [1], ary
+ RUBY
+ end
+
+ def test_legacy_register_one_same
+ assert_separately([], __FILE__, __LINE__, <<-'RUBY')
+ require '-test-/postponed_job'
+ # Registering the same job three times should result in three of the same handle
+ handles = Bug.postponed_job_register_one_same
+ assert_equal [handles[0]], handles.uniq
+ RUBY
+ end
- Bug.postponed_job_register_one(ary = [])
- assert_equal [1], ary
+ if Bug.respond_to?(:postponed_job_register_in_c_thread)
+ def test_legacy_register_in_c_thread
+ assert_separately([], __FILE__, __LINE__, <<-'RUBY')
+ require '-test-/postponed_job'
+ assert Bug.postponed_job_register_in_c_thread(ary = [])
+ assert_equal [1], ary
+ RUBY
+ end
end
end
diff --git a/test/-ext-/required.rb b/test/-ext-/required.rb
new file mode 100644
index 0000000000..70514355ff
--- /dev/null
+++ b/test/-ext-/required.rb
@@ -0,0 +1,10 @@
+require 'continuation'
+cont = nil
+a = [*1..10].reject do |i|
+ callcc {|c| cont = c} if !cont and i == 10
+ false
+end
+if a.size < 1000
+ a.unshift(:x)
+ cont.call
+end
diff --git a/test/-ext-/string/test_capacity.rb b/test/-ext-/string/test_capacity.rb
index df59e76778..bcca64d85a 100644
--- a/test/-ext-/string/test_capacity.rb
+++ b/test/-ext-/string/test_capacity.rb
@@ -4,27 +4,26 @@ require '-test-/string'
require 'rbconfig/sizeof'
class Test_StringCapacity < Test::Unit::TestCase
- def capa(str)
- Bug::String.capacity(str)
- end
-
def test_capacity_embedded
- size = RbConfig::SIZEOF['void*'] * 3 - 1
- assert_equal size, capa('foo')
+ assert_equal GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE] - embed_header_size - 1, capa('foo')
+ assert_equal max_embed_len, capa('1' * max_embed_len)
+ assert_equal max_embed_len, capa('1' * (max_embed_len - 1))
end
def test_capacity_shared
- assert_equal 0, capa(:abcdefghijklmnopqrstuvwxyz.to_s)
+ sym = ("a" * GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE]).to_sym
+ assert_equal 0, capa(sym.to_s)
end
def test_capacity_normal
- assert_equal 128, capa('1'*128)
+ assert_equal max_embed_len + 1, capa('1' * (max_embed_len + 1))
+ assert_equal max_embed_len + 100, capa('1' * (max_embed_len + 100))
end
def test_s_new_capacity
assert_equal("", String.new(capacity: 1000))
assert_equal(String, String.new(capacity: 1000).class)
- assert_equal(10000, capa(String.new(capacity: 10000)))
+ assert_equal(10_000, capa(String.new(capacity: 10_000)))
assert_equal("", String.new(capacity: -1000))
assert_equal(capa(String.new(capacity: -10000)), capa(String.new(capacity: -1000)))
@@ -39,21 +38,38 @@ class Test_StringCapacity < Test::Unit::TestCase
end
def test_literal_capacity
- s = "I am testing string literal capacity"
+ s = eval(%{
+ # frozen_string_literal: true
+ "#{"a" * (max_embed_len + 1)}"
+ })
assert_equal(s.length, capa(s))
end
def test_capacity_frozen
s = String.new("I am testing", capacity: 1000)
- s << "fstring capacity"
+ s << "a" * GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE]
s.freeze
assert_equal(s.length, capa(s))
end
def test_capacity_fstring
- s = String.new("I am testing", capacity: 1000)
+ s = String.new("a" * max_embed_len, capacity: max_embed_len * 3)
s << "fstring capacity"
s = -s
assert_equal(s.length, capa(s))
end
+
+ private
+
+ def capa(str)
+ Bug::String.capacity(str)
+ end
+
+ def embed_header_size
+ 3 * RbConfig::SIZEOF['void*']
+ end
+
+ def max_embed_len
+ GC::INTERNAL_CONSTANTS[:RVARGC_MAX_ALLOCATE_SIZE] - embed_header_size - 1
+ end
end
diff --git a/test/-ext-/string/test_cstr.rb b/test/-ext-/string/test_cstr.rb
index d909781700..efc64119dc 100644
--- a/test/-ext-/string/test_cstr.rb
+++ b/test/-ext-/string/test_cstr.rb
@@ -43,7 +43,11 @@ class Test_StringCStr < Test::Unit::TestCase
end
def test_rb_str_new_frozen_embed
- str = Bug::String.cstr_noembed("rbconfig.rb")
+ # "rbconfi" is the smallest "maximum embeddable string". VWA adds
+ # a capacity field, which removes one pointer capacity for embedded objects,
+ # so if VWA is enabled, but there is only one size pool, then the
+ # maximum embeddable capacity on 32 bit machines is 8 bytes.
+ str = Bug::String.cstr_noembed("rbconfi")
str = Bug::String.rb_str_new_frozen(str)
assert_equal true, Bug::String.cstr_embedded?(str)
end
diff --git a/test/-ext-/string/test_fstring.rb b/test/-ext-/string/test_fstring.rb
index 9b4956ecef..fcec6be543 100644
--- a/test/-ext-/string/test_fstring.rb
+++ b/test/-ext-/string/test_fstring.rb
@@ -15,19 +15,27 @@ class Test_String_Fstring < Test::Unit::TestCase
def test_rb_enc_interned_str_autoloaded_encoding
assert_separately([], <<~RUBY)
require '-test-/string'
- assert_include(Encoding::Windows_31J.inspect, 'autoload')
- Bug::String.rb_enc_interned_str(Encoding::Windows_31J)
+ assert_include(Encoding::CESU_8.inspect, 'autoload')
+ Bug::String.rb_enc_interned_str(Encoding::CESU_8)
RUBY
end
+ def test_rb_enc_interned_str_null_encoding
+ assert_equal Encoding::ASCII_8BIT, Bug::String.rb_enc_interned_str(nil).encoding
+ end
+
def test_rb_enc_str_new_autoloaded_encoding
assert_separately([], <<~RUBY)
require '-test-/string'
- assert_include(Encoding::Windows_31J.inspect, 'autoload')
- Bug::String.rb_enc_str_new(Encoding::Windows_31J)
+ assert_include(Encoding::CESU_8.inspect, 'autoload')
+ Bug::String.rb_enc_str_new(Encoding::CESU_8)
RUBY
end
+ def test_rb_enc_str_new_null_encoding
+ assert_equal Encoding::ASCII_8BIT, Bug::String.rb_enc_str_new(nil).encoding
+ end
+
def test_instance_variable
str = __method__.to_s * 3
str.instance_variable_set(:@test, 42)
@@ -49,6 +57,10 @@ class Test_String_Fstring < Test::Unit::TestCase
assert_raise(TypeError) {fstr.singleton_class}
end
+ def test_fake_str
+ assert_equal([*"a".."z"].join(""), Bug::String.fstring_fake_str)
+ end
+
class S < String
end
@@ -57,18 +69,4 @@ class Test_String_Fstring < Test::Unit::TestCase
str.freeze
assert_fstring(str) {|s| assert_instance_of(S, s)}
end
-
- def test_shared_string_safety
- _unused = -('a' * 30).force_encoding(Encoding::ASCII)
- begin
- verbose_back, $VERBOSE = $VERBOSE, nil
- str = ('a' * 30).force_encoding(Encoding::ASCII).taint
- ensure
- $VERBOSE = verbose_back
- end
- frozen_str = Bug::String.rb_str_new_frozen(str)
- assert_fstring(frozen_str) {|s| assert_equal(str, s)}
- GC.start
- assert_equal('a' * 30, str, "[Bug #16151]")
- end
end
diff --git a/test/-ext-/string/test_rb_str_dup.rb b/test/-ext-/string/test_rb_str_dup.rb
index 49b6af9598..c76a90252f 100644
--- a/test/-ext-/string/test_rb_str_dup.rb
+++ b/test/-ext-/string/test_rb_str_dup.rb
@@ -3,13 +3,15 @@ require '-test-/string'
class Test_RbStrDup < Test::Unit::TestCase
def test_nested_shared_non_frozen
- str = Bug::String.rb_str_dup(Bug::String.rb_str_dup("a" * 50))
+ orig_str = "a" * GC::INTERNAL_CONSTANTS[:RVARGC_MAX_ALLOCATE_SIZE]
+ str = Bug::String.rb_str_dup(Bug::String.rb_str_dup(orig_str))
assert_send([Bug::String, :shared_string?, str])
assert_not_send([Bug::String, :sharing_with_shared?, str], '[Bug #15792]')
end
def test_nested_shared_frozen
- str = Bug::String.rb_str_dup(Bug::String.rb_str_dup("a" * 50).freeze)
+ orig_str = "a" * GC::INTERNAL_CONSTANTS[:RVARGC_MAX_ALLOCATE_SIZE]
+ str = Bug::String.rb_str_dup(Bug::String.rb_str_dup(orig_str).freeze)
assert_send([Bug::String, :shared_string?, str])
assert_not_send([Bug::String, :sharing_with_shared?, str], '[Bug #15792]')
end
diff --git a/test/-ext-/string/test_set_len.rb b/test/-ext-/string/test_set_len.rb
index 58f51012fb..1531d76167 100644
--- a/test/-ext-/string/test_set_len.rb
+++ b/test/-ext-/string/test_set_len.rb
@@ -4,23 +4,25 @@ require "-test-/string"
class Test_StrSetLen < Test::Unit::TestCase
def setup
- @s0 = [*"a".."z"].join("").freeze
+ # Make string long enough so that it is not embedded
+ @range_end = ("0".ord + GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE]).chr
+ @s0 = [*"0"..@range_end].join("").freeze
@s1 = Bug::String.new(@s0)
end
def teardown
- orig = [*"a".."z"].join("")
+ orig = [*"0"..@range_end].join("")
assert_equal(orig, @s0)
end
def test_non_shared
@s1.modify!
- assert_equal("abc", @s1.set_len(3))
+ assert_equal("012", @s1.set_len(3))
end
def test_shared
assert_raise(RuntimeError) {
- assert_equal("abc", @s1.set_len(3))
+ @s1.set_len(3)
}
end
@@ -32,4 +34,51 @@ class Test_StrSetLen < Test::Unit::TestCase
assert_equal 128, Bug::String.capacity(str)
assert_equal 127, str.set_len(127).bytesize, bug12757
end
+
+ def test_coderange_after_append
+ u = -"\u3042"
+ str = Bug::String.new(encoding: Encoding::UTF_8)
+ bsize = u.bytesize
+ str.append(u)
+ assert_equal 0, str.bytesize
+ str.set_len(bsize)
+ assert_equal bsize, str.bytesize
+ assert_predicate str, :valid_encoding?
+ assert_not_predicate str, :ascii_only?
+ assert_equal u, str
+ end
+
+ def test_coderange_after_trunc
+ u = -"\u3042"
+ bsize = u.bytesize
+ str = Bug::String.new(u)
+ str.set_len(bsize - 1)
+ assert_equal bsize - 1, str.bytesize
+ assert_not_predicate str, :valid_encoding?
+ assert_not_predicate str, :ascii_only?
+ str.append(u.byteslice(-1))
+ str.set_len(bsize)
+ assert_equal bsize, str.bytesize
+ assert_predicate str, :valid_encoding?
+ assert_not_predicate str, :ascii_only?
+ assert_equal u, str
+ end
+
+ def test_valid_encoding_after_resized
+ s = "\0\0".force_encoding(Encoding::UTF_16BE)
+ str = Bug::String.new(s)
+ assert_predicate str, :valid_encoding?
+ str.resize(1)
+ assert_not_predicate str, :valid_encoding?
+ str.resize(2)
+ assert_predicate str, :valid_encoding?
+ str.resize(3)
+ assert_not_predicate str, :valid_encoding?
+
+ s = "\xDB\x00\xDC\x00".force_encoding(Encoding::UTF_16BE)
+ str = Bug::String.new(s)
+ assert_predicate str, :valid_encoding?
+ str.resize(2)
+ assert_not_predicate str, :valid_encoding?
+ end
end
diff --git a/test/-ext-/string/test_too_many_dummy_encodings.rb b/test/-ext-/string/test_too_many_dummy_encodings.rb
new file mode 100644
index 0000000000..b96b40db7b
--- /dev/null
+++ b/test/-ext-/string/test_too_many_dummy_encodings.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: false
+require 'test/unit'
+require "-test-/string"
+
+class Test_TooManyDummyEncodings < Test::Unit::TestCase
+ def test_exceed_encoding_table_size
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ require "-test-/string"
+ assert_raise_with_message(EncodingError, /too many encoding/) do
+ 1_000.times{|i| Bug::String.rb_define_dummy_encoding("R_#{i}") } # now 256 entries
+ end
+ end;
+ end
+end
diff --git a/test/-ext-/struct/test_data.rb b/test/-ext-/struct/test_data.rb
new file mode 100644
index 0000000000..8dbc9113a5
--- /dev/null
+++ b/test/-ext-/struct/test_data.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: false
+require 'test/unit'
+require "-test-/struct"
+
+class Bug::Struct::Test_Data < Test::Unit::TestCase
+ def test_data_new_default
+ klass = Bug::Struct.data_new(false)
+ assert_equal Data, klass.superclass
+ assert_equal %i[mem1 mem2], klass.members
+ end
+
+ def test_data_new_superclass
+ superclass = Data.define
+ klass = Bug::Struct.data_new(superclass)
+ assert_equal superclass, klass.superclass
+ assert_equal %i[mem1 mem2], klass.members
+ end
+end
diff --git a/test/-ext-/symbol/test_type.rb b/test/-ext-/symbol/test_type.rb
index 7cb3c7b6ef..2b0fbe5b79 100644
--- a/test/-ext-/symbol/test_type.rb
+++ b/test/-ext-/symbol/test_type.rb
@@ -93,16 +93,16 @@ module Test_Symbol
assert_symtype("@foo=", :attrset?)
assert_symtype("@@foo=", :attrset?)
assert_symtype("$foo=", :attrset?)
- assert_symtype("0=", :attrset?)
- assert_symtype("@=", :attrset?)
- assert_symtype("@@=", :attrset?)
+ assert_not_symtype("0=", :attrset?)
+ assert_not_symtype("@=", :attrset?)
+ assert_not_symtype("@@=", :attrset?)
assert_not_symtype("foo", :attrset?)
assert_not_symtype("Foo", :attrset?)
assert_not_symtype("@foo", :attrset?)
assert_not_symtype("@@foo", :attrset?)
assert_not_symtype("$foo", :attrset?)
assert_not_symtype("[foo]", :attrset?)
- assert_symtype("[foo]=", :attrset?)
+ assert_not_symtype("[foo]=", :attrset?)
assert_equal(:"foo=", Bug::Symbol.attrset("foo"))
assert_symtype(Bug::Symbol.attrset("foo"), :attrset?)
assert_equal(:"Foo=", Bug::Symbol.attrset("Foo"))
@@ -114,7 +114,6 @@ module Test_Symbol
assert_equal(:"$foo=", Bug::Symbol.attrset("$foo"))
assert_symtype(Bug::Symbol.attrset("$foo"), :attrset?)
assert_equal(:"[foo]=", Bug::Symbol.attrset("[foo]"))
- assert_symtype(Bug::Symbol.attrset("[foo]"), :attrset?)
assert_equal(:[]=, Bug::Symbol.attrset(:[]))
assert_symtype(Bug::Symbol.attrset("foo?="), :attrset?)
assert_equal(:"foo?=", Bug::Symbol.attrset(:foo?))
@@ -135,5 +134,10 @@ module Test_Symbol
Bug::Symbol.find(cx)
}
end
+
+ def test_const_name_type
+ sym = "\xb5".force_encoding(Encoding::Windows_1253)
+ assert_not_operator Bug::Symbol, :const?, sym, sym.encode(Encoding::UTF_8)
+ end
end
end
diff --git a/test/-ext-/test_abi.rb b/test/-ext-/test_abi.rb
new file mode 100644
index 0000000000..d3ea6bb9b1
--- /dev/null
+++ b/test/-ext-/test_abi.rb
@@ -0,0 +1,47 @@
+# frozen_string_literal: true
+
+return unless RUBY_PATCHLEVEL < 0
+
+class TestABI < Test::Unit::TestCase
+ def test_require_lib_with_incorrect_abi_on_dev_ruby
+ omit "ABI is not checked" unless abi_checking_supported?
+
+ assert_separately [], <<~RUBY
+ err = assert_raise(LoadError) { require "-test-/abi" }
+ assert_match(/incompatible ABI version/, err.message)
+ assert_include err.message, "/-test-/abi."
+ RUBY
+ end
+
+ def test_disable_abi_check_using_environment_variable
+ omit "ABI is not checked" unless abi_checking_supported?
+
+ assert_separately [{ "RUBY_ABI_CHECK" => "0" }], <<~RUBY
+ assert_nothing_raised { require "-test-/abi" }
+ RUBY
+ end
+
+ def test_enable_abi_check_using_environment_variable
+ omit "ABI is not checked" unless abi_checking_supported?
+
+ assert_separately [{ "RUBY_ABI_CHECK" => "1" }], <<~RUBY
+ err = assert_raise(LoadError) { require "-test-/abi" }
+ assert_match(/incompatible ABI version/, err.message)
+ assert_include err.message, "/-test-/abi."
+ RUBY
+ end
+
+ def test_require_lib_with_incorrect_abi_on_release_ruby
+ omit "ABI is enforced" if abi_checking_supported?
+
+ assert_separately [], <<~RUBY
+ assert_nothing_raised { require "-test-/abi" }
+ RUBY
+ end
+
+ private
+
+ def abi_checking_supported?
+ !(RUBY_PLATFORM =~ /mswin|mingw/)
+ end
+end
diff --git a/test/-ext-/test_bug-3571.rb b/test/-ext-/test_bug-3571.rb
index c75d2e8523..5952ce2a33 100644
--- a/test/-ext-/test_bug-3571.rb
+++ b/test/-ext-/test_bug-3571.rb
@@ -13,8 +13,8 @@ end
SRC
out = [
"start() function is unimplemented on this machine",
- "-:2:in `start'",
- "-:2:in `<main>'",
+ "-:2:in 'Bug.start'",
+ "-:2:in '<main>'",
]
assert_in_out_err(%w"-r-test-/bug_3571", src, [], out, bug3571)
end
diff --git a/test/-ext-/test_ensure_and_callcc.rb b/test/-ext-/test_ensure_and_callcc.rb
new file mode 100644
index 0000000000..9303a094ea
--- /dev/null
+++ b/test/-ext-/test_ensure_and_callcc.rb
@@ -0,0 +1,40 @@
+# -*- coding: us-ascii -*-
+# frozen_string_literal: false
+require 'test/unit'
+
+class TestEnsureAndCallcc < Test::Unit::TestCase
+ def test_bug20655_dir_chdir_using_rb_ensure
+ require 'tmpdir'
+ need_continuation
+ called = 0
+ tmp = nil
+ Dir.mktmpdir do |tmpdir|
+ Dir.chdir(tmpdir) do
+ tmp = Dir.pwd
+ cont = nil
+ callcc{|c| cont = c}
+ assert_equal(tmp, Dir.pwd, "BUG #20655: ensure called and pwd was changed unexpectedly")
+ called += 1
+ cont.call if called < 10
+ end
+ end
+ end
+
+ def test_bug20655_extension_using_rb_ensure
+ need_continuation
+ require '-test-/ensure_and_callcc'
+ EnsureAndCallcc.reset
+ assert_equal(0, EnsureAndCallcc.ensure_called)
+ EnsureAndCallcc.require_with_ensure(File.join(__dir__, 'required'))
+ assert_equal(1, EnsureAndCallcc.ensure_called,
+ "BUG #20655: ensure called unexpectedly in the required script even without exceptions")
+ end
+
+ private
+ def need_continuation
+ unless respond_to?(:callcc, true)
+ EnvUtil.suppress_warning {require 'continuation'}
+ end
+ omit 'requires callcc support' unless respond_to?(:callcc, true)
+ end
+end
diff --git a/test/-ext-/test_random.rb b/test/-ext-/test_random.rb
index 838e5d2f14..e5cebcc871 100644
--- a/test/-ext-/test_random.rb
+++ b/test/-ext-/test_random.rb
@@ -1,11 +1,13 @@
require 'test/unit'
module TestRandomExt
+ def setup
+ super
+ assert_nothing_raised(LoadError) {require '-test-/random'}
+ end
+
class TestLoop < Test::Unit::TestCase
- def setup
- super
- assert_nothing_raised(LoadError) {require '-test-/random'}
- end
+ include TestRandomExt
def test_bytes
rnd = Bug::Random::Loop.new(1)
@@ -24,4 +26,20 @@ module TestRandomExt
assert_equal(1.00, Bug::Random::Loop.new(4<<14).rand)
end
end
+
+ class TestVersionZero < Test::Unit::TestCase
+ include TestRandomExt
+
+ def test_bad_version
+ assert_raise(TypeError) {Bug::Random::VersionZero.new}
+ end
+ end
+
+ class TestVersionMax < Test::Unit::TestCase
+ include TestRandomExt
+
+ def test_bad_version
+ assert_raise(TypeError) {Bug::Random::VersionMax.new}
+ end
+ end
end
diff --git a/test/-ext-/thread/helper.rb b/test/-ext-/thread/helper.rb
new file mode 100644
index 0000000000..3ea2057d15
--- /dev/null
+++ b/test/-ext-/thread/helper.rb
@@ -0,0 +1,51 @@
+module ThreadInstrumentation
+ module TestHelper
+ private
+
+ def record
+ Bug::ThreadInstrumentation.register_callback(!ENV["GVL_DEBUG"])
+ yield
+ ensure
+ timeline = Bug::ThreadInstrumentation.unregister_callback
+ if $!
+ raise
+ else
+ return timeline
+ end
+ end
+
+ def timeline_for(thread, timeline)
+ timeline.select { |t, _| t == thread }.map(&:last)
+ end
+
+ def assert_consistent_timeline(events)
+ refute_predicate events, :empty?
+
+ previous_event = nil
+ events.each do |event|
+ refute_equal :exited, previous_event, "`exited` must be the final event: #{events.inspect}"
+ case event
+ when :started
+ assert_nil previous_event, "`started` must be the first event: #{events.inspect}"
+ when :ready
+ unless previous_event.nil?
+ assert %i(started suspended).include?(previous_event), "`ready` must be preceded by `started` or `suspended`: #{events.inspect}"
+ end
+ when :resumed
+ unless previous_event.nil?
+ assert_equal :ready, previous_event, "`resumed` must be preceded by `ready`: #{events.inspect}"
+ end
+ when :suspended
+ unless previous_event.nil?
+ assert_equal :resumed, previous_event, "`suspended` must be preceded by `resumed`: #{events.inspect}"
+ end
+ when :exited
+ unless previous_event.nil?
+ assert %i(resumed suspended).include?(previous_event), "`exited` must be preceded by `resumed` or `suspended`: #{events.inspect}"
+ end
+ end
+ previous_event = event
+ end
+ end
+ end
+end
diff --git a/test/-ext-/thread/test_instrumentation_api.rb b/test/-ext-/thread/test_instrumentation_api.rb
new file mode 100644
index 0000000000..663e41be53
--- /dev/null
+++ b/test/-ext-/thread/test_instrumentation_api.rb
@@ -0,0 +1,289 @@
+# frozen_string_literal: false
+require 'envutil'
+require_relative "helper"
+
+class TestThreadInstrumentation < Test::Unit::TestCase
+ include ThreadInstrumentation::TestHelper
+
+ def setup
+ pend("No windows support") if /mswin|mingw|bccwin/ =~ RUBY_PLATFORM
+
+ require '-test-/thread/instrumentation'
+
+ cleanup_threads
+ end
+
+ def teardown
+ return if /mswin|mingw|bccwin/ =~ RUBY_PLATFORM
+ Bug::ThreadInstrumentation.unregister_callback
+ cleanup_threads
+ end
+
+ THREADS_COUNT = 3
+
+ def test_single_thread_timeline
+ thread = nil
+ full_timeline = record do
+ thread = Thread.new { 1 + 1 }
+ thread.join
+ end
+ assert_equal %i(started ready resumed suspended exited), timeline_for(thread, full_timeline)
+ ensure
+ thread&.kill
+ end
+
+ def test_thread_pass_single_thread
+ full_timeline = record do
+ Thread.pass
+ end
+ assert_equal [], timeline_for(Thread.current, full_timeline)
+ end
+
+ def test_thread_pass_multi_thread
+ thread = Thread.new do
+ cpu_bound_work(0.5)
+ end
+
+ full_timeline = record do
+ Thread.pass
+ end
+
+ assert_equal %i(suspended ready resumed), timeline_for(Thread.current, full_timeline)
+ ensure
+ thread&.kill
+ thread&.join
+ end
+
+ def test_multi_thread_timeline
+ threads = nil
+ full_timeline = record do
+ threads = threaded_cpu_bound_work(1.0)
+ results = threads.map(&:value)
+ results.each do |r|
+ refute_equal false, r
+ end
+ assert_equal [false] * THREADS_COUNT, threads.map(&:status)
+ end
+
+ threads.each do |thread|
+ timeline = timeline_for(thread, full_timeline)
+ assert_consistent_timeline(timeline)
+ assert_operator timeline.count(:suspended), :>=, 1, "Expected threads to yield suspended at least once: #{timeline.inspect}"
+ end
+
+ timeline = timeline_for(Thread.current, full_timeline)
+ assert_consistent_timeline(timeline)
+ ensure
+ threads&.each(&:kill)
+ end
+
+ def test_join_suspends # Bug #18900
+ thread = other_thread = nil
+ full_timeline = record do
+ other_thread = Thread.new { sleep 0.3 }
+ thread = Thread.new { other_thread.join }
+ thread.join
+ end
+
+ timeline = timeline_for(thread, full_timeline)
+ assert_consistent_timeline(timeline)
+ assert_equal %i(started ready resumed suspended ready resumed suspended exited), timeline
+ ensure
+ other_thread&.kill
+ thread&.kill
+ end
+
+ def test_io_release_gvl
+ r, w = IO.pipe
+ thread = nil
+ full_timeline = record do
+ thread = Thread.new do
+ w.write("Hello\n")
+ end
+ thread.join
+ end
+
+ timeline = timeline_for(thread, full_timeline)
+ assert_consistent_timeline(timeline)
+ assert_equal %i(started ready resumed suspended ready resumed suspended exited), timeline
+ ensure
+ r&.close
+ w&.close
+ end
+
+ def test_queue_releases_gvl
+ queue1 = Queue.new
+ queue2 = Queue.new
+
+ thread = nil
+
+ full_timeline = record do
+ thread = Thread.new do
+ queue1 << true
+ queue2.pop
+ end
+
+ queue1.pop
+ queue2 << true
+ thread.join
+ end
+
+ timeline = timeline_for(thread, full_timeline)
+ assert_consistent_timeline(timeline)
+ assert_equal %i(started ready resumed suspended ready resumed suspended exited), timeline
+ end
+
+ def test_blocking_on_ractor
+ assert_ractor(<<-"RUBY", require_relative: "helper", require: "-test-/thread/instrumentation")
+ include ThreadInstrumentation::TestHelper
+
+ ractor = Ractor.new {
+ Ractor.receive # wait until woke
+ Thread.current
+ }
+
+ # Wait for the main thread to block, then wake the ractor
+ Thread.new do
+ while Thread.main.status != "sleep"
+ Thread.pass
+ end
+ ractor.send true
+ end
+
+ full_timeline = record do
+ ractor.take
+ end
+
+ timeline = timeline_for(Thread.current, full_timeline)
+ assert_consistent_timeline(timeline)
+ assert_equal %i(suspended ready resumed), timeline
+ RUBY
+ end
+
+ def test_sleeping_inside_ractor
+ assert_ractor(<<-"RUBY", require_relative: "helper", require: "-test-/thread/instrumentation")
+ include ThreadInstrumentation::TestHelper
+
+ thread = nil
+
+ full_timeline = record do
+ thread = Ractor.new{
+ sleep 0.1
+ Thread.current
+ }.take
+ sleep 0.1
+ end
+
+ timeline = timeline_for(thread, full_timeline)
+ assert_consistent_timeline(timeline)
+ assert_equal %i(started ready resumed suspended ready resumed suspended exited), timeline
+ RUBY
+ end
+
+ def test_thread_blocked_forever_on_mutex
+ mutex = Mutex.new
+ mutex.lock
+ thread = nil
+
+ full_timeline = record do
+ thread = Thread.new do
+ mutex.lock
+ end
+ 10.times { Thread.pass }
+ sleep 0.1
+ end
+
+ mutex.unlock
+ thread.join
+
+ timeline = timeline_for(thread, full_timeline)
+ assert_consistent_timeline(timeline)
+ assert_equal %i(started ready resumed suspended), timeline
+ end
+
+ def test_thread_blocked_temporarily_on_mutex
+ mutex = Mutex.new
+ mutex.lock
+ thread = nil
+
+ full_timeline = record do
+ thread = Thread.new do
+ mutex.lock
+ end
+ 10.times { Thread.pass }
+ sleep 0.1
+ mutex.unlock
+ 10.times { Thread.pass }
+ sleep 0.1
+ end
+
+ thread.join
+
+ timeline = timeline_for(thread, full_timeline)
+ assert_consistent_timeline(timeline)
+ assert_equal %i(started ready resumed suspended ready resumed suspended exited), timeline
+ end
+
+ def test_thread_instrumentation_fork_safe
+ skip "No fork()" unless Process.respond_to?(:fork)
+
+ thread_statuses = full_timeline = nil
+ IO.popen("-") do |read_pipe|
+ if read_pipe
+ thread_statuses = Marshal.load(read_pipe)
+ full_timeline = Marshal.load(read_pipe)
+ else
+ threads = threaded_cpu_bound_work.each(&:join)
+ Marshal.dump(threads.map(&:status), STDOUT)
+ full_timeline = Bug::ThreadInstrumentation.unregister_callback.map { |t, e| [t.to_s, e ] }
+ Marshal.dump(full_timeline, STDOUT)
+ end
+ end
+ assert_predicate $?, :success?
+
+ assert_equal [false] * THREADS_COUNT, thread_statuses
+ thread_names = full_timeline.map(&:first).uniq
+ thread_names.each do |thread_name|
+ assert_consistent_timeline(timeline_for(thread_name, full_timeline))
+ end
+ end
+
+ def test_thread_instrumentation_unregister
+ assert Bug::ThreadInstrumentation::register_and_unregister_callbacks
+ end
+
+ private
+
+ def fib(n = 30)
+ return n if n <= 1
+ fib(n-1) + fib(n-2)
+ end
+
+ def cpu_bound_work(duration)
+ deadline = Process.clock_gettime(Process::CLOCK_MONOTONIC) + duration
+ i = 0
+ while deadline > Process.clock_gettime(Process::CLOCK_MONOTONIC)
+ fib(25)
+ i += 1
+ end
+ i > 0 ? i : false
+ end
+
+ def threaded_cpu_bound_work(duration = 0.5)
+ THREADS_COUNT.times.map do
+ Thread.new do
+ cpu_bound_work(duration)
+ end
+ end
+ end
+
+ def cleanup_threads
+ Thread.list.each do |thread|
+ if thread != Thread.current
+ thread.kill
+ thread.join rescue nil
+ end
+ end
+ assert_equal [Thread.current], Thread.list
+ end
+end
diff --git a/test/-ext-/thread/test_lock_native_thread.rb b/test/-ext-/thread/test_lock_native_thread.rb
new file mode 100644
index 0000000000..8a5ba78838
--- /dev/null
+++ b/test/-ext-/thread/test_lock_native_thread.rb
@@ -0,0 +1,50 @@
+# frozen_string_literal: false
+
+require 'envutil'
+
+mn_supported_p = -> do
+ out, *_ = EnvUtil.invoke_ruby([{'RUBY_MN_THREADS' => '1'}, '-v'], '', true)
+ return /\+MN/ =~ out
+end
+
+if mn_supported_p.call
+ # test only on MN threads
+else
+ return
+end
+
+class TestThreadLockNativeThread < Test::Unit::TestCase
+ def test_lock_native_thread
+ assert_separately([{'RUBY_MN_THREADS' => '1'}], <<-RUBY)
+ require '-test-/thread/lock_native_thread'
+
+ Thread.new{
+ assert_equal true, Thread.current.lock_native_thread
+ }.join
+
+ # main thread already has DNT
+ assert_equal false, Thread.current.lock_native_thread
+ RUBY
+ end
+
+ def test_lock_native_thread_tls
+ assert_separately([{'RUBY_MN_THREADS' => '1'}], <<-RUBY)
+ require '-test-/thread/lock_native_thread'
+ tn = 10
+ ln = 1_000
+
+ ts = tn.times.map{|i|
+ Thread.new(i){|i|
+ Thread.current.set_tls i
+ assert_equal true, Thread.current.lock_native_thread
+
+ ln.times{
+ assert_equal i, Thread.current.get_tls
+ Thread.pass
+ }
+ }
+ }
+ ts.each(&:join)
+ RUBY
+ end
+end
diff --git a/test/-ext-/thread_fd/test_thread_fd_close.rb b/test/-ext-/thread_fd/test_thread_fd_close.rb
index a53949b93b..1d2ef63635 100644
--- a/test/-ext-/thread_fd/test_thread_fd_close.rb
+++ b/test/-ext-/thread_fd/test_thread_fd_close.rb
@@ -1,7 +1,6 @@
# frozen_string_literal: true
require 'test/unit'
require '-test-/thread_fd'
-require 'io/wait'
class TestThreadFdClose < Test::Unit::TestCase
diff --git a/test/-ext-/tracepoint/test_tracepoint.rb b/test/-ext-/tracepoint/test_tracepoint.rb
index 9d1679602a..48ffe2605c 100644
--- a/test/-ext-/tracepoint/test_tracepoint.rb
+++ b/test/-ext-/tracepoint/test_tracepoint.rb
@@ -11,6 +11,7 @@ class TestTracepointObj < Test::Unit::TestCase
def test_tracks_objspace_events
result = EnvUtil.suppress_warning {eval(<<-EOS, nil, __FILE__, __LINE__+1)}
+ # frozen_string_literal: false
Bug.tracepoint_track_objspace_events {
99
'abc'
diff --git a/test/-ext-/wait/test_wait.rb b/test/-ext-/wait/test_wait.rb
index 79127c041b..8e53f067cf 100644
--- a/test/-ext-/wait/test_wait.rb
+++ b/test/-ext-/wait/test_wait.rb
@@ -12,14 +12,18 @@ class TestWait < Test::Unit::TestCase
end
def test_wait_for_invalid_fd
- r, w = IO.pipe
- r.close
+ assert_separately [], <<~'RUBY'
+ require '-test-/wait'
- IO.for_fd(w.fileno).close
+ r, w = IO.pipe
+ r.close
- assert_raise(Errno::EBADF) do
- IO.io_wait(w, IO::WRITABLE, nil)
- end
+ IO.for_fd(w.fileno).close
+
+ assert_raise(Errno::EBADF) do
+ IO.io_wait(w, IO::WRITABLE, nil)
+ end
+ RUBY
end
def test_wait_for_closed_pipe
diff --git a/test/.excludes-parsey/TestBugReporter.rb b/test/.excludes-parsey/TestBugReporter.rb
new file mode 100644
index 0000000000..72357760a6
--- /dev/null
+++ b/test/.excludes-parsey/TestBugReporter.rb
@@ -0,0 +1 @@
+exclude(:test_bug_reporter_add, "unexpected +PRISM in the Ruby description")
diff --git a/test/.excludes-parsey/TestM17N.rb b/test/.excludes-parsey/TestM17N.rb
new file mode 100644
index 0000000000..7f8c44d02a
--- /dev/null
+++ b/test/.excludes-parsey/TestM17N.rb
@@ -0,0 +1 @@
+exclude(:test_regexp_usascii, "https://bugs.ruby-lang.org/issues/20504")
diff --git a/test/.excludes-parsey/TestMixedUnicodeEscape.rb b/test/.excludes-parsey/TestMixedUnicodeEscape.rb
new file mode 100644
index 0000000000..7bf964ebf1
--- /dev/null
+++ b/test/.excludes-parsey/TestMixedUnicodeEscape.rb
@@ -0,0 +1 @@
+exclude(:test_basic, "https://bugs.ruby-lang.org/issues/20504")
diff --git a/test/.excludes-parsey/TestRubyLiteral.rb b/test/.excludes-parsey/TestRubyLiteral.rb
new file mode 100644
index 0000000000..853f23a3b9
--- /dev/null
+++ b/test/.excludes-parsey/TestRubyLiteral.rb
@@ -0,0 +1 @@
+exclude(:test_dregexp, "https://bugs.ruby-lang.org/issues/20504")
diff --git a/test/.excludes-parsey/TestRubyOptions.rb b/test/.excludes-parsey/TestRubyOptions.rb
new file mode 100644
index 0000000000..f6ac8c744a
--- /dev/null
+++ b/test/.excludes-parsey/TestRubyOptions.rb
@@ -0,0 +1,10 @@
+exclude(:test_crash_report_executable_path, "unexpected +PRISM in the Ruby description")
+exclude(:test_crash_report_script_path, "unexpected +PRISM in the Ruby description")
+exclude(:test_crash_report_script, "unexpected +PRISM in the Ruby description")
+exclude(:test_crash_report, "unexpected +PRISM in the Ruby description")
+exclude(:test_rjit_disabled_version, "unexpected +PRISM in the Ruby description")
+exclude(:test_segv_loaded_features, "unexpected +PRISM in the Ruby description")
+exclude(:test_segv_setproctitle, "unexpected +PRISM in the Ruby description")
+exclude(:test_segv_test, "unexpected +PRISM in the Ruby description")
+exclude(:test_verbose, "unexpected +PRISM in the Ruby description")
+exclude(:test_version, "unexpected +PRISM in the Ruby description")
diff --git a/test/excludes/TestArray.rb b/test/.excludes/TestArray.rb
index 73da272007..73da272007 100644
--- a/test/excludes/TestArray.rb
+++ b/test/.excludes/TestArray.rb
diff --git a/test/.excludes/TestArraySubclass.rb b/test/.excludes/TestArraySubclass.rb
new file mode 100644
index 0000000000..73da272007
--- /dev/null
+++ b/test/.excludes/TestArraySubclass.rb
@@ -0,0 +1 @@
+exclude(:test_shared_marking, "The target code has already been changed")
diff --git a/test/excludes/TestException.rb b/test/.excludes/TestException.rb
index 38d66d63d2..38d66d63d2 100644
--- a/test/excludes/TestException.rb
+++ b/test/.excludes/TestException.rb
diff --git a/test/.excludes/TestGem.rb b/test/.excludes/TestGem.rb
new file mode 100644
index 0000000000..042af26eff
--- /dev/null
+++ b/test/.excludes/TestGem.rb
@@ -0,0 +1,4 @@
+if RbConfig::CONFIG["LIBRUBY_RELATIVE"] == "yes"
+ exclude(/test_looks_for_gemdeps_files_automatically_from_binstubs/,
+ "can't test before installation")
+end
diff --git a/test/excludes/TestIO_Console.rb b/test/.excludes/TestIO_Console.rb
index caf1935fec..caf1935fec 100644
--- a/test/excludes/TestIO_Console.rb
+++ b/test/.excludes/TestIO_Console.rb
diff --git a/test/excludes/TestISeq.rb b/test/.excludes/TestISeq.rb
index b99181eeaf..b99181eeaf 100644
--- a/test/excludes/TestISeq.rb
+++ b/test/.excludes/TestISeq.rb
diff --git a/test/.excludes/TestThread.rb b/test/.excludes/TestThread.rb
new file mode 100644
index 0000000000..f26ea420a6
--- /dev/null
+++ b/test/.excludes/TestThread.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: false
+exclude(/_stack_size$/, 'often too expensive')
+if /freebsd13/ =~ RUBY_PLATFORM
+ # http://rubyci.s3.amazonaws.com/freebsd13/ruby-master/log/20220216T143001Z.fail.html.gz
+ #
+ # 1) Error:
+ # TestThread#test_signal_at_join:
+ # Timeout::Error: execution of assert_separately expired timeout (120 sec)
+ # pid 30743 killed by SIGABRT (signal 6) (core dumped)
+ # |
+ #
+ # /usr/home/chkbuild/chkbuild/tmp/build/20220216T143001Z/ruby/test/ruby/test_thread.rb:1390:in `test_signal_at_join'
+ exclude(:test_signal_at_join, 'gets stuck somewhere')
+end
+if /mswin/ =~ RUBY_PLATFORM && ENV.key?('GITHUB_ACTIONS')
+ # to avoid "`failed to allocate memory (NoMemoryError)" error
+ exclude(:test_thread_interrupt_for_killed_thread, 'TODO')
+end
diff --git a/test/.excludes/TestThreadQueue.rb b/test/.excludes/TestThreadQueue.rb
new file mode 100644
index 0000000000..c8231e372a
--- /dev/null
+++ b/test/.excludes/TestThreadQueue.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: false
+if /freebsd13/ =~ RUBY_PLATFORM
+ # http://rubyci.s3.amazonaws.com/freebsd13/ruby-master/log/20220308T023001Z.fail.html.gz
+ #
+ # 1) Failure:
+ # TestThreadQueue#test_thr_kill [/usr/home/chkbuild/chkbuild/tmp/build/20220308T023001Z/ruby/test/ruby/test_thread_queue.rb:175]:
+ # only 169/250 done in 60 seconds.
+ exclude(:test_thr_kill, 'gets stuck somewhere')
+end
diff --git a/test/excludes/_appveyor/TestArray.rb b/test/.excludes/_appveyor/TestArray.rb
index 7d03833f07..7d03833f07 100644
--- a/test/excludes/_appveyor/TestArray.rb
+++ b/test/.excludes/_appveyor/TestArray.rb
diff --git a/test/base64/test_base64.rb b/test/base64/test_base64.rb
deleted file mode 100644
index ce716043a8..0000000000
--- a/test/base64/test_base64.rb
+++ /dev/null
@@ -1,115 +0,0 @@
-# coding: US-ASCII
-# frozen_string_literal: true
-require "test/unit"
-require "base64"
-
-class TestBase64 < Test::Unit::TestCase
- def test_sample
- assert_equal("U2VuZCByZWluZm9yY2VtZW50cw==\n", Base64.encode64('Send reinforcements'))
- assert_equal('Send reinforcements', Base64.decode64("U2VuZCByZWluZm9yY2VtZW50cw==\n"))
- assert_equal(
- "Tm93IGlzIHRoZSB0aW1lIGZvciBhbGwgZ29vZCBjb2RlcnMKdG8gbGVhcm4g\nUnVieQ==\n",
- Base64.encode64("Now is the time for all good coders\nto learn Ruby"))
- assert_equal(
- "Now is the time for all good coders\nto learn Ruby",
- Base64.decode64("Tm93IGlzIHRoZSB0aW1lIGZvciBhbGwgZ29vZCBjb2RlcnMKdG8gbGVhcm4g\nUnVieQ==\n"))
- assert_equal(
- "VGhpcyBpcyBsaW5lIG9uZQpUaGlzIGlzIGxpbmUgdHdvClRoaXMgaXMgbGlu\nZSB0aHJlZQpBbmQgc28gb24uLi4K\n",
- Base64.encode64("This is line one\nThis is line two\nThis is line three\nAnd so on...\n"))
- assert_equal(
- "This is line one\nThis is line two\nThis is line three\nAnd so on...\n",
- Base64.decode64("VGhpcyBpcyBsaW5lIG9uZQpUaGlzIGlzIGxpbmUgdHdvClRoaXMgaXMgbGluZSB0aHJlZQpBbmQgc28gb24uLi4K"))
- end
-
- def test_encode64
- assert_equal("", Base64.encode64(""))
- assert_equal("AA==\n", Base64.encode64("\0"))
- assert_equal("AAA=\n", Base64.encode64("\0\0"))
- assert_equal("AAAA\n", Base64.encode64("\0\0\0"))
- assert_equal("/w==\n", Base64.encode64("\377"))
- assert_equal("//8=\n", Base64.encode64("\377\377"))
- assert_equal("////\n", Base64.encode64("\377\377\377"))
- assert_equal("/+8=\n", Base64.encode64("\xff\xef"))
- end
-
- def test_decode64
- assert_equal("", Base64.decode64(""))
- assert_equal("\0", Base64.decode64("AA==\n"))
- assert_equal("\0\0", Base64.decode64("AAA=\n"))
- assert_equal("\0\0\0", Base64.decode64("AAAA\n"))
- assert_equal("\377", Base64.decode64("/w==\n"))
- assert_equal("\377\377", Base64.decode64("//8=\n"))
- assert_equal("\377\377\377", Base64.decode64("////\n"))
- assert_equal("\xff\xef", Base64.decode64("/+8=\n"))
- end
-
- def test_strict_encode64
- assert_equal("", Base64.strict_encode64(""))
- assert_equal("AA==", Base64.strict_encode64("\0"))
- assert_equal("AAA=", Base64.strict_encode64("\0\0"))
- assert_equal("AAAA", Base64.strict_encode64("\0\0\0"))
- assert_equal("/w==", Base64.strict_encode64("\377"))
- assert_equal("//8=", Base64.strict_encode64("\377\377"))
- assert_equal("////", Base64.strict_encode64("\377\377\377"))
- assert_equal("/+8=", Base64.strict_encode64("\xff\xef"))
- end
-
- def test_strict_decode64
- assert_equal("", Base64.strict_decode64(""))
- assert_equal("\0", Base64.strict_decode64("AA=="))
- assert_equal("\0\0", Base64.strict_decode64("AAA="))
- assert_equal("\0\0\0", Base64.strict_decode64("AAAA"))
- assert_equal("\377", Base64.strict_decode64("/w=="))
- assert_equal("\377\377", Base64.strict_decode64("//8="))
- assert_equal("\377\377\377", Base64.strict_decode64("////"))
- assert_equal("\xff\xef", Base64.strict_decode64("/+8="))
-
- assert_raise(ArgumentError) { Base64.strict_decode64("^") }
- assert_raise(ArgumentError) { Base64.strict_decode64("A") }
- assert_raise(ArgumentError) { Base64.strict_decode64("A^") }
- assert_raise(ArgumentError) { Base64.strict_decode64("AA") }
- assert_raise(ArgumentError) { Base64.strict_decode64("AA=") }
- assert_raise(ArgumentError) { Base64.strict_decode64("AA===") }
- assert_raise(ArgumentError) { Base64.strict_decode64("AA=x") }
- assert_raise(ArgumentError) { Base64.strict_decode64("AAA") }
- assert_raise(ArgumentError) { Base64.strict_decode64("AAA^") }
- assert_raise(ArgumentError) { Base64.strict_decode64("AB==") }
- assert_raise(ArgumentError) { Base64.strict_decode64("AAB=") }
- end
-
- def test_urlsafe_encode64
- assert_equal("", Base64.urlsafe_encode64(""))
- assert_equal("AA==", Base64.urlsafe_encode64("\0"))
- assert_equal("AAA=", Base64.urlsafe_encode64("\0\0"))
- assert_equal("AAAA", Base64.urlsafe_encode64("\0\0\0"))
- assert_equal("_w==", Base64.urlsafe_encode64("\377"))
- assert_equal("__8=", Base64.urlsafe_encode64("\377\377"))
- assert_equal("____", Base64.urlsafe_encode64("\377\377\377"))
- assert_equal("_-8=", Base64.urlsafe_encode64("\xff\xef"))
- end
-
- def test_urlsafe_encode64_unpadded
- assert_equal("", Base64.urlsafe_encode64("", padding: false))
- assert_equal("AA", Base64.urlsafe_encode64("\0", padding: false))
- assert_equal("AAA", Base64.urlsafe_encode64("\0\0", padding: false))
- assert_equal("AAAA", Base64.urlsafe_encode64("\0\0\0", padding: false))
- end
-
- def test_urlsafe_decode64
- assert_equal("", Base64.urlsafe_decode64(""))
- assert_equal("\0", Base64.urlsafe_decode64("AA=="))
- assert_equal("\0\0", Base64.urlsafe_decode64("AAA="))
- assert_equal("\0\0\0", Base64.urlsafe_decode64("AAAA"))
- assert_equal("\377", Base64.urlsafe_decode64("_w=="))
- assert_equal("\377\377", Base64.urlsafe_decode64("__8="))
- assert_equal("\377\377\377", Base64.urlsafe_decode64("____"))
- assert_equal("\xff\xef", Base64.urlsafe_decode64("_+8="))
- end
-
- def test_urlsafe_decode64_unpadded
- assert_equal("\0", Base64.urlsafe_decode64("AA"))
- assert_equal("\0\0", Base64.urlsafe_decode64("AAA"))
- assert_equal("\0\0\0", Base64.urlsafe_decode64("AAAA"))
- assert_raise(ArgumentError) { Base64.urlsafe_decode64("AA=") }
- end
-end
diff --git a/test/bigdecimal/helper.rb b/test/bigdecimal/helper.rb
deleted file mode 100644
index 22b05f09ae..0000000000
--- a/test/bigdecimal/helper.rb
+++ /dev/null
@@ -1,28 +0,0 @@
-# frozen_string_literal: false
-require "test/unit"
-require "bigdecimal"
-
-module TestBigDecimalBase
- def setup
- @mode = BigDecimal.mode(BigDecimal::EXCEPTION_ALL)
- BigDecimal.mode(BigDecimal::EXCEPTION_ALL, true)
- BigDecimal.mode(BigDecimal::EXCEPTION_UNDERFLOW, true)
- BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, true)
- BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_HALF_UP)
- BigDecimal.limit(0)
- end
-
- def teardown
- [BigDecimal::EXCEPTION_INFINITY, BigDecimal::EXCEPTION_NaN,
- BigDecimal::EXCEPTION_UNDERFLOW, BigDecimal::EXCEPTION_OVERFLOW].each do |mode|
- BigDecimal.mode(mode, !(@mode & mode).zero?)
- end
- end
-
- def under_gc_stress
- stress, GC.stress = GC.stress, true
- yield
- ensure
- GC.stress = stress
- end
-end
diff --git a/test/bigdecimal/test_bigdecimal.rb b/test/bigdecimal/test_bigdecimal.rb
deleted file mode 100644
index 99f92c461c..0000000000
--- a/test/bigdecimal/test_bigdecimal.rb
+++ /dev/null
@@ -1,2120 +0,0 @@
-# frozen_string_literal: false
-require_relative "helper"
-require 'bigdecimal/math'
-require 'rbconfig/sizeof'
-
-class TestBigDecimal < Test::Unit::TestCase
- include TestBigDecimalBase
-
- if defined? RbConfig::LIMITS
- LIMITS = RbConfig::LIMITS
- else
- require 'fiddle'
- LONG_MAX = (1 << (Fiddle::SIZEOF_LONG*8 - 1)) - 1
- LONG_MIN = [LONG_MAX + 1].pack("L!").unpack("l!")[0]
- LIMITS = {
- "FIXNUM_MIN" => LONG_MIN / 2,
- "FIXNUM_MAX" => LONG_MAX / 2,
- "INT64_MIN" => -9223372036854775808,
- "INT64_MAX" => 9223372036854775807,
- "UINT64_MAX" => 18446744073709551615,
- }.freeze
- end
-
- ROUNDING_MODE_MAP = [
- [ BigDecimal::ROUND_UP, :up],
- [ BigDecimal::ROUND_DOWN, :down],
- [ BigDecimal::ROUND_DOWN, :truncate],
- [ BigDecimal::ROUND_HALF_UP, :half_up],
- [ BigDecimal::ROUND_HALF_UP, :default],
- [ BigDecimal::ROUND_HALF_DOWN, :half_down],
- [ BigDecimal::ROUND_HALF_EVEN, :half_even],
- [ BigDecimal::ROUND_HALF_EVEN, :banker],
- [ BigDecimal::ROUND_CEILING, :ceiling],
- [ BigDecimal::ROUND_CEILING, :ceil],
- [ BigDecimal::ROUND_FLOOR, :floor],
- ]
-
- def assert_nan(x)
- assert(x.nan?, "Expected #{x.inspect} to be NaN")
- end
-
- def assert_positive_infinite(x)
- assert(x.infinite?, "Expected #{x.inspect} to be positive infinite")
- assert_operator(x, :>, 0)
- end
-
- def assert_negative_infinite(x)
- assert(x.infinite?, "Expected #{x.inspect} to be negative infinite")
- assert_operator(x, :<, 0)
- end
-
- def assert_positive_zero(x)
- assert_equal(BigDecimal::SIGN_POSITIVE_ZERO, x.sign,
- "Expected #{x.inspect} to be positive zero")
- end
-
- def assert_negative_zero(x)
- assert_equal(BigDecimal::SIGN_NEGATIVE_ZERO, x.sign,
- "Expected #{x.inspect} to be negative zero")
- end
-
- def test_not_equal
- assert_not_equal BigDecimal("1"), BigDecimal("2")
- end
-
- def test_BigDecimal
- assert_equal(1, BigDecimal("1"))
- assert_equal(1, BigDecimal("1", 1))
- assert_equal(1, BigDecimal(" 1 "))
- assert_equal(111, BigDecimal("1_1_1_"))
- assert_equal(10**(-1), BigDecimal("1E-1"), '#4825')
- assert_equal(1234, BigDecimal(" \t\n\r \r1234 \t\n\r \r"))
-
- assert_raise(ArgumentError) { BigDecimal("1", -1) }
- assert_raise_with_message(ArgumentError, /"1__1_1"/) { BigDecimal("1__1_1") }
- assert_raise_with_message(ArgumentError, /"_1_1_1"/) { BigDecimal("_1_1_1") }
-
- BigDecimal.save_exception_mode do
- BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
- BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
- assert_positive_infinite(BigDecimal("Infinity"))
- assert_positive_infinite(BigDecimal("1E1111111111111111111"))
- assert_positive_infinite(BigDecimal(" \t\n\r \rInfinity \t\n\r \r"))
- assert_negative_infinite(BigDecimal("-Infinity"))
- assert_negative_infinite(BigDecimal(" \t\n\r \r-Infinity \t\n\r \r"))
- assert_nan(BigDecimal("NaN"))
- assert_nan(BigDecimal(" \t\n\r \rNaN \t\n\r \r"))
- end
- end
-
- def test_BigDecimal_bug7522
- bd = BigDecimal("1.12", 1)
- assert_same(bd, BigDecimal(bd))
- assert_same(bd, BigDecimal(bd, exception: false))
- assert_not_same(bd, BigDecimal(bd, 1))
- assert_not_same(bd, BigDecimal(bd, 1, exception: false))
- end
-
- def test_BigDecimal_with_invalid_string
- [
- '', '.', 'e1', 'd1', '.e', '.d', '1.e', '1.d', '.1e', '.1d',
- '2,30', '19,000.0', '-2,30', '-19,000.0', '+2,30', '+19,000.0',
- '2.3,0', '19.000,0', '-2.3,0', '-19.000,0', '+2.3,0', '+19.000,0',
- '2.3.0', '19.000.0', '-2.3.0', '-19.000.0', '+2.3.0', '+19.000.0',
- 'invlaid value', '123 xyz'
- ].each do |invalid_string|
- assert_raise_with_message(ArgumentError, %Q[invalid value for BigDecimal(): "#{invalid_string}"]) do
- BigDecimal(invalid_string)
- end
- end
-
- BigDecimal.save_exception_mode do
- BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
- BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
- assert_raise_with_message(ArgumentError, /"Infinity_"/) { BigDecimal("Infinity_") }
- assert_raise_with_message(ArgumentError, /"\+Infinity_"/) { BigDecimal("+Infinity_") }
- assert_raise_with_message(ArgumentError, /"-Infinity_"/) { BigDecimal("-Infinity_") }
- assert_raise_with_message(ArgumentError, /"NaN_"/) { BigDecimal("NaN_") }
- end
- end
-
- def test_BigDecimal_with_integer
- assert_equal(BigDecimal("0"), BigDecimal(0))
- assert_equal(BigDecimal("1"), BigDecimal(1))
- assert_equal(BigDecimal("-1"), BigDecimal(-1))
- assert_equal(BigDecimal((2**100).to_s), BigDecimal(2**100))
- assert_equal(BigDecimal((-2**100).to_s), BigDecimal(-2**100))
-
- assert_equal(BigDecimal(LIMITS["FIXNUM_MIN"].to_s), BigDecimal(LIMITS["FIXNUM_MIN"]))
-
- assert_equal(BigDecimal(LIMITS["FIXNUM_MAX"].to_s), BigDecimal(LIMITS["FIXNUM_MAX"]))
-
- assert_equal(BigDecimal(LIMITS["INT64_MIN"].to_s), BigDecimal(LIMITS["INT64_MIN"]))
-
- assert_equal(BigDecimal(LIMITS["INT64_MAX"].to_s), BigDecimal(LIMITS["INT64_MAX"]))
-
- assert_equal(BigDecimal(LIMITS["UINT64_MAX"].to_s), BigDecimal(LIMITS["UINT64_MAX"]))
- end
-
- def test_BigDecimal_with_rational
- assert_equal(BigDecimal("0.333333333333333333333"), BigDecimal(1.quo(3), 21))
- assert_equal(BigDecimal("-0.333333333333333333333"), BigDecimal(-1.quo(3), 21))
- assert_raise_with_message(ArgumentError, "can't omit precision for a Rational.") { BigDecimal(42.quo(7)) }
- end
-
- def test_BigDecimal_with_float
- assert_equal(BigDecimal("0.1235"), BigDecimal(0.1234567, 4))
- assert_equal(BigDecimal("-0.1235"), BigDecimal(-0.1234567, 4))
- assert_raise_with_message(ArgumentError, "can't omit precision for a Float.") { BigDecimal(4.2) }
- assert_raise(ArgumentError) { BigDecimal(0.1, Float::DIG + 2) }
- assert_nothing_raised { BigDecimal(0.1, Float::DIG + 1) }
-
- assert_same(BigDecimal(0.0), BigDecimal(0.0))
- assert_same(BigDecimal(-0.0), BigDecimal(-0.0))
-
- bug9214 = '[ruby-core:58858]'
- assert_equal(BigDecimal(-0.0).sign, -1, bug9214)
-
- BigDecimal.save_exception_mode do
- BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
- assert_nan(BigDecimal(Float::NAN))
- assert_same(BigDecimal(Float::NAN), BigDecimal(Float::NAN))
- end
- BigDecimal.save_exception_mode do
- BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false)
- assert_positive_infinite(BigDecimal(Float::INFINITY))
- assert_same(BigDecimal(Float::INFINITY), BigDecimal(Float::INFINITY))
- assert_negative_infinite(BigDecimal(-Float::INFINITY))
- assert_same(BigDecimal(-Float::INFINITY), BigDecimal(-Float::INFINITY))
- end
- end
-
- def test_BigDecimal_with_complex
- assert_equal(BigDecimal("1"), BigDecimal(Complex(1, 0)))
- assert_equal(BigDecimal("0.333333333333333333333"), BigDecimal(Complex(1.quo(3), 0), 21))
- assert_equal(BigDecimal("0.1235"), BigDecimal(Complex(0.1234567, 0), 4))
-
- assert_raise_with_message(ArgumentError, "Unable to make a BigDecimal from non-zero imaginary number") { BigDecimal(Complex(1, 1)) }
- end
-
- def test_BigDecimal_with_big_decimal
- assert_equal(BigDecimal(1), BigDecimal(BigDecimal(1)))
- assert_equal(BigDecimal('+0'), BigDecimal(BigDecimal('+0')))
- assert_equal(BigDecimal('-0'), BigDecimal(BigDecimal('-0')))
- BigDecimal.save_exception_mode do
- BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
- BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
- assert_positive_infinite(BigDecimal(BigDecimal('Infinity')))
- assert_negative_infinite(BigDecimal(BigDecimal('-Infinity')))
- assert_nan(BigDecimal(BigDecimal('NaN')))
- end
- end
-
- if RUBY_VERSION < '2.7'
- def test_BigDecimal_with_tainted_string
- Thread.new {
- $SAFE = 1
- BigDecimal('1'.taint)
- }.join
- ensure
- $SAFE = 0
- end
- end
-
- def test_BigDecimal_with_exception_keyword
- assert_raise(ArgumentError) {
- BigDecimal('.', exception: true)
- }
- assert_nothing_raised(ArgumentError) {
- assert_equal(nil, BigDecimal(".", exception: false))
- }
- assert_raise(ArgumentError) {
- BigDecimal("1", -1, exception: true)
- }
- assert_nothing_raised(ArgumentError) {
- assert_equal(nil, BigDecimal("1", -1, exception: false))
- }
- assert_raise(ArgumentError) {
- BigDecimal(42.quo(7), exception: true)
- }
- assert_nothing_raised(ArgumentError) {
- assert_equal(nil, BigDecimal(42.quo(7), exception: false))
- }
- assert_raise(ArgumentError) {
- BigDecimal(4.2, exception: true)
- }
- assert_nothing_raised(ArgumentError) {
- assert_equal(nil, BigDecimal(4.2, exception: false))
- }
- # TODO: support conversion from complex
- # assert_raise(RangeError) {
- # BigDecimal(1i, exception: true)
- # }
- # assert_nothing_raised(RangeError) {
- # assert_equal(nil, BigDecimal(1i, exception: false))
- # }
- assert_raise_with_message(TypeError, "can't convert nil into BigDecimal") {
- BigDecimal(nil, exception: true)
- }
- assert_raise_with_message(TypeError, "can't convert true into BigDecimal") {
- BigDecimal(true, exception: true)
- }
- assert_raise_with_message(TypeError, "can't convert false into BigDecimal") {
- BigDecimal(false, exception: true)
- }
- assert_raise_with_message(TypeError, "can't convert Object into BigDecimal") {
- BigDecimal(Object.new, exception: true)
- }
- assert_nothing_raised(TypeError) {
- assert_equal(nil, BigDecimal(nil, exception: false))
- }
- assert_nothing_raised(TypeError) {
- assert_equal(nil, BigDecimal(:test, exception: false))
- }
- assert_nothing_raised(TypeError) {
- assert_equal(nil, BigDecimal(Object.new, exception: false))
- }
- assert_nothing_raised(TypeError) {
- assert_equal(nil, BigDecimal(Object.new, exception: false))
- }
- # TODO: support to_d
- # assert_nothing_raised(TypeError) {
- # o = Object.new
- # def o.to_d; 3.14; end
- # assert_equal(3.14, BigDecimal(o, exception: false))
- # }
- # assert_nothing_raised(RuntimeError) {
- # o = Object.new
- # def o.to_d; raise; end
- # assert_equal(nil, BigDecimal(o, exception: false))
- # }
- end
-
- def test_s_ver
- assert_raise_with_message(NoMethodError, /undefined method `ver'/) { BigDecimal.ver }
- end
-
- def test_s_allocate
- assert_raise_with_message(TypeError, /allocator undefined for BigDecimal/) { BigDecimal.allocate }
- end
-
- def test_s_new
- assert_raise_with_message(NoMethodError, /undefined method `new'/) { BigDecimal.new("1") }
- end
-
- def test_s_interpret_loosely
- assert_equal(BigDecimal('1'), BigDecimal.interpret_loosely("1__1_1"))
- assert_equal(BigDecimal('2.5'), BigDecimal.interpret_loosely("2.5"))
- assert_equal(BigDecimal('2.5'), BigDecimal.interpret_loosely("2.5 degrees"))
- assert_equal(BigDecimal('2.5e1'), BigDecimal.interpret_loosely("2.5e1 degrees"))
- assert_equal(BigDecimal('0'), BigDecimal.interpret_loosely("degrees 100.0"))
- assert_equal(BigDecimal('0.125'), BigDecimal.interpret_loosely("0.1_2_5"))
- assert_equal(BigDecimal('0.125'), BigDecimal.interpret_loosely("0.1_2_5__"))
- assert_equal(BigDecimal('1'), BigDecimal.interpret_loosely("1_.125"))
- assert_equal(BigDecimal('1'), BigDecimal.interpret_loosely("1._125"))
- assert_equal(BigDecimal('0.1'), BigDecimal.interpret_loosely("0.1__2_5"))
- assert_equal(BigDecimal('0.1'), BigDecimal.interpret_loosely("0.1_e10"))
- assert_equal(BigDecimal('0.1'), BigDecimal.interpret_loosely("0.1e_10"))
- assert_equal(BigDecimal('1'), BigDecimal.interpret_loosely("0.1e1__0"))
- assert_equal(BigDecimal('1.2'), BigDecimal.interpret_loosely("1.2.3"))
- assert_equal(BigDecimal('1'), BigDecimal.interpret_loosely("1."))
- assert_equal(BigDecimal('1'), BigDecimal.interpret_loosely("1e"))
-
- assert_equal(BigDecimal('0.0'), BigDecimal.interpret_loosely("invalid"))
-
- assert(BigDecimal.interpret_loosely("2.5").frozen?)
- end
-
- def _test_mode(type)
- BigDecimal.mode(type, true)
- assert_raise(FloatDomainError) { yield }
-
- BigDecimal.mode(type, false)
- assert_nothing_raised { yield }
- end
-
- def test_mode
- assert_raise(ArgumentError) { BigDecimal.mode(BigDecimal::EXCEPTION_ALL, 1) }
- assert_raise(ArgumentError) { BigDecimal.mode(BigDecimal::ROUND_MODE, 256) }
- assert_raise(ArgumentError) { BigDecimal.mode(BigDecimal::ROUND_MODE, :xyzzy) }
- assert_raise(TypeError) { BigDecimal.mode(0xf000, true) }
-
- begin
- saved_mode = BigDecimal.mode(BigDecimal::ROUND_MODE)
-
- [ BigDecimal::ROUND_UP,
- BigDecimal::ROUND_DOWN,
- BigDecimal::ROUND_HALF_UP,
- BigDecimal::ROUND_HALF_DOWN,
- BigDecimal::ROUND_CEILING,
- BigDecimal::ROUND_FLOOR,
- BigDecimal::ROUND_HALF_EVEN,
- ].each do |mode|
- BigDecimal.mode(BigDecimal::ROUND_MODE, mode)
- assert_equal(mode, BigDecimal.mode(BigDecimal::ROUND_MODE))
- end
- ensure
- BigDecimal.mode(BigDecimal::ROUND_MODE, saved_mode)
- end
-
- BigDecimal.save_rounding_mode do
- ROUNDING_MODE_MAP.each do |const, sym|
- BigDecimal.mode(BigDecimal::ROUND_MODE, sym)
- assert_equal(const, BigDecimal.mode(BigDecimal::ROUND_MODE))
- end
- end
- end
-
- def test_thread_local_mode
- begin
- saved_mode = BigDecimal.mode(BigDecimal::ROUND_MODE)
-
- BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_UP)
- Thread.start {
- BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_HALF_EVEN)
- assert_equal(BigDecimal::ROUND_HALF_EVEN, BigDecimal.mode(BigDecimal::ROUND_MODE))
- }.join
- assert_equal(BigDecimal::ROUND_UP, BigDecimal.mode(BigDecimal::ROUND_MODE))
- ensure
- BigDecimal.mode(BigDecimal::ROUND_MODE, saved_mode)
- end
- end
-
- def test_save_exception_mode
- BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
- mode = BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW)
- BigDecimal.save_exception_mode do
- BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, true)
- end
- assert_equal(mode, BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW))
-
- BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_FLOOR)
- BigDecimal.save_exception_mode do
- BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_HALF_EVEN)
- end
- assert_equal(BigDecimal::ROUND_HALF_EVEN, BigDecimal.mode(BigDecimal::ROUND_MODE))
-
- assert_equal(42, BigDecimal.save_exception_mode { 42 })
- end
-
- def test_save_rounding_mode
- saved_mode = BigDecimal.mode(BigDecimal::ROUND_MODE)
-
- BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_FLOOR)
- BigDecimal.save_rounding_mode do
- BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_HALF_EVEN)
- end
- assert_equal(BigDecimal::ROUND_FLOOR, BigDecimal.mode(BigDecimal::ROUND_MODE))
-
- assert_equal(42, BigDecimal.save_rounding_mode { 42 })
- ensure
- BigDecimal.mode(BigDecimal::ROUND_MODE, saved_mode)
- end
-
- def test_save_limit
- begin
- old = BigDecimal.limit
- BigDecimal.limit(100)
- BigDecimal.save_limit do
- BigDecimal.limit(200)
- end
- assert_equal(100, BigDecimal.limit);
- ensure
- BigDecimal.limit(old)
- end
-
- assert_equal(42, BigDecimal.save_limit { 42 })
- end
-
- def test_exception_nan
- _test_mode(BigDecimal::EXCEPTION_NaN) { BigDecimal("NaN") }
- end
-
- def test_exception_infinity
- _test_mode(BigDecimal::EXCEPTION_INFINITY) { BigDecimal("Infinity") }
- end
-
- def test_exception_underflow
- _test_mode(BigDecimal::EXCEPTION_UNDERFLOW) do
- x = BigDecimal("0.1")
- 100.times do
- x *= x
- end
- end
- end
-
- def test_exception_overflow
- _test_mode(BigDecimal::EXCEPTION_OVERFLOW) do
- x = BigDecimal("10")
- 100.times do
- x *= x
- end
- end
- end
-
- def test_exception_zerodivide
- BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
- _test_mode(BigDecimal::EXCEPTION_ZERODIVIDE) { 1 / BigDecimal("0") }
- _test_mode(BigDecimal::EXCEPTION_ZERODIVIDE) { -1 / BigDecimal("0") }
- end
-
- def test_round_up
- n4 = BigDecimal("4") # n4 / 9 = 0.44444...
- n5 = BigDecimal("5") # n5 / 9 = 0.55555...
- n6 = BigDecimal("6") # n6 / 9 = 0.66666...
- m4, m5, m6 = -n4, -n5, -n6
- n2h = BigDecimal("2.5")
- n3h = BigDecimal("3.5")
- m2h, m3h = -n2h, -n3h
-
- BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_UP)
- assert_operator(n4, :<, n4 / 9 * 9)
- assert_operator(n5, :<, n5 / 9 * 9)
- assert_operator(n6, :<, n6 / 9 * 9)
- assert_operator(m4, :>, m4 / 9 * 9)
- assert_operator(m5, :>, m5 / 9 * 9)
- assert_operator(m6, :>, m6 / 9 * 9)
- assert_equal(3, n2h.round)
- assert_equal(4, n3h.round)
- assert_equal(-3, m2h.round)
- assert_equal(-4, m3h.round)
-
- BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_DOWN)
- assert_operator(n4, :>, n4 / 9 * 9)
- assert_operator(n5, :>, n5 / 9 * 9)
- assert_operator(n6, :>, n6 / 9 * 9)
- assert_operator(m4, :<, m4 / 9 * 9)
- assert_operator(m5, :<, m5 / 9 * 9)
- assert_operator(m6, :<, m6 / 9 * 9)
- assert_equal(2, n2h.round)
- assert_equal(3, n3h.round)
- assert_equal(-2, m2h.round)
- assert_equal(-3, m3h.round)
-
- BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_HALF_UP)
- assert_operator(n4, :>, n4 / 9 * 9)
- assert_operator(n5, :<, n5 / 9 * 9)
- assert_operator(n6, :<, n6 / 9 * 9)
- assert_operator(m4, :<, m4 / 9 * 9)
- assert_operator(m5, :>, m5 / 9 * 9)
- assert_operator(m6, :>, m6 / 9 * 9)
- assert_equal(3, n2h.round)
- assert_equal(4, n3h.round)
- assert_equal(-3, m2h.round)
- assert_equal(-4, m3h.round)
-
- BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_HALF_DOWN)
- assert_operator(n4, :>, n4 / 9 * 9)
- assert_operator(n5, :>, n5 / 9 * 9)
- assert_operator(n6, :<, n6 / 9 * 9)
- assert_operator(m4, :<, m4 / 9 * 9)
- assert_operator(m5, :<, m5 / 9 * 9)
- assert_operator(m6, :>, m6 / 9 * 9)
- assert_equal(2, n2h.round)
- assert_equal(3, n3h.round)
- assert_equal(-2, m2h.round)
- assert_equal(-3, m3h.round)
-
- BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_HALF_EVEN)
- assert_operator(n4, :>, n4 / 9 * 9)
- assert_operator(n5, :<, n5 / 9 * 9)
- assert_operator(n6, :<, n6 / 9 * 9)
- assert_operator(m4, :<, m4 / 9 * 9)
- assert_operator(m5, :>, m5 / 9 * 9)
- assert_operator(m6, :>, m6 / 9 * 9)
- assert_equal(2, n2h.round)
- assert_equal(4, n3h.round)
- assert_equal(-2, m2h.round)
- assert_equal(-4, m3h.round)
-
- BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_CEILING)
- assert_operator(n4, :<, n4 / 9 * 9)
- assert_operator(n5, :<, n5 / 9 * 9)
- assert_operator(n6, :<, n6 / 9 * 9)
- assert_operator(m4, :<, m4 / 9 * 9)
- assert_operator(m5, :<, m5 / 9 * 9)
- assert_operator(m6, :<, m6 / 9 * 9)
- assert_equal(3, n2h.round)
- assert_equal(4, n3h.round)
- assert_equal(-2, m2h.round)
- assert_equal(-3, m3h.round)
-
- BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_FLOOR)
- assert_operator(n4, :>, n4 / 9 * 9)
- assert_operator(n5, :>, n5 / 9 * 9)
- assert_operator(n6, :>, n6 / 9 * 9)
- assert_operator(m4, :>, m4 / 9 * 9)
- assert_operator(m5, :>, m5 / 9 * 9)
- assert_operator(m6, :>, m6 / 9 * 9)
- assert_equal(2, n2h.round)
- assert_equal(3, n3h.round)
- assert_equal(-3, m2h.round)
- assert_equal(-4, m3h.round)
- end
-
- def test_zero_p
- BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false)
- BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
-
- assert_equal(true, BigDecimal("0").zero?)
- assert_equal(true, BigDecimal("-0").zero?)
- assert_equal(false, BigDecimal("1").zero?)
- assert_equal(true, BigDecimal("0E200000000000000").zero?)
- assert_equal(false, BigDecimal("Infinity").zero?)
- assert_equal(false, BigDecimal("-Infinity").zero?)
- assert_equal(false, BigDecimal("NaN").zero?)
- end
-
- def test_nonzero_p
- BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false)
- BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
-
- assert_equal(nil, BigDecimal("0").nonzero?)
- assert_equal(nil, BigDecimal("-0").nonzero?)
- assert_equal(BigDecimal("1"), BigDecimal("1").nonzero?)
- assert_positive_infinite(BigDecimal("Infinity").nonzero?)
- assert_negative_infinite(BigDecimal("-Infinity").nonzero?)
- assert_nan(BigDecimal("NaN").nonzero?)
- end
-
- def test_double_fig
- assert_kind_of(Integer, BigDecimal.double_fig)
- end
-
- def test_cmp
- n1 = BigDecimal("1")
- n2 = BigDecimal("2")
- assert_equal( 0, n1 <=> n1)
- assert_equal( 1, n2 <=> n1)
- assert_equal(-1, n1 <=> n2)
- assert_operator(n1, :==, n1)
- assert_operator(n1, :!=, n2)
- assert_operator(n1, :<, n2)
- assert_operator(n1, :<=, n1)
- assert_operator(n1, :<=, n2)
- assert_operator(n2, :>, n1)
- assert_operator(n2, :>=, n1)
- assert_operator(n1, :>=, n1)
-
- assert_operator(BigDecimal("-0"), :==, BigDecimal("0"))
- assert_operator(BigDecimal("0"), :<, BigDecimal("1"))
- assert_operator(BigDecimal("1"), :>, BigDecimal("0"))
- assert_operator(BigDecimal("1"), :>, BigDecimal("-1"))
- assert_operator(BigDecimal("-1"), :<, BigDecimal("1"))
- assert_operator(BigDecimal((2**100).to_s), :>, BigDecimal("1"))
- assert_operator(BigDecimal("1"), :<, BigDecimal((2**100).to_s))
-
- BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
- inf = BigDecimal("Infinity")
- assert_operator(inf, :>, 1)
- assert_operator(1, :<, inf)
-
- assert_operator(BigDecimal("1E-1"), :==, 10**(-1), '#4825')
- assert_equal(0, BigDecimal("1E-1") <=> 10**(-1), '#4825')
- end
-
- def test_cmp_issue9192
- bug9192 = '[ruby-core:58756] [#9192]'
- operators = { :== => :==, :< => :>, :> => :<, :<= => :>=, :>= => :<= }
- 5.upto(8) do |i|
- s = "706.0#{i}"
- d = BigDecimal(s)
- f = s.to_f
- operators.each do |op, inv|
- assert_equal(d.send(op, f), f.send(inv, d),
- "(BigDecimal(#{s.inspect}) #{op} #{s}) and (#{s} #{inv} BigDecimal(#{s.inspect})) is different #{bug9192}")
- end
- end
- end
-
- def test_cmp_nan
- n1 = BigDecimal("1")
- BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
- assert_equal(nil, BigDecimal("NaN") <=> n1)
- assert_equal(false, BigDecimal("NaN") > n1)
- assert_equal(nil, BigDecimal("NaN") <=> BigDecimal("NaN"))
- assert_equal(false, BigDecimal("NaN") == BigDecimal("NaN"))
- end
-
- def test_cmp_failing_coercion
- n1 = BigDecimal("1")
- assert_equal(nil, n1 <=> nil)
- assert_raise(ArgumentError){n1 > nil}
- end
-
- def test_cmp_coerce
- n1 = BigDecimal("1")
- n2 = BigDecimal("2")
- o1 = Object.new; def o1.coerce(x); [x, BigDecimal("1")]; end
- o2 = Object.new; def o2.coerce(x); [x, BigDecimal("2")]; end
- assert_equal( 0, n1 <=> o1)
- assert_equal( 1, n2 <=> o1)
- assert_equal(-1, n1 <=> o2)
- assert_operator(n1, :==, o1)
- assert_operator(n1, :!=, o2)
- assert_operator(n1, :<, o2)
- assert_operator(n1, :<=, o1)
- assert_operator(n1, :<=, o2)
- assert_operator(n2, :>, o1)
- assert_operator(n2, :>=, o1)
- assert_operator(n1, :>=, 1)
-
- bug10109 = '[ruby-core:64190]'
- BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false)
- assert_operator(BigDecimal(0), :<, Float::INFINITY, bug10109)
- assert_operator(Float::INFINITY, :>, BigDecimal(0), bug10109)
- end
-
- def test_cmp_bignum
- assert_operator(BigDecimal((2**100).to_s), :==, 2**100)
- end
-
- def test_cmp_data
- d = Time.now; def d.coerce(x); [x, x]; end
- assert_operator(BigDecimal((2**100).to_s), :==, d)
- end
-
- def test_precs_deprecated
- saved = Warning[:deprecated]
- Warning[:deprecated] = true
- assert_warn(/BigDecimal#precs is deprecated and will be removed in the future/) do
- BigDecimal("1").precs
- end
- ensure
- Warning[:deprecated] = saved
- end
-
- def test_precs
- assert_separately(["-rbigdecimal"], "#{<<~"begin;"}\n#{<<~'end;'}")
- begin;
- $VERBOSE = nil
- a = BigDecimal("1").precs
- assert_instance_of(Array, a)
- assert_equal(2, a.size)
- assert_kind_of(Integer, a[0])
- assert_kind_of(Integer, a[1])
- end;
- end
-
- def test_hash
- a = []
- b = BigDecimal("1")
- 10.times { a << b *= 10 }
- h = {}
- a.each_with_index {|x, i| h[x] = i }
- a.each_with_index do |x, i|
- assert_equal(i, h[x])
- end
- end
-
- def test_marshal
- s = Marshal.dump(BigDecimal("1", 1))
- assert_equal(BigDecimal("1", 1), Marshal.load(s))
-
- # corrupt data
- s = s.gsub(/BigDecimal.*\z/m) {|x| x.gsub(/\d/m, "-") }
- assert_raise(TypeError) { Marshal.load(s) }
- end
-
- def test_finite_infinite_nan
- BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
- BigDecimal.mode(BigDecimal::EXCEPTION_ZERODIVIDE, false)
-
- x = BigDecimal("0")
- assert_equal(true, x.finite?)
- assert_equal(nil, x.infinite?)
- assert_equal(false, x.nan?)
- y = 1 / x
- assert_equal(false, y.finite?)
- assert_equal(1, y.infinite?)
- assert_equal(false, y.nan?)
- y = -1 / x
- assert_equal(false, y.finite?)
- assert_equal(-1, y.infinite?)
- assert_equal(false, y.nan?)
-
- BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
- y = 0 / x
- assert_equal(false, y.finite?)
- assert_equal(nil, y.infinite?)
- assert_equal(true, y.nan?)
- end
-
- def test_to_i
- BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
- BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
-
- x = BigDecimal("0")
- assert_kind_of(Integer, x.to_i)
- assert_equal(0, x.to_i)
- assert_raise(FloatDomainError){( 1 / x).to_i}
- assert_raise(FloatDomainError){(-1 / x).to_i}
- assert_raise(FloatDomainError) {( 0 / x).to_i}
- x = BigDecimal("1")
- assert_equal(1, x.to_i)
- x = BigDecimal((2**100).to_s)
- assert_equal(2**100, x.to_i)
- end
-
- def test_to_f
- BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
- BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
- BigDecimal.mode(BigDecimal::EXCEPTION_ZERODIVIDE, false)
-
- x = BigDecimal("0")
- assert_instance_of(Float, x.to_f)
- assert_equal(0.0, x.to_f)
- assert_equal( 1.0 / 0.0, ( 1 / x).to_f)
- assert_equal(-1.0 / 0.0, (-1 / x).to_f)
- assert_nan(( 0 / x).to_f)
- x = BigDecimal("1")
- assert_equal(1.0, x.to_f)
- x = BigDecimal((2**100).to_s)
- assert_equal((2**100).to_f, x.to_f)
- x = BigDecimal("1" + "0" * 10000)
- assert_equal(0, BigDecimal("-0").to_f)
-
- BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, true)
- assert_raise(FloatDomainError) { x.to_f }
- BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
- assert_kind_of(Float, x .to_f)
- assert_kind_of(Float, (-x).to_f)
-
- bug6944 = '[ruby-core:47342]'
-
- BigDecimal.mode(BigDecimal::EXCEPTION_UNDERFLOW, true)
- x = "1e#{Float::MIN_10_EXP - 2*Float::DIG}"
- assert_raise(FloatDomainError, x) {BigDecimal(x).to_f}
- x = "-#{x}"
- assert_raise(FloatDomainError, x) {BigDecimal(x).to_f}
- x = "1e#{Float::MIN_10_EXP - Float::DIG}"
- assert_nothing_raised(FloatDomainError, x) {
- assert_in_delta(0.0, BigDecimal(x).to_f, 10**Float::MIN_10_EXP, bug6944)
- }
- x = "-#{x}"
- assert_nothing_raised(FloatDomainError, x) {
- assert_in_delta(0.0, BigDecimal(x).to_f, 10**Float::MIN_10_EXP, bug6944)
- }
-
- BigDecimal.mode(BigDecimal::EXCEPTION_UNDERFLOW, false)
- x = "1e#{Float::MIN_10_EXP - 2*Float::DIG}"
- assert_equal( 0.0, BigDecimal(x).to_f, x)
- x = "-#{x}"
- assert_equal(-0.0, BigDecimal(x).to_f, x)
- x = "1e#{Float::MIN_10_EXP - Float::DIG}"
- assert_nothing_raised(FloatDomainError, x) {
- assert_in_delta(0.0, BigDecimal(x).to_f, 10**Float::MIN_10_EXP, bug6944)
- }
- x = "-#{x}"
- assert_nothing_raised(FloatDomainError, x) {
- assert_in_delta(0.0, BigDecimal(x).to_f, 10**Float::MIN_10_EXP, bug6944)
- }
-
- assert_equal( 0.0, BigDecimal( '9e-325').to_f)
- assert_equal( 0.0, BigDecimal( '10e-325').to_f)
- assert_equal(-0.0, BigDecimal( '-9e-325').to_f)
- assert_equal(-0.0, BigDecimal('-10e-325').to_f)
- end
-
- def test_to_r
- BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
- BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
-
- x = BigDecimal("0")
- assert_kind_of(Rational, x.to_r)
- assert_equal(0, x.to_r)
- assert_raise(FloatDomainError) {( 1 / x).to_r}
- assert_raise(FloatDomainError) {(-1 / x).to_r}
- assert_raise(FloatDomainError) {( 0 / x).to_r}
-
- assert_equal(1, BigDecimal("1").to_r)
- assert_equal(Rational(3, 2), BigDecimal("1.5").to_r)
- assert_equal((2**100).to_r, BigDecimal((2**100).to_s).to_r)
- end
-
- def test_coerce
- a, b = BigDecimal("1").coerce(1.0)
- assert_instance_of(BigDecimal, a)
- assert_instance_of(BigDecimal, b)
- assert_equal(2, 1 + BigDecimal("1"), '[ruby-core:25697]')
-
- a, b = BigDecimal("1").coerce(1.quo(10))
- assert_equal(BigDecimal("0.1"), a, '[ruby-core:34318]')
-
- a, b = BigDecimal("0.11111").coerce(1.quo(3))
- assert_equal(BigDecimal("0." + "3"*a.precision), a)
-
- assert_nothing_raised(TypeError, '#7176') do
- BigDecimal('1') + Rational(1)
- end
- end
-
- def test_uplus
- x = BigDecimal("1")
- assert_equal(x, x.send(:+@))
- end
-
- def test_neg
- BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false)
- BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
-
- assert_equal(BigDecimal("-1"), BigDecimal("1").send(:-@))
- assert_equal(BigDecimal("-0"), BigDecimal("0").send(:-@))
- assert_equal(BigDecimal("0"), BigDecimal("-0").send(:-@))
- assert_equal(BigDecimal("-Infinity"), BigDecimal("Infinity").send(:-@))
- assert_equal(BigDecimal("Infinity"), BigDecimal("-Infinity").send(:-@))
- assert_equal(true, BigDecimal("NaN").send(:-@).nan?)
- end
-
- def test_add
- x = BigDecimal("1")
- assert_equal(BigDecimal("2"), x + x)
- assert_equal(1, BigDecimal("0") + 1)
- assert_equal(1, x + 0)
-
- assert_equal(BigDecimal::SIGN_POSITIVE_ZERO, (BigDecimal("0") + 0).sign)
- assert_equal(BigDecimal::SIGN_POSITIVE_ZERO, (BigDecimal("-0") + 0).sign)
- assert_equal(BigDecimal::SIGN_NEGATIVE_ZERO, (BigDecimal("-0") + BigDecimal("-0")).sign)
-
- x = BigDecimal((2**100).to_s)
- assert_equal(BigDecimal((2**100+1).to_s), x + 1)
-
- BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false)
- inf = BigDecimal("Infinity")
- neginf = BigDecimal("-Infinity")
-
- BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, true)
- assert_raise_with_message(FloatDomainError, "Computation results to 'Infinity'") { inf + inf }
- assert_raise_with_message(FloatDomainError, "Computation results to '-Infinity'") { neginf + neginf }
- end
-
- def test_sub
- x = BigDecimal("1")
- assert_equal(BigDecimal("0"), x - x)
- assert_equal(-1, BigDecimal("0") - 1)
- assert_equal(1, x - 0)
-
- assert_equal(BigDecimal::SIGN_POSITIVE_ZERO, (BigDecimal("0") - 0).sign)
- assert_equal(BigDecimal::SIGN_NEGATIVE_ZERO, (BigDecimal("-0") - 0).sign)
- assert_equal(BigDecimal::SIGN_POSITIVE_ZERO, (BigDecimal("-0") - BigDecimal("-0")).sign)
-
- x = BigDecimal((2**100).to_s)
- assert_equal(BigDecimal((2**100-1).to_s), x - 1)
-
- BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false)
- inf = BigDecimal("Infinity")
- neginf = BigDecimal("-Infinity")
-
- BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, true)
- assert_raise_with_message(FloatDomainError, "Computation results to 'Infinity'") { inf - neginf }
- assert_raise_with_message(FloatDomainError, "Computation results to '-Infinity'") { neginf - inf }
- end
-
- def test_sub_with_float
- assert_kind_of(BigDecimal, BigDecimal("3") - 1.0)
- end
-
- def test_sub_with_rational
- assert_kind_of(BigDecimal, BigDecimal("3") - 1.quo(3))
- end
-
- def test_mult
- x = BigDecimal((2**100).to_s)
- assert_equal(BigDecimal((2**100 * 3).to_s), (x * 3).to_i)
- assert_equal(x, (x * 1).to_i)
- assert_equal(x, (BigDecimal("1") * x).to_i)
- assert_equal(BigDecimal((2**200).to_s), (x * x).to_i)
-
- BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false)
- inf = BigDecimal("Infinity")
- neginf = BigDecimal("-Infinity")
-
- BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, true)
- assert_raise_with_message(FloatDomainError, "Computation results to 'Infinity'") { inf * inf }
- assert_raise_with_message(FloatDomainError, "Computation results to '-Infinity'") { neginf * inf }
- end
-
- def test_mult_with_float
- assert_kind_of(BigDecimal, BigDecimal("3") * 1.5)
- assert_equal(BigDecimal("64.4"), BigDecimal(1) * 64.4)
- end
-
- def test_mult_with_rational
- assert_kind_of(BigDecimal, BigDecimal("3") * 1.quo(3))
- end
-
- def test_mult_with_nil
- assert_raise(TypeError) {
- BigDecimal('1.1') * nil
- }
- end
-
- def test_div
- x = BigDecimal((2**100).to_s)
- assert_equal(BigDecimal((2**100 / 3).to_s), (x / 3).to_i)
- assert_equal(BigDecimal::SIGN_POSITIVE_ZERO, (BigDecimal("0") / 1).sign)
- assert_equal(BigDecimal::SIGN_NEGATIVE_ZERO, (BigDecimal("-0") / 1).sign)
- assert_equal(2, BigDecimal("2") / 1)
- assert_equal(-2, BigDecimal("2") / -1)
-
- assert_equal(BigDecimal('1486.868686869'), BigDecimal('1472.0') / BigDecimal('0.99'), '[ruby-core:59365] [#9316]')
-
- assert_equal(4.124045235, BigDecimal('0.9932') / (700 * BigDecimal('0.344045') / BigDecimal('1000.0')), '[#9305]')
-
- BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false)
- assert_positive_zero(BigDecimal("1.0") / BigDecimal("Infinity"))
- assert_negative_zero(BigDecimal("-1.0") / BigDecimal("Infinity"))
- assert_negative_zero(BigDecimal("1.0") / BigDecimal("-Infinity"))
- assert_positive_zero(BigDecimal("-1.0") / BigDecimal("-Infinity"))
-
- BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, true)
- BigDecimal.mode(BigDecimal::EXCEPTION_ZERODIVIDE, false)
- assert_raise_with_message(FloatDomainError, "Computation results to 'Infinity'") { BigDecimal("1") / 0 }
- assert_raise_with_message(FloatDomainError, "Computation results to '-Infinity'") { BigDecimal("-1") / 0 }
- end
-
- def test_div_with_float
- assert_kind_of(BigDecimal, BigDecimal("3") / 1.5)
- assert_equal(BigDecimal("0.5"), BigDecimal(1) / 2.0)
- end
-
- def test_div_with_rational
- assert_kind_of(BigDecimal, BigDecimal("3") / 1.quo(3))
- end
-
- def test_div_with_complex
- q = BigDecimal("3") / 1i
- assert_kind_of(Complex, q)
- end
-
- def test_div_error
- assert_raise(TypeError) { BigDecimal(20) / '2' }
- end
-
- def test_mod
- x = BigDecimal((2**100).to_s)
- assert_equal(1, x % 3)
- assert_equal(2, (-x) % 3)
- assert_equal(-2, x % -3)
- assert_equal(-1, (-x) % -3)
- end
-
- def test_mod_with_float
- assert_kind_of(BigDecimal, BigDecimal("3") % 1.5)
- end
-
- def test_mod_with_rational
- assert_kind_of(BigDecimal, BigDecimal("3") % 1.quo(3))
- end
-
- def test_remainder
- x = BigDecimal((2**100).to_s)
- assert_equal(1, x.remainder(3))
- assert_equal(-1, (-x).remainder(3))
- assert_equal(1, x.remainder(-3))
- assert_equal(-1, (-x).remainder(-3))
- end
-
- def test_remainder_with_float
- assert_kind_of(BigDecimal, BigDecimal("3").remainder(1.5))
- end
-
- def test_remainder_with_rational
- assert_kind_of(BigDecimal, BigDecimal("3").remainder(1.quo(3)))
- end
-
- def test_divmod
- x = BigDecimal((2**100).to_s)
- assert_equal([(x / 3).floor, 1], x.divmod(3))
- assert_equal([(-x / 3).floor, 2], (-x).divmod(3))
-
- assert_equal([0, 0], BigDecimal("0").divmod(2))
-
- BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
- assert_raise(ZeroDivisionError){BigDecimal("0").divmod(0)}
- end
-
- def test_divmod_error
- assert_raise(TypeError) { BigDecimal(20).divmod('2') }
- end
-
- def test_add_bigdecimal
- x = BigDecimal((2**100).to_s)
- assert_equal(3000000000000000000000000000000, x.add(x, 1))
- assert_equal(2500000000000000000000000000000, x.add(x, 2))
- assert_equal(2540000000000000000000000000000, x.add(x, 3))
- end
-
- def test_sub_bigdecimal
- x = BigDecimal((2**100).to_s)
- assert_equal(1000000000000000000000000000000, x.sub(1, 1))
- assert_equal(1300000000000000000000000000000, x.sub(1, 2))
- assert_equal(1270000000000000000000000000000, x.sub(1, 3))
- end
-
- def test_mult_bigdecimal
- x = BigDecimal((2**100).to_s)
- assert_equal(4000000000000000000000000000000, x.mult(3, 1))
- assert_equal(3800000000000000000000000000000, x.mult(3, 2))
- assert_equal(3800000000000000000000000000000, x.mult(3, 3))
- end
-
- def test_div_bigdecimal
- x = BigDecimal((2**100).to_s)
- assert_equal(422550200076076467165567735125, x.div(3))
- assert_equal(400000000000000000000000000000, x.div(3, 1))
- assert_equal(420000000000000000000000000000, x.div(3, 2))
- assert_equal(423000000000000000000000000000, x.div(3, 3))
- BigDecimal.save_exception_mode do
- BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false)
- assert_equal(0, BigDecimal("0").div(BigDecimal("Infinity")))
- end
- end
-
- def test_abs_bigdecimal
- x = BigDecimal((2**100).to_s)
- assert_equal(1267650600228229401496703205376, x.abs)
- x = BigDecimal("-" + (2**100).to_s)
- assert_equal(1267650600228229401496703205376, x.abs)
- x = BigDecimal("0")
- assert_equal(0, x.abs)
- x = BigDecimal("-0")
- assert_equal(0, x.abs)
-
- BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false)
- x = BigDecimal("Infinity")
- assert_equal(BigDecimal("Infinity"), x.abs)
- x = BigDecimal("-Infinity")
- assert_equal(BigDecimal("Infinity"), x.abs)
-
- BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
- x = BigDecimal("NaN")
- assert_nan(x.abs)
- end
-
- def test_sqrt_bigdecimal
- x = BigDecimal("0.09")
- assert_in_delta(0.3, x.sqrt(1), 0.001)
- x = BigDecimal((2**100).to_s)
- y = BigDecimal("1125899906842624")
- e = y.exponent
- assert_equal(true, (x.sqrt(100) - y).abs < BigDecimal("1E#{e-100}"))
- assert_equal(true, (x.sqrt(200) - y).abs < BigDecimal("1E#{e-200}"))
- assert_equal(true, (x.sqrt(300) - y).abs < BigDecimal("1E#{e-300}"))
- x = BigDecimal("-" + (2**100).to_s)
- assert_raise_with_message(FloatDomainError, "sqrt of negative value") { x.sqrt(1) }
- x = BigDecimal((2**200).to_s)
- assert_equal(2**100, x.sqrt(1))
-
- BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
- BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
- assert_raise_with_message(FloatDomainError, "sqrt of 'NaN'(Not a Number)") { BigDecimal("NaN").sqrt(1) }
- assert_raise_with_message(FloatDomainError, "sqrt of negative value") { BigDecimal("-Infinity").sqrt(1) }
-
- assert_equal(0, BigDecimal("0").sqrt(1))
- assert_equal(0, BigDecimal("-0").sqrt(1))
- assert_equal(1, BigDecimal("1").sqrt(1))
- assert_positive_infinite(BigDecimal("Infinity").sqrt(1))
- end
-
- def test_sqrt_5266
- x = BigDecimal('2' + '0'*100)
- assert_equal('0.14142135623730950488016887242096980785696718753769480731',
- x.sqrt(56).to_s(56).split(' ')[0])
- assert_equal('0.1414213562373095048801688724209698078569671875376948073',
- x.sqrt(55).to_s(55).split(' ')[0])
-
- x = BigDecimal('2' + '0'*200)
- assert_equal('0.14142135623730950488016887242096980785696718753769480731766797379907324784621070388503875343276415727350138462',
- x.sqrt(110).to_s(110).split(' ')[0])
- assert_equal('0.1414213562373095048801688724209698078569671875376948073176679737990732478462107038850387534327641572735013846',
- x.sqrt(109).to_s(109).split(' ')[0])
- end
-
- def test_fix
- x = BigDecimal("1.1")
- assert_equal(1, x.fix)
- assert_kind_of(BigDecimal, x.fix)
- end
-
- def test_frac
- x = BigDecimal("1.1")
- assert_equal(0.1, x.frac)
- assert_equal(0.1, BigDecimal("0.1").frac)
- BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
- assert_nan(BigDecimal("NaN").frac)
- end
-
- def test_round
- assert_equal(3, BigDecimal("3.14159").round)
- assert_equal(9, BigDecimal("8.7").round)
- assert_equal(3.142, BigDecimal("3.14159").round(3))
- assert_equal(13300.0, BigDecimal("13345.234").round(-2))
-
- x = BigDecimal("111.111")
- assert_equal(111 , x.round)
- assert_equal(111.1 , x.round(1))
- assert_equal(111.11 , x.round(2))
- assert_equal(111.111, x.round(3))
- assert_equal(111.111, x.round(4))
- assert_equal(110 , x.round(-1))
- assert_equal(100 , x.round(-2))
- assert_equal( 0 , x.round(-3))
- assert_equal( 0 , x.round(-4))
-
- x = BigDecimal("2.5")
- assert_equal(3, x.round(0, BigDecimal::ROUND_UP))
- assert_equal(2, x.round(0, BigDecimal::ROUND_DOWN))
- assert_equal(3, x.round(0, BigDecimal::ROUND_HALF_UP))
- assert_equal(2, x.round(0, BigDecimal::ROUND_HALF_DOWN))
- assert_equal(2, x.round(0, BigDecimal::ROUND_HALF_EVEN))
- assert_equal(3, x.round(0, BigDecimal::ROUND_CEILING))
- assert_equal(2, x.round(0, BigDecimal::ROUND_FLOOR))
- assert_raise(ArgumentError) { x.round(0, 256) }
-
- x = BigDecimal("-2.5")
- assert_equal(-3, x.round(0, BigDecimal::ROUND_UP))
- assert_equal(-2, x.round(0, BigDecimal::ROUND_DOWN))
- assert_equal(-3, x.round(0, BigDecimal::ROUND_HALF_UP))
- assert_equal(-2, x.round(0, BigDecimal::ROUND_HALF_DOWN))
- assert_equal(-2, x.round(0, BigDecimal::ROUND_HALF_EVEN))
- assert_equal(-2, x.round(0, BigDecimal::ROUND_CEILING))
- assert_equal(-3, x.round(0, BigDecimal::ROUND_FLOOR))
-
- ROUNDING_MODE_MAP.each do |const, sym|
- assert_equal(x.round(0, const), x.round(0, sym))
- end
-
- bug3803 = '[ruby-core:32136]'
- 15.times do |n|
- x = BigDecimal("5#{'0'*n}1")
- assert_equal(10**(n+2), x.round(-(n+2), BigDecimal::ROUND_HALF_DOWN), bug3803)
- assert_equal(10**(n+2), x.round(-(n+2), BigDecimal::ROUND_HALF_EVEN), bug3803)
- x = BigDecimal("0.5#{'0'*n}1")
- assert_equal(1, x.round(0, BigDecimal::ROUND_HALF_DOWN), bug3803)
- assert_equal(1, x.round(0, BigDecimal::ROUND_HALF_EVEN), bug3803)
- x = BigDecimal("-0.5#{'0'*n}1")
- assert_equal(-1, x.round(0, BigDecimal::ROUND_HALF_DOWN), bug3803)
- assert_equal(-1, x.round(0, BigDecimal::ROUND_HALF_EVEN), bug3803)
- end
-
- assert_instance_of(Integer, x.round)
- assert_instance_of(Integer, x.round(0))
- assert_instance_of(Integer, x.round(-1))
- assert_instance_of(BigDecimal, x.round(1))
- end
-
- def test_round_half_even
- assert_equal(BigDecimal('12.0'), BigDecimal('12.5').round(half: :even))
- assert_equal(BigDecimal('14.0'), BigDecimal('13.5').round(half: :even))
-
- assert_equal(BigDecimal('2.2'), BigDecimal('2.15').round(1, half: :even))
- assert_equal(BigDecimal('2.2'), BigDecimal('2.25').round(1, half: :even))
- assert_equal(BigDecimal('2.4'), BigDecimal('2.35').round(1, half: :even))
-
- assert_equal(BigDecimal('-2.2'), BigDecimal('-2.15').round(1, half: :even))
- assert_equal(BigDecimal('-2.2'), BigDecimal('-2.25').round(1, half: :even))
- assert_equal(BigDecimal('-2.4'), BigDecimal('-2.35').round(1, half: :even))
-
- assert_equal(BigDecimal('7.1364'), BigDecimal('7.13645').round(4, half: :even))
- assert_equal(BigDecimal('7.1365'), BigDecimal('7.1364501').round(4, half: :even))
- assert_equal(BigDecimal('7.1364'), BigDecimal('7.1364499').round(4, half: :even))
-
- assert_equal(BigDecimal('-7.1364'), BigDecimal('-7.13645').round(4, half: :even))
- assert_equal(BigDecimal('-7.1365'), BigDecimal('-7.1364501').round(4, half: :even))
- assert_equal(BigDecimal('-7.1364'), BigDecimal('-7.1364499').round(4, half: :even))
- end
-
- def test_round_half_up
- assert_equal(BigDecimal('13.0'), BigDecimal('12.5').round(half: :up))
- assert_equal(BigDecimal('14.0'), BigDecimal('13.5').round(half: :up))
-
- assert_equal(BigDecimal('2.2'), BigDecimal('2.15').round(1, half: :up))
- assert_equal(BigDecimal('2.3'), BigDecimal('2.25').round(1, half: :up))
- assert_equal(BigDecimal('2.4'), BigDecimal('2.35').round(1, half: :up))
-
- assert_equal(BigDecimal('-2.2'), BigDecimal('-2.15').round(1, half: :up))
- assert_equal(BigDecimal('-2.3'), BigDecimal('-2.25').round(1, half: :up))
- assert_equal(BigDecimal('-2.4'), BigDecimal('-2.35').round(1, half: :up))
-
- assert_equal(BigDecimal('7.1365'), BigDecimal('7.13645').round(4, half: :up))
- assert_equal(BigDecimal('7.1365'), BigDecimal('7.1364501').round(4, half: :up))
- assert_equal(BigDecimal('7.1364'), BigDecimal('7.1364499').round(4, half: :up))
-
- assert_equal(BigDecimal('-7.1365'), BigDecimal('-7.13645').round(4, half: :up))
- assert_equal(BigDecimal('-7.1365'), BigDecimal('-7.1364501').round(4, half: :up))
- assert_equal(BigDecimal('-7.1364'), BigDecimal('-7.1364499').round(4, half: :up))
- end
-
- def test_round_half_down
- assert_equal(BigDecimal('12.0'), BigDecimal('12.5').round(half: :down))
- assert_equal(BigDecimal('13.0'), BigDecimal('13.5').round(half: :down))
-
- assert_equal(BigDecimal('2.1'), BigDecimal('2.15').round(1, half: :down))
- assert_equal(BigDecimal('2.2'), BigDecimal('2.25').round(1, half: :down))
- assert_equal(BigDecimal('2.3'), BigDecimal('2.35').round(1, half: :down))
-
- assert_equal(BigDecimal('-2.1'), BigDecimal('-2.15').round(1, half: :down))
- assert_equal(BigDecimal('-2.2'), BigDecimal('-2.25').round(1, half: :down))
- assert_equal(BigDecimal('-2.3'), BigDecimal('-2.35').round(1, half: :down))
-
- assert_equal(BigDecimal('7.1364'), BigDecimal('7.13645').round(4, half: :down))
- assert_equal(BigDecimal('7.1365'), BigDecimal('7.1364501').round(4, half: :down))
- assert_equal(BigDecimal('7.1364'), BigDecimal('7.1364499').round(4, half: :down))
-
- assert_equal(BigDecimal('-7.1364'), BigDecimal('-7.13645').round(4, half: :down))
- assert_equal(BigDecimal('-7.1365'), BigDecimal('-7.1364501').round(4, half: :down))
- assert_equal(BigDecimal('-7.1364'), BigDecimal('-7.1364499').round(4, half: :down))
- end
-
- def test_round_half_nil
- x = BigDecimal("2.5")
-
- BigDecimal.save_rounding_mode do
- BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_UP)
- assert_equal(3, x.round(0, half: nil))
- end
-
- BigDecimal.save_rounding_mode do
- BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_DOWN)
- assert_equal(2, x.round(0, half: nil))
- end
-
- BigDecimal.save_rounding_mode do
- BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_HALF_UP)
- assert_equal(3, x.round(0, half: nil))
- end
-
- BigDecimal.save_rounding_mode do
- BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_HALF_DOWN)
- assert_equal(2, x.round(0, half: nil))
- end
-
- BigDecimal.save_rounding_mode do
- BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_HALF_EVEN)
- assert_equal(2, x.round(0, half: nil))
- end
-
- BigDecimal.save_rounding_mode do
- BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_CEILING)
- assert_equal(3, x.round(0, half: nil))
- end
-
- BigDecimal.save_rounding_mode do
- BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_FLOOR)
- assert_equal(2, x.round(0, half: nil))
- end
- end
-
- def test_round_half_invalid_option
- assert_raise_with_message(ArgumentError, "invalid rounding mode: invalid") { BigDecimal('12.5').round(half: :invalid) }
- assert_raise_with_message(ArgumentError, "invalid rounding mode: invalid") { BigDecimal('2.15').round(1, half: :invalid) }
- end
-
- def test_truncate
- assert_equal(3, BigDecimal("3.14159").truncate)
- assert_equal(8, BigDecimal("8.7").truncate)
- assert_equal(3.141, BigDecimal("3.14159").truncate(3))
- assert_equal(13300.0, BigDecimal("13345.234").truncate(-2))
-
- assert_equal(-3, BigDecimal("-3.14159").truncate)
- assert_equal(-8, BigDecimal("-8.7").truncate)
- assert_equal(-3.141, BigDecimal("-3.14159").truncate(3))
- assert_equal(-13300.0, BigDecimal("-13345.234").truncate(-2))
- end
-
- def test_floor
- assert_equal(3, BigDecimal("3.14159").floor)
- assert_equal(-10, BigDecimal("-9.1").floor)
- assert_equal(3.141, BigDecimal("3.14159").floor(3))
- assert_equal(13300.0, BigDecimal("13345.234").floor(-2))
- end
-
- def test_ceil
- assert_equal(4, BigDecimal("3.14159").ceil)
- assert_equal(-9, BigDecimal("-9.1").ceil)
- assert_equal(3.142, BigDecimal("3.14159").ceil(3))
- assert_equal(13400.0, BigDecimal("13345.234").ceil(-2))
- end
-
- def test_to_s
- assert_equal('-123.45678 90123 45678 9', BigDecimal('-123.45678901234567890').to_s('5F'))
- assert_equal('+123.45678901 23456789', BigDecimal('123.45678901234567890').to_s('+8F'))
- assert_equal(' 123.4567890123456789', BigDecimal('123.45678901234567890').to_s(' F'))
- assert_equal('0.1234567890123456789e3', BigDecimal('123.45678901234567890').to_s)
- assert_equal('0.12345 67890 12345 6789e3', BigDecimal('123.45678901234567890').to_s(5))
- end
-
- def test_split
- x = BigDecimal('-123.45678901234567890')
- assert_equal([-1, "1234567890123456789", 10, 3], x.split)
- assert_equal([1, "0", 10, 0], BigDecimal("0").split)
- assert_equal([-1, "0", 10, 0], BigDecimal("-0").split)
-
- BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
- BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
- assert_equal([0, "NaN", 10, 0], BigDecimal("NaN").split)
- assert_equal([1, "Infinity", 10, 0], BigDecimal("Infinity").split)
- assert_equal([-1, "Infinity", 10, 0], BigDecimal("-Infinity").split)
- end
-
- def test_exponent
- x = BigDecimal('-123.45678901234567890')
- assert_equal(3, x.exponent)
- end
-
- def test_inspect
- assert_equal("0.123456789012e0", BigDecimal("0.123456789012").inspect)
- assert_equal("0.123456789012e4", BigDecimal("1234.56789012").inspect)
- assert_equal("0.123456789012e-4", BigDecimal("0.0000123456789012").inspect)
- end
-
- def test_power
- assert_nothing_raised(TypeError, '[ruby-core:47632]') do
- 1000.times { BigDecimal('1001.10')**0.75 }
- end
- end
-
- def test_power_with_nil
- assert_raise(TypeError) do
- BigDecimal(3) ** nil
- end
- end
-
- def test_power_of_nan
- BigDecimal.save_exception_mode do
- BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
- assert_nan(BigDecimal::NAN ** 0)
- assert_nan(BigDecimal::NAN ** 1)
- assert_nan(BigDecimal::NAN ** 42)
- assert_nan(BigDecimal::NAN ** -42)
- assert_nan(BigDecimal::NAN ** 42.0)
- assert_nan(BigDecimal::NAN ** -42.0)
- assert_nan(BigDecimal::NAN ** BigDecimal(42))
- assert_nan(BigDecimal::NAN ** BigDecimal(-42))
- assert_nan(BigDecimal::NAN ** BigDecimal::INFINITY)
- BigDecimal.save_exception_mode do
- BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false)
- assert_nan(BigDecimal::NAN ** (-BigDecimal::INFINITY))
- end
- end
- end
-
- def test_power_with_Bignum
- BigDecimal.save_exception_mode do
- BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false)
- assert_equal(0, BigDecimal(0) ** (2**100))
-
- assert_positive_infinite(BigDecimal(0) ** -(2**100))
- assert_positive_infinite((-BigDecimal(0)) ** -(2**100))
- assert_negative_infinite((-BigDecimal(0)) ** -(2**100 + 1))
-
- assert_equal(1, BigDecimal(1) ** (2**100))
-
- assert_positive_infinite(BigDecimal(3) ** (2**100))
- assert_positive_zero(BigDecimal(3) ** (-2**100))
-
- assert_negative_infinite(BigDecimal(-3) ** (2**100))
- assert_positive_infinite(BigDecimal(-3) ** (2**100 + 1))
- assert_negative_zero(BigDecimal(-3) ** (-2**100))
- assert_positive_zero(BigDecimal(-3) ** (-2**100 - 1))
-
- assert_positive_zero(BigDecimal(0.5, Float::DIG) ** (2**100))
- assert_positive_infinite(BigDecimal(0.5, Float::DIG) ** (-2**100))
-
- assert_negative_zero(BigDecimal(-0.5, Float::DIG) ** (2**100))
- assert_positive_zero(BigDecimal(-0.5, Float::DIG) ** (2**100 - 1))
- assert_negative_infinite(BigDecimal(-0.5, Float::DIG) ** (-2**100))
- assert_positive_infinite(BigDecimal(-0.5, Float::DIG) ** (-2**100 - 1))
- end
- end
-
- def test_power_with_BigDecimal
- assert_nothing_raised do
- assert_in_delta(3 ** 3, BigDecimal(3) ** BigDecimal(3))
- end
- end
-
- def test_power_of_finite_with_zero
- x = BigDecimal(1)
- assert_equal(1, x ** 0)
- assert_equal(1, x ** 0.quo(1))
- assert_equal(1, x ** 0.0)
- assert_equal(1, x ** BigDecimal(0))
-
- x = BigDecimal(42)
- assert_equal(1, x ** 0)
- assert_equal(1, x ** 0.quo(1))
- assert_equal(1, x ** 0.0)
- assert_equal(1, x ** BigDecimal(0))
-
- x = BigDecimal(-42)
- assert_equal(1, x ** 0)
- assert_equal(1, x ** 0.quo(1))
- assert_equal(1, x ** 0.0)
- assert_equal(1, x ** BigDecimal(0))
- end
-
- def test_power_of_three
- x = BigDecimal(3)
- assert_equal(81, x ** 4)
- assert_equal(1.quo(81), x ** -4)
- assert_in_delta(1.0/81, x ** -4)
- end
-
- def test_power_of_zero
- zero = BigDecimal(0)
- assert_equal(0, zero ** 4)
- assert_equal(0, zero ** 4.quo(1))
- assert_equal(0, zero ** 4.0)
- assert_equal(0, zero ** BigDecimal(4))
- assert_equal(1, zero ** 0)
- assert_equal(1, zero ** 0.quo(1))
- assert_equal(1, zero ** 0.0)
- assert_equal(1, zero ** BigDecimal(0))
- BigDecimal.save_exception_mode do
- BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false)
- BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
- assert_positive_infinite(zero ** -1)
- assert_positive_infinite(zero ** -1.quo(1))
- assert_positive_infinite(zero ** -1.0)
- assert_positive_infinite(zero ** BigDecimal(-1))
-
- m_zero = BigDecimal("-0")
- assert_negative_infinite(m_zero ** -1)
- assert_negative_infinite(m_zero ** -1.quo(1))
- assert_negative_infinite(m_zero ** -1.0)
- assert_negative_infinite(m_zero ** BigDecimal(-1))
- assert_positive_infinite(m_zero ** -2)
- assert_positive_infinite(m_zero ** -2.quo(1))
- assert_positive_infinite(m_zero ** -2.0)
- assert_positive_infinite(m_zero ** BigDecimal(-2))
- end
- end
-
- def test_power_of_positive_infinity
- BigDecimal.save_exception_mode do
- BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
- assert_positive_infinite(BigDecimal::INFINITY ** 3)
- assert_positive_infinite(BigDecimal::INFINITY ** 3.quo(1))
- assert_positive_infinite(BigDecimal::INFINITY ** 3.0)
- assert_positive_infinite(BigDecimal::INFINITY ** BigDecimal(3))
- assert_positive_infinite(BigDecimal::INFINITY ** 2)
- assert_positive_infinite(BigDecimal::INFINITY ** 2.quo(1))
- assert_positive_infinite(BigDecimal::INFINITY ** 2.0)
- assert_positive_infinite(BigDecimal::INFINITY ** BigDecimal(2))
- assert_positive_infinite(BigDecimal::INFINITY ** 1)
- assert_positive_infinite(BigDecimal::INFINITY ** 1.quo(1))
- assert_positive_infinite(BigDecimal::INFINITY ** 1.0)
- assert_positive_infinite(BigDecimal::INFINITY ** BigDecimal(1))
- assert_equal(1, BigDecimal::INFINITY ** 0)
- assert_equal(1, BigDecimal::INFINITY ** 0.quo(1))
- assert_equal(1, BigDecimal::INFINITY ** 0.0)
- assert_equal(1, BigDecimal::INFINITY ** BigDecimal(0))
- assert_positive_zero(BigDecimal::INFINITY ** -1)
- assert_positive_zero(BigDecimal::INFINITY ** -1.quo(1))
- assert_positive_zero(BigDecimal::INFINITY ** -1.0)
- assert_positive_zero(BigDecimal::INFINITY ** BigDecimal(-1))
- assert_positive_zero(BigDecimal::INFINITY ** -2)
- assert_positive_zero(BigDecimal::INFINITY ** -2.0)
- assert_positive_zero(BigDecimal::INFINITY ** BigDecimal(-2))
- end
- end
-
- def test_power_of_negative_infinity
- BigDecimal.save_exception_mode do
- BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
- assert_negative_infinite((-BigDecimal::INFINITY) ** 3)
- assert_negative_infinite((-BigDecimal::INFINITY) ** 3.quo(1))
- assert_negative_infinite((-BigDecimal::INFINITY) ** 3.0)
- assert_negative_infinite((-BigDecimal::INFINITY) ** BigDecimal(3))
- assert_positive_infinite((-BigDecimal::INFINITY) ** 2)
- assert_positive_infinite((-BigDecimal::INFINITY) ** 2.quo(1))
- assert_positive_infinite((-BigDecimal::INFINITY) ** 2.0)
- assert_positive_infinite((-BigDecimal::INFINITY) ** BigDecimal(2))
- assert_negative_infinite((-BigDecimal::INFINITY) ** 1)
- assert_negative_infinite((-BigDecimal::INFINITY) ** 1.quo(1))
- assert_negative_infinite((-BigDecimal::INFINITY) ** 1.0)
- assert_negative_infinite((-BigDecimal::INFINITY) ** BigDecimal(1))
- assert_equal(1, (-BigDecimal::INFINITY) ** 0)
- assert_equal(1, (-BigDecimal::INFINITY) ** 0.quo(1))
- assert_equal(1, (-BigDecimal::INFINITY) ** 0.0)
- assert_equal(1, (-BigDecimal::INFINITY) ** BigDecimal(0))
- assert_negative_zero((-BigDecimal::INFINITY) ** -1)
- assert_negative_zero((-BigDecimal::INFINITY) ** -1.quo(1))
- assert_negative_zero((-BigDecimal::INFINITY) ** -1.0)
- assert_negative_zero((-BigDecimal::INFINITY) ** BigDecimal(-1))
- assert_positive_zero((-BigDecimal::INFINITY) ** -2)
- assert_positive_zero((-BigDecimal::INFINITY) ** -2.quo(1))
- assert_positive_zero((-BigDecimal::INFINITY) ** -2.0)
- assert_positive_zero((-BigDecimal::INFINITY) ** BigDecimal(-2))
- end
- end
-
- def test_power_without_prec
- pi = BigDecimal("3.14159265358979323846264338327950288419716939937511")
- e = BigDecimal("2.71828182845904523536028747135266249775724709369996")
- pow = BigDecimal("0.2245915771836104547342715220454373502758931513399678438732330680117143493477164265678321738086407229773690574073268002736527e2")
- assert_equal(pow, pi.power(e))
-
- n = BigDecimal("2222")
- assert_equal(BigDecimal("0.5171353084572525892492416e12"), (n ** 3.5))
- assert_equal(BigDecimal("0.517135308457252592e12"), (n ** 3.5r))
- assert_equal(BigDecimal("0.517135308457252589249241582e12"), (n ** BigDecimal("3.5",15)))
- end
-
- def test_power_with_prec
- pi = BigDecimal("3.14159265358979323846264338327950288419716939937511")
- e = BigDecimal("2.71828182845904523536028747135266249775724709369996")
- pow = BigDecimal("22.459157718361045473")
- assert_equal(pow, pi.power(e, 20))
-
- b = BigDecimal('1.034482758620689655172413793103448275862068965517241379310344827586206896551724')
- assert_equal(BigDecimal('0.114523E1'), b.power(4, 5), '[Bug #8818] [ruby-core:56802]')
- end
-
- def test_limit
- BigDecimal.save_limit do
- BigDecimal.limit(1)
- x = BigDecimal("3")
- assert_equal(90, x ** 4) # OK? must it be 80?
- # 3 * 3 * 3 * 3 = 10 * 3 * 3 = 30 * 3 = 90 ???
- assert_raise(ArgumentError) { BigDecimal.limit(-1) }
-
- bug7458 = '[ruby-core:50269] [#7458]'
- one = BigDecimal('1')
- epsilon = BigDecimal('0.7E-18')
-
- BigDecimal.limit(0)
- assert_equal(BigDecimal("1.0000000000000000007"), one + epsilon, "limit(0) #{bug7458}")
-
- 1.upto(18) do |lim|
- BigDecimal.limit(lim)
- assert_equal(BigDecimal("1.0"), one + epsilon, "limit(#{lim}) #{bug7458}")
- end
-
- BigDecimal.limit(19)
- assert_equal(BigDecimal("1.000000000000000001"), one + epsilon, "limit(19) #{bug7458}")
-
- BigDecimal.limit(20)
- assert_equal(BigDecimal("1.0000000000000000007"), one + epsilon, "limit(20) #{bug7458}")
- end
- end
-
- def test_sign
- BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
- BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
- BigDecimal.mode(BigDecimal::EXCEPTION_ZERODIVIDE, false)
-
- assert_equal(BigDecimal::SIGN_POSITIVE_ZERO, BigDecimal("0").sign)
- assert_equal(BigDecimal::SIGN_NEGATIVE_ZERO, BigDecimal("-0").sign)
- assert_equal(BigDecimal::SIGN_POSITIVE_FINITE, BigDecimal("1").sign)
- assert_equal(BigDecimal::SIGN_NEGATIVE_FINITE, BigDecimal("-1").sign)
- assert_equal(BigDecimal::SIGN_POSITIVE_INFINITE, (BigDecimal("1") / 0).sign)
- assert_equal(BigDecimal::SIGN_NEGATIVE_INFINITE, (BigDecimal("-1") / 0).sign)
- assert_equal(BigDecimal::SIGN_NaN, (BigDecimal("0") / 0).sign)
- end
-
- def test_inf
- BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
- BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
- inf = BigDecimal("Infinity")
-
- assert_equal(inf, inf + inf)
- assert_nan((inf + (-inf)))
- assert_nan((inf - inf))
- assert_equal(inf, inf - (-inf))
- assert_equal(inf, inf * inf)
- assert_nan((inf / inf))
-
- assert_equal(inf, inf + 1)
- assert_equal(inf, inf - 1)
- assert_equal(inf, inf * 1)
- assert_nan((inf * 0))
- assert_equal(inf, inf / 1)
-
- assert_equal(inf, 1 + inf)
- assert_equal(-inf, 1 - inf)
- assert_equal(inf, 1 * inf)
- assert_equal(-inf, -1 * inf)
- assert_nan((0 * inf))
- assert_equal(BigDecimal::SIGN_POSITIVE_ZERO, (1 / inf).sign)
- assert_equal(BigDecimal::SIGN_NEGATIVE_ZERO, (-1 / inf).sign)
- end
-
- def assert_equal_us_ascii_string(a, b)
- assert_equal(a, b)
- assert_equal(Encoding::US_ASCII, b.encoding)
- end
-
- def test_to_special_string
- BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
- BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
- nan = BigDecimal("NaN")
- assert_equal_us_ascii_string("NaN", nan.to_s)
- inf = BigDecimal("Infinity")
- assert_equal_us_ascii_string("Infinity", inf.to_s)
- assert_equal_us_ascii_string(" Infinity", inf.to_s(" "))
- assert_equal_us_ascii_string("+Infinity", inf.to_s("+"))
- assert_equal_us_ascii_string("-Infinity", (-inf).to_s)
- pzero = BigDecimal("0")
- assert_equal_us_ascii_string("0.0", pzero.to_s)
- assert_equal_us_ascii_string(" 0.0", pzero.to_s(" "))
- assert_equal_us_ascii_string("+0.0", pzero.to_s("+"))
- assert_equal_us_ascii_string("-0.0", (-pzero).to_s)
- end
-
- def test_to_string
- assert_equal_us_ascii_string("0.01", BigDecimal("0.01").to_s("F"))
- s = "0." + "0" * 100 + "1"
- assert_equal_us_ascii_string(s, BigDecimal(s).to_s("F"))
- s = "1" + "0" * 100 + ".0"
- assert_equal_us_ascii_string(s, BigDecimal(s).to_s("F"))
- end
-
- def test_ctov
- assert_equal(0.1, BigDecimal("1E-1"))
- assert_equal(10, BigDecimal("1E+1"))
- assert_equal(1, BigDecimal("+1"))
- BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
-
- assert_equal(BigDecimal::SIGN_POSITIVE_INFINITE, BigDecimal("1E1" + "0" * 10000).sign)
- assert_equal(BigDecimal::SIGN_NEGATIVE_INFINITE, BigDecimal("-1E1" + "0" * 10000).sign)
- assert_equal(BigDecimal::SIGN_POSITIVE_ZERO, BigDecimal("1E-1" + "0" * 10000).sign)
- assert_equal(BigDecimal::SIGN_NEGATIVE_ZERO, BigDecimal("-1E-1" + "0" * 10000).sign)
- end
-
- def test_split_under_gc_stress
- bug3258 = '[ruby-dev:41213]'
- expect = 10.upto(20).map{|i|[1, "1", 10, i+1].inspect}
- assert_in_out_err(%w[-rbigdecimal --disable-gems], <<-EOS, expect, [], bug3258)
- GC.stress = true
- 10.upto(20) do |i|
- p BigDecimal("1"+"0"*i).split
- end
- EOS
- end
-
- def test_coerce_under_gc_stress
- assert_in_out_err(%w[-rbigdecimal --disable-gems], <<-EOS, [], [])
- expect = ":too_long_to_embed_as_string can't be coerced into BigDecimal"
- b = BigDecimal("1")
- GC.stress = true
- 10.times do
- begin
- b.coerce(:too_long_to_embed_as_string)
- rescue => e
- raise unless e.is_a?(TypeError)
- raise "'\#{expect}' is expected, but '\#{e.message}'" unless e.message == expect
- end
- end
- EOS
- end
-
- def test_INFINITY
- assert_positive_infinite(BigDecimal::INFINITY)
- end
-
- def test_NAN
- assert_nan(BigDecimal::NAN)
- end
-
- def test_exp_with_zero_precision
- assert_raise(ArgumentError) do
- BigMath.exp(1, 0)
- end
- end
-
- def test_exp_with_negative_precision
- assert_raise(ArgumentError) do
- BigMath.exp(1, -42)
- end
- end
-
- def test_exp_with_complex
- assert_raise(ArgumentError) do
- BigMath.exp(Complex(1, 2), 20)
- end
- end
-
- def test_exp_with_negative
- x = BigDecimal(-1)
- y = BigMath.exp(x, 20)
- assert_equal(y, BigMath.exp(-1, 20))
- assert_equal(BigDecimal(-1), x)
- end
-
- def test_exp_with_negative_infinite
- BigDecimal.save_exception_mode do
- BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false)
- assert_equal(0, BigMath.exp(-BigDecimal::INFINITY, 20))
- end
- end
-
- def test_exp_with_positive_infinite
- BigDecimal.save_exception_mode do
- BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false)
- assert(BigMath.exp(BigDecimal::INFINITY, 20) > 0)
- assert_positive_infinite(BigMath.exp(BigDecimal::INFINITY, 20))
- end
- end
-
- def test_exp_with_nan
- BigDecimal.save_exception_mode do
- BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
- assert_nan(BigMath.exp(BigDecimal::NAN, 20))
- end
- end
-
- def test_exp_with_1
- assert_in_epsilon(Math::E, BigMath.exp(1, 20))
- end
-
- def test_BigMath_exp
- prec = 20
- assert_in_epsilon(Math.exp(20), BigMath.exp(BigDecimal("20"), prec))
- assert_in_epsilon(Math.exp(40), BigMath.exp(BigDecimal("40"), prec))
- assert_in_epsilon(Math.exp(-20), BigMath.exp(BigDecimal("-20"), prec))
- assert_in_epsilon(Math.exp(-40), BigMath.exp(BigDecimal("-40"), prec))
- end
-
- def test_BigMath_exp_with_float
- prec = 20
- assert_in_epsilon(Math.exp(20), BigMath.exp(20.0, prec))
- assert_in_epsilon(Math.exp(40), BigMath.exp(40.0, prec))
- assert_in_epsilon(Math.exp(-20), BigMath.exp(-20.0, prec))
- assert_in_epsilon(Math.exp(-40), BigMath.exp(-40.0, prec))
- end
-
- def test_BigMath_exp_with_fixnum
- prec = 20
- assert_in_epsilon(Math.exp(20), BigMath.exp(20, prec))
- assert_in_epsilon(Math.exp(40), BigMath.exp(40, prec))
- assert_in_epsilon(Math.exp(-20), BigMath.exp(-20, prec))
- assert_in_epsilon(Math.exp(-40), BigMath.exp(-40, prec))
- end
-
- def test_BigMath_exp_with_rational
- prec = 20
- assert_in_epsilon(Math.exp(20), BigMath.exp(Rational(40,2), prec))
- assert_in_epsilon(Math.exp(40), BigMath.exp(Rational(80,2), prec))
- assert_in_epsilon(Math.exp(-20), BigMath.exp(Rational(-40,2), prec))
- assert_in_epsilon(Math.exp(-40), BigMath.exp(Rational(-80,2), prec))
- end
-
- def test_BigMath_exp_under_gc_stress
- assert_in_out_err(%w[-rbigdecimal --disable-gems], <<-EOS, [], [])
- expect = ":too_long_to_embed_as_string can't be coerced into BigDecimal"
- 10.times do
- begin
- BigMath.exp(:too_long_to_embed_as_string, 6)
- rescue => e
- raise unless e.is_a?(ArgumentError)
- raise "'\#{expect}' is expected, but '\#{e.message}'" unless e.message == expect
- end
- end
- EOS
- end
-
- def test_BigMath_log_with_string
- assert_raise(ArgumentError) do
- BigMath.log("foo", 20)
- end
- end
-
- def test_BigMath_log_with_nil
- assert_raise(ArgumentError) do
- BigMath.log(nil, 20)
- end
- end
-
- def test_BigMath_log_with_non_integer_precision
- assert_raise(ArgumentError) do
- BigMath.log(1, 0.5)
- end
- end
-
- def test_BigMath_log_with_nil_precision
- assert_raise(ArgumentError) do
- BigMath.log(1, nil)
- end
- end
-
- def test_BigMath_log_with_complex
- assert_raise(Math::DomainError) do
- BigMath.log(Complex(1, 2), 20)
- end
- end
-
- def test_BigMath_log_with_zero_arg
- assert_raise(Math::DomainError) do
- BigMath.log(0, 20)
- end
- end
-
- def test_BigMath_log_with_negative_arg
- assert_raise(Math::DomainError) do
- BigMath.log(-1, 20)
- end
- end
-
- def test_BigMath_log_with_zero_precision
- assert_raise(ArgumentError) do
- BigMath.log(1, 0)
- end
- end
-
- def test_BigMath_log_with_negative_precision
- assert_raise(ArgumentError) do
- BigMath.log(1, -42)
- end
- end
-
- def test_BigMath_log_with_negative_infinite
- BigDecimal.save_exception_mode do
- BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false)
- assert_raise(Math::DomainError) do
- BigMath.log(-BigDecimal::INFINITY, 20)
- end
- end
- end
-
- def test_BigMath_log_with_positive_infinite
- BigDecimal.save_exception_mode do
- BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, false)
- assert(BigMath.log(BigDecimal::INFINITY, 20) > 0)
- assert_positive_infinite(BigMath.log(BigDecimal::INFINITY, 20))
- end
- end
-
- def test_BigMath_log_with_nan
- BigDecimal.save_exception_mode do
- BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
- assert_nan(BigMath.log(BigDecimal::NAN, 20))
- end
- end
-
- def test_BigMath_log_with_float_nan
- BigDecimal.save_exception_mode do
- BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
- assert_nan(BigMath.log(Float::NAN, 20))
- end
- end
-
- def test_BigMath_log_with_1
- assert_in_delta(0.0, BigMath.log(1, 20))
- assert_in_delta(0.0, BigMath.log(1.0, 20))
- assert_in_delta(0.0, BigMath.log(BigDecimal(1), 20))
- end
-
- def test_BigMath_log_with_exp_1
- assert_in_delta(1.0, BigMath.log(BigMath.E(10), 10))
- end
-
- def test_BigMath_log_with_2
- assert_in_delta(Math.log(2), BigMath.log(2, 20))
- assert_in_delta(Math.log(2), BigMath.log(2.0, 20))
- assert_in_delta(Math.log(2), BigMath.log(BigDecimal(2), 20))
- end
-
- def test_BigMath_log_with_square_of_E
- assert_in_delta(2, BigMath.log(BigMath.E(20)**2, 20))
- end
-
- def test_BigMath_log_with_high_precision_case
- e = BigDecimal('2.71828182845904523536028747135266249775724709369996')
- e_3 = e.mult(e, 50).mult(e, 50)
- log_3 = BigMath.log(e_3, 50)
- assert_in_delta(3, log_3, 0.0000000000_0000000000_0000000000_0000000000_0000000001)
- end
-
- def test_BigMath_log_with_42
- assert_in_delta(Math.log(42), BigMath.log(42, 20))
- assert_in_delta(Math.log(42), BigMath.log(42.0, 20))
- assert_in_delta(Math.log(42), BigMath.log(BigDecimal(42), 20))
- end
-
- def test_BigMath_log_with_101
- # this is mainly a performance test (should be very fast, not the 0.3 s)
- assert_in_delta(Math.log(101), BigMath.log(101, 20), 1E-15)
- end
-
- def test_BigMath_log_with_reciprocal_of_42
- assert_in_delta(Math.log(1e-42), BigMath.log(1e-42, 20))
- assert_in_delta(Math.log(1e-42), BigMath.log(BigDecimal("1e-42"), 20))
- end
-
- def test_BigMath_log_under_gc_stress
- assert_in_out_err(%w[-rbigdecimal --disable-gems], <<-EOS, [], [])
- expect = ":too_long_to_embed_as_string can't be coerced into BigDecimal"
- 10.times do
- begin
- BigMath.log(:too_long_to_embed_as_string, 6)
- rescue => e
- raise unless e.is_a?(ArgumentError)
- raise "'\#{expect}' is expected, but '\#{e.message}'" unless e.message == expect
- end
- end
- EOS
- end
-
- def test_frozen_p
- x = BigDecimal(1)
- assert(x.frozen?)
- assert((x + x).frozen?)
- end
-
- def test_clone
- assert_warning(/^$/) do
- x = BigDecimal(0)
- assert_same(x, x.clone)
- end
- end
-
- def test_dup
- assert_warning(/^$/) do
- [1, -1, 2**100, -2**100].each do |i|
- x = BigDecimal(i)
- assert_same(x, x.dup)
- end
- end
- end
-
- def test_new_subclass
- c = Class.new(BigDecimal)
- assert_raise_with_message(NoMethodError, /undefined method `new'/) { c.new(1) }
- end
-
- def test_to_d
- bug6093 = '[ruby-core:42969]'
- code = "exit(BigDecimal('10.0') == 10.0.to_d)"
- assert_ruby_status(%w[-rbigdecimal -rbigdecimal/util -rmathn -], code, bug6093)
- end if RUBY_VERSION < '2.5' # mathn was removed from Ruby 2.5
-
- def test_bug6406
- assert_in_out_err(%w[-rbigdecimal --disable-gems], <<-EOS, [], [])
- Thread.current.keys.to_s
- EOS
- end
-
- def test_precision_only_integer
- assert_equal(0, BigDecimal(0).precision)
- assert_equal(1, BigDecimal(1).precision)
- assert_equal(1, BigDecimal(-1).precision)
- assert_equal(2, BigDecimal(10).precision)
- assert_equal(2, BigDecimal(-10).precision)
- assert_equal(9, BigDecimal(100_000_000).precision)
- assert_equal(9, BigDecimal(-100_000_000).precision)
- assert_equal(12, BigDecimal(100_000_000_000).precision)
- assert_equal(12, BigDecimal(-100_000_000_000).precision)
- assert_equal(21, BigDecimal(100_000_000_000_000_000_000).precision)
- assert_equal(21, BigDecimal(-100_000_000_000_000_000_000).precision)
- assert_equal(103, BigDecimal("111e100").precision)
- assert_equal(103, BigDecimal("-111e100").precision)
- end
-
- def test_precision_only_fraction
- assert_equal(1, BigDecimal("0.1").precision)
- assert_equal(1, BigDecimal("-0.1").precision)
- assert_equal(1, BigDecimal("0.01").precision)
- assert_equal(1, BigDecimal("-0.01").precision)
- assert_equal(2, BigDecimal("0.11").precision)
- assert_equal(2, BigDecimal("-0.11").precision)
- assert_equal(21, BigDecimal("0.000_000_000_000_000_000_001").precision)
- assert_equal(21, BigDecimal("-0.000_000_000_000_000_000_001").precision)
- assert_equal(100, BigDecimal("111e-100").precision)
- assert_equal(100, BigDecimal("-111e-100").precision)
- end
-
- def test_precision_full
- assert_equal(1, BigDecimal("0.1").precision)
- assert_equal(1, BigDecimal("-0.1").precision)
- assert_equal(1, BigDecimal("0.01").precision)
- assert_equal(1, BigDecimal("-0.01").precision)
- assert_equal(2, BigDecimal("0.11").precision)
- assert_equal(2, BigDecimal("-0.11").precision)
- assert_equal(5, BigDecimal("11111e-2").precision)
- assert_equal(5, BigDecimal("-11111e-2").precision)
- assert_equal(21, BigDecimal("100.000_000_000_000_000_001").precision)
- assert_equal(21, BigDecimal("-100.000_000_000_000_000_001").precision)
- end
-
- def test_precision_special
- BigDecimal.save_exception_mode do
- BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
- BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
-
- assert_equal(0, BigDecimal("Infinity").precision)
- assert_equal(0, BigDecimal("-Infinity").precision)
- assert_equal(0, BigDecimal("NaN").precision)
- end
- end
-
- def test_n_significant_digits_only_integer
- assert_equal(0, BigDecimal(0).n_significant_digits)
- assert_equal(1, BigDecimal(1).n_significant_digits)
- assert_equal(1, BigDecimal(-1).n_significant_digits)
- assert_equal(1, BigDecimal(10).n_significant_digits)
- assert_equal(1, BigDecimal(-10).n_significant_digits)
- assert_equal(3, BigDecimal(101).n_significant_digits)
- assert_equal(3, BigDecimal(-101).n_significant_digits)
- assert_equal(1, BigDecimal(100_000_000_000_000_000_000).n_significant_digits)
- assert_equal(1, BigDecimal(-100_000_000_000_000_000_000).n_significant_digits)
- assert_equal(21, BigDecimal(100_000_000_000_000_000_001).n_significant_digits)
- assert_equal(21, BigDecimal(-100_000_000_000_000_000_001).n_significant_digits)
- assert_equal(3, BigDecimal("111e100").n_significant_digits)
- assert_equal(3, BigDecimal("-111e100").n_significant_digits)
- end
-
- def test_n_significant_digits_only_fraction
- assert_equal(1, BigDecimal("0.1").n_significant_digits)
- assert_equal(1, BigDecimal("-0.1").n_significant_digits)
- assert_equal(1, BigDecimal("0.01").n_significant_digits)
- assert_equal(1, BigDecimal("-0.01").n_significant_digits)
- assert_equal(2, BigDecimal("0.11").n_significant_digits)
- assert_equal(2, BigDecimal("-0.11").n_significant_digits)
- assert_equal(1, BigDecimal("0.000_000_000_000_000_000_001").n_significant_digits)
- assert_equal(1, BigDecimal("-0.000_000_000_000_000_000_001").n_significant_digits)
- assert_equal(3, BigDecimal("111e-100").n_significant_digits)
- assert_equal(3, BigDecimal("-111e-100").n_significant_digits)
- end
-
- def test_n_significant_digits_full
- assert_equal(2, BigDecimal("1.1").n_significant_digits)
- assert_equal(2, BigDecimal("-1.1").n_significant_digits)
- assert_equal(3, BigDecimal("1.01").n_significant_digits)
- assert_equal(3, BigDecimal("-1.01").n_significant_digits)
- assert_equal(5, BigDecimal("11111e-2").n_significant_digits)
- assert_equal(5, BigDecimal("-11111e-2").n_significant_digits)
- assert_equal(21, BigDecimal("100.000_000_000_000_000_001").n_significant_digits)
- assert_equal(21, BigDecimal("-100.000_000_000_000_000_001").n_significant_digits)
- end
-
- def test_n_significant_digits_special
- BigDecimal.save_exception_mode do
- BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false)
- BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false)
-
- assert_equal(0, BigDecimal("Infinity").n_significant_digits)
- assert_equal(0, BigDecimal("-Infinity").n_significant_digits)
- assert_equal(0, BigDecimal("NaN").n_significant_digits)
- end
- end
-
- def test_initialize_copy_dup_clone_frozen_error
- bd = BigDecimal(1)
- bd2 = BigDecimal(2)
- err = RUBY_VERSION >= '2.5' ? FrozenError : TypeError
- assert_raise(err) { bd.send(:initialize_copy, bd2) }
- assert_raise(err) { bd.send(:initialize_clone, bd2) }
- assert_raise(err) { bd.send(:initialize_dup, bd2) }
- end
-
- def assert_no_memory_leak(code, *rest, **opt)
- code = "8.times {20_000.times {begin #{code}; rescue NoMemoryError; end}; GC.start}"
- super(["-rbigdecimal"],
- "b = BigDecimal('10'); b.nil?; " \
- "GC.add_stress_to_class(BigDecimal); "\
- "#{code}", code, *rest, rss: true, limit: 1.1, **opt)
- end
-
- if EnvUtil.gc_stress_to_class?
- def test_no_memory_leak_allocate
- assert_no_memory_leak("BigDecimal.allocate")
- end
-
- def test_no_memory_leak_initialize
- assert_no_memory_leak("BigDecimal()")
- end
-
- def test_no_memory_leak_BigDecimal
- assert_no_memory_leak("BigDecimal('10')")
- assert_no_memory_leak("BigDecimal(b)")
- end
-
- def test_no_memory_leak_create
- assert_no_memory_leak("b + 10")
- end
- end
-end
diff --git a/test/bigdecimal/test_bigdecimal_util.rb b/test/bigdecimal/test_bigdecimal_util.rb
deleted file mode 100644
index ffd4c5f679..0000000000
--- a/test/bigdecimal/test_bigdecimal_util.rb
+++ /dev/null
@@ -1,126 +0,0 @@
-# frozen_string_literal: false
-require_relative "helper"
-require 'bigdecimal/util'
-
-class TestBigDecimalUtil < Test::Unit::TestCase
- include TestBigDecimalBase
-
- def test_BigDecimal_to_d
- x = BigDecimal(1)
- assert_same(x, x.to_d)
- end
-
- def test_Integer_to_d
- assert_equal(BigDecimal(1), 1.to_d)
- assert_equal(BigDecimal(2<<100), (2<<100).to_d)
-
- assert(1.to_d.frozen?)
- end
-
- def test_Float_to_d_without_precision
- delta = 1.0/10**(Float::DIG+1)
- assert_in_delta(BigDecimal(0.5, 0), 0.5.to_d, delta)
- assert_in_delta(BigDecimal(355.0/113.0, 0), (355.0/113.0).to_d, delta)
-
- assert_equal(9.05, 9.05.to_d.to_f)
- assert_equal("9.05", 9.05.to_d.to_s('F'))
-
- assert_equal(Math::PI, Math::PI.to_d.to_f)
-
- bug9214 = '[ruby-core:58858]'
- assert_equal((-0.0).to_d.sign, -1, bug9214)
-
- assert_raise(TypeError) { 0.3.to_d(nil) }
- assert_raise(TypeError) { 0.3.to_d(false) }
-
- assert(1.1.to_d.frozen?)
-
- assert_equal(BigDecimal("999_999.9999"), 999_999.9999.to_d)
- end
-
- def test_Float_to_d_with_precision
- digits = 5
- delta = 1.0/10**(digits)
- assert_in_delta(BigDecimal(0.5, 5), 0.5.to_d(digits), delta)
- assert_in_delta(BigDecimal(355.0/113.0, 5), (355.0/113.0).to_d(digits), delta)
-
- bug9214 = '[ruby-core:58858]'
- assert_equal((-0.0).to_d(digits).sign, -1, bug9214)
-
- assert(1.1.to_d(digits).frozen?)
- end
-
- def test_Float_to_d_bug13331
- assert_equal(64.4.to_d,
- 1.to_d * 64.4,
- "[ruby-core:80234] [Bug #13331]")
-
- assert_equal((2*Math::PI).to_d,
- 2.to_d * Math::PI,
- "[ruby-core:80234] [Bug #13331]")
- end
-
- def test_Rational_to_d
- digits = 100
- delta = 1.0/10**(digits)
- assert_in_delta(BigDecimal(1.quo(2), digits), 1.quo(2).to_d(digits), delta)
- assert_in_delta(BigDecimal(355.quo(113), digits), 355.quo(113).to_d(digits), delta)
-
- assert(355.quo(113).to_d(digits).frozen?)
- end
-
- def test_Rational_to_d_with_zero_precision
- assert_equal(BigDecimal(355.quo(113), 0), 355.quo(113).to_d(0))
- end
-
- def test_Rational_to_d_with_negative_precision
- assert_raise(ArgumentError) { 355.quo(113).to_d(-42) }
- end
-
- def test_Complex_to_d
- BigDecimal.save_rounding_mode do
- BigDecimal.mode(BigDecimal::ROUND_MODE, BigDecimal::ROUND_HALF_EVEN)
-
- assert_equal(BigDecimal("1"), Complex(1, 0).to_d)
- assert_equal(BigDecimal("0.333333333333333333333"),
- Complex(1.quo(3), 0).to_d(21))
- assert_equal(BigDecimal("0.1234567"), Complex(0.1234567, 0).to_d)
- assert_equal(BigDecimal("0.1235"), Complex(0.1234567, 0).to_d(4))
-
- assert_raise_with_message(ArgumentError, "can't omit precision for a Rational.") { Complex(1.quo(3), 0).to_d }
-
- assert_raise_with_message(ArgumentError, "Unable to make a BigDecimal from non-zero imaginary number") { Complex(1, 1).to_d }
- end
- end
-
- def test_String_to_d
- assert_equal(BigDecimal('1'), "1__1_1".to_d)
- assert_equal(BigDecimal('2.5'), "2.5".to_d)
- assert_equal(BigDecimal('2.5'), "2.5 degrees".to_d)
- assert_equal(BigDecimal('2.5e1'), "2.5e1 degrees".to_d)
- assert_equal(BigDecimal('0'), "degrees 100.0".to_d)
- assert_equal(BigDecimal('0.125'), "0.1_2_5".to_d)
- assert_equal(BigDecimal('0.125'), "0.1_2_5__".to_d)
- assert_equal(BigDecimal('1'), "1_.125".to_d)
- assert_equal(BigDecimal('1'), "1._125".to_d)
- assert_equal(BigDecimal('0.1'), "0.1__2_5".to_d)
- assert_equal(BigDecimal('0.1'), "0.1_e10".to_d)
- assert_equal(BigDecimal('0.1'), "0.1e_10".to_d)
- assert_equal(BigDecimal('1'), "0.1e1__0".to_d)
- assert_equal(BigDecimal('1.2'), "1.2.3".to_d)
- assert_equal(BigDecimal('1'), "1.".to_d)
- assert_equal(BigDecimal('1'), "1e".to_d)
-
- assert("2.5".to_d.frozen?)
- end
-
- def test_invalid_String_to_d
- assert_equal("invalid".to_d, BigDecimal('0.0'))
- end
-
- def test_Nil_to_d
- assert_equal(nil.to_d, BigDecimal('0.0'))
-
- assert(nil.to_d)
- end
-end
diff --git a/test/bigdecimal/test_bigmath.rb b/test/bigdecimal/test_bigmath.rb
deleted file mode 100644
index 5bf1fbf318..0000000000
--- a/test/bigdecimal/test_bigmath.rb
+++ /dev/null
@@ -1,81 +0,0 @@
-# frozen_string_literal: false
-require_relative "helper"
-require "bigdecimal/math"
-
-class TestBigMath < Test::Unit::TestCase
- include TestBigDecimalBase
- include BigMath
- N = 20
- PINF = BigDecimal("+Infinity")
- MINF = BigDecimal("-Infinity")
- NAN = BigDecimal("NaN")
-
- def test_const
- assert_in_delta(Math::PI, PI(N))
- assert_in_delta(Math::E, E(N))
- end
-
- def test_sqrt
- assert_in_delta(2**0.5, sqrt(BigDecimal("2"), N))
- assert_equal(10, sqrt(BigDecimal("100"), N))
- assert_equal(0.0, sqrt(BigDecimal("0"), N))
- assert_equal(0.0, sqrt(BigDecimal("-0"), N))
- assert_raise(FloatDomainError) {sqrt(BigDecimal("-1.0"), N)}
- assert_raise(FloatDomainError) {sqrt(NAN, N)}
- assert_raise(FloatDomainError) {sqrt(PINF, N)}
- end
-
- def test_sin
- assert_in_delta(0.0, sin(BigDecimal("0.0"), N))
- assert_in_delta(Math.sqrt(2.0) / 2, sin(PI(N) / 4, N))
- assert_in_delta(1.0, sin(PI(N) / 2, N))
- assert_in_delta(0.0, sin(PI(N) * 2, N))
- assert_in_delta(0.0, sin(PI(N), N))
- assert_in_delta(-1.0, sin(PI(N) / -2, N))
- assert_in_delta(0.0, sin(PI(N) * -2, N))
- assert_in_delta(0.0, sin(-PI(N), N))
- assert_in_delta(0.0, sin(PI(N) * 21, N))
- assert_in_delta(0.0, sin(PI(N) * 30, N))
- assert_in_delta(-1.0, sin(PI(N) * BigDecimal("301.5"), N))
- end
-
- def test_cos
- assert_in_delta(1.0, cos(BigDecimal("0.0"), N))
- assert_in_delta(Math.sqrt(2.0) / 2, cos(PI(N) / 4, N))
- assert_in_delta(0.0, cos(PI(N) / 2, N))
- assert_in_delta(1.0, cos(PI(N) * 2, N))
- assert_in_delta(-1.0, cos(PI(N), N))
- assert_in_delta(0.0, cos(PI(N) / -2, N))
- assert_in_delta(1.0, cos(PI(N) * -2, N))
- assert_in_delta(-1.0, cos(-PI(N), N))
- assert_in_delta(-1.0, cos(PI(N) * 21, N))
- assert_in_delta(1.0, cos(PI(N) * 30, N))
- assert_in_delta(0.0, cos(PI(N) * BigDecimal("301.5"), N))
- end
-
- def test_atan
- assert_equal(0.0, atan(BigDecimal("0.0"), N))
- assert_in_delta(Math::PI/4, atan(BigDecimal("1.0"), N))
- assert_in_delta(Math::PI/6, atan(sqrt(BigDecimal("3.0"), N) / 3, N))
- assert_in_delta(Math::PI/2, atan(PINF, N))
- assert_equal(BigDecimal("0.823840753418636291769355073102514088959345624027952954058347023122539489"),
- atan(BigDecimal("1.08"), 72).round(72), '[ruby-dev:41257]')
- end
-
- def test_log
- assert_equal(0, BigMath.log(BigDecimal("1.0"), 10))
- assert_in_epsilon(Math.log(10)*1000, BigMath.log(BigDecimal("1e1000"), 10))
- assert_raise(Math::DomainError) {BigMath.log(BigDecimal("0"), 10)}
- assert_raise(Math::DomainError) {BigMath.log(BigDecimal("-1"), 10)}
- assert_separately(%w[-rbigdecimal], <<-SRC)
- begin
- x = BigMath.log(BigDecimal("1E19999999999999"), 10)
- rescue FloatDomainError
- else
- unless x.infinite?
- assert_in_epsilon(Math.log(10)*19999999999999, x)
- end
- end
- SRC
- end
-end
diff --git a/test/bigdecimal/test_ractor.rb b/test/bigdecimal/test_ractor.rb
deleted file mode 100644
index f78663f15e..0000000000
--- a/test/bigdecimal/test_ractor.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: true
-require_relative "helper"
-
-class TestBigDecimalRactor < Test::Unit::TestCase
- include TestBigDecimalBase
-
- def setup
- super
- skip unless defined? Ractor
- end
-
- def test_ractor_shareable
- assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
- begin;
- $VERBOSE = nil
- require "bigdecimal"
- r = Ractor.new BigDecimal(Math::PI, Float::DIG+1) do |pi|
- BigDecimal('2.0')*pi
- end
- assert_equal(2*Math::PI, r.take)
- end;
- end
-end
diff --git a/test/cgi/test_cgi_cookie.rb b/test/cgi/test_cgi_cookie.rb
index 115a57e4a1..eadae45313 100644
--- a/test/cgi/test_cgi_cookie.rb
+++ b/test/cgi/test_cgi_cookie.rb
@@ -60,6 +60,27 @@ class CGICookieTest < Test::Unit::TestCase
end
+ def test_cgi_cookie_new_with_domain
+ h = {'name'=>'name1', 'value'=>'value1'}
+ cookie = CGI::Cookie.new(h.merge('domain'=>'a.example.com'))
+ assert_equal('a.example.com', cookie.domain)
+
+ cookie = CGI::Cookie.new(h.merge('domain'=>'.example.com'))
+ assert_equal('.example.com', cookie.domain)
+
+ cookie = CGI::Cookie.new(h.merge('domain'=>'1.example.com'))
+ assert_equal('1.example.com', cookie.domain, 'enhanced by RFC 1123')
+
+ assert_raise(ArgumentError) {
+ CGI::Cookie.new(h.merge('domain'=>'-a.example.com'))
+ }
+
+ assert_raise(ArgumentError) {
+ CGI::Cookie.new(h.merge('domain'=>'a-.example.com'))
+ }
+ end
+
+
def test_cgi_cookie_scriptname
cookie = CGI::Cookie.new('name1', 'value1')
assert_equal('', cookie.path)
@@ -101,6 +122,11 @@ class CGICookieTest < Test::Unit::TestCase
end
end
+ def test_cgi_cookie_parse_not_decode_name
+ cookie_str = "%66oo=baz;foo=bar"
+ cookies = CGI::Cookie.parse(cookie_str)
+ assert_equal({"%66oo" => ["baz"], "foo" => ["bar"]}, cookies)
+ end
def test_cgi_cookie_arrayinterface
cookie = CGI::Cookie.new('name1', 'a', 'b', 'c')
@@ -113,6 +139,70 @@ class CGICookieTest < Test::Unit::TestCase
end
+ def test_cgi_cookie_domain_injection_into_name
+ name = "a=b; domain=example.com;"
+ path = "/"
+ domain = "example.jp"
+ assert_raise(ArgumentError) do
+ CGI::Cookie.new('name' => name,
+ 'value' => "value",
+ 'domain' => domain,
+ 'path' => path)
+ end
+ end
+
+
+ def test_cgi_cookie_newline_injection_into_name
+ name = "a=b;\r\nLocation: http://example.com#"
+ path = "/"
+ domain = "example.jp"
+ assert_raise(ArgumentError) do
+ CGI::Cookie.new('name' => name,
+ 'value' => "value",
+ 'domain' => domain,
+ 'path' => path)
+ end
+ end
+
+
+ def test_cgi_cookie_multibyte_injection_into_name
+ name = "a=b;\u3042"
+ path = "/"
+ domain = "example.jp"
+ assert_raise(ArgumentError) do
+ CGI::Cookie.new('name' => name,
+ 'value' => "value",
+ 'domain' => domain,
+ 'path' => path)
+ end
+ end
+
+
+ def test_cgi_cookie_injection_into_path
+ name = "name"
+ path = "/; samesite=none"
+ domain = "example.jp"
+ assert_raise(ArgumentError) do
+ CGI::Cookie.new('name' => name,
+ 'value' => "value",
+ 'domain' => domain,
+ 'path' => path)
+ end
+ end
+
+
+ def test_cgi_cookie_injection_into_domain
+ name = "name"
+ path = "/"
+ domain = "example.jp; samesite=none"
+ assert_raise(ArgumentError) do
+ CGI::Cookie.new('name' => name,
+ 'value' => "value",
+ 'domain' => domain,
+ 'path' => path)
+ end
+ end
+
instance_methods.each do |method|
private method if method =~ /^test_(.*)/ && $1 != ENV['TEST']
diff --git a/test/cgi/test_cgi_header.rb b/test/cgi/test_cgi_header.rb
index bab2d0348a..ec2f4deb72 100644
--- a/test/cgi/test_cgi_header.rb
+++ b/test/cgi/test_cgi_header.rb
@@ -176,6 +176,14 @@ class CGIHeaderTest < Test::Unit::TestCase
end
+ def test_cgi_http_header_crlf_injection
+ cgi = CGI.new
+ assert_raise(RuntimeError) { cgi.http_header("text/xhtml\r\nBOO") }
+ assert_raise(RuntimeError) { cgi.http_header("type" => "text/xhtml\r\nBOO") }
+ assert_raise(RuntimeError) { cgi.http_header("status" => "200 OK\r\nBOO") }
+ assert_raise(RuntimeError) { cgi.http_header("location" => "text/xhtml\r\nBOO") }
+ end
+
instance_methods.each do |method|
private method if method =~ /^test_(.*)/ && $1 != ENV['TEST']
diff --git a/test/cgi/test_cgi_util.rb b/test/cgi/test_cgi_util.rb
index 6ce8b42c20..b0612fc87d 100644
--- a/test/cgi/test_cgi_util.rb
+++ b/test/cgi/test_cgi_util.rb
@@ -23,7 +23,6 @@ class CGIUtilTest < Test::Unit::TestCase
ENV.update(@environ)
end
-
def test_cgi_escape
assert_equal('%26%3C%3E%22+%E3%82%86%E3%82%93%E3%82%86%E3%82%93', CGI.escape(@str1))
assert_equal('%26%3C%3E%22+%E3%82%86%E3%82%93%E3%82%86%E3%82%93'.ascii_only?, CGI.escape(@str1).ascii_only?) if defined?(::Encoding)
@@ -70,6 +69,63 @@ class CGIUtilTest < Test::Unit::TestCase
end;
end
+ def test_cgi_escapeURIComponent
+ assert_equal('%26%3C%3E%22%20%E3%82%86%E3%82%93%E3%82%86%E3%82%93', CGI.escapeURIComponent(@str1))
+ assert_equal('%26%3C%3E%22%20%E3%82%86%E3%82%93%E3%82%86%E3%82%93'.ascii_only?, CGI.escapeURIComponent(@str1).ascii_only?) if defined?(::Encoding)
+ end
+
+ def test_cgi_escape_uri_component
+ assert_equal('%26%3C%3E%22%20%E3%82%86%E3%82%93%E3%82%86%E3%82%93', CGI.escape_uri_component(@str1))
+ end
+
+ def test_cgi_escapeURIComponent_with_unreserved_characters
+ assert_equal("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~",
+ CGI.escapeURIComponent("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~"),
+ "should not encode any unreserved characters, as per RFC3986 Section 2.3")
+ end
+
+ def test_cgi_escapeURIComponent_with_invalid_byte_sequence
+ assert_equal('%C0%3C%3C', CGI.escapeURIComponent("\xC0\<\<".dup.force_encoding("UTF-8")))
+ end
+
+ def test_cgi_escapeURIComponent_preserve_encoding
+ assert_equal(Encoding::US_ASCII, CGI.escapeURIComponent("\xC0\<\<".dup.force_encoding("US-ASCII")).encoding)
+ assert_equal(Encoding::ASCII_8BIT, CGI.escapeURIComponent("\xC0\<\<".dup.force_encoding("ASCII-8BIT")).encoding)
+ assert_equal(Encoding::UTF_8, CGI.escapeURIComponent("\xC0\<\<".dup.force_encoding("UTF-8")).encoding)
+ end
+
+ def test_cgi_unescapeURIComponent
+ str = CGI.unescapeURIComponent('%26%3C%3E%22%20%E3%82%86%E3%82%93%E3%82%86%E3%82%93')
+ assert_equal(@str1, str)
+ return unless defined?(::Encoding)
+
+ assert_equal("foo+bar", CGI.unescapeURIComponent("foo+bar"))
+
+ assert_equal(@str1.encoding, str.encoding)
+ assert_equal("\u{30E1 30E2 30EA 691C 7D22}", CGI.unescapeURIComponent("\u{30E1 30E2 30EA}%E6%A4%9C%E7%B4%A2"))
+ end
+
+ def test_cgi_unescape_uri_component
+ str = CGI.unescape_uri_component('%26%3C%3E%22%20%E3%82%86%E3%82%93%E3%82%86%E3%82%93')
+ assert_equal(@str1, str)
+ end
+
+ def test_cgi_unescapeURIComponent_preserve_encoding
+ assert_equal(Encoding::US_ASCII, CGI.unescapeURIComponent("%C0%3C%3C".dup.force_encoding("US-ASCII")).encoding)
+ assert_equal(Encoding::ASCII_8BIT, CGI.unescapeURIComponent("%C0%3C%3C".dup.force_encoding("ASCII-8BIT")).encoding)
+ assert_equal(Encoding::UTF_8, CGI.unescapeURIComponent("%C0%3C%3C".dup.force_encoding("UTF-8")).encoding)
+ end
+
+ def test_cgi_unescapeURIComponent_accept_charset
+ return unless defined?(::Encoding)
+
+ assert_raise(TypeError) {CGI.unescapeURIComponent('', nil)}
+ assert_separately(%w[-rcgi/util], "#{<<-"begin;"}\n#{<<-"end;"}")
+ begin;
+ assert_equal("", CGI.unescapeURIComponent(''))
+ end;
+ end
+
def test_cgi_pretty
assert_equal("<HTML>\n <BODY>\n </BODY>\n</HTML>\n",CGI.pretty("<HTML><BODY></BODY></HTML>"))
assert_equal("<HTML>\n\t<BODY>\n\t</BODY>\n</HTML>\n",CGI.pretty("<HTML><BODY></BODY></HTML>","\t"))
@@ -104,6 +160,24 @@ class CGIUtilTest < Test::Unit::TestCase
assert_not_predicate CGI.escapeHTML("Ruby".freeze), :frozen?
end
+ def test_cgi_escape_html_large
+ return if RUBY_ENGINE == 'jruby'
+ ulong_max, size_max = RbConfig::LIMITS.values_at("ULONG_MAX", "SIZE_MAX")
+ return unless ulong_max < size_max # Platforms not concerned
+
+ size = (ulong_max / 6 + 1)
+ begin
+ str = '"' * size
+ escaped = CGI.escapeHTML(str)
+ rescue NoMemoryError
+ omit "Not enough memory"
+ rescue => e
+ end
+ assert_raise_with_message(ArgumentError, /overflow/, ->{"length = #{escaped.length}"}) do
+ raise e if e
+ end
+ end
+
def test_cgi_unescapeHTML
assert_equal("'&\"><", CGI.unescapeHTML("&#39;&amp;&quot;&gt;&lt;"))
end
@@ -112,6 +186,22 @@ class CGIUtilTest < Test::Unit::TestCase
assert_equal('&<&amp>&quot&abcdefghijklmn', CGI.unescapeHTML('&&lt;&amp&gt;&quot&abcdefghijklmn'))
end
+ module UnescapeHTMLTests
+ def test_cgi_unescapeHTML_following_known_first_letter
+ assert_equal('&a>&q>&l>&g>', CGI.unescapeHTML('&a&gt;&q&gt;&l&gt;&g&gt;'))
+ end
+
+ def test_cgi_unescapeHTML_following_number_sign
+ assert_equal('&#>&#x>', CGI.unescapeHTML('&#&gt;&#x&gt;'))
+ end
+
+ def test_cgi_unescapeHTML_following_invalid_numeric
+ assert_equal('&#1114112>&#x110000>', CGI.unescapeHTML('&#1114112&gt;&#x110000&gt;'))
+ end
+ end
+
+ include UnescapeHTMLTests
+
Encoding.list.each do |enc|
begin
escaped = "&#39;&amp;&quot;&gt;&lt;".encode(enc)
@@ -197,7 +287,7 @@ class CGIUtilPureRubyTest < Test::Unit::TestCase
remove_method :escapeHTML
alias _unescapeHTML unescapeHTML
remove_method :unescapeHTML
- end
+ end if defined?(CGI::Escape)
end
def teardown
@@ -206,9 +296,11 @@ class CGIUtilPureRubyTest < Test::Unit::TestCase
remove_method :_escapeHTML
alias unescapeHTML _unescapeHTML
remove_method :_unescapeHTML
- end
+ end if defined?(CGI::Escape)
end
+ include CGIUtilTest::UnescapeHTMLTests
+
def test_cgi_escapeHTML_with_invalid_byte_sequence
assert_equal("&lt;\xA4??&gt;", CGI.escapeHTML(%[<\xA4??>]))
end
diff --git a/test/coverage/autostart.rb b/test/coverage/autostart.rb
new file mode 100644
index 0000000000..067fe0a40d
--- /dev/null
+++ b/test/coverage/autostart.rb
@@ -0,0 +1,2 @@
+require 'coverage'
+Coverage.start(:all)
diff --git a/test/coverage/main.rb b/test/coverage/main.rb
new file mode 100644
index 0000000000..74f1e95fa3
--- /dev/null
+++ b/test/coverage/main.rb
@@ -0,0 +1 @@
+puts Coverage.peek_result[__FILE__][:lines]
diff --git a/test/coverage/test_coverage.rb b/test/coverage/test_coverage.rb
index 22557bd9d8..4773280cae 100644
--- a/test/coverage/test_coverage.rb
+++ b/test/coverage/test_coverage.rb
@@ -5,29 +5,47 @@ require "tmpdir"
require "envutil"
class TestCoverage < Test::Unit::TestCase
+ # The command-line arguments that we will pass to the ruby subprocess invoked
+ # by assert_in_out_err. In general this is just requiring the coverage
+ # library, but if prism is enabled we want to additionally pass that option
+ # through.
+ ARGV = ["-rcoverage"]
+
+ if RubyVM::InstructionSequence.compile('').to_a[4][:parser] == :prism
+ ARGV << "-W:no-experimental"
+ ARGV << "--parser=prism"
+ end
+
def test_result_without_start
- assert_in_out_err(%w[-rcoverage], <<-"end;", [], /coverage measurement is not enabled/)
+ assert_in_out_err(ARGV, <<-"end;", [], /coverage measurement is not enabled/)
Coverage.result
p :NG
end;
end
def test_peek_result_without_start
- assert_in_out_err(%w[-rcoverage], <<-"end;", [], /coverage measurement is not enabled/)
+ assert_in_out_err(ARGV, <<-"end;", [], /coverage measurement is not enabled/)
Coverage.peek_result
p :NG
end;
end
def test_result_with_nothing
- assert_in_out_err(%w[-rcoverage], <<-"end;", ["{}"], [])
+ assert_in_out_err(ARGV, <<-"end;", ["{}"], [])
Coverage.start
p Coverage.result
end;
end
+ def test_coverage_in_main_script
+ autostart_path = File.expand_path("autostart.rb", __dir__)
+ main_path = File.expand_path("main.rb", __dir__)
+
+ assert_in_out_err(['-r', autostart_path, main_path], "", ["1"], [])
+ end
+
def test_coverage_running?
- assert_in_out_err(%w[-rcoverage], <<-"end;", ["false", "true", "true", "false"], [])
+ assert_in_out_err(ARGV, <<-"end;", ["false", "true", "true", "false"], [])
p Coverage.running?
Coverage.start
p Coverage.running?
@@ -49,7 +67,7 @@ class TestCoverage < Test::Unit::TestCase
EOS
end
- assert_in_out_err(%w[-rcoverage], <<-"end;", ["[1, 0, nil]", "[1, 1, nil]", "[1, 1, nil]"], [])
+ assert_in_out_err(ARGV, <<-"end;", ["[1, 0, nil]", "[1, 1, nil]", "[1, 1, nil]"], [])
Coverage.start
tmp = Dir.pwd
require tmp + "/test.rb"
@@ -85,7 +103,7 @@ class TestCoverage < Test::Unit::TestCase
exp1 = { "#{tmp}/test.rb" => [1, 0, nil] }.inspect
exp2 = {}.inspect
exp3 = { "#{tmp}/test2.rb" => [1] }.inspect
- assert_in_out_err(%w[-rcoverage], <<-"end;", [exp1, exp2, exp3], [])
+ assert_in_out_err(ARGV, <<-"end;", [exp1, exp2, exp3], [])
Coverage.start
tmp = Dir.pwd
require tmp + "/test.rb"
@@ -117,7 +135,7 @@ class TestCoverage < Test::Unit::TestCase
f.puts "])"
end
- assert_in_out_err(%w[-rcoverage], <<-"end;", ["10003"], [])
+ assert_in_out_err(ARGV, <<-"end;", ["10003"], [])
Coverage.start
tmp = Dir.pwd
require tmp + '/test.rb'
@@ -136,7 +154,7 @@ class TestCoverage < Test::Unit::TestCase
f.puts 'REPEATS = 400'
f.puts 'def add_method(target)'
f.puts ' REPEATS.times do'
- f.puts ' target.class_eval(<<~RUBY, __FILE__, __LINE__ + 1)'
+ f.puts ' target.class_eval(<<~RUBY)'
f.puts ' def foo'
f.puts ' #{"\n" * rand(REPEATS)}'
f.puts ' end'
@@ -146,17 +164,43 @@ class TestCoverage < Test::Unit::TestCase
f.puts 'end'
end
- assert_in_out_err(%w[-W0 -rcoverage], <<-"end;", ["[1, 1, 1, 400, nil, nil, nil, nil, nil, nil, nil]"], [], bug13305)
- Coverage.start
+ assert_in_out_err(["-W0", *ARGV], <<-"end;", ["[1, 1, 1, 400, nil, nil, nil, nil, nil, nil, nil]"], [], bug13305)
+ Coverage.start(:all)
tmp = Dir.pwd
require tmp + '/test.rb'
add_method(Class.new)
- p Coverage.result[tmp + "/test.rb"]
+ p Coverage.result[tmp + "/test.rb"][:lines]
end;
}
}
end
+ def test_eval_coverage
+ assert_in_out_err(ARGV, <<-"end;", ["[1, 1, 1, nil, 0, nil]"], [])
+ Coverage.start(eval: true, lines: true)
+
+ eval(<<-RUBY, TOPLEVEL_BINDING, "test.rb")
+ _out = String.new
+ if _out.empty?
+ _out << 'Hello World'
+ else
+ _out << 'Goodbye World'
+ end
+ RUBY
+
+ p Coverage.result["test.rb"][:lines]
+ end;
+ end
+
+ def test_coverage_supported
+ assert Coverage.supported?(:lines)
+ assert Coverage.supported?(:oneshot_lines)
+ assert Coverage.supported?(:branches)
+ assert Coverage.supported?(:methods)
+ assert Coverage.supported?(:eval)
+ refute Coverage.supported?(:all)
+ end
+
def test_nocoverage_optimized_line
assert_ruby_status(%w[], "#{<<-"begin;"}\n#{<<-'end;'}")
begin;
@@ -181,6 +225,27 @@ class TestCoverage < Test::Unit::TestCase
end;
end
+ def test_coverage_ensure_if_return
+ result = {
+ :branches => {
+ [:if, 0, 3, 2, 6, 5] => {
+ [:then, 1, 3, 7, 3, 7] => 0,
+ [:else, 2, 5, 4, 5, 10] => 1,
+ },
+ },
+ }
+ assert_coverage(<<~"end;", { branches: true }, result)
+ def flush
+ ensure
+ if $!
+ else
+ return
+ end
+ end
+ flush
+ end;
+ end
+
def assert_coverage(code, opt, stdout)
stdout = [stdout] unless stdout.is_a?(Array)
stdout = stdout.map {|s| s.to_s }
@@ -188,7 +253,7 @@ class TestCoverage < Test::Unit::TestCase
Dir.chdir(tmp) {
File.write("test.rb", code)
- assert_in_out_err(%w[-W0 -rcoverage], <<-"end;", stdout, [])
+ assert_in_out_err(["-W0", *ARGV], <<-"end;", stdout, [])
Coverage.start(#{ opt })
tmp = Dir.pwd
require tmp + '/test.rb'
@@ -588,7 +653,7 @@ class TestCoverage < Test::Unit::TestCase
"{:lines=>[0, 1, 1, nil, 0, nil, nil]}",
"{:lines=>[0, 1, 0, nil, 1, nil, nil]}",
]
- assert_in_out_err(%w[-rcoverage], <<-"end;", exp, [])
+ assert_in_out_err(ARGV, <<-"end;", exp, [])
Coverage.start(lines: true)
tmp = Dir.pwd
f = tmp + "/test.rb"
@@ -622,7 +687,7 @@ class TestCoverage < Test::Unit::TestCase
"{:branches=>{[:if, 0, 2, 2, 6, 5]=>{[:then, 1, 3, 4, 3, 8]=>0, [:else, 2, 5, 4, 5, 12]=>1}}}",
"{:branches=>{[:if, 0, 2, 2, 6, 5]=>{[:then, 1, 3, 4, 3, 8]=>0, [:else, 2, 5, 4, 5, 12]=>1}}}",
]
- assert_in_out_err(%w[-rcoverage], <<-"end;", exp, [])
+ assert_in_out_err(ARGV, <<-"end;", exp, [])
Coverage.start(branches: true)
tmp = Dir.pwd
f = tmp + "/test.rb"
@@ -658,7 +723,7 @@ class TestCoverage < Test::Unit::TestCase
"{:methods=>{[Object, :foo, 1, 0, 7, 3]=>1}}",
"{:methods=>{[Object, :foo, 1, 0, 7, 3]=>1}}"
]
- assert_in_out_err(%w[-rcoverage], <<-"end;", exp, [])
+ assert_in_out_err(ARGV, <<-"end;", exp, [])
Coverage.start(methods: true)
tmp = Dir.pwd
f = tmp + "/test.rb"
@@ -694,7 +759,7 @@ class TestCoverage < Test::Unit::TestCase
"{:oneshot_lines=>[5]}",
"{:oneshot_lines=>[]}",
]
- assert_in_out_err(%w[-rcoverage], <<-"end;", exp, [])
+ assert_in_out_err(ARGV, <<-"end;", exp, [])
Coverage.start(oneshot_lines: true)
tmp = Dir.pwd
f = tmp + "/test.rb"
@@ -774,4 +839,185 @@ class TestCoverage < Test::Unit::TestCase
end
end;
end
+
+ def test_coverage_suspendable
+ Dir.mktmpdir {|tmp|
+ Dir.chdir(tmp) {
+ File.open("test.rb", "w") do |f|
+ f.puts <<-EOS
+ def foo
+ :ok
+ end
+
+ def bar
+ :ok
+ end
+
+ def baz
+ :ok
+ end
+ EOS
+ end
+
+ assert_separately(%w[-rcoverage], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ cov1 = [0, 0, nil, nil, 0, 1, nil, nil, 0, 0, nil]
+ cov2 = [0, 0, nil, nil, 0, 1, nil, nil, 0, 1, nil]
+ Coverage.setup
+ tmp = Dir.pwd
+ require tmp + "/test.rb"
+ foo
+ Coverage.resume
+ bar
+ Coverage.suspend
+ baz
+ assert_equal cov1, Coverage.peek_result[tmp + "/test.rb"]
+ Coverage.resume
+ baz
+ assert_equal cov2, Coverage.result[tmp + "/test.rb"]
+ end;
+
+ assert_separately(%w[-rcoverage], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ cov1 = {
+ lines: [0, 0, nil, nil, 0, 1, nil, nil, 0, 0, nil],
+ branches: {},
+ methods: {
+ [Object, :baz, 9, 12, 11, 15]=>0,
+ [Object, :bar, 5, 12, 7, 15]=>1,
+ [Object, :foo, 1, 12, 3, 15]=>0,
+ }
+ }
+
+ cov2 = {
+ lines: [0, 0, nil, nil, 0, 1, nil, nil, 0, 1, nil],
+ branches: {},
+ methods: {
+ [Object, :baz, 9, 12, 11, 15]=>1,
+ [Object, :bar, 5, 12, 7, 15]=>1,
+ [Object, :foo, 1, 12, 3, 15]=>0,
+ }
+ }
+
+ Coverage.setup(:all)
+ tmp = Dir.pwd
+ require tmp + "/test.rb"
+ foo
+ Coverage.resume
+ bar
+ Coverage.suspend
+ baz
+ assert_equal cov1, Coverage.peek_result[tmp + "/test.rb"]
+ Coverage.resume
+ baz
+ assert_equal cov2, Coverage.result[tmp + "/test.rb"]
+ end;
+
+ assert_separately(%w[-rcoverage], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ cov1 = {:oneshot_lines=>[6]}
+ cov2 = {:oneshot_lines=>[6, 10]}
+ Coverage.setup(oneshot_lines: true)
+ tmp = Dir.pwd
+ require tmp + "/test.rb"
+ foo
+ Coverage.resume
+ bar
+ Coverage.suspend
+ baz
+ assert_equal cov1, Coverage.peek_result[tmp + "/test.rb"]
+ Coverage.resume
+ baz
+ assert_equal cov2, Coverage.result[tmp + "/test.rb"]
+ end;
+ }
+ }
+ end
+
+ def test_coverage_state
+ assert_in_out_err(ARGV, <<-"end;", [":idle", ":running", ":running", ":idle"], [])
+ p Coverage.state
+ Coverage.start
+ p Coverage.state
+ Coverage.peek_result
+ p Coverage.state
+ Coverage.result
+ p Coverage.state
+ end;
+
+ assert_in_out_err(ARGV, <<-"end;", [":idle", ":suspended", ":running", ":suspended", ":running", ":suspended", ":idle"], [])
+ p Coverage.state
+ Coverage.setup
+ p Coverage.state
+ Coverage.resume
+ p Coverage.state
+ Coverage.suspend
+ p Coverage.state
+ Coverage.resume
+ p Coverage.state
+ Coverage.suspend
+ p Coverage.state
+ Coverage.result
+ p Coverage.state
+ end;
+ end
+
+ def test_result_without_resume
+ assert_in_out_err(ARGV, <<-"end;", ["{}"], [])
+ Coverage.setup
+ p Coverage.result
+ end;
+ end
+
+ def test_result_after_suspend
+ assert_in_out_err(ARGV, <<-"end;", ["{}"], [])
+ Coverage.start
+ Coverage.suspend
+ p Coverage.result
+ end;
+ end
+
+ def test_resume_without_setup
+ assert_in_out_err(ARGV, <<-"end;", [], /coverage measurement is not set up yet/)
+ Coverage.resume
+ p :NG
+ end;
+ end
+
+ def test_suspend_without_setup
+ assert_in_out_err(ARGV, <<-"end;", [], /coverage measurement is not running/)
+ Coverage.suspend
+ p :NG
+ end;
+ end
+
+ def test_double_resume
+ assert_in_out_err(ARGV, <<-"end;", [], /coverage measurement is already running/)
+ Coverage.start
+ Coverage.resume
+ p :NG
+ end;
+ end
+
+ def test_double_suspend
+ assert_in_out_err(ARGV, <<-"end;", [], /coverage measurement is not running/)
+ Coverage.setup
+ Coverage.suspend
+ p :NG
+ end;
+ end
+
+ def test_tag_break_with_branch_coverage
+ result = {
+ :branches => {
+ [:"&.", 0, 1, 0, 1, 6] => {
+ [:then, 1, 1, 0, 1, 6] => 1,
+ [:else, 2, 1, 0, 1, 6] => 0,
+ },
+ },
+ }
+ assert_coverage(<<~"end;", { branches: true }, result)
+ 1&.tap do break end
+ end;
+ end
end
diff --git a/test/csv/helper.rb b/test/csv/helper.rb
deleted file mode 100644
index 1f9cf96979..0000000000
--- a/test/csv/helper.rb
+++ /dev/null
@@ -1,42 +0,0 @@
-require "tempfile"
-require "test/unit"
-
-require "csv"
-
-require_relative "../lib/with_different_ofs"
-
-module Helper
- def with_chunk_size(chunk_size)
- chunk_size_keep = ENV["CSV_PARSER_SCANNER_TEST_CHUNK_SIZE"]
- begin
- ENV["CSV_PARSER_SCANNER_TEST_CHUNK_SIZE"] = chunk_size
- yield
- ensure
- ENV["CSV_PARSER_SCANNER_TEST_CHUNK_SIZE"] = chunk_size_keep
- end
- end
-
- def with_verbose(verbose)
- original = $VERBOSE
- begin
- $VERBOSE = verbose
- yield
- ensure
- $VERBOSE = original
- end
- end
-
- def with_default_internal(encoding)
- original = Encoding.default_internal
- begin
- with_verbose(false) do
- Encoding.default_internal = encoding
- end
- yield
- ensure
- with_verbose(false) do
- Encoding.default_internal = original
- end
- end
- end
-end
diff --git a/test/csv/interface/test_delegation.rb b/test/csv/interface/test_delegation.rb
deleted file mode 100644
index 349257633b..0000000000
--- a/test/csv/interface/test_delegation.rb
+++ /dev/null
@@ -1,47 +0,0 @@
-# frozen_string_literal: false
-
-require_relative "../helper"
-
-class TestCSVInterfaceDelegation < Test::Unit::TestCase
- class TestStringIO < self
- def setup
- @csv = CSV.new("h1,h2")
- end
-
- def test_flock
- assert_raise(NotImplementedError) do
- @csv.flock(File::LOCK_EX)
- end
- end
-
- def test_ioctl
- assert_raise(NotImplementedError) do
- @csv.ioctl(0)
- end
- end
-
- def test_stat
- assert_raise(NotImplementedError) do
- @csv.stat
- end
- end
-
- def test_to_i
- assert_raise(NotImplementedError) do
- @csv.to_i
- end
- end
-
- def test_binmode?
- assert_equal(false, @csv.binmode?)
- end
-
- def test_path
- assert_equal(nil, @csv.path)
- end
-
- def test_to_io
- assert_instance_of(StringIO, @csv.to_io)
- end
- end
-end
diff --git a/test/csv/interface/test_read.rb b/test/csv/interface/test_read.rb
deleted file mode 100644
index b86c54fc9f..0000000000
--- a/test/csv/interface/test_read.rb
+++ /dev/null
@@ -1,339 +0,0 @@
-# frozen_string_literal: false
-
-require_relative "../helper"
-
-class TestCSVInterfaceRead < Test::Unit::TestCase
- extend DifferentOFS
-
- def setup
- super
- @data = ""
- @data << "1\t2\t3\r\n"
- @data << "4\t5\r\n"
- @input = Tempfile.new(["interface-read", ".csv"], binmode: true)
- @input << @data
- @input.rewind
- @rows = [
- ["1", "2", "3"],
- ["4", "5"],
- ]
- end
-
- def teardown
- @input.close(true)
- super
- end
-
- def test_foreach
- rows = []
- CSV.foreach(@input.path, col_sep: "\t", row_sep: "\r\n").each do |row|
- rows << row
- end
- assert_equal(@rows, rows)
- end
-
- def test_foreach_mode
- rows = []
- CSV.foreach(@input.path, "r", col_sep: "\t", row_sep: "\r\n").each do |row|
- rows << row
- end
- assert_equal(@rows, rows)
- end
-
- def test_foreach_enumurator
- rows = CSV.foreach(@input.path, col_sep: "\t", row_sep: "\r\n").to_a
- assert_equal(@rows, rows)
- end
-
- def test_closed?
- csv = CSV.open(@input.path, "r+", col_sep: "\t", row_sep: "\r\n")
- assert_not_predicate(csv, :closed?)
- csv.close
- assert_predicate(csv, :closed?)
- end
-
- def test_open_auto_close
- csv = nil
- CSV.open(@input.path) do |_csv|
- csv = _csv
- end
- assert_predicate(csv, :closed?)
- end
-
- def test_open_closed
- csv = nil
- CSV.open(@input.path) do |_csv|
- csv = _csv
- csv.close
- end
- assert_predicate(csv, :closed?)
- end
-
- def test_open_block_return_value
- return_value = CSV.open(@input.path) do
- "Return value."
- end
- assert_equal("Return value.", return_value)
- end
-
- def test_open_encoding_valid
- # U+1F600 GRINNING FACE
- # U+1F601 GRINNING FACE WITH SMILING EYES
- File.open(@input.path, "w") do |file|
- file << "\u{1F600},\u{1F601}"
- end
- CSV.open(@input.path, encoding: "utf-8") do |csv|
- assert_equal([["\u{1F600}", "\u{1F601}"]],
- csv.to_a)
- end
- end
-
- def test_open_encoding_invalid
- # U+1F600 GRINNING FACE
- # U+1F601 GRINNING FACE WITH SMILING EYES
- File.open(@input.path, "w") do |file|
- file << "\u{1F600},\u{1F601}"
- end
- CSV.open(@input.path, encoding: "EUC-JP") do |csv|
- error = assert_raise(CSV::MalformedCSVError) do
- csv.shift
- end
- assert_equal("Invalid byte sequence in EUC-JP in line 1.",
- error.message)
- end
- end
-
- def test_open_encoding_nonexistent
- _output, error = capture_output do
- CSV.open(@input.path, encoding: "nonexistent") do
- end
- end
- assert_equal("path:0: warning: Unsupported encoding nonexistent ignored\n",
- error.gsub(/\A.+:\d+: /, "path:0: "))
- end
-
- def test_open_encoding_utf_8_with_bom
- # U+FEFF ZERO WIDTH NO-BREAK SPACE, BOM
- # U+1F600 GRINNING FACE
- # U+1F601 GRINNING FACE WITH SMILING EYES
- File.open(@input.path, "w") do |file|
- file << "\u{FEFF}\u{1F600},\u{1F601}"
- end
- CSV.open(@input.path, encoding: "bom|utf-8") do |csv|
- assert_equal([["\u{1F600}", "\u{1F601}"]],
- csv.to_a)
- end
- end
-
- def test_open_invalid_byte_sequence_in_utf_8
- CSV.open(@input.path, "w", encoding: Encoding::CP932) do |rows|
- error = assert_raise(Encoding::InvalidByteSequenceError) do
- rows << ["\x82\xa0"]
- end
- assert_equal('"\x82" on UTF-8',
- error.message)
- end
- end
-
- def test_open_with_invalid_nil
- CSV.open(@input.path, "w", encoding: Encoding::CP932, invalid: nil) do |rows|
- error = assert_raise(Encoding::InvalidByteSequenceError) do
- rows << ["\x82\xa0"]
- end
- assert_equal('"\x82" on UTF-8',
- error.message)
- end
- end
-
- def test_open_with_invalid_replace
- CSV.open(@input.path, "w", encoding: Encoding::CP932, invalid: :replace) do |rows|
- rows << ["\x82\xa0".force_encoding(Encoding::UTF_8)]
- end
- CSV.open(@input.path, encoding: Encoding::CP932) do |csv|
- assert_equal([["??"]],
- csv.to_a)
- end
- end
-
- def test_open_with_invalid_replace_and_replace_string
- CSV.open(@input.path, "w", encoding: Encoding::CP932, invalid: :replace, replace: "X") do |rows|
- rows << ["\x82\xa0".force_encoding(Encoding::UTF_8)]
- end
- CSV.open(@input.path, encoding: Encoding::CP932) do |csv|
- assert_equal([["XX"]],
- csv.to_a)
- end
- end
-
- def test_open_with_undef_replace
- # U+00B7 Middle Dot
- CSV.open(@input.path, "w", encoding: Encoding::CP932, undef: :replace) do |rows|
- rows << ["\u00B7"]
- end
- CSV.open(@input.path, encoding: Encoding::CP932) do |csv|
- assert_equal([["?"]],
- csv.to_a)
- end
- end
-
- def test_open_with_undef_replace_and_replace_string
- # U+00B7 Middle Dot
- CSV.open(@input.path, "w", encoding: Encoding::CP932, undef: :replace, replace: "X") do |rows|
- rows << ["\u00B7"]
- end
- CSV.open(@input.path, encoding: Encoding::CP932) do |csv|
- assert_equal([["X"]],
- csv.to_a)
- end
- end
-
- def test_parse
- assert_equal(@rows,
- CSV.parse(@data, col_sep: "\t", row_sep: "\r\n"))
- end
-
- def test_parse_block
- rows = []
- CSV.parse(@data, col_sep: "\t", row_sep: "\r\n") do |row|
- rows << row
- end
- assert_equal(@rows, rows)
- end
-
- def test_parse_enumerator
- rows = CSV.parse(@data, col_sep: "\t", row_sep: "\r\n").to_a
- assert_equal(@rows, rows)
- end
-
- def test_parse_headers_only
- table = CSV.parse("a,b,c", headers: true)
- assert_equal([
- ["a", "b", "c"],
- [],
- ],
- [
- table.headers,
- table.each.to_a,
- ])
- end
-
- def test_parse_line
- assert_equal(["1", "2", "3"],
- CSV.parse_line("1;2;3", col_sep: ";"))
- end
-
- def test_parse_line_shortcut
- assert_equal(["1", "2", "3"],
- "1;2;3".parse_csv(col_sep: ";"))
- end
-
- def test_parse_line_empty
- assert_equal(nil, CSV.parse_line("")) # to signal eof
- end
-
- def test_parse_line_empty_line
- assert_equal([], CSV.parse_line("\n1,2,3"))
- end
-
- def test_read
- assert_equal(@rows,
- CSV.read(@input.path, col_sep: "\t", row_sep: "\r\n"))
- end
-
- def test_readlines
- assert_equal(@rows,
- CSV.readlines(@input.path, col_sep: "\t", row_sep: "\r\n"))
- end
-
- def test_open_read
- rows = CSV.open(@input.path, col_sep: "\t", row_sep: "\r\n") do |csv|
- csv.read
- end
- assert_equal(@rows, rows)
- end
-
- def test_open_readlines
- rows = CSV.open(@input.path, col_sep: "\t", row_sep: "\r\n") do |csv|
- csv.readlines
- end
- assert_equal(@rows, rows)
- end
-
- def test_table
- table = CSV.table(@input.path, col_sep: "\t", row_sep: "\r\n")
- assert_equal(CSV::Table.new([
- CSV::Row.new([:"1", :"2", :"3"], [4, 5, nil]),
- ]),
- table)
- end
-
- def test_shift # aliased as gets() and readline()
- CSV.open(@input.path, "rb+", col_sep: "\t", row_sep: "\r\n") do |csv|
- rows = [
- csv.shift,
- csv.shift,
- csv.shift,
- ]
- assert_equal(@rows + [nil],
- rows)
- end
- end
-
- def test_enumerator
- CSV.open(@input.path, col_sep: "\t", row_sep: "\r\n") do |csv|
- assert_equal(@rows, csv.each.to_a)
- end
- end
-
- def test_shift_and_each
- CSV.open(@input.path, col_sep: "\t", row_sep: "\r\n") do |csv|
- rows = []
- rows << csv.shift
- rows.concat(csv.each.to_a)
- assert_equal(@rows, rows)
- end
- end
-
- def test_each_twice
- CSV.open(@input.path, col_sep: "\t", row_sep: "\r\n") do |csv|
- assert_equal([
- @rows,
- [],
- ],
- [
- csv.each.to_a,
- csv.each.to_a,
- ])
- end
- end
-
- def test_eof?
- eofs = []
- CSV.open(@input.path, col_sep: "\t", row_sep: "\r\n") do |csv|
- eofs << csv.eof?
- csv.shift
- eofs << csv.eof?
- csv.shift
- eofs << csv.eof?
- end
- assert_equal([false, false, true],
- eofs)
- end
-
- def test_new_nil
- assert_raise_with_message ArgumentError, "Cannot parse nil as CSV" do
- CSV.new(nil)
- end
- end
-
- def test_options_not_modified
- options = {}.freeze
- CSV.foreach(@input.path, **options)
- CSV.open(@input.path, **options) {}
- CSV.parse("", **options)
- CSV.parse_line("", **options)
- CSV.read(@input.path, **options)
- CSV.readlines(@input.path, **options)
- CSV.table(@input.path, **options)
- end
-end
diff --git a/test/csv/interface/test_read_write.rb b/test/csv/interface/test_read_write.rb
deleted file mode 100644
index 20c9fe317e..0000000000
--- a/test/csv/interface/test_read_write.rb
+++ /dev/null
@@ -1,115 +0,0 @@
-# frozen_string_literal: false
-
-require_relative "../helper"
-
-class TestCSVInterfaceReadWrite < Test::Unit::TestCase
- extend DifferentOFS
-
- def test_filter
- input = <<-CSV.freeze
-1;2;3
-4;5
- CSV
- output = ""
- CSV.filter(input, output,
- in_col_sep: ";",
- out_col_sep: ",",
- converters: :all) do |row|
- row.map! {|n| n * 2}
- row << "Added\r"
- end
- assert_equal(<<-CSV, output)
-2,4,6,"Added\r"
-8,10,"Added\r"
- CSV
- end
-
- def test_filter_headers_true
- input = <<-CSV.freeze
-Name,Value
-foo,0
-bar,1
-baz,2
- CSV
- output = ""
- CSV.filter(input, output, headers: true) do |row|
- row[0] += "X"
- row[1] = row[1].to_i + 1
- end
- assert_equal(<<-CSV, output)
-fooX,1
-barX,2
-bazX,3
- CSV
- end
-
- def test_filter_headers_true_write_headers
- input = <<-CSV.freeze
-Name,Value
-foo,0
-bar,1
-baz,2
- CSV
- output = ""
- CSV.filter(input, output, headers: true, out_write_headers: true) do |row|
- if row.is_a?(Array)
- row[0] += "X"
- row[1] += "Y"
- else
- row[0] += "X"
- row[1] = row[1].to_i + 1
- end
- end
- assert_equal(<<-CSV, output)
-NameX,ValueY
-fooX,1
-barX,2
-bazX,3
- CSV
- end
-
- def test_filter_headers_array_write_headers
- input = <<-CSV.freeze
-foo,0
-bar,1
-baz,2
- CSV
- output = ""
- CSV.filter(input, output,
- headers: ["Name", "Value"],
- out_write_headers: true) do |row|
- row[0] += "X"
- row[1] = row[1].to_i + 1
- end
- assert_equal(<<-CSV, output)
-Name,Value
-fooX,1
-barX,2
-bazX,3
- CSV
- end
-
- def test_instance_same
- data = ""
- assert_equal(CSV.instance(data, col_sep: ";").object_id,
- CSV.instance(data, col_sep: ";").object_id)
- end
-
- def test_instance_append
- output = ""
- CSV.instance(output, col_sep: ";") << ["a", "b", "c"]
- assert_equal(<<-CSV, output)
-a;b;c
- CSV
- CSV.instance(output, col_sep: ";") << [1, 2, 3]
- assert_equal(<<-CSV, output)
-a;b;c
-1;2;3
- CSV
- end
-
- def test_instance_shortcut
- assert_equal(CSV.instance,
- CSV {|csv| csv})
- end
-end
diff --git a/test/csv/interface/test_write.rb b/test/csv/interface/test_write.rb
deleted file mode 100644
index 8650ecd624..0000000000
--- a/test/csv/interface/test_write.rb
+++ /dev/null
@@ -1,174 +0,0 @@
-# frozen_string_literal: false
-
-require_relative "../helper"
-
-class TestCSVInterfaceWrite < Test::Unit::TestCase
- extend DifferentOFS
-
- def setup
- super
- @output = Tempfile.new(["interface-write", ".csv"])
- end
-
- def teardown
- @output.close(true)
- super
- end
-
- def test_generate_default
- csv_text = CSV.generate do |csv|
- csv << [1, 2, 3] << [4, nil, 5]
- end
- assert_equal(<<-CSV, csv_text)
-1,2,3
-4,,5
- CSV
- end
-
- def test_generate_append
- csv_text = <<-CSV
-1,2,3
-4,,5
- CSV
- CSV.generate(csv_text) do |csv|
- csv << ["last", %Q{"row"}]
- end
- assert_equal(<<-CSV, csv_text)
-1,2,3
-4,,5
-last,"""row"""
- CSV
- end
-
- def test_generate_no_new_line
- csv_text = CSV.generate("test") do |csv|
- csv << ["row"]
- end
- assert_equal(<<-CSV, csv_text)
-testrow
- CSV
- end
-
- def test_generate_line_col_sep
- line = CSV.generate_line(["1", "2", "3"], col_sep: ";")
- assert_equal(<<-LINE, line)
-1;2;3
- LINE
- end
-
- def test_generate_line_row_sep
- line = CSV.generate_line(["1", "2"], row_sep: nil)
- assert_equal(<<-LINE.chomp, line)
-1,2
- LINE
- end
-
- def test_generate_line_shortcut
- line = ["1", "2", "3"].to_csv(col_sep: ";")
- assert_equal(<<-LINE, line)
-1;2;3
- LINE
- end
-
- def test_headers_detection
- headers = ["a", "b", "c"]
- CSV.open(@output.path, "w", headers: true) do |csv|
- csv << headers
- csv << ["1", "2", "3"]
- assert_equal(headers, csv.headers)
- end
- end
-
- def test_lineno
- CSV.open(@output.path, "w") do |csv|
- n_lines = 20
- n_lines.times do
- csv << ["a", "b", "c"]
- end
- assert_equal(n_lines, csv.lineno)
- end
- end
-
- def test_append_row
- CSV.open(@output.path, "wb") do |csv|
- csv <<
- CSV::Row.new([], ["1", "2", "3"]) <<
- CSV::Row.new([], ["a", "b", "c"])
- end
- assert_equal(<<-CSV, File.read(@output.path, mode: "rb"))
-1,2,3
-a,b,c
- CSV
- end
-
- def test_append_hash
- CSV.open(@output.path, "wb", headers: true) do |csv|
- csv << [:a, :b, :c]
- csv << {a: 1, b: 2, c: 3}
- csv << {a: 4, b: 5, c: 6}
- end
- assert_equal(<<-CSV, File.read(@output.path, mode: "rb"))
-a,b,c
-1,2,3
-4,5,6
- CSV
- end
-
- def test_append_hash_headers_array
- CSV.open(@output.path, "wb", headers: [:b, :a, :c]) do |csv|
- csv << {a: 1, b: 2, c: 3}
- csv << {a: 4, b: 5, c: 6}
- end
- assert_equal(<<-CSV, File.read(@output.path, mode: "rb"))
-2,1,3
-5,4,6
- CSV
- end
-
- def test_append_hash_headers_string
- CSV.open(@output.path, "wb", headers: "b|a|c", col_sep: "|") do |csv|
- csv << {"a" => 1, "b" => 2, "c" => 3}
- csv << {"a" => 4, "b" => 5, "c" => 6}
- end
- assert_equal(<<-CSV, File.read(@output.path, mode: "rb"))
-2|1|3
-5|4|6
- CSV
- end
-
- def test_write_headers
- CSV.open(@output.path,
- "wb",
- headers: "b|a|c",
- write_headers: true,
- col_sep: "|" ) do |csv|
- csv << {"a" => 1, "b" => 2, "c" => 3}
- csv << {"a" => 4, "b" => 5, "c" => 6}
- end
- assert_equal(<<-CSV, File.read(@output.path, mode: "rb"))
-b|a|c
-2|1|3
-5|4|6
- CSV
- end
-
- def test_write_headers_empty
- CSV.open(@output.path,
- "wb",
- headers: "b|a|c",
- write_headers: true,
- col_sep: "|" ) do |csv|
- end
- assert_equal(<<-CSV, File.read(@output.path, mode: "rb"))
-b|a|c
- CSV
- end
-
- def test_options_not_modified
- options = {}.freeze
- CSV.generate(**options) {}
- CSV.generate_line([], **options)
- CSV.filter("", "", **options)
- CSV.instance("", **options)
- end
-end
diff --git a/test/csv/line_endings.gz b/test/csv/line_endings.gz
deleted file mode 100644
index 39e1729ee4..0000000000
--- a/test/csv/line_endings.gz
+++ /dev/null
Binary files differ
diff --git a/test/csv/parse/test_column_separator.rb b/test/csv/parse/test_column_separator.rb
deleted file mode 100644
index d6eaa7b6de..0000000000
--- a/test/csv/parse/test_column_separator.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-# -*- coding: utf-8 -*-
-# frozen_string_literal: false
-
-require_relative "../helper"
-
-class TestCSVParseColumnSeparator < Test::Unit::TestCase
- extend DifferentOFS
-
- def test_comma
- assert_equal([["a", "b", nil, "d"]],
- CSV.parse("a,b,,d", col_sep: ","))
- end
-
- def test_space
- assert_equal([["a", "b", nil, "d"]],
- CSV.parse("a b d", col_sep: " "))
- end
-
- def test_tab
- assert_equal([["a", "b", nil, "d"]],
- CSV.parse("a\tb\t\td", col_sep: "\t"))
- end
-
- def test_multiple_characters_include_sub_separator
- assert_equal([["a b", nil, "d"]],
- CSV.parse("a b d", col_sep: " "))
- end
-
- def test_multiple_characters_leading_empty_fields
- data = <<-CSV
-<=><=>A<=>B<=>C
-1<=>2<=>3
- CSV
- assert_equal([
- [nil, nil, "A", "B", "C"],
- ["1", "2", "3"],
- ],
- CSV.parse(data, col_sep: "<=>"))
- end
-end
diff --git a/test/csv/parse/test_convert.rb b/test/csv/parse/test_convert.rb
deleted file mode 100644
index bfe6ddd527..0000000000
--- a/test/csv/parse/test_convert.rb
+++ /dev/null
@@ -1,110 +0,0 @@
-# -*- coding: utf-8 -*-
-# frozen_string_literal: false
-
-require_relative "../helper"
-
-class TestCSVParseConvert < Test::Unit::TestCase
- extend DifferentOFS
-
- def setup
- super
- @data = "Numbers,:integer,1,:float,3.015"
- @parser = CSV.new(@data)
-
- @custom = lambda {|field| /\A:(\S.*?)\s*\Z/ =~ field ? $1.to_sym : field}
-
- @time = Time.utc(2018, 12, 30, 6, 41, 29)
- @windows_safe_time_data = @time.strftime("%a %b %d %H:%M:%S %Y")
- end
-
- def test_integer
- @parser.convert(:integer)
- assert_equal(["Numbers", ":integer", 1, ":float", "3.015"],
- @parser.shift)
- end
-
- def test_float
- @parser.convert(:float)
- assert_equal(["Numbers", ":integer", 1.0, ":float", 3.015],
- @parser.shift)
- end
-
- def test_float_integer
- @parser.convert(:float)
- @parser.convert(:integer)
- assert_equal(["Numbers", ":integer", 1.0, ":float", 3.015],
- @parser.shift)
- end
-
- def test_integer_float
- @parser.convert(:integer)
- @parser.convert(:float)
- assert_equal(["Numbers", ":integer", 1, ":float", 3.015],
- @parser.shift)
- end
-
- def test_numberic
- @parser.convert(:numeric)
- assert_equal(["Numbers", ":integer", 1, ":float", 3.015],
- @parser.shift)
- end
-
- def test_all
- @data << ",#{@windows_safe_time_data}"
- @parser = CSV.new(@data)
- @parser.convert(:all)
- assert_equal(["Numbers", ":integer", 1, ":float", 3.015, @time.to_datetime],
- @parser.shift)
- end
-
- def test_custom
- @parser.convert do |field|
- /\A:(\S.*?)\s*\Z/ =~ field ? $1.to_sym : field
- end
- assert_equal(["Numbers", :integer, "1", :float, "3.015"],
- @parser.shift)
- end
-
- def test_builtin_custom
- @parser.convert(:numeric)
- @parser.convert(&@custom)
- assert_equal(["Numbers", :integer, 1, :float, 3.015],
- @parser.shift)
- end
-
- def test_custom_field_info_line
- @parser.convert do |field, info|
- assert_equal(1, info.line)
- info.index == 4 ? Float(field).floor : field
- end
- assert_equal(["Numbers", ":integer", "1", ":float", 3],
- @parser.shift)
- end
-
- def test_custom_field_info_header
- headers = ["one", "two", "three", "four", "five"]
- @parser = CSV.new(@data, headers: headers)
- @parser.convert do |field, info|
- info.header == "three" ? Integer(field) * 100 : field
- end
- assert_equal(CSV::Row.new(headers,
- ["Numbers", ":integer", 100, ":float", "3.015"]),
- @parser.shift)
- end
-
- def test_custom_blank_field
- converter = lambda {|field| field.nil?}
- row = CSV.parse_line('nil,', converters: converter)
- assert_equal([false, true], row)
- end
-
- def test_nil_value
- assert_equal(["nil", "", "a"],
- CSV.parse_line(',"",a', nil_value: "nil"))
- end
-
- def test_empty_value
- assert_equal([nil, "empty", "a"],
- CSV.parse_line(',"",a', empty_value: "empty"))
- end
-end
diff --git a/test/csv/parse/test_each.rb b/test/csv/parse/test_each.rb
deleted file mode 100644
index ce0b71d058..0000000000
--- a/test/csv/parse/test_each.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# -*- coding: utf-8 -*-
-# frozen_string_literal: false
-
-require_relative "../helper"
-
-class TestCSVParseEach < Test::Unit::TestCase
- extend DifferentOFS
-
- def test_twice
- data = <<-CSV
-Ruby,2.6.0,script
- CSV
- csv = CSV.new(data)
- assert_equal([
- [["Ruby", "2.6.0", "script"]],
- [],
- ],
- [
- csv.to_a,
- csv.to_a,
- ])
- end
-end
diff --git a/test/csv/parse/test_general.rb b/test/csv/parse/test_general.rb
deleted file mode 100644
index 14903d462c..0000000000
--- a/test/csv/parse/test_general.rb
+++ /dev/null
@@ -1,259 +0,0 @@
-# -*- coding: utf-8 -*-
-# frozen_string_literal: false
-
-require "timeout"
-
-require_relative "../helper"
-
-#
-# 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 TestCSVParseGeneral < Test::Unit::TestCase
- extend DifferentOFS
-
- BIG_DATA = "123456789\n" * 1024
-
- 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_rob_edge_cases
- [ [%Q{"a\nb"}, ["a\nb"]],
- [%Q{"\n\n\n"}, ["\n\n\n"]],
- [%Q{a,"b\n\nc"}, ['a', "b\n\nc"]],
- [%Q{,"\r\n"}, [nil,"\r\n"]],
- [%Q{,"\r\n."}, [nil,"\r\n."]],
- [%Q{"a\na","one newline"}, ["a\na", 'one newline']],
- [%Q{"a\n\na","two newlines"}, ["a\n\na", 'two newlines']],
- [%Q{"a\r\na","one CRLF"}, ["a\r\na", 'one CRLF']],
- [%Q{"a\r\n\r\na","two CRLFs"}, ["a\r\n\r\na", 'two CRLFs']],
- [%Q{with blank,"start\n\nfinish"\n}, ['with blank', "start\n\nfinish"]],
- ].each do |edge_case|
- assert_equal(edge_case.last, CSV.parse_line(edge_case.first))
- end
- end
-
- def test_non_regex_edge_cases
- # An early version of the non-regex parser fails this test
- [ [ "foo,\"foo,bar,baz,foo\",\"foo\"",
- ["foo", "foo,bar,baz,foo", "foo"] ] ].each do |edge_case|
- assert_equal(edge_case.last, CSV.parse_line(edge_case.first))
- end
-
- assert_raise(CSV::MalformedCSVError) do
- CSV.parse_line("1,\"23\"4\"5\", 6")
- end
- end
-
- def test_malformed_csv_cr_first_line
- error = assert_raise(CSV::MalformedCSVError) do
- CSV.parse_line("1,2\r,3", row_sep: "\n")
- end
- assert_equal("Unquoted fields do not allow new line <\"\\r\"> in line 1.",
- error.message)
- end
-
- def test_malformed_csv_cr_middle_line
- csv = <<-CSV
-line,1,abc
-line,2,"def\nghi"
-
-line,4,some\rjunk
-line,5,jkl
- CSV
-
- error = assert_raise(CSV::MalformedCSVError) do
- CSV.parse(csv)
- end
- assert_equal("Unquoted fields do not allow new line <\"\\r\"> in line 4.",
- error.message)
- end
-
- def test_malformed_csv_unclosed_quote
- error = assert_raise(CSV::MalformedCSVError) do
- CSV.parse_line('1,2,"3...')
- end
- assert_equal("Unclosed quoted field in line 1.",
- error.message)
- end
-
- def test_malformed_csv_illegal_quote_middle_line
- csv = <<-CSV
-line,1,abc
-line,2,"def\nghi"
-
-line,4,8'10"
-line,5,jkl
- CSV
-
- error = assert_raise(CSV::MalformedCSVError) do
- CSV.parse(csv)
- end
- assert_equal("Illegal quoting in line 4.",
- error.message)
- end
-
- def test_the_parse_fails_fast_when_it_can_for_unquoted_fields
- assert_parse_errors_out('valid,fields,bad start"' + BIG_DATA)
- end
-
- def test_the_parse_fails_fast_when_it_can_for_unescaped_quotes
- assert_parse_errors_out('valid,fields,"bad start"unescaped' + BIG_DATA)
- end
-
- def test_field_size_limit_controls_lookahead
- assert_parse_errors_out( 'valid,fields,"' + BIG_DATA + '"',
- field_size_limit: 2048 )
- end
-
- def test_field_size_limit_in_extended_column_not_exceeding
- data = <<~DATA
- "a","b"
- "
- 2
- ",""
- DATA
- assert_nothing_raised(CSV::MalformedCSVError) do
- CSV.parse(data, field_size_limit: 4)
- end
- end
-
- def test_field_size_limit_in_extended_column_exceeding
- data = <<~DATA
- "a","b"
- "
- 2345
- ",""
- DATA
- assert_parse_errors_out(data, field_size_limit: 5)
- end
-
- def test_row_sep_auto_cr
- assert_equal([["a"]], CSV.parse("a\r"))
- end
-
- def test_row_sep_auto_lf
- assert_equal([["a"]], CSV.parse("a\n"))
- end
-
- def test_row_sep_auto_cr_lf
- assert_equal([["a"]], CSV.parse("a\r\n"))
- end
-
- def test_seeked_string_io
- input_with_bom = StringIO.new("\ufeffã‚,ã„,ã†\r\na,b,c\r\n")
- input_with_bom.read(3)
- assert_equal([
- ["ã‚", "ã„", "ã†"],
- ["a", "b", "c"],
- ],
- CSV.new(input_with_bom).each.to_a)
- end
-
- private
- def assert_parse_errors_out(data, **options)
- assert_raise(CSV::MalformedCSVError) do
- timeout = 0.2
- if defined?(RubyVM::JIT.enabled?) and RubyVM::JIT.enabled?
- timeout = 5 # for --jit-wait
- end
- Timeout.timeout(timeout) do
- CSV.parse(data, **options)
- fail("Parse didn't error out")
- end
- end
- end
-end
diff --git a/test/csv/parse/test_header.rb b/test/csv/parse/test_header.rb
deleted file mode 100644
index 481c5107c6..0000000000
--- a/test/csv/parse/test_header.rb
+++ /dev/null
@@ -1,335 +0,0 @@
-# -*- coding: utf-8 -*-
-# frozen_string_literal: false
-
-require_relative "../helper"
-
-class TestCSVHeaders < Test::Unit::TestCase
- extend DifferentOFS
-
- def setup
- super
- @data = <<-CSV
-first,second,third
-A,B,C
-1,2,3
- 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_predicate(row, :header_row?)
- assert_not_predicate(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_predicate(row, :header_row?)
- assert_not_predicate(row, :field_row?)
- end
-
- def test_csv_header_string_inherits_separators
- # parse with custom col_sep
- csv = nil
- assert_nothing_raised(Exception) do
- csv = CSV.parse( @data.tr(",", "|"), col_sep: "|",
- headers: "my|new|headers" )
- end
-
- # verify headers were recognized
- 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)
- 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_predicate(row, :header_row?)
- assert_not_predicate(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_not_predicate(row, :header_row?)
- assert_predicate(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_not_predicate(row, :header_row?)
- assert_predicate(row, :field_row?)
-
- # empty
- assert_nil(csv[3])
- end
-
- def test_converters
- # create test data where headers and fields look alike
- data = <<-CSV
-1,2,3
-1,2,3
- 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
- # Note that the trailing space is intentional
- csv = CSV.parse( "One,TWO Three ", headers: true,
- return_headers: true,
- header_converters: :symbol )
- assert_equal([:one, :two_three], csv.headers)
- end
-
- def test_builtin_symbol_converter_with_punctuation
- csv = CSV.parse( "One, Two & Three ($)", headers: true,
- return_headers: true,
- header_converters: :symbol )
- assert_equal([:one, :two_three], csv.headers)
- end
-
- def test_builtin_converters_with_blank_header
- csv = CSV.parse( "one,,three", headers: true,
- return_headers: true,
- header_converters: [:downcase, :symbol] )
- assert_equal([:one, nil, :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 = <<-CSV
-
-
-A,B,C
-
-1,2,3
-
-
-
- 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_headers_reader
- # no headers
- assert_nil(CSV.new(@data).headers)
-
- # headers
- csv = CSV.new(@data, headers: true)
- assert_equal(true, csv.headers) # before headers are read
- csv.shift # set headers
- assert_equal(%w[first second third], csv.headers) # after headers are read
- end
-
- def test_blank_row
- @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
-
- def test_nil_row_header
- @data = <<-CSV
-A
-
-1
- CSV
-
- csv = CSV.parse(@data, headers: true)
-
- # ensure nil row creates Row object with headers
- row = csv[0]
- assert_equal([["A"], [nil]],
- [row.headers, row.fields])
- end
-
- def test_parse_empty
- assert_equal(CSV::Table.new([]),
- CSV.parse("", headers: true))
- end
-
- def test_parse_empty_line
- assert_equal(CSV::Table.new([]),
- CSV.parse("\n", headers: true))
- end
-
- def test_specified_empty
- assert_equal(CSV::Table.new([],
- headers: ["header1"]),
- CSV.parse("", headers: ["header1"]))
- end
-
- def test_specified_empty_line
- assert_equal(CSV::Table.new([CSV::Row.new(["header1"], [])],
- headers: ["header1"]),
- CSV.parse("\n", headers: ["header1"]))
- end
-end
diff --git a/test/csv/parse/test_invalid.rb b/test/csv/parse/test_invalid.rb
deleted file mode 100644
index 9dfd081380..0000000000
--- a/test/csv/parse/test_invalid.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# -*- coding: utf-8 -*-
-# frozen_string_literal: false
-
-require_relative "../helper"
-
-class TestCSVParseInvalid < Test::Unit::TestCase
- def test_no_column_mixed_new_lines
- error = assert_raise(CSV::MalformedCSVError) do
- CSV.parse("\n" +
- "\r")
- end
- assert_equal("New line must be <\"\\n\"> not <\"\\r\"> in line 2.",
- error.message)
- end
-
- def test_ignore_invalid_line
- csv = CSV.new(<<-CSV, headers: true, return_headers: true)
-head1,head2,head3
-aaa,bbb,ccc
-ddd,ee"e.fff
-ggg,hhh,iii
- CSV
- headers = ["head1", "head2", "head3"]
- assert_equal(CSV::Row.new(headers, headers),
- csv.shift)
- assert_equal(CSV::Row.new(headers, ["aaa", "bbb", "ccc"]),
- csv.shift)
- assert_equal(false, csv.eof?)
- error = assert_raise(CSV::MalformedCSVError) do
- csv.shift
- end
- assert_equal("Illegal quoting in line 3.",
- error.message)
- assert_equal(false, csv.eof?)
- assert_equal(CSV::Row.new(headers, ["ggg", "hhh", "iii"]),
- csv.shift)
- assert_equal(true, csv.eof?)
- end
-end
diff --git a/test/csv/parse/test_liberal_parsing.rb b/test/csv/parse/test_liberal_parsing.rb
deleted file mode 100644
index 2f7b34689f..0000000000
--- a/test/csv/parse/test_liberal_parsing.rb
+++ /dev/null
@@ -1,160 +0,0 @@
-# -*- coding: utf-8 -*-
-# frozen_string_literal: false
-
-require_relative "../helper"
-
-class TestCSVParseLiberalParsing < Test::Unit::TestCase
- extend DifferentOFS
-
- def test_middle_quote_start
- input = '"Johnson, Dwayne",Dwayne "The Rock" Johnson'
- error = assert_raise(CSV::MalformedCSVError) do
- CSV.parse_line(input)
- end
- assert_equal("Illegal quoting in line 1.",
- error.message)
- assert_equal(["Johnson, Dwayne", 'Dwayne "The Rock" Johnson'],
- CSV.parse_line(input, liberal_parsing: true))
- end
-
- def test_middle_quote_end
- input = '"quoted" field'
- error = assert_raise(CSV::MalformedCSVError) do
- CSV.parse_line(input)
- end
- assert_equal("Any value after quoted field isn't allowed in line 1.",
- error.message)
- assert_equal(['"quoted" field'],
- CSV.parse_line(input, liberal_parsing: true))
- end
-
- def test_quote_after_column_separator
- error = assert_raise(CSV::MalformedCSVError) do
- CSV.parse_line('is,this "three," or four,fields', liberal_parsing: true)
- end
- assert_equal("Unclosed quoted field in line 1.",
- error.message)
- end
-
- def test_quote_before_column_separator
- assert_equal(["is", 'this "three', ' or four"', "fields"],
- CSV.parse_line('is,this "three, or four",fields',
- liberal_parsing: true))
- end
-
- def test_backslash_quote
- assert_equal([
- "1",
- "\"Hamlet says, \\\"Seems",
- "\\\" madam! Nay it is; I know not \\\"seems.\\\"\"",
- ],
- CSV.parse_line('1,' +
- '"Hamlet says, \"Seems,' +
- '\" madam! Nay it is; I know not \"seems.\""',
- liberal_parsing: true))
- end
-
- def test_space_quote
- input = <<~CSV
- Los Angeles, 34°03'N, 118°15'W
- New York City, 40°42'46"N, 74°00'21"W
- Paris, 48°51'24"N, 2°21'03"E
- CSV
- assert_equal(
- [
- ["Los Angeles", " 34°03'N", " 118°15'W"],
- ["New York City", " 40°42'46\"N", " 74°00'21\"W"],
- ["Paris", " 48°51'24\"N", " 2°21'03\"E"],
- ],
- CSV.parse(input, liberal_parsing: true))
- end
-
- def test_double_quote_outside_quote
- data = %Q{a,""b""}
- error = assert_raise(CSV::MalformedCSVError) do
- CSV.parse(data)
- end
- assert_equal("Any value after quoted field isn't allowed in line 1.",
- error.message)
- assert_equal([
- [["a", %Q{""b""}]],
- [["a", %Q{"b"}]],
- ],
- [
- CSV.parse(data, liberal_parsing: true),
- CSV.parse(data,
- liberal_parsing: {
- double_quote_outside_quote: true,
- }),
- ])
- end
-
- class TestBackslashQuote < Test::Unit::TestCase
- extend ::DifferentOFS
-
- def test_double_quote_outside_quote
- data = %Q{a,""b""}
- assert_equal([
- [["a", %Q{""b""}]],
- [["a", %Q{"b"}]],
- ],
- [
- CSV.parse(data,
- liberal_parsing: {
- backslash_quote: true
- }),
- CSV.parse(data,
- liberal_parsing: {
- backslash_quote: true,
- double_quote_outside_quote: true
- }),
- ])
- end
-
- def test_unquoted_value
- data = %q{\"\"a\"\"}
- assert_equal([
- [[%q{\"\"a\"\"}]],
- [[%q{""a""}]],
- ],
- [
- CSV.parse(data, liberal_parsing: true),
- CSV.parse(data,
- liberal_parsing: {
- backslash_quote: true
- }),
- ])
- end
-
- def test_unquoted_value_multiple_characters_col_sep
- data = %q{a<\\"b<=>x}
- assert_equal([[%Q{a<"b}, "x"]],
- CSV.parse(data,
- col_sep: "<=>",
- liberal_parsing: {
- backslash_quote: true
- }))
- end
-
- def test_quoted_value
- data = %q{"\"\"a\"\""}
- assert_equal([
- [[%q{"\"\"a\"\""}]],
- [[%q{""a""}]],
- [[%q{""a""}]],
- ],
- [
- CSV.parse(data, liberal_parsing: true),
- CSV.parse(data,
- liberal_parsing: {
- backslash_quote: true
- }),
- CSV.parse(data,
- liberal_parsing: {
- backslash_quote: true,
- double_quote_outside_quote: true
- }),
- ])
- end
- end
-end
diff --git a/test/csv/parse/test_quote_char_nil.rb b/test/csv/parse/test_quote_char_nil.rb
deleted file mode 100644
index fc3b646759..0000000000
--- a/test/csv/parse/test_quote_char_nil.rb
+++ /dev/null
@@ -1,93 +0,0 @@
-# -*- coding: utf-8 -*-
-# frozen_string_literal: false
-
-require_relative "../helper"
-
-class TestCSVParseQuoteCharNil < Test::Unit::TestCase
- extend DifferentOFS
-
- def test_full
- assert_equal(["a", "b"], CSV.parse_line(%Q{a,b}, quote_char: nil))
- end
-
- def test_end_with_nil
- assert_equal(["a", nil, nil, nil], CSV.parse_line(%Q{a,,,}, quote_char: nil))
- end
-
- def test_nil_nil
- assert_equal([nil, nil], CSV.parse_line(%Q{,}, quote_char: nil))
- end
-
- def test_unquoted_value_multiple_characters_col_sep
- data = %q{a<b<=>x}
- assert_equal([[%Q{a<b}, "x"]], CSV.parse(data, col_sep: "<=>", quote_char: nil))
- end
-
- def test_csv_header_string
- data = <<~DATA
- first,second,third
- A,B,C
- 1,2,3
- DATA
- assert_equal(
- CSV::Table.new([
- CSV::Row.new(["my", "new", "headers"], ["first", "second", "third"]),
- CSV::Row.new(["my", "new", "headers"], ["A", "B", "C"]),
- CSV::Row.new(["my", "new", "headers"], ["1", "2", "3"])
- ]),
- CSV.parse(data, headers: "my,new,headers", quote_char: nil)
- )
- end
-
- def test_comma
- assert_equal([["a", "b", nil, "d"]],
- CSV.parse("a,b,,d", col_sep: ",", quote_char: nil))
- end
-
- def test_space
- assert_equal([["a", "b", nil, "d"]],
- CSV.parse("a b d", col_sep: " ", quote_char: nil))
- end
-
- def encode_array(array, encoding)
- array.collect do |element|
- element ? element.encode(encoding) : element
- end
- end
-
- def test_space_no_ascii
- encoding = Encoding::UTF_16LE
- assert_equal([encode_array(["a", "b", nil, "d"], encoding)],
- CSV.parse("a b d".encode(encoding),
- col_sep: " ".encode(encoding),
- quote_char: nil))
- end
-
- def test_multiple_space
- assert_equal([["a b", nil, "d"]],
- CSV.parse("a b d", col_sep: " ", quote_char: nil))
- end
-
- def test_multiple_characters_leading_empty_fields
- data = <<-CSV
-<=><=>A<=>B<=>C
-1<=>2<=>3
- CSV
- assert_equal([
- [nil, nil, "A", "B", "C"],
- ["1", "2", "3"],
- ],
- CSV.parse(data, col_sep: "<=>", quote_char: nil))
- end
-
- def test_line
- lines = [
- "abc,def\n",
- ]
- csv = CSV.new(lines.join(""), quote_char: nil)
- lines.each do |line|
- csv.shift
- assert_equal(line, csv.line)
- end
- end
-end
diff --git a/test/csv/parse/test_rewind.rb b/test/csv/parse/test_rewind.rb
deleted file mode 100644
index 0aa403b756..0000000000
--- a/test/csv/parse/test_rewind.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-# -*- coding: utf-8 -*-
-# frozen_string_literal: false
-
-require_relative "../helper"
-
-class TestCSVParseRewind < Test::Unit::TestCase
- extend DifferentOFS
-
- def parse(data, **options)
- csv = CSV.new(data, **options)
- records = csv.to_a
- csv.rewind
- [records, csv.to_a]
- end
-
- def test_default
- data = <<-CSV
-Ruby,2.6.0,script
- CSV
- assert_equal([
- [["Ruby", "2.6.0", "script"]],
- [["Ruby", "2.6.0", "script"]],
- ],
- parse(data))
- end
-
- def test_have_headers
- data = <<-CSV
-Language,Version,Type
-Ruby,2.6.0,script
- CSV
- assert_equal([
- [CSV::Row.new(["Language", "Version", "Type"],
- ["Ruby", "2.6.0", "script"])],
- [CSV::Row.new(["Language", "Version", "Type"],
- ["Ruby", "2.6.0", "script"])],
- ],
- parse(data, headers: true))
- end
-end
diff --git a/test/csv/parse/test_row_separator.rb b/test/csv/parse/test_row_separator.rb
deleted file mode 100644
index eaf6adc910..0000000000
--- a/test/csv/parse/test_row_separator.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# -*- coding: utf-8 -*-
-# frozen_string_literal: false
-
-require_relative "../helper"
-
-class TestCSVParseRowSeparator < Test::Unit::TestCase
- extend DifferentOFS
- include Helper
-
- def test_multiple_characters
- with_chunk_size("1") do
- assert_equal([["a"], ["b"]],
- CSV.parse("a\r\nb\r\n", row_sep: "\r\n"))
- end
- end
-end
diff --git a/test/csv/parse/test_skip_lines.rb b/test/csv/parse/test_skip_lines.rb
deleted file mode 100644
index 98d67ae51c..0000000000
--- a/test/csv/parse/test_skip_lines.rb
+++ /dev/null
@@ -1,118 +0,0 @@
-# frozen_string_literal: false
-
-require_relative "../helper"
-
-class TestCSVParseSkipLines < Test::Unit::TestCase
- extend DifferentOFS
- include Helper
-
- def test_default
- csv = CSV.new("a,b,c\n")
- assert_nil(csv.skip_lines)
- end
-
- def test_regexp
- csv = <<-CSV
-1
-#2
- #3
-4
- CSV
- assert_equal([
- ["1"],
- ["4"],
- ],
- CSV.parse(csv, :skip_lines => /\A\s*#/))
- end
-
- def test_regexp_quoted
- csv = <<-CSV
-1
-#2
-"#3"
-4
- CSV
- assert_equal([
- ["1"],
- ["#3"],
- ["4"],
- ],
- CSV.parse(csv, :skip_lines => /\A\s*#/))
- end
-
- def test_string
- csv = <<-CSV
-1
-.2
-3.
-4
- CSV
- assert_equal([
- ["1"],
- ["4"],
- ],
- CSV.parse(csv, :skip_lines => "."))
- end
-
- class RegexStub
- end
-
- def test_not_matchable
- regex_stub = RegexStub.new
- csv = CSV.new("1\n", :skip_lines => regex_stub)
- error = assert_raise(ArgumentError) do
- csv.shift
- end
- assert_equal(":skip_lines has to respond to #match: #{regex_stub.inspect}",
- error.message)
- end
-
- class Matchable
- def initialize(pattern)
- @pattern = pattern
- end
-
- def match(line)
- @pattern.match(line)
- end
- end
-
- def test_matchable
- csv = <<-CSV
-1
-# 2
-3
-# 4
- CSV
- assert_equal([
- ["1"],
- ["3"],
- ],
- CSV.parse(csv, :skip_lines => Matchable.new(/\A#/)))
- end
-
- def test_multibyte_data
- # U+3042 HIRAGANA LETTER A
- # U+3044 HIRAGANA LETTER I
- # U+3046 HIRAGANA LETTER U
- value = "\u3042\u3044\u3046"
- with_chunk_size("5") do
- assert_equal([[value], [value]],
- CSV.parse("#{value}\n#{value}\n",
- :skip_lines => /\A#/))
- end
- end
-
- def test_empty_line_and_liberal_parsing
- assert_equal([["a", "b"]],
- CSV.parse("a,b\n",
- :liberal_parsing => true,
- :skip_lines => /^$/))
- end
-
- def test_crlf
- assert_equal([["a", "b"]],
- CSV.parse("a,b\r\n,\r\n",
- :skip_lines => /^,+$/))
- end
-end
diff --git a/test/csv/parse/test_strip.rb b/test/csv/parse/test_strip.rb
deleted file mode 100644
index 3564fcb3ba..0000000000
--- a/test/csv/parse/test_strip.rb
+++ /dev/null
@@ -1,83 +0,0 @@
-# -*- coding: utf-8 -*-
-# frozen_string_literal: false
-
-require_relative "../helper"
-
-class TestCSVParseStrip < Test::Unit::TestCase
- extend DifferentOFS
-
- def test_both
- assert_equal(["a", "b"],
- CSV.parse_line(%Q{ a , b }, strip: true))
- end
-
- def test_left
- assert_equal(["a", "b"],
- CSV.parse_line(%Q{ a, b}, strip: true))
- end
-
- def test_right
- assert_equal(["a", "b"],
- CSV.parse_line(%Q{a ,b }, strip: true))
- end
-
- def test_middle
- assert_equal(["a b"],
- CSV.parse_line(%Q{a b}, strip: true))
- end
-
- def test_quoted
- assert_equal([" a ", " b "],
- CSV.parse_line(%Q{" a "," b "}, strip: true))
- end
-
- def test_liberal_parsing
- assert_equal([" a ", "b", " c ", " d "],
- CSV.parse_line(%Q{" a ", b , " c "," d " },
- strip: true,
- liberal_parsing: true))
- end
-
- def test_string
- assert_equal(["a", " b"],
- CSV.parse_line(%Q{ a , " b" },
- strip: " "))
- end
-
- def test_no_quote
- assert_equal([" a ", " b "],
- CSV.parse_line(%Q{" a ", b },
- strip: %Q{"},
- quote_char: nil))
- end
-
- def test_do_not_strip_cr
- assert_equal([
- ["a", "b "],
- ["a", "b "],
- ],
- CSV.parse(%Q{"a" ,"b " \r} +
- %Q{"a" ,"b " \r},
- strip: true))
- end
-
- def test_do_not_strip_lf
- assert_equal([
- ["a", "b "],
- ["a", "b "],
- ],
- CSV.parse(%Q{"a" ,"b " \n} +
- %Q{"a" ,"b " \n},
- strip: true))
- end
-
- def test_do_not_strip_crlf
- assert_equal([
- ["a", "b "],
- ["a", "b "],
- ],
- CSV.parse(%Q{"a" ,"b " \r\n} +
- %Q{"a" ,"b " \r\n},
- strip: true))
- end
-end
diff --git a/test/csv/parse/test_unconverted_fields.rb b/test/csv/parse/test_unconverted_fields.rb
deleted file mode 100644
index 437124ebd3..0000000000
--- a/test/csv/parse/test_unconverted_fields.rb
+++ /dev/null
@@ -1,117 +0,0 @@
-# -*- coding: utf-8 -*-
-# frozen_string_literal: false
-
-require_relative "../helper"
-
-class TestCSVParseUnconvertedFields < Test::Unit::TestCase
- extend DifferentOFS
-
- def setup
- super
- @custom = lambda {|field| /\A:(\S.*?)\s*\Z/ =~ field ? $1.to_sym : field}
-
- @headers = ["first", "second", "third"]
- @data = <<-CSV
-first,second,third
-1,2,3
- CSV
- end
-
-
- def test_custom
- row = CSV.parse_line("Numbers,:integer,1,:float,3.015",
- converters: [:numeric, @custom],
- unconverted_fields: true)
- assert_equal([
- ["Numbers", :integer, 1, :float, 3.015],
- ["Numbers", ":integer", "1", ":float", "3.015"],
- ],
- [
- row,
- row.unconverted_fields,
- ])
- end
-
- def test_no_fields
- row = CSV.parse_line("\n",
- converters: [:numeric, @custom],
- unconverted_fields: true)
- assert_equal([
- [],
- [],
- ],
- [
- row,
- row.unconverted_fields,
- ])
- end
-
- def test_parsed_header
- row = CSV.parse_line(@data,
- converters: :numeric,
- unconverted_fields: true,
- headers: :first_row)
- assert_equal([
- CSV::Row.new(@headers,
- [1, 2, 3]),
- ["1", "2", "3"],
- ],
- [
- row,
- row.unconverted_fields,
- ])
- end
-
- def test_return_headers
- row = CSV.parse_line(@data,
- converters: :numeric,
- unconverted_fields: true,
- headers: :first_row,
- return_headers: true)
- assert_equal([
- CSV::Row.new(@headers,
- @headers),
- @headers,
- ],
- [
- row,
- row.unconverted_fields,
- ])
- end
-
- def test_header_converters
- row = CSV.parse_line(@data,
- converters: :numeric,
- unconverted_fields: true,
- headers: :first_row,
- return_headers: true,
- header_converters: :symbol)
- assert_equal([
- CSV::Row.new(@headers.collect(&:to_sym),
- @headers),
- @headers,
- ],
- [
- row,
- row.unconverted_fields,
- ])
- end
-
- def test_specified_headers
- row = CSV.parse_line("\n",
- converters: :numeric,
- unconverted_fields: true,
- headers: %w{my new headers},
- return_headers: true,
- header_converters: :symbol)
- assert_equal([
- CSV::Row.new([:my, :new, :headers],
- ["my", "new", "headers"]),
- [],
- ],
- [
- row,
- row.unconverted_fields,
- ])
- end
-end
diff --git a/test/csv/test_data_converters.rb b/test/csv/test_data_converters.rb
deleted file mode 100644
index 1620e077be..0000000000
--- a/test/csv/test_data_converters.rb
+++ /dev/null
@@ -1,106 +0,0 @@
-# -*- coding: utf-8 -*-
-# frozen_string_literal: false
-
-require_relative "helper"
-
-class TestCSVDataConverters < Test::Unit::TestCase
- extend DifferentOFS
-
- def setup
- super
- @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_builtin_date_time_converter_iso8601_date
- iso8601_string = "2018-01-14"
- datetime = DateTime.new(2018, 1, 14)
- assert_equal(datetime,
- CSV::Converters[:date_time][iso8601_string])
- end
-
- def test_builtin_date_time_converter_iso8601_minute
- iso8601_string = "2018-01-14T22:25"
- datetime = DateTime.new(2018, 1, 14, 22, 25)
- assert_equal(datetime,
- CSV::Converters[:date_time][iso8601_string])
- end
-
- def test_builtin_date_time_converter_iso8601_second
- iso8601_string = "2018-01-14T22:25:19"
- datetime = DateTime.new(2018, 1, 14, 22, 25, 19)
- assert_equal(datetime,
- CSV::Converters[:date_time][iso8601_string])
- end
-
- def test_builtin_date_time_converter_iso8601_under_second
- iso8601_string = "2018-01-14T22:25:19.1"
- datetime = DateTime.new(2018, 1, 14, 22, 25, 19.1)
- assert_equal(datetime,
- CSV::Converters[:date_time][iso8601_string])
- end
-
- def test_builtin_date_time_converter_iso8601_under_second_offset
- iso8601_string = "2018-01-14T22:25:19.1+09:00"
- datetime = DateTime.new(2018, 1, 14, 22, 25, 19.1, "+9")
- assert_equal(datetime,
- CSV::Converters[:date_time][iso8601_string])
- end
-
- def test_builtin_date_time_converter_iso8601_offset
- iso8601_string = "2018-01-14T22:25:19+09:00"
- datetime = DateTime.new(2018, 1, 14, 22, 25, 19, "+9")
- assert_equal(datetime,
- CSV::Converters[:date_time][iso8601_string])
- end
-
- def test_builtin_date_time_converter_iso8601_utc
- iso8601_string = "2018-01-14T22:25:19Z"
- datetime = DateTime.new(2018, 1, 14, 22, 25, 19)
- assert_equal(datetime,
- CSV::Converters[:date_time][iso8601_string])
- end
-end
diff --git a/test/csv/test_encodings.rb b/test/csv/test_encodings.rb
deleted file mode 100644
index 8d228c05f3..0000000000
--- a/test/csv/test_encodings.rb
+++ /dev/null
@@ -1,372 +0,0 @@
-# -*- coding: utf-8 -*-
-# frozen_string_literal: false
-
-require_relative "helper"
-
-class TestCSVEncodings < Test::Unit::TestCase
- extend DifferentOFS
- include Helper
-
- def setup
- super
- require 'tempfile'
- @temp_csv_file = Tempfile.new(%w"test_csv. .csv")
- @temp_csv_path = @temp_csv_file.path
- @temp_csv_file.close
- end
-
- def teardown
- @temp_csv_file.close!
- super
- end
-
- ########################################
- ### Hand Test Some Popular Encodings ###
- ########################################
-
- def test_parses_utf8_encoding
- assert_parses( [ %w[ one two … ],
- %w[ 1 … 3 ],
- %w[ … 5 6 ] ], "UTF-8" )
- end
-
- def test_parses_latin1_encoding
- assert_parses( [ %w[ one two Résumé ],
- %w[ 1 Résumé 3 ],
- %w[ Résumé 5 6 ] ], "ISO-8859-1" )
- end
-
- def test_parses_utf16be_encoding
- assert_parses( [ %w[ one two … ],
- %w[ 1 … 3 ],
- %w[ … 5 6 ] ], "UTF-16BE" )
- end
-
- def test_parses_shift_jis_encoding
- assert_parses( [ %w[ 一 二 三 ],
- %w[ 四 五 六 ],
- %w[ 七 å…« ä¹ ] ], "Shift_JIS" )
- end
-
- ###########################################################
- ### Try Simple Reading for All Non-dummy Ruby Encodings ###
- ###########################################################
-
- def test_reading_with_most_encodings
- each_encoding do |encoding|
- begin
- assert_parses( [ %w[ abc def ],
- %w[ ghi jkl ] ], encoding )
- rescue Encoding::ConverterNotFoundError
- fail("Failed to support #{encoding.name}.")
- end
- end
- end
-
- def test_regular_expression_escaping
- each_encoding do |encoding|
- begin
- assert_parses( [ %w[ abc def ],
- %w[ ghi jkl ] ], encoding, col_sep: "|" )
- rescue Encoding::ConverterNotFoundError
- fail("Failed to properly escape #{encoding.name}.")
- end
- end
- end
-
- def test_read_with_default_encoding
- data = "abc"
- default_external = Encoding.default_external
- each_encoding do |encoding|
- File.open(@temp_csv_path, "wb", encoding: encoding) {|f| f << data}
- begin
- no_warnings do
- Encoding.default_external = encoding
- end
- result = CSV.read(@temp_csv_path)[0][0]
- ensure
- no_warnings do
- Encoding.default_external = default_external
- end
- end
- assert_equal(encoding, result.encoding)
- end
- end
-
- #######################################################################
- ### Stress Test ASCII Compatible and Non-ASCII Compatible Encodings ###
- #######################################################################
-
- def test_auto_line_ending_detection
- # arrange data to place a \r at the end of CSV's read ahead point
- encode_for_tests([["a" * 509]], row_sep: "\r\n") do |data|
- assert_equal("\r\n".encode(data.encoding), CSV.new(data).row_sep)
- end
- end
-
- def test_csv_chars_are_transcoded
- encode_for_tests([%w[abc def]]) do |data|
- %w[col_sep row_sep quote_char].each do |csv_char|
- assert_equal( "|".encode(data.encoding),
- CSV.new(data, csv_char.to_sym => "|").send(csv_char) )
- end
- end
- end
-
- def test_parser_works_with_encoded_headers
- encode_for_tests([%w[one two three], %w[1 2 3]]) do |data|
- parsed = CSV.parse(data, headers: true)
- assert_all?(parsed.headers, "Wrong data encoding.") {|h| h.encoding == data.encoding}
- parsed.each do |row|
- assert_all?(row.fields, "Wrong data encoding.") {|f| f.encoding == data.encoding}
- end
- end
- end
-
- def test_built_in_converters_transcode_to_utf_8_then_convert
- encode_for_tests([%w[one two three], %w[1 2 3]]) do |data|
- parsed = CSV.parse(data, converters: :integer)
- assert_all?(parsed[0], "Wrong data encoding.") {|f| f.encoding == data.encoding}
- assert_equal([1, 2, 3], parsed[1])
- end
- end
-
- def test_built_in_header_converters_transcode_to_utf_8_then_convert
- encode_for_tests([%w[one two three], %w[1 2 3]]) do |data|
- parsed = CSV.parse( data, headers: true,
- header_converters: :downcase )
- assert_all?(parsed.headers, "Wrong data encoding.") {|h| h.encoding.name == "UTF-8"}
- assert_all?(parsed[0].fields, "Wrong data encoding.") {|f| f.encoding == data.encoding}
- end
- end
-
- def test_open_allows_you_to_set_encodings
- encode_for_tests([%w[abc def]]) do |data|
- # read and write in encoding
- File.open(@temp_csv_path, "wb:#{data.encoding.name}") { |f| f << data }
- CSV.open(@temp_csv_path, "rb:#{data.encoding.name}") do |csv|
- csv.each do |row|
- assert_all?(row, "Wrong data encoding.") {|f| f.encoding == data.encoding}
- end
- end
-
- # read and write with transcoding
- File.open(@temp_csv_path, "wb:UTF-32BE:#{data.encoding.name}") do |f|
- f << data
- end
- CSV.open(@temp_csv_path, "rb:UTF-32BE:#{data.encoding.name}") do |csv|
- csv.each do |row|
- assert_all?(row, "Wrong data encoding.") {|f| f.encoding == data.encoding}
- end
- end
- end
- end
-
- def test_foreach_allows_you_to_set_encodings
- encode_for_tests([%w[abc def]]) do |data|
- # read and write in encoding
- File.open(@temp_csv_path, "wb", encoding: data.encoding) { |f| f << data }
- CSV.foreach(@temp_csv_path, encoding: data.encoding) do |row|
- row.each {|f| assert_equal(f.encoding, data.encoding)}
- end
-
- # read and write with transcoding
- File.open(@temp_csv_path, "wb:UTF-32BE:#{data.encoding.name}") do |f|
- f << data
- end
- CSV.foreach( @temp_csv_path,
- encoding: "UTF-32BE:#{data.encoding.name}" ) do |row|
- assert_all?(row, "Wrong data encoding.") {|f| f.encoding == data.encoding}
- end
- end
- end
-
- def test_read_allows_you_to_set_encodings
- encode_for_tests([%w[abc def]]) do |data|
- # read and write in encoding
- File.open(@temp_csv_path, "wb:#{data.encoding.name}") { |f| f << data }
- rows = CSV.read(@temp_csv_path, encoding: data.encoding.name)
- assert_all?(rows.flatten, "Wrong data encoding.") {|f| f.encoding == data.encoding}
-
- # read and write with transcoding
- File.open(@temp_csv_path, "wb:UTF-32BE:#{data.encoding.name}") do |f|
- f << data
- end
- rows = CSV.read( @temp_csv_path,
- encoding: "UTF-32BE:#{data.encoding.name}" )
- assert_all?(rows.flatten, "Wrong data encoding.") {|f| f.encoding == data.encoding}
- end
- end
-
- #################################
- ### Write CSV in any Encoding ###
- #################################
-
- def test_can_write_csv_in_any_encoding
- each_encoding do |encoding|
- # test generate_line with encoding hint
- begin
- csv = %w[abc d|ef].map { |f| f.encode(encoding) }.
- to_csv(col_sep: "|", encoding: encoding.name)
- rescue Encoding::ConverterNotFoundError
- next
- end
- assert_equal(encoding, csv.encoding)
-
- # test generate_line with encoding guessing from fields
- csv = %w[abc d|ef].map { |f| f.encode(encoding) }.to_csv(col_sep: "|")
- assert_equal(encoding, csv.encoding)
-
- # writing to files
- data = encode_ary([%w[abc d,ef], %w[123 456 ]], encoding)
- CSV.open(@temp_csv_path, "wb:#{encoding.name}") do |f|
- data.each { |row| f << row }
- end
- assert_equal(data, CSV.read(@temp_csv_path, encoding: encoding.name))
- end
- end
-
- def test_encoding_is_upgraded_during_writing_as_needed
- data = ["foo".force_encoding("US-ASCII"), "\u3042"]
- assert_equal("US-ASCII", data.first.encoding.name)
- assert_equal("UTF-8", data.last.encoding.name)
- assert_equal("UTF-8", data.join('').encoding.name)
- assert_equal("UTF-8", data.to_csv.encoding.name)
- end
-
- def test_encoding_is_upgraded_for_ascii_content_during_writing_as_needed
- data = ["foo".force_encoding("ISO-8859-1"), "\u3042"]
- assert_equal("ISO-8859-1", data.first.encoding.name)
- assert_equal("UTF-8", data.last.encoding.name)
- assert_equal("UTF-8", data.join('').encoding.name)
- assert_equal("UTF-8", data.to_csv.encoding.name)
- end
-
- def test_encoding_is_not_upgraded_for_non_ascii_content_during_writing_as_needed
- data = ["\u00c0".encode("ISO-8859-1"), "\u3042"]
- assert_equal([
- "ISO-8859-1",
- "UTF-8",
- ],
- data.collect {|field| field.encoding.name})
- assert_raise(Encoding::CompatibilityError) do
- data.to_csv
- end
- end
-
- def test_explicit_encoding
- bug9766 = '[ruby-core:62113] [Bug #9766]'
- s = CSV.generate(encoding: "Windows-31J") do |csv|
- csv << ["foo".force_encoding("ISO-8859-1"), "\u3042"]
- end
- assert_equal(["foo,\u3042\n".encode(Encoding::Windows_31J), Encoding::Windows_31J], [s, s.encoding], bug9766)
- end
-
- def test_encoding_with_default_internal
- with_default_internal(Encoding::UTF_8) do
- s = CSV.generate(String.new(encoding: Encoding::Big5), encoding: Encoding::Big5) do |csv|
- csv << ["漢字"]
- end
- assert_equal(["漢字\n".encode(Encoding::Big5), Encoding::Big5], [s, s.encoding])
- end
- end
-
- def test_row_separator_detection_with_invalid_encoding
- csv = CSV.new("invalid,\xF8\r\nvalid,x\r\n".force_encoding("UTF-8"),
- encoding: "UTF-8")
- assert_equal("\r\n", csv.row_sep)
- end
-
- def test_invalid_encoding_row_error
- csv = CSV.new("valid,x\rinvalid,\xF8\r".force_encoding("UTF-8"),
- encoding: "UTF-8", row_sep: "\r")
- error = assert_raise(CSV::MalformedCSVError) do
- csv.shift
- csv.shift
- end
- assert_equal("Invalid byte sequence in UTF-8 in line 2.",
- error.message)
- end
-
- private
-
- def assert_parses(fields, encoding, **options)
- encoding = Encoding.find(encoding) unless encoding.is_a? Encoding
- orig_fields = fields
- fields = encode_ary(fields, encoding)
- data = ary_to_data(fields, **options)
- parsed = CSV.parse(data, **options)
- assert_equal(fields, parsed)
- parsed.flatten.each_with_index do |field, i|
- assert_equal(encoding, field.encoding, "Field[#{i + 1}] was transcoded.")
- end
- File.open(@temp_csv_path, "wb") {|f| f.print(data)}
- CSV.open(@temp_csv_path, "rb:#{encoding}", **options) do |csv|
- csv.each_with_index do |row, i|
- assert_equal(fields[i], row)
- end
- end
- begin
- CSV.open(@temp_csv_path,
- "rb:#{encoding}:#{__ENCODING__}",
- **options) do |csv|
- csv.each_with_index do |row, i|
- assert_equal(orig_fields[i], row)
- end
- end unless encoding == __ENCODING__
- rescue Encoding::ConverterNotFoundError
- end
- options[:encoding] = encoding.name
- CSV.open(@temp_csv_path, **options) do |csv|
- csv.each_with_index do |row, i|
- assert_equal(fields[i], row)
- end
- end
- options.delete(:encoding)
- options[:external_encoding] = encoding.name
- options[:internal_encoding] = __ENCODING__.name
- begin
- CSV.open(@temp_csv_path, **options) do |csv|
- csv.each_with_index do |row, i|
- assert_equal(orig_fields[i], row)
- end
- end unless encoding == __ENCODING__
- rescue Encoding::ConverterNotFoundError
- end
- end
-
- def encode_ary(ary, encoding)
- ary.map { |row| row.map { |field| field.encode(encoding) } }
- end
-
- def ary_to_data(ary, **options)
- encoding = ary.flatten.first.encoding
- quote_char = (options[:quote_char] || '"').encode(encoding)
- col_sep = (options[:col_sep] || ",").encode(encoding)
- row_sep = (options[:row_sep] || "\n").encode(encoding)
- ary.map { |row|
- row.map { |field|
- [quote_char, field.encode(encoding), quote_char].join('')
- }.join(col_sep) + row_sep
- }.join('').encode(encoding)
- end
-
- def encode_for_tests(data, **options)
- yield ary_to_data(encode_ary(data, "UTF-8"), **options)
- yield ary_to_data(encode_ary(data, "UTF-16BE"), **options)
- end
-
- def each_encoding
- Encoding.list.each do |encoding|
- next if encoding.dummy? # skip "dummy" encodings
- yield encoding
- end
- end
-
- def no_warnings
- old_verbose, $VERBOSE = $VERBOSE, nil
- yield
- ensure
- $VERBOSE = old_verbose
- end
-end
diff --git a/test/csv/test_features.rb b/test/csv/test_features.rb
deleted file mode 100644
index d6eb2dc13b..0000000000
--- a/test/csv/test_features.rb
+++ /dev/null
@@ -1,359 +0,0 @@
-# -*- coding: utf-8 -*-
-# frozen_string_literal: false
-
-begin
- require "zlib"
-rescue LoadError
-end
-
-require_relative "helper"
-require "tempfile"
-
-class TestCSVFeatures < Test::Unit::TestCase
- extend DifferentOFS
-
- 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
- super
- @sample_data = <<-CSV
-line,1,abc
-line,2,"def\nghi"
-
-line,4,jkl
- CSV
- @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_col_sep_nil
- assert_raise_with_message(ArgumentError,
- ":col_sep must be 1 or more characters: nil") do
- CSV.parse(@sample_data, col_sep: nil)
- end
- end
-
- def test_col_sep_empty
- assert_raise_with_message(ArgumentError,
- ":col_sep must be 1 or more characters: \"\"") do
- CSV.parse(@sample_data, col_sep: "")
- end
- end
-
- def test_row_sep
- error = assert_raise(CSV::MalformedCSVError) do
- CSV.parse_line("1,2,3\n,4,5\r\n", row_sep: "\r\n")
- end
- assert_equal("Unquoted fields do not allow new line <\"\\n\"> in line 1.",
- error.message)
- 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_quote_char_special_regexp_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_quote_char_special_regexp_char_liberal_parsing
- 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: "|",
- liberal_parsing: true))
- end
- end
-
- def test_csv_char_readers
- %w[col_sep row_sep quote_char].each do |reader|
- csv = CSV.new("abc,def", reader.to_sym => "|")
- assert_equal("|", csv.send(reader))
- 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).row_sep
- assert_equal(line_end, discovered)
- end
-
- assert_equal("\n", CSV.new("\n\r\n\r").row_sep)
-
- assert_equal($/, CSV.new("").row_sep)
-
- assert_equal($/, CSV.new(STDERR).row_sep)
- end
-
- def test_line
- lines = [
- %Q(\u{3000}abc,def\n),
- %Q(\u{3000}abc,"d\nef"\n),
- %Q(\u{3000}abc,"d\r\nef"\n),
- %Q(\u{3000}abc,"d\ref")
- ]
- csv = CSV.new(lines.join(''))
- lines.each do |line|
- csv.shift
- assert_equal(line, csv.line)
- end
- 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_with_message(ArgumentError, /unknown keyword/) {
- CSV.new(@sample_data, unknown: :error)
- }
- assert_raise_with_message(ArgumentError, /unknown keyword/) {
- CSV.new(@sample_data, universal_newline: true)
- }
- 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
-
- def test_csv_behavior_readers
- %w[ unconverted_fields return_headers write_headers
- skip_blanks force_quotes ].each do |behavior|
- assert_not_predicate(CSV.new("abc,def"), "#{behavior}?", "Behavior defaulted to on.")
- csv = CSV.new("abc,def", behavior.to_sym => true)
- assert_predicate(csv, "#{behavior}?", "Behavior change now registered.")
- end
- end
-
- def test_converters_reader
- # no change
- assert_equal( [:integer],
- CSV.new("abc,def", converters: [:integer]).converters )
-
- # just one
- assert_equal( [:integer],
- CSV.new("abc,def", converters: :integer).converters )
-
- # expanded
- assert_equal( [:integer, :float],
- CSV.new("abc,def", converters: :numeric).converters )
-
- # custom
- csv = CSV.new("abc,def", converters: [:integer, lambda { }])
- assert_equal(2, csv.converters.size)
- assert_equal(:integer, csv.converters.first)
- assert_instance_of(Proc, csv.converters.last)
- end
-
- def test_header_converters_reader
- # no change
- hc = :header_converters
- assert_equal([:downcase], CSV.new("abc,def", hc => [:downcase]).send(hc))
-
- # just one
- assert_equal([:downcase], CSV.new("abc,def", hc => :downcase).send(hc))
-
- # custom
- csv = CSV.new("abc,def", hc => [:symbol, lambda { }])
- assert_equal(2, csv.send(hc).size)
- assert_equal(:symbol, csv.send(hc).first)
- assert_instance_of(Proc, csv.send(hc).last)
- end
-
- # reported by Kev Jackson
- def test_failing_to_escape_col_sep
- assert_nothing_raised(Exception) { CSV.new(String.new, col_sep: "|") }
- end
-
- # reported by Chris Roos
- def test_failing_to_reset_headers_in_rewind
- csv = CSV.new("forename,surname", headers: true, return_headers: true)
- csv.each {|row| assert_predicate row, :header_row?}
- csv.rewind
- csv.each {|row| assert_predicate row, :header_row?}
- end
-
- def test_gzip_reader
- 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.row_sep)
- ensure
- zipped.close
- end if defined?(Zlib::GzipReader)
-
- def test_gzip_writer
- Tempfile.create(%w"temp .gz") {|tempfile|
- tempfile.close
- file = tempfile.path
- 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_include(Zlib::GzipReader.open(file) {|f| f.read},
- $INPUT_RECORD_SEPARATOR, "@row_sep did not default")
- }
- end if defined?(Zlib::GzipWriter)
-
- def test_inspect_is_smart_about_io_types
- str = CSV.new("string,data").inspect
- assert_include(str, "io_type:StringIO", "IO type not detected.")
-
- str = CSV.new($stderr).inspect
- assert_include(str, "io_type:$stderr", "IO type not detected.")
-
- Tempfile.create(%w"temp .csv") {|tempfile|
- tempfile.close
- path = tempfile.path
- File.open(path, "w") { |csv| csv << "one,two,three\n1,2,3\n" }
- str = CSV.open(path) { |csv| csv.inspect }
- assert_include(str, "io_type:File", "IO type not detected.")
- }
- end
-
- def test_inspect_shows_key_attributes
- str = @csv.inspect
- %w[lineno col_sep row_sep quote_char].each do |attr_name|
- assert_match(/\b#{attr_name}:[^\s>]+/, str)
- end
- end
-
- def test_inspect_shows_headers_when_available
- csv = CSV.new("one,two,three\n1,2,3\n", headers: true)
- assert_include(csv.inspect, "headers:true", "Header hint not shown.")
- csv.shift # load headers
- assert_match(/headers:\[[^\]]+\]/, csv.inspect)
- end
-
- def test_inspect_encoding_is_ascii_compatible
- csv = CSV.new("one,two,three\n1,2,3\n".encode("UTF-16BE"))
- assert_send([Encoding, :compatible?,
- Encoding.find("US-ASCII"), csv.inspect.encoding],
- "inspect() was not ASCII compatible.")
- end
-
- def test_version
- assert_not_nil(CSV::VERSION)
- assert_instance_of(String, CSV::VERSION)
- assert_predicate(CSV::VERSION, :frozen?)
- assert_match(/\A\d\.\d\.\d\z/, CSV::VERSION)
- end
-
- def test_table_nil_equality
- assert_nothing_raised(NoMethodError) { CSV.parse("test", headers: true) == nil }
- end
-
- # non-seekable input stream for testing https://github.com/ruby/csv/issues/44
- class DummyIO
- extend Forwardable
- def_delegators :@io, :gets, :read, :pos, :eof? # no seek or rewind!
- def initialize(data)
- @io = StringIO.new(data)
- end
- end
-
- def test_line_separator_autodetection_for_non_seekable_input_lf
- c = CSV.new(DummyIO.new("one,two,three\nfoo,bar,baz\n"))
- assert_equal [["one", "two", "three"], ["foo", "bar", "baz"]], c.each.to_a
- end
-
- def test_line_separator_autodetection_for_non_seekable_input_cr
- c = CSV.new(DummyIO.new("one,two,three\rfoo,bar,baz\r"))
- assert_equal [["one", "two", "three"], ["foo", "bar", "baz"]], c.each.to_a
- end
-
- def test_line_separator_autodetection_for_non_seekable_input_cr_lf
- c = CSV.new(DummyIO.new("one,two,three\r\nfoo,bar,baz\r\n"))
- assert_equal [["one", "two", "three"], ["foo", "bar", "baz"]], c.each.to_a
- end
-
- def test_line_separator_autodetection_for_non_seekable_input_1024_over_lf
- table = (1..10).map { |row| (1..200).map { |col| "row#{row}col#{col}" }.to_a }.to_a
- input = table.map { |line| line.join(",") }.join("\n")
- c = CSV.new(DummyIO.new(input))
- assert_equal table, c.each.to_a
- end
-
- def test_line_separator_autodetection_for_non_seekable_input_1024_over_cr_lf
- table = (1..10).map { |row| (1..200).map { |col| "row#{row}col#{col}" }.to_a }.to_a
- input = table.map { |line| line.join(",") }.join("\r\n")
- c = CSV.new(DummyIO.new(input))
- assert_equal table, c.each.to_a
- end
-
- def test_line_separator_autodetection_for_non_seekable_input_many_cr_only
- # input with lots of CRs (to make sure no bytes are lost due to look-ahead)
- c = CSV.new(DummyIO.new("foo\r" + "\r" * 9999 + "bar\r"))
- assert_equal [["foo"]] + [[]] * 9999 + [["bar"]], c.each.to_a
- end
-end
diff --git a/test/csv/test_row.rb b/test/csv/test_row.rb
deleted file mode 100644
index b717945041..0000000000
--- a/test/csv/test_row.rb
+++ /dev/null
@@ -1,435 +0,0 @@
-# -*- coding: utf-8 -*-
-# frozen_string_literal: false
-
-require_relative "helper"
-
-class TestCSVRow < Test::Unit::TestCase
- extend DifferentOFS
-
- def setup
- super
- @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_not_predicate(row, :header_row?)
- assert_predicate(row, :field_row?)
- row = CSV::Row.new(%w{A B C}, [1, 2, 3], false) # explicit
- assert_not_predicate(row, :header_row?)
- assert_predicate(row, :field_row?)
-
- # header row
- row = CSV::Row.new(%w{A B C}, [1, 2, 3], true)
- assert_predicate(row, :header_row?)
- assert_not_predicate(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))
-
- # by range
- assert_equal([2,3], @row.field(1..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_fetch
- # only by name
- assert_equal(2, @row.fetch('B'))
-
- # missing header raises KeyError
- assert_raise KeyError do
- @row.fetch('foo')
- end
-
- # missing header yields itself to block
- assert_equal 'bar', @row.fetch('foo') { |header|
- header == 'foo' ? 'bar' : false }
-
- # missing header returns the given default value
- assert_equal 'bar', @row.fetch('foo', 'bar')
-
- # more than one vararg raises ArgumentError
- assert_raise ArgumentError do
- @row.fetch('foo', 'bar', 'baz')
- end
- end
-
- def test_has_key?
- assert_equal(true, @row.has_key?('B'))
- assert_equal(false, @row.has_key?('foo'))
-
- # aliases
- assert_equal(true, @row.header?('B'))
- assert_equal(false, @row.header?('foo'))
-
- assert_equal(true, @row.include?('B'))
- assert_equal(false, @row.include?('foo'))
-
- assert_equal(true, @row.member?('B'))
- assert_equal(false, @row.member?('foo'))
-
- assert_equal(true, @row.key?('B'))
- assert_equal(false, @row.key?('foo'))
- 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"))
-
- end
-
- def test_delete_if
- assert_equal(@row, @row.delete_if { |h, f| h == "A" and not f.nil? })
- assert_equal([["B", 2], ["C", 3], ["A", nil]], @row.to_a)
- end
-
- def test_delete_if_without_block
- enum = @row.delete_if
- assert_instance_of(Enumerator, enum)
- assert_equal(@row.size, enum.size)
-
- assert_equal(@row, enum.each { |h, f| h == "A" and not f.nil? })
- assert_equal([["B", 2], ["C", 3], ["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
- # 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 { })
-
- # without block
- ary = @row.to_a
- enum = @row.each
- assert_instance_of(Enumerator, enum)
- assert_equal(@row.size, enum.size)
- enum.each do |pair|
- assert_equal(ary.first.first, pair.first)
- assert_equal(ary.shift.last, pair.last)
- end
- end
-
- def test_each_pair
- assert_equal([
- ["A", 1],
- ["B", 2],
- ["C", 3],
- ["A", 4],
- ["A", nil],
- ],
- @row.each_pair.to_a)
- 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, (_, 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
- hash = @row.to_hash
- assert_equal({"A" => @row["A"], "B" => @row["B"], "C" => @row["C"]}, hash)
- hash.keys.each_with_index do |string_key, h|
- assert_predicate(string_key, :frozen?)
- assert_same(string_key, @row.headers[h])
- end
- 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_not_empty(@row, "Row was empty.")
-
- assert_equal([@row.headers.size, @row.fields.size].max, @row.size)
- end
-
- def test_inspect_shows_header_field_pairs
- str = @row.inspect
- @row.each do |header, field|
- assert_include(str, "#{header.inspect}:#{field.inspect}",
- "Header field pair not found.")
- end
- end
-
- def test_inspect_encoding_is_ascii_compatible
- assert_send([Encoding, :compatible?,
- Encoding.find("US-ASCII"),
- @row.inspect.encoding],
- "inspect() was not ASCII compatible.")
- end
-
- def test_inspect_shows_symbol_headers_as_bare_attributes
- str = CSV::Row.new(@row.headers.map { |h| h.to_sym }, @row.fields).inspect
- @row.each do |header, field|
- assert_include(str, "#{header}:#{field.inspect}",
- "Header field pair not found.")
- end
- end
-
- def test_can_be_compared_with_other_classes
- assert_not_nil(CSV::Row.new([ ], [ ]), "The row was nil")
- end
-
- def test_can_be_compared_when_not_a_row
- r = @row == []
- assert_equal false, r
- end
-
- def test_dig_by_index
- assert_equal(2, @row.dig(1))
-
- assert_nil(@row.dig(100))
- end
-
- def test_dig_by_header
- assert_equal(2, @row.dig("B"))
-
- assert_nil(@row.dig("Missing"))
- end
-
- def test_dig_cell
- row = CSV::Row.new(%w{A}, [["foo", ["bar", ["baz"]]]])
-
- assert_equal("foo", row.dig(0, 0))
- assert_equal("bar", row.dig(0, 1, 0))
-
- assert_equal("foo", row.dig("A", 0))
- assert_equal("bar", row.dig("A", 1, 0))
- end
-
- def test_dig_cell_no_dig
- row = CSV::Row.new(%w{A}, ["foo"])
-
- assert_raise(TypeError) do
- row.dig(0, 0)
- end
- assert_raise(TypeError) do
- row.dig("A", 0)
- end
- end
-
- def test_dup
- row = CSV::Row.new(["A"], ["foo"])
- dupped_row = row.dup
- dupped_row["A"] = "bar"
- assert_equal(["foo", "bar"],
- [row["A"], dupped_row["A"]])
- dupped_row.delete("A")
- assert_equal(["foo", nil],
- [row["A"], dupped_row["A"]])
- end
-end
diff --git a/test/csv/test_table.rb b/test/csv/test_table.rb
deleted file mode 100644
index 3202963a67..0000000000
--- a/test/csv/test_table.rb
+++ /dev/null
@@ -1,620 +0,0 @@
-# -*- coding: utf-8 -*-
-# frozen_string_literal: false
-
-require_relative "helper"
-
-class TestCSVTable < Test::Unit::TestCase
- extend DifferentOFS
-
- def setup
- super
- @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
- )
-
- @header_only_table = CSV::Table.new([], headers: %w{A B C})
- 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)
-
- col_or_row = rows.by_col_or_row
- assert_equal(:row, rows.mode)
- assert_equal(:col_or_row, col_or_row.mode)
- assert_equal(@table, col_or_row)
-
- # 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_headers_empty
- t = CSV::Table.new([])
- assert_equal Array.new, t.headers
- end
-
- def test_headers_only
- assert_equal(%w[A B C], @header_only_table.headers)
- end
-
- def test_headers_modified_by_row
- table = CSV::Table.new([], headers: ["A", "B"])
- table << ["a", "b"]
- table.first << {"C" => "c"}
- assert_equal(["A", "B", "C"], 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 row with Range
- assert_equal([@table[1], @table[2]], @table[1..2])
-
- # 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(<<-CSV, @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,
- CSV
-
- # 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_set_by_col_with_header_row
- r = [ CSV::Row.new(%w{X Y Z}, [97, 98, 99], true) ]
- t = CSV::Table.new(r)
- t.by_col!
- t['A'] = [42]
- assert_equal(['A'], t['A'])
- 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 { })
-
- # without block
- enum = @table.each
- assert_instance_of(Enumerator, enum)
- assert_equal(@table.size, enum.size)
-
- i = 0
- enum.each do |row|
- assert_equal(@rows[i], row)
- i += 1
- end
-
- ###################
- ### Column Mode ###
- ###################
- @table.by_col!
-
- headers = @table.headers
- @table.each do |header, column|
- assert_equal(headers.shift, header)
- assert_equal(@table[header], column)
- end
-
- # without block
- enum = @table.each
- assert_instance_of(Enumerator, enum)
- assert_equal(@table.headers.size, enum.size)
-
- headers = @table.headers
- enum.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_each_split
- yielded_values = []
- @table.each do |column1, column2, column3|
- yielded_values << [column1, column2, column3]
- end
- assert_equal(@rows.collect(&:to_a),
- yielded_values)
- 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 = <<-CSV
-A,B,C
-1,2,3
-4,5,6
-7,8,9
- 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") )
- assert_equal( csv.lines.to_a[1..-1].join(''),
- @table.to_csv(:write_headers => false) )
-
- # 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_one
- ##################
- ### 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(<<-CSV, @table.to_csv)
-B,C
-2,3
-8,9
- CSV
- end
-
- def test_delete_mixed_multiple
- ##################
- ### Mixed Mode ###
- ##################
- # delete row and col
- second_row = @rows[1]
- a_col = @rows.map { |row| row["A"] }
- a_col_without_second_row = a_col[0..0] + a_col[2..-1]
- assert_equal([
- second_row,
- a_col_without_second_row,
- ],
- @table.delete(1, "A"))
-
- # verify resulting table
- assert_equal(<<-CSV, @table.to_csv)
-B,C
-2,3
-8,9
- CSV
- end
-
- def test_delete_column
- ###################
- ### Column Mode ###
- ###################
- @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(<<-CSV, @table.to_csv)
-B
-2
-5
-8
- CSV
- end
-
- def test_delete_row
- ################
- ### Row Mode ###
- ################
- @table.by_row!
-
- assert_equal(@rows[1], @table.delete(1))
- assert_raise(TypeError) { @table.delete("C") }
-
- # verify resulting table
- assert_equal(<<-CSV, @table.to_csv)
-A,B,C
-1,2,3
-7,8,9
- CSV
- end
-
- def test_delete_with_blank_rows
- data = "col1,col2\nra1,ra2\n\nrb1,rb2"
- table = CSV.parse(data, :headers => true)
- assert_equal(["ra2", nil, "rb2"], table.delete("col2"))
- end
-
- def test_delete_if_row
- ######################
- ### 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(<<-CSV, @table.to_csv)
-A,B,C
-4,5,6
- CSV
- end
-
- def test_delete_if_row_without_block
- ######################
- ### Mixed/Row Mode ###
- ######################
- enum = @table.delete_if
- assert_instance_of(Enumerator, enum)
- assert_equal(@table.size, enum.size)
-
- # verify that we can chain the call
- assert_equal(@table, enum.each { |row| (row["B"] % 2).zero? })
-
- # verify resulting table
- assert_equal(<<-CSV, @table.to_csv)
-A,B,C
-4,5,6
- CSV
- end
-
- def test_delete_if_column
- ###################
- ### Column Mode ###
- ###################
- @table.by_col!
-
- assert_equal(@table, @table.delete_if { |h, v| h > "A" })
- assert_equal(<<-CSV, @table.to_csv)
-A
-1
-4
-7
- CSV
- end
-
- def test_delete_if_column_without_block
- ###################
- ### Column Mode ###
- ###################
- @table.by_col!
-
- enum = @table.delete_if
- assert_instance_of(Enumerator, enum)
- assert_equal(@table.headers.size, enum.size)
-
- assert_equal(@table, enum.each { |h, v| h > "A" })
- assert_equal(<<-CSV, @table.to_csv)
-A
-1
-4
-7
- CSV
- end
-
- def test_delete_headers_only
- ###################
- ### Column Mode ###
- ###################
- @header_only_table.by_col!
-
- # delete by index
- assert_equal([], @header_only_table.delete(0))
- assert_equal(%w[B C], @header_only_table.headers)
-
- # delete by header
- assert_equal([], @header_only_table.delete("C"))
- assert_equal(%w[B], @header_only_table.headers)
- 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_not_empty(@table, "Table was empty.")
-
- assert_equal(@rows.size, @table.size)
- end
-
- def test_inspect_shows_current_mode
- str = @table.inspect
- assert_include(str, "mode:#{@table.mode}", "Mode not shown.")
-
- @table.by_col!
- str = @table.inspect
- assert_include(str, "mode:#{@table.mode}", "Mode not shown.")
- end
-
- def test_inspect_encoding_is_ascii_compatible
- assert_send([Encoding, :compatible?,
- Encoding.find("US-ASCII"),
- @table.inspect.encoding],
- "inspect() was not ASCII compatible." )
- end
-
- def test_dig_mixed
- # by row
- assert_equal(@rows[0], @table.dig(0))
- assert_nil(@table.dig(100)) # empty row
-
- # by col
- assert_equal([2, 5, 8], @table.dig("B"))
- assert_equal([nil] * @rows.size, @table.dig("Z")) # empty col
-
- # by row then col
- assert_equal(2, @table.dig(0, 1))
- assert_equal(6, @table.dig(1, "C"))
-
- # by col then row
- assert_equal(5, @table.dig("B", 1))
- assert_equal(9, @table.dig("C", 2))
- end
-
- def test_dig_by_column
- @table.by_col!
-
- assert_equal([2, 5, 8], @table.dig(1))
- assert_equal([2, 5, 8], @table.dig("B"))
-
- # by col then row
- assert_equal(5, @table.dig("B", 1))
- assert_equal(9, @table.dig("C", 2))
- end
-
- def test_dig_by_row
- @table.by_row!
-
- assert_equal(@rows[1], @table.dig(1))
- assert_raise(TypeError) { @table.dig("B") }
-
- # by row then col
- assert_equal(2, @table.dig(0, 1))
- assert_equal(6, @table.dig(1, "C"))
- end
-
- def test_dig_cell
- table = CSV::Table.new([CSV::Row.new(["A"], [["foo", ["bar", ["baz"]]]])])
-
- # by row, col then cell
- assert_equal("foo", table.dig(0, "A", 0))
- assert_equal(["baz"], table.dig(0, "A", 1, 1))
-
- # by col, row then cell
- assert_equal("foo", table.dig("A", 0, 0))
- assert_equal(["baz"], table.dig("A", 0, 1, 1))
- end
-
- def test_dig_cell_no_dig
- table = CSV::Table.new([CSV::Row.new(["A"], ["foo"])])
-
- # by row, col then cell
- assert_raise(TypeError) do
- table.dig(0, "A", 0)
- end
-
- # by col, row then cell
- assert_raise(TypeError) do
- table.dig("A", 0, 0)
- end
- end
-end
diff --git a/test/csv/write/test_converters.rb b/test/csv/write/test_converters.rb
deleted file mode 100644
index 0e0080b4c5..0000000000
--- a/test/csv/write/test_converters.rb
+++ /dev/null
@@ -1,53 +0,0 @@
-# -*- coding: utf-8 -*-
-# frozen_string_literal: false
-
-require_relative "../helper"
-
-module TestCSVWriteConverters
- def test_one
- assert_equal(%Q[=a,=b,=c\n],
- generate_line(["a", "b", "c"],
- write_converters: ->(value) {"=" + value}))
- end
-
- def test_multiple
- assert_equal(%Q[=a_,=b_,=c_\n],
- generate_line(["a", "b", "c"],
- write_converters: [
- ->(value) {"=" + value},
- ->(value) {value + "_"},
- ]))
- end
-
- def test_nil_value
- assert_equal(%Q[a,NaN,29\n],
- generate_line(["a", nil, 29],
- write_nil_value: "NaN"))
- end
-
- def test_empty_value
- assert_equal(%Q[a,,29\n],
- generate_line(["a", "", 29],
- write_empty_value: nil))
- end
-end
-
-class TestCSVWriteConvertersGenerateLine < Test::Unit::TestCase
- include TestCSVWriteConverters
- extend DifferentOFS
-
- def generate_line(row, **kwargs)
- CSV.generate_line(row, **kwargs)
- end
-end
-
-class TestCSVWriteConvertersGenerate < Test::Unit::TestCase
- include TestCSVWriteConverters
- extend DifferentOFS
-
- def generate_line(row, **kwargs)
- CSV.generate(**kwargs) do |csv|
- csv << row
- end
- end
-end
diff --git a/test/csv/write/test_force_quotes.rb b/test/csv/write/test_force_quotes.rb
deleted file mode 100644
index 622dcb021b..0000000000
--- a/test/csv/write/test_force_quotes.rb
+++ /dev/null
@@ -1,78 +0,0 @@
-# frozen_string_literal: false
-
-require_relative "../helper"
-
-module TestCSVWriteForceQuotes
- def test_default
- assert_equal(%Q[1,2,3#{$INPUT_RECORD_SEPARATOR}],
- generate_line(["1", "2", "3"]))
- end
-
- def test_true
- assert_equal(%Q["1","2","3"#{$INPUT_RECORD_SEPARATOR}],
- generate_line(["1", "2", "3"],
- force_quotes: true))
- end
-
- def test_false
- assert_equal(%Q[1,2,3#{$INPUT_RECORD_SEPARATOR}],
- generate_line(["1", "2", "3"],
- force_quotes: false))
- end
-
- def test_field_name
- assert_equal(%Q["1",2,"3"#{$INPUT_RECORD_SEPARATOR}],
- generate_line(["1", "2", "3"],
- headers: ["a", "b", "c"],
- force_quotes: ["a", :c]))
- end
-
- def test_field_name_without_headers
- force_quotes = ["a", "c"]
- error = assert_raise(ArgumentError) do
- generate_line(["1", "2", "3"],
- force_quotes: force_quotes)
- end
- assert_equal(":headers is required when you use field name " +
- "in :force_quotes: " +
- "#{force_quotes.first.inspect}: #{force_quotes.inspect}",
- error.message)
- end
-
- def test_field_index
- assert_equal(%Q["1",2,"3"#{$INPUT_RECORD_SEPARATOR}],
- generate_line(["1", "2", "3"],
- force_quotes: [0, 2]))
- end
-
- def test_field_unknown
- force_quotes = [1.1]
- error = assert_raise(ArgumentError) do
- generate_line(["1", "2", "3"],
- force_quotes: force_quotes)
- end
- assert_equal(":force_quotes element must be field index or field name: " +
- "#{force_quotes.first.inspect}: #{force_quotes.inspect}",
- error.message)
- end
-end
-
-class TestCSVWriteForceQuotesGenerateLine < Test::Unit::TestCase
- include TestCSVWriteForceQuotes
- extend DifferentOFS
-
- def generate_line(row, **kwargs)
- CSV.generate_line(row, **kwargs)
- end
-end
-
-class TestCSVWriteForceQuotesGenerate < Test::Unit::TestCase
- include TestCSVWriteForceQuotes
- extend DifferentOFS
-
- def generate_line(row, **kwargs)
- CSV.generate(**kwargs) do |csv|
- csv << row
- end
- end
-end
diff --git a/test/csv/write/test_general.rb b/test/csv/write/test_general.rb
deleted file mode 100644
index 677119e1ae..0000000000
--- a/test/csv/write/test_general.rb
+++ /dev/null
@@ -1,246 +0,0 @@
-# -*- coding: utf-8 -*-
-# frozen_string_literal: false
-
-require_relative "../helper"
-
-module TestCSVWriteGeneral
- include Helper
-
- def test_tab
- assert_equal("\t#{$INPUT_RECORD_SEPARATOR}",
- generate_line(["\t"]))
- end
-
- def test_quote_character
- assert_equal(%Q[foo,"""",baz#{$INPUT_RECORD_SEPARATOR}],
- generate_line(["foo", %Q["], "baz"]))
- end
-
- def test_quote_character_double
- assert_equal(%Q[foo,"""""",baz#{$INPUT_RECORD_SEPARATOR}],
- generate_line(["foo", %Q[""], "baz"]))
- end
-
- def test_quote
- assert_equal(%Q[foo,"""bar""",baz#{$INPUT_RECORD_SEPARATOR}],
- generate_line(["foo", %Q["bar"], "baz"]))
- end
-
- def test_quote_lf
- assert_equal(%Q["""\n","""\n"#{$INPUT_RECORD_SEPARATOR}],
- generate_line([%Q["\n], %Q["\n]]))
- end
-
- def test_quote_cr
- assert_equal(%Q["""\r","""\r"#{$INPUT_RECORD_SEPARATOR}],
- generate_line([%Q["\r], %Q["\r]]))
- end
-
- def test_quote_last
- assert_equal(%Q[foo,"bar"""#{$INPUT_RECORD_SEPARATOR}],
- generate_line(["foo", %Q[bar"]]))
- end
-
- def test_quote_lf_last
- assert_equal(%Q[foo,"\nbar"""#{$INPUT_RECORD_SEPARATOR}],
- generate_line(["foo", %Q[\nbar"]]))
- end
-
- def test_quote_lf_value_lf
- assert_equal(%Q[foo,"""\nbar\n"""#{$INPUT_RECORD_SEPARATOR}],
- generate_line(["foo", %Q["\nbar\n"]]))
- end
-
- def test_quote_lf_value_lf_nil
- assert_equal(%Q[foo,"""\nbar\n""",#{$INPUT_RECORD_SEPARATOR}],
- generate_line(["foo", %Q["\nbar\n"], nil]))
- end
-
- def test_cr
- assert_equal(%Q[foo,"\r",baz#{$INPUT_RECORD_SEPARATOR}],
- generate_line(["foo", "\r", "baz"]))
- end
-
- def test_lf
- assert_equal(%Q[foo,"\n",baz#{$INPUT_RECORD_SEPARATOR}],
- generate_line(["foo", "\n", "baz"]))
- end
-
- def test_cr_lf
- assert_equal(%Q[foo,"\r\n",baz#{$INPUT_RECORD_SEPARATOR}],
- generate_line(["foo", "\r\n", "baz"]))
- end
-
- def test_cr_dot_lf
- assert_equal(%Q[foo,"\r.\n",baz#{$INPUT_RECORD_SEPARATOR}],
- generate_line(["foo", "\r.\n", "baz"]))
- end
-
- def test_cr_lf_cr
- assert_equal(%Q[foo,"\r\n\r",baz#{$INPUT_RECORD_SEPARATOR}],
- generate_line(["foo", "\r\n\r", "baz"]))
- end
-
- def test_cr_lf_lf
- assert_equal(%Q[foo,"\r\n\n",baz#{$INPUT_RECORD_SEPARATOR}],
- generate_line(["foo", "\r\n\n", "baz"]))
- end
-
- def test_cr_lf_comma
- assert_equal(%Q["\r\n,"#{$INPUT_RECORD_SEPARATOR}],
- generate_line(["\r\n,"]))
- end
-
- def test_cr_lf_comma_nil
- assert_equal(%Q["\r\n,",#{$INPUT_RECORD_SEPARATOR}],
- generate_line(["\r\n,", nil]))
- end
-
- def test_comma
- assert_equal(%Q[","#{$INPUT_RECORD_SEPARATOR}],
- generate_line([","]))
- end
-
- def test_comma_double
- assert_equal(%Q[",",","#{$INPUT_RECORD_SEPARATOR}],
- generate_line([",", ","]))
- end
-
- def test_comma_and_value
- assert_equal(%Q[foo,"foo,bar",baz#{$INPUT_RECORD_SEPARATOR}],
- generate_line(["foo", "foo,bar", "baz"]))
- end
-
- def test_one_element
- assert_equal(%Q[foo#{$INPUT_RECORD_SEPARATOR}],
- generate_line(["foo"]))
- end
-
- def test_nil_values_only
- assert_equal(%Q[,,#{$INPUT_RECORD_SEPARATOR}],
- generate_line([nil, nil, nil]))
- end
-
- def test_nil_double_only
- assert_equal(%Q[,#{$INPUT_RECORD_SEPARATOR}],
- generate_line([nil, nil]))
- end
-
- def test_nil_values
- assert_equal(%Q[foo,,,#{$INPUT_RECORD_SEPARATOR}],
- generate_line(["foo", nil, nil, nil]))
- end
-
- def test_nil_value_first
- assert_equal(%Q[,foo,baz#{$INPUT_RECORD_SEPARATOR}],
- generate_line([nil, "foo", "baz"]))
- end
-
- def test_nil_value_middle
- assert_equal(%Q[foo,,baz#{$INPUT_RECORD_SEPARATOR}],
- generate_line(["foo", nil, "baz"]))
- end
-
- def test_nil_value_last
- assert_equal(%Q[foo,baz,#{$INPUT_RECORD_SEPARATOR}],
- generate_line(["foo", "baz", nil]))
- end
-
- def test_nil_empty
- assert_equal(%Q[,""#{$INPUT_RECORD_SEPARATOR}],
- generate_line([nil, ""]))
- end
-
- def test_nil_cr
- assert_equal(%Q[,"\r"#{$INPUT_RECORD_SEPARATOR}],
- generate_line([nil, "\r"]))
- end
-
- def test_values
- assert_equal(%Q[foo,bar#{$INPUT_RECORD_SEPARATOR}],
- generate_line(["foo", "bar"]))
- end
-
- def test_semi_colon
- assert_equal(%Q[;#{$INPUT_RECORD_SEPARATOR}],
- generate_line([";"]))
- end
-
- def test_semi_colon_values
- assert_equal(%Q[;,;#{$INPUT_RECORD_SEPARATOR}],
- generate_line([";", ";"]))
- end
-
- def test_tab_values
- assert_equal(%Q[\t,\t#{$INPUT_RECORD_SEPARATOR}],
- generate_line(["\t", "\t"]))
- end
-
- def test_col_sep
- assert_equal(%Q[a;b;;c#{$INPUT_RECORD_SEPARATOR}],
- generate_line(["a", "b", nil, "c"],
- col_sep: ";"))
- assert_equal(%Q[a\tb\t\tc#{$INPUT_RECORD_SEPARATOR}],
- generate_line(["a", "b", nil, "c"],
- col_sep: "\t"))
- end
-
- def test_row_sep
- assert_equal(%Q[a,b,,c\r\n],
- generate_line(["a", "b", nil, "c"],
- row_sep: "\r\n"))
- end
-
- def test_force_quotes
- assert_equal(%Q["1","b","","already ""quoted"""#{$INPUT_RECORD_SEPARATOR}],
- generate_line([1, "b", nil, %Q{already "quoted"}],
- force_quotes: true))
- end
-
- def test_encoding_utf8
- assert_equal(%Q[ã‚,ã„,ã†#{$INPUT_RECORD_SEPARATOR}],
- generate_line(["ã‚" , "ã„", "ã†"]))
- end
-
- def test_encoding_euc_jp
- row = ["ã‚", "ã„", "ã†"].collect {|field| field.encode("EUC-JP")}
- assert_equal(%Q[ã‚,ã„,ã†#{$INPUT_RECORD_SEPARATOR}].encode("EUC-JP"),
- generate_line(row))
- end
-
- def test_encoding_with_default_internal
- with_default_internal(Encoding::UTF_8) do
- row = ["ã‚", "ã„", "ã†"].collect {|field| field.encode("EUC-JP")}
- assert_equal(%Q[ã‚,ã„,ã†#{$INPUT_RECORD_SEPARATOR}].encode("EUC-JP"),
- generate_line(row, encoding: Encoding::EUC_JP))
- end
- end
-
- def test_with_default_internal
- with_default_internal(Encoding::UTF_8) do
- row = ["ã‚", "ã„", "ã†"].collect {|field| field.encode("EUC-JP")}
- assert_equal(%Q[ã‚,ã„,ã†#{$INPUT_RECORD_SEPARATOR}].encode("EUC-JP"),
- generate_line(row))
- end
- end
-end
-
-class TestCSVWriteGeneralGenerateLine < Test::Unit::TestCase
- include TestCSVWriteGeneral
- extend DifferentOFS
-
- def generate_line(row, **kwargs)
- CSV.generate_line(row, **kwargs)
- end
-end
-
-class TestCSVWriteGeneralGenerate < Test::Unit::TestCase
- include TestCSVWriteGeneral
- extend DifferentOFS
-
- def generate_line(row, **kwargs)
- CSV.generate(**kwargs) do |csv|
- csv << row
- end
- end
-end
diff --git a/test/csv/write/test_quote_empty.rb b/test/csv/write/test_quote_empty.rb
deleted file mode 100644
index 70f73dad4a..0000000000
--- a/test/csv/write/test_quote_empty.rb
+++ /dev/null
@@ -1,70 +0,0 @@
-# -*- coding: utf-8 -*-
-# frozen_string_literal: false
-
-require_relative "../helper"
-
-module TestCSVWriteQuoteEmpty
- def test_quote_empty_default
- assert_equal(%Q["""",""#{$INPUT_RECORD_SEPARATOR}],
- generate_line([%Q["], ""]))
- end
-
- def test_quote_empty_false
- assert_equal(%Q["""",#{$INPUT_RECORD_SEPARATOR}],
- generate_line([%Q["], ""],
- quote_empty: false))
- end
-
- def test_empty_default
- assert_equal(%Q[foo,"",baz#{$INPUT_RECORD_SEPARATOR}],
- generate_line(["foo", "", "baz"]))
- end
-
- def test_empty_false
- assert_equal(%Q[foo,,baz#{$INPUT_RECORD_SEPARATOR}],
- generate_line(["foo", "", "baz"],
- quote_empty: false))
- end
-
- def test_empty_only_default
- assert_equal(%Q[""#{$INPUT_RECORD_SEPARATOR}],
- generate_line([""]))
- end
-
- def test_empty_only_false
- assert_equal(%Q[#{$INPUT_RECORD_SEPARATOR}],
- generate_line([""],
- quote_empty: false))
- end
-
- def test_empty_double_default
- assert_equal(%Q["",""#{$INPUT_RECORD_SEPARATOR}],
- generate_line(["", ""]))
- end
-
- def test_empty_double_false
- assert_equal(%Q[,#{$INPUT_RECORD_SEPARATOR}],
- generate_line(["", ""],
- quote_empty: false))
- end
-end
-
-class TestCSVWriteQuoteEmptyGenerateLine < Test::Unit::TestCase
- include TestCSVWriteQuoteEmpty
- extend DifferentOFS
-
- def generate_line(row, **kwargs)
- CSV.generate_line(row, **kwargs)
- end
-end
-
-class TestCSVWriteQuoteEmptyGenerate < Test::Unit::TestCase
- include TestCSVWriteQuoteEmpty
- extend DifferentOFS
-
- def generate_line(row, **kwargs)
- CSV.generate(**kwargs) do |csv|
- csv << row
- end
- end
-end
diff --git a/test/date/test_date.rb b/test/date/test_date.rb
index 6e99bc562c..3f9c893efa 100644
--- a/test/date/test_date.rb
+++ b/test/date/test_date.rb
@@ -175,4 +175,33 @@ class TestDate < Test::Unit::TestCase
assert_equal(-1, -Float::INFINITY <=> Date::Infinity.new)
assert_equal(-1, -Date::Infinity.new <=> Float::INFINITY)
end
+
+ def test_deconstruct_keys
+ d = Date.new(1999,5,23)
+ assert_equal({year: 1999, month: 5, day: 23, wday: 0, yday: 143}, d.deconstruct_keys(nil))
+ assert_equal({year: 1999}, d.deconstruct_keys([:year, :century]))
+ assert_equal(
+ {year: 1999, month: 5, day: 23, wday: 0, yday: 143},
+ d.deconstruct_keys([:year, :month, :day, :wday, :yday])
+ )
+
+ dt = DateTime.new(1999, 5, 23, 4, 20, Rational(1, 10000))
+
+ assert_equal(
+ {year: 1999, month: 5, day: 23, wday: 0, yday: 143,
+ hour: 4, min: 20, sec: 0, sec_fraction: Rational(1, 10000), zone: "+00:00"},
+ dt.deconstruct_keys(nil)
+ )
+
+ assert_equal({year: 1999}, dt.deconstruct_keys([:year, :century]))
+
+ assert_equal(
+ {year: 1999, month: 5, day: 23, wday: 0, yday: 143,
+ hour: 4, min: 20, sec: 0, sec_fraction: Rational(1, 10000), zone: "+00:00"},
+ dt.deconstruct_keys([:year, :month, :day, :wday, :yday, :hour, :min, :sec, :sec_fraction, :zone])
+ )
+
+ dtz = DateTime.parse('3rd Feb 2001 04:05:06+03:30')
+ assert_equal({zone: '+03:30'}, dtz.deconstruct_keys([:zone]))
+ end
end
diff --git a/test/date/test_date_conv.rb b/test/date/test_date_conv.rb
index d41ff45d85..ed478b41bb 100644
--- a/test/date/test_date_conv.rb
+++ b/test/date/test_date_conv.rb
@@ -77,6 +77,11 @@ class TestDateConv < Test::Unit::TestCase
assert_equal([2004, 9, 19, 1, 2, 3, 456789],
[t.year, t.mon, t.mday, t.hour, t.min, t.sec, t.usec])
+ d = DateTime.new(1582, 10, 3, 1, 2, 3, 0) + 456789.to_r/86400000000
+ t = d.to_time.utc
+ assert_equal([1582, 10, 13, 1, 2, 3, 456789],
+ [t.year, t.mon, t.mday, t.hour, t.min, t.sec, t.usec])
+
if Time.allocate.respond_to?(:nsec)
d = DateTime.new(2004, 9, 19, 1, 2, 3, 0) + 456789123.to_r/86400000000000
t = d.to_time.utc
@@ -100,6 +105,10 @@ class TestDateConv < Test::Unit::TestCase
t = Time.utc(2004, 9, 19, 1, 2, 3, 456789)
d = t.to_date
assert_equal([2004, 9, 19, 0], [d.year, d.mon, d.mday, d.day_fraction])
+
+ t = Time.utc(1582, 10, 13, 1, 2, 3, 456789)
+ d = t.to_date # using ITALY
+ assert_equal([1582, 10, 3, 0], [d.year, d.mon, d.mday, d.day_fraction])
end
def test_to_date__from_date
@@ -136,6 +145,14 @@ class TestDateConv < Test::Unit::TestCase
[d.year, d.mon, d.mday, d.hour, d.min, d.sec,
d.sec_fraction, d.offset])
+ t = Time.utc(1582, 10, 13, 1, 2, 3, 456789)
+ d = t.to_datetime # using ITALY
+ assert_equal([1582, 10, 3, 1, 2, 3,
+ 456789.to_r/1000000,
+ 0],
+ [d.year, d.mon, d.mday, d.hour, d.min, d.sec,
+ d.sec_fraction, d.offset])
+
t = Time.now
d = t.to_datetime
require 'time'
diff --git a/test/date/test_date_parse.rb b/test/date/test_date_parse.rb
index 9f92635387..16362e3bff 100644
--- a/test/date/test_date_parse.rb
+++ b/test/date/test_date_parse.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
require 'test/unit'
require 'date'
+require 'envutil'
class TestDateParse < Test::Unit::TestCase
@@ -40,6 +41,7 @@ class TestDateParse < Test::Unit::TestCase
[['Sat Aug 28 02:29:34 Mountain Daylight Time 2000',false],[2000,8,28,2,29,34,'Mountain Daylight Time',-6*3600,6], __LINE__],
[['Sat Aug 28 02:29:34 Mexico Standard Time 2000',false],[2000,8,28,2,29,34,'Mexico Standard Time',-6*3600,6], __LINE__],
[['Sat Aug 28 02:29:34 E. Australia Standard Time 2000',false],[2000,8,28,2,29,34,'E. Australia Standard Time',10*3600,6], __LINE__],
+ [['Sat Aug 28 02:29:34 W. Central Africa Standard Time 2000',false],[2000,8,28,2,29,34,'W. Central Africa Standard Time',1*3600,6], __LINE__],
# part of iso 8601
[['1999-05-23 23:55:21',false],[1999,5,23,23,55,21,nil,nil,nil], __LINE__],
@@ -131,6 +133,7 @@ class TestDateParse < Test::Unit::TestCase
[['19990523235521.123[-9]',false],[1999,5,23,23,55,21,'-9',-(9*3600),nil], __LINE__],
[['19990523235521.123[+9]',false],[1999,5,23,23,55,21,'+9',+(9*3600),nil], __LINE__],
[['19990523235521.123[9]',false],[1999,5,23,23,55,21,'9',+(9*3600),nil], __LINE__],
+ [['19990523235521.123[9 ]',false],[1999,5,23,23,55,21,'9 ',+(9*3600),nil], __LINE__],
[['19990523235521.123[-9.50]',false],[1999,5,23,23,55,21,'-9.50',-(9*3600+30*60),nil], __LINE__],
[['19990523235521.123[+9.50]',false],[1999,5,23,23,55,21,'+9.50',+(9*3600+30*60),nil], __LINE__],
[['19990523235521.123[-5:EST]',false],[1999,5,23,23,55,21,'EST',-5*3600,nil], __LINE__],
@@ -139,6 +142,7 @@ class TestDateParse < Test::Unit::TestCase
[['235521.123',false],[nil,nil,nil,23,55,21,nil,nil,nil], __LINE__],
[['235521.123[-9]',false],[nil,nil,nil,23,55,21,'-9',-9*3600,nil], __LINE__],
[['235521.123[+9]',false],[nil,nil,nil,23,55,21,'+9',+9*3600,nil], __LINE__],
+ [['235521.123[-9 ]',false],[nil,nil,nil,23,55,21,'-9 ',-9*3600,nil], __LINE__],
[['235521.123[-5:EST]',false],[nil,nil,nil,23,55,21,'EST',-5*3600,nil], __LINE__],
[['235521.123[+9:JST]',false],[nil,nil,nil,23,55,21,'JST',+9*3600,nil], __LINE__],
@@ -584,6 +588,18 @@ class TestDateParse < Test::Unit::TestCase
assert_equal(5025, h[:offset])
end
+ def test__parse_too_long_year
+ str = "Jan 1" + "0" * 100_000
+ h = EnvUtil.timeout(3) {Date._parse(str, limit: 100_010)}
+ assert_equal(100_000, Math.log10(h[:year]))
+ assert_equal(1, h[:mon])
+
+ str = "Jan - 1" + "0" * 100_000
+ h = EnvUtil.timeout(3) {Date._parse(str, limit: 100_010)}
+ assert_equal(1, h[:mon])
+ assert_not_include(h, :year)
+ end
+
require 'time'
def test_parse__time
@@ -847,6 +863,11 @@ class TestDateParse < Test::Unit::TestCase
h = Date._iso8601('')
assert_equal({}, h)
+
+ h = Date._iso8601(nil)
+ assert_equal({}, h)
+
+ assert_raise(TypeError) {Date._iso8601('01-02-03T04:05:06Z'.to_sym)}
end
def test__rfc3339
@@ -862,6 +883,11 @@ class TestDateParse < Test::Unit::TestCase
h = Date._rfc3339('')
assert_equal({}, h)
+
+ h = Date._rfc3339(nil)
+ assert_equal({}, h)
+
+ assert_raise(TypeError) {Date._rfc3339('2001-02-03T04:05:06Z'.to_sym)}
end
def test__xmlschema
@@ -944,6 +970,11 @@ class TestDateParse < Test::Unit::TestCase
h = Date._xmlschema('')
assert_equal({}, h)
+
+ h = Date._xmlschema(nil)
+ assert_equal({}, h)
+
+ assert_raise(TypeError) {Date._xmlschema('2001-02-03'.to_sym)}
end
def test__rfc2822
@@ -976,6 +1007,11 @@ class TestDateParse < Test::Unit::TestCase
h = Date._rfc2822('')
assert_equal({}, h)
+
+ h = Date._rfc2822(nil)
+ assert_equal({}, h)
+
+ assert_raise(TypeError) {Date._rfc2822('Sat, 3 Feb 2001 04:05:06 UT'.to_sym)}
end
def test__httpdate
@@ -996,6 +1032,11 @@ class TestDateParse < Test::Unit::TestCase
h = Date._httpdate('')
assert_equal({}, h)
+
+ h = Date._httpdate(nil)
+ assert_equal({}, h)
+
+ assert_raise(TypeError) {Date._httpdate('Sat, 03 Feb 2001 04:05:06 GMT'.to_sym)}
end
def test__jisx0301
@@ -1072,6 +1113,11 @@ class TestDateParse < Test::Unit::TestCase
h = Date._jisx0301('')
assert_equal({}, h)
+
+ h = Date._jisx0301(nil)
+ assert_equal({}, h)
+
+ assert_raise(TypeError) {Date._jisx0301('H13.02.03T04:05:06.07+0100'.to_sym)}
end
def test_iso8601
@@ -1228,4 +1274,31 @@ class TestDateParse < Test::Unit::TestCase
assert_equal(s0, s)
end
+ def test_length_limit
+ assert_raise(ArgumentError) { Date._parse("1" * 1000) }
+ assert_raise(ArgumentError) { Date._iso8601("1" * 1000) }
+ assert_raise(ArgumentError) { Date._rfc3339("1" * 1000) }
+ assert_raise(ArgumentError) { Date._xmlschema("1" * 1000) }
+ assert_raise(ArgumentError) { Date._rfc2822("1" * 1000) }
+ assert_raise(ArgumentError) { Date._rfc822("1" * 1000) }
+ assert_raise(ArgumentError) { Date._jisx0301("1" * 1000) }
+
+ assert_raise(ArgumentError) { Date.parse("1" * 1000) }
+ assert_raise(ArgumentError) { Date.iso8601("1" * 1000) }
+ assert_raise(ArgumentError) { Date.rfc3339("1" * 1000) }
+ assert_raise(ArgumentError) { Date.xmlschema("1" * 1000) }
+ assert_raise(ArgumentError) { Date.rfc2822("1" * 1000) }
+ assert_raise(ArgumentError) { Date.rfc822("1" * 1000) }
+ assert_raise(ArgumentError) { Date.jisx0301("1" * 1000) }
+
+ assert_raise(ArgumentError) { DateTime.parse("1" * 1000) }
+ assert_raise(ArgumentError) { DateTime.iso8601("1" * 1000) }
+ assert_raise(ArgumentError) { DateTime.rfc3339("1" * 1000) }
+ assert_raise(ArgumentError) { DateTime.xmlschema("1" * 1000) }
+ assert_raise(ArgumentError) { DateTime.rfc2822("1" * 1000) }
+ assert_raise(ArgumentError) { DateTime.rfc822("1" * 1000) }
+ assert_raise(ArgumentError) { DateTime.jisx0301("1" * 1000) }
+
+ assert_raise(ArgumentError) { Date._parse("Jan " + "9" * 1000000) }
+ end
end
diff --git a/test/date/test_date_ractor.rb b/test/date/test_date_ractor.rb
index 7b0c3f4911..7ec953d87a 100644
--- a/test/date/test_date_ractor.rb
+++ b/test/date/test_date_ractor.rb
@@ -2,7 +2,7 @@
require 'test/unit'
require 'date'
-class TestDateParse < Test::Unit::TestCase
+class TestDateParseRactor < Test::Unit::TestCase
def code(klass = Date, share: false)
<<~RUBY.gsub('Date', klass.name)
share = #{share}
diff --git a/test/date/test_date_strftime.rb b/test/date/test_date_strftime.rb
index f82874d26d..dd04c0d9a4 100644
--- a/test/date/test_date_strftime.rb
+++ b/test/date/test_date_strftime.rb
@@ -48,7 +48,7 @@ class TestDateStrftime < Test::Unit::TestCase
'%t'=>["\t",{}],
'%u'=>['6',{:cwday=>6}],
'%V'=>['05',{:cweek=>5}],
- '%v'=>[' 3-Feb-2001',{:mday=>3,:mon=>2,:year=>2001}],
+ '%v'=>[' 3-FEB-2001',{:mday=>3,:mon=>2,:year=>2001}],
'%z'=>['+0000',{:zone=>'+0000',:offset=>0}],
'%+'=>['Sat Feb 3 00:00:00 +00:00 2001',
{:wday=>6,:mon=>2,:mday=>3,
@@ -125,7 +125,7 @@ class TestDateStrftime < Test::Unit::TestCase
def test_strftime__3_2
s = Time.now.strftime('%G')
- skip if s.empty? || s == '%G'
+ omit if s.empty? || s == '%G'
(Date.new(1970,1,1)..Date.new(2037,12,31)).each do |d|
t = Time.utc(d.year,d.mon,d.mday)
assert_equal(t.strftime('%G'), d.strftime('%G'))
diff --git a/test/date/test_date_strptime.rb b/test/date/test_date_strptime.rb
index fc42ebf7cd..4efe1a47d0 100644
--- a/test/date/test_date_strptime.rb
+++ b/test/date/test_date_strptime.rb
@@ -180,6 +180,10 @@ class TestDateStrptime < Test::Unit::TestCase
[['fri1feb034pm+5', '%a%d%b%y%H%p%Z'], [2003,2,1,16,nil,nil,'+5',5*3600,5]],
[['E. Australia Standard Time', '%Z'], [nil,nil,nil,nil,nil,nil,'E. Australia Standard Time',10*3600,nil], __LINE__],
+
+ # out of range
+ [['+0.9999999999999999999999', '%Z'], [nil,nil,nil,nil,nil,nil,'+0.9999999999999999999999',+1*3600,nil], __LINE__],
+ [['+9999999999999999999999.0', '%Z'], [nil,nil,nil,nil,nil,nil,'+9999999999999999999999.0',nil,nil], __LINE__],
].each do |x, y|
h = Date._strptime(*x)
a = h.values_at(:year,:mon,:mday,:hour,:min,:sec,:zone,:offset,:wday)
@@ -292,6 +296,11 @@ class TestDateStrptime < Test::Unit::TestCase
assert_not_nil(Date._strptime('Januari', '%B'))
assert_nil(Date._strptime('Sundai,', '%A,'))
assert_nil(Date._strptime('Januari,', '%B,'))
+
+ assert_nil(Date._strptime('+24:00', '%Z')[:offset])
+ assert_nil(Date._strptime('+23:60', '%Z')[:offset])
+ assert_nil(Date._strptime('+23:00:60', '%Z')[:offset])
+ assert_nil(Date._strptime('+23:00:60', '%Z')[:offset])
end
def test_strptime
diff --git a/test/did_you_mean/core_ext/test_name_error_extension.rb b/test/did_you_mean/core_ext/test_name_error_extension.rb
index 9dc08dbde3..116c7cd7b9 100644
--- a/test/did_you_mean/core_ext/test_name_error_extension.rb
+++ b/test/did_you_mean/core_ext/test_name_error_extension.rb
@@ -1,7 +1,9 @@
require_relative '../helper'
class NameErrorExtensionTest < Test::Unit::TestCase
- SPELL_CHECKERS = DidYouMean::SPELL_CHECKERS
+ include DidYouMean::TestHelper
+
+ SPELL_CHECKERS = DidYouMean.spell_checkers
class TestSpellChecker
def initialize(*); end
@@ -9,18 +11,23 @@ class NameErrorExtensionTest < Test::Unit::TestCase
end
def setup
- @org, SPELL_CHECKERS['NameError'] = SPELL_CHECKERS['NameError'], TestSpellChecker
+ @original_spell_checker = DidYouMean.spell_checkers['NameError']
+ DidYouMean.correct_error(NameError, TestSpellChecker)
@error = assert_raise(NameError){ doesnt_exist }
end
def teardown
- SPELL_CHECKERS['NameError'] = @org
+ DidYouMean.correct_error(NameError, @original_spell_checker)
end
def test_message
- assert_match(/Did you mean\? does_exist/, @error.to_s)
- assert_match(/Did you mean\? does_exist/, @error.message)
+ if Exception.method_defined?(:detailed_message)
+ assert_match(/Did you mean\? does_exist/, @error.detailed_message)
+ else
+ assert_match(/Did you mean\? does_exist/, @error.to_s)
+ assert_match(/Did you mean\? does_exist/, @error.message)
+ end
end
def test_to_s_does_not_make_disruptive_changes_to_error_message
@@ -28,8 +35,8 @@ class NameErrorExtensionTest < Test::Unit::TestCase
raise NameError, "uninitialized constant Object"
end
- error.to_s
- assert_equal 1, error.to_s.scan("Did you mean?").count
+ get_message(error)
+ assert_equal 1, get_message(error).scan("Did you mean?").count
end
def test_correctable_error_objects_are_dumpable
@@ -40,9 +47,9 @@ class NameErrorExtensionTest < Test::Unit::TestCase
e
end
- error.to_s
+ get_message(error)
- assert_equal "undefined method `sizee' for #<File:test_name_error_extension.rb (closed)>",
- Marshal.load(Marshal.dump(error)).original_message
+ assert_match(/^undefined method [`']sizee' for /,
+ Marshal.load(Marshal.dump(error)).original_message)
end
end
diff --git a/test/did_you_mean/helper.rb b/test/did_you_mean/helper.rb
index d8aa41c3d1..d40d58d95d 100644
--- a/test/did_you_mean/helper.rb
+++ b/test/did_you_mean/helper.rb
@@ -4,6 +4,10 @@ module DidYouMean
module TestHelper
class << self
attr_reader :root
+
+ def ractor_compatible?
+ defined?(Ractor) && RUBY_VERSION >= "3.1.0"
+ end
end
if File.file?(File.expand_path('../lib/did_you_mean.rb', __dir__))
@@ -25,5 +29,15 @@ module DidYouMean
def assert_correction(expected, array)
assert_equal Array(expected), array, "Expected #{array.inspect} to only include #{expected.inspect}"
end
+
+ def get_message(err)
+ if err.respond_to?(:detailed_message)
+ err.detailed_message(highlight: false)
+ else
+ err.to_s
+ end
+ end
+
+ module_function :get_message
end
end
diff --git a/test/did_you_mean/spell_checking/test_key_name_check.rb b/test/did_you_mean/spell_checking/test_key_name_check.rb
index ea05ff69e4..2f246f04d7 100644
--- a/test/did_you_mean/spell_checking/test_key_name_check.rb
+++ b/test/did_you_mean/spell_checking/test_key_name_check.rb
@@ -8,11 +8,11 @@ class KeyNameCheckTest < Test::Unit::TestCase
error = assert_raise(KeyError) { hash.fetch(:bax) }
assert_correction ":bar", error.corrections
- assert_match "Did you mean? :bar", error.to_s
+ assert_match "Did you mean? :bar", get_message(error)
error = assert_raise(KeyError) { hash.fetch("fooo") }
assert_correction %("foo"), error.corrections
- assert_match %(Did you mean? "foo"), error.to_s
+ assert_match %(Did you mean? "foo"), get_message(error)
end
def test_corrects_hash_key_name_with_fetch_values
@@ -20,11 +20,11 @@ class KeyNameCheckTest < Test::Unit::TestCase
error = assert_raise(KeyError) { hash.fetch_values("foo", :bar, :bax) }
assert_correction ":bar", error.corrections
- assert_match "Did you mean? :bar", error.to_s
+ assert_match "Did you mean? :bar", get_message(error)
error = assert_raise(KeyError) { hash.fetch_values("foo", :bar, "fooo") }
assert_correction %("foo"), error.corrections
- assert_match %(Did you mean? "foo"), error.to_s
+ assert_match %(Did you mean? "foo"), get_message(error)
end
def test_correct_symbolized_hash_keys_with_string_value
@@ -32,13 +32,13 @@ class KeyNameCheckTest < Test::Unit::TestCase
error = assert_raise(KeyError) { hash.fetch('foo_1') }
assert_correction %(:foo_1), error.corrections
- assert_match %(Did you mean? :foo_1), error.to_s
+ assert_match %(Did you mean? :foo_1), get_message(error)
end
def test_corrects_sprintf_key_name
error = assert_raise(KeyError) { sprintf("%<foo>d", {fooo: 1}) }
assert_correction ":fooo", error.corrections
- assert_match "Did you mean? :fooo", error.to_s
+ assert_match "Did you mean? :fooo", get_message(error)
end
def test_corrects_env_key_name
@@ -46,7 +46,7 @@ class KeyNameCheckTest < Test::Unit::TestCase
ENV["BAR"] = "2"
error = assert_raise(KeyError) { ENV.fetch("BAX") }
assert_correction %("BAR"), error.corrections
- assert_match %(Did you mean? "BAR"), error.to_s
+ assert_match %(Did you mean? "BAR"), get_message(error)
ensure
ENV.delete("FOO")
ENV.delete("BAR")
diff --git a/test/did_you_mean/spell_checking/test_method_name_check.rb b/test/did_you_mean/spell_checking/test_method_name_check.rb
index 6e14e6acc4..4daaf7cec7 100644
--- a/test/did_you_mean/spell_checking/test_method_name_check.rb
+++ b/test/did_you_mean/spell_checking/test_method_name_check.rb
@@ -4,6 +4,8 @@ class MethodNameCheckTest < Test::Unit::TestCase
include DidYouMean::TestHelper
class User
+ attr_writer :writer
+ attr_reader :reader
def friends; end
def first_name; end
def descendants; end
@@ -41,28 +43,28 @@ class MethodNameCheckTest < Test::Unit::TestCase
error = assert_raise(NoMethodError){ @user.flrst_name }
assert_correction :first_name, error.corrections
- assert_match "Did you mean? first_name", error.to_s
+ assert_match "Did you mean? first_name", get_message(error)
end
def test_corrections_include_private_method
error = assert_raise(NoMethodError){ @user.friend }
assert_correction :friends, error.corrections
- assert_match "Did you mean? friends", error.to_s
+ assert_match "Did you mean? friends", get_message(error)
end
def test_corrections_include_method_from_module
error = assert_raise(NoMethodError){ @user.fr0m_module }
assert_correction :from_module, error.corrections
- assert_match "Did you mean? from_module", error.to_s
+ assert_match "Did you mean? from_module", get_message(error)
end
def test_corrections_include_class_method
error = assert_raise(NoMethodError){ User.l0ad }
assert_correction :load, error.corrections
- assert_match "Did you mean? load", error.to_s
+ assert_match "Did you mean? load", get_message(error)
end
def test_private_methods_should_not_be_suggested
@@ -77,7 +79,7 @@ class MethodNameCheckTest < Test::Unit::TestCase
error = assert_raise(NoMethodError){ @user.call_incorrect_private_method }
assert_correction :raise, error.corrections
- assert_match "Did you mean? raise", error.to_s
+ assert_match "Did you mean? raise", get_message(error)
end
def test_exclude_methods_on_nil
@@ -104,7 +106,7 @@ class MethodNameCheckTest < Test::Unit::TestCase
end
end
- assert_equal 1, error.to_s.scan(/Did you mean/).count
+ assert_equal 1, get_message(error).scan(/Did you mean/).count
end
def test_does_not_append_suggestions_three_times
@@ -116,7 +118,7 @@ class MethodNameCheckTest < Test::Unit::TestCase
end
end
- assert_equal 1, error.to_s.scan(/Did you mean/).count
+ assert_equal 1, get_message(error).scan(/Did you mean/).count
end
def test_suggests_corrections_on_nested_error
@@ -128,20 +130,36 @@ class MethodNameCheckTest < Test::Unit::TestCase
end
end
- assert_equal 1, error.to_s.scan(/Did you mean/).count
+ assert_equal 1, get_message(error).scan(/Did you mean/).count
end
def test_suggests_yield
error = assert_raise(NoMethodError) { yeild(1) }
assert_correction :yield, error.corrections
- assert_match "Did you mean? yield", error.to_s
+ assert_match "Did you mean? yield", get_message(error)
end
def test_does_not_suggest_yield
error = assert_raise(NoMethodError) { 1.yeild }
assert_correction [], error.corrections
- assert_not_match(/Did you mean\? +yield/, error.to_s)
+ assert_not_match(/Did you mean\? +yield/, get_message(error))
end if RUBY_ENGINE != "jruby"
+
+ # Do not suggest `name=` for `name`
+ def test_does_not_suggest_writer
+ error = assert_raise(NoMethodError) { @user.writer }
+
+ assert_correction [], error.corrections
+ assert_not_match(/Did you mean\? writer=/, get_message(error))
+ end
+
+ # Do not suggest `name` for `name=`
+ def test_does_not_suggest_reader
+ error = assert_raise(NoMethodError) { @user.reader = 1 }
+
+ assert_correction [], error.corrections
+ assert_not_match(/Did you mean\? reader/, get_message(error))
+ end
end
diff --git a/test/did_you_mean/spell_checking/test_pattern_key_name_check.rb b/test/did_you_mean/spell_checking/test_pattern_key_name_check.rb
new file mode 100644
index 0000000000..10f973802b
--- /dev/null
+++ b/test/did_you_mean/spell_checking/test_pattern_key_name_check.rb
@@ -0,0 +1,20 @@
+require_relative '../helper'
+
+return if !defined?(::NoMatchingPatternKeyError)
+
+class PatternKeyNameCheckTest < Test::Unit::TestCase
+ include DidYouMean::TestHelper
+
+ def test_corrects_hash_key_name_with_single_pattern_match
+ error = assert_raise(NoMatchingPatternKeyError) do
+ eval(<<~RUBY, binding, __FILE__, __LINE__)
+ hash = {foo: 1, bar: 2, baz: 3}
+ hash => {fooo:}
+ fooo = 1 # suppress "unused variable: fooo" warning
+ RUBY
+ end
+
+ assert_correction ":foo", error.corrections
+ assert_match "Did you mean? :foo", get_message(error)
+ end
+end
diff --git a/test/did_you_mean/spell_checking/test_require_path_check.rb b/test/did_you_mean/spell_checking/test_require_path_check.rb
index f67fab0568..d6c06e9999 100644
--- a/test/did_you_mean/spell_checking/test_require_path_check.rb
+++ b/test/did_you_mean/spell_checking/test_require_path_check.rb
@@ -11,7 +11,7 @@ class RequirePathCheckTest < Test::Unit::TestCase
end
assert_correction 'ostruct', error.corrections
- assert_match "Did you mean? ostruct", error.to_s
+ assert_match "Did you mean? ostruct", get_message(error)
end
def test_load_error_from_require_for_nested_files_has_suggestions
@@ -20,13 +20,13 @@ class RequirePathCheckTest < Test::Unit::TestCase
end
assert_correction 'net/http', error.corrections
- assert_match "Did you mean? net/http", error.to_s
+ assert_match "Did you mean? net/http", get_message(error)
error = assert_raise LoadError do
require 'net-http'
end
assert_correction ['net/http', 'net/https'], error.corrections
- assert_match "Did you mean? net/http", error.to_s
+ assert_match "Did you mean? net/http", get_message(error)
end
end
diff --git a/test/did_you_mean/spell_checking/test_variable_name_check.rb b/test/did_you_mean/spell_checking/test_variable_name_check.rb
index 193e2b7520..0350b62660 100644
--- a/test/did_you_mean/spell_checking/test_variable_name_check.rb
+++ b/test/did_you_mean/spell_checking/test_variable_name_check.rb
@@ -39,7 +39,7 @@ class VariableNameCheckTest < Test::Unit::TestCase
end
assert_correction :first_name, error.corrections
- assert_match "Did you mean? first_name", error.to_s
+ assert_match "Did you mean? first_name", get_message(error)
end
def test_corrections_include_method_from_module
@@ -48,7 +48,7 @@ class VariableNameCheckTest < Test::Unit::TestCase
end
assert_correction :from_module, error.corrections
- assert_match "Did you mean? from_module", error.to_s
+ assert_match "Did you mean? from_module", get_message(error)
end
def test_corrections_include_local_variable_name
@@ -57,7 +57,7 @@ class VariableNameCheckTest < Test::Unit::TestCase
error = (eprson rescue $!) # Do not use @assert_raise here as it changes a scope.
assert_correction :person, error.corrections
- assert_match "Did you mean? person", error.to_s
+ assert_match "Did you mean? person", get_message(error)
end
end
@@ -81,30 +81,30 @@ class VariableNameCheckTest < Test::Unit::TestCase
end
assert_correction :false, false_error.corrections
- assert_match "Did you mean? false", false_error.to_s
+ assert_match "Did you mean? false", get_message(false_error)
assert_correction :true, true_error.corrections
- assert_match "Did you mean? true", true_error.to_s
+ assert_match "Did you mean? true", get_message(true_error)
assert_correction :nil, nil_error.corrections
- assert_match "Did you mean? nil", nil_error.to_s
+ assert_match "Did you mean? nil", get_message(nil_error)
assert_correction :__FILE__, file_error.corrections
- assert_match "Did you mean? __FILE__", file_error.to_s
+ assert_match "Did you mean? __FILE__", get_message(file_error)
end
def test_suggests_yield
error = assert_raise(NameError) { yeild }
assert_correction :yield, error.corrections
- assert_match "Did you mean? yield", error.to_s
+ assert_match "Did you mean? yield", get_message(error)
end
def test_corrections_include_instance_variable_name
error = assert_raise(NameError){ @user.to_s }
assert_correction :@email_address, error.corrections
- assert_match "Did you mean? @email_address", error.to_s
+ assert_match "Did you mean? @email_address", get_message(error)
end
def test_corrections_include_private_method
@@ -113,7 +113,7 @@ class VariableNameCheckTest < Test::Unit::TestCase
end
assert_correction :cia_codename, error.corrections
- assert_match "Did you mean? cia_codename", error.to_s
+ assert_match "Did you mean? cia_codename", get_message(error)
end
@@does_exist = true
@@ -122,7 +122,7 @@ class VariableNameCheckTest < Test::Unit::TestCase
error = assert_raise(NameError){ @@doesnt_exist }
assert_correction :@@does_exist, error.corrections
- assert_match "Did you mean? @@does_exist", error.to_s
+ assert_match "Did you mean? @@does_exist", get_message(error)
end
def test_struct_name_error
@@ -130,11 +130,23 @@ class VariableNameCheckTest < Test::Unit::TestCase
error = assert_raise(NameError){ value[:doesnt_exist] }
assert_correction [:does_exist, :does_exist=], error.corrections
- assert_match "Did you mean? does_exist", error.to_s
+ assert_match "Did you mean? does_exist", get_message(error)
end
def test_exclude_typical_incorrect_suggestions
error = assert_raise(NameError){ foo }
assert_empty error.corrections
end
+
+ def test_exclude_duplicates_with_same_name
+ error = assert_raise(NameError) do
+ eval(<<~RUBY, binding, __FILE__, __LINE__)
+ bar = 1
+ def bar;end
+ zar
+ RUBY
+ end
+
+ assert_correction [:bar], error.corrections
+ end
end
diff --git a/test/did_you_mean/test_ractor_compatibility.rb b/test/did_you_mean/test_ractor_compatibility.rb
new file mode 100644
index 0000000000..7385f10612
--- /dev/null
+++ b/test/did_you_mean/test_ractor_compatibility.rb
@@ -0,0 +1,117 @@
+require_relative './helper'
+
+return if not DidYouMean::TestHelper.ractor_compatible?
+
+class RactorCompatibilityTest < Test::Unit::TestCase
+ def test_class_name_suggestion_works_in_ractor
+ assert_ractor(<<~CODE, require_relative: "helper")
+ class ::Book; end
+ include DidYouMean::TestHelper
+ error = Ractor.new {
+ begin
+ Boook
+ rescue NameError => e
+ e.corrections # It is important to call the #corrections method within Ractor.
+ e
+ end
+ }.take
+
+ assert_correction "Book", error.corrections
+ CODE
+ end
+
+ def test_key_name_suggestion_works_in_ractor
+ assert_ractor(<<~CODE, require_relative: "helper")
+ include DidYouMean::TestHelper
+ error = Ractor.new {
+ begin
+ hash = { "foo" => 1, bar: 2 }
+
+ hash.fetch(:bax)
+ rescue KeyError => e
+ e.corrections # It is important to call the #corrections method within Ractor.
+ e
+ end
+ }.take
+
+ assert_correction ":bar", error.corrections
+ assert_match "Did you mean? :bar", get_message(error)
+ CODE
+ end
+
+ def test_method_name_suggestion_works_in_ractor
+ assert_ractor(<<~CODE, require_relative: "helper")
+ include DidYouMean::TestHelper
+ error = Ractor.new {
+ begin
+ self.to__s
+ rescue NoMethodError => e
+ e.corrections # It is important to call the #corrections method within Ractor.
+ e
+ end
+ }.take
+
+ assert_correction :to_s, error.corrections
+ assert_match "Did you mean? to_s", get_message(error)
+ CODE
+ end
+
+ if defined?(::NoMatchingPatternKeyError)
+ def test_pattern_key_name_suggestion_works_in_ractor
+ assert_ractor(<<~CODE, require_relative: "helper")
+ include DidYouMean::TestHelper
+ error = Ractor.new {
+ begin
+ eval(<<~RUBY, binding, __FILE__, __LINE__)
+ hash = {foo: 1, bar: 2, baz: 3}
+ hash => {fooo:}
+ fooo = 1 # suppress "unused variable: fooo" warning
+ RUBY
+ rescue NoMatchingPatternKeyError => e
+ e.corrections # It is important to call the #corrections method within Ractor.
+ e
+ end
+ }.take
+
+ assert_correction ":foo", error.corrections
+ assert_match "Did you mean? :foo", get_message(error)
+ CODE
+ end
+ end
+
+ def test_can_raise_other_name_error_in_ractor
+ assert_ractor(<<~CODE, require_relative: "helper")
+ class FirstNameError < NameError; end
+ include DidYouMean::TestHelper
+ error = Ractor.new {
+ begin
+ raise FirstNameError, "Other name error"
+ rescue FirstNameError => e
+ e.corrections # It is important to call the #corrections method within Ractor.
+ e
+ end
+ }.take
+
+ assert_not_match(/Did you mean\?/, error.message)
+ CODE
+ end
+
+ def test_variable_name_suggestion_works_in_ractor
+ assert_ractor(<<~CODE, require_relative: "helper")
+ include DidYouMean::TestHelper
+ error = Ractor.new {
+ in_ractor = in_ractor = 1
+
+ begin
+ in_reactor
+ rescue NameError => e
+ e.corrections # It is important to call the #corrections method within Ractor.
+ e
+ end
+ }.take
+
+ assert_correction :in_ractor, error.corrections
+ assert_match "Did you mean? in_ractor", get_message(error)
+ CODE
+ end
+end
diff --git a/test/did_you_mean/test_spell_checker.rb b/test/did_you_mean/test_spell_checker.rb
index 98460b4d94..8445380de3 100644
--- a/test/did_you_mean/test_spell_checker.rb
+++ b/test/did_you_mean/test_spell_checker.rb
@@ -10,6 +10,7 @@ class SpellCheckerTest < Test::Unit::TestCase
assert_spell 'eval', input: 'veal', dictionary: ['email', 'fail', 'eval']
assert_spell 'sub!', input: 'suv!', dictionary: ['sub', 'gsub', 'sub!']
assert_spell 'sub', input: 'suv', dictionary: ['sub', 'gsub', 'sub!']
+ assert_spell 'Foo', input: 'FOo', dictionary: ['Foo', 'FOo']
assert_spell %w(gsub! gsub), input: 'gsuv!', dictionary: %w(sub gsub gsub!)
assert_spell %w(sub! sub gsub!), input: 'ssub!', dictionary: %w(sub sub! gsub gsub!)
diff --git a/test/did_you_mean/test_verbose_formatter.rb b/test/did_you_mean/test_verbose_formatter.rb
deleted file mode 100644
index d8f2f46273..0000000000
--- a/test/did_you_mean/test_verbose_formatter.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-require_relative './helper'
-
-class VerboseFormatterTest < Test::Unit::TestCase
- def setup
- require_relative File.join(DidYouMean::TestHelper.root, 'verbose')
-
- DidYouMean.formatter = DidYouMean::VerboseFormatter.new
- end
-
- def teardown
- DidYouMean.formatter = DidYouMean::PlainFormatter.new
- end
-
- def test_message
- @error = assert_raise(NoMethodError){ 1.zeor? }
-
- assert_match <<~MESSAGE.strip, @error.message
- undefined method `zeor?' for 1:Integer
-
- Did you mean? zero?
- MESSAGE
- end
-end
diff --git a/test/digest/test_digest_extend.rb b/test/digest/test_digest_extend.rb
index bd599f2d20..a66b896e1e 100644
--- a/test/digest/test_digest_extend.rb
+++ b/test/digest/test_digest_extend.rb
@@ -6,6 +6,11 @@ require_relative '../lib/with_different_ofs'
class TestDigestExtend < Test::Unit::TestCase
extend DifferentOFS
+ TEST_DIGEST = %w[SHA1024 SHA512 SHA384 SHA256 SHA1].find do |n|
+ break Digest.const_get(n)
+ rescue LoadError
+ end
+
class MyDigest < Digest::Class
def initialize(*arg)
super
@@ -54,7 +59,7 @@ class TestDigestExtend < Test::Unit::TestCase
end
def test_class_reset
- a = Digest::SHA1.new
+ a = TEST_DIGEST.new
base = a.to_s
assert_equal(base, a.reset.to_s)
b = a.new
@@ -62,7 +67,7 @@ class TestDigestExtend < Test::Unit::TestCase
b.update('1')
assert_not_equal(base, b.to_s)
assert_equal(base, b.reset.to_s)
- end
+ end if TEST_DIGEST
def test_digest
assert_equal("\3", MyDigest.digest("foo"))
@@ -83,7 +88,7 @@ class TestDigestExtend < Test::Unit::TestCase
end
def test_new
- a = Digest::SHA1.new
+ a = TEST_DIGEST.new
b = a.new
obj = a.to_s
assert_equal(obj, a.to_s)
@@ -91,7 +96,7 @@ class TestDigestExtend < Test::Unit::TestCase
a.update('1')
assert_not_equal(obj, a.to_s)
assert_equal(obj, b.to_s)
- end
+ end if TEST_DIGEST
def test_digest_hexdigest
[:digest, :hexdigest].each do |m|
diff --git a/test/digest/test_ractor.rb b/test/digest/test_ractor.rb
index 0dbdcb9c8c..b34a3653b4 100644
--- a/test/digest/test_ractor.rb
+++ b/test/digest/test_ractor.rb
@@ -13,10 +13,6 @@ module TestDigestRactor
Data1 = "abc"
Data2 = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
- def setup
- pend unless defined?(Ractor)
- end
-
def test_s_hexdigest
assert_in_out_err([], <<-"end;", ["true", "true"], [])
$VERBOSE = nil
@@ -98,4 +94,4 @@ module TestDigestRactor
Data2 => "12a053384a9c0c88e405a06c27dcf49ada62eb2b",
}
end if defined?(Digest::RMD160)
-end
+end if defined?(Ractor)
diff --git a/test/drb/drbtest.rb b/test/drb/drbtest.rb
deleted file mode 100644
index acef380ad6..0000000000
--- a/test/drb/drbtest.rb
+++ /dev/null
@@ -1,394 +0,0 @@
-# frozen_string_literal: false
-require 'test/unit'
-require 'envutil'
-require 'drb/drb'
-require 'drb/extservm'
-require 'timeout'
-
-module DRbTests
-
-class DRbService
- @@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_eq.rb).each do |nm|
- add_service_command(nm)
- end
-
- def initialize
- @manager = DRb::ExtServManager.new
- start
- @manager.uri = server.uri
- end
-
- def start
- @server = DRb::DRbServer.new('druby://localhost:0', manager, {})
- end
-
- attr_reader :manager
- attr_reader :server
-
- def ext_service(name)
- EnvUtil.timeout(100, RuntimeError) do
- manager.service(name)
- end
- end
-
- def finish
- server.instance_variable_get(:@grp).list.each {|th| th.join }
- server.stop_service
- manager.instance_variable_get(:@queue)&.push(nil)
- manager.instance_variable_get(:@thread)&.join
- DRb::DRbConn.stop_pool
- 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 DRbBase
- def setup
- @drb_service ||= DRbService.new
- end
-
- def setup_service(service_name)
- @service_name = service_name
- @ext = @drb_service.ext_service(@service_name)
- @there = @ext.front
- end
-
- def teardown
- @ext.stop_service if defined?(@ext) && @ext
- if defined?(@service_name) && @service_name
- @drb_service.manager.unregist(@service_name)
- while (@there&&@there.to_s rescue nil)
- # nop
- end
- signal = /mswin|mingw/ =~ RUBY_PLATFORM ? :KILL : :TERM
- Thread.list.each {|th|
- if th.respond_to?(:pid) && th[:drb_service] == @service_name
- 10.times do
- begin
- Process.kill signal, th.pid
- break
- rescue Errno::ESRCH
- break
- rescue Errno::EPERM # on Windows
- sleep 0.1
- retry
- end
- end
- th.join
- end
- }
- end
- @drb_service.finish
- DRb::DRbConn.stop_pool
- end
-end
-
-module DRbCore
- include DRbBase
-
- 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_respond_to(@there, [:to_a, true])
- assert_respond_to(@there, [:eval, true])
- assert_not_respond_to(@there, [:eval, false])
- assert_not_respond_to(@there, :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_basic_object
- obj = @there.basic_object
- assert_kind_of(DRb::DRbObject, obj)
- assert_equal(1, obj.foo)
- assert_raise(NoMethodError){obj.prot}
- assert_raise(NoMethodError){obj.priv}
- end
-
- def test_02_unknown
- obj = @there.unknown_class
- assert_kind_of(DRb::DRbUnknown, obj)
- assert_equal('DRbTests::Unknown2', obj.name)
-
- obj = @there.unknown_module
- assert_kind_of(DRb::DRbUnknown, obj)
- assert_equal('DRbTests::DRbEx::', obj.name)
-
- assert_raise(DRb::DRbUnknownError) do
- @there.unknown_error
- end
-
- onecky = FailOnecky.new('3')
-
- assert_raise(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_raise(DRb::DRbConnError) do
- @there.sum(1, 1, 1, 1, 1, 1, 1, 1, 1)
- end
- assert_raise(DRb::DRbConnError) do
- @there.sum('1' * 4096)
- end
- end
-
- def test_04
- assert_respond_to(@there, 'sum')
- assert_not_respond_to(@there, "foobar")
- end
-
- def test_05_eq
- a = @there.to_a[0]
- b = @there.to_a[0]
- assert_not_same(a, b)
- assert_equal(a, b)
- assert_equal(a, @there)
- assert_equal(a.hash, b.hash)
- assert_equal(a.hash, @there.hash)
- assert_operator(a, :eql?, b)
- assert_operator(a, :eql?, @there)
- end
-
- def test_06_timeout
- skip if RUBY_PLATFORM.include?("armv7l-linux")
- skip if RUBY_PLATFORM.include?("sparc-solaris2.10")
- skip if defined?(RubyVM::JIT) && RubyVM::JIT.enabled? # expecting a certain delay is difficult for --jit-wait CI
- Timeout.timeout(60) do
- ten = Onecky.new(10)
- assert_raise(Timeout::Error) do
- @there.do_timeout(ten)
- end
- assert_raise(Timeout::Error) do
- @there.do_timeout(ten)
- end
- end
- end
-
- def test_07_private_missing
- e = assert_raise(NoMethodError) {
- @there.method_missing(:eval, 'nil')
- }
- assert_match(/^private method \`eval\'/, e.message)
-
- e = assert_raise(NoMethodError) {
- @there.call_private_method
- }
- assert_match(/^private method \`call_private_method\'/, e.message)
- end
-
- def test_07_protected_missing
- e = assert_raise(NoMethodError) {
- @there.call_protected_method
- }
- assert_match(/^protected method \`call_protected_method\'/, e.message)
- end
-
- def test_07_public_missing
- e = assert_raise(NoMethodError) {
- @there.method_missing(:undefined_method_test)
- }
- assert_match(/^undefined method \`undefined_method_test\'/, e.message)
- end
-
- def test_07_send_missing
- assert_raise(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_raise(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
- include DRbBase
-
- 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
-
-end
diff --git a/test/drb/ignore_test_drb.rb b/test/drb/ignore_test_drb.rb
deleted file mode 100644
index 996a554c0f..0000000000
--- a/test/drb/ignore_test_drb.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-# frozen_string_literal: false
-require 'drbtest'
-
-module DRbTests
-
-class TestDRbReusePort < Test::Unit::TestCase
- include DRbAry
-
- def setup
- setup_service 'ut_port.rb'
- end
-end
-
-end
diff --git a/test/drb/test_acl.rb b/test/drb/test_acl.rb
deleted file mode 100644
index ea7b32e76f..0000000000
--- a/test/drb/test_acl.rb
+++ /dev/null
@@ -1,207 +0,0 @@
-# frozen_string_literal: false
-# 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'
-
-module DRbTests
-
-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_operator(a, :match, h)
- assert_operator(b, :match, h)
- end
- end
-
- def test_ip_v6
- a = ACL::ACLEntry.new('::ffff:192.0.0.0/104')
- assert_not_operator(a, :match, @hosts['localhost'])
- assert_operator(a, :match, @hosts['yum'])
- assert_operator(a, :match, @hosts['ipv6'])
- assert_not_operator(a, :match, @hosts['too'])
- end
-
- def test_ip
- a = ACL::ACLEntry.new('192.0.0.0/8')
- assert_not_operator(a, :match, @hosts['localhost'])
- assert_operator(a, :match, @hosts['yum'])
-
- a = ACL::ACLEntry.new('192.168.1.0/255.255.255.0')
- assert_not_operator(a, :match, @hosts['localhost'])
- assert_operator(a, :match, @hosts['yum'])
- assert_operator(a, :match, @hosts['x68k'])
-
- a = ACL::ACLEntry.new('192.168.1.0/24')
- assert_not_operator(a, :match, @hosts['localhost'])
- assert_operator(a, :match, @hosts['yum'])
- assert_operator(a, :match, @hosts['x68k'])
-
- a = ACL::ACLEntry.new('92.0.0.0/8')
- assert_not_operator(a, :match, @hosts['localhost'])
- assert_not_operator(a, :match, @hosts['yum'])
- assert_not_operator(a, :match, @hosts['x68k'])
-
- a = ACL::ACLEntry.new('127.0.0.0/255.0.0.0')
- assert_operator(a, :match, @hosts['localhost'])
- assert_not_operator(a, :match, @hosts['yum'])
- assert_not_operator(a, :match, @hosts['x68k'])
-
- assert_raise(IPAddr::InvalidPrefixError) {
- ACL::ACLEntry.new('192.168.0.0/33')
- }
- assert_raise(IPAddr::InvalidPrefixError) {
- ACL::ACLEntry.new('192.168.0.0/255.255.0.255')
- }
- end
-
- def test_name
- a = ACL::ACLEntry.new('*.jp')
- assert_not_operator(a, :match, @hosts['localhost'])
- assert_operator(a, :match, @hosts['yum'])
-
- a = ACL::ACLEntry.new('yum.*.jp')
- assert_operator(a, :match, @hosts['yum'])
- assert_not_operator(a, :match, @hosts['lc630'])
-
- a = ACL::ACLEntry.new('*.macos.or.jp')
- assert_operator(a, :match, @hosts['yum'])
- assert_operator(a, :match, @hosts['lc630'])
- assert_not_operator(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_operator(a, :match, h)
- end
- end
-
- def test_all_2
- a = build(%w(localhost 127.0.0.0/8 yum.* *))
- @hostlist.each do |h|
- assert_operator(a, :match, h)
- end
- end
-
- def test_1
- a = build(%w(192.168.1.0/255.255.255.252 yum.*.jp))
- assert_operator(a, :match, @hosts['x68k'])
- assert_operator(a, :match, @hosts['lc630'])
- assert_operator(a, :match, @hosts['lib30'])
- assert_not_operator(a, :match, @hosts['ns00'])
- assert_operator(a, :match, @hosts['yum'])
- end
-
- def test_2
- a = build(%w(*.linux.or.jp))
- assert_not_operator(a, :match, @hosts['yum'])
- assert_operator(a, :match, @hosts['x68k'])
- assert_not_operator(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_operator(a, :allow_addr?, h)
- end
- end
-
- def test_not_0
- a = ACL.new([], ACL::ALLOW_DENY)
- @hostlist.each do |h|
- assert_not_operator(a, :allow_addr?, h)
- end
- end
-
- def test_1
- data = %w(deny all
- allow localhost
- allow x68k.*)
-
- a = ACL.new(data)
- assert_operator(a, :allow_addr?, @hosts['x68k'])
- assert_operator(a, :allow_addr?, @hosts['localhost'])
- assert_not_operator(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_not_operator(a, :allow_addr?, @hosts['x68k'])
- assert_operator(a, :allow_addr?, @hosts['localhost'])
- assert_not_operator(a, :allow_addr?, @hosts['lc630'])
- end
-end
-
-end
diff --git a/test/drb/test_drb.rb b/test/drb/test_drb.rb
deleted file mode 100644
index 1ee1b265d0..0000000000
--- a/test/drb/test_drb.rb
+++ /dev/null
@@ -1,370 +0,0 @@
-# frozen_string_literal: false
-require_relative 'drbtest'
-
-module DRbTests
-
-class TestDRbCore < Test::Unit::TestCase
- include DRbCore
-
- def setup
- super
- setup_service 'ut_drb.rb'
- end
-end
-
-module DRbYield
- include DRbBase
-
- 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
-end
-
-class TestDRbYield < Test::Unit::TestCase
- include DRbYield
-
- def setup
- super
- setup_service 'ut_drb.rb'
- end
-end
-
-class TestDRbRubyYield < Test::Unit::TestCase
- include DRbYield
-
- def setup
- @there = self
- super
- end
-
- 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
-
-end
-
-class TestDRbRuby18Yield < Test::Unit::TestCase
- include DRbYield
-
- 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
- super
- end
-end
-
-class TestDRbAry < Test::Unit::TestCase
- include DRbAry
-
- def setup
- super
- setup_service 'ut_array.rb'
- end
-end
-
-class TestDRbMServer < Test::Unit::TestCase
- include DRbBase
-
- def setup
- super
- setup_service 'ut_drb.rb'
- @server = (1..3).collect do |n|
- DRb::DRbServer.new("druby://localhost:0", Onecky.new(n.to_s))
- end
- end
-
- def teardown
- @server.each do |s|
- s.stop_service
- end
- super
- end
-
- def test_01
- assert_equal(6, @there.sample(@server[0].front, @server[1].front, @server[2].front))
- end
-end
-
-class TestDRbSafe1 < Test::Unit::TestCase
- include DRbAry
- def setup
- super
- setup_service 'ut_safe1.rb'
- end
-end
-
-class TestDRbLarge < Test::Unit::TestCase
- include DRbBase
-
- def setup
- super
- setup_service 'ut_large.rb'
- end
-
- def test_01_large_ary
- ary = [2] * 10240
- assert_equal(10240, @there.size(ary))
- assert_equal(20480, @there.sum(ary))
- assert_equal(2 ** 10240, @there.multiply(ary))
- assert_equal(2, @there.avg(ary))
- assert_equal(2, @there.median(ary))
- end
-
- def test_02_large_ary
- ary = ["Hello, World"] * 10240
- assert_equal(10240, @there.size(ary))
- assert_equal(ary[0..ary.length].inject(:+), @there.sum(ary))
- assert_raise(TypeError) {@there.multiply(ary)}
- assert_raise(TypeError) {@there.avg(ary)}
- assert_raise(TypeError) {@there.median(ary)}
- end
-
- def test_03_large_ary
- ary = [Thread.current] * 10240
- assert_equal(10240, @there.size(ary))
- end
-
- def test_04_many_arg
- assert_raise(DRb::DRbConnError) {
- @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
-
- def test_06_array_operations
- ary = [1,50,3,844,7,45,23]
- assert_equal(7, @there.size(ary))
- assert_equal(973, @there.sum(ary))
- assert_equal(917217000, @there.multiply(ary))
- assert_equal(139.0, @there.avg(ary))
- assert_equal(23.0, @there.median(ary))
-
- ary2 = [1,2,3,4]
- assert_equal(4, @there.size(ary2))
- assert_equal(10, @there.sum(ary2))
- assert_equal(24, @there.multiply(ary2))
- assert_equal(2.5, @there.avg(ary2))
- assert_equal(2.5, @there.median(ary2))
-
- end
-
- def test_07_one_element_array
- ary = [50]
- assert_equal(1, @there.size(ary))
- assert_equal(50, @there.sum(ary))
- assert_equal(50, @there.multiply(ary))
- assert_equal(50.0, @there.avg(ary))
- assert_equal(50.0, @there.median(ary))
- end
-
- def test_08_empty_array
- ary = []
- assert_equal(0, @there.size(ary))
- assert_equal(nil, @there.sum(ary))
- assert_equal(nil, @there.multiply(ary))
- assert_equal(nil, @there.avg(ary))
- assert_equal(nil, @there.median(ary))
- end
-end
-
-class TestBug4409 < Test::Unit::TestCase
- include DRbBase
-
- def setup
- super
- setup_service 'ut_eq.rb'
- end
-
- def test_bug4409
- foo = @there.foo
- assert_operator(@there, :foo?, foo)
- end
-end
-
-class TestDRbAnyToS < Test::Unit::TestCase
- class BO < BasicObject
- end
-
- def test_any_to_s
- server = DRb::DRbServer.new('druby://localhost:0')
- server.singleton_class.send(:public, :any_to_s)
- assert_equal("foo:String", server.any_to_s("foo"))
- assert_match(/\A#<DRbTests::TestDRbAnyToS::BO:0x[0-9a-f]+>\z/, server.any_to_s(BO.new))
- server.stop_service
- server.thread.join
- DRb::DRbConn.stop_pool
- end
-end
-
-class TestDRbTCP < Test::Unit::TestCase
- def test_immediate_close
- server = DRb::DRbServer.new('druby://localhost:0')
- host, port, = DRb::DRbTCPSocket.send(:parse_uri, server.uri)
- socket = TCPSocket.open host, port
- socket.shutdown
- socket.close
- client = DRb::DRbTCPSocket.new(server.uri, socket)
- assert client
- ensure
- client&.close
- socket&.close
- server.stop_service
- server.thread.join
- DRb::DRbConn.stop_pool
- end
-end
-
-class TestBug16634 < Test::Unit::TestCase
- include DRbBase
-
- def setup
- super
- setup_service 'ut_drb.rb'
- end
-
- def test_bug16634
- assert_equal(42, @there.keyword_test1(a: 42))
- assert_equal("default", @there.keyword_test2)
- assert_equal(42, @there.keyword_test2(b: 42))
- assert_equal({:a=>42, :b=>42}, @there.keyword_test3(a: 42, b: 42))
- end
-end
-
-end
diff --git a/test/drb/test_drbobject.rb b/test/drb/test_drbobject.rb
deleted file mode 100644
index 2b0e2061ee..0000000000
--- a/test/drb/test_drbobject.rb
+++ /dev/null
@@ -1,69 +0,0 @@
-require 'test/unit'
-require 'drb'
-require 'drb/timeridconv'
-require 'drb/weakidconv'
-
-module DRbObjectTest
- class Foo
- def initialize
- @foo = 'foo'
- end
- end
-
- def teardown
- DRb.stop_service
- DRb::DRbConn.stop_pool
- end
-
- def drb_eq(obj)
- proxy = DRbObject.new(obj)
- assert_equal(obj, DRb.to_obj(proxy.__drbref))
- end
-
- def test_DRbObject_id_dereference
- drb_eq(Foo.new)
- drb_eq(Foo)
- drb_eq(File)
- drb_eq(Enumerable)
- drb_eq(nil)
- drb_eq(1)
- drb_eq($stdout)
- drb_eq([])
- end
-end
-
-class TestDRbObject < Test::Unit::TestCase
- include DRbObjectTest
-
- def setup
- DRb.start_service
- end
-end
-
-class TestDRbObjectTimerIdConv < Test::Unit::TestCase
- include DRbObjectTest
-
- def setup
- @idconv = DRb::TimerIdConv.new
- DRb.start_service(nil, nil, {:idconv => @idconv})
- end
-
- def teardown
- super
- # stop DRb::TimerIdConv::TimerHolder2#on_gc
- @idconv.instance_eval do
- @holder.instance_eval do
- @expires = nil
- end
- end
- GC.start
- end
-end
-
-class TestDRbObjectWeakIdConv < Test::Unit::TestCase
- include DRbObjectTest
-
- def setup
- DRb.start_service(nil, nil, {:idconv => DRb::WeakIdConv.new})
- end
-end
diff --git a/test/drb/test_drbssl.rb b/test/drb/test_drbssl.rb
deleted file mode 100644
index 0254c7ab50..0000000000
--- a/test/drb/test_drbssl.rb
+++ /dev/null
@@ -1,72 +0,0 @@
-# frozen_string_literal: false
-require_relative 'drbtest'
-
-begin
- require 'drb/ssl'
-rescue LoadError
-end
-
-module DRbTests
-
-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
-
- def start
- 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
-
- @server = DRb::DRbServer.new('drbssl://localhost:0', manager, config)
- end
-end
-
-class TestDRbSSLCore < Test::Unit::TestCase
- include DRbCore
- def setup
- @drb_service = DRbSSLService.new
- super
- setup_service 'ut_drb_drbssl.rb'
- 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
- LeakChecker.skip if defined?(LeakChecker)
- @drb_service = DRbSSLService.new
- super
- setup_service 'ut_array_drbssl.rb'
- end
-end
-
-
-end
-
-end
diff --git a/test/drb/test_drbunix.rb b/test/drb/test_drbunix.rb
deleted file mode 100644
index 95b3c3ca91..0000000000
--- a/test/drb/test_drbunix.rb
+++ /dev/null
@@ -1,60 +0,0 @@
-# frozen_string_literal: false
-require_relative 'drbtest'
-
-begin
- require 'drb/unix'
-rescue LoadError
-end
-
-module DRbTests
-
-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
-
- def start
- @server = DRb::DRbServer.new('drbunix:', manager, {})
- end
-end
-
-class TestDRbUNIXCore < Test::Unit::TestCase
- include DRbCore
- def setup
- @drb_service = DRbUNIXService.new
- super
- setup_service 'ut_drb_drbunix.rb'
- end
-
- def test_02_unknown
- end
-
- def test_01_02_loop
- end
-
- def test_05_eq
- end
-
- def test_bad_uri
- assert_raise(DRb::DRbBadURI) do
- DRb::DRbServer.new("badfile\n""drbunix:")
- end
- end
-end
-
-class TestDRbUNIXAry < Test::Unit::TestCase
- include DRbAry
- def setup
- @drb_service = DRbUNIXService.new
- super
- setup_service 'ut_array_drbunix.rb'
- end
-end
-
-
-end
-
-end
diff --git a/test/drb/ut_array.rb b/test/drb/ut_array.rb
deleted file mode 100644
index d13dda3d8e..0000000000
--- a/test/drb/ut_array.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: false
-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])
- es = DRb::ExtServ.new(ARGV.shift, ARGV.shift)
- DRb.thread.join
- es.stop_service if es.alive?
-end
-
diff --git a/test/drb/ut_array_drbssl.rb b/test/drb/ut_array_drbssl.rb
deleted file mode 100644
index 5938d9ff3d..0000000000
--- a/test/drb/ut_array_drbssl.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# frozen_string_literal: false
-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
-
- module DRbTests
-
- TEST_KEY_DH1024 = OpenSSL::PKey::DH.new <<-_end_of_pem_
------BEGIN DH PARAMETERS-----
-MIGHAoGBAKnKQ8MNK6nYZzLrrcuTsLxuiJGXoOO5gT+tljOTbHBuiktdMTITzIY0
-pFxIvjG05D7HoBZQfrR0c92NGWPkAiCkhQKB8JCbPVzwNLDy6DZ0pmofDKrEsYHG
-AQjjxMXhwULlmuR/K+WwlaZPiLIBYalLAZQ7ZbOPeVkJ8ePao0eLAgEC
------END DH PARAMETERS-----
- _end_of_pem_
-
- end
-
- config = Hash.new
- config[:SSLTmpDhCallback] = proc { DRbTests::TEST_KEY_DH1024 }
- 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://localhost:0', [1, 2, 'III', 4, "five", 6], config)
- es = DRb::ExtServ.new(ARGV.shift, ARGV.shift)
- DRb.thread.join
- es.stop_service if es.alive?
-end
-
diff --git a/test/drb/ut_array_drbunix.rb b/test/drb/ut_array_drbunix.rb
deleted file mode 100644
index b656cdaddd..0000000000
--- a/test/drb/ut_array_drbunix.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: false
-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
- es.stop_service if es.alive?
-end
-
diff --git a/test/drb/ut_drb.rb b/test/drb/ut_drb.rb
deleted file mode 100644
index 7c0603b009..0000000000
--- a/test/drb/ut_drb.rb
+++ /dev/null
@@ -1,189 +0,0 @@
-# frozen_string_literal: false
-require 'drb/drb'
-require 'drb/extserv'
-require 'timeout'
-
-module DRbTests
-
-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
- @xary2_hash = nil
- @hash = nil
- @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.timeout(0.1) do
- n.sleep(2)
- end
- end
-
- def unknown_module
- FooBar.new
- end
-
- class BO < ::BasicObject
- def foo; 1 end
- protected def prot; 2; end
- private def priv; 3; end
- end
- def basic_object
- @basic_object = BO.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
-
- def keyword_test1(a:)
- a
- end
-
- def keyword_test2(b: "default")
- b
- end
-
- def keyword_test3(**opt)
- opt
- end
-
- private
- def call_private_method
- true
- end
-
- protected
- def call_protected_method
- true
- end
-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', DRbTests::DRbEx.new)
- es = DRb::ExtServ.new(ARGV.shift, ARGV.shift)
- DRb.thread.join
- es.stop_service if es.alive?
-end
diff --git a/test/drb/ut_drb_drbssl.rb b/test/drb/ut_drb_drbssl.rb
deleted file mode 100644
index c8251716d6..0000000000
--- a/test/drb/ut_drb_drbssl.rb
+++ /dev/null
@@ -1,40 +0,0 @@
-# frozen_string_literal: false
-require_relative "ut_drb"
-require 'drb/ssl'
-
-if __FILE__ == $0
- def ARGV.shift
- it = super()
- raise "usage: #{$0} <manager-uri> <name>" unless it
- it
- end
-
- module DRbTests
-
- TEST_KEY_DH1024 = OpenSSL::PKey::DH.new <<-_end_of_pem_
------BEGIN DH PARAMETERS-----
-MIGHAoGBAKnKQ8MNK6nYZzLrrcuTsLxuiJGXoOO5gT+tljOTbHBuiktdMTITzIY0
-pFxIvjG05D7HoBZQfrR0c92NGWPkAiCkhQKB8JCbPVzwNLDy6DZ0pmofDKrEsYHG
-AQjjxMXhwULlmuR/K+WwlaZPiLIBYalLAZQ7ZbOPeVkJ8ePao0eLAgEC
------END DH PARAMETERS-----
- _end_of_pem_
-
- end
-
- config = Hash.new
- config[:SSLTmpDhCallback] = proc { DRbTests::TEST_KEY_DH1024 }
- 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', DRbTests::DRbEx.new, config)
- es = DRb::ExtServ.new(ARGV.shift, ARGV.shift)
- DRb.thread.join
- es.stop_service if es.alive?
-end
-
diff --git a/test/drb/ut_drb_drbunix.rb b/test/drb/ut_drb_drbunix.rb
deleted file mode 100644
index ecf0920451..0000000000
--- a/test/drb/ut_drb_drbunix.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-# frozen_string_literal: false
-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:', DRbTests::DRbEx.new)
- es = DRb::ExtServ.new(ARGV.shift, ARGV.shift)
- DRb.thread.join
- es.stop_service if es.alive?
-end
-
diff --git a/test/drb/ut_eq.rb b/test/drb/ut_eq.rb
deleted file mode 100644
index 56285a384f..0000000000
--- a/test/drb/ut_eq.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-# frozen_string_literal: false
-require 'drb/drb'
-require 'drb/extserv'
-
-module DRbTests
-
-class Foo
- include DRbUndumped
-end
-
-class Bar
- include DRbUndumped
- def initialize
- @foo = Foo.new
- end
- attr_reader :foo
-
- def foo?(foo)
- @foo == foo
- end
-end
-
-end
-
-if __FILE__ == $0
- def ARGV.shift
- it = super()
- raise "usage: #{$0} <uri> <name>" unless it
- it
- end
-
- DRb.start_service('druby://localhost:0', DRbTests::Bar.new)
- es = DRb::ExtServ.new(ARGV.shift, ARGV.shift)
- DRb.thread.join
- es.stop_service if es.alive?
-end
-
diff --git a/test/drb/ut_large.rb b/test/drb/ut_large.rb
deleted file mode 100644
index 9376ff119d..0000000000
--- a/test/drb/ut_large.rb
+++ /dev/null
@@ -1,62 +0,0 @@
-# frozen_string_literal: false
-require 'drb/drb'
-require 'drb/extserv'
-require 'timeout'
-
-module DRbTests
-
-class DRbLarge
- include DRbUndumped
-
- def size(ary)
- ary.size
- end
-
- def sum(ary)
- ary.inject(:+)
- end
-
- def multiply(ary)
- ary.inject(:*)
- end
-
- def avg(ary)
- return if ary.empty?
- if ary.any? {|n| n.is_a? String}
- raise TypeError
- else
- sum(ary).to_f / ary.count
- end
- end
-
- def median(ary)
- return if ary.empty?
- if ary.any? {|n| n.is_a? String}
- raise TypeError
- else
- avg ary.sort[((ary.length - 1) / 2)..(ary.length / 2)]
- end
- end
-
- def arg_test(*arg)
- # nop
- end
-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', DRbTests::DRbLarge.new)
- es = DRb::ExtServ.new(ARGV.shift, ARGV.shift)
- DRb.thread.join
- es.stop_service if es.alive?
-end
-
diff --git a/test/drb/ut_port.rb b/test/drb/ut_port.rb
deleted file mode 100644
index d317a307cc..0000000000
--- a/test/drb/ut_port.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: false
-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
- es.stop_service if es.alive?
-end
diff --git a/test/drb/ut_safe1.rb b/test/drb/ut_safe1.rb
deleted file mode 100644
index 4b16fa7d6d..0000000000
--- a/test/drb/ut_safe1.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: false
-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
- es.stop_service if es.alive?
-end
diff --git a/test/drb/ut_timerholder.rb b/test/drb/ut_timerholder.rb
deleted file mode 100644
index 1753b30c74..0000000000
--- a/test/drb/ut_timerholder.rb
+++ /dev/null
@@ -1,74 +0,0 @@
-# frozen_string_literal: false
-require 'test/unit'
-require 'drb/timeridconv'
-
-module DRbTests
-
-class TimerIdConvTest < Test::Unit::TestCase
- def test_usecase_01
- keeping = 0.1
- idconv = DRb::TimerIdConv.new(keeping)
-
- key = idconv.to_id(self)
- assert_equal(key, self.__id__)
- sleep(keeping)
- assert_equal(idconv.to_id(false), false.__id__)
- assert_equal(idconv.to_obj(key), self)
- sleep(keeping)
-
- assert_equal(idconv.to_obj(key), self)
- sleep(keeping)
-
- assert_equal(idconv.to_id(true), true.__id__)
- sleep(keeping)
-
- assert_raise do
- assert_equal(idconv.to_obj(key), self)
- end
-
- assert_raise do
- assert_equal(idconv.to_obj(false.__id__), false)
- end
-
- key = idconv.to_id(self)
- assert_equal(key, self.__id__)
- assert_equal(idconv.to_id(true), true.__id__)
- sleep(keeping)
- GC.start
- sleep(keeping)
- GC.start
- assert_raise do
- assert_equal(idconv.to_obj(key), self)
- end
- end
-
- def test_usecase_02
- keeping = 0.1
- idconv = DRb::TimerIdConv.new(keeping)
-
- key = idconv.to_id(self)
- assert_equal(key, self.__id__)
- sleep(keeping)
- GC.start
- sleep(keeping)
- GC.start
- assert_raise do
- assert_equal(idconv.to_obj(key), self)
- end
- GC.start
-
- key = idconv.to_id(self)
- assert_equal(key, self.__id__)
- sleep(keeping)
- GC.start
- sleep(keeping)
- GC.start
- assert_raise do
- assert_equal(idconv.to_obj(key), self)
- end
- end
-end
-
-
-end
-
diff --git a/test/dtrace/helper.rb b/test/dtrace/helper.rb
index ce730800b4..7fa16965f1 100644
--- a/test/dtrace/helper.rb
+++ b/test/dtrace/helper.rb
@@ -122,7 +122,7 @@ module DTrace
def trap_probe d_program, ruby_program
if Hash === d_program
d_program = d_program[IMPL] or
- skip "#{d_program} not implemented for #{IMPL}"
+ omit "#{d_program} not implemented for #{IMPL}"
elsif String === d_program && IMPL == :stap
d_program = dtrace2systemtap(d_program)
end
diff --git a/test/erb/test_erb.rb b/test/erb/test_erb.rb
index fb5e9b611e..555345a140 100644
--- a/test/erb/test_erb.rb
+++ b/test/erb/test_erb.rb
@@ -73,12 +73,28 @@ class TestERB < Test::Unit::TestCase
assert_equal("", ERB::Util.html_escape(""))
assert_equal("abc", ERB::Util.html_escape("abc"))
assert_equal("&lt;&lt;", ERB::Util.html_escape("<\<"))
+ assert_equal("&#39;&amp;&quot;&gt;&lt;", ERB::Util.html_escape("'&\"><"))
assert_equal("", ERB::Util.html_escape(nil))
assert_equal("123", ERB::Util.html_escape(123))
end
+ def test_html_escape_to_s
+ object = Object.new
+ def object.to_s
+ "object"
+ end
+ assert_equal("object", ERB::Util.html_escape(object))
+ end
+
+ def test_html_escape_extension
+ assert_nil(ERB::Util.method(:html_escape).source_location)
+ end if RUBY_ENGINE == 'ruby'
+
def test_concurrent_default_binding
+ # This test randomly fails with JRuby -- NameError: undefined local variable or method `template2'
+ pend if RUBY_ENGINE == 'jruby'
+
template1 = 'one <%= ERB.new(template2).result %>'
eval 'template2 = "two"', TOPLEVEL_BINDING
@@ -236,6 +252,8 @@ EOS
end
def test_invalid_trim_mode
+ pend if RUBY_ENGINE == 'truffleruby'
+
assert_warning(/#{__FILE__}:#{__LINE__ + 1}/) do
@erb.new("", trim_mode: 'abc-def')
end
@@ -695,6 +713,18 @@ EOS
erb = Marshal.load(Marshal.dump(erb))
assert_raise(ArgumentError) {erb.result}
end
+
+ def test_multi_line_comment_lineno
+ erb = ERB.new(<<~EOS)
+ <%= __LINE__ %>
+ <%#
+ %><%= __LINE__ %>
+ EOS
+ assert_equal <<~EOS, erb.result
+ 1
+ 3
+ EOS
+ end
end
class TestERBCoreWOStrScan < TestERBCore
diff --git a/test/erb/test_erb_command.rb b/test/erb/test_erb_command.rb
index 0baa59ddd5..6bf252c5cd 100644
--- a/test/erb/test_erb_command.rb
+++ b/test/erb/test_erb_command.rb
@@ -4,27 +4,17 @@ require 'test/unit'
class TestErbCommand < Test::Unit::TestCase
def test_var
- assert_in_out_err(["-I#{File.expand_path('../../lib', __dir__)}", "-w",
+ pend if RUBY_ENGINE == 'truffleruby'
+ assert_in_out_err(["-I#{File.expand_path('../../lib', __dir__)}",
File.expand_path("../../libexec/erb", __dir__),
"var=hoge"],
"<%=var%>", ["hoge"])
end
def test_template_file_encoding
- assert_in_out_err(["-I#{File.expand_path('../../lib', __dir__)}", "-w",
+ pend if RUBY_ENGINE == 'truffleruby'
+ assert_in_out_err(["-I#{File.expand_path('../../lib', __dir__)}",
File.expand_path("../../libexec/erb", __dir__)],
"<%=''.encoding.to_s%>", ["UTF-8"])
end
-
- # These interfaces will be removed at Ruby 2.7.
- def test_deprecated_option
- warnings = [
- "warning: -S option of erb command is deprecated. Please do not use this.",
- /\n.+\/libexec\/erb:\d+: warning: Passing safe_level with the 2nd argument of ERB\.new is deprecated\. Do not use it, and specify other arguments as keyword arguments\.\n/,
- ]
- assert_in_out_err(["-I#{File.expand_path('../../lib', __dir__)}", "-w",
- File.expand_path("../../libexec/erb", __dir__),
- "-S", "0"],
- "hoge", ["hoge"], warnings)
- end
end
diff --git a/test/error_highlight/test_error_highlight.rb b/test/error_highlight/test_error_highlight.rb
index 9fc14202b5..5f4c386990 100644
--- a/test/error_highlight/test_error_highlight.rb
+++ b/test/error_highlight/test_error_highlight.rb
@@ -1,11 +1,12 @@
require "test/unit"
require "error_highlight"
+require "did_you_mean"
require "tempfile"
class ErrorHighlightTest < Test::Unit::TestCase
class DummyFormatter
- def message_for(corrections)
+ def self.message_for(corrections)
""
end
end
@@ -13,7 +14,7 @@ class ErrorHighlightTest < Test::Unit::TestCase
def setup
if defined?(DidYouMean)
@did_you_mean_old_formatter = DidYouMean.formatter
- DidYouMean.formatter = DummyFormatter.new
+ DidYouMean.formatter = DummyFormatter
end
end
@@ -23,14 +24,48 @@ class ErrorHighlightTest < Test::Unit::TestCase
end
end
- def assert_error_message(klass, expected_msg, &blk)
- err = assert_raise(klass, &blk)
- assert_equal(expected_msg.chomp, err.message)
+ begin
+ method_not_exist
+ rescue NameError
+ if $!.message.include?("`")
+ def preprocess(msg)
+ msg
+ end
+ else
+ def preprocess(msg)
+ msg.sub("`", "'")
+ end
+ end
+ end
+
+ if Exception.method_defined?(:detailed_message)
+ def assert_error_message(klass, expected_msg, &blk)
+ omit unless klass < ErrorHighlight::CoreExt
+ err = assert_raise(klass, &blk)
+ assert_equal(preprocess(expected_msg).chomp, err.detailed_message(highlight: false).sub(/ \((?:NoMethod|Name)Error\)/, ""))
+ end
+ else
+ def assert_error_message(klass, expected_msg, &blk)
+ omit unless klass < ErrorHighlight::CoreExt
+ err = assert_raise(klass, &blk)
+ assert_equal(preprocess(expected_msg).chomp, err.message)
+ end
+ end
+
+ if begin; 1.time; rescue; $!.message.end_with?("an instance of Integer"); end
+ # new message format
+ NEW_MESSAGE_FORMAT = true
+ NIL_RECV_MESSAGE = "nil"
+ ONE_RECV_MESSAGE = "an instance of Integer"
+ else
+ NEW_MESSAGE_FORMAT = false
+ NIL_RECV_MESSAGE = "nil:NilClass"
+ ONE_RECV_MESSAGE = "1:Integer"
end
def test_CALL_noarg_1
assert_error_message(NoMethodError, <<~END) do
-undefined method `foo' for nil:NilClass
+undefined method `foo' for #{ NIL_RECV_MESSAGE }
nil.foo + 1
^^^^
@@ -42,7 +77,7 @@ undefined method `foo' for nil:NilClass
def test_CALL_noarg_2
assert_error_message(NoMethodError, <<~END) do
-undefined method `foo' for nil:NilClass
+undefined method `foo' for #{ NIL_RECV_MESSAGE }
.foo + 1
^^^^
@@ -55,7 +90,7 @@ undefined method `foo' for nil:NilClass
def test_CALL_noarg_3
assert_error_message(NoMethodError, <<~END) do
-undefined method `foo' for nil:NilClass
+undefined method `foo' for #{ NIL_RECV_MESSAGE }
foo + 1
^^^
@@ -68,7 +103,7 @@ undefined method `foo' for nil:NilClass
def test_CALL_noarg_4
assert_error_message(NoMethodError, <<~END) do
-undefined method `foo' for nil:NilClass
+undefined method `foo' for #{ NIL_RECV_MESSAGE }
(nil).foo + 1
^^^^
@@ -80,7 +115,7 @@ undefined method `foo' for nil:NilClass
def test_CALL_arg_1
assert_error_message(NoMethodError, <<~END) do
-undefined method `foo' for nil:NilClass
+undefined method `foo' for #{ NIL_RECV_MESSAGE }
nil.foo (42)
^^^^
@@ -92,7 +127,7 @@ undefined method `foo' for nil:NilClass
def test_CALL_arg_2
assert_error_message(NoMethodError, <<~END) do
-undefined method `foo' for nil:NilClass
+undefined method `foo' for #{ NIL_RECV_MESSAGE }
.foo (
^^^^
@@ -107,7 +142,7 @@ undefined method `foo' for nil:NilClass
def test_CALL_arg_3
assert_error_message(NoMethodError, <<~END) do
-undefined method `foo' for nil:NilClass
+undefined method `foo' for #{ NIL_RECV_MESSAGE }
foo (
^^^
@@ -122,7 +157,7 @@ undefined method `foo' for nil:NilClass
def test_CALL_arg_4
assert_error_message(NoMethodError, <<~END) do
-undefined method `foo' for nil:NilClass
+undefined method `foo' for #{ NIL_RECV_MESSAGE }
nil.foo(42)
^^^^
@@ -134,7 +169,7 @@ undefined method `foo' for nil:NilClass
def test_CALL_arg_5
assert_error_message(NoMethodError, <<~END) do
-undefined method `foo' for nil:NilClass
+undefined method `foo' for #{ NIL_RECV_MESSAGE }
.foo(
^^^^
@@ -149,7 +184,7 @@ undefined method `foo' for nil:NilClass
def test_CALL_arg_6
assert_error_message(NoMethodError, <<~END) do
-undefined method `foo' for nil:NilClass
+undefined method `foo' for #{ NIL_RECV_MESSAGE }
foo(
^^^
@@ -164,7 +199,7 @@ undefined method `foo' for nil:NilClass
def test_QCALL_1
assert_error_message(NoMethodError, <<~END) do
-undefined method `foo' for 1:Integer
+undefined method `foo' for #{ ONE_RECV_MESSAGE }
1&.foo
^^^^^
@@ -176,7 +211,7 @@ undefined method `foo' for 1:Integer
def test_QCALL_2
assert_error_message(NoMethodError, <<~END) do
-undefined method `foo' for 1:Integer
+undefined method `foo' for #{ ONE_RECV_MESSAGE }
1&.foo(42)
^^^^^
@@ -188,7 +223,7 @@ undefined method `foo' for 1:Integer
def test_CALL_aref_1
assert_error_message(NoMethodError, <<~END) do
-undefined method `[]' for nil:NilClass
+undefined method `[]' for #{ NIL_RECV_MESSAGE }
nil [ ]
^^^
@@ -200,7 +235,7 @@ undefined method `[]' for nil:NilClass
def test_CALL_aref_2
assert_error_message(NoMethodError, <<~END) do
-undefined method `[]' for nil:NilClass
+undefined method `[]' for #{ NIL_RECV_MESSAGE }
nil [0]
^^^
@@ -212,7 +247,7 @@ undefined method `[]' for nil:NilClass
def test_CALL_aref_3
assert_error_message(NoMethodError, <<~END) do
-undefined method `[]' for nil:NilClass
+undefined method `[]' for #{ NIL_RECV_MESSAGE }
END
nil [
@@ -223,8 +258,9 @@ undefined method `[]' for nil:NilClass
def test_CALL_aref_4
v = Object.new
+ recv = NEW_MESSAGE_FORMAT ? "an instance of Object" : v.inspect
assert_error_message(NoMethodError, <<~END) do
-undefined method `[]' for #{ v.inspect }
+undefined method `[]' for #{ recv }
v &.[](0)
^^^^
@@ -236,7 +272,7 @@ undefined method `[]' for #{ v.inspect }
def test_CALL_aref_5
assert_error_message(NoMethodError, <<~END) do
-undefined method `[]' for nil:NilClass
+undefined method `[]' for #{ NIL_RECV_MESSAGE }
(nil)[ ]
^^^
@@ -248,7 +284,7 @@ undefined method `[]' for nil:NilClass
def test_CALL_aset
assert_error_message(NoMethodError, <<~END) do
-undefined method `[]=' for nil:NilClass
+undefined method `[]=' for #{ NIL_RECV_MESSAGE }
nil.[]=
^^^^
@@ -261,7 +297,7 @@ undefined method `[]=' for nil:NilClass
def test_CALL_op_asgn
v = nil
assert_error_message(NoMethodError, <<~END) do
-undefined method `+' for nil:NilClass
+undefined method `+' for #{ NIL_RECV_MESSAGE }
v += 42
^
@@ -273,7 +309,7 @@ undefined method `+' for nil:NilClass
def test_CALL_special_call_1
assert_error_message(NoMethodError, <<~END) do
-undefined method `call' for nil:NilClass
+undefined method `call' for #{ NIL_RECV_MESSAGE }
END
nil.()
@@ -282,7 +318,7 @@ undefined method `call' for nil:NilClass
def test_CALL_special_call_2
assert_error_message(NoMethodError, <<~END) do
-undefined method `call' for nil:NilClass
+undefined method `call' for #{ NIL_RECV_MESSAGE }
END
nil.(42)
@@ -291,7 +327,7 @@ undefined method `call' for nil:NilClass
def test_CALL_send
assert_error_message(NoMethodError, <<~END) do
-undefined method `foo' for nil:NilClass
+undefined method `foo' for #{ NIL_RECV_MESSAGE }
nil.send(:foo, 42)
^^^^^
@@ -303,7 +339,7 @@ undefined method `foo' for nil:NilClass
def test_ATTRASGN_1
assert_error_message(NoMethodError, <<~END) do
-undefined method `[]=' for nil:NilClass
+undefined method `[]=' for #{ NIL_RECV_MESSAGE }
nil [ ] = 42
^^^^^
@@ -315,7 +351,7 @@ undefined method `[]=' for nil:NilClass
def test_ATTRASGN_2
assert_error_message(NoMethodError, <<~END) do
-undefined method `[]=' for nil:NilClass
+undefined method `[]=' for #{ NIL_RECV_MESSAGE }
nil [0] = 42
^^^^^
@@ -327,7 +363,7 @@ undefined method `[]=' for nil:NilClass
def test_ATTRASGN_3
assert_error_message(NoMethodError, <<~END) do
-undefined method `foo=' for nil:NilClass
+undefined method `foo=' for #{ NIL_RECV_MESSAGE }
nil.foo = 42
^^^^^^
@@ -339,7 +375,7 @@ undefined method `foo=' for nil:NilClass
def test_ATTRASGN_4
assert_error_message(NoMethodError, <<~END) do
-undefined method `[]=' for nil:NilClass
+undefined method `[]=' for #{ NIL_RECV_MESSAGE }
(nil)[0] = 42
^^^^^
@@ -351,7 +387,7 @@ undefined method `[]=' for nil:NilClass
def test_ATTRASGN_5
assert_error_message(NoMethodError, <<~END) do
-undefined method `foo=' for nil:NilClass
+undefined method `foo=' for #{ NIL_RECV_MESSAGE }
(nil).foo = 42
^^^^^^
@@ -363,7 +399,7 @@ undefined method `foo=' for nil:NilClass
def test_OPCALL_binary_1
assert_error_message(NoMethodError, <<~END) do
-undefined method `+' for nil:NilClass
+undefined method `+' for #{ NIL_RECV_MESSAGE }
nil + 42
^
@@ -375,7 +411,7 @@ undefined method `+' for nil:NilClass
def test_OPCALL_binary_2
assert_error_message(NoMethodError, <<~END) do
-undefined method `+' for nil:NilClass
+undefined method `+' for #{ NIL_RECV_MESSAGE }
nil + # comment
^
@@ -388,7 +424,7 @@ undefined method `+' for nil:NilClass
def test_OPCALL_binary_3
assert_error_message(NoMethodError, <<~END) do
-undefined method `+' for nil:NilClass
+undefined method `+' for #{ NIL_RECV_MESSAGE }
(nil) + 42
^
@@ -400,7 +436,7 @@ undefined method `+' for nil:NilClass
def test_OPCALL_unary_1
assert_error_message(NoMethodError, <<~END) do
-undefined method `+@' for nil:NilClass
+undefined method `+@' for #{ NIL_RECV_MESSAGE }
+ nil
^
@@ -412,7 +448,7 @@ undefined method `+@' for nil:NilClass
def test_OPCALL_unary_2
assert_error_message(NoMethodError, <<~END) do
-undefined method `+@' for nil:NilClass
+undefined method `+@' for #{ NIL_RECV_MESSAGE }
+(nil)
^
@@ -424,7 +460,7 @@ undefined method `+@' for nil:NilClass
def test_FCALL_1
assert_error_message(NoMethodError, <<~END) do
-undefined method `foo' for nil:NilClass
+undefined method `foo' for #{ NIL_RECV_MESSAGE }
nil.instance_eval { foo() }
^^^
@@ -436,7 +472,7 @@ undefined method `foo' for nil:NilClass
def test_FCALL_2
assert_error_message(NoMethodError, <<~END) do
-undefined method `foo' for nil:NilClass
+undefined method `foo' for #{ NIL_RECV_MESSAGE }
nil.instance_eval { foo(42) }
^^^
@@ -448,7 +484,7 @@ undefined method `foo' for nil:NilClass
def test_VCALL_2
assert_error_message(NameError, <<~END) do
-undefined local variable or method `foo' for nil:NilClass
+undefined local variable or method `foo' for #{ NIL_RECV_MESSAGE }
nil.instance_eval { foo }
^^^
@@ -462,7 +498,7 @@ undefined local variable or method `foo' for nil:NilClass
v = nil
assert_error_message(NoMethodError, <<~END) do
-undefined method `[]' for nil:NilClass
+undefined method `[]' for #{ NIL_RECV_MESSAGE }
v [0] += 42
^^^
@@ -476,7 +512,7 @@ undefined method `[]' for nil:NilClass
v = nil
assert_error_message(NoMethodError, <<~END) do
-undefined method `[]' for nil:NilClass
+undefined method `[]' for #{ NIL_RECV_MESSAGE }
v [0] += # comment
^^^
@@ -491,7 +527,7 @@ undefined method `[]' for nil:NilClass
v = nil
assert_error_message(NoMethodError, <<~END) do
-undefined method `[]' for nil:NilClass
+undefined method `[]' for #{ NIL_RECV_MESSAGE }
END
v [
@@ -505,7 +541,7 @@ undefined method `[]' for nil:NilClass
v = nil
assert_error_message(NoMethodError, <<~END) do
-undefined method `[]' for nil:NilClass
+undefined method `[]' for #{ NIL_RECV_MESSAGE }
(v)[0] += 42
^^^
@@ -520,7 +556,7 @@ undefined method `[]' for nil:NilClass
def v.[](x); nil; end
assert_error_message(NoMethodError, <<~END) do
-undefined method `+' for nil:NilClass
+undefined method `+' for #{ NIL_RECV_MESSAGE }
v [0] += 42
^
@@ -535,7 +571,7 @@ undefined method `+' for nil:NilClass
def v.[](x); nil; end
assert_error_message(NoMethodError, <<~END) do
-undefined method `+' for nil:NilClass
+undefined method `+' for #{ NIL_RECV_MESSAGE }
v [0 ] += # comment
^
@@ -551,7 +587,7 @@ undefined method `+' for nil:NilClass
def v.[](x); nil; end
assert_error_message(NoMethodError, <<~END) do
-undefined method `+' for nil:NilClass
+undefined method `+' for #{ NIL_RECV_MESSAGE }
END
v [
@@ -566,7 +602,7 @@ undefined method `+' for nil:NilClass
def v.[](x); nil; end
assert_error_message(NoMethodError, <<~END) do
-undefined method `+' for nil:NilClass
+undefined method `+' for #{ NIL_RECV_MESSAGE }
(v)[0] += 42
^
@@ -641,7 +677,7 @@ undefined method `[]=' for #{ v.inspect }
v = nil
assert_error_message(NoMethodError, <<~END) do
-undefined method `foo' for nil:NilClass
+undefined method `foo' for #{ NIL_RECV_MESSAGE }
v.foo += 42
^^^^
@@ -655,7 +691,7 @@ undefined method `foo' for nil:NilClass
v = nil
assert_error_message(NoMethodError, <<~END) do
-undefined method `foo' for nil:NilClass
+undefined method `foo' for #{ NIL_RECV_MESSAGE }
v.foo += # comment
^^^^
@@ -670,7 +706,7 @@ undefined method `foo' for nil:NilClass
v = nil
assert_error_message(NoMethodError, <<~END) do
-undefined method `foo' for nil:NilClass
+undefined method `foo' for #{ NIL_RECV_MESSAGE }
(v).foo += 42
^^^^
@@ -685,7 +721,7 @@ undefined method `foo' for nil:NilClass
def v.foo; nil; end
assert_error_message(NoMethodError, <<~END) do
-undefined method `+' for nil:NilClass
+undefined method `+' for #{ NIL_RECV_MESSAGE }
v.foo += 42
^
@@ -700,7 +736,7 @@ undefined method `+' for nil:NilClass
def v.foo; nil; end
assert_error_message(NoMethodError, <<~END) do
-undefined method `+' for nil:NilClass
+undefined method `+' for #{ NIL_RECV_MESSAGE }
v.foo += # comment
^
@@ -716,7 +752,7 @@ undefined method `+' for nil:NilClass
def v.foo; nil; end
assert_error_message(NoMethodError, <<~END) do
-undefined method `+' for nil:NilClass
+undefined method `+' for #{ NIL_RECV_MESSAGE }
(v).foo += 42
^
@@ -809,6 +845,54 @@ uninitialized constant ErrorHighlightTest::NotDefined
end
end
+ def test_COLON2_3
+ assert_error_message(NameError, <<~END) do
+uninitialized constant ErrorHighlightTest::NotDefined
+
+ ErrorHighlightTest::NotDefined::Foo
+ ^^^^^^^^^^^^
+ END
+
+ ErrorHighlightTest::NotDefined::Foo
+ end
+ end
+
+ def test_COLON2_4
+ assert_error_message(NameError, <<~END) do
+uninitialized constant ErrorHighlightTest::NotDefined
+
+ ::ErrorHighlightTest::NotDefined::Foo
+ ^^^^^^^^^^^^
+ END
+
+ ::ErrorHighlightTest::NotDefined::Foo
+ end
+ end
+
+ if ErrorHighlight.const_get(:Spotter).const_get(:OPT_GETCONSTANT_PATH)
+ def test_COLON2_5
+ # Unfortunately, we cannot identify which `NotDefined` caused the NameError
+ assert_error_message(NameError, <<~END) do
+ uninitialized constant ErrorHighlightTest::NotDefined
+ END
+
+ ErrorHighlightTest::NotDefined::NotDefined
+ end
+ end
+ else
+ def test_COLON2_5
+ assert_error_message(NameError, <<~END) do
+uninitialized constant ErrorHighlightTest::NotDefined
+
+ ErrorHighlightTest::NotDefined::NotDefined
+ ^^^^^^^^^^^^
+ END
+
+ ErrorHighlightTest::NotDefined::NotDefined
+ end
+ end
+ end
+
def test_COLON3
assert_error_message(NameError, <<~END) do
uninitialized constant NotDefined
@@ -862,7 +946,7 @@ uninitialized constant ErrorHighlightTest::OP_CDECL_TEST::NotDefined
def test_OP_CDECL_op_1
assert_error_message(NoMethodError, <<~END) do
-undefined method `+' for nil:NilClass
+undefined method `+' for #{ NIL_RECV_MESSAGE }
OP_CDECL_TEST::Nil += 1
^
@@ -874,7 +958,7 @@ undefined method `+' for nil:NilClass
def test_OP_CDECL_op_2
assert_error_message(NoMethodError, <<~END) do
-undefined method `+' for nil:NilClass
+undefined method `+' for #{ NIL_RECV_MESSAGE }
OP_CDECL_TEST::Nil += # comment
^
@@ -887,7 +971,7 @@ undefined method `+' for nil:NilClass
def test_OP_CDECL_op_3
assert_error_message(NoMethodError, <<~END) do
-undefined method `+' for nil:NilClass
+undefined method `+' for #{ NIL_RECV_MESSAGE }
Nil += 1
^
@@ -911,8 +995,9 @@ uninitialized constant NotDefined
end
def test_OP_CDECL_toplevel_2
+ recv = NEW_MESSAGE_FORMAT ? "class ErrorHighlightTest" : "ErrorHighlightTest:Class"
assert_error_message(NoMethodError, <<~END) do
-undefined method `+' for ErrorHighlightTest:Class
+undefined method `+' for #{ recv }
::ErrorHighlightTest += 1
^
@@ -973,18 +1058,16 @@ local variable `foo' is not defined for #{ b.inspect }
def test_multibyte
assert_error_message(NoMethodError, <<~END) do
-undefined method `ã‚ã„ã†ãˆãŠ' for nil:NilClass
+undefined method `ã‚ã„ã†ãˆãŠ' for #{ NIL_RECV_MESSAGE }
END
nil.ã‚ã„ã†ãˆãŠ
end
end
- if false
-
def test_args_CALL_1
assert_error_message(TypeError, <<~END) do
-nil can't be coerced into Integer
+nil can't be coerced into Integer (TypeError)
1.+(nil)
^^^
@@ -997,7 +1080,7 @@ nil can't be coerced into Integer
def test_args_CALL_2
v = []
assert_error_message(TypeError, <<~END) do
-no implicit conversion from nil to integer
+no implicit conversion from nil to integer (TypeError)
v[nil]
^^^
@@ -1010,7 +1093,7 @@ no implicit conversion from nil to integer
def test_args_ATTRASGN_1
v = []
assert_error_message(ArgumentError, <<~END) do
-wrong number of arguments (given 1, expected 2..3)
+wrong number of arguments (given 1, expected 2..3) (ArgumentError)
v [ ] = 1
^^^^^^
@@ -1023,7 +1106,7 @@ wrong number of arguments (given 1, expected 2..3)
def test_args_ATTRASGN_2
v = []
assert_error_message(TypeError, <<~END) do
-no implicit conversion from nil to integer
+no implicit conversion from nil to integer (TypeError)
v [nil] = 1
^^^^^^^^
@@ -1035,7 +1118,7 @@ no implicit conversion from nil to integer
def test_args_ATTRASGN_3
assert_error_message(TypeError, <<~END) do
-no implicit conversion of String into Integer
+no implicit conversion of String into Integer (TypeError)
$stdin.lineno = "str"
^^^^^
@@ -1047,7 +1130,7 @@ no implicit conversion of String into Integer
def test_args_OPCALL
assert_error_message(TypeError, <<~END) do
-nil can't be coerced into Integer
+nil can't be coerced into Integer (TypeError)
1 + nil
^^^
@@ -1059,7 +1142,7 @@ nil can't be coerced into Integer
def test_args_FCALL_1
assert_error_message(TypeError, <<~END) do
-no implicit conversion of Symbol into String
+no implicit conversion of Symbol into String (TypeError)
"str".instance_eval { gsub("foo", :sym) }
^^^^^^^^^^^
@@ -1071,7 +1154,7 @@ no implicit conversion of Symbol into String
def test_args_FCALL_2
assert_error_message(TypeError, <<~END) do
-no implicit conversion of Symbol into String
+no implicit conversion of Symbol into String (TypeError)
"str".instance_eval { gsub "foo", :sym }
^^^^^^^^^^^
@@ -1085,7 +1168,7 @@ no implicit conversion of Symbol into String
v = []
assert_error_message(TypeError, <<~END) do
-no implicit conversion from nil to integer
+no implicit conversion from nil to integer (TypeError)
v [nil] += 42
^^^^^^^^^^
@@ -1099,7 +1182,7 @@ no implicit conversion from nil to integer
v = []
assert_error_message(ArgumentError, <<~END) do
-wrong number of arguments (given 0, expected 1..2)
+wrong number of arguments (given 0, expected 1..2) (ArgumentError)
v [ ] += 42
^^^^^^^^
@@ -1113,7 +1196,7 @@ wrong number of arguments (given 0, expected 1..2)
v = [1]
assert_error_message(TypeError, <<~END) do
-nil can't be coerced into Integer
+nil can't be coerced into Integer (TypeError)
v [0] += nil
^^^^^^^^^
@@ -1128,7 +1211,7 @@ nil can't be coerced into Integer
def v.foo; 1; end
assert_error_message(TypeError, <<~END) do
-nil can't be coerced into Integer
+nil can't be coerced into Integer (TypeError)
v.foo += nil
^^^
@@ -1138,18 +1221,16 @@ nil can't be coerced into Integer
end
end
- end
-
def test_custom_formatter
custom_formatter = Object.new
def custom_formatter.message_for(spot)
- "\n\n" + spot.inspect
+ "\n\n" + spot.except(:script_lines).inspect
end
original_formatter, ErrorHighlight.formatter = ErrorHighlight.formatter, custom_formatter
assert_error_message(NoMethodError, <<~END) do
-undefined method `time' for 1:Integer
+undefined method `time' for #{ ONE_RECV_MESSAGE }
{:first_lineno=>#{ __LINE__ + 3 }, :first_column=>7, :last_lineno=>#{ __LINE__ + 3 }, :last_column=>12, :snippet=>" 1.time {}\\n"}
END
@@ -1167,7 +1248,7 @@ undefined method `time' for 1:Integer
tmp.close
assert_error_message(NoMethodError, <<~END.gsub("_", "\t")) do
-undefined method `time' for 1:Integer
+undefined method `time' for #{ ONE_RECV_MESSAGE }
_ _1.time {}
_ _ ^^^^^
@@ -1184,7 +1265,7 @@ _ _ ^^^^^
tmp.close
assert_error_message(NoMethodError, <<~END) do
-undefined method `time' for 1:Integer
+undefined method `time' for #{ ONE_RECV_MESSAGE }
1.time {}
^^^^^
@@ -1194,4 +1275,98 @@ undefined method `time' for 1:Integer
end
end
end
+
+ def test_simulate_funcallv_from_embedded_ruby
+ assert_error_message(NoMethodError, <<~END) do
+undefined method `foo' for #{ NIL_RECV_MESSAGE }
+ END
+
+ nil.foo + 1
+ rescue NoMethodError => exc
+ def exc.backtrace_locations = []
+ raise
+ end
+ end
+
+ def test_spoofed_filename
+ Tempfile.create(["error_highlight_test", ".rb"], binmode: true) do |tmp|
+ tmp << "module Dummy\nend\n"
+ tmp.close
+
+ recv = NEW_MESSAGE_FORMAT ? "an instance of String" : '"dummy":String'
+ assert_error_message(NameError, <<~END) do
+ undefined local variable or method `foo' for #{ recv }
+ END
+
+ "dummy".instance_eval do
+ eval <<-END, nil, tmp.path
+ foo
+ END
+ end
+ end
+ end
+ end
+
+ def raise_name_error
+ 1.time
+ end
+
+ def test_spot_with_backtrace_location
+ lineno = __LINE__
+ begin
+ raise_name_error
+ rescue NameError => exc
+ end
+
+ spot = ErrorHighlight.spot(exc).except(:script_lines)
+ assert_equal(lineno - 4, spot[:first_lineno])
+ assert_equal(lineno - 4, spot[:last_lineno])
+ assert_equal(5, spot[:first_column])
+ assert_equal(10, spot[:last_column])
+ assert_equal(" 1.time\n", spot[:snippet])
+
+ spot = ErrorHighlight.spot(exc, backtrace_location: exc.backtrace_locations[1]).except(:script_lines)
+ assert_equal(lineno + 2, spot[:first_lineno])
+ assert_equal(lineno + 2, spot[:last_lineno])
+ assert_equal(6, spot[:first_column])
+ assert_equal(22, spot[:last_column])
+ assert_equal(" raise_name_error\n", spot[:snippet])
+ end
+
+ def test_spot_with_node
+ omit unless RubyVM::AbstractSyntaxTree.respond_to?(:node_id_for_backtrace_location)
+
+ # We can't revisit instruction sequences to find node ids if the prism
+ # compiler was used instead of the parse.y compiler. In that case, we'll
+ # omit some tests.
+ omit if RubyVM::InstructionSequence.compile("").to_a[4][:parser] == :prism
+
+ begin
+ raise_name_error
+ rescue NameError => exc
+ end
+
+ bl = exc.backtrace_locations.first
+ expected_spot = ErrorHighlight.spot(exc, backtrace_location: bl)
+ ast = RubyVM::AbstractSyntaxTree.parse_file(__FILE__, keep_script_lines: true)
+ node_id = RubyVM::AbstractSyntaxTree.node_id_for_backtrace_location(bl)
+ node = find_node_by_id(ast, node_id)
+ actual_spot = ErrorHighlight.spot(node)
+
+ assert_equal expected_spot, actual_spot
+ end
+
+ private
+
+ def find_node_by_id(node, node_id)
+ return node if node.node_id == node_id
+
+ node.children.each do |child|
+ next unless child.is_a?(RubyVM::AbstractSyntaxTree::Node)
+ found = find_node_by_id(child, node_id)
+ return found if found
+ end
+
+ return false
+ end
end
diff --git a/test/excludes/TestThread.rb b/test/excludes/TestThread.rb
deleted file mode 100644
index ea73a4c010..0000000000
--- a/test/excludes/TestThread.rb
+++ /dev/null
@@ -1,2 +0,0 @@
-# frozen_string_literal: false
-exclude(/_stack_size$/, 'often too expensive')
diff --git a/test/fiber/autoload.rb b/test/fiber/autoload.rb
new file mode 100644
index 0000000000..dcb27164a7
--- /dev/null
+++ b/test/fiber/autoload.rb
@@ -0,0 +1,3 @@
+sleep 0.01
+module TestFiberSchedulerAutoload
+end
diff --git a/test/fiber/scheduler.rb b/test/fiber/scheduler.rb
index 8c2fdcb0e0..3926226ca3 100644
--- a/test/fiber/scheduler.rb
+++ b/test/fiber/scheduler.rb
@@ -1,8 +1,13 @@
# frozen_string_literal: true
# This is an example and simplified scheduler for test purposes.
-# It is not efficient for a large number of file descriptors as it uses IO.select().
-# Production Fiber schedulers should use epoll/kqueue/etc.
+# - It is not efficient for a large number of file descriptors as it uses
+# IO.select().
+# - It does not correctly handle multiple calls to `wait` with the same file
+# descriptor and overlapping events.
+# - Production fiber schedulers should use epoll/kqueue/etc. Consider using the
+# [`io-event`](https://github.com/socketry/io-event) gem instead of this
+# scheduler if you want something simple to build on.
require 'fiber'
require 'socket'
@@ -14,7 +19,17 @@ rescue LoadError
end
class Scheduler
- def initialize
+ experimental = Warning[:experimental]
+ begin
+ Warning[:experimental] = false
+ IO::Buffer.new(0)
+ ensure
+ Warning[:experimental] = experimental
+ end
+
+ def initialize(fiber = Fiber.current)
+ @fiber = fiber
+
@readable = {}
@writable = {}
@waiting = {}
@@ -22,7 +37,7 @@ class Scheduler
@closed = false
@lock = Thread::Mutex.new
- @blocking = 0
+ @blocking = Hash.new.compare_by_identity
@ready = []
@urgent = IO.pipe
@@ -32,6 +47,10 @@ class Scheduler
attr :writable
attr :waiting
+ def transfer
+ @fiber.transfer
+ end
+
def next_timeout
_fiber, timeout = @waiting.min_by{|key, value| value}
@@ -49,8 +68,8 @@ class Scheduler
def run
# $stderr.puts [__method__, Fiber.current].inspect
- while @readable.any? or @writable.any? or @waiting.any? or @blocking.positive?
- # Can only handle file descriptors up to 1024...
+ while @readable.any? or @writable.any? or @waiting.any? or @blocking.any?
+ # May only handle file descriptors up to 1024...
readable, writable = IO.select(@readable.keys + [@urgent.first], @writable.keys, [], next_timeout)
# puts "readable: #{readable}" if readable&.any?
@@ -75,7 +94,7 @@ class Scheduler
end
selected.each do |fiber, events|
- fiber.resume(events)
+ fiber.transfer(events)
end
if @waiting.any?
@@ -85,7 +104,7 @@ class Scheduler
waiting.each do |fiber, timeout|
if fiber.alive?
if timeout <= time
- fiber.resume
+ fiber.transfer
else
@waiting[fiber] = timeout
end
@@ -101,16 +120,22 @@ class Scheduler
end
ready.each do |fiber|
- fiber.resume
+ fiber.transfer
end
end
end
end
+ # A fiber scheduler hook, invoked when the scheduler goes out of scope.
def scheduler_close
close(true)
end
+ # If the `scheduler_close` hook does not exist, this method `close` will be
+ # invoked instead when the fiber scheduler goes out of scope. This is legacy
+ # behaviour, you should almost certainly use `scheduler_close`. The reason for
+ # this, is `scheduler_close` is called when the scheduler goes out of scope,
+ # while `close` may be called by the user.
def close(internal = false)
# $stderr.puts [__method__, Fiber.current].inspect
@@ -145,6 +170,7 @@ class Scheduler
Process.clock_gettime(Process::CLOCK_MONOTONIC)
end
+ # This hook is invoked by `Timeout.timeout` and related code.
def timeout_after(duration, klass, message, &block)
fiber = Fiber.current
@@ -163,6 +189,7 @@ class Scheduler
end
end
+ # This hook is invoked by `Process.wait`, `system`, and backticks.
def process_wait(pid, flags)
# $stderr.puts [__method__, pid, flags, Fiber.current].inspect
@@ -172,21 +199,47 @@ class Scheduler
end.value
end
+ # This hook is invoked by `IO#read` and `IO#write` in the case that `io_read`
+ # and `io_write` hooks are not available. This implementation is not
+ # completely general, in the sense that calling `io_wait` multiple times with
+ # the same `io` and `events` will not work, which is okay for tests but not
+ # for real code. Correct fiber schedulers should not have this limitation.
def io_wait(io, events, duration)
# $stderr.puts [__method__, io, events, duration, Fiber.current].inspect
+ fiber = Fiber.current
+
unless (events & IO::READABLE).zero?
- @readable[io] = Fiber.current
+ @readable[io] = fiber
+ readable = true
end
unless (events & IO::WRITABLE).zero?
- @writable[io] = Fiber.current
+ @writable[io] = fiber
+ writable = true
+ end
+
+ if duration
+ @waiting[fiber] = current_time + duration
end
- Fiber.yield
+ @fiber.transfer
+ ensure
+ @waiting.delete(fiber) if duration
+ @readable.delete(io) if readable
+ @writable.delete(io) if writable
+ end
+
+ # This hook is invoked by `IO.select`. Using a thread ensures that the
+ # operation does not block the fiber scheduler.
+ def io_select(...)
+ # Emulate the operation using a non-blocking thread:
+ Thread.new do
+ IO.select(...)
+ end.value
end
- # Used for Kernel#sleep and Thread::Mutex#sleep
+ # This hook is invoked by `Kernel#sleep` and `Thread::Mutex#sleep`.
def kernel_sleep(duration = nil)
# $stderr.puts [__method__, duration, Fiber.current].inspect
@@ -195,32 +248,35 @@ class Scheduler
return true
end
- # Used when blocking on synchronization (Thread::Mutex#lock,
- # Thread::Queue#pop, Thread::SizedQueue#push, ...)
+ # This hook is invoked by blocking options such as `Thread::Mutex#lock`,
+ # `Thread::Queue#pop` and `Thread::SizedQueue#push`, which are unblocked by
+ # other threads/fibers. To unblock a blocked fiber, you should call `unblock`
+ # with the same `blocker` and `fiber` arguments.
def block(blocker, timeout = nil)
# $stderr.puts [__method__, blocker, timeout].inspect
+ fiber = Fiber.current
+
if timeout
- @waiting[Fiber.current] = current_time + timeout
+ @waiting[fiber] = current_time + timeout
begin
- Fiber.yield
+ @fiber.transfer
ensure
# Remove from @waiting in the case #unblock was called before the timeout expired:
- @waiting.delete(Fiber.current)
+ @waiting.delete(fiber)
end
else
- @blocking += 1
+ @blocking[fiber] = true
begin
- Fiber.yield
+ @fiber.transfer
ensure
- @blocking -= 1
+ @blocking.delete(fiber)
end
end
end
- # Used when synchronization wakes up a previously-blocked fiber
- # (Thread::Mutex#unlock, Thread::Queue#push, ...).
- # This might be called from another thread.
+ # This method is invoked from a thread or fiber to unblock a fiber that is
+ # blocked by `block`. It is expected to be thread safe.
def unblock(blocker, fiber)
# $stderr.puts [__method__, blocker, fiber].inspect
# $stderr.puts blocker.backtrace.inspect
@@ -234,14 +290,20 @@ class Scheduler
io.write_nonblock('.')
end
+ # This hook is invoked by `Fiber.schedule`. Strictly speaking, you should use
+ # it to create scheduled fibers, but it is not required in practice;
+ # `Fiber.new` is usually sufficient.
def fiber(&block)
fiber = Fiber.new(blocking: false, &block)
- fiber.resume
+ fiber.transfer
return fiber
end
+ # This hook is invoked by `Addrinfo.getaddrinfo`. Using a thread ensures that
+ # the operation does not block the fiber scheduler, since `getaddrinfo` is
+ # usually provided by `libc` and is blocking.
def address_resolve(hostname)
Thread.new do
Addrinfo.getaddrinfo(hostname, nil).map(&:ip_address).uniq
@@ -249,6 +311,133 @@ class Scheduler
end
end
+# This scheduler class implements `io_read` and `io_write` hooks which require
+# `IO::Buffer`.
+class IOBufferScheduler < Scheduler
+ EAGAIN = -Errno::EAGAIN::Errno
+
+ def io_read(io, buffer, length, offset)
+ total = 0
+ io.nonblock = true
+
+ while true
+ maximum_size = buffer.size - offset
+ result = blocking{buffer.read(io, maximum_size, offset)}
+
+ if result > 0
+ total += result
+ offset += result
+ break if total >= length
+ elsif result == 0
+ break
+ elsif result == EAGAIN
+ if length > 0
+ self.io_wait(io, IO::READABLE, nil)
+ else
+ return result
+ end
+ elsif result < 0
+ return result
+ end
+ end
+
+ return total
+ end
+
+ def io_write(io, buffer, length, offset)
+ total = 0
+ io.nonblock = true
+
+ while true
+ maximum_size = buffer.size - offset
+ result = blocking{buffer.write(io, maximum_size, offset)}
+
+ if result > 0
+ total += result
+ offset += result
+ break if total >= length
+ elsif result == 0
+ break
+ elsif result == EAGAIN
+ if length > 0
+ self.io_wait(io, IO::WRITABLE, nil)
+ else
+ return result
+ end
+ elsif result < 0
+ return result
+ end
+ end
+
+ return total
+ end
+
+ def io_pread(io, buffer, from, length, offset)
+ total = 0
+ io.nonblock = true
+
+ while true
+ maximum_size = buffer.size - offset
+ result = blocking{buffer.pread(io, from, maximum_size, offset)}
+
+ if result > 0
+ total += result
+ offset += result
+ from += result
+ break if total >= length
+ elsif result == 0
+ break
+ elsif result == EAGAIN
+ if length > 0
+ self.io_wait(io, IO::READABLE, nil)
+ else
+ return result
+ end
+ elsif result < 0
+ return result
+ end
+ end
+
+ return total
+ end
+
+ def io_pwrite(io, buffer, from, length, offset)
+ total = 0
+ io.nonblock = true
+
+ while true
+ maximum_size = buffer.size - offset
+ result = blocking{buffer.pwrite(io, from, maximum_size, offset)}
+
+ if result > 0
+ total += result
+ offset += result
+ from += result
+ break if total >= length
+ elsif result == 0
+ break
+ elsif result == EAGAIN
+ if length > 0
+ self.io_wait(io, IO::WRITABLE, nil)
+ else
+ return result
+ end
+ elsif result < 0
+ return result
+ end
+ end
+
+ return total
+ end
+
+ def blocking(&block)
+ Fiber.blocking(&block)
+ end
+end
+
+# This scheduler has a broken implementation of `unblock`` in the sense that it
+# raises an exception. This is used to test the behavior of the scheduler when
+# unblock raises an exception.
class BrokenUnblockScheduler < Scheduler
def unblock(blocker, fiber)
super
@@ -257,6 +446,9 @@ class BrokenUnblockScheduler < Scheduler
end
end
+# This scheduler has a broken implementation of `unblock` in the sense that it
+# sleeps. This is used to test the behavior of the scheduler when unblock
+# messes with the internal thread state in an unexpected way.
class SleepingUnblockScheduler < Scheduler
# This method is invoked when the thread is exiting.
def unblock(blocker, fiber)
@@ -266,3 +458,16 @@ class SleepingUnblockScheduler < Scheduler
sleep(0.1)
end
end
+
+# This scheduler has a broken implementation of `kernel_sleep` in the sense that
+# it invokes a blocking sleep which can cause a deadlock in some cases.
+class SleepingBlockingScheduler < Scheduler
+ def kernel_sleep(duration = nil)
+ # Deliberaly sleep in a blocking state which can trigger a deadlock if the implementation is not correct.
+ Fiber.blocking{sleep 0.0001}
+
+ self.block(:sleep, duration)
+
+ return true
+ end
+end
diff --git a/test/fiber/test_address_resolve.rb b/test/fiber/test_address_resolve.rb
index 457221b9b1..09c8db6049 100644
--- a/test/fiber/test_address_resolve.rb
+++ b/test/fiber/test_address_resolve.rb
@@ -179,7 +179,7 @@ class TestAddressResolve < Test::Unit::TestCase
Fiber.set_scheduler scheduler
Fiber.schedule do
- assert_raise(SocketError) {
+ assert_raise(Socket::ResolutionError) {
Addrinfo.getaddrinfo("non-existing-domain.abc", nil)
}
end
@@ -269,7 +269,7 @@ class TestAddressResolve < Test::Unit::TestCase
Fiber.set_scheduler scheduler
Fiber.schedule do
- result = Socket.getnameinfo(["AF_INET", 80, "example.com"], Socket::NI_NUMERICSERV)
+ result = Socket.getnameinfo(["AF_INET", 80, "example.com"], Socket::NI_NUMERICSERV | Socket::NI_NUMERICHOST)
assert_equal(["1.2.3.4", "80"], result)
end
diff --git a/test/fiber/test_enumerator.rb b/test/fiber/test_enumerator.rb
index cd4ccd1de5..e9410f925c 100644
--- a/test/fiber/test_enumerator.rb
+++ b/test/fiber/test_enumerator.rb
@@ -6,16 +6,10 @@ class TestFiberEnumerator < Test::Unit::TestCase
MESSAGE = "Hello World"
def test_read_characters
- skip "UNIXSocket is not defined!" unless defined?(UNIXSocket)
+ omit "UNIXSocket is not defined!" unless defined?(UNIXSocket)
i, o = UNIXSocket.pair
- unless i.nonblock? && o.nonblock?
- i.close
- o.close
- skip "I/O is not non-blocking!"
- end
-
message = String.new
thread = Thread.new do
@@ -48,4 +42,12 @@ class TestFiberEnumerator < Test::Unit::TestCase
assert_predicate(i, :closed?)
assert_predicate(o, :closed?)
end
+
+ def enumerator_fiber_is_nonblocking
+ enumerator = Enumerator.new do |yielder|
+ yielder << Fiber.current.blocking?
+ end
+
+ assert_equal(false, enumerator.next)
+ end
end
diff --git a/test/fiber/test_io.rb b/test/fiber/test_io.rb
index ce65a55f78..4891c607f7 100644
--- a/test/fiber/test_io.rb
+++ b/test/fiber/test_io.rb
@@ -6,14 +6,12 @@ class TestFiberIO < Test::Unit::TestCase
MESSAGE = "Hello World"
def test_read
- skip "UNIXSocket is not defined!" unless defined?(UNIXSocket)
+ omit unless defined?(UNIXSocket)
i, o = UNIXSocket.pair
-
- unless i.nonblock? && o.nonblock?
- i.close
- o.close
- skip "I/O is not non-blocking!"
+ if RUBY_PLATFORM=~/mswin|mingw/
+ i.nonblock = true
+ o.nonblock = true
end
message = nil
@@ -41,11 +39,15 @@ class TestFiberIO < Test::Unit::TestCase
end
def test_heavy_read
- skip unless defined?(UNIXSocket)
+ omit unless defined?(UNIXSocket)
16.times.map do
Thread.new do
i, o = UNIXSocket.pair
+ if RUBY_PLATFORM=~/mswin|mingw/
+ i.nonblock = true
+ o.nonblock = true
+ end
scheduler = Scheduler.new
Fiber.set_scheduler scheduler
@@ -64,16 +66,11 @@ class TestFiberIO < Test::Unit::TestCase
end
def test_epipe_on_read
- skip "UNIXSocket is not defined!" unless defined?(UNIXSocket)
+ omit unless defined?(UNIXSocket)
+ omit "nonblock=true isn't properly supported on Windows" if RUBY_PLATFORM=~/mswin|mingw/
i, o = UNIXSocket.pair
- unless i.nonblock? && o.nonblock?
- i.close
- o.close
- skip "I/O is not non-blocking!"
- end
-
error = nil
thread = Thread.new do
@@ -140,4 +137,142 @@ class TestFiberIO < Test::Unit::TestCase
server.close
th.join
end
+
+ def test_read_write_blocking
+ omit "UNIXSocket is not defined!" unless defined?(UNIXSocket)
+
+ i, o = UNIXSocket.pair
+ i.nonblock = false
+ o.nonblock = false
+
+ message = nil
+
+ thread = Thread.new do
+ # This scheduler provides non-blocking `io_read`/`io_write`:
+ scheduler = IOBufferScheduler.new
+ Fiber.set_scheduler scheduler
+
+ Fiber.schedule do
+ message = i.read(20)
+ i.close
+ end
+
+ Fiber.schedule do
+ o.write("Hello World")
+ o.close
+ end
+ end
+
+ thread.join
+
+ assert_equal MESSAGE, message
+ assert_predicate(i, :closed?)
+ assert_predicate(o, :closed?)
+ end
+
+ def test_puts_empty
+ omit "UNIXSocket is not defined!" unless defined?(UNIXSocket)
+
+ i, o = UNIXSocket.pair
+ i.nonblock = false
+ o.nonblock = false
+
+ thread = Thread.new do
+ # This scheduler provides non-blocking `io_read`/`io_write`:
+ scheduler = IOBufferScheduler.new
+ Fiber.set_scheduler scheduler
+
+ Fiber.schedule do
+ # This was causing a segfault on older Ruby.
+ o.puts ""
+ o.puts nil
+ o.close
+ end
+ end
+
+ thread.join
+
+ message = i.read
+ i.close
+
+ assert_equal $/*2, message
+ end
+
+ def test_io_select
+ omit "UNIXSocket is not defined!" unless defined?(UNIXSocket)
+
+ UNIXSocket.pair do |r, w|
+ result = nil
+
+ thread = Thread.new do
+ scheduler = Scheduler.new
+ Fiber.set_scheduler scheduler
+
+ Fiber.schedule do
+ w.write("Hello World")
+ result = IO.select([r], [w])
+ end
+ end
+
+ thread.join
+
+ assert_equal [[r], [w], []], result
+ end
+ end
+
+ def test_backquote
+ result = nil
+
+ thread = Thread.new do
+ scheduler = Scheduler.new
+ Fiber.set_scheduler scheduler
+ Fiber.schedule do
+ result = `#{EnvUtil.rubybin} -e "sleep 0.1;puts %[ok]"`
+ end
+ end
+ thread.join
+
+ assert_equal "ok\n", result
+ end
+
+ # Tests for https://bugs.ruby-lang.org/issues/20723 which would
+ # otherwise deadlock this test.
+ def test_close_while_reading_on_thread
+ # Windows has UNIXSocket, but only with VS 2019+
+ omit "UNIXSocket is not defined!" unless defined?(UNIXSocket)
+
+ i, o = Socket.pair(:UNIX, :STREAM)
+ if RUBY_PLATFORM=~/mswin|mingw/
+ i.nonblock = true
+ o.nonblock = true
+ end
+
+ reading_thread = Thread.new do
+ Thread.current.report_on_exception = false
+ i.wait_readable
+ end
+
+ fs_thread = Thread.new do
+ # Wait until the reading thread is blocked on read:
+ Thread.pass until reading_thread.status == "sleep"
+
+ scheduler = Scheduler.new
+ Fiber.set_scheduler scheduler
+ Fiber.schedule do
+ i.close
+ end
+ end
+
+ assert_raise(IOError) { reading_thread.join }
+ refute_nil fs_thread.join(5), "expected thread to terminate within 5 seconds"
+
+ assert_predicate(i, :closed?)
+ ensure
+ fs_thread&.kill
+ fs_thread&.join rescue nil
+ reading_thread&.kill
+ reading_thread&.join rescue nil
+ i&.close
+ o&.close
+ end
end
diff --git a/test/fiber/test_io_buffer.rb b/test/fiber/test_io_buffer.rb
new file mode 100644
index 0000000000..a08b1ce1a9
--- /dev/null
+++ b/test/fiber/test_io_buffer.rb
@@ -0,0 +1,199 @@
+# frozen_string_literal: true
+require 'test/unit'
+require_relative 'scheduler'
+
+require 'timeout'
+
+class TestFiberIOBuffer < Test::Unit::TestCase
+ MESSAGE = "Hello World"
+
+ def test_read_write_blocking
+ omit "UNIXSocket is not defined!" unless defined?(UNIXSocket)
+
+ i, o = UNIXSocket.pair
+ i.nonblock = false
+ o.nonblock = false
+
+ message = nil
+
+ thread = Thread.new do
+ scheduler = IOBufferScheduler.new
+ Fiber.set_scheduler scheduler
+
+ Fiber.schedule do
+ message = i.read(20)
+ i.close
+ end
+
+ Fiber.schedule do
+ o.write(MESSAGE)
+ o.close
+ end
+ end
+
+ thread.join
+
+ assert_equal MESSAGE, message
+ assert_predicate(i, :closed?)
+ assert_predicate(o, :closed?)
+ ensure
+ i&.close
+ o&.close
+ end
+
+ def test_timeout_after
+ omit "UNIXSocket is not defined!" unless defined?(UNIXSocket)
+
+ i, o = UNIXSocket.pair
+ i.nonblock = false
+ o.nonblock = false
+
+ message = nil
+ error = nil
+
+ thread = Thread.new do
+ scheduler = IOBufferScheduler.new
+ Fiber.set_scheduler scheduler
+
+ Fiber.schedule do
+ Timeout.timeout(0.1) do
+ message = i.read(20)
+ end
+ rescue Timeout::Error => error
+ # Assertions below.
+ ensure
+ i.close
+ end
+ end
+
+ thread.join
+
+ assert_nil message
+ assert_kind_of Timeout::Error, error
+ ensure
+ i&.close
+ o&.close
+ end
+
+ def test_read_nonblock
+ omit "UNIXSocket is not defined!" unless defined?(UNIXSocket)
+
+ i, o = UNIXSocket.pair
+
+ message = nil
+
+ thread = Thread.new do
+ scheduler = IOBufferScheduler.new
+ Fiber.set_scheduler scheduler
+
+ Fiber.schedule do
+ message = i.read_nonblock(20, exception: false)
+ i.close
+ end
+ end
+
+ thread.join
+
+ assert_equal :wait_readable, message
+ ensure
+ i&.close
+ o&.close
+ end
+
+ def test_write_nonblock
+ omit "UNIXSocket is not defined!" unless defined?(UNIXSocket)
+
+ i, o = UNIXSocket.pair
+
+ thread = Thread.new do
+ scheduler = IOBufferScheduler.new
+ Fiber.set_scheduler scheduler
+
+ Fiber.schedule do
+ o.write_nonblock(MESSAGE, exception: false)
+ o.close
+ end
+ end
+
+ thread.join
+
+ assert_equal MESSAGE, i.read
+ ensure
+ i&.close
+ o&.close
+ end
+
+ def test_io_buffer_read_write
+ omit "UNIXSocket is not defined!" unless defined?(UNIXSocket)
+
+ i, o = UNIXSocket.pair
+ source_buffer = IO::Buffer.for("Hello World!")
+ destination_buffer = IO::Buffer.new(source_buffer.size)
+
+ # Test non-scheduler code path:
+ source_buffer.write(o, source_buffer.size)
+ destination_buffer.read(i, source_buffer.size)
+ assert_equal source_buffer, destination_buffer
+
+ # Test scheduler code path:
+ destination_buffer.clear
+
+ thread = Thread.new do
+ scheduler = IOBufferScheduler.new
+ Fiber.set_scheduler scheduler
+
+ Fiber.schedule do
+ source_buffer.write(o, source_buffer.size)
+ destination_buffer.read(i, source_buffer.size)
+ end
+ end
+
+ thread.join
+
+ assert_equal source_buffer, destination_buffer
+ ensure
+ i&.close
+ o&.close
+ end
+
+ def nonblockable?(io)
+ io.nonblock{}
+ true
+ rescue
+ false
+ end
+
+ def test_io_buffer_pread_pwrite
+ file = Tempfile.new("test_io_buffer_pread_pwrite")
+
+ omit "Non-blocking file IO is not supported" unless nonblockable?(file)
+
+ source_buffer = IO::Buffer.for("Hello World!")
+ destination_buffer = IO::Buffer.new(source_buffer.size)
+
+ # Test non-scheduler code path:
+ source_buffer.pwrite(file, 1, source_buffer.size)
+ destination_buffer.pread(file, 1, source_buffer.size)
+ assert_equal source_buffer, destination_buffer
+
+ # Test scheduler code path:
+ destination_buffer.clear
+ file.truncate(0)
+
+ thread = Thread.new do
+ scheduler = IOBufferScheduler.new
+ Fiber.set_scheduler scheduler
+
+ Fiber.schedule do
+ source_buffer.pwrite(file, 1, source_buffer.size)
+ destination_buffer.pread(file, 1, source_buffer.size)
+ end
+ end
+
+ thread.join
+
+ assert_equal source_buffer, destination_buffer
+ ensure
+ file&.close!
+ end
+end
diff --git a/test/fiber/test_mutex.rb b/test/fiber/test_mutex.rb
index b0655f06a5..2cee2cc235 100644
--- a/test/fiber/test_mutex.rb
+++ b/test/fiber/test_mutex.rb
@@ -194,7 +194,7 @@ class TestFiberMutex < Test::Unit::TestCase
end
def test_mutex_deadlock
- error_pattern = /No live threads left. Deadlock\?/
+ error_pattern = /lock already owned by another fiber/
assert_in_out_err %W[-I#{__dir__} -], <<-RUBY, ['in synchronize'], error_pattern, success: false
require 'scheduler'
@@ -207,7 +207,7 @@ class TestFiberMutex < Test::Unit::TestCase
Fiber.schedule do
mutex.synchronize do
puts 'in synchronize'
- Fiber.yield
+ scheduler.transfer
end
end
@@ -217,4 +217,24 @@ class TestFiberMutex < Test::Unit::TestCase
thread.join
RUBY
end
+
+ def test_mutex_fiber_deadlock_no_scheduler
+ thr = Thread.new do
+ loop do
+ sleep 1
+ end
+ end
+
+ mutex = Mutex.new
+ mutex.synchronize do
+ error = assert_raise ThreadError do
+ Fiber.new do
+ mutex.lock
+ end.resume
+ end
+ assert_includes error.message, "deadlock; lock already owned by another fiber belonging to the same thread"
+ end
+ ensure
+ thr&.kill&.join
+ end
end
diff --git a/test/fiber/test_process.rb b/test/fiber/test_process.rb
index c6583cac9b..a09b070c0a 100644
--- a/test/fiber/test_process.rb
+++ b/test/fiber/test_process.rb
@@ -3,13 +3,15 @@ require 'test/unit'
require_relative 'scheduler'
class TestFiberProcess < Test::Unit::TestCase
+ TRUE_CMD = RUBY_PLATFORM =~ /mswin|mingw/ ? "exit 0" : "true"
+
def test_process_wait
Thread.new do
scheduler = Scheduler.new
Fiber.set_scheduler scheduler
Fiber.schedule do
- pid = Process.spawn("true")
+ pid = Process.spawn(TRUE_CMD)
Process.wait(pid)
# TODO test that scheduler was invoked.
@@ -25,7 +27,7 @@ class TestFiberProcess < Test::Unit::TestCase
Fiber.set_scheduler scheduler
Fiber.schedule do
- system("true")
+ system(TRUE_CMD)
# TODO test that scheduler was invoked (currently it's not).
@@ -33,4 +35,40 @@ class TestFiberProcess < Test::Unit::TestCase
end
end.join
end
+
+ def test_system_faulty_process_wait
+ Thread.new do
+ scheduler = Scheduler.new
+
+ def scheduler.process_wait(pid, flags)
+ Fiber.blocking{Process.wait(pid, flags)}
+
+ # Don't return `Process::Status` instance.
+ return false
+ end
+
+ Fiber.set_scheduler scheduler
+
+ Fiber.schedule do
+ assert_raise TypeError do
+ system(TRUE_CMD)
+ end
+ end
+ end.join
+ end
+
+ def test_fork
+ omit 'fork not supported' unless Process.respond_to?(:fork)
+ Thread.new do
+ scheduler = Scheduler.new
+ Fiber.set_scheduler scheduler
+
+ Fiber.schedule do
+ pid = Process.fork {}
+ Process.wait(pid)
+
+ assert_predicate $?, :success?
+ end
+ end.join
+ end
end
diff --git a/test/fiber/test_queue.rb b/test/fiber/test_queue.rb
new file mode 100644
index 0000000000..d78b026f11
--- /dev/null
+++ b/test/fiber/test_queue.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+require 'test/unit'
+require_relative 'scheduler'
+
+class TestFiberQueue < Test::Unit::TestCase
+ def test_pop_with_timeout
+ queue = Thread::Queue.new
+ kill = false
+ result = :unspecified
+
+ thread = Thread.new do
+ scheduler = Scheduler.new
+ Fiber.set_scheduler(scheduler)
+
+ Fiber.schedule do
+ result = queue.pop(timeout: 0.0001)
+ end
+
+ scheduler.run
+ end
+ until thread.join(2)
+ kill = true
+ thread.kill
+ end
+
+ assert_false(kill, 'Getting stuck due to a possible compiler bug.')
+ assert_nil result
+ end
+
+ def test_pop_with_timeout_and_value
+ queue = Thread::Queue.new
+ queue.push(:something)
+ kill = false
+ result = :unspecified
+
+ thread = Thread.new do
+ scheduler = Scheduler.new
+ Fiber.set_scheduler(scheduler)
+
+ Fiber.schedule do
+ result = queue.pop(timeout: 0.0001)
+ end
+
+ scheduler.run
+ end
+ until thread.join(2)
+ kill = true
+ thread.kill
+ end
+
+ assert_false(kill, 'Getting stuck due to a possible compiler bug.')
+ assert_equal :something, result
+ end
+end
diff --git a/test/fiber/test_ractor.rb b/test/fiber/test_ractor.rb
index d03455a9f7..3c4ccbd8e5 100644
--- a/test/fiber/test_ractor.rb
+++ b/test/fiber/test_ractor.rb
@@ -4,7 +4,7 @@ require "fiber"
class TestFiberCurrentRactor < Test::Unit::TestCase
def setup
- skip unless defined? Ractor
+ omit unless defined? Ractor
end
def test_ractor_shareable
diff --git a/test/fiber/test_scheduler.rb b/test/fiber/test_scheduler.rb
index f0f5b79f36..34effad816 100644
--- a/test/fiber/test_scheduler.rb
+++ b/test/fiber/test_scheduler.rb
@@ -27,6 +27,18 @@ class TestFiberScheduler < Test::Unit::TestCase
refute f.blocking?
end
+ def test_fiber_blocking
+ f = Fiber.new(blocking: false) do
+ fiber = Fiber.current
+ refute fiber.blocking?
+ Fiber.blocking do |_fiber|
+ assert_equal fiber, _fiber
+ assert fiber.blocking?
+ end
+ end
+ f.resume
+ end
+
def test_closed_at_thread_exit
scheduler = Scheduler.new
@@ -55,6 +67,7 @@ class TestFiberScheduler < Test::Unit::TestCase
def test_close_at_exit
assert_in_out_err %W[-I#{__dir__} -], <<-RUBY, ['Running Fiber'], [], success: true
require 'scheduler'
+ Warning[:experimental] = false
scheduler = Scheduler.new
Fiber.set_scheduler scheduler
@@ -103,4 +116,70 @@ class TestFiberScheduler < Test::Unit::TestCase
thread.join
end
+
+ def test_autoload
+ 10.times do
+ Object.autoload(:TestFiberSchedulerAutoload, File.expand_path("autoload.rb", __dir__))
+
+ thread = Thread.new do
+ scheduler = Scheduler.new
+ Fiber.set_scheduler scheduler
+
+ 10.times do
+ Fiber.schedule do
+ Object.const_get(:TestFiberSchedulerAutoload)
+ end
+ end
+ end
+
+ thread.join
+ ensure
+ $LOADED_FEATURES.delete(File.expand_path("autoload.rb", __dir__))
+ Object.send(:remove_const, :TestFiberSchedulerAutoload)
+ end
+ end
+
+ def test_deadlock
+ mutex = Thread::Mutex.new
+ condition = Thread::ConditionVariable.new
+ q = 0.0001
+
+ signaller = Thread.new do
+ loop do
+ mutex.synchronize do
+ condition.signal
+ end
+ sleep q
+ end
+ end
+
+ i = 0
+
+ thread = Thread.new do
+ scheduler = SleepingBlockingScheduler.new
+ Fiber.set_scheduler scheduler
+
+ Fiber.schedule do
+ 10.times do
+ mutex.synchronize do
+ condition.wait(mutex)
+ sleep q
+ i += 1
+ end
+ end
+ end
+ end
+
+ # Wait for 10 seconds at most... if it doesn't finish, it's deadlocked.
+ thread.join(10)
+
+ # If it's deadlocked, it will never finish, so this will be 0.
+ assert_equal 10, i
+ ensure
+ # Make sure the threads are dead...
+ thread.kill
+ signaller.kill
+ thread.join
+ signaller.join
+ end
end
diff --git a/test/fiber/test_storage.rb b/test/fiber/test_storage.rb
new file mode 100644
index 0000000000..3726decbdb
--- /dev/null
+++ b/test/fiber/test_storage.rb
@@ -0,0 +1,115 @@
+# frozen_string_literal: true
+require 'test/unit'
+
+class TestFiberStorage < Test::Unit::TestCase
+ def test_storage
+ Fiber.new do
+ Fiber[:x] = 10
+ assert_kind_of Hash, Fiber.current.storage
+ assert_predicate Fiber.current.storage, :any?
+ end.resume
+ end
+
+ def test_storage_inherited
+ Fiber.new do
+ Fiber[:foo] = :bar
+
+ Fiber.new do
+ assert_equal :bar, Fiber[:foo]
+ Fiber[:bar] = :baz
+ end.resume
+
+ assert_nil Fiber[:bar]
+ end.resume
+ end
+
+ def test_variable_assignment
+ Fiber.new do
+ Fiber[:foo] = :bar
+ assert_equal :bar, Fiber[:foo]
+ end.resume
+ end
+
+ def test_storage_assignment
+ old, Warning[:experimental] = Warning[:experimental], false
+
+ Fiber.new do
+ Fiber.current.storage = {foo: :bar}
+ assert_equal :bar, Fiber[:foo]
+ end.resume
+ ensure
+ Warning[:experimental] = old
+ end
+
+ def test_storage_only_allow_access_from_same_fiber
+ old, Warning[:experimental] = Warning[:experimental], false
+
+ f = Fiber.new do
+ Fiber[:a] = 1
+ end
+ assert_raise(ArgumentError) { f.storage }
+ assert_raise(ArgumentError) { f.storage = {} }
+ ensure
+ Warning[:experimental] = old
+ end
+
+ def test_inherited_storage
+ Fiber.new(storage: {foo: :bar}) do
+ f = Fiber.new do
+ assert_equal :bar, Fiber[:foo]
+ end
+ f.resume
+ end.resume
+ end
+
+ def test_enumerator_inherited_storage
+ Fiber.new do
+ Fiber[:item] = "Hello World"
+
+ enumerator = Enumerator.new do |out|
+ out << Fiber.current
+ out << Fiber[:item]
+ end
+
+ # The fiber within the enumerator is not equal to the current...
+ assert_not_equal Fiber.current, enumerator.next
+
+ # But it inherited the storage from the current fiber:
+ assert_equal "Hello World", enumerator.next
+ end.resume
+ end
+
+ def test_thread_inherited_storage
+ Fiber.new do
+ Fiber[:x] = 10
+
+ x = Thread.new do
+ Fiber[:y] = 20
+ Fiber[:x]
+ end.value
+
+ assert_equal 10, x
+ assert_equal nil, Fiber[:y]
+ end.resume
+ end
+
+ def test_enumerator_count
+ Fiber.new do
+ Fiber[:count] = 0
+
+ enumerator = Enumerator.new do |y|
+ Fiber[:count] += 1
+ y << Fiber[:count]
+ end
+
+ assert_equal 1, enumerator.next
+ assert_equal 0, Fiber[:count]
+ end.resume
+ end
+
+ def test_storage_assignment_type_error
+ assert_raise(TypeError) do
+ Fiber.new(storage: {Object.new => "bar"}) {}
+ end
+ end
+end
diff --git a/test/fiber/test_thread.rb b/test/fiber/test_thread.rb
index 5c25c43de2..5e3cc6d0e1 100644
--- a/test/fiber/test_thread.rb
+++ b/test/fiber/test_thread.rb
@@ -20,6 +20,28 @@ class TestFiberThread < Test::Unit::TestCase
assert_equal :done, thread.value
end
+ def test_thread_join_timeout
+ sleeper = nil
+
+ thread = Thread.new do
+ scheduler = Scheduler.new
+ Fiber.set_scheduler scheduler
+
+ Fiber.schedule do
+ sleeper = Thread.new{sleep}
+ sleeper.join(0.1)
+ end
+
+ scheduler.run
+ end
+
+ thread.join
+
+ assert_predicate sleeper, :alive?
+ ensure
+ sleeper&.kill&.join
+ end
+
def test_thread_join_implicit
sleeping = false
finished = false
diff --git a/test/fiddle/helper.rb b/test/fiddle/helper.rb
index 0ea3bf57f4..e470f5a276 100644
--- a/test/fiddle/helper.rb
+++ b/test/fiddle/helper.rb
@@ -49,8 +49,14 @@ when /linux/
libm_so = libc_so
else
# glibc
- libc_so = "libc.so.6"
- libm_so = "libm.so.6"
+ case RUBY_PLATFORM
+ when /alpha-linux/, /ia64-linux/
+ libc_so = "libc.so.6.1"
+ libm_so = "libm.so.6.1"
+ else
+ libc_so = "libc.so.6"
+ libm_so = "libm.so.6"
+ end
end
when /mingw/, /mswin/
require "rbconfig"
diff --git a/test/fiddle/test_c_struct_entry.rb b/test/fiddle/test_c_struct_entry.rb
index 9fd16d7101..45de2efe21 100644
--- a/test/fiddle/test_c_struct_entry.rb
+++ b/test/fiddle/test_c_struct_entry.rb
@@ -8,7 +8,7 @@ end
module Fiddle
class TestCStructEntity < TestCase
def test_class_size
- types = [TYPE_DOUBLE, TYPE_CHAR]
+ types = [TYPE_DOUBLE, TYPE_CHAR, TYPE_DOUBLE, TYPE_BOOL]
size = CStructEntity.size types
@@ -20,6 +20,12 @@ module Fiddle
expected = PackInfo.align expected, alignments[1]
expected += PackInfo::SIZE_MAP[TYPE_CHAR]
+ expected = PackInfo.align expected, alignments[2]
+ expected += PackInfo::SIZE_MAP[TYPE_DOUBLE]
+
+ expected = PackInfo.align expected, alignments[3]
+ expected += PackInfo::SIZE_MAP[TYPE_BOOL]
+
expected = PackInfo.align expected, alignments.max
assert_equal expected, size
diff --git a/test/fiddle/test_closure.rb b/test/fiddle/test_closure.rb
index 9e748bf5ee..abb6bdbd32 100644
--- a/test/fiddle/test_closure.rb
+++ b/test/fiddle/test_closure.rb
@@ -6,6 +6,17 @@ end
module Fiddle
class TestClosure < Fiddle::TestCase
+ def teardown
+ super
+ # Ensure freeing all closures.
+ # See https://github.com/ruby/fiddle/issues/102#issuecomment-1241763091 .
+ not_freed_closures = []
+ ObjectSpace.each_object(Fiddle::Closure) do |closure|
+ not_freed_closures << closure unless closure.freed?
+ end
+ assert_equal([], not_freed_closures)
+ end
+
def test_argument_errors
assert_raise(TypeError) do
Closure.new(TYPE_INT, TYPE_INT)
@@ -21,37 +32,40 @@ module Fiddle
end
def test_type_symbol
- closure = Closure.new(:int, [:void])
- assert_equal([
- TYPE_INT,
- [TYPE_VOID],
- ],
- [
- closure.instance_variable_get(:@ctype),
- closure.instance_variable_get(:@args),
- ])
+ Closure.create(:int, [:void]) do |closure|
+ assert_equal([
+ TYPE_INT,
+ [TYPE_VOID],
+ ],
+ [
+ closure.instance_variable_get(:@ctype),
+ closure.instance_variable_get(:@args),
+ ])
+ end
end
def test_call
- closure = Class.new(Closure) {
+ closure_class = Class.new(Closure) do
def call
10
end
- }.new(TYPE_INT, [])
-
- func = Function.new(closure, [], TYPE_INT)
- assert_equal 10, func.call
+ end
+ closure_class.create(TYPE_INT, []) do |closure|
+ func = Function.new(closure, [], TYPE_INT)
+ assert_equal 10, func.call
+ end
end
def test_returner
- closure = Class.new(Closure) {
+ closure_class = Class.new(Closure) do
def call thing
thing
end
- }.new(TYPE_INT, [TYPE_INT])
-
- func = Function.new(closure, [TYPE_INT], TYPE_INT)
- assert_equal 10, func.call(10)
+ end
+ closure_class.create(TYPE_INT, [TYPE_INT]) do |closure|
+ func = Function.new(closure, [TYPE_INT], TYPE_INT)
+ assert_equal 10, func.call(10)
+ end
end
def test_const_string
@@ -61,25 +75,53 @@ module Fiddle
@return_string
end
end
- closure = closure_class.new(:const_string, [:const_string])
+ closure_class.create(:const_string, [:const_string]) do |closure|
+ func = Function.new(closure, [:const_string], :const_string)
+ assert_equal("Hello! World!", func.call("World!"))
+ end
+ end
- func = Function.new(closure, [:const_string], :const_string)
- assert_equal("Hello! World!", func.call("World!"))
+ def test_bool
+ closure_class = Class.new(Closure) do
+ def call(bool)
+ not bool
+ end
+ end
+ closure_class.create(:bool, [:bool]) do |closure|
+ func = Function.new(closure, [:bool], :bool)
+ assert_equal(false, func.call(true))
+ end
+ end
+
+ def test_free
+ Closure.create(:int, [:void]) do |closure|
+ assert(!closure.freed?)
+ closure.free
+ assert(closure.freed?)
+ closure.free
+ end
end
def test_block_caller
cb = Closure::BlockCaller.new(TYPE_INT, [TYPE_INT]) do |one|
one
end
- func = Function.new(cb, [TYPE_INT], TYPE_INT)
- assert_equal 11, func.call(11)
+ begin
+ func = Function.new(cb, [TYPE_INT], TYPE_INT)
+ assert_equal 11, func.call(11)
+ ensure
+ cb.free
+ end
end
- def test_memsize
+ def test_memsize_ruby_dev_42480
require 'objspace'
- bug = '[ruby-dev:42480]'
n = 10000
- assert_equal(n, n.times {ObjectSpace.memsize_of(Closure.allocate)}, bug)
+ n.times do
+ Closure.create(:int, [:void]) do |closure|
+ ObjectSpace.memsize_of(closure)
+ end
+ end
end
%w[INT SHORT CHAR LONG LONG_LONG].each do |name|
@@ -89,20 +131,21 @@ module Fiddle
define_method("test_conversion_#{n.downcase}") do
arg = nil
- clos = Class.new(Closure) do
+ closure_class = Class.new(Closure) do
define_method(:call) {|x| arg = x}
- end.new(t, [t])
-
- v = ~(~0 << (8*s))
-
- arg = nil
- assert_equal(v, clos.call(v))
- assert_equal(arg, v, n)
-
- arg = nil
- func = Function.new(clos, [t], t)
- assert_equal(v, func.call(v))
- assert_equal(arg, v, n)
+ end
+ closure_class.create(t, [t]) do |closure|
+ v = ~(~0 << (8*s))
+
+ arg = nil
+ assert_equal(v, closure.call(v))
+ assert_equal(arg, v, n)
+
+ arg = nil
+ func = Function.new(closure, [t], t)
+ assert_equal(v, func.call(v))
+ assert_equal(arg, v, n)
+ end
end
end
end
diff --git a/test/fiddle/test_cparser.rb b/test/fiddle/test_cparser.rb
index ae319197a4..f1b67476ba 100644
--- a/test/fiddle/test_cparser.rb
+++ b/test/fiddle/test_cparser.rb
@@ -24,14 +24,32 @@ module Fiddle
assert_equal(TYPE_SHORT, parse_ctype('const short'))
assert_equal(TYPE_SHORT, parse_ctype('short int'))
assert_equal(TYPE_SHORT, parse_ctype('const short int'))
+ assert_equal(TYPE_SHORT, parse_ctype('int short'))
+ assert_equal(TYPE_SHORT, parse_ctype('const int short'))
assert_equal(TYPE_SHORT, parse_ctype('signed short'))
assert_equal(TYPE_SHORT, parse_ctype('const signed short'))
+ assert_equal(TYPE_SHORT, parse_ctype('short signed'))
+ assert_equal(TYPE_SHORT, parse_ctype('const short signed'))
assert_equal(TYPE_SHORT, parse_ctype('signed short int'))
assert_equal(TYPE_SHORT, parse_ctype('const signed short int'))
+ assert_equal(TYPE_SHORT, parse_ctype('signed int short'))
+ assert_equal(TYPE_SHORT, parse_ctype('const signed int short'))
+ assert_equal(TYPE_SHORT, parse_ctype('int signed short'))
+ assert_equal(TYPE_SHORT, parse_ctype('const int signed short'))
+ assert_equal(TYPE_SHORT, parse_ctype('int short signed'))
+ assert_equal(TYPE_SHORT, parse_ctype('const int short signed'))
assert_equal(-TYPE_SHORT, parse_ctype('unsigned short'))
assert_equal(-TYPE_SHORT, parse_ctype('const unsigned short'))
assert_equal(-TYPE_SHORT, parse_ctype('unsigned short int'))
assert_equal(-TYPE_SHORT, parse_ctype('const unsigned short int'))
+ assert_equal(-TYPE_SHORT, parse_ctype('unsigned int short'))
+ assert_equal(-TYPE_SHORT, parse_ctype('const unsigned int short'))
+ assert_equal(-TYPE_SHORT, parse_ctype('short int unsigned'))
+ assert_equal(-TYPE_SHORT, parse_ctype('const short int unsigned'))
+ assert_equal(-TYPE_SHORT, parse_ctype('int unsigned short'))
+ assert_equal(-TYPE_SHORT, parse_ctype('const int unsigned short'))
+ assert_equal(-TYPE_SHORT, parse_ctype('int short unsigned'))
+ assert_equal(-TYPE_SHORT, parse_ctype('const int short unsigned'))
end
def test_int_ctype
@@ -50,14 +68,32 @@ module Fiddle
assert_equal(TYPE_LONG, parse_ctype('const long'))
assert_equal(TYPE_LONG, parse_ctype('long int'))
assert_equal(TYPE_LONG, parse_ctype('const long int'))
+ assert_equal(TYPE_LONG, parse_ctype('int long'))
+ assert_equal(TYPE_LONG, parse_ctype('const int long'))
assert_equal(TYPE_LONG, parse_ctype('signed long'))
assert_equal(TYPE_LONG, parse_ctype('const signed long'))
assert_equal(TYPE_LONG, parse_ctype('signed long int'))
assert_equal(TYPE_LONG, parse_ctype('const signed long int'))
+ assert_equal(TYPE_LONG, parse_ctype('signed int long'))
+ assert_equal(TYPE_LONG, parse_ctype('const signed int long'))
+ assert_equal(TYPE_LONG, parse_ctype('long signed'))
+ assert_equal(TYPE_LONG, parse_ctype('const long signed'))
+ assert_equal(TYPE_LONG, parse_ctype('long int signed'))
+ assert_equal(TYPE_LONG, parse_ctype('const long int signed'))
+ assert_equal(TYPE_LONG, parse_ctype('int long signed'))
+ assert_equal(TYPE_LONG, parse_ctype('const int long signed'))
assert_equal(-TYPE_LONG, parse_ctype('unsigned long'))
assert_equal(-TYPE_LONG, parse_ctype('const unsigned long'))
assert_equal(-TYPE_LONG, parse_ctype('unsigned long int'))
assert_equal(-TYPE_LONG, parse_ctype('const unsigned long int'))
+ assert_equal(-TYPE_LONG, parse_ctype('long int unsigned'))
+ assert_equal(-TYPE_LONG, parse_ctype('const long int unsigned'))
+ assert_equal(-TYPE_LONG, parse_ctype('unsigned int long'))
+ assert_equal(-TYPE_LONG, parse_ctype('const unsigned int long'))
+ assert_equal(-TYPE_LONG, parse_ctype('int unsigned long'))
+ assert_equal(-TYPE_LONG, parse_ctype('const int unsigned long'))
+ assert_equal(-TYPE_LONG, parse_ctype('int long unsigned'))
+ assert_equal(-TYPE_LONG, parse_ctype('const int long unsigned'))
end
def test_size_t_ctype
@@ -85,6 +121,10 @@ module Fiddle
assert_equal(TYPE_UINTPTR_T, parse_ctype("const uintptr_t"))
end
+ def test_bool_ctype
+ assert_equal(TYPE_BOOL, parse_ctype('bool'))
+ end
+
def test_undefined_ctype
assert_raise(DLError) { parse_ctype('DWORD') }
end
diff --git a/test/fiddle/test_fiddle.rb b/test/fiddle/test_fiddle.rb
index 8751d96920..9bddb056c9 100644
--- a/test/fiddle/test_fiddle.rb
+++ b/test/fiddle/test_fiddle.rb
@@ -5,6 +5,13 @@ rescue LoadError
end
class TestFiddle < Fiddle::TestCase
+ def test_nil_true_etc
+ assert_equal Fiddle::Qtrue, Fiddle.dlwrap(true)
+ assert_equal Fiddle::Qfalse, Fiddle.dlwrap(false)
+ assert_equal Fiddle::Qnil, Fiddle.dlwrap(nil)
+ assert Fiddle::Qundef
+ end
+
def test_windows_constant
require 'rbconfig'
if RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
@@ -14,4 +21,38 @@ class TestFiddle < Fiddle::TestCase
end
end
+ def test_dlopen_linker_script_input_linux
+ omit("This is only for Linux") unless RUBY_PLATFORM.match?("linux")
+ if Dir.glob("/usr/lib/*/libncurses.so").empty?
+ omit("libncurses.so is needed")
+ end
+ # libncurses.so uses INPUT() on Debian GNU/Linux
+ # $ cat /usr/lib/x86_64-linux-gnu/libncurses.so
+ # INPUT(libncurses.so.6 -ltinfo)
+ handle = Fiddle.dlopen("libncurses.so")
+ begin
+ assert_equal("libncurses.so",
+ File.basename(handle.file_name, ".*"))
+ ensure
+ handle.close
+ end
+ end
+
+ def test_dlopen_linker_script_group_linux
+ omit("This is only for Linux") unless RUBY_PLATFORM.match?("linux")
+ # libc.so uses GROUP() on Debian GNU/Linux
+ # $ cat /usr/lib/x86_64-linux-gnu/libc.so
+ # /* GNU ld script
+ # Use the shared library, but some functions are only in
+ # the static library, so try that secondarily. */
+ # OUTPUT_FORMAT(elf64-x86-64)
+ # GROUP ( /lib/x86_64-linux-gnu/libc.so.6 /usr/lib/x86_64-linux-gnu/libc_nonshared.a AS_NEEDED ( /lib64/ld-linux-x86-64.so.2 ) )
+ handle = Fiddle.dlopen("libc.so")
+ begin
+ assert_equal("libc.so",
+ File.basename(handle.file_name, ".*"))
+ ensure
+ handle.close
+ end
+ end
end if defined?(Fiddle)
diff --git a/test/fiddle/test_func.rb b/test/fiddle/test_func.rb
index 44893017e8..df79539e76 100644
--- a/test/fiddle/test_func.rb
+++ b/test/fiddle/test_func.rb
@@ -60,25 +60,35 @@ module Fiddle
end
def test_qsort1
- cb = Class.new(Closure) {
+ closure_class = Class.new(Closure) do
def call(x, y)
Pointer.new(x)[0] <=> Pointer.new(y)[0]
end
- }.new(TYPE_INT, [TYPE_VOIDP, TYPE_VOIDP])
+ end
- qsort = Function.new(@libc['qsort'],
- [TYPE_VOIDP, TYPE_SIZE_T, TYPE_SIZE_T, TYPE_VOIDP],
- TYPE_VOID)
- buff = "9341"
- qsort.call(buff, buff.size, 1, cb)
- assert_equal("1349", buff)
+ closure_class.create(TYPE_INT, [TYPE_VOIDP, TYPE_VOIDP]) do |callback|
+ qsort = Function.new(@libc['qsort'],
+ [TYPE_VOIDP, TYPE_SIZE_T, TYPE_SIZE_T, TYPE_VOIDP],
+ TYPE_VOID)
+ buff = "9341"
+ qsort.call(buff, buff.size, 1, callback)
+ assert_equal("1349", buff)
- bug4929 = '[ruby-core:37395]'
- buff = "9341"
- under_gc_stress do
- qsort.call(buff, buff.size, 1, cb)
+ bug4929 = '[ruby-core:37395]'
+ buff = "9341"
+ under_gc_stress do
+ qsort.call(buff, buff.size, 1, callback)
+ end
+ assert_equal("1349", buff, bug4929)
+ end
+ ensure
+ # Ensure freeing all closures.
+ # See https://github.com/ruby/fiddle/issues/102#issuecomment-1241763091 .
+ not_freed_closures = []
+ ObjectSpace.each_object(Fiddle::Closure) do |closure|
+ not_freed_closures << closure unless closure.freed?
end
- assert_equal("1349", buff, bug4929)
+ assert_equal([], not_freed_closures)
end
def test_snprintf
@@ -135,5 +145,22 @@ module Fiddle
assert_equal("string: He, const string: World, uint: 29\n",
output_buffer[0, written])
end
+
+ def test_rb_memory_view_available_p
+ omit "MemoryView is unavailable" unless defined? Fiddle::MemoryView
+ libruby = Fiddle.dlopen(nil)
+ case Fiddle::SIZEOF_VOIDP
+ when Fiddle::SIZEOF_LONG_LONG
+ value_type = -Fiddle::TYPE_LONG_LONG
+ else
+ value_type = -Fiddle::TYPE_LONG
+ end
+ rb_memory_view_available_p =
+ Function.new(libruby["rb_memory_view_available_p"],
+ [value_type],
+ :bool,
+ need_gvl: true)
+ assert_equal(false, rb_memory_view_available_p.call(Fiddle::Qnil))
+ end
end
end if defined?(Fiddle)
diff --git a/test/fiddle/test_function.rb b/test/fiddle/test_function.rb
index 8ac4f60aa3..2bd67c9da1 100644
--- a/test/fiddle/test_function.rb
+++ b/test/fiddle/test_function.rb
@@ -15,6 +15,16 @@ module Fiddle
end
end
+ def teardown
+ # Ensure freeing all closures.
+ # See https://github.com/ruby/fiddle/issues/102#issuecomment-1241763091 .
+ not_freed_closures = []
+ ObjectSpace.each_object(Fiddle::Closure) do |closure|
+ not_freed_closures << closure unless closure.freed?
+ end
+ assert_equal([], not_freed_closures)
+ end
+
def test_default_abi
func = Function.new(@libm['sin'], [TYPE_DOUBLE], TYPE_DOUBLE)
assert_equal Function::DEFAULT, func.abi
@@ -75,18 +85,20 @@ module Fiddle
end
def test_argument_count
- closure = Class.new(Closure) {
+ closure_class = Class.new(Closure) do
def call one
10 + one
end
- }.new(TYPE_INT, [TYPE_INT])
- func = Function.new(closure, [TYPE_INT], TYPE_INT)
-
- assert_raise(ArgumentError) do
- func.call(1,2,3)
end
- assert_raise(ArgumentError) do
- func.call
+ closure_class.create(TYPE_INT, [TYPE_INT]) do |closure|
+ func = Function.new(closure, [TYPE_INT], TYPE_INT)
+
+ assert_raise(ArgumentError) do
+ func.call(1,2,3)
+ end
+ assert_raise(ArgumentError) do
+ func.call
+ end
end
end
@@ -155,6 +167,8 @@ module Fiddle
end
def test_nogvl_poll
+ require "envutil" unless defined?(EnvUtil)
+
# XXX hack to quiet down CI errors on EINTR from r64353
# [ruby-core:88360] [Misc #14937]
# Making pipes (and sockets) non-blocking by default would allow
@@ -168,13 +182,13 @@ module Fiddle
end
f = Function.new(poll, [TYPE_VOIDP, TYPE_INT, TYPE_INT], TYPE_INT)
- msec = 200
+ msec = EnvUtil.apply_timeout_scale(1000)
t0 = Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond)
th = Thread.new { f.call(nil, 0, msec) }
n1 = f.call(nil, 0, msec)
n2 = th.value
t1 = Process.clock_gettime(Process::CLOCK_MONOTONIC, :millisecond)
- assert_in_delta(msec, t1 - t0, 180, 'slept amount of time')
+ assert_in_delta(msec, t1 - t0, EnvUtil.apply_timeout_scale(500), 'slept amount of time')
assert_equal(0, n1, perror("poll(2) in main-thread"))
assert_equal(0, n2, perror("poll(2) in sub-thread"))
end
diff --git a/test/fiddle/test_handle.rb b/test/fiddle/test_handle.rb
index 7e3ff9d844..412c10e09d 100644
--- a/test/fiddle/test_handle.rb
+++ b/test/fiddle/test_handle.rb
@@ -22,12 +22,14 @@ module Fiddle
def test_static_sym_unknown
assert_raise(DLError) { Fiddle::Handle.sym('fooo') }
assert_raise(DLError) { Fiddle::Handle['fooo'] }
+ refute Fiddle::Handle.sym_defined?('fooo')
end
def test_static_sym
begin
# Linux / Darwin / FreeBSD
refute_nil Fiddle::Handle.sym('dlopen')
+ assert Fiddle::Handle.sym_defined?('dlopen')
assert_equal Fiddle::Handle.sym('dlopen'), Fiddle::Handle['dlopen']
return
rescue
@@ -54,6 +56,7 @@ module Fiddle
handle = Fiddle::Handle.new(LIBC_SO)
assert_raise(DLError) { handle.sym('fooo') }
assert_raise(DLError) { handle['fooo'] }
+ refute handle.sym_defined?('fooo')
end
def test_sym_with_bad_args
@@ -66,6 +69,7 @@ module Fiddle
handle = Handle.new(LIBC_SO)
refute_nil handle.sym('calloc')
refute_nil handle['calloc']
+ assert handle.sym_defined?('calloc')
end
def test_handle_close
@@ -179,12 +183,18 @@ module Fiddle
# it calls _nss_cache_cycle_prevention_function with dlsym(3).
# So our Fiddle::Handle#sym must call dlerror(3) before call dlsym.
# In general uses of dlerror(3) should call it before use it.
+ verbose, $VERBOSE = $VERBOSE, nil
require 'socket'
Socket.gethostbyname("localhost")
Fiddle.dlopen("/lib/libc.so.7").sym('strcpy')
+ ensure
+ $VERBOSE = verbose
end if /freebsd/=~ RUBY_PLATFORM
def test_no_memory_leak
+ # https://github.com/ruby/fiddle/actions/runs/3202406059/jobs/5231356410
+ omit if RUBY_VERSION >= '3.2'
+
if respond_to?(:assert_nothing_leaked_memory)
n_tries = 100_000
assert_nothing_leaked_memory(SIZEOF_VOIDP * (n_tries / 100)) do
diff --git a/test/fiddle/test_import.rb b/test/fiddle/test_import.rb
index afa8df9e00..090ace620d 100644
--- a/test/fiddle/test_import.rb
+++ b/test/fiddle/test_import.rb
@@ -22,7 +22,6 @@ module Fiddle
extern "int fprintf(FILE*, char*)" rescue nil
extern "int gettimeofday(timeval*, timezone*)" rescue nil
- BoundQsortCallback = bind("void *bound_qsort_callback(void*, void*)"){|ptr1,ptr2| ptr1[0] <=> ptr2[0]}
Timeval = struct [
"long tv_sec",
"long tv_usec",
@@ -59,11 +58,6 @@ module Fiddle
]
}
]
-
- CallCallback = bind("void call_callback(void*, void*)"){ | ptr1, ptr2|
- f = Function.new(ptr1.to_i, [TYPE_VOIDP], TYPE_VOID)
- f.call(ptr2)
- }
end
class TestImport < TestCase
@@ -130,11 +124,28 @@ module Fiddle
name = $1.sub(/P\z/,"*").gsub(/_(?!T\z)/, " ").downcase
type_name = name
end
+ type_name = "unsigned #{$1}" if type_name =~ /\Au(long|short|char|int|long long)\z/
+
define_method("test_sizeof_#{name}") do
assert_equal(size, Fiddle::Importer.sizeof(type_name), type)
end
end
+ # Assert that the unsigned constants are equal to the "negative" signed ones
+ # for backwards compatibility
+ def test_unsigned_equals_negative_signed
+ Fiddle.constants.grep(/\ATYPE_(?!VOID|VARIADIC\z)(U.*)/) do |unsigned|
+ assert_equal(-Fiddle.const_get(unsigned.to_s.sub(/U/, '')),
+ Fiddle.const_get(unsigned))
+ end
+ end
+
+ def test_type_constants
+ Fiddle::Types.constants.each do |const|
+ assert_equal Fiddle::Types.const_get(const), Fiddle.const_get("TYPE_#{const}")
+ end
+ end
+
def test_unsigned_result()
d = (2 ** 31) + 1
diff --git a/test/fiddle/test_pack.rb b/test/fiddle/test_pack.rb
new file mode 100644
index 0000000000..ade1dd5040
--- /dev/null
+++ b/test/fiddle/test_pack.rb
@@ -0,0 +1,37 @@
+begin
+ require_relative 'helper'
+ require 'fiddle/pack'
+rescue LoadError
+ return
+end
+
+module Fiddle
+ class TestPack < TestCase
+ def test_pack_map
+ if defined?(TYPE_LONG_LONG)
+ assert_equal [0xffff_ffff_ffff_ffff], [0xffff_ffff_ffff_ffff].pack(PackInfo::PACK_MAP[-TYPE_LONG_LONG]).unpack(PackInfo::PACK_MAP[-TYPE_LONG_LONG])
+ end
+
+ case Fiddle::SIZEOF_VOIDP
+ when 8
+ assert_equal [0xffff_ffff_ffff_ffff], [0xffff_ffff_ffff_ffff].pack(PackInfo::PACK_MAP[TYPE_VOIDP]).unpack(PackInfo::PACK_MAP[TYPE_VOIDP])
+ when 4
+ assert_equal [0xffff_ffff], [0xffff_ffff].pack(PackInfo::PACK_MAP[TYPE_VOIDP]).unpack(PackInfo::PACK_MAP[TYPE_VOIDP])
+ end
+
+ case Fiddle::SIZEOF_LONG
+ when 8
+ assert_equal [0xffff_ffff_ffff_ffff], [0xffff_ffff_ffff_ffff].pack(PackInfo::PACK_MAP[-TYPE_LONG]).unpack(PackInfo::PACK_MAP[-TYPE_LONG])
+ when 4
+ assert_equal [0xffff_ffff], [0xffff_ffff].pack(PackInfo::PACK_MAP[-TYPE_LONG]).unpack(PackInfo::PACK_MAP[-TYPE_LONG])
+ end
+
+ if Fiddle::SIZEOF_INT == 4
+ assert_equal [0xffff_ffff], [0xffff_ffff].pack(PackInfo::PACK_MAP[-TYPE_INT]).unpack(PackInfo::PACK_MAP[-TYPE_INT])
+ end
+
+ assert_equal [0xffff], [0xffff].pack(PackInfo::PACK_MAP[-TYPE_SHORT]).unpack(PackInfo::PACK_MAP[-TYPE_SHORT])
+ assert_equal [0xff], [0xff].pack(PackInfo::PACK_MAP[-TYPE_CHAR]).unpack(PackInfo::PACK_MAP[-TYPE_CHAR])
+ end
+ end
+end
diff --git a/test/fiddle/test_pointer.rb b/test/fiddle/test_pointer.rb
index 7d708ee417..f2c1d285ad 100644
--- a/test/fiddle/test_pointer.rb
+++ b/test/fiddle/test_pointer.rb
@@ -10,6 +10,22 @@ module Fiddle
Fiddle.dlwrap arg
end
+ def test_can_read_write_memory
+ # Allocate some memory
+ address = Fiddle.malloc(Fiddle::SIZEOF_VOIDP)
+
+ bytes_to_write = Fiddle::SIZEOF_VOIDP.times.to_a.pack("C*")
+
+ # Write to the memory
+ Fiddle::Pointer.write(address, bytes_to_write)
+
+ # Read the bytes out again
+ bytes = Fiddle::Pointer.read(address, Fiddle::SIZEOF_VOIDP)
+ assert_equal bytes_to_write, bytes
+ ensure
+ Fiddle.free address
+ end
+
def test_cptr_to_int
null = Fiddle::NULL
assert_equal(null.to_i, null.to_int)
@@ -272,6 +288,9 @@ module Fiddle
end
def test_no_memory_leak
+ # https://github.com/ruby/fiddle/actions/runs/3202406059/jobs/5231356410
+ omit if RUBY_VERSION >= '3.2'
+
if respond_to?(:assert_nothing_leaked_memory)
n_tries = 100_000
assert_nothing_leaked_memory(SIZEOF_VOIDP * (n_tries / 100)) do
diff --git a/test/fileutils/clobber.rb b/test/fileutils/clobber.rb
index fdcecd5e08..ac5c8c79c0 100644
--- a/test/fileutils/clobber.rb
+++ b/test/fileutils/clobber.rb
@@ -4,10 +4,7 @@ require 'test/unit'
require 'tmpdir'
require_relative 'fileasserts'
-class TestFileUtils < Test::Unit::TestCase
-end
-
-module TestFileUtils::Clobber
+module TestFileUtilsClobber
include Test::Unit::FileAssertions
def my_rm_rf(path)
diff --git a/test/fileutils/test_dryrun.rb b/test/fileutils/test_dryrun.rb
index fd8a7805ec..a3efbb4bdf 100644
--- a/test/fileutils/test_dryrun.rb
+++ b/test/fileutils/test_dryrun.rb
@@ -8,7 +8,7 @@ require_relative 'visibility_tests'
class TestFileUtilsDryRun < Test::Unit::TestCase
include FileUtils::DryRun
- include TestFileUtilsInc::Visibility
+ include TestFileUtilsIncVisibility
def setup
super
diff --git a/test/fileutils/test_fileutils.rb b/test/fileutils/test_fileutils.rb
index 36b5d6ef50..d2096a04cc 100644
--- a/test/fileutils/test_fileutils.rb
+++ b/test/fileutils/test_fileutils.rb
@@ -93,12 +93,24 @@ class TestFileUtils < Test::Unit::TestCase
@@no_broken_symlink
end
+ def has_capsh?
+ !!system('capsh', '--print', out: File::NULL, err: File::NULL)
+ end
+
+ def has_root_file_capabilities?
+ !!system(
+ 'capsh', '--has-p=CAP_DAC_OVERRIDE', '--has-p=CAP_CHOWN', '--has-p=CAP_FOWNER',
+ out: File::NULL, err: File::NULL
+ )
+ end
+
def root_in_posix?
if /cygwin/ =~ RUBY_PLATFORM
# FIXME: privilege if groups include root user?
return Process.groups.include?(0)
- end
- if Process.respond_to?('uid')
+ elsif has_capsh?
+ return has_root_file_capabilities?
+ elsif Process.respond_to?('uid')
return Process.uid == 0
else
return false
@@ -317,7 +329,7 @@ class TestFileUtils < Test::Unit::TestCase
def test_cp_preserve_permissions
bug4507 = '[ruby-core:35518]'
touch 'tmp/cptmp'
- chmod 0755, 'tmp/cptmp'
+ chmod 0o755, 'tmp/cptmp'
cp 'tmp/cptmp', 'tmp/cptmp2'
assert_equal_filemode('tmp/cptmp', 'tmp/cptmp2', bug4507, mask: ~File.umask)
@@ -327,9 +339,9 @@ class TestFileUtils < Test::Unit::TestCase
bug7246 = '[ruby-core:48603]'
mkdir 'tmp/cptmp'
mkdir 'tmp/cptmp/d1'
- chmod 0745, 'tmp/cptmp/d1'
+ chmod 0o745, 'tmp/cptmp/d1'
mkdir 'tmp/cptmp/d2'
- chmod 0700, 'tmp/cptmp/d2'
+ chmod 0o700, 'tmp/cptmp/d2'
cp_r 'tmp/cptmp', 'tmp/cptmp2', :preserve => true
assert_equal_filemode('tmp/cptmp/d1', 'tmp/cptmp2/d1', bug7246)
assert_equal_filemode('tmp/cptmp/d2', 'tmp/cptmp2/d2', bug7246)
@@ -472,10 +484,14 @@ class TestFileUtils < Test::Unit::TestCase
else
def test_cp_r_socket
pend "Skipping socket test on JRuby" if RUBY_ENGINE == 'jruby'
+
Dir.mkdir('tmp/cpr_src')
UNIXServer.new('tmp/cpr_src/socket').close
cp_r 'tmp/cpr_src', 'tmp/cpr_dest'
assert_equal(true, File.socket?('tmp/cpr_dest/socket'))
+ rescue Errno::EINVAL => error
+ # On some platforms (windows) sockets cannot be copied by FileUtils.
+ omit error.message
end if defined?(UNIXServer)
end
@@ -750,6 +766,24 @@ class TestFileUtils < Test::Unit::TestCase
assert_file_not_exist 'tmp/tmpdir3'
end
+ def test_rm_r_no_permissions
+ check_singleton :rm_rf
+
+ return if /mswin|mingw/ =~ RUBY_PLATFORM
+
+ mkdir 'tmpdatadir'
+ touch 'tmpdatadir/tmpdata'
+ chmod "-x", 'tmpdatadir'
+
+ begin
+ assert_raise Errno::EACCES do
+ rm_r 'tmpdatadir'
+ end
+ ensure
+ chmod "+x", 'tmpdatadir'
+ end
+ end
+
def test_remove_entry_cjk_path
dir = "tmpdir\u3042"
my_rm_rf dir
@@ -823,7 +857,7 @@ class TestFileUtils < Test::Unit::TestCase
if File.sticky?('tmp/tmpdir')
Dir.mkdir 'tmp/tmpdir/d', 0
assert_raise(Errno::EACCES) {remove_entry_secure 'tmp/tmpdir/d'}
- File.chmod 0777, 'tmp/tmpdir/d'
+ File.chmod 0o777, 'tmp/tmpdir/d'
Dir.rmdir 'tmp/tmpdir/d'
end
end
@@ -980,6 +1014,43 @@ class TestFileUtils < Test::Unit::TestCase
}
end if have_symlink?
+ def test_ln_sr
+ check_singleton :ln_sr
+
+ TARGETS.each do |fname|
+ begin
+ lnfname = 'tmp/lnsdest'
+ ln_sr fname, lnfname
+ assert FileTest.symlink?(lnfname), 'not symlink'
+ assert_equal "../#{fname}", File.readlink(lnfname), fname
+ ensure
+ rm_f lnfname
+ end
+ end
+ mkdir 'data/src'
+ File.write('data/src/xxx', 'ok')
+ File.symlink '../data/src', 'tmp/src'
+ ln_sr 'tmp/src/xxx', 'data'
+ assert File.symlink?('data/xxx')
+ assert_equal 'ok', File.read('data/xxx')
+ end if have_symlink?
+
+ def test_ln_sr_broken_symlink
+ assert_nothing_raised {
+ ln_sr 'tmp/symlink', 'tmp/symlink'
+ }
+ end if have_symlink? and !no_broken_symlink?
+
+ def test_ln_sr_pathname
+ # pathname
+ touch 'tmp/lns_dest'
+ assert_nothing_raised {
+ ln_sr Pathname.new('tmp/lns_dest'), 'tmp/symlink_tmp1'
+ ln_sr 'tmp/lns_dest', Pathname.new('tmp/symlink_tmp2')
+ ln_sr Pathname.new('tmp/lns_dest'), Pathname.new('tmp/symlink_tmp3')
+ }
+ end if have_symlink?
+
def test_mkdir
check_singleton :mkdir
@@ -1098,6 +1169,14 @@ class TestFileUtils < Test::Unit::TestCase
ensure
Dir.rmdir(drive) if drive and File.directory?(drive)
end
+
+ def test_mkdir_p_offline_drive
+ offline_drive = ("A".."Z").to_a.reverse.find {|d| !File.exist?("#{d}:/") }
+
+ assert_raise(Errno::ENOENT) {
+ mkdir_p "#{offline_drive}:/new_dir"
+ }
+ end
end
def test_mkdir_p_file_perm
@@ -1170,6 +1249,14 @@ class TestFileUtils < Test::Unit::TestCase
install Pathname.new('tmp/a'), 'tmp/b'
rm_f 'tmp/a'; touch 'tmp/a'
install Pathname.new('tmp/a'), Pathname.new('tmp/b')
+ my_rm_rf 'tmp/new_dir_end_with_slash'
+ install Pathname.new('tmp/a'), 'tmp/new_dir_end_with_slash/'
+ my_rm_rf 'tmp/new_dir_end_with_slash'
+ my_rm_rf 'tmp/new_dir'
+ install Pathname.new('tmp/a'), 'tmp/new_dir/a'
+ my_rm_rf 'tmp/new_dir'
+ install Pathname.new('tmp/a'), 'tmp/new_dir/new_dir_end_with_slash/'
+ my_rm_rf 'tmp/new_dir'
rm_f 'tmp/a'
touch 'tmp/a'
touch 'tmp/b'
@@ -1227,9 +1314,9 @@ class TestFileUtils < Test::Unit::TestCase
check_singleton :chmod
touch 'tmp/a'
- chmod 0700, 'tmp/a'
+ chmod 0o700, 'tmp/a'
assert_filemode 0700, 'tmp/a'
- chmod 0500, 'tmp/a'
+ chmod 0o500, 'tmp/a'
assert_filemode 0500, 'tmp/a'
end if have_file_perm?
@@ -1333,9 +1420,9 @@ class TestFileUtils < Test::Unit::TestCase
assert_output_lines(["chmod 700 tmp/a", "chmod 500 tmp/a"]) {
touch 'tmp/a'
- chmod 0700, 'tmp/a', verbose: true
+ chmod 0o700, 'tmp/a', verbose: true
assert_filemode 0700, 'tmp/a', mask: 0777
- chmod 0500, 'tmp/a', verbose: true
+ chmod 0o500, 'tmp/a', verbose: true
assert_filemode 0500, 'tmp/a', mask: 0777
}
end if have_file_perm?
@@ -1343,7 +1430,7 @@ class TestFileUtils < Test::Unit::TestCase
def test_s_chmod_verbose
assert_output_lines(["chmod 700 tmp/a"], FileUtils) {
touch 'tmp/a'
- FileUtils.chmod 0700, 'tmp/a', verbose: true
+ FileUtils.chmod 0o700, 'tmp/a', verbose: true
assert_filemode 0700, 'tmp/a', mask: 0777
}
end if have_file_perm?
@@ -1656,7 +1743,7 @@ class TestFileUtils < Test::Unit::TestCase
def test_remove_file_file_perm
File.open('data/tmp', 'w') {|f| f.puts 'dummy' }
- File.chmod 0, 'data/tmp'
+ File.chmod 0o000, 'data/tmp'
remove_file 'data/tmp'
assert_file_not_exist 'data/tmp'
end if have_file_perm?
@@ -1671,7 +1758,7 @@ class TestFileUtils < Test::Unit::TestCase
def test_remove_dir_file_perm
Dir.mkdir 'data/tmpdir'
- File.chmod 0555, 'data/tmpdir'
+ File.chmod 0o555, 'data/tmpdir'
remove_dir 'data/tmpdir'
assert_file_not_exist 'data/tmpdir'
end if have_file_perm?
@@ -1790,7 +1877,7 @@ cd -
return if /mswin|mingw/ =~ RUBY_PLATFORM
mkdir 'tmpdatadir'
- chmod 700, 'tmpdatadir'
+ chmod 0o000, 'tmpdatadir'
rm_rf 'tmpdatadir'
assert_file_not_exist 'tmpdatadir'
diff --git a/test/fileutils/test_nowrite.rb b/test/fileutils/test_nowrite.rb
index 543fa39f5a..659fa20886 100644
--- a/test/fileutils/test_nowrite.rb
+++ b/test/fileutils/test_nowrite.rb
@@ -8,7 +8,7 @@ require_relative 'visibility_tests'
class TestFileUtilsNoWrite < Test::Unit::TestCase
include FileUtils::NoWrite
- include TestFileUtilsInc::Visibility
+ include TestFileUtilsIncVisibility
def setup
super
diff --git a/test/fileutils/test_verbose.rb b/test/fileutils/test_verbose.rb
index cf65be8e03..7987af2395 100644
--- a/test/fileutils/test_verbose.rb
+++ b/test/fileutils/test_verbose.rb
@@ -8,7 +8,7 @@ require_relative 'visibility_tests'
class TestFileUtilsVerbose < Test::Unit::TestCase
include FileUtils::Verbose
- include TestFileUtilsInc::Visibility
+ include TestFileUtilsIncVisibility
def setup
super
diff --git a/test/fileutils/visibility_tests.rb b/test/fileutils/visibility_tests.rb
index 4c02c9d207..9f8f8dc9e1 100644
--- a/test/fileutils/visibility_tests.rb
+++ b/test/fileutils/visibility_tests.rb
@@ -2,14 +2,11 @@
require 'test/unit'
require 'fileutils'
-class TestFileUtilsInc < Test::Unit::TestCase
-end
-
##
# These tests are reused in the FileUtils::Verbose, FileUtils::NoWrite and
# FileUtils::DryRun tests
-module TestFileUtilsInc::Visibility
+module TestFileUtilsIncVisibility
FileUtils::METHODS.each do |m|
define_method "test_singleton_visibility_#{m}" do
diff --git a/test/io/console/test_io_console.rb b/test/io/console/test_io_console.rb
index 3d12b1f463..0a113ebd2f 100644
--- a/test/io/console/test_io_console.rb
+++ b/test/io/console/test_io_console.rb
@@ -7,8 +7,15 @@ rescue LoadError
end
class TestIO_Console < Test::Unit::TestCase
- PATHS = $LOADED_FEATURES.grep(%r"/io/console(?:\.#{RbConfig::CONFIG['DLEXT']}|\.rb|/\w+\.rb)\z") {$`}
+ begin
+ PATHS = $LOADED_FEATURES.grep(%r"/io/console(?:\.#{RbConfig::CONFIG['DLEXT']}|\.rb|/\w+\.rb)\z") {$`}
+ rescue Encoding::CompatibilityError
+ $stderr.puts "test_io_console.rb debug"
+ $LOADED_FEATURES.each{|path| $stderr.puts [path, path.encoding].inspect}
+ raise
+ end
PATHS.uniq!
+ INCLUDE_OPTS = "-I#{PATHS.join(File::PATH_SEPARATOR)}"
# FreeBSD seems to hang on TTOU when running parallel tests
# tested on FreeBSD 11.x.
@@ -30,18 +37,27 @@ class TestIO_Console < Test::Unit::TestCase
trap(:TTOU, @old_ttou) if defined?(@old_ttou) and @old_ttou
end
+ exceptions = %w[ENODEV ENOTTY EBADF ENXIO].map {|e|
+ Errno.const_get(e) if Errno.const_defined?(e)
+ }
+ exceptions.compact!
+ FailedPathExceptions = (exceptions unless exceptions.empty?)
+
def test_failed_path
- exceptions = %w[ENODEV ENOTTY EBADF ENXIO].map {|e|
- Errno.const_get(e) if Errno.const_defined?(e)
- }
- exceptions.compact!
- omit if exceptions.empty?
File.open(IO::NULL) do |f|
- e = assert_raise(*exceptions) do
+ e = assert_raise(*FailedPathExceptions) do
f.echo?
end
assert_include(e.message, IO::NULL)
end
+ end if FailedPathExceptions
+
+ def test_bad_keyword
+ assert_raise_with_message(ArgumentError, /unknown keyword:.*bad/) do
+ File.open(IO::NULL) do |f|
+ f.raw(bad: 0)
+ end
+ end
end
end
@@ -226,7 +242,6 @@ defined?(PTY) and defined?(IO.console) and TestIO_Console.class_eval do
end
def test_getpass
- omit unless IO.method_defined?("getpass")
run_pty("p IO.console.getpass('> ')") do |r, w|
assert_equal("> ", r.readpartial(10))
sleep 0.1
@@ -244,6 +259,15 @@ defined?(PTY) and defined?(IO.console) and TestIO_Console.class_eval do
assert_equal("\r\n", r.gets)
assert_equal("\"asdf\"", r.gets.chomp)
end
+
+ run_pty("$VERBOSE, $/ = nil, '.'; p IO.console.getpass('> ')") do |r, w|
+ assert_equal("> ", r.readpartial(10))
+ sleep 0.1
+ w.print "asdf\n"
+ sleep 0.1
+ assert_equal("\r\n", r.gets)
+ assert_equal("\"asdf\"", r.gets.chomp)
+ end
end
def test_iflush
@@ -351,6 +375,15 @@ defined?(PTY) and defined?(IO.console) and TestIO_Console.class_eval do
end
def test_intr
+ # This test fails randomly on FreeBSD 13
+ # http://rubyci.s3.amazonaws.com/freebsd13/ruby-master/log/20220304T163001Z.fail.html.gz
+ #
+ # 1) Failure:
+ # TestIO_Console#test_intr [/usr/home/chkbuild/chkbuild/tmp/build/20220304T163001Z/ruby/test/io/console/test_io_console.rb:387]:
+ # <"25"> expected but was
+ # <"-e:12:in `p': \e[1mexecution expired (\e[1;4mTimeout::Error\e[m\e[1m)\e[m">.
+ omit if /freebsd/ =~ RUBY_PLATFORM
+
run_pty("#{<<~"begin;"}\n#{<<~'end;'}") do |r, w, _|
begin;
require 'timeout'
@@ -375,7 +408,7 @@ defined?(PTY) and defined?(IO.console) and TestIO_Console.class_eval do
if cc = ctrl["intr"]
assert_ctrl("#{cc.ord}", cc, r, w)
assert_ctrl("#{cc.ord}", cc, r, w)
- assert_ctrl("Interrupt", cc, r, w) unless /linux/ =~ RUBY_PLATFORM
+ assert_ctrl("Interrupt", cc, r, w) unless /linux|solaris/ =~ RUBY_PLATFORM
end
if cc = ctrl["dsusp"]
assert_ctrl("#{cc.ord}", cc, r, w)
@@ -401,6 +434,10 @@ defined?(PTY) and defined?(IO.console) and TestIO_Console.class_eval do
assert_equal(["true"], run_pty("IO.console(:close); p IO.console(:tty?)"))
end
+ def test_console_kw
+ assert_equal(["File"], run_pty("IO.console.close; p IO.console(:clone, freeze: true).class"))
+ end
+
def test_sync
assert_equal(["true"], run_pty("p IO.console.sync"))
end
@@ -421,7 +458,9 @@ defined?(PTY) and defined?(IO.console) and TestIO_Console.class_eval do
def run_pty(src, n = 1)
pend("PTY.spawn cannot control terminal on JRuby") if RUBY_ENGINE == 'jruby'
- r, w, pid = PTY.spawn(EnvUtil.rubybin, "-I#{TestIO_Console::PATHS.join(File::PATH_SEPARATOR)}", "-rio/console", "-e", src)
+ args = [TestIO_Console::INCLUDE_OPTS, "-rio/console", "-e", src]
+ args.shift if args.first == "-I" # statically linked
+ r, w, pid = PTY.spawn(EnvUtil.rubybin, *args)
rescue RuntimeError
omit $!
else
@@ -477,6 +516,12 @@ defined?(IO.console) and TestIO_Console.class_eval do
IO.console(:close)
end
+ def test_console_kw
+ io = IO.console(:clone, freeze: true)
+ io.close
+ assert_kind_of(IO, io)
+ end
+
def test_sync
assert(IO.console.sync, "console should be unbuffered")
ensure
@@ -507,6 +552,7 @@ defined?(IO.console) and TestIO_Console.class_eval do
t2 = Tempfile.new("noctty_run")
t2.close
cmd = [*NOCTTY[1..-1],
+ TestIO_Console::INCLUDE_OPTS,
'-e', 'open(ARGV[0], "w") {|f|',
'-e', 'STDOUT.reopen(f)',
'-e', 'STDERR.reopen(f)',
diff --git a/test/io/console/test_ractor.rb b/test/io/console/test_ractor.rb
new file mode 100644
index 0000000000..b30988f47e
--- /dev/null
+++ b/test/io/console/test_ractor.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+require 'test/unit'
+require 'rbconfig'
+
+class TestIOConsoleInRactor < Test::Unit::TestCase
+ def test_ractor
+ ext = "/io/console.#{RbConfig::CONFIG['DLEXT']}"
+ path = $".find {|path| path.end_with?(ext)}
+ assert_in_out_err(%W[-r#{path}], "#{<<~"begin;"}\n#{<<~'end;'}", ["true"], [])
+ begin;
+ $VERBOSE = nil
+ r = Ractor.new do
+ $stdout.console_mode
+ rescue SystemCallError
+ true
+ rescue Ractor::UnsafeError
+ false
+ else
+ true # should not success
+ end
+ puts r.take
+ end;
+
+ assert_in_out_err(%W[-r#{path}], "#{<<~"begin;"}\n#{<<~'end;'}", ["true"], [])
+ begin;
+ console = IO.console
+ $VERBOSE = nil
+ r = Ractor.new do
+ IO.console
+ end
+ puts console.class == r.take.class
+ end;
+ end
+end if defined? Ractor
diff --git a/test/io/nonblock/test_flush.rb b/test/io/nonblock/test_flush.rb
index 08d129de3f..447d761f18 100644
--- a/test/io/nonblock/test_flush.rb
+++ b/test/io/nonblock/test_flush.rb
@@ -15,7 +15,7 @@ class TestIONonblock < Test::Unit::TestCase
Socket.pair(:INET, :STREAM) {|s1, s2|
return if flush_test(s1, s2)
}
- skip "nonblocking IO did not work"
+ omit "nonblocking IO did not work"
end
def flush_test(r, w)
diff --git a/test/io/wait/test_io_wait.rb b/test/io/wait/test_io_wait.rb
index 6b4722e1be..cbc01f9622 100644
--- a/test/io/wait/test_io_wait.rb
+++ b/test/io/wait/test_io_wait.rb
@@ -3,10 +3,9 @@
require 'test/unit'
require 'timeout'
require 'socket'
-begin
- require 'io/wait'
-rescue LoadError
-end
+
+# For `IO#ready?` and `IO#nread`:
+require 'io/wait'
class TestIOWait < Test::Unit::TestCase
@@ -37,6 +36,7 @@ class TestIOWait < Test::Unit::TestCase
end
def test_ready?
+ omit 'unstable on MinGW' if /mingw/ =~ RUBY_PLATFORM
assert_not_predicate @r, :ready?, "shouldn't ready, but ready"
@w.syswrite "."
sleep 0.1
@@ -50,6 +50,7 @@ class TestIOWait < Test::Unit::TestCase
end
def test_wait
+ omit 'unstable on MinGW' if /mingw/ =~ RUBY_PLATFORM
assert_nil @r.wait(0)
@w.syswrite "."
sleep 0.1
@@ -161,6 +162,34 @@ class TestIOWait < Test::Unit::TestCase
assert_equal @w, @w.wait(0.01, :read_write)
end
+ def test_wait_mask_writable
+ omit("Missing IO::WRITABLE!") unless IO.const_defined?(:WRITABLE)
+ assert_equal IO::WRITABLE, @w.wait(IO::WRITABLE, 0)
+ end
+
+ def test_wait_mask_readable
+ omit("Missing IO::READABLE!") unless IO.const_defined?(:READABLE)
+ @w.write("Hello World\n" * 3)
+ assert_equal IO::READABLE, @r.wait(IO::READABLE, 0)
+
+ @r.gets
+ assert_equal IO::READABLE, @r.wait(IO::READABLE, 0)
+ end
+
+ def test_wait_mask_zero
+ omit("Missing IO::WRITABLE!") unless IO.const_defined?(:WRITABLE)
+ assert_raise(ArgumentError) do
+ @w.wait(0, 0)
+ end
+ end
+
+ def test_wait_mask_negative
+ omit("Missing IO::WRITABLE!") unless IO.const_defined?(:WRITABLE)
+ assert_raise(ArgumentError) do
+ @w.wait(-6, 0)
+ end
+ end
+
private
def fill_pipe
diff --git a/test/io/wait/test_io_wait_uncommon.rb b/test/io/wait/test_io_wait_uncommon.rb
index b6f1c29bcd..0f922f4e24 100644
--- a/test/io/wait/test_io_wait_uncommon.rb
+++ b/test/io/wait/test_io_wait_uncommon.rb
@@ -1,6 +1,5 @@
# frozen_string_literal: true
require 'test/unit'
-require 'io/wait'
# test uncommon device types to check portability problems
# We may optimize IO#wait_*able for non-Linux kernels in the future
@@ -13,7 +12,7 @@ class TestIOWaitUncommon < Test::Unit::TestCase
end
def test_fifo_wait
- skip 'no mkfifo' unless File.respond_to?(:mkfifo) && IO.const_defined?(:NONBLOCK)
+ omit 'no mkfifo' unless File.respond_to?(:mkfifo) && IO.const_defined?(:NONBLOCK)
require 'tmpdir'
Dir.mktmpdir('rubytest-fifo') do |dir|
fifo = "#{dir}/fifo"
@@ -45,7 +44,7 @@ class TestIOWaitUncommon < Test::Unit::TestCase
rescue Errno::ENOENT
return # Ignore silently
rescue SystemCallError => e
- skip "#{dev} could not be opened #{e.message} (#{e.class})"
+ omit "#{dev} could not be opened #{e.message} (#{e.class})"
end
if block
yield fp
diff --git a/test/io/wait/test_ractor.rb b/test/io/wait/test_ractor.rb
index 3d286af77f..800216e610 100644
--- a/test/io/wait/test_ractor.rb
+++ b/test/io/wait/test_ractor.rb
@@ -1,13 +1,8 @@
# frozen_string_literal: true
require 'test/unit'
require 'rbconfig'
-require 'io/wait'
class TestIOWaitInRactor < Test::Unit::TestCase
- def setup
- omit unless defined? Ractor
- end
-
def test_ractor
ext = "/io/wait.#{RbConfig::CONFIG['DLEXT']}"
path = $".find {|path| path.end_with?(ext)}
@@ -19,4 +14,4 @@ class TestIOWaitInRactor < Test::Unit::TestCase
puts r.take
end;
end
-end
+end if defined? Ractor
diff --git a/test/irb/command/test_cd.rb b/test/irb/command/test_cd.rb
new file mode 100644
index 0000000000..4537286f73
--- /dev/null
+++ b/test/irb/command/test_cd.rb
@@ -0,0 +1,65 @@
+require "tempfile"
+require_relative "../helper"
+
+module TestIRB
+ class CDTest < IntegrationTestCase
+ def setup
+ super
+
+ write_ruby <<~'RUBY'
+ class Foo
+ class Bar
+ def bar
+ "this is bar"
+ end
+ end
+
+ def foo
+ "this is foo"
+ end
+ end
+
+ binding.irb
+ RUBY
+ end
+
+ def test_cd
+ out = run_ruby_file do
+ type "cd Foo"
+ type "ls"
+ type "cd Bar"
+ type "ls"
+ type "cd .."
+ type "exit"
+ end
+
+ assert_match(/irb\(Foo\):002>/, out)
+ assert_match(/Foo#methods: foo/, out)
+ assert_match(/irb\(Foo::Bar\):004>/, out)
+ assert_match(/Bar#methods: bar/, out)
+ assert_match(/irb\(Foo\):006>/, out)
+ end
+
+ def test_cd_moves_top_level_with_no_args
+ out = run_ruby_file do
+ type "cd Foo"
+ type "cd Bar"
+ type "cd"
+ type "exit"
+ end
+
+ assert_match(/irb\(Foo::Bar\):003>/, out)
+ assert_match(/irb\(main\):004>/, out)
+ end
+
+ def test_cd_with_error
+ out = run_ruby_file do
+ type "cd Baz"
+ type "exit"
+ end
+
+ assert_match(/Error: uninitialized constant Baz/, out)
+ assert_match(/irb\(main\):002>/, out) # the context should not change
+ end
+ end
+end
diff --git a/test/irb/command/test_custom_command.rb b/test/irb/command/test_custom_command.rb
new file mode 100644
index 0000000000..13f412c210
--- /dev/null
+++ b/test/irb/command/test_custom_command.rb
@@ -0,0 +1,194 @@
+# frozen_string_literal: true
+require "irb"
+
+require_relative "../helper"
+
+module TestIRB
+ class CustomCommandIntegrationTest < TestIRB::IntegrationTestCase
+ def test_command_registration_can_happen_after_irb_require
+ write_ruby <<~RUBY
+ require "irb"
+ require "irb/command"
+
+ class PrintCommand < IRB::Command::Base
+ category 'CommandTest'
+ description 'print_command'
+ def execute(*)
+ puts "Hello from PrintCommand"
+ end
+ end
+
+ IRB::Command.register(:print!, PrintCommand)
+
+ binding.irb
+ RUBY
+
+ output = run_ruby_file do
+ type "print!"
+ type "exit"
+ end
+
+ assert_include(output, "Hello from PrintCommand")
+ end
+
+ def test_command_registration_accepts_string_too
+ write_ruby <<~RUBY
+ require "irb/command"
+
+ class PrintCommand < IRB::Command::Base
+ category 'CommandTest'
+ description 'print_command'
+ def execute(*)
+ puts "Hello from PrintCommand"
+ end
+ end
+
+ IRB::Command.register("print!", PrintCommand)
+
+ binding.irb
+ RUBY
+
+ output = run_ruby_file do
+ type "print!"
+ type "exit"
+ end
+
+ assert_include(output, "Hello from PrintCommand")
+ end
+
+ def test_arguments_propagation
+ write_ruby <<~RUBY
+ require "irb/command"
+
+ class PrintArgCommand < IRB::Command::Base
+ category 'CommandTest'
+ description 'print_command_arg'
+ def execute(arg)
+ $nth_execution ||= 0
+ puts "\#{$nth_execution} arg=\#{arg.inspect}"
+ $nth_execution += 1
+ end
+ end
+
+ IRB::Command.register(:print_arg, PrintArgCommand)
+
+ binding.irb
+ RUBY
+
+ output = run_ruby_file do
+ type "print_arg"
+ type "print_arg \n"
+ type "print_arg a r g"
+ type "print_arg a r g \n"
+ type "exit"
+ end
+
+ assert_include(output, "0 arg=\"\"")
+ assert_include(output, "1 arg=\"\"")
+ assert_include(output, "2 arg=\"a r g\"")
+ assert_include(output, "3 arg=\"a r g\"")
+ end
+
+ def test_def_extend_command_still_works
+ write_ruby <<~RUBY
+ require "irb"
+
+ class FooBarCommand < IRB::Command::Base
+ category 'FooBarCategory'
+ description 'foobar_description'
+ def execute(*)
+ $nth_execution ||= 1
+ puts "\#{$nth_execution} FooBar executed"
+ $nth_execution += 1
+ end
+ end
+
+ IRB::ExtendCommandBundle.def_extend_command(:foobar, FooBarCommand, nil, [:fbalias, IRB::Command::OVERRIDE_ALL])
+
+ binding.irb
+ RUBY
+
+ output = run_ruby_file do
+ type "foobar"
+ type "fbalias"
+ type "help foobar"
+ type "exit"
+ end
+
+ assert_include(output, "1 FooBar executed")
+ assert_include(output, "2 FooBar executed")
+ assert_include(output, "foobar_description")
+ end
+
+ def test_no_meta_command_also_works
+ write_ruby <<~RUBY
+ require "irb/command"
+
+ class NoMetaCommand < IRB::Command::Base
+ def execute(*)
+ puts "This command does not override meta attributes"
+ end
+ end
+
+ IRB::Command.register(:no_meta, NoMetaCommand)
+
+ binding.irb
+ RUBY
+
+ output = run_ruby_file do
+ type "no_meta"
+ type "help no_meta"
+ type "exit"
+ end
+
+ assert_include(output, "This command does not override meta attributes")
+ assert_include(output, "No description provided.")
+ assert_not_include(output, "Maybe IRB bug")
+ end
+
+ def test_command_name_local_variable
+ write_ruby <<~RUBY
+ require "irb/command"
+
+ class FooBarCommand < IRB::Command::Base
+ category 'CommandTest'
+ description 'test'
+ def execute(arg)
+ puts "arg=\#{arg.inspect}"
+ end
+ end
+
+ IRB::Command.register(:foo_bar, FooBarCommand)
+
+ binding.irb
+ RUBY
+
+ output = run_ruby_file do
+ type "binding.irb"
+ type "foo_bar == 1 || 1"
+ type "foo_bar =~ /2/ || 2"
+ type "exit"
+ type "binding.irb"
+ type "foo_bar = '3'; foo_bar"
+ type "foo_bar == 4 || '4'"
+ type "foo_bar =~ /5/ || '5'"
+ type "exit"
+ type "binding.irb"
+ type "foo_bar ||= '6'; foo_bar"
+ type "foo_bar == 7 || '7'"
+ type "foo_bar =~ /8/ || '8'"
+ type "exit"
+ type "exit"
+ end
+
+ assert_include(output, 'arg="== 1 || 1"')
+ assert_include(output, 'arg="=~ /2/ || 2"')
+ assert_include(output, '=> "3"')
+ assert_include(output, '=> "4"')
+ assert_include(output, '=> "5"')
+ assert_include(output, '=> "6"')
+ assert_include(output, '=> "7"')
+ assert_include(output, '=> "8"')
+ end
+ end
+end
diff --git a/test/irb/command/test_disable_irb.rb b/test/irb/command/test_disable_irb.rb
new file mode 100644
index 0000000000..14a20043d5
--- /dev/null
+++ b/test/irb/command/test_disable_irb.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: false
+require 'irb'
+
+require_relative "../helper"
+
+module TestIRB
+ class DisableIRBTest < IntegrationTestCase
+ def test_disable_irb_disable_further_irb_breakpoints
+ write_ruby <<~'ruby'
+ puts "First line"
+ puts "Second line"
+ binding.irb
+ puts "Third line"
+ binding.irb
+ puts "Fourth line"
+ ruby
+
+ output = run_ruby_file do
+ type "disable_irb"
+ end
+
+ assert_match(/First line\r\n/, output)
+ assert_match(/Second line\r\n/, output)
+ assert_match(/Third line\r\n/, output)
+ assert_match(/Fourth line\r\n/, output)
+ end
+ end
+end
diff --git a/test/irb/command/test_force_exit.rb b/test/irb/command/test_force_exit.rb
new file mode 100644
index 0000000000..191a786872
--- /dev/null
+++ b/test/irb/command/test_force_exit.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: false
+require 'irb'
+
+require_relative "../helper"
+
+module TestIRB
+ class ForceExitTest < IntegrationTestCase
+ def test_forced_exit_finishes_process_immediately
+ write_ruby <<~'ruby'
+ puts "First line"
+ puts "Second line"
+ binding.irb
+ puts "Third line"
+ binding.irb
+ puts "Fourth line"
+ ruby
+
+ output = run_ruby_file do
+ type "123"
+ type "456"
+ type "exit!"
+ end
+
+ assert_match(/First line\r\n/, output)
+ assert_match(/Second line\r\n/, output)
+ assert_match(/irb\(main\):001> 123/, output)
+ assert_match(/irb\(main\):002> 456/, output)
+ refute_match(/Third line\r\n/, output)
+ refute_match(/Fourth line\r\n/, output)
+ end
+
+ def test_forced_exit_in_nested_sessions
+ write_ruby <<~'ruby'
+ def foo
+ binding.irb
+ end
+
+ binding.irb
+ binding.irb
+ ruby
+
+ output = run_ruby_file do
+ type "123"
+ type "foo"
+ type "exit!"
+ end
+
+ assert_match(/irb\(main\):001> 123/, output)
+ end
+ end
+end
diff --git a/test/irb/command/test_help.rb b/test/irb/command/test_help.rb
new file mode 100644
index 0000000000..b34832b022
--- /dev/null
+++ b/test/irb/command/test_help.rb
@@ -0,0 +1,75 @@
+require "tempfile"
+require_relative "../helper"
+
+module TestIRB
+ class HelpTest < IntegrationTestCase
+ def setup
+ super
+
+ write_rc <<~'RUBY'
+ IRB.conf[:USE_PAGER] = false
+ RUBY
+
+ write_ruby <<~'RUBY'
+ binding.irb
+ RUBY
+ end
+
+ def test_help
+ out = run_ruby_file do
+ type "help"
+ type "exit"
+ end
+
+ assert_match(/List all available commands/, out)
+ assert_match(/Start the debugger of debug\.gem/, out)
+ end
+
+ def test_command_help
+ out = run_ruby_file do
+ type "help ls"
+ type "exit"
+ end
+
+ assert_match(/Usage: ls \[obj\]/, out)
+ end
+
+ def test_command_help_not_found
+ out = run_ruby_file do
+ type "help foo"
+ type "exit"
+ end
+
+ assert_match(/Can't find command `foo`\. Please check the command name and try again\./, out)
+ end
+
+ def test_show_cmds
+ out = run_ruby_file do
+ type "help"
+ type "exit"
+ end
+
+ assert_match(/List all available commands/, out)
+ assert_match(/Start the debugger of debug\.gem/, out)
+ end
+
+ def test_help_lists_user_aliases
+ out = run_ruby_file do
+ type "help"
+ type "exit"
+ end
+
+ assert_match(/\$\s+Alias for `show_source`/, out)
+ assert_match(/@\s+Alias for `whereami`/, out)
+ end
+
+ def test_help_lists_helper_methods
+ out = run_ruby_file do
+ type "help"
+ type "exit"
+ end
+
+ assert_match(/Helper methods\s+conf\s+Returns the current IRB context/, out)
+ end
+ end
+end
diff --git a/test/irb/command/test_multi_irb_commands.rb b/test/irb/command/test_multi_irb_commands.rb
new file mode 100644
index 0000000000..e313c0c5d2
--- /dev/null
+++ b/test/irb/command/test_multi_irb_commands.rb
@@ -0,0 +1,50 @@
+require "tempfile"
+require_relative "../helper"
+
+module TestIRB
+ class MultiIRBTest < IntegrationTestCase
+ def setup
+ super
+
+ write_ruby <<~'RUBY'
+ binding.irb
+ RUBY
+ end
+
+ def test_jobs_command_with_print_deprecated_warning
+ out = run_ruby_file do
+ type "jobs"
+ type "exit"
+ end
+
+ assert_match(/Multi-irb commands are deprecated and will be removed in IRB 2\.0\.0\. Please use workspace commands instead\./, out)
+ assert_match(%r|If you have any use case for multi-irb, please leave a comment at https://github.com/ruby/irb/issues/653|, out)
+ assert_match(/#0->irb on main \(#<Thread:0x.+ run>: running\)/, out)
+ end
+
+ def test_irb_jobs_and_kill_commands
+ out = run_ruby_file do
+ type "irb"
+ type "jobs"
+ type "kill 1"
+ type "exit"
+ end
+
+ assert_match(/#0->irb on main \(#<Thread:0x.+ sleep_forever>: stop\)/, out)
+ assert_match(/#1->irb#1 on main \(#<Thread:0x.+ run>: running\)/, out)
+ end
+
+ def test_irb_fg_jobs_and_kill_commands
+ out = run_ruby_file do
+ type "irb"
+ type "fg 0"
+ type "jobs"
+ type "kill 1"
+ type "exit"
+ end
+
+ assert_match(/#0->irb on main \(#<Thread:0x.+ run>: running\)/, out)
+ assert_match(/#1->irb#1 on main \(#<Thread:0x.+ sleep_forever>: stop\)/, out)
+ end
+ end
+end
diff --git a/test/irb/command/test_show_source.rb b/test/irb/command/test_show_source.rb
new file mode 100644
index 0000000000..d014c78fc4
--- /dev/null
+++ b/test/irb/command/test_show_source.rb
@@ -0,0 +1,397 @@
+# frozen_string_literal: false
+require 'irb'
+
+require_relative "../helper"
+
+module TestIRB
+ class ShowSourceTest < IntegrationTestCase
+ def setup
+ super
+
+ write_rc <<~'RUBY'
+ IRB.conf[:USE_PAGER] = false
+ RUBY
+ end
+
+ def test_show_source
+ write_ruby <<~'RUBY'
+ binding.irb
+ RUBY
+
+ out = run_ruby_file do
+ type "show_source IRB.conf"
+ type "exit"
+ end
+
+ assert_match(%r[/irb\/init\.rb], out)
+ end
+
+ def test_show_source_alias
+ write_ruby <<~'RUBY'
+ binding.irb
+ RUBY
+
+ out = run_ruby_file do
+ type "$ IRB.conf"
+ type "exit"
+ end
+
+ assert_match(%r[/irb\/init\.rb], out)
+ end
+
+ def test_show_source_with_missing_signature
+ write_ruby <<~'RUBY'
+ binding.irb
+ RUBY
+
+ out = run_ruby_file do
+ type "show_source foo"
+ type "exit"
+ end
+
+ assert_match(%r[Couldn't locate a definition for foo], out)
+ end
+
+ def test_show_source_with_missing_constant
+ write_ruby <<~'RUBY'
+ binding.irb
+ RUBY
+
+ out = run_ruby_file do
+ type "show_source Foo"
+ type "exit"
+ end
+
+ assert_match(%r[Couldn't locate a definition for Foo], out)
+ end
+
+ def test_show_source_string
+ write_ruby <<~'RUBY'
+ binding.irb
+ RUBY
+
+ out = run_ruby_file do
+ type "show_source 'IRB.conf'"
+ type "exit"
+ end
+
+ assert_match(%r[/irb\/init\.rb], out)
+ end
+
+ def test_show_source_method_s
+ write_ruby <<~RUBY
+ class Baz
+ def foo
+ end
+ end
+
+ class Bar < Baz
+ def foo
+ super
+ end
+ end
+
+ binding.irb
+ RUBY
+
+ out = run_ruby_file do
+ type "show_source Bar#foo -s"
+ type "exit"
+ end
+
+ assert_match(%r[#{@ruby_file.to_path}:2\s+def foo\r\n end\r\n], out)
+ end
+
+ def test_show_source_method_s_with_incorrect_signature
+ write_ruby <<~RUBY
+ class Baz
+ def foo
+ end
+ end
+
+ class Bar < Baz
+ def foo
+ super
+ end
+ end
+
+ binding.irb
+ RUBY
+
+ out = run_ruby_file do
+ type "show_source Bar#fooo -s"
+ type "exit"
+ end
+
+ assert_match(%r[Error: Couldn't locate a super definition for Bar#fooo], out)
+ end
+
+ def test_show_source_private_method
+ write_ruby <<~RUBY
+ class Bar
+ private def foo
+ end
+ end
+ binding.irb
+ RUBY
+
+ out = run_ruby_file do
+ type "show_source Bar#foo"
+ type "exit"
+ end
+
+ assert_match(%r[#{@ruby_file.to_path}:2\s+private def foo\r\n end\r\n], out)
+ end
+
+ def test_show_source_private_singleton_method
+ write_ruby <<~RUBY
+ class Bar
+ private def foo
+ end
+ end
+ binding.irb
+ RUBY
+
+ out = run_ruby_file do
+ type "bar = Bar.new"
+ type "show_source bar.foo"
+ type "exit"
+ end
+
+ assert_match(%r[#{@ruby_file.to_path}:2\s+private def foo\r\n end\r\n], out)
+ end
+
+ def test_show_source_method_multiple_s
+ write_ruby <<~RUBY
+ class Baz
+ def foo
+ end
+ end
+
+ class Bar < Baz
+ def foo
+ super
+ end
+ end
+
+ class Bob < Bar
+ def foo
+ super
+ end
+ end
+
+ binding.irb
+ RUBY
+
+ out = run_ruby_file do
+ type "show_source Bob#foo -ss"
+ type "exit"
+ end
+
+ assert_match(%r[#{@ruby_file.to_path}:2\s+def foo\r\n end\r\n], out)
+ end
+
+ def test_show_source_method_no_instance_method
+ write_ruby <<~RUBY
+ class Baz
+ end
+
+ class Bar < Baz
+ def foo
+ super
+ end
+ end
+
+ binding.irb
+ RUBY
+
+ out = run_ruby_file do
+ type "show_source Bar#foo -s"
+ type "exit"
+ end
+
+ assert_match(%r[Error: Couldn't locate a super definition for Bar#foo], out)
+ end
+
+ def test_show_source_method_exceeds_super_chain
+ write_ruby <<~RUBY
+ class Baz
+ def foo
+ end
+ end
+
+ class Bar < Baz
+ def foo
+ super
+ end
+ end
+
+ binding.irb
+ RUBY
+
+ out = run_ruby_file do
+ type "show_source Bar#foo -ss"
+ type "exit"
+ end
+
+ assert_match(%r[Error: Couldn't locate a super definition for Bar#foo], out)
+ end
+
+ def test_show_source_method_accidental_characters
+ write_ruby <<~'RUBY'
+ class Baz
+ def foo
+ end
+ end
+
+ class Bar < Baz
+ def foo
+ super
+ end
+ end
+
+ binding.irb
+ RUBY
+
+ out = run_ruby_file do
+ type "show_source Bar#foo -sddddd"
+ type "exit"
+ end
+
+ assert_match(%r[#{@ruby_file.to_path}:2\s+def foo\r\n end], out)
+ end
+
+ def test_show_source_receiver_super
+ write_ruby <<~RUBY
+ class Baz
+ def foo
+ end
+ end
+
+ class Bar < Baz
+ def foo
+ super
+ end
+ end
+
+ binding.irb
+ RUBY
+
+ out = run_ruby_file do
+ type "bar = Bar.new"
+ type "show_source bar.foo -s"
+ type "exit"
+ end
+
+ assert_match(%r[#{@ruby_file.to_path}:2\s+def foo\r\n end], out)
+ end
+
+ def test_show_source_with_double_colons
+ write_ruby <<~RUBY
+ class Foo
+ end
+
+ class Foo
+ class Bar
+ end
+ end
+
+ binding.irb
+ RUBY
+
+ out = run_ruby_file do
+ type "show_source ::Foo"
+ type "exit"
+ end
+
+ assert_match(%r[#{@ruby_file.to_path}:1\s+class Foo\r\nend], out)
+
+ out = run_ruby_file do
+ type "show_source ::Foo::Bar"
+ type "exit"
+ end
+
+ assert_match(%r[#{@ruby_file.to_path}:5\s+class Bar\r\n end], out)
+ end
+
+ def test_show_source_keep_script_lines
+ pend unless defined?(RubyVM.keep_script_lines)
+
+ write_ruby <<~RUBY
+ binding.irb
+ RUBY
+
+ out = run_ruby_file do
+ type "def foo; end"
+ type "show_source foo"
+ type "exit"
+ end
+
+ assert_match(%r[#{@ruby_file.to_path}\(irb\):1\s+def foo; end], out)
+ end
+
+ def test_show_source_unavailable_source
+ write_ruby <<~RUBY
+ binding.irb
+ RUBY
+
+ out = run_ruby_file do
+ type "RubyVM.keep_script_lines = false if defined?(RubyVM.keep_script_lines)"
+ type "def foo; end"
+ type "show_source foo"
+ type "exit"
+ end
+ assert_match(%r[#{@ruby_file.to_path}\(irb\):2\s+Source not available], out)
+ end
+
+ def test_show_source_shows_binary_source
+ write_ruby <<~RUBY
+ # io-console is an indirect dependency of irb
+ require "io/console"
+
+ binding.irb
+ RUBY
+
+ out = run_ruby_file do
+ # IO::ConsoleMode is defined in io-console gem's C extension
+ type "show_source IO::ConsoleMode"
+ type "exit"
+ end
+
+ # A safeguard to make sure the test subject is actually defined
+ refute_match(/NameError/, out)
+ assert_match(%r[Defined in binary file:.+io/console], out)
+ end
+
+ def test_show_source_with_constant_lookup
+ write_ruby <<~RUBY
+ X = 1
+ module M
+ Y = 1
+ Z = 2
+ end
+ class A
+ Z = 1
+ Array = 1
+ class B
+ include M
+ Object.new.instance_eval { binding.irb }
+ end
+ end
+ RUBY
+
+ out = run_ruby_file do
+ type "show_source X"
+ type "show_source Y"
+ type "show_source Z"
+ type "show_source Array"
+ type "exit"
+ end
+
+ assert_match(%r[#{@ruby_file.to_path}:1\s+X = 1], out)
+ assert_match(%r[#{@ruby_file.to_path}:3\s+Y = 1], out)
+ assert_match(%r[#{@ruby_file.to_path}:7\s+Z = 1], out)
+ assert_match(%r[#{@ruby_file.to_path}:8\s+Array = 1], out)
+ end
+ end
+end
diff --git a/test/irb/helper.rb b/test/irb/helper.rb
new file mode 100644
index 0000000000..ea2c6ef16a
--- /dev/null
+++ b/test/irb/helper.rb
@@ -0,0 +1,234 @@
+require "test/unit"
+require "pathname"
+require "rubygems"
+
+begin
+ require_relative "../lib/helper"
+ require_relative "../lib/envutil"
+rescue LoadError # ruby/ruby defines helpers differently
+end
+
+begin
+ require "pty"
+rescue LoadError # some platforms don't support PTY
+end
+
+module IRB
+ class InputMethod; end
+end
+
+module TestIRB
+ RUBY_3_4 = Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("3.4.0.dev")
+ class TestCase < Test::Unit::TestCase
+ class TestInputMethod < ::IRB::InputMethod
+ attr_reader :list, :line_no
+
+ def initialize(list = [])
+ @line_no = 0
+ @list = list
+ end
+
+ def gets
+ @list[@line_no]&.tap {@line_no += 1}
+ end
+
+ def eof?
+ @line_no >= @list.size
+ end
+
+ def encoding
+ Encoding.default_external
+ end
+
+ def reset
+ @line_no = 0
+ end
+ end
+
+ def ruby_core?
+ !Pathname(__dir__).join("../../", "irb.gemspec").exist?
+ end
+
+ def setup_envs(home:)
+ @backup_home = ENV["HOME"]
+ ENV["HOME"] = home
+ @backup_xdg_config_home = ENV.delete("XDG_CONFIG_HOME")
+ @backup_irbrc = ENV.delete("IRBRC")
+ end
+
+ def teardown_envs
+ ENV["HOME"] = @backup_home
+ ENV["XDG_CONFIG_HOME"] = @backup_xdg_config_home
+ ENV["IRBRC"] = @backup_irbrc
+ end
+
+ def save_encodings
+ @default_encoding = [Encoding.default_external, Encoding.default_internal]
+ @stdio_encodings = [STDIN, STDOUT, STDERR].map {|io| [io.external_encoding, io.internal_encoding] }
+ end
+
+ def restore_encodings
+ EnvUtil.suppress_warning do
+ Encoding.default_external, Encoding.default_internal = *@default_encoding
+ [STDIN, STDOUT, STDERR].zip(@stdio_encodings) do |io, encs|
+ io.set_encoding(*encs)
+ end
+ end
+ end
+
+ def without_rdoc(&block)
+ ::Kernel.send(:alias_method, :irb_original_require, :require)
+
+ ::Kernel.define_method(:require) do |name|
+ raise LoadError, "cannot load such file -- rdoc (test)" if name.match?("rdoc") || name.match?(/^rdoc\/.*/)
+ ::Kernel.send(:irb_original_require, name)
+ end
+
+ yield
+ ensure
+ EnvUtil.suppress_warning {
+ ::Kernel.send(:alias_method, :require, :irb_original_require)
+ ::Kernel.undef_method :irb_original_require
+ }
+ end
+ end
+
+ class IntegrationTestCase < TestCase
+ LIB = File.expand_path("../../lib", __dir__)
+ TIMEOUT_SEC = 3
+
+ def setup
+ @envs = {}
+ @tmpfiles = []
+
+ unless defined?(PTY)
+ omit "Integration tests require PTY."
+ end
+
+ if ruby_core?
+ omit "This test works only under ruby/irb"
+ end
+
+ write_rc <<~RUBY
+ IRB.conf[:USE_PAGER] = false
+ RUBY
+ end
+
+ def teardown
+ @tmpfiles.each do |tmpfile|
+ File.unlink(tmpfile)
+ end
+ end
+
+ def run_ruby_file(&block)
+ cmd = [EnvUtil.rubybin, "-I", LIB, @ruby_file.to_path]
+ tmp_dir = Dir.mktmpdir
+
+ @commands = []
+ lines = []
+
+ yield
+
+ # Test should not depend on user's irbrc file
+ @envs["HOME"] ||= tmp_dir
+ @envs["XDG_CONFIG_HOME"] ||= tmp_dir
+ @envs["IRBRC"] = nil unless @envs.key?("IRBRC")
+
+ envs_for_spawn = @envs.merge('TERM' => 'dumb', 'TEST_IRB_FORCE_INTERACTIVE' => 'true')
+
+ PTY.spawn(envs_for_spawn, *cmd) do |read, write, pid|
+ Timeout.timeout(TIMEOUT_SEC) do
+ while line = safe_gets(read)
+ lines << line
+
+ # means the breakpoint is triggered
+ if line.match?(/binding\.irb/)
+ while command = @commands.shift
+ write.puts(command)
+ end
+ end
+ end
+ end
+ ensure
+ read.close
+ write.close
+ kill_safely(pid)
+ end
+
+ lines.join
+ rescue Timeout::Error
+ message = <<~MSG
+ Test timedout.
+
+ #{'=' * 30} OUTPUT #{'=' * 30}
+ #{lines.map { |l| " #{l}" }.join}
+ #{'=' * 27} END OF OUTPUT #{'=' * 27}
+ MSG
+ assert_block(message) { false }
+ ensure
+ FileUtils.remove_entry tmp_dir
+ end
+
+ # read.gets could raise exceptions on some platforms
+ # https://github.com/ruby/ruby/blob/master/ext/pty/pty.c#L721-L728
+ def safe_gets(read)
+ read.gets
+ rescue Errno::EIO
+ nil
+ end
+
+ def kill_safely pid
+ return if wait_pid pid, TIMEOUT_SEC
+
+ Process.kill :TERM, pid
+ return if wait_pid pid, 0.2
+
+ Process.kill :KILL, pid
+ Process.waitpid(pid)
+ rescue Errno::EPERM, Errno::ESRCH
+ end
+
+ def wait_pid pid, sec
+ total_sec = 0.0
+ wait_sec = 0.001 # 1ms
+
+ while total_sec < sec
+ if Process.waitpid(pid, Process::WNOHANG) == pid
+ return true
+ end
+ sleep wait_sec
+ total_sec += wait_sec
+ wait_sec *= 2
+ end
+
+ false
+ rescue Errno::ECHILD
+ true
+ end
+
+ def type(command)
+ @commands << command
+ end
+
+ def write_ruby(program)
+ @ruby_file = Tempfile.create(%w{irbtest- .rb})
+ @tmpfiles << @ruby_file
+ @ruby_file.write(program)
+ @ruby_file.close
+ end
+
+ def write_rc(content)
+ # Append irbrc content if a tempfile for it already exists
+ if @irbrc
+ @irbrc = File.open(@irbrc, "a")
+ else
+ @irbrc = Tempfile.new('irbrc')
+ @tmpfiles << @irbrc
+ end
+
+ @irbrc.write(content)
+ @irbrc.close
+ @envs['IRBRC'] = @irbrc.path
+ end
+ end
+end
diff --git a/test/irb/test_cmd.rb b/test/irb/test_cmd.rb
deleted file mode 100644
index e6bb587b5c..0000000000
--- a/test/irb/test_cmd.rb
+++ /dev/null
@@ -1,529 +0,0 @@
-# frozen_string_literal: false
-require "test/unit"
-require "irb"
-require "irb/extend-command"
-
-module TestIRB
- class ExtendCommand < Test::Unit::TestCase
- class TestInputMethod < ::IRB::InputMethod
- attr_reader :list, :line_no
-
- def initialize(list = [])
- super("test")
- @line_no = 0
- @list = list
- end
-
- def gets
- @list[@line_no]&.tap {@line_no += 1}
- end
-
- def eof?
- @line_no >= @list.size
- end
-
- def encoding
- Encoding.default_external
- end
-
- def reset
- @line_no = 0
- end
- end
-
- def setup
- @pwd = Dir.pwd
- @tmpdir = File.join(Dir.tmpdir, "test_reline_config_#{$$}")
- begin
- Dir.mkdir(@tmpdir)
- rescue Errno::EEXIST
- FileUtils.rm_rf(@tmpdir)
- Dir.mkdir(@tmpdir)
- end
- Dir.chdir(@tmpdir)
- @home_backup = ENV["HOME"]
- ENV["HOME"] = @tmpdir
- @xdg_config_home_backup = ENV.delete("XDG_CONFIG_HOME")
- @default_encoding = [Encoding.default_external, Encoding.default_internal]
- @stdio_encodings = [STDIN, STDOUT, STDERR].map {|io| [io.external_encoding, io.internal_encoding] }
- IRB.instance_variable_get(:@CONF).clear
- @is_win = (RbConfig::CONFIG['host_os'] =~ /mswin|msys|mingw|cygwin|bccwin|wince|emc/)
- end
-
- def teardown
- ENV["XDG_CONFIG_HOME"] = @xdg_config_home_backup
- ENV["HOME"] = @home_backup
- Dir.chdir(@pwd)
- FileUtils.rm_rf(@tmpdir)
- EnvUtil.suppress_warning {
- Encoding.default_external, Encoding.default_internal = *@default_encoding
- [STDIN, STDOUT, STDERR].zip(@stdio_encodings) do |io, encs|
- io.set_encoding(*encs)
- end
- }
- end
-
- def test_irb_info_multiline
- FileUtils.touch("#{@tmpdir}/.inputrc")
- FileUtils.touch("#{@tmpdir}/.irbrc")
- IRB.setup(__FILE__, argv: [])
- IRB.conf[:USE_MULTILINE] = true
- IRB.conf[:USE_SINGLELINE] = false
- IRB.conf[:VERBOSE] = false
- lang_backup = ENV.delete("LANG")
- lc_all_backup = ENV.delete("LC_ALL")
- workspace = IRB::WorkSpace.new(self)
- irb = IRB::Irb.new(workspace, TestInputMethod.new([]))
- IRB.conf[:MAIN_CONTEXT] = irb.context
- expected = %r{
- Ruby\sversion:\s.+\n
- IRB\sversion:\sirb\s.+\n
- InputMethod:\sAbstract\sInputMethod\n
- \.irbrc\spath:\s.+\n
- RUBY_PLATFORM:\s.+\n
- #{@is_win ? 'Code\spage:\s\d+\n' : ''}
- }x
- assert_match expected, irb.context.main.irb_info.to_s
- ensure
- ENV["LANG"] = lang_backup
- ENV["LC_ALL"] = lc_all_backup
- end
-
- def test_irb_info_singleline
- FileUtils.touch("#{@tmpdir}/.inputrc")
- FileUtils.touch("#{@tmpdir}/.irbrc")
- IRB.setup(__FILE__, argv: [])
- IRB.conf[:USE_MULTILINE] = false
- IRB.conf[:USE_SINGLELINE] = true
- IRB.conf[:VERBOSE] = false
- lang_backup = ENV.delete("LANG")
- lc_all_backup = ENV.delete("LC_ALL")
- workspace = IRB::WorkSpace.new(self)
- irb = IRB::Irb.new(workspace, TestInputMethod.new([]))
- IRB.conf[:MAIN_CONTEXT] = irb.context
- expected = %r{
- Ruby\sversion:\s.+\n
- IRB\sversion:\sirb\s.+\n
- InputMethod:\sAbstract\sInputMethod\n
- \.irbrc\spath:\s.+\n
- RUBY_PLATFORM:\s.+\n
- #{@is_win ? 'Code\spage:\s\d+\n' : ''}
- }x
- assert_match expected, irb.context.main.irb_info.to_s
- ensure
- ENV["LANG"] = lang_backup
- ENV["LC_ALL"] = lc_all_backup
- end
-
- def test_irb_info_multiline_without_rc_files
- inputrc_backup = ENV["INPUTRC"]
- ENV["INPUTRC"] = "unknown_inpurc"
- ext_backup = IRB::IRBRC_EXT
- IRB.__send__(:remove_const, :IRBRC_EXT)
- IRB.const_set(:IRBRC_EXT, "unknown_ext")
- IRB.setup(__FILE__, argv: [])
- IRB.conf[:USE_MULTILINE] = true
- IRB.conf[:USE_SINGLELINE] = false
- IRB.conf[:VERBOSE] = false
- lang_backup = ENV.delete("LANG")
- lc_all_backup = ENV.delete("LC_ALL")
- workspace = IRB::WorkSpace.new(self)
- irb = IRB::Irb.new(workspace, TestInputMethod.new([]))
- IRB.conf[:MAIN_CONTEXT] = irb.context
- expected = %r{
- Ruby\sversion:\s.+\n
- IRB\sversion:\sirb\s.+\n
- InputMethod:\sAbstract\sInputMethod\n
- RUBY_PLATFORM:\s.+\n
- #{@is_win ? 'Code\spage:\s\d+\n' : ''}
- \z
- }x
- assert_match expected, irb.context.main.irb_info.to_s
- ensure
- ENV["INPUTRC"] = inputrc_backup
- IRB.__send__(:remove_const, :IRBRC_EXT)
- IRB.const_set(:IRBRC_EXT, ext_backup)
- ENV["LANG"] = lang_backup
- ENV["LC_ALL"] = lc_all_backup
- end
-
- def test_irb_info_singleline_without_rc_files
- inputrc_backup = ENV["INPUTRC"]
- ENV["INPUTRC"] = "unknown_inpurc"
- ext_backup = IRB::IRBRC_EXT
- IRB.__send__(:remove_const, :IRBRC_EXT)
- IRB.const_set(:IRBRC_EXT, "unknown_ext")
- IRB.setup(__FILE__, argv: [])
- IRB.conf[:USE_MULTILINE] = false
- IRB.conf[:USE_SINGLELINE] = true
- IRB.conf[:VERBOSE] = false
- lang_backup = ENV.delete("LANG")
- lc_all_backup = ENV.delete("LC_ALL")
- workspace = IRB::WorkSpace.new(self)
- irb = IRB::Irb.new(workspace, TestInputMethod.new([]))
- IRB.conf[:MAIN_CONTEXT] = irb.context
- expected = %r{
- Ruby\sversion:\s.+\n
- IRB\sversion:\sirb\s.+\n
- InputMethod:\sAbstract\sInputMethod\n
- RUBY_PLATFORM:\s.+\n
- #{@is_win ? 'Code\spage:\s\d+\n' : ''}
- \z
- }x
- assert_match expected, irb.context.main.irb_info.to_s
- ensure
- ENV["INPUTRC"] = inputrc_backup
- IRB.__send__(:remove_const, :IRBRC_EXT)
- IRB.const_set(:IRBRC_EXT, ext_backup)
- ENV["LANG"] = lang_backup
- ENV["LC_ALL"] = lc_all_backup
- end
-
- def test_irb_info_lang
- FileUtils.touch("#{@tmpdir}/.inputrc")
- FileUtils.touch("#{@tmpdir}/.irbrc")
- IRB.setup(__FILE__, argv: [])
- IRB.conf[:USE_MULTILINE] = true
- IRB.conf[:USE_SINGLELINE] = false
- IRB.conf[:VERBOSE] = false
- lang_backup = ENV.delete("LANG")
- lc_all_backup = ENV.delete("LC_ALL")
- ENV["LANG"] = "ja_JP.UTF-8"
- ENV["LC_ALL"] = "en_US.UTF-8"
- workspace = IRB::WorkSpace.new(self)
- irb = IRB::Irb.new(workspace, TestInputMethod.new([]))
- IRB.conf[:MAIN_CONTEXT] = irb.context
- expected = %r{
- Ruby\sversion: .+\n
- IRB\sversion:\sirb .+\n
- InputMethod:\sAbstract\sInputMethod\n
- \.irbrc\spath: .+\n
- RUBY_PLATFORM: .+\n
- LANG\senv:\sja_JP\.UTF-8\n
- LC_ALL\s env:\sen_US\.UTF-8\n
- }x
- assert_match expected, irb.context.main.irb_info.to_s
- ensure
- ENV["LANG"] = lang_backup
- ENV["LC_ALL"] = lc_all_backup
- end
-
- def test_measure
- IRB.init_config(nil)
- IRB.conf[:PROMPT] = {
- DEFAULT: {
- PROMPT_I: '> ',
- PROMPT_S: '> ',
- PROMPT_C: '> ',
- PROMPT_N: '> '
- }
- }
- IRB.conf[:VERBOSE] = false
- IRB.conf[:PROMPT_MODE] = :DEFAULT
- IRB.conf[:MEASURE] = false
- input = TestInputMethod.new([
- "3\n",
- "measure\n",
- "3\n",
- "measure :off\n",
- "3\n",
- ])
- c = Class.new(Object)
- irb = IRB::Irb.new(IRB::WorkSpace.new(c.new), input)
- irb.context.return_format = "=> %s\n"
- out, err = capture_output do
- irb.eval_input
- end
- assert_empty err
- assert_match(/\A=> 3\nTIME is added\.\n=> nil\nprocessing time: .+\n=> 3\n=> nil\n=> 3\n/, out)
- assert_empty(c.class_variables)
- end
-
- def test_measure_enabled_by_rc
- IRB.init_config(nil)
- IRB.conf[:PROMPT] = {
- DEFAULT: {
- PROMPT_I: '> ',
- PROMPT_S: '> ',
- PROMPT_C: '> ',
- PROMPT_N: '> '
- }
- }
- IRB.conf[:VERBOSE] = false
- IRB.conf[:PROMPT_MODE] = :DEFAULT
- IRB.conf[:MEASURE] = true
- input = TestInputMethod.new([
- "3\n",
- "measure :off\n",
- "3\n",
- ])
- irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
- irb.context.return_format = "=> %s\n"
- out, err = capture_output do
- irb.eval_input
- end
- assert_empty err
- assert_match(/\Aprocessing time: .+\n=> 3\n=> nil\n=> 3\n/, out)
- end
-
- def test_measure_enabled_by_rc_with_custom
- IRB.init_config(nil)
- IRB.conf[:PROMPT] = {
- DEFAULT: {
- PROMPT_I: '> ',
- PROMPT_S: '> ',
- PROMPT_C: '> ',
- PROMPT_N: '> '
- }
- }
- IRB.conf[:VERBOSE] = false
- IRB.conf[:PROMPT_MODE] = :DEFAULT
- IRB.conf[:MEASURE] = true
- IRB.conf[:MEASURE_PROC][:CUSTOM] = proc { |line, line_no, &block|
- time = Time.now
- result = block.()
- puts 'custom processing time: %fs' % (Time.now - time) if IRB.conf[:MEASURE]
- result
- }
- input = TestInputMethod.new([
- "3\n",
- "measure :off\n",
- "3\n",
- ])
- irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
- irb.context.return_format = "=> %s\n"
- out, err = capture_output do
- irb.eval_input
- end
- assert_empty err
- assert_match(/\Acustom processing time: .+\n=> 3\n=> nil\n=> 3\n/, out)
- end
-
- def test_measure_with_custom
- IRB.init_config(nil)
- IRB.conf[:PROMPT] = {
- DEFAULT: {
- PROMPT_I: '> ',
- PROMPT_S: '> ',
- PROMPT_C: '> ',
- PROMPT_N: '> '
- }
- }
- IRB.conf[:VERBOSE] = false
- IRB.conf[:PROMPT_MODE] = :DEFAULT
- IRB.conf[:MEASURE] = false
- IRB.conf[:MEASURE_PROC][:CUSTOM] = proc { |line, line_no, &block|
- time = Time.now
- result = block.()
- puts 'custom processing time: %fs' % (Time.now - time) if IRB.conf[:MEASURE]
- result
- }
- input = TestInputMethod.new([
- "3\n",
- "measure\n",
- "3\n",
- "measure :off\n",
- "3\n",
- ])
- irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
- irb.context.return_format = "=> %s\n"
- out, err = capture_output do
- irb.eval_input
- end
- assert_empty err
- assert_match(/\A=> 3\nCUSTOM is added\.\n=> nil\ncustom processing time: .+\n=> 3\n=> nil\n=> 3\n/, out)
- end
-
- def test_measure_with_proc
- IRB.init_config(nil)
- IRB.conf[:PROMPT] = {
- DEFAULT: {
- PROMPT_I: '> ',
- PROMPT_S: '> ',
- PROMPT_C: '> ',
- PROMPT_N: '> '
- }
- }
- IRB.conf[:VERBOSE] = false
- IRB.conf[:PROMPT_MODE] = :DEFAULT
- IRB.conf[:MEASURE] = false
- input = TestInputMethod.new([
- "3\n",
- "measure { |context, code, line_no, &block|\n",
- " result = block.()\n",
- " puts 'aaa' if IRB.conf[:MEASURE]\n",
- " result\n",
- "}\n",
- "3\n",
- "measure { |context, code, line_no, &block|\n",
- " result = block.()\n",
- " puts 'bbb' if IRB.conf[:MEASURE]\n",
- " result\n",
- "}\n",
- "3\n",
- "measure :off\n",
- "3\n",
- ])
- c = Class.new(Object)
- irb = IRB::Irb.new(IRB::WorkSpace.new(c.new), input)
- irb.context.return_format = "=> %s\n"
- out, err = capture_output do
- irb.eval_input
- end
- assert_empty err
- assert_match(/\A=> 3\nBLOCK is added\.\n=> nil\naaa\n=> 3\nBLOCK is added.\naaa\n=> nil\nbbb\n=> 3\n=> nil\n=> 3\n/, out)
- assert_empty(c.class_variables)
- end
-
- def test_irb_source
- IRB.init_config(nil)
- File.write("#{@tmpdir}/a.rb", "a = 'hi'\n")
- input = TestInputMethod.new([
- "a = 'bug17564'\n",
- "a\n",
- "irb_source '#{@tmpdir}/a.rb'\n",
- "a\n",
- ])
- IRB.conf[:VERBOSE] = false
- IRB.conf[:PROMPT_MODE] = :SIMPLE
- irb = IRB::Irb.new(IRB::WorkSpace.new(self), input)
- IRB.conf[:MAIN_CONTEXT] = irb.context
- out, err = capture_output do
- irb.eval_input
- end
- assert_empty err
- assert_pattern_list([
- /=> "bug17564"\n/,
- /=> "bug17564"\n/,
- / => "hi"\n/,
- / => nil\n/,
- /=> "hi"\n/,
- ], out)
- end
-
- def test_irb_load
- IRB.init_config(nil)
- File.write("#{@tmpdir}/a.rb", "a = 'hi'\n")
- input = TestInputMethod.new([
- "a = 'bug17564'\n",
- "a\n",
- "irb_load '#{@tmpdir}/a.rb'\n",
- "a\n",
- ])
- IRB.conf[:VERBOSE] = false
- IRB.conf[:PROMPT_MODE] = :SIMPLE
- irb = IRB::Irb.new(IRB::WorkSpace.new(self), input)
- IRB.conf[:MAIN_CONTEXT] = irb.context
- out, err = capture_output do
- irb.eval_input
- end
- assert_empty err
- assert_pattern_list([
- /=> "bug17564"\n/,
- /=> "bug17564"\n/,
- / => "hi"\n/,
- / => nil\n/,
- /=> "bug17564"\n/,
- ], out)
- end
-
- def test_ls
- input = TestInputMethod.new([
- "class P\n",
- " def m() end\n",
- " def m2() end\n",
- "end\n",
-
- "class C < P\n",
- " def m1() end\n",
- " def m2() end\n",
- "end\n",
-
- "module M\n",
- " def m1() end\n",
- " def m3() end\n",
- "end\n",
-
- "module M2\n",
- " include M\n",
- " def m4() end\n",
- "end\n",
-
- "obj = C.new\n",
- "obj.instance_variable_set(:@a, 1)\n",
- "obj.extend M2\n",
- "def obj.m5() end\n",
- "ls obj\n",
- ])
- IRB.init_config(nil)
- workspace = IRB::WorkSpace.new(self)
- IRB.conf[:VERBOSE] = false
- irb = IRB::Irb.new(workspace, input)
- IRB.conf[:MAIN_CONTEXT] = irb.context
- irb.context.return_format = "=> %s\n"
- out, err = capture_output do
- irb.eval_input
- end
- assert_empty err
- assert_match(/^instance variables:\s+@a\n/m, out)
- assert_match(/P#methods:\s+m\n/m, out)
- assert_match(/C#methods:\s+m2\n/m, out)
- assert_match(/M#methods:\s+m1\s+m3\n/m, out)
- assert_match(/M2#methods:\s+m4\n/m, out)
- assert_match(/C.methods:\s+m5\n/m, out)
- end
-
- def test_ls_with_no_singleton_class
- input = TestInputMethod.new([
- "ls 42",
- ])
- IRB.init_config(nil)
- workspace = IRB::WorkSpace.new(self)
- IRB.conf[:VERBOSE] = false
- irb = IRB::Irb.new(workspace, input)
- IRB.conf[:MAIN_CONTEXT] = irb.context
- irb.context.return_format = "=> %s\n"
- out, err = capture_output do
- irb.eval_input
- end
- assert_empty err
- assert_match(/Comparable#methods:\s+/, out)
- assert_match(/Numeric#methods:\s+/, out)
- assert_match(/Integer#methods:\s+/, out)
- end
-
- def test_show_source
- input = TestInputMethod.new([
- "show_source 'IRB.conf'\n",
- ])
- IRB.init_config(nil)
- workspace = IRB::WorkSpace.new(self)
- IRB.conf[:VERBOSE] = false
- irb = IRB::Irb.new(workspace, input)
- IRB.conf[:MAIN_CONTEXT] = irb.context
- irb.context.return_format = "=> %s\n"
- out, err = capture_output do
- irb.eval_input
- end
- assert_empty err
- assert_match(%r[/irb\.rb], out)
- end
-
- def test_whereami
- input = TestInputMethod.new([
- "whereami\n",
- ])
- IRB.init_config(nil)
- workspace = IRB::WorkSpace.new(self)
- IRB.conf[:VERBOSE] = false
- irb = IRB::Irb.new(workspace, input)
- IRB.conf[:MAIN_CONTEXT] = irb.context
- irb.context.return_format = "=> %s\n"
- out, err = capture_output do
- irb.eval_input
- end
- assert_empty err
- assert_match(/^From: .+ @ line \d+ :\n/, out)
- end
- end
-end
diff --git a/test/irb/test_color.rb b/test/irb/test_color.rb
index 6ad64a0ae2..9d78f5233e 100644
--- a/test/irb/test_color.rb
+++ b/test/irb/test_color.rb
@@ -1,11 +1,11 @@
# frozen_string_literal: false
-require 'test/unit'
require 'irb/color'
-require 'rubygems'
require 'stringio'
+require_relative "helper"
+
module TestIRB
- class TestColor < Test::Unit::TestCase
+ class ColorTest < TestCase
CLEAR = "\e[0m"
BOLD = "\e[1m"
UNDERLINE = "\e[4m"
@@ -17,6 +17,20 @@ module TestIRB
MAGENTA = "\e[35m"
CYAN = "\e[36m"
+ def setup
+ super
+ if IRB.respond_to?(:conf)
+ @colorize, IRB.conf[:USE_COLORIZE] = IRB.conf[:USE_COLORIZE], true
+ end
+ end
+
+ def teardown
+ if instance_variable_defined?(:@colorize)
+ IRB.conf[:USE_COLORIZE] = @colorize
+ end
+ super
+ end
+
def test_colorize
text = "text"
{
@@ -75,6 +89,7 @@ module TestIRB
":class" => "#{YELLOW}:#{CLEAR}#{YELLOW}class#{CLEAR}",
"[:end, 2]" => "[#{YELLOW}:#{CLEAR}#{YELLOW}end#{CLEAR}, #{BLUE}#{BOLD}2#{CLEAR}]",
"[:>, 3]" => "[#{YELLOW}:#{CLEAR}#{YELLOW}>#{CLEAR}, #{BLUE}#{BOLD}3#{CLEAR}]",
+ "[:`, 4]" => "[#{YELLOW}:#{CLEAR}#{YELLOW}`#{CLEAR}, #{BLUE}#{BOLD}4#{CLEAR}]",
":Hello ? world : nil" => "#{YELLOW}:#{CLEAR}#{YELLOW}Hello#{CLEAR} ? world : #{CYAN}#{BOLD}nil#{CLEAR}",
'raise "foo#{bar}baz"' => "raise #{RED}#{BOLD}\"#{CLEAR}#{RED}foo#{CLEAR}#{RED}\#{#{CLEAR}bar#{RED}}#{CLEAR}#{RED}baz#{CLEAR}#{RED}#{BOLD}\"#{CLEAR}",
'["#{obj.inspect}"]' => "[#{RED}#{BOLD}\"#{CLEAR}#{RED}\#{#{CLEAR}obj.inspect#{RED}}#{CLEAR}#{RED}#{BOLD}\"#{CLEAR}]",
@@ -84,20 +99,20 @@ module TestIRB
"foo %i[bar]" => "foo #{YELLOW}%i[#{CLEAR}#{YELLOW}bar#{CLEAR}#{YELLOW}]#{CLEAR}",
"foo :@bar, baz, :@@qux, :$quux" => "foo #{YELLOW}:#{CLEAR}#{YELLOW}@bar#{CLEAR}, baz, #{YELLOW}:#{CLEAR}#{YELLOW}@@qux#{CLEAR}, #{YELLOW}:#{CLEAR}#{YELLOW}$quux#{CLEAR}",
"`echo`" => "#{RED}#{BOLD}`#{CLEAR}#{RED}echo#{CLEAR}#{RED}#{BOLD}`#{CLEAR}",
- "\t" => "\t", # not ^I
+ "\t" => Reline::Unicode.escape_for_print("\t") == ' ' ? ' ' : "\t", # not ^I
"foo(*%W(bar))" => "foo(*#{RED}#{BOLD}%W(#{CLEAR}#{RED}bar#{CLEAR}#{RED}#{BOLD})#{CLEAR})",
"$stdout" => "#{GREEN}#{BOLD}$stdout#{CLEAR}",
"__END__" => "#{GREEN}__END__#{CLEAR}",
+ "foo\n__END__\nbar" => "foo\n#{GREEN}__END__#{CLEAR}\nbar",
+ "foo\n<<A\0\0bar\nA\nbaz" => "foo\n#{RED}<<A#{CLEAR}^@^@bar\n#{RED}A#{CLEAR}\nbaz",
+ "<<A+1\nA" => "#{RED}<<A#{CLEAR}+#{BLUE}#{BOLD}1#{CLEAR}\n#{RED}A#{CLEAR}",
}
- # specific to Ruby 2.7+
- if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.7.0')
- tests.merge!({
- "4.5.6" => "#{MAGENTA}#{BOLD}4.5#{CLEAR}#{RED}#{REVERSE}.6#{CLEAR}",
- "\e[0m\n" => "#{RED}#{REVERSE}^[#{CLEAR}[#{BLUE}#{BOLD}0#{CLEAR}#{RED}#{REVERSE}m#{CLEAR}\n",
- "<<EOS\nhere\nEOS" => "#{RED}<<EOS#{CLEAR}\n#{RED}here#{CLEAR}\n#{RED}EOS#{CLEAR}",
- })
- end
+ tests.merge!({
+ "4.5.6" => "#{MAGENTA}#{BOLD}4.5#{CLEAR}#{RED}#{REVERSE}.6#{CLEAR}",
+ "\e[0m\n" => "#{RED}#{REVERSE}^[#{CLEAR}[#{BLUE}#{BOLD}0#{CLEAR}#{RED}#{REVERSE}m#{CLEAR}\n",
+ "<<EOS\nhere\nEOS" => "#{RED}<<EOS#{CLEAR}\n#{RED}here#{CLEAR}\n#{RED}EOS#{CLEAR}",
+ })
# specific to Ruby 3.0+
if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('3.0.0')
@@ -111,12 +126,15 @@ module TestIRB
"class bad; end" => "#{GREEN}class#{CLEAR} #{RED}#{REVERSE}bad#{CLEAR}; #{GREEN}end#{CLEAR}",
"def req(@a) end" => "#{GREEN}def#{CLEAR} #{BLUE}#{BOLD}req#{CLEAR}(#{RED}#{REVERSE}@a#{CLEAR}) #{GREEN}end#{CLEAR}",
})
- else
- tests.merge!({
- "[1]]]\u0013" => "[1]]]^S",
+ if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('3.2.0')
+ tests.merge!({
+ "def req(true) end" => "#{GREEN}def#{CLEAR} #{BLUE}#{BOLD}req#{CLEAR}(#{RED}#{REVERSE}true#{CLEAR}#{RED}#{REVERSE})#{CLEAR} #{RED}#{REVERSE}end#{CLEAR}",
})
+ end
+ else
tests.merge!({
- "def req(true) end" => "def req(true) end",
+ "[1]]]\u0013" => "[#{BLUE}#{BOLD}1#{CLEAR}]#{RED}#{REVERSE}]#{CLEAR}]^S",
+ "def req(true) end" => "#{GREEN}def#{CLEAR} #{BLUE}#{BOLD}req#{CLEAR}(#{RED}#{REVERSE}true#{CLEAR}) end",
"nil = 1" => "#{CYAN}#{BOLD}nil#{CLEAR} = #{BLUE}#{BOLD}1#{CLEAR}",
"alias $x $1" => "#{GREEN}alias#{CLEAR} #{GREEN}#{BOLD}$x#{CLEAR} $1",
"class bad; end" => "#{GREEN}class#{CLEAR} bad; #{GREEN}end#{CLEAR}",
@@ -125,31 +143,34 @@ module TestIRB
end
tests.each do |code, result|
- if colorize_code_supported?
- assert_equal_with_term(result, code, complete: true)
- assert_equal_with_term(result, code, complete: false)
+ assert_equal_with_term(result, code, complete: true)
+ assert_equal_with_term(result, code, complete: false)
- assert_equal_with_term(code, code, complete: true, tty: false)
- assert_equal_with_term(code, code, complete: false, tty: false)
+ assert_equal_with_term(code, code, complete: true, tty: false)
+ assert_equal_with_term(code, code, complete: false, tty: false)
- assert_equal_with_term(code, code, complete: true, colorable: false)
+ assert_equal_with_term(code, code, complete: true, colorable: false)
- assert_equal_with_term(code, code, complete: false, colorable: false)
+ assert_equal_with_term(code, code, complete: false, colorable: false)
- assert_equal_with_term(result, code, complete: true, tty: false, colorable: true)
+ assert_equal_with_term(result, code, complete: true, tty: false, colorable: true)
- assert_equal_with_term(result, code, complete: false, tty: false, colorable: true)
- else
- assert_equal_with_term(code, code)
- end
+ assert_equal_with_term(result, code, complete: false, tty: false, colorable: true)
end
end
- def test_colorize_code_complete_true
- unless complete_option_supported?
- pend '`complete: true` is the same as `complete: false` in Ruby 2.6-'
- end
+ def test_colorize_code_with_local_variables
+ code = "a /(b +1)/i"
+ result_without_lvars = "a #{RED}#{BOLD}/#{CLEAR}#{RED}(b +1)#{CLEAR}#{RED}#{BOLD}/i#{CLEAR}"
+ result_with_lvar = "a /(b #{BLUE}#{BOLD}+1#{CLEAR})/i"
+ result_with_lvars = "a /(b +#{BLUE}#{BOLD}1#{CLEAR})/i"
+ assert_equal_with_term(result_without_lvars, code)
+ assert_equal_with_term(result_with_lvar, code, local_variables: ['a'])
+ assert_equal_with_term(result_with_lvars, code, local_variables: ['a', 'b'])
+ end
+
+ def test_colorize_code_complete_true
# `complete: true` behaviors. Warn end-of-file.
{
"'foo' + 'bar" => "#{RED}#{BOLD}'#{CLEAR}#{RED}foo#{CLEAR}#{RED}#{BOLD}'#{CLEAR} + #{RED}#{BOLD}'#{CLEAR}#{RED}#{REVERSE}bar#{CLEAR}",
@@ -171,27 +192,13 @@ module TestIRB
"'foo' + 'bar" => "#{RED}#{BOLD}'#{CLEAR}#{RED}foo#{CLEAR}#{RED}#{BOLD}'#{CLEAR} + #{RED}#{BOLD}'#{CLEAR}#{RED}bar#{CLEAR}",
"('foo" => "(#{RED}#{BOLD}'#{CLEAR}#{RED}foo#{CLEAR}",
}.each do |code, result|
- if colorize_code_supported?
- assert_equal_with_term(result, code, complete: false)
-
- assert_equal_with_term(code, code, complete: false, tty: false)
-
- assert_equal_with_term(code, code, complete: false, colorable: false)
+ assert_equal_with_term(result, code, complete: false)
- assert_equal_with_term(result, code, complete: false, tty: false, colorable: true)
+ assert_equal_with_term(code, code, complete: false, tty: false)
- unless complete_option_supported?
- assert_equal_with_term(result, code, complete: true)
+ assert_equal_with_term(code, code, complete: false, colorable: false)
- assert_equal_with_term(code, code, complete: true, tty: false)
-
- assert_equal_with_term(code, code, complete: true, colorable: false)
-
- assert_equal_with_term(result, code, complete: true, tty: false, colorable: true)
- end
- else
- assert_equal_with_term(code, code)
- end
+ assert_equal_with_term(result, code, complete: false, tty: false, colorable: true)
end
end
@@ -217,16 +224,6 @@ module TestIRB
private
- # `#colorize_code` is supported only for Ruby 2.5+. It just returns the original code in 2.4-.
- def colorize_code_supported?
- Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.5.0')
- end
-
- # `complete: true` is the same as `complete: false` in Ruby 2.6-
- def complete_option_supported?
- Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.7.0')
- end
-
def with_term(tty: true)
stdout = $stdout
io = StringIO.new
diff --git a/test/irb/test_color_printer.rb b/test/irb/test_color_printer.rb
index 93ec700146..c2c624d868 100644
--- a/test/irb/test_color_printer.rb
+++ b/test/irb/test_color_printer.rb
@@ -1,11 +1,11 @@
# frozen_string_literal: false
-require 'test/unit'
require 'irb/color_printer'
-require 'rubygems'
require 'stringio'
+require_relative "helper"
+
module TestIRB
- class TestColorPrinter < Test::Unit::TestCase
+ class ColorPrinterTest < TestCase
CLEAR = "\e[0m"
BOLD = "\e[1m"
RED = "\e[31m"
@@ -14,6 +14,10 @@ module TestIRB
CYAN = "\e[36m"
def setup
+ super
+ if IRB.respond_to?(:conf)
+ @colorize, IRB.conf[:USE_COLORIZE] = IRB.conf[:USE_COLORIZE], true
+ end
@get_screen_size = Reline.method(:get_screen_size)
Reline.instance_eval { undef :get_screen_size }
def Reline.get_screen_size
@@ -24,18 +28,19 @@ module TestIRB
def teardown
Reline.instance_eval { undef :get_screen_size }
Reline.define_singleton_method(:get_screen_size, @get_screen_size)
+ if instance_variable_defined?(:@colorize)
+ IRB.conf[:USE_COLORIZE] = @colorize
+ end
+ super
end
IRBTestColorPrinter = Struct.new(:a)
def test_color_printer
- unless ripper_lexer_scan_supported?
- pend 'Ripper::Lexer#scan is supported in Ruby 2.7+'
- end
{
1 => "#{BLUE}#{BOLD}1#{CLEAR}\n",
"a\nb" => %[#{RED}#{BOLD}"#{CLEAR}#{RED}a\\nb#{CLEAR}#{RED}#{BOLD}"#{CLEAR}\n],
- IRBTestColorPrinter.new('test') => "#{GREEN}#<struct TestIRB::TestColorPrinter::IRBTestColorPrinter#{CLEAR} a#{GREEN}=#{CLEAR}#{RED}#{BOLD}\"#{CLEAR}#{RED}test#{CLEAR}#{RED}#{BOLD}\"#{CLEAR}#{GREEN}>#{CLEAR}\n",
+ IRBTestColorPrinter.new('test') => "#{GREEN}#<struct TestIRB::ColorPrinterTest::IRBTestColorPrinter#{CLEAR} a#{GREEN}=#{CLEAR}#{RED}#{BOLD}\"#{CLEAR}#{RED}test#{CLEAR}#{RED}#{BOLD}\"#{CLEAR}#{GREEN}>#{CLEAR}\n",
Ripper::Lexer.new('1').scan => "[#{GREEN}#<Ripper::Lexer::Elem:#{CLEAR} on_int@1:0 END token: #{RED}#{BOLD}\"#{CLEAR}#{RED}1#{CLEAR}#{RED}#{BOLD}\"#{CLEAR}#{GREEN}>#{CLEAR}]\n",
Class.new{define_method(:pretty_print){|q| q.text("[__FILE__, __LINE__, __ENCODING__]")}}.new => "[#{CYAN}#{BOLD}__FILE__#{CLEAR}, #{CYAN}#{BOLD}__LINE__#{CLEAR}, #{CYAN}#{BOLD}__ENCODING__#{CLEAR}]\n",
}.each do |object, result|
@@ -46,10 +51,6 @@ module TestIRB
private
- def ripper_lexer_scan_supported?
- Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.7.0')
- end
-
def with_term
stdout = $stdout
io = StringIO.new
diff --git a/test/irb/test_command.rb b/test/irb/test_command.rb
new file mode 100644
index 0000000000..69931e3e4f
--- /dev/null
+++ b/test/irb/test_command.rb
@@ -0,0 +1,958 @@
+# frozen_string_literal: false
+require "irb"
+
+require_relative "helper"
+
+module TestIRB
+ class CommandTestCase < TestCase
+ def setup
+ @pwd = Dir.pwd
+ @tmpdir = File.join(Dir.tmpdir, "test_reline_config_#{$$}")
+ begin
+ Dir.mkdir(@tmpdir)
+ rescue Errno::EEXIST
+ FileUtils.rm_rf(@tmpdir)
+ Dir.mkdir(@tmpdir)
+ end
+ Dir.chdir(@tmpdir)
+ setup_envs(home: @tmpdir)
+ save_encodings
+ IRB.instance_variable_get(:@CONF).clear
+ IRB.instance_variable_set(:@existing_rc_name_generators, nil)
+ @is_win = (RbConfig::CONFIG['host_os'] =~ /mswin|msys|mingw|cygwin|bccwin|wince|emc/)
+ end
+
+ def teardown
+ teardown_envs
+ Dir.chdir(@pwd)
+ FileUtils.rm_rf(@tmpdir)
+ restore_encodings
+ end
+
+ def execute_lines(*lines, conf: {}, main: self, irb_path: nil)
+ capture_output do
+ IRB.init_config(nil)
+ IRB.conf[:VERBOSE] = false
+ IRB.conf[:PROMPT_MODE] = :SIMPLE
+ IRB.conf[:USE_PAGER] = false
+ IRB.conf.merge!(conf)
+ input = TestInputMethod.new(lines)
+ irb = IRB::Irb.new(IRB::WorkSpace.new(main), input)
+ irb.context.return_format = "=> %s\n"
+ irb.context.irb_path = irb_path if irb_path
+ IRB.conf[:MAIN_CONTEXT] = irb.context
+ irb.eval_input
+ end
+ end
+ end
+
+ class FrozenObjectTest < CommandTestCase
+ def test_calling_command_on_a_frozen_main
+ main = Object.new.freeze
+
+ out, err = execute_lines(
+ "irb_info",
+ main: main
+ )
+ assert_empty(err)
+ assert_match(/RUBY_PLATFORM/, out)
+ end
+ end
+
+ class InfoTest < CommandTestCase
+ def setup
+ super
+ @locals_backup = ENV.delete("LANG"), ENV.delete("LC_ALL")
+ end
+
+ def teardown
+ super
+ ENV["LANG"], ENV["LC_ALL"] = @locals_backup
+ end
+
+ def test_irb_info_multiline
+ FileUtils.touch("#{@tmpdir}/.inputrc")
+ FileUtils.touch("#{@tmpdir}/.irbrc")
+ FileUtils.touch("#{@tmpdir}/_irbrc")
+
+ out, err = execute_lines(
+ "irb_info",
+ conf: { USE_MULTILINE: true, USE_SINGLELINE: false }
+ )
+
+ expected = %r{
+ Ruby\sversion:\s.+\n
+ IRB\sversion:\sirb\s.+\n
+ InputMethod:\sAbstract\sInputMethod\n
+ Completion: .+\n
+ \.irbrc\spaths:.*\.irbrc.*_irbrc\n
+ RUBY_PLATFORM:\s.+\n
+ East\sAsian\sAmbiguous\sWidth:\s\d\n
+ #{@is_win ? 'Code\spage:\s\d+\n' : ''}
+ }x
+
+ assert_empty err
+ assert_match expected, out
+ end
+
+ def test_irb_info_singleline
+ FileUtils.touch("#{@tmpdir}/.inputrc")
+ FileUtils.touch("#{@tmpdir}/.irbrc")
+
+ out, err = execute_lines(
+ "irb_info",
+ conf: { USE_MULTILINE: false, USE_SINGLELINE: true }
+ )
+
+ expected = %r{
+ Ruby\sversion:\s.+\n
+ IRB\sversion:\sirb\s.+\n
+ InputMethod:\sAbstract\sInputMethod\n
+ Completion: .+\n
+ \.irbrc\spaths:\s.+\n
+ RUBY_PLATFORM:\s.+\n
+ East\sAsian\sAmbiguous\sWidth:\s\d\n
+ #{@is_win ? 'Code\spage:\s\d+\n' : ''}
+ }x
+
+ assert_empty err
+ assert_match expected, out
+ end
+
+ def test_irb_info_multiline_without_rc_files
+ inputrc_backup = ENV["INPUTRC"]
+ ENV["INPUTRC"] = "unknown_inpurc"
+ ext_backup = IRB::IRBRC_EXT
+ IRB.__send__(:remove_const, :IRBRC_EXT)
+ IRB.const_set(:IRBRC_EXT, "unknown_ext")
+
+ out, err = execute_lines(
+ "irb_info",
+ conf: { USE_MULTILINE: true, USE_SINGLELINE: false }
+ )
+
+ expected = %r{
+ Ruby\sversion:\s.+\n
+ IRB\sversion:\sirb\s.+\n
+ InputMethod:\sAbstract\sInputMethod\n
+ Completion: .+\n
+ RUBY_PLATFORM:\s.+\n
+ East\sAsian\sAmbiguous\sWidth:\s\d\n
+ #{@is_win ? 'Code\spage:\s\d+\n' : ''}
+ }x
+
+ assert_empty err
+ assert_match expected, out
+ ensure
+ ENV["INPUTRC"] = inputrc_backup
+ IRB.__send__(:remove_const, :IRBRC_EXT)
+ IRB.const_set(:IRBRC_EXT, ext_backup)
+ end
+
+ def test_irb_info_singleline_without_rc_files
+ inputrc_backup = ENV["INPUTRC"]
+ ENV["INPUTRC"] = "unknown_inpurc"
+ ext_backup = IRB::IRBRC_EXT
+ IRB.__send__(:remove_const, :IRBRC_EXT)
+ IRB.const_set(:IRBRC_EXT, "unknown_ext")
+
+ out, err = execute_lines(
+ "irb_info",
+ conf: { USE_MULTILINE: false, USE_SINGLELINE: true }
+ )
+
+ expected = %r{
+ Ruby\sversion:\s.+\n
+ IRB\sversion:\sirb\s.+\n
+ InputMethod:\sAbstract\sInputMethod\n
+ Completion: .+\n
+ RUBY_PLATFORM:\s.+\n
+ East\sAsian\sAmbiguous\sWidth:\s\d\n
+ #{@is_win ? 'Code\spage:\s\d+\n' : ''}
+ }x
+
+ assert_empty err
+ assert_match expected, out
+ ensure
+ ENV["INPUTRC"] = inputrc_backup
+ IRB.__send__(:remove_const, :IRBRC_EXT)
+ IRB.const_set(:IRBRC_EXT, ext_backup)
+ end
+
+ def test_irb_info_lang
+ FileUtils.touch("#{@tmpdir}/.inputrc")
+ FileUtils.touch("#{@tmpdir}/.irbrc")
+ ENV["LANG"] = "ja_JP.UTF-8"
+ ENV["LC_ALL"] = "en_US.UTF-8"
+
+ out, err = execute_lines(
+ "irb_info",
+ conf: { USE_MULTILINE: true, USE_SINGLELINE: false }
+ )
+
+ expected = %r{
+ Ruby\sversion: .+\n
+ IRB\sversion:\sirb .+\n
+ InputMethod:\sAbstract\sInputMethod\n
+ Completion: .+\n
+ \.irbrc\spaths: .+\n
+ RUBY_PLATFORM: .+\n
+ LANG\senv:\sja_JP\.UTF-8\n
+ LC_ALL\senv:\sen_US\.UTF-8\n
+ East\sAsian\sAmbiguous\sWidth:\s\d\n
+ }x
+
+ assert_empty err
+ assert_match expected, out
+ end
+ end
+
+ class MeasureTest < CommandTestCase
+ def test_measure
+ conf = {
+ PROMPT: {
+ DEFAULT: {
+ PROMPT_I: '> ',
+ PROMPT_S: '> ',
+ PROMPT_C: '> '
+ }
+ },
+ PROMPT_MODE: :DEFAULT,
+ MEASURE: false
+ }
+
+ c = Class.new(Object)
+ out, err = execute_lines(
+ "measure\n",
+ "3\n",
+ "measure :off\n",
+ "3\n",
+ "measure :on\n",
+ "3\n",
+ "measure :off\n",
+ "3\n",
+ conf: conf,
+ main: c
+ )
+
+ assert_empty err
+ assert_match(/\A(TIME is added\.\nprocessing time: .+\n=> 3\n=> 3\n){2}/, out)
+ assert_empty(c.class_variables)
+ end
+
+ def test_measure_keeps_previous_value
+ conf = {
+ PROMPT: {
+ DEFAULT: {
+ PROMPT_I: '> ',
+ PROMPT_S: '> ',
+ PROMPT_C: '> '
+ }
+ },
+ PROMPT_MODE: :DEFAULT,
+ MEASURE: false
+ }
+
+ c = Class.new(Object)
+ out, err = execute_lines(
+ "measure\n",
+ "3\n",
+ "_\n",
+ conf: conf,
+ main: c
+ )
+
+ assert_empty err
+ assert_match(/\ATIME is added\.\nprocessing time: .+\n=> 3\nprocessing time: .+\n=> 3/, out)
+ assert_empty(c.class_variables)
+ end
+
+ def test_measure_enabled_by_rc
+ conf = {
+ PROMPT: {
+ DEFAULT: {
+ PROMPT_I: '> ',
+ PROMPT_S: '> ',
+ PROMPT_C: '> '
+ }
+ },
+ PROMPT_MODE: :DEFAULT,
+ MEASURE: true
+ }
+
+ out, err = execute_lines(
+ "3\n",
+ "measure :off\n",
+ "3\n",
+ conf: conf,
+ )
+
+ assert_empty err
+ assert_match(/\Aprocessing time: .+\n=> 3\n=> 3\n/, out)
+ end
+
+ def test_measure_enabled_by_rc_with_custom
+ measuring_proc = proc { |line, line_no, &block|
+ time = Time.now
+ result = block.()
+ puts 'custom processing time: %fs' % (Time.now - time) if IRB.conf[:MEASURE]
+ result
+ }
+ conf = {
+ PROMPT: {
+ DEFAULT: {
+ PROMPT_I: '> ',
+ PROMPT_S: '> ',
+ PROMPT_C: '> '
+ }
+ },
+ PROMPT_MODE: :DEFAULT,
+ MEASURE: true,
+ MEASURE_PROC: { CUSTOM: measuring_proc }
+ }
+
+ out, err = execute_lines(
+ "3\n",
+ "measure :off\n",
+ "3\n",
+ conf: conf,
+ )
+ assert_empty err
+ assert_match(/\Acustom processing time: .+\n=> 3\n=> 3\n/, out)
+ end
+
+ def test_measure_with_custom
+ measuring_proc = proc { |line, line_no, &block|
+ time = Time.now
+ result = block.()
+ puts 'custom processing time: %fs' % (Time.now - time) if IRB.conf[:MEASURE]
+ result
+ }
+ conf = {
+ PROMPT: {
+ DEFAULT: {
+ PROMPT_I: '> ',
+ PROMPT_S: '> ',
+ PROMPT_C: '> '
+ }
+ },
+ PROMPT_MODE: :DEFAULT,
+ MEASURE: false,
+ MEASURE_PROC: { CUSTOM: measuring_proc }
+ }
+ out, err = execute_lines(
+ "3\n",
+ "measure\n",
+ "3\n",
+ "measure :off\n",
+ "3\n",
+ conf: conf
+ )
+
+ assert_empty err
+ assert_match(/\A=> 3\nCUSTOM is added\.\ncustom processing time: .+\n=> 3\n=> 3\n/, out)
+ end
+
+ def test_measure_toggle
+ conf = {
+ PROMPT: {
+ DEFAULT: {
+ PROMPT_I: '> ',
+ PROMPT_S: '> ',
+ PROMPT_C: '> '
+ }
+ },
+ PROMPT_MODE: :DEFAULT,
+ MEASURE: false,
+ MEASURE_PROC: {
+ FOO: proc { |&block| puts 'foo'; block.call },
+ BAR: proc { |&block| puts 'bar'; block.call }
+ }
+ }
+ out, err = execute_lines(
+ "measure :foo\n",
+ "1\n",
+ "measure :on, :bar\n",
+ "2\n",
+ "measure :off, :foo\n",
+ "3\n",
+ "measure :off, :bar\n",
+ "4\n",
+ conf: conf
+ )
+
+ assert_empty err
+ assert_match(/\AFOO is added\.\nfoo\n=> 1\nBAR is added\.\nbar\nfoo\n=> 2\nbar\n=> 3\n=> 4\n/, out)
+ end
+
+ def test_measure_with_proc_warning
+ conf = {
+ PROMPT: {
+ DEFAULT: {
+ PROMPT_I: '> ',
+ PROMPT_S: '> ',
+ PROMPT_C: '> '
+ }
+ },
+ PROMPT_MODE: :DEFAULT,
+ MEASURE: false,
+ }
+ c = Class.new(Object)
+ out, err = execute_lines(
+ "3\n",
+ "measure do\n",
+ "3\n",
+ conf: conf,
+ main: c
+ )
+
+ assert_match(/to add custom measure/, err)
+ assert_match(/\A=> 3\n=> 3\n/, out)
+ assert_empty(c.class_variables)
+ end
+ end
+
+ class IrbSourceTest < CommandTestCase
+ def test_irb_source
+ File.write("#{@tmpdir}/a.rb", "a = 'hi'\n")
+ out, err = execute_lines(
+ "a = 'bug17564'\n",
+ "a\n",
+ "irb_source '#{@tmpdir}/a.rb'\n",
+ "a\n",
+ )
+ assert_empty err
+ assert_pattern_list([
+ /=> "bug17564"\n/,
+ /=> "bug17564"\n/,
+ / => "hi"\n/,
+ / => "hi"\n/,
+ ], out)
+ end
+
+ def test_irb_source_without_argument
+ out, err = execute_lines(
+ "irb_source\n",
+ )
+ assert_empty err
+ assert_match(/Please specify the file name./, out)
+ end
+ end
+
+ class IrbLoadTest < CommandTestCase
+ def test_irb_load
+ File.write("#{@tmpdir}/a.rb", "a = 'hi'\n")
+ out, err = execute_lines(
+ "a = 'bug17564'\n",
+ "a\n",
+ "irb_load '#{@tmpdir}/a.rb'\n",
+ "a\n",
+ )
+ assert_empty err
+ assert_pattern_list([
+ /=> "bug17564"\n/,
+ /=> "bug17564"\n/,
+ / => "hi"\n/,
+ / => "bug17564"\n/,
+ ], out)
+ end
+
+ def test_irb_load_without_argument
+ out, err = execute_lines(
+ "irb_load\n",
+ )
+
+ assert_empty err
+ assert_match(/Please specify the file name./, out)
+ end
+ end
+
+ class WorkspaceCommandTestCase < CommandTestCase
+ def setup
+ super
+ # create Foo under the test class's namespace so it doesn't pollute global namespace
+ self.class.class_eval <<~RUBY
+ class Foo; end
+ RUBY
+ end
+ end
+
+ class CwwsTest < WorkspaceCommandTestCase
+ def test_cwws_returns_the_current_workspace_object
+ out, err = execute_lines(
+ "cwws"
+ )
+
+ assert_empty err
+ assert_include(out, "Current workspace: #{self}")
+ end
+ end
+
+ class PushwsTest < WorkspaceCommandTestCase
+ def test_pushws_switches_to_new_workspace_and_pushes_the_current_one_to_the_stack
+ out, err = execute_lines(
+ "pushws #{self.class}::Foo.new",
+ "self.class",
+ "popws",
+ "self.class"
+ )
+ assert_empty err
+
+ assert_match(/=> #{self.class}::Foo\n/, out)
+ assert_match(/=> #{self.class}\n$/, out)
+ end
+
+ def test_pushws_extends_the_new_workspace_with_command_bundle
+ out, err = execute_lines(
+ "pushws Object.new",
+ "self.singleton_class.ancestors"
+ )
+ assert_empty err
+ assert_include(out, "IRB::ExtendCommandBundle")
+ end
+
+ def test_pushws_prints_workspace_stack_when_no_arg_is_given
+ out, err = execute_lines(
+ "pushws",
+ )
+ assert_empty err
+ assert_include(out, "[#<TestIRB::PushwsTe...>]")
+ end
+
+ def test_pushws_without_argument_swaps_the_top_two_workspaces
+ out, err = execute_lines(
+ "pushws #{self.class}::Foo.new",
+ "self.class",
+ "pushws",
+ "self.class"
+ )
+ assert_empty err
+ assert_match(/=> #{self.class}::Foo\n/, out)
+ assert_match(/=> #{self.class}\n$/, out)
+ end
+ end
+
+ class WorkspacesTest < WorkspaceCommandTestCase
+ def test_workspaces_returns_the_stack_of_workspaces
+ out, err = execute_lines(
+ "pushws #{self.class}::Foo.new\n",
+ "workspaces",
+ )
+
+ assert_empty err
+ assert_match(/\[#<TestIRB::Workspac...>, #<TestIRB::Workspac...>\]\n/, out)
+ end
+ end
+
+ class PopwsTest < WorkspaceCommandTestCase
+ def test_popws_replaces_the_current_workspace_with_the_previous_one
+ out, err = execute_lines(
+ "pushws Foo.new\n",
+ "popws\n",
+ "cwws\n",
+ "self.class",
+ )
+ assert_empty err
+ assert_include(out, "=> #{self.class}")
+ end
+
+ def test_popws_prints_help_message_if_the_workspace_is_empty
+ out, err = execute_lines(
+ "popws\n",
+ )
+ assert_empty err
+ assert_match(/\[#<TestIRB::PopwsTes...>\]\n/, out)
+ end
+ end
+
+ class ChwsTest < WorkspaceCommandTestCase
+ def test_chws_replaces_the_current_workspace
+ out, err = execute_lines(
+ "chws #{self.class}::Foo.new\n",
+ "cwws\n",
+ "self.class\n"
+ )
+ assert_empty err
+ assert_include(out, "Current workspace: #<#{self.class.name}::Foo")
+ assert_include(out, "=> #{self.class}::Foo")
+ end
+
+ def test_chws_does_nothing_when_receiving_no_argument
+ out, err = execute_lines(
+ "chws\n",
+ )
+ assert_empty err
+ assert_include(out, "Current workspace: #{self}")
+ end
+ end
+
+ class WhereamiTest < CommandTestCase
+ def test_whereami
+ out, err = execute_lines(
+ "whereami\n",
+ )
+ assert_empty err
+ assert_match(/^From: .+ @ line \d+ :\n/, out)
+ end
+
+ def test_whereami_alias
+ out, err = execute_lines(
+ "@\n",
+ )
+ assert_empty err
+ assert_match(/^From: .+ @ line \d+ :\n/, out)
+ end
+ end
+
+ class LsTest < CommandTestCase
+ def test_ls
+ out, err = execute_lines(
+ "class P\n",
+ " def m() end\n",
+ " def m2() end\n",
+ "end\n",
+
+ "class C < P\n",
+ " def m1() end\n",
+ " def m2() end\n",
+ "end\n",
+
+ "module M\n",
+ " def m1() end\n",
+ " def m3() end\n",
+ "end\n",
+
+ "module M2\n",
+ " include M\n",
+ " def m4() end\n",
+ "end\n",
+
+ "obj = C.new\n",
+ "obj.instance_variable_set(:@a, 1)\n",
+ "obj.extend M2\n",
+ "def obj.m5() end\n",
+ "ls obj\n",
+ )
+
+ assert_empty err
+ assert_match(/^instance variables:\s+@a\n/m, out)
+ assert_match(/P#methods:\s+m\n/m, out)
+ assert_match(/C#methods:\s+m2\n/m, out)
+ assert_match(/M#methods:\s+m1\s+m3\n/m, out)
+ assert_match(/M2#methods:\s+m4\n/m, out)
+ assert_match(/C.methods:\s+m5\n/m, out)
+ end
+
+ def test_ls_class
+ out, err = execute_lines(
+ "module M1\n",
+ " def m2; end\n",
+ " def m3; end\n",
+ "end\n",
+
+ "class C1\n",
+ " def m1; end\n",
+ " def m2; end\n",
+ "end\n",
+
+ "class C2 < C1\n",
+ " include M1\n",
+ " def m3; end\n",
+ " def m4; end\n",
+ " def self.m3; end\n",
+ " def self.m5; end\n",
+ "end\n",
+ "ls C2"
+ )
+
+ assert_empty err
+ assert_match(/C2.methods:\s+m3\s+m5\n/, out)
+ assert_match(/C2#methods:\s+m3\s+m4\n.*M1#methods:\s+m2\n.*C1#methods:\s+m1\n/, out)
+ assert_not_match(/Module#methods/, out)
+ assert_not_match(/Class#methods/, out)
+ end
+
+ def test_ls_module
+ out, err = execute_lines(
+ "module M1\n",
+ " def m1; end\n",
+ " def m2; end\n",
+ "end\n",
+
+ "module M2\n",
+ " include M1\n",
+ " def m1; end\n",
+ " def m3; end\n",
+ " def self.m4; end\n",
+ "end\n",
+ "ls M2"
+ )
+
+ assert_empty err
+ assert_match(/M2\.methods:\s+m4\n/, out)
+ assert_match(/M2#methods:\s+m1\s+m3\n.*M1#methods:\s+m2\n/, out)
+ assert_not_match(/Module#methods/, out)
+ end
+
+ def test_ls_instance
+ out, err = execute_lines(
+ "class Foo; def bar; end; end\n",
+ "ls Foo.new"
+ )
+
+ assert_empty err
+ assert_match(/Foo#methods:\s+bar/, out)
+ # don't duplicate
+ assert_not_match(/Foo#methods:\s+bar\n.*Foo#methods/, out)
+ end
+
+ def test_ls_grep
+ out, err = execute_lines("ls 42\n")
+ assert_empty err
+ assert_match(/times/, out)
+ assert_match(/polar/, out)
+
+ [
+ "ls 42, grep: /times/\n",
+ "ls 42 -g times\n",
+ "ls 42 -G times\n",
+ ].each do |line|
+ out, err = execute_lines(line)
+ assert_empty err
+ assert_match(/times/, out)
+ assert_not_match(/polar/, out)
+ end
+ end
+
+ def test_ls_grep_empty
+ out, err = execute_lines("ls\n")
+ assert_empty err
+ assert_match(/assert/, out)
+ assert_match(/refute/, out)
+
+ [
+ "ls grep: /assert/\n",
+ "ls -g assert\n",
+ "ls -G assert\n",
+ ].each do |line|
+ out, err = execute_lines(line)
+ assert_empty err
+ assert_match(/assert/, out)
+ assert_not_match(/refute/, out)
+ end
+ end
+
+ def test_ls_with_no_singleton_class
+ out, err = execute_lines(
+ "ls 42",
+ )
+ assert_empty err
+ assert_match(/Comparable#methods:\s+/, out)
+ assert_match(/Numeric#methods:\s+/, out)
+ assert_match(/Integer#methods:\s+/, out)
+ end
+ end
+
+ class ShowDocTest < CommandTestCase
+ def test_show_doc
+ out, err = execute_lines("show_doc String#gsub")
+
+ # the former is what we'd get without document content installed, like on CI
+ # the latter is what we may get locally
+ possible_rdoc_output = [/Nothing known about String#gsub/, /gsub\(pattern\)/]
+ assert_not_include err, "[Deprecation]"
+ assert(possible_rdoc_output.any? { |output| output.match?(out) }, "Expect the `show_doc` command to match one of the possible outputs. Got:\n#{out}")
+ ensure
+ # this is the only way to reset the redefined method without coupling the test with its implementation
+ EnvUtil.suppress_warning { load "irb/command/help.rb" }
+ end if defined?(RDoc)
+
+ def test_show_doc_without_rdoc
+ _, err = without_rdoc do
+ execute_lines("show_doc String#gsub")
+ end
+
+ assert_include(err, "Can't display document because `rdoc` is not installed.\n")
+ ensure
+ # this is the only way to reset the redefined method without coupling the test with its implementation
+ EnvUtil.suppress_warning { load "irb/command/help.rb" }
+ end
+ end
+
+ class EditTest < CommandTestCase
+ def setup
+ @original_visual = ENV["VISUAL"]
+ @original_editor = ENV["EDITOR"]
+ # noop the command so nothing gets executed
+ ENV["VISUAL"] = ": code"
+ ENV["EDITOR"] = ": code2"
+ end
+
+ def teardown
+ ENV["VISUAL"] = @original_visual
+ ENV["EDITOR"] = @original_editor
+ end
+
+ def test_edit_without_arg
+ out, err = execute_lines(
+ "edit",
+ irb_path: __FILE__
+ )
+
+ assert_empty err
+ assert_match("path: #{__FILE__}", out)
+ assert_match("command: ': code'", out)
+ end
+
+ def test_edit_without_arg_and_non_existing_irb_path
+ out, err = execute_lines(
+ "edit",
+ irb_path: '/path/to/file.rb(irb)'
+ )
+
+ assert_empty err
+ assert_match(/Can not find file: \/path\/to\/file\.rb\(irb\)/, out)
+ end
+
+ def test_edit_with_path
+ out, err = execute_lines(
+ "edit #{__FILE__}"
+ )
+
+ assert_empty err
+ assert_match("path: #{__FILE__}", out)
+ assert_match("command: ': code'", out)
+ end
+
+ def test_edit_with_non_existing_path
+ out, err = execute_lines(
+ "edit test_cmd_non_existing_path.rb"
+ )
+
+ assert_empty err
+ assert_match(/Can not find file: test_cmd_non_existing_path\.rb/, out)
+ end
+
+ def test_edit_with_constant
+ out, err = execute_lines(
+ "edit IRB::Irb"
+ )
+
+ assert_empty err
+ assert_match(/path: .*\/lib\/irb\.rb/, out)
+ assert_match("command: ': code'", out)
+ end
+
+ def test_edit_with_class_method
+ out, err = execute_lines(
+ "edit IRB.start"
+ )
+
+ assert_empty err
+ assert_match(/path: .*\/lib\/irb\.rb/, out)
+ assert_match("command: ': code'", out)
+ end
+
+ def test_edit_with_instance_method
+ out, err = execute_lines(
+ "edit IRB::Irb#run"
+ )
+
+ assert_empty err
+ assert_match(/path: .*\/lib\/irb\.rb/, out)
+ assert_match("command: ': code'", out)
+ end
+
+ def test_edit_with_editor_env_var
+ ENV.delete("VISUAL")
+
+ out, err = execute_lines(
+ "edit",
+ irb_path: __FILE__
+ )
+
+ assert_empty err
+ assert_match("path: #{__FILE__}", out)
+ assert_match("command: ': code2'", out)
+ end
+ end
+
+ class HistoryCmdTest < CommandTestCase
+ def teardown
+ TestInputMethod.send(:remove_const, "HISTORY") if defined?(TestInputMethod::HISTORY)
+ super
+ end
+
+ def test_history
+ TestInputMethod.const_set("HISTORY", %w[foo bar baz])
+
+ out, err = without_rdoc do
+ execute_lines("history")
+ end
+
+ assert_include(out, <<~EOF)
+ 2: baz
+ 1: bar
+ 0: foo
+ EOF
+ assert_empty err
+ end
+
+ def test_multiline_history_with_truncation
+ TestInputMethod.const_set("HISTORY", ["foo", "bar", <<~INPUT])
+ [].each do |x|
+ puts x
+ end
+ INPUT
+
+ out, err = without_rdoc do
+ execute_lines("hist")
+ end
+
+ assert_include(out, <<~EOF)
+ 2: [].each do |x|
+ puts x
+ ...
+ 1: bar
+ 0: foo
+ EOF
+ assert_empty err
+ end
+
+ def test_history_grep
+ TestInputMethod.const_set("HISTORY", ["foo", "bar", <<~INPUT])
+ [].each do |x|
+ puts x
+ end
+ INPUT
+
+ out, err = without_rdoc do
+ execute_lines("hist -g each\n")
+ end
+
+ assert_include(out, <<~EOF)
+ 2: [].each do |x|
+ puts x
+ ...
+ EOF
+ assert_empty err
+ end
+
+ end
+
+ class HelperMethodInsallTest < CommandTestCase
+ def test_helper_method_install
+ IRB::ExtendCommandBundle.module_eval do
+ def foobar
+ "test_helper_method_foobar"
+ end
+ end
+
+ out, err = execute_lines("foobar.upcase")
+ assert_empty err
+ assert_include(out, '=> "TEST_HELPER_METHOD_FOOBAR"')
+ ensure
+ IRB::ExtendCommandBundle.remove_method :foobar
+ end
+ end
+end
diff --git a/test/irb/test_completion.rb b/test/irb/test_completion.rb
index 819a958887..c9a0eafa3d 100644
--- a/test/irb/test_completion.rb
+++ b/test/irb/test_completion.rb
@@ -1,115 +1,317 @@
# frozen_string_literal: false
-require "test/unit"
+require "pathname"
require "irb"
+require_relative "helper"
+
module TestIRB
- class TestCompletion < Test::Unit::TestCase
- def test_nonstring_module_name
- begin
- require "irb/completion"
- bug5938 = '[ruby-core:42244]'
- bundle_exec = ENV.key?('BUNDLE_GEMFILE') ? ['-rbundler/setup'] : []
- cmds = bundle_exec + %W[-W0 -rirb -rirb/completion -e IRB.setup(__FILE__)
- -e IRB.conf[:MAIN_CONTEXT]=IRB::Irb.new.context
- -e module\sFoo;def\sself.name;//;end;end
- -e IRB::InputCompletor::CompletionProc.call("[1].first.")
- -- -f --]
- status = assert_in_out_err(cmds, "", //, [], bug5938)
- assert(status.success?, bug5938)
- rescue LoadError
- pend "cannot load irb/completion"
+ class CompletionTest < TestCase
+ def completion_candidates(target, bind)
+ IRB::RegexpCompletor.new.completion_candidates('', target, '', bind: bind)
+ end
+
+ def doc_namespace(target, bind)
+ IRB::RegexpCompletor.new.doc_namespace('', target, '', bind: bind)
+ end
+
+ class CommandCompletionTest < CompletionTest
+ def test_command_completion
+ completor = IRB::RegexpCompletor.new
+ binding.eval("some_var = 1")
+ # completion for help command's argument should only include command names
+ assert_include(completor.completion_candidates('help ', 's', '', bind: binding), 'show_source')
+ assert_not_include(completor.completion_candidates('help ', 's', '', bind: binding), 'some_var')
+
+ assert_include(completor.completion_candidates('', 'show_s', '', bind: binding), 'show_source')
+ assert_not_include(completor.completion_candidates(';', 'show_s', '', bind: binding), 'show_source')
+ end
+ end
+
+ class MethodCompletionTest < CompletionTest
+ def test_complete_string
+ assert_include(completion_candidates("'foo'.up", binding), "'foo'.upcase")
+ # completing 'foo bar'.up
+ assert_include(completion_candidates("bar'.up", binding), "bar'.upcase")
+ assert_equal("String.upcase", doc_namespace("'foo'.upcase", binding))
+ end
+
+ def test_complete_regexp
+ assert_include(completion_candidates("/foo/.ma", binding), "/foo/.match")
+ # completing /foo bar/.ma
+ assert_include(completion_candidates("bar/.ma", binding), "bar/.match")
+ assert_equal("Regexp.match", doc_namespace("/foo/.match", binding))
+ end
+
+ def test_complete_array
+ assert_include(completion_candidates("[].an", binding), "[].any?")
+ assert_equal("Array.any?", doc_namespace("[].any?", binding))
+ end
+
+ def test_complete_hash_and_proc
+ # hash
+ assert_include(completion_candidates("{}.an", binding), "{}.any?")
+ assert_equal(["Hash.any?", "Proc.any?"], doc_namespace("{}.any?", binding))
+
+ # proc
+ assert_include(completion_candidates("{}.bin", binding), "{}.binding")
+ assert_equal(["Hash.binding", "Proc.binding"], doc_namespace("{}.binding", binding))
+ end
+
+ def test_complete_numeric
+ assert_include(completion_candidates("1.positi", binding), "1.positive?")
+ assert_equal("Integer.positive?", doc_namespace("1.positive?", binding))
+
+ assert_include(completion_candidates("1r.positi", binding), "1r.positive?")
+ assert_equal("Rational.positive?", doc_namespace("1r.positive?", binding))
+
+ assert_include(completion_candidates("0xFFFF.positi", binding), "0xFFFF.positive?")
+ assert_equal("Integer.positive?", doc_namespace("0xFFFF.positive?", binding))
+
+ assert_empty(completion_candidates("1i.positi", binding))
+ end
+
+ def test_complete_symbol
+ assert_include(completion_candidates(":foo.to_p", binding), ":foo.to_proc")
+ assert_equal("Symbol.to_proc", doc_namespace(":foo.to_proc", binding))
+ end
+
+ def test_complete_class
+ assert_include(completion_candidates("String.ne", binding), "String.new")
+ assert_equal("String.new", doc_namespace("String.new", binding))
+ end
+ end
+
+ class RequireComepletionTest < CompletionTest
+ def test_complete_require
+ candidates = IRB::RegexpCompletor.new.completion_candidates("require ", "'irb", "", bind: binding)
+ %w['irb/init 'irb/ruby-lex].each do |word|
+ assert_include candidates, word
+ end
+ # Test cache
+ candidates = IRB::RegexpCompletor.new.completion_candidates("require ", "'irb", "", bind: binding)
+ %w['irb/init 'irb/ruby-lex].each do |word|
+ assert_include candidates, word
+ end
+ # Test string completion not disturbed by require completion
+ candidates = IRB::RegexpCompletor.new.completion_candidates("'string ", "'.", "", bind: binding)
+ assert_include candidates, "'.upcase"
+ end
+
+ def test_complete_require_with_pathname_in_load_path
+ temp_dir = Dir.mktmpdir
+ File.write(File.join(temp_dir, "foo.rb"), "test")
+ test_path = Pathname.new(temp_dir)
+ $LOAD_PATH << test_path
+
+ candidates = IRB::RegexpCompletor.new.completion_candidates("require ", "'foo", "", bind: binding)
+ assert_include candidates, "'foo"
+ ensure
+ $LOAD_PATH.pop if test_path
+ FileUtils.remove_entry(temp_dir) if temp_dir
+ end
+
+ def test_complete_require_with_string_convertable_in_load_path
+ temp_dir = Dir.mktmpdir
+ File.write(File.join(temp_dir, "foo.rb"), "test")
+ object = Object.new
+ object.define_singleton_method(:to_s) { temp_dir }
+ $LOAD_PATH << object
+
+ candidates = IRB::RegexpCompletor.new.completion_candidates("require ", "'foo", "", bind: binding)
+ assert_include candidates, "'foo"
+ ensure
+ $LOAD_PATH.pop if object
+ FileUtils.remove_entry(temp_dir) if temp_dir
+ end
+
+ def test_complete_require_with_malformed_object_in_load_path
+ object = Object.new
+ def object.to_s; raise; end
+ $LOAD_PATH << object
+
+ assert_nothing_raised do
+ IRB::RegexpCompletor.new.completion_candidates("require ", "'foo", "", bind: binding)
+ end
+ ensure
+ $LOAD_PATH.pop if object
+ end
+
+ def test_complete_require_library_name_first
+ # Test that library name is completed first with subdirectories
+ candidates = IRB::RegexpCompletor.new.completion_candidates("require ", "'irb", "", bind: binding)
+ assert_equal "'irb", candidates.first
+ end
+
+ def test_complete_require_relative
+ candidates = Dir.chdir(__dir__ + "/../..") do
+ IRB::RegexpCompletor.new.completion_candidates("require_relative ", "'lib/irb", "", bind: binding)
+ end
+ %w['lib/irb/init 'lib/irb/ruby-lex].each do |word|
+ assert_include candidates, word
+ end
+ # Test cache
+ candidates = Dir.chdir(__dir__ + "/../..") do
+ IRB::RegexpCompletor.new.completion_candidates("require_relative ", "'lib/irb", "", bind: binding)
+ end
+ %w['lib/irb/init 'lib/irb/ruby-lex].each do |word|
+ assert_include candidates, word
+ end
end
end
- def test_complete_numeric
- assert_include(IRB::InputCompletor.retrieve_completion_data("1r.positi", bind: binding), "1r.positive?")
- assert_empty(IRB::InputCompletor.retrieve_completion_data("1i.positi", bind: binding))
+ class VariableCompletionTest < CompletionTest
+ def test_complete_variable
+ # Bug fix issues https://github.com/ruby/irb/issues/368
+ # Variables other than `str_example` and `@str_example` are defined to ensure that irb completion does not cause unintended behavior
+ str_example = ''
+ @str_example = ''
+ private_methods = ''
+ methods = ''
+ global_variables = ''
+ local_variables = ''
+ instance_variables = ''
+
+ # suppress "assigned but unused variable" warning
+ str_example.clear
+ @str_example.clear
+ private_methods.clear
+ methods.clear
+ global_variables.clear
+ local_variables.clear
+ instance_variables.clear
+
+ assert_include(completion_candidates("str_examp", binding), "str_example")
+ assert_equal("String", doc_namespace("str_example", binding))
+ assert_equal("String.to_s", doc_namespace("str_example.to_s", binding))
+
+ assert_include(completion_candidates("@str_examp", binding), "@str_example")
+ assert_equal("String", doc_namespace("@str_example", binding))
+ assert_equal("String.to_s", doc_namespace("@str_example.to_s", binding))
+ end
+
+ def test_complete_sort_variables
+ xzy, xzy_1, xzy2 = '', '', ''
+
+ xzy.clear
+ xzy_1.clear
+ xzy2.clear
+
+ candidates = completion_candidates("xz", binding)
+ assert_equal(%w[xzy xzy2 xzy_1], candidates)
+ end
+ end
+
+ class ConstantCompletionTest < CompletionTest
+ class Foo
+ B3 = 1
+ B1 = 1
+ B2 = 1
+ end
+
+ def test_complete_constants
+ assert_equal(["Foo"], completion_candidates("Fo", binding))
+ assert_equal(["Foo::B1", "Foo::B2", "Foo::B3"], completion_candidates("Foo::B", binding))
+ assert_equal(["Foo::B1.positive?"], completion_candidates("Foo::B1.pos", binding))
+
+ assert_equal(["::Forwardable"], completion_candidates("::Fo", binding))
+ assert_equal("Forwardable", doc_namespace("::Forwardable", binding))
+ end
+ end
+
+ def test_not_completing_empty_string
+ assert_equal([], completion_candidates("", binding))
+ assert_equal([], completion_candidates(" ", binding))
+ assert_equal([], completion_candidates("\t", binding))
+ assert_equal(nil, doc_namespace("", binding))
end
def test_complete_symbol
- %w"UTF-16LE UTF-7".each do |enc|
+ symbols = %w"UTF-16LE UTF-7".map do |enc|
"K".force_encoding(enc).to_sym
rescue
end
- _ = :aiueo
- assert_include(IRB::InputCompletor.retrieve_completion_data(":a", bind: binding), ":aiueo")
- assert_empty(IRB::InputCompletor.retrieve_completion_data(":irb_unknown_symbol_abcdefg", bind: binding))
+ symbols += [:aiueo, :"aiu eo"]
+ candidates = completion_candidates(":a", binding)
+ assert_include(candidates, ":aiueo")
+ assert_not_include(candidates, ":aiu eo")
+ assert_empty(completion_candidates(":irb_unknown_symbol_abcdefg", binding))
+ # Do not complete empty symbol for performance reason
+ assert_empty(completion_candidates(":", binding))
end
def test_complete_invalid_three_colons
- assert_empty(IRB::InputCompletor.retrieve_completion_data(":::A", bind: binding))
- assert_empty(IRB::InputCompletor.retrieve_completion_data(":::", bind: binding))
+ assert_empty(completion_candidates(":::A", binding))
+ assert_empty(completion_candidates(":::", binding))
end
- def test_complete_symbol_failure
- assert_nil(IRB::InputCompletor::PerfectMatchedProc.(":aiueo", bind: binding))
+ def test_complete_absolute_constants_with_special_characters
+ assert_empty(completion_candidates("::A:", binding))
+ assert_empty(completion_candidates("::A.", binding))
+ assert_empty(completion_candidates("::A(", binding))
+ assert_empty(completion_candidates("::A)", binding))
+ assert_empty(completion_candidates("::A[", binding))
end
def test_complete_reserved_words
- candidates = IRB::InputCompletor.retrieve_completion_data("de", bind: binding)
+ candidates = completion_candidates("de", binding)
%w[def defined?].each do |word|
assert_include candidates, word
end
- candidates = IRB::InputCompletor.retrieve_completion_data("__", bind: binding)
+ candidates = completion_candidates("__", binding)
%w[__ENCODING__ __LINE__ __FILE__].each do |word|
assert_include candidates, word
end
end
- def test_complete_predicate?
- candidates = IRB::InputCompletor.retrieve_completion_data("1.posi", bind: binding)
- assert_include candidates, '1.positive?'
+ def test_complete_methods
+ obj = Object.new
+ obj.singleton_class.class_eval {
+ def public_hoge; end
+ private def private_hoge; end
- namespace = IRB::InputCompletor.retrieve_completion_data("1.positive?", bind: binding, doc_namespace: true)
- assert_equal "Integer.positive?", namespace
- end
+ # Support for overriding #methods etc.
+ def methods; end
+ def private_methods; end
+ def global_variables; end
+ def local_variables; end
+ def instance_variables; end
+ }
+ bind = obj.instance_exec { binding }
- def test_complete_require
- candidates = IRB::InputCompletor::CompletionProc.("'irb", "require ", "")
- %w['irb/init 'irb/ruby-lex].each do |word|
- assert_include candidates, word
- end
- # Test cache
- candidates = IRB::InputCompletor::CompletionProc.("'irb", "require ", "")
- %w['irb/init 'irb/ruby-lex].each do |word|
- assert_include candidates, word
- end
+ assert_include(completion_candidates("public_hog", bind), "public_hoge")
+ assert_include(doc_namespace("public_hoge", bind), "public_hoge")
+
+ assert_include(completion_candidates("private_hog", bind), "private_hoge")
+ assert_include(doc_namespace("private_hoge", bind), "private_hoge")
end
+ end
- def test_complete_require_library_name_first
- pend 'Need to use virtual library paths'
- candidates = IRB::InputCompletor::CompletionProc.("'csv", "require ", "")
- assert_equal "'csv", candidates.first
+ class DeprecatedInputCompletorTest < TestCase
+ def setup
+ save_encodings
+ @verbose, $VERBOSE = $VERBOSE, nil
+ IRB.init_config(nil)
+ IRB.conf[:VERBOSE] = false
+ IRB.conf[:MAIN_CONTEXT] = IRB::Context.new(IRB::WorkSpace.new(binding))
end
- def test_complete_require_relative
- candidates = Dir.chdir(__dir__ + "/../..") do
- IRB::InputCompletor::CompletionProc.("'lib/irb", "require_relative ", "")
- end
- %w['lib/irb/init 'lib/irb/ruby-lex].each do |word|
- assert_include candidates, word
- end
- # Test cache
- candidates = Dir.chdir(__dir__ + "/../..") do
- IRB::InputCompletor::CompletionProc.("'lib/irb", "require_relative ", "")
- end
- %w['lib/irb/init 'lib/irb/ruby-lex].each do |word|
- assert_include candidates, word
- end
+ def teardown
+ restore_encodings
+ $VERBOSE = @verbose
end
- def test_complete_variable
- str_example = ''
- str_example.clear # suppress "assigned but unused variable" warning
- assert_include(IRB::InputCompletor.retrieve_completion_data("str_examp", bind: binding), "str_example")
- assert_equal(IRB::InputCompletor.retrieve_completion_data("str_example", bind: binding, doc_namespace: true), "String")
- assert_equal(IRB::InputCompletor.retrieve_completion_data("str_example.to_s", bind: binding, doc_namespace: true), "String.to_s")
+ def test_completion_proc
+ assert_include(IRB::InputCompletor::CompletionProc.call('1.ab'), '1.abs')
+ assert_include(IRB::InputCompletor::CompletionProc.call('1.ab', '', ''), '1.abs')
end
- def test_complete_class_method
- assert_include(IRB::InputCompletor.retrieve_completion_data("String.new", bind: binding), "String.new")
- assert_equal(IRB::InputCompletor.retrieve_completion_data("String.new", bind: binding, doc_namespace: true), "String.new")
+ def test_retrieve_completion_data
+ assert_include(IRB::InputCompletor.retrieve_completion_data('1.ab'), '1.abs')
+ assert_equal(IRB::InputCompletor.retrieve_completion_data('1.abs', doc_namespace: true), 'Integer.abs')
+ bind = eval('a = 1; binding')
+ assert_include(IRB::InputCompletor.retrieve_completion_data('a.ab', bind: bind), 'a.abs')
+ assert_equal(IRB::InputCompletor.retrieve_completion_data('a.abs', bind: bind, doc_namespace: true), 'Integer.abs')
end
end
end
diff --git a/test/irb/test_context.rb b/test/irb/test_context.rb
index ba3b94ce49..7ad8fd2fc4 100644
--- a/test/irb/test_context.rb
+++ b/test/irb/test_context.rb
@@ -1,45 +1,16 @@
# frozen_string_literal: false
-require 'test/unit'
require 'tempfile'
require 'irb'
-require 'rubygems' if defined?(Gem)
-module TestIRB
- class TestContext < Test::Unit::TestCase
- class TestInputMethod < ::IRB::InputMethod
- attr_reader :list, :line_no
-
- def initialize(list = [])
- super("test")
- @line_no = 0
- @list = list
- end
-
- def gets
- @list[@line_no]&.tap {@line_no += 1}
- end
-
- def eof?
- @line_no >= @list.size
- end
-
- def encoding
- Encoding.default_external
- end
-
- def reset
- @line_no = 0
- end
-
- def winsize
- [10, 20]
- end
- end
+require_relative "helper"
+module TestIRB
+ class ContextTest < TestCase
def setup
IRB.init_config(nil)
IRB.conf[:USE_SINGLELINE] = false
IRB.conf[:VERBOSE] = false
+ IRB.conf[:USE_PAGER] = false
workspace = IRB::WorkSpace.new(Object.new)
@context = IRB::Context.new(nil, workspace, TestInputMethod.new)
@@ -48,53 +19,16 @@ module TestIRB
def Reline.get_screen_size
[36, 80]
end
+ save_encodings
end
def teardown
Reline.instance_eval { undef :get_screen_size }
Reline.define_singleton_method(:get_screen_size, @get_screen_size)
- end
-
- def test_last_value
- assert_nil(@context.last_value)
- assert_nil(@context.evaluate('_', 1))
- obj = Object.new
- @context.set_last_value(obj)
- assert_same(obj, @context.last_value)
- assert_same(obj, @context.evaluate('_', 1))
- end
-
- def test_evaluate_with_exception
- assert_nil(@context.evaluate("$!", 1))
- e = assert_raise_with_message(RuntimeError, 'foo') {
- @context.evaluate("raise 'foo'", 1)
- }
- assert_equal('foo', e.message)
- assert_same(e, @context.evaluate('$!', 1, exception: e))
- e = assert_raise(SyntaxError) {
- @context.evaluate("1,2,3", 1, exception: e)
- }
- assert_match(/\A\(irb\):1:/, e.message)
- assert_not_match(/rescue _\.class/, e.message)
- end
-
- def test_evaluate_with_encoding_error_without_lineno
- pend if RUBY_ENGINE == 'truffleruby'
- assert_raise_with_message(EncodingError, /invalid symbol/) {
- @context.evaluate(%q[{"\xAE": 1}], 1)
- # The backtrace of this invalid encoding hash doesn't contain lineno.
- }
- end
-
- def test_evaluate_with_onigmo_warning
- pend if RUBY_ENGINE == 'truffleruby'
- assert_warning("(irb):1: warning: character class has duplicated range: /[aa]/\n") do
- @context.evaluate('/[aa]/', 1)
- end
+ restore_encodings
end
def test_eval_input
- pend if RUBY_ENGINE == 'truffleruby'
verbose, $VERBOSE = $VERBOSE, nil
input = TestInputMethod.new([
"raise 'Foo'\n",
@@ -107,17 +41,32 @@ module TestIRB
irb.eval_input
end
assert_empty err
- assert_pattern_list([:*, /\(irb\):1:in `<main>': Foo \(RuntimeError\)\n/,
- :*, /#<RuntimeError: Foo>\n/,
- :*, /0$/,
- :*, /0$/,
- /\s*/], out)
+
+ expected_output =
+ if RUBY_3_4
+ [
+ :*, /\(irb\):1:in '<main>': Foo \(RuntimeError\)\n/,
+ :*, /#<RuntimeError: Foo>\n/,
+ :*, /0$/,
+ :*, /0$/,
+ /\s*/
+ ]
+ else
+ [
+ :*, /\(irb\):1:in `<main>': Foo \(RuntimeError\)\n/,
+ :*, /#<RuntimeError: Foo>\n/,
+ :*, /0$/,
+ :*, /0$/,
+ /\s*/
+ ]
+ end
+
+ assert_pattern_list(expected_output, out)
ensure
$VERBOSE = verbose
end
def test_eval_input_raise2x
- pend if RUBY_ENGINE == 'truffleruby'
input = TestInputMethod.new([
"raise 'Foo'\n",
"raise 'Bar'\n",
@@ -128,81 +77,145 @@ module TestIRB
irb.eval_input
end
assert_empty err
- assert_pattern_list([
- :*, /\(irb\):1:in `<main>': Foo \(RuntimeError\)\n/,
- :*, /\(irb\):2:in `<main>': Bar \(RuntimeError\)\n/,
- :*, /#<RuntimeError: Bar>\n/,
- ], out)
+ expected_output =
+ if RUBY_3_4
+ [
+ :*, /\(irb\):1:in '<main>': Foo \(RuntimeError\)\n/,
+ :*, /\(irb\):2:in '<main>': Bar \(RuntimeError\)\n/,
+ :*, /#<RuntimeError: Bar>\n/,
+ ]
+ else
+ [
+ :*, /\(irb\):1:in `<main>': Foo \(RuntimeError\)\n/,
+ :*, /\(irb\):2:in `<main>': Bar \(RuntimeError\)\n/,
+ :*, /#<RuntimeError: Bar>\n/,
+ ]
+ end
+ assert_pattern_list(expected_output, out)
end
- def test_eval_object_without_inspect_method
- verbose, $VERBOSE = $VERBOSE, nil
- all_assertions do |all|
- IRB::Inspector::INSPECTORS.invert.each_value do |mode|
- all.for(mode) do
- input = TestInputMethod.new([
- "[BasicObject.new, Class.new]\n",
- ])
- irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
- irb.context.inspect_mode = mode
- out, err = capture_output do
- irb.eval_input
- end
- assert_empty err
- assert_match(/\(Object doesn't support #inspect\)\n(=> )?\n/, out)
+ def test_prompt_n_deprecation
+ irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), TestInputMethod.new)
+
+ _, err = capture_output do
+ irb.context.prompt_n = "foo"
+ irb.context.prompt_n
+ end
+
+ assert_include err, "IRB::Context#prompt_n is deprecated"
+ assert_include err, "IRB::Context#prompt_n= is deprecated"
+ end
+
+ def test_output_to_pipe
+ require 'stringio'
+ input = TestInputMethod.new(["n=1"])
+ input.instance_variable_set(:@stdout, StringIO.new)
+ irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
+ irb.context.echo_on_assignment = :truncate
+ irb.context.prompt_mode = :DEFAULT
+ out, err = capture_output do
+ irb.eval_input
+ end
+ assert_empty err
+ assert_equal "=> 1\n", out
+ end
+
+ {
+ successful: [
+ [false, "class Foo < Struct.new(:bar); end; Foo.new(123)\n", /#<struct bar=123>/],
+ [:p, "class Foo < Struct.new(:bar); end; Foo.new(123)\n", /#<struct bar=123>/],
+ [true, "class Foo < Struct.new(:bar); end; Foo.new(123)\n", /#<struct #<Class:.*>::Foo bar=123>/],
+ [:yaml, "123", /--- 123\n/],
+ [:marshal, "123", Marshal.dump(123)],
+ ],
+ failed: [
+ [false, "BasicObject.new", /#<NoMethodError: undefined method (`|')to_s' for/],
+ [:p, "class Foo; undef inspect ;end; Foo.new", /#<NoMethodError: undefined method (`|')inspect' for/],
+ [:yaml, "BasicObject.new", /#<NoMethodError: undefined method (`|')inspect' for/],
+ [:marshal, "[Object.new, Class.new]", /#<TypeError: can't dump anonymous class #<Class:/]
+ ]
+ }.each do |scenario, cases|
+ cases.each do |inspect_mode, input, expected|
+ define_method "test_#{inspect_mode}_inspect_mode_#{scenario}" do
+ verbose, $VERBOSE = $VERBOSE, nil
+ irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), TestInputMethod.new([input]))
+ irb.context.inspect_mode = inspect_mode
+ out, err = capture_output do
+ irb.eval_input
end
+ assert_empty err
+ assert_match(expected, out)
+ ensure
+ $VERBOSE = verbose
end
end
+ end
+
+ def test_object_inspection_handles_basic_object
+ verbose, $VERBOSE = $VERBOSE, nil
+ irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), TestInputMethod.new(["BasicObject.new"]))
+ out, err = capture_output do
+ irb.eval_input
+ end
+ assert_empty err
+ assert_not_match(/NoMethodError/, out)
+ assert_match(/#<BasicObject:.*>/, out)
ensure
$VERBOSE = verbose
end
- def test_default_config
- assert_equal(true, @context.use_colorize?)
- assert_equal(true, @context.use_autocomplete?)
- end
+ def test_object_inspection_falls_back_to_kernel_inspect_when_errored
+ verbose, $VERBOSE = $VERBOSE, nil
+ main = Object.new
+ main.singleton_class.module_eval <<~RUBY
+ class Foo
+ def inspect
+ raise "foo"
+ end
+ end
+ RUBY
- def test_assignment_expression
- input = TestInputMethod.new
- irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
- [
- "foo = bar",
- "@foo = bar",
- "$foo = bar",
- "@@foo = bar",
- "::Foo = bar",
- "a::Foo = bar",
- "Foo = bar",
- "foo.bar = 1",
- "foo[1] = bar",
- "foo += bar",
- "foo -= bar",
- "foo ||= bar",
- "foo &&= bar",
- "foo, bar = 1, 2",
- "foo.bar=(1)",
- "foo; foo = bar",
- "foo; foo = bar; ;\n ;",
- "foo\nfoo = bar",
- ].each do |exp|
- assert(
- irb.assignment_expression?(exp),
- "#{exp.inspect}: should be an assignment expression"
- )
+ irb = IRB::Irb.new(IRB::WorkSpace.new(main), TestInputMethod.new(["Foo.new"]))
+ out, err = capture_output do
+ irb.eval_input
end
+ assert_empty err
+ assert_match(/An error occurred when inspecting the object: #<RuntimeError: foo>/, out)
+ assert_match(/Result of Kernel#inspect: #<#<Class:.*>::Foo:/, out)
+ ensure
+ $VERBOSE = verbose
+ end
- [
- "foo",
- "foo.bar",
- "foo[0]",
- "foo = bar; foo",
- "foo = bar\nfoo",
- ].each do |exp|
- refute(
- irb.assignment_expression?(exp),
- "#{exp.inspect}: should not be an assignment expression"
- )
+ def test_object_inspection_prints_useful_info_when_kernel_inspect_also_errored
+ verbose, $VERBOSE = $VERBOSE, nil
+ main = Object.new
+ main.singleton_class.module_eval <<~RUBY
+ class Foo
+ def initialize
+ # Kernel#inspect goes through instance variables with #inspect
+ # So this will cause Kernel#inspect to fail
+ @foo = BasicObject.new
+ end
+
+ def inspect
+ raise "foo"
+ end
+ end
+ RUBY
+
+ irb = IRB::Irb.new(IRB::WorkSpace.new(main), TestInputMethod.new(["Foo.new"]))
+ out, err = capture_output do
+ irb.eval_input
end
+ assert_empty err
+ assert_match(/An error occurred when inspecting the object: #<RuntimeError: foo>/, out)
+ assert_match(/An error occurred when running Kernel#inspect: #<NoMethodError: undefined method (`|')inspect' for/, out)
+ ensure
+ $VERBOSE = verbose
+ end
+
+ def test_default_config
+ assert_equal(true, @context.use_autocomplete?)
end
def test_echo_on_assignment
@@ -322,99 +335,103 @@ module TestIRB
end
def test_omit_multiline_on_assignment
- input = TestInputMethod.new([
- "class A; def inspect; ([?* * 1000] * 3).join(%{\\n}); end; end; a = A.new\n",
- "a\n"
- ])
- value = ([?* * 1000] * 3).join(%{\n})
- value_first_line = (?* * 1000).to_s
- irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
- irb.context.return_format = "=> %s\n"
-
- irb.context.echo = true
- irb.context.echo_on_assignment = false
- out, err = capture_output do
- irb.eval_input
- end
- assert_empty err
- assert_equal("=> \n#{value}\n", out)
- irb.context.evaluate('A.remove_method(:inspect)', 0)
-
- input.reset
- irb.context.echo = true
- irb.context.echo_on_assignment = :truncate
- out, err = capture_output do
- irb.eval_input
- end
- assert_empty err
- assert_equal("=> #{value_first_line[0..(input.winsize.last - 9)]}...\e[0m\n=> \n#{value}\n", out)
- irb.context.evaluate('A.remove_method(:inspect)', 0)
-
- input.reset
- irb.context.echo = true
- irb.context.echo_on_assignment = true
- out, err = capture_output do
- irb.eval_input
- end
- assert_empty err
- assert_equal("=> \n#{value}\n=> \n#{value}\n", out)
- irb.context.evaluate('A.remove_method(:inspect)', 0)
-
- input.reset
- irb.context.echo = false
- irb.context.echo_on_assignment = false
- out, err = capture_output do
- irb.eval_input
- end
- assert_empty err
- assert_equal("", out)
- irb.context.evaluate('A.remove_method(:inspect)', 0)
-
- input.reset
- irb.context.echo = false
- irb.context.echo_on_assignment = :truncate
- out, err = capture_output do
- irb.eval_input
- end
- assert_empty err
- assert_equal("", out)
- irb.context.evaluate('A.remove_method(:inspect)', 0)
-
- input.reset
- irb.context.echo = false
- irb.context.echo_on_assignment = true
- out, err = capture_output do
- irb.eval_input
+ without_colorize do
+ input = TestInputMethod.new([
+ "class A; def inspect; ([?* * 1000] * 3).join(%{\\n}); end; end; a = A.new\n",
+ "a\n"
+ ])
+ value = ([?* * 1000] * 3).join(%{\n})
+ value_first_line = (?* * 1000).to_s
+ irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
+ irb.context.return_format = "=> %s\n"
+
+ irb.context.echo = true
+ irb.context.echo_on_assignment = false
+ out, err = capture_output do
+ irb.eval_input
+ end
+ assert_empty err
+ assert_equal("=> \n#{value}\n", out)
+ irb.context.evaluate_expression('A.remove_method(:inspect)', 0)
+
+ input.reset
+ irb.context.echo = true
+ irb.context.echo_on_assignment = :truncate
+ out, err = capture_output do
+ irb.eval_input
+ end
+ assert_empty err
+ assert_equal("=> #{value_first_line[0..(input.winsize.last - 9)]}...\n=> \n#{value}\n", out)
+ irb.context.evaluate_expression('A.remove_method(:inspect)', 0)
+
+ input.reset
+ irb.context.echo = true
+ irb.context.echo_on_assignment = true
+ out, err = capture_output do
+ irb.eval_input
+ end
+ assert_empty err
+ assert_equal("=> \n#{value}\n=> \n#{value}\n", out)
+ irb.context.evaluate_expression('A.remove_method(:inspect)', 0)
+
+ input.reset
+ irb.context.echo = false
+ irb.context.echo_on_assignment = false
+ out, err = capture_output do
+ irb.eval_input
+ end
+ assert_empty err
+ assert_equal("", out)
+ irb.context.evaluate_expression('A.remove_method(:inspect)', 0)
+
+ input.reset
+ irb.context.echo = false
+ irb.context.echo_on_assignment = :truncate
+ out, err = capture_output do
+ irb.eval_input
+ end
+ assert_empty err
+ assert_equal("", out)
+ irb.context.evaluate_expression('A.remove_method(:inspect)', 0)
+
+ input.reset
+ irb.context.echo = false
+ irb.context.echo_on_assignment = true
+ out, err = capture_output do
+ irb.eval_input
+ end
+ assert_empty err
+ assert_equal("", out)
+ irb.context.evaluate_expression('A.remove_method(:inspect)', 0)
end
- assert_empty err
- assert_equal("", out)
- irb.context.evaluate('A.remove_method(:inspect)', 0)
end
def test_echo_on_assignment_conf
# Default
IRB.conf[:ECHO] = nil
IRB.conf[:ECHO_ON_ASSIGNMENT] = nil
- input = TestInputMethod.new()
- irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
+ without_colorize do
+ input = TestInputMethod.new()
+ irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
- assert(irb.context.echo?, "echo? should be true by default")
- assert_equal(:truncate, irb.context.echo_on_assignment?, "echo_on_assignment? should be :truncate by default")
+ assert(irb.context.echo?, "echo? should be true by default")
+ assert_equal(:truncate, irb.context.echo_on_assignment?, "echo_on_assignment? should be :truncate by default")
- # Explicitly set :ECHO to false
- IRB.conf[:ECHO] = false
- irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
+ # Explicitly set :ECHO to false
+ IRB.conf[:ECHO] = false
+ irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
- refute(irb.context.echo?, "echo? should be false when IRB.conf[:ECHO] is set to false")
- assert_equal(:truncate, irb.context.echo_on_assignment?, "echo_on_assignment? should be :truncate by default")
+ refute(irb.context.echo?, "echo? should be false when IRB.conf[:ECHO] is set to false")
+ assert_equal(:truncate, irb.context.echo_on_assignment?, "echo_on_assignment? should be :truncate by default")
- # Explicitly set :ECHO_ON_ASSIGNMENT to true
- IRB.conf[:ECHO] = nil
- IRB.conf[:ECHO_ON_ASSIGNMENT] = false
- irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
+ # Explicitly set :ECHO_ON_ASSIGNMENT to true
+ IRB.conf[:ECHO] = nil
+ IRB.conf[:ECHO_ON_ASSIGNMENT] = false
+ irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
- assert(irb.context.echo?, "echo? should be true by default")
- refute(irb.context.echo_on_assignment?, "echo_on_assignment? should be false when IRB.conf[:ECHO_ON_ASSIGNMENT] is set to false")
+ assert(irb.context.echo?, "echo? should be true by default")
+ refute(irb.context.echo_on_assignment?, "echo_on_assignment? should be false when IRB.conf[:ECHO_ON_ASSIGNMENT] is set to false")
+ end
end
def test_multiline_output_on_default_inspector
@@ -422,29 +439,52 @@ module TestIRB
def main.inspect
"abc\ndef"
end
- input = TestInputMethod.new([
- "self"
- ])
- irb = IRB::Irb.new(IRB::WorkSpace.new(main), input)
- irb.context.return_format = "=> %s\n"
- # The default
- irb.context.newline_before_multiline_output = true
- out, err = capture_output do
- irb.eval_input
+ without_colorize do
+ input = TestInputMethod.new([
+ "self"
+ ])
+ irb = IRB::Irb.new(IRB::WorkSpace.new(main), input)
+ irb.context.return_format = "=> %s\n"
+
+ # The default
+ irb.context.newline_before_multiline_output = true
+ out, err = capture_output do
+ irb.eval_input
+ end
+ assert_empty err
+ assert_equal("=> \nabc\ndef\n",
+ out)
+
+ # No newline before multiline output
+ input.reset
+ irb.context.newline_before_multiline_output = false
+ out, err = capture_output do
+ irb.eval_input
+ end
+ assert_empty err
+ assert_equal("=> abc\ndef\n", out)
end
- assert_empty err
- assert_equal("=> \nabc\ndef\n",
- out)
+ end
- # No newline before multiline output
- input.reset
- irb.context.newline_before_multiline_output = false
+ def test_default_return_format
+ IRB.conf[:PROMPT][:MY_PROMPT] = {
+ :PROMPT_I => "%03n> ",
+ :PROMPT_S => "%03n> ",
+ :PROMPT_C => "%03n> "
+ # without :RETURN
+ # :RETURN => "%s\n"
+ }
+ IRB.conf[:PROMPT_MODE] = :MY_PROMPT
+ input = TestInputMethod.new([
+ "3"
+ ])
+ irb = IRB::Irb.new(IRB::WorkSpace.new(Object.new), input)
out, err = capture_output do
irb.eval_input
end
assert_empty err
- assert_equal("=> abc\ndef\n",
+ assert_equal("3\n",
out)
end
@@ -459,28 +499,35 @@ module TestIRB
irb.eval_input
end
assert_empty err
- if '2.5.0' <= RUBY_VERSION && RUBY_VERSION < '3.0.0' && STDOUT.tty?
- expected = [
- :*, /Traceback \(most recent call last\):\n/,
- :*, /\t 2: from \(irb\):1:in `<main>'\n/,
- :*, /\t 1: from \(irb\):1:in `hoge'\n/,
- :*, /\(irb\):1:in `fuga': unhandled exception\n/,
- ]
- else
- expected = [
- :*, /\(irb\):1:in `fuga': unhandled exception\n/,
- :*, /\tfrom \(irb\):1:in `hoge'\n/,
- :*, /\tfrom \(irb\):1:in `<main>'\n/,
- :*
- ]
- end
- assert_pattern_list(expected, out)
+ expected_output =
+ if RUBY_3_4
+ [
+ :*, /\(irb\):1:in 'fuga': unhandled exception\n/,
+ :*, /\tfrom \(irb\):1:in 'hoge'\n/,
+ :*, /\tfrom \(irb\):1:in '<main>'\n/,
+ :*
+ ]
+ elsif RUBY_VERSION < '3.0.0' && STDOUT.tty?
+ [
+ :*, /Traceback \(most recent call last\):\n/,
+ :*, /\t 2: from \(irb\):1:in `<main>'\n/,
+ :*, /\t 1: from \(irb\):1:in `hoge'\n/,
+ :*, /\(irb\):1:in `fuga': unhandled exception\n/,
+ ]
+ else
+ [
+ :*, /\(irb\):1:in `fuga': unhandled exception\n/,
+ :*, /\tfrom \(irb\):1:in `hoge'\n/,
+ :*, /\tfrom \(irb\):1:in `<main>'\n/,
+ :*
+ ]
+ end
+ assert_pattern_list(expected_output, out)
ensure
$VERBOSE = verbose
end
def test_eval_input_with_invalid_byte_sequence_exception
- pend if RUBY_ENGINE == 'truffleruby'
verbose, $VERBOSE = $VERBOSE, nil
input = TestInputMethod.new([
%Q{def hoge() fuga; end; def fuga() raise "A\\xF3B"; end; hoge\n},
@@ -490,22 +537,31 @@ module TestIRB
irb.eval_input
end
assert_empty err
- if '2.5.0' <= RUBY_VERSION && RUBY_VERSION < '3.0.0' && STDOUT.tty?
- expected = [
- :*, /Traceback \(most recent call last\):\n/,
- :*, /\t 2: from \(irb\):1:in `<main>'\n/,
- :*, /\t 1: from \(irb\):1:in `hoge'\n/,
- :*, /\(irb\):1:in `fuga': A\\xF3B \(RuntimeError\)\n/,
- ]
- else
- expected = [
- :*, /\(irb\):1:in `fuga': A\\xF3B \(RuntimeError\)\n/,
- :*, /\tfrom \(irb\):1:in `hoge'\n/,
- :*, /\tfrom \(irb\):1:in `<main>'\n/,
- :*
- ]
- end
- assert_pattern_list(expected, out)
+ expected_output =
+ if RUBY_3_4
+ [
+ :*, /\(irb\):1:in 'fuga': A\\xF3B \(RuntimeError\)\n/,
+ :*, /\tfrom \(irb\):1:in 'hoge'\n/,
+ :*, /\tfrom \(irb\):1:in '<main>'\n/,
+ :*
+ ]
+ elsif RUBY_VERSION < '3.0.0' && STDOUT.tty?
+ [
+ :*, /Traceback \(most recent call last\):\n/,
+ :*, /\t 2: from \(irb\):1:in `<main>'\n/,
+ :*, /\t 1: from \(irb\):1:in `hoge'\n/,
+ :*, /\(irb\):1:in `fuga': A\\xF3B \(RuntimeError\)\n/,
+ ]
+ else
+ [
+ :*, /\(irb\):1:in `fuga': A\\xF3B \(RuntimeError\)\n/,
+ :*, /\tfrom \(irb\):1:in `hoge'\n/,
+ :*, /\tfrom \(irb\):1:in `<main>'\n/,
+ :*
+ ]
+ end
+
+ assert_pattern_list(expected_output, out)
ensure
$VERBOSE = verbose
end
@@ -527,47 +583,47 @@ module TestIRB
irb.eval_input
end
assert_empty err
- if '2.5.0' <= RUBY_VERSION && RUBY_VERSION < '3.0.0' && STDOUT.tty?
+ if RUBY_VERSION < '3.0.0' && STDOUT.tty?
expected = [
:*, /Traceback \(most recent call last\):\n/,
:*, /\t... \d+ levels...\n/,
- :*, /\t16: from \(irb\):1:in `a4'\n/,
- :*, /\t15: from \(irb\):1:in `a5'\n/,
- :*, /\t14: from \(irb\):1:in `a6'\n/,
- :*, /\t13: from \(irb\):1:in `a7'\n/,
- :*, /\t12: from \(irb\):1:in `a8'\n/,
- :*, /\t11: from \(irb\):1:in `a9'\n/,
- :*, /\t10: from \(irb\):1:in `a10'\n/,
- :*, /\t 9: from \(irb\):1:in `a11'\n/,
- :*, /\t 8: from \(irb\):1:in `a12'\n/,
- :*, /\t 7: from \(irb\):1:in `a13'\n/,
- :*, /\t 6: from \(irb\):1:in `a14'\n/,
- :*, /\t 5: from \(irb\):1:in `a15'\n/,
- :*, /\t 4: from \(irb\):1:in `a16'\n/,
- :*, /\t 3: from \(irb\):1:in `a17'\n/,
- :*, /\t 2: from \(irb\):1:in `a18'\n/,
- :*, /\t 1: from \(irb\):1:in `a19'\n/,
- :*, /\(irb\):1:in `a20': unhandled exception\n/,
+ :*, /\t16: from \(irb\):1:in (`|')a4'\n/,
+ :*, /\t15: from \(irb\):1:in (`|')a5'\n/,
+ :*, /\t14: from \(irb\):1:in (`|')a6'\n/,
+ :*, /\t13: from \(irb\):1:in (`|')a7'\n/,
+ :*, /\t12: from \(irb\):1:in (`|')a8'\n/,
+ :*, /\t11: from \(irb\):1:in (`|')a9'\n/,
+ :*, /\t10: from \(irb\):1:in (`|')a10'\n/,
+ :*, /\t 9: from \(irb\):1:in (`|')a11'\n/,
+ :*, /\t 8: from \(irb\):1:in (`|')a12'\n/,
+ :*, /\t 7: from \(irb\):1:in (`|')a13'\n/,
+ :*, /\t 6: from \(irb\):1:in (`|')a14'\n/,
+ :*, /\t 5: from \(irb\):1:in (`|')a15'\n/,
+ :*, /\t 4: from \(irb\):1:in (`|')a16'\n/,
+ :*, /\t 3: from \(irb\):1:in (`|')a17'\n/,
+ :*, /\t 2: from \(irb\):1:in (`|')a18'\n/,
+ :*, /\t 1: from \(irb\):1:in (`|')a19'\n/,
+ :*, /\(irb\):1:in (`|')a20': unhandled exception\n/,
]
else
expected = [
- :*, /\(irb\):1:in `a20': unhandled exception\n/,
- :*, /\tfrom \(irb\):1:in `a19'\n/,
- :*, /\tfrom \(irb\):1:in `a18'\n/,
- :*, /\tfrom \(irb\):1:in `a17'\n/,
- :*, /\tfrom \(irb\):1:in `a16'\n/,
- :*, /\tfrom \(irb\):1:in `a15'\n/,
- :*, /\tfrom \(irb\):1:in `a14'\n/,
- :*, /\tfrom \(irb\):1:in `a13'\n/,
- :*, /\tfrom \(irb\):1:in `a12'\n/,
- :*, /\tfrom \(irb\):1:in `a11'\n/,
- :*, /\tfrom \(irb\):1:in `a10'\n/,
- :*, /\tfrom \(irb\):1:in `a9'\n/,
- :*, /\tfrom \(irb\):1:in `a8'\n/,
- :*, /\tfrom \(irb\):1:in `a7'\n/,
- :*, /\tfrom \(irb\):1:in `a6'\n/,
- :*, /\tfrom \(irb\):1:in `a5'\n/,
- :*, /\tfrom \(irb\):1:in `a4'\n/,
+ :*, /\(irb\):1:in (`|')a20': unhandled exception\n/,
+ :*, /\tfrom \(irb\):1:in (`|')a19'\n/,
+ :*, /\tfrom \(irb\):1:in (`|')a18'\n/,
+ :*, /\tfrom \(irb\):1:in (`|')a17'\n/,
+ :*, /\tfrom \(irb\):1:in (`|')a16'\n/,
+ :*, /\tfrom \(irb\):1:in (`|')a15'\n/,
+ :*, /\tfrom \(irb\):1:in (`|')a14'\n/,
+ :*, /\tfrom \(irb\):1:in (`|')a13'\n/,
+ :*, /\tfrom \(irb\):1:in (`|')a12'\n/,
+ :*, /\tfrom \(irb\):1:in (`|')a11'\n/,
+ :*, /\tfrom \(irb\):1:in (`|')a10'\n/,
+ :*, /\tfrom \(irb\):1:in (`|')a9'\n/,
+ :*, /\tfrom \(irb\):1:in (`|')a8'\n/,
+ :*, /\tfrom \(irb\):1:in (`|')a7'\n/,
+ :*, /\tfrom \(irb\):1:in (`|')a6'\n/,
+ :*, /\tfrom \(irb\):1:in (`|')a5'\n/,
+ :*, /\tfrom \(irb\):1:in (`|')a4'\n/,
:*, /\t... \d+ levels...\n/,
]
end
@@ -576,6 +632,43 @@ module TestIRB
$VERBOSE = verbose
end
+ def test_prompt_main_escape
+ main = Struct.new(:to_s).new("main\a\t\r\n")
+ irb = IRB::Irb.new(IRB::WorkSpace.new(main), TestInputMethod.new)
+ assert_equal("irb(main )>", irb.send(:format_prompt, 'irb(%m)>', nil, 1, 1))
+ end
+
+ def test_prompt_main_inspect_escape
+ main = Struct.new(:inspect).new("main\\n\nmain")
+ irb = IRB::Irb.new(IRB::WorkSpace.new(main), TestInputMethod.new)
+ assert_equal("irb(main\\n main)>", irb.send(:format_prompt, 'irb(%M)>', nil, 1, 1))
+ end
+
+ def test_prompt_main_truncate
+ main = Struct.new(:to_s).new("a" * 100)
+ def main.inspect; to_s.inspect; end
+ irb = IRB::Irb.new(IRB::WorkSpace.new(main), TestInputMethod.new)
+ assert_equal('irb(aaaaaaaaaaaaaaaaaaaaaaaaaaaaa...)>', irb.send(:format_prompt, 'irb(%m)>', nil, 1, 1))
+ assert_equal('irb("aaaaaaaaaaaaaaaaaaaaaaaaaaaa...)>', irb.send(:format_prompt, 'irb(%M)>', nil, 1, 1))
+ end
+
+ def test_prompt_main_raise
+ main = Object.new
+ def main.to_s; raise TypeError; end
+ def main.inspect; raise ArgumentError; end
+ irb = IRB::Irb.new(IRB::WorkSpace.new(main), TestInputMethod.new)
+ assert_equal("irb(!TypeError)>", irb.send(:format_prompt, 'irb(%m)>', nil, 1, 1))
+ assert_equal("irb(!ArgumentError)>", irb.send(:format_prompt, 'irb(%M)>', nil, 1, 1))
+ end
+
+ def test_prompt_format
+ main = 'main'
+ irb = IRB::Irb.new(IRB::WorkSpace.new(main), TestInputMethod.new)
+ assert_equal('%% main %m %main %%m >', irb.send(:format_prompt, '%%%% %m %%m %%%m %%%%m %l', '>', 1, 1))
+ assert_equal('42,%i, 42,%3i,042,%03i', irb.send(:format_prompt, '%i,%%i,%3i,%%3i,%03i,%%03i', nil, 42, 1))
+ assert_equal('42,%n, 42,%3n,042,%03n', irb.send(:format_prompt, '%n,%%n,%3n,%%3n,%03n,%%03n', nil, 1, 42))
+ end
+
def test_lineno
input = TestInputMethod.new([
"\n",
@@ -596,5 +689,40 @@ module TestIRB
:*, /\b6\n/,
], out)
end
+
+ def test_irb_path_setter
+ @context.irb_path = __FILE__
+ assert_equal(__FILE__, @context.irb_path)
+ assert_equal("#{__FILE__}(irb)", @context.instance_variable_get(:@eval_path))
+ @context.irb_path = 'file/does/not/exist'
+ assert_equal('file/does/not/exist', @context.irb_path)
+ assert_equal('file/does/not/exist', @context.instance_variable_get(:@eval_path))
+ @context.irb_path = "#{__FILE__}(irb)"
+ assert_equal("#{__FILE__}(irb)", @context.irb_path)
+ assert_equal("#{__FILE__}(irb)", @context.instance_variable_get(:@eval_path))
+ end
+
+ def test_build_completor
+ verbose, $VERBOSE = $VERBOSE, nil
+ original_completor = IRB.conf[:COMPLETOR]
+ IRB.conf[:COMPLETOR] = :regexp
+ assert_equal 'IRB::RegexpCompletor', @context.send(:build_completor).class.name
+ IRB.conf[:COMPLETOR] = :unknown
+ assert_equal 'IRB::RegexpCompletor', @context.send(:build_completor).class.name
+ # :type is tested in test_type_completor.rb
+ ensure
+ $VERBOSE = verbose
+ IRB.conf[:COMPLETOR] = original_completor
+ end
+
+ private
+
+ def without_colorize
+ original_value = IRB.conf[:USE_COLORIZE]
+ IRB.conf[:USE_COLORIZE] = false
+ yield
+ ensure
+ IRB.conf[:USE_COLORIZE] = original_value
+ end
end
end
diff --git a/test/irb/test_debugger_integration.rb b/test/irb/test_debugger_integration.rb
new file mode 100644
index 0000000000..8b1bddea17
--- /dev/null
+++ b/test/irb/test_debugger_integration.rb
@@ -0,0 +1,496 @@
+# frozen_string_literal: true
+
+require "tempfile"
+require "tmpdir"
+
+require_relative "helper"
+
+module TestIRB
+ class DebuggerIntegrationTest < IntegrationTestCase
+ def setup
+ super
+
+ if RUBY_ENGINE == 'truffleruby'
+ omit "This test runs with ruby/debug, which doesn't work with truffleruby"
+ end
+
+ @envs.merge!("NO_COLOR" => "true", "RUBY_DEBUG_HISTORY_FILE" => '')
+ end
+
+ def test_backtrace
+ write_ruby <<~'RUBY'
+ def foo
+ binding.irb
+ end
+ foo
+ RUBY
+
+ output = run_ruby_file do
+ type "backtrace"
+ type "exit!"
+ end
+
+ assert_match(/irb\(main\):001> backtrace/, output)
+ assert_match(/Object#foo at #{@ruby_file.to_path}/, output)
+ end
+
+ def test_debug
+ write_ruby <<~'ruby'
+ binding.irb
+ puts "hello"
+ ruby
+
+ output = run_ruby_file do
+ type "debug"
+ type "next"
+ type "continue"
+ end
+
+ assert_match(/irb\(main\):001> debug/, output)
+ assert_match(/irb:rdbg\(main\):002> next/, output)
+ assert_match(/=> 2\| puts "hello"/, output)
+ end
+
+ def test_debug_command_only_runs_once
+ write_ruby <<~'ruby'
+ binding.irb
+ ruby
+
+ output = run_ruby_file do
+ type "debug"
+ type "debug"
+ type "continue"
+ end
+
+ assert_match(/irb\(main\):001> debug/, output)
+ assert_match(/irb:rdbg\(main\):002> debug/, output)
+ assert_match(/IRB is already running with a debug session/, output)
+ end
+
+ def test_debug_command_can_only_be_called_from_binding_irb
+ write_ruby <<~'ruby'
+ require "irb"
+ # trick test framework
+ puts "binding.irb"
+ IRB.start
+ ruby
+
+ output = run_ruby_file do
+ type "debug"
+ type "exit"
+ end
+
+ assert_include(output, "Debugging commands are only available when IRB is started with binding.irb")
+ end
+
+ def test_next
+ write_ruby <<~'ruby'
+ binding.irb
+ puts "hello"
+ ruby
+
+ output = run_ruby_file do
+ type "next"
+ type "continue"
+ end
+
+ assert_match(/irb\(main\):001> next/, output)
+ assert_match(/=> 2\| puts "hello"/, output)
+ end
+
+ def test_break
+ write_ruby <<~'RUBY'
+ binding.irb
+ puts "Hello"
+ RUBY
+
+ output = run_ruby_file do
+ type "break 2"
+ type "continue"
+ type "continue"
+ end
+
+ assert_match(/irb\(main\):001> break/, output)
+ assert_match(/=> 2\| puts "Hello"/, output)
+ end
+
+ def test_delete
+ write_ruby <<~'RUBY'
+ binding.irb
+ puts "Hello"
+ binding.irb
+ puts "World"
+ RUBY
+
+ output = run_ruby_file do
+ type "break 4"
+ type "continue"
+ type "delete 0"
+ type "continue"
+ end
+
+ assert_match(/irb:rdbg\(main\):003> delete/, output)
+ assert_match(/deleted: #0 BP - Line/, output)
+ end
+
+ def test_step
+ write_ruby <<~'RUBY'
+ def foo
+ puts "Hello"
+ end
+ binding.irb
+ foo
+ RUBY
+
+ output = run_ruby_file do
+ type "step"
+ type "step"
+ type "continue"
+ end
+
+ assert_match(/irb\(main\):001> step/, output)
+ assert_match(/=> 5\| foo/, output)
+ assert_match(/=> 2\| puts "Hello"/, output)
+ end
+
+ def test_long_stepping
+ write_ruby <<~'RUBY'
+ class Foo
+ def foo(num)
+ bar(num + 10)
+ end
+
+ def bar(num)
+ num
+ end
+ end
+
+ binding.irb
+ Foo.new.foo(100)
+ RUBY
+
+ output = run_ruby_file do
+ type "step"
+ type "step"
+ type "step"
+ type "step"
+ type "num"
+ type "continue"
+ end
+
+ assert_match(/irb\(main\):001> step/, output)
+ assert_match(/irb:rdbg\(main\):002> step/, output)
+ assert_match(/irb:rdbg\(#<Foo:.*>\):003> step/, output)
+ assert_match(/irb:rdbg\(#<Foo:.*>\):004> step/, output)
+ assert_match(/irb:rdbg\(#<Foo:.*>\):005> num/, output)
+ assert_match(/=> 110/, output)
+ end
+
+ def test_continue
+ write_ruby <<~'RUBY'
+ binding.irb
+ puts "Hello"
+ binding.irb
+ puts "World"
+ RUBY
+
+ output = run_ruby_file do
+ type "continue"
+ type "continue"
+ end
+
+ assert_match(/irb\(main\):001> continue/, output)
+ assert_match(/=> 3: binding.irb/, output)
+ assert_match(/irb:rdbg\(main\):002> continue/, output)
+ end
+
+ def test_finish
+ write_ruby <<~'RUBY'
+ def foo
+ binding.irb
+ puts "Hello"
+ end
+ foo
+ RUBY
+
+ output = run_ruby_file do
+ type "finish"
+ type "continue"
+ end
+
+ assert_match(/irb\(main\):001> finish/, output)
+ assert_match(/=> 4\| end/, output)
+ end
+
+ def test_info
+ write_ruby <<~'RUBY'
+ def foo
+ a = "He" + "llo"
+ binding.irb
+ end
+ foo
+ RUBY
+
+ output = run_ruby_file do
+ type "info"
+ type "continue"
+ end
+
+ assert_match(/irb\(main\):001> info/, output)
+ assert_match(/%self = main/, output)
+ assert_match(/a = "Hello"/, output)
+ end
+
+ def test_catch
+ write_ruby <<~'RUBY'
+ binding.irb
+ 1 / 0
+ RUBY
+
+ output = run_ruby_file do
+ type "catch ZeroDivisionError"
+ type "continue"
+ type "continue"
+ end
+
+ assert_match(/irb\(main\):001> catch/, output)
+ assert_match(/Stop by #0 BP - Catch "ZeroDivisionError"/, output)
+ end
+
+ def test_exit
+ write_ruby <<~'RUBY'
+ binding.irb
+ puts "he" + "llo"
+ RUBY
+
+ output = run_ruby_file do
+ type "debug"
+ type "exit"
+ end
+
+ assert_match(/irb:rdbg\(main\):002>/, output)
+ assert_match(/hello/, output)
+ end
+
+ def test_force_exit
+ write_ruby <<~'RUBY'
+ binding.irb
+ puts "he" + "llo"
+ RUBY
+
+ output = run_ruby_file do
+ type "debug"
+ type "exit!"
+ end
+
+ assert_match(/irb:rdbg\(main\):002>/, output)
+ assert_not_match(/hello/, output)
+ end
+
+ def test_quit
+ write_ruby <<~'RUBY'
+ binding.irb
+ puts "he" + "llo"
+ RUBY
+
+ output = run_ruby_file do
+ type "debug"
+ type "quit!"
+ end
+
+ assert_match(/irb:rdbg\(main\):002>/, output)
+ assert_not_match(/hello/, output)
+ end
+
+ def test_prompt_line_number_continues
+ write_ruby <<~'ruby'
+ binding.irb
+ puts "Hello"
+ puts "World"
+ ruby
+
+ output = run_ruby_file do
+ type "123"
+ type "456"
+ type "next"
+ type "info"
+ type "next"
+ type "continue"
+ end
+
+ assert_match(/irb\(main\):003> next/, output)
+ assert_match(/irb:rdbg\(main\):004> info/, output)
+ assert_match(/irb:rdbg\(main\):005> next/, output)
+ end
+
+ def test_prompt_irb_name_is_kept
+ write_rc <<~RUBY
+ IRB.conf[:IRB_NAME] = "foo"
+ RUBY
+
+ write_ruby <<~'ruby'
+ binding.irb
+ puts "Hello"
+ ruby
+
+ output = run_ruby_file do
+ type "next"
+ type "continue"
+ end
+
+ assert_match(/foo\(main\):001> next/, output)
+ assert_match(/foo:rdbg\(main\):002> continue/, output)
+ end
+
+ def test_irb_commands_are_available_after_moving_around_with_the_debugger
+ write_ruby <<~'ruby'
+ class Foo
+ def bar
+ puts "bar"
+ end
+ end
+
+ binding.irb
+ Foo.new.bar
+ ruby
+
+ output = run_ruby_file do
+ # Due to the way IRB defines its commands, moving into the Foo instance from main is necessary for proper testing.
+ type "next"
+ type "step"
+ type "irb_info"
+ type "continue"
+ end
+
+ assert_include(output, "InputMethod: RelineInputMethod")
+ end
+
+ def test_help_command_is_delegated_to_the_debugger
+ write_ruby <<~'ruby'
+ binding.irb
+ ruby
+
+ output = run_ruby_file do
+ type "debug"
+ type "help"
+ type "continue"
+ end
+
+ assert_include(output, "### Frame control")
+ end
+
+ def test_help_display_different_content_when_debugger_is_enabled
+ write_ruby <<~'ruby'
+ binding.irb
+ ruby
+
+ output = run_ruby_file do
+ type "debug"
+ type "help"
+ type "continue"
+ end
+
+ # IRB's commands should still be listed
+ assert_match(/help\s+List all available commands/, output)
+ # debug gem's commands should be appended at the end
+ assert_match(/Debugging \(from debug\.gem\)\s+### Control flow/, output)
+ end
+
+ def test_input_is_evaluated_in_the_context_of_the_current_thread
+ write_ruby <<~'ruby'
+ current_thread = Thread.current
+ binding.irb
+ ruby
+
+ output = run_ruby_file do
+ type "debug"
+ type '"Threads match: #{current_thread == Thread.current}"'
+ type "continue"
+ end
+
+ assert_match(/irb\(main\):001> debug/, output)
+ assert_match(/Threads match: true/, output)
+ end
+
+ def test_irb_switches_debugger_interface_if_debug_was_already_activated
+ write_ruby <<~'ruby'
+ require 'debug'
+ class Foo
+ def bar
+ puts "bar"
+ end
+ end
+
+ binding.irb
+ Foo.new.bar
+ ruby
+
+ output = run_ruby_file do
+ # Due to the way IRB defines its commands, moving into the Foo instance from main is necessary for proper testing.
+ type "next"
+ type "step"
+ type 'irb_info'
+ type "continue"
+ end
+
+ assert_match(/irb\(main\):001> next/, output)
+ assert_include(output, "InputMethod: RelineInputMethod")
+ end
+
+ def test_debugger_cant_be_activated_while_multi_irb_is_active
+ write_ruby <<~'ruby'
+ binding.irb
+ a = 1
+ ruby
+
+ output = run_ruby_file do
+ type "jobs"
+ type "next"
+ type "exit"
+ end
+
+ assert_match(/irb\(main\):001> jobs/, output)
+ assert_include(output, "Can't start the debugger when IRB is running in a multi-IRB session.")
+ end
+
+ def test_multi_irb_commands_are_not_available_after_activating_the_debugger
+ write_ruby <<~'ruby'
+ binding.irb
+ a = 1
+ ruby
+
+ output = run_ruby_file do
+ type "next"
+ type "jobs"
+ type "continue"
+ end
+
+ assert_match(/irb\(main\):001> next/, output)
+ assert_include(output, "Multi-IRB commands are not available when the debugger is enabled.")
+ end
+
+ def test_irb_passes_empty_input_to_debugger_to_repeat_the_last_command
+ write_ruby <<~'ruby'
+ binding.irb
+ puts "foo"
+ puts "bar"
+ puts "baz"
+ ruby
+
+ output = run_ruby_file do
+ type "next"
+ type ""
+ # Test that empty input doesn't repeat expressions
+ type "123"
+ type ""
+ type "next"
+ type ""
+ type ""
+ end
+
+ assert_include(output, "=> 2\| puts \"foo\"")
+ assert_include(output, "=> 3\| puts \"bar\"")
+ assert_include(output, "=> 4\| puts \"baz\"")
+ end
+ end
+end
diff --git a/test/irb/test_eval_history.rb b/test/irb/test_eval_history.rb
new file mode 100644
index 0000000000..54913ceff5
--- /dev/null
+++ b/test/irb/test_eval_history.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+require "irb"
+
+require_relative "helper"
+
+module TestIRB
+ class EvalHistoryTest < TestCase
+ def setup
+ save_encodings
+ IRB.instance_variable_get(:@CONF).clear
+ end
+
+ def teardown
+ restore_encodings
+ end
+
+ def execute_lines(*lines, conf: {}, main: self, irb_path: nil)
+ IRB.init_config(nil)
+ IRB.conf[:VERBOSE] = false
+ IRB.conf[:PROMPT_MODE] = :SIMPLE
+ IRB.conf[:USE_PAGER] = false
+ IRB.conf.merge!(conf)
+ input = TestInputMethod.new(lines)
+ irb = IRB::Irb.new(IRB::WorkSpace.new(main), input)
+ irb.context.return_format = "=> %s\n"
+ irb.context.irb_path = irb_path if irb_path
+ IRB.conf[:MAIN_CONTEXT] = irb.context
+ capture_output do
+ irb.eval_input
+ end
+ end
+
+ def test_eval_history_is_disabled_by_default
+ out, err = execute_lines(
+ "a = 1",
+ "__"
+ )
+
+ assert_empty(err)
+ assert_match(/undefined local variable or method (`|')__'/, out)
+ end
+
+ def test_eval_history_can_be_retrieved_with_double_underscore
+ out, err = execute_lines(
+ "a = 1",
+ "__",
+ conf: { EVAL_HISTORY: 5 }
+ )
+
+ assert_empty(err)
+ assert_match("=> 1\n" + "=> 1 1\n", out)
+ end
+
+ def test_eval_history_respects_given_limit
+ out, err = execute_lines(
+ "'foo'\n",
+ "'bar'\n",
+ "'baz'\n",
+ "'xyz'\n",
+ "__",
+ conf: { EVAL_HISTORY: 4 }
+ )
+
+ assert_empty(err)
+ # Because eval_history injects `__` into the history AND decide to ignore it, we only get <limit> - 1 results
+ assert_match("2 \"bar\"\n" + "3 \"baz\"\n" + "4 \"xyz\"\n", out)
+ end
+ end
+end
diff --git a/test/irb/test_evaluation.rb b/test/irb/test_evaluation.rb
new file mode 100644
index 0000000000..adb69b2067
--- /dev/null
+++ b/test/irb/test_evaluation.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+require "tempfile"
+
+require_relative "helper"
+
+module TestIRB
+ class EchoingTest < IntegrationTestCase
+ def test_irb_echos_by_default
+ write_ruby <<~'RUBY'
+ binding.irb
+ RUBY
+
+ output = run_ruby_file do
+ type "123123"
+ type "exit"
+ end
+
+ assert_include(output, "=> 123123")
+ end
+
+ def test_irb_doesnt_echo_line_with_semicolon
+ write_ruby <<~'RUBY'
+ binding.irb
+ RUBY
+
+ output = run_ruby_file do
+ type "123123;"
+ type "123123 ;"
+ type "123123; "
+ type <<~RUBY
+ if true
+ 123123
+ end;
+ RUBY
+ type "'evaluation ends'"
+ type "exit"
+ end
+
+ assert_include(output, "=> \"evaluation ends\"")
+ assert_not_include(output, "=> 123123")
+ end
+ end
+end
diff --git a/test/irb/test_helper_method.rb b/test/irb/test_helper_method.rb
new file mode 100644
index 0000000000..291278c16a
--- /dev/null
+++ b/test/irb/test_helper_method.rb
@@ -0,0 +1,134 @@
+# frozen_string_literal: true
+require "irb"
+
+require_relative "helper"
+
+module TestIRB
+ class HelperMethodTestCase < TestCase
+ def setup
+ $VERBOSE = nil
+ @verbosity = $VERBOSE
+ save_encodings
+ IRB.instance_variable_get(:@CONF).clear
+ end
+
+ def teardown
+ $VERBOSE = @verbosity
+ restore_encodings
+ end
+
+ def execute_lines(*lines, conf: {}, main: self, irb_path: nil)
+ IRB.init_config(nil)
+ IRB.conf[:VERBOSE] = false
+ IRB.conf[:PROMPT_MODE] = :SIMPLE
+ IRB.conf.merge!(conf)
+ input = TestInputMethod.new(lines)
+ irb = IRB::Irb.new(IRB::WorkSpace.new(main), input)
+ irb.context.return_format = "=> %s\n"
+ irb.context.irb_path = irb_path if irb_path
+ IRB.conf[:MAIN_CONTEXT] = irb.context
+ IRB.conf[:USE_PAGER] = false
+ capture_output do
+ irb.eval_input
+ end
+ end
+ end
+
+ module TestHelperMethod
+ class ConfTest < HelperMethodTestCase
+ def test_conf_returns_the_context_object
+ out, err = execute_lines("conf.ap_name")
+
+ assert_empty err
+ assert_include out, "=> \"irb\""
+ end
+ end
+ end
+
+ class HelperMethodIntegrationTest < IntegrationTestCase
+ def test_arguments_propogation
+ write_ruby <<~RUBY
+ require "irb/helper_method"
+
+ class MyHelper < IRB::HelperMethod::Base
+ description "This is a test helper"
+
+ def execute(
+ required_arg, optional_arg = nil, *splat_arg, required_keyword_arg:,
+ optional_keyword_arg: nil, **double_splat_arg, &block_arg
+ )
+ puts [required_arg, optional_arg, splat_arg, required_keyword_arg, optional_keyword_arg, double_splat_arg, block_arg.call].to_s
+ end
+ end
+
+ IRB::HelperMethod.register(:my_helper, MyHelper)
+
+ binding.irb
+ RUBY
+
+ output = run_ruby_file do
+ type <<~INPUT
+ my_helper(
+ "required", "optional", "splat", required_keyword_arg: "required",
+ optional_keyword_arg: "optional", a: 1, b: 2
+ ) { "block" }
+ INPUT
+ type "exit"
+ end
+
+ assert_include(output, '["required", "optional", ["splat"], "required", "optional", {:a=>1, :b=>2}, "block"]')
+ end
+
+ def test_helper_method_injection_can_happen_after_irb_require
+ write_ruby <<~RUBY
+ require "irb"
+
+ class MyHelper < IRB::HelperMethod::Base
+ description "This is a test helper"
+
+ def execute
+ puts "Hello from MyHelper"
+ end
+ end
+
+ IRB::HelperMethod.register(:my_helper, MyHelper)
+
+ binding.irb
+ RUBY
+
+ output = run_ruby_file do
+ type "my_helper"
+ type "exit"
+ end
+
+ assert_include(output, 'Hello from MyHelper')
+ end
+
+ def test_helper_method_instances_are_memoized
+ write_ruby <<~RUBY
+ require "irb/helper_method"
+
+ class MyHelper < IRB::HelperMethod::Base
+ description "This is a test helper"
+
+ def execute(val)
+ @val ||= val
+ end
+ end
+
+ IRB::HelperMethod.register(:my_helper, MyHelper)
+
+ binding.irb
+ RUBY
+
+ output = run_ruby_file do
+ type "my_helper(100)"
+ type "my_helper(200)"
+ type "exit"
+ end
+
+ assert_include(output, '=> 100')
+ assert_not_include(output, '=> 200')
+ end
+ end
+end
diff --git a/test/irb/test_history.rb b/test/irb/test_history.rb
index 81b7fe8679..84f0438929 100644
--- a/test/irb/test_history.rb
+++ b/test/irb/test_history.rb
@@ -1,51 +1,42 @@
# frozen_string_literal: false
-require 'test/unit'
require 'irb'
-require 'irb/ext/save-history'
require 'readline'
+require "tempfile"
+
+require_relative "helper"
+
+return if RUBY_PLATFORM.match?(/solaris|mswin|mingw/i)
module TestIRB
- class TestHistory < Test::Unit::TestCase
+ class HistoryTest < TestCase
def setup
- IRB.conf[:RC_NAME_GENERATOR] = nil
+ @original_verbose, $VERBOSE = $VERBOSE, nil
+ @tmpdir = Dir.mktmpdir("test_irb_history_")
+ setup_envs(home: @tmpdir)
+ @backup_default_external = Encoding.default_external
+ IRB.instance_variable_set(:@existing_rc_name_generators, nil)
end
def teardown
- IRB.conf[:RC_NAME_GENERATOR] = nil
+ IRB.instance_variable_set(:@existing_rc_name_generators, nil)
+ teardown_envs
+ Encoding.default_external = @backup_default_external
+ $VERBOSE = @original_verbose
+ FileUtils.rm_rf(@tmpdir)
end
- class TestInputMethod < ::IRB::InputMethod
- HISTORY = Array.new
+ class TestInputMethodWithRelineHistory < TestInputMethod
+ # When IRB.conf[:USE_MULTILINE] is true, IRB::RelineInputMethod uses Reline::History
+ HISTORY = Reline::History.new(Reline.core.config)
include IRB::HistorySavingAbility
+ end
- attr_reader :list, :line_no
-
- def initialize(list = [])
- super("test")
- @line_no = 0
- @list = list
- end
-
- def gets
- @list[@line_no]&.tap {@line_no += 1}
- end
-
- def eof?
- @line_no >= @list.size
- end
-
- def encoding
- Encoding.default_external
- end
-
- def reset
- @line_no = 0
- end
+ class TestInputMethodWithReadlineHistory < TestInputMethod
+ # When IRB.conf[:USE_MULTILINE] is false, IRB::ReadlineInputMethod uses Readline::HISTORY
+ HISTORY = Readline::HISTORY
- def winsize
- [10, 20]
- end
+ include IRB::HistorySavingAbility
end
def test_history_save_1
@@ -127,10 +118,80 @@ module TestIRB
INPUT
end
- def test_history_concurrent_use
+ def test_history_concurrent_use_reline
omit "Skip Editline" if /EditLine/n.match(Readline::VERSION)
IRB.conf[:SAVE_HISTORY] = 1
- assert_history(<<~EXPECTED_HISTORY, <<~INITIAL_HISTORY, <<~INPUT) do |history_file|
+ history_concurrent_use_for_input_method(TestInputMethodWithRelineHistory)
+ end
+
+ def test_history_concurrent_use_readline
+ omit "Skip Editline" if /EditLine/n.match(Readline::VERSION)
+ IRB.conf[:SAVE_HISTORY] = 1
+ history_concurrent_use_for_input_method(TestInputMethodWithReadlineHistory)
+ end
+
+ def test_history_concurrent_use_not_present
+ IRB.conf[:LC_MESSAGES] = IRB::Locale.new
+ IRB.conf[:SAVE_HISTORY] = 1
+ io = TestInputMethodWithRelineHistory.new
+ io.class::HISTORY.clear
+ io.load_history
+ io.class::HISTORY << 'line1'
+ io.class::HISTORY << 'line2'
+
+ history_file = IRB.rc_file("_history")
+ assert_not_send [File, :file?, history_file]
+ File.write(history_file, "line0\n")
+ io.save_history
+ assert_equal(%w"line0 line1 line2", File.read(history_file).split)
+ end
+
+ def test_history_different_encodings
+ IRB.conf[:SAVE_HISTORY] = 2
+ Encoding.default_external = Encoding::US_ASCII
+ locale = IRB::Locale.new("C")
+ assert_history(<<~EXPECTED_HISTORY.encode(Encoding::US_ASCII), <<~INITIAL_HISTORY.encode(Encoding::UTF_8), <<~INPUT, locale: locale)
+ ????
+ exit
+ EXPECTED_HISTORY
+ 😀
+ INITIAL_HISTORY
+ exit
+ INPUT
+ end
+
+ def test_history_does_not_raise_when_history_file_directory_does_not_exist
+ backup_history_file = IRB.conf[:HISTORY_FILE]
+ IRB.conf[:SAVE_HISTORY] = 1
+ IRB.conf[:HISTORY_FILE] = "fake/fake/fake/history_file"
+ io = TestInputMethodWithRelineHistory.new
+
+ assert_warn(/history file does not exist/) do
+ io.save_history
+ end
+
+ # assert_warn reverts $VERBOSE to EnvUtil.original_verbose, which is true in some cases
+ # We want to keep $VERBOSE as nil until teardown is called
+ # TODO: check if this is an assert_warn issue
+ $VERBOSE = nil
+ ensure
+ IRB.conf[:HISTORY_FILE] = backup_history_file
+ end
+
+ def test_no_home_no_history_file_does_not_raise_history_save
+ ENV['HOME'] = nil
+ io = TestInputMethodWithRelineHistory.new
+ assert_nil(IRB.rc_file('_history'))
+ assert_nothing_raised do
+ io.load_history
+ io.save_history
+ end
+ end
+
+ private
+
+ def history_concurrent_use_for_input_method(input_method)
+ assert_history(<<~EXPECTED_HISTORY, <<~INITIAL_HISTORY, <<~INPUT, input_method) do |history_file|
exit
5
exit
@@ -143,7 +204,7 @@ module TestIRB
5
exit
INPUT
- assert_history(<<~EXPECTED_HISTORY2, <<~INITIAL_HISTORY2, <<~INPUT2)
+ assert_history(<<~EXPECTED_HISTORY2, <<~INITIAL_HISTORY2, <<~INPUT2, input_method)
exit
EXPECTED_HISTORY2
1
@@ -158,35 +219,31 @@ module TestIRB
end
end
- private
-
- def assert_history(expected_history, initial_irb_history, input)
- backup_verbose, $VERBOSE = $VERBOSE, nil
- backup_home = ENV["HOME"]
- backup_xdg_config_home = ENV.delete("XDG_CONFIG_HOME")
- IRB.conf[:LC_MESSAGES] = IRB::Locale.new
+ def assert_history(expected_history, initial_irb_history, input, input_method = TestInputMethodWithRelineHistory, locale: IRB::Locale.new)
+ IRB.conf[:LC_MESSAGES] = locale
actual_history = nil
- Dir.mktmpdir("test_irb_history_#{$$}") do |tmpdir|
- ENV["HOME"] = tmpdir
- open(IRB.rc_file("_history"), "w") do |f|
- f.write(initial_irb_history)
- end
+ history_file = IRB.rc_file("_history")
+ ENV["HOME"] = @tmpdir
+ File.open(history_file, "w") do |f|
+ f.write(initial_irb_history)
+ end
- io = TestInputMethod.new
+ io = input_method.new
+ io.class::HISTORY.clear
+ io.load_history
+ if block_given?
+ previous_history = []
+ io.class::HISTORY.each { |line| previous_history << line }
+ yield history_file
io.class::HISTORY.clear
- io.load_history
- if block_given?
- history = io.class::HISTORY.dup
- yield IRB.rc_file("_history")
- io.class::HISTORY.replace(history)
- end
- io.class::HISTORY.concat(input.split)
- io.save_history
+ previous_history.each { |line| io.class::HISTORY << line }
+ end
+ input.split.each { |line| io.class::HISTORY << line }
+ io.save_history
- io.load_history
- open(IRB.rc_file("_history"), "r") do |f|
- actual_history = f.read
- end
+ io.load_history
+ File.open(history_file, "r") do |f|
+ actual_history = f.read
end
assert_equal(expected_history, actual_history, <<~MESSAGE)
expected:
@@ -194,10 +251,6 @@ module TestIRB
but actual:
#{actual_history}
MESSAGE
- ensure
- $VERBOSE = backup_verbose
- ENV["HOME"] = backup_home
- ENV["XDG_CONFIG_HOME"] = backup_xdg_config_home
end
def with_temp_stdio
@@ -208,4 +261,226 @@ module TestIRB
end
end
end
-end if not RUBY_PLATFORM.match?(/solaris|mswin|mingw/i)
+
+ class IRBHistoryIntegrationTest < IntegrationTestCase
+ def test_history_saving_with_debug
+ write_history ""
+
+ write_ruby <<~'RUBY'
+ def foo
+ end
+
+ binding.irb
+
+ foo
+ RUBY
+
+ output = run_ruby_file do
+ type "'irb session'"
+ type "next"
+ type "'irb:debug session'"
+ type "step"
+ type "irb_info"
+ type "puts Reline::HISTORY.to_a.to_s"
+ type "q!"
+ end
+
+ assert_include(output, "InputMethod: RelineInputMethod")
+ # check that in-memory history is preserved across sessions
+ assert_include output, %q(
+ ["'irb session'", "next", "'irb:debug session'", "step", "irb_info", "puts Reline::HISTORY.to_a.to_s"]
+ ).strip
+
+ assert_equal <<~HISTORY, @history_file.open.read
+ 'irb session'
+ next
+ 'irb:debug session'
+ step
+ irb_info
+ puts Reline::HISTORY.to_a.to_s
+ q!
+ HISTORY
+ end
+
+ def test_history_saving_with_debug_without_prior_history
+ tmpdir = Dir.mktmpdir("test_irb_history_")
+ # Intentionally not creating the file so we test the reset counter logic
+ history_file = File.join(tmpdir, "irb_history")
+
+ write_rc <<~RUBY
+ IRB.conf[:HISTORY_FILE] = "#{history_file}"
+ RUBY
+
+ write_ruby <<~'RUBY'
+ def foo
+ end
+
+ binding.irb
+
+ foo
+ RUBY
+
+ output = run_ruby_file do
+ type "'irb session'"
+ type "next"
+ type "'irb:debug session'"
+ type "step"
+ type "irb_info"
+ type "puts Reline::HISTORY.to_a.to_s"
+ type "q!"
+ end
+
+ assert_include(output, "InputMethod: RelineInputMethod")
+ # check that in-memory history is preserved across sessions
+ assert_include output, %q(
+ ["'irb session'", "next", "'irb:debug session'", "step", "irb_info", "puts Reline::HISTORY.to_a.to_s"]
+ ).strip
+
+ assert_equal <<~HISTORY, File.read(history_file)
+ 'irb session'
+ next
+ 'irb:debug session'
+ step
+ irb_info
+ puts Reline::HISTORY.to_a.to_s
+ q!
+ HISTORY
+ ensure
+ FileUtils.rm_rf(tmpdir)
+ end
+
+ def test_history_saving_with_nested_sessions
+ write_history ""
+
+ write_ruby <<~'RUBY'
+ def foo
+ binding.irb
+ end
+
+ binding.irb
+ RUBY
+
+ run_ruby_file do
+ type "'outer session'"
+ type "foo"
+ type "'inner session'"
+ type "exit"
+ type "'outer session again'"
+ type "exit"
+ end
+
+ assert_equal <<~HISTORY, @history_file.open.read
+ 'outer session'
+ foo
+ 'inner session'
+ exit
+ 'outer session again'
+ exit
+ HISTORY
+ end
+
+ def test_nested_history_saving_from_inner_session_with_exit!
+ write_history ""
+
+ write_ruby <<~'RUBY'
+ def foo
+ binding.irb
+ end
+
+ binding.irb
+ RUBY
+
+ run_ruby_file do
+ type "'outer session'"
+ type "foo"
+ type "'inner session'"
+ type "exit!"
+ end
+
+ assert_equal <<~HISTORY, @history_file.open.read
+ 'outer session'
+ foo
+ 'inner session'
+ exit!
+ HISTORY
+ end
+
+ def test_nested_history_saving_from_outer_session_with_exit!
+ write_history ""
+
+ write_ruby <<~'RUBY'
+ def foo
+ binding.irb
+ end
+
+ binding.irb
+ RUBY
+
+ run_ruby_file do
+ type "'outer session'"
+ type "foo"
+ type "'inner session'"
+ type "exit"
+ type "'outer session again'"
+ type "exit!"
+ end
+
+ assert_equal <<~HISTORY, @history_file.open.read
+ 'outer session'
+ foo
+ 'inner session'
+ exit
+ 'outer session again'
+ exit!
+ HISTORY
+ end
+
+ def test_history_saving_with_nested_sessions_and_prior_history
+ write_history <<~HISTORY
+ old_history_1
+ old_history_2
+ old_history_3
+ HISTORY
+
+ write_ruby <<~'RUBY'
+ def foo
+ binding.irb
+ end
+
+ binding.irb
+ RUBY
+
+ run_ruby_file do
+ type "'outer session'"
+ type "foo"
+ type "'inner session'"
+ type "exit"
+ type "'outer session again'"
+ type "exit"
+ end
+
+ assert_equal <<~HISTORY, @history_file.open.read
+ old_history_1
+ old_history_2
+ old_history_3
+ 'outer session'
+ foo
+ 'inner session'
+ exit
+ 'outer session again'
+ exit
+ HISTORY
+ end
+
+ private
+
+ def write_history(history)
+ @history_file = Tempfile.new('irb_history')
+ @history_file.write(history)
+ @history_file.close
+ write_rc <<~RUBY
+ IRB.conf[:HISTORY_FILE] = "#{@history_file.path}"
+ RUBY
+ end
+ end
+end
diff --git a/test/irb/test_init.rb b/test/irb/test_init.rb
index e5417b18c3..3e8d01c5ce 100644
--- a/test/irb/test_init.rb
+++ b/test/irb/test_init.rb
@@ -1,21 +1,28 @@
# frozen_string_literal: false
-require "test/unit"
require "irb"
require "fileutils"
+require_relative "helper"
+
module TestIRB
- class TestInit < Test::Unit::TestCase
+ class InitTest < TestCase
def setup
# IRBRC is for RVM...
@backup_env = %w[HOME XDG_CONFIG_HOME IRBRC].each_with_object({}) do |env, hash|
hash[env] = ENV.delete(env)
end
- ENV["HOME"] = @tmpdir = Dir.mktmpdir("test_irb_init_#{$$}")
+ ENV["HOME"] = @tmpdir = File.realpath(Dir.mktmpdir("test_irb_init_#{$$}"))
+ end
+
+ def reset_rc_name_generators
+ IRB.instance_variable_set(:@existing_rc_name_generators, nil)
end
def teardown
ENV.update(@backup_env)
FileUtils.rm_rf(@tmpdir)
+ IRB.conf.delete(:SCRIPT)
+ reset_rc_name_generators
end
def test_setup_with_argv_preserves_global_argv
@@ -32,38 +39,80 @@ module TestIRB
assert_equal orig, $0
end
- def test_rc_file
+ def test_rc_files
tmpdir = @tmpdir
Dir.chdir(tmpdir) do
- IRB.conf[:RC_NAME_GENERATOR] = nil
- assert_equal(tmpdir+"/.irb#{IRB::IRBRC_EXT}", IRB.rc_file)
- assert_equal(tmpdir+"/.irb_history", IRB.rc_file("_history"))
- IRB.conf[:RC_NAME_GENERATOR] = nil
- FileUtils.touch(tmpdir+"/.irb#{IRB::IRBRC_EXT}")
- assert_equal(tmpdir+"/.irb#{IRB::IRBRC_EXT}", IRB.rc_file)
- assert_equal(tmpdir+"/.irb_history", IRB.rc_file("_history"))
+ home = ENV['HOME'] = "#{tmpdir}/home"
+ xdg_config_home = ENV['XDG_CONFIG_HOME'] = "#{tmpdir}/xdg"
+ reset_rc_name_generators
+ assert_empty(IRB.irbrc_files)
+ assert_equal("#{home}/.irb_history", IRB.rc_file('_history'))
+ FileUtils.mkdir_p(home)
+ FileUtils.mkdir_p("#{xdg_config_home}/irb")
+ FileUtils.mkdir_p("#{home}/.config/irb")
+ reset_rc_name_generators
+ assert_empty(IRB.irbrc_files)
+ assert_equal("#{xdg_config_home}/irb/irb_history", IRB.rc_file('_history'))
+ home_irbrc = "#{home}/.irbrc"
+ config_irbrc = "#{home}/.config/irb/irbrc"
+ xdg_config_irbrc = "#{xdg_config_home}/irb/irbrc"
+ [home_irbrc, config_irbrc, xdg_config_irbrc].each do |file|
+ FileUtils.touch(file)
+ end
+ current_dir_irbrcs = %w[.irbrc irbrc _irbrc $irbrc].map { |file| "#{tmpdir}/#{file}" }
+ current_dir_irbrcs.each { |file| FileUtils.touch(file) }
+ reset_rc_name_generators
+ assert_equal([xdg_config_irbrc, home_irbrc, *current_dir_irbrcs], IRB.irbrc_files)
+ assert_equal(xdg_config_irbrc.sub(/rc$/, '_history'), IRB.rc_file('_history'))
+ ENV['XDG_CONFIG_HOME'] = nil
+ reset_rc_name_generators
+ assert_equal([home_irbrc, config_irbrc, *current_dir_irbrcs], IRB.irbrc_files)
+ assert_equal(home_irbrc.sub(/rc$/, '_history'), IRB.rc_file('_history'))
+ ENV['XDG_CONFIG_HOME'] = ''
+ reset_rc_name_generators
+ assert_equal([home_irbrc, config_irbrc] + current_dir_irbrcs, IRB.irbrc_files)
+ assert_equal(home_irbrc.sub(/rc$/, '_history'), IRB.rc_file('_history'))
+ ENV['XDG_CONFIG_HOME'] = xdg_config_home
+ ENV['IRBRC'] = "#{tmpdir}/.irbrc"
+ reset_rc_name_generators
+ assert_equal([ENV['IRBRC'], xdg_config_irbrc, home_irbrc] + (current_dir_irbrcs - [ENV['IRBRC']]), IRB.irbrc_files)
+ assert_equal(ENV['IRBRC'] + '_history', IRB.rc_file('_history'))
+ ENV['IRBRC'] = ENV['HOME'] = ENV['XDG_CONFIG_HOME'] = nil
+ reset_rc_name_generators
+ assert_equal(current_dir_irbrcs, IRB.irbrc_files)
+ assert_nil(IRB.rc_file('_history'))
end
end
- def test_rc_file_in_subdir
+ def test_duplicated_rc_files
tmpdir = @tmpdir
Dir.chdir(tmpdir) do
- FileUtils.mkdir_p("#{tmpdir}/mydir")
- Dir.chdir("#{tmpdir}/mydir") do
- IRB.conf[:RC_NAME_GENERATOR] = nil
- assert_equal(tmpdir+"/.irb#{IRB::IRBRC_EXT}", IRB.rc_file)
- assert_equal(tmpdir+"/.irb_history", IRB.rc_file("_history"))
- IRB.conf[:RC_NAME_GENERATOR] = nil
- FileUtils.touch(tmpdir+"/.irb#{IRB::IRBRC_EXT}")
- assert_equal(tmpdir+"/.irb#{IRB::IRBRC_EXT}", IRB.rc_file)
- assert_equal(tmpdir+"/.irb_history", IRB.rc_file("_history"))
+ ENV['XDG_CONFIG_HOME'] = "#{ENV['HOME']}/.config"
+ FileUtils.mkdir_p("#{ENV['XDG_CONFIG_HOME']}/irb")
+ env_irbrc = ENV['IRBRC'] = "#{tmpdir}/_irbrc"
+ xdg_config_irbrc = "#{ENV['XDG_CONFIG_HOME']}/irb/irbrc"
+ home_irbrc = "#{ENV['HOME']}/.irbrc"
+ current_dir_irbrc = "#{tmpdir}/irbrc"
+ [env_irbrc, xdg_config_irbrc, home_irbrc, current_dir_irbrc].each do |file|
+ FileUtils.touch(file)
end
+ reset_rc_name_generators
+ assert_equal([env_irbrc, xdg_config_irbrc, home_irbrc, current_dir_irbrc], IRB.irbrc_files)
end
end
- def test_recovery_sigint
+ def test_sigint_restore_default
+ pend "This test gets stuck on Solaris for unknown reason; contribution is welcome" if RUBY_PLATFORM =~ /solaris/
+ bundle_exec = ENV.key?('BUNDLE_GEMFILE') ? ['-rbundler/setup'] : []
+ # IRB should restore SIGINT handler
+ status = assert_in_out_err(bundle_exec + %w[-W0 -rirb -e Signal.trap("SIGINT","DEFAULT");binding.irb;loop{Process.kill("SIGINT",$$)} -- -f --], "exit\n", //, //)
+ Process.kill("SIGKILL", status.pid) if !status.exited? && !status.stopped? && !status.signaled?
+ end
+
+ def test_sigint_restore_block
bundle_exec = ENV.key?('BUNDLE_GEMFILE') ? ['-rbundler/setup'] : []
- status = assert_in_out_err(bundle_exec + %w[-W0 -rirb -e binding.irb;loop{Process.kill("SIGINT",$$)} -- -f --], "exit\n", //, //)
+ # IRB should restore SIGINT handler
+ status = assert_in_out_err(bundle_exec + %w[-W0 -rirb -e x=false;Signal.trap("SIGINT"){x=true};binding.irb;loop{Process.kill("SIGINT",$$);if(x);break;end} -- -f --], "exit\n", //, //)
Process.kill("SIGKILL", status.pid) if !status.exited? && !status.stopped? && !status.signaled?
end
@@ -78,6 +127,10 @@ module TestIRB
IRB.setup(__FILE__)
refute IRB.conf[:USE_COLORIZE]
+ ENV['NO_COLOR'] = ''
+ IRB.setup(__FILE__)
+ assert IRB.conf[:USE_COLORIZE]
+
ENV['NO_COLOR'] = nil
IRB.setup(__FILE__)
assert IRB.conf[:USE_COLORIZE]
@@ -86,6 +139,124 @@ module TestIRB
IRB.conf[:USE_COLORIZE] = orig_use_colorize
end
+ def test_use_autocomplete_environment_variable
+ orig_use_autocomplete_env = ENV['IRB_USE_AUTOCOMPLETE']
+ orig_use_autocomplete_conf = IRB.conf[:USE_AUTOCOMPLETE]
+
+ ENV['IRB_USE_AUTOCOMPLETE'] = nil
+ IRB.setup(__FILE__)
+ assert IRB.conf[:USE_AUTOCOMPLETE]
+
+ ENV['IRB_USE_AUTOCOMPLETE'] = ''
+ IRB.setup(__FILE__)
+ assert IRB.conf[:USE_AUTOCOMPLETE]
+
+ ENV['IRB_USE_AUTOCOMPLETE'] = 'false'
+ IRB.setup(__FILE__)
+ refute IRB.conf[:USE_AUTOCOMPLETE]
+
+ ENV['IRB_USE_AUTOCOMPLETE'] = 'true'
+ IRB.setup(__FILE__)
+ assert IRB.conf[:USE_AUTOCOMPLETE]
+ ensure
+ ENV["IRB_USE_AUTOCOMPLETE"] = orig_use_autocomplete_env
+ IRB.conf[:USE_AUTOCOMPLETE] = orig_use_autocomplete_conf
+ end
+
+ def test_completor_environment_variable
+ orig_use_autocomplete_env = ENV['IRB_COMPLETOR']
+ orig_use_autocomplete_conf = IRB.conf[:COMPLETOR]
+
+ ENV['IRB_COMPLETOR'] = nil
+ IRB.setup(__FILE__)
+ assert_equal(:regexp, IRB.conf[:COMPLETOR])
+
+ ENV['IRB_COMPLETOR'] = 'regexp'
+ IRB.setup(__FILE__)
+ assert_equal(:regexp, IRB.conf[:COMPLETOR])
+
+ ENV['IRB_COMPLETOR'] = 'type'
+ IRB.setup(__FILE__)
+ assert_equal(:type, IRB.conf[:COMPLETOR])
+
+ ENV['IRB_COMPLETOR'] = 'regexp'
+ IRB.setup(__FILE__, argv: ['--type-completor'])
+ assert_equal :type, IRB.conf[:COMPLETOR]
+
+ ENV['IRB_COMPLETOR'] = 'type'
+ IRB.setup(__FILE__, argv: ['--regexp-completor'])
+ assert_equal :regexp, IRB.conf[:COMPLETOR]
+ ensure
+ ENV['IRB_COMPLETOR'] = orig_use_autocomplete_env
+ IRB.conf[:COMPLETOR] = orig_use_autocomplete_conf
+ end
+
+ def test_completor_setup_with_argv
+ orig_completor_conf = IRB.conf[:COMPLETOR]
+
+ # Default is :regexp
+ IRB.setup(__FILE__, argv: [])
+ assert_equal :regexp, IRB.conf[:COMPLETOR]
+
+ IRB.setup(__FILE__, argv: ['--type-completor'])
+ assert_equal :type, IRB.conf[:COMPLETOR]
+
+ IRB.setup(__FILE__, argv: ['--regexp-completor'])
+ assert_equal :regexp, IRB.conf[:COMPLETOR]
+ ensure
+ IRB.conf[:COMPLETOR] = orig_completor_conf
+ end
+
+ def test_noscript
+ argv = %w[--noscript -- -f]
+ IRB.setup(eval("__FILE__"), argv: argv)
+ assert_nil IRB.conf[:SCRIPT]
+ assert_equal(['-f'], argv)
+
+ argv = %w[--noscript -- a]
+ IRB.setup(eval("__FILE__"), argv: argv)
+ assert_nil IRB.conf[:SCRIPT]
+ assert_equal(['a'], argv)
+
+ argv = %w[--noscript a]
+ IRB.setup(eval("__FILE__"), argv: argv)
+ assert_nil IRB.conf[:SCRIPT]
+ assert_equal(['a'], argv)
+
+ argv = %w[--script --noscript a]
+ IRB.setup(eval("__FILE__"), argv: argv)
+ assert_nil IRB.conf[:SCRIPT]
+ assert_equal(['a'], argv)
+
+ argv = %w[--noscript --script a]
+ IRB.setup(eval("__FILE__"), argv: argv)
+ assert_equal('a', IRB.conf[:SCRIPT])
+ assert_equal([], argv)
+ end
+
+ def test_dash
+ argv = %w[-]
+ IRB.setup(eval("__FILE__"), argv: argv)
+ assert_equal('-', IRB.conf[:SCRIPT])
+ assert_equal([], argv)
+
+ argv = %w[-- -]
+ IRB.setup(eval("__FILE__"), argv: argv)
+ assert_equal('-', IRB.conf[:SCRIPT])
+ assert_equal([], argv)
+
+ argv = %w[-- - -f]
+ IRB.setup(eval("__FILE__"), argv: argv)
+ assert_equal('-', IRB.conf[:SCRIPT])
+ assert_equal(['-f'], argv)
+ end
+
+ def test_option_tracer
+ argv = %w[--tracer]
+ IRB.setup(eval("__FILE__"), argv: argv)
+ assert_equal(true, IRB.conf[:USE_TRACER])
+ end
+
private
def with_argv(argv)
@@ -96,4 +267,118 @@ module TestIRB
ARGV.replace(orig)
end
end
+
+ class ConfigValidationTest < TestCase
+ def setup
+ # To prevent the test from using the user's .irbrc file
+ @home = Dir.mktmpdir
+ setup_envs(home: @home)
+ super
+ end
+
+ def teardown
+ super
+ teardown_envs
+ File.unlink(@irbrc)
+ Dir.rmdir(@home)
+ IRB.instance_variable_set(:@existing_rc_name_generators, nil)
+ end
+
+ def test_irb_name_converts_non_string_values_to_string
+ assert_no_irb_validation_error(<<~'RUBY')
+ IRB.conf[:IRB_NAME] = :foo
+ RUBY
+
+ assert_equal "foo", IRB.conf[:IRB_NAME]
+ end
+
+ def test_irb_rc_name_only_takes_callable_objects
+ assert_irb_validation_error(<<~'RUBY', "IRB.conf[:IRB_RC] should be a callable object. Got :foo.")
+ IRB.conf[:IRB_RC] = :foo
+ RUBY
+ end
+
+ def test_back_trace_limit_only_accepts_integers
+ assert_irb_validation_error(<<~'RUBY', "IRB.conf[:BACK_TRACE_LIMIT] should be an integer. Got \"foo\".")
+ IRB.conf[:BACK_TRACE_LIMIT] = "foo"
+ RUBY
+ end
+
+ def test_prompt_only_accepts_hash
+ assert_irb_validation_error(<<~'RUBY', "IRB.conf[:PROMPT] should be a Hash. Got \"foo\".")
+ IRB.conf[:PROMPT] = "foo"
+ RUBY
+ end
+
+ def test_eval_history_only_accepts_integers
+ assert_irb_validation_error(<<~'RUBY', "IRB.conf[:EVAL_HISTORY] should be an integer. Got \"foo\".")
+ IRB.conf[:EVAL_HISTORY] = "foo"
+ RUBY
+ end
+
+ private
+
+ def assert_irb_validation_error(rc_content, error_message)
+ write_rc rc_content
+
+ assert_raise_with_message(TypeError, error_message) do
+ IRB.setup(__FILE__)
+ end
+ end
+
+ def assert_no_irb_validation_error(rc_content)
+ write_rc rc_content
+
+ assert_nothing_raised do
+ IRB.setup(__FILE__)
+ end
+ end
+
+ def write_rc(content)
+ @irbrc = Tempfile.new('irbrc')
+ @irbrc.write(content)
+ @irbrc.close
+ ENV['IRBRC'] = @irbrc.path
+ end
+ end
+
+ class InitIntegrationTest < IntegrationTestCase
+ def setup
+ super
+
+ write_ruby <<~'RUBY'
+ binding.irb
+ RUBY
+ end
+
+ def test_load_error_in_rc_file_is_warned
+ write_rc <<~'IRBRC'
+ require "file_that_does_not_exist"
+ IRBRC
+
+ output = run_ruby_file do
+ type "'foobar'"
+ type "exit"
+ end
+
+ # IRB session should still be started
+ assert_includes output, "foobar"
+ assert_includes output, 'cannot load such file -- file_that_does_not_exist (LoadError)'
+ end
+
+ def test_normal_errors_in_rc_file_is_warned
+ write_rc <<~'IRBRC'
+ raise "I'm an error"
+ IRBRC
+
+ output = run_ruby_file do
+ type "'foobar'"
+ type "exit"
+ end
+
+ # IRB session should still be started
+ assert_includes output, "foobar"
+ assert_includes output, 'I\'m an error (RuntimeError)'
+ end
+ end
end
diff --git a/test/irb/test_input_method.rb b/test/irb/test_input_method.rb
new file mode 100644
index 0000000000..bd107551df
--- /dev/null
+++ b/test/irb/test_input_method.rb
@@ -0,0 +1,195 @@
+# frozen_string_literal: false
+
+require "irb"
+begin
+ require "rdoc"
+rescue LoadError
+end
+require_relative "helper"
+
+module TestIRB
+ class InputMethodTest < TestCase
+ def setup
+ @conf_backup = IRB.conf.dup
+ IRB.init_config(nil)
+ IRB.conf[:LC_MESSAGES] = IRB::Locale.new
+ save_encodings
+ end
+
+ def teardown
+ IRB.conf.replace(@conf_backup)
+ restore_encodings
+ # Reset Reline configuration overridden by RelineInputMethod.
+ Reline.instance_variable_set(:@core, nil)
+ end
+ end
+
+ class RelineInputMethodTest < InputMethodTest
+ def test_initialization
+ Reline.completion_proc = nil
+ Reline.dig_perfect_match_proc = nil
+ IRB::RelineInputMethod.new(IRB::RegexpCompletor.new)
+
+ assert_nil Reline.completion_append_character
+ assert_equal '', Reline.completer_quote_characters
+ assert_equal IRB::InputMethod::BASIC_WORD_BREAK_CHARACTERS, Reline.basic_word_break_characters
+ assert_not_nil Reline.completion_proc
+ assert_not_nil Reline.dig_perfect_match_proc
+ end
+
+ def test_colorize
+ IRB.conf[:USE_COLORIZE] = true
+ IRB.conf[:VERBOSE] = false
+ original_colorable = IRB::Color.method(:colorable?)
+ IRB::Color.instance_eval { undef :colorable? }
+ IRB::Color.define_singleton_method(:colorable?) { true }
+ workspace = IRB::WorkSpace.new(binding)
+ input_method = IRB::RelineInputMethod.new(IRB::RegexpCompletor.new)
+ IRB.conf[:MAIN_CONTEXT] = IRB::Irb.new(workspace, input_method).context
+ assert_equal "\e[1m$\e[0m\e[m", Reline.output_modifier_proc.call('$', complete: false)
+ assert_equal "\e[1m$\e[0m\e[m \e[34m\e[1m1\e[0m + \e[34m\e[1m2\e[0m", Reline.output_modifier_proc.call('$ 1 + 2', complete: false)
+ assert_equal "\e[32m\e[1m$a\e[0m", Reline.output_modifier_proc.call('$a', complete: false)
+ ensure
+ IRB::Color.instance_eval { undef :colorable? }
+ IRB::Color.define_singleton_method(:colorable?, original_colorable)
+ end
+
+ def test_initialization_without_use_autocomplete
+ original_show_doc_proc = Reline.dialog_proc(:show_doc)&.dialog_proc
+ empty_proc = Proc.new {}
+ Reline.add_dialog_proc(:show_doc, empty_proc)
+
+ IRB.conf[:USE_AUTOCOMPLETE] = false
+
+ IRB::RelineInputMethod.new(IRB::RegexpCompletor.new)
+
+ refute Reline.autocompletion
+ assert_equal empty_proc, Reline.dialog_proc(:show_doc).dialog_proc
+ ensure
+ Reline.add_dialog_proc(:show_doc, original_show_doc_proc, Reline::DEFAULT_DIALOG_CONTEXT)
+ end
+
+ def test_initialization_with_use_autocomplete
+ omit 'This test requires RDoc' unless defined?(RDoc)
+ original_show_doc_proc = Reline.dialog_proc(:show_doc)&.dialog_proc
+ empty_proc = Proc.new {}
+ Reline.add_dialog_proc(:show_doc, empty_proc)
+
+ IRB.conf[:USE_AUTOCOMPLETE] = true
+
+ IRB::RelineInputMethod.new(IRB::RegexpCompletor.new)
+
+ assert Reline.autocompletion
+ assert_not_equal empty_proc, Reline.dialog_proc(:show_doc).dialog_proc
+ ensure
+ Reline.add_dialog_proc(:show_doc, original_show_doc_proc, Reline::DEFAULT_DIALOG_CONTEXT)
+ end
+
+ def test_initialization_with_use_autocomplete_but_without_rdoc
+ original_show_doc_proc = Reline.dialog_proc(:show_doc)&.dialog_proc
+ empty_proc = Proc.new {}
+ Reline.add_dialog_proc(:show_doc, empty_proc)
+
+ IRB.conf[:USE_AUTOCOMPLETE] = true
+
+ without_rdoc do
+ IRB::RelineInputMethod.new(IRB::RegexpCompletor.new)
+ end
+
+ assert Reline.autocompletion
+ # doesn't register show_doc dialog
+ assert_equal empty_proc, Reline.dialog_proc(:show_doc).dialog_proc
+ ensure
+ Reline.add_dialog_proc(:show_doc, original_show_doc_proc, Reline::DEFAULT_DIALOG_CONTEXT)
+ end
+ end
+
+ class DisplayDocumentTest < InputMethodTest
+ def setup
+ super
+ @driver = RDoc::RI::Driver.new(use_stdout: true)
+ end
+
+ def display_document(target, bind, driver = nil)
+ input_method = IRB::RelineInputMethod.new(IRB::RegexpCompletor.new)
+ input_method.instance_variable_set(:@rdoc_ri_driver, driver) if driver
+ input_method.instance_variable_set(:@completion_params, ['', target, '', bind])
+ input_method.display_document(target)
+ end
+
+ def test_perfectly_matched_namespace_triggers_document_display
+ omit unless has_rdoc_content?
+
+ out, err = capture_output do
+ display_document("String", binding, @driver)
+ end
+
+ assert_empty(err)
+
+ assert_include(out, " S\bSt\btr\bri\bin\bng\bg")
+ end
+
+ def test_perfectly_matched_multiple_namespaces_triggers_document_display
+ result = nil
+ out, err = capture_output do
+ result = display_document("{}.nil?", binding, @driver)
+ end
+
+ assert_empty(err)
+
+ # check if there're rdoc contents (e.g. CI doesn't generate them)
+ if has_rdoc_content?
+ # if there's rdoc content, we can verify by checking stdout
+ # rdoc generates control characters for formatting method names
+ assert_include(out, "P\bPr\bro\boc\bc.\b.n\bni\bil\bl?\b?") # Proc.nil?
+ assert_include(out, "H\bHa\bas\bsh\bh.\b.n\bni\bil\bl?\b?") # Hash.nil?
+ else
+ # this is a hacky way to verify the rdoc rendering code path because CI doesn't have rdoc content
+ # if there are multiple namespaces to be rendered, PerfectMatchedProc renders the result with a document
+ # which always returns the bytes rendered, even if it's 0
+ assert_equal(0, result)
+ end
+ end
+
+ def test_not_matched_namespace_triggers_nothing
+ result = nil
+ out, err = capture_output do
+ result = display_document("Stri", binding, @driver)
+ end
+
+ assert_empty(err)
+ assert_empty(out)
+ assert_nil(result)
+ end
+
+ def test_perfect_matching_stops_without_rdoc
+ result = nil
+
+ out, err = capture_output do
+ without_rdoc do
+ result = display_document("String", binding)
+ end
+ end
+
+ assert_empty(err)
+ assert_not_match(/from ruby core/, out)
+ assert_nil(result)
+ end
+
+ def test_perfect_matching_handles_nil_namespace
+ out, err = capture_output do
+ # symbol literal has `nil` doc namespace so it's a good test subject
+ assert_nil(display_document(":aiueo", binding, @driver))
+ end
+
+ assert_empty(err)
+ assert_empty(out)
+ end
+
+ private
+
+ def has_rdoc_content?
+ File.exist?(RDoc::RI::Paths::BASE)
+ end
+ end if defined?(RDoc)
+end
diff --git a/test/irb/test_irb.rb b/test/irb/test_irb.rb
new file mode 100644
index 0000000000..2913f3d48e
--- /dev/null
+++ b/test/irb/test_irb.rb
@@ -0,0 +1,936 @@
+# frozen_string_literal: true
+require "irb"
+
+require_relative "helper"
+
+module TestIRB
+ class InputTest < IntegrationTestCase
+ def test_symbol_aliases_are_handled_correctly
+ write_ruby <<~'RUBY'
+ class Foo
+ end
+ binding.irb
+ RUBY
+
+ output = run_ruby_file do
+ type "$ Foo"
+ type "exit!"
+ end
+
+ assert_include output, "From: #{@ruby_file.path}:1"
+ end
+
+ def test_symbol_aliases_are_handled_correctly_with_singleline_mode
+ write_rc <<~RUBY
+ IRB.conf[:USE_SINGLELINE] = true
+ RUBY
+
+ write_ruby <<~'RUBY'
+ class Foo
+ end
+ binding.irb
+ RUBY
+
+ output = run_ruby_file do
+ type "irb_info"
+ type "$ Foo"
+ type "exit!"
+ end
+
+ # Make sure it's tested in singleline mode
+ assert_include output, "InputMethod: ReadlineInputMethod"
+ assert_include output, "From: #{@ruby_file.path}:1"
+ end
+
+ def test_underscore_stores_last_result
+ write_ruby <<~'RUBY'
+ binding.irb
+ RUBY
+
+ output = run_ruby_file do
+ type "1 + 1"
+ type "_ + 10"
+ type "exit!"
+ end
+
+ assert_include output, "=> 12"
+ end
+
+ def test_commands_dont_override_stored_last_result
+ write_ruby <<~'RUBY'
+ binding.irb
+ RUBY
+
+ output = run_ruby_file do
+ type "1 + 1"
+ type "ls"
+ type "_ + 10"
+ type "exit!"
+ end
+
+ assert_include output, "=> 12"
+ end
+
+ def test_evaluate_with_encoding_error_without_lineno
+ if RUBY_ENGINE == 'truffleruby'
+ omit "Remove me after https://github.com/ruby/prism/issues/2129 is addressed and adopted in TruffleRuby"
+ end
+
+ if RUBY_VERSION >= "3.3."
+ omit "Now raises SyntaxError"
+ end
+
+ write_ruby <<~'RUBY'
+ binding.irb
+ RUBY
+
+ output = run_ruby_file do
+ type %q[:"\xAE"]
+ type "exit!"
+ end
+
+ assert_include output, 'invalid symbol in encoding UTF-8 :"\xAE"'
+ # EncodingError would be wrapped with ANSI escape sequences, so we assert it separately
+ assert_include output, "EncodingError"
+ end
+
+ def test_evaluate_still_emits_warning
+ write_ruby <<~'RUBY'
+ binding.irb
+ RUBY
+
+ output = run_ruby_file do
+ type %q[def foo; END {}; end]
+ type "exit!"
+ end
+
+ assert_include output, '(irb):1: warning: END in method; use at_exit'
+ end
+
+ def test_symbol_aliases_dont_affect_ruby_syntax
+ write_ruby <<~'RUBY'
+ $foo = "It's a foo"
+ @bar = "It's a bar"
+ binding.irb
+ RUBY
+
+ output = run_ruby_file do
+ type "$foo"
+ type "@bar"
+ type "exit!"
+ end
+
+ assert_include output, "=> \"It's a foo\""
+ assert_include output, "=> \"It's a bar\""
+ end
+
+ def test_empty_input_echoing_behaviour
+ write_ruby <<~'RUBY'
+ binding.irb
+ RUBY
+
+ output = run_ruby_file do
+ type ""
+ type " "
+ type "exit"
+ end
+
+ assert_not_match(/irb\(main\):001> (\r*\n)?=> nil/, output)
+ assert_match(/irb\(main\):002> (\r*\n)?=> nil/, output)
+ end
+ end
+
+ class NestedBindingIrbTest < IntegrationTestCase
+ def test_current_context_restore
+ write_ruby <<~'RUBY'
+ binding.irb
+ RUBY
+
+ output = run_ruby_file do
+ type '$ctx = IRB.CurrentContext'
+ type 'binding.irb'
+ type 'p context_changed: IRB.CurrentContext != $ctx'
+ type 'exit'
+ type 'p context_restored: IRB.CurrentContext == $ctx'
+ type 'exit'
+ end
+
+ assert_include output, '{:context_changed=>true}'
+ assert_include output, '{:context_restored=>true}'
+ end
+ end
+
+ class IrbIOConfigurationTest < TestCase
+ Row = Struct.new(:content, :current_line_spaces, :new_line_spaces, :indent_level)
+
+ class MockIO_AutoIndent
+ attr_reader :calculated_indent
+
+ def initialize(*params)
+ @params = params
+ end
+
+ def auto_indent(&block)
+ @calculated_indent = block.call(*@params)
+ end
+ end
+
+ class MockIO_DynamicPrompt
+ attr_reader :prompt_list
+
+ def initialize(params, &assertion)
+ @params = params
+ end
+
+ def dynamic_prompt(&block)
+ @prompt_list = block.call(@params)
+ end
+ end
+
+ def setup
+ save_encodings
+ @irb = build_irb
+ end
+
+ def teardown
+ restore_encodings
+ end
+
+ class AutoIndentationTest < IrbIOConfigurationTest
+ def test_auto_indent
+ input_with_correct_indents = [
+ [%q(def each_top_level_statement), 0, 2],
+ [%q( initialize_input), 2, 2],
+ [%q( catch(:TERM_INPUT) do), 2, 4],
+ [%q( loop do), 4, 6],
+ [%q( begin), 6, 8],
+ [%q( prompt), 8, 8],
+ [%q( unless l = lex), 8, 10],
+ [%q( throw :TERM_INPUT if @line == ''), 10, 10],
+ [%q( else), 8, 10],
+ [%q( @line_no += l.count("\n")), 10, 10],
+ [%q( next if l == "\n"), 10, 10],
+ [%q( @line.concat l), 10, 10],
+ [%q( if @code_block_open or @ltype or @continue or @indent > 0), 10, 12],
+ [%q( next), 12, 12],
+ [%q( end), 10, 10],
+ [%q( end), 8, 8],
+ [%q( if @line != "\n"), 8, 10],
+ [%q( @line.force_encoding(@io.encoding)), 10, 10],
+ [%q( yield @line, @exp_line_no), 10, 10],
+ [%q( end), 8, 8],
+ [%q( break if @io.eof?), 8, 8],
+ [%q( @line = ''), 8, 8],
+ [%q( @exp_line_no = @line_no), 8, 8],
+ [%q( ), nil, 8],
+ [%q( @indent = 0), 8, 8],
+ [%q( rescue TerminateLineInput), 6, 8],
+ [%q( initialize_input), 8, 8],
+ [%q( prompt), 8, 8],
+ [%q( end), 6, 6],
+ [%q( end), 4, 4],
+ [%q( end), 2, 2],
+ [%q(end), 0, 0],
+ ]
+
+ assert_rows_with_correct_indents(input_with_correct_indents)
+ end
+
+ def test_braces_on_their_own_line
+ input_with_correct_indents = [
+ [%q(if true), 0, 2],
+ [%q( [), 2, 4],
+ [%q( ]), 2, 2],
+ [%q(end), 0, 0],
+ ]
+
+ assert_rows_with_correct_indents(input_with_correct_indents)
+ end
+
+ def test_multiple_braces_in_a_line
+ input_with_correct_indents = [
+ [%q([[[), 0, 6],
+ [%q( ]), 4, 4],
+ [%q( ]), 2, 2],
+ [%q(]), 0, 0],
+ [%q([<<FOO]), 0, 0],
+ [%q(hello), 0, 0],
+ [%q(FOO), 0, 0],
+ ]
+
+ assert_rows_with_correct_indents(input_with_correct_indents)
+ end
+
+ def test_a_closed_brace_and_not_closed_brace_in_a_line
+ input_with_correct_indents = [
+ [%q(p() {), 0, 2],
+ [%q(}), 0, 0],
+ ]
+
+ assert_rows_with_correct_indents(input_with_correct_indents)
+ end
+
+ def test_symbols
+ input_with_correct_indents = [
+ [%q(:a), 0, 0],
+ [%q(:A), 0, 0],
+ [%q(:+), 0, 0],
+ [%q(:@@a), 0, 0],
+ [%q(:@a), 0, 0],
+ [%q(:$a), 0, 0],
+ [%q(:def), 0, 0],
+ [%q(:`), 0, 0],
+ ]
+
+ assert_rows_with_correct_indents(input_with_correct_indents)
+ end
+
+ def test_incomplete_coding_magic_comment
+ input_with_correct_indents = [
+ [%q(#coding:u), 0, 0],
+ ]
+
+ assert_rows_with_correct_indents(input_with_correct_indents)
+ end
+
+ def test_incomplete_encoding_magic_comment
+ input_with_correct_indents = [
+ [%q(#encoding:u), 0, 0],
+ ]
+
+ assert_rows_with_correct_indents(input_with_correct_indents)
+ end
+
+ def test_incomplete_emacs_coding_magic_comment
+ input_with_correct_indents = [
+ [%q(# -*- coding: u), 0, 0],
+ ]
+
+ assert_rows_with_correct_indents(input_with_correct_indents)
+ end
+
+ def test_incomplete_vim_coding_magic_comment
+ input_with_correct_indents = [
+ [%q(# vim:set fileencoding=u), 0, 0],
+ ]
+
+ assert_rows_with_correct_indents(input_with_correct_indents)
+ end
+
+ def test_mixed_rescue
+ input_with_correct_indents = [
+ [%q(def m), 0, 2],
+ [%q( begin), 2, 4],
+ [%q( begin), 4, 6],
+ [%q( x = a rescue 4), 6, 6],
+ [%q( y = [(a rescue 5)]), 6, 6],
+ [%q( [x, y]), 6, 6],
+ [%q( rescue => e), 4, 6],
+ [%q( raise e rescue 8), 6, 6],
+ [%q( end), 4, 4],
+ [%q( rescue), 2, 4],
+ [%q( raise rescue 11), 4, 4],
+ [%q( end), 2, 2],
+ [%q(rescue => e), 0, 2],
+ [%q( raise e rescue 14), 2, 2],
+ [%q(end), 0, 0],
+ ]
+
+ assert_rows_with_correct_indents(input_with_correct_indents)
+ end
+
+ def test_oneliner_method_definition
+ input_with_correct_indents = [
+ [%q(class A), 0, 2],
+ [%q( def foo0), 2, 4],
+ [%q( 3), 4, 4],
+ [%q( end), 2, 2],
+ [%q( def foo1()), 2, 4],
+ [%q( 3), 4, 4],
+ [%q( end), 2, 2],
+ [%q( def foo2(a, b)), 2, 4],
+ [%q( a + b), 4, 4],
+ [%q( end), 2, 2],
+ [%q( def foo3 a, b), 2, 4],
+ [%q( a + b), 4, 4],
+ [%q( end), 2, 2],
+ [%q( def bar0() = 3), 2, 2],
+ [%q( def bar1(a) = a), 2, 2],
+ [%q( def bar2(a, b) = a + b), 2, 2],
+ [%q( def bar3() = :s), 2, 2],
+ [%q( def bar4() = Time.now), 2, 2],
+ [%q(end), 0, 0],
+ ]
+
+ assert_rows_with_correct_indents(input_with_correct_indents)
+ end
+
+ def test_tlambda
+ input_with_correct_indents = [
+ [%q(if true), 0, 2, 1],
+ [%q( -> {), 2, 4, 2],
+ [%q( }), 2, 2, 1],
+ [%q(end), 0, 0, 0],
+ ]
+
+ assert_rows_with_correct_indents(input_with_correct_indents, assert_indent_level: true)
+ end
+
+ def test_corresponding_syntax_to_keyword_do_in_class
+ input_with_correct_indents = [
+ [%q(class C), 0, 2, 1],
+ [%q( while method_name do), 2, 4, 2],
+ [%q( 3), 4, 4, 2],
+ [%q( end), 2, 2, 1],
+ [%q( foo do), 2, 4, 2],
+ [%q( 3), 4, 4, 2],
+ [%q( end), 2, 2, 1],
+ [%q(end), 0, 0, 0],
+ ]
+
+ assert_rows_with_correct_indents(input_with_correct_indents, assert_indent_level: true)
+ end
+
+ def test_corresponding_syntax_to_keyword_do
+ input_with_correct_indents = [
+ [%q(while i > 0), 0, 2, 1],
+ [%q( 3), 2, 2, 1],
+ [%q(end), 0, 0, 0],
+ [%q(while true), 0, 2, 1],
+ [%q( 3), 2, 2, 1],
+ [%q(end), 0, 0, 0],
+ [%q(while ->{i > 0}.call), 0, 2, 1],
+ [%q( 3), 2, 2, 1],
+ [%q(end), 0, 0, 0],
+ [%q(while ->{true}.call), 0, 2, 1],
+ [%q( 3), 2, 2, 1],
+ [%q(end), 0, 0, 0],
+ [%q(while i > 0 do), 0, 2, 1],
+ [%q( 3), 2, 2, 1],
+ [%q(end), 0, 0, 0],
+ [%q(while true do), 0, 2, 1],
+ [%q( 3), 2, 2, 1],
+ [%q(end), 0, 0, 0],
+ [%q(while ->{i > 0}.call do), 0, 2, 1],
+ [%q( 3), 2, 2, 1],
+ [%q(end), 0, 0, 0],
+ [%q(while ->{true}.call do), 0, 2, 1],
+ [%q( 3), 2, 2, 1],
+ [%q(end), 0, 0, 0],
+ [%q(foo do), 0, 2, 1],
+ [%q( 3), 2, 2, 1],
+ [%q(end), 0, 0, 0],
+ [%q(foo true do), 0, 2, 1],
+ [%q( 3), 2, 2, 1],
+ [%q(end), 0, 0, 0],
+ [%q(foo ->{true} do), 0, 2, 1],
+ [%q( 3), 2, 2, 1],
+ [%q(end), 0, 0, 0],
+ [%q(foo ->{i > 0} do), 0, 2, 1],
+ [%q( 3), 2, 2, 1],
+ [%q(end), 0, 0, 0],
+ ]
+
+ assert_rows_with_correct_indents(input_with_correct_indents, assert_indent_level: true)
+ end
+
+ def test_corresponding_syntax_to_keyword_for
+ input_with_correct_indents = [
+ [%q(for i in [1]), 0, 2, 1],
+ [%q( puts i), 2, 2, 1],
+ [%q(end), 0, 0, 0],
+ ]
+
+ assert_rows_with_correct_indents(input_with_correct_indents, assert_indent_level: true)
+ end
+
+ def test_corresponding_syntax_to_keyword_for_with_do
+ input_with_correct_indents = [
+ [%q(for i in [1] do), 0, 2, 1],
+ [%q( puts i), 2, 2, 1],
+ [%q(end), 0, 0, 0],
+ ]
+
+ assert_rows_with_correct_indents(input_with_correct_indents, assert_indent_level: true)
+ end
+
+ def test_typing_incomplete_include_interpreted_as_keyword_in
+ input_with_correct_indents = [
+ [%q(module E), 0, 2, 1],
+ [%q(end), 0, 0, 0],
+ [%q(class A), 0, 2, 1],
+ [%q( in), 2, 2, 1] # scenario typing `include E`
+ ]
+
+ assert_rows_with_correct_indents(input_with_correct_indents, assert_indent_level: true)
+
+ end
+
+ def test_bracket_corresponding_to_times
+ input_with_correct_indents = [
+ [%q(3.times { |i|), 0, 2, 1],
+ [%q( puts i), 2, 2, 1],
+ [%q(}), 0, 0, 0],
+ ]
+
+ assert_rows_with_correct_indents(input_with_correct_indents, assert_indent_level: true)
+ end
+
+ def test_do_corresponding_to_times
+ input_with_correct_indents = [
+ [%q(3.times do |i|), 0, 2, 1],
+ [%q( puts i), 2, 2, 1],
+ [%q(end), 0, 0, 0],
+ ]
+
+ assert_rows_with_correct_indents(input_with_correct_indents, assert_indent_level: true)
+ end
+
+ def test_bracket_corresponding_to_loop
+ input_with_correct_indents = [
+ ['loop {', 0, 2, 1],
+ [' 3', 2, 2, 1],
+ ['}', 0, 0, 0],
+ ]
+
+ assert_rows_with_correct_indents(input_with_correct_indents, assert_indent_level: true)
+ end
+
+ def test_do_corresponding_to_loop
+ input_with_correct_indents = [
+ [%q(loop do), 0, 2, 1],
+ [%q( 3), 2, 2, 1],
+ [%q(end), 0, 0, 0],
+ ]
+
+ assert_rows_with_correct_indents(input_with_correct_indents, assert_indent_level: true)
+ end
+
+ def test_embdoc_indent
+ input_with_correct_indents = [
+ [%q(=begin), 0, 0, 0],
+ [%q(a), 0, 0, 0],
+ [%q( b), 1, 1, 0],
+ [%q(=end), 0, 0, 0],
+ [%q(if 1), 0, 2, 1],
+ [%q( 2), 2, 2, 1],
+ [%q(=begin), 0, 0, 0],
+ [%q(a), 0, 0, 0],
+ [%q( b), 1, 1, 0],
+ [%q(=end), 0, 2, 1],
+ [%q( 3), 2, 2, 1],
+ [%q(end), 0, 0, 0],
+ ]
+
+ assert_rows_with_correct_indents(input_with_correct_indents, assert_indent_level: true)
+ end
+
+ def test_heredoc_with_indent
+ input_with_correct_indents = [
+ [%q(<<~Q+<<~R), 0, 2, 1],
+ [%q(a), 2, 2, 1],
+ [%q(a), 2, 2, 1],
+ [%q( b), 2, 2, 1],
+ [%q( b), 2, 2, 1],
+ [%q( Q), 0, 2, 1],
+ [%q( c), 4, 4, 1],
+ [%q( c), 4, 4, 1],
+ [%q( R), 0, 0, 0],
+ ]
+
+ assert_rows_with_correct_indents(input_with_correct_indents, assert_indent_level: true)
+ end
+
+ def test_oneliner_def_in_multiple_lines
+ input_with_correct_indents = [
+ [%q(def a()=[), 0, 2, 1],
+ [%q( 1,), 2, 2, 1],
+ [%q(].), 0, 0, 0],
+ [%q(to_s), 0, 0, 0],
+ ]
+
+ assert_rows_with_correct_indents(input_with_correct_indents, assert_indent_level: true)
+ end
+
+ def test_broken_heredoc
+ input_with_correct_indents = [
+ [%q(def foo), 0, 2, 1],
+ [%q( <<~Q), 2, 4, 2],
+ [%q( Qend), 4, 4, 2],
+ ]
+
+ assert_rows_with_correct_indents(input_with_correct_indents, assert_indent_level: true)
+ end
+
+ def test_pasted_code_keep_base_indent_spaces
+ input_with_correct_indents = [
+ [%q( def foo), 0, 6, 1],
+ [%q( if bar), 6, 10, 2],
+ [%q( [1), 10, 12, 3],
+ [%q( ]+[["a), 10, 14, 4],
+ [%q(b" + `c), 0, 14, 4],
+ [%q(d` + /e), 0, 14, 4],
+ [%q(f/ + :"g), 0, 14, 4],
+ [%q(h".tap do), 0, 16, 5],
+ [%q( 1), 16, 16, 5],
+ [%q( end), 14, 14, 4],
+ [%q( ]), 12, 12, 3],
+ [%q( ]), 10, 10, 2],
+ [%q( end), 8, 6, 1],
+ [%q( end), 4, 0, 0],
+ ]
+
+ assert_rows_with_correct_indents(input_with_correct_indents, assert_indent_level: true)
+ end
+
+ def test_pasted_code_keep_base_indent_spaces_with_heredoc
+ input_with_correct_indents = [
+ [%q( def foo), 0, 6, 1],
+ [%q( if bar), 6, 10, 2],
+ [%q( [1), 10, 12, 3],
+ [%q( ]+[["a), 10, 14, 4],
+ [%q(b" + <<~A + <<-B + <<C), 0, 16, 5],
+ [%q( a#{), 16, 18, 6],
+ [%q( 1), 18, 18, 6],
+ [%q( }), 16, 16, 5],
+ [%q( A), 14, 16, 5],
+ [%q( b#{), 16, 18, 6],
+ [%q( 1), 18, 18, 6],
+ [%q( }), 16, 16, 5],
+ [%q( B), 14, 0, 0],
+ [%q(c#{), 0, 2, 1],
+ [%q(1), 2, 2, 1],
+ [%q(}), 0, 0, 0],
+ [%q(C), 0, 14, 4],
+ [%q( ]), 12, 12, 3],
+ [%q( ]), 10, 10, 2],
+ [%q( end), 8, 6, 1],
+ [%q( end), 4, 0, 0],
+ ]
+
+ assert_rows_with_correct_indents(input_with_correct_indents, assert_indent_level: true)
+ end
+
+ def test_heredoc_keep_indent_spaces
+ (1..4).each do |indent|
+ row = Row.new(' ' * indent, nil, [4, indent].max, 2)
+ lines = ['def foo', ' <<~Q', row.content]
+ assert_row_indenting(lines, row)
+ assert_indent_level(lines, row.indent_level)
+ end
+ end
+
+ private
+
+ def assert_row_indenting(lines, row)
+ actual_current_line_spaces = calculate_indenting(lines, false)
+
+ error_message = <<~MSG
+ Incorrect spaces calculation for line:
+
+ ```
+ > #{lines.last}
+ ```
+
+ All lines:
+
+ ```
+ #{lines.join("\n")}
+ ```
+ MSG
+ assert_equal(row.current_line_spaces, actual_current_line_spaces, error_message)
+
+ error_message = <<~MSG
+ Incorrect spaces calculation for line after the current line:
+
+ ```
+ #{lines.last}
+ >
+ ```
+
+ All lines:
+
+ ```
+ #{lines.join("\n")}
+ ```
+ MSG
+ actual_next_line_spaces = calculate_indenting(lines, true)
+ assert_equal(row.new_line_spaces, actual_next_line_spaces, error_message)
+ end
+
+ def assert_rows_with_correct_indents(rows_with_spaces, assert_indent_level: false)
+ lines = []
+ rows_with_spaces.map do |row|
+ row = Row.new(*row)
+ lines << row.content
+ assert_row_indenting(lines, row)
+
+ if assert_indent_level
+ assert_indent_level(lines, row.indent_level)
+ end
+ end
+ end
+
+ def assert_indent_level(lines, expected)
+ code = lines.map { |l| "#{l}\n" }.join # code should end with "\n"
+ _tokens, opens, _ = @irb.scanner.check_code_state(code, local_variables: [])
+ indent_level = @irb.scanner.calc_indent_level(opens)
+ error_message = "Calculated the wrong number of indent level for:\n #{lines.join("\n")}"
+ assert_equal(expected, indent_level, error_message)
+ end
+
+ def calculate_indenting(lines, add_new_line)
+ lines = lines + [""] if add_new_line
+ last_line_index = lines.length - 1
+ byte_pointer = lines.last.length
+
+ mock_io = MockIO_AutoIndent.new(lines, last_line_index, byte_pointer, add_new_line)
+ @irb.context.auto_indent_mode = true
+ @irb.context.io = mock_io
+ @irb.configure_io
+
+ mock_io.calculated_indent
+ end
+ end
+
+ class DynamicPromptTest < IrbIOConfigurationTest
+ def test_endless_range_at_end_of_line
+ input_with_prompt = [
+ ['001:0: :> ', %q(a = 3..)],
+ ['002:0: :> ', %q()],
+ ]
+
+ assert_dynamic_prompt(input_with_prompt)
+ end
+
+ def test_heredoc_with_embexpr
+ input_with_prompt = [
+ ['001:0:":* ', %q(<<A+%W[#{<<B)],
+ ['002:0:":* ', %q(#{<<C+%W[)],
+ ['003:0:":* ', %q(a)],
+ ['004:2:]:* ', %q(C)],
+ ['005:2:]:* ', %q(a)],
+ ['006:0:":* ', %q(]})],
+ ['007:0:":* ', %q(})],
+ ['008:0:":* ', %q(A)],
+ ['009:2:]:* ', %q(B)],
+ ['010:1:]:* ', %q(})],
+ ['011:0: :> ', %q(])],
+ ['012:0: :> ', %q()],
+ ]
+
+ assert_dynamic_prompt(input_with_prompt)
+ end
+
+ def test_heredoc_prompt_with_quotes
+ input_with_prompt = [
+ ["001:1:':* ", %q(<<~'A')],
+ ["002:1:':* ", %q(#{foobar})],
+ ["003:0: :> ", %q(A)],
+ ["004:1:`:* ", %q(<<~`A`)],
+ ["005:1:`:* ", %q(whoami)],
+ ["006:0: :> ", %q(A)],
+ ['007:1:":* ', %q(<<~"A")],
+ ['008:1:":* ', %q(foobar)],
+ ['009:0: :> ', %q(A)],
+ ]
+
+ assert_dynamic_prompt(input_with_prompt)
+ end
+
+ def test_backtick_method
+ input_with_prompt = [
+ ['001:0: :> ', %q(self.`(arg))],
+ ['002:0: :> ', %q()],
+ ['003:0: :> ', %q(def `(); end)],
+ ['004:0: :> ', %q()],
+ ]
+
+ assert_dynamic_prompt(input_with_prompt)
+ end
+
+ def test_dynamic_prompt
+ input_with_prompt = [
+ ['001:1: :* ', %q(def hoge)],
+ ['002:1: :* ', %q( 3)],
+ ['003:0: :> ', %q(end)],
+ ]
+
+ assert_dynamic_prompt(input_with_prompt)
+ end
+
+ def test_dynamic_prompt_with_double_newline_breaking_code
+ input_with_prompt = [
+ ['001:1: :* ', %q(if true)],
+ ['002:2: :* ', %q(%)],
+ ['003:1: :* ', %q(;end)],
+ ['004:1: :* ', %q(;hello)],
+ ['005:0: :> ', %q(end)],
+ ]
+
+ assert_dynamic_prompt(input_with_prompt)
+ end
+
+ def test_dynamic_prompt_with_multiline_literal
+ input_with_prompt = [
+ ['001:1: :* ', %q(if true)],
+ ['002:2:]:* ', %q( %w[)],
+ ['003:2:]:* ', %q( a)],
+ ['004:1: :* ', %q( ])],
+ ['005:1: :* ', %q( b)],
+ ['006:2:]:* ', %q( %w[)],
+ ['007:2:]:* ', %q( c)],
+ ['008:1: :* ', %q( ])],
+ ['009:0: :> ', %q(end)],
+ ]
+
+ assert_dynamic_prompt(input_with_prompt)
+ end
+
+ def test_dynamic_prompt_with_blank_line
+ input_with_prompt = [
+ ['001:1:]:* ', %q(%w[)],
+ ['002:1:]:* ', %q()],
+ ['003:0: :> ', %q(])],
+ ]
+
+ assert_dynamic_prompt(input_with_prompt)
+ end
+
+ def assert_dynamic_prompt(input_with_prompt)
+ expected_prompt_list, lines = input_with_prompt.transpose
+ def @irb.generate_prompt(opens, continue, line_offset)
+ ltype = @scanner.ltype_from_open_tokens(opens)
+ indent = @scanner.calc_indent_level(opens)
+ continue = opens.any? || continue
+ line_no = @line_no + line_offset
+ '%03d:%01d:%1s:%s ' % [line_no, indent, ltype, continue ? '*' : '>']
+ end
+ io = MockIO_DynamicPrompt.new(lines)
+ @irb.context.io = io
+ @irb.configure_io
+
+ error_message = <<~EOM
+ Expected dynamic prompt:
+ #{expected_prompt_list.join("\n")}
+
+ Actual dynamic prompt:
+ #{io.prompt_list.join("\n")}
+ EOM
+ assert_equal(expected_prompt_list, io.prompt_list, error_message)
+ end
+ end
+
+ private
+
+ def build_binding
+ Object.new.instance_eval { binding }
+ end
+
+ def build_irb
+ IRB.init_config(nil)
+ workspace = IRB::WorkSpace.new(build_binding)
+
+ IRB.conf[:VERBOSE] = false
+ IRB::Irb.new(workspace, TestInputMethod.new)
+ end
+ end
+
+ class BacktraceFilteringTest < TestIRB::IntegrationTestCase
+ def setup
+ super
+ # These tests are sensitive to warnings, so we disable them
+ original_rubyopt = [ENV["RUBYOPT"], @envs["RUBYOPT"]].compact.join(" ")
+ @envs["RUBYOPT"] = original_rubyopt + " -W0"
+ end
+
+ def test_backtrace_filtering
+ write_ruby <<~'RUBY'
+ def foo
+ raise "error"
+ end
+
+ def bar
+ foo
+ end
+
+ binding.irb
+ RUBY
+
+ output = run_ruby_file do
+ type "bar"
+ type "exit"
+ end
+
+ assert_match(/irbtest-.*\.rb:2:in (`|'Object#)foo': error \(RuntimeError\)/, output)
+ frame_traces = output.split("\n").select { |line| line.strip.match?(/from /) }.map(&:strip)
+
+ expected_traces = if RUBY_VERSION >= "3.3.0"
+ [
+ /from .*\/irbtest-.*.rb:6:in (`|'Object#)bar'/,
+ /from .*\/irbtest-.*.rb\(irb\):1:in [`']<main>'/,
+ /from <internal:kernel>:\d+:in (`|'Kernel#)loop'/,
+ /from <internal:prelude>:\d+:in (`|'Binding#)irb'/,
+ /from .*\/irbtest-.*.rb:9:in [`']<main>'/
+ ]
+ else
+ [
+ /from .*\/irbtest-.*.rb:6:in (`|'Object#)bar'/,
+ /from .*\/irbtest-.*.rb\(irb\):1:in [`']<main>'/,
+ /from <internal:prelude>:\d+:in (`|'Binding#)irb'/,
+ /from .*\/irbtest-.*.rb:9:in [`']<main>'/
+ ]
+ end
+
+ expected_traces.reverse! if RUBY_VERSION < "3.0.0"
+
+ expected_traces.each_with_index do |expected_trace, index|
+ assert_match(expected_trace, frame_traces[index])
+ end
+ end
+
+ def test_backtrace_filtering_with_backtrace_filter
+ write_rc <<~'RUBY'
+ class TestBacktraceFilter
+ def self.call(backtrace)
+ backtrace.reject { |line| line.include?("internal") }
+ end
+ end
+
+ IRB.conf[:BACKTRACE_FILTER] = TestBacktraceFilter
+ RUBY
+
+ write_ruby <<~'RUBY'
+ def foo
+ raise "error"
+ end
+
+ def bar
+ foo
+ end
+
+ binding.irb
+ RUBY
+
+ output = run_ruby_file do
+ type "bar"
+ type "exit"
+ end
+
+ assert_match(/irbtest-.*\.rb:2:in (`|'Object#)foo': error \(RuntimeError\)/, output)
+ frame_traces = output.split("\n").select { |line| line.strip.match?(/from /) }.map(&:strip)
+
+ expected_traces = [
+ /from .*\/irbtest-.*.rb:6:in (`|'Object#)bar'/,
+ /from .*\/irbtest-.*.rb\(irb\):1:in [`']<main>'/,
+ /from .*\/irbtest-.*.rb:9:in [`']<main>'/
+ ]
+
+ expected_traces.reverse! if RUBY_VERSION < "3.0.0"
+
+ expected_traces.each_with_index do |expected_trace, index|
+ assert_match(expected_trace, frame_traces[index])
+ end
+ end
+ end
+end
diff --git a/test/irb/test_locale.rb b/test/irb/test_locale.rb
new file mode 100644
index 0000000000..930a38834c
--- /dev/null
+++ b/test/irb/test_locale.rb
@@ -0,0 +1,118 @@
+require "irb"
+require "stringio"
+
+require_relative "helper"
+
+module TestIRB
+ class LocaleTestCase < TestCase
+ def test_initialize_with_en
+ locale = IRB::Locale.new("en_US.UTF-8")
+
+ assert_equal("en", locale.lang)
+ assert_equal("US", locale.territory)
+ assert_equal("UTF-8", locale.encoding.name)
+ assert_equal(nil, locale.modifier)
+ end
+
+ def test_initialize_with_ja
+ locale = IRB::Locale.new("ja_JP.UTF-8")
+
+ assert_equal("ja", locale.lang)
+ assert_equal("JP", locale.territory)
+ assert_equal("UTF-8", locale.encoding.name)
+ assert_equal(nil, locale.modifier)
+ end
+
+ def test_initialize_with_legacy_ja_encoding_ujis
+ original_stderr = $stderr
+ $stderr = StringIO.new
+
+ locale = IRB::Locale.new("ja_JP.ujis")
+
+ assert_equal("ja", locale.lang)
+ assert_equal("JP", locale.territory)
+ assert_equal(Encoding::EUC_JP, locale.encoding)
+ assert_equal(nil, locale.modifier)
+
+ assert_include $stderr.string, "ja_JP.ujis is obsolete. use ja_JP.EUC-JP"
+ ensure
+ $stderr = original_stderr
+ end
+
+ def test_initialize_with_legacy_ja_encoding_euc
+ original_stderr = $stderr
+ $stderr = StringIO.new
+
+ locale = IRB::Locale.new("ja_JP.euc")
+
+ assert_equal("ja", locale.lang)
+ assert_equal("JP", locale.territory)
+ assert_equal(Encoding::EUC_JP, locale.encoding)
+ assert_equal(nil, locale.modifier)
+
+ assert_include $stderr.string, "ja_JP.euc is obsolete. use ja_JP.EUC-JP"
+ ensure
+ $stderr = original_stderr
+ end
+
+ %w(IRB_LANG LC_MESSAGES LC_ALL LANG).each do |env_var|
+ define_method "test_initialize_with_#{env_var.downcase}" do
+ original_values = {
+ "IRB_LANG" => ENV["IRB_LANG"],
+ "LC_MESSAGES" => ENV["LC_MESSAGES"],
+ "LC_ALL" => ENV["LC_ALL"],
+ "LANG" => ENV["LANG"],
+ }
+
+ ENV["IRB_LANG"] = ENV["LC_MESSAGES"] = ENV["LC_ALL"] = ENV["LANG"] = nil
+ ENV[env_var] = "zh_TW.UTF-8"
+
+ locale = IRB::Locale.new
+
+ assert_equal("zh", locale.lang)
+ assert_equal("TW", locale.territory)
+ assert_equal("UTF-8", locale.encoding.name)
+ assert_equal(nil, locale.modifier)
+ ensure
+ original_values.each do |key, value|
+ ENV[key] = value
+ end
+ end
+ end
+
+ def test_load
+ # reset Locale's internal cache
+ IRB::Locale.class_variable_set(:@@loaded, [])
+ # Because error.rb files define the same class, loading them causes method redefinition warnings.
+ original_verbose = $VERBOSE
+ $VERBOSE = nil
+
+ jp_local = IRB::Locale.new("ja_JP.UTF-8")
+ jp_local.load("irb/error.rb")
+ msg = IRB::CantReturnToNormalMode.new.message
+ assert_equal("Normalモードã«æˆ»ã‚Œã¾ã›ã‚“.", msg)
+
+ # reset Locale's internal cache
+ IRB::Locale.class_variable_set(:@@loaded, [])
+
+ en_local = IRB::Locale.new("en_US.UTF-8")
+ en_local.load("irb/error.rb")
+ msg = IRB::CantReturnToNormalMode.new.message
+ assert_equal("Can't return to normal mode.", msg)
+ ensure
+ # before turning warnings back on, load the error.rb file again to avoid warnings in other tests
+ IRB::Locale.new.load("irb/error.rb")
+ $VERBOSE = original_verbose
+ end
+
+ def test_find
+ jp_local = IRB::Locale.new("ja_JP.UTF-8")
+ path = jp_local.find("irb/error.rb")
+ assert_include(path, "/lib/irb/lc/ja/error.rb")
+
+ en_local = IRB::Locale.new("en_US.UTF-8")
+ path = en_local.find("irb/error.rb")
+ assert_include(path, "/lib/irb/lc/error.rb")
+ end
+ end
+end
diff --git a/test/irb/test_nesting_parser.rb b/test/irb/test_nesting_parser.rb
new file mode 100644
index 0000000000..2db3cdab57
--- /dev/null
+++ b/test/irb/test_nesting_parser.rb
@@ -0,0 +1,338 @@
+# frozen_string_literal: false
+require 'irb'
+
+require_relative "helper"
+
+module TestIRB
+ class NestingParserTest < TestCase
+ def setup
+ save_encodings
+ end
+
+ def teardown
+ restore_encodings
+ end
+
+ def parse_by_line(code)
+ IRB::NestingParser.parse_by_line(IRB::RubyLex.ripper_lex_without_warning(code))
+ end
+
+ def test_open_tokens
+ code = <<~'EOS'
+ class A
+ def f
+ if true
+ tap do
+ {
+ x: "
+ #{p(1, 2, 3
+ EOS
+ opens = IRB::NestingParser.open_tokens(IRB::RubyLex.ripper_lex_without_warning(code))
+ assert_equal(%w[class def if do { " #{ (], opens.map(&:tok))
+ end
+
+ def test_parse_by_line
+ code = <<~EOS
+ (((((1+2
+ ).to_s())).tap do (((
+ EOS
+ _tokens, prev_opens, next_opens, min_depth = parse_by_line(code).last
+ assert_equal(%w[( ( ( ( (], prev_opens.map(&:tok))
+ assert_equal(%w[( ( do ( ( (], next_opens.map(&:tok))
+ assert_equal(2, min_depth)
+ end
+
+ def test_ruby_syntax
+ code = <<~'EOS'
+ class A
+ 1 if 2
+ 1 while 2
+ 1 until 2
+ 1 unless 2
+ 1 rescue 2
+ begin; rescue; ensure; end
+ tap do; rescue; ensure; end
+ class B; end
+ module C; end
+ def f; end
+ def `; end
+ def f() = 1
+ %(); %w[]; %q(); %r{}; %i[]
+ "#{1}"; ''; /#{1}/; `#{1}`
+ :sym; :"sym"; :+; :`; :if
+ [1, 2, 3]
+ { x: 1, y: 2 }
+ (a, (*b, c), d), e = 1, 2, 3
+ ->(a){}; ->(a) do end
+ -> a = -> b = :do do end do end
+ if 1; elsif 2; else; end
+ unless 1; end
+ while 1; end
+ until 1; end
+ for i in j; end
+ case 1; when 2; end
+ puts(1, 2, 3)
+ loop{|i|}
+ loop do |i| end
+ end
+ EOS
+ line_results = parse_by_line(code)
+ assert_equal(code.lines.size, line_results.size)
+ class_open, *inner_line_results, class_close = line_results
+ assert_equal(['class'], class_open[2].map(&:tok))
+ inner_line_results.each {|result| assert_equal(['class'], result[2].map(&:tok)) }
+ assert_equal([], class_close[2].map(&:tok))
+ end
+
+ def test_multiline_string
+ code = <<~EOS
+ "
+ aaa
+ bbb
+ "
+ <<A
+ aaa
+ bbb
+ A
+ EOS
+ line_results = parse_by_line(code)
+ assert_equal(code.lines.size, line_results.size)
+ string_content_line, string_opens = line_results[1]
+ assert_equal("\naaa\nbbb\n", string_content_line.first.first.tok)
+ assert_equal("aaa\n", string_content_line.first.last)
+ assert_equal(['"'], string_opens.map(&:tok))
+ heredoc_content_line, heredoc_opens = line_results[6]
+ assert_equal("aaa\nbbb\n", heredoc_content_line.first.first.tok)
+ assert_equal("bbb\n", heredoc_content_line.first.last)
+ assert_equal(['<<A'], heredoc_opens.map(&:tok))
+ _line, _prev_opens, next_opens, _min_depth = line_results.last
+ assert_equal([], next_opens)
+ end
+
+ def test_backslash_continued_nested_symbol
+ code = <<~'EOS'
+ x = <<A, :\
+ heredoc #{
+ here
+ }
+ A
+ =begin
+ embdoc
+ =end
+ # comment
+
+ if # this is symbol :if
+ while
+ EOS
+ line_results = parse_by_line(code)
+ assert_equal(%w[: <<A #{], line_results[2][2].map(&:tok))
+ assert_equal(%w[while], line_results.last[2].map(&:tok))
+ end
+
+ def test_oneliner_def
+ code = <<~EOC
+ if true
+ # normal oneliner def
+ def f = 1
+ def f() = 1
+ def f(*) = 1
+ # keyword, backtick, op
+ def * = 1
+ def ` = 1
+ def if = 1
+ def *() = 1
+ def `() = 1
+ def if() = 1
+ # oneliner def with receiver
+ def a.* = 1
+ def $a.* = 1
+ def @a.` = 1
+ def A.` = 1
+ def ((a;b;c)).*() = 1
+ def ((a;b;c)).if() = 1
+ def ((a;b;c)).end() = 1
+ # multiline oneliner def
+ def f =
+ 1
+ def f()
+ =
+ 1
+ # oneliner def with comment and embdoc
+ def # comment
+ =begin
+ embdoc
+ =end
+ ((a;b;c))
+ . # comment
+ =begin
+ embdoc
+ =end
+ f (*) # comment
+ =begin
+ embdoc
+ =end
+ =
+ 1
+ # nested oneliner def
+ def f(x = def f() = 1) = def f() = 1
+ EOC
+ _tokens, _prev_opens, next_opens, min_depth = parse_by_line(code).last
+ assert_equal(['if'], next_opens.map(&:tok))
+ assert_equal(1, min_depth)
+ end
+
+ def test_heredoc_embexpr
+ code = <<~'EOS'
+ <<A+<<B+<<C+(<<D+(<<E)
+ #{
+ <<~F+"#{<<~G}
+ #{
+ here
+ }
+ F
+ G
+ "
+ }
+ A
+ B
+ C
+ D
+ E
+ )
+ EOS
+ line_results = parse_by_line(code)
+ last_opens = line_results.last[-2]
+ assert_equal([], last_opens)
+ _tokens, _prev_opens, next_opens, _min_depth = line_results[4]
+ assert_equal(%w[( <<E <<D <<C <<B <<A #{ " <<~G <<~F #{], next_opens.map(&:tok))
+ end
+
+ def test_for_in
+ code = <<~EOS
+ for i in j
+ here
+ end
+ for i in j do
+ here
+ end
+ for i in
+ j do
+ here
+ end
+ for
+ # comment
+ i in j do
+ here
+ end
+ for (a;b;c).d in (a;b;c) do
+ here
+ end
+ for i in :in + :do do
+ here
+ end
+ for i in -> do end do
+ here
+ end
+ EOS
+ line_results = parse_by_line(code).select { |tokens,| tokens.map(&:last).include?('here') }
+ assert_equal(7, line_results.size)
+ line_results.each do |_tokens, _prev_opens, next_opens, _min_depth|
+ assert_equal(['for'], next_opens.map(&:tok))
+ end
+ end
+
+ def test_while_until
+ base_code = <<~'EOS'
+ while_or_until true
+ here
+ end
+ while_or_until a < c
+ here
+ end
+ while_or_until true do
+ here
+ end
+ while_or_until
+ # comment
+ (a + b) <
+ # comment
+ c do
+ here
+ end
+ while_or_until :\
+ do do
+ here
+ end
+ while_or_until def do; end == :do do
+ here
+ end
+ while_or_until -> do end do
+ here
+ end
+ EOS
+ %w[while until].each do |keyword|
+ code = base_code.gsub('while_or_until', keyword)
+ line_results = parse_by_line(code).select { |tokens,| tokens.map(&:last).include?('here') }
+ assert_equal(7, line_results.size)
+ line_results.each do |_tokens, _prev_opens, next_opens, _min_depth|
+ assert_equal([keyword], next_opens.map(&:tok) )
+ end
+ end
+ end
+
+ def test_undef_alias
+ codes = [
+ 'undef foo',
+ 'alias foo bar',
+ 'undef !',
+ 'alias + -',
+ 'alias $a $b',
+ 'undef do',
+ 'alias do do',
+ 'undef :do',
+ 'alias :do :do',
+ 'undef :"#{alias do do}"',
+ 'alias :"#{undef do}" do',
+ 'alias do :"#{undef do}"'
+ ]
+ code_with_comment = <<~EOS
+ undef #
+ #
+ do #
+ alias #
+ #
+ do #
+ #
+ do #
+ EOS
+ code_with_heredoc = <<~EOS
+ <<~A; alias
+ A
+ :"#{<<~A}"
+ A
+ do
+ EOS
+ [*codes, code_with_comment, code_with_heredoc].each do |code|
+ opens = IRB::NestingParser.open_tokens(IRB::RubyLex.ripper_lex_without_warning('(' + code + "\nif"))
+ assert_equal(%w[( if], opens.map(&:tok))
+ end
+ end
+
+ def test_case_in
+ code = <<~EOS
+ case 1
+ in 1
+ here
+ in
+ 2
+ here
+ end
+ EOS
+ line_results = parse_by_line(code).select { |tokens,| tokens.map(&:last).include?('here') }
+ assert_equal(2, line_results.size)
+ line_results.each do |_tokens, _prev_opens, next_opens, _min_depth|
+ assert_equal(['in'], next_opens.map(&:tok))
+ end
+ end
+ end
+end
diff --git a/test/irb/test_option.rb b/test/irb/test_option.rb
index aa634c02a2..fec31f384f 100644
--- a/test/irb/test_option.rb
+++ b/test/irb/test_option.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: false
-require 'test/unit'
+require_relative "helper"
module TestIRB
- class TestOption < Test::Unit::TestCase
+ class OptionTest < TestCase
def test_end_of_option
bug4117 = '[ruby-core:33574]'
bundle_exec = ENV.key?('BUNDLE_GEMFILE') ? ['-rbundler/setup'] : []
diff --git a/test/irb/test_raise_exception.rb b/test/irb/test_raise_exception.rb
new file mode 100644
index 0000000000..44a5ae87e1
--- /dev/null
+++ b/test/irb/test_raise_exception.rb
@@ -0,0 +1,74 @@
+# frozen_string_literal: false
+require "tmpdir"
+
+require_relative "helper"
+
+module TestIRB
+ class RaiseExceptionTest < TestCase
+ def test_raise_exception_with_nil_backtrace
+ bundle_exec = ENV.key?('BUNDLE_GEMFILE') ? ['-rbundler/setup'] : []
+ assert_in_out_err(bundle_exec + %w[-rirb -W0 -e IRB.start(__FILE__) -- -f --], <<-IRB, /#<Exception: foo>/, [])
+ raise Exception.new("foo").tap {|e| def e.backtrace; nil; end }
+IRB
+ end
+
+ def test_raise_exception_with_message_exception
+ bundle_exec = ENV.key?('BUNDLE_GEMFILE') ? ['-rbundler/setup'] : []
+ expected = /#<Exception: foo>\nbacktraces are hidden because bar was raised when processing them/
+ assert_in_out_err(bundle_exec + %w[-rirb -W0 -e IRB.start(__FILE__) -- -f --], <<-IRB, expected, [])
+ e = Exception.new("foo")
+ def e.message; raise 'bar'; end
+ raise e
+IRB
+ end
+
+ def test_raise_exception_with_message_inspect_exception
+ bundle_exec = ENV.key?('BUNDLE_GEMFILE') ? ['-rbundler/setup'] : []
+ expected = /Uninspectable exception occurred/
+ assert_in_out_err(bundle_exec + %w[-rirb -W0 -e IRB.start(__FILE__) -- -f --], <<-IRB, expected, [])
+ e = Exception.new("foo")
+ def e.message; raise; end
+ def e.inspect; raise; end
+ raise e
+IRB
+ end
+
+ def test_raise_exception_with_invalid_byte_sequence
+ pend if RUBY_ENGINE == 'truffleruby' || /mswin|mingw/ =~ RUBY_PLATFORM
+ bundle_exec = ENV.key?('BUNDLE_GEMFILE') ? ['-rbundler/setup'] : []
+ assert_in_out_err(bundle_exec + %w[-rirb -W0 -e IRB.start(__FILE__) -- -f --], <<~IRB, /A\\xF3B \(StandardError\)/, [])
+ raise StandardError, "A\\xf3B"
+ IRB
+ end
+
+ def test_raise_exception_with_different_encoding_containing_invalid_byte_sequence
+ backup_home = ENV["HOME"]
+ Dir.mktmpdir("test_irb_raise_no_backtrace_exception_#{$$}") do |tmpdir|
+ ENV["HOME"] = tmpdir
+
+ bundle_exec = ENV.key?('BUNDLE_GEMFILE') ? ['-rbundler/setup'] : []
+ File.open("#{tmpdir}/euc.rb", 'w') do |f|
+ f.write(<<~EOF)
+ # encoding: euc-jp
+
+ def raise_euc_with_invalid_byte_sequence
+ raise "\xA4\xA2\\xFF"
+ end
+ EOF
+ end
+ env = {}
+ %w(LC_MESSAGES LC_ALL LC_CTYPE LANG).each {|n| env[n] = "ja_JP.UTF-8" }
+ # TruffleRuby warns when the locale does not exist
+ env['TRUFFLERUBYOPT'] = "#{ENV['TRUFFLERUBYOPT']} --log.level=SEVERE" if RUBY_ENGINE == 'truffleruby'
+ args = [env] + bundle_exec + %W[-rirb -C #{tmpdir} -W0 -e IRB.start(__FILE__) -- -f --]
+ error = /raise_euc_with_invalid_byte_sequence': ã‚\\xFF \(RuntimeError\)/
+ assert_in_out_err(args, <<~IRB, error, [], encoding: "UTF-8")
+ require_relative 'euc'
+ raise_euc_with_invalid_byte_sequence
+ IRB
+ end
+ ensure
+ ENV["HOME"] = backup_home
+ end
+ end
+end
diff --git a/test/irb/test_raise_no_backtrace_exception.rb b/test/irb/test_raise_no_backtrace_exception.rb
deleted file mode 100644
index 530adc0cbf..0000000000
--- a/test/irb/test_raise_no_backtrace_exception.rb
+++ /dev/null
@@ -1,54 +0,0 @@
-# frozen_string_literal: false
-require 'test/unit'
-
-module TestIRB
- class TestRaiseNoBacktraceException < Test::Unit::TestCase
- def test_raise_exception
- pend if RUBY_ENGINE == 'truffleruby'
- bundle_exec = ENV.key?('BUNDLE_GEMFILE') ? ['-rbundler/setup'] : []
- assert_in_out_err(bundle_exec + %w[-rirb -W0 -e IRB.start(__FILE__) -- -f --], <<-IRB, /Exception: foo/, [])
- e = Exception.new("foo")
- puts e.inspect
- def e.backtrace; nil; end
- raise e
-IRB
- end
-
- def test_raise_exception_with_invalid_byte_sequence
- pend if RUBY_ENGINE == 'truffleruby' || /mswin|mingw/ =~ RUBY_PLATFORM
- bundle_exec = ENV.key?('BUNDLE_GEMFILE') ? ['-rbundler/setup'] : []
- assert_in_out_err(bundle_exec + %w[-rirb -W0 -e IRB.start(__FILE__) -- -f --], <<~IRB, /A\\xF3B \(StandardError\)/, [])
- raise StandardError, "A\\xf3B"
- IRB
- end
-
- def test_raise_exception_with_different_encoding_containing_invalid_byte_sequence
- pend if RUBY_ENGINE == 'truffleruby'
- backup_home = ENV["HOME"]
- Dir.mktmpdir("test_irb_raise_no_backtrace_exception_#{$$}") do |tmpdir|
- ENV["HOME"] = tmpdir
-
- bundle_exec = ENV.key?('BUNDLE_GEMFILE') ? ['-rbundler/setup'] : []
- File.open("#{tmpdir}/euc.rb", 'w') do |f|
- f.write(<<~EOF)
- # encoding: euc-jp
-
- def raise_euc_with_invalid_byte_sequence
- raise "\xA4\xA2\\xFF"
- end
- EOF
- end
- env = {}
- %w(LC_MESSAGES LC_ALL LC_CTYPE LANG).each {|n| env[n] = "ja_JP.UTF-8" }
- args = [env] + bundle_exec + %W[-rirb -C #{tmpdir} -W0 -e IRB.start(__FILE__) -- -f --]
- error = /`raise_euc_with_invalid_byte_sequence': ã‚\\xFF \(RuntimeError\)/
- assert_in_out_err(args, <<~IRB, error, [], encoding: "UTF-8")
- require_relative 'euc'
- raise_euc_with_invalid_byte_sequence
- IRB
- end
- ensure
- ENV["HOME"] = backup_home
- end
- end
-end
diff --git a/test/irb/test_ruby_lex.rb b/test/irb/test_ruby_lex.rb
index e02370d3f7..4e406a8ce0 100644
--- a/test/irb/test_ruby_lex.rb
+++ b/test/irb/test_ruby_lex.rb
@@ -1,606 +1,242 @@
-$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
-require 'irb/ruby-lex'
-require 'test/unit'
-require 'ostruct'
+# frozen_string_literal: true
+require "irb"
-module TestIRB
- class TestRubyLex < Test::Unit::TestCase
- Row = Struct.new(:content, :current_line_spaces, :new_line_spaces, :nesting_level)
-
- class MockIO_AutoIndent
- def initialize(params, &assertion)
- @params = params
- @assertion = assertion
- end
-
- def auto_indent(&block)
- result = block.call(*@params)
- @assertion.call(result)
- end
- end
-
- def assert_indenting(lines, correct_space_count, add_new_line)
- lines = lines + [""] if add_new_line
- last_line_index = lines.length - 1
- byte_pointer = lines.last.length
-
- ruby_lex = RubyLex.new()
- io = MockIO_AutoIndent.new([lines, last_line_index, byte_pointer, add_new_line]) do |auto_indent|
- error_message = "Calculated the wrong number of spaces for:\n #{lines.join("\n")}"
- assert_equal(correct_space_count, auto_indent, error_message)
- end
- ruby_lex.set_input(io)
- context = OpenStruct.new(auto_indent_mode: true)
- ruby_lex.set_auto_indent(context)
- end
-
- def assert_nesting_level(lines, expected)
- ruby_lex = RubyLex.new()
- io = proc{ lines.join("\n") }
- ruby_lex.set_input(io, io)
- ruby_lex.lex
- error_message = "Calculated the wrong number of nesting level for:\n #{lines.join("\n")}"
- assert_equal(expected, ruby_lex.instance_variable_get(:@indent), error_message)
- end
-
- def test_auto_indent
- input_with_correct_indents = [
- Row.new(%q(def each_top_level_statement), nil, 2),
- Row.new(%q( initialize_input), nil, 2),
- Row.new(%q( catch(:TERM_INPUT) do), nil, 4),
- Row.new(%q( loop do), nil, 6),
- Row.new(%q( begin), nil, 8),
- Row.new(%q( prompt), nil, 8),
- Row.new(%q( unless l = lex), nil, 10),
- Row.new(%q( throw :TERM_INPUT if @line == ''), nil, 10),
- Row.new(%q( else), 8, 10),
- Row.new(%q( @line_no += l.count("\n")), nil, 10),
- Row.new(%q( next if l == "\n"), nil, 10),
- Row.new(%q( @line.concat l), nil, 10),
- Row.new(%q( if @code_block_open or @ltype or @continue or @indent > 0), nil, 12),
- Row.new(%q( next), nil, 12),
- Row.new(%q( end), 10, 10),
- Row.new(%q( end), 8, 8),
- Row.new(%q( if @line != "\n"), nil, 10),
- Row.new(%q( @line.force_encoding(@io.encoding)), nil, 10),
- Row.new(%q( yield @line, @exp_line_no), nil, 10),
- Row.new(%q( end), 8, 8),
- Row.new(%q( break if @io.eof?), nil, 8),
- Row.new(%q( @line = ''), nil, 8),
- Row.new(%q( @exp_line_no = @line_no), nil, 8),
- Row.new(%q( ), nil, 8),
- Row.new(%q( @indent = 0), nil, 8),
- Row.new(%q( rescue TerminateLineInput), 6, 8),
- Row.new(%q( initialize_input), nil, 8),
- Row.new(%q( prompt), nil, 8),
- Row.new(%q( end), 6, 6),
- Row.new(%q( end), 4, 4),
- Row.new(%q( end), 2, 2),
- Row.new(%q(end), 0, 0),
- ]
-
- lines = []
- input_with_correct_indents.each do |row|
- lines << row.content
- assert_indenting(lines, row.current_line_spaces, false)
- assert_indenting(lines, row.new_line_spaces, true)
- end
- end
-
- def test_braces_on_their_own_line
- input_with_correct_indents = [
- Row.new(%q(if true), nil, 2),
- Row.new(%q( [), nil, 4),
- Row.new(%q( ]), 2, 2),
- Row.new(%q(end), 0, 0),
- ]
-
- lines = []
- input_with_correct_indents.each do |row|
- lines << row.content
- assert_indenting(lines, row.current_line_spaces, false)
- assert_indenting(lines, row.new_line_spaces, true)
- end
- end
-
- def test_multiple_braces_in_a_line
- input_with_correct_indents = [
- Row.new(%q([[[), nil, 6),
- Row.new(%q( ]), 4, 4),
- Row.new(%q( ]), 2, 2),
- Row.new(%q(]), 0, 0),
- Row.new(%q([<<FOO]), 0, 0),
- Row.new(%q(hello), 0, 0),
- Row.new(%q(FOO), nil, 0),
- ]
-
- lines = []
- input_with_correct_indents.each do |row|
- lines << row.content
- assert_indenting(lines, row.current_line_spaces, false)
- assert_indenting(lines, row.new_line_spaces, true)
- end
- end
-
- def test_a_closed_brace_and_not_closed_brace_in_a_line
- input_with_correct_indents = [
- Row.new(%q(p() {), nil, 2),
- Row.new(%q(}), 0, 0),
- ]
-
- lines = []
- input_with_correct_indents.each do |row|
- lines << row.content
- assert_indenting(lines, row.current_line_spaces, false)
- assert_indenting(lines, row.new_line_spaces, true)
- end
- end
-
- def test_symbols
- input_with_correct_indents = [
- Row.new(%q(:a), nil, 0),
- Row.new(%q(:A), nil, 0),
- Row.new(%q(:+), nil, 0),
- Row.new(%q(:@@a), nil, 0),
- Row.new(%q(:@a), nil, 0),
- Row.new(%q(:$a), nil, 0),
- Row.new(%q(:def), nil, 0),
- Row.new(%q(:`), nil, 0),
- ]
-
- lines = []
- input_with_correct_indents.each do |row|
- lines << row.content
- assert_indenting(lines, row.current_line_spaces, false)
- assert_indenting(lines, row.new_line_spaces, true)
- end
- end
-
- def test_endless_range_at_end_of_line
- if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.6.0')
- pend 'Endless range is available in 2.6.0 or later'
- end
- input_with_prompt = [
- PromptRow.new('001:0: :> ', %q(a = 3..)),
- PromptRow.new('002:0: :* ', %q()),
- ]
-
- lines = input_with_prompt.map(&:content)
- expected_prompt_list = input_with_prompt.map(&:prompt)
- assert_dynamic_prompt(lines, expected_prompt_list)
- end
-
- def test_incomplete_coding_magic_comment
- input_with_correct_indents = [
- Row.new(%q(#coding:u), nil, 0),
- ]
-
- lines = []
- input_with_correct_indents.each do |row|
- lines << row.content
- assert_indenting(lines, row.current_line_spaces, false)
- assert_indenting(lines, row.new_line_spaces, true)
- end
- end
-
- def test_incomplete_encoding_magic_comment
- input_with_correct_indents = [
- Row.new(%q(#encoding:u), nil, 0),
- ]
-
- lines = []
- input_with_correct_indents.each do |row|
- lines << row.content
- assert_indenting(lines, row.current_line_spaces, false)
- assert_indenting(lines, row.new_line_spaces, true)
- end
- end
-
- def test_incomplete_emacs_coding_magic_comment
- input_with_correct_indents = [
- Row.new(%q(# -*- coding: u), nil, 0),
- ]
-
- lines = []
- input_with_correct_indents.each do |row|
- lines << row.content
- assert_indenting(lines, row.current_line_spaces, false)
- assert_indenting(lines, row.new_line_spaces, true)
- end
- end
-
- def test_incomplete_vim_coding_magic_comment
- input_with_correct_indents = [
- Row.new(%q(# vim:set fileencoding=u), nil, 0),
- ]
-
- lines = []
- input_with_correct_indents.each do |row|
- lines << row.content
- assert_indenting(lines, row.current_line_spaces, false)
- assert_indenting(lines, row.new_line_spaces, true)
- end
- end
-
- def test_mixed_rescue
- input_with_correct_indents = [
- Row.new(%q(def m), nil, 2),
- Row.new(%q( begin), nil, 4),
- Row.new(%q( begin), nil, 6),
- Row.new(%q( x = a rescue 4), nil, 6),
- Row.new(%q( y = [(a rescue 5)]), nil, 6),
- Row.new(%q( [x, y]), nil, 6),
- Row.new(%q( rescue => e), 4, 6),
- Row.new(%q( raise e rescue 8), nil, 6),
- Row.new(%q( end), 4, 4),
- Row.new(%q( rescue), 2, 4),
- Row.new(%q( raise rescue 11), nil, 4),
- Row.new(%q( end), 2, 2),
- Row.new(%q(rescue => e), 0, 2),
- Row.new(%q( raise e rescue 14), nil, 2),
- Row.new(%q(end), 0, 0),
- ]
-
- lines = []
- input_with_correct_indents.each do |row|
- lines << row.content
- assert_indenting(lines, row.current_line_spaces, false)
- assert_indenting(lines, row.new_line_spaces, true)
- end
- end
-
- def test_oneliner_method_definition
- input_with_correct_indents = [
- Row.new(%q(class A), nil, 2),
- Row.new(%q( def foo0), nil, 4),
- Row.new(%q( 3), nil, 4),
- Row.new(%q( end), 2, 2),
- Row.new(%q( def foo1()), nil, 4),
- Row.new(%q( 3), nil, 4),
- Row.new(%q( end), 2, 2),
- Row.new(%q( def foo2(a, b)), nil, 4),
- Row.new(%q( a + b), nil, 4),
- Row.new(%q( end), 2, 2),
- Row.new(%q( def foo3 a, b), nil, 4),
- Row.new(%q( a + b), nil, 4),
- Row.new(%q( end), 2, 2),
- Row.new(%q( def bar0() = 3), nil, 2),
- Row.new(%q( def bar1(a) = a), nil, 2),
- Row.new(%q( def bar2(a, b) = a + b), nil, 2),
- Row.new(%q( def bar3() = :s), nil, 2),
- Row.new(%q( def bar4() = Time.now), nil, 2),
- Row.new(%q(end), 0, 0),
- ]
-
- lines = []
- input_with_correct_indents.each do |row|
- lines << row.content
- assert_indenting(lines, row.current_line_spaces, false)
- assert_indenting(lines, row.new_line_spaces, true)
- end
- end
-
- def test_tlambda
- input_with_correct_indents = [
- Row.new(%q(if true), nil, 2, 1),
- Row.new(%q( -> {), nil, 4, 2),
- Row.new(%q( }), 2, 2, 1),
- Row.new(%q(end), 0, 0, 0),
- ]
+require_relative "helper"
- lines = []
- input_with_correct_indents.each do |row|
- lines << row.content
- assert_indenting(lines, row.current_line_spaces, false)
- assert_indenting(lines, row.new_line_spaces, true)
- assert_nesting_level(lines, row.nesting_level)
- end
+module TestIRB
+ class RubyLexTest < TestCase
+ def setup
+ save_encodings
end
- def test_corresponding_syntax_to_keyword_do_in_class
- input_with_correct_indents = [
- Row.new(%q(class C), nil, 2, 1),
- Row.new(%q( while method_name do), nil, 4, 2),
- Row.new(%q( 3), nil, 4, 2),
- Row.new(%q( end), 2, 2, 1),
- Row.new(%q( foo do), nil, 4, 2),
- Row.new(%q( 3), nil, 4, 2),
- Row.new(%q( end), 2, 2, 1),
- Row.new(%q(end), 0, 0, 0),
- ]
-
- lines = []
- input_with_correct_indents.each do |row|
- lines << row.content
- assert_indenting(lines, row.current_line_spaces, false)
- assert_indenting(lines, row.new_line_spaces, true)
- assert_nesting_level(lines, row.nesting_level)
- end
+ def teardown
+ restore_encodings
end
- def test_corresponding_syntax_to_keyword_do
- input_with_correct_indents = [
- Row.new(%q(while i > 0), nil, 2, 1),
- Row.new(%q( 3), nil, 2, 1),
- Row.new(%q(end), 0, 0, 0),
- Row.new(%q(while true), nil, 2, 1),
- Row.new(%q( 3), nil, 2, 1),
- Row.new(%q(end), 0, 0, 0),
- Row.new(%q(while ->{i > 0}.call), nil, 2, 1),
- Row.new(%q( 3), nil, 2, 1),
- Row.new(%q(end), 0, 0, 0),
- Row.new(%q(while ->{true}.call), nil, 2, 1),
- Row.new(%q( 3), nil, 2, 1),
- Row.new(%q(end), 0, 0, 0),
- Row.new(%q(while i > 0 do), nil, 2, 1),
- Row.new(%q( 3), nil, 2, 1),
- Row.new(%q(end), 0, 0, 0),
- Row.new(%q(while true do), nil, 2, 1),
- Row.new(%q( 3), nil, 2, 1),
- Row.new(%q(end), 0, 0, 0),
- Row.new(%q(while ->{i > 0}.call do), nil, 2, 1),
- Row.new(%q( 3), nil, 2, 1),
- Row.new(%q(end), 0, 0, 0),
- Row.new(%q(while ->{true}.call do), nil, 2, 1),
- Row.new(%q( 3), nil, 2, 1),
- Row.new(%q(end), 0, 0, 0),
- Row.new(%q(foo do), nil, 2, 1),
- Row.new(%q( 3), nil, 2, 1),
- Row.new(%q(end), 0, 0, 0),
- Row.new(%q(foo true do), nil, 2, 1),
- Row.new(%q( 3), nil, 2, 1),
- Row.new(%q(end), 0, 0, 0),
- Row.new(%q(foo ->{true} do), nil, 2, 1),
- Row.new(%q( 3), nil, 2, 1),
- Row.new(%q(end), 0, 0, 0),
- Row.new(%q(foo ->{i > 0} do), nil, 2, 1),
- Row.new(%q( 3), nil, 2, 1),
- Row.new(%q(end), 0, 0, 0),
- ]
-
- lines = []
- input_with_correct_indents.each do |row|
- lines << row.content
- assert_indenting(lines, row.current_line_spaces, false)
- assert_indenting(lines, row.new_line_spaces, true)
- assert_nesting_level(lines, row.nesting_level)
+ def test_interpolate_token_with_heredoc_and_unclosed_embexpr
+ code = <<~'EOC'
+ â‘ +<<A-â‘¡
+ #{â‘¢*<<B/â‘£
+ #{⑤&<<C|⑥
+ EOC
+ ripper_tokens = Ripper.tokenize(code)
+ rubylex_tokens = IRB::RubyLex.ripper_lex_without_warning(code)
+ # Assert no missing part
+ assert_equal(code, rubylex_tokens.map(&:tok).join)
+ # Assert ripper tokens are not removed
+ ripper_tokens.each do |tok|
+ assert(rubylex_tokens.any? { |t| t.tok == tok && t.tok != :on_ignored_by_ripper })
end
- end
-
- def test_corresponding_syntax_to_keyword_for
- input_with_correct_indents = [
- Row.new(%q(for i in [1]), nil, 2, 1),
- Row.new(%q( puts i), nil, 2, 1),
- Row.new(%q(end), 0, 0, 0),
- ]
-
- lines = []
- input_with_correct_indents.each do |row|
- lines << row.content
- assert_indenting(lines, row.current_line_spaces, false)
- assert_indenting(lines, row.new_line_spaces, true)
- assert_nesting_level(lines, row.nesting_level)
+ # Assert interpolated token position
+ rubylex_tokens.each do |t|
+ row, col = t.pos
+ assert_equal t.tok, code.lines[row - 1].byteslice(col, t.tok.bytesize)
end
end
- def test_corresponding_syntax_to_keyword_for_with_do
- input_with_correct_indents = [
- Row.new(%q(for i in [1] do), nil, 2, 1),
- Row.new(%q( puts i), nil, 2, 1),
- Row.new(%q(end), 0, 0, 0),
- ]
-
- lines = []
- input_with_correct_indents.each do |row|
- lines << row.content
- assert_indenting(lines, row.current_line_spaces, false)
- assert_indenting(lines, row.new_line_spaces, true)
- assert_nesting_level(lines, row.nesting_level)
- end
+ def test_local_variables_dependent_code
+ lines = ["a /1#/ do", "2"]
+ assert_indent_level(lines, 1)
+ assert_code_block_open(lines, true)
+ assert_indent_level(lines, 0, local_variables: ['a'])
+ assert_code_block_open(lines, false, local_variables: ['a'])
end
- def test_bracket_corresponding_to_times
- input_with_correct_indents = [
- Row.new(%q(3.times { |i|), nil, 2, 1),
- Row.new(%q( puts i), nil, 2, 1),
- Row.new(%q(}), 0, 0, 0),
- ]
-
- lines = []
- input_with_correct_indents.each do |row|
- lines << row.content
- assert_indenting(lines, row.current_line_spaces, false)
- assert_indenting(lines, row.new_line_spaces, true)
- assert_nesting_level(lines, row.nesting_level)
- end
+ def test_literal_ends_with_space
+ assert_code_block_open(['% a'], true)
+ assert_code_block_open(['% a '], false)
end
- def test_do_corresponding_to_times
- input_with_correct_indents = [
- Row.new(%q(3.times do |i|), nil, 2, 1),
- #Row.new(%q( puts i), nil, 2, 1),
- #Row.new(%q(end), 0, 0, 0),
- ]
-
- lines = []
- input_with_correct_indents.each do |row|
- lines << row.content
- assert_indenting(lines, row.current_line_spaces, false)
- assert_indenting(lines, row.new_line_spaces, true)
- assert_nesting_level(lines, row.nesting_level)
- end
+ def test_literal_ends_with_newline
+ assert_code_block_open(['%'], true)
+ assert_code_block_open(['%', ''], false)
end
- def test_bracket_corresponding_to_loop
- input_with_correct_indents = [
- Row.new(%q(loop {), nil, 2, 1),
- Row.new(%q( 3), nil, 2, 1),
- Row.new(%q(}), 0, 0, 0),
- ]
-
- lines = []
- input_with_correct_indents.each do |row|
- lines << row.content
- assert_indenting(lines, row.current_line_spaces, false)
- assert_indenting(lines, row.new_line_spaces, true)
- assert_nesting_level(lines, row.nesting_level)
- end
- end
-
- def test_do_corresponding_to_loop
- input_with_correct_indents = [
- Row.new(%q(loop do), nil, 2, 1),
- Row.new(%q( 3), nil, 2, 1),
- Row.new(%q(end), 0, 0, 0),
- ]
-
- lines = []
- input_with_correct_indents.each do |row|
- lines << row.content
- assert_indenting(lines, row.current_line_spaces, false)
- assert_indenting(lines, row.new_line_spaces, true)
- assert_nesting_level(lines, row.nesting_level)
- end
+ def test_should_continue
+ assert_should_continue(['a'], false)
+ assert_should_continue(['/a/'], false)
+ assert_should_continue(['a;'], false)
+ assert_should_continue(['<<A', 'A'], false)
+ assert_should_continue(['a...'], false)
+ assert_should_continue(['a\\'], true)
+ assert_should_continue(['a.'], true)
+ assert_should_continue(['a+'], true)
+ assert_should_continue(['a; #comment', '', '=begin', 'embdoc', '=end', ''], false)
+ assert_should_continue(['a+ #comment', '', '=begin', 'embdoc', '=end', ''], true)
end
- def test_heredoc_with_indent
- input_with_correct_indents = [
- Row.new(%q(<<~Q), 0, 0, 0),
- Row.new(%q({), 0, 0, 0),
- Row.new(%q( #), 2, 0, 0),
- Row.new(%q(}), 0, 0, 0)
- ]
+ def test_code_block_open_with_should_continue
+ # syntax ok
+ assert_code_block_open(['a'], false) # continue: false
+ assert_code_block_open(['a\\'], true) # continue: true
- lines = []
- input_with_correct_indents.each do |row|
- lines << row.content
- assert_indenting(lines, row.current_line_spaces, false)
- assert_indenting(lines, row.new_line_spaces, true)
- assert_nesting_level(lines, row.nesting_level)
- end
- end
+ # recoverable syntax error code is not terminated
+ assert_code_block_open(['a+'], true)
- def test_oneliner_def_in_multiple_lines
- input_with_correct_indents = [
- Row.new(%q(def a()=[), nil, 4, 2),
- Row.new(%q( 1,), nil, 4, 1),
- Row.new(%q(].), 0, 0, 0),
- Row.new(%q(to_s), nil, 0, 0),
- ]
+ # unrecoverable syntax error code is terminated
+ assert_code_block_open(['.; a+'], false)
- lines = []
- input_with_correct_indents.each do |row|
- lines << row.content
- assert_indenting(lines, row.current_line_spaces, false)
- assert_indenting(lines, row.new_line_spaces, true)
- assert_nesting_level(lines, row.nesting_level)
- end
- end
-
- def test_broken_heredoc
- if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.7.0')
- pend 'This test needs Ripper::Lexer#scan to take broken tokens'
- end
- input_with_correct_indents = [
- Row.new(%q(def foo), nil, 2, 1),
- Row.new(%q( <<~Q), 2, 2, 1),
- Row.new(%q( Qend), 2, 2, 1),
- ]
-
- lines = []
- input_with_correct_indents.each do |row|
- lines << row.content
- assert_indenting(lines, row.current_line_spaces, false)
- assert_indenting(lines, row.new_line_spaces, true)
- assert_nesting_level(lines, row.nesting_level)
- end
- end
-
- PromptRow = Struct.new(:prompt, :content)
-
- class MockIO_DynamicPrompt
- def initialize(params, &assertion)
- @params = params
- @assertion = assertion
- end
-
- def dynamic_prompt(&block)
- result = block.call(@params)
- @assertion.call(result)
- end
- end
-
- def assert_dynamic_prompt(lines, expected_prompt_list)
- pend if RUBY_ENGINE == 'truffleruby'
- ruby_lex = RubyLex.new()
- io = MockIO_DynamicPrompt.new(lines) do |prompt_list|
- error_message = <<~EOM
- Expected dynamic prompt:
- #{expected_prompt_list.join("\n")}
-
- Actual dynamic prompt:
- #{prompt_list.join("\n")}
- EOM
- assert_equal(expected_prompt_list, prompt_list, error_message)
- end
- ruby_lex.set_prompt do |ltype, indent, continue, line_no|
- '%03d:%01d:%1s:%s ' % [line_no, indent, ltype, continue ? '*' : '>']
- end
- ruby_lex.set_input(io)
- end
-
- def test_dyanmic_prompt
- input_with_prompt = [
- PromptRow.new('001:1: :* ', %q(def hoge)),
- PromptRow.new('002:1: :* ', %q( 3)),
- PromptRow.new('003:0: :> ', %q(end)),
- ]
-
- lines = input_with_prompt.map(&:content)
- expected_prompt_list = input_with_prompt.map(&:prompt)
- assert_dynamic_prompt(lines, expected_prompt_list)
- end
-
- def test_dyanmic_prompt_with_blank_line
- input_with_prompt = [
- PromptRow.new('001:0:]:* ', %q(%w[)),
- PromptRow.new('002:0:]:* ', %q()),
- PromptRow.new('003:0: :> ', %q(])),
- ]
-
- lines = input_with_prompt.map(&:content)
- expected_prompt_list = input_with_prompt.map(&:prompt)
- assert_dynamic_prompt(lines, expected_prompt_list)
+ # other syntax error that failed to determine if it is recoverable or not
+ assert_code_block_open(['@; a'], false)
+ assert_code_block_open(['@; a+'], true)
+ assert_code_block_open(['@; (a'], true)
end
def test_broken_percent_literal
- if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.7.0')
- pend 'This test needs Ripper::Lexer#scan to take broken tokens'
- end
-
- tokens = RubyLex.ripper_lex_without_warning('%wwww')
+ tokens = IRB::RubyLex.ripper_lex_without_warning('%wwww')
pos_to_index = {}
tokens.each_with_index { |t, i|
- assert_nil(pos_to_index[t[0]], "There is already another token in the position of #{t.inspect}.")
- pos_to_index[t[0]] = i
+ assert_nil(pos_to_index[t.pos], "There is already another token in the position of #{t.inspect}.")
+ pos_to_index[t.pos] = i
}
end
def test_broken_percent_literal_in_method
- if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.7.0')
- pend 'This test needs Ripper::Lexer#scan to take broken tokens'
- end
-
- tokens = RubyLex.ripper_lex_without_warning(<<~EOC.chomp)
+ tokens = IRB::RubyLex.ripper_lex_without_warning(<<~EOC.chomp)
def foo
%wwww
end
EOC
pos_to_index = {}
tokens.each_with_index { |t, i|
- assert_nil(pos_to_index[t[0]], "There is already another token in the position of #{t.inspect}.")
- pos_to_index[t[0]] = i
+ assert_nil(pos_to_index[t.pos], "There is already another token in the position of #{t.inspect}.")
+ pos_to_index[t.pos] = i
}
end
+
+ def test_unterminated_code
+ ['do', '<<A'].each do |code|
+ tokens = IRB::RubyLex.ripper_lex_without_warning(code)
+ assert_equal(code, tokens.map(&:tok).join, "Cannot reconstruct code from tokens")
+ error_tokens = tokens.map(&:event).grep(/error/)
+ assert_empty(error_tokens, 'Error tokens must be ignored if there is corresponding non-error token')
+ end
+ end
+
+ def test_unterminated_heredoc_string_literal
+ ['<<A;<<B', "<<A;<<B\n", "%W[\#{<<A;<<B", "%W[\#{<<A;<<B\n"].each do |code|
+ tokens = IRB::RubyLex.ripper_lex_without_warning(code)
+ string_literal = IRB::NestingParser.open_tokens(tokens).last
+ assert_equal('<<A', string_literal&.tok)
+ end
+ end
+
+ def test_indent_level_with_heredoc_and_embdoc
+ reference_code = <<~EOC.chomp
+ if true
+ hello
+ p(
+ )
+ EOC
+ code_with_heredoc = <<~EOC.chomp
+ if true
+ <<~A
+ A
+ p(
+ )
+ EOC
+ code_with_embdoc = <<~EOC.chomp
+ if true
+ =begin
+ =end
+ p(
+ )
+ EOC
+ expected = 1
+ assert_indent_level(reference_code.lines, expected)
+ assert_indent_level(code_with_heredoc.lines, expected)
+ assert_indent_level(code_with_embdoc.lines, expected)
+ end
+
+ def test_assignment_expression
+ ruby_lex = IRB::RubyLex.new
+
+ [
+ "foo = bar",
+ "@foo = bar",
+ "$foo = bar",
+ "@@foo = bar",
+ "::Foo = bar",
+ "a::Foo = bar",
+ "Foo = bar",
+ "foo.bar = 1",
+ "foo[1] = bar",
+ "foo += bar",
+ "foo -= bar",
+ "foo ||= bar",
+ "foo &&= bar",
+ "foo, bar = 1, 2",
+ "foo.bar=(1)",
+ "foo; foo = bar",
+ "foo; foo = bar; ;\n ;",
+ "foo\nfoo = bar",
+ ].each do |exp|
+ assert(
+ ruby_lex.assignment_expression?(exp, local_variables: []),
+ "#{exp.inspect}: should be an assignment expression"
+ )
+ end
+
+ [
+ "foo",
+ "foo.bar",
+ "foo[0]",
+ "foo = bar; foo",
+ "foo = bar\nfoo",
+ ].each do |exp|
+ refute(
+ ruby_lex.assignment_expression?(exp, local_variables: []),
+ "#{exp.inspect}: should not be an assignment expression"
+ )
+ end
+ end
+
+ def test_assignment_expression_with_local_variable
+ ruby_lex = IRB::RubyLex.new
+ code = "a /1;x=1#/"
+ refute(ruby_lex.assignment_expression?(code, local_variables: []), "#{code}: should not be an assignment expression")
+ assert(ruby_lex.assignment_expression?(code, local_variables: [:a]), "#{code}: should be an assignment expression")
+ refute(ruby_lex.assignment_expression?("", local_variables: [:a]), "empty code should not be an assignment expression")
+ end
+
+ def test_initialising_the_old_top_level_ruby_lex
+ assert_in_out_err(["--disable-gems", "-W:deprecated"], <<~RUBY, [], /warning: constant ::RubyLex is deprecated/)
+ require "irb"
+ ::RubyLex.new(nil)
+ RUBY
+ end
+
+ private
+
+ def assert_indent_level(lines, expected, local_variables: [])
+ indent_level, _continue, _code_block_open = check_state(lines, local_variables: local_variables)
+ error_message = "Calculated the wrong number of indent level for:\n #{lines.join("\n")}"
+ assert_equal(expected, indent_level, error_message)
+ end
+
+ def assert_should_continue(lines, expected, local_variables: [])
+ _indent_level, continue, _code_block_open = check_state(lines, local_variables: local_variables)
+ error_message = "Wrong result of should_continue for:\n #{lines.join("\n")}"
+ assert_equal(expected, continue, error_message)
+ end
+
+ def assert_code_block_open(lines, expected, local_variables: [])
+ if RUBY_ENGINE == 'truffleruby'
+ omit "Remove me after https://github.com/ruby/prism/issues/2129 is addressed and adopted in TruffleRuby"
+ end
+
+ _indent_level, _continue, code_block_open = check_state(lines, local_variables: local_variables)
+ error_message = "Wrong result of code_block_open for:\n #{lines.join("\n")}"
+ assert_equal(expected, code_block_open, error_message)
+ end
+
+ def check_state(lines, local_variables: [])
+ code = lines.map { |l| "#{l}\n" }.join # code should end with "\n"
+ ruby_lex = IRB::RubyLex.new
+ tokens, opens, terminated = ruby_lex.check_code_state(code, local_variables: local_variables)
+ indent_level = ruby_lex.calc_indent_level(opens)
+ continue = ruby_lex.should_continue?(tokens)
+ [indent_level, continue, !terminated]
+ end
end
end
diff --git a/test/irb/test_tracer.rb b/test/irb/test_tracer.rb
new file mode 100644
index 0000000000..540f8be131
--- /dev/null
+++ b/test/irb/test_tracer.rb
@@ -0,0 +1,90 @@
+# frozen_string_literal: false
+require 'tempfile'
+require 'irb'
+
+require_relative "helper"
+
+module TestIRB
+ class ContextWithTracerIntegrationTest < IntegrationTestCase
+ def setup
+ super
+
+ omit "Tracer gem is not available when running on TruffleRuby" if RUBY_ENGINE == "truffleruby"
+
+ @envs.merge!("NO_COLOR" => "true")
+ end
+
+ def example_ruby_file
+ <<~'RUBY'
+ class Foo
+ def self.foo
+ 100
+ end
+ end
+
+ def bar(obj)
+ obj.foo
+ end
+
+ binding.irb
+ RUBY
+ end
+
+ def test_use_tracer_enabled_when_gem_is_unavailable
+ write_rc <<~RUBY
+ # Simulate the absence of the tracer gem
+ ::Kernel.send(:alias_method, :irb_original_require, :require)
+
+ ::Kernel.define_method(:require) do |name|
+ raise LoadError, "cannot load such file -- tracer (test)" if name.match?("tracer")
+ ::Kernel.send(:irb_original_require, name)
+ end
+
+ IRB.conf[:USE_TRACER] = true
+ RUBY
+
+ write_ruby example_ruby_file
+
+ output = run_ruby_file do
+ type "bar(Foo)"
+ type "exit"
+ end
+
+ assert_include(output, "Tracer extension of IRB is enabled but tracer gem wasn't found.")
+ end
+
+ def test_use_tracer_enabled_when_gem_is_available
+ write_rc <<~RUBY
+ IRB.conf[:USE_TRACER] = true
+ RUBY
+
+ write_ruby example_ruby_file
+
+ output = run_ruby_file do
+ type "bar(Foo)"
+ type "exit"
+ end
+
+ assert_include(output, "Object#bar at")
+ assert_include(output, "Foo.foo at")
+ assert_include(output, "Foo.foo #=> 100")
+ assert_include(output, "Object#bar #=> 100")
+
+ # Test that the tracer output does not include IRB's own files
+ assert_not_include(output, "irb/workspace.rb")
+ end
+
+ def test_use_tracer_is_disabled_by_default
+ write_ruby example_ruby_file
+
+ output = run_ruby_file do
+ type "bar(Foo)"
+ type "exit"
+ end
+
+ assert_not_include(output, "#depth:")
+ assert_not_include(output, "Foo.foo")
+ end
+
+ end
+end
diff --git a/test/irb/test_type_completor.rb b/test/irb/test_type_completor.rb
new file mode 100644
index 0000000000..412d7c696d
--- /dev/null
+++ b/test/irb/test_type_completor.rb
@@ -0,0 +1,93 @@
+# frozen_string_literal: true
+
+# Run test only when Ruby >= 3.0 and repl_type_completor is available
+return unless RUBY_VERSION >= '3.0.0'
+return if RUBY_ENGINE == 'truffleruby' # needs endless method definition
+begin
+ require 'repl_type_completor'
+rescue LoadError
+ return
+end
+
+require 'irb'
+require 'tempfile'
+require_relative './helper'
+
+module TestIRB
+ class TypeCompletorTest < TestCase
+ DummyContext = Struct.new(:irb_path)
+
+ def setup
+ ReplTypeCompletor.load_rbs unless ReplTypeCompletor.rbs_loaded?
+ context = DummyContext.new('(irb)')
+ @completor = IRB::TypeCompletor.new(context)
+ end
+
+ def empty_binding
+ binding
+ end
+
+ def assert_completion(preposing, target, binding: empty_binding, include: nil, exclude: nil)
+ raise ArgumentError if include.nil? && exclude.nil?
+ candidates = @completor.completion_candidates(preposing, target, '', bind: binding)
+ assert ([*include] - candidates).empty?, "Expected #{candidates} to include #{include}" if include
+ assert (candidates & [*exclude]).empty?, "Expected #{candidates} not to include #{exclude}" if exclude
+ end
+
+ def assert_doc_namespace(preposing, target, namespace, binding: empty_binding)
+ @completor.completion_candidates(preposing, target, '', bind: binding)
+ assert_equal namespace, @completor.doc_namespace(preposing, target, '', bind: binding)
+ end
+
+ def test_type_completion
+ bind = eval('num = 1; binding')
+ assert_completion('num.times.map(&:', 'ab', binding: bind, include: 'abs')
+ assert_doc_namespace('num.chr.', 'upcase', 'String#upcase', binding: bind)
+ end
+
+ def test_inspect
+ assert_match(/\AReplTypeCompletor.*\z/, @completor.inspect)
+ end
+
+ def test_empty_completion
+ candidates = @completor.completion_candidates('(', ')', '', bind: binding)
+ assert_equal [], candidates
+ assert_doc_namespace('(', ')', nil)
+ end
+
+ def test_command_completion
+ binding.eval("some_var = 1")
+ # completion for help command's argument should only include command names
+ assert_include(@completor.completion_candidates('help ', 's', '', bind: binding), 'show_source')
+ assert_not_include(@completor.completion_candidates('help ', 's', '', bind: binding), 'some_var')
+
+ assert_include(@completor.completion_candidates('', 'show_s', '', bind: binding), 'show_source')
+ assert_not_include(@completor.completion_candidates(';', 'show_s', '', bind: binding), 'show_source')
+ end
+ end
+
+ class TypeCompletorIntegrationTest < IntegrationTestCase
+ def test_type_completor
+ write_rc <<~RUBY
+ IRB.conf[:COMPLETOR] = :type
+ RUBY
+
+ write_ruby <<~'RUBY'
+ binding.irb
+ RUBY
+
+ output = run_ruby_file do
+ type "irb_info"
+ type "sleep 0.01 until ReplTypeCompletor.rbs_loaded?"
+ type "completor = IRB.CurrentContext.io.instance_variable_get(:@completor);"
+ type "n = 10"
+ type "puts completor.completion_candidates 'a = n.abs;', 'a.b', '', bind: binding"
+ type "puts completor.doc_namespace 'a = n.chr;', 'a.encoding', '', bind: binding"
+ type "exit!"
+ end
+ assert_match(/Completion: Autocomplete, ReplTypeCompletor/, output)
+ assert_match(/a\.bit_length/, output)
+ assert_match(/String#encoding/, output)
+ end
+ end
+end
diff --git a/test/irb/test_workspace.rb b/test/irb/test_workspace.rb
index 1a1dc1f49b..ad515f91df 100644
--- a/test/irb/test_workspace.rb
+++ b/test/irb/test_workspace.rb
@@ -1,13 +1,13 @@
# frozen_string_literal: false
-require 'test/unit'
require 'tempfile'
-require 'rubygems'
require 'irb'
require 'irb/workspace'
require 'irb/color'
+require_relative "helper"
+
module TestIRB
- class TestWorkSpace < Test::Unit::TestCase
+ class WorkSpaceTest < TestCase
def test_code_around_binding
IRB.conf[:USE_COLORIZE] = false
Tempfile.create('irb') do |f|
@@ -80,9 +80,7 @@ module TestIRB
assert_equal(nil, workspace.code_around_binding)
end
-
def test_toplevel_binding_local_variables
- pend if RUBY_ENGINE == 'truffleruby'
bug17623 = '[ruby-core:102468]'
bundle_exec = ENV.key?('BUNDLE_GEMFILE') ? ['-rbundler/setup'] : []
top_srcdir = "#{__dir__}/../.."
@@ -91,7 +89,7 @@ module TestIRB
irb_path = "#{top_srcdir}/#{dir}/irb"
File.exist?(irb_path)
end or omit 'irb command not found'
- assert_in_out_err(bundle_exec + ['-W0', "-C#{top_srcdir}", '-e', <<~RUBY , '--', '-f', '--'], 'binding.local_variables', /\[:_\]/, [], bug17623)
+ assert_in_out_err(bundle_exec + ['-W0', "-C#{top_srcdir}", '-e', <<~RUBY, '--', '-f', '--'], 'binding.local_variables', /\[:_\]/, [], bug17623)
version = 'xyz' # typical rubygems loading file
load('#{irb_path}')
RUBY
diff --git a/test/irb/yamatanooroti/test_rendering.rb b/test/irb/yamatanooroti/test_rendering.rb
index ac6df30c62..834c501d5c 100644
--- a/test/irb/yamatanooroti/test_rendering.rb
+++ b/test/irb/yamatanooroti/test_rendering.rb
@@ -2,181 +2,538 @@ require 'irb'
begin
require 'yamatanooroti'
+rescue LoadError, NameError
+ # On Ruby repository, this test suite doesn't run because Ruby repo doesn't
+ # have the yamatanooroti gem.
+ return
+end
- class IRB::TestRendering < Yamatanooroti::TestCase
- def setup
- @pwd = Dir.pwd
- suffix = '%010d' % Random.rand(0..65535)
- @tmpdir = File.join(File.expand_path(Dir.tmpdir), "test_irb_#{$$}_#{suffix}")
- begin
- Dir.mkdir(@tmpdir)
- rescue Errno::EEXIST
- FileUtils.rm_rf(@tmpdir)
- Dir.mkdir(@tmpdir)
- end
- @irbrc_backup = ENV['IRBRC']
- @irbrc_file = ENV['IRBRC'] = File.join(@tmpdir, 'temporaty_irbrc')
- File.unlink(@irbrc_file) if File.exist?(@irbrc_file)
- end
-
- def teardown
+class IRB::RenderingTest < Yamatanooroti::TestCase
+ def setup
+ @original_term = ENV['TERM']
+ @home_backup = ENV['HOME']
+ @xdg_config_home_backup = ENV['XDG_CONFIG_HOME']
+ ENV['TERM'] = "xterm-256color"
+ @pwd = Dir.pwd
+ suffix = '%010d' % Random.rand(0..65535)
+ @tmpdir = File.join(File.expand_path(Dir.tmpdir), "test_irb_#{$$}_#{suffix}")
+ begin
+ Dir.mkdir(@tmpdir)
+ rescue Errno::EEXIST
FileUtils.rm_rf(@tmpdir)
- ENV['IRBRC'] = @irbrc_backup
- ENV.delete('RELINE_TEST_PROMPT') if ENV['RELINE_TEST_PROMPT']
+ Dir.mkdir(@tmpdir)
end
+ @irbrc_backup = ENV['IRBRC']
+ @irbrc_file = ENV['IRBRC'] = File.join(@tmpdir, 'temporaty_irbrc')
+ File.unlink(@irbrc_file) if File.exist?(@irbrc_file)
+ ENV['HOME'] = File.join(@tmpdir, 'home')
+ ENV['XDG_CONFIG_HOME'] = File.join(@tmpdir, 'xdg_config_home')
+ end
- def test_launch
- write_irbrc <<~'LINES'
- puts 'start IRB'
- LINES
- start_terminal(25, 80, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB')
- write(<<~EOC)
- 'Hello, World!'
- EOC
- close
- assert_screen(<<~EOC)
- start IRB
- irb(main):001:0> 'Hello, World!'
- => "Hello, World!"
- irb(main):002:0>
- EOC
- end
+ def teardown
+ FileUtils.rm_rf(@tmpdir)
+ ENV['IRBRC'] = @irbrc_backup
+ ENV['TERM'] = @original_term
+ ENV['HOME'] = @home_backup
+ ENV['XDG_CONFIG_HOME'] = @xdg_config_home_backup
+ end
- def test_multiline_paste
- write_irbrc <<~'LINES'
- puts 'start IRB'
- LINES
- start_terminal(25, 80, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB')
- write(<<~EOC)
- class A
- def inspect; '#<A>'; end
- def a; self; end
- def b; true; end
- end
-
- a = A.new
-
- a
- .a
- .b
- EOC
- close
- assert_screen(<<~EOC)
- start IRB
- irb(main):001:1* class A
- irb(main):002:1* def inspect; '#<A>'; end
- irb(main):003:1* def a; self; end
- irb(main):004:1* def b; true; end
- irb(main):005:0> end
- => :b
- irb(main):006:0>
- irb(main):007:0> a = A.new
- => #<A>
- irb(main):008:0>
- irb(main):009:0> a
- irb(main):010:0> .a
- irb(main):011:0> .b
- => true
- irb(main):012:0>
- EOC
- end
+ def test_launch
+ write_irbrc <<~'LINES'
+ puts 'start IRB'
+ LINES
+ start_terminal(25, 80, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB')
+ write(<<~EOC)
+ 'Hello, World!'
+ EOC
+ close
+ assert_screen(<<~EOC)
+ start IRB
+ irb(main):001> 'Hello, World!'
+ => "Hello, World!"
+ irb(main):002>
+ EOC
+ end
- def test_evaluate_each_toplevel_statement_by_multiline_paste
- write_irbrc <<~'LINES'
- puts 'start IRB'
- LINES
- start_terminal(40, 80, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB')
- write(<<~EOC)
- class A
- def inspect; '#<A>'; end
- def b; self; end
- def c; true; end
- end
-
- a = A.new
-
- a
- .b
- # aaa
- .c
-
- (a)
- &.b()
-
-
- class A def b; self; end; def c; true; end; end;
- a = A.new
- a
- .b
- # aaa
- .c
- (a)
- &.b()
- EOC
- close
+ def test_configuration_file_is_skipped_with_dash_f
+ write_irbrc <<~'LINES'
+ puts '.irbrc file should be ignored when -f is used'
+ LINES
+ start_terminal(25, 80, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb -f}, startup_message: '')
+ write(<<~EOC)
+ 'Hello, World!'
+ EOC
+ close
+ assert_screen(<<~EOC)
+ irb(main):001> 'Hello, World!'
+ => "Hello, World!"
+ irb(main):002>
+ EOC
+ end
+
+ def test_configuration_file_is_skipped_with_dash_f_for_nested_sessions
+ write_irbrc <<~'LINES'
+ puts '.irbrc file should be ignored when -f is used'
+ LINES
+ start_terminal(25, 80, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb -f}, startup_message: '')
+ write(<<~EOC)
+ 'Hello, World!'
+ binding.irb
+ exit!
+ EOC
+ close
+ assert_screen(<<~EOC)
+ irb(main):001> 'Hello, World!'
+ => "Hello, World!"
+ irb(main):002> binding.irb
+ irb(main):003> exit!
+ irb(main):001>
+ EOC
+ end
+
+ def test_nomultiline
+ write_irbrc <<~'LINES'
+ puts 'start IRB'
+ LINES
+ start_terminal(25, 80, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb --nomultiline}, startup_message: 'start IRB')
+ write(<<~EOC)
+ if true
+ if false
+ a = "hello
+ world"
+ puts a
+ end
+ end
+ EOC
+ close
+ assert_screen(<<~EOC)
+ start IRB
+ irb(main):001> if true
+ irb(main):002* if false
+ irb(main):003* a = "hello
+ irb(main):004" world"
+ irb(main):005* puts a
+ irb(main):006* end
+ irb(main):007* end
+ => nil
+ irb(main):008>
+ EOC
+ end
+
+ def test_multiline_paste
+ write_irbrc <<~'LINES'
+ puts 'start IRB'
+ LINES
+ start_terminal(25, 80, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB')
+ write(<<~EOC)
+ class A
+ def inspect; '#<A>'; end
+ def a; self; end
+ def b; true; end
+ end
+
+ a = A.new
+
+ a
+ .a
+ .b
+ .itself
+ EOC
+ close
+ assert_screen(<<~EOC)
+ start IRB
+ irb(main):001* class A
+ irb(main):002* def inspect; '#<A>'; end
+ irb(main):003* def a; self; end
+ irb(main):004* def b; true; end
+ irb(main):005> end
+ => :b
+ irb(main):006>
+ irb(main):007> a = A.new
+ => #<A>
+ irb(main):008>
+ irb(main):009> a
+ irb(main):010> .a
+ irb(main):011> .b
+ irb(main):012> .itself
+ => true
+ irb(main):013>
+ EOC
+ end
+
+ def test_evaluate_each_toplevel_statement_by_multiline_paste
+ write_irbrc <<~'LINES'
+ puts 'start IRB'
+ LINES
+ start_terminal(40, 80, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB')
+ write(<<~EOC)
+ class A
+ def inspect; '#<A>'; end
+ def b; self; end
+ def c; true; end
+ end
+
+ a = A.new
+
+ a
+ .b
+ # aaa
+ .c
+
+ (a)
+ &.b()
+
+ class A def b; self; end; def c; true; end; end;
+ a = A.new
+ a
+ .b
+ # aaa
+ .c
+ (a)
+ &.b()
+ .itself
+ EOC
+ close
+ assert_screen(<<~EOC)
+ start IRB
+ irb(main):001* class A
+ irb(main):002* def inspect; '#<A>'; end
+ irb(main):003* def b; self; end
+ irb(main):004* def c; true; end
+ irb(main):005> end
+ => :c
+ irb(main):006>
+ irb(main):007> a = A.new
+ => #<A>
+ irb(main):008>
+ irb(main):009> a
+ irb(main):010> .b
+ irb(main):011> # aaa
+ irb(main):012> .c
+ => true
+ irb(main):013>
+ irb(main):014> (a)
+ irb(main):015> &.b()
+ => #<A>
+ irb(main):016>
+ irb(main):017> class A def b; self; end; def c; true; end; end;
+ irb(main):018> a = A.new
+ => #<A>
+ irb(main):019> a
+ irb(main):020> .b
+ irb(main):021> # aaa
+ irb(main):022> .c
+ => true
+ irb(main):023> (a)
+ irb(main):024> &.b()
+ irb(main):025> .itself
+ => #<A>
+ irb(main):026>
+ EOC
+ end
+
+ def test_symbol_with_backtick
+ write_irbrc <<~'LINES'
+ puts 'start IRB'
+ LINES
+ start_terminal(40, 80, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB')
+ write(<<~EOC)
+ :`
+ EOC
+ close
+ assert_screen(<<~EOC)
+ start IRB
+ irb(main):001> :`
+ => :`
+ irb(main):002>
+ EOC
+ end
+
+ def test_autocomplete_with_multiple_doc_namespaces
+ write_irbrc <<~'LINES'
+ puts 'start IRB'
+ LINES
+ start_terminal(3, 50, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB')
+ write("{}.__id_")
+ write("\C-i")
+ sleep 0.2
+ close
+ screen = result.join("\n").sub(/\n*\z/, "\n")
+ assert_match(/start\ IRB\nirb\(main\):001> {}\.__id__\n }\.__id__(?:Press )?/, screen)
+ end
+
+ def test_autocomplete_with_showdoc_in_gaps_on_narrow_screen_right
+ rdoc_dir = File.join(@tmpdir, 'rdoc')
+ system("bundle exec rdoc -r -o #{rdoc_dir}")
+ write_irbrc <<~LINES
+ IRB.conf[:EXTRA_DOC_DIRS] = ['#{rdoc_dir}']
+ IRB.conf[:PROMPT][:MY_PROMPT] = {
+ :PROMPT_I => "%03n> ",
+ :PROMPT_S => "%03n> ",
+ :PROMPT_C => "%03n> "
+ }
+ IRB.conf[:PROMPT_MODE] = :MY_PROMPT
+ puts 'start IRB'
+ LINES
+ start_terminal(4, 19, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB')
+ write("IR")
+ write("\C-i")
+ sleep 0.2
+ close
+
+ # This is because on macOS we display different shortcut for displaying the full doc
+ # 'O' is for 'Option' and 'A' is for 'Alt'
+ if RUBY_PLATFORM =~ /darwin/
assert_screen(<<~EOC)
start IRB
- irb(main):001:1* class A
- irb(main):002:1* def inspect; '#<A>'; end
- irb(main):003:1* def b; self; end
- irb(main):004:1* def c; true; end
- irb(main):005:0> end
- => :c
- irb(main):006:0>
- irb(main):007:0> a = A.new
- => #<A>
- irb(main):008:0>
- irb(main):009:0> a
- irb(main):010:0> .b
- irb(main):011:0> # aaa
- irb(main):012:0> .c
- => true
- irb(main):013:0>
- irb(main):014:0> (a)
- irb(main):015:0> &.b()
- => #<A>
- irb(main):016:0>
- irb(main):017:0>
- irb(main):018:0> class A def b; self; end; def c; true; end; end;
- => :c
- irb(main):019:0> a = A.new
- => #<A>
- irb(main):020:0> a
- irb(main):021:0> .b
- irb(main):022:0> # aaa
- irb(main):023:0> .c
- => true
- irb(main):024:0> (a)
- irb(main):025:0> &.b()
- => #<A>
- irb(main):026:0>
- EOC
- end
-
- def test_symbol_with_backtick
- write_irbrc <<~'LINES'
- puts 'start IRB'
- LINES
- start_terminal(40, 80, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB')
- write(<<~EOC)
- :`
+ 001> IRB
+ IRBPress Opti
+ IRB
EOC
- close
+ else
assert_screen(<<~EOC)
start IRB
- irb(main):001:0> :`
- => :`
- irb(main):002:0>
+ 001> IRB
+ IRBPress Alt+
+ IRB
EOC
end
+ end
- private def write_irbrc(content)
- File.open(@irbrc_file, 'w') do |f|
- f.write content
- end
+ def test_autocomplete_with_showdoc_in_gaps_on_narrow_screen_left
+ rdoc_dir = File.join(@tmpdir, 'rdoc')
+ system("bundle exec rdoc -r -o #{rdoc_dir}")
+ write_irbrc <<~LINES
+ IRB.conf[:EXTRA_DOC_DIRS] = ['#{rdoc_dir}']
+ IRB.conf[:PROMPT][:MY_PROMPT] = {
+ :PROMPT_I => "%03n> ",
+ :PROMPT_S => "%03n> ",
+ :PROMPT_C => "%03n> "
+ }
+ IRB.conf[:PROMPT_MODE] = :MY_PROMPT
+ puts 'start IRB'
+ LINES
+ start_terminal(4, 12, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB')
+ write("IR")
+ write("\C-i")
+ sleep 0.2
+ close
+ assert_screen(<<~EOC)
+ start IRB
+ 001> IRB
+ PressIRB
+ IRB
+ EOC
+ end
+
+ def test_assignment_expression_truncate
+ write_irbrc <<~'LINES'
+ puts 'start IRB'
+ LINES
+ start_terminal(40, 80, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB')
+ # Assignment expression code that turns into non-assignment expression after evaluation
+ code = "a /'/i if false; a=1; x=1000.times.to_a#'.size"
+ write(code + "\n")
+ close
+ assert_screen(<<~EOC)
+ start IRB
+ irb(main):001> #{code}
+ =>
+ [0,
+ ...
+ irb(main):002>
+ EOC
+ end
+
+ def test_ctrl_c_is_handled
+ write_irbrc <<~'LINES'
+ puts 'start IRB'
+ LINES
+ start_terminal(40, 80, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB')
+ # Assignment expression code that turns into non-assignment expression after evaluation
+ write("\C-c")
+ close
+ assert_screen(<<~EOC)
+ start IRB
+ irb(main):001>
+ ^C
+ irb(main):001>
+ EOC
+ end
+
+ def test_show_cmds_with_pager_can_quit_with_ctrl_c
+ write_irbrc <<~'LINES'
+ puts 'start IRB'
+ LINES
+ start_terminal(40, 80, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB')
+ write("help\n")
+ write("G") # move to the end of the screen
+ write("\C-c") # quit pager
+ write("'foo' + 'bar'\n") # eval something to make sure IRB resumes
+ close
+
+ screen = result.join("\n").sub(/\n*\z/, "\n")
+ # IRB::Abort should be rescued
+ assert_not_match(/IRB::Abort/, screen)
+ # IRB should resume
+ assert_match(/foobar/, screen)
+ end
+
+ def test_pager_page_content_pages_output_when_it_does_not_fit_in_the_screen_because_of_total_length
+ write_irbrc <<~'LINES'
+ puts 'start IRB'
+ require "irb/pager"
+ LINES
+ start_terminal(10, 80, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB')
+ write("IRB::Pager.page_content('a' * (80 * 8))\n")
+ write("'foo' + 'bar'\n") # eval something to make sure IRB resumes
+ close
+
+ screen = result.join("\n").sub(/\n*\z/, "\n")
+ assert_match(/a{80}/, screen)
+ # because pager is invoked, foobar will not be evaluated
+ assert_not_match(/foobar/, screen)
+ end
+
+ def test_pager_page_content_pages_output_when_it_does_not_fit_in_the_screen_because_of_screen_height
+ write_irbrc <<~'LINES'
+ puts 'start IRB'
+ require "irb/pager"
+ LINES
+ start_terminal(10, 80, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB')
+ write("IRB::Pager.page_content('a\n' * 8)\n")
+ write("'foo' + 'bar'\n") # eval something to make sure IRB resumes
+ close
+
+ screen = result.join("\n").sub(/\n*\z/, "\n")
+ assert_match(/(a\n){8}/, screen)
+ # because pager is invoked, foobar will not be evaluated
+ assert_not_match(/foobar/, screen)
+ end
+
+ def test_pager_page_content_doesnt_page_output_when_it_fits_in_the_screen
+ write_irbrc <<~'LINES'
+ puts 'start IRB'
+ require "irb/pager"
+ LINES
+ start_terminal(10, 80, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB')
+ write("IRB::Pager.page_content('a' * (80 * 7))\n")
+ write("'foo' + 'bar'\n") # eval something to make sure IRB resumes
+ close
+
+ screen = result.join("\n").sub(/\n*\z/, "\n")
+ assert_match(/a{80}/, screen)
+ # because pager is not invoked, foobar will be evaluated
+ assert_match(/foobar/, screen)
+ end
+
+ def test_long_evaluation_output_is_paged
+ write_irbrc <<~'LINES'
+ puts 'start IRB'
+ require "irb/pager"
+ LINES
+ start_terminal(10, 80, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB')
+ write("'a' * 80 * 11\n")
+ write("'foo' + 'bar'\n") # eval something to make sure IRB resumes
+ close
+
+ screen = result.join("\n").sub(/\n*\z/, "\n")
+ assert_match(/(a{80}\n){8}/, screen)
+ # because pager is invoked, foobar will not be evaluated
+ assert_not_match(/foobar/, screen)
+ end
+
+ def test_long_evaluation_output_is_preserved_after_paging
+ write_irbrc <<~'LINES'
+ puts 'start IRB'
+ require "irb/pager"
+ LINES
+ start_terminal(10, 80, %W{ruby -I#{@pwd}/lib #{@pwd}/exe/irb}, startup_message: 'start IRB')
+ write("'a' * 80 * 11\n")
+ write("q") # quit pager
+ write("'foo' + 'bar'\n") # eval something to make sure IRB resumes
+ close
+
+ screen = result.join("\n").sub(/\n*\z/, "\n")
+ # confirm pager has exited
+ assert_match(/foobar/, screen)
+ # confirm output is preserved
+ assert_match(/(a{80}\n){6}/, screen)
+ end
+
+ def test_debug_integration_hints_debugger_commands
+ write_irbrc <<~'LINES'
+ IRB.conf[:USE_COLORIZE] = false
+ LINES
+ script = Tempfile.create(["debug", ".rb"])
+ script.write <<~RUBY
+ puts 'start IRB'
+ binding.irb
+ RUBY
+ script.close
+ start_terminal(40, 80, %W{ruby -I#{@pwd}/lib #{script.to_path}}, startup_message: 'start IRB')
+ write("debug\n")
+ write("pp 1\n")
+ write("pp 1")
+ close
+
+ screen = result.join("\n").sub(/\n*\z/, "\n")
+ # submitted input shouldn't contain hint
+ assert_include(screen, "irb:rdbg(main):002> pp 1\n")
+ # unsubmitted input should contain hint
+ assert_include(screen, "irb:rdbg(main):003> pp 1 # debug command\n")
+ ensure
+ File.unlink(script) if script
+ end
+
+ def test_debug_integration_doesnt_hint_non_debugger_commands
+ write_irbrc <<~'LINES'
+ IRB.conf[:USE_COLORIZE] = false
+ LINES
+ script = Tempfile.create(["debug", ".rb"])
+ script.write <<~RUBY
+ puts 'start IRB'
+ binding.irb
+ RUBY
+ script.close
+ start_terminal(40, 80, %W{ruby -I#{@pwd}/lib #{script.to_path}}, startup_message: 'start IRB')
+ write("debug\n")
+ write("foo")
+ close
+
+ screen = result.join("\n").sub(/\n*\z/, "\n")
+ assert_include(screen, "irb:rdbg(main):002> foo\n")
+ ensure
+ File.unlink(script) if script
+ end
+
+ def test_debug_integration_doesnt_hint_debugger_commands_in_nomultiline_mode
+ write_irbrc <<~'LINES'
+ IRB.conf[:USE_SINGLELINE] = true
+ LINES
+ script = Tempfile.create(["debug", ".rb"])
+ script.write <<~RUBY
+ puts 'start IRB'
+ binding.irb
+ RUBY
+ script.close
+ start_terminal(40, 80, %W{ruby -I#{@pwd}/lib #{script.to_path}}, startup_message: 'start IRB')
+ write("debug\n")
+ write("pp 1")
+ close
+
+ screen = result.join("\n").sub(/\n*\z/, "\n")
+ # submitted input shouldn't contain hint
+ assert_include(screen, "irb:rdbg(main):002> pp 1\n")
+ ensure
+ File.unlink(script) if script
+ end
+
+ private
+
+ def write_irbrc(content)
+ File.open(@irbrc_file, 'w') do |f|
+ f.write content
end
end
-rescue LoadError, NameError
- # On Ruby repository, this test suit doesn't run because Ruby repo doesn't
- # have the yamatanooroti gem.
end
diff --git a/test/json/json_addition_test.rb b/test/json/json_addition_test.rb
index e95ace8375..3a7a58176a 100644
--- a/test/json/json_addition_test.rb
+++ b/test/json/json_addition_test.rb
@@ -1,5 +1,5 @@
#frozen_string_literal: false
-require 'test_helper'
+require_relative 'test_helper'
require 'json/add/core'
require 'json/add/complex'
require 'json/add/rational'
@@ -165,7 +165,7 @@ class JSONAdditionTest < Test::Unit::TestCase
def test_utc_datetime
now = Time.now
- d = DateTime.parse(now.to_s, :create_additions => true) # usual case
+ d = DateTime.parse(now.to_s) # usual case
assert_equal d, parse(d.to_json, :create_additions => true)
d = DateTime.parse(now.utc.to_s) # of = 0
assert_equal d, parse(d.to_json, :create_additions => true)
@@ -183,14 +183,14 @@ class JSONAdditionTest < Test::Unit::TestCase
def test_bigdecimal
assert_equal BigDecimal('3.141', 23), JSON(JSON(BigDecimal('3.141', 23)), :create_additions => true)
assert_equal BigDecimal('3.141', 666), JSON(JSON(BigDecimal('3.141', 666)), :create_additions => true)
- end
+ end if defined?(::BigDecimal)
def test_ostruct
o = OpenStruct.new
# XXX this won't work; o.foo = { :bar => true }
o.foo = { 'bar' => true }
assert_equal o, parse(JSON(o), :create_additions => true)
- end
+ end if defined?(::OpenStruct)
def test_set
s = Set.new([:a, :b, :c, :a])
diff --git a/test/json/json_common_interface_test.rb b/test/json/json_common_interface_test.rb
index 9148b78c8b..c16f6ceaaf 100644
--- a/test/json/json_common_interface_test.rb
+++ b/test/json/json_common_interface_test.rb
@@ -1,5 +1,5 @@
#frozen_string_literal: false
-require 'test_helper'
+require_relative 'test_helper'
require 'stringio'
require 'tempfile'
@@ -99,18 +99,26 @@ class JSONCommonInterfaceTest < Test::Unit::TestCase
def test_dump
too_deep = '[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]'
- assert_equal too_deep, dump(eval(too_deep))
- assert_kind_of String, Marshal.dump(eval(too_deep))
- assert_raise(ArgumentError) { dump(eval(too_deep), 100) }
- assert_raise(ArgumentError) { Marshal.dump(eval(too_deep), 100) }
- assert_equal too_deep, dump(eval(too_deep), 101)
- assert_kind_of String, Marshal.dump(eval(too_deep), 101)
- output = StringIO.new
- dump(eval(too_deep), output)
- assert_equal too_deep, output.string
- output = StringIO.new
- dump(eval(too_deep), output, 101)
- assert_equal too_deep, output.string
+ obj = eval(too_deep)
+ assert_equal too_deep, dump(obj)
+ assert_kind_of String, Marshal.dump(obj)
+ assert_raise(ArgumentError) { dump(obj, 100) }
+ assert_raise(ArgumentError) { Marshal.dump(obj, 100) }
+ assert_equal too_deep, dump(obj, 101)
+ assert_kind_of String, Marshal.dump(obj, 101)
+
+ assert_equal too_deep, JSON.dump(obj, StringIO.new, 101, strict: false).string
+ assert_equal too_deep, dump(obj, StringIO.new, 101, strict: false).string
+ assert_raise(JSON::GeneratorError) { JSON.dump(Object.new, StringIO.new, 101, strict: true).string }
+ assert_raise(JSON::GeneratorError) { dump(Object.new, StringIO.new, 101, strict: true).string }
+
+ assert_equal too_deep, dump(obj, nil, nil, strict: false)
+ assert_equal too_deep, dump(obj, nil, 101, strict: false)
+ assert_equal too_deep, dump(obj, StringIO.new, nil, strict: false).string
+ assert_equal too_deep, dump(obj, nil, strict: false)
+ assert_equal too_deep, dump(obj, 101, strict: false)
+ assert_equal too_deep, dump(obj, StringIO.new, strict: false).string
+ assert_equal too_deep, dump(obj, strict: false)
end
def test_dump_should_modify_defaults
diff --git a/test/json/json_encoding_test.rb b/test/json/json_encoding_test.rb
index cc7b71553a..be87f3c3d6 100644
--- a/test/json/json_encoding_test.rb
+++ b/test/json/json_encoding_test.rb
@@ -1,6 +1,5 @@
-# encoding: utf-8
-#frozen_string_literal: false
-require 'test_helper'
+# frozen_string_literal: false
+require_relative 'test_helper'
class JSONEncodingTest < Test::Unit::TestCase
include JSON
@@ -86,9 +85,7 @@ class JSONEncodingTest < Test::Unit::TestCase
def test_chars
(0..0x7f).each do |i|
json = '["\u%04x"]' % i
- if RUBY_VERSION >= "1.9."
- i = i.chr
- end
+ i = i.chr
assert_equal i, parse(json).first[0]
if i == ?\b
generated = generate(["" << i])
diff --git a/test/json/json_ext_parser_test.rb b/test/json/json_ext_parser_test.rb
index c5a030ea8a..f49f88b596 100644
--- a/test/json/json_ext_parser_test.rb
+++ b/test/json/json_ext_parser_test.rb
@@ -1,8 +1,10 @@
#frozen_string_literal: false
-require 'test_helper'
+require_relative 'test_helper'
class JSONExtParserTest < Test::Unit::TestCase
if defined?(JSON::Ext::Parser)
+ include JSON
+
def test_allocate
parser = JSON::Ext::Parser.new("{}")
assert_raise(TypeError, '[ruby-core:35079]') do
@@ -11,5 +13,22 @@ class JSONExtParserTest < Test::Unit::TestCase
parser = JSON::Ext::Parser.allocate
assert_raise(TypeError, '[ruby-core:35079]') { parser.source }
end
+
+ def test_error_messages
+ ex = assert_raise(ParserError) { parse('Infinity') }
+ assert_equal "unexpected token at 'Infinity'", ex.message
+
+ unless RUBY_PLATFORM =~ /java/
+ ex = assert_raise(ParserError) { parse('-Infinity') }
+ assert_equal "unexpected token at '-Infinity'", ex.message
+ end
+
+ ex = assert_raise(ParserError) { parse('NaN') }
+ assert_equal "unexpected token at 'NaN'", ex.message
+ end
+
+ def parse(json)
+ JSON::Ext::Parser.new(json).parse
+ end
end
end
diff --git a/test/json/json_fixtures_test.rb b/test/json/json_fixtures_test.rb
index 845abb4867..acc8749965 100644
--- a/test/json/json_fixtures_test.rb
+++ b/test/json/json_fixtures_test.rb
@@ -1,5 +1,5 @@
#frozen_string_literal: false
-require 'test_helper'
+require_relative 'test_helper'
class JSONFixturesTest < Test::Unit::TestCase
def setup
diff --git a/test/json/json_generator_test.rb b/test/json/json_generator_test.rb
index f31b6b290e..19b4c7434f 100644..100755
--- a/test/json/json_generator_test.rb
+++ b/test/json/json_generator_test.rb
@@ -1,8 +1,7 @@
#!/usr/bin/env ruby
-# encoding: utf-8
# frozen_string_literal: false
-require 'test_helper'
+require_relative 'test_helper'
class JSONGeneratorTest < Test::Unit::TestCase
include JSON
@@ -62,6 +61,14 @@ EOT
assert_equal '666', generate(666)
end
+ def test_dump_unenclosed_hash
+ assert_equal '{"a":1,"b":2}', dump(a: 1, b: 2)
+ end
+
+ def test_dump_strict
+ assert_equal '{}', dump({}, strict: true)
+ end
+
def test_generate_pretty
json = pretty_generate({})
assert_equal(<<'EOT'.chomp, json)
@@ -149,7 +156,8 @@ EOT
:ascii_only => false,
:buffer_initial_length => 1024,
:depth => 0,
- :escape_slash => false,
+ :script_safe => false,
+ :strict => false,
:indent => " ",
:max_nesting => 100,
:object_nl => "\n",
@@ -166,7 +174,8 @@ EOT
:ascii_only => false,
:buffer_initial_length => 1024,
:depth => 0,
- :escape_slash => false,
+ :script_safe => false,
+ :strict => false,
:indent => "",
:max_nesting => 100,
:object_nl => "",
@@ -183,7 +192,8 @@ EOT
:ascii_only => false,
:buffer_initial_length => 1024,
:depth => 0,
- :escape_slash => false,
+ :script_safe => false,
+ :strict => false,
:indent => "",
:max_nesting => 0,
:object_nl => "",
@@ -233,7 +243,7 @@ EOT
def test_gc
if respond_to?(:assert_in_out_err) && !(RUBY_PLATFORM =~ /java/)
- assert_in_out_err(%w[-rjson --disable-gems], <<-EOS, [], [])
+ assert_in_out_err(%w[-rjson -Ilib -Iext], <<-EOS, [], [])
bignum_too_long_to_embed_as_string = 1234567890123456789012345
expect = bignum_too_long_to_embed_as_string.to_s
GC.stress = true
@@ -336,7 +346,13 @@ EOT
def test_json_generate
assert_raise JSON::GeneratorError do
- assert_equal true, generate(["\xea"])
+ generate(["\xea"])
+ end
+ end
+
+ def test_json_generate_unsupported_types
+ assert_raise JSON::GeneratorError do
+ generate(Object.new, strict: true)
end
end
@@ -370,6 +386,18 @@ EOT
#
data = [ '/' ]
json = '["\/"]'
+ assert_equal json, generate(data, :script_safe => true)
+ #
+ data = [ "\u2028\u2029" ]
+ json = '["\u2028\u2029"]'
+ assert_equal json, generate(data, :script_safe => true)
+ #
+ data = [ "ABC \u2028 DEF \u2029 GHI" ]
+ json = '["ABC \u2028 DEF \u2029 GHI"]'
+ assert_equal json, generate(data, :script_safe => true)
+ #
+ data = [ "/\u2028\u2029" ]
+ json = '["\/\u2028\u2029"]'
assert_equal json, generate(data, :escape_slash => true)
#
data = ['"']
@@ -391,6 +419,31 @@ EOT
end
end
+ if defined?(JSON::Ext::Generator) and RUBY_PLATFORM != "java"
+ def test_string_ext_included_calls_super
+ included = false
+
+ Module.send(:alias_method, :included_orig, :included)
+ Module.send(:remove_method, :included)
+ Module.send(:define_method, :included) do |base|
+ included_orig(base)
+ included = true
+ end
+
+ Class.new(String) do
+ include JSON::Ext::Generator::GeneratorMethods::String
+ end
+
+ assert included
+ ensure
+ if Module.private_method_defined?(:included_orig)
+ Module.send(:remove_method, :included) if Module.method_defined?(:included)
+ Module.send(:alias_method, :included, :included_orig)
+ Module.send(:remove_method, :included_orig)
+ end
+ end
+ end
+
if defined?(Encoding)
def test_nonutf8_encoding
assert_equal("\"5\u{b0}\"", "5\xb0".force_encoding("iso-8859-1").to_json)
diff --git a/test/json/json_generic_object_test.rb b/test/json/json_generic_object_test.rb
index 82742dcd63..d6d7e30816 100644
--- a/test/json/json_generic_object_test.rb
+++ b/test/json/json_generic_object_test.rb
@@ -1,5 +1,5 @@
#frozen_string_literal: false
-require 'test_helper'
+require_relative 'test_helper'
class JSONGenericObjectTest < Test::Unit::TestCase
include JSON
@@ -79,4 +79,4 @@ class JSONGenericObjectTest < Test::Unit::TestCase
ensure
JSON::GenericObject.json_creatable = false
end
-end
+end if defined?(JSON::GenericObject)
diff --git a/test/json/json_parser_test.rb b/test/json/json_parser_test.rb
index dce693e548..49c7c8565d 100644
--- a/test/json/json_parser_test.rb
+++ b/test/json/json_parser_test.rb
@@ -1,10 +1,16 @@
# encoding: utf-8
# frozen_string_literal: false
-require 'test_helper'
+require_relative 'test_helper'
require 'stringio'
require 'tempfile'
-require 'ostruct'
-require 'bigdecimal'
+begin
+ require 'ostruct'
+rescue LoadError
+end
+begin
+ require 'bigdecimal'
+rescue LoadError
+end
class JSONParserTest < Test::Unit::TestCase
include JSON
@@ -21,6 +27,9 @@ class JSONParserTest < Test::Unit::TestCase
end if defined?(Encoding::UTF_16)
def test_error_message_encoding
+ # https://github.com/flori/json/actions/runs/6478148162/job/17589572890
+ pend if RUBY_ENGINE == 'truffleruby'
+
bug10705 = '[ruby-core:67386] [Bug #10705]'
json = ".\"\xE2\x88\x9A\"".force_encoding(Encoding::UTF_8)
e = assert_raise(JSON::ParserError) {
@@ -84,6 +93,7 @@ class JSONParserTest < Test::Unit::TestCase
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 } '))
+ assert_equal({ "" => 123 }, parse('{"":123}'))
end
def test_parse_numbers
@@ -112,6 +122,10 @@ class JSONParserTest < Test::Unit::TestCase
def test_parse_bigdecimals
assert_equal(BigDecimal, JSON.parse('{"foo": 9.01234567890123456789}', decimal_class: BigDecimal)["foo"].class)
assert_equal(BigDecimal("0.901234567890123456789E1"),JSON.parse('{"foo": 9.01234567890123456789}', decimal_class: BigDecimal)["foo"] )
+ end if defined?(::BigDecimal)
+
+ def test_parse_string_mixed_unicode
+ assert_equal(["éé"], JSON.parse("[\"\\u00e9é\"]"))
end
if Array.method_defined?(:permutation)
@@ -401,21 +415,6 @@ EOT
end
end
- class SubOpenStruct < OpenStruct
- def [](k)
- __send__(k)
- end
-
- def []=(k, v)
- @item_set = true
- __send__("#{k}=", v)
- end
-
- def item_set?
- @item_set
- end
- end
-
def test_parse_object_custom_hash_derived_class
res = parse('{"foo":"bar"}', :object_class => SubHash)
assert_equal({"foo" => "bar"}, res)
@@ -423,24 +422,41 @@ EOT
assert res.item_set?
end
- def test_parse_object_custom_non_hash_derived_class
- res = parse('{"foo":"bar"}', :object_class => SubOpenStruct)
- assert_equal "bar", res.foo
- assert_equal(SubOpenStruct, res.class)
- assert res.item_set?
- end
+ if defined?(::OpenStruct)
+ class SubOpenStruct < OpenStruct
+ def [](k)
+ __send__(k)
+ end
- def test_parse_generic_object
- res = parse(
- '{"foo":"bar", "baz":{}}',
- :object_class => JSON::GenericObject
- )
- assert_equal(JSON::GenericObject, res.class)
- assert_equal "bar", res.foo
- assert_equal "bar", res["foo"]
- assert_equal "bar", res[:foo]
- assert_equal "bar", res.to_hash[:foo]
- assert_equal(JSON::GenericObject, res.baz.class)
+ def []=(k, v)
+ @item_set = true
+ __send__("#{k}=", v)
+ end
+
+ def item_set?
+ @item_set
+ end
+ end
+
+ def test_parse_object_custom_non_hash_derived_class
+ res = parse('{"foo":"bar"}', :object_class => SubOpenStruct)
+ assert_equal "bar", res.foo
+ assert_equal(SubOpenStruct, res.class)
+ assert res.item_set?
+ end
+
+ def test_parse_generic_object
+ res = parse(
+ '{"foo":"bar", "baz":{}}',
+ :object_class => JSON::GenericObject
+ )
+ assert_equal(JSON::GenericObject, res.class)
+ assert_equal "bar", res.foo
+ assert_equal "bar", res["foo"]
+ assert_equal "bar", res[:foo]
+ assert_equal "bar", res.to_hash[:foo]
+ assert_equal(JSON::GenericObject, res.baz.class)
+ end
end
def test_generate_core_subclasses_with_new_to_json
diff --git a/test/json/json_string_matching_test.rb b/test/json/json_string_matching_test.rb
index 5d55dc31b0..b9cf904aaa 100644
--- a/test/json/json_string_matching_test.rb
+++ b/test/json/json_string_matching_test.rb
@@ -1,5 +1,5 @@
#frozen_string_literal: false
-require 'test_helper'
+require_relative 'test_helper'
require 'time'
class JSONStringMatchingTest < Test::Unit::TestCase
diff --git a/test/json/ractor_test.rb b/test/json/ractor_test.rb
index 71105e55ec..ba9bf7a7f6 100644
--- a/test/json/ractor_test.rb
+++ b/test/json/ractor_test.rb
@@ -1,7 +1,11 @@
-# encoding: utf-8
# frozen_string_literal: false
-require 'test_helper'
+require_relative 'test_helper'
+
+begin
+ require_relative './lib/helper'
+rescue LoadError
+end
class JSONInRactorTest < Test::Unit::TestCase
def test_generate
diff --git a/test/lib/!Nothing_to_test.rb b/test/lib/!Nothing_to_test.rb
new file mode 100644
index 0000000000..c1f4c439d3
--- /dev/null
+++ b/test/lib/!Nothing_to_test.rb
@@ -0,0 +1,5 @@
+### Empty test file for chkbuild ###
+
+# If chkbuild fails with `test-all`, each child file/directory is
+# executed individually, but test-unit fails if there are no test
+# files in the specified directory.
diff --git a/test/lib/jit_support.rb b/test/lib/jit_support.rb
index 3bca63a549..cf3baaaeb7 100644
--- a/test/lib/jit_support.rb
+++ b/test/lib/jit_support.rb
@@ -1,93 +1,33 @@
require 'rbconfig'
module JITSupport
- JIT_TIMEOUT = 600 # 10min for each...
- JIT_SUCCESS_PREFIX = 'JIT success \(\d+\.\dms\)'
- JIT_RECOMPILE_PREFIX = 'JIT recompile'
- JIT_COMPACTION_PREFIX = 'JIT compaction \(\d+\.\dms\)'
- UNSUPPORTED_COMPILERS = [
- %r[\A.*/bin/intel64/icc\b],
- %r[\A/opt/developerstudio\d+\.\d+/bin/cc\z],
- ]
- # debian-riscv64: "gcc: internal compiler error: Segmentation fault signal terminated program cc1" https://rubyci.org/logs/rubyci.s3.amazonaws.com/debian-riscv64/ruby-master/log/20200420T083601Z.fail.html.gz
- # freebsd12: cc1 internal failure https://rubyci.org/logs/rubyci.s3.amazonaws.com/freebsd12/ruby-master/log/20200306T103003Z.fail.html.gz
- # rhel8: one or more PCH files were found, but they were invalid https://rubyci.org/logs/rubyci.s3.amazonaws.com/rhel8/ruby-master/log/20200306T153003Z.fail.html.gz
- # centos8: ditto https://rubyci.org/logs/rubyci.s3.amazonaws.com/centos8/ruby-master/log/20200512T003004Z.fail.html.gz
- PENDING_RUBYCI_NICKNAMES = %w[
- debian-riscv64
- freebsd12
- rhel8
- centos8
- ]
-
module_function
- # Run Ruby script with --jit-wait (Synchronous JIT compilation).
- # Returns [stdout, stderr]
- def eval_with_jit(env = nil, script, **opts)
- stdout, stderr = nil, nil
- # retry 3 times while cc1 error happens.
- 3.times do |i|
- stdout, stderr, status = eval_with_jit_without_retry(env, script, **opts)
- assert_equal(true, status.success?, "Failed to run script with JIT:\n#{code_block(script)}\nstdout:\n#{code_block(stdout)}\nstderr:\n#{code_block(stderr)}")
- break unless retried_stderr?(stderr)
- end
- [stdout, stderr]
- end
- def eval_with_jit_without_retry(env = nil, script, verbose: 0, min_calls: 5, save_temps: false, max_cache: 1000, wait: true, timeout: JIT_TIMEOUT)
- args = [
- '--disable-gems', "--jit-verbose=#{verbose}",
- "--jit-min-calls=#{min_calls}", "--jit-max-cache=#{max_cache}",
- ]
- args << '--jit-wait' if wait
- args << '--jit-save-temps' if save_temps
- args << '--jit-debug' if defined?(@jit_debug) && @jit_debug
- args << '-e' << script
- base_env = { 'MJIT_SEARCH_BUILD_DIR' => 'true' } # workaround to skip requiring `make install` for `make test-all`
- if preloadenv = RbConfig::CONFIG['PRELOADENV'] and !preloadenv.empty?
- so = "mjit_build_dir.#{RbConfig::CONFIG['SOEXT']}"
- base_env[preloadenv] = File.realpath(so) rescue nil
- end
- args.unshift(env ? base_env.merge!(env) : base_env)
- EnvUtil.invoke_ruby(args,
- '', true, true, timeout: timeout,
- )
+ def yjit_supported?
+ return @yjit_supported if defined?(@yjit_supported)
+ # nil in mswin
+ @yjit_supported = ![nil, 'no'].include?(RbConfig::CONFIG['YJIT_SUPPORT'])
end
- def supported?
- return @supported if defined?(@supported)
- @supported = RbConfig::CONFIG["MJIT_SUPPORT"] != 'no' && UNSUPPORTED_COMPILERS.all? do |regexp|
- !regexp.match?(RbConfig::CONFIG['MJIT_CC'])
- end && !appveyor_pdb_corrupted? && !PENDING_RUBYCI_NICKNAMES.include?(ENV['RUBYCI_NICKNAME'])
+ def yjit_enabled?
+ defined?(RubyVM::YJIT.enabled?) && RubyVM::YJIT.enabled?
end
- # AppVeyor's Visual Studio 2013 / 2015 are known to spuriously generate broken pch / pdb, like:
- # error C2859: c:\projects\ruby\x64-mswin_120\include\ruby-2.8.0\x64-mswin64_120\rb_mjit_header-2.8.0.pdb
- # is not the pdb file that was used when this precompiled header was created, recreate the precompiled header.
- # https://ci.appveyor.com/project/ruby/ruby/builds/32159878/job/l2p38snw8yxxpp8h
- #
- # Until we figure out why, this allows us to skip testing JIT when it happens.
- def appveyor_pdb_corrupted?
- return false unless ENV.key?('APPVEYOR')
- stdout, _stderr, _status = eval_with_jit_without_retry('proc {}.call', verbose: 2, min_calls: 1)
- stdout.include?('.pdb is not the pdb file that was used when this precompiled header was created, recreate the precompiled header.')
+ def yjit_force_enabled?
+ "#{RbConfig::CONFIG['CFLAGS']} #{RbConfig::CONFIG['CPPFLAGS']}".match?(/(\A|\s)-D ?YJIT_FORCE_ENABLE\b/)
end
- def remove_mjit_logs(stderr)
- if defined?(RubyVM::JIT) && RubyVM::JIT.enabled? # utility for -DFORCE_MJIT_ENABLE
- stderr.gsub(/^MJIT warning: Skipped to compile unsupported instruction: \w+\n/m, '')
- else
- stderr
- end
+ def rjit_supported?
+ return @rjit_supported if defined?(@rjit_supported)
+ # nil in mswin
+ @rjit_supported = ![nil, 'no'].include?(RbConfig::CONFIG['RJIT_SUPPORT'])
end
- def code_block(code)
- %Q["""\n#{code}\n"""\n\n]
+ def rjit_enabled?
+ defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled?
end
- # We're retrying cc1 not found error on gcc, which should be solved in the future but ignored for now.
- def retried_stderr?(stderr)
- RbConfig::CONFIG['CC'].start_with?('gcc') &&
- stderr.include?("error trying to exec 'cc1': execvp: No such file or directory")
+ def rjit_force_enabled?
+ "#{RbConfig::CONFIG['CFLAGS']} #{RbConfig::CONFIG['CPPFLAGS']}".match?(/(\A|\s)-D ?RJIT_FORCE_ENABLE\b/)
end
end
diff --git a/test/lib/parser_support.rb b/test/lib/parser_support.rb
new file mode 100644
index 0000000000..0daf45e87b
--- /dev/null
+++ b/test/lib/parser_support.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+module ParserSupport
+ module_function
+
+ # Determines whether or not Prism is being used in the current process. This
+ # would have been determined by `--parser=prism` on either the command line or
+ # from within various environment variables.
+ def prism_enabled?
+ RubyVM::InstructionSequence.compile("").to_a[4][:parser] == :prism
+ end
+
+ # Determines whether or not Prism would be used by a subprocess. This is
+ # necessary because some tests run in subprocesses, and we need to know if we
+ # expect Prism to be used by those tests. This happens if Prism is configured
+ # as the default parser.
+ def prism_enabled_in_subprocess?
+ EnvUtil.invoke_ruby(["-v"], "", true, false)[0].include?("+PRISM")
+ end
+end
diff --git a/test/logger/test_formatter.rb b/test/logger/test_formatter.rb
new file mode 100644
index 0000000000..9465722991
--- /dev/null
+++ b/test/logger/test_formatter.rb
@@ -0,0 +1,35 @@
+# coding: US-ASCII
+# frozen_string_literal: false
+require 'logger'
+
+class TestFormatter < Test::Unit::TestCase
+ def test_call
+ severity = 'INFO'
+ time = Time.now
+ progname = 'ruby'
+ msg = 'This is a test'
+ formatter = Logger::Formatter.new
+
+ result = formatter.call(severity, time, progname, msg)
+ time_matcher = /\d{4}\-\d{2}\-\d{2}T\d{2}:\d{2}:\d{2}\.\d{6}/
+ matcher = /#{severity[0..0]}, \[#{time_matcher} #\d+\] #{severity} -- #{progname}: #{msg}\n/
+
+ assert_match(matcher, result)
+ end
+
+ class CustomFormatter < Logger::Formatter
+ def call(time)
+ format_datetime(time)
+ end
+ end
+
+ def test_format_datetime
+ time = Time.now
+ formatter = CustomFormatter.new
+
+ result = formatter.call(time)
+ matcher = /^\d{4}\-\d{2}\-\d{2}T\d{2}:\d{2}:\d{2}\.\d{6}$/
+
+ assert_match(matcher, result)
+ end
+end
diff --git a/test/logger/test_logdevice.rb b/test/logger/test_logdevice.rb
index d360fa2107..8f1c15542a 100644
--- a/test/logger/test_logdevice.rb
+++ b/test/logger/test_logdevice.rb
@@ -435,6 +435,7 @@ class TestLogDevice < Test::Unit::TestCase
logdev1.write(message)
assert_file.identical?(log, logdev1.dev)
+ # NOTE: below assertion fails in JRuby 9.3 and TruffleRuby
assert_file.identical?(log + ".0", logdev2.dev)
logdev2.write(message)
@@ -451,7 +452,7 @@ class TestLogDevice < Test::Unit::TestCase
end
ensure
logdev0.close
- end unless /mswin|mingw|cygwin/ =~ RUBY_PLATFORM
+ end unless /mswin|mingw|cygwin/ =~ RbConfig::CONFIG['host_os']
def test_shifting_midnight
Dir.mktmpdir do |tmpdir|
diff --git a/test/logger/test_logger.rb b/test/logger/test_logger.rb
index 3281d17c7b..2023553a6c 100644
--- a/test/logger/test_logger.rb
+++ b/test/logger/test_logger.rb
@@ -13,7 +13,7 @@ class TestLogger < Test::Unit::TestCase
class Log
attr_reader :label, :datetime, :pid, :severity, :progname, :msg
def initialize(line)
- /\A(\w+), \[([^#]*)#(\d+)\]\s+(\w+) -- (\w*): ([\x0-\xff]*)/ =~ line
+ /\A(\w+), \[([^#]*) #(\d+)\]\s+(\w+) -- (\w*): ([\x0-\xff]*)/ =~ line
@label, @datetime, @pid, @severity, @progname, @msg = $1, $2, $3, $4, $5, $6
end
end
@@ -113,6 +113,15 @@ class TestLogger < Test::Unit::TestCase
assert_raise(ArgumentError) { @logger.level = 'something_wrong' }
end
+ def test_reraise_write_errors
+ c = Object.new
+ e = Class.new(StandardError)
+ c.define_singleton_method(:write){|*| raise e}
+ c.define_singleton_method(:close){}
+ logger = Logger.new(c, :reraise_write_errors=>[e])
+ assert_raise(e) { logger.warn('foo') }
+ end
+
def test_progname
assert_nil(@logger.progname)
@logger.progname = "name"
@@ -124,7 +133,7 @@ class TestLogger < Test::Unit::TestCase
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)
+ 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)
@@ -203,7 +212,7 @@ class TestLogger < Test::Unit::TestCase
# default
logger = Logger.new(STDERR)
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)
+ assert_match(/^\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\d.\s*\d+$/, log.datetime)
# config
logger = Logger.new(STDERR, datetime_format: "%d%b%Y@%H:%M:%S")
log = log_add(logger, INFO, "foo")
diff --git a/test/logger/test_logperiod.rb b/test/logger/test_logperiod.rb
index 6e6e5e9533..ee38d877c6 100644
--- a/test/logger/test_logperiod.rb
+++ b/test/logger/test_logperiod.rb
@@ -1,80 +1,67 @@
# coding: US-ASCII
# frozen_string_literal: false
-require 'logger'
-require 'time'
+require "logger"
+require "time"
class TestLogPeriod < Test::Unit::TestCase
def test_next_rotate_time
time = Time.parse("2019-07-18 13:52:02")
- daily_result = Logger::Period.next_rotate_time(time, 'daily')
- next_day = Time.parse("2019-07-19 00:00:00")
- assert_equal(next_day, daily_result)
+ assert_next_rotate_time_words(time, "2019-07-19 00:00:00", ["daily", :daily])
+ assert_next_rotate_time_words(time, "2019-07-21 00:00:00", ["weekly", :weekly])
+ assert_next_rotate_time_words(time, "2019-08-01 00:00:00", ["monthly", :monthly])
- weekly_result = Logger::Period.next_rotate_time(time, 'weekly')
- next_week = Time.parse("2019-07-21 00:00:00")
- assert_equal(next_week, weekly_result)
-
- monthly_result = Logger::Period.next_rotate_time(time, 'monthly')
- next_month = Time.parse("2019-08-1 00:00:00")
- assert_equal(next_month, monthly_result)
-
- assert_raise(ArgumentError) { Logger::Period.next_rotate_time(time, 'invalid') }
+ assert_raise(ArgumentError) { Logger::Period.next_rotate_time(time, "invalid") }
end
def test_next_rotate_time_extreme_cases
# First day of Month and Saturday
time = Time.parse("2018-07-01 00:00:00")
- daily_result = Logger::Period.next_rotate_time(time, 'daily')
- next_day = Time.parse("2018-07-02 00:00:00")
- assert_equal(next_day, daily_result)
-
- weekly_result = Logger::Period.next_rotate_time(time, 'weekly')
- next_week = Time.parse("2018-07-08 00:00:00")
- assert_equal(next_week, weekly_result)
+ assert_next_rotate_time_words(time, "2018-07-02 00:00:00", ["daily", :daily])
+ assert_next_rotate_time_words(time, "2018-07-08 00:00:00", ["weekly", :weekly])
+ assert_next_rotate_time_words(time, "2018-08-01 00:00:00", ["monthly", :monthly])
- monthly_result = Logger::Period.next_rotate_time(time, 'monthly')
- next_month = Time.parse("2018-08-1 00:00:00")
- assert_equal(next_month, monthly_result)
-
- assert_raise(ArgumentError) { Logger::Period.next_rotate_time(time, 'invalid') }
+ assert_raise(ArgumentError) { Logger::Period.next_rotate_time(time, "invalid") }
end
def test_previous_period_end
time = Time.parse("2019-07-18 13:52:02")
- daily_result = Logger::Period.previous_period_end(time, 'daily')
- day_ago = Time.parse("2019-07-17 23:59:59")
- assert_equal(day_ago, daily_result)
-
- weekly_result = Logger::Period.previous_period_end(time, 'weekly')
- week_ago = Time.parse("2019-07-13 23:59:59")
- assert_equal(week_ago, weekly_result)
-
- monthly_result = Logger::Period.previous_period_end(time, 'monthly')
- month_ago = Time.parse("2019-06-30 23:59:59")
- assert_equal(month_ago, monthly_result)
+ assert_previous_period_end_words(time, "2019-07-17 23:59:59", ["daily", :daily])
+ assert_previous_period_end_words(time, "2019-07-13 23:59:59", ["weekly", :weekly])
+ assert_previous_period_end_words(time, "2019-06-30 23:59:59", ["monthly", :monthly])
- assert_raise(ArgumentError) { Logger::Period.next_rotate_time(time, 'invalid') }
+ assert_raise(ArgumentError) { Logger::Period.previous_period_end(time, "invalid") }
end
def test_previous_period_end_extreme_cases
# First day of Month and Saturday
time = Time.parse("2018-07-01 00:00:00")
+ previous_date = "2018-06-30 23:59:59"
- daily_result = Logger::Period.previous_period_end(time, 'daily')
- day_ago = Time.parse("2018-06-30 23:59:59")
- assert_equal(day_ago, daily_result)
+ assert_previous_period_end_words(time, previous_date, ["daily", :daily])
+ assert_previous_period_end_words(time, previous_date, ["weekly", :weekly])
+ assert_previous_period_end_words(time, previous_date, ["monthly", :monthly])
- weekly_result = Logger::Period.previous_period_end(time, 'weekly')
- week_ago = Time.parse("2018-06-30 23:59:59")
- assert_equal(week_ago, weekly_result)
+ assert_raise(ArgumentError) { Logger::Period.previous_period_end(time, "invalid") }
+ end
+
+ private
- monthly_result = Logger::Period.previous_period_end(time, 'monthly')
- month_ago = Time.parse("2018-06-30 23:59:59")
- assert_equal(month_ago, monthly_result)
+ def assert_next_rotate_time_words(time, next_date, words)
+ assert_time_words(:next_rotate_time, time, next_date, words)
+ end
+
+ def assert_previous_period_end_words(time, previous_date, words)
+ assert_time_words(:previous_period_end, time, previous_date, words)
+ end
- assert_raise(ArgumentError) { Logger::Period.next_rotate_time(time, 'invalid') }
+ def assert_time_words(method, time, date, words)
+ words.each do |word|
+ daily_result = Logger::Period.public_send(method, time, word)
+ expected_result = Time.parse(date)
+ assert_equal(expected_result, daily_result)
+ end
end
end
diff --git a/test/logger/test_severity.rb b/test/logger/test_severity.rb
index dad63472a6..e1069c8262 100644
--- a/test/logger/test_severity.rb
+++ b/test/logger/test_severity.rb
@@ -3,6 +3,8 @@
require 'logger'
class TestLoggerSeverity < Test::Unit::TestCase
+ include Logger::Severity
+
def test_enum
logger_levels = Logger.constants
levels = ["WARN", "UNKNOWN", "INFO", "FATAL", "DEBUG", "ERROR"]
@@ -23,4 +25,34 @@ class TestLoggerSeverity < Test::Unit::TestCase
assert(logger.level) == Logger::Severity.const_get(level)
end
end
+
+ def test_thread_local_level
+ logger = Logger.new(nil)
+ logger.level = INFO # default level
+ other = Logger.new(nil)
+ other.level = ERROR # default level
+
+ assert_equal(other.level, ERROR)
+ logger.with_level(:WARN) do
+ assert_equal(other.level, ERROR)
+ assert_equal(logger.level, WARN)
+
+ logger.with_level(DEBUG) do # verify reentrancy
+ assert_equal(logger.level, DEBUG)
+
+ Thread.new do
+ assert_equal(logger.level, INFO)
+ logger.with_level(:WARN) do
+ assert_equal(other.level, ERROR)
+ assert_equal(logger.level, WARN)
+ end
+ assert_equal(logger.level, INFO)
+ end.join
+
+ assert_equal(logger.level, DEBUG)
+ end
+ assert_equal(logger.level, WARN)
+ end
+ assert_equal(logger.level, INFO)
+ end
end
diff --git a/test/mkmf/base.rb b/test/mkmf/base.rb
index 4f67478a56..7df07c16a6 100644
--- a/test/mkmf/base.rb
+++ b/test/mkmf/base.rb
@@ -20,136 +20,137 @@ $INCFLAGS << " -I."
$extout_prefix = "$(extout)$(target_prefix)/"
class TestMkmf < Test::Unit::TestCase
-end
-
-module TestMkmf::Base
- MKMFLOG = proc {File.read("mkmf.log") rescue ""}
+ module Base
+ MKMFLOG = proc {File.read("mkmf.log") rescue ""}
- class Capture
- attr_accessor :origin
- def initialize
- @buffer = ""
- @filter = nil
- @out = true
- @origin = nil
- end
- def clear
- @buffer.clear
- end
- def flush
- STDOUT.print @filter ? @filter.call(@buffer) : @buffer
- clear
- end
- def reopen(io)
- case io
- when Capture
- initialize_copy(io)
- when File
- @out = false
- @origin.reopen(io) if @origin
- when IO
+ class Capture
+ attr_accessor :origin
+ def initialize
+ @buffer = ""
+ @filter = nil
@out = true
- @origin.reopen(io) if @origin
- else
- @out = false
+ @origin = nil
end
- end
- def filter(&block)
- @filter = block
- end
- def write(*s)
- if @out
- @buffer.concat(*s)
- elsif @origin
- @origin.write(*s)
+ def clear
+ @buffer.clear
+ end
+ def flush
+ STDOUT.print @filter ? @filter.call(@buffer) : @buffer
+ clear
+ end
+ def reopen(io)
+ case io
+ when Capture
+ initialize_copy(io)
+ when File
+ @out = false
+ @origin.reopen(io) if @origin
+ when IO
+ @out = true
+ @origin.reopen(io) if @origin
+ else
+ @out = false
+ end
+ end
+ def filter(&block)
+ @filter = block
+ end
+ def write(*s)
+ if @out
+ @buffer.concat(*s)
+ elsif @origin
+ @origin.write(*s)
+ end
end
end
- end
- attr_reader :stdout
+ attr_reader :stdout
- def mkmflog(msg)
- proc {MKMFLOG[] << msg}
- end
+ def mkmflog(msg)
+ proc {MKMFLOG[] << msg}
+ end
- def setup
- @rbconfig = rbconfig0 = RbConfig::CONFIG
- @mkconfig = mkconfig0 = RbConfig::MAKEFILE_CONFIG
- rbconfig = {
- "hdrdir" => $hdrdir,
- "srcdir" => $srcdir,
- "topdir" => $topdir,
- }
- mkconfig = {
- "hdrdir" => "$(top_srcdir)/include",
- "srcdir" => "$(top_srcdir)",
- "topdir" => $topdir,
- }
- rbconfig0.each_pair {|key, val| rbconfig[key] ||= val.dup}
- mkconfig0.each_pair {|key, val| mkconfig[key] ||= val.dup}
- RbConfig.module_eval {
- remove_const(:CONFIG)
- const_set(:CONFIG, rbconfig)
- remove_const(:MAKEFILE_CONFIG)
- const_set(:MAKEFILE_CONFIG, mkconfig)
- }
- MakeMakefile.class_eval {
- remove_const(:CONFIG)
- const_set(:CONFIG, mkconfig)
- }
- @tmpdir = Dir.mktmpdir
- @curdir = Dir.pwd
- @mkmfobj = Object.new
- @stdout = Capture.new
- Dir.chdir(@tmpdir)
- @quiet, Logging.quiet = Logging.quiet, true
- init_mkmf
- $INCFLAGS[0, 0] = "-I. "
- end
+ def setup
+ @rbconfig = rbconfig0 = RbConfig::CONFIG
+ @mkconfig = mkconfig0 = RbConfig::MAKEFILE_CONFIG
+ rbconfig = {
+ "hdrdir" => $hdrdir,
+ "srcdir" => $srcdir,
+ "topdir" => $topdir,
+ }
+ mkconfig = {
+ "hdrdir" => "$(top_srcdir)/include",
+ "srcdir" => "$(top_srcdir)",
+ "topdir" => $topdir,
+ }
+ rbconfig0.each_pair {|key, val| rbconfig[key] ||= val.dup}
+ mkconfig0.each_pair {|key, val| mkconfig[key] ||= val.dup}
+ RbConfig.module_eval {
+ remove_const(:CONFIG)
+ const_set(:CONFIG, rbconfig)
+ remove_const(:MAKEFILE_CONFIG)
+ const_set(:MAKEFILE_CONFIG, mkconfig)
+ }
+ MakeMakefile.class_eval {
+ remove_const(:CONFIG)
+ const_set(:CONFIG, mkconfig)
+ }
+ @tmpdir = Dir.mktmpdir
+ @curdir = Dir.pwd
+ @mkmfobj = Object.new
+ @stdout = Capture.new
+ Dir.chdir(@tmpdir)
+ @quiet, Logging.quiet = Logging.quiet, true
+ init_mkmf
+ $INCFLAGS[0, 0] = "-I. "
+ end
- def teardown
- rbconfig0 = @rbconfig
- mkconfig0 = @mkconfig
- RbConfig.module_eval {
- remove_const(:CONFIG)
- const_set(:CONFIG, rbconfig0)
- remove_const(:MAKEFILE_CONFIG)
- const_set(:MAKEFILE_CONFIG, mkconfig0)
- }
- MakeMakefile.class_eval {
- remove_const(:CONFIG)
- const_set(:CONFIG, mkconfig0)
- }
- Logging.quiet = @quiet
- Logging.log_close
- FileUtils.rm_f("mkmf.log")
- Dir.chdir(@curdir)
- FileUtils.rm_rf(@tmpdir)
- end
+ def teardown
+ return if @omitted
+ rbconfig0 = @rbconfig
+ mkconfig0 = @mkconfig
+ RbConfig.module_eval {
+ remove_const(:CONFIG)
+ const_set(:CONFIG, rbconfig0)
+ remove_const(:MAKEFILE_CONFIG)
+ const_set(:MAKEFILE_CONFIG, mkconfig0)
+ }
+ MakeMakefile.class_eval {
+ remove_const(:CONFIG)
+ const_set(:CONFIG, mkconfig0)
+ }
+ Logging.quiet = @quiet
+ Logging.log_close
+ FileUtils.rm_f("mkmf.log")
+ Dir.chdir(@curdir)
+ FileUtils.rm_rf(@tmpdir)
+ end
- def mkmf(*args, &block)
- @stdout.clear
- stdout, @stdout.origin, $stdout = @stdout.origin, $stdout, @stdout
- verbose, $VERBOSE = $VERBOSE, false
- @mkmfobj.instance_eval(*args, &block)
- ensure
- $VERBOSE = verbose
- $stdout, @stdout.origin = @stdout.origin, stdout
- end
+ def mkmf(*args, &block)
+ @stdout.clear
+ stdout, @stdout.origin, $stdout = @stdout.origin, $stdout, @stdout
+ verbose, $VERBOSE = $VERBOSE, false
+ @mkmfobj.instance_eval(*args, &block)
+ ensure
+ $VERBOSE = verbose
+ $stdout, @stdout.origin = @stdout.origin, stdout
+ end
- def config_value(name)
- create_tmpsrc("---config-value=#{name}")
- xpopen(cpp_command('')) do |f|
- f.grep(/^---config-value=(.*)/) {return $1}
+ def config_value(name)
+ create_tmpsrc("---config-value=#{name}")
+ xpopen(cpp_command('')) do |f|
+ f.grep(/^---config-value=(.*)/) {return $1}
+ end
+ nil
end
- nil
end
-end
-class TestMkmf
- include TestMkmf::Base
+ include Base
- def assert_separately(args, src, *rest, **options)
- super(args + ["-r#{__FILE__}"], "extend TestMkmf::Base; setup\nEND{teardown}\n#{src}", *rest, **options)
+ def assert_separately(args, extra_args, src, *rest, **options)
+ super(args + ["-r#{__FILE__}"] + %w[- --] + extra_args,
+ "extend TestMkmf::Base; setup\nEND{teardown}\n#{src}",
+ *rest,
+ **options)
end
end
diff --git a/test/mkmf/test_config.rb b/test/mkmf/test_config.rb
index 07ed641415..0d2cb3751c 100644
--- a/test/mkmf/test_config.rb
+++ b/test/mkmf/test_config.rb
@@ -1,17 +1,57 @@
# frozen_string_literal: false
-$extmk = true
+require_relative 'base'
+require 'tempfile'
-require 'test/unit'
-require 'mkmf'
+class TestMkmfConfig < TestMkmf
+ def test_dir_config
+ bug8074 = '[Bug #8074]'
+ lib = RbConfig.expand(RbConfig::MAKEFILE_CONFIG["libdir"], "exec_prefix"=>"/test/foo")
+ assert_separately([], %w[--with-foo-dir=/test/foo], <<-"end;")
+ assert_equal(%w[/test/foo/include #{lib}], dir_config("foo"), #{bug8074.dump})
+ end;
+ end
+
+ def test_with_config_with_arg_and_value
+ assert_separately([], %w[--with-foo=bar], <<-'end;')
+ assert_equal("bar", with_config("foo"))
+ end;
+ end
+
+ def test_with_config_with_arg_and_no_value
+ assert_separately([], %w[--with-foo], <<-'end;')
+ assert_equal(true, with_config("foo"))
+ end;
+ end
+
+ def test_with_config_without_arg
+ assert_separately([], %w[--without-foo], <<-'end;')
+ assert_equal(false, with_config("foo"))
+ end;
+ end
+
+ def test_with_target_rbconfig
+ Tempfile.create(%w"rbconfig .rb", ".") do |tmp|
+ tmp.puts <<~'end;'
+ module RbConfig
+ CONFIG = {}
+ MAKEFILE_CONFIG = {}
-class TestMkmf < Test::Unit::TestCase
- class TestConfig < Test::Unit::TestCase
- def test_dir_config
- bug8074 = '[Bug #8074]'
- lib = RbConfig.expand(RbConfig::MAKEFILE_CONFIG["libdir"], "exec_prefix"=>"")
- assert_separately %w[-rmkmf - -- --with-foo-dir=/test/foo], %{
- assert_equal(%w[/test/foo/include /test/foo#{lib}], dir_config("foo"), #{bug8074.dump})
- }
+ def self.fire_update!(key, value); end
+ def self.expand(val, config = CONFIG); val; end
+ end;
+ ::RbConfig::CONFIG.each do |k, v|
+ tmp.puts " CONFIG[#{k.dump}] = #{v.dump}"
+ end
+ ::RbConfig::MAKEFILE_CONFIG.each do |k, v|
+ tmp.puts " MAKEFILE_CONFIG[#{k.dump}] = #{v.dump}"
+ end
+ tmp.puts " CONFIG['testing-only'] = 'ok'"
+ tmp.puts "end"
+ tmp.close
+ assert_separately([], ["--target-rbconfig=#{tmp.path}"], <<-'end;')
+ assert_equal("ok", MakeMakefile::RbConfig::CONFIG["testing-only"])
+ assert_not_equal(::RbConfig, MakeMakefile::RbConfig)
+ end;
end
end
end
diff --git a/test/mkmf/test_configuration.rb b/test/mkmf/test_configuration.rb
new file mode 100644
index 0000000000..0261f78a01
--- /dev/null
+++ b/test/mkmf/test_configuration.rb
@@ -0,0 +1,39 @@
+# frozen_string_literal: false
+require_relative 'base'
+
+class TestMkmfConfiguration < TestMkmf
+ def test_verbose_with_rbconfig_verbose_disabled
+ makefile = mkmf do
+ self.class::CONFIG['MKMF_VERBOSE'] = "0"
+ init_mkmf(self.class::CONFIG)
+ configuration '.'
+ end
+ verbose = makefile.grep(/^V =/).first[/^V = (.)$/, 1]
+
+ assert_equal "0", verbose
+ end
+
+ def test_verbose_with_rbconfig_verbose_enabled
+ makefile = mkmf do
+ self.class::CONFIG['MKMF_VERBOSE'] = "1"
+ init_mkmf(self.class::CONFIG)
+ configuration '.'
+ end
+ verbose = makefile.grep(/^V =/).first[/^V = (.)$/, 1]
+
+ assert_equal "1", verbose
+ end
+
+ def test_verbose_with_arg
+ assert_separately([], %w[--with-verbose], <<-'end;')
+ makefile = mkmf do
+ self.class::CONFIG['MKMF_VERBOSE'] = "0"
+ init_mkmf(self.class::CONFIG)
+ configuration '.'
+ end
+ verbose = makefile.grep(/^V =/).first[/^V = (.)$/, 1]
+
+ assert_equal "1", verbose
+ end;
+ end
+end
diff --git a/test/mkmf/test_constant.rb b/test/mkmf/test_constant.rb
index f5a87a1caa..f22b82ff95 100644
--- a/test/mkmf/test_constant.rb
+++ b/test/mkmf/test_constant.rb
@@ -1,38 +1,44 @@
# frozen_string_literal: false
require_relative 'base'
-class TestMkmf
- class TestTryConstant < TestMkmf
- def test_simple
- assert_equal( 0, mkmf {try_constant("0")}, MKMFLOG)
- assert_equal( 1, mkmf {try_constant("1")}, MKMFLOG)
- assert_equal(-1, mkmf {try_constant("-1")}, MKMFLOG)
+class TestMkmfTryConstant < TestMkmf
+ def setup
+ if ENV.key?('APPVEYOR')
+ @omitted = true
+ omit 'This test fails too often on AppVeyor'
end
+ super
+ end
- def test_sizeof
- assert_equal(config_value("SIZEOF_INT").to_i, mkmf {try_constant("sizeof(int)")}, MKMFLOG)
- assert_equal(config_value("SIZEOF_LONG").to_i, mkmf {try_constant("sizeof(long)")}, MKMFLOG)
- assert_equal(config_value("SIZEOF_VOIDP").to_i, mkmf {try_constant("sizeof(void*)")}, MKMFLOG)
- assert_equal(config_value("SIZEOF_VALUE").to_i, mkmf {try_constant("sizeof(Qnil)")}, MKMFLOG)
- end
+ def test_simple
+ assert_equal( 0, mkmf {try_constant("0")}, MKMFLOG)
+ assert_equal( 1, mkmf {try_constant("1")}, MKMFLOG)
+ assert_equal(-1, mkmf {try_constant("-1")}, MKMFLOG)
+ end
- def test_long
- sizeof_int = config_value("SIZEOF_INT").to_i
- sizeof_long = config_value("SIZEOF_LONG").to_i
- if sizeof_long > sizeof_int
- type = 'long'
- else
- sizeof_long_long = config_value("SIZEOF_LONG_LONG").to_i
- return if !sizeof_long_long or sizeof_long_long <= sizeof_int
- type = 'LONG_LONG'
- end
+ def test_sizeof
+ assert_equal(config_value("SIZEOF_INT").to_i, mkmf {try_constant("sizeof(int)")}, MKMFLOG)
+ assert_equal(config_value("SIZEOF_LONG").to_i, mkmf {try_constant("sizeof(long)")}, MKMFLOG)
+ assert_equal(config_value("SIZEOF_VOIDP").to_i, mkmf {try_constant("sizeof(void*)")}, MKMFLOG)
+ assert_equal(config_value("SIZEOF_VALUE").to_i, mkmf {try_constant("sizeof(Qnil)")}, MKMFLOG)
+ end
- decl = "#define CONFTEST_VALUE (unsigned #{type})(((unsigned #{type})1)<<(CHAR_BIT*sizeof(int)))"
- assert_operator(mkmf {try_constant("CONFTEST_VALUE", [[decl]])}, :>, 0, MKMFLOG)
+ def test_long
+ sizeof_int = config_value("SIZEOF_INT").to_i
+ sizeof_long = config_value("SIZEOF_LONG").to_i
+ if sizeof_long > sizeof_int
+ type = 'long'
+ else
+ sizeof_long_long = config_value("SIZEOF_LONG_LONG").to_i
+ return if !sizeof_long_long or sizeof_long_long <= sizeof_int
+ type = 'LONG_LONG'
end
- def test_large_unsigned
- assert_operator(mkmf {try_constant("1U<<(CHAR_BIT*sizeof(int)-1)")}, :>, 0, MKMFLOG)
- end
+ decl = "#define CONFTEST_VALUE (unsigned #{type})(((unsigned #{type})1)<<(CHAR_BIT*sizeof(int)))"
+ assert_operator(mkmf {try_constant("CONFTEST_VALUE", [[decl]])}, :>, 0, MKMFLOG)
+ end
+
+ def test_large_unsigned
+ assert_operator(mkmf {try_constant("1U<<(CHAR_BIT*sizeof(int)-1)")}, :>, 0, MKMFLOG)
end
end
diff --git a/test/mkmf/test_convertible.rb b/test/mkmf/test_convertible.rb
index 1baf892842..d65db4265b 100644
--- a/test/mkmf/test_convertible.rb
+++ b/test/mkmf/test_convertible.rb
@@ -1,35 +1,33 @@
# frozen_string_literal: false
require_relative 'base'
-class TestMkmf
- class TestConvertible < TestMkmf
- def test_typeof_builtin
- ["", ["signed ", ""], "unsigned "].each do |signed, prefix|
- %w[short int long].each do |type|
- assert_equal((prefix || signed)+type,
- mkmf {convertible_int(signed+type)}, MKMFLOG)
- end
+class TestMkmfConvertible < TestMkmf
+ def test_typeof_builtin
+ ["", ["signed ", ""], "unsigned "].each do |signed, prefix|
+ %w[short int long].each do |type|
+ assert_equal((prefix || signed)+type,
+ mkmf {convertible_int(signed+type)}, MKMFLOG)
end
end
+ end
- def test_typeof_typedef
- ["", ["signed ", ""], "unsigned "].each do |signed, prefix|
- %w[short int long].each do |type|
- open("confdefs.h", "w") {|f|
- f.puts "typedef #{signed}#{type} test1_t;"
- }
- $defs.clear
- assert_equal((prefix || signed)+type,
- mkmf {convertible_int("test1_t", "confdefs.h")}, MKMFLOG)
- (u = signed[/^u/]) and u.upcase!
- assert_include($defs, "-DTYPEOF_TEST1_T="+"#{prefix||signed}#{type}".quote)
- assert_include($defs, "-DPRI_TEST1T_PREFIX=PRI_#{type.upcase}_PREFIX")
- assert_include($defs, "-DTEST1T2NUM=#{u}#{type.upcase}2NUM")
- assert_include($defs, "-DNUM2TEST1T=NUM2#{u}#{type.upcase}")
- end
+ def test_typeof_typedef
+ ["", ["signed ", ""], "unsigned "].each do |signed, prefix|
+ %w[short int long].each do |type|
+ open("confdefs.h", "w") {|f|
+ f.puts "typedef #{signed}#{type} test1_t;"
+ }
+ $defs.clear
+ assert_equal((prefix || signed)+type,
+ mkmf {convertible_int("test1_t", "confdefs.h")}, MKMFLOG)
+ (u = signed[/^u/]) and u.upcase!
+ assert_include($defs, "-DTYPEOF_TEST1_T="+"#{prefix||signed}#{type}".quote)
+ assert_include($defs, "-DPRI_TEST1T_PREFIX=PRI_#{type.upcase}_PREFIX")
+ assert_include($defs, "-DTEST1T2NUM=#{u}#{type.upcase}2NUM")
+ assert_include($defs, "-DNUM2TEST1T=NUM2#{u}#{type.upcase}")
end
- ensure
- File.unlink("confdefs.h")
end
+ ensure
+ File.unlink("confdefs.h")
end
end
diff --git a/test/mkmf/test_egrep_cpp.rb b/test/mkmf/test_egrep_cpp.rb
index ce276bef20..7ac0e60010 100644
--- a/test/mkmf/test_egrep_cpp.rb
+++ b/test/mkmf/test_egrep_cpp.rb
@@ -2,14 +2,12 @@
require_relative 'base'
require 'tempfile'
-class TestMkmf
- class TestEgrepCpp < TestMkmf
- def test_egrep_cpp
- assert_equal(true, egrep_cpp(/ruby_init/, ""), MKMFLOG)
- end
+class TestMkmfEgrepCpp < TestMkmf
+ def test_egrep_cpp
+ assert_equal(true, egrep_cpp(/ruby_init/, ""), MKMFLOG)
+ end
- def test_not_have_func
- assert_equal(false, egrep_cpp(/never match/, ""), MKMFLOG)
- end
+ def test_not_have_func
+ assert_equal(false, egrep_cpp(/never match/, ""), MKMFLOG)
end
end
diff --git a/test/mkmf/test_find_executable.rb b/test/mkmf/test_find_executable.rb
index 7ffc28ecc8..88b70c21c0 100644
--- a/test/mkmf/test_find_executable.rb
+++ b/test/mkmf/test_find_executable.rb
@@ -1,58 +1,56 @@
# frozen_string_literal: false
require_relative 'base'
-class TestMkmf
- class TestFindExecutable < TestMkmf
- def setup
- super
- @path, ENV["PATH"] = ENV["PATH"], @tmpdir
- end
+class TestMkmfFindExecutable < TestMkmf
+ def setup
+ super
+ @path, ENV["PATH"] = ENV["PATH"], @tmpdir
+ end
- def each_exts(&block)
- name = "foobar#{$$}#{rand(1000)}"
- stdout.filter {|s| s.sub(name, "<executable>")}
- exts = mkmf {self.class::CONFIG['EXECUTABLE_EXTS']}.split
- exts[0] ||= ""
- exts.each do |ext|
- yield name+ext, name
- end
+ def each_exts(&block)
+ name = "foobar#{$$}#{rand(1000)}"
+ stdout.filter {|s| s.sub(name, "<executable>")}
+ exts = mkmf {self.class::CONFIG['EXECUTABLE_EXTS']}.split
+ exts[0] ||= ""
+ exts.each do |ext|
+ yield name+ext, name
end
+ end
- def teardown
- ENV["PATH"] = @path
- super
- end
+ def teardown
+ ENV["PATH"] = @path
+ super
+ end
- def test_find_executable
- bug2669 = '[ruby-core:27912]'
- each_exts do |full, name|
- begin
- open(full, "w") {|ff| ff.chmod(0755)}
- result = mkmf {find_executable(name)}
- ensure
- File.unlink(full)
- end
- assert_equal("#{@tmpdir}/#{full}", result, bug2669)
+ def test_find_executable
+ bug2669 = '[ruby-core:27912]'
+ each_exts do |full, name|
+ begin
+ open(full, "w") {|ff| ff.chmod(0755)}
+ result = mkmf {find_executable(name)}
+ ensure
+ File.unlink(full)
end
+ assert_equal("#{@tmpdir}/#{full}", result, bug2669)
end
+ end
- def test_find_executable_dir
- each_exts do |full, name|
- begin
- Dir.mkdir(full)
- result = mkmf {find_executable(name)}
- ensure
- Dir.rmdir(full)
- end
- assert_nil(result)
+ def test_find_executable_dir
+ each_exts do |full, name|
+ begin
+ Dir.mkdir(full)
+ result = mkmf {find_executable(name)}
+ ensure
+ Dir.rmdir(full)
end
+ assert_nil(result)
end
+ end
- if /mingw|mswin/ =~ RUBY_PLATFORM
- def test_quoted_path_on_windows
- ENV["PATH"] = %["#{@tmpdir}"]
- test_find_executable
- end
+ if /mingw|mswin/ =~ RUBY_PLATFORM
+ def test_quoted_path_on_windows
+ ENV["PATH"] = %["#{@tmpdir}"]
+ test_find_executable
end
end
end
diff --git a/test/mkmf/test_flags.rb b/test/mkmf/test_flags.rb
index a3596d8e55..3d908c6bb4 100644
--- a/test/mkmf/test_flags.rb
+++ b/test/mkmf/test_flags.rb
@@ -1,57 +1,55 @@
# frozen_string_literal: false
require_relative 'base'
-class TestMkmf
- class TestFlags < TestMkmf
- def test_valid_warnflags
- val = $extmk
- warnflags = $warnflags
- makefile = mkmf do
- $extmk = false
- self.class::CONFIG['warnflags'] = %w"-Wextra
- -Wno-unused-parameter -Wno-parentheses -Wno-long-long
- -Wno-missing-field-initializers -Werror=pointer-arith
- -Werror=write-strings -Werror=declaration-after-statement
- -Werror=shorten-64-to-32
- -Werror-implicit-function-declaration
- ".join(' ')
- self.class::CONFIG['GCC'] = 'yes'
- init_mkmf(self.class::CONFIG)
- configuration '.'
- end
- generated_flags = makefile.grep(/warnflags/).first[/^warnflags = (.*)$/, 1].split
+class TestMkmfFlags < TestMkmf
+ def test_valid_warnflags
+ val = $extmk
+ warnflags = $warnflags
+ makefile = mkmf do
+ $extmk = false
+ self.class::CONFIG['warnflags'] = %w"-Wextra
+ -Wno-unused-parameter -Wno-parentheses -Wno-long-long
+ -Wno-missing-field-initializers -Werror=pointer-arith
+ -Werror=write-strings -Werror=declaration-after-statement
+ -Werror=shorten-64-to-32
+ -Werror-implicit-function-declaration
+ ".join(' ')
+ self.class::CONFIG['GCC'] = 'yes'
+ init_mkmf(self.class::CONFIG)
+ configuration '.'
+ end
+ generated_flags = makefile.grep(/warnflags/).first[/^warnflags = (.*)$/, 1].split
- assert_equal %w"
- -Wextra -Wno-unused-parameter -Wno-parentheses
- -Wno-long-long -Wno-missing-field-initializers -Wpointer-arith
- -Wwrite-strings -Wdeclaration-after-statement
- -Wshorten-64-to-32 -Wimplicit-function-declaration
- ", generated_flags
+ assert_equal %w"
+ -Wextra -Wno-unused-parameter -Wno-parentheses
+ -Wno-long-long -Wno-missing-field-initializers -Wpointer-arith
+ -Wwrite-strings -Wdeclaration-after-statement
+ -Wshorten-64-to-32 -Werror-implicit-function-declaration
+ ", generated_flags
- ensure
- $warnflags = warnflags
- $extmk = val
- end
+ ensure
+ $warnflags = warnflags
+ $extmk = val
+ end
- def test_try_ldflag_invalid_opt
- assert_separately([], <<-'end;') #do
- assert(!try_ldflags("nosuch.c"), TestMkmf::MKMFLOG)
- assert(have_devel?, TestMkmf::MKMFLOG)
- end;
- end
+ def test_try_ldflag_invalid_opt
+ assert_separately([], [], <<-'end;', timeout: 30) #do
+ assert(!try_ldflags("nosuch.c"), TestMkmf::MKMFLOG)
+ assert(have_devel?, TestMkmf::MKMFLOG)
+ end;
+ end
- def test_try_cflag_invalid_opt
- assert_separately([], <<-'end;', timeout: 30) #do
- assert(!try_cflags("nosuch.c"), TestMkmf::MKMFLOG)
- assert(have_devel?, TestMkmf::MKMFLOG)
- end;
- end
+ def test_try_cflag_invalid_opt
+ assert_separately([], [], <<-'end;', timeout: 30) #do
+ assert(!try_cflags("nosuch.c"), TestMkmf::MKMFLOG)
+ assert(have_devel?, TestMkmf::MKMFLOG)
+ end;
+ end
- def test_try_cppflag_invalid_opt
- assert_separately([], <<-'end;') #do
- assert(!try_cppflags("nosuch.c"), TestMkmf::MKMFLOG)
- assert(have_devel?, TestMkmf::MKMFLOG)
- end;
- end
+ def test_try_cppflag_invalid_opt
+ assert_separately([], [], <<-'end;', timeout: 30) #do
+ assert(!try_cppflags("nosuch.c"), TestMkmf::MKMFLOG)
+ assert(have_devel?, TestMkmf::MKMFLOG)
+ end;
end
end
diff --git a/test/mkmf/test_framework.rb b/test/mkmf/test_framework.rb
index ba15299ae0..3245e43c75 100644
--- a/test/mkmf/test_framework.rb
+++ b/test/mkmf/test_framework.rb
@@ -1,49 +1,47 @@
# frozen_string_literal: false
require_relative 'base'
-class TestMkmf
- class TestHaveFramework < TestMkmf
- def create_framework(fw, hdrname = "#{fw}.h")
- Dir.mktmpdir("frameworks") do |dir|
- fwdir = "#{dir}/#{fw}.framework"
- hdrdir = "#{fwdir}/Headers"
- FileUtils.mkdir_p(hdrdir)
- File.write("#{hdrdir}/#{hdrname}", "")
- src = "#{fwdir}/main.c"
- File.write(src, "void #{fw}(void) {}\n")
- cmd = LINK_SO.dup
- RbConfig.expand(cmd, RbConfig::CONFIG.merge("OBJS"=>src))
- cmd.gsub!("$@", "#{fwdir}/#{fw}")
- cmd.gsub!(/ -bundle /, ' -dynamiclib ')
- assert(xsystem(cmd), MKMFLOG)
- $INCFLAGS << " " << "-F#{dir}".quote
- yield fw, hdrname
- end
+class TestMkmfHaveFramework < TestMkmf
+ def create_framework(fw, hdrname = "#{fw}.h")
+ Dir.mktmpdir("frameworks") do |dir|
+ fwdir = "#{dir}/#{fw}.framework"
+ hdrdir = "#{fwdir}/Headers"
+ FileUtils.mkdir_p(hdrdir)
+ File.write("#{hdrdir}/#{hdrname}", "")
+ src = "#{fwdir}/main.c"
+ File.write(src, "void #{fw}(void) {}\n")
+ cmd = LINK_SO.dup
+ RbConfig.expand(cmd, RbConfig::CONFIG.merge("OBJS"=>src))
+ cmd.gsub!("$@", "#{fwdir}/#{fw}")
+ cmd.gsub!(/ -bundle /, ' -dynamiclib ')
+ assert(xsystem(cmd), MKMFLOG)
+ $INCFLAGS << " " << "-F#{dir}".quote
+ yield fw, hdrname
end
+ end
- def test_single_framework
- assert(have_framework(%w"Ruby ruby.h"), mkmflog("try as Objective-C"))
- end
+ def test_single_framework
+ assert(have_framework(%w"Ruby ruby.h"), mkmflog("try as Objective-C"))
+ end
- def test_multi_frameworks
- assert(have_framework(%w"Ruby ruby.h"), mkmflog("try as Objective-C"))
- create_framework("MkmfTest") do |fw|
- assert(have_framework(fw), MKMFLOG)
- end
+ def test_multi_frameworks
+ assert(have_framework(%w"Ruby ruby.h"), mkmflog("try as Objective-C"))
+ create_framework("MkmfTest") do |fw|
+ assert(have_framework(fw), MKMFLOG)
end
+ end
- def test_empty_framework
- create_framework("MkmfTest") do |fw|
- assert(have_framework(fw), MKMFLOG)
- end
+ def test_empty_framework
+ create_framework("MkmfTest") do |fw|
+ assert(have_framework(fw), MKMFLOG)
end
+ end
- def test_different_name_header
- _bug8593 = '[ruby-core:55745] [Bug #8593]'
- create_framework("MkmfTest", "test_mkmf.h") do |fw, hdrname|
- assert(!have_framework(fw), MKMFLOG)
- assert(have_framework([fw, hdrname]), MKMFLOG)
- end
+ def test_different_name_header
+ _bug8593 = '[ruby-core:55745] [Bug #8593]'
+ create_framework("MkmfTest", "test_mkmf.h") do |fw, hdrname|
+ assert(!have_framework(fw), MKMFLOG)
+ assert(have_framework([fw, hdrname]), MKMFLOG)
end
end
end if /darwin/ =~ RUBY_PLATFORM
diff --git a/test/mkmf/test_have_func.rb b/test/mkmf/test_have_func.rb
index 6204ab24f0..521a0bb435 100644
--- a/test/mkmf/test_have_func.rb
+++ b/test/mkmf/test_have_func.rb
@@ -2,16 +2,14 @@
require_relative 'base'
require 'tempfile'
-class TestMkmf
- class TestHaveFunc < TestMkmf
- def test_have_func
- assert_equal(true, have_func("ruby_init"), MKMFLOG)
- assert_include($defs, '-DHAVE_RUBY_INIT')
- end
+class TestMkmfHaveFunc < TestMkmf
+ def test_have_func
+ assert_equal(true, have_func("ruby_init"), MKMFLOG)
+ assert_include($defs, '-DHAVE_RUBY_INIT')
+ end
- def test_not_have_func
- assert_equal(false, have_func("no_ruby_init"), MKMFLOG)
- assert_not_include($defs, '-DHAVE_RUBY_INIT')
- end
+ def test_not_have_func
+ assert_equal(false, have_func("no_ruby_init"), MKMFLOG)
+ assert_not_include($defs, '-DHAVE_RUBY_INIT')
end
end
diff --git a/test/mkmf/test_have_library.rb b/test/mkmf/test_have_library.rb
index bb9ce6972d..e34a9b06da 100644
--- a/test/mkmf/test_have_library.rb
+++ b/test/mkmf/test_have_library.rb
@@ -2,55 +2,53 @@
require_relative 'base'
require 'tempfile'
-class TestMkmf
- class TestHaveLibrary < TestMkmf
- LIBRARY_NAME = 'mkmftest'
- HEADER_NAME = "#{LIBRARY_NAME}.h"
- FUNC_NAME = 'ruby_mkmftest_foo'
- ARPREFIX = config_string('LIBRUBY_A') {|lib| lib[/\A\w+/]}
-
- def create_library(libname = LIBRARY_NAME)
- lib = "#{ARPREFIX}#{libname}.#{$LIBEXT}"
- open(HEADER_NAME, "w") do |hdr|
- hdr.puts "void #{FUNC_NAME}(void);"
- hdr.puts "void #{FUNC_NAME}_fake(void);"
- end
- create_tmpsrc("#include \"#{HEADER_NAME}\"\n""void #{FUNC_NAME}(void) {}")
- assert(xsystem(cc_command), "compile failed: #{cc_command}")
- command = "#{CONFIG['AR']} #{config_string('ARFLAGS') || 'cru '}#{lib} #{CONFTEST}.#{$OBJEXT}"
- assert(xsystem(command), "making library failed: #{command}")
- File.unlink("#{CONFTEST}.#{$OBJEXT}")
- config_string('RANLIB') do |ranlib|
- command = "#{ranlib} #{lib}"
- assert(xsystem(command), "ranlib failed: #{command}")
- end
+class TestMkmfHaveLibrary < TestMkmf
+ LIBRARY_NAME = 'mkmftest'
+ HEADER_NAME = "#{LIBRARY_NAME}.h"
+ FUNC_NAME = 'ruby_mkmftest_foo'
+ ARPREFIX = config_string('LIBRUBY_A') {|lib| lib[/\A\w+/]}
+
+ def create_library(libname = LIBRARY_NAME)
+ lib = "#{ARPREFIX}#{libname}.#{$LIBEXT}"
+ open(HEADER_NAME, "w") do |hdr|
+ hdr.puts "void #{FUNC_NAME}(void);"
+ hdr.puts "void #{FUNC_NAME}_fake(void);"
end
-
- def assert_have_library(*args)
- assert_equal(true, have_library(LIBRARY_NAME, *args), MKMFLOG)
+ create_tmpsrc("#include \"#{HEADER_NAME}\"\n""void #{FUNC_NAME}(void) {}")
+ assert(xsystem(cc_command), "compile failed: #{cc_command}")
+ command = "#{CONFIG['AR']} #{config_string('ARFLAGS') || 'cru '}#{lib} #{CONFTEST}.#{$OBJEXT}"
+ assert(xsystem(command), "making library failed: #{command}")
+ File.unlink("#{CONFTEST}.#{$OBJEXT}")
+ config_string('RANLIB') do |ranlib|
+ command = "#{ranlib} #{lib}"
+ assert(xsystem(command), "ranlib failed: #{command}")
end
+ end
- def assert_not_have_library(*args)
- assert_equal(false, have_library(LIBRARY_NAME, *args), MKMFLOG)
- end
+ def assert_have_library(*args)
+ assert_equal(true, have_library(LIBRARY_NAME, *args), MKMFLOG)
+ end
- def test_have_library
- create_library
- assert_have_library
- end
+ def assert_not_have_library(*args)
+ assert_equal(false, have_library(LIBRARY_NAME, *args), MKMFLOG)
+ end
- def test_have_library_with_name
- create_library
- assert_have_library(FUNC_NAME, HEADER_NAME)
- end
+ def test_have_library
+ create_library
+ assert_have_library
+ end
- def test_not_have_library
- assert_not_have_library
- end
+ def test_have_library_with_name
+ create_library
+ assert_have_library(FUNC_NAME, HEADER_NAME)
+ end
- def test_not_have_library_with_name
- create_library
- assert_not_have_library("#{FUNC_NAME}_fake", HEADER_NAME)
- end
+ def test_not_have_library
+ assert_not_have_library
+ end
+
+ def test_not_have_library_with_name
+ create_library
+ assert_not_have_library("#{FUNC_NAME}_fake", HEADER_NAME)
end
end
diff --git a/test/mkmf/test_have_macro.rb b/test/mkmf/test_have_macro.rb
index ebc5648097..3178bfea0b 100644
--- a/test/mkmf/test_have_macro.rb
+++ b/test/mkmf/test_have_macro.rb
@@ -2,35 +2,33 @@
require_relative 'base'
require 'tempfile'
-class TestMkmf
- class TestHaveMacro < TestMkmf
- MACRO_NAME = "RUBY_MKMFTEST_FOOBAR"
+class TestMkmfHaveMacro < TestMkmf
+ MACRO_NAME = "RUBY_MKMFTEST_FOOBAR"
- def test_have_macro_opt
- assert_equal(true, have_macro(MACRO_NAME, nil, "-D#{MACRO_NAME}"), MKMFLOG)
- end
+ def test_have_macro_opt
+ assert_equal(true, have_macro(MACRO_NAME, nil, "-D#{MACRO_NAME}"), MKMFLOG)
+ end
- def test_have_macro_header
- Tempfile.create(%w"test_mkmf .h", ".") do |tmp|
- tmp.puts("#undef #{MACRO_NAME}")
- tmp.puts("#define #{MACRO_NAME} 1")
- tmp.close
- base = File.basename(tmp.path)
- assert_equal(true, have_macro(MACRO_NAME, base, "-I."), MKMFLOG)
- end
+ def test_have_macro_header
+ Tempfile.create(%w"test_mkmf .h", ".") do |tmp|
+ tmp.puts("#undef #{MACRO_NAME}")
+ tmp.puts("#define #{MACRO_NAME} 1")
+ tmp.close
+ base = File.basename(tmp.path)
+ assert_equal(true, have_macro(MACRO_NAME, base, "-I."), MKMFLOG)
end
+ end
- def test_not_have_macro_opt
- assert_equal(false, have_macro(MACRO_NAME, nil, "-U#{MACRO_NAME}"), MKMFLOG)
- end
+ def test_not_have_macro_opt
+ assert_equal(false, have_macro(MACRO_NAME, nil, "-U#{MACRO_NAME}"), MKMFLOG)
+ end
- def test_not_have_macro_header
- Tempfile.create(%w"test_mkmf .h", ".") do |tmp|
- tmp.puts("#undef #{MACRO_NAME}")
- tmp.close
- base = File.basename(tmp.path)
- assert_equal(false, have_macro(MACRO_NAME, base, "-I."), MKMFLOG)
- end
+ def test_not_have_macro_header
+ Tempfile.create(%w"test_mkmf .h", ".") do |tmp|
+ tmp.puts("#undef #{MACRO_NAME}")
+ tmp.close
+ base = File.basename(tmp.path)
+ assert_equal(false, have_macro(MACRO_NAME, base, "-I."), MKMFLOG)
end
end
end
diff --git a/test/mkmf/test_have_var.rb b/test/mkmf/test_have_var.rb
deleted file mode 100644
index 5367ec2248..0000000000
--- a/test/mkmf/test_have_var.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-# frozen_string_literal: false
-require_relative 'base'
-require 'tempfile'
-
-class TestMkmf
- class TestHaveVar < TestMkmf
- def test_have_var
- assert_equal(true, have_var("ruby_version"), MKMFLOG)
- assert_include($defs, '-DHAVE_RUBY_VERSION')
- end
-
- def test_not_have_var
- assert_equal(false, have_var("rb_vm_something_flag"), MKMFLOG)
- assert_not_include($defs, '-DHAVE_RB_VM_SOMETHING_FLAG')
- end
- end
-end
diff --git a/test/mkmf/test_install.rb b/test/mkmf/test_install.rb
index 7f8c603d42..009d55f72d 100644
--- a/test/mkmf/test_install.rb
+++ b/test/mkmf/test_install.rb
@@ -1,27 +1,25 @@
# frozen_string_literal: false
require_relative 'base'
-class TestMkmf
- class TestInstall < TestMkmf
- def test_install_dirs
- Dir.mktmpdir do |dir|
- File.write(dir+"/extconf.rb", "require 'mkmf'; create_makefile('test')")
- all_assertions do |a|
+class TestMkmfInstall < TestMkmf
+ def test_install_dirs
+ Dir.mktmpdir do |dir|
+ File.write(dir+"/extconf.rb", "require 'mkmf'; create_makefile('test')")
+ all_assertions do |a|
+ a.foreach(
+ ["site"],
+ ["vendor", "--vendor"],
+ ) do |dest, *options|
+ assert_ruby_status(["-C", dir, "extconf.rb", *options])
+ mf = File.read(dir+"/Makefile")
a.foreach(
- ["site"],
- ["vendor", "--vendor"],
- ) do |dest, *options|
- assert_ruby_status(["-C", dir, "extconf.rb", *options])
- mf = File.read(dir+"/Makefile")
- a.foreach(
- ["RUBYCOMMONDIR", "$(#{dest}dir)$(target_prefix)"],
- ["RUBYLIBDIR", "$(#{dest}libdir)$(target_prefix)"],
- ["RUBYARCHDIR", "$(#{dest}archdir)$(target_prefix)"],
- ["HDRDIR", "$(#{dest}hdrdir)$(target_prefix)"],
- ["ARCHHDRDIR", "$(#{dest}archhdrdir)$(target_prefix)"],
- ) do |(var, path)|
- assert_equal path, mf[/^#{var}\s*=\s*(.*)$/, 1]
- end
+ ["RUBYCOMMONDIR", "$(#{dest}dir)$(target_prefix)"],
+ ["RUBYLIBDIR", "$(#{dest}libdir)$(target_prefix)"],
+ ["RUBYARCHDIR", "$(#{dest}archdir)$(target_prefix)"],
+ ["HDRDIR", "$(#{dest}hdrdir)$(target_prefix)"],
+ ["ARCHHDRDIR", "$(#{dest}archhdrdir)$(target_prefix)"],
+ ) do |(var, path)|
+ assert_equal path, mf[/^#{var}\s*=\s*(.*)$/, 1]
end
end
end
diff --git a/test/mkmf/test_libs.rb b/test/mkmf/test_libs.rb
index 9c5e1d29fb..2f84d024e2 100644
--- a/test/mkmf/test_libs.rb
+++ b/test/mkmf/test_libs.rb
@@ -1,94 +1,92 @@
# frozen_string_literal: false
require_relative 'base'
-class TestMkmf
- class TestLibs < TestMkmf
- def test_split_libs
- assert_equal(%w[-lfoo -lbar], split_libs("-lfoo -lbar"))
- end
+class TestMkmfLibs < TestMkmf
+ def test_split_libs
+ assert_equal(%w[-lfoo -lbar], split_libs("-lfoo -lbar"))
+ end
- def test_split_libs_macos
- assert_equal(%w[-ObjC -framework\ Ruby], split_libs("-ObjC -framework Ruby"), 'Bug #6987')
- end if /darwin/ =~ RUBY_PLATFORM
+ def test_split_libs_macos
+ assert_equal(%w[-ObjC -framework\ Ruby], split_libs("-ObjC -framework Ruby"), 'Bug #6987')
+ end if /darwin/ =~ RUBY_PLATFORM
- def test_split_libs_windows
- assert_equal(%w[zdll.lib libffi.lib], split_libs("zdll.lib libffi.lib"))
- end if /mswin/ =~ RUBY_PLATFORM
+ def test_split_libs_windows
+ assert_equal(%w[zdll.lib libffi.lib], split_libs("zdll.lib libffi.lib"))
+ end if /mswin/ =~ RUBY_PLATFORM
- def assert_in_order(array, x, y, mesg = nil)
- mesg = "#{x} must proceed to #{y}#{': ' if mesg}#{mesg}"
- assert_operator(array.index(x), :<, array.rindex(y), mesg)
- end
+ def assert_in_order(array, x, y, mesg = nil)
+ mesg = "#{x} must proceed to #{y}#{': ' if mesg}#{mesg}"
+ assert_operator(array.index(x), :<, array.rindex(y), mesg)
+ end
- def test_merge_simple
- bug = '[ruby-dev:21765]'
- assert_equal([], merge_libs(%w[]))
- assert_equal(%w[a b], merge_libs(%w[a], %w[b]))
- array = merge_libs(%w[a c], %w[b])
- assert_in_order(array, "a", "c", bug)
- end
+ def test_merge_simple
+ bug = '[ruby-dev:21765]'
+ assert_equal([], merge_libs(%w[]))
+ assert_equal(%w[a b], merge_libs(%w[a], %w[b]))
+ array = merge_libs(%w[a c], %w[b])
+ assert_in_order(array, "a", "c", bug)
+ end
- def test_merge_seq
- bug = '[ruby-dev:21765]'
- array = merge_libs(%w[a c d], %w[c b e])
- assert_in_order(array, "a", "c", bug)
- assert_in_order(array, "c", "d", bug)
- assert_in_order(array, "c", "b", bug)
- assert_in_order(array, "b", "e", bug)
- end
+ def test_merge_seq
+ bug = '[ruby-dev:21765]'
+ array = merge_libs(%w[a c d], %w[c b e])
+ assert_in_order(array, "a", "c", bug)
+ assert_in_order(array, "c", "d", bug)
+ assert_in_order(array, "c", "b", bug)
+ assert_in_order(array, "b", "e", bug)
+ end
- def test_merge_seq_pre
- bug = '[ruby-dev:21765]'
- array = merge_libs(%w[a c d], %w[b c d e])
- assert_in_order(array, "a", "c", bug)
- assert_in_order(array, "c", "d", bug)
- assert_in_order(array, "b", "c", bug)
- assert_in_order(array, "d", "e", bug)
- end
+ def test_merge_seq_pre
+ bug = '[ruby-dev:21765]'
+ array = merge_libs(%w[a c d], %w[b c d e])
+ assert_in_order(array, "a", "c", bug)
+ assert_in_order(array, "c", "d", bug)
+ assert_in_order(array, "b", "c", bug)
+ assert_in_order(array, "d", "e", bug)
+ end
- def test_merge_cyclic
- bug = '[ruby-dev:21765]'
- array = merge_libs(%w[a c d], %w[b c b])
- assert_in_order(array, "a", "c", bug)
- assert_in_order(array, "c", "d", bug)
- assert_in_order(array, "b", "c", bug)
- assert_in_order(array, "c", "b", bug)
- end
+ def test_merge_cyclic
+ bug = '[ruby-dev:21765]'
+ array = merge_libs(%w[a c d], %w[b c b])
+ assert_in_order(array, "a", "c", bug)
+ assert_in_order(array, "c", "d", bug)
+ assert_in_order(array, "b", "c", bug)
+ assert_in_order(array, "c", "b", bug)
+ end
- def test_merge_cyclic_2
- bug = '[ruby-dev:21765]'
- array = merge_libs(%w[a c a d], %w[b c b])
- assert_in_order(array, "a", "c", bug)
- assert_in_order(array, "c", "a", bug)
- assert_in_order(array, "c", "d", bug)
- assert_in_order(array, "a", "d", bug)
- assert_in_order(array, "b", "c", bug)
- assert_in_order(array, "c", "b", bug)
- end
+ def test_merge_cyclic_2
+ bug = '[ruby-dev:21765]'
+ array = merge_libs(%w[a c a d], %w[b c b])
+ assert_in_order(array, "a", "c", bug)
+ assert_in_order(array, "c", "a", bug)
+ assert_in_order(array, "c", "d", bug)
+ assert_in_order(array, "a", "d", bug)
+ assert_in_order(array, "b", "c", bug)
+ assert_in_order(array, "c", "b", bug)
+ end
- def test_merge_reversal
- bug = '[ruby-dev:22440]'
- array = merge_libs(%w[a b c], %w[c d a])
- assert_in_order(array, "a", "b" , bug)
- assert_in_order(array, "c", "d" , bug)
- ## assume that a and c have no dependency
- end
+ def test_merge_reversal
+ bug = '[ruby-dev:22440]'
+ array = merge_libs(%w[a b c], %w[c d a])
+ assert_in_order(array, "a", "b" , bug)
+ assert_in_order(array, "c", "d" , bug)
+ ## assume that a and c have no dependency
+ end
- def test_merge_reversal_followed
- bug7467 = '[ruby-core:50314] [Bug #7467]'
- array = nil
- assert_nothing_raised(bug7467) {
- array = merge_libs(%w[a b c d e f g h], %w[d c d e], [])
- }
- assert_in_order(array, "a", "b", bug7467)
- assert_in_order(array, "b", "c", bug7467)
- assert_in_order(array, "c", "d", bug7467)
- assert_in_order(array, "d", "e", bug7467)
- assert_in_order(array, "e", "f", bug7467)
- assert_in_order(array, "f", "g", bug7467)
- assert_in_order(array, "g", "h", bug7467)
- assert_in_order(array, "d", "c", bug7467)
- assert_in_order(array, "c", "e", bug7467)
- end
+ def test_merge_reversal_followed
+ bug7467 = '[ruby-core:50314] [Bug #7467]'
+ array = nil
+ assert_nothing_raised(bug7467) {
+ array = merge_libs(%w[a b c d e f g h], %w[d c d e], [])
+ }
+ assert_in_order(array, "a", "b", bug7467)
+ assert_in_order(array, "b", "c", bug7467)
+ assert_in_order(array, "c", "d", bug7467)
+ assert_in_order(array, "d", "e", bug7467)
+ assert_in_order(array, "e", "f", bug7467)
+ assert_in_order(array, "f", "g", bug7467)
+ assert_in_order(array, "g", "h", bug7467)
+ assert_in_order(array, "d", "c", bug7467)
+ assert_in_order(array, "c", "e", bug7467)
end
end if RUBY_ENGINE == "ruby"
diff --git a/test/mkmf/test_mkmf.rb b/test/mkmf/test_mkmf.rb
index adb86eca8d..55f9aa3b88 100644
--- a/test/mkmf/test_mkmf.rb
+++ b/test/mkmf/test_mkmf.rb
@@ -2,14 +2,12 @@
require 'test/unit'
require 'mkmf'
-class TestMkmf < Test::Unit::TestCase
- class TestGlobal < TestMkmf
- main = TOPLEVEL_BINDING.receiver
- MakeMakefile.public_instance_methods(false).each do |m|
- define_method(:"test_global_#{m}") do
- assert_respond_to(main, [m, true])
- assert_not_respond_to(main, [m, false])
- end
+class TestMkmfGlobal < Test::Unit::TestCase
+ main = TOPLEVEL_BINDING.receiver
+ MakeMakefile.public_instance_methods(false).each do |m|
+ define_method(:"test_global_#{m}") do
+ assert_respond_to(main, [m, true])
+ assert_not_respond_to(main, [m, false])
end
end
end
diff --git a/test/mkmf/test_pkg_config.rb b/test/mkmf/test_pkg_config.rb
new file mode 100644
index 0000000000..f6a960c7d9
--- /dev/null
+++ b/test/mkmf/test_pkg_config.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: false
+require_relative 'base'
+require 'shellwords'
+
+class TestMkmfPkgConfig < TestMkmf
+ PKG_CONFIG = config_string("PKG_CONFIG") {|path| find_executable0(path)}
+
+ def setup
+ super
+
+ if PKG_CONFIG
+ @fixtures_dir = File.join(Dir.pwd, "fixtures")
+ @fixtures_lib_dir = File.join(@fixtures_dir, "lib")
+ @fixtures_inc_dir = File.join(@fixtures_dir, "include")
+
+ FileUtils.mkdir(@fixtures_dir)
+ File.write("fixtures/test1.pc", <<~EOF)
+ libdir=#{@fixtures_lib_dir}
+ includedir=#{@fixtures_inc_dir}
+
+ Name: test1
+ Description: Test for mkmf pkg-config method
+ Version: 1.2.3
+ Libs: -L${libdir} -ltest1-public
+ Libs.private: -ltest1-private
+ Cflags: -I${includedir}/cflags-I --cflags-other
+ EOF
+
+ @pkg_config_path, ENV["PKG_CONFIG_PATH"] = ENV["PKG_CONFIG_PATH"], @fixtures_dir
+ end
+ end
+
+ def teardown
+ if PKG_CONFIG
+ ENV["PKG_CONFIG_PATH"] = @pkg_config_path
+ end
+
+ super
+ end
+
+ def test_pkgconfig_with_option_returns_nil_on_error
+ pend("skipping because pkg-config is not installed") unless PKG_CONFIG
+ assert_nil(pkg_config("package-does-not-exist", "exists"), MKMFLOG)
+ end
+
+ def test_pkgconfig_with_libs_option_returns_output
+ pend("skipping because pkg-config is not installed") unless PKG_CONFIG
+ expected = ["-L#{@fixtures_lib_dir}", "-ltest1-public"].sort
+ actual = pkg_config("test1", "libs").shellsplit.sort
+ assert_equal(expected, actual, MKMFLOG)
+ end
+
+ def test_pkgconfig_with_cflags_option_returns_output
+ pend("skipping because pkg-config is not installed") unless PKG_CONFIG
+ expected = ["--cflags-other", "-I#{@fixtures_inc_dir}/cflags-I"].sort
+ actual = pkg_config("test1", "cflags").shellsplit.sort
+ assert_equal(expected, actual, MKMFLOG)
+ end
+
+ def test_pkgconfig_with_multiple_options
+ pend("skipping because pkg-config is not installed") unless PKG_CONFIG
+ expected = ["-L#{@fixtures_lib_dir}", "-ltest1-public", "-ltest1-private"].sort
+ actual = pkg_config("test1", "libs", "static").shellsplit.sort
+ assert_equal(expected, actual, MKMFLOG)
+ end
+end
diff --git a/test/mkmf/test_signedness.rb b/test/mkmf/test_signedness.rb
index 589dcb56e8..a59e3548a2 100644
--- a/test/mkmf/test_signedness.rb
+++ b/test/mkmf/test_signedness.rb
@@ -1,30 +1,28 @@
# frozen_string_literal: false
require_relative 'base'
-class TestMkmf
- class TestSignedness < TestMkmf
- def test_typeof_builtin
- bug4144 = '[ruby-dev:42731]'
- [["", "-1"], ["signed ", "-1"], ["unsigned ", "+1"]].each do |signed, expect|
- %w[short int long].each do |type|
- assert_equal(expect.to_i, mkmf {check_signedness(signed+type)}, mkmflog(bug4144))
- end
+class TestMkmfSignedness < TestMkmf
+ def test_typeof_builtin
+ bug4144 = '[ruby-dev:42731]'
+ [["", "-1"], ["signed ", "-1"], ["unsigned ", "+1"]].each do |signed, expect|
+ %w[short int long].each do |type|
+ assert_equal(expect.to_i, mkmf {check_signedness(signed+type)}, mkmflog(bug4144))
end
end
+ end
- def test_typeof_typedef
- [["", "-1"], ["signed ", "-1"], ["unsigned ", "+1"]].each do |signed, expect|
- %w[short int long].each do |type|
- open("confdefs.h", "w") {|f|
- f.puts "typedef #{signed}#{type} test1_t;"
- }
- $defs.clear
- assert_equal(expect.to_i, mkmf {check_signedness("test1_t", "confdefs.h")}, MKMFLOG)
- assert_include($defs, "-DSIGNEDNESS_OF_TEST1_T=#{expect}")
- end
+ def test_typeof_typedef
+ [["", "-1"], ["signed ", "-1"], ["unsigned ", "+1"]].each do |signed, expect|
+ %w[short int long].each do |type|
+ open("confdefs.h", "w") {|f|
+ f.puts "typedef #{signed}#{type} test1_t;"
+ }
+ $defs.clear
+ assert_equal(expect.to_i, mkmf {check_signedness("test1_t", "confdefs.h")}, MKMFLOG)
+ assert_include($defs, "-DSIGNEDNESS_OF_TEST1_T=#{expect}")
end
- ensure
- File.unlink("confdefs.h")
end
+ ensure
+ File.unlink("confdefs.h")
end
end
diff --git a/test/mkmf/test_sizeof.rb b/test/mkmf/test_sizeof.rb
index 742c3d6454..6fb0a6a8f6 100644
--- a/test/mkmf/test_sizeof.rb
+++ b/test/mkmf/test_sizeof.rb
@@ -1,48 +1,46 @@
# frozen_string_literal: false
require_relative 'base'
-class TestMkmf
- class TestSizeof < TestMkmf
- def setup
- super
- @sizeof_short = config_value("SIZEOF_SHORT").to_i
- @sizeof_int = config_value("SIZEOF_INT").to_i
- @sizeof_long = config_value("SIZEOF_LONG").to_i
- @sizeof_long_long = config_value("SIZEOF_LONG_LONG").to_i
- @sizeof___int64 = config_value("SIZEOF___INT64").to_i
- end
+class TestMkmfSizeof < TestMkmf
+ def setup
+ super
+ @sizeof_short = config_value("SIZEOF_SHORT").to_i
+ @sizeof_int = config_value("SIZEOF_INT").to_i
+ @sizeof_long = config_value("SIZEOF_LONG").to_i
+ @sizeof_long_long = config_value("SIZEOF_LONG_LONG").to_i
+ @sizeof___int64 = config_value("SIZEOF___INT64").to_i
+ end
- def test_sizeof_builtin
- %w[char short int long float double void*].each do |type|
- assert_kind_of(Integer, mkmf {check_sizeof(type)}, MKMFLOG)
- end
- assert_operator(@sizeof_short, :<=, @sizeof_int)
- assert_operator(@sizeof_int, :<=, @sizeof_long)
- assert_operator(@sizeof_long, :<=, @sizeof_long_long) unless @sizeof_long_long.zero?
- assert_equal(8, @sizeof___int64) unless @sizeof___int64.zero?
+ def test_sizeof_builtin
+ %w[char short int long float double void*].each do |type|
+ assert_kind_of(Integer, mkmf {check_sizeof(type)}, MKMFLOG)
end
+ assert_operator(@sizeof_short, :<=, @sizeof_int)
+ assert_operator(@sizeof_int, :<=, @sizeof_long)
+ assert_operator(@sizeof_long, :<=, @sizeof_long_long) unless @sizeof_long_long.zero?
+ assert_equal(8, @sizeof___int64) unless @sizeof___int64.zero?
+ end
- def test_sizeof_struct
- open("confdefs.h", "w") {|f|
- f.puts "typedef struct {char x;} test1_t;"
- }
- assert_equal(1, mkmf {check_sizeof("test1_t", "confdefs.h")}, MKMFLOG)
+ def test_sizeof_struct
+ open("confdefs.h", "w") {|f|
+ f.puts "typedef struct {char x;} test1_t;"
+ }
+ assert_equal(1, mkmf {check_sizeof("test1_t", "confdefs.h")}, MKMFLOG)
- open("confdefs.h", "w") {|f|
- f.puts "typedef struct {char x, y;} test1_t;"
- }
- assert_equal(2, mkmf {check_sizeof("test1_t", "confdefs.h")}, MKMFLOG)
+ open("confdefs.h", "w") {|f|
+ f.puts "typedef struct {char x, y;} test1_t;"
+ }
+ assert_equal(2, mkmf {check_sizeof("test1_t", "confdefs.h")}, MKMFLOG)
- open("confdefs.h", "w") {|f|
- f.puts "typedef struct {int x;} test1_t;"
- }
- assert_equal(@sizeof_int, mkmf {check_sizeof("test1_t", "confdefs.h")}, MKMFLOG)
- open("confdefs.h", "w") {|f|
- f.puts "typedef struct {int x, y;} test1_t;"
- }
- assert_equal(2 * @sizeof_int, mkmf {check_sizeof("test1_t", "confdefs.h")}, MKMFLOG)
- ensure
- File.unlink("confdefs.h")
- end
+ open("confdefs.h", "w") {|f|
+ f.puts "typedef struct {int x;} test1_t;"
+ }
+ assert_equal(@sizeof_int, mkmf {check_sizeof("test1_t", "confdefs.h")}, MKMFLOG)
+ open("confdefs.h", "w") {|f|
+ f.puts "typedef struct {int x, y;} test1_t;"
+ }
+ assert_equal(2 * @sizeof_int, mkmf {check_sizeof("test1_t", "confdefs.h")}, MKMFLOG)
+ ensure
+ File.unlink("confdefs.h")
end
end
diff --git a/test/monitor/test_monitor.rb b/test/monitor/test_monitor.rb
index 8ff6d006df..4c55afca6c 100644
--- a/test/monitor/test_monitor.rb
+++ b/test/monitor/test_monitor.rb
@@ -300,6 +300,8 @@ class TestMonitor < Test::Unit::TestCase
result4 = cond.wait
assert_equal(true, result4)
assert_equal("bar", c)
+ ensure
+ queue3.enq(nil)
end
end
assert_join_threads([th, th2])
diff --git a/test/net/fixtures/Makefile b/test/net/fixtures/Makefile
index b2bc9c7368..88c232e3b6 100644
--- a/test/net/fixtures/Makefile
+++ b/test/net/fixtures/Makefile
@@ -5,11 +5,11 @@ regen_certs:
make server.crt
cacert.pem: server.key
- openssl req -new -x509 -days 1825 -key server.key -out cacert.pem -text -subj "/C=JP/ST=Shimane/L=Matz-e city/O=Ruby Core Team/CN=Ruby Test CA/emailAddress=security@ruby-lang.org"
+ openssl req -new -x509 -days 3650 -key server.key -out cacert.pem -subj "/C=JP/ST=Shimane/L=Matz-e city/O=Ruby Core Team/CN=Ruby Test CA/emailAddress=security@ruby-lang.org"
server.csr:
- openssl req -new -key server.key -out server.csr -text -subj "/C=JP/ST=Shimane/O=Ruby Core Team/OU=Ruby Test/CN=localhost"
+ openssl req -new -key server.key -out server.csr -subj "/C=JP/ST=Shimane/O=Ruby Core Team/OU=Ruby Test/CN=localhost"
server.crt: server.csr cacert.pem
- openssl x509 -days 1825 -CA cacert.pem -CAkey server.key -set_serial 00 -in server.csr -req -text -out server.crt
+ openssl x509 -days 3650 -CA cacert.pem -CAkey server.key -set_serial 00 -in server.csr -req -out server.crt
rm server.csr
diff --git a/test/net/fixtures/cacert.pem b/test/net/fixtures/cacert.pem
index f623bd62ed..24c83f1c65 100644
--- a/test/net/fixtures/cacert.pem
+++ b/test/net/fixtures/cacert.pem
@@ -1,24 +1,24 @@
-----BEGIN CERTIFICATE-----
-MIID7TCCAtWgAwIBAgIJAIltvxrFAuSnMA0GCSqGSIb3DQEBCwUAMIGMMQswCQYD
-VQQGEwJKUDEQMA4GA1UECAwHU2hpbWFuZTEUMBIGA1UEBwwLTWF0ei1lIGNpdHkx
-FzAVBgNVBAoMDlJ1YnkgQ29yZSBUZWFtMRUwEwYDVQQDDAxSdWJ5IFRlc3QgQ0Ex
-JTAjBgkqhkiG9w0BCQEWFnNlY3VyaXR5QHJ1YnktbGFuZy5vcmcwHhcNMTkwMTAy
-MDI1ODI4WhcNMjQwMTAxMDI1ODI4WjCBjDELMAkGA1UEBhMCSlAxEDAOBgNVBAgM
-B1NoaW1hbmUxFDASBgNVBAcMC01hdHotZSBjaXR5MRcwFQYDVQQKDA5SdWJ5IENv
-cmUgVGVhbTEVMBMGA1UEAwwMUnVieSBUZXN0IENBMSUwIwYJKoZIhvcNAQkBFhZz
-ZWN1cml0eUBydWJ5LWxhbmcub3JnMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
-CgKCAQEAznlbjRVhz1NlutHVrhcGnK8W0qug2ujKXv1njSC4U6nJF6py7I9EeehV
-SaKePyv+I9z3K1LnfUHOtUbdwdKC77yN66A6q2aqzu5q09/NSykcZGOIF0GuItYI
-3nvW3IqBddff2ffsyR+9pBjfb5AIPP08WowF9q4s1eGULwZc4w2B8PFhtxYANd7d
-BvGLXFlcufv9tDtzyRi4t7eqxCRJkZQIZNZ6DHHIJrNxejOILfHLarI12yk8VK6L
-2LG4WgGqyeePiRyd1o1MbuiAFYqAwpXNUbRKg5NaZGwBHZk8UZ+uFKt1QMBURO5R
-WFy1c349jbWszTqFyL4Lnbg9HhAowQIDAQABo1AwTjAdBgNVHQ4EFgQU9tEiKdU9
-I9derQyc5nWPnc34nVMwHwYDVR0jBBgwFoAU9tEiKdU9I9derQyc5nWPnc34nVMw
-DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAxj7F/u3C3fgq24N7hGRA
-of7ClFQxGmo/IGT0AISzW3HiVYiFaikKhbO1NwD9aBpD8Zwe62sCqMh8jGV/b0+q
-aOORnWYNy2R6r9FkASAglmdF6xn3bhgGD5ls4pCvcG9FynGnGc24g6MrjFNrBYUS
-2iIZsg36i0IJswo/Dy6HLphCms2BMCD3DeWtfjePUiTmQHJo6HsQIKP/u4N4Fvee
-uMBInei2M4VU74fLXbmKl1F9AEX7JDP3BKSZG19Ch5pnUo4uXM1uNTGsi07P4Y0s
-K44+SKBC0bYEFbDK0eQWMrX3kIhkPxyIWhxdq9/NqPYjShuSEAhA6CSpmRg0pqc+
-mA==
+MIID+zCCAuOgAwIBAgIUGMvHl3EhtKPKcgc3NQSAYfFuC+8wDQYJKoZIhvcNAQEL
+BQAwgYwxCzAJBgNVBAYTAkpQMRAwDgYDVQQIDAdTaGltYW5lMRQwEgYDVQQHDAtN
+YXR6LWUgY2l0eTEXMBUGA1UECgwOUnVieSBDb3JlIFRlYW0xFTATBgNVBAMMDFJ1
+YnkgVGVzdCBDQTElMCMGCSqGSIb3DQEJARYWc2VjdXJpdHlAcnVieS1sYW5nLm9y
+ZzAeFw0yNDAxMDExMTQ3MjNaFw0zMzEyMjkxMTQ3MjNaMIGMMQswCQYDVQQGEwJK
+UDEQMA4GA1UECAwHU2hpbWFuZTEUMBIGA1UEBwwLTWF0ei1lIGNpdHkxFzAVBgNV
+BAoMDlJ1YnkgQ29yZSBUZWFtMRUwEwYDVQQDDAxSdWJ5IFRlc3QgQ0ExJTAjBgkq
+hkiG9w0BCQEWFnNlY3VyaXR5QHJ1YnktbGFuZy5vcmcwggEiMA0GCSqGSIb3DQEB
+AQUAA4IBDwAwggEKAoIBAQCw+egZQ6eumJKq3hfKfED4dE/tL4FI5sjqont9ABVI
++1GSqyi1bFBgsRjM0THllIdMbKmJtWwnKW8J+5OgNN8y6Xxv8JmM/Y5vQt2lis0f
+qXmG8UTz0VTWdlAXXmhUs6lSADvAaIe4RVrCsZ97L3ZQTryY7JRVcbB4khUN3Gp0
+yg+801SXzoFTTa+UGIRLE66jH51aa5VXu99hnv1OiH8tQrjdi8mH6uG/icq4XuIe
+NWMF32wHqIOOPvQcWV3M5D2vxJEj702Ku6k9OQXkAo17qRSEonWW4HtLbtmS8He1
+JNPc/n3dVUm+fM6NoDXPoLP7j55G9zKyqGtGAWXAj1MTAgMBAAGjUzBRMB0GA1Ud
+DgQWBBSJGVleDvFp9cu9R+E0/OKYzGkwkTAfBgNVHSMEGDAWgBSJGVleDvFp9cu9
+R+E0/OKYzGkwkTAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBl
+8GLB8skAWlkSw/FwbUmEV3zyqu+p7PNP5YIYoZs0D74e7yVulGQ6PKMZH5hrZmHo
+orFSQU+VUUirG8nDGj7Rzce8WeWBxsaDGC8CE2dq6nC6LuUwtbdMnBrH0LRWAz48
+jGFF3jHtVz8VsGfoZTZCjukWqNXvU6hETT9GsfU+PZqbqcTVRPH52+XgYayKdIbD
+r97RM4X3+aXBHcUW0b76eyyi65RR/Xtvn8ioZt2AdX7T2tZzJyXJN3Hupp77s6Ui
+AZR35SToHCZeTZD12YBvLBdaTPLZN7O/Q/aAO9ZiJaZ7SbFOjz813B2hxXab4Fob
+2uJX6eMWTVxYK5D4M9lm
-----END CERTIFICATE-----
diff --git a/test/net/fixtures/server.crt b/test/net/fixtures/server.crt
index 5ca78a6d14..5d2923795d 100644
--- a/test/net/fixtures/server.crt
+++ b/test/net/fixtures/server.crt
@@ -1,82 +1,21 @@
-Certificate:
- Data:
- Version: 3 (0x2)
- Serial Number: 2 (0x2)
- Signature Algorithm: sha256WithRSAEncryption
- Issuer: C=JP, ST=Shimane, L=Matz-e city, O=Ruby Core Team, CN=Ruby Test CA/emailAddress=security@ruby-lang.org
- Validity
- Not Before: Jan 2 03:27:13 2019 GMT
- Not After : Jan 1 03:27:13 2024 GMT
- Subject: C=JP, ST=Shimane, O=Ruby Core Team, OU=Ruby Test, CN=localhost
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- Public-Key: (2048 bit)
- Modulus:
- 00:e8:da:9c:01:2e:2b:10:ec:49:cd:5e:07:13:07:
- 9c:70:9e:c6:74:bc:13:c2:e1:6f:c6:82:fd:e3:48:
- e0:2c:a5:68:c7:9e:42:de:60:54:65:e6:6a:14:57:
- 7a:30:d0:cc:b5:b6:d9:c3:d2:df:c9:25:97:54:67:
- cf:f6:be:5e:cb:8b:ee:03:c5:e1:e2:f9:e7:f7:d1:
- 0c:47:f0:b8:da:33:5a:ad:41:ad:e7:b5:a2:7b:b7:
- bf:30:da:60:f8:e3:54:a2:bc:3a:fd:1b:74:d9:dc:
- 74:42:e9:29:be:df:ac:b4:4f:eb:32:f4:06:f1:e1:
- 8c:4b:a8:8b:fb:29:e7:b1:bf:1d:01:ee:73:0f:f9:
- 40:dc:d5:15:79:d9:c6:73:d0:c0:dd:cb:e4:da:19:
- 47:80:c6:14:04:72:fd:9a:7c:8f:11:82:76:49:04:
- 79:cc:f2:5c:31:22:95:13:3e:5d:40:a6:4d:e0:a3:
- 02:26:7d:52:3b:bb:ed:65:a1:0f:ed:6b:b0:3c:d4:
- de:61:15:5e:d3:dd:68:09:9f:4a:57:a5:c2:a9:6d:
- 86:92:c5:f4:a4:d4:b7:13:3b:52:63:24:05:e2:cc:
- e3:8a:3c:d4:35:34:2b:10:bb:58:72:e7:e1:8d:1d:
- 74:8c:61:16:20:3d:d0:1c:4e:8f:6e:fd:fe:64:10:
- 4f:41
- Exponent: 65537 (0x10001)
- X509v3 extensions:
- X509v3 Basic Constraints:
- CA:FALSE
- Netscape Comment:
- OpenSSL Generated Certificate
- X509v3 Subject Key Identifier:
- ED:28:C2:7E:AB:4B:C8:E8:FE:55:6D:66:95:31:1C:2D:60:F9:02:36
- X509v3 Authority Key Identifier:
- keyid:F6:D1:22:29:D5:3D:23:D7:5E:AD:0C:9C:E6:75:8F:9D:CD:F8:9D:53
-
- Signature Algorithm: sha256WithRSAEncryption
- 1d:b8:c5:8b:72:41:20:65:ad:27:6f:15:63:06:26:12:8d:9c:
- ad:ca:f4:db:97:b4:90:cb:ff:35:94:bb:2a:a7:a1:ab:1e:35:
- 2d:a5:3f:c9:24:b0:1a:58:89:75:3e:81:0a:2c:4f:98:f9:51:
- fb:c0:a3:09:d0:0a:9b:e7:a2:b7:c3:60:40:c8:f4:6d:b2:6a:
- 56:12:17:4c:00:24:31:df:9c:60:ae:b1:68:54:a9:e6:b5:4a:
- 04:e6:92:05:86:d9:5a:dc:96:30:a5:58:de:14:99:0f:e5:15:
- 89:3e:9b:eb:80:e3:bd:83:c3:ea:33:35:4b:3e:2f:d3:0d:64:
- 93:67:7f:8d:f5:3f:0c:27:bc:37:5a:cc:d6:47:16:af:5a:62:
- d2:da:51:f8:74:06:6b:24:ad:28:68:08:98:37:7d:ed:0e:ab:
- 1e:82:61:05:d0:ba:75:a0:ab:21:b0:9a:fd:2b:54:86:1d:0d:
- 1f:c2:d4:77:1f:72:26:5e:ad:8a:9f:09:36:6d:44:be:74:c2:
- 5a:3e:ff:5c:9d:75:d6:38:7b:c5:39:f9:44:6e:a1:d1:8e:ff:
- 63:db:c4:bb:c6:91:92:ca:5c:60:9b:1d:eb:0a:de:08:ee:bf:
- da:76:03:65:62:29:8b:f8:7f:c7:86:73:1e:f6:1f:2d:89:69:
- fd:be:bd:6e
-----BEGIN CERTIFICATE-----
-MIID4zCCAsugAwIBAgIBAjANBgkqhkiG9w0BAQsFADCBjDELMAkGA1UEBhMCSlAx
-EDAOBgNVBAgMB1NoaW1hbmUxFDASBgNVBAcMC01hdHotZSBjaXR5MRcwFQYDVQQK
-DA5SdWJ5IENvcmUgVGVhbTEVMBMGA1UEAwwMUnVieSBUZXN0IENBMSUwIwYJKoZI
-hvcNAQkBFhZzZWN1cml0eUBydWJ5LWxhbmcub3JnMB4XDTE5MDEwMjAzMjcxM1oX
-DTI0MDEwMTAzMjcxM1owYDELMAkGA1UEBhMCSlAxEDAOBgNVBAgMB1NoaW1hbmUx
-FzAVBgNVBAoMDlJ1YnkgQ29yZSBUZWFtMRIwEAYDVQQLDAlSdWJ5IFRlc3QxEjAQ
-BgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
-AOjanAEuKxDsSc1eBxMHnHCexnS8E8Lhb8aC/eNI4CylaMeeQt5gVGXmahRXejDQ
-zLW22cPS38kll1Rnz/a+XsuL7gPF4eL55/fRDEfwuNozWq1Bree1onu3vzDaYPjj
-VKK8Ov0bdNncdELpKb7frLRP6zL0BvHhjEuoi/sp57G/HQHucw/5QNzVFXnZxnPQ
-wN3L5NoZR4DGFARy/Zp8jxGCdkkEeczyXDEilRM+XUCmTeCjAiZ9Uju77WWhD+1r
-sDzU3mEVXtPdaAmfSlelwqlthpLF9KTUtxM7UmMkBeLM44o81DU0KxC7WHLn4Y0d
-dIxhFiA90BxOj279/mQQT0ECAwEAAaN7MHkwCQYDVR0TBAIwADAsBglghkgBhvhC
-AQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFO0o
-wn6rS8jo/lVtZpUxHC1g+QI2MB8GA1UdIwQYMBaAFPbRIinVPSPXXq0MnOZ1j53N
-+J1TMA0GCSqGSIb3DQEBCwUAA4IBAQAduMWLckEgZa0nbxVjBiYSjZytyvTbl7SQ
-y/81lLsqp6GrHjUtpT/JJLAaWIl1PoEKLE+Y+VH7wKMJ0Aqb56K3w2BAyPRtsmpW
-EhdMACQx35xgrrFoVKnmtUoE5pIFhtla3JYwpVjeFJkP5RWJPpvrgOO9g8PqMzVL
-Pi/TDWSTZ3+N9T8MJ7w3WszWRxavWmLS2lH4dAZrJK0oaAiYN33tDqsegmEF0Lp1
-oKshsJr9K1SGHQ0fwtR3H3ImXq2Knwk2bUS+dMJaPv9cnXXWOHvFOflEbqHRjv9j
-28S7xpGSylxgmx3rCt4I7r/adgNlYimL+H/HhnMe9h8tiWn9vr1u
+MIIDYTCCAkkCAQAwDQYJKoZIhvcNAQELBQAwgYwxCzAJBgNVBAYTAkpQMRAwDgYD
+VQQIDAdTaGltYW5lMRQwEgYDVQQHDAtNYXR6LWUgY2l0eTEXMBUGA1UECgwOUnVi
+eSBDb3JlIFRlYW0xFTATBgNVBAMMDFJ1YnkgVGVzdCBDQTElMCMGCSqGSIb3DQEJ
+ARYWc2VjdXJpdHlAcnVieS1sYW5nLm9yZzAeFw0yNDAxMDExMTQ3MjNaFw0zMzEy
+MjkxMTQ3MjNaMGAxCzAJBgNVBAYTAkpQMRAwDgYDVQQIDAdTaGltYW5lMRcwFQYD
+VQQKDA5SdWJ5IENvcmUgVGVhbTESMBAGA1UECwwJUnVieSBUZXN0MRIwEAYDVQQD
+DAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCw+egZ
+Q6eumJKq3hfKfED4dE/tL4FI5sjqont9ABVI+1GSqyi1bFBgsRjM0THllIdMbKmJ
+tWwnKW8J+5OgNN8y6Xxv8JmM/Y5vQt2lis0fqXmG8UTz0VTWdlAXXmhUs6lSADvA
+aIe4RVrCsZ97L3ZQTryY7JRVcbB4khUN3Gp0yg+801SXzoFTTa+UGIRLE66jH51a
+a5VXu99hnv1OiH8tQrjdi8mH6uG/icq4XuIeNWMF32wHqIOOPvQcWV3M5D2vxJEj
+702Ku6k9OQXkAo17qRSEonWW4HtLbtmS8He1JNPc/n3dVUm+fM6NoDXPoLP7j55G
+9zKyqGtGAWXAj1MTAgMBAAEwDQYJKoZIhvcNAQELBQADggEBACtGNdj5TEtnJBYp
+M+LhBeU3oNteldfycEm993gJp6ghWZFg23oX8fVmyEeJr/3Ca9bAgDqg0t9a0npN
+oWKEY6wVKqcHgu3gSvThF5c9KhGbeDDmlTSVVNQmXWX0K2d4lS2cwZHH8mCm2mrY
+PDqlEkSc7k4qSiqigdS8i80Yk+lDXWsm8CjsiC93qaRM7DnS0WPQR0c16S95oM6G
+VklFKUSDAuFjw9aVWA/nahOucjn0w5fVW6lyIlkBslC1ChlaDgJmvhz+Ol3iMsE0
+kAmFNu2KKPVrpMWaBID49QwQTDyhetNLaVVFM88iUdA9JDoVMEuP1mm39JqyzHTu
+uBrdP4Q=
-----END CERTIFICATE-----
diff --git a/test/net/fixtures/server.key b/test/net/fixtures/server.key
index 7f2380e71e..6a83d5bcf4 100644
--- a/test/net/fixtures/server.key
+++ b/test/net/fixtures/server.key
@@ -1,28 +1,27 @@
------BEGIN PRIVATE KEY-----
-MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDo2pwBLisQ7EnN
-XgcTB5xwnsZ0vBPC4W/Ggv3jSOAspWjHnkLeYFRl5moUV3ow0My1ttnD0t/JJZdU
-Z8/2vl7Li+4DxeHi+ef30QxH8LjaM1qtQa3ntaJ7t78w2mD441SivDr9G3TZ3HRC
-6Sm+36y0T+sy9Abx4YxLqIv7Keexvx0B7nMP+UDc1RV52cZz0MDdy+TaGUeAxhQE
-cv2afI8RgnZJBHnM8lwxIpUTPl1Apk3gowImfVI7u+1loQ/ta7A81N5hFV7T3WgJ
-n0pXpcKpbYaSxfSk1LcTO1JjJAXizOOKPNQ1NCsQu1hy5+GNHXSMYRYgPdAcTo9u
-/f5kEE9BAgMBAAECggEBAOHkwhc7DLh8IhTDNSW26oMu5OP2WU1jmiYAigDmf+OQ
-DBgrZj+JQBci8qINQxL8XLukSZn5hvQCLc7Kbyu1/wyEEUFDxSGGwwzclodr9kho
-LX2LDASPZrOSzD2+fPi2wTKmXKuS6Uc44OjQfZkYMNkz9r4Vkm8xGgOD3VipjIYX
-QXlhhdqkXZcNABsihCV52GKkDFSVm8jv95YJc5xhoYCy/3a4/qPdF0aT2R7oYUej
-hKrxVDskyooe8Zg/JTydZNV5GQEDmW01/K3r6XGT26oPi1AqMU1gtv/jkW56CRQQ
-1got8smnqM+AV7Slf9R6DauIPdQJ2S8wsr/o8ISBsOECgYEA9YrqEP2gAYSGFXRt
-liw0WI2Ant8BqXS6yvq1jLo/qWhLw/ph4Di73OQ2mpycVTpgfGr2wFPQR1XJ+0Fd
-U+Ir/C3Q7FK4VIGHK7B0zNvZr5tEjlFfeRezo2JMVw5YWeSagIFcSwK+KqCTH9qc
-pw/Eb8nB/4XNcpTZu7Fg0Wc+ooUCgYEA8sVaicn1Wxkpb45a4qfrA6wOr5xdJ4cC
-A5qs7vjX2OdPIQOmoQhdI7bCWFXZzF33wA4YCws6j5wRaySLIJqdms8Gl9QnODy1
-ZlA5gwKToBC/jqPmWAXSKb8EH7cHilaxU9OKnQ7CfwlGLHqjMtjrhR7KHlt3CVRs
-oRmvsjZVXI0CgYAmPedslAO6mMhFSSfULrhMXmV82OCqYrrA6EEkVNGbcdnzAOkD
-gfKIWabDd8bFY10po4Mguy0CHzNhBXIioWQWV5BlbhC1YKMLw+S9DzSdLAKGY9gJ
-xQ4+UQ3wtRQ/k+IYR413RUsW2oFvgZ3KSyNeAb9MK6uuv84VdG/OzVSs/QKBgQDn
-kap//l2EbObiWyaERunckdVcW0lcN+KK75J/TGwPoOwQsLvTpPe65kxRGGrtDsEQ
-uCDk/+v3KkZPLgdrrTAih9FhJ+PVN8tMcb+6IM4SA4fFFr/UPJEwct0LJ3oQ0grJ
-y+HPWFHb/Uurh7t99/4H98uR02sjQh1wOeEmm78mzQKBgQDm+LzGH0se6CXQ6cdZ
-g1JRZeXkDEsrW3hfAsW62xJQmXcWxBoblP9OamMY+A06rM5og3JbDk5Zm6JsOaA8
-wS2gw4ilp46jors4eQey8ux7kB9LzdBoDBBElnsbjLO8oBNZlVcYXg+6BOl/CUi7
-2whRF0FEjKA8ehrNhAq+VFfFNw==
------END PRIVATE KEY-----
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEAsPnoGUOnrpiSqt4XynxA+HRP7S+BSObI6qJ7fQAVSPtRkqso
+tWxQYLEYzNEx5ZSHTGypibVsJylvCfuToDTfMul8b/CZjP2Ob0LdpYrNH6l5hvFE
+89FU1nZQF15oVLOpUgA7wGiHuEVawrGfey92UE68mOyUVXGweJIVDdxqdMoPvNNU
+l86BU02vlBiESxOuox+dWmuVV7vfYZ79Toh/LUK43YvJh+rhv4nKuF7iHjVjBd9s
+B6iDjj70HFldzOQ9r8SRI+9NirupPTkF5AKNe6kUhKJ1luB7S27ZkvB3tSTT3P59
+3VVJvnzOjaA1z6Cz+4+eRvcysqhrRgFlwI9TEwIDAQABAoIBAEEYiyDP29vCzx/+
+dS3LqnI5BjUuJhXUnc6AWX/PCgVAO+8A+gZRgvct7PtZb0sM6P9ZcLrweomlGezI
+FrL0/6xQaa8bBr/ve/a8155OgcjFo6fZEw3Dz7ra5fbSiPmu4/b/kvrg+Br1l77J
+aun6uUAs1f5B9wW+vbR7tzbT/mxaUeDiBzKpe15GwcvbJtdIVMa2YErtRjc1/5B2
+BGVXyvlJv0SIlcIEMsHgnAFOp1ZgQ08aDzvilLq8XVMOahAhP1O2A3X8hKdXPyrx
+IVWE9bS9ptTo+eF6eNl+d7htpKGEZHUxinoQpWEBTv+iOoHsVunkEJ3vjLP3lyI/
+fY0NQ1ECgYEA3RBXAjgvIys2gfU3keImF8e/TprLge1I2vbWmV2j6rZCg5r/AS0u
+pii5CvJ5/T5vfJPNgPBy8B/yRDs+6PJO1GmnlhOkG9JAIPkv0RBZvR0PMBtbp6nT
+Y3yo1lwamBVBfY6rc0sLTzosZh2aGoLzrHNMQFMGaauORzBFpY5lU50CgYEAzPHl
+u5DI6Xgep1vr8QvCUuEesCOgJg8Yh1UqVoY/SmQh6MYAv1I9bLGwrb3WW/7kqIoD
+fj0aQV5buVZI2loMomtU9KY5SFIsPV+JuUpy7/+VE01ZQM5FdY8wiYCQiVZYju9X
+Wz5LxMNoz+gT7pwlLCsC4N+R8aoBk404aF1gum8CgYAJ7VTq7Zj4TFV7Soa/T1eE
+k9y8a+kdoYk3BASpCHJ29M5R2KEA7YV9wrBklHTz8VzSTFTbKHEQ5W5csAhoL5Fo
+qoHzFFi3Qx7MHESQb9qHyolHEMNx6QdsHUn7rlEnaTTyrXh3ifQtD6C0yTmFXUIS
+CW9wKApOrnyKJ9nI0HcuZQKBgQCMtoV6e9VGX4AEfpuHvAAnMYQFgeBiYTkBKltQ
+XwozhH63uMMomUmtSG87Sz1TmrXadjAhy8gsG6I0pWaN7QgBuFnzQ/HOkwTm+qKw
+AsrZt4zeXNwsH7QXHEJCFnCmqw9QzEoZTrNtHJHpNboBuVnYcoueZEJrP8OnUG3r
+UjmopwKBgAqB2KYYMUqAOvYcBnEfLDmyZv9BTVNHbR2lKkMYqv5LlvDaBxVfilE0
+2riO4p6BaAdvzXjKeRrGNEKoHNBpOSfYCOM16NjL8hIZB1CaV3WbT5oY+jp7Mzd5
+7d56RZOE+ERK2uz/7JX9VSsM/LbH9pJibd4e8mikDS9ntciqOH/3
+-----END RSA PRIVATE KEY-----
diff --git a/test/net/http/test_http.rb b/test/net/http/test_http.rb
index c859021956..a49cc87e8d 100644
--- a/test/net/http/test_http.rb
+++ b/test/net/http/test_http.rb
@@ -126,10 +126,10 @@ class TestNetHTTP < Test::Unit::TestCase
def test_proxy_address_no_proxy
TestNetHTTPUtils.clean_http_proxy_env do
- http = Net::HTTP.new 'hostname.example', nil, 'proxy.example', nil, nil, nil, 'example'
+ http = Net::HTTP.new 'hostname.example', nil, 'proxy.com', nil, nil, nil, 'example'
assert_nil http.proxy_address
- http = Net::HTTP.new '10.224.1.1', nil, 'proxy.example', nil, nil, nil, 'example,10.224.0.0/22'
+ http = Net::HTTP.new '10.224.1.1', nil, 'proxy.com', nil, nil, nil, 'example,10.224.0.0/22'
assert_nil http.proxy_address
end
end
@@ -178,13 +178,8 @@ class TestNetHTTP < Test::Unit::TestCase
http = Net::HTTP.new 'hostname.example'
assert_equal true, http.proxy?
- if Net::HTTP::ENVIRONMENT_VARIABLE_IS_MULTIUSER_SAFE
- assert_equal 'foo', http.proxy_user
- assert_equal 'bar', http.proxy_pass
- else
- assert_nil http.proxy_user
- assert_nil http.proxy_pass
- end
+ assert_equal 'foo', http.proxy_user
+ assert_equal 'bar', http.proxy_pass
end
end
@@ -195,13 +190,8 @@ class TestNetHTTP < Test::Unit::TestCase
http = Net::HTTP.new 'hostname.example'
assert_equal true, http.proxy?
- if Net::HTTP::ENVIRONMENT_VARIABLE_IS_MULTIUSER_SAFE
- assert_equal "Y\\X", http.proxy_user
- assert_equal "R%S] ?X", http.proxy_pass
- else
- assert_nil http.proxy_user
- assert_nil http.proxy_pass
- end
+ assert_equal "Y\\X", http.proxy_user
+ assert_equal "R%S] ?X", http.proxy_pass
end
end
@@ -264,6 +254,18 @@ class TestNetHTTP < Test::Unit::TestCase
end
end
+ def test_default_configuration
+ Net::HTTP.default_configuration = { open_timeout: 5 }
+ http = Net::HTTP.new 'hostname.example'
+ assert_equal 5, http.open_timeout
+ assert_equal 60, http.read_timeout
+
+ http.open_timeout = 10
+ assert_equal 10, http.open_timeout
+ ensure
+ Net::HTTP.default_configuration = nil
+ end
+
end
module TestNetHTTP_version_1_1_methods
@@ -452,7 +454,11 @@ module TestNetHTTP_version_1_1_methods
def test_post
start {|http|
_test_post__base http
+ }
+ start {|http|
_test_post__file http
+ }
+ start {|http|
_test_post__no_data http
}
end
@@ -639,10 +645,12 @@ module TestNetHTTP_version_1_2_methods
# _test_request__range http # WEBrick does not support Range: header.
_test_request__HEAD http
_test_request__POST http
- _test_request__stream_body http
_test_request__uri http
_test_request__uri_host http
}
+ start {|http|
+ _test_request__stream_body http
+ }
end
def _test_request__GET(http)
@@ -853,7 +861,13 @@ Content-Type: application/octet-stream
__EOM__
start {|http|
_test_set_form_urlencoded(http, data.reject{|k,v|!v.is_a?(String)})
+ }
+ start {|http|
+ @server.mount('/', lambda {|req, res| res.body = req.body })
_test_set_form_multipart(http, false, data, expected)
+ }
+ start {|http|
+ @server.mount('/', lambda {|req, res| res.body = req.body })
_test_set_form_multipart(http, true, data, expected)
}
}
@@ -897,6 +911,7 @@ __EOM__
expected.sub!(/<filename>/, filename)
expected.sub!(/<data>/, $test_net_http_data)
start {|http|
+ @server.mount('/', lambda {|req, res| res.body = req.body })
data.each{|k,v|v.rewind rescue nil}
req = Net::HTTP::Post.new('/')
req.set_form(data, 'multipart/form-data')
@@ -912,10 +927,11 @@ __EOM__
header)
assert_equal(expected, body)
- data.each{|k,v|v.rewind rescue nil}
- req['Transfer-Encoding'] = 'chunked'
- res = http.request req
- #assert_equal(expected, res.body)
+ # TODO: test with chunked
+ # data.each{|k,v|v.rewind rescue nil}
+ # req['Transfer-Encoding'] = 'chunked'
+ # res = http.request req
+ # assert_equal(expected, res.body)
}
}
end
@@ -994,7 +1010,7 @@ class TestNetHTTPContinue < Test::Unit::TestCase
end
def mount_proc(&block)
- @server.mount('/continue', WEBrick::HTTPServlet::ProcHandler.new(block.to_proc))
+ @server.mount('/continue', block.to_proc)
end
def test_expect_continue
@@ -1049,7 +1065,7 @@ class TestNetHTTPContinue < Test::Unit::TestCase
def test_expect_continue_error_before_body
@log_tester = nil
mount_proc {|req, res|
- raise WEBrick::HTTPStatus::Forbidden
+ raise TestNetHTTPUtils::Forbidden
}
start {|http|
uheader = {'content-type' => 'application/x-www-form-urlencoded', 'content-length' => '5', 'expect' => '100-continue'}
@@ -1094,7 +1110,7 @@ class TestNetHTTPSwitchingProtocols < Test::Unit::TestCase
end
def mount_proc(&block)
- @server.mount('/continue', WEBrick::HTTPServlet::ProcHandler.new(block.to_proc))
+ @server.mount('/continue', block.to_proc)
end
def test_info
@@ -1168,6 +1184,30 @@ class TestNetHTTPKeepAlive < Test::Unit::TestCase
}
end
+ def test_keep_alive_reset_on_new_connection
+ # Using debug log output on accepting connection:
+ #
+ # "[2021-04-29 20:36:46] DEBUG accept: 127.0.0.1:50674\n"
+ @log_tester = nil
+ @logger_level = :debug
+
+ start {|http|
+ res = http.get('/')
+ http.keep_alive_timeout = 1
+ assert_kind_of Net::HTTPResponse, res
+ assert_kind_of String, res.body
+ http.finish
+ assert_equal 1, @log.grep(/accept/i).size
+
+ sleep 1.5
+ http.start
+ res = http.get('/')
+ assert_kind_of Net::HTTPResponse, res
+ assert_kind_of String, res.body
+ assert_equal 2, @log.grep(/accept/i).size
+ }
+ end
+
class MockSocket
attr_reader :count
def initialize(success_after: nil)
@@ -1220,6 +1260,16 @@ class TestNetHTTPKeepAlive < Test::Unit::TestCase
}
end
+ def test_http_retry_failed_with_block
+ start {|http|
+ http.max_retries = 10
+ called = 0
+ assert_raise(Errno::ECONNRESET){ http.get('/'){called += 1; raise Errno::ECONNRESET} }
+ assert_equal 1, called
+ }
+ @log_tester = nil
+ end
+
def test_keep_alive_server_close
def @server.run(sock)
sock.close
@@ -1270,3 +1320,87 @@ class TestNetHTTPLocalBind < Test::Unit::TestCase
end
end
+class TestNetHTTPForceEncoding < Test::Unit::TestCase
+ CONFIG = {
+ 'host' => 'localhost',
+ 'proxy_host' => nil,
+ 'proxy_port' => nil,
+ }
+
+ include TestNetHTTPUtils
+
+ def fe_request(force_enc, content_type=nil)
+ @server.mount_proc('/fe') do |req, res|
+ res['Content-Type'] = content_type if content_type
+ res.body = "hello\u1234"
+ end
+
+ http = Net::HTTP.new(config('host'), config('port'))
+ http.local_host = Addrinfo.tcp(config('host'), config('port')).ip_address
+ assert_not_nil(http.local_host)
+ assert_nil(http.local_port)
+
+ http.response_body_encoding = force_enc
+ http.get('/fe')
+ end
+
+ def test_response_body_encoding_false
+ res = fe_request(false)
+ assert_equal("hello\u1234".b, res.body)
+ assert_equal(Encoding::ASCII_8BIT, res.body.encoding)
+ end
+
+ def test_response_body_encoding_true_without_content_type
+ res = fe_request(true)
+ assert_equal("hello\u1234".b, res.body)
+ assert_equal(Encoding::ASCII_8BIT, res.body.encoding)
+ end
+
+ def test_response_body_encoding_true_with_content_type
+ res = fe_request(true, 'text/html; charset=utf-8')
+ assert_equal("hello\u1234", res.body)
+ assert_equal(Encoding::UTF_8, res.body.encoding)
+ end
+
+ def test_response_body_encoding_string_without_content_type
+ res = fe_request('utf-8')
+ assert_equal("hello\u1234", res.body)
+ assert_equal(Encoding::UTF_8, res.body.encoding)
+ end
+
+ def test_response_body_encoding_encoding_without_content_type
+ res = fe_request(Encoding::UTF_8)
+ assert_equal("hello\u1234", res.body)
+ assert_equal(Encoding::UTF_8, res.body.encoding)
+ end
+end
+
+class TestNetHTTPPartialResponse < Test::Unit::TestCase
+ CONFIG = {
+ 'host' => '127.0.0.1',
+ 'proxy_host' => nil,
+ 'proxy_port' => nil,
+ }
+
+ include TestNetHTTPUtils
+
+ def test_partial_response
+ str = "0123456789"
+ @server.mount_proc('/') do |req, res|
+ res.status = 200
+ res['Content-Type'] = 'text/plain'
+
+ res.body = str
+ res['Content-Length'] = str.length + 1
+ end
+ @server.mount_proc('/show_ip') { |req, res| res.body = req.remote_ip }
+
+ http = Net::HTTP.new(config('host'), config('port'))
+ res = http.get('/')
+ assert_equal(str, res.body)
+
+ http = Net::HTTP.new(config('host'), config('port'))
+ http.ignore_eof = false
+ assert_raise(EOFError) {http.get('/')}
+ end
+end
diff --git a/test/net/http/test_http_request.rb b/test/net/http/test_http_request.rb
index 239b2d1009..7fd82b0353 100644
--- a/test/net/http/test_http_request.rb
+++ b/test/net/http/test_http_request.rb
@@ -46,8 +46,9 @@ class HTTPRequestTest < Test::Unit::TestCase
assert_not_predicate req, :response_body_permitted?
expected = {
- 'accept' => %w[*/*],
- 'user-agent' => %w[Ruby],
+ 'accept' => %w[*/*],
+ "accept-encoding" => %w[gzip;q=1.0,deflate;q=0.6,identity;q=0.3],
+ 'user-agent' => %w[Ruby],
}
assert_equal expected, req.to_hash
diff --git a/test/net/http/test_httpheader.rb b/test/net/http/test_httpheader.rb
index cfbe36bcfd..69563168db 100644
--- a/test/net/http/test_httpheader.rb
+++ b/test/net/http/test_httpheader.rb
@@ -28,7 +28,11 @@ class HTTPHeaderTest < Test::Unit::TestCase
assert_raise(NoMethodError){ @c.initialize_http_header("foo"=>[]) }
assert_raise(ArgumentError){ @c.initialize_http_header("foo"=>"a\nb") }
assert_raise(ArgumentError){ @c.initialize_http_header("foo"=>"a\rb") }
- assert_raise(ArgumentError){ @c.initialize_http_header("foo"=>"a\xff") }
+ end
+
+ def test_initialize_with_broken_coderange
+ error = RUBY_VERSION >= "3.2" ? Encoding::CompatibilityError : ArgumentError
+ assert_raise(error){ @c.initialize_http_header("foo"=>"a\xff") }
end
def test_initialize_with_symbol
@@ -308,6 +312,18 @@ class HTTPHeaderTest < Test::Unit::TestCase
end
def test_content_range
+ @c['Content-Range'] = "bytes 0-499/1000"
+ assert_equal 0..499, @c.content_range
+ @c['Content-Range'] = "bytes 1-500/1000"
+ assert_equal 1..500, @c.content_range
+ @c['Content-Range'] = "bytes 1-1/1000"
+ assert_equal 1..1, @c.content_range
+ @c['Content-Range'] = "tokens 1-1/1000"
+ assert_equal nil, @c.content_range
+
+ try_invalid_content_range "invalid"
+ try_invalid_content_range "bytes 123-abc"
+ try_invalid_content_range "bytes abc-123"
end
def test_range_length
@@ -317,6 +333,15 @@ class HTTPHeaderTest < Test::Unit::TestCase
assert_equal 500, @c.range_length
@c['Content-Range'] = "bytes 1-1/1000"
assert_equal 1, @c.range_length
+ @c['Content-Range'] = "tokens 1-1/1000"
+ assert_equal nil, @c.range_length
+
+ try_invalid_content_range "bytes 1-1/abc"
+ end
+
+ def try_invalid_content_range(s)
+ @c['Content-Range'] = "#{s}"
+ assert_raise(Net::HTTPHeaderSyntaxError, s){ @c.content_range }
end
def test_chunked?
diff --git a/test/net/http/test_httpresponse.rb b/test/net/http/test_httpresponse.rb
index 00b0072e70..01281063cd 100644
--- a/test/net/http/test_httpresponse.rb
+++ b/test/net/http/test_httpresponse.rb
@@ -54,6 +54,241 @@ EOS
assert_equal 'hello', body
end
+ def test_read_body_body_encoding_false
+ body = "hello\u1234"
+ io = dummy_io(<<EOS)
+HTTP/1.1 200 OK
+Connection: close
+Content-Length: #{body.bytesize}
+
+#{body}
+EOS
+
+ res = Net::HTTPResponse.read_new(io)
+
+ body = nil
+
+ res.reading_body io, true do
+ body = res.read_body
+ end
+
+ assert_equal "hello\u1234".b, body
+ assert_equal Encoding::ASCII_8BIT, body.encoding
+ end
+
+ def test_read_body_body_encoding_encoding
+ body = "hello\u1234"
+ io = dummy_io(<<EOS)
+HTTP/1.1 200 OK
+Connection: close
+Content-Length: #{body.bytesize}
+
+#{body}
+EOS
+
+ res = Net::HTTPResponse.read_new(io)
+ res.body_encoding = Encoding.find('utf-8')
+
+ body = nil
+
+ res.reading_body io, true do
+ body = res.read_body
+ end
+
+ assert_equal "hello\u1234", body
+ assert_equal Encoding::UTF_8, body.encoding
+ end
+
+ def test_read_body_body_encoding_string
+ body = "hello\u1234"
+ io = dummy_io(<<EOS)
+HTTP/1.1 200 OK
+Connection: close
+Content-Length: #{body.bytesize}
+
+#{body}
+EOS
+
+ res = Net::HTTPResponse.read_new(io)
+ res.body_encoding = 'utf-8'
+
+ body = nil
+
+ res.reading_body io, true do
+ body = res.read_body
+ end
+
+ assert_equal "hello\u1234", body
+ assert_equal Encoding::UTF_8, body.encoding
+ end
+
+ def test_read_body_body_encoding_true_without_content_type_header
+ body = "hello\u1234"
+ io = dummy_io(<<EOS)
+HTTP/1.1 200 OK
+Connection: close
+Content-Length: #{body.bytesize}
+
+#{body}
+EOS
+
+ res = Net::HTTPResponse.read_new(io)
+ res.body_encoding = true
+
+ body = nil
+
+ res.reading_body io, true do
+ body = res.read_body
+ end
+
+ assert_equal "hello\u1234".b, body
+ assert_equal Encoding::ASCII_8BIT, body.encoding
+ end
+
+ def test_read_body_body_encoding_true_with_utf8_content_type_header
+ body = "hello\u1234"
+ io = dummy_io(<<EOS)
+HTTP/1.1 200 OK
+Connection: close
+Content-Length: #{body.bytesize}
+Content-Type: text/plain; charset=utf-8
+
+#{body}
+EOS
+
+ res = Net::HTTPResponse.read_new(io)
+ res.body_encoding = true
+
+ body = nil
+
+ res.reading_body io, true do
+ body = res.read_body
+ end
+
+ assert_equal "hello\u1234", body
+ assert_equal Encoding::UTF_8, body.encoding
+ end
+
+ def test_read_body_body_encoding_true_with_iso_8859_1_content_type_header
+ body = "hello\u1234"
+ io = dummy_io(<<EOS)
+HTTP/1.1 200 OK
+Connection: close
+Content-Length: #{body.bytesize}
+Content-Type: text/plain; charset=iso-8859-1
+
+#{body}
+EOS
+
+ res = Net::HTTPResponse.read_new(io)
+ res.body_encoding = true
+
+ body = nil
+
+ res.reading_body io, true do
+ body = res.read_body
+ end
+
+ assert_equal "hello\u1234".force_encoding("ISO-8859-1"), body
+ assert_equal Encoding::ISO_8859_1, body.encoding
+ end
+
+ def test_read_body_body_encoding_true_with_utf8_meta_charset
+ res_body = "<html><meta charset=\"utf-8\">hello\u1234</html>"
+ io = dummy_io(<<EOS)
+HTTP/1.1 200 OK
+Connection: close
+Content-Length: #{res_body.bytesize}
+Content-Type: text/html
+
+#{res_body}
+EOS
+
+ res = Net::HTTPResponse.read_new(io)
+ res.body_encoding = true
+
+ body = nil
+
+ res.reading_body io, true do
+ body = res.read_body
+ end
+
+ assert_equal res_body, body
+ assert_equal Encoding::UTF_8, body.encoding
+ end
+
+ def test_read_body_body_encoding_true_with_iso8859_1_meta_charset
+ res_body = "<html><meta charset=\"iso-8859-1\">hello\u1234</html>"
+ io = dummy_io(<<EOS)
+HTTP/1.1 200 OK
+Connection: close
+Content-Length: #{res_body.bytesize}
+Content-Type: text/html
+
+#{res_body}
+EOS
+
+ res = Net::HTTPResponse.read_new(io)
+ res.body_encoding = true
+
+ body = nil
+
+ res.reading_body io, true do
+ body = res.read_body
+ end
+
+ assert_equal res_body.force_encoding("ISO-8859-1"), body
+ assert_equal Encoding::ISO_8859_1, body.encoding
+ end
+
+ def test_read_body_body_encoding_true_with_utf8_meta_content_charset
+ res_body = "<meta http-equiv='content-type' content='text/html; charset=UTF-8'>hello\u1234</html>"
+ io = dummy_io(<<EOS)
+HTTP/1.1 200 OK
+Connection: close
+Content-Length: #{res_body.bytesize}
+Content-Type: text/html
+
+#{res_body}
+EOS
+
+ res = Net::HTTPResponse.read_new(io)
+ res.body_encoding = true
+
+ body = nil
+
+ res.reading_body io, true do
+ body = res.read_body
+ end
+
+ assert_equal res_body, body
+ assert_equal Encoding::UTF_8, body.encoding
+ end
+
+ def test_read_body_body_encoding_true_with_iso8859_1_meta_content_charset
+ res_body = "<meta http-equiv='content-type' content='text/html; charset=ISO-8859-1'>hello\u1234</html>"
+ io = dummy_io(<<EOS)
+HTTP/1.1 200 OK
+Connection: close
+Content-Length: #{res_body.bytesize}
+Content-Type: text/html
+
+#{res_body}
+EOS
+
+ res = Net::HTTPResponse.read_new(io)
+ res.body_encoding = true
+
+ body = nil
+
+ res.reading_body io, true do
+ body = res.read_body
+ end
+
+ assert_equal res_body.force_encoding("ISO-8859-1"), body
+ assert_equal Encoding::ISO_8859_1, body.encoding
+ end
+
def test_read_body_block
io = dummy_io(<<EOS)
HTTP/1.1 200 OK
@@ -77,8 +312,8 @@ EOS
end
def test_read_body_block_mod
- # http://ci.rvm.jp/results/trunk-mjit-wait@silicon-docker/3019353
- if defined?(RubyVM::JIT) ? RubyVM::JIT.enabled? : defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled?
+ # http://ci.rvm.jp/results/trunk-rjit-wait@silicon-docker/3019353
+ if defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled?
omit 'too unstable with --jit-wait, and extending read_timeout did not help it'
end
IO.pipe do |r, w|
@@ -127,9 +362,11 @@ EOS
if Net::HTTP::HAVE_ZLIB
assert_equal nil, res['content-encoding']
+ assert_equal '5', res['content-length']
assert_equal 'hello', body
else
assert_equal 'deflate', res['content-encoding']
+ assert_equal '13', res['content-length']
assert_equal "x\x9C\xCBH\xCD\xC9\xC9\a\x00\x06,\x02\x15", body
end
end
@@ -155,9 +392,11 @@ EOS
if Net::HTTP::HAVE_ZLIB
assert_equal nil, res['content-encoding']
+ assert_equal '5', res['content-length']
assert_equal 'hello', body
else
assert_equal 'DEFLATE', res['content-encoding']
+ assert_equal '13', res['content-length']
assert_equal "x\x9C\xCBH\xCD\xC9\xC9\a\x00\x06,\x02\x15", body
end
end
@@ -188,9 +427,11 @@ EOS
if Net::HTTP::HAVE_ZLIB
assert_equal nil, res['content-encoding']
+ assert_equal nil, res['content-length']
assert_equal 'hello', body
else
assert_equal 'deflate', res['content-encoding']
+ assert_equal nil, res['content-length']
assert_equal "x\x9C\xCBH\xCD\xC9\xC9\a\x00\x06,\x02\x15", body
end
end
@@ -215,6 +456,7 @@ EOS
end
assert_equal 'deflate', res['content-encoding'], 'Bug #7831'
+ assert_equal '13', res['content-length']
assert_equal "x\x9C\xCBH\xCD\xC9\xC9\a\x00\x06,\x02\x15", body, 'Bug #7381'
end
@@ -238,9 +480,11 @@ EOS
if Net::HTTP::HAVE_ZLIB
assert_equal nil, res['content-encoding']
+ assert_equal nil, res['content-length']
assert_equal 'hello', body
else
assert_equal 'deflate', res['content-encoding']
+ assert_equal nil, res['content-length']
assert_equal "x\x9C\xCBH\xCD\xC9\xC9\a\x00\x06,\x02\x15\r\n", body
end
end
@@ -288,9 +532,11 @@ EOS
if Net::HTTP::HAVE_ZLIB
assert_equal nil, res['content-encoding']
+ assert_equal '0', res['content-length']
assert_equal '', body
else
assert_equal 'deflate', res['content-encoding']
+ assert_equal '0', res['content-length']
assert_equal '', body
end
end
@@ -314,9 +560,11 @@ EOS
if Net::HTTP::HAVE_ZLIB
assert_equal nil, res['content-encoding']
+ assert_equal nil, res['content-length']
assert_equal '', body
else
assert_equal 'deflate', res['content-encoding']
+ assert_equal nil, res['content-length']
assert_equal '', body
end
end
@@ -341,6 +589,41 @@ EOS
assert_equal 'hello', body
end
+ def test_read_body_receiving_no_body
+ io = dummy_io(<<EOS)
+HTTP/1.1 204 OK
+Connection: close
+
+EOS
+
+ res = Net::HTTPResponse.read_new(io)
+ res.body_encoding = 'utf-8'
+
+ body = 'something to override'
+
+ res.reading_body io, true do
+ body = res.read_body
+ end
+
+ assert_equal nil, body
+ assert_equal nil, res.body
+ end
+
+ def test_read_body_outside_of_reading_body
+ io = dummy_io(<<EOS)
+HTTP/1.1 200 OK
+Connection: close
+Content-Length: 0
+
+EOS
+
+ res = Net::HTTPResponse.read_new(io)
+
+ assert_raise IOError do
+ res.read_body
+ end
+ end
+
def test_uri_equals
uri = URI 'http://example'
diff --git a/test/net/http/test_https.rb b/test/net/http/test_https.rb
index 4dc9f1b026..e860c8745e 100644
--- a/test/net/http/test_https.rb
+++ b/test/net/http/test_https.rb
@@ -137,7 +137,7 @@ class TestNetHTTPS < Test::Unit::TestCase
def test_session_reuse
# FIXME: The new_session_cb is known broken for clients in OpenSSL 1.1.0h.
# See https://github.com/openssl/openssl/pull/5967 for details.
- skip if OpenSSL::OPENSSL_LIBRARY_VERSION =~ /OpenSSL 1.1.0h/
+ omit if OpenSSL::OPENSSL_LIBRARY_VERSION.include?('OpenSSL 1.1.0h')
http = Net::HTTP.new(HOST, config("port"))
http.use_ssl = true
@@ -148,38 +148,40 @@ class TestNetHTTPS < Test::Unit::TestCase
# support session resuse. Limiting the version to the TLSv1.2 stack allows
# this test to continue to work on LibreSSL 3.2+. LibreSSL may eventually
# support session reuse, but there are no current plans to do so.
- http.ssl_version = :TLSv1
+ http.ssl_version = :TLSv1_2
end
http.start
- assert_equal false, http.instance_variable_get(:@socket).io.session_reused?
+ session_reused = http.instance_variable_get(:@socket).io.session_reused?
+ assert_false session_reused unless session_reused.nil? # can not detect re-use under JRuby
http.get("/")
http.finish
http.start
- assert_equal true, http.instance_variable_get(:@socket).io.session_reused?
+ session_reused = http.instance_variable_get(:@socket).io.session_reused?
+ assert_true session_reused unless session_reused.nil? # can not detect re-use under JRuby
assert_equal $test_net_http_data, http.get("/").body
http.finish
end
def test_session_reuse_but_expire
# FIXME: The new_session_cb is known broken for clients in OpenSSL 1.1.0h.
- skip if OpenSSL::OPENSSL_LIBRARY_VERSION =~ /OpenSSL 1.1.0h/
+ omit if OpenSSL::OPENSSL_LIBRARY_VERSION.include?('OpenSSL 1.1.0h')
http = Net::HTTP.new(HOST, config("port"))
http.use_ssl = true
http.cert_store = TEST_STORE
- http.ssl_timeout = -1
+ http.ssl_timeout = 1
http.start
http.get("/")
http.finish
-
+ sleep 1.25
http.start
http.get("/")
socket = http.instance_variable_get(:@socket).io
- assert_equal false, socket.session_reused?
+ assert_equal false, socket.session_reused?, "NOTE: OpenSSL library version is #{OpenSSL::OPENSSL_LIBRARY_VERSION}"
http.finish
end
@@ -236,27 +238,6 @@ class TestNetHTTPS < Test::Unit::TestCase
http.request_get("/") {|res| }
}
assert_match(/certificate verify failed/, ex.message)
- unless /mswin|mingw/ =~ RUBY_PLATFORM
- # on Windows, Errno::ECONNRESET will be raised, and it'll be eaten by
- # WEBrick
- @log_tester = lambda {|log|
- assert_equal(1, log.length)
- assert_match(/ERROR OpenSSL::SSL::SSLError:/, log[0])
- }
- end
- end
-
- def test_identity_verify_failure
- # the certificate's subject has CN=localhost
- http = Net::HTTP.new(HOST_IP, config("port"))
- http.use_ssl = true
- http.cert_store = TEST_STORE
- @log_tester = lambda {|_| }
- ex = assert_raise(OpenSSL::SSL::SSLError){
- http.request_get("/") {|res| }
- }
- re_msg = /certificate verify failed|hostname \"#{HOST_IP}\" does not match/
- assert_match(re_msg, ex.message)
end
def test_timeout_during_SSL_handshake
@@ -291,7 +272,7 @@ class TestNetHTTPS < Test::Unit::TestCase
end
def test_max_version
- http = Net::HTTP.new(HOST_IP, config("port"))
+ http = Net::HTTP.new(HOST, config("port"))
http.use_ssl = true
http.max_version = :SSL2
http.verify_callback = Proc.new do |preverify_ok, store_ctx|
@@ -301,8 +282,48 @@ class TestNetHTTPS < Test::Unit::TestCase
ex = assert_raise(OpenSSL::SSL::SSLError){
http.request_get("/") {|res| }
}
- re_msg = /\ASSL_connect returned=1 errno=0 |SSL_CTX_set_max_proto_version/
+ re_msg = /\ASSL_connect returned=1 errno=0 |SSL_CTX_set_max_proto_version|No appropriate protocol/
assert_match(re_msg, ex.message)
end
end if defined?(OpenSSL::SSL)
+
+class TestNetHTTPSIdentityVerifyFailure < Test::Unit::TestCase
+ include TestNetHTTPUtils
+
+ def self.read_fixture(key)
+ File.read(File.expand_path("../fixtures/#{key}", __dir__))
+ end
+
+ HOST = 'localhost'
+ HOST_IP = '127.0.0.1'
+ CA_CERT = OpenSSL::X509::Certificate.new(read_fixture("cacert.pem"))
+ SERVER_KEY = OpenSSL::PKey.read(read_fixture("server.key"))
+ SERVER_CERT = OpenSSL::X509::Certificate.new(read_fixture("server.crt"))
+ DHPARAMS = OpenSSL::PKey::DH.new(read_fixture("dhparams.pem"))
+ TEST_STORE = OpenSSL::X509::Store.new.tap {|s| s.add_cert(CA_CERT) }
+
+ CONFIG = {
+ 'host' => HOST_IP,
+ 'proxy_host' => nil,
+ 'proxy_port' => nil,
+ 'ssl_enable' => true,
+ 'ssl_certificate' => SERVER_CERT,
+ 'ssl_private_key' => SERVER_KEY,
+ 'ssl_tmp_dh_callback' => proc { DHPARAMS },
+ }
+
+ def test_identity_verify_failure
+ # the certificate's subject has CN=localhost
+ http = Net::HTTP.new(HOST_IP, config("port"))
+ http.use_ssl = true
+ http.cert_store = TEST_STORE
+ @log_tester = lambda {|_| }
+ ex = assert_raise(OpenSSL::SSL::SSLError){
+ http.request_get("/") {|res| }
+ sleep 0.5
+ }
+ re_msg = /certificate verify failed|hostname \"#{HOST_IP}\" does not match/
+ assert_match(re_msg, ex.message)
+ end
+end if defined?(OpenSSL::SSL)
diff --git a/test/net/http/test_https_proxy.rb b/test/net/http/test_https_proxy.rb
index f833f1a1e3..f4c6aa0b6a 100644
--- a/test/net/http/test_https_proxy.rb
+++ b/test/net/http/test_https_proxy.rb
@@ -10,7 +10,7 @@ class HTTPSProxyTest < Test::Unit::TestCase
begin
OpenSSL
rescue LoadError
- skip 'autoload problem. see [ruby-dev:45021][Bug #5786]'
+ omit 'autoload problem. see [ruby-dev:45021][Bug #5786]'
end
TCPServer.open("127.0.0.1", 0) {|serv|
@@ -43,5 +43,52 @@ class HTTPSProxyTest < Test::Unit::TestCase
assert_join_threads([client_thread, server_thread])
}
end
-end if defined?(OpenSSL)
+
+ def read_fixture(key)
+ File.read(File.expand_path("../fixtures/#{key}", __dir__))
+ end
+
+ def test_https_proxy_ssl_connection
+ begin
+ OpenSSL
+ rescue LoadError
+ omit 'autoload problem. see [ruby-dev:45021][Bug #5786]'
+ end
+
+ TCPServer.open("127.0.0.1", 0) {|tcpserver|
+ ctx = OpenSSL::SSL::SSLContext.new
+ ctx.key = OpenSSL::PKey.read(read_fixture("server.key"))
+ ctx.cert = OpenSSL::X509::Certificate.new(read_fixture("server.crt"))
+ serv = OpenSSL::SSL::SSLServer.new(tcpserver, ctx)
+
+ _, port, _, _ = serv.addr
+ client_thread = Thread.new {
+ proxy = Net::HTTP.Proxy("127.0.0.1", port, 'user', 'password', true)
+ http = proxy.new("foo.example.org", 8000)
+ http.use_ssl = true
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
+ begin
+ http.start
+ rescue EOFError
+ end
+ }
+ server_thread = Thread.new {
+ sock = serv.accept
+ begin
+ 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-core:96672]")
+ ensure
+ sock.close
+ end
+ }
+ assert_join_threads([client_thread, server_thread])
+ }
+ end
+end if defined?(OpenSSL)
diff --git a/test/net/http/utils.rb b/test/net/http/utils.rb
index e343e16712..1d43497af0 100644
--- a/test/net/http/utils.rb
+++ b/test/net/http/utils.rb
@@ -1,13 +1,229 @@
# frozen_string_literal: false
-require 'webrick'
-begin
- require "webrick/https"
-rescue LoadError
- # SSL features cannot be tested
-end
-require 'webrick/httpservlet/abstract'
+require 'socket'
+require 'openssl'
module TestNetHTTPUtils
+
+ class Forbidden < StandardError; end
+
+ class HTTPServer
+ def initialize(config, &block)
+ @config = config
+ @server = TCPServer.new(@config['host'], 0)
+ @port = @server.addr[1]
+ @procs = {}
+
+ if @config['ssl_enable']
+ context = OpenSSL::SSL::SSLContext.new
+ context.cert = @config['ssl_certificate']
+ context.key = @config['ssl_private_key']
+ context.tmp_dh_callback = @config['ssl_tmp_dh_callback']
+ @ssl_server = OpenSSL::SSL::SSLServer.new(@server, context)
+ end
+
+ @block = block
+ end
+
+ def start
+ @thread = Thread.new do
+ loop do
+ socket = @ssl_server ? @ssl_server.accept : @server.accept
+ run(socket)
+ rescue
+ ensure
+ socket.close if socket
+ end
+ end
+ end
+
+ def run(socket)
+ handle_request(socket)
+ end
+
+ def shutdown
+ @thread&.kill
+ @server&.close
+ @thread&.join
+ end
+
+ def mount(path, proc)
+ @procs[path] = proc
+ end
+
+ def mount_proc(path, &block)
+ mount(path, block.to_proc)
+ end
+
+ def handle_request(socket)
+ request_line = socket.gets
+ return if request_line.nil? || request_line.strip.empty?
+
+ method, path, _version = request_line.split
+ headers = {}
+ while (line = socket.gets)
+ break if line.strip.empty?
+ key, value = line.split(': ', 2)
+ headers[key] = value.strip
+ end
+
+ if headers['Expect'] == '100-continue'
+ socket.write "HTTP/1.1 100 Continue\r\n\r\n"
+ end
+
+ req = Request.new(method, path, headers, socket)
+ if @procs.key?(req.path) || @procs.key?("#{req.path}/")
+ proc = @procs[req.path] || @procs["#{req.path}/"]
+ res = Response.new(socket)
+ begin
+ proc.call(req, res)
+ rescue Forbidden
+ res.status = 403
+ end
+ res.finish
+ else
+ @block.call(method, path, headers, socket)
+ end
+ end
+
+ def port
+ @port
+ end
+
+ class Request
+ attr_reader :method, :path, :headers, :query, :body
+ def initialize(method, path, headers, socket)
+ @method = method
+ @path, @query = parse_path_and_query(path)
+ @headers = headers
+ @socket = socket
+ if method == 'POST' && (@path == '/continue' || @headers['Content-Type'].include?('multipart/form-data'))
+ if @headers['Transfer-Encoding'] == 'chunked'
+ @body = read_chunked_body
+ else
+ @body = read_body
+ end
+ @query = @body.split('&').each_with_object({}) do |pair, hash|
+ key, value = pair.split('=')
+ hash[key] = value
+ end if @body && @body.include?('=')
+ end
+ end
+
+ def [](key)
+ @headers[key.downcase]
+ end
+
+ def []=(key, value)
+ @headers[key.downcase] = value
+ end
+
+ def continue
+ @socket.write "HTTP\/1.1 100 continue\r\n\r\n"
+ end
+
+ def remote_ip
+ @socket.peeraddr[3]
+ end
+
+ def peeraddr
+ @socket.peeraddr
+ end
+
+ private
+
+ def parse_path_and_query(path)
+ path, query_string = path.split('?', 2)
+ query = {}
+ if query_string
+ query_string.split('&').each do |pair|
+ key, value = pair.split('=', 2)
+ query[key] = value
+ end
+ end
+ [path, query]
+ end
+
+ def read_body
+ content_length = @headers['Content-Length']&.to_i
+ return unless content_length && content_length > 0
+ @socket.read(content_length)
+ end
+
+ def read_chunked_body
+ body = ""
+ while (chunk_size = @socket.gets.strip.to_i(16)) > 0
+ body << @socket.read(chunk_size)
+ @socket.read(2) # read \r\n after each chunk
+ end
+ body
+ end
+ end
+
+ class Response
+ attr_accessor :body, :headers, :status, :chunked, :cookies
+ def initialize(client)
+ @client = client
+ @body = ""
+ @headers = {}
+ @status = 200
+ @chunked = false
+ @cookies = []
+ end
+
+ def [](key)
+ @headers[key.downcase]
+ end
+
+ def []=(key, value)
+ @headers[key.downcase] = value
+ end
+
+ def write_chunk(chunk)
+ return unless @chunked
+ @client.write("#{chunk.bytesize.to_s(16)}\r\n")
+ @client.write("#{chunk}\r\n")
+ end
+
+ def finish
+ @client.write build_response_headers
+ if @chunked
+ write_chunk(@body)
+ @client.write "0\r\n\r\n"
+ else
+ @client.write @body
+ end
+ end
+
+ private
+
+ def build_response_headers
+ response = "HTTP/1.1 #{@status} #{status_message(@status)}\r\n"
+ if @chunked
+ @headers['Transfer-Encoding'] = 'chunked'
+ else
+ @headers['Content-Length'] = @body.bytesize.to_s
+ end
+ @headers.each do |key, value|
+ response << "#{key}: #{value}\r\n"
+ end
+ @cookies.each do |cookie|
+ response << "Set-Cookie: #{cookie}\r\n"
+ end
+ response << "\r\n"
+ response
+ end
+
+ def status_message(code)
+ case code
+ when 200 then 'OK'
+ when 301 then 'Moved Permanently'
+ when 403 then 'Forbidden'
+ else 'Unknown'
+ end
+ end
+ end
+ end
+
def start(&block)
new().start(&block)
end
@@ -15,7 +231,7 @@ module TestNetHTTPUtils
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.set_debug_output logfile
http
end
@@ -25,7 +241,7 @@ module TestNetHTTPUtils
end
def logfile
- $DEBUG ? $stderr : NullWriter.new
+ $stderr if $DEBUG
end
def setup
@@ -33,91 +249,94 @@ module TestNetHTTPUtils
end
def teardown
+ sleep 0.5 if @config['ssl_enable']
if @server
@server.shutdown
- @server_thread.join
- WEBrick::Utils::TimeoutHandler.terminate
end
@log_tester.call(@log) if @log_tester
- # resume global state
Net::HTTP.version_1_2
end
def spawn_server
@log = []
- @log_tester = lambda {|log| assert_equal([], log ) }
+ @log_tester = lambda {|log| assert_equal([], log) }
@config = self.class::CONFIG
- server_config = {
- :BindAddress => config('host'),
- :Port => 0,
- :Logger => WEBrick::Log.new(@log, WEBrick::BasicLog::WARN),
- :AccessLog => [],
- :ServerType => Thread,
- }
- server_config[:OutputBufferSize] = 4 if config('chunked')
- server_config[:RequestTimeout] = config('RequestTimeout') if config('RequestTimeout')
- if defined?(OpenSSL) and config('ssl_enable')
- server_config.update({
- :SSLEnable => true,
- :SSLCertificate => config('ssl_certificate'),
- :SSLPrivateKey => config('ssl_private_key'),
- :SSLTmpDhCallback => config('ssl_tmp_dh_callback'),
- })
- end
- @server = WEBrick::HTTPServer.new(server_config)
- @server.mount('/', Servlet, config('chunked'))
- @server_thread = @server.start
- @config['port'] = @server[:Port]
- 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 initialize(this, chunked = false)
- @chunked = chunked
- end
-
- def do_GET(req, res)
- if req['Accept'] != '*/*'
- res['Content-Type'] = req['Accept']
+ @server = HTTPServer.new(@config) do |method, path, headers, socket|
+ @log << "DEBUG accept: #{@config['host']}:#{socket.addr[1]}" if @logger_level == :debug
+ case method
+ when 'HEAD'
+ handle_head(path, headers, socket)
+ when 'GET'
+ handle_get(path, headers, socket)
+ when 'POST'
+ handle_post(path, headers, socket)
+ when 'PATCH'
+ handle_patch(path, headers, socket)
else
- res['Content-Type'] = $test_net_http_data_type
+ socket.print "HTTP/1.1 405 Method Not Allowed\r\nContent-Length: 0\r\n\r\n"
end
- res.body = $test_net_http_data
- res.chunked = @chunked
end
+ @server.start
+ @config['port'] = @server.port
+ end
- # echo server
- def do_POST(req, res)
- res['Content-Type'] = req['Content-Type']
- res['X-request-uri'] = req.request_uri.to_s
- res.body = req.body
- res.chunked = @chunked
+ def handle_head(path, headers, socket)
+ if headers['Accept'] != '*/*'
+ content_type = headers['Accept']
+ else
+ content_type = $test_net_http_data_type
end
+ response = "HTTP/1.1 200 OK\r\nContent-Type: #{content_type}\r\nContent-Length: #{$test_net_http_data.bytesize}"
+ socket.print(response)
+ end
- def do_PATCH(req, res)
- res['Content-Type'] = req['Content-Type']
- res.body = req.body
- res.chunked = @chunked
+ def handle_get(path, headers, socket)
+ if headers['Accept'] != '*/*'
+ content_type = headers['Accept']
+ else
+ content_type = $test_net_http_data_type
end
+ response = "HTTP/1.1 200 OK\r\nContent-Type: #{content_type}\r\nContent-Length: #{$test_net_http_data.bytesize}\r\n\r\n#{$test_net_http_data}"
+ socket.print(response)
+ end
+
+ def handle_post(path, headers, socket)
+ body = socket.read(headers['Content-Length'].to_i)
+ scheme = headers['X-Request-Scheme'] || 'http'
+ host = @config['host']
+ port = socket.addr[1]
+ charset = parse_content_type(headers['Content-Type'])[1]
+ path = "#{scheme}://#{host}:#{port}#{path}"
+ path = path.encode(charset) if charset
+ response = "HTTP/1.1 200 OK\r\nContent-Type: #{headers['Content-Type']}\r\nContent-Length: #{body.bytesize}\r\nX-request-uri: #{path}\r\n\r\n#{body}"
+ socket.print(response)
+ end
+
+ def handle_patch(path, headers, socket)
+ body = socket.read(headers['Content-Length'].to_i)
+ response = "HTTP/1.1 200 OK\r\nContent-Type: #{headers['Content-Type']}\r\nContent-Length: #{body.bytesize}\r\n\r\n#{body}"
+ socket.print(response)
end
- class NullWriter
- def <<(s) end
- def puts(*args) end
- def print(*args) end
- def printf(*args) end
+ def parse_content_type(content_type)
+ return [nil, nil] unless content_type
+ type, *params = content_type.split(';').map(&:strip)
+ charset = params.find { |param| param.start_with?('charset=') }
+ charset = charset.split('=', 2).last if charset
+ [type, charset]
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'
+
def self.clean_http_proxy_env
orig = {
- 'http_proxy' => ENV['http_proxy'],
+ 'http_proxy' => ENV['http_proxy'],
'http_proxy_user' => ENV['http_proxy_user'],
'http_proxy_pass' => ENV['http_proxy_pass'],
- 'no_proxy' => ENV['no_proxy'],
+ 'no_proxy' => ENV['no_proxy'],
}
orig.each_key do |key|
diff --git a/test/net/protocol/test_protocol.rb b/test/net/protocol/test_protocol.rb
index d3dc2ccf4c..2f42fa3236 100644
--- a/test/net/protocol/test_protocol.rb
+++ b/test/net/protocol/test_protocol.rb
@@ -57,6 +57,14 @@ class TestProtocol < Test::Unit::TestCase
mockio
end
+ def test_readuntil
+ assert_output("", "") do
+ sio = StringIO.new("12345".dup)
+ io = Net::BufferedIO.new(sio)
+ assert_equal "12345", io.readuntil("5")
+ end
+ end
+
def test_write0_multibyte
mockio = create_mockio(max: 1)
io = Net::BufferedIO.new(mockio)
@@ -119,4 +127,33 @@ class TestProtocol < Test::Unit::TestCase
io.write_timeout = 0.1
assert_raise(Net::WriteTimeout){ io.write("a"*50,"a"*50,"a") }
end
+
+ class FakeReadPartialIO
+ def initialize(chunks)
+ @chunks = chunks.map(&:dup)
+ end
+
+ def read_nonblock(size, buf = nil, exception: false)
+ if buf
+ buf.replace(@chunks.shift)
+ buf
+ else
+ @chunks.shift
+ end
+ end
+ end
+
+ def test_shareable_buffer_leak # https://github.com/ruby/net-protocol/pull/19
+ expected_chunks = [
+ "aaaaa",
+ "bbbbb",
+ ]
+ fake_io = FakeReadPartialIO.new(expected_chunks)
+ io = Net::BufferedIO.new(fake_io)
+ actual_chunks = []
+ reader = Net::ReadAdapter.new(-> (chunk) { actual_chunks << chunk })
+ io.read(5, reader)
+ io.read(5, reader)
+ assert_equal expected_chunks, actual_chunks
+ end
end
diff --git a/test/nkf/test_kconv.rb b/test/nkf/test_kconv.rb
deleted file mode 100644
index 3968cc47dc..0000000000
--- a/test/nkf/test_kconv.rb
+++ /dev/null
@@ -1,82 +0,0 @@
-# frozen_string_literal: false
-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
- def test_kconv
- str = "\xc2\xa1"
- %w/UTF-8 EUC-JP/.each do |enc|
- s = str.dup.force_encoding(enc)
- assert_equal(s, s.kconv(enc))
- end
- end
-end
diff --git a/test/nkf/test_nkf.rb b/test/nkf/test_nkf.rb
deleted file mode 100644
index eb51bf8e7d..0000000000
--- a/test/nkf/test_nkf.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-# frozen_string_literal: false
-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
-
- def test_ruby_dev_36909
- assert_nothing_raised do
- 100.times { NKF.nkf("--oc=eucJP-nkf", "foo") }
- end
- end
-
-end
diff --git a/test/objspace/test_objspace.rb b/test/objspace/test_objspace.rb
index 8ed04f59c9..b54a438132 100644
--- a/test/objspace/test_objspace.rb
+++ b/test/objspace/test_objspace.rb
@@ -29,12 +29,12 @@ class TestObjSpace < Test::Unit::TestCase
end
def test_memsize_of_root_shared_string
- a = "hello" * 5
+ a = "a" * GC::INTERNAL_CONSTANTS[:RVARGC_MAX_ALLOCATE_SIZE]
b = a.dup
c = nil
ObjectSpace.each_object(String) {|x| break c = x if x == a and x.frozen?}
- rv_size = GC::INTERNAL_CONSTANTS[:RVALUE_SIZE]
- assert_equal([rv_size, rv_size, 26 + rv_size], [a, b, c].map {|x| ObjectSpace.memsize_of(x)})
+ rv_size = GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE]
+ assert_equal([rv_size, rv_size, a.length + 1 + rv_size], [a, b, c].map {|x| ObjectSpace.memsize_of(x)})
end
def test_argf_memsize
@@ -140,6 +140,19 @@ class TestObjSpace < Test::Unit::TestCase
end;
end
+ def test_reachable_objects_during_iteration
+ omit 'flaky on Visual Studio with: [BUG] Unnormalized Fixnum value' if /mswin/ =~ RUBY_PLATFORM
+ opts = %w[--disable-gem --disable=frozen-string-literal -robjspace]
+ assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}"
+ begin;
+ ObjectSpace.each_object{|o|
+ o.inspect
+ ObjectSpace.reachable_objects_from(Class)
+ }
+ end;
+ end
+
+
def test_reachable_objects_from_root
root_objects = ObjectSpace.reachable_objects_from_root
@@ -204,44 +217,65 @@ class TestObjSpace < Test::Unit::TestCase
assert_equal(c3, ObjectSpace.allocation_generation(o3))
assert_equal(self.class.name, ObjectSpace.allocation_class_path(o3))
assert_equal(__method__, ObjectSpace.allocation_method_id(o3))
+
+ # [Bug #19456]
+ o4 =
+ # This line intentionally left blank
+ # This line intentionally left blank
+ 1.0 / 0.0; line4 = __LINE__; _c4 = GC.count
+ assert_equal(__FILE__, ObjectSpace.allocation_sourcefile(o4))
+ assert_equal(line4, ObjectSpace.allocation_sourceline(o4))
+
+ # The line number should be based on newarray instead of getinstancevariable.
+ line5 = __LINE__; o5 = [ # newarray (leaf)
+ @ivar, # getinstancevariable (not leaf)
+ ]
+ assert_equal(__FILE__, ObjectSpace.allocation_sourcefile(o5))
+ assert_equal(line5, ObjectSpace.allocation_sourceline(o5))
+
+ # [Bug #19482]
+ EnvUtil.under_gc_stress do
+ 100.times do
+ Class.new
+ end
+ end
}
end
def test_trace_object_allocations_start_stop_clear
ObjectSpace.trace_object_allocations_clear # clear object_table to get rid of erroneous detection for obj3
- GC.disable # suppress potential object reuse. see [Bug #11271]
- begin
- ObjectSpace.trace_object_allocations_start
+ EnvUtil.without_gc do # suppress potential object reuse. see [Bug #11271]
begin
ObjectSpace.trace_object_allocations_start
begin
ObjectSpace.trace_object_allocations_start
- obj0 = Object.new
+ begin
+ ObjectSpace.trace_object_allocations_start
+ obj0 = Object.new
+ ensure
+ ObjectSpace.trace_object_allocations_stop
+ obj1 = Object.new
+ end
ensure
ObjectSpace.trace_object_allocations_stop
- obj1 = Object.new
+ obj2 = Object.new
end
ensure
ObjectSpace.trace_object_allocations_stop
- obj2 = Object.new
+ obj3 = Object.new
end
- ensure
- ObjectSpace.trace_object_allocations_stop
- obj3 = Object.new
- end
- assert_equal(__FILE__, ObjectSpace.allocation_sourcefile(obj0))
- assert_equal(__FILE__, ObjectSpace.allocation_sourcefile(obj1))
- assert_equal(__FILE__, ObjectSpace.allocation_sourcefile(obj2))
- assert_equal(nil , ObjectSpace.allocation_sourcefile(obj3)) # after tracing
+ assert_equal(__FILE__, ObjectSpace.allocation_sourcefile(obj0))
+ assert_equal(__FILE__, ObjectSpace.allocation_sourcefile(obj1))
+ assert_equal(__FILE__, ObjectSpace.allocation_sourcefile(obj2))
+ assert_equal(nil , ObjectSpace.allocation_sourcefile(obj3)) # after tracing
- ObjectSpace.trace_object_allocations_clear
- assert_equal(nil, ObjectSpace.allocation_sourcefile(obj0))
- assert_equal(nil, ObjectSpace.allocation_sourcefile(obj1))
- assert_equal(nil, ObjectSpace.allocation_sourcefile(obj2))
- assert_equal(nil, ObjectSpace.allocation_sourcefile(obj3))
- ensure
- GC.enable
+ ObjectSpace.trace_object_allocations_clear
+ assert_equal(nil, ObjectSpace.allocation_sourcefile(obj0))
+ assert_equal(nil, ObjectSpace.allocation_sourcefile(obj1))
+ assert_equal(nil, ObjectSpace.allocation_sourcefile(obj2))
+ assert_equal(nil, ObjectSpace.allocation_sourcefile(obj3))
+ end
end
def test_trace_object_allocations_gc_stress
@@ -254,18 +288,55 @@ class TestObjSpace < Test::Unit::TestCase
end
def test_dump_flags
+ # Ensure that the fstring is promoted to old generation
+ 4.times { GC.start }
info = ObjectSpace.dump("foo".freeze)
assert_match(/"wb_protected":true, "old":true/, info)
assert_match(/"fstring":true/, info)
JSON.parse(info) if defined?(JSON)
end
+ if defined?(RubyVM::Shape)
+ class TooComplex; end
+
+ def test_dump_too_complex_shape
+ omit "flaky test"
+
+ RubyVM::Shape::SHAPE_MAX_VARIATIONS.times do
+ TooComplex.new.instance_variable_set(:"@a#{_1}", 1)
+ end
+
+ tc = TooComplex.new
+ info = ObjectSpace.dump(tc)
+ assert_not_match(/"too_complex_shape"/, info)
+ tc.instance_variable_set(:@new_ivar, 1)
+ info = ObjectSpace.dump(tc)
+ assert_match(/"too_complex_shape":true/, info)
+ if defined?(JSON)
+ assert_true(JSON.parse(info)["too_complex_shape"])
+ end
+ end
+ end
+
+ class NotTooComplex ; end
+
+ def test_dump_not_too_complex_shape
+ tc = NotTooComplex.new
+ tc.instance_variable_set(:@new_ivar, 1)
+ info = ObjectSpace.dump(tc)
+
+ assert_not_match(/"too_complex_shape"/, info)
+ if defined?(JSON)
+ assert_nil(JSON.parse(info)["too_complex_shape"])
+ end
+ end
+
def test_dump_to_default
line = nil
info = nil
ObjectSpace.trace_object_allocations do
line = __LINE__ + 1
- str = "hello world"
+ str = "hello w"
info = ObjectSpace.dump(str)
end
assert_dump_object(info, line)
@@ -277,7 +348,7 @@ class TestObjSpace < Test::Unit::TestCase
th = Thread.start {r.read}
ObjectSpace.trace_object_allocations do
line = __LINE__ + 1
- str = "hello world"
+ str = "hello w"
ObjectSpace.dump(str, output: w)
end
w.close
@@ -289,12 +360,50 @@ class TestObjSpace < Test::Unit::TestCase
def assert_dump_object(info, line)
loc = caller_locations(1, 1)[0]
assert_match(/"type":"STRING"/, info)
- assert_match(/"embedded":true, "bytesize":11, "value":"hello world", "encoding":"UTF-8"/, info)
+ assert_match(/"embedded":true, "bytesize":7, "value":"hello w", "encoding":"UTF-8"/, info)
assert_match(/"file":"#{Regexp.escape __FILE__}", "line":#{line}/, info)
assert_match(/"method":"#{loc.base_label}"/, info)
JSON.parse(info) if defined?(JSON)
end
+ def test_dump_array
+ # Empty array
+ info = ObjectSpace.dump([])
+ assert_include(info, '"length":0, "embedded":true')
+ assert_not_include(info, '"shared":true')
+
+ # Non-embed array
+ arr = (1..10).to_a
+ info = ObjectSpace.dump(arr)
+ assert_include(info, '"length":10')
+ assert_not_include(info, '"embedded":true')
+ assert_not_include(info, '"shared":true')
+
+ # Shared array
+ arr1 = (1..10).to_a
+ arr = []
+ arr.replace(arr1)
+ info = ObjectSpace.dump(arr)
+ assert_include(info, '"length":10, "shared":true')
+ assert_not_include(info, '"embedded":true')
+ end
+
+ def test_dump_object
+ klass = Class.new
+
+ # Empty object
+ info = ObjectSpace.dump(klass.new)
+ assert_include(info, '"embedded":true')
+ assert_include(info, '"ivars":0')
+
+ # Non-embed object
+ obj = klass.new
+ 5.times { |i| obj.instance_variable_set("@ivar#{i}", 0) }
+ info = ObjectSpace.dump(obj)
+ assert_not_include(info, '"embedded":true')
+ assert_include(info, '"ivars":5')
+ end
+
def test_dump_control_char
assert_include(ObjectSpace.dump("\x0f"), '"value":"\u000f"')
assert_include(ObjectSpace.dump("\C-?"), '"value":"\u007f"')
@@ -306,7 +415,7 @@ class TestObjSpace < Test::Unit::TestCase
assert_equal('true', ObjectSpace.dump(true))
assert_equal('false', ObjectSpace.dump(false))
assert_equal('0', ObjectSpace.dump(0))
- assert_equal('{"type":"SYMBOL", "value":"foo"}', ObjectSpace.dump(:foo))
+ assert_equal('{"type":"SYMBOL", "value":"test_dump_special_consts"}', ObjectSpace.dump(:test_dump_special_consts))
end
def test_dump_singleton_class
@@ -380,7 +489,7 @@ class TestObjSpace < Test::Unit::TestCase
@obj1 = Object.new
GC.start
@obj2 = Object.new
- ObjectSpace.dump_all(output: :stdout, since: gc_gen)
+ ObjectSpace.dump_all(output: :stdout, since: gc_gen, shapes: false)
end
p dump_my_heap_please
@@ -388,7 +497,7 @@ class TestObjSpace < Test::Unit::TestCase
assert_equal 'nil', output.pop
since = output.shift.to_i
assert_operator output.size, :>, 0
- generations = output.map { |l| JSON.parse(l)["generation"] }.uniq.sort
+ generations = output.map { |l| JSON.parse(l) }.map { |o| o["generation"] }.uniq.sort
assert_equal [since, since + 1], generations
end
end
@@ -431,6 +540,59 @@ class TestObjSpace < Test::Unit::TestCase
end
end
+ def test_dump_objects_dumps_page_slot_sizes
+ assert_in_out_err(%w[-robjspace], "#{<<-"begin;"}\n#{<<-'end;'}") do |output, error|
+ begin;
+ def dump_my_heap_please
+ ObjectSpace.dump_all(output: $stdout)
+ end
+
+ p $stdout == dump_my_heap_please
+ end;
+ assert_equal 'true', output.pop
+ assert(output.count > 1)
+ output.each { |l|
+ obj = JSON.parse(l)
+ next if obj["type"] == "ROOT"
+ next if obj["type"] == "SHAPE"
+
+ assert_not_nil obj["slot_size"]
+ assert_equal 0, obj["slot_size"] % (GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE] + GC::INTERNAL_CONSTANTS[:RVALUE_OVERHEAD])
+ }
+ end
+ end
+
+ def test_dump_callinfo_includes_mid
+ assert_in_out_err(%w[-robjspace --disable-gems], "#{<<-"begin;"}\n#{<<-'end;'}") do |output, error|
+ begin;
+ class Foo
+ def foo
+ super(bar: 123) # should not crash on 0 mid
+ end
+
+ def bar
+ baz(bar: 123) # mid: baz
+ end
+ end
+
+ ObjectSpace.dump_all(output: $stdout)
+ end;
+ assert_empty error
+ assert(output.count > 1)
+ assert_includes output.grep(/"imemo_type":"callinfo"/).join("\n"), '"mid":"baz"'
+ end
+ end
+
+ def test_dump_string_coderange
+ assert_includes ObjectSpace.dump("TEST STRING"), '"coderange":"7bit"'
+ unknown = "TEST STRING".dup.force_encoding(Encoding::UTF_16BE)
+ 2.times do # ensure that dumping the string doesn't mutate it
+ assert_includes ObjectSpace.dump(unknown), '"coderange":"unknown"'
+ end
+ assert_includes ObjectSpace.dump("Fée"), '"coderange":"valid"'
+ assert_includes ObjectSpace.dump("\xFF"), '"coderange":"broken"'
+ end
+
def test_dump_escapes_method_name
method_name = "foo\"bar"
klass = Class.new do
@@ -449,6 +611,13 @@ class TestObjSpace < Test::Unit::TestCase
ObjectSpace.trace_object_allocations_stop
end
+ def test_dump_includes_slot_size
+ str = "TEST"
+ dump = ObjectSpace.dump(str)
+
+ assert_includes dump, "\"slot_size\":#{GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE]}"
+ end
+
def test_dump_reference_addresses_match_dump_all_addresses
assert_in_out_err(%w[-robjspace], "#{<<-"begin;"}\n#{<<-'end;'}") do |output, error|
begin;
@@ -470,31 +639,70 @@ class TestObjSpace < Test::Unit::TestCase
end
end
+ def assert_test_string_entry_correct_in_dump_all(output)
+ # `TEST STRING` appears twice in the output of `ObjectSpace.dump_all`
+ # 1. To create the T_STRING object for the literal string "TEST STRING"
+ # 2. When it is assigned to the `str` variable with a new encoding
+ #
+ # This test makes assertions on the assignment to `str`, so we look for
+ # the second appearance of /TEST STRING/ in the output
+ test_string_in_dump_all = output.grep(/TEST2/)
+
+ begin
+ assert_equal(2, test_string_in_dump_all.size, "number of strings")
+ rescue Test::Unit::AssertionFailedError => e
+ STDERR.puts e.inspect
+ STDERR.puts test_string_in_dump_all
+ if test_string_in_dump_all.size == 3
+ STDERR.puts "This test is skipped because it seems hard to fix."
+ else
+ raise
+ end
+ end
+
+ strs = test_string_in_dump_all.reject do |s|
+ s.include?("fstring")
+ end
+
+ assert_equal(1, strs.length)
+
+ entry_hash = JSON.parse(strs[0])
+
+ assert_equal(5, entry_hash["bytesize"], "bytesize is wrong")
+ assert_equal("TEST2", entry_hash["value"], "value is wrong")
+ assert_equal("UTF-8", entry_hash["encoding"], "encoding is wrong")
+ assert_equal("-", entry_hash["file"], "file is wrong")
+ assert_equal(5, entry_hash["line"], "line is wrong")
+ assert_equal("dump_my_heap_please", entry_hash["method"], "method is wrong")
+ assert_not_nil(entry_hash["generation"])
+ end
+
def test_dump_all
- entry = /"bytesize":11, "value":"TEST STRING", "encoding":"UTF-8", "file":"-", "line":4, "method":"dump_my_heap_please", "generation":/
opts = %w[--disable-gem --disable=frozen-string-literal -robjspace]
assert_in_out_err(opts, "#{<<-"begin;"}#{<<-'end;'}") do |output, error|
+ # frozen_string_literal: false
begin;
def dump_my_heap_please
ObjectSpace.trace_object_allocations_start
GC.start
- str = "TEST STRING".force_encoding("UTF-8")
+ str = "TEST2".force_encoding("UTF-8")
ObjectSpace.dump_all(output: :stdout)
end
p dump_my_heap_please
end;
- assert_equal 'nil', output.pop
- assert_match(entry, output.grep(/TEST STRING/).join("\n"))
+
+ assert_test_string_entry_correct_in_dump_all(output)
end
assert_in_out_err(%w[-robjspace], "#{<<-"begin;"}#{<<-'end;'}") do |(output), (error)|
begin;
+ # frozen_string_literal: false
def dump_my_heap_please
ObjectSpace.trace_object_allocations_start
GC.start
- (str = "TEST STRING").force_encoding("UTF-8")
+ (str = "TEST2").force_encoding("UTF-8")
ObjectSpace.dump_all().path
end
@@ -503,7 +711,8 @@ class TestObjSpace < Test::Unit::TestCase
assert_nil(error)
dump = File.readlines(output)
File.unlink(output)
- assert_match(entry, dump.grep(/TEST STRING/).join("\n"))
+
+ assert_test_string_entry_correct_in_dump_all(dump)
end
if defined?(JSON)
@@ -620,6 +829,7 @@ class TestObjSpace < Test::Unit::TestCase
def test_objspace_trace
assert_in_out_err(%w[-robjspace/trace], "#{<<-"begin;"}\n#{<<-'end;'}") do |out, err|
begin;
+ # frozen_string_literal: false
a = "foo"
b = "b" + "a" + "r"
c = 42
@@ -627,9 +837,93 @@ class TestObjSpace < Test::Unit::TestCase
end;
assert_equal ["objspace/trace is enabled"], err
assert_equal 3, out.size
- assert_equal '"foo" @ -:2', out[0]
- assert_equal '"bar" @ -:3', out[1]
+ assert_equal '"foo" @ -:3', out[0]
+ assert_equal '"bar" @ -:4', out[1]
assert_equal '42', out[2]
end
end
+
+ def load_allocation_path_helper method, to_binary: false
+
+ Tempfile.create(["test_ruby_load_allocation_path", ".rb"]) do |t|
+ path = t.path
+ str = "#{Time.now.to_f.to_s}_#{rand.to_s}"
+ t.puts script = <<~RUBY
+ # frozen-string-literal: true
+ return if Time.now.to_i > 0
+ $gv = 'rnd-#{str}' # unreachable, but the string literal was written
+ RUBY
+
+ t.close
+
+ if to_binary
+ bin = RubyVM::InstructionSequence.compile_file(t.path).to_binary
+ bt = Tempfile.new(['test_ruby_load_allocation_path', '.yarb'], mode: File::Constants::WRONLY)
+ bt.write bin
+ bt.close
+
+ path = bt.path
+ end
+
+ assert_separately(%w[-robjspace -rtempfile], <<~RUBY)
+ GC.disable
+ path = "#{path}"
+ ObjectSpace.trace_object_allocations do
+ #{method}
+ end
+
+ n = 0
+ dump = ObjectSpace.dump_all(output: :string)
+ dump.each_line do |line|
+ if /"value":"rnd-#{str}"/ =~ line && /"frozen":true/ =~ line
+ assert Regexp.new('"file":"' + "#{path}") =~ line
+ assert Regexp.new('"line":') !~ line
+ n += 1
+ end
+ rescue ArgumentError
+ end
+
+ assert_equal(1, n)
+ RUBY
+ ensure
+ bt.unlink if bt
+ end
+ end
+
+ def test_load_allocation_path_load
+ load_allocation_path_helper 'load(path)'
+ end
+
+ def test_load_allocation_path_compile_file
+ load_allocation_path_helper 'RubyVM::InstructionSequence.compile_file(path)'
+ end
+
+ def test_load_allocation_path_load_from_binary
+ # load_allocation_path_helper 'iseq = RubyVM::InstructionSequence.load_from_binary(File.binread(path))', to_binary: true
+ end
+
+ def test_utf8_method_names
+ name = "utf8_â¨â•¯Â°â–¡Â°â©â•¯ï¸µâ”»â”â”»"
+ obj = ObjectSpace.trace_object_allocations do
+ __send__(name)
+ end
+ dump = ObjectSpace.dump(obj)
+ assert_equal name, JSON.parse(dump)["method"], dump
+ end
+
+ def test_dump_shapes
+ json = ObjectSpace.dump_shapes(output: :string)
+ json.each_line do |line|
+ assert_include(line, '"type":"SHAPE"')
+ end
+
+ assert_empty ObjectSpace.dump_shapes(output: :string, since: RubyVM.stat(:next_shape_id))
+ assert_equal 2, ObjectSpace.dump_shapes(output: :string, since: RubyVM.stat(:next_shape_id) - 2).lines.size
+ end
+
+ private
+
+ def utf8_â¨â•¯Â°â–¡Â°â©â•¯ï¸µâ”»â”â”»
+ "1#{2}"
+ end
end
diff --git a/test/objspace/test_ractor.rb b/test/objspace/test_ractor.rb
new file mode 100644
index 0000000000..4901eeae2e
--- /dev/null
+++ b/test/objspace/test_ractor.rb
@@ -0,0 +1,17 @@
+require "test/unit"
+
+class TestObjSpaceRactor < Test::Unit::TestCase
+ def test_tracing_does_not_crash
+ assert_ractor(<<~RUBY, require: 'objspace')
+ ObjectSpace.trace_object_allocations do
+ r = Ractor.new do
+ obj = 'a' * 1024
+ Ractor.yield obj
+ end
+
+ r.take
+ r.take
+ end
+ RUBY
+ end
+end
diff --git a/test/open-uri/test_ftp.rb b/test/open-uri/test_ftp.rb
new file mode 100644
index 0000000000..9698ff2777
--- /dev/null
+++ b/test/open-uri/test_ftp.rb
@@ -0,0 +1,216 @@
+# frozen_string_literal: true
+require 'test/unit'
+require 'socket'
+require 'open-uri'
+
+class TestOpenURIFtp < Test::Unit::TestCase
+ def with_env(h)
+ begin
+ old = {}
+ h.each_key {|k| old[k] = ENV[k] }
+ h.each {|k, v| ENV[k] = v }
+ yield
+ ensure
+ h.each_key {|k| ENV[k] = old[k] }
+ end
+ end
+
+ begin
+ require 'net/ftp'
+
+ def test_ftp_invalid_request
+ assert_raise(ArgumentError) { URI("ftp://127.0.0.1/").read }
+ assert_raise(ArgumentError) { URI("ftp://127.0.0.1/a%0Db").read }
+ assert_raise(ArgumentError) { URI("ftp://127.0.0.1/a%0Ab").read }
+ assert_raise(ArgumentError) { URI("ftp://127.0.0.1/a%0Db/f").read }
+ assert_raise(ArgumentError) { URI("ftp://127.0.0.1/a%0Ab/f").read }
+ assert_nothing_raised(URI::InvalidComponentError) { URI("ftp://127.0.0.1/d/f;type=x") }
+ end
+
+ def test_ftp
+ TCPServer.open("127.0.0.1", 0) {|serv|
+ _, port, _, host = serv.addr
+ th = Thread.new {
+ s = serv.accept
+ begin
+ s.print "220 Test FTP Server\r\n"
+ assert_equal("USER anonymous\r\n", s.gets); s.print "331 name ok\r\n"
+ assert_match(/\APASS .*\r\n\z/, s.gets); s.print "230 logged in\r\n"
+ assert_equal("TYPE I\r\n", s.gets); s.print "200 type set to I\r\n"
+ assert_equal("CWD foo\r\n", s.gets); s.print "250 CWD successful\r\n"
+ assert_equal("PASV\r\n", s.gets)
+ TCPServer.open("127.0.0.1", 0) {|data_serv|
+ _, data_serv_port, _, _ = data_serv.addr
+ hi = data_serv_port >> 8
+ lo = data_serv_port & 0xff
+ s.print "227 Entering Passive Mode (127,0,0,1,#{hi},#{lo}).\r\n"
+ assert_equal("RETR bar\r\n", s.gets); s.print "150 file okay\r\n"
+ data_sock = data_serv.accept
+ begin
+ data_sock << "content"
+ ensure
+ data_sock.close
+ end
+ s.print "226 transfer complete\r\n"
+ assert_nil(s.gets)
+ }
+ ensure
+ s.close if s
+ end
+ }
+ begin
+ content = URI("ftp://#{host}:#{port}/foo/bar").read
+ assert_equal("content", content)
+ ensure
+ Thread.kill(th)
+ th.join
+ end
+ }
+ end
+
+ def test_ftp_active
+ TCPServer.open("127.0.0.1", 0) {|serv|
+ _, port, _, host = serv.addr
+ th = Thread.new {
+ s = serv.accept
+ begin
+ content = "content"
+ s.print "220 Test FTP Server\r\n"
+ assert_equal("USER anonymous\r\n", s.gets); s.print "331 name ok\r\n"
+ assert_match(/\APASS .*\r\n\z/, s.gets); s.print "230 logged in\r\n"
+ assert_equal("TYPE I\r\n", s.gets); s.print "200 type set to I\r\n"
+ assert_equal("CWD foo\r\n", s.gets); s.print "250 CWD successful\r\n"
+ assert(m = /\APORT 127,0,0,1,(\d+),(\d+)\r\n\z/.match(s.gets))
+ active_port = m[1].to_i << 8 | m[2].to_i
+ TCPSocket.open("127.0.0.1", active_port) {|data_sock|
+ s.print "200 data connection opened\r\n"
+ assert_equal("RETR bar\r\n", s.gets); s.print "150 file okay\r\n"
+ begin
+ data_sock << content
+ ensure
+ data_sock.close
+ end
+ s.print "226 transfer complete\r\n"
+ assert_nil(s.gets)
+ }
+ ensure
+ s.close if s
+ end
+ }
+ begin
+ content = URI("ftp://#{host}:#{port}/foo/bar").read(:ftp_active_mode=>true)
+ assert_equal("content", content)
+ ensure
+ Thread.kill(th)
+ th.join
+ end
+ }
+ end
+
+ def test_ftp_ascii
+ TCPServer.open("127.0.0.1", 0) {|serv|
+ _, port, _, host = serv.addr
+ th = Thread.new {
+ s = serv.accept
+ begin
+ content = "content"
+ s.print "220 Test FTP Server\r\n"
+ assert_equal("USER anonymous\r\n", s.gets); s.print "331 name ok\r\n"
+ assert_match(/\APASS .*\r\n\z/, s.gets); s.print "230 logged in\r\n"
+ assert_equal("TYPE I\r\n", s.gets); s.print "200 type set to I\r\n"
+ assert_equal("CWD /foo\r\n", s.gets); s.print "250 CWD successful\r\n"
+ assert_equal("TYPE A\r\n", s.gets); s.print "200 type set to A\r\n"
+ assert_equal("SIZE bar\r\n", s.gets); s.print "213 #{content.bytesize}\r\n"
+ assert_equal("PASV\r\n", s.gets)
+ TCPServer.open("127.0.0.1", 0) {|data_serv|
+ _, data_serv_port, _, _ = data_serv.addr
+ hi = data_serv_port >> 8
+ lo = data_serv_port & 0xff
+ s.print "227 Entering Passive Mode (127,0,0,1,#{hi},#{lo}).\r\n"
+ assert_equal("RETR bar\r\n", s.gets); s.print "150 file okay\r\n"
+ data_sock = data_serv.accept
+ begin
+ data_sock << content
+ ensure
+ data_sock.close
+ end
+ s.print "226 transfer complete\r\n"
+ assert_nil(s.gets)
+ }
+ ensure
+ s.close if s
+ end
+ }
+ begin
+ length = []
+ progress = []
+ content = URI("ftp://#{host}:#{port}/%2Ffoo/b%61r;type=a").read(
+ :content_length_proc => lambda {|n| length << n },
+ :progress_proc => lambda {|n| progress << n })
+ assert_equal("content", content)
+ assert_equal([7], length)
+ assert_equal(7, progress.inject(&:+))
+ ensure
+ Thread.kill(th)
+ th.join
+ end
+ }
+ end
+ rescue LoadError
+ # net-ftp is the bundled gems at Ruby 3.1
+ end
+
+ def test_ftp_over_http_proxy
+ TCPServer.open("127.0.0.1", 0) {|proxy_serv|
+ proxy_port = proxy_serv.addr[1]
+ th = Thread.new {
+ proxy_sock = proxy_serv.accept
+ begin
+ req = proxy_sock.gets("\r\n\r\n")
+ assert_match(%r{\AGET ftp://192.0.2.1/foo/bar }, req)
+ proxy_sock.print "HTTP/1.0 200 OK\r\n"
+ proxy_sock.print "Content-Length: 4\r\n\r\n"
+ proxy_sock.print "ab\r\n"
+ ensure
+ proxy_sock.close
+ end
+ }
+ begin
+ with_env('ftp_proxy'=>"http://127.0.0.1:#{proxy_port}") {
+ content = URI("ftp://192.0.2.1/foo/bar").read
+ assert_equal("ab\r\n", content)
+ }
+ ensure
+ Thread.kill(th)
+ th.join
+ end
+ }
+ end
+
+ def test_ftp_over_http_proxy_auth
+ TCPServer.open("127.0.0.1", 0) {|proxy_serv|
+ proxy_port = proxy_serv.addr[1]
+ th = Thread.new {
+ proxy_sock = proxy_serv.accept
+ begin
+ req = proxy_sock.gets("\r\n\r\n")
+ assert_match(%r{\AGET ftp://192.0.2.1/foo/bar }, req)
+ assert_match(%r{Proxy-Authorization: Basic #{['proxy-user:proxy-password'].pack('m').chomp}\r\n}, req)
+ proxy_sock.print "HTTP/1.0 200 OK\r\n"
+ proxy_sock.print "Content-Length: 4\r\n\r\n"
+ proxy_sock.print "ab\r\n"
+ ensure
+ proxy_sock.close
+ end
+ }
+ begin
+ content = URI("ftp://192.0.2.1/foo/bar").read(
+ :proxy_http_basic_authentication => ["http://127.0.0.1:#{proxy_port}", "proxy-user", "proxy-password"])
+ assert_equal("ab\r\n", content)
+ ensure
+ Thread.kill(th)
+ th.join
+ end
+ }
+ end
+end
diff --git a/test/open-uri/test_open-uri.rb b/test/open-uri/test_open-uri.rb
index 72ebcdb0da..0679180ce9 100644
--- a/test/open-uri/test_open-uri.rb
+++ b/test/open-uri/test_open-uri.rb
@@ -1,75 +1,18 @@
# frozen_string_literal: true
require 'test/unit'
require 'open-uri'
-require 'webrick'
-require 'webrick/httpproxy'
+require 'stringio'
+require_relative 'utils'
begin
require 'zlib'
rescue LoadError
end
class TestOpenURI < Test::Unit::TestCase
-
- NullLog = Object.new
- def NullLog.<<(arg)
- #puts arg if / INFO / !~ arg
- end
-
- def with_http(log_tester=lambda {|log| assert_equal([], log) })
- log = []
- logger = WEBrick::Log.new(log, WEBrick::BasicLog::WARN)
- Dir.mktmpdir {|dr|
- srv = WEBrick::HTTPServer.new({
- :DocumentRoot => dr,
- :ServerType => Thread,
- :Logger => logger,
- :AccessLog => [[NullLog, ""]],
- :BindAddress => '127.0.0.1',
- :Port => 0})
- _, port, _, host = srv.listeners[0].addr
- server_thread = srv.start
- server_thread2 = Thread.new {
- server_thread.join
- if log_tester
- log_tester.call(log)
- end
- }
- client_thread = Thread.new {
- begin
- yield srv, dr, "http://#{host}:#{port}", server_thread, log
- ensure
- srv.shutdown
- end
- }
- assert_join_threads([client_thread, server_thread2])
- }
- ensure
- WEBrick::Utils::TimeoutHandler.terminate
- end
-
- def with_env(h)
- begin
- old = {}
- h.each_key {|k| old[k] = ENV[k] }
- h.each {|k, v| ENV[k] = v }
- yield
- ensure
- h.each_key {|k| ENV[k] = old[k] }
- end
- end
-
- def setup
- @proxies = %w[http_proxy HTTP_PROXY ftp_proxy FTP_PROXY no_proxy]
- @old_proxies = @proxies.map {|k| ENV[k] }
- @proxies.each {|k| ENV[k] = nil }
- end
-
- def teardown
- @proxies.each_with_index {|k, i| ENV[k] = @old_proxies[i] }
- end
+ include TestOpenURIUtils
def test_200_uri_open
- with_http {|srv, dr, url|
+ with_http {|srv, url|
srv.mount_proc("/urifoo200", lambda { |req, res| res.body = "urifoo200" } )
URI.open("#{url}/urifoo200") {|f|
assert_equal("200", f.status[0])
@@ -79,7 +22,7 @@ class TestOpenURI < Test::Unit::TestCase
end
def test_200
- with_http {|srv, dr, url|
+ with_http {|srv, url|
srv.mount_proc("/foo200", lambda { |req, res| res.body = "foo200" } )
URI.open("#{url}/foo200") {|f|
assert_equal("200", f.status[0])
@@ -89,7 +32,7 @@ class TestOpenURI < Test::Unit::TestCase
end
def test_200big
- with_http {|srv, dr, url|
+ with_http {|srv, url|
content = "foo200big"*10240
srv.mount_proc("/foo200big", lambda { |req, res| res.body = content } )
URI.open("#{url}/foo200big") {|f|
@@ -104,14 +47,14 @@ class TestOpenURI < Test::Unit::TestCase
assert_equal(1, server_log.length)
assert_match(%r{ERROR `/not-exist' not found}, server_log[0])
}
- with_http(log_tester) {|srv, dr, url, server_thread, server_log|
+ with_http(log_tester) {|srv, url, server_thread, server_log|
exc = assert_raise(OpenURI::HTTPError) { URI.open("#{url}/not-exist") {} }
assert_equal("404", exc.io.status[0])
}
end
def test_open_uri
- with_http {|srv, dr, url|
+ with_http {|srv, url|
srv.mount_proc("/foo_ou", lambda { |req, res| res.body = "foo_ou" } )
u = URI("#{url}/foo_ou")
URI.open(u) {|f|
@@ -155,7 +98,7 @@ class TestOpenURI < Test::Unit::TestCase
URI("http://example.com/").read(open_timeout: 0.000001)
end if false # avoid external resources in tests
- with_http {|srv, dr, url|
+ with_http {|srv, url|
url += '/'
srv.mount_proc('/', lambda { |_, res| res.body = 'hi' })
begin
@@ -172,8 +115,21 @@ class TestOpenURI < Test::Unit::TestCase
assert_raise(ArgumentError) { URI.open("http://127.0.0.1/", :invalid_option=>true) {} }
end
+ def test_pass_keywords
+ begin
+ f = URI.open(File::NULL, mode: 0666)
+ assert_kind_of File, f
+ ensure
+ f&.close
+ end
+
+ o = Object.new
+ def o.open(foo: ) foo end
+ assert_equal 1, URI.open(o, foo: 1)
+ end
+
def test_mode
- with_http {|srv, dr, url|
+ with_http {|srv, url|
srv.mount_proc("/mode", lambda { |req, res| res.body = "mode" } )
URI.open("#{url}/mode", "r") {|f|
assert_equal("200", f.status[0])
@@ -195,7 +151,7 @@ class TestOpenURI < Test::Unit::TestCase
end
def test_without_block
- with_http {|srv, dr, url|
+ with_http {|srv, url|
srv.mount_proc("/without_block", lambda { |req, res| res.body = "without_block" } )
begin
f = URI.open("#{url}/without_block")
@@ -208,7 +164,7 @@ class TestOpenURI < Test::Unit::TestCase
end
def test_close_in_block_small
- with_http {|srv, dr, url|
+ with_http {|srv, url|
srv.mount_proc("/close200", lambda { |req, res| res.body = "close200" } )
assert_nothing_raised {
URI.open("#{url}/close200") {|f|
@@ -219,7 +175,7 @@ class TestOpenURI < Test::Unit::TestCase
end
def test_close_in_block_big
- with_http {|srv, dr, url|
+ with_http {|srv, url|
content = "close200big"*10240
srv.mount_proc("/close200big", lambda { |req, res| res.body = content } )
assert_nothing_raised {
@@ -233,8 +189,8 @@ class TestOpenURI < Test::Unit::TestCase
def test_header
myheader1 = 'barrrr'
myheader2 = nil
- with_http {|srv, dr, url|
- srv.mount_proc("/h/") {|req, res| myheader2 = req['myheader']; res.body = "foo" }
+ with_http {|srv, url|
+ srv.mount_proc("/h/", lambda {|req, res| myheader2 = req['myheader']; res.body = "foo" } )
URI.open("#{url}/h/", 'MyHeader'=>myheader1) {|f|
assert_equal("foo", f.read)
assert_equal(myheader1, myheader2)
@@ -254,175 +210,11 @@ class TestOpenURI < Test::Unit::TestCase
}
end
- def test_proxy
- with_http {|srv, dr, url|
- proxy_log = StringIO.new(''.dup)
- proxy_logger = WEBrick::Log.new(proxy_log, WEBrick::BasicLog::WARN)
- proxy_auth_log = ''.dup
- proxy = WEBrick::HTTPProxyServer.new({
- :ServerType => Thread,
- :Logger => proxy_logger,
- :AccessLog => [[NullLog, ""]],
- :ProxyAuthProc => lambda {|req, res|
- proxy_auth_log << req.request_line
- },
- :BindAddress => '127.0.0.1',
- :Port => 0})
- _, proxy_port, _, proxy_host = proxy.listeners[0].addr
- proxy_url = "http://#{proxy_host}:#{proxy_port}/"
- begin
- proxy_thread = proxy.start
- srv.mount_proc("/proxy", lambda { |req, res| res.body = "proxy" } )
- URI.open("#{url}/proxy", :proxy=>proxy_url) {|f|
- assert_equal("200", f.status[0])
- assert_equal("proxy", f.read)
- }
- assert_match(/#{Regexp.quote url}/, proxy_auth_log); proxy_auth_log.clear
- URI.open("#{url}/proxy", :proxy=>URI(proxy_url)) {|f|
- assert_equal("200", f.status[0])
- assert_equal("proxy", f.read)
- }
- assert_match(/#{Regexp.quote url}/, proxy_auth_log); proxy_auth_log.clear
- URI.open("#{url}/proxy", :proxy=>nil) {|f|
- assert_equal("200", f.status[0])
- assert_equal("proxy", f.read)
- }
- assert_equal("", proxy_auth_log); proxy_auth_log.clear
- assert_raise(ArgumentError) {
- URI.open("#{url}/proxy", :proxy=>:invalid) {}
- }
- assert_equal("", proxy_auth_log); proxy_auth_log.clear
- with_env("http_proxy"=>proxy_url) {
- # should not use proxy for 127.0.0.0/8.
- URI.open("#{url}/proxy") {|f|
- assert_equal("200", f.status[0])
- assert_equal("proxy", f.read)
- }
- }
- assert_equal("", proxy_auth_log); proxy_auth_log.clear
- ensure
- proxy.shutdown
- proxy_thread.join
- end
- assert_equal("", proxy_log.string)
- }
- end
-
- def test_proxy_http_basic_authentication_failure
- with_http {|srv, dr, url|
- proxy_log = StringIO.new(''.dup)
- proxy_logger = WEBrick::Log.new(proxy_log, WEBrick::BasicLog::WARN)
- proxy_auth_log = ''.dup
- proxy = WEBrick::HTTPProxyServer.new({
- :ServerType => Thread,
- :Logger => proxy_logger,
- :AccessLog => [[NullLog, ""]],
- :ProxyAuthProc => lambda {|req, res|
- proxy_auth_log << req.request_line
- if req["Proxy-Authorization"] != "Basic #{['user:pass'].pack('m').chomp}"
- raise WEBrick::HTTPStatus::ProxyAuthenticationRequired
- end
- },
- :BindAddress => '127.0.0.1',
- :Port => 0})
- _, proxy_port, _, proxy_host = proxy.listeners[0].addr
- proxy_url = "http://#{proxy_host}:#{proxy_port}/"
- begin
- th = proxy.start
- srv.mount_proc("/proxy", lambda { |req, res| res.body = "proxy" } )
- exc = assert_raise(OpenURI::HTTPError) { URI.open("#{url}/proxy", :proxy=>proxy_url) {} }
- assert_equal("407", exc.io.status[0])
- assert_match(/#{Regexp.quote url}/, proxy_auth_log); proxy_auth_log.clear
- ensure
- proxy.shutdown
- th.join
- end
- assert_match(/ERROR WEBrick::HTTPStatus::ProxyAuthenticationRequired/, proxy_log.string)
- }
- end
-
- def test_proxy_http_basic_authentication_success
- with_http {|srv, dr, url|
- proxy_log = StringIO.new(''.dup)
- proxy_logger = WEBrick::Log.new(proxy_log, WEBrick::BasicLog::WARN)
- proxy_auth_log = ''.dup
- proxy = WEBrick::HTTPProxyServer.new({
- :ServerType => Thread,
- :Logger => proxy_logger,
- :AccessLog => [[NullLog, ""]],
- :ProxyAuthProc => lambda {|req, res|
- proxy_auth_log << req.request_line
- if req["Proxy-Authorization"] != "Basic #{['user:pass'].pack('m').chomp}"
- raise WEBrick::HTTPStatus::ProxyAuthenticationRequired
- end
- },
- :BindAddress => '127.0.0.1',
- :Port => 0})
- _, proxy_port, _, proxy_host = proxy.listeners[0].addr
- proxy_url = "http://#{proxy_host}:#{proxy_port}/"
- begin
- th = proxy.start
- srv.mount_proc("/proxy", lambda { |req, res| res.body = "proxy" } )
- URI.open("#{url}/proxy",
- :proxy_http_basic_authentication=>[proxy_url, "user", "pass"]) {|f|
- assert_equal("200", f.status[0])
- assert_equal("proxy", f.read)
- }
- assert_match(/#{Regexp.quote url}/, proxy_auth_log); proxy_auth_log.clear
- assert_raise(ArgumentError) {
- URI.open("#{url}/proxy",
- :proxy_http_basic_authentication=>[true, "user", "pass"]) {}
- }
- assert_equal("", proxy_auth_log); proxy_auth_log.clear
- ensure
- proxy.shutdown
- th.join
- end
- assert_equal("", proxy_log.string)
- }
- end
-
- def test_authenticated_proxy_http_basic_authentication_success
- with_http {|srv, dr, url|
- proxy_log = StringIO.new(''.dup)
- proxy_logger = WEBrick::Log.new(proxy_log, WEBrick::BasicLog::WARN)
- proxy_auth_log = ''.dup
- proxy = WEBrick::HTTPProxyServer.new({
- :ServerType => Thread,
- :Logger => proxy_logger,
- :AccessLog => [[NullLog, ""]],
- :ProxyAuthProc => lambda {|req, res|
- proxy_auth_log << req.request_line
- if req["Proxy-Authorization"] != "Basic #{['user:pass'].pack('m').chomp}"
- raise WEBrick::HTTPStatus::ProxyAuthenticationRequired
- end
- },
- :BindAddress => '127.0.0.1',
- :Port => 0})
- _, proxy_port, _, proxy_host = proxy.listeners[0].addr
- proxy_url = "http://user:pass@#{proxy_host}:#{proxy_port}/"
- begin
- th = proxy.start
- srv.mount_proc("/proxy", lambda { |req, res| res.body = "proxy" } )
- URI.open("#{url}/proxy", :proxy => proxy_url) {|f|
- assert_equal("200", f.status[0])
- assert_equal("proxy", f.read)
- }
- assert_match(/#{Regexp.quote url}/, proxy_auth_log); proxy_auth_log.clear
- assert_equal("", proxy_auth_log); proxy_auth_log.clear
- ensure
- proxy.shutdown
- th.join
- end
- assert_equal("", proxy_log.string)
- }
- end
-
def test_redirect
- with_http {|srv, dr, url|
- srv.mount_proc("/r1/") {|req, res| res.status = 301; res["location"] = "#{url}/r2"; res.body = "r1" }
- srv.mount_proc("/r2/") {|req, res| res.body = "r2" }
- srv.mount_proc("/to-file/") {|req, res| res.status = 301; res["location"] = "file:///foo" }
+ with_http {|srv, url|
+ srv.mount_proc("/r1/", lambda {|req, res| res.status = 301; res["location"] = "#{url}/r2"; res.body = "r1" } )
+ srv.mount_proc("/r2/", lambda {|req, res| res.body = "r2" } )
+ srv.mount_proc("/to-file/", lambda {|req, res| res.status = 301; res["location"] = "file:///foo" } )
URI.open("#{url}/r1/") {|f|
assert_equal("#{url}/r2", f.base_uri.to_s)
assert_equal("r2", f.read)
@@ -433,9 +225,9 @@ class TestOpenURI < Test::Unit::TestCase
end
def test_redirect_loop
- with_http {|srv, dr, url|
- srv.mount_proc("/r1/") {|req, res| res.status = 301; res["location"] = "#{url}/r2"; res.body = "r1" }
- srv.mount_proc("/r2/") {|req, res| res.status = 301; res["location"] = "#{url}/r1"; res.body = "r2" }
+ with_http {|srv, url|
+ srv.mount_proc("/r1/", lambda {|req, res| res.status = 301; res["location"] = "#{url}/r2"; res.body = "r1" } )
+ srv.mount_proc("/r2/", lambda {|req, res| res.status = 301; res["location"] = "#{url}/r1"; res.body = "r2" } )
assert_raise(RuntimeError) { URI.open("#{url}/r1/") {} }
}
end
@@ -500,20 +292,20 @@ class TestOpenURI < Test::Unit::TestCase
end
def setup_redirect_auth(srv, url)
- srv.mount_proc("/r1/") {|req, res|
+ srv.mount_proc("/r1/", lambda {|req, res|
res.status = 301
res["location"] = "#{url}/r2"
- }
- srv.mount_proc("/r2/") {|req, res|
+ })
+ srv.mount_proc("/r2/", lambda {|req, res|
if req["Authorization"] != "Basic #{['user:pass'].pack('m').chomp}"
- raise WEBrick::HTTPStatus::Unauthorized
+ raise Unauthorized
end
res.body = "r2"
- }
+ })
end
def test_redirect_auth_success
- with_http {|srv, dr, url|
+ with_http {|srv, url|
setup_redirect_auth(srv, url)
URI.open("#{url}/r2/", :http_basic_authentication=>['user', 'pass']) {|f|
assert_equal("r2", f.read)
@@ -524,9 +316,9 @@ class TestOpenURI < Test::Unit::TestCase
def test_redirect_auth_failure_r2
log_tester = lambda {|server_log|
assert_equal(1, server_log.length)
- assert_match(/ERROR WEBrick::HTTPStatus::Unauthorized/, server_log[0])
+ assert_match(/ERROR Unauthorized/, server_log[0])
}
- with_http(log_tester) {|srv, dr, url, server_thread, server_log|
+ with_http(log_tester) {|srv, url, server_thread, server_log|
setup_redirect_auth(srv, url)
exc = assert_raise(OpenURI::HTTPError) { URI.open("#{url}/r2/") {} }
assert_equal("401", exc.io.status[0])
@@ -536,23 +328,102 @@ class TestOpenURI < Test::Unit::TestCase
def test_redirect_auth_failure_r1
log_tester = lambda {|server_log|
assert_equal(1, server_log.length)
- assert_match(/ERROR WEBrick::HTTPStatus::Unauthorized/, server_log[0])
+ assert_match(/ERROR Unauthorized/, server_log[0])
}
- with_http(log_tester) {|srv, dr, url, server_thread, server_log|
+ with_http(log_tester) {|srv, url, server_thread, server_log|
setup_redirect_auth(srv, url)
exc = assert_raise(OpenURI::HTTPError) { URI.open("#{url}/r1/", :http_basic_authentication=>['user', 'pass']) {} }
assert_equal("401", exc.io.status[0])
}
end
+ def test_redirect_without_request_specific_fields_hash
+ authorization_header = nil
+ redirected_authorization_header = nil
+ with_http {|srv, url|
+ srv.mount_proc("/r1/", lambda {|req, res| res.status = 301; res["location"] = "#{url}/r2"; authorization_header = req["Authorization"]; } )
+ srv.mount_proc("/r2/", lambda {|req, res| redirected_authorization_header = req["Authorization"]; } )
+ URI.open("#{url}/r1/", "Authorization" => "dummy_token") {|f|
+ assert_equal("dummy_token", authorization_header)
+ assert_equal("#{url}/r2", f.base_uri.to_s)
+ assert_equal("dummy_token", redirected_authorization_header)
+ }
+ }
+ end
+
+ def test_redirect_with_request_specific_fields_hash
+ authorization_header = nil
+ redirected_authorization_header = "exposed_dummy_token"
+ with_http {|srv, url|
+ srv.mount_proc("/r1/", lambda {|req, res| res.status = 301; res["location"] = "#{url}/r2"; authorization_header = req["Authorization"]; } )
+ srv.mount_proc("/r2/", lambda {|req, res| redirected_authorization_header = req["Authorization"]; } )
+ URI.open("#{url}/r1/", request_specific_fields: {"Authorization" => "dummy_token"}) {|f|
+ assert_equal("dummy_token", authorization_header)
+ assert_equal("#{url}/r2", f.base_uri.to_s)
+ assert_equal(nil, redirected_authorization_header)
+ }
+ }
+ end
+
+ def test_redirect_with_request_specific_fields_proc
+ authorization_header = nil
+ redirected_authorization_header = nil
+
+ modify_authorization_header = Proc.new do |uri|
+ authorization_token = if uri.to_s.include?("/r1")
+ "dummy_token"
+ else
+ "masked_dummy_token"
+ end
+ { "Authorization" => authorization_token }
+ end
+
+ with_http {|srv, url|
+ srv.mount_proc("/r1/", lambda {|req, res| res.status = 301; res["location"] = "#{url}/r2"; authorization_header = req["Authorization"] } )
+ srv.mount_proc("/r2/", lambda {|req, res| redirected_authorization_header = req["Authorization"]; } )
+ URI.open("#{url}/r1/", request_specific_fields: modify_authorization_header) {|f|
+ assert_equal("dummy_token", authorization_header)
+ assert_equal("#{url}/r2", f.base_uri.to_s)
+ assert_equal("masked_dummy_token", redirected_authorization_header)
+ }
+ }
+ end
+
+ def test_redirect_with_invalid_request_specific_fields_format
+ with_http {|srv, url|
+ srv.mount_proc("/r1/", lambda {|req, res| res.body = "r1" } )
+ exc = assert_raise(ArgumentError) { URI.open("#{url}/r1/", request_specific_fields: "dummy_token") {} }
+ assert_equal('Invalid request_specific_fields option: "dummy_token"', exc.message)
+ }
+ end
+
+ def test_max_redirects_success
+ with_http {|srv, url|
+ srv.mount_proc("/r1/", lambda {|req, res| res.status = 301; res["location"] = "#{url}/r2"; res.body = "r1" } )
+ srv.mount_proc("/r2/", lambda {|req, res| res.status = 301; res["location"] = "#{url}/r3"; res.body = "r2" } )
+ srv.mount_proc("/r3/", lambda {|req, res| res.body = "r3" } )
+ URI.open("#{url}/r1/", max_redirects: 2) { |f| assert_equal("r3", f.read) }
+ }
+ end
+
+ def test_max_redirects_too_many
+ with_http {|srv, url|
+ srv.mount_proc("/r1/", lambda {|req, res| res.status = 301; res["location"] = "#{url}/r2"; res.body = "r1" } )
+ srv.mount_proc("/r2/", lambda {|req, res| res.status = 301; res["location"] = "#{url}/r3"; res.body = "r2" } )
+ srv.mount_proc("/r3/", lambda {|req, res| res.body = "r3" } )
+ exc = assert_raise(OpenURI::TooManyRedirects) { URI.open("#{url}/r1/", max_redirects: 1) {} }
+ assert_equal("Too many redirects", exc.message)
+ }
+ end
+
def test_userinfo
assert_raise(ArgumentError) { URI.open("http://user:pass@127.0.0.1/") {} }
end
def test_progress
- with_http {|srv, dr, url|
+ with_http {|srv, url|
content = "a" * 100000
- srv.mount_proc("/data/") {|req, res| res.body = content }
+ srv.mount_proc("/data/", lambda {|req, res| res.body = content })
length = []
progress = []
URI.open("#{url}/data/",
@@ -570,9 +441,9 @@ class TestOpenURI < Test::Unit::TestCase
end
def test_progress_chunked
- with_http {|srv, dr, url|
+ with_http {|srv, url|
content = "a" * 100000
- srv.mount_proc("/data/") {|req, res| res.body = content; res.chunked = true }
+ srv.mount_proc("/data/", lambda {|req, res| res.body = content; res.chunked = true } )
length = []
progress = []
URI.open("#{url}/data/",
@@ -590,7 +461,7 @@ class TestOpenURI < Test::Unit::TestCase
end
def test_uri_read
- with_http {|srv, dr, url|
+ with_http {|srv, url|
srv.mount_proc("/uriread", lambda { |req, res| res.body = "uriread" } )
data = URI("#{url}/uriread").read
assert_equal("200", data.status[0])
@@ -599,12 +470,12 @@ class TestOpenURI < Test::Unit::TestCase
end
def test_encoding
- with_http {|srv, dr, url|
+ with_http {|srv, url|
content_u8 = "\u3042"
content_ej = "\xa2\xa4".dup.force_encoding("euc-jp")
- srv.mount_proc("/u8/") {|req, res| res.body = content_u8; res['content-type'] = 'text/plain; charset=utf-8' }
- srv.mount_proc("/ej/") {|req, res| res.body = content_ej; res['content-type'] = 'TEXT/PLAIN; charset=EUC-JP' }
- srv.mount_proc("/nc/") {|req, res| res.body = "aa"; res['content-type'] = 'Text/Plain' }
+ srv.mount_proc("/u8/", lambda {|req, res| res.body = content_u8; res['content-type'] = 'text/plain; charset=utf-8' } )
+ srv.mount_proc("/ej/", lambda {|req, res| res.body = content_ej; res['content-type'] = 'TEXT/PLAIN; charset=EUC-JP' } )
+ srv.mount_proc("/nc/", lambda {|req, res| res.body = "aa"; res['content-type'] = 'Text/Plain' } )
URI.open("#{url}/u8/") {|f|
assert_equal(content_u8, f.read)
assert_equal("text/plain", f.content_type)
@@ -643,9 +514,9 @@ class TestOpenURI < Test::Unit::TestCase
end
def test_quoted_attvalue
- with_http {|srv, dr, url|
+ with_http {|srv, url|
content_u8 = "\u3042"
- srv.mount_proc("/qu8/") {|req, res| res.body = content_u8; res['content-type'] = 'text/plain; charset="utf\-8"' }
+ srv.mount_proc("/qu8/", lambda {|req, res| res.body = content_u8; res['content-type'] = 'text/plain; charset="utf\-8"' } )
URI.open("#{url}/qu8/") {|f|
assert_equal(content_u8, f.read)
assert_equal("text/plain", f.content_type)
@@ -655,8 +526,8 @@ class TestOpenURI < Test::Unit::TestCase
end
def test_last_modified
- with_http {|srv, dr, url|
- srv.mount_proc("/data/") {|req, res| res.body = "foo"; res['last-modified'] = 'Fri, 07 Aug 2009 06:05:04 GMT' }
+ with_http {|srv, url|
+ srv.mount_proc("/data/", lambda {|req, res| res.body = "foo"; res['last-modified'] = 'Fri, 07 Aug 2009 06:05:04 GMT' } )
URI.open("#{url}/data/") {|f|
assert_equal("foo", f.read)
assert_equal(Time.utc(2009,8,7,6,5,4), f.last_modified)
@@ -665,12 +536,12 @@ class TestOpenURI < Test::Unit::TestCase
end
def test_content_encoding
- with_http {|srv, dr, url|
+ with_http {|srv, url|
content = "abc" * 10000
Zlib::GzipWriter.wrap(StringIO.new(content_gz="".b)) {|z| z.write content }
- srv.mount_proc("/data/") {|req, res| res.body = content_gz; res['content-encoding'] = 'gzip' }
- srv.mount_proc("/data2/") {|req, res| res.body = content_gz; res['content-encoding'] = 'gzip'; res.chunked = true }
- srv.mount_proc("/noce/") {|req, res| res.body = content_gz }
+ srv.mount_proc("/data/", lambda {|req, res| res.body = content_gz; res['content-encoding'] = 'gzip' } )
+ srv.mount_proc("/data2/", lambda {|req, res| res.body = content_gz; res['content-encoding'] = 'gzip'; res.chunked = true } )
+ srv.mount_proc("/noce/", lambda {|req, res| res.body = content_gz } )
URI.open("#{url}/data/") {|f|
assert_equal [], f.content_encoding
assert_equal(content, f.read)
@@ -687,12 +558,12 @@ class TestOpenURI < Test::Unit::TestCase
end if defined?(Zlib::GzipWriter)
def test_multiple_cookies
- with_http {|srv, dr, url|
- srv.mount_proc("/mcookie/") {|req, res|
+ with_http {|srv, url|
+ srv.mount_proc("/mcookie/", lambda {|req, res|
res.cookies << "name1=value1; blabla"
res.cookies << "name2=value2; blabla"
res.body = "foo"
- }
+ })
URI.open("#{url}/mcookie/") {|f|
assert_equal("foo", f.read)
assert_equal(["name1=value1; blabla", "name2=value2; blabla"],
@@ -703,204 +574,14 @@ class TestOpenURI < Test::Unit::TestCase
# 192.0.2.0/24 is TEST-NET. [RFC3330]
- begin
- require 'net/ftp'
+ def test_meta_init_doesnt_bump_global_constant_state
+ omit "RubyVM.stat not defined" unless defined? RubyVM.stat
+ omit unless RubyVM.stat.has_key?(:global_constant_state)
- def test_ftp_invalid_request
- assert_raise(ArgumentError) { URI("ftp://127.0.0.1/").read }
- assert_raise(ArgumentError) { URI("ftp://127.0.0.1/a%0Db").read }
- assert_raise(ArgumentError) { URI("ftp://127.0.0.1/a%0Ab").read }
- assert_raise(ArgumentError) { URI("ftp://127.0.0.1/a%0Db/f").read }
- assert_raise(ArgumentError) { URI("ftp://127.0.0.1/a%0Ab/f").read }
- assert_nothing_raised(URI::InvalidComponentError) { URI("ftp://127.0.0.1/d/f;type=x") }
- end
+ OpenURI::Meta.init(Object.new) # prewarm
- def test_ftp
- TCPServer.open("127.0.0.1", 0) {|serv|
- _, port, _, host = serv.addr
- th = Thread.new {
- s = serv.accept
- begin
- s.print "220 Test FTP Server\r\n"
- assert_equal("USER anonymous\r\n", s.gets); s.print "331 name ok\r\n"
- assert_match(/\APASS .*\r\n\z/, s.gets); s.print "230 logged in\r\n"
- assert_equal("TYPE I\r\n", s.gets); s.print "200 type set to I\r\n"
- assert_equal("CWD foo\r\n", s.gets); s.print "250 CWD successful\r\n"
- assert_equal("PASV\r\n", s.gets)
- TCPServer.open("127.0.0.1", 0) {|data_serv|
- _, data_serv_port, _, _ = data_serv.addr
- hi = data_serv_port >> 8
- lo = data_serv_port & 0xff
- s.print "227 Entering Passive Mode (127,0,0,1,#{hi},#{lo}).\r\n"
- assert_equal("RETR bar\r\n", s.gets); s.print "150 file okay\r\n"
- data_sock = data_serv.accept
- begin
- data_sock << "content"
- ensure
- data_sock.close
- end
- s.print "226 transfer complete\r\n"
- assert_nil(s.gets)
- }
- ensure
- s.close if s
- end
- }
- begin
- content = URI("ftp://#{host}:#{port}/foo/bar").read
- assert_equal("content", content)
- ensure
- Thread.kill(th)
- th.join
- end
- }
- end
-
- def test_ftp_active
- TCPServer.open("127.0.0.1", 0) {|serv|
- _, port, _, host = serv.addr
- th = Thread.new {
- s = serv.accept
- begin
- content = "content"
- s.print "220 Test FTP Server\r\n"
- assert_equal("USER anonymous\r\n", s.gets); s.print "331 name ok\r\n"
- assert_match(/\APASS .*\r\n\z/, s.gets); s.print "230 logged in\r\n"
- assert_equal("TYPE I\r\n", s.gets); s.print "200 type set to I\r\n"
- assert_equal("CWD foo\r\n", s.gets); s.print "250 CWD successful\r\n"
- assert(m = /\APORT 127,0,0,1,(\d+),(\d+)\r\n\z/.match(s.gets))
- active_port = m[1].to_i << 8 | m[2].to_i
- TCPSocket.open("127.0.0.1", active_port) {|data_sock|
- s.print "200 data connection opened\r\n"
- assert_equal("RETR bar\r\n", s.gets); s.print "150 file okay\r\n"
- begin
- data_sock << content
- ensure
- data_sock.close
- end
- s.print "226 transfer complete\r\n"
- assert_nil(s.gets)
- }
- ensure
- s.close if s
- end
- }
- begin
- content = URI("ftp://#{host}:#{port}/foo/bar").read(:ftp_active_mode=>true)
- assert_equal("content", content)
- ensure
- Thread.kill(th)
- th.join
- end
- }
- end
-
- def test_ftp_ascii
- TCPServer.open("127.0.0.1", 0) {|serv|
- _, port, _, host = serv.addr
- th = Thread.new {
- s = serv.accept
- begin
- content = "content"
- s.print "220 Test FTP Server\r\n"
- assert_equal("USER anonymous\r\n", s.gets); s.print "331 name ok\r\n"
- assert_match(/\APASS .*\r\n\z/, s.gets); s.print "230 logged in\r\n"
- assert_equal("TYPE I\r\n", s.gets); s.print "200 type set to I\r\n"
- assert_equal("CWD /foo\r\n", s.gets); s.print "250 CWD successful\r\n"
- assert_equal("TYPE A\r\n", s.gets); s.print "200 type set to A\r\n"
- assert_equal("SIZE bar\r\n", s.gets); s.print "213 #{content.bytesize}\r\n"
- assert_equal("PASV\r\n", s.gets)
- TCPServer.open("127.0.0.1", 0) {|data_serv|
- _, data_serv_port, _, _ = data_serv.addr
- hi = data_serv_port >> 8
- lo = data_serv_port & 0xff
- s.print "227 Entering Passive Mode (127,0,0,1,#{hi},#{lo}).\r\n"
- assert_equal("RETR bar\r\n", s.gets); s.print "150 file okay\r\n"
- data_sock = data_serv.accept
- begin
- data_sock << content
- ensure
- data_sock.close
- end
- s.print "226 transfer complete\r\n"
- assert_nil(s.gets)
- }
- ensure
- s.close if s
- end
- }
- begin
- length = []
- progress = []
- content = URI("ftp://#{host}:#{port}/%2Ffoo/b%61r;type=a").read(
- :content_length_proc => lambda {|n| length << n },
- :progress_proc => lambda {|n| progress << n })
- assert_equal("content", content)
- assert_equal([7], length)
- assert_equal(7, progress.inject(&:+))
- ensure
- Thread.kill(th)
- th.join
- end
- }
- end
- rescue LoadError
- # net-ftp is the bundled gems at Ruby 3.1
- end
-
- def test_ftp_over_http_proxy
- TCPServer.open("127.0.0.1", 0) {|proxy_serv|
- proxy_port = proxy_serv.addr[1]
- th = Thread.new {
- proxy_sock = proxy_serv.accept
- begin
- req = proxy_sock.gets("\r\n\r\n")
- assert_match(%r{\AGET ftp://192.0.2.1/foo/bar }, req)
- proxy_sock.print "HTTP/1.0 200 OK\r\n"
- proxy_sock.print "Content-Length: 4\r\n\r\n"
- proxy_sock.print "ab\r\n"
- ensure
- proxy_sock.close
- end
- }
- begin
- with_env('ftp_proxy'=>"http://127.0.0.1:#{proxy_port}") {
- content = URI("ftp://192.0.2.1/foo/bar").read
- assert_equal("ab\r\n", content)
- }
- ensure
- Thread.kill(th)
- th.join
- end
- }
+ before = RubyVM.stat(:global_constant_state)
+ OpenURI::Meta.init(Object.new)
+ assert_equal 0, RubyVM.stat(:global_constant_state) - before
end
-
- def test_ftp_over_http_proxy_auth
- TCPServer.open("127.0.0.1", 0) {|proxy_serv|
- proxy_port = proxy_serv.addr[1]
- th = Thread.new {
- proxy_sock = proxy_serv.accept
- begin
- req = proxy_sock.gets("\r\n\r\n")
- assert_match(%r{\AGET ftp://192.0.2.1/foo/bar }, req)
- assert_match(%r{Proxy-Authorization: Basic #{['proxy-user:proxy-password'].pack('m').chomp}\r\n}, req)
- proxy_sock.print "HTTP/1.0 200 OK\r\n"
- proxy_sock.print "Content-Length: 4\r\n\r\n"
- proxy_sock.print "ab\r\n"
- ensure
- proxy_sock.close
- end
- }
- begin
- content = URI("ftp://192.0.2.1/foo/bar").read(
- :proxy_http_basic_authentication => ["http://127.0.0.1:#{proxy_port}", "proxy-user", "proxy-password"])
- assert_equal("ab\r\n", content)
- ensure
- Thread.kill(th)
- th.join
- end
- }
- end
-
end
-
diff --git a/test/open-uri/test_proxy.rb b/test/open-uri/test_proxy.rb
new file mode 100644
index 0000000000..a36a63f21f
--- /dev/null
+++ b/test/open-uri/test_proxy.rb
@@ -0,0 +1,174 @@
+# frozen_string_literal: true
+require 'test/unit'
+require 'open-uri'
+require 'stringio'
+require_relative 'utils'
+
+class TestOpenURIProxy < Test::Unit::TestCase
+ include TestOpenURIUtils
+
+ def with_env(h)
+ begin
+ old = {}
+ h.each_key {|k| old[k] = ENV[k] }
+ h.each {|k, v| ENV[k] = v }
+ yield
+ ensure
+ h.each_key {|k| ENV[k] = old[k] }
+ end
+ end
+
+ def setup
+ @proxies = %w[http_proxy HTTP_PROXY ftp_proxy FTP_PROXY no_proxy]
+ @old_proxies = @proxies.map {|k| ENV[k] }
+ @proxies.each {|k| ENV[k] = nil }
+ end
+
+ def teardown
+ @proxies.each_with_index {|k, i| ENV[k] = @old_proxies[i] }
+ end
+
+ def test_proxy
+ with_http {|srv, url|
+ proxy_log = StringIO.new(''.dup)
+ proxy_access_log = StringIO.new(''.dup)
+ proxy_auth_log = ''.dup
+ proxy_host = '127.0.0.1'
+ proxy = SimpleHTTPProxyServer.new(proxy_host, 0, lambda {|req, res|
+ proxy_auth_log << req.request_line
+ }, proxy_log, proxy_access_log)
+ proxy_port = proxy.instance_variable_get(:@server).addr[1]
+ proxy_url = "http://#{proxy_host}:#{proxy_port}/"
+ begin
+ proxy_thread = proxy.start
+ srv.mount_proc("/proxy", lambda { |req, res| res.body = "proxy" } )
+ URI.open("#{url}/proxy", :proxy=>proxy_url) {|f|
+ assert_equal("200", f.status[0])
+ assert_equal("proxy", f.read)
+ }
+ assert_match(/#{Regexp.quote url}/, proxy_auth_log); proxy_auth_log.clear
+ URI.open("#{url}/proxy", :proxy=>URI(proxy_url)) {|f|
+ assert_equal("200", f.status[0])
+ assert_equal("proxy", f.read)
+ }
+ assert_match(/#{Regexp.quote url}/, proxy_auth_log); proxy_auth_log.clear
+ URI.open("#{url}/proxy", :proxy=>nil) {|f|
+ assert_equal("200", f.status[0])
+ assert_equal("proxy", f.read)
+ }
+ assert_equal("", proxy_auth_log); proxy_auth_log.clear
+ assert_raise(ArgumentError) {
+ URI.open("#{url}/proxy", :proxy=>:invalid) {}
+ }
+ assert_equal("", proxy_auth_log); proxy_auth_log.clear
+ with_env("http_proxy"=>proxy_url) {
+ # should not use proxy for 127.0.0.0/8.
+ URI.open("#{url}/proxy") {|f|
+ assert_equal("200", f.status[0])
+ assert_equal("proxy", f.read)
+ }
+ }
+ assert_equal("", proxy_auth_log); proxy_auth_log.clear
+ ensure
+ proxy.shutdown
+ proxy_thread.join
+ end
+ assert_equal("", proxy_log.string)
+ }
+ end
+
+ def test_proxy_http_basic_authentication_failure
+ with_http {|srv, url|
+ proxy_log = StringIO.new(''.dup)
+ proxy_access_log = StringIO.new(''.dup)
+ proxy_auth_log = ''.dup
+ proxy_host = '127.0.0.1'
+ proxy = SimpleHTTPProxyServer.new(proxy_host, 0, lambda {|req, res|
+ proxy_auth_log << req.request_line
+ if req["Proxy-Authorization"] != "Basic #{['user:pass'].pack('m').chomp}"
+ raise ProxyAuthenticationRequired
+ end
+ }, proxy_log, proxy_access_log)
+ proxy_port = proxy.instance_variable_get(:@server).addr[1]
+ proxy_url = "http://#{proxy_host}:#{proxy_port}/"
+ begin
+ th = proxy.start
+ srv.mount_proc("/proxy", lambda { |req, res| res.body = "proxy" } )
+ exc = assert_raise(OpenURI::HTTPError) { URI.open("#{url}/proxy", :proxy=>proxy_url) {} }
+ assert_equal("407", exc.io.status[0])
+ assert_match(/#{Regexp.quote url}/, proxy_auth_log); proxy_auth_log.clear
+ ensure
+ proxy.shutdown
+ th.join
+ end
+ assert_match(/ERROR ProxyAuthenticationRequired/, proxy_log.string)
+ }
+ end
+
+ def test_proxy_http_basic_authentication_success
+ with_http {|srv, url|
+ proxy_log = StringIO.new(''.dup)
+ proxy_access_log = StringIO.new(''.dup)
+ proxy_auth_log = ''.dup
+ proxy_host = '127.0.0.1'
+ proxy = SimpleHTTPProxyServer.new(proxy_host, 0, lambda {|req, res|
+ proxy_auth_log << req.request_line
+ if req["Proxy-Authorization"] != "Basic #{['user:pass'].pack('m').chomp}"
+ raise ProxyAuthenticationRequired
+ end
+ }, proxy_log, proxy_access_log)
+ proxy_port = proxy.instance_variable_get(:@server).addr[1]
+ proxy_url = "http://#{proxy_host}:#{proxy_port}/"
+ begin
+ th = proxy.start
+ srv.mount_proc("/proxy", lambda { |req, res| res.body = "proxy" } )
+ URI.open("#{url}/proxy",
+ :proxy_http_basic_authentication=>[proxy_url, "user", "pass"]) {|f|
+ assert_equal("200", f.status[0])
+ assert_equal("proxy", f.read)
+ }
+ assert_match(/#{Regexp.quote url}/, proxy_auth_log); proxy_auth_log.clear
+ assert_raise(ArgumentError) {
+ URI.open("#{url}/proxy",
+ :proxy_http_basic_authentication=>[true, "user", "pass"]) {}
+ }
+ assert_equal("", proxy_auth_log); proxy_auth_log.clear
+ ensure
+ proxy.shutdown
+ th.join
+ end
+ assert_equal("", proxy_log.string)
+ }
+ end
+
+ def test_authenticated_proxy_http_basic_authentication_success
+ with_http {|srv, url|
+ proxy_log = StringIO.new(''.dup)
+ proxy_access_log = StringIO.new(''.dup)
+ proxy_auth_log = ''.dup
+ proxy_host = '127.0.0.1'
+ proxy = SimpleHTTPProxyServer.new(proxy_host, 0, lambda {|req, res|
+ proxy_auth_log << req.request_line
+ if req["Proxy-Authorization"] != "Basic #{['user:pass'].pack('m').chomp}"
+ raise ProxyAuthenticationRequired
+ end
+ }, proxy_log, proxy_access_log)
+ proxy_port = proxy.instance_variable_get(:@server).addr[1]
+ proxy_url = "http://user:pass@#{proxy_host}:#{proxy_port}/"
+ begin
+ th = proxy.start
+ srv.mount_proc("/proxy", lambda { |req, res| res.body = "proxy" } )
+ URI.open("#{url}/proxy", :proxy => proxy_url) {|f|
+ assert_equal("200", f.status[0])
+ assert_equal("proxy", f.read)
+ }
+ assert_match(/#{Regexp.quote url}/, proxy_auth_log); proxy_auth_log.clear
+ assert_equal("", proxy_auth_log); proxy_auth_log.clear
+ ensure
+ proxy.shutdown
+ th.join
+ end
+ assert_equal("", proxy_log.string)
+ }
+ end
+end
diff --git a/test/open-uri/test_ssl.rb b/test/open-uri/test_ssl.rb
index 4f645d83b9..389391e685 100644
--- a/test/open-uri/test_ssl.rb
+++ b/test/open-uri/test_ssl.rb
@@ -1,59 +1,14 @@
# frozen_string_literal: true
require 'test/unit'
require 'open-uri'
-require 'stringio'
-require 'webrick'
+require_relative 'utils'
begin
require 'openssl'
- require 'webrick/https'
rescue LoadError
end
-require 'webrick/httpproxy'
class TestOpenURISSL < Test::Unit::TestCase
-end
-
-class TestOpenURISSL
- NullLog = Object.new
- def NullLog.<<(arg)
- end
-
- def with_https(log_tester=lambda {|log| assert_equal([], log) })
- log = []
- logger = WEBrick::Log.new(log, WEBrick::BasicLog::WARN)
- Dir.mktmpdir {|dr|
- srv = WEBrick::HTTPServer.new({
- :DocumentRoot => dr,
- :ServerType => Thread,
- :Logger => logger,
- :AccessLog => [[NullLog, ""]],
- :SSLEnable => true,
- :SSLCertificate => OpenSSL::X509::Certificate.new(SERVER_CERT),
- :SSLPrivateKey => OpenSSL::PKey::RSA.new(SERVER_KEY),
- :SSLTmpDhCallback => proc { OpenSSL::PKey::DH.new(DHPARAMS) },
- :BindAddress => '127.0.0.1',
- :Port => 0})
- _, port, _, host = srv.listeners[0].addr
- threads = []
- server_thread = srv.start
- threads << Thread.new {
- server_thread.join
- if log_tester
- log_tester.call(log)
- end
- }
- threads << Thread.new {
- begin
- yield srv, dr, "https://#{host}:#{port}", server_thread, log, threads
- ensure
- srv.shutdown
- end
- }
- assert_join_threads(threads)
- }
- ensure
- WEBrick::Utils::TimeoutHandler.terminate
- end
+ include TestOpenURIUtils
def setup
@proxies = %w[http_proxy HTTP_PROXY https_proxy HTTPS_PROXY ftp_proxy FTP_PROXY no_proxy]
@@ -68,7 +23,9 @@ class TestOpenURISSL
def setup_validation(srv, dr)
cacert_filename = "#{dr}/cacert.pem"
URI.open(cacert_filename, "w") {|f| f << CA_CERT }
- srv.mount_proc("/data", lambda { |req, res| res.body = "ddd" } )
+ if srv.respond_to?(:mount_proc)
+ srv.mount_proc("/data", lambda { |req, res| res.body = "ddd" } )
+ end
cacert_filename
end
@@ -93,50 +50,29 @@ class TestOpenURISSL
end
def test_validation_failure
- unless /mswin|mingw/ =~ RUBY_PLATFORM
- # on Windows, Errno::ECONNRESET will be raised, and it'll be eaten by
- # WEBrick
- log_tester = lambda {|server_log|
- assert_equal(1, server_log.length)
- assert_match(/ERROR OpenSSL::SSL::SSLError:/, server_log[0])
- }
- end
- with_https(log_tester) {|srv, dr, url, server_thread, server_log|
+ with_https(nil) {|srv, dr, url|
setup_validation(srv, dr)
assert_raise(OpenSSL::SSL::SSLError) { URI.open("#{url}/data") {} }
+ sleep 0.5 unless RUBY_PLATFORM =~ /mswin|mingw/
+ }
+ end
+
+ def test_ssl_min_version
+ with_https {|srv, dr, url|
+ setup_validation(srv, dr)
+ URI.open("#{url}/data", :ssl_verify_mode => OpenSSL::SSL::VERIFY_NONE, :ssl_min_version => :TLS1_2) {|f|
+ assert_equal("200", f.status[0])
+ assert_equal("ddd", f.read)
+ }
}
end
- def with_https_proxy(proxy_log_tester=lambda {|proxy_log, proxy_access_log| assert_equal([], proxy_log) })
- proxy_log = []
- proxy_logger = WEBrick::Log.new(proxy_log, WEBrick::BasicLog::WARN)
- with_https {|srv, dr, url, server_thread, server_log, threads|
- srv.mount_proc("/proxy", lambda { |req, res| res.body = "proxy" } )
- cacert_filename = "#{dr}/cacert.pem"
- open(cacert_filename, "w") {|f| f << CA_CERT }
- cacert_directory = "#{dr}/certs"
- Dir.mkdir cacert_directory
- hashed_name = "%08x.0" % OpenSSL::X509::Certificate.new(CA_CERT).subject.hash
- open("#{cacert_directory}/#{hashed_name}", "w") {|f| f << CA_CERT }
- proxy = WEBrick::HTTPProxyServer.new({
- :ServerType => Thread,
- :Logger => proxy_logger,
- :AccessLog => [[proxy_access_log=[], WEBrick::AccessLog::COMMON_LOG_FORMAT]],
- :BindAddress => '127.0.0.1',
- :Port => 0})
- _, proxy_port, _, proxy_host = proxy.listeners[0].addr
- proxy_thread = proxy.start
- threads << Thread.new {
- proxy_thread.join
- if proxy_log_tester
- proxy_log_tester.call(proxy_log, proxy_access_log)
- end
+ def test_bad_ssl_version
+ with_https(nil) {|srv, dr, url|
+ setup_validation(srv, dr)
+ assert_raise(ArgumentError) {
+ URI.open("#{url}/data", :ssl_verify_mode => OpenSSL::SSL::VERIFY_NONE, :ssl_min_version => :TLS_no_such_version) {}
}
- begin
- yield srv, dr, url, cacert_filename, cacert_directory, proxy_host, proxy_port
- ensure
- proxy.shutdown
- end
}
end
@@ -173,341 +109,3 @@ class TestOpenURISSL
end
end if defined?(OpenSSL::SSL)
-
-if defined?(OpenSSL::SSL)
-# cp /etc/ssl/openssl.cnf . # I copied from OpenSSL 1.1.1b source
-
-# mkdir demoCA demoCA/private demoCA/newcerts
-# touch demoCA/index.txt
-# echo 00 > demoCA/serial
-# openssl genrsa -des3 -out demoCA/private/cakey.pem 2048
-# openssl req -new -key demoCA/private/cakey.pem -out demoCA/careq.pem -subj "/C=JP/ST=Tokyo/O=RubyTest/CN=Ruby Test CA"
-# # basicConstraints=CA:TRUE is required; the default openssl.cnf has it in [v3_ca]
-# openssl ca -config openssl.cnf -extensions v3_ca -out demoCA/cacert.pem -startdate 090101000000Z -enddate 491231235959Z -batch -keyfile demoCA/private/cakey.pem -selfsign -infiles demoCA/careq.pem
-
-# mkdir server
-# openssl genrsa -des3 -out server/server.key 2048
-# openssl req -new -key server/server.key -out server/csr.pem -subj "/C=JP/ST=Tokyo/O=RubyTest/CN=127.0.0.1"
-# openssl ca -config openssl.cnf -startdate 090101000000Z -enddate 491231235959Z -in server/csr.pem -keyfile demoCA/private/cakey.pem -cert demoCA/cacert.pem -out server/cert.pem
-
-# demoCA/cacert.pem => TestOpenURISSL::CA_CERT
-# server/cert.pem => TestOpenURISSL::SERVER_CERT
-# `openssl rsa -in server/server.key -text` => TestOpenURISSL::SERVER_KEY
-
-TestOpenURISSL::CA_CERT = <<'End'
-Certificate:
- Data:
- Version: 3 (0x2)
- Serial Number: 0 (0x0)
- Signature Algorithm: sha256WithRSAEncryption
- Issuer: C=JP, ST=Tokyo, O=RubyTest, CN=Ruby Test CA
- Validity
- Not Before: Jan 1 00:00:00 2009 GMT
- Not After : Dec 31 23:59:59 2049 GMT
- Subject: C=JP, ST=Tokyo, O=RubyTest, CN=Ruby Test CA
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public-Key: (2048 bit)
- Modulus:
- 00:ad:f3:4d:5b:0b:01:54:cc:86:36:d1:93:6b:33:
- 56:25:90:61:d6:9a:a0:f4:24:20:ee:c8:14:ab:0f:
- 4b:89:d8:7c:bb:c0:f8:7f:fb:e9:a2:d5:1c:6b:6f:
- dc:5c:23:b1:49:aa:2c:e8:ca:43:48:64:69:4b:8a:
- bd:44:57:9b:14:d9:7a:b2:49:00:d6:c2:74:67:62:
- 52:1d:a9:32:df:fe:7a:22:20:49:83:e1:cb:3d:dc:
- 1a:2a:f0:36:20:c1:e8:c8:89:d4:51:1a:68:91:20:
- e0:ba:67:0a:b2:6b:f8:e3:8c:f5:ee:a1:36:b1:89:
- ec:23:b6:f2:39:a9:b9:2e:ea:de:d9:86:e5:42:11:
- 46:ed:10:9a:90:76:44:4e:4d:49:2d:49:e8:e3:cb:
- ff:7a:7d:80:cb:bf:c4:c3:69:ba:9c:60:4a:de:af:
- bf:26:78:b8:fb:46:d1:37:d0:89:ba:78:93:6a:37:
- a5:e9:58:e7:e2:e3:7d:7c:95:20:79:41:56:15:cd:
- b2:c6:3b:e1:b7:e7:ba:47:60:9a:05:b1:07:f3:26:
- 72:9d:3b:1b:02:18:3d:d5:de:e6:e9:30:a9:b5:8f:
- 15:1b:40:f9:64:61:54:d3:53:e8:c4:29:4a:89:f3:
- e5:0d:fd:16:61:ee:f2:6d:8a:45:a8:34:7e:53:46:
- 8e:87
- Exponent: 65537 (0x10001)
- X509v3 extensions:
- X509v3 Subject Key Identifier:
- A0:7E:0B:AD:A3:AD:37:D7:21:0B:75:6F:8A:90:5F:8C:C9:69:DF:98
- X509v3 Authority Key Identifier:
- keyid:A0:7E:0B:AD:A3:AD:37:D7:21:0B:75:6F:8A:90:5F:8C:C9:69:DF:98
-
- X509v3 Basic Constraints: critical
- CA:TRUE
- Signature Algorithm: sha256WithRSAEncryption
- 06:ea:06:02:19:9a:cb:94:a2:7e:c0:86:71:66:e7:a5:71:46:
- a2:25:55:f5:e5:58:df:d1:91:58:e6:8a:0e:91:b3:22:4c:88:
- 4d:5f:02:af:0f:73:65:0d:af:9a:f2:e4:36:f3:1f:e8:28:1d:
- 9c:74:72:5b:f7:12:e8:fa:45:d6:df:e5:f1:d3:91:f4:0e:db:
- e2:56:63:ee:82:57:6f:12:ad:d7:0d:de:5a:8c:3d:76:d2:87:
- c9:48:1c:c4:f3:89:63:3c:c2:25:e0:dd:63:a6:4c:6c:5a:07:
- 7b:86:78:62:86:02:a1:ef:0e:41:75:c5:d4:61:ab:c3:3b:9b:
- 51:0b:e6:34:6d:0b:14:5a:2d:aa:d3:58:26:43:8f:4c:d7:45:
- 73:1e:67:66:5e:f3:0c:69:70:27:a1:d5:70:f3:5a:10:98:c8:
- 4f:8a:3b:9f:ad:8e:8d:49:8f:fb:f6:36:5d:4f:70:f9:4f:54:
- 33:cf:a2:a6:1d:8c:61:b9:30:42:f2:49:d1:3d:a1:f1:eb:1e:
- 78:a6:30:f8:8a:48:89:c7:3e:bd:0d:d8:72:04:a6:00:e5:62:
- a4:13:3f:9e:b6:86:25:dc:d1:ff:3a:fc:f5:0e:e4:0e:f7:b8:
- 66:90:fe:4f:c2:54:2a:7f:61:6e:e7:4b:bf:40:7e:75:30:02:
- 5b:bb:91:1b
------BEGIN CERTIFICATE-----
-MIIDXDCCAkSgAwIBAgIBADANBgkqhkiG9w0BAQsFADBHMQswCQYDVQQGEwJKUDEO
-MAwGA1UECAwFVG9reW8xETAPBgNVBAoMCFJ1YnlUZXN0MRUwEwYDVQQDDAxSdWJ5
-IFRlc3QgQ0EwHhcNMDkwMTAxMDAwMDAwWhcNNDkxMjMxMjM1OTU5WjBHMQswCQYD
-VQQGEwJKUDEOMAwGA1UECAwFVG9reW8xETAPBgNVBAoMCFJ1YnlUZXN0MRUwEwYD
-VQQDDAxSdWJ5IFRlc3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
-AQCt801bCwFUzIY20ZNrM1YlkGHWmqD0JCDuyBSrD0uJ2Hy7wPh/++mi1Rxrb9xc
-I7FJqizoykNIZGlLir1EV5sU2XqySQDWwnRnYlIdqTLf/noiIEmD4cs93Boq8DYg
-wejIidRRGmiRIOC6Zwqya/jjjPXuoTaxiewjtvI5qbku6t7ZhuVCEUbtEJqQdkRO
-TUktSejjy/96fYDLv8TDabqcYErer78meLj7RtE30Im6eJNqN6XpWOfi4318lSB5
-QVYVzbLGO+G357pHYJoFsQfzJnKdOxsCGD3V3ubpMKm1jxUbQPlkYVTTU+jEKUqJ
-8+UN/RZh7vJtikWoNH5TRo6HAgMBAAGjUzBRMB0GA1UdDgQWBBSgfguto6031yEL
-dW+KkF+MyWnfmDAfBgNVHSMEGDAWgBSgfguto6031yELdW+KkF+MyWnfmDAPBgNV
-HRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAG6gYCGZrLlKJ+wIZxZuel
-cUaiJVX15Vjf0ZFY5ooOkbMiTIhNXwKvD3NlDa+a8uQ28x/oKB2cdHJb9xLo+kXW
-3+Xx05H0DtviVmPugldvEq3XDd5ajD120ofJSBzE84ljPMIl4N1jpkxsWgd7hnhi
-hgKh7w5BdcXUYavDO5tRC+Y0bQsUWi2q01gmQ49M10VzHmdmXvMMaXAnodVw81oQ
-mMhPijufrY6NSY/79jZdT3D5T1Qzz6KmHYxhuTBC8knRPaHx6x54pjD4ikiJxz69
-DdhyBKYA5WKkEz+etoYl3NH/Ovz1DuQO97hmkP5PwlQqf2Fu50u/QH51MAJbu5Eb
------END CERTIFICATE-----
-End
-
-TestOpenURISSL::SERVER_CERT = <<'End'
-Certificate:
- Data:
- Version: 3 (0x2)
- Serial Number: 1 (0x1)
- Signature Algorithm: sha256WithRSAEncryption
- Issuer: C=JP, ST=Tokyo, O=RubyTest, CN=Ruby Test CA
- Validity
- Not Before: Jan 1 00:00:00 2009 GMT
- Not After : Dec 31 23:59:59 2049 GMT
- Subject: C=JP, ST=Tokyo, O=RubyTest, CN=127.0.0.1
- Subject Public Key Info:
- Public Key Algorithm: rsaEncryption
- RSA Public-Key: (2048 bit)
- Modulus:
- 00:cb:b3:71:95:12:70:fc:db:d4:a9:a7:66:d6:d3:
- 09:dd:06:80:19:e1:f2:d6:1e:31:b6:6b:20:75:51:
- dc:a7:37:a9:ac:5b:57:5d:69:36:b6:de:1d:2c:f6:
- 44:64:f8:e8:d6:f0:da:38:6a:ba:c2:b1:9e:dc:bb:
- 79:94:e0:25:0c:ce:76:87:17:5d:79:9e:14:9e:bd:
- 4c:0d:aa:74:10:3a:96:ef:76:82:d5:72:16:b5:c1:
- ac:17:2d:90:83:73:5c:d7:a6:f5:36:0f:4c:55:f3:
- 30:5d:19:dc:01:0e:f8:e6:fe:a5:ad:52:88:59:dc:
- 4a:07:ed:a2:eb:a1:01:63:c4:8a:92:ba:06:80:9b:
- 0d:85:f2:9f:f9:70:ac:d7:ad:f0:7a:3f:b8:92:2a:
- 33:ca:69:d0:01:65:5d:31:38:1d:f6:1f:b2:17:07:
- 7e:ac:88:67:a6:c4:5f:3e:93:94:61:e6:e4:49:9d:
- ba:d4:d2:e8:e3:93:d1:66:79:c5:e3:1d:f8:5a:50:
- 54:58:3d:04:b0:fd:65:d1:b3:8a:b5:8a:30:5f:b2:
- dc:34:1a:14:f7:74:4c:03:29:97:63:5a:d7:de:bb:
- eb:7f:4a:2a:90:59:c0:2b:47:09:82:8f:75:de:14:
- 3f:bc:78:9a:69:25:80:5b:6c:a0:65:12:0d:29:61:
- ac:f9
- Exponent: 65537 (0x10001)
- X509v3 extensions:
- X509v3 Basic Constraints:
- CA:FALSE
- Netscape Comment:
- OpenSSL Generated Certificate
- X509v3 Subject Key Identifier:
- EC:6B:7C:79:B8:3B:11:1D:42:F3:9A:2A:CF:9A:15:59:D7:F9:D8:C6
- X509v3 Authority Key Identifier:
- keyid:A0:7E:0B:AD:A3:AD:37:D7:21:0B:75:6F:8A:90:5F:8C:C9:69:DF:98
-
- Signature Algorithm: sha256WithRSAEncryption
- 29:14:db:71:e9:a0:86:f8:cc:4d:e4:8a:76:78:a7:ff:4e:94:
- b4:4d:92:dc:57:9a:52:64:46:27:15:8b:4f:2a:18:a7:0d:fc:
- d2:75:ce:4e:49:97:0b:46:71:57:23:e3:a5:c0:c5:71:94:fc:
- f2:1d:3b:06:93:82:03:59:56:d4:fb:09:06:08:b4:97:50:33:
- cf:58:89:dd:91:31:07:26:9a:7e:7f:8d:71:de:09:dc:4f:e5:
- 6b:a3:10:71:d4:50:24:43:a0:1c:f5:2a:d9:1a:fb:e3:d6:f1:
- bc:6b:42:67:16:b4:3b:31:f4:ec:03:7d:78:e2:64:16:57:6d:
- ba:7c:0c:e1:14:b2:7c:75:4e:2b:09:3e:86:e4:aa:cc:7e:5c:
- 2b:bd:8d:26:4d:49:36:74:86:fe:c5:a6:15:4a:af:e8:b4:4e:
- d5:f2:e1:59:c2:fb:7e:c3:c4:f1:63:d8:c2:b0:9a:ae:31:96:
- 90:c3:09:d0:ce:2e:31:90:d7:83:dd:ac:31:cc:f7:87:41:08:
- 92:33:28:52:fa:2d:9e:ad:ae:6a:9f:c3:be:ce:c1:a6:e4:16:
- 2f:69:34:40:86:b6:10:21:0e:31:69:81:9e:fc:fd:c3:06:25:
- 65:37:d3:d9:4a:20:84:aa:e7:0e:60:7c:bf:3f:88:67:ac:e5:
- 8c:e0:61:d6
------BEGIN CERTIFICATE-----
-MIIDgTCCAmmgAwIBAgIBATANBgkqhkiG9w0BAQsFADBHMQswCQYDVQQGEwJKUDEO
-MAwGA1UECAwFVG9reW8xETAPBgNVBAoMCFJ1YnlUZXN0MRUwEwYDVQQDDAxSdWJ5
-IFRlc3QgQ0EwHhcNMDkwMTAxMDAwMDAwWhcNNDkxMjMxMjM1OTU5WjBEMQswCQYD
-VQQGEwJKUDEOMAwGA1UECAwFVG9reW8xETAPBgNVBAoMCFJ1YnlUZXN0MRIwEAYD
-VQQDDAkxMjcuMC4wLjEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDL
-s3GVEnD829Spp2bW0wndBoAZ4fLWHjG2ayB1UdynN6msW1ddaTa23h0s9kRk+OjW
-8No4arrCsZ7cu3mU4CUMznaHF115nhSevUwNqnQQOpbvdoLVcha1wawXLZCDc1zX
-pvU2D0xV8zBdGdwBDvjm/qWtUohZ3EoH7aLroQFjxIqSugaAmw2F8p/5cKzXrfB6
-P7iSKjPKadABZV0xOB32H7IXB36siGemxF8+k5Rh5uRJnbrU0ujjk9FmecXjHfha
-UFRYPQSw/WXRs4q1ijBfstw0GhT3dEwDKZdjWtfeu+t/SiqQWcArRwmCj3XeFD+8
-eJppJYBbbKBlEg0pYaz5AgMBAAGjezB5MAkGA1UdEwQCMAAwLAYJYIZIAYb4QgEN
-BB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBTsa3x5
-uDsRHULzmirPmhVZ1/nYxjAfBgNVHSMEGDAWgBSgfguto6031yELdW+KkF+MyWnf
-mDANBgkqhkiG9w0BAQsFAAOCAQEAKRTbcemghvjMTeSKdnin/06UtE2S3FeaUmRG
-JxWLTyoYpw380nXOTkmXC0ZxVyPjpcDFcZT88h07BpOCA1lW1PsJBgi0l1Azz1iJ
-3ZExByaafn+Ncd4J3E/la6MQcdRQJEOgHPUq2Rr749bxvGtCZxa0OzH07AN9eOJk
-FldtunwM4RSyfHVOKwk+huSqzH5cK72NJk1JNnSG/sWmFUqv6LRO1fLhWcL7fsPE
-8WPYwrCarjGWkMMJ0M4uMZDXg92sMcz3h0EIkjMoUvotnq2uap/Dvs7BpuQWL2k0
-QIa2ECEOMWmBnvz9wwYlZTfT2UoghKrnDmB8vz+IZ6zljOBh1g==
------END CERTIFICATE-----
-End
-
-TestOpenURISSL::SERVER_KEY = <<'End'
-RSA Private-Key: (2048 bit, 2 primes)
-modulus:
- 00:cb:b3:71:95:12:70:fc:db:d4:a9:a7:66:d6:d3:
- 09:dd:06:80:19:e1:f2:d6:1e:31:b6:6b:20:75:51:
- dc:a7:37:a9:ac:5b:57:5d:69:36:b6:de:1d:2c:f6:
- 44:64:f8:e8:d6:f0:da:38:6a:ba:c2:b1:9e:dc:bb:
- 79:94:e0:25:0c:ce:76:87:17:5d:79:9e:14:9e:bd:
- 4c:0d:aa:74:10:3a:96:ef:76:82:d5:72:16:b5:c1:
- ac:17:2d:90:83:73:5c:d7:a6:f5:36:0f:4c:55:f3:
- 30:5d:19:dc:01:0e:f8:e6:fe:a5:ad:52:88:59:dc:
- 4a:07:ed:a2:eb:a1:01:63:c4:8a:92:ba:06:80:9b:
- 0d:85:f2:9f:f9:70:ac:d7:ad:f0:7a:3f:b8:92:2a:
- 33:ca:69:d0:01:65:5d:31:38:1d:f6:1f:b2:17:07:
- 7e:ac:88:67:a6:c4:5f:3e:93:94:61:e6:e4:49:9d:
- ba:d4:d2:e8:e3:93:d1:66:79:c5:e3:1d:f8:5a:50:
- 54:58:3d:04:b0:fd:65:d1:b3:8a:b5:8a:30:5f:b2:
- dc:34:1a:14:f7:74:4c:03:29:97:63:5a:d7:de:bb:
- eb:7f:4a:2a:90:59:c0:2b:47:09:82:8f:75:de:14:
- 3f:bc:78:9a:69:25:80:5b:6c:a0:65:12:0d:29:61:
- ac:f9
-publicExponent: 65537 (0x10001)
-privateExponent:
- 12:be:d5:b2:01:3b:72:99:8c:4d:7c:81:43:3d:b2:
- 87:ab:84:78:5d:49:aa:98:a6:bc:81:c9:3f:e2:a3:
- aa:a3:bd:b2:85:c9:59:68:48:47:b5:d2:fb:83:42:
- 32:04:91:f0:cd:c3:57:33:c3:32:0d:84:70:0d:b4:
- 97:95:b4:f3:23:c0:d6:97:b8:db:6b:47:bc:7f:f1:
- 12:c4:df:df:6a:74:df:5e:89:95:b8:e5:0c:1e:e1:
- 86:54:84:1b:04:af:c3:8c:b2:be:21:d4:45:88:96:
- a7:ca:ac:6b:50:84:69:45:7f:db:9e:5f:bb:dd:40:
- d6:cf:f0:91:3c:84:d3:38:65:c9:15:f7:9e:37:aa:
- 1a:2e:bc:16:b6:95:be:bc:af:45:76:ba:ad:99:f6:
- ef:6a:e8:fd:f0:31:89:19:c4:04:67:a1:ec:c4:79:
- 59:08:77:ab:0b:65:88:88:02:b1:38:5c:80:4e:27:
- 78:b2:a5:bd:b5:ad:d5:9c:4c:ea:ad:db:05:56:25:
- 70:28:da:22:fb:d8:de:8c:3b:78:fe:3e:cf:ed:1b:
- f9:97:c6:b6:4a:bf:60:08:8f:dc:85:5e:b1:49:ab:
- 87:8b:68:72:f4:6a:3f:bc:db:a3:6c:f7:e8:b0:15:
- bb:4b:ba:37:49:a2:d1:7c:f8:4f:1b:05:11:22:d9:
- 81
-prime1:
- 00:fb:d2:cb:14:61:00:c1:7a:83:ba:fe:79:97:a2:
- 4d:5a:ea:40:78:96:6e:d2:be:71:5b:c6:2c:1f:c9:
- 18:48:6b:ae:20:86:87:b5:08:0b:17:69:ca:93:cd:
- 00:36:22:51:7b:d5:2d:8c:0c:0e:de:bc:86:a8:07:
- 0e:c5:57:e4:df:be:ed:7d:cc:b1:a4:d6:a8:2b:00:
- 65:2a:69:30:5e:dc:6d:6d:c4:c8:7e:20:34:eb:6f:
- 5e:cf:b3:b8:2e:8d:56:31:44:a8:17:ea:be:65:19:
- ff:da:14:e0:0c:73:56:14:08:47:4c:5b:79:51:74:
- 5d:bc:e7:fe:01:2f:55:27:69
-prime2:
- 00:cf:14:54:47:bb:5f:5d:d6:2b:2d:ed:a6:8a:6f:
- 36:fc:47:5e:9f:84:ae:aa:1f:f8:44:50:91:15:f5:
- ed:9d:29:d9:2b:2a:19:66:56:2e:96:15:b5:8e:a9:
- 7f:89:27:21:b5:57:55:7e:2a:c5:8c:93:fe:f6:0a:
- a5:17:15:91:91:b3:7d:35:1a:d5:9a:2e:b8:0d:ad:
- e6:97:6d:83:a3:27:29:ee:00:74:ef:57:34:f3:07:
- ad:12:43:37:0c:5c:b7:26:34:bc:4e:3a:43:65:6b:
- 0c:b8:23:ac:77:fd:b2:23:eb:7b:65:70:f6:96:c4:
- 17:2c:aa:24:b8:a5:5e:b7:11
-exponent1:
- 00:92:32:ae:f4:05:dd:0a:76:b6:43:b9:b9:9d:ee:
- fc:39:ec:05:c1:fc:94:1a:85:b6:0a:31:e3:2c:10:
- f3:a8:17:db:df:c6:3a:c3:3f:08:31:6f:99:cc:75:
- 17:ca:55:e2:38:a2:6a:ef:03:91:1e:7f:15:2e:37:
- ea:bb:67:6b:d8:fa:5f:a6:c9:4f:d9:03:46:5e:b0:
- bc:0b:03:46:b1:cc:07:3b:d3:23:13:16:5f:a2:cf:
- e5:9b:70:1b:5d:eb:70:3e:ea:3d:2c:a5:7c:23:f6:
- 14:33:e8:2a:ab:0f:ca:c9:96:84:ce:2f:cd:1f:1d:
- 0f:ce:bc:61:1b:0e:ff:c1:01
-exponent2:
- 00:9e:0b:f3:03:48:73:d1:e7:9a:cf:13:f9:ae:e0:
- 91:03:dc:e8:d0:30:f1:2a:30:fa:48:11:81:9a:54:
- 37:c5:62:e2:37:fa:8a:a6:3b:92:94:c3:fe:ec:e2:
- 5a:cf:70:09:5f:21:47:c3:e2:9b:21:de:f6:92:0c:
- af:d1:bd:89:7b:bd:95:0b:49:ee:cb:1d:6b:26:2d:
- 9a:b7:ea:42:b4:ec:38:29:49:39:f6:4e:05:c0:93:
- 14:39:c3:09:29:ab:3d:b1:b0:40:24:28:7d:b5:d3:
- 0d:43:21:1f:09:f9:9b:d3:a4:6f:6a:8d:db:f6:57:
- b5:24:46:bb:7e:1d:e0:fb:31
-coefficient:
- 10:93:1d:c8:33:a5:c1:d3:84:6a:22:68:e5:60:cc:
- 9c:27:0a:52:0b:58:a3:0c:83:f4:f4:46:09:0c:a1:
- 41:a6:ea:bf:80:9d:0e:5d:d8:3d:25:00:c5:a1:35:
- 7a:8c:ea:95:16:94:c3:7c:8f:2b:e0:53:ea:66:ae:
- 19:be:55:04:3d:ee:e2:4b:a8:69:1b:7e:d8:09:7f:
- ed:7c:ee:95:88:10:dc:4b:5b:bf:81:a4:e8:dc:7e:
- 4f:e5:c3:90:c4:e5:5a:90:10:32:d6:08:b5:1f:5d:
- 09:18:d8:44:28:e4:c4:c7:07:75:9b:9b:b3:80:86:
- 68:9d:fe:68:f3:4d:db:66
-writing RSA key
------BEGIN RSA PRIVATE KEY-----
-MIIEpAIBAAKCAQEAy7NxlRJw/NvUqadm1tMJ3QaAGeHy1h4xtmsgdVHcpzeprFtX
-XWk2tt4dLPZEZPjo1vDaOGq6wrGe3Lt5lOAlDM52hxddeZ4Unr1MDap0EDqW73aC
-1XIWtcGsFy2Qg3Nc16b1Ng9MVfMwXRncAQ745v6lrVKIWdxKB+2i66EBY8SKkroG
-gJsNhfKf+XCs163wej+4kiozymnQAWVdMTgd9h+yFwd+rIhnpsRfPpOUYebkSZ26
-1NLo45PRZnnF4x34WlBUWD0EsP1l0bOKtYowX7LcNBoU93RMAymXY1rX3rvrf0oq
-kFnAK0cJgo913hQ/vHiaaSWAW2ygZRINKWGs+QIDAQABAoIBABK+1bIBO3KZjE18
-gUM9soerhHhdSaqYpryByT/io6qjvbKFyVloSEe10vuDQjIEkfDNw1czwzINhHAN
-tJeVtPMjwNaXuNtrR7x/8RLE399qdN9eiZW45Qwe4YZUhBsEr8OMsr4h1EWIlqfK
-rGtQhGlFf9ueX7vdQNbP8JE8hNM4ZckV9543qhouvBa2lb68r0V2uq2Z9u9q6P3w
-MYkZxARnoezEeVkId6sLZYiIArE4XIBOJ3iypb21rdWcTOqt2wVWJXAo2iL72N6M
-O3j+Ps/tG/mXxrZKv2AIj9yFXrFJq4eLaHL0aj+826Ns9+iwFbtLujdJotF8+E8b
-BREi2YECgYEA+9LLFGEAwXqDuv55l6JNWupAeJZu0r5xW8YsH8kYSGuuIIaHtQgL
-F2nKk80ANiJRe9UtjAwO3ryGqAcOxVfk377tfcyxpNaoKwBlKmkwXtxtbcTIfiA0
-629ez7O4Lo1WMUSoF+q+ZRn/2hTgDHNWFAhHTFt5UXRdvOf+AS9VJ2kCgYEAzxRU
-R7tfXdYrLe2mim82/Eden4Suqh/4RFCRFfXtnSnZKyoZZlYulhW1jql/iSchtVdV
-firFjJP+9gqlFxWRkbN9NRrVmi64Da3ml22Doycp7gB071c08wetEkM3DFy3JjS8
-TjpDZWsMuCOsd/2yI+t7ZXD2lsQXLKokuKVetxECgYEAkjKu9AXdCna2Q7m5ne78
-OewFwfyUGoW2CjHjLBDzqBfb38Y6wz8IMW+ZzHUXylXiOKJq7wORHn8VLjfqu2dr
-2PpfpslP2QNGXrC8CwNGscwHO9MjExZfos/lm3AbXetwPuo9LKV8I/YUM+gqqw/K
-yZaEzi/NHx0PzrxhGw7/wQECgYEAngvzA0hz0eeazxP5ruCRA9zo0DDxKjD6SBGB
-mlQ3xWLiN/qKpjuSlMP+7OJaz3AJXyFHw+KbId72kgyv0b2Je72VC0nuyx1rJi2a
-t+pCtOw4KUk59k4FwJMUOcMJKas9sbBAJCh9tdMNQyEfCfmb06Rvao3b9le1JEa7
-fh3g+zECgYAQkx3IM6XB04RqImjlYMycJwpSC1ijDIP09EYJDKFBpuq/gJ0OXdg9
-JQDFoTV6jOqVFpTDfI8r4FPqZq4ZvlUEPe7iS6hpG37YCX/tfO6ViBDcS1u/gaTo
-3H5P5cOQxOVakBAy1gi1H10JGNhEKOTExwd1m5uzgIZonf5o803bZg==
------END RSA PRIVATE KEY-----
-End
-
-TestOpenURISSL::DHPARAMS = <<'End'
- DH Parameters: (2048 bit)
- prime:
- 00:ec:4e:a4:06:b6:22:ca:f9:8a:00:cc:d0:ee:2f:
- 16:bf:05:64:f5:8f:fe:7f:c4:bb:b0:24:cd:ef:5d:
- 8a:90:ad:dc:a9:dd:63:84:90:d8:25:ba:d8:78:d5:
- 77:91:42:0a:84:fc:56:1e:13:9b:1c:aa:43:d5:1f:
- 38:52:92:fe:b3:66:f9:e7:e8:8c:77:a1:a6:2f:b3:
- 98:98:d2:13:fc:57:1c:2a:14:dc:bd:e6:9b:54:19:
- 99:4f:ce:81:64:a6:32:7f:8e:61:50:5f:45:3a:e5:
- 0c:f7:13:f3:b8:ad:d5:77:ca:09:42:f7:d8:30:27:
- 7b:2c:f0:b4:b5:a0:04:96:34:0b:47:81:1d:7f:c1:
- 3a:62:86:8e:7d:f8:13:7f:9a:b1:8b:09:23:9e:55:
- 59:41:cd:f0:86:09:c4:b7:d1:69:54:cb:d0:f5:e9:
- 27:c9:e1:81:e4:a1:df:6b:20:1c:df:e8:54:02:f2:
- 37:fc:2a:f7:d5:b3:6f:79:7e:70:22:78:79:18:3c:
- 75:14:68:4a:05:9f:ac:d4:7f:9a:79:db:9d:0a:6e:
- ec:0a:04:70:bf:c9:4a:59:81:a2:1f:33:9b:4a:66:
- bc:03:ce:8a:1b:e3:03:ec:ba:39:26:ab:90:dc:39:
- 41:a1:d8:f7:20:3c:8f:af:12:2f:f7:a9:6f:44:f1:
- 6d:03
- generator: 2 (0x2)
------BEGIN DH PARAMETERS-----
-MIIBCAKCAQEA7E6kBrYiyvmKAMzQ7i8WvwVk9Y/+f8S7sCTN712KkK3cqd1jhJDY
-JbrYeNV3kUIKhPxWHhObHKpD1R84UpL+s2b55+iMd6GmL7OYmNIT/FccKhTcveab
-VBmZT86BZKYyf45hUF9FOuUM9xPzuK3Vd8oJQvfYMCd7LPC0taAEljQLR4Edf8E6
-YoaOffgTf5qxiwkjnlVZQc3whgnEt9FpVMvQ9eknyeGB5KHfayAc3+hUAvI3/Cr3
-1bNveX5wInh5GDx1FGhKBZ+s1H+aedudCm7sCgRwv8lKWYGiHzObSma8A86KG+MD
-7Lo5JquQ3DlBodj3IDyPrxIv96lvRPFtAwIBAg==
------END DH PARAMETERS-----
-End
-
-end
diff --git a/test/open-uri/utils.rb b/test/open-uri/utils.rb
new file mode 100644
index 0000000000..e7ca64bd1c
--- /dev/null
+++ b/test/open-uri/utils.rb
@@ -0,0 +1,738 @@
+require 'socket'
+require 'net/http'
+begin
+ require 'openssl'
+rescue LoadError
+end
+
+class SimpleHTTPServer
+ def initialize(bind_addr, port, log)
+ @server = TCPServer.new(bind_addr, port)
+ @log = log
+ @procs = {}
+ end
+
+ def mount_proc(path, proc)
+ @procs[path] = proc
+ end
+
+ def start
+ @thread = Thread.new do
+ loop do
+ client = @server.accept
+ handle_request(client)
+ client.close
+ end
+ end
+ end
+
+ def shutdown
+ @thread.kill
+ @server.close
+ end
+
+ private
+
+ def handle_request(client)
+ request_line = client.gets
+ return if request_line.nil?
+
+ method, path, _ = request_line.split
+ headers = {}
+ while (line = client.gets) && line != "\r\n"
+ key, value = line.split(": ", 2)
+ headers[key.downcase] = value.strip
+ end
+
+ if @procs.key?(path) || @procs.key?("#{path}/")
+ proc = @procs[path] || @procs["#{path}/"]
+ req = Request.new(method, path, headers)
+ res = Response.new(client)
+ proc.call(req, res)
+ res.finish
+ else
+ @log << "ERROR `#{path}' not found"
+ client.print "HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\n\r\n"
+ end
+ rescue ::TestOpenURI::Unauthorized
+ @log << "ERROR Unauthorized"
+ client.print "HTTP/1.1 401 Unauthorized\r\nContent-Length: 0\r\n\r\n"
+ end
+
+ class Request
+ attr_reader :method, :path, :headers
+ def initialize(method, path, headers)
+ @method = method
+ @path = path
+ @headers = headers
+ parse_basic_auth
+ end
+
+ def [](key)
+ @headers[key.downcase]
+ end
+
+ def []=(key, value)
+ @headers[key.downcase] = value
+ end
+
+ private
+
+ def parse_basic_auth
+ auth = @headers['Authorization']
+ return unless auth && auth.start_with?('Basic ')
+
+ encoded_credentials = auth.split(' ', 2).last
+ decoded_credentials = [encoded_credentials].pack("m")
+ @username, @password = decoded_credentials.split(':', 2)
+ end
+ end
+
+ class Response
+ attr_accessor :body, :headers, :status, :chunked, :cookies
+ def initialize(client)
+ @client = client
+ @body = ""
+ @headers = {}
+ @status = 200
+ @chunked = false
+ @cookies = []
+ end
+
+ def [](key)
+ @headers[key.downcase]
+ end
+
+ def []=(key, value)
+ @headers[key.downcase] = value
+ end
+
+ def write_chunk(chunk)
+ return unless @chunked
+ @client.write("#{chunk.bytesize.to_s(16)}\r\n")
+ @client.write("#{chunk}\r\n")
+ end
+
+ def finish
+ @client.write build_response_headers
+ if @chunked
+ write_chunk(@body)
+ @client.write "0\r\n\r\n"
+ else
+ @client.write @body
+ end
+ end
+
+ private
+
+ def build_response_headers
+ response = "HTTP/1.1 #{@status} #{status_message(@status)}\r\n"
+ if @chunked
+ @headers['Transfer-Encoding'] = 'chunked'
+ else
+ @headers['Content-Length'] = @body.bytesize.to_s
+ end
+ @headers.each do |key, value|
+ response << "#{key}: #{value}\r\n"
+ end
+ @cookies.each do |cookie|
+ response << "Set-Cookie: #{cookie}\r\n"
+ end
+ response << "\r\n"
+ response
+ end
+
+ def status_message(code)
+ case code
+ when 200 then 'OK'
+ when 301 then 'Moved Permanently'
+ else 'Unknown'
+ end
+ end
+ end
+end
+
+class SimpleHTTPProxyServer
+ def initialize(host, port, auth_proc = nil, log, access_log)
+ @server = TCPServer.new(host, port)
+ @auth_proc = auth_proc
+ @log = log
+ @access_log = access_log
+ end
+
+ def start
+ @thread = Thread.new do
+ loop do
+ client = @server.accept
+ request_line = client.gets
+ headers = {}
+ while (line = client.gets) && (line != "\r\n")
+ key, value = line.chomp.split(/:\s*/, 2)
+ headers[key] = value
+ end
+ next unless request_line
+
+ method, path, _ = request_line.split(' ')
+ handle_request(client, method, path, request_line, headers)
+ rescue IOError
+ end
+ end
+ end
+
+ def shutdown
+ @thread.kill
+ @server.close
+ end
+
+ private
+
+ def handle_request(client, method, path, request_line, headers)
+ if @auth_proc
+ req = Request.new(method, path, request_line, headers)
+ res = Struct.new(:body, :status).new("", 200)
+ @auth_proc.call(req, res)
+ if res.status != 200
+ client.print "HTTP/1.1 #{res.status}\r\nContent-Type: text/plain\r\n\r\n#{res.body}"
+ return
+ end
+ end
+
+ if method == 'CONNECT'
+ proxy_connect(path, client)
+ else
+ proxy_request(path, client)
+ end
+ rescue TestOpenURIProxy::ProxyAuthenticationRequired
+ @log << "ERROR ProxyAuthenticationRequired"
+ client.print "HTTP/1.1 407 Proxy Authentication Required\r\nContent-Length: 0\r\n\r\n"
+ ensure
+ client.close
+ end
+
+ def proxy_connect(path, client)
+ host, port = path.split(':')
+ backend = TCPSocket.new(host, port.to_i)
+ client.puts "HTTP/1.1 200 Connection Established\r\n\r\n"
+ @access_log << "CONNECT #{path} \n"
+ begin
+ while fds = IO.select([client, backend])
+ if fds[0].include?(client)
+ data = client.readpartial(1024)
+ backend.write(data)
+ elsif fds[0].include?(backend)
+ data = backend.readpartial(1024)
+ client.write(data)
+ end
+ end
+ rescue
+ backend.close
+ end
+ end
+
+ def proxy_request(path, client)
+ path.gsub!(/\Ahttps?:\/\//, '')
+ host, path = path.split('/')
+ host, port = host.split(':')
+ Net::HTTP.start(host, port) do |http|
+ response = http.get("/#{path}")
+ client.print "HTTP/1.1 #{response.code}\r\nContent-Type: #{response.content_type}\r\n\r\n#{response.body}"
+ end
+ end
+
+ class Request
+ attr_reader :method, :path, :request_line, :headers
+ def initialize(method, path, request_line, headers)
+ @method = method
+ @path = path
+ @request_line = request_line
+ @headers = headers
+ end
+
+ def [](key)
+ @headers[key]
+ end
+ end
+end
+
+class SimpleHTTPSServer
+ def initialize(cert, key, dh, bind_addr, port, log)
+ @cert = cert
+ @key = key
+ @dh = dh
+ @bind_addr = bind_addr
+ @port = port
+ @log = log
+ @server = TCPServer.new(@bind_addr, @port)
+ context = OpenSSL::SSL::SSLContext.new
+ context.cert = @cert
+ context.key = @key
+ context.tmp_dh_callback = proc { @dh }
+ @ssl_server = OpenSSL::SSL::SSLServer.new(@server, context)
+ end
+
+ def start
+ @thread = Thread.new do
+ loop do
+ ssl_socket = @ssl_server.accept
+ handle_request(ssl_socket)
+ ssl_socket.close
+ end
+ rescue OpenSSL::SSL::SSLError
+ end
+ end
+
+ def shutdown
+ @thread.kill
+ @server.close
+ end
+
+ def handle_request(socket)
+ request_line = socket.gets
+ return if request_line.nil? || request_line.strip.empty?
+
+ _, path, _ = request_line.split
+ headers = {}
+ while (line = socket.gets)
+ break if line.strip.empty?
+ key, value = line.split(': ', 2)
+ headers[key] = value.strip
+ end
+
+ response = case path
+ when '/data'
+ "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 3\r\n\r\nddd"
+ when "/proxy"
+ "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: 5\r\n\r\nproxy"
+ else
+ "HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\n\r\n"
+ end
+
+ socket.print(response)
+ end
+end
+
+module TestOpenURIUtils
+ class Unauthorized < StandardError; end
+ class ProxyAuthenticationRequired < StandardError; end
+
+ def with_http(log_tester=lambda {|log| assert_equal([], log) })
+ log = []
+ host = "127.0.0.1"
+ srv = SimpleHTTPServer.new(host, 0, log)
+
+ server_thread = srv.start
+ server_thread2 = Thread.new {
+ server_thread.join
+ if log_tester
+ log_tester.call(log)
+ end
+ }
+
+ port = srv.instance_variable_get(:@server).addr[1]
+
+ client_thread = Thread.new {
+ begin
+ yield srv, "http://#{host}:#{port}", server_thread, log
+ ensure
+ srv.shutdown
+ end
+ }
+ assert_join_threads([client_thread, server_thread2])
+ end
+
+ def with_https_proxy(proxy_log_tester=lambda {|proxy_log, proxy_access_log| assert_equal([], proxy_log) })
+ proxy_log = []
+ proxy_access_log = []
+ with_https {|srv, dr, url|
+ srv.instance_variable_get(:@server).setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, true)
+ cacert_filename = "#{dr}/cacert.pem"
+ open(cacert_filename, "w") {|f| f << CA_CERT }
+ cacert_directory = "#{dr}/certs"
+ Dir.mkdir cacert_directory
+ hashed_name = "%08x.0" % OpenSSL::X509::Certificate.new(CA_CERT).subject.hash
+ open("#{cacert_directory}/#{hashed_name}", "w") {|f| f << CA_CERT }
+ proxy_host = '127.0.0.1'
+ proxy = SimpleHTTPProxyServer.new(proxy_host, 0, proxy_log, proxy_access_log)
+ proxy_port = proxy.instance_variable_get(:@server).addr[1]
+ proxy_thread = proxy.start
+ thread = Thread.new {
+ proxy_thread.join
+ if proxy_log_tester
+ proxy_log_tester.call(proxy_log, proxy_access_log)
+ end
+ }
+ begin
+ yield srv, dr, url, cacert_filename, cacert_directory, proxy_host, proxy_port
+ sleep 1
+ ensure
+ proxy.shutdown
+ end
+ assert_join_threads([thread])
+ }
+ end
+
+ if defined?(OpenSSL::SSL)
+ def with_https(log_tester=lambda {|log| assert_equal([], log) })
+ log = []
+ Dir.mktmpdir {|dr|
+ cert = OpenSSL::X509::Certificate.new(SERVER_CERT)
+ key = OpenSSL::PKey::RSA.new(SERVER_KEY)
+ dh = OpenSSL::PKey::DH.new(DHPARAMS)
+ host = '127.0.0.1'
+ srv = SimpleHTTPSServer.new(cert, key, dh, host, 0, log)
+ port = srv.instance_variable_get(:@server).addr[1]
+ threads = []
+ server_thread = srv.start
+ threads << Thread.new {
+ server_thread.join
+ if log_tester
+ log_tester.call(log)
+ end
+ }
+ threads << Thread.new {
+ begin
+ yield srv, dr, "https://#{host}:#{port}"
+ ensure
+ srv.shutdown
+ end
+ }
+ assert_join_threads(threads)
+ }
+ end
+
+ # cp /etc/ssl/openssl.cnf . # I copied from OpenSSL 1.1.1b source
+
+ # mkdir demoCA demoCA/private demoCA/newcerts
+ # touch demoCA/index.txt
+ # echo 00 > demoCA/serial
+ # openssl genrsa -des3 -out demoCA/private/cakey.pem 2048
+ # openssl req -new -key demoCA/private/cakey.pem -out demoCA/careq.pem -subj "/C=JP/ST=Tokyo/O=RubyTest/CN=Ruby Test CA"
+ # # basicConstraints=CA:TRUE is required; the default openssl.cnf has it in [v3_ca]
+ # openssl ca -config openssl.cnf -extensions v3_ca -out demoCA/cacert.pem -startdate 090101000000Z -enddate 491231235959Z -batch -keyfile demoCA/private/cakey.pem -selfsign -infiles demoCA/careq.pem
+
+ # mkdir server
+ # openssl genrsa -des3 -out server/server.key 2048
+ # openssl req -new -key server/server.key -out server/csr.pem -subj "/C=JP/ST=Tokyo/O=RubyTest/CN=127.0.0.1"
+ # openssl ca -config openssl.cnf -startdate 090101000000Z -enddate 491231235959Z -in server/csr.pem -keyfile demoCA/private/cakey.pem -cert demoCA/cacert.pem -out server/cert.pem
+
+ # demoCA/cacert.pem => TestOpenURISSL::CA_CERT
+ # server/cert.pem => TestOpenURISSL::SERVER_CERT
+ # `openssl rsa -in server/server.key -text` => TestOpenURISSL::SERVER_KEY
+
+ CA_CERT = <<'End'
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 0 (0x0)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=JP, ST=Tokyo, O=RubyTest, CN=Ruby Test CA
+ Validity
+ Not Before: Jan 1 00:00:00 2009 GMT
+ Not After : Dec 31 23:59:59 2049 GMT
+ Subject: C=JP, ST=Tokyo, O=RubyTest, CN=Ruby Test CA
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:ad:f3:4d:5b:0b:01:54:cc:86:36:d1:93:6b:33:
+ 56:25:90:61:d6:9a:a0:f4:24:20:ee:c8:14:ab:0f:
+ 4b:89:d8:7c:bb:c0:f8:7f:fb:e9:a2:d5:1c:6b:6f:
+ dc:5c:23:b1:49:aa:2c:e8:ca:43:48:64:69:4b:8a:
+ bd:44:57:9b:14:d9:7a:b2:49:00:d6:c2:74:67:62:
+ 52:1d:a9:32:df:fe:7a:22:20:49:83:e1:cb:3d:dc:
+ 1a:2a:f0:36:20:c1:e8:c8:89:d4:51:1a:68:91:20:
+ e0:ba:67:0a:b2:6b:f8:e3:8c:f5:ee:a1:36:b1:89:
+ ec:23:b6:f2:39:a9:b9:2e:ea:de:d9:86:e5:42:11:
+ 46:ed:10:9a:90:76:44:4e:4d:49:2d:49:e8:e3:cb:
+ ff:7a:7d:80:cb:bf:c4:c3:69:ba:9c:60:4a:de:af:
+ bf:26:78:b8:fb:46:d1:37:d0:89:ba:78:93:6a:37:
+ a5:e9:58:e7:e2:e3:7d:7c:95:20:79:41:56:15:cd:
+ b2:c6:3b:e1:b7:e7:ba:47:60:9a:05:b1:07:f3:26:
+ 72:9d:3b:1b:02:18:3d:d5:de:e6:e9:30:a9:b5:8f:
+ 15:1b:40:f9:64:61:54:d3:53:e8:c4:29:4a:89:f3:
+ e5:0d:fd:16:61:ee:f2:6d:8a:45:a8:34:7e:53:46:
+ 8e:87
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ A0:7E:0B:AD:A3:AD:37:D7:21:0B:75:6F:8A:90:5F:8C:C9:69:DF:98
+ X509v3 Authority Key Identifier:
+ keyid:A0:7E:0B:AD:A3:AD:37:D7:21:0B:75:6F:8A:90:5F:8C:C9:69:DF:98
+
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: sha256WithRSAEncryption
+ 06:ea:06:02:19:9a:cb:94:a2:7e:c0:86:71:66:e7:a5:71:46:
+ a2:25:55:f5:e5:58:df:d1:91:58:e6:8a:0e:91:b3:22:4c:88:
+ 4d:5f:02:af:0f:73:65:0d:af:9a:f2:e4:36:f3:1f:e8:28:1d:
+ 9c:74:72:5b:f7:12:e8:fa:45:d6:df:e5:f1:d3:91:f4:0e:db:
+ e2:56:63:ee:82:57:6f:12:ad:d7:0d:de:5a:8c:3d:76:d2:87:
+ c9:48:1c:c4:f3:89:63:3c:c2:25:e0:dd:63:a6:4c:6c:5a:07:
+ 7b:86:78:62:86:02:a1:ef:0e:41:75:c5:d4:61:ab:c3:3b:9b:
+ 51:0b:e6:34:6d:0b:14:5a:2d:aa:d3:58:26:43:8f:4c:d7:45:
+ 73:1e:67:66:5e:f3:0c:69:70:27:a1:d5:70:f3:5a:10:98:c8:
+ 4f:8a:3b:9f:ad:8e:8d:49:8f:fb:f6:36:5d:4f:70:f9:4f:54:
+ 33:cf:a2:a6:1d:8c:61:b9:30:42:f2:49:d1:3d:a1:f1:eb:1e:
+ 78:a6:30:f8:8a:48:89:c7:3e:bd:0d:d8:72:04:a6:00:e5:62:
+ a4:13:3f:9e:b6:86:25:dc:d1:ff:3a:fc:f5:0e:e4:0e:f7:b8:
+ 66:90:fe:4f:c2:54:2a:7f:61:6e:e7:4b:bf:40:7e:75:30:02:
+ 5b:bb:91:1b
+-----BEGIN CERTIFICATE-----
+MIIDXDCCAkSgAwIBAgIBADANBgkqhkiG9w0BAQsFADBHMQswCQYDVQQGEwJKUDEO
+MAwGA1UECAwFVG9reW8xETAPBgNVBAoMCFJ1YnlUZXN0MRUwEwYDVQQDDAxSdWJ5
+IFRlc3QgQ0EwHhcNMDkwMTAxMDAwMDAwWhcNNDkxMjMxMjM1OTU5WjBHMQswCQYD
+VQQGEwJKUDEOMAwGA1UECAwFVG9reW8xETAPBgNVBAoMCFJ1YnlUZXN0MRUwEwYD
+VQQDDAxSdWJ5IFRlc3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
+AQCt801bCwFUzIY20ZNrM1YlkGHWmqD0JCDuyBSrD0uJ2Hy7wPh/++mi1Rxrb9xc
+I7FJqizoykNIZGlLir1EV5sU2XqySQDWwnRnYlIdqTLf/noiIEmD4cs93Boq8DYg
+wejIidRRGmiRIOC6Zwqya/jjjPXuoTaxiewjtvI5qbku6t7ZhuVCEUbtEJqQdkRO
+TUktSejjy/96fYDLv8TDabqcYErer78meLj7RtE30Im6eJNqN6XpWOfi4318lSB5
+QVYVzbLGO+G357pHYJoFsQfzJnKdOxsCGD3V3ubpMKm1jxUbQPlkYVTTU+jEKUqJ
+8+UN/RZh7vJtikWoNH5TRo6HAgMBAAGjUzBRMB0GA1UdDgQWBBSgfguto6031yEL
+dW+KkF+MyWnfmDAfBgNVHSMEGDAWgBSgfguto6031yELdW+KkF+MyWnfmDAPBgNV
+HRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAG6gYCGZrLlKJ+wIZxZuel
+cUaiJVX15Vjf0ZFY5ooOkbMiTIhNXwKvD3NlDa+a8uQ28x/oKB2cdHJb9xLo+kXW
+3+Xx05H0DtviVmPugldvEq3XDd5ajD120ofJSBzE84ljPMIl4N1jpkxsWgd7hnhi
+hgKh7w5BdcXUYavDO5tRC+Y0bQsUWi2q01gmQ49M10VzHmdmXvMMaXAnodVw81oQ
+mMhPijufrY6NSY/79jZdT3D5T1Qzz6KmHYxhuTBC8knRPaHx6x54pjD4ikiJxz69
+DdhyBKYA5WKkEz+etoYl3NH/Ovz1DuQO97hmkP5PwlQqf2Fu50u/QH51MAJbu5Eb
+-----END CERTIFICATE-----
+End
+
+ SERVER_CERT = <<'End'
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1 (0x1)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C=JP, ST=Tokyo, O=RubyTest, CN=Ruby Test CA
+ Validity
+ Not Before: Jan 1 00:00:00 2009 GMT
+ Not After : Dec 31 23:59:59 2049 GMT
+ Subject: C=JP, ST=Tokyo, O=RubyTest, CN=127.0.0.1
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:cb:b3:71:95:12:70:fc:db:d4:a9:a7:66:d6:d3:
+ 09:dd:06:80:19:e1:f2:d6:1e:31:b6:6b:20:75:51:
+ dc:a7:37:a9:ac:5b:57:5d:69:36:b6:de:1d:2c:f6:
+ 44:64:f8:e8:d6:f0:da:38:6a:ba:c2:b1:9e:dc:bb:
+ 79:94:e0:25:0c:ce:76:87:17:5d:79:9e:14:9e:bd:
+ 4c:0d:aa:74:10:3a:96:ef:76:82:d5:72:16:b5:c1:
+ ac:17:2d:90:83:73:5c:d7:a6:f5:36:0f:4c:55:f3:
+ 30:5d:19:dc:01:0e:f8:e6:fe:a5:ad:52:88:59:dc:
+ 4a:07:ed:a2:eb:a1:01:63:c4:8a:92:ba:06:80:9b:
+ 0d:85:f2:9f:f9:70:ac:d7:ad:f0:7a:3f:b8:92:2a:
+ 33:ca:69:d0:01:65:5d:31:38:1d:f6:1f:b2:17:07:
+ 7e:ac:88:67:a6:c4:5f:3e:93:94:61:e6:e4:49:9d:
+ ba:d4:d2:e8:e3:93:d1:66:79:c5:e3:1d:f8:5a:50:
+ 54:58:3d:04:b0:fd:65:d1:b3:8a:b5:8a:30:5f:b2:
+ dc:34:1a:14:f7:74:4c:03:29:97:63:5a:d7:de:bb:
+ eb:7f:4a:2a:90:59:c0:2b:47:09:82:8f:75:de:14:
+ 3f:bc:78:9a:69:25:80:5b:6c:a0:65:12:0d:29:61:
+ ac:f9
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Netscape Comment:
+ OpenSSL Generated Certificate
+ X509v3 Subject Key Identifier:
+ EC:6B:7C:79:B8:3B:11:1D:42:F3:9A:2A:CF:9A:15:59:D7:F9:D8:C6
+ X509v3 Authority Key Identifier:
+ keyid:A0:7E:0B:AD:A3:AD:37:D7:21:0B:75:6F:8A:90:5F:8C:C9:69:DF:98
+
+ Signature Algorithm: sha256WithRSAEncryption
+ 29:14:db:71:e9:a0:86:f8:cc:4d:e4:8a:76:78:a7:ff:4e:94:
+ b4:4d:92:dc:57:9a:52:64:46:27:15:8b:4f:2a:18:a7:0d:fc:
+ d2:75:ce:4e:49:97:0b:46:71:57:23:e3:a5:c0:c5:71:94:fc:
+ f2:1d:3b:06:93:82:03:59:56:d4:fb:09:06:08:b4:97:50:33:
+ cf:58:89:dd:91:31:07:26:9a:7e:7f:8d:71:de:09:dc:4f:e5:
+ 6b:a3:10:71:d4:50:24:43:a0:1c:f5:2a:d9:1a:fb:e3:d6:f1:
+ bc:6b:42:67:16:b4:3b:31:f4:ec:03:7d:78:e2:64:16:57:6d:
+ ba:7c:0c:e1:14:b2:7c:75:4e:2b:09:3e:86:e4:aa:cc:7e:5c:
+ 2b:bd:8d:26:4d:49:36:74:86:fe:c5:a6:15:4a:af:e8:b4:4e:
+ d5:f2:e1:59:c2:fb:7e:c3:c4:f1:63:d8:c2:b0:9a:ae:31:96:
+ 90:c3:09:d0:ce:2e:31:90:d7:83:dd:ac:31:cc:f7:87:41:08:
+ 92:33:28:52:fa:2d:9e:ad:ae:6a:9f:c3:be:ce:c1:a6:e4:16:
+ 2f:69:34:40:86:b6:10:21:0e:31:69:81:9e:fc:fd:c3:06:25:
+ 65:37:d3:d9:4a:20:84:aa:e7:0e:60:7c:bf:3f:88:67:ac:e5:
+ 8c:e0:61:d6
+-----BEGIN CERTIFICATE-----
+MIIDgTCCAmmgAwIBAgIBATANBgkqhkiG9w0BAQsFADBHMQswCQYDVQQGEwJKUDEO
+MAwGA1UECAwFVG9reW8xETAPBgNVBAoMCFJ1YnlUZXN0MRUwEwYDVQQDDAxSdWJ5
+IFRlc3QgQ0EwHhcNMDkwMTAxMDAwMDAwWhcNNDkxMjMxMjM1OTU5WjBEMQswCQYD
+VQQGEwJKUDEOMAwGA1UECAwFVG9reW8xETAPBgNVBAoMCFJ1YnlUZXN0MRIwEAYD
+VQQDDAkxMjcuMC4wLjEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDL
+s3GVEnD829Spp2bW0wndBoAZ4fLWHjG2ayB1UdynN6msW1ddaTa23h0s9kRk+OjW
+8No4arrCsZ7cu3mU4CUMznaHF115nhSevUwNqnQQOpbvdoLVcha1wawXLZCDc1zX
+pvU2D0xV8zBdGdwBDvjm/qWtUohZ3EoH7aLroQFjxIqSugaAmw2F8p/5cKzXrfB6
+P7iSKjPKadABZV0xOB32H7IXB36siGemxF8+k5Rh5uRJnbrU0ujjk9FmecXjHfha
+UFRYPQSw/WXRs4q1ijBfstw0GhT3dEwDKZdjWtfeu+t/SiqQWcArRwmCj3XeFD+8
+eJppJYBbbKBlEg0pYaz5AgMBAAGjezB5MAkGA1UdEwQCMAAwLAYJYIZIAYb4QgEN
+BB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0GA1UdDgQWBBTsa3x5
+uDsRHULzmirPmhVZ1/nYxjAfBgNVHSMEGDAWgBSgfguto6031yELdW+KkF+MyWnf
+mDANBgkqhkiG9w0BAQsFAAOCAQEAKRTbcemghvjMTeSKdnin/06UtE2S3FeaUmRG
+JxWLTyoYpw380nXOTkmXC0ZxVyPjpcDFcZT88h07BpOCA1lW1PsJBgi0l1Azz1iJ
+3ZExByaafn+Ncd4J3E/la6MQcdRQJEOgHPUq2Rr749bxvGtCZxa0OzH07AN9eOJk
+FldtunwM4RSyfHVOKwk+huSqzH5cK72NJk1JNnSG/sWmFUqv6LRO1fLhWcL7fsPE
+8WPYwrCarjGWkMMJ0M4uMZDXg92sMcz3h0EIkjMoUvotnq2uap/Dvs7BpuQWL2k0
+QIa2ECEOMWmBnvz9wwYlZTfT2UoghKrnDmB8vz+IZ6zljOBh1g==
+-----END CERTIFICATE-----
+End
+
+ SERVER_KEY = <<'End'
+RSA Private-Key: (2048 bit, 2 primes)
+modulus:
+ 00:cb:b3:71:95:12:70:fc:db:d4:a9:a7:66:d6:d3:
+ 09:dd:06:80:19:e1:f2:d6:1e:31:b6:6b:20:75:51:
+ dc:a7:37:a9:ac:5b:57:5d:69:36:b6:de:1d:2c:f6:
+ 44:64:f8:e8:d6:f0:da:38:6a:ba:c2:b1:9e:dc:bb:
+ 79:94:e0:25:0c:ce:76:87:17:5d:79:9e:14:9e:bd:
+ 4c:0d:aa:74:10:3a:96:ef:76:82:d5:72:16:b5:c1:
+ ac:17:2d:90:83:73:5c:d7:a6:f5:36:0f:4c:55:f3:
+ 30:5d:19:dc:01:0e:f8:e6:fe:a5:ad:52:88:59:dc:
+ 4a:07:ed:a2:eb:a1:01:63:c4:8a:92:ba:06:80:9b:
+ 0d:85:f2:9f:f9:70:ac:d7:ad:f0:7a:3f:b8:92:2a:
+ 33:ca:69:d0:01:65:5d:31:38:1d:f6:1f:b2:17:07:
+ 7e:ac:88:67:a6:c4:5f:3e:93:94:61:e6:e4:49:9d:
+ ba:d4:d2:e8:e3:93:d1:66:79:c5:e3:1d:f8:5a:50:
+ 54:58:3d:04:b0:fd:65:d1:b3:8a:b5:8a:30:5f:b2:
+ dc:34:1a:14:f7:74:4c:03:29:97:63:5a:d7:de:bb:
+ eb:7f:4a:2a:90:59:c0:2b:47:09:82:8f:75:de:14:
+ 3f:bc:78:9a:69:25:80:5b:6c:a0:65:12:0d:29:61:
+ ac:f9
+publicExponent: 65537 (0x10001)
+privateExponent:
+ 12:be:d5:b2:01:3b:72:99:8c:4d:7c:81:43:3d:b2:
+ 87:ab:84:78:5d:49:aa:98:a6:bc:81:c9:3f:e2:a3:
+ aa:a3:bd:b2:85:c9:59:68:48:47:b5:d2:fb:83:42:
+ 32:04:91:f0:cd:c3:57:33:c3:32:0d:84:70:0d:b4:
+ 97:95:b4:f3:23:c0:d6:97:b8:db:6b:47:bc:7f:f1:
+ 12:c4:df:df:6a:74:df:5e:89:95:b8:e5:0c:1e:e1:
+ 86:54:84:1b:04:af:c3:8c:b2:be:21:d4:45:88:96:
+ a7:ca:ac:6b:50:84:69:45:7f:db:9e:5f:bb:dd:40:
+ d6:cf:f0:91:3c:84:d3:38:65:c9:15:f7:9e:37:aa:
+ 1a:2e:bc:16:b6:95:be:bc:af:45:76:ba:ad:99:f6:
+ ef:6a:e8:fd:f0:31:89:19:c4:04:67:a1:ec:c4:79:
+ 59:08:77:ab:0b:65:88:88:02:b1:38:5c:80:4e:27:
+ 78:b2:a5:bd:b5:ad:d5:9c:4c:ea:ad:db:05:56:25:
+ 70:28:da:22:fb:d8:de:8c:3b:78:fe:3e:cf:ed:1b:
+ f9:97:c6:b6:4a:bf:60:08:8f:dc:85:5e:b1:49:ab:
+ 87:8b:68:72:f4:6a:3f:bc:db:a3:6c:f7:e8:b0:15:
+ bb:4b:ba:37:49:a2:d1:7c:f8:4f:1b:05:11:22:d9:
+ 81
+prime1:
+ 00:fb:d2:cb:14:61:00:c1:7a:83:ba:fe:79:97:a2:
+ 4d:5a:ea:40:78:96:6e:d2:be:71:5b:c6:2c:1f:c9:
+ 18:48:6b:ae:20:86:87:b5:08:0b:17:69:ca:93:cd:
+ 00:36:22:51:7b:d5:2d:8c:0c:0e:de:bc:86:a8:07:
+ 0e:c5:57:e4:df:be:ed:7d:cc:b1:a4:d6:a8:2b:00:
+ 65:2a:69:30:5e:dc:6d:6d:c4:c8:7e:20:34:eb:6f:
+ 5e:cf:b3:b8:2e:8d:56:31:44:a8:17:ea:be:65:19:
+ ff:da:14:e0:0c:73:56:14:08:47:4c:5b:79:51:74:
+ 5d:bc:e7:fe:01:2f:55:27:69
+prime2:
+ 00:cf:14:54:47:bb:5f:5d:d6:2b:2d:ed:a6:8a:6f:
+ 36:fc:47:5e:9f:84:ae:aa:1f:f8:44:50:91:15:f5:
+ ed:9d:29:d9:2b:2a:19:66:56:2e:96:15:b5:8e:a9:
+ 7f:89:27:21:b5:57:55:7e:2a:c5:8c:93:fe:f6:0a:
+ a5:17:15:91:91:b3:7d:35:1a:d5:9a:2e:b8:0d:ad:
+ e6:97:6d:83:a3:27:29:ee:00:74:ef:57:34:f3:07:
+ ad:12:43:37:0c:5c:b7:26:34:bc:4e:3a:43:65:6b:
+ 0c:b8:23:ac:77:fd:b2:23:eb:7b:65:70:f6:96:c4:
+ 17:2c:aa:24:b8:a5:5e:b7:11
+exponent1:
+ 00:92:32:ae:f4:05:dd:0a:76:b6:43:b9:b9:9d:ee:
+ fc:39:ec:05:c1:fc:94:1a:85:b6:0a:31:e3:2c:10:
+ f3:a8:17:db:df:c6:3a:c3:3f:08:31:6f:99:cc:75:
+ 17:ca:55:e2:38:a2:6a:ef:03:91:1e:7f:15:2e:37:
+ ea:bb:67:6b:d8:fa:5f:a6:c9:4f:d9:03:46:5e:b0:
+ bc:0b:03:46:b1:cc:07:3b:d3:23:13:16:5f:a2:cf:
+ e5:9b:70:1b:5d:eb:70:3e:ea:3d:2c:a5:7c:23:f6:
+ 14:33:e8:2a:ab:0f:ca:c9:96:84:ce:2f:cd:1f:1d:
+ 0f:ce:bc:61:1b:0e:ff:c1:01
+exponent2:
+ 00:9e:0b:f3:03:48:73:d1:e7:9a:cf:13:f9:ae:e0:
+ 91:03:dc:e8:d0:30:f1:2a:30:fa:48:11:81:9a:54:
+ 37:c5:62:e2:37:fa:8a:a6:3b:92:94:c3:fe:ec:e2:
+ 5a:cf:70:09:5f:21:47:c3:e2:9b:21:de:f6:92:0c:
+ af:d1:bd:89:7b:bd:95:0b:49:ee:cb:1d:6b:26:2d:
+ 9a:b7:ea:42:b4:ec:38:29:49:39:f6:4e:05:c0:93:
+ 14:39:c3:09:29:ab:3d:b1:b0:40:24:28:7d:b5:d3:
+ 0d:43:21:1f:09:f9:9b:d3:a4:6f:6a:8d:db:f6:57:
+ b5:24:46:bb:7e:1d:e0:fb:31
+coefficient:
+ 10:93:1d:c8:33:a5:c1:d3:84:6a:22:68:e5:60:cc:
+ 9c:27:0a:52:0b:58:a3:0c:83:f4:f4:46:09:0c:a1:
+ 41:a6:ea:bf:80:9d:0e:5d:d8:3d:25:00:c5:a1:35:
+ 7a:8c:ea:95:16:94:c3:7c:8f:2b:e0:53:ea:66:ae:
+ 19:be:55:04:3d:ee:e2:4b:a8:69:1b:7e:d8:09:7f:
+ ed:7c:ee:95:88:10:dc:4b:5b:bf:81:a4:e8:dc:7e:
+ 4f:e5:c3:90:c4:e5:5a:90:10:32:d6:08:b5:1f:5d:
+ 09:18:d8:44:28:e4:c4:c7:07:75:9b:9b:b3:80:86:
+ 68:9d:fe:68:f3:4d:db:66
+writing RSA key
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpAIBAAKCAQEAy7NxlRJw/NvUqadm1tMJ3QaAGeHy1h4xtmsgdVHcpzeprFtX
+XWk2tt4dLPZEZPjo1vDaOGq6wrGe3Lt5lOAlDM52hxddeZ4Unr1MDap0EDqW73aC
+1XIWtcGsFy2Qg3Nc16b1Ng9MVfMwXRncAQ745v6lrVKIWdxKB+2i66EBY8SKkroG
+gJsNhfKf+XCs163wej+4kiozymnQAWVdMTgd9h+yFwd+rIhnpsRfPpOUYebkSZ26
+1NLo45PRZnnF4x34WlBUWD0EsP1l0bOKtYowX7LcNBoU93RMAymXY1rX3rvrf0oq
+kFnAK0cJgo913hQ/vHiaaSWAW2ygZRINKWGs+QIDAQABAoIBABK+1bIBO3KZjE18
+gUM9soerhHhdSaqYpryByT/io6qjvbKFyVloSEe10vuDQjIEkfDNw1czwzINhHAN
+tJeVtPMjwNaXuNtrR7x/8RLE399qdN9eiZW45Qwe4YZUhBsEr8OMsr4h1EWIlqfK
+rGtQhGlFf9ueX7vdQNbP8JE8hNM4ZckV9543qhouvBa2lb68r0V2uq2Z9u9q6P3w
+MYkZxARnoezEeVkId6sLZYiIArE4XIBOJ3iypb21rdWcTOqt2wVWJXAo2iL72N6M
+O3j+Ps/tG/mXxrZKv2AIj9yFXrFJq4eLaHL0aj+826Ns9+iwFbtLujdJotF8+E8b
+BREi2YECgYEA+9LLFGEAwXqDuv55l6JNWupAeJZu0r5xW8YsH8kYSGuuIIaHtQgL
+F2nKk80ANiJRe9UtjAwO3ryGqAcOxVfk377tfcyxpNaoKwBlKmkwXtxtbcTIfiA0
+629ez7O4Lo1WMUSoF+q+ZRn/2hTgDHNWFAhHTFt5UXRdvOf+AS9VJ2kCgYEAzxRU
+R7tfXdYrLe2mim82/Eden4Suqh/4RFCRFfXtnSnZKyoZZlYulhW1jql/iSchtVdV
+firFjJP+9gqlFxWRkbN9NRrVmi64Da3ml22Doycp7gB071c08wetEkM3DFy3JjS8
+TjpDZWsMuCOsd/2yI+t7ZXD2lsQXLKokuKVetxECgYEAkjKu9AXdCna2Q7m5ne78
+OewFwfyUGoW2CjHjLBDzqBfb38Y6wz8IMW+ZzHUXylXiOKJq7wORHn8VLjfqu2dr
+2PpfpslP2QNGXrC8CwNGscwHO9MjExZfos/lm3AbXetwPuo9LKV8I/YUM+gqqw/K
+yZaEzi/NHx0PzrxhGw7/wQECgYEAngvzA0hz0eeazxP5ruCRA9zo0DDxKjD6SBGB
+mlQ3xWLiN/qKpjuSlMP+7OJaz3AJXyFHw+KbId72kgyv0b2Je72VC0nuyx1rJi2a
+t+pCtOw4KUk59k4FwJMUOcMJKas9sbBAJCh9tdMNQyEfCfmb06Rvao3b9le1JEa7
+fh3g+zECgYAQkx3IM6XB04RqImjlYMycJwpSC1ijDIP09EYJDKFBpuq/gJ0OXdg9
+JQDFoTV6jOqVFpTDfI8r4FPqZq4ZvlUEPe7iS6hpG37YCX/tfO6ViBDcS1u/gaTo
+3H5P5cOQxOVakBAy1gi1H10JGNhEKOTExwd1m5uzgIZonf5o803bZg==
+-----END RSA PRIVATE KEY-----
+End
+
+ DHPARAMS = <<'End'
+ DH Parameters: (2048 bit)
+ prime:
+ 00:ec:4e:a4:06:b6:22:ca:f9:8a:00:cc:d0:ee:2f:
+ 16:bf:05:64:f5:8f:fe:7f:c4:bb:b0:24:cd:ef:5d:
+ 8a:90:ad:dc:a9:dd:63:84:90:d8:25:ba:d8:78:d5:
+ 77:91:42:0a:84:fc:56:1e:13:9b:1c:aa:43:d5:1f:
+ 38:52:92:fe:b3:66:f9:e7:e8:8c:77:a1:a6:2f:b3:
+ 98:98:d2:13:fc:57:1c:2a:14:dc:bd:e6:9b:54:19:
+ 99:4f:ce:81:64:a6:32:7f:8e:61:50:5f:45:3a:e5:
+ 0c:f7:13:f3:b8:ad:d5:77:ca:09:42:f7:d8:30:27:
+ 7b:2c:f0:b4:b5:a0:04:96:34:0b:47:81:1d:7f:c1:
+ 3a:62:86:8e:7d:f8:13:7f:9a:b1:8b:09:23:9e:55:
+ 59:41:cd:f0:86:09:c4:b7:d1:69:54:cb:d0:f5:e9:
+ 27:c9:e1:81:e4:a1:df:6b:20:1c:df:e8:54:02:f2:
+ 37:fc:2a:f7:d5:b3:6f:79:7e:70:22:78:79:18:3c:
+ 75:14:68:4a:05:9f:ac:d4:7f:9a:79:db:9d:0a:6e:
+ ec:0a:04:70:bf:c9:4a:59:81:a2:1f:33:9b:4a:66:
+ bc:03:ce:8a:1b:e3:03:ec:ba:39:26:ab:90:dc:39:
+ 41:a1:d8:f7:20:3c:8f:af:12:2f:f7:a9:6f:44:f1:
+ 6d:03
+ generator: 2 (0x2)
+-----BEGIN DH PARAMETERS-----
+MIIBCAKCAQEA7E6kBrYiyvmKAMzQ7i8WvwVk9Y/+f8S7sCTN712KkK3cqd1jhJDY
+JbrYeNV3kUIKhPxWHhObHKpD1R84UpL+s2b55+iMd6GmL7OYmNIT/FccKhTcveab
+VBmZT86BZKYyf45hUF9FOuUM9xPzuK3Vd8oJQvfYMCd7LPC0taAEljQLR4Edf8E6
+YoaOffgTf5qxiwkjnlVZQc3whgnEt9FpVMvQ9eknyeGB5KHfayAc3+hUAvI3/Cr3
+1bNveX5wInh5GDx1FGhKBZ+s1H+aedudCm7sCgRwv8lKWYGiHzObSma8A86KG+MD
+7Lo5JquQ3DlBodj3IDyPrxIv96lvRPFtAwIBAg==
+-----END DH PARAMETERS-----
+End
+ end
+end
diff --git a/test/openssl/fixtures/pkey/dh1024.pem b/test/openssl/fixtures/pkey/dh1024.pem
deleted file mode 100644
index f99c757f21..0000000000
--- a/test/openssl/fixtures/pkey/dh1024.pem
+++ /dev/null
@@ -1,5 +0,0 @@
------BEGIN DH PARAMETERS-----
-MIGHAoGBAKnKQ8MNK6nYZzLrrcuTsLxuiJGXoOO5gT+tljOTbHBuiktdMTITzIY0
-pFxIvjG05D7HoBZQfrR0c92NGWPkAiCkhQKB8JCbPVzwNLDy6DZ0pmofDKrEsYHG
-AQjjxMXhwULlmuR/K+WwlaZPiLIBYalLAZQ7ZbOPeVkJ8ePao0eLAgEC
------END DH PARAMETERS-----
diff --git a/test/openssl/fixtures/pkey/dh2048_ffdhe2048.pem b/test/openssl/fixtures/pkey/dh2048_ffdhe2048.pem
new file mode 100644
index 0000000000..9b182b7201
--- /dev/null
+++ b/test/openssl/fixtures/pkey/dh2048_ffdhe2048.pem
@@ -0,0 +1,8 @@
+-----BEGIN DH PARAMETERS-----
+MIIBCAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz
++8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a
+87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7
+YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi
+7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD
+ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg==
+-----END DH PARAMETERS-----
diff --git a/test/openssl/fixtures/pkey/dsa2048.pem b/test/openssl/fixtures/pkey/dsa2048.pem
new file mode 100644
index 0000000000..3f22b22b58
--- /dev/null
+++ b/test/openssl/fixtures/pkey/dsa2048.pem
@@ -0,0 +1,15 @@
+-----BEGIN PRIVATE KEY-----
+MIICXgIBADCCAjYGByqGSM44BAEwggIpAoIBAQDXZhJ/dQoWkQELzjzlx8FtIp96
+voCYe5NY0H8j0jz7GyHpXt41+MteqkZK3/Ah+cNR9uG8iEYArAZ71LcWotfee2Gz
+xdxozr9bRt0POYhO2YIsfMpBrEskPsDH2g/2nFV8l4OJgxU2qZUrF4PN5ha+Mu6u
+sVtN8hjvAvnbf4Pxn0b8NN9f4PJncroUa8acv5WsV85E1RW7NYCefggU4LytYIHg
+euRF9eY9gVCX5MkUgW2xODHIYJhwk/+5lJxG7qUsSahD/nPHO/yoWgdVHq2DkdTq
+KYXkAxx2PJcTBOHTglhE6mgCbEKp8vcfElnBWyCT6QykclZiPXXD2JV829J/Ah0A
+vYa+/G/gUZiomyejVje6UsGoCc+vInxmovOL8QKCAQEAhnKEigYPw6u8JY7v5iGo
+Ylz8qiMFYmaJCwevf3KCjWeEXuNO4OrKdfzkQl1tPuGLioYFfP1A2yGosjdUdLEB
+0JqnzlKxUp+G6RfBj+WYzbgc5hr7t0M+reAJh09/hDzqfxjcgiHstq7mpRXBP8Y7
+iu27s7TRYJNSAYRvWcXNSBEUym3mHBBbZn7VszYooSrn60/iZ8I+VY1UF/fgqhbj
+JfaaZNQCDO9K3Vb3rsXoYd8+bOZIen9uHB+pNjMqhpl4waysqrlpGFeeqdxivH6S
+vkrHLs6/eWVMnS08RdcryoCrI3Bm8mMBKQglDwKLnWLfzG565qEhslzyCd/l9k9a
+cwQfAh0Ao8/g72fSFmo04FizM7DZJSIPqDLjfZu9hLvUFA==
+-----END PRIVATE KEY-----
diff --git a/test/openssl/fixtures/pkey/p256_too_large.pem b/test/openssl/fixtures/pkey/p256_too_large.pem
new file mode 100644
index 0000000000..a73ac37f87
--- /dev/null
+++ b/test/openssl/fixtures/pkey/p256_too_large.pem
@@ -0,0 +1,5 @@
+-----BEGIN EC PRIVATE KEY-----
+MHcCAQEEIP+TT0V8Fndsnacji9tyf6hmhHywcOWTee9XkiBeJoVloAoGCCqGSM49
+AwEHoUQDQgAEBkhhJIU/2/YdPSlY2I1k25xjK4trr5OXSgXvBC21PtY0HQ7lor7A
+jzT0giJITqmcd81fwGw5+96zLcdxTF1hVQ==
+-----END EC PRIVATE KEY-----
diff --git a/test/openssl/fixtures/pkey/p384_invalid.pem b/test/openssl/fixtures/pkey/p384_invalid.pem
new file mode 100644
index 0000000000..d5cdc9a3af
--- /dev/null
+++ b/test/openssl/fixtures/pkey/p384_invalid.pem
@@ -0,0 +1,6 @@
+-----BEGIN EC PRIVATE KEY-----
+MIGkAgEBBDDA1Tm0m7YhkfeVpFuarAJYVlHp2tQj+1fOBiLa10t9E8TiQO/hVfxB
+vGaVEQwOheWgBwYFK4EEACKhZANiAASyGqmryZGqdpsq5gEDIfNvgC3AwSJxiBCL
+XKHBTFRp+tCezLDOK/6V8KK/vVGBJlGFW6/I7ahyXprxS7xs7hPA9iz5YiuqXlu+
+lbrIpZOz7b73hyQQCkvbBO/Avg+hPAk=
+-----END EC PRIVATE KEY-----
diff --git a/test/openssl/test_asn1.rb b/test/openssl/test_asn1.rb
index 6bd847806b..7b1722e5df 100644
--- a/test/openssl/test_asn1.rb
+++ b/test/openssl/test_asn1.rb
@@ -14,7 +14,7 @@ class OpenSSL::TestASN1 < OpenSSL::TestCase
["keyUsage","keyCertSign, cRLSign",true],
["subjectKeyIdentifier","hash",false],
]
- dgst = OpenSSL::Digest.new('SHA1')
+ dgst = OpenSSL::Digest.new('SHA256')
cert = OpenSSL::TestUtils.issue_cert(
subj, key, s, exts, nil, nil, digest: dgst, not_before: now, not_after: now+3600)
@@ -42,7 +42,7 @@ class OpenSSL::TestASN1 < OpenSSL::TestCase
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("1.2.840.113549.1.1.11", sig.value[0].oid)
assert_equal(OpenSSL::ASN1::Null, sig.value[1].class)
dn = tbs_cert.value[3] # issuer
@@ -170,7 +170,7 @@ class OpenSSL::TestASN1 < OpenSSL::TestCase
str = +"\000"; str[0] = 0b00000110.chr
assert_equal(str, extv.value)
- ext = extensions.value[0].value[2] # subjetKeyIdentifier
+ ext = extensions.value[0].value[2] # subjectKeyIdentifier
assert_equal(OpenSSL::ASN1::Sequence, ext.class)
assert_equal(2, ext.value.size)
assert_equal(OpenSSL::ASN1::ObjectId, ext.value[0].class)
@@ -189,7 +189,7 @@ class OpenSSL::TestASN1 < OpenSSL::TestCase
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.new('SHA1'), tbs_cert.to_der)
+ cululated_sig = key.sign(OpenSSL::Digest.new('SHA256'), tbs_cert.to_der)
assert_equal(cululated_sig, sig_val.value)
end
@@ -323,14 +323,9 @@ class OpenSSL::TestASN1 < OpenSSL::TestCase
assert_raise(OpenSSL::ASN1::ASN1Error) { OpenSSL::ASN1::ObjectId.new("3.0".b).to_der }
assert_raise(OpenSSL::ASN1::ASN1Error) { OpenSSL::ASN1::ObjectId.new("0.40".b).to_der }
- begin
- oid = (0...100).to_a.join(".").b
- obj = OpenSSL::ASN1::ObjectId.new(oid)
- assert_equal oid, obj.oid
- rescue OpenSSL::ASN1::ASN1Error
- pend "OBJ_obj2txt() not working (LibreSSL?)" if $!.message =~ /OBJ_obj2txt/
- raise
- end
+ oid = (0...100).to_a.join(".").b
+ obj = OpenSSL::ASN1::ObjectId.new(oid)
+ assert_equal oid, obj.oid
aki = [
OpenSSL::ASN1::ObjectId.new("authorityKeyIdentifier"),
@@ -404,9 +399,6 @@ class OpenSSL::TestASN1 < OpenSSL::TestCase
def test_utctime
encode_decode_test B(%w{ 17 0D }) + "160908234339Z".b,
OpenSSL::ASN1::UTCTime.new(Time.utc(2016, 9, 8, 23, 43, 39))
- # Seconds is omitted
- decode_test B(%w{ 17 0B }) + "1609082343Z".b,
- OpenSSL::ASN1::UTCTime.new(Time.utc(2016, 9, 8, 23, 43, 0))
begin
# possible range of UTCTime is 1969-2068 currently
encode_decode_test B(%w{ 17 0D }) + "690908234339Z".b,
@@ -432,8 +424,6 @@ class OpenSSL::TestASN1 < OpenSSL::TestCase
OpenSSL::ASN1::GeneralizedTime.new(Time.utc(2016, 12, 8, 19, 34, 29))
encode_decode_test B(%w{ 18 0F }) + "99990908234339Z".b,
OpenSSL::ASN1::GeneralizedTime.new(Time.utc(9999, 9, 8, 23, 43, 39))
- decode_test B(%w{ 18 0D }) + "201612081934Z".b,
- OpenSSL::ASN1::GeneralizedTime.new(Time.utc(2016, 12, 8, 19, 34, 0))
# not implemented
# decode_test B(%w{ 18 13 }) + "20161208193439+0930".b,
# OpenSSL::ASN1::GeneralizedTime.new(Time.new(2016, 12, 8, 19, 34, 39, "+09:30"))
diff --git a/test/openssl/test_bn.rb b/test/openssl/test_bn.rb
index c36d6b89d8..ea88ff06ce 100644
--- a/test/openssl/test_bn.rb
+++ b/test/openssl/test_bn.rb
@@ -174,6 +174,14 @@ class OpenSSL::TestBN < OpenSSL::TestCase
assert_equal(0, 59.to_bn.mod_sqr(59))
end
+ def test_mod_sqrt
+ assert_equal(4, 4.to_bn.mod_sqrt(5).mod_sqr(5))
+ # One of 189484 or 326277 is returned as a square root of 2 (mod 515761).
+ assert_equal(2, 2.to_bn.mod_sqrt(515761).mod_sqr(515761))
+ assert_equal(0, 5.to_bn.mod_sqrt(5))
+ assert_raise(OpenSSL::BNError) { 3.to_bn.mod_sqrt(5) }
+ end
+
def test_mod_inverse
assert_equal(2, 3.to_bn.mod_inverse(5))
assert_raise(OpenSSL::BNError) { 3.to_bn.mod_inverse(6) }
@@ -248,6 +256,10 @@ class OpenSSL::TestBN < OpenSSL::TestCase
r5 = OpenSSL::BN.rand_range(256)
assert_include(0..255, r5)
}
+
+ # Aliases
+ assert_include(128..255, OpenSSL::BN.pseudo_rand(8))
+ assert_include(0..255, OpenSSL::BN.pseudo_rand_range(256))
end
begin
@@ -330,6 +342,31 @@ class OpenSSL::TestBN < OpenSSL::TestCase
e.set_flags(0)
assert_equal(4, e.get_flags(OpenSSL::BN::CONSTTIME))
end
+
+ if respond_to?(:ractor)
+ ractor
+ def test_ractor
+ assert_equal(@e1, Ractor.new { OpenSSL::BN.new("999") }.take)
+ assert_equal(@e3, Ractor.new { OpenSSL::BN.new("\a\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 2) }.take)
+ assert_equal("999", Ractor.new(@e1) { |e1| e1.to_s }.take)
+ assert_equal("07FFFFFFFFFFFFFFFFFFFFFFFFFF", Ractor.new(@e3) { |e3| e3.to_s(16) }.take)
+ assert_equal(2**107-1, Ractor.new(@e3) { _1.to_i }.take)
+ assert_equal([1000, -999], Ractor.new(@e2) { _1.coerce(1000) }.take)
+ assert_equal(false, Ractor.new { 1.to_bn.zero? }.take)
+ assert_equal(true, Ractor.new { 1.to_bn.one? }.take)
+ assert_equal(true, Ractor.new(@e2) { _1.negative? }.take)
+ assert_equal("-03E7", Ractor.new(@e2) { _1.to_s(16) }.take)
+ assert_equal(2**107-1, Ractor.new(@e3) { _1.to_i }.take)
+ assert_equal([1000, -999], Ractor.new(@e2) { _1.coerce(1000) }.take)
+ assert_equal(true, Ractor.new { 0.to_bn.zero? }.take)
+ assert_equal(true, Ractor.new { 1.to_bn.one? }.take )
+ assert_equal(false,Ractor.new { 2.to_bn.odd? }.take)
+ assert_equal(true, Ractor.new(@e2) { _1.negative? }.take)
+ assert_include(128..255, Ractor.new { OpenSSL::BN.rand(8)}.take)
+ assert_include(0...2**32, Ractor.new { OpenSSL::BN.generate_prime(32) }.take)
+ assert_equal(0, Ractor.new { OpenSSL::BN.new(999).get_flags(OpenSSL::BN::CONSTTIME) }.take)
+ end
+ end
end
end
diff --git a/test/openssl/test_cipher.rb b/test/openssl/test_cipher.rb
index 6d18c0c85c..41885fd59b 100644
--- a/test/openssl/test_cipher.rb
+++ b/test/openssl/test_cipher.rb
@@ -108,12 +108,6 @@ class OpenSSL::TestCipher < OpenSSL::TestCase
assert_not_equal s1, s2
end
- def test_empty_data
- cipher = OpenSSL::Cipher.new("DES-EDE3-CBC").encrypt
- cipher.random_key
- assert_raise(ArgumentError) { cipher.update("") }
- end
-
def test_initialize
cipher = OpenSSL::Cipher.new("DES-EDE3-CBC")
assert_raise(RuntimeError) { cipher.__send__(:initialize, "DES-EDE3-CBC") }
@@ -135,14 +129,11 @@ class OpenSSL::TestCipher < OpenSSL::TestCase
end
def test_ciphers
- OpenSSL::Cipher.ciphers.each{|name|
- next if /netbsd/ =~ RUBY_PLATFORM && /idea|rc5/i =~ name
- begin
- assert_kind_of(OpenSSL::Cipher, OpenSSL::Cipher.new(name))
- rescue OpenSSL::Cipher::CipherError => e
- raise unless /wrap/ =~ name and /wrap mode not allowed/ =~ e.message
- end
- }
+ ciphers = OpenSSL::Cipher.ciphers
+ assert_kind_of Array, ciphers
+ assert_include ciphers, "aes-128-cbc"
+ assert_include ciphers, "aes128" # alias of aes-128-cbc
+ assert_include ciphers, "aes-128-gcm"
end
def test_AES
@@ -214,7 +205,7 @@ class OpenSSL::TestCipher < OpenSSL::TestCase
assert_raise(OpenSSL::Cipher::CipherError) { cipher.update(ct2) }
end if has_cipher?("aes-128-ccm") &&
OpenSSL::Cipher.new("aes-128-ccm").authenticated? &&
- OpenSSL::OPENSSL_VERSION_NUMBER >= 0x1010103f # version >= 1.1.1c
+ openssl?(1, 1, 1, 0x03, 0xf) # version >= 1.1.1c
def test_aes_gcm
# GCM spec Appendix B Test Case 4
@@ -340,6 +331,22 @@ class OpenSSL::TestCipher < OpenSSL::TestCase
assert_equal tag1, tag2
end
+ def test_aes_keywrap_pad
+ # RFC 5649 Section 6; The second example
+ kek = ["5840df6e29b02af1ab493b705bf16ea1ae8338f4dcc176a8"].pack("H*")
+ key = ["466f7250617369"].pack("H*")
+ wrap = ["afbeb0f07dfbf5419200f2ccb50bb24f"].pack("H*")
+
+ begin
+ cipher = OpenSSL::Cipher.new("id-aes192-wrap-pad").encrypt
+ rescue OpenSSL::Cipher::CipherError, RuntimeError
+ omit "id-aes192-wrap-pad is not supported: #$!"
+ end
+ cipher.key = kek
+ ct = cipher.update(key) << cipher.final
+ assert_equal wrap, ct
+ end
+
def test_non_aead_cipher_set_auth_data
assert_raise(OpenSSL::Cipher::CipherError) {
cipher = OpenSSL::Cipher.new("aes-128-cfb").encrypt
diff --git a/test/openssl/test_config.rb b/test/openssl/test_config.rb
index 769e65ceb5..6dbb9c6138 100644
--- a/test/openssl/test_config.rb
+++ b/test/openssl/test_config.rb
@@ -61,14 +61,14 @@ foo\\bar::foo\\bar = baz
[default1 default2]\t\t # space is allowed in section name
fo =b ar # space allowed in value
[emptysection]
- [doller ]
+ [dollar ]
foo=bar
bar = $(foo)
baz = 123$(default::bar)456${foo}798
qux = ${baz}
quxx = $qux.$qux
__EOC__
- assert_equal(['default', 'default1 default2', 'doller', 'emptysection', 'foo', 'foo\\bar'], c.sections.sort)
+ assert_equal(['default', 'default1 default2', 'dollar', 'emptysection', 'foo', 'foo\\bar'], c.sections.sort)
assert_equal(['', 'a', 'bar', 'baz', 'd', 'dq', 'dq2', 'esc', 'foo\\bar', 'sq'], c['default'].keys.sort)
assert_equal('c', c['default'][''])
assert_equal('', c['default']['a'])
@@ -84,29 +84,26 @@ __EOC__
assert_equal('baz', c['foo\\bar']['foo\\bar'])
assert_equal('b ar', c['default1 default2']['fo'])
- # dolloer
- assert_equal('bar', c['doller']['foo'])
- assert_equal('bar', c['doller']['bar'])
- assert_equal('123baz456bar798', c['doller']['baz'])
- assert_equal('123baz456bar798', c['doller']['qux'])
- assert_equal('123baz456bar798.123baz456bar798', c['doller']['quxx'])
+ # dollar
+ assert_equal('bar', c['dollar']['foo'])
+ assert_equal('bar', c['dollar']['bar'])
+ assert_equal('123baz456bar798', c['dollar']['baz'])
+ assert_equal('123baz456bar798', c['dollar']['qux'])
+ assert_equal('123baz456bar798.123baz456bar798', c['dollar']['quxx'])
- excn = assert_raise(OpenSSL::ConfigError) do
+ assert_raise_with_message(OpenSSL::ConfigError, /error in line 1: variable has no value/) do
OpenSSL::Config.parse("foo = $bar")
end
- assert_equal("error in line 1: variable has no value", excn.message)
- excn = assert_raise(OpenSSL::ConfigError) do
+ assert_raise_with_message(OpenSSL::ConfigError, /error in line 1: no close brace/) do
OpenSSL::Config.parse("foo = $(bar")
end
- assert_equal("error in line 1: no close brace", excn.message)
- excn = assert_raise(OpenSSL::ConfigError) do
+ assert_raise_with_message(OpenSSL::ConfigError, /error in line 1: missing equal sign/) do
OpenSSL::Config.parse("f o =b ar # no space in key")
end
- assert_equal("error in line 1: missing equal sign", excn.message)
- excn = assert_raise(OpenSSL::ConfigError) do
+ assert_raise_with_message(OpenSSL::ConfigError, /error in line 7: missing close square bracket/) do
OpenSSL::Config.parse(<<__EOC__)
# comment 1 # comments
@@ -117,7 +114,6 @@ __EOC__
[third # section not terminated
__EOC__
end
- assert_equal("error in line 7: missing close square bracket", excn.message)
end
def test_s_parse_include
diff --git a/test/openssl/test_digest.rb b/test/openssl/test_digest.rb
index 8d7046e831..988330e405 100644
--- a/test/openssl/test_digest.rb
+++ b/test/openssl/test_digest.rb
@@ -54,7 +54,7 @@ class OpenSSL::TestDigest < OpenSSL::TestCase
end
def test_digest_constants
- %w{MD4 MD5 RIPEMD160 SHA1 SHA224 SHA256 SHA384 SHA512}.each do |name|
+ %w{MD5 SHA1 SHA224 SHA256 SHA384 SHA512}.each do |name|
assert_not_nil(OpenSSL::Digest.new(name))
klass = OpenSSL::Digest.const_get(name.tr('-', '_'))
assert_not_nil(klass.new)
@@ -67,7 +67,7 @@ class OpenSSL::TestDigest < OpenSSL::TestCase
end
def encode16(str)
- str.unpack("H*").first
+ str.unpack1("H*")
end
def test_sha2
@@ -88,7 +88,7 @@ class OpenSSL::TestDigest < OpenSSL::TestCase
end
def test_sha512_truncate
- pend "SHA512_224 is not implemented" unless digest_available?('SHA512-224')
+ pend "SHA512_224 is not implemented" unless digest_available?('sha512-224')
sha512_224_a = "d5cdb9ccc769a5121d4175f2bfdd13d6310e0d3d361ea75d82108327"
sha512_256_a = "455e518824bc0601f9fb858ff5c37d417d67c2f8e0df2babe4808858aea830f8"
@@ -100,7 +100,7 @@ class OpenSSL::TestDigest < OpenSSL::TestCase
end
def test_sha3
- pend "SHA3 is not implemented" unless digest_available?('SHA3-224')
+ pend "SHA3 is not implemented" unless digest_available?('sha3-224')
s224 = '6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7'
s256 = 'a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a'
s384 = '0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2ac3713831264adb47fb6bd1e058d5f004'
@@ -126,6 +126,15 @@ class OpenSSL::TestDigest < OpenSSL::TestCase
end
end
+ def test_digests
+ digests = OpenSSL::Digest.digests
+ assert_kind_of Array, digests
+ assert_include digests, "md5"
+ assert_include digests, "sha1"
+ assert_include digests, "sha256"
+ assert_include digests, "sha512"
+ end
+
private
def check_digest(oid)
@@ -138,11 +147,8 @@ class OpenSSL::TestDigest < OpenSSL::TestCase
end
def digest_available?(name)
- begin
- OpenSSL::Digest.new(name)
- rescue RuntimeError
- false
- end
+ @digests ||= OpenSSL::Digest.digests
+ @digests.include?(name)
end
end
diff --git a/test/openssl/test_engine.rb b/test/openssl/test_engine.rb
index 1ede6ed086..b6025f915b 100644
--- a/test/openssl/test_engine.rb
+++ b/test/openssl/test_engine.rb
@@ -26,7 +26,7 @@ class OpenSSL::TestEngine < OpenSSL::TestCase
with_openssl <<-'end;'
orig = OpenSSL::Engine.engines
pend "'openssl' is already loaded" if orig.any? { |e| e.id == "openssl" }
- engine = get_engine
+ engine = OpenSSL::Engine.by_id("openssl")
assert_not_nil(engine)
assert_equal(1, OpenSSL::Engine.engines.size - orig.size)
end;
@@ -34,7 +34,7 @@ class OpenSSL::TestEngine < OpenSSL::TestCase
def test_openssl_engine_id_name_inspect
with_openssl <<-'end;'
- engine = get_engine
+ engine = OpenSSL::Engine.by_id("openssl")
assert_equal("openssl", engine.id)
assert_not_nil(engine.name)
assert_not_nil(engine.inspect)
@@ -43,7 +43,7 @@ class OpenSSL::TestEngine < OpenSSL::TestCase
def test_openssl_engine_digest_sha1
with_openssl <<-'end;'
- engine = get_engine
+ engine = OpenSSL::Engine.by_id("openssl")
digest = engine.digest("SHA1")
assert_not_nil(digest)
data = "test"
@@ -59,12 +59,21 @@ class OpenSSL::TestEngine < OpenSSL::TestCase
end
with_openssl(<<-'end;', ignore_stderr: true)
- engine = get_engine
+ engine = OpenSSL::Engine.by_id("openssl")
algo = "RC4"
data = "a" * 1000
key = OpenSSL::Random.random_bytes(16)
- encrypted = crypt_data(data, key, :encrypt) { engine.cipher(algo) }
- decrypted = crypt_data(encrypted, key, :decrypt) { OpenSSL::Cipher.new(algo) }
+
+ cipher = engine.cipher(algo)
+ cipher.encrypt
+ cipher.key = key
+ encrypted = cipher.update(data) + cipher.final
+
+ cipher = OpenSSL::Cipher.new(algo)
+ cipher.decrypt
+ cipher.key = key
+ decrypted = cipher.update(encrypted) + cipher.final
+
assert_equal(data, decrypted)
end;
end
@@ -73,25 +82,10 @@ class OpenSSL::TestEngine < OpenSSL::TestCase
# this is required because OpenSSL::Engine methods change global state
def with_openssl(code, **opts)
- assert_separately([{ "OSSL_MDEBUG" => nil }, "-ropenssl"], <<~"end;", **opts)
- require #{__FILE__.dump}
- include OpenSSL::TestEngine::Utils
+ assert_separately(["-ropenssl"], <<~"end;", **opts)
#{code}
end;
end
-
- module Utils
- def get_engine
- OpenSSL::Engine.by_id("openssl")
- end
-
- def crypt_data(data, key, mode)
- cipher = yield
- cipher.send mode
- cipher.key = key
- cipher.update(data) + cipher.final
- end
- end
end
end
diff --git a/test/openssl/test_fips.rb b/test/openssl/test_fips.rb
index 8cd474f9a3..4a3dd43a41 100644
--- a/test/openssl/test_fips.rb
+++ b/test/openssl/test_fips.rb
@@ -4,22 +4,46 @@ require_relative 'utils'
if defined?(OpenSSL)
class OpenSSL::TestFIPS < OpenSSL::TestCase
+ def test_fips_mode_get_is_true_on_fips_mode_enabled
+ unless ENV["TEST_RUBY_OPENSSL_FIPS_ENABLED"]
+ omit "Only for FIPS mode environment"
+ end
+
+ assert_separately(["-ropenssl"], <<~"end;")
+ assert OpenSSL.fips_mode == true, ".fips_mode should return true on FIPS mode enabled"
+ end;
+ end
+
+ def test_fips_mode_get_is_false_on_fips_mode_disabled
+ if ENV["TEST_RUBY_OPENSSL_FIPS_ENABLED"]
+ omit "Only for non-FIPS mode environment"
+ end
+
+ assert_separately(["-ropenssl"], <<~"end;")
+ message = ".fips_mode should return false on FIPS mode disabled. " \
+ "If you run the test on FIPS mode, please set " \
+ "TEST_RUBY_OPENSSL_FIPS_ENABLED=true"
+ assert OpenSSL.fips_mode == false, message
+ end;
+ end
+
def test_fips_mode_is_reentrant
- OpenSSL.fips_mode = false
- OpenSSL.fips_mode = false
+ assert_separately(["-ropenssl"], <<~"end;")
+ OpenSSL.fips_mode = false
+ OpenSSL.fips_mode = false
+ end;
end
- def test_fips_mode_get
- return unless OpenSSL::OPENSSL_FIPS
- assert_separately([{ "OSSL_MDEBUG" => nil }, "-ropenssl"], <<~"end;")
- require #{__FILE__.dump}
+ def test_fips_mode_get_with_fips_mode_set
+ omit('OpenSSL is not FIPS-capable') unless OpenSSL::OPENSSL_FIPS
+ assert_separately(["-ropenssl"], <<~"end;")
begin
OpenSSL.fips_mode = true
- assert OpenSSL.fips_mode == true, ".fips_mode returns true when .fips_mode=true"
+ assert OpenSSL.fips_mode == true, ".fips_mode should return true when .fips_mode=true"
OpenSSL.fips_mode = false
- assert OpenSSL.fips_mode == false, ".fips_mode returns false when .fips_mode=false"
+ assert OpenSSL.fips_mode == false, ".fips_mode should return false when .fips_mode=false"
rescue OpenSSL::OpenSSLError
pend "Could not set FIPS mode (OpenSSL::OpenSSLError: \#$!); skipping"
end
diff --git a/test/openssl/test_hmac.rb b/test/openssl/test_hmac.rb
index 2f53a813e1..3cb707448a 100644
--- a/test/openssl/test_hmac.rb
+++ b/test/openssl/test_hmac.rb
@@ -62,6 +62,14 @@ class OpenSSL::TestHMAC < OpenSSL::TestCase
b64digest = OpenSSL::HMAC.base64digest("MD5", key, "Hi There")
assert_equal "kpRyejY4uxwT9I74FYv8nQ==", b64digest
end
+
+ def test_zero_length_key
+ # Empty string as the key
+ hexdigest = OpenSSL::HMAC.hexdigest("SHA256", "\0"*32, "test")
+ assert_equal "43b0cef99265f9e34c10ea9d3501926d27b39f57c6d674561d8ba236e7a819fb", hexdigest
+ hexdigest = OpenSSL::HMAC.hexdigest("SHA256", "", "test")
+ assert_equal "43b0cef99265f9e34c10ea9d3501926d27b39f57c6d674561d8ba236e7a819fb", hexdigest
+ end
end
end
diff --git a/test/openssl/test_ns_spki.rb b/test/openssl/test_ns_spki.rb
index ed3be86e2c..d76fc9e5cf 100644
--- a/test/openssl/test_ns_spki.rb
+++ b/test/openssl/test_ns_spki.rb
@@ -22,7 +22,7 @@ class OpenSSL::TestNSSPI < OpenSSL::TestCase
spki = OpenSSL::Netscape::SPKI.new
spki.challenge = "RandomString"
spki.public_key = key1.public_key
- spki.sign(key1, OpenSSL::Digest.new('SHA1'))
+ spki.sign(key1, OpenSSL::Digest.new('SHA256'))
assert(spki.verify(spki.public_key))
assert(spki.verify(key1.public_key))
assert(!spki.verify(key2.public_key))
@@ -38,13 +38,13 @@ class OpenSSL::TestNSSPI < OpenSSL::TestCase
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(@b64.unpack1("m"), 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)
+ spki = OpenSSL::Netscape::SPKI.new(@b64.unpack1("m"))
assert_equal(@b64, spki.to_pem)
- assert_equal(@b64.unpack("m").first, spki.to_der)
+ assert_equal(@b64.unpack1("m"), spki.to_der)
assert_equal("MozillaIsMyFriend", spki.challenge)
assert_equal(OpenSSL::PKey::RSA, spki.public_key.class)
end
diff --git a/test/openssl/test_ocsp.rb b/test/openssl/test_ocsp.rb
index ef7321abd6..cf96fc22e5 100644
--- a/test/openssl/test_ocsp.rb
+++ b/test/openssl/test_ocsp.rb
@@ -99,7 +99,7 @@ class OpenSSL::TestOCSP < OpenSSL::TestCase
request.sign(@cert, @cert_key, [@ca_cert], 0)
asn1 = OpenSSL::ASN1.decode(request.to_der)
assert_equal cid.to_der, asn1.value[0].value.find { |a| a.tag_class == :UNIVERSAL }.value[0].value[0].to_der
- assert_equal OpenSSL::ASN1.ObjectId("sha1WithRSAEncryption").to_der, asn1.value[1].value[0].value[0].value[0].to_der
+ assert_equal OpenSSL::ASN1.ObjectId("sha256WithRSAEncryption").to_der, asn1.value[1].value[0].value[0].value[0].to_der
assert_equal @cert.to_der, asn1.value[1].value[0].value[2].value[0].value[0].to_der
assert_equal @ca_cert.to_der, asn1.value[1].value[0].value[2].value[0].value[1].to_der
assert_equal asn1.to_der, OpenSSL::OCSP::Request.new(asn1.to_der).to_der
@@ -228,7 +228,7 @@ class OpenSSL::TestOCSP < OpenSSL::TestCase
assert_equal OpenSSL::OCSP::V_CERTSTATUS_REVOKED, single.cert_status
assert_equal OpenSSL::OCSP::REVOKED_STATUS_UNSPECIFIED, single.revocation_reason
assert_equal now - 400, single.revocation_time
- assert_in_delta (now - 301), single.this_update, 1
+ assert_in_delta (now - 300), single.this_update, 1
assert_equal nil, single.next_update
assert_equal [], single.extensions
diff --git a/test/openssl/test_ossl.rb b/test/openssl/test_ossl.rb
index e1d86bd40b..3a90ead10a 100644
--- a/test/openssl/test_ossl.rb
+++ b/test/openssl/test_ossl.rb
@@ -1,8 +1,6 @@
# frozen_string_literal: true
require_relative "utils"
-require 'benchmark'
-
if defined?(OpenSSL)
class OpenSSL::OSSL < OpenSSL::SSLTestCase
@@ -44,6 +42,12 @@ class OpenSSL::OSSL < OpenSSL::SSLTestCase
end
def test_memcmp_timing
+ begin
+ require "benchmark"
+ rescue LoadError
+ pend "Benchmark is not available in this environment. Please install it with `gem install benchmark`."
+ end
+
# Ensure using fixed_length_secure_compare takes almost exactly the same amount of time to compare two different strings.
# Regular string comparison will short-circuit on the first non-matching character, failing this test.
# NOTE: this test may be susceptible to noise if the system running the tests is otherwise under load.
@@ -60,6 +64,19 @@ class OpenSSL::OSSL < OpenSSL::SSLTestCase
assert_operator(a_b_time, :<, a_c_time * 10, "fixed_length_secure_compare timing test failed")
assert_operator(a_c_time, :<, a_b_time * 10, "fixed_length_secure_compare timing test failed")
end
+
+ def test_error_data
+ # X509V3_EXT_nconf_nid() called from OpenSSL::X509::ExtensionFactory#create_ext is a function
+ # that uses ERR_raise_data() to append additional information about the error.
+ #
+ # The generated message should look like:
+ # "subjectAltName = IP:not.a.valid.ip.address: bad ip address (value=not.a.valid.ip.address)"
+ # "subjectAltName = IP:not.a.valid.ip.address: error in extension (name=subjectAltName, value=IP:not.a.valid.ip.address)"
+ ef = OpenSSL::X509::ExtensionFactory.new
+ assert_raise_with_message(OpenSSL::X509::ExtensionError, /value=(IP:)?not.a.valid.ip.address\)/) {
+ ef.create_ext("subjectAltName", "IP:not.a.valid.ip.address")
+ }
+ end
end
end
diff --git a/test/openssl/test_pair.rb b/test/openssl/test_pair.rb
index 8316ec2a9c..10942191dd 100644
--- a/test/openssl/test_pair.rb
+++ b/test/openssl/test_pair.rb
@@ -2,7 +2,7 @@
require_relative 'utils'
require_relative 'ut_eof'
-if defined?(OpenSSL)
+if defined?(OpenSSL::SSL)
module OpenSSL::SSLPairM
def setup
@@ -23,7 +23,6 @@ module OpenSSL::SSLPairM
sctx = OpenSSL::SSL::SSLContext.new
sctx.cert = @svr_cert
sctx.key = @svr_key
- sctx.tmp_dh_callback = proc { OpenSSL::TestUtils::Fixtures.pkey("dh-1") }
sctx.options |= OpenSSL::SSL::OP_NO_COMPRESSION
ssls = OpenSSL::SSL::SSLServer.new(tcps, sctx)
ns = ssls.accept
@@ -102,6 +101,27 @@ module OpenSSL::TestPairM
}
end
+ def test_getbyte
+ ssl_pair {|s1, s2|
+ s1 << "a"
+ assert_equal(97, s2.getbyte)
+ }
+ end
+
+ def test_readbyte
+ ssl_pair {|s1, s2|
+ s1 << "b"
+ assert_equal(98, s2.readbyte)
+ }
+ end
+
+ def test_readbyte_eof
+ ssl_pair {|s1, s2|
+ s2.close
+ assert_raise(EOFError) { s1.readbyte }
+ }
+ end
+
def test_gets
ssl_pair {|s1, s2|
s1 << "abc\n\n$def123ghi"
@@ -116,6 +136,17 @@ module OpenSSL::TestPairM
}
end
+ def test_gets_chomp
+ ssl_pair {|s1, s2|
+ s1 << "line1\r\nline2\r\nline3\r\n"
+ s1.close
+
+ assert_equal("line1", s2.gets("\r\n", chomp: true))
+ assert_equal("line2\r\n", s2.gets("\r\n", chomp: false))
+ assert_equal("line3", s2.gets(chomp: true))
+ }
+ end
+
def test_gets_eof_limit
ssl_pair {|s1, s2|
s1.write("hello")
@@ -240,12 +271,17 @@ module OpenSSL::TestPairM
buf = +"garbage"
assert_equal :wait_readable, s2.read_nonblock(100, buf, exception: false)
- assert_equal "", buf
+ assert_equal "garbage", buf
s1.close
buf = +"garbage"
- assert_equal nil, s2.read(100, buf)
+ assert_nil s2.read(100, buf)
assert_equal "", buf
+
+ buf = +"garbage"
+ ret = s2.read(0, buf)
+ assert_same buf, ret
+ assert_equal "", ret
}
end
@@ -383,7 +419,6 @@ module OpenSSL::TestPairM
ctx2 = OpenSSL::SSL::SSLContext.new
ctx2.cert = @svr_cert
ctx2.key = @svr_key
- ctx2.tmp_dh_callback = proc { OpenSSL::TestUtils::Fixtures.pkey("dh-1") }
sock1, sock2 = tcp_pair
@@ -431,7 +466,6 @@ module OpenSSL::TestPairM
ctx = OpenSSL::SSL::SSLContext.new
ctx.cert = @svr_cert
ctx.key = @svr_key
- ctx.tmp_dh_callback = proc { OpenSSL::TestUtils::Fixtures.pkey("dh-1") }
sock1, sock2 = tcp_pair
diff --git a/test/openssl/test_pkcs12.rb b/test/openssl/test_pkcs12.rb
index fdbe753b17..faf26c9e3e 100644
--- a/test/openssl/test_pkcs12.rb
+++ b/test/openssl/test_pkcs12.rb
@@ -5,6 +5,9 @@ if defined?(OpenSSL)
module OpenSSL
class TestPKCS12 < OpenSSL::TestCase
+ DEFAULT_PBE_PKEYS = "PBE-SHA1-3DES"
+ DEFAULT_PBE_CERTS = "PBE-SHA1-3DES"
+
def setup
super
ca = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA")
@@ -14,47 +17,41 @@ module OpenSSL
["subjectKeyIdentifier","hash",false],
["authorityKeyIdentifier","keyid:always",false],
]
- @cacert = issue_cert(ca, Fixtures.pkey("rsa2048"), 1, ca_exts, nil, nil)
+ ca_key = Fixtures.pkey("rsa-1")
+ @cacert = issue_cert(ca, ca_key, 1, ca_exts, nil, nil)
inter_ca = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=Intermediate CA")
- inter_ca_key = OpenSSL::PKey.read <<-_EOS_
------BEGIN RSA PRIVATE KEY-----
-MIICXAIBAAKBgQDp7hIG0SFMG/VWv1dBUWziAPrNmkMXJgTCAoB7jffzRtyyN04K
-oq/89HAszTMStZoMigQURfokzKsjpUp8OYCAEsBtt9d5zPndWMz/gHN73GrXk3LT
-ZsxEn7Xv5Da+Y9F/Hx2QZUHarV5cdZixq2NbzWGwrToogOQMh2pxN3Z/0wIDAQAB
-AoGBAJysUyx3olpsGzv3OMRJeahASbmsSKTXVLZvoIefxOINosBFpCIhZccAG6UV
-5c/xCvS89xBw8aD15uUfziw3AuT8QPEtHCgfSjeT7aWzBfYswEgOW4XPuWr7EeI9
-iNHGD6z+hCN/IQr7FiEBgTp6A+i/hffcSdR83fHWKyb4M7TRAkEA+y4BNd668HmC
-G5MPRx25n6LixuBxrNp1umfjEI6UZgEFVpYOg4agNuimN6NqM253kcTR94QNTUs5
-Kj3EhG1YWwJBAO5rUjiOyCNVX2WUQrOMYK/c1lU7fvrkdygXkvIGkhsPoNRzLPeA
-HGJszKtrKD8bNihWpWNIyqKRHfKVD7yXT+kCQGCAhVCIGTRoypcDghwljHqLnysf
-ci0h5ZdPcIqc7ODfxYhFsJ/Rql5ONgYsT5Ig/+lOQAkjf+TRYM4c2xKx2/8CQBvG
-jv6dy70qDgIUgqzONtlmHeYyFzn9cdBO5sShdVYHvRHjFSMEXsosqK9zvW2UqvuK
-FJx7d3f29gkzynCLJDkCQGQZlEZJC4vWmWJGRKJ24P6MyQn3VsPfErSKOg4lvyM3
-Li8JsX5yIiuVYaBg/6ha3tOg4TCa5K/3r3tVliRZ2Es=
------END RSA PRIVATE KEY-----
- _EOS_
- @inter_cacert = issue_cert(inter_ca, inter_ca_key, 2, ca_exts, @cacert, Fixtures.pkey("rsa2048"))
+ inter_ca_key = Fixtures.pkey("rsa-2")
+ @inter_cacert = issue_cert(inter_ca, inter_ca_key, 2, ca_exts, @cacert, ca_key)
exts = [
["keyUsage","digitalSignature",true],
["subjectKeyIdentifier","hash",false],
]
ee = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=Ruby PKCS12 Test Certificate")
- @mykey = Fixtures.pkey("rsa1024")
+ @mykey = Fixtures.pkey("rsa-3")
@mycert = issue_cert(ee, @mykey, 3, exts, @inter_cacert, inter_ca_key)
end
- def test_create
+ def test_create_single_key_single_cert
pkcs12 = OpenSSL::PKCS12.create(
"omg",
"hello",
@mykey,
- @mycert
+ @mycert,
+ nil,
+ DEFAULT_PBE_PKEYS,
+ DEFAULT_PBE_CERTS,
)
- assert_equal @mycert.to_der, pkcs12.certificate.to_der
+ assert_equal @mycert, pkcs12.certificate
assert_equal @mykey.to_der, pkcs12.key.to_der
assert_nil pkcs12.ca_certs
+
+ der = pkcs12.to_der
+ decoded = OpenSSL::PKCS12.new(der, "omg")
+ assert_equal @mykey.to_der, decoded.key.to_der
+ assert_equal @mycert, decoded.certificate
+ assert_equal [], Array(decoded.ca_certs)
end
def test_create_no_pass
@@ -62,14 +59,17 @@ Li8JsX5yIiuVYaBg/6ha3tOg4TCa5K/3r3tVliRZ2Es=
nil,
"hello",
@mykey,
- @mycert
+ @mycert,
+ nil,
+ DEFAULT_PBE_PKEYS,
+ DEFAULT_PBE_CERTS,
)
- assert_equal @mycert.to_der, pkcs12.certificate.to_der
+ assert_equal @mycert, pkcs12.certificate
assert_equal @mykey.to_der, pkcs12.key.to_der
assert_nil pkcs12.ca_certs
decoded = OpenSSL::PKCS12.new(pkcs12.to_der)
- assert_cert @mycert, decoded.certificate
+ assert_equal @mycert, decoded.certificate
end
def test_create_with_chain
@@ -80,7 +80,9 @@ Li8JsX5yIiuVYaBg/6ha3tOg4TCa5K/3r3tVliRZ2Es=
"hello",
@mykey,
@mycert,
- chain
+ chain,
+ DEFAULT_PBE_PKEYS,
+ DEFAULT_PBE_CERTS,
)
assert_equal chain, pkcs12.ca_certs
end
@@ -95,14 +97,16 @@ Li8JsX5yIiuVYaBg/6ha3tOg4TCa5K/3r3tVliRZ2Es=
"hello",
@mykey,
@mycert,
- chain
+ chain,
+ DEFAULT_PBE_PKEYS,
+ DEFAULT_PBE_CERTS,
)
decoded = OpenSSL::PKCS12.new(pkcs12.to_der, passwd)
assert_equal chain.size, decoded.ca_certs.size
- assert_include_cert @cacert, decoded.ca_certs
- assert_include_cert @inter_cacert, decoded.ca_certs
- assert_cert @mycert, decoded.certificate
+ assert_include decoded.ca_certs, @cacert
+ assert_include decoded.ca_certs, @inter_cacert
+ assert_equal @mycert, decoded.certificate
assert_equal @mykey.to_der, decoded.key.to_der
end
@@ -126,8 +130,8 @@ Li8JsX5yIiuVYaBg/6ha3tOg4TCa5K/3r3tVliRZ2Es=
@mykey,
@mycert,
[],
- nil,
- nil,
+ DEFAULT_PBE_PKEYS,
+ DEFAULT_PBE_CERTS,
2048
)
@@ -138,8 +142,8 @@ Li8JsX5yIiuVYaBg/6ha3tOg4TCa5K/3r3tVliRZ2Es=
@mykey,
@mycert,
[],
- nil,
- nil,
+ DEFAULT_PBE_PKEYS,
+ DEFAULT_PBE_CERTS,
"omg"
)
end
@@ -152,8 +156,8 @@ Li8JsX5yIiuVYaBg/6ha3tOg4TCa5K/3r3tVliRZ2Es=
@mykey,
@mycert,
[],
- nil,
- nil,
+ DEFAULT_PBE_PKEYS,
+ DEFAULT_PBE_CERTS,
nil,
2048
)
@@ -165,148 +169,174 @@ Li8JsX5yIiuVYaBg/6ha3tOg4TCa5K/3r3tVliRZ2Es=
@mykey,
@mycert,
[],
- nil,
- nil,
+ DEFAULT_PBE_PKEYS,
+ DEFAULT_PBE_CERTS,
nil,
"omg"
)
end
end
- def test_new_with_one_key_and_one_cert
- # generated with:
- # openssl version #=> OpenSSL 1.0.2h 3 May 2016
- # openssl pkcs12 -in <@mycert> -inkey <RSA1024> -export -out <out>
- str = <<~EOF.unpack("m").first
-MIIGQQIBAzCCBgcGCSqGSIb3DQEHAaCCBfgEggX0MIIF8DCCAu8GCSqGSIb3DQEH
-BqCCAuAwggLcAgEAMIIC1QYJKoZIhvcNAQcBMBwGCiqGSIb3DQEMAQYwDgQIeZPM
-Rh6KiXgCAggAgIICqL6O+LCZmBzdIg6mozPF3FpY0hVbWHvTNMiDHieW3CrAanhN
-YCH2/wHqH8WpFpEWwF0qEEXAWjHsIlYB4Cfqo6b7XpuZe5eVESsjNTOTMF1JCUJj
-A6iNefXmCFLync1JK5LUodRDhTlKLU1WPK20X9X4vuEwHn8wt5RUb8P0E+Xh6rpS
-XC4LkZKT45zF3cJa/n5+dW65ohVGNVnF9D1bCNEKHMOllK1V9omutQ9slW88hpga
-LGiFsJoFOb/ESGb78KO+bd6zbX1MdKdBV+WD6t1uF/cgU65y+2A4nXs1urda+MJ7
-7iVqiB7Vnc9cANTbAkTSGNyoUDVM/NZde782/8IvddLAzUZ2EftoRDke6PvuBOVL
-ljBhNWmdamrtBqzuzVZCRdWq44KZkF2Xoc9asepwIkdVmntzQF7f1Z+Ta5yg6HFp
-xnr7CuM+MlHEShXkMgYtHnwAq10fDMSXIvjhi/AA5XUAusDO3D+hbtcRDcJ4uUes
-dm5dhQE2qJ02Ysn4aH3o1F3RYNOzrxejHJwl0D2TCE8Ww2X342xib57+z9u03ufj
-jswhiMKxy67f1LhUMq3XrT3uV6kCVXk/KUOUPcXPlPVNA5JmZeFhMp6GrtB5xJJ9
-wwBZD8UL5A2U2Mxi2OZsdUBv8eo3jnjZ284aFpt+mCjIHrLW5O0jwY8OCwSlYUoY
-IY00wlabX0s82kBcIQNZbC1RSV2267ro/7A0MClc8YQ/zWN0FKY6apgtUkHJI1cL
-1dc77mhnjETjwW94iLMDFy4zQfVu7IfCBqOBzygRNnqqUG66UhTs1xFnWM0mWXl/
-Zh9+AMpbRLIPaKCktIjl5juzzm+KEgkhD+707XRCFIGUYGP5bSHzGaz8PK9hj0u1
-E2SpZHUvYOcawmxtA7pmpSxl5uQjMIIC+QYJKoZIhvcNAQcBoIIC6gSCAuYwggLi
-MIIC3gYLKoZIhvcNAQwKAQKgggKmMIICojAcBgoqhkiG9w0BDAEDMA4ECKB338m8
-qSzHAgIIAASCAoACFhJeqA3xx+s1qIH6udNQYY5hAL6oz7SXoGwFhDiceSyJjmAD
-Dby9XWM0bPl1Gj5nqdsuI/lAM++fJeoETk+rxw8q6Ofk2zUaRRE39qgpwBwSk44o
-0SAFJ6bzHpc5CFh6sZmDaUX5Lm9GtjnGFmmsPTSJT5an5JuJ9WczGBEd0nSBQhJq
-xHbTGZiN8i3SXcIH531Sub+CBIFWy5lyCKgDYh/kgJFGQAaWUOjLI+7dCEESonXn
-F3Jh2uPbnDF9MGJyAFoNgWFhgSpi1cf6AUi87GY4Oyur88ddJ1o0D0Kz2uw8/bpG
-s3O4PYnIW5naZ8mozzbnYByEFk7PoTwM7VhoFBfYNtBoAI8+hBnPY/Y71YUojEXf
-SeX6QbtkIANfzS1XuFNKElShC3DPQIHpKzaatEsfxHfP+8VOav6zcn4mioao7NHA
-x7Dp6R1enFGoQOq4UNjBT8YjnkG5vW8zQHW2dAHLTJBq6x2Fzm/4Pjo/8vM1FiGl
-BQdW5vfDeJ/l6NgQm3xR9ka2E2HaDqIcj1zWbN8jy/bHPFJYuF/HH8MBV/ngMIXE
-vFEW/ToYv8eif0+EpUtzBsCKD4a7qYYYh87RmEVoQU96q6m+UbhpD2WztYfAPkfo
-OSL9j2QHhVczhL7OAgqNeM95pOsjA9YMe7exTeqK31LYnTX8oH8WJD1xGbRSJYgu
-SY6PQbumcJkc/TFPn0GeVUpiDdf83SeG50lo/i7UKQi2l1hi5Y51fQhnBnyMr68D
-llSZEvSWqfDxBJkBpeg6PIYvkTpEwKRJpVQoM3uYvdqVSSnW6rydqIb+snfOrlhd
-f+xCtq9xr+kHeTSqLIDRRAnMfgFRhY3IBlj6MSUwIwYJKoZIhvcNAQkVMRYEFBdb
-8XGWehZ6oPj56Pf/uId46M9AMDEwITAJBgUrDgMCGgUABBRvSCB04/f8f13pp2PF
-vyl2WuMdEwQIMWFFphPkIUICAggA
- EOF
- p12 = OpenSSL::PKCS12.new(str, "abc123")
+ def test_create_with_keytype
+ OpenSSL::PKCS12.create(
+ "omg",
+ "hello",
+ @mykey,
+ @mycert,
+ [],
+ DEFAULT_PBE_PKEYS,
+ DEFAULT_PBE_CERTS,
+ nil,
+ nil,
+ OpenSSL::PKCS12::KEY_SIG
+ )
- assert_equal @mykey.to_der, p12.key.to_der
- assert_equal @mycert.subject.to_der, p12.certificate.subject.to_der
- assert_equal [], Array(p12.ca_certs)
+ assert_raise(ArgumentError) do
+ OpenSSL::PKCS12.create(
+ "omg",
+ "hello",
+ @mykey,
+ @mycert,
+ [],
+ DEFAULT_PBE_PKEYS,
+ DEFAULT_PBE_CERTS,
+ nil,
+ nil,
+ 2048
+ )
+ end
end
def test_new_with_no_keys
# generated with:
- # openssl pkcs12 -in <@mycert> -nokeys -export -out <out>
- str = <<~EOF.unpack("m").first
-MIIDHAIBAzCCAuIGCSqGSIb3DQEHAaCCAtMEggLPMIICyzCCAscGCSqGSIb3DQEH
-BqCCArgwggK0AgEAMIICrQYJKoZIhvcNAQcBMBwGCiqGSIb3DQEMAQYwDgQIX4+W
-irqwH40CAggAgIICgOaCyo+5+6IOVoGCCL80c50bkkzAwqdXxvkKExJSdcJz2uMU
-0gRrKnZEjL5wrUsN8RwZu8DvgQTEhNEkKsUgM7AWainmN/EnwohIdHZAHpm6WD67
-I9kLGp0/DHrqZrV9P2dLfhXLUSQE8PI0tqZPZ8UEABhizkViw4eISTkrOUN7pGbN
-Qtx/oqgitXDuX2polbxYYDwt9vfHZhykHoKgew26SeJyZfeMs/WZ6olEI4cQUAFr
-mvYGuC1AxEGTo9ERmU8Pm16j9Hr9PFk50WYe+rnk9oX3wJogQ7XUWS5kYf7XRycd
-NDkNiwV/ts94bbuaGZp1YA6I48FXpIc8b5fX7t9tY0umGaWy0bARe1L7o0Y89EPe
-lMg25rOM7j3uPtFG8whbSfdETSy57UxzzTcJ6UwexeaK6wb2jqEmj5AOoPLWeaX0
-LyOAszR3v7OPAcjIDYZGdrbb3MZ2f2vo2pdQfu9698BrWhXuM7Odh73RLhJVreNI
-aezNOAtPyBlvGiBQBGTzRIYHSLL5Y5aVj2vWLAa7hjm5qTL5C5mFdDIo6TkEMr6I
-OsexNQofEGs19kr8nARXDlcbEimk2VsPj4efQC2CEXZNzURsKca82pa62MJ8WosB
-DTFd8X06zZZ4nED50vLopZvyW4fyW60lELwOyThAdG8UchoAaz2baqP0K4de44yM
-Y5/yPFDu4+GoimipJfbiYviRwbzkBxYW8+958ILh0RtagLbvIGxbpaym9PqGjOzx
-ShNXjLK2aAFZsEizQ8kd09quJHU/ogq2cUXdqqhmOqPnUWrJVi/VCoRB3Pv1/lE4
-mrUgr2YZ11rYvBw6g5XvNvFcSc53OKyV7SLn0dwwMTAhMAkGBSsOAwIaBQAEFEWP
-1WRQykaoD4uJCpTx/wv0SLLBBAiDKI26LJK7xgICCAA=
+ # openssl pkcs12 -certpbe PBE-SHA1-3DES -in <@mycert> -nokeys -export
+ str = <<~EOF.unpack1("m")
+MIIGJAIBAzCCBeoGCSqGSIb3DQEHAaCCBdsEggXXMIIF0zCCBc8GCSqGSIb3
+DQEHBqCCBcAwggW8AgEAMIIFtQYJKoZIhvcNAQcBMBwGCiqGSIb3DQEMAQMw
+DgQIjv5c3OHvnBgCAggAgIIFiMJa8Z/w7errRvCQPXh9dGQz3eJaFq3S2gXD
+rh6oiwsgIRJZvYAWgU6ll9NV7N5SgvS2DDNVuc3tsP8TPWjp+bIxzS9qmGUV
+kYWuURWLMKhpF12ZRDab8jcIwBgKoSGiDJk8xHjx6L613/XcRM6ln3VeQK+C
+hlW5kXniNAUAgTft25Fn61Xa8xnhmsz/fk1ycGnyGjKCnr7Mgy7KV0C1vs23
+18n8+b1ktDWLZPYgpmXuMFVh0o+HJTV3O86mkIhJonMcnOMgKZ+i8KeXaocN
+JQlAPBG4+HOip7FbQT/h6reXv8/J+hgjLfqAb5aV3m03rUX9mXx66nR1tQU0
+Jq+XPfDh5+V4akIczLlMyyo/xZjI1/qupcMjr+giOGnGd8BA3cuXW+ueLQiA
+PpTp+DQLVHRfz9XTZbyqOReNEtEXvO9gOlKSEY5lp65ItXVEs2Oqyf9PfU9y
+DUltN6fCMilwPyyrsIBKXCu2ZLM5h65KVCXAYEX9lNqj9zrQ7vTqvCNN8RhS
+ScYouTX2Eqa4Z+gTZWLHa8RCQFoyP6hd+97/Tg2Gv2UTH0myQxIVcnpdi1wy
+cqb+er7tyKbcO96uSlUjpj/JvjlodtjJcX+oinEqGb/caj4UepbBwiG3vv70
+63bS3jTsOLNjDRsR9if3LxIhLa6DW8zOJiGC+EvMD1o4dzHcGVpQ/pZWCHZC
++YiNJpQOBApiZluE+UZ0m3XrtHFQYk7xblTrh+FJF91wBsok0rZXLAKd8m4p
+OJsc7quCq3cuHRRTzJQ4nSe01uqbwGDAYwLvi6VWy3svU5qa05eDRmgzEFTG
+e84Gp/1LQCtpQFr4txkjFchO2whWS80KoQKqmLPyGm1D9Lv53Q4ZsKMgNihs
+rEepuaOZMKHl4yMAYFoOXZCAYzfbhN6b2phcFAHjMUHUw9e3F0QuDk9D0tsr
+riYTrkocqlOKfK4QTomx27O0ON2J6f1rtEojGgfl9RNykN7iKGzjS3914QjW
+W6gGiZejxHsDPEAa4gUp0WiSUSXtD5WJgoyAzLydR2dKWsQ4WlaUXi01CuGy
++xvncSn2nO3bbot8VD5H6XU1CjREVtnIfbeRYO/uofyLUP3olK5RqN6ne6Xo
+eXnJ/bjYphA8NGuuuvuW1SCITmINkZDLC9cGlER9+K65RR/DR3TigkexXMeN
+aJ70ivZYAl0OuhZt3TGIlAzS64TIoyORe3z7Ta1Pp9PZQarYJpF9BBIZIFor
+757PHHuQKRuugiRkp8B7v4eq1BQ+VeAxCKpyZ7XrgEtbY/AWDiaKcGPKPjc3
+AqQraVeQm7kMBT163wFmZArCphzkDOI3bz2oEO8YArMgLq2Vto9jAZlqKyWr
+pi2bSJxuoP1aoD58CHcWMrf8/j1LVdQhKgHQXSik2ID0H2Wc/XnglhzlVFuJ
+JsNIW/EGJlZh/5WDez9U0bXqnBlu3uasPEOezdoKlcCmQlmTO5+uLHYLEtNA
+EH9MtnGZebi9XS5meTuS6z5LILt8O9IHZxmT3JRPHYj287FEzotlLdcJ4Ee5
+enW41UHjLrfv4OaITO1hVuoLRGdzjESx/fHMWmxroZ1nVClxECOdT42zvIYJ
+J3xBZ0gppzQ5fjoYiKjJpxTflRxUuxshk3ih6VUoKtqj/W18tBQ3g5SOlkgT
+yCW8r74yZlfYmNrPyDMUQYpLUPWj2n71GF0KyPfTU5yOatRgvheh262w5BG3
+omFY7mb3tCv8/U2jdMIoukRKacpZiagofz3SxojOJq52cHnCri+gTHBMX0cO
+j58ygfntHWRzst0pV7Ze2X3fdCAJ4DokH6bNJNthcgmolFJ/y3V1tJjgsdtQ
+7Pjn/vE6xUV0HXE2x4yoVYNirbAMIvkN/X+atxrN0dA4AchN+zGp8TAxMCEw
+CQYFKw4DAhoFAAQUQ+6XXkyhf6uYgtbibILN2IjKnOAECLiqoY45MPCrAgII
+AA==
EOF
p12 = OpenSSL::PKCS12.new(str, "abc123")
assert_equal nil, p12.key
assert_equal nil, p12.certificate
assert_equal 1, p12.ca_certs.size
- assert_equal @mycert.subject.to_der, p12.ca_certs[0].subject.to_der
+ assert_equal @mycert.subject, p12.ca_certs[0].subject
end
def test_new_with_no_certs
# generated with:
- # openssl pkcs12 -inkey <RSA1024> -nocerts -export -out <out>
- str = <<~EOF.unpack("m").first
-MIIDJwIBAzCCAu0GCSqGSIb3DQEHAaCCAt4EggLaMIIC1jCCAtIGCSqGSIb3DQEH
-AaCCAsMEggK/MIICuzCCArcGCyqGSIb3DQEMCgECoIICpjCCAqIwHAYKKoZIhvcN
-AQwBAzAOBAg6AaYnJs84SwICCAAEggKAQzZH+fWSpcQYD1J7PsGSune85A++fLCQ
-V7tacp2iv95GJkxwYmfTP176pJdgs00mceB9UJ/u9EX5nD0djdjjQjwo6sgKjY0q
-cpVhZw8CMxw7kBD2dhtui0zT8z5hy03LePxsjEKsGiSbeVeeGbSfw/I6AAYbv+Uh
-O/YPBGumeHj/D2WKnfsHJLQ9GAV3H6dv5VKYNxjciK7f/JEyZCuUQGIN64QFHDhJ
-7fzLqd/ul3FZzJZO6a+dwvcgux09SKVXDRSeFmRCEX4b486iWhJJVspCo9P2KNne
-ORrpybr3ZSwxyoICmjyo8gj0OSnEfdx9790Ej1takPqSA1wIdSdBLekbZqB0RBQg
-DEuPOsXNo3QFi8ji1vu0WBRJZZSNC2hr5NL6lNR+DKxG8yzDll2j4W4BBIp22mAE
-7QRX7kVxu17QJXQhOUac4Dd1qXmzebP8t6xkAxD9L7BWEN5OdiXWwSWGjVjMBneX
-nYObi/3UT/aVc5WHMHK2BhCI1bwH51E6yZh06d5m0TQpYGUTWDJdWGBSrp3A+8jN
-N2PMQkWBFrXP3smHoTEN4oZC4FWiPsIEyAkQsfKRhcV9lGKl2Xgq54ROTFLnwKoj
-Z3zJScnq9qmNzvVZSMmDLkjLyDq0pxRxGKBvgouKkWY7VFFIwwBIJM39iDJ5NbBY
-i1AQFTRsRSsZrNVPasCXrIq7bhMoJZb/YZOGBLNyJVqKUoYXhtwsajzSq54VlWft
-JxsPayEd4Vi6O9EU1ahnj6qFEZiKFzsicgK2J1Rb8cYagrp0XWjHW0SBn5GVUWCg
-GUokSFG/0JTdeYTo/sQuG4qNgJkOolRjpeI48Fciq5VUWLvVdKioXzAxMCEwCQYF
-Kw4DAhoFAAQUYAuwVtGD1TdgbFK4Yal2XBgwUR4ECEawsN3rNaa6AgIIAA==
+ # openssl pkcs12 -inkey fixtures/openssl/pkey/rsa-1.pem -nocerts -export
+ str = <<~EOF.unpack1("m")
+MIIJ7wIBAzCCCbUGCSqGSIb3DQEHAaCCCaYEggmiMIIJnjCCCZoGCSqGSIb3
+DQEHAaCCCYsEggmHMIIJgzCCCX8GCyqGSIb3DQEMCgECoIIJbjCCCWowHAYK
+KoZIhvcNAQwBAzAOBAjX5nN8jyRKwQICCAAEgglIBIRLHfiY1mNHpl3FdX6+
+72L+ZOVXnlZ1MY9HSeg0RMkCJcm0mJ2UD7INUOGXvwpK9fr6WJUZM1IqTihQ
+1dM0crRC2m23aP7KtAlXh2DYD3otseDtwoN/NE19RsiJzeIiy5TSW1d47weU
++D4Ig/9FYVFPTDgMzdCxXujhvO/MTbZIjqtcS+IOyF+91KkXrHkfkGjZC7KS
+WRmYw9BBuIPQEewdTI35sAJcxT8rK7JIiL/9mewbSE+Z28Wq1WXwmjL3oZm9
+lw6+f515b197GYEGomr6LQqJJamSYpwQbTGHonku6Tf3ylB4NLFqOnRCKE4K
+zRSSYIqJBlKHmQ4pDm5awoupHYxMZLZKZvXNYyYN3kV8r1iiNVlY7KBR4CsX
+rqUkXehRmcPnuqEMW8aOpuYe/HWf8PYI93oiDZjcEZMwW2IZFFrgBbqUeNCM
+CQTkjAYxi5FyoaoTnHrj/aRtdLOg1xIJe4KKcmOXAVMmVM9QEPNfUwiXJrE7
+n42gl4NyzcZpxqwWBT++9TnQGZ/lEpwR6dzkZwICNQLdQ+elsdT7mumywP+1
+WaFqg9kpurimaiBu515vJNp9Iqv1Nmke6R8Lk6WVRKPg4Akw0fkuy6HS+LyN
+ofdCfVUkPGN6zkjAxGZP9ZBwvXUbLRC5W3N5qZuAy5WcsS75z+oVeX9ePV63
+cue23sClu8JSJcw3HFgPaAE4sfkQ4MoihPY5kezgT7F7Lw/j86S0ebrDNp4N
+Y685ec81NRHJ80CAM55f3kGCOEhoifD4VZrvr1TdHZY9Gm3b1RYaJCit2huF
+nlOfzeimdcv/tkjb6UsbpXx3JKkF2NFFip0yEBERRCdWRYMUpBRcl3ad6XHy
+w0pVTgIjTxGlbbtOCi3siqMOK0GNt6UgjoEFc1xqjsgLwU0Ta2quRu7RFPGM
+GoEwoC6VH23p9Hr4uTFOL0uHfkKWKunNN+7YPi6LT6IKmTQwrp+fTO61N6Xh
+KlqTpwESKsIJB2iMnc8wBkjXJtmG/e2n5oTqfhICIrxYmEb7zKDyK3eqeTj3
+FhQh2t7cUIiqcT52AckUqniPmlE6hf82yBjhaQUPfi/ExTBtTDSmFfRPUzq+
+Rlla4OHllPRzUXJExyansgCxZbPqlw46AtygSWRGcWoYAKUKwwoYjerqIV5g
+JoZICV9BOU9TXco1dHXZQTs/nnTwoRmYiL/Ly5XpvUAnQOhYeCPjBeFnPSBR
+R/hRNqrDH2MOV57v5KQIH2+mvy26tRG+tVGHmLMaOJeQkjLdxx+az8RfXIrH
+7hpAsoBb+g9jUDY1mUVavPk1T45GMpQH8u3kkzRvChfOst6533GyIZhE7FhN
+KanC6ACabVFDUs6P9pK9RPQMp1qJfpA0XJFx5TCbVbPkvnkZd8K5Tl/tzNM1
+n32eRao4MKr9KDwoDL93S1yJgYTlYjy1XW/ewdedtX+B4koAoz/wSXDYO+GQ
+Zu6ZSpKSEHTRPhchsJ4oICvpriVaJkn0/Z7H3YjNMB9U5RR9+GiIg1wY1Oa1
+S3WfuwrrI6eqfbQwj6PDNu3IKy6srEgvJwaofQALNBPSYWbauM2brc8qsD+t
+n8jC/aD1aMcy00+9t3H/RVCjEOb3yKfUpAldIkEA2NTTnZpoDQDXeNYU2F/W
+yhmFjJy8A0O4QOk2xnZK9kcxSRs0v8vI8HivvgWENoVPscsDC4742SSIe6SL
+f/T08reIX11f0K70rMtLhtFMQdHdYOTNl6JzhkHPLr/f9MEZsBEQx52depnF
+ARb3gXGbCt7BAi0OeCEBSbLr2yWuW4r55N0wRZSOBtgqgjsiHP7CDQSkbL6p
+FPlQS1do9gBSHiNYvsmN1LN5bG+mhcVb0UjZub4mL0EqGadjDfDdRJmWqlX0
+r5dyMcOWQVy4O2cPqYFlcP9lk8buc5otcyVI2isrAFdlvBK29oK6jc52Aq5Q
+0b2ESDlgX8WRgiOPPxK8dySKEeuIwngCtJyNTecP9Ug06TDsu0znZGCXJ+3P
+8JOpykgA8EQdOZOYHbo76ZfB2SkklI5KeRA5IBjGs9G3TZ4PHLy2DIwsbWzS
+H1g01o1x264nx1cJ+eEgUN/KIiGFIib42RS8Af4D5e+Vj54Rt3axq+ag3kI+
+53p8uotyu+SpvvXUP7Kv4xpQ/L6k41VM0rfrd9+DrlDVvSfxP2uh6I1TKF7A
+CT5n8zguMbng4PGjxvyPBM5k62t6hN5fuw6Af0aZFexh+IjB/5wFQ6onSz23
+fBzMW4St7RgSs8fDg3lrM+5rwXiey1jxY1ddaxOoUsWRMvvdd7rZxRZQoN5v
+AcI5iMkK/vvpQgC/sfzhtXtrJ2XOPZ+GVgi7VcuDLKSkdFMcPbGzO8SdxUnS
+SLV5XTKqKND+Lrfx7DAoKi5wbDFHu5496/MHK5qP4tBe6sJ5bZc+KDJIH46e
+wTV1oWtB5tV4q46hOb5WRcn/Wjz3HSKaGZgx5QbK1MfKTzD5CTUn+ArMockX
+2wJhPnFK85U4rgv8iBuh9bRjyw+YaKf7Z3loXRiE1eRG6RzuPF0ZecFiDumk
+AC/VUXynJhzePBLqzrQj0exanACdullN+pSfHiRWBxR2VFUkjoFP5X45GK3z
+OstSH6FOkMVU4afqEmjsIwozDFIyin5EyWTtdhJe3szdJSGY23Tut+9hUatx
+9FDFLESOd8z3tyQSNiLk/Hib+e/lbjxqbXBG/p/oyvP3N999PLUPtpKqtYkV
+H0+18sNh9CVfojiJl44fzxe8yCnuefBjut2PxEN0EFRBPv9P2wWlmOxkPKUq
+NrCJP0rDj5aONLrNZPrR8bZNdIShkZ/rKkoTuA0WMZ+xUlDRxAupdMkWAlrz
+8IcwNcdDjPnkGObpN5Ctm3vK7UGSBmPeNqkXOYf3QTJ9gStJEd0F6+DzTN5C
+KGt1IyuGwZqL2Yk51FDIIkr9ykEnBMaA39LS7GFHEDNGlW+fKC7AzA0zfoOr
+fXZlHMBuqHtXqk3zrsHRqGGoocigg4ctrhD1UREYKj+eIj1TBiRdf7c6+COf
+NIOmej8pX3FmZ4ui+dDA8r2ctgsWHrb4A6iiH+v1DRA61GtoaA/tNRggewXW
+VXCZCGWyyTuyHGOqq5ozrv5MlzZLWD/KV/uDsAWmy20RAed1C4AzcXlpX25O
+M4SNl47g5VRNJRtMqokc8j6TjZrzMDEwITAJBgUrDgMCGgUABBRrkIRuS5qg
+BC8fv38mue8LZVcbHQQIUNrWKEnskCoCAggA
EOF
p12 = OpenSSL::PKCS12.new(str, "abc123")
- assert_equal @mykey.to_der, p12.key.to_der
+ assert_equal Fixtures.pkey("rsa-1").to_der, p12.key.to_der
assert_equal nil, p12.certificate
assert_equal [], Array(p12.ca_certs)
end
def test_dup
- p12 = OpenSSL::PKCS12.create("pass", "name", @mykey, @mycert)
+ p12 = OpenSSL::PKCS12.create(
+ "pass",
+ "name",
+ @mykey,
+ @mycert,
+ nil,
+ DEFAULT_PBE_PKEYS,
+ DEFAULT_PBE_CERTS,
+ )
assert_equal p12.to_der, p12.dup.to_der
end
-
- private
- def assert_cert expected, actual
- [
- :subject,
- :issuer,
- :serial,
- :not_before,
- :not_after,
- ].each do |attribute|
- assert_equal expected.send(attribute), actual.send(attribute)
- end
- assert_equal expected.to_der, actual.to_der
- end
-
- def assert_include_cert cert, ary
- der = cert.to_der
- ary.each do |candidate|
- if candidate.to_der == der
- return true
- end
- end
- false
- end
end
end
diff --git a/test/openssl/test_pkcs7.rb b/test/openssl/test_pkcs7.rb
index ba8b93d034..c049ed444a 100644
--- a/test/openssl/test_pkcs7.rb
+++ b/test/openssl/test_pkcs7.rb
@@ -155,6 +155,21 @@ class OpenSSL::TestPKCS7 < OpenSSL::TestCase
assert_equal(data, p7.decrypt(@rsa1024))
end
+ def test_empty_signed_data_ruby_bug_19974
+ data = "-----BEGIN PKCS7-----\nMAsGCSqGSIb3DQEHAg==\n-----END PKCS7-----\n"
+ assert_raise(ArgumentError) { OpenSSL::PKCS7.new(data) }
+
+ data = <<END
+MIME-Version: 1.0
+Content-Disposition: attachment; filename="smime.p7m"
+Content-Type: application/x-pkcs7-mime; smime-type=signed-data; name="smime.p7m"
+Content-Transfer-Encoding: base64
+
+#{data}
+END
+ assert_raise(OpenSSL::PKCS7::PKCS7Error) { OpenSSL::PKCS7.read_smime(data) }
+ end
+
def test_graceful_parsing_failure #[ruby-core:43250]
contents = File.read(__FILE__)
assert_raise(ArgumentError) { OpenSSL::PKCS7.new(contents) }
@@ -212,6 +227,12 @@ END
assert_equal(p7.to_der, OpenSSL::PKCS7.read_smime(smime).to_der)
end
+ def test_to_text
+ p7 = OpenSSL::PKCS7.new
+ p7.type = "signed"
+ assert_match(/signed/, p7.to_text)
+ end
+
def test_degenerate_pkcs7
ca_cert_pem = <<END
-----BEGIN CERTIFICATE-----
diff --git a/test/openssl/test_pkey.rb b/test/openssl/test_pkey.rb
index 4a539d8c46..811d5103d6 100644
--- a/test/openssl/test_pkey.rb
+++ b/test/openssl/test_pkey.rb
@@ -27,23 +27,30 @@ class OpenSSL::TestPKey < OpenSSL::PKeyTestCase
end
def test_s_generate_parameters
- # 512 is non-default; 1024 is used if 'dsa_paramgen_bits' is not specified
- # with OpenSSL 1.1.0.
- pkey = OpenSSL::PKey.generate_parameters("DSA", {
- "dsa_paramgen_bits" => 512,
- "dsa_paramgen_q_bits" => 256,
+ pkey = OpenSSL::PKey.generate_parameters("EC", {
+ "ec_paramgen_curve" => "secp384r1",
})
- assert_instance_of OpenSSL::PKey::DSA, pkey
- assert_equal 512, pkey.p.num_bits
- assert_equal 256, pkey.q.num_bits
- assert_equal nil, pkey.priv_key
+ assert_instance_of OpenSSL::PKey::EC, pkey
+ assert_equal "secp384r1", pkey.group.curve_name
+ assert_equal nil, pkey.private_key
# Invalid options are checked
assert_raise(OpenSSL::PKey::PKeyError) {
- OpenSSL::PKey.generate_parameters("DSA", "invalid" => "option")
+ OpenSSL::PKey.generate_parameters("EC", "invalid" => "option")
}
+ end
+
+ def test_s_generate_parameters_with_block
+ # DSA kengen is not FIPS-approved.
+ # https://github.com/openssl/openssl/commit/49a35f0#diff-605396c063194975af8ce31399d42690ab18186b422fb5012101cc9132660fe1R611-R614
+ omit_on_fips
# Parameter generation callback is called
+ if openssl?(3, 0, 0, 0) && !openssl?(3, 0, 0, 6)
+ # Errors in BN_GENCB were not properly handled. This special pend is to
+ # suppress failures on Ubuntu 22.04, which uses OpenSSL 3.0.2.
+ pend "unstable test on OpenSSL 3.0.[0-5]"
+ end
cb_called = []
assert_raise(RuntimeError) {
OpenSSL::PKey.generate_parameters("DSA") { |*args|
@@ -59,14 +66,13 @@ class OpenSSL::TestPKey < OpenSSL::PKeyTestCase
# DSA key pair cannot be generated without parameters
OpenSSL::PKey.generate_key("DSA")
}
- pkey_params = OpenSSL::PKey.generate_parameters("DSA", {
- "dsa_paramgen_bits" => 512,
- "dsa_paramgen_q_bits" => 256,
+ pkey_params = OpenSSL::PKey.generate_parameters("EC", {
+ "ec_paramgen_curve" => "secp384r1",
})
pkey = OpenSSL::PKey.generate_key(pkey_params)
- assert_instance_of OpenSSL::PKey::DSA, pkey
- assert_equal 512, pkey.p.num_bits
- assert_not_equal nil, pkey.priv_key
+ assert_instance_of OpenSSL::PKey::EC, pkey
+ assert_equal "secp384r1", pkey.group.curve_name
+ assert_not_equal nil, pkey.private_key
end
def test_hmac_sign_verify
@@ -82,6 +88,9 @@ class OpenSSL::TestPKey < OpenSSL::PKeyTestCase
end
def test_ed25519
+ # Ed25519 is not FIPS-approved.
+ omit_on_fips
+
# Test vector from RFC 8032 Section 7.1 TEST 2
priv_pem = <<~EOF
-----BEGIN PRIVATE KEY-----
@@ -96,9 +105,11 @@ class OpenSSL::TestPKey < OpenSSL::PKeyTestCase
begin
priv = OpenSSL::PKey.read(priv_pem)
pub = OpenSSL::PKey.read(pub_pem)
- rescue OpenSSL::PKey::PKeyError
+ rescue OpenSSL::PKey::PKeyError => e
# OpenSSL < 1.1.1
- pend "Ed25519 is not implemented"
+ pend "Ed25519 is not implemented" unless openssl?(1, 1, 1)
+
+ raise e
end
assert_instance_of OpenSSL::PKey::PKey, priv
assert_instance_of OpenSSL::PKey::PKey, pub
@@ -106,6 +117,19 @@ class OpenSSL::TestPKey < OpenSSL::PKeyTestCase
assert_equal pub_pem, priv.public_to_pem
assert_equal pub_pem, pub.public_to_pem
+ begin
+ assert_equal "4ccd089b28ff96da9db6c346ec114e0f5b8a319f35aba624da8cf6ed4fb8a6fb",
+ priv.raw_private_key.unpack1("H*")
+ assert_equal OpenSSL::PKey.new_raw_private_key("ED25519", priv.raw_private_key).private_to_pem,
+ priv.private_to_pem
+ assert_equal "3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c",
+ priv.raw_public_key.unpack1("H*")
+ assert_equal OpenSSL::PKey.new_raw_public_key("ED25519", priv.raw_public_key).public_to_pem,
+ pub.public_to_pem
+ rescue NoMethodError
+ pend "running OpenSSL version does not have raw public key support"
+ end
+
sig = [<<~EOF.gsub(/[^0-9a-f]/, "")].pack("H*")
92a009a9f0d4cab8720e820b5f642540
a2b27b5416503f8fb3762223ebdb69da
@@ -150,6 +174,32 @@ class OpenSSL::TestPKey < OpenSSL::PKeyTestCase
assert_equal alice_pem, alice.private_to_pem
assert_equal bob_pem, bob.public_to_pem
assert_equal [shared_secret].pack("H*"), alice.derive(bob)
+ begin
+ alice_private = OpenSSL::PKey.new_raw_private_key("X25519", alice.raw_private_key)
+ bob_public = OpenSSL::PKey.new_raw_public_key("X25519", bob.raw_public_key)
+ alice_private_raw = alice.raw_private_key.unpack1("H*")
+ bob_public_raw = bob.raw_public_key.unpack1("H*")
+ rescue NoMethodError
+ # OpenSSL < 1.1.1
+ pend "running OpenSSL version does not have raw public key support"
+ end
+ assert_equal alice_private.private_to_pem,
+ alice.private_to_pem
+ assert_equal bob_public.public_to_pem,
+ bob.public_to_pem
+ assert_equal "77076d0a7318a57d3c16c17251b26645df4c2f87ebc0992ab177fba51db92c2a",
+ alice_private_raw
+ assert_equal "de9edb7d7b7dc1b4d35b61c2ece435373f8343c85b78674dadfc7e146f882b4f",
+ bob_public_raw
+ end
+
+ def raw_initialize
+ pend "Ed25519 is not implemented" unless openssl?(1, 1, 1) # >= v1.1.1
+
+ assert_raise(OpenSSL::PKey::PKeyError) { OpenSSL::PKey.new_raw_private_key("foo123", "xxx") }
+ assert_raise(OpenSSL::PKey::PKeyError) { OpenSSL::PKey.new_raw_private_key("ED25519", "xxx") }
+ assert_raise(OpenSSL::PKey::PKeyError) { OpenSSL::PKey.new_raw_public_key("foo123", "xxx") }
+ assert_raise(OpenSSL::PKey::PKeyError) { OpenSSL::PKey.new_raw_public_key("ED25519", "xxx") }
end
def test_compare?
diff --git a/test/openssl/test_pkey_dh.rb b/test/openssl/test_pkey_dh.rb
index f80af8f841..d32ffaf6b1 100644
--- a/test/openssl/test_pkey_dh.rb
+++ b/test/openssl/test_pkey_dh.rb
@@ -18,53 +18,75 @@ class OpenSSL::TestPKeyDH < OpenSSL::PKeyTestCase
assert_key(dh)
end if ENV["OSSL_TEST_ALL"]
- def test_new_break
+ def test_new_break_on_non_fips
+ omit_on_fips
+
assert_nil(OpenSSL::PKey::DH.new(NEW_KEYLEN) { break })
assert_raise(RuntimeError) do
OpenSSL::PKey::DH.new(NEW_KEYLEN) { raise }
end
end
+ def test_new_break_on_fips
+ omit_on_non_fips
+
+ # The block argument is not executed in FIPS case.
+ # See https://github.com/ruby/openssl/issues/692 for details.
+ assert(OpenSSL::PKey::DH.new(NEW_KEYLEN) { break })
+ assert(OpenSSL::PKey::DH.new(NEW_KEYLEN) { raise })
+ end
+
def test_derive_key
- dh1 = Fixtures.pkey("dh1024").generate_key!
- dh2 = Fixtures.pkey("dh1024").generate_key!
+ params = Fixtures.pkey("dh2048_ffdhe2048")
+ dh1 = OpenSSL::PKey.generate_key(params)
+ dh2 = OpenSSL::PKey.generate_key(params)
dh1_pub = OpenSSL::PKey.read(dh1.public_to_der)
dh2_pub = OpenSSL::PKey.read(dh2.public_to_der)
+
z = dh1.g.mod_exp(dh1.priv_key, dh1.p).mod_exp(dh2.priv_key, dh1.p).to_s(2)
assert_equal z, dh1.derive(dh2_pub)
assert_equal z, dh2.derive(dh1_pub)
+ assert_raise(OpenSSL::PKey::PKeyError) { params.derive(dh1_pub) }
+ assert_raise(OpenSSL::PKey::PKeyError) { dh1_pub.derive(params) }
+
assert_equal z, dh1.compute_key(dh2.pub_key)
assert_equal z, dh2.compute_key(dh1.pub_key)
end
def test_DHparams
- dh1024 = Fixtures.pkey("dh1024")
+ dh = Fixtures.pkey("dh2048_ffdhe2048")
+ dh_params = dh.public_key
+
asn1 = OpenSSL::ASN1::Sequence([
- OpenSSL::ASN1::Integer(dh1024.p),
- OpenSSL::ASN1::Integer(dh1024.g)
+ OpenSSL::ASN1::Integer(dh.p),
+ OpenSSL::ASN1::Integer(dh.g)
])
key = OpenSSL::PKey::DH.new(asn1.to_der)
- assert_same_dh dup_public(dh1024), key
+ assert_same_dh dh_params, key
pem = <<~EOF
-----BEGIN DH PARAMETERS-----
- MIGHAoGBAKnKQ8MNK6nYZzLrrcuTsLxuiJGXoOO5gT+tljOTbHBuiktdMTITzIY0
- pFxIvjG05D7HoBZQfrR0c92NGWPkAiCkhQKB8JCbPVzwNLDy6DZ0pmofDKrEsYHG
- AQjjxMXhwULlmuR/K+WwlaZPiLIBYalLAZQ7ZbOPeVkJ8ePao0eLAgEC
+ MIIBCAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz
+ +8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a
+ 87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7
+ YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi
+ 7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD
+ ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg==
-----END DH PARAMETERS-----
EOF
+
key = OpenSSL::PKey::DH.new(pem)
- assert_same_dh dup_public(dh1024), key
+ assert_same_dh dh_params, key
key = OpenSSL::PKey.read(pem)
- assert_same_dh dup_public(dh1024), key
+ assert_same_dh dh_params, key
- assert_equal asn1.to_der, dh1024.to_der
- assert_equal pem, dh1024.export
+ assert_equal asn1.to_der, dh.to_der
+ assert_equal pem, dh.export
end
def test_public_key
- dh = Fixtures.pkey("dh1024")
+ dh = Fixtures.pkey("dh2048_ffdhe2048")
public_key = dh.public_key
assert_no_key(public_key) #implies public_key.public? is false!
assert_equal(dh.to_der, public_key.to_der)
@@ -72,22 +94,28 @@ class OpenSSL::TestPKeyDH < OpenSSL::PKeyTestCase
end
def test_generate_key
- dh = Fixtures.pkey("dh1024").public_key # creates a copy
+ # Deprecated in v3.0.0; incompatible with OpenSSL 3.0
+ # Creates a copy with params only
+ dh = Fixtures.pkey("dh2048_ffdhe2048").public_key
assert_no_key(dh)
dh.generate_key!
assert_key(dh)
- end
- def test_key_exchange
- dh = Fixtures.pkey("dh1024")
dh2 = dh.public_key
- dh.generate_key!
dh2.generate_key!
assert_equal(dh.compute_key(dh2.pub_key), dh2.compute_key(dh.pub_key))
- end
+ end if !openssl?(3, 0, 0)
def test_params_ok?
- dh0 = Fixtures.pkey("dh1024")
+ # Skip the tests in old OpenSSL version 1.1.1c or early versions before
+ # applying the following commits in OpenSSL 1.1.1d to make `DH_check`
+ # function pass the RFC 7919 FFDHE group texts.
+ # https://github.com/openssl/openssl/pull/9435
+ unless openssl?(1, 1, 1, 4)
+ pend 'DH check for RFC 7919 FFDHE group texts is not implemented'
+ end
+
+ dh0 = Fixtures.pkey("dh2048_ffdhe2048")
dh1 = OpenSSL::PKey::DH.new(OpenSSL::ASN1::Sequence([
OpenSSL::ASN1::Integer(dh0.p),
@@ -103,17 +131,36 @@ class OpenSSL::TestPKeyDH < OpenSSL::PKeyTestCase
end
def test_dup
- dh = Fixtures.pkey("dh1024")
- dh2 = dh.dup
- assert_equal dh.to_der, dh2.to_der # params
- assert_equal_params dh, dh2 # keys
- dh2.set_pqg(dh2.p + 1, nil, dh2.g)
- assert_not_equal dh2.p, dh.p
- assert_equal dh2.g, dh.g
+ # Parameters only
+ dh1 = Fixtures.pkey("dh2048_ffdhe2048")
+ dh2 = dh1.dup
+ assert_equal dh1.to_der, dh2.to_der
+ assert_not_equal nil, dh1.p
+ assert_not_equal nil, dh1.g
+ assert_equal [dh1.p, dh1.g], [dh2.p, dh2.g]
+ assert_equal nil, dh1.pub_key
+ assert_equal nil, dh1.priv_key
+ assert_equal [dh1.pub_key, dh1.priv_key], [dh2.pub_key, dh2.priv_key]
+
+ # PKey is immutable in OpenSSL >= 3.0
+ if !openssl?(3, 0, 0)
+ dh2.set_pqg(dh2.p + 1, nil, dh2.g)
+ assert_not_equal dh2.p, dh1.p
+ end
+
+ # With a key pair
+ dh3 = OpenSSL::PKey.generate_key(Fixtures.pkey("dh2048_ffdhe2048"))
+ dh4 = dh3.dup
+ assert_equal dh3.to_der, dh4.to_der
+ assert_equal dh1.to_der, dh4.to_der # encodes parameters only
+ assert_equal [dh1.p, dh1.g], [dh4.p, dh4.g]
+ assert_not_equal nil, dh3.pub_key
+ assert_not_equal nil, dh3.priv_key
+ assert_equal [dh3.pub_key, dh3.priv_key], [dh4.pub_key, dh4.priv_key]
end
def test_marshal
- dh = Fixtures.pkey("dh1024")
+ dh = Fixtures.pkey("dh2048_ffdhe2048")
deserialized = Marshal.load(Marshal.dump(dh))
assert_equal dh.to_der, deserialized.to_der
@@ -121,11 +168,6 @@ class OpenSSL::TestPKeyDH < OpenSSL::PKeyTestCase
private
- def assert_equal_params(dh1, dh2)
- assert_equal(dh1.g, dh2.g)
- assert_equal(dh1.p, dh2.p)
- end
-
def assert_no_key(dh)
assert_equal(false, dh.public?)
assert_equal(false, dh.private?)
diff --git a/test/openssl/test_pkey_dsa.rb b/test/openssl/test_pkey_dsa.rb
index 147e50176b..3e8a83b2d0 100644
--- a/test/openssl/test_pkey_dsa.rb
+++ b/test/openssl/test_pkey_dsa.rb
@@ -4,6 +4,11 @@ require_relative 'utils'
if defined?(OpenSSL) && defined?(OpenSSL::PKey::DSA)
class OpenSSL::TestPKeyDSA < OpenSSL::PKeyTestCase
+ def setup
+ # May not be available in FIPS mode as DSA has been deprecated in FIPS 186-5
+ omit_on_fips
+ end
+
def test_private
key = Fixtures.pkey("dsa1024")
assert_equal true, key.private?
@@ -28,28 +33,49 @@ class OpenSSL::TestPKeyDSA < OpenSSL::PKeyTestCase
end
end
+ def test_generate
+ # DSA.generate used to call DSA_generate_parameters_ex(), which adjusts the
+ # size of q according to the size of p
+ key1024 = OpenSSL::PKey::DSA.generate(1024)
+ assert_predicate key1024, :private?
+ assert_equal 1024, key1024.p.num_bits
+ assert_equal 160, key1024.q.num_bits
+
+ key2048 = OpenSSL::PKey::DSA.generate(2048)
+ assert_equal 2048, key2048.p.num_bits
+ assert_equal 256, key2048.q.num_bits
+
+ if ENV["OSSL_TEST_ALL"] == "1" # slow
+ key3072 = OpenSSL::PKey::DSA.generate(3072)
+ assert_equal 3072, key3072.p.num_bits
+ assert_equal 256, key3072.q.num_bits
+ end
+ end
+
def test_sign_verify
- dsa512 = Fixtures.pkey("dsa512")
+ # The DSA valid size is 2048 or 3072 on FIPS.
+ # https://github.com/openssl/openssl/blob/7649b5548e5c0352b91d9d3ed695e42a2ac1e99c/providers/common/securitycheck.c#L185-L188
+ dsa = Fixtures.pkey("dsa2048")
data = "Sign me!"
if defined?(OpenSSL::Digest::DSS1)
- signature = dsa512.sign(OpenSSL::Digest.new('DSS1'), data)
- assert_equal true, dsa512.verify(OpenSSL::Digest.new('DSS1'), signature, data)
+ signature = dsa.sign(OpenSSL::Digest.new('DSS1'), data)
+ assert_equal true, dsa.verify(OpenSSL::Digest.new('DSS1'), signature, data)
end
- signature = dsa512.sign("SHA1", data)
- assert_equal true, dsa512.verify("SHA1", signature, data)
+ signature = dsa.sign("SHA256", data)
+ assert_equal true, dsa.verify("SHA256", signature, data)
- signature0 = (<<~'end;').unpack("m")[0]
- MCwCFH5h40plgU5Fh0Z4wvEEpz0eE9SnAhRPbkRB8ggsN/vsSEYMXvJwjGg/
- 6g==
+ signature0 = (<<~'end;').unpack1("m")
+ MD4CHQC0zmRkVOAHJTm28fS5PVUv+4LtBeNaKqr/yfmVAh0AsTcLqofWHoW8X5oWu8AOvngOcFVZ
+ cLTvhY3XNw==
end;
- assert_equal true, dsa512.verify("SHA256", signature0, data)
+ assert_equal true, dsa.verify("SHA256", signature0, data)
signature1 = signature0.succ
- assert_equal false, dsa512.verify("SHA256", signature1, data)
+ assert_equal false, dsa.verify("SHA256", signature1, data)
end
def test_sign_verify_raw
- key = Fixtures.pkey("dsa512")
+ key = Fixtures.pkey("dsa2048")
data = 'Sign me!'
digest = OpenSSL::Digest.digest('SHA1', data)
@@ -138,6 +164,8 @@ class OpenSSL::TestPKeyDSA < OpenSSL::PKeyTestCase
def test_PUBKEY
dsa512 = Fixtures.pkey("dsa512")
+ dsa512pub = OpenSSL::PKey::DSA.new(dsa512.public_to_der)
+
asn1 = OpenSSL::ASN1::Sequence([
OpenSSL::ASN1::Sequence([
OpenSSL::ASN1::ObjectId("DSA"),
@@ -153,7 +181,7 @@ class OpenSSL::TestPKeyDSA < OpenSSL::PKeyTestCase
])
key = OpenSSL::PKey::DSA.new(asn1.to_der)
assert_not_predicate key, :private?
- assert_same_dsa dup_public(dsa512), key
+ assert_same_dsa dsa512pub, key
pem = <<~EOF
-----BEGIN PUBLIC KEY-----
@@ -166,10 +194,15 @@ class OpenSSL::TestPKeyDSA < OpenSSL::PKeyTestCase
-----END PUBLIC KEY-----
EOF
key = OpenSSL::PKey::DSA.new(pem)
- assert_same_dsa dup_public(dsa512), key
+ assert_same_dsa dsa512pub, key
- assert_equal asn1.to_der, dup_public(dsa512).to_der
- assert_equal pem, dup_public(dsa512).export
+ assert_equal asn1.to_der, key.to_der
+ assert_equal pem, key.export
+
+ assert_equal asn1.to_der, dsa512.public_to_der
+ assert_equal asn1.to_der, key.public_to_der
+ assert_equal pem, dsa512.public_to_pem
+ assert_equal pem, key.public_to_pem
end
def test_read_DSAPublicKey_pem
@@ -201,8 +234,12 @@ fWLOqqkzFeRrYMDzUpl36XktY6Yq8EJYlW9pCMmBVNy/dQ==
key = Fixtures.pkey("dsa1024")
key2 = key.dup
assert_equal key.params, key2.params
- key2.set_pqg(key2.p + 1, key2.q, key2.g)
- assert_not_equal key.params, key2.params
+
+ # PKey is immutable in OpenSSL >= 3.0
+ if !openssl?(3, 0, 0)
+ key2.set_pqg(key2.p + 1, key2.q, key2.g)
+ assert_not_equal key.params, key2.params
+ end
end
def test_marshal
diff --git a/test/openssl/test_pkey_ec.rb b/test/openssl/test_pkey_ec.rb
index 0a460bd536..2cb8e287ab 100644
--- a/test/openssl/test_pkey_ec.rb
+++ b/test/openssl/test_pkey_ec.rb
@@ -1,34 +1,22 @@
# frozen_string_literal: true
require_relative 'utils'
-if defined?(OpenSSL) && defined?(OpenSSL::PKey::EC)
+if defined?(OpenSSL)
class OpenSSL::TestEC < OpenSSL::PKeyTestCase
def test_ec_key
- builtin_curves = OpenSSL::PKey::EC.builtin_curves
- assert_not_empty builtin_curves
-
- builtin_curves.each do |curve_name, comment|
- # Oakley curves and X25519 are not suitable for signing and causes
- # FIPS-selftest failure on some environment, so skip for now.
- next if ["Oakley", "X25519"].any? { |n| curve_name.start_with?(n) }
-
- key = OpenSSL::PKey::EC.new(curve_name)
- key.generate_key!
-
- assert_predicate key, :private?
- assert_predicate key, :public?
- assert_nothing_raised { key.check_key }
+ key1 = OpenSSL::PKey::EC.generate("prime256v1")
+
+ # PKey is immutable in OpenSSL >= 3.0; constructing an empty EC object is
+ # deprecated
+ if !openssl?(3, 0, 0)
+ key2 = OpenSSL::PKey::EC.new
+ key2.group = key1.group
+ key2.private_key = key1.private_key
+ key2.public_key = key1.public_key
+ assert_equal key1.to_der, key2.to_der
end
- key1 = OpenSSL::PKey::EC.new("prime256v1").generate_key!
-
- key2 = OpenSSL::PKey::EC.new
- key2.group = key1.group
- key2.private_key = key1.private_key
- key2.public_key = key1.public_key
- assert_equal key1.to_der, key2.to_der
-
key3 = OpenSSL::PKey::EC.new(key1)
assert_equal key1.to_der, key3.to_der
@@ -37,10 +25,25 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase
key5 = key1.dup
assert_equal key1.to_der, key5.to_der
- key_tmp = OpenSSL::PKey::EC.new("prime256v1").generate_key!
- key5.private_key = key_tmp.private_key
- key5.public_key = key_tmp.public_key
- assert_not_equal key1.to_der, key5.to_der
+
+ # PKey is immutable in OpenSSL >= 3.0; EC object should not be modified
+ if !openssl?(3, 0, 0)
+ key_tmp = OpenSSL::PKey::EC.generate("prime256v1")
+ key5.private_key = key_tmp.private_key
+ key5.public_key = key_tmp.public_key
+ assert_not_equal key1.to_der, key5.to_der
+ end
+ end
+
+ def test_builtin_curves
+ builtin_curves = OpenSSL::PKey::EC.builtin_curves
+ assert_not_empty builtin_curves
+ assert_equal 2, builtin_curves[0].size
+ assert_kind_of String, builtin_curves[0][0]
+ assert_kind_of String, builtin_curves[0][1]
+
+ builtin_curve_names = builtin_curves.map { |name, comment| name }
+ assert_include builtin_curve_names, "prime256v1"
end
def test_generate
@@ -52,6 +55,15 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase
assert_equal(true, ec.private?)
end
+ def test_generate_key
+ ec = OpenSSL::PKey::EC.new("prime256v1")
+ assert_equal false, ec.private?
+ assert_raise(OpenSSL::PKey::ECError) { ec.to_der }
+ ec.generate_key!
+ assert_equal true, ec.private?
+ assert_nothing_raised { ec.to_der }
+ end if !openssl?(3, 0, 0)
+
def test_marshal
key = Fixtures.pkey("p256")
deserialized = Marshal.load(Marshal.dump(key))
@@ -60,31 +72,42 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase
end
def test_check_key
- key = OpenSSL::PKey::EC.new("prime256v1").generate_key!
- assert_equal(true, key.check_key)
- assert_equal(true, key.private?)
- assert_equal(true, key.public?)
- key2 = OpenSSL::PKey::EC.new(key.group)
- assert_equal(false, key2.private?)
- assert_equal(false, key2.public?)
- key2.public_key = key.public_key
- assert_equal(false, key2.private?)
- assert_equal(true, key2.public?)
- key2.private_key = key.private_key
+ key0 = Fixtures.pkey("p256")
+ assert_equal(true, key0.check_key)
+ assert_equal(true, key0.private?)
+ assert_equal(true, key0.public?)
+
+ key1 = OpenSSL::PKey.read(key0.public_to_der)
+ assert_equal(true, key1.check_key)
+ assert_equal(false, key1.private?)
+ assert_equal(true, key1.public?)
+
+ key2 = OpenSSL::PKey.read(key0.private_to_der)
assert_equal(true, key2.private?)
assert_equal(true, key2.public?)
assert_equal(true, key2.check_key)
- key2.private_key += 1
- assert_raise(OpenSSL::PKey::ECError) { key2.check_key }
+
+ # Behavior of EVP_PKEY_public_check changes between OpenSSL 1.1.1 and 3.0
+ key4 = Fixtures.pkey("p256_too_large")
+ assert_raise(OpenSSL::PKey::ECError) { key4.check_key }
+
+ key5 = Fixtures.pkey("p384_invalid")
+ assert_raise(OpenSSL::PKey::ECError) { key5.check_key }
+
+ # EC#private_key= is deprecated in 3.0 and won't work on OpenSSL 3.0
+ if !openssl?(3, 0, 0)
+ key2.private_key += 1
+ assert_raise(OpenSSL::PKey::ECError) { key2.check_key }
+ end
end
def test_sign_verify
p256 = Fixtures.pkey("p256")
data = "Sign me!"
- signature = p256.sign("SHA1", data)
- assert_equal true, p256.verify("SHA1", signature, data)
+ signature = p256.sign("SHA256", data)
+ assert_equal true, p256.verify("SHA256", signature, data)
- signature0 = (<<~'end;').unpack("m")[0]
+ signature0 = (<<~'end;').unpack1("m")
MEQCIEOTY/hD7eI8a0qlzxkIt8LLZ8uwiaSfVbjX2dPAvN11AiAQdCYx56Fq
QdBp1B4sxJoA8jvODMMklMyBKVmudboA6A==
end;
@@ -107,7 +130,7 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase
assert_equal [zIUT].pack("H*"), a.derive(b)
assert_equal a.derive(b), a.dh_compute_key(b.public_key)
- end
+ end if !openssl?(3, 0, 0) # TODO: Test it without using #private_key=
def test_sign_verify_raw
key = Fixtures.pkey("p256")
@@ -136,7 +159,7 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase
end
def test_dsa_sign_asn1_FIPS186_3
- key = OpenSSL::PKey::EC.new("prime256v1").generate_key!
+ key = OpenSSL::PKey::EC.generate("prime256v1")
size = key.group.order.num_bits / 8 + 1
dgst = (1..size).to_a.pack('C*')
sig = key.dsa_sign_asn1(dgst)
@@ -145,8 +168,8 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase
end
def test_dh_compute_key
- key_a = OpenSSL::PKey::EC.new("prime256v1").generate_key!
- key_b = OpenSSL::PKey::EC.new(key_a.group).generate_key!
+ key_a = OpenSSL::PKey::EC.generate("prime256v1")
+ key_b = OpenSSL::PKey::EC.generate(key_a.group)
pub_a = key_a.public_key
pub_b = key_b.public_key
@@ -182,7 +205,32 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase
assert_equal pem, p256.export
end
+ def test_ECPrivateKey_with_parameters
+ p256 = Fixtures.pkey("p256")
+
+ # The format used by "openssl ecparam -name prime256v1 -genkey -outform PEM"
+ #
+ # "EC PARAMETERS" block should be ignored if it is followed by an
+ # "EC PRIVATE KEY" block
+ in_pem = <<~EOF
+ -----BEGIN EC PARAMETERS-----
+ BggqhkjOPQMBBw==
+ -----END EC PARAMETERS-----
+ -----BEGIN EC PRIVATE KEY-----
+ MHcCAQEEIID49FDqcf1O1eO8saTgG70UbXQw9Fqwseliit2aWhH1oAoGCCqGSM49
+ AwEHoUQDQgAEFglk2c+oVUIKQ64eZG9bhLNPWB7lSZ/ArK41eGy5wAzU/0G51Xtt
+ CeBUl+MahZtn9fO1JKdF4qJmS39dXnpENg==
+ -----END EC PRIVATE KEY-----
+ EOF
+
+ key = OpenSSL::PKey::EC.new(in_pem)
+ assert_same_ec p256, key
+ assert_equal p256.to_der, key.to_der
+ end
+
def test_ECPrivateKey_encrypted
+ omit_on_fips
+
p256 = Fixtures.pkey("p256")
# key = abcdef
pem = <<~EOF
@@ -210,6 +258,8 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase
def test_PUBKEY
p256 = Fixtures.pkey("p256")
+ p256pub = OpenSSL::PKey::EC.new(p256.public_to_der)
+
asn1 = OpenSSL::ASN1::Sequence([
OpenSSL::ASN1::Sequence([
OpenSSL::ASN1::ObjectId("id-ecPublicKey"),
@@ -221,7 +271,7 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase
])
key = OpenSSL::PKey::EC.new(asn1.to_der)
assert_not_predicate key, :private?
- assert_same_ec dup_public(p256), key
+ assert_same_ec p256pub, key
pem = <<~EOF
-----BEGIN PUBLIC KEY-----
@@ -230,10 +280,15 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase
-----END PUBLIC KEY-----
EOF
key = OpenSSL::PKey::EC.new(pem)
- assert_same_ec dup_public(p256), key
+ assert_same_ec p256pub, key
+
+ assert_equal asn1.to_der, key.to_der
+ assert_equal pem, key.export
- assert_equal asn1.to_der, dup_public(p256).to_der
- assert_equal pem, dup_public(p256).export
+ assert_equal asn1.to_der, p256.public_to_der
+ assert_equal asn1.to_der, key.public_to_der
+ assert_equal pem, p256.public_to_pem
+ assert_equal pem, key.public_to_pem
end
def test_ec_group
@@ -269,7 +324,7 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase
def test_ec_point
group = OpenSSL::PKey::EC::Group.new("prime256v1")
- key = OpenSSL::PKey::EC.new(group).generate_key!
+ key = OpenSSL::PKey::EC.generate(group)
point = key.public_key
point2 = OpenSSL::PKey::EC::Point.new(group, point.to_bn)
diff --git a/test/openssl/test_pkey_rsa.rb b/test/openssl/test_pkey_rsa.rb
index 5e127f5407..02693c277b 100644
--- a/test/openssl/test_pkey_rsa.rb
+++ b/test/openssl/test_pkey_rsa.rb
@@ -11,12 +11,10 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase
key.set_factors(rsa.p, rsa.q)
assert_raise(OpenSSL::PKey::RSAError){ key.private_encrypt("foo") }
assert_raise(OpenSSL::PKey::RSAError){ key.private_decrypt("foo") }
- end
+ end if !openssl?(3, 0, 0) # Impossible state in OpenSSL 3.0
def test_private
- # Generated by key size and public exponent
- key = OpenSSL::PKey::RSA.new(512, 3)
- assert(key.private?)
+ key = Fixtures.pkey("rsa2048")
# Generated by DER
key2 = OpenSSL::PKey::RSA.new(key.to_der)
@@ -31,67 +29,81 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase
assert(!key4.private?)
rsa1024 = Fixtures.pkey("rsa1024")
- # Generated by RSA#set_key
- key5 = OpenSSL::PKey::RSA.new
- key5.set_key(rsa1024.n, rsa1024.e, rsa1024.d)
- assert(key5.private?)
-
- # Generated by RSA#set_key, without d
- key6 = OpenSSL::PKey::RSA.new
- key6.set_key(rsa1024.n, rsa1024.e, nil)
- assert(!key6.private?)
+ if !openssl?(3, 0, 0)
+ key = OpenSSL::PKey::RSA.new
+ # Generated by RSA#set_key
+ key5 = OpenSSL::PKey::RSA.new
+ key5.set_key(rsa1024.n, rsa1024.e, rsa1024.d)
+ assert(key5.private?)
+
+ # Generated by RSA#set_key, without d
+ key6 = OpenSSL::PKey::RSA.new
+ key6.set_key(rsa1024.n, rsa1024.e, nil)
+ assert(!key6.private?)
+ end
end
def test_new
- key = OpenSSL::PKey::RSA.new(512)
- assert_equal 512, key.n.num_bits
+ key = OpenSSL::PKey::RSA.new(2048)
+ assert_equal 2048, key.n.num_bits
assert_equal 65537, key.e
assert_not_nil key.d
+ assert(key.private?)
+ end
+
+ def test_new_public_exponent
+ # At least 2024-bits RSA key are required in FIPS.
+ omit_on_fips
# Specify public exponent
- key2 = OpenSSL::PKey::RSA.new(512, 3)
- assert_equal 512, key2.n.num_bits
- assert_equal 3, key2.e
- assert_not_nil key2.d
+ key = OpenSSL::PKey::RSA.new(512, 3)
+ assert_equal 512, key.n.num_bits
+ assert_equal 3, key.e
end
def test_s_generate
- key1 = OpenSSL::PKey::RSA.generate(512)
- assert_equal 512, key1.n.num_bits
+ key1 = OpenSSL::PKey::RSA.generate(2048)
+ assert_equal 2048, key1.n.num_bits
assert_equal 65537, key1.e
+ end
+
+ def test_s_generate_public_exponent
+ # At least 2024-bits RSA key are required in FIPS.
+ omit_on_fips
# Specify public exponent
- key2 = OpenSSL::PKey::RSA.generate(512, 3)
- assert_equal 512, key2.n.num_bits
- assert_equal 3, key2.e
- assert_not_nil key2.d
+ key = OpenSSL::PKey::RSA.generate(512, 3)
+ assert_equal 512, key.n.num_bits
+ assert_equal 3, key.e
end
def test_new_break
- assert_nil(OpenSSL::PKey::RSA.new(1024) { break })
+ assert_nil(OpenSSL::PKey::RSA.new(2048) { break })
assert_raise(RuntimeError) do
- OpenSSL::PKey::RSA.new(1024) { raise }
+ OpenSSL::PKey::RSA.new(2048) { raise }
end
end
def test_sign_verify
- rsa1024 = Fixtures.pkey("rsa1024")
+ rsa = Fixtures.pkey("rsa2048")
data = "Sign me!"
- signature = rsa1024.sign("SHA1", data)
- assert_equal true, rsa1024.verify("SHA1", signature, data)
-
- signature0 = (<<~'end;').unpack("m")[0]
- oLCgbprPvfhM4pjFQiDTFeWI9Sk+Og7Nh9TmIZ/xSxf2CGXQrptlwo7NQ28+
- WA6YQo8jPH4hSuyWIM4Gz4qRYiYRkl5TDMUYob94zm8Si1HxEiS9354tzvqS
- zS8MLW2BtNPuTubMxTItHGTnOzo9sUg0LAHVFt8kHG2NfKAw/gQ=
+ signature = rsa.sign("SHA256", data)
+ assert_equal true, rsa.verify("SHA256", signature, data)
+
+ signature0 = (<<~'end;').unpack1("m")
+ ooy49i8aeFtkDYUU0RPDsEugGiNw4lZxpbQPnIwtdftEkka945IqKZ/MY3YSw7wKsvBZeaTy8GqL
+ lSWLThsRFDV+UUS9zUBbQ9ygNIT8OjdV+tNL63ZpKGprczSnw4F05MQIpajNRud/8jiI9rf+Wysi
+ WwXecjMl2FlXlLJHY4PFQZU5TiametB4VCQRMcjLo1uf26u/yRpiGaYyqn5vxs0SqNtUDM1UL6x4
+ NHCAdqLjuFRQPjYp1vGLD3eSl4061pS8x1NVap3YGbYfGUyzZO4VfwFwf1jPdhp/OX/uZw4dGB2H
+ gSK+q1JiDFwEE6yym5tdKovL1g1NhFYHF6gkZg==
end;
- assert_equal true, rsa1024.verify("SHA256", signature0, data)
+ assert_equal true, rsa.verify("SHA256", signature0, data)
signature1 = signature0.succ
- assert_equal false, rsa1024.verify("SHA256", signature1, data)
+ assert_equal false, rsa.verify("SHA256", signature1, data)
end
def test_sign_verify_options
- key = Fixtures.pkey("rsa1024")
+ key = Fixtures.pkey("rsa2048")
data = "Sign me!"
pssopts = {
"rsa_padding_mode" => "pss",
@@ -99,21 +111,26 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase
"rsa_mgf1_md" => "SHA1"
}
sig_pss = key.sign("SHA256", data, pssopts)
- assert_equal 128, sig_pss.bytesize
+ assert_equal 256, sig_pss.bytesize
assert_equal true, key.verify("SHA256", sig_pss, data, pssopts)
assert_equal true, key.verify_pss("SHA256", sig_pss, data,
salt_length: 20, mgf1_hash: "SHA1")
# Defaults to PKCS #1 v1.5 padding => verification failure
assert_equal false, key.verify("SHA256", sig_pss, data)
+
+ # option type check
+ assert_raise_with_message(TypeError, /expected Hash/) {
+ key.sign("SHA256", data, ["x"])
+ }
end
def test_sign_verify_raw
key = Fixtures.pkey("rsa-1")
data = "Sign me!"
- hash = OpenSSL::Digest.digest("SHA1", data)
- signature = key.sign_raw("SHA1", hash)
- assert_equal true, key.verify_raw("SHA1", signature, hash)
- assert_equal true, key.verify("SHA1", signature, data)
+ hash = OpenSSL::Digest.digest("SHA256", data)
+ signature = key.sign_raw("SHA256", hash)
+ assert_equal true, key.verify_raw("SHA256", signature, hash)
+ assert_equal true, key.verify("SHA256", signature, data)
# Too long data
assert_raise(OpenSSL::PKey::PKeyError) {
@@ -126,9 +143,9 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase
"rsa_pss_saltlen" => 20,
"rsa_mgf1_md" => "SHA256"
}
- sig_pss = key.sign_raw("SHA1", hash, pssopts)
- assert_equal true, key.verify("SHA1", sig_pss, data, pssopts)
- assert_equal true, key.verify_raw("SHA1", sig_pss, hash, pssopts)
+ sig_pss = key.sign_raw("SHA256", hash, pssopts)
+ assert_equal true, key.verify("SHA256", sig_pss, data, pssopts)
+ assert_equal true, key.verify_raw("SHA256", sig_pss, hash, pssopts)
end
def test_sign_verify_raw_legacy
@@ -167,12 +184,12 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase
end
def test_sign_verify_pss
- key = Fixtures.pkey("rsa1024")
+ key = Fixtures.pkey("rsa2048")
data = "Sign me!"
invalid_data = "Sign me?"
signature = key.sign_pss("SHA256", data, salt_length: 20, mgf1_hash: "SHA1")
- assert_equal 128, signature.bytesize
+ assert_equal 256, signature.bytesize
assert_equal true,
key.verify_pss("SHA256", signature, data, salt_length: 20, mgf1_hash: "SHA1")
assert_equal true,
@@ -188,25 +205,42 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase
assert_equal false,
key.verify_pss("SHA256", signature, data, salt_length: 20, mgf1_hash: "SHA1")
- signature = key.sign_pss("SHA256", data, salt_length: :max, mgf1_hash: "SHA1")
- assert_equal true,
- key.verify_pss("SHA256", signature, data, salt_length: 94, mgf1_hash: "SHA1")
- assert_equal true,
- key.verify_pss("SHA256", signature, data, salt_length: :auto, mgf1_hash: "SHA1")
+ # The sign_pss with `salt_length: :max` raises the "invalid salt length"
+ # error in FIPS. We need to skip the tests in FIPS.
+ # According to FIPS 186-5 section 5.4, the salt length shall be between zero
+ # and the output block length of the digest function (inclusive).
+ #
+ # FIPS 186-5 section 5.4 PKCS #1
+ # https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-5.pdf
+ unless OpenSSL.fips_mode
+ signature = key.sign_pss("SHA256", data, salt_length: :max, mgf1_hash: "SHA1")
+ # Should verify on the following salt_length (sLen).
+ # sLen <= emLen (octat) - 2 - hLen (octet) = 2048 / 8 - 2 - 256 / 8 = 222
+ # https://datatracker.ietf.org/doc/html/rfc8017#section-9.1.1
+ assert_equal true,
+ key.verify_pss("SHA256", signature, data, salt_length: 222, mgf1_hash: "SHA1")
+ assert_equal true,
+ key.verify_pss("SHA256", signature, data, salt_length: :auto, mgf1_hash: "SHA1")
+ end
assert_raise(OpenSSL::PKey::RSAError) {
- key.sign_pss("SHA256", data, salt_length: 95, mgf1_hash: "SHA1")
+ key.sign_pss("SHA256", data, salt_length: 223, mgf1_hash: "SHA1")
}
end
def test_encrypt_decrypt
rsapriv = Fixtures.pkey("rsa-1")
- rsapub = dup_public(rsapriv)
+ rsapub = OpenSSL::PKey.read(rsapriv.public_to_der)
# Defaults to PKCS #1 v1.5
raw = "data"
- enc = rsapub.encrypt(raw)
- assert_equal raw, rsapriv.decrypt(enc)
+ # According to the NIST SP 800-131A Rev. 2 section 6, PKCS#1 v1.5 padding is
+ # not permitted for key agreement and key transport using RSA in FIPS.
+ # https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar2.pdf
+ unless OpenSSL.fips_mode
+ enc = rsapub.encrypt(raw)
+ assert_equal raw, rsapriv.decrypt(enc)
+ end
# Invalid options
assert_raise(OpenSSL::PKey::PKeyError) {
@@ -216,14 +250,16 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase
def test_encrypt_decrypt_legacy
rsapriv = Fixtures.pkey("rsa-1")
- rsapub = dup_public(rsapriv)
+ rsapub = OpenSSL::PKey.read(rsapriv.public_to_der)
# Defaults to PKCS #1 v1.5
- raw = "data"
- enc_legacy = rsapub.public_encrypt(raw)
- assert_equal raw, rsapriv.decrypt(enc_legacy)
- enc_new = rsapub.encrypt(raw)
- assert_equal raw, rsapriv.private_decrypt(enc_new)
+ unless OpenSSL.fips_mode
+ raw = "data"
+ enc_legacy = rsapub.public_encrypt(raw)
+ assert_equal raw, rsapriv.decrypt(enc_legacy)
+ enc_new = rsapub.encrypt(raw)
+ assert_equal raw, rsapriv.private_decrypt(enc_new)
+ end
# OAEP with default parameters
raw = "data"
@@ -235,80 +271,116 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase
def test_export
rsa1024 = Fixtures.pkey("rsa1024")
- key = OpenSSL::PKey::RSA.new
- # key has only n, e and d
- key.set_key(rsa1024.n, rsa1024.e, rsa1024.d)
- assert_equal rsa1024.public_key.export, key.export
+ pub = OpenSSL::PKey.read(rsa1024.public_to_der)
+ assert_not_equal rsa1024.export, pub.export
+ assert_equal rsa1024.public_to_pem, pub.export
- # key has only n, e, d, p and q
- key.set_factors(rsa1024.p, rsa1024.q)
- assert_equal rsa1024.public_key.export, key.export
+ # PKey is immutable in OpenSSL >= 3.0
+ if !openssl?(3, 0, 0)
+ key = OpenSSL::PKey::RSA.new
- # key has n, e, d, p, q, dmp1, dmq1 and iqmp
- key.set_crt_params(rsa1024.dmp1, rsa1024.dmq1, rsa1024.iqmp)
- assert_equal rsa1024.export, key.export
+ # key has only n, e and d
+ key.set_key(rsa1024.n, rsa1024.e, rsa1024.d)
+ assert_equal rsa1024.public_key.export, key.export
+
+ # key has only n, e, d, p and q
+ key.set_factors(rsa1024.p, rsa1024.q)
+ assert_equal rsa1024.public_key.export, key.export
+
+ # key has n, e, d, p, q, dmp1, dmq1 and iqmp
+ key.set_crt_params(rsa1024.dmp1, rsa1024.dmq1, rsa1024.iqmp)
+ assert_equal rsa1024.export, key.export
+ end
end
def test_to_der
rsa1024 = Fixtures.pkey("rsa1024")
- key = OpenSSL::PKey::RSA.new
- # key has only n, e and d
- key.set_key(rsa1024.n, rsa1024.e, rsa1024.d)
- assert_equal rsa1024.public_key.to_der, key.to_der
+ pub = OpenSSL::PKey.read(rsa1024.public_to_der)
+ assert_not_equal rsa1024.to_der, pub.to_der
+ assert_equal rsa1024.public_to_der, pub.to_der
- # key has only n, e, d, p and q
- key.set_factors(rsa1024.p, rsa1024.q)
- assert_equal rsa1024.public_key.to_der, key.to_der
+ # PKey is immutable in OpenSSL >= 3.0
+ if !openssl?(3, 0, 0)
+ key = OpenSSL::PKey::RSA.new
- # key has n, e, d, p, q, dmp1, dmq1 and iqmp
- key.set_crt_params(rsa1024.dmp1, rsa1024.dmq1, rsa1024.iqmp)
- assert_equal rsa1024.to_der, key.to_der
+ # key has only n, e and d
+ key.set_key(rsa1024.n, rsa1024.e, rsa1024.d)
+ assert_equal rsa1024.public_key.to_der, key.to_der
+
+ # key has only n, e, d, p and q
+ key.set_factors(rsa1024.p, rsa1024.q)
+ assert_equal rsa1024.public_key.to_der, key.to_der
+
+ # key has n, e, d, p, q, dmp1, dmq1 and iqmp
+ key.set_crt_params(rsa1024.dmp1, rsa1024.dmq1, rsa1024.iqmp)
+ assert_equal rsa1024.to_der, key.to_der
+ end
end
def test_RSAPrivateKey
- rsa1024 = Fixtures.pkey("rsa1024")
+ rsa = Fixtures.pkey("rsa2048")
asn1 = OpenSSL::ASN1::Sequence([
OpenSSL::ASN1::Integer(0),
- OpenSSL::ASN1::Integer(rsa1024.n),
- OpenSSL::ASN1::Integer(rsa1024.e),
- OpenSSL::ASN1::Integer(rsa1024.d),
- OpenSSL::ASN1::Integer(rsa1024.p),
- OpenSSL::ASN1::Integer(rsa1024.q),
- OpenSSL::ASN1::Integer(rsa1024.dmp1),
- OpenSSL::ASN1::Integer(rsa1024.dmq1),
- OpenSSL::ASN1::Integer(rsa1024.iqmp)
+ OpenSSL::ASN1::Integer(rsa.n),
+ OpenSSL::ASN1::Integer(rsa.e),
+ OpenSSL::ASN1::Integer(rsa.d),
+ OpenSSL::ASN1::Integer(rsa.p),
+ OpenSSL::ASN1::Integer(rsa.q),
+ OpenSSL::ASN1::Integer(rsa.dmp1),
+ OpenSSL::ASN1::Integer(rsa.dmq1),
+ OpenSSL::ASN1::Integer(rsa.iqmp)
])
key = OpenSSL::PKey::RSA.new(asn1.to_der)
assert_predicate key, :private?
- assert_same_rsa rsa1024, key
+ assert_same_rsa rsa, key
pem = <<~EOF
-----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==
+ 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-----
EOF
key = OpenSSL::PKey::RSA.new(pem)
- assert_same_rsa rsa1024, key
+ assert_same_rsa rsa, key
+
+ assert_equal asn1.to_der, rsa.to_der
+ assert_equal pem, rsa.export
- assert_equal asn1.to_der, rsa1024.to_der
- assert_equal pem, rsa1024.export
+ # Unknown PEM prepended
+ cert = issue_cert(OpenSSL::X509::Name.new([["CN", "nobody"]]), rsa, 1, [], nil, nil)
+ str = cert.to_text + cert.to_pem + rsa.to_pem
+ key = OpenSSL::PKey::RSA.new(str)
+ assert_same_rsa rsa, key
end
def test_RSAPrivateKey_encrypted
+ omit_on_fips
+
rsa1024 = Fixtures.pkey("rsa1024")
# key = abcdef
pem = <<~EOF
@@ -346,13 +418,15 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase
def test_RSAPublicKey
rsa1024 = Fixtures.pkey("rsa1024")
+ rsa1024pub = OpenSSL::PKey::RSA.new(rsa1024.public_to_der)
+
asn1 = OpenSSL::ASN1::Sequence([
OpenSSL::ASN1::Integer(rsa1024.n),
OpenSSL::ASN1::Integer(rsa1024.e)
])
key = OpenSSL::PKey::RSA.new(asn1.to_der)
assert_not_predicate key, :private?
- assert_same_rsa dup_public(rsa1024), key
+ assert_same_rsa rsa1024pub, key
pem = <<~EOF
-----BEGIN RSA PUBLIC KEY-----
@@ -362,11 +436,13 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase
-----END RSA PUBLIC KEY-----
EOF
key = OpenSSL::PKey::RSA.new(pem)
- assert_same_rsa dup_public(rsa1024), key
+ assert_same_rsa rsa1024pub, key
end
def test_PUBKEY
rsa1024 = Fixtures.pkey("rsa1024")
+ rsa1024pub = OpenSSL::PKey::RSA.new(rsa1024.public_to_der)
+
asn1 = OpenSSL::ASN1::Sequence([
OpenSSL::ASN1::Sequence([
OpenSSL::ASN1::ObjectId("rsaEncryption"),
@@ -381,7 +457,7 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase
])
key = OpenSSL::PKey::RSA.new(asn1.to_der)
assert_not_predicate key, :private?
- assert_same_rsa dup_public(rsa1024), key
+ assert_same_rsa rsa1024pub, key
pem = <<~EOF
-----BEGIN PUBLIC KEY-----
@@ -392,13 +468,20 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase
-----END PUBLIC KEY-----
EOF
key = OpenSSL::PKey::RSA.new(pem)
- assert_same_rsa dup_public(rsa1024), key
+ assert_same_rsa rsa1024pub, key
+
+ assert_equal asn1.to_der, key.to_der
+ assert_equal pem, key.export
- assert_equal asn1.to_der, dup_public(rsa1024).to_der
- assert_equal pem, dup_public(rsa1024).export
+ assert_equal asn1.to_der, rsa1024.public_to_der
+ assert_equal asn1.to_der, key.public_to_der
+ assert_equal pem, rsa1024.public_to_pem
+ assert_equal pem, key.public_to_pem
end
def test_pem_passwd
+ omit_on_fips
+
key = Fixtures.pkey("rsa1024")
pem3c = key.to_pem("aes-128-cbc", "key")
assert_match (/ENCRYPTED/), pem3c
@@ -445,55 +528,66 @@ class OpenSSL::TestPKeyRSA < OpenSSL::PKeyTestCase
end
def test_private_encoding_encrypted
- rsa1024 = Fixtures.pkey("rsa1024")
- encoded = rsa1024.private_to_der("aes-128-cbc", "abcdef")
+ rsa = Fixtures.pkey("rsa2048")
+ encoded = rsa.private_to_der("aes-128-cbc", "abcdef")
asn1 = OpenSSL::ASN1.decode(encoded) # PKCS #8 EncryptedPrivateKeyInfo
assert_kind_of OpenSSL::ASN1::Sequence, asn1
assert_equal 2, asn1.value.size
- assert_not_equal rsa1024.private_to_der, encoded
- assert_same_rsa rsa1024, OpenSSL::PKey.read(encoded, "abcdef")
- assert_same_rsa rsa1024, OpenSSL::PKey.read(encoded) { "abcdef" }
+ assert_not_equal rsa.private_to_der, encoded
+ assert_same_rsa rsa, OpenSSL::PKey.read(encoded, "abcdef")
+ assert_same_rsa rsa, OpenSSL::PKey.read(encoded) { "abcdef" }
assert_raise(OpenSSL::PKey::PKeyError) { OpenSSL::PKey.read(encoded, "abcxyz") }
- encoded = rsa1024.private_to_pem("aes-128-cbc", "abcdef")
+ encoded = rsa.private_to_pem("aes-128-cbc", "abcdef")
assert_match (/BEGIN ENCRYPTED PRIVATE KEY/), encoded.lines[0]
- assert_same_rsa rsa1024, OpenSSL::PKey.read(encoded, "abcdef")
+ assert_same_rsa rsa, OpenSSL::PKey.read(encoded, "abcdef")
- # certtool --load-privkey=test/fixtures/pkey/rsa1024.pem --to-p8 --password=abcdef
+ # certtool --load-privkey=test/openssl/fixtures/pkey/rsa2048.pem --to-p8 --password=abcdef
pem = <<~EOF
-----BEGIN ENCRYPTED PRIVATE KEY-----
- MIICojAcBgoqhkiG9w0BDAEDMA4ECLqajUdSNfzwAgIEkQSCAoCDWhxr1HUrKLXA
- FsFGGQfPT0aKH4gZipaSXXQRl0KwifHwHoDtfo/mAkJVZMnUVOm1AQ4LTFS3EdTy
- JUwICGEQHb7QAiokIRoi0K2yHhOxVO8qgbnWuisWpiT6Ru1jCqTs/wcqlqF7z2jM
- oXDk/vuekKst1DDXDcHrzhDkwhCQWj6jt1r2Vwaryy0FyeqsWAgBDiK2LsnCgkGD
- 21uhNZ/iWMG6tvY9hB8MDdiBJ41YdSG/AKLulAxQ1ibJz0Tasu66TmwFvWhBlME+
- QbqfgmkgWg5buu53SvDfCA47zXihclbtdfW+U3CJ9OJkx0535TVdZbuC1QgKXvG7
- 4iKGFRMWYJqZvZM3GL4xbC75AxjXZsdCfV81VjZxjeU6ung/NRzCuCUcmBOQzo1D
- Vv6COwAa6ttQWM0Ti8oIQHdu5Qi+nuOEHDLxCxD962M37H99sEO5cESjmrGVxhEo
- 373L4+11geGSCajdp0yiAGnXQfwaKta8cL693bRObN+b1Y+vqtDKH26N9a4R3qgg
- 2XwgQ5GH5CODoXZpi0wxncXO+3YuuhGeArtzKSXLNxHzIMlY7wZX+0e9UU03zfV/
- aOe4/q5DpkNxgHePt0oEpamSKY5W3jzVi1dlFWsRjud1p/Grt2zjSWTYClBlJqG1
- A/3IeDZCu+acaePJjFyv5dFffIj2l4bAYB+LFrZlSu3F/EimO/dCDWJ9JGlMK0aF
- l9brh7786Mo+YfyklaqMMEHBbbR2Es7PR6Gt7lrcIXmzy9XSsxT6IiD1rG9KKR3i
- CQxTup6JAx9w1q+adL+Ypikoy3gGD/ccUY6TtPoCmkQwSCS+JqQnFlCiThDJbu+V
- eqqUNkZq
+ MIIFOTBjBgkqhkiG9w0BBQ0wVjA1BgkqhkiG9w0BBQwwKAQSsTIsinrhNMr4owUz
+ cwYGgB0lAgMJJ8ACARAwCgYIKoZIhvcNAgkwHQYJYIZIAWUDBAECBBDtDYqmQOLV
+ Nh0T0DslWgovBIIE0ESbJey2Pjf9brTp9/41CPnI9Ev78CGSv8Ihyuynu6G7oj7N
+ G7jUB1pVMQ7ivebF5DmM0qHAix6fDqJetB3WCnRQpMLyIdq5VrnKwFNhwGYduWA5
+ IyaAc4DHj02e6YLyBTIKpu79OSFxLrnLCRaTbvZIUQaGhyd6pB7iAhqz5YBC0rpa
+ iMK5TRlNGPYG9n2eGFOhvUsbJ4T8VDzjpVWw0VNRaukXtg4xiR6o1f0qSXqAb5d9
+ REq5DfaQfoOKTV9j7KJHDRrBQG81vkU4K+xILrCBfbcYb82aCoinwSep9LC30HaH
+ LZ0hYQOuD/k/UbgjToS2wyMnkz75MN5ZNhDMZl/mACQdsMMtIxG37Mpo1Ca33uZi
+ 71TCOEKIblZS11L1YhIni9Af8pOuHJBWwezP2zN2nPwV6OhgL7Jlax7ICQOPC6L/
+ yRGgC5eT4lDDAuTy0IdUhr0r5XrFzZR0/5Vgsq9cGfk9QkXOoETRhQVkEfUDdCs6
+ 6CK+SwUR9qh5824ShODFG0SQpsqBPIVtkGrypBSUJtICmGMOAsclB7RDN7/opJwp
+ qv/iRJ5dhWrhRgQ/DfYifvO5On7RgC2hm48gF3Pt6XCA857ryyYxLYeMY42tAUqp
+ Hmc9HL7bMYF/jl3cJ32+gLvI3PBVvrvyeAhRo6z7MFVe9I04OywV6BHUx1Us6ybF
+ qkYnSpcJZdu7HyvzXm7XWLFmt7K5BlAgnFsa/8+cI1BGPgQRc1j0SWepXsSwFZX6
+ JkNQ0dewq4uRJXbGyQgfh5I5ETpqDhSt2JfBwAoze6cx3DPC711PUamxyWMiejs+
+ mYdia4p62NxaUvyXWmCGIEOzajRwywEhf9OLAmfqTN41TIrEL4BUxqtzDyw8Nl8T
+ KB7nJEC366jFASfumNQkXXyH5yBIF+XwwSKUOObRZVn2rUzFToo51hHu9efxHoXa
+ jZlpfglWijkmOuwoIGlGHOq8gUn76oq9WbV+YO+fWm/mf4S3ECzmYzxb6a1uCTy/
+ Itkm2qOe3yTM1t+oCqZ0/MeTZ84ALQaWv5reQfjronPZ1jeNtxrYz28tJ4KwBn0U
+ bJReXbOLsHAymipncxlmaevbx4GPTduu/lbpxefoN95w+SpEdyTmVWrfaCTgAbad
+ EzcRl60my3xOMQ7CaUbRgGiwohqHDvuXzeqoZ96u6CwfAoEfy4jETmKLRH6uTtj7
+ 4jdTyoqyizjpvaM8LPspBS+oqFwLxBjpseQuScrZO1BjPxrImLy2/VRqwJ+CF4FB
+ iijEgDgDc1EMIGe5YmOAV+i22n9RqX+2IvkYp7CWXrB9/lmirLFukd7hT8DLPUGq
+ AvSZwTPbDPoZKG3DAebC3DbiC7A3x0KZp24doNRLamZ/MyKHo2Rzl0UhkzDU0ly2
+ eAnyNYsOAQck+C6L+ieD95Gksm9YJWurwttm5JragbIJwMCrsBQd4bXDkKdRhxS2
+ JpS0dT/aoDmgTzoG07x4cZk0rjBkfX1ta0j0b1lz7/PZXl9AbRvFdq5sJpmv4Ryz
+ S+OERqo4IEfJJq2WJ92WR+HLGV3Gvsdb7znZTEF1tp4pWOLAt83Pry282UJxO7Pe
+ ySf/868TEmXams06GYvH+7cMiIT2m9Dc+EFgNaPmm0uMmJ+ZjqHKSOLzrL7C
-----END ENCRYPTED PRIVATE KEY-----
EOF
- assert_same_rsa rsa1024, OpenSSL::PKey.read(pem, "abcdef")
- end
-
- def test_public_encoding
- rsa1024 = Fixtures.pkey("rsa1024")
- assert_equal dup_public(rsa1024).to_der, rsa1024.public_to_der
- assert_equal dup_public(rsa1024).to_pem, rsa1024.public_to_pem
+ assert_same_rsa rsa, OpenSSL::PKey.read(pem, "abcdef")
end
def test_dup
key = Fixtures.pkey("rsa1024")
key2 = key.dup
assert_equal key.params, key2.params
- key2.set_key(key2.n, 3, key2.d)
- assert_not_equal key.params, key2.params
+
+ # PKey is immutable in OpenSSL >= 3.0
+ if !openssl?(3, 0, 0)
+ key2.set_key(key2.n, 3, key2.d)
+ assert_not_equal key.params, key2.params
+ end
end
def test_marshal
diff --git a/test/openssl/test_provider.rb b/test/openssl/test_provider.rb
new file mode 100644
index 0000000000..6f85c00c98
--- /dev/null
+++ b/test/openssl/test_provider.rb
@@ -0,0 +1,83 @@
+# frozen_string_literal: true
+require_relative 'utils'
+if defined?(OpenSSL) && defined?(OpenSSL::Provider)
+
+class OpenSSL::TestProvider < OpenSSL::TestCase
+ def test_openssl_provider_name_inspect
+ with_openssl <<-'end;'
+ provider = OpenSSL::Provider.load("default")
+ assert_equal("default", provider.name)
+ assert_not_nil(provider.inspect)
+ end;
+ end
+
+ def test_openssl_provider_names
+ # We expect the following providers are loaded in the cases:
+ # * Non-FIPS: default
+ # * FIPS: fips, base
+ # Use the null provider to test the added provider.
+ # See provider(7) - OPENSSL PROVIDERS to see the list of providers, and
+ # OSSL_PROVIDER-null(7) to check the details of the null provider.
+ with_openssl <<-'end;'
+ num = OpenSSL::Provider.provider_names.size
+
+ added_provider = OpenSSL::Provider.load("null")
+ assert_equal(num + 1, OpenSSL::Provider.provider_names.size)
+ assert_includes(OpenSSL::Provider.provider_names, "null")
+
+ assert_equal(true, added_provider.unload)
+ assert_equal(num, OpenSSL::Provider.provider_names.size)
+ assert_not_includes(OpenSSL::Provider.provider_names, "null")
+ end;
+ end
+
+ def test_unloaded_openssl_provider
+ with_openssl <<-'end;'
+ default_provider = OpenSSL::Provider.load("default")
+ assert_equal(true, default_provider.unload)
+ assert_raise(OpenSSL::Provider::ProviderError) { default_provider.name }
+ assert_raise(OpenSSL::Provider::ProviderError) { default_provider.unload }
+ end;
+ end
+
+ def test_openssl_legacy_provider
+ # The legacy provider is not supported on FIPS.
+ omit_on_fips
+
+ with_openssl(<<-'end;')
+ begin
+ OpenSSL::Provider.load("legacy")
+ rescue OpenSSL::Provider::ProviderError
+ omit "Only for OpenSSL with legacy provider"
+ end
+
+ algo = "RC4"
+ data = "a" * 1000
+ key = OpenSSL::Random.random_bytes(16)
+
+ # default provider does not support RC4
+ cipher = OpenSSL::Cipher.new(algo)
+ cipher.encrypt
+ cipher.key = key
+ encrypted = cipher.update(data) + cipher.final
+
+ other_cipher = OpenSSL::Cipher.new(algo)
+ other_cipher.decrypt
+ other_cipher.key = key
+ decrypted = other_cipher.update(encrypted) + other_cipher.final
+
+ assert_equal(data, decrypted)
+ end;
+ end
+
+ private
+
+ # this is required because OpenSSL::Provider methods change global state
+ def with_openssl(code, **opts)
+ assert_separately(["-ropenssl"], <<~"end;", **opts)
+ #{code}
+ end;
+ end
+end
+
+end
diff --git a/test/openssl/test_ssl.rb b/test/openssl/test_ssl.rb
index 5dccac5fac..f011e881e9 100644
--- a/test/openssl/test_ssl.rb
+++ b/test/openssl/test_ssl.rb
@@ -1,9 +1,20 @@
# frozen_string_literal: true
require_relative "utils"
-if defined?(OpenSSL)
+if defined?(OpenSSL::SSL)
class OpenSSL::TestSSL < OpenSSL::SSLTestCase
+ def test_bad_socket
+ bad_socket = Struct.new(:sync).new
+ assert_raise TypeError do
+ socket = OpenSSL::SSL::SSLSocket.new bad_socket
+ # if the socket is not a T_FILE, `connect` will segv because it tries
+ # to get the underlying file descriptor but the API it calls assumes
+ # the object type is T_FILE
+ socket.connect
+ end
+ end
+
def test_ctx_options
ctx = OpenSSL::SSL::SSLContext.new
@@ -106,6 +117,30 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
}
end
+ def test_socket_close_write
+ server_proc = proc do |ctx, ssl|
+ message = ssl.read
+ ssl.write(message)
+ ssl.close_write
+ ensure
+ ssl.close
+ end
+
+ start_server(server_proc: server_proc) do |port|
+ ctx = OpenSSL::SSL::SSLContext.new
+ ssl = OpenSSL::SSL::SSLSocket.open("127.0.0.1", port, context: ctx)
+ ssl.sync_close = true
+ ssl.connect
+
+ message = "abc"*1024
+ ssl.write message
+ ssl.close_write
+ assert_equal message, ssl.read
+ ensure
+ ssl&.close
+ end
+ end
+
def test_add_certificate
ctx_proc = -> ctx {
# Unset values set by start_server
@@ -124,9 +159,6 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end
def test_add_certificate_multiple_certs
- pend "EC is not supported" unless defined?(OpenSSL::PKey::EC)
- pend "TLS 1.2 is not supported" unless tls12_supported?
-
ca2_key = Fixtures.pkey("rsa-3")
ca2_exts = [
["basicConstraints", "CA:TRUE", true],
@@ -185,6 +217,24 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
}
end
+ def test_read_with_timeout
+ omit "does not support timeout" unless IO.method_defined?(:timeout)
+
+ start_server do |port|
+ server_connect(port) do |ssl|
+ str = +("x" * 100 + "\n")
+ ssl.syswrite(str)
+ assert_equal(str, ssl.sysread(str.bytesize))
+
+ ssl.timeout = 1
+ assert_raise(IO::TimeoutError) {ssl.read(1)}
+
+ ssl.syswrite(str)
+ assert_equal(str, ssl.sysread(str.bytesize))
+ end
+ end
+ end
+
def test_getbyte
start_server { |port|
server_connect(port) { |ssl|
@@ -198,6 +248,19 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
}
end
+ def test_readbyte
+ start_server { |port|
+ server_connect(port) { |ssl|
+ str = +("x" * 100 + "\n")
+ ssl.syswrite(str)
+ newstr = str.bytesize.times.map { |i|
+ ssl.readbyte
+ }.pack("C*")
+ assert_equal(str, newstr)
+ }
+ }
+ end
+
def test_sync_close
start_server do |port|
begin
@@ -365,59 +428,20 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
}
end
- def test_read_nonblock_without_session
- EnvUtil.suppress_warning do
- start_server(start_immediately: false) { |port|
- sock = TCPSocket.new("127.0.0.1", port)
- ssl = OpenSSL::SSL::SSLSocket.new(sock)
- ssl.sync_close = true
-
- assert_equal :wait_readable, ssl.read_nonblock(100, exception: false)
- ssl.write("abc\n")
- IO.select [ssl]
- assert_equal('a', ssl.read_nonblock(1))
- assert_equal("bc\n", ssl.read_nonblock(100))
- assert_equal :wait_readable, ssl.read_nonblock(100, exception: false)
- ssl.close
- }
- end
- end
-
- def test_starttls
- server_proc = -> (ctx, ssl) {
- while line = ssl.gets
- if line =~ /^STARTTLS$/
- ssl.write("x")
- ssl.flush
- ssl.accept
- break
- end
- ssl.write(line)
- end
- readwrite_loop(ctx, ssl)
- }
-
- EnvUtil.suppress_warning do # read/write on not started session
- start_server(start_immediately: false,
- server_proc: server_proc) { |port|
- begin
- sock = TCPSocket.new("127.0.0.1", port)
- ssl = OpenSSL::SSL::SSLSocket.new(sock)
-
- ssl.puts "plaintext"
- assert_equal "plaintext\n", ssl.gets
+ def test_unstarted_session
+ start_server do |port|
+ sock = TCPSocket.new("127.0.0.1", port)
+ ssl = OpenSSL::SSL::SSLSocket.new(sock)
- ssl.puts("STARTTLS")
- ssl.read(1)
- ssl.connect
+ assert_raise(OpenSSL::SSL::SSLError) { ssl.syswrite("data") }
+ assert_raise(OpenSSL::SSL::SSLError) { ssl.sysread(1) }
- ssl.puts "over-tls"
- assert_equal "over-tls\n", ssl.gets
- ensure
- ssl&.close
- sock&.close
- end
- }
+ ssl.connect
+ ssl.puts "abc"
+ assert_equal "abc\n", ssl.gets
+ ensure
+ ssl&.close
+ sock&.close
end
end
@@ -512,6 +536,40 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
}
end
+ def test_ca_file
+ start_server(ignore_listener_error: true) { |port|
+ # X509_STORE is shared; setting ca_file to SSLContext affects store
+ store = OpenSSL::X509::Store.new
+ assert_equal false, store.verify(@svr_cert)
+
+ ctx = Tempfile.create("ca_cert.pem") { |f|
+ f.puts(@ca_cert.to_pem)
+ f.close
+
+ ctx = OpenSSL::SSL::SSLContext.new
+ ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
+ ctx.cert_store = store
+ ctx.ca_file = f.path
+ ctx.setup
+ ctx
+ }
+ assert_nothing_raised {
+ server_connect(port, ctx) { |ssl| ssl.puts("abc"); ssl.gets }
+ }
+ assert_equal true, store.verify(@svr_cert)
+ }
+ end
+
+ def test_ca_file_not_found
+ path = Tempfile.create("ca_cert.pem") { |f| f.path }
+ ctx = OpenSSL::SSL::SSLContext.new
+ ctx.ca_file = path
+ # OpenSSL >= 1.1.0: /no certificate or crl found/
+ assert_raise(OpenSSL::SSL::SSLError) {
+ ctx.setup
+ }
+ end
+
def test_finished_messages
server_finished = nil
server_peer_finished = nil
@@ -526,6 +584,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
}) { |port|
ctx = OpenSSL::SSL::SSLContext.new
ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE
+ ctx.max_version = :TLS1_2 if libressl?(3, 2, 0) && !libressl?(3, 3, 0)
server_connect(port, ctx) { |ssl|
ssl.puts "abc"; ssl.gets
@@ -553,11 +612,10 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end
def test_post_connect_check_with_anon_ciphers
- pend "TLS 1.2 is not supported" unless tls12_supported?
-
ctx_proc = -> ctx {
ctx.ssl_version = :TLSv1_2
ctx.ciphers = "aNULL"
+ ctx.tmp_dh = Fixtures.pkey("dh-1")
ctx.security_level = 0
}
@@ -596,8 +654,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
exts = [
["keyUsage","keyEncipherment,digitalSignature",true],
- ["subjectAltName","DNS:localhost.localdomain",false],
- ["subjectAltName","IP:127.0.0.1",false],
+ ["subjectAltName","DNS:localhost.localdomain,IP:127.0.0.1",false],
]
@svr_cert = issue_cert(@svr, @svr_key, 4, exts, @ca_cert, @ca_key)
start_server { |port|
@@ -671,7 +728,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
assert_equal(true, OpenSSL::SSL.verify_wildcard("xn--qdk4b9b", "xn--qdk4b9b"))
end
- # Comments in this test is excerpted from http://tools.ietf.org/html/rfc6125#page-27
+ # Comments in this test is excerpted from https://www.rfc-editor.org/rfc/rfc6125#page-27
def test_post_connection_check_wildcard_san
# case-insensitive ASCII comparison
# RFC 6125, section 6.4.1
@@ -708,10 +765,16 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
# buzz.example.net, respectively). ...
assert_equal(true, OpenSSL::SSL.verify_certificate_identity(
create_cert_with_san('DNS:baz*.example.com'), 'baz1.example.com'))
+
+ # LibreSSL 3.5.0+ doesn't support other wildcard certificates
+ # (it isn't required to, as RFC states MAY, not MUST)
+ return if libressl?(3, 5, 0)
+
assert_equal(true, OpenSSL::SSL.verify_certificate_identity(
create_cert_with_san('DNS:*baz.example.com'), 'foobaz.example.com'))
assert_equal(true, OpenSSL::SSL.verify_certificate_identity(
create_cert_with_san('DNS:b*z.example.com'), 'buzz.example.com'))
+
# Section 6.4.3 of RFC6125 states that client should NOT match identifier
# where wildcard is other than left-most label.
#
@@ -830,9 +893,56 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end
end
+ def test_keylog_cb
+ pend "Keylog callback is not supported" if !openssl?(1, 1, 1) || libressl?
+
+ prefix = 'CLIENT_RANDOM'
+ context = OpenSSL::SSL::SSLContext.new
+ context.min_version = context.max_version = OpenSSL::SSL::TLS1_2_VERSION
+
+ cb_called = false
+ context.keylog_cb = proc do |_sock, line|
+ cb_called = true
+ assert_equal(prefix, line.split.first)
+ end
+
+ start_server do |port|
+ server_connect(port, context) do |ssl|
+ ssl.puts "abc"
+ assert_equal("abc\n", ssl.gets)
+ assert_equal(true, cb_called)
+ end
+ end
+
+ if tls13_supported?
+ prefixes = [
+ 'SERVER_HANDSHAKE_TRAFFIC_SECRET',
+ 'EXPORTER_SECRET',
+ 'SERVER_TRAFFIC_SECRET_0',
+ 'CLIENT_HANDSHAKE_TRAFFIC_SECRET',
+ 'CLIENT_TRAFFIC_SECRET_0',
+ ]
+ context = OpenSSL::SSL::SSLContext.new
+ context.min_version = context.max_version = OpenSSL::SSL::TLS1_3_VERSION
+ cb_called = false
+ context.keylog_cb = proc do |_sock, line|
+ cb_called = true
+ assert_not_nil(prefixes.delete(line.split.first))
+ end
+
+ start_server do |port|
+ server_connect(port, context) do |ssl|
+ ssl.puts "abc"
+ assert_equal("abc\n", ssl.gets)
+ assert_equal(true, cb_called)
+ end
+ assert_equal(0, prefixes.size)
+ end
+ end
+ end
+
def test_tlsext_hostname
fooctx = OpenSSL::SSL::SSLContext.new
- fooctx.tmp_dh_callback = proc { Fixtures.pkey("dh-1") }
fooctx.cert = @cli_cert
fooctx.key = @cli_key
@@ -884,7 +994,6 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
ctx2 = OpenSSL::SSL::SSLContext.new
ctx2.cert = @svr_cert
ctx2.key = @svr_key
- ctx2.tmp_dh_callback = proc { Fixtures.pkey("dh-1") }
ctx2.servername_cb = lambda { |args| Object.new }
sock1, sock2 = socketpair
@@ -927,14 +1036,12 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end
end
- begin
- sock = TCPSocket.new("127.0.0.1", port)
- sock.puts "abc"
- ensure
- sock&.close
- end
+ sock = TCPSocket.new("127.0.0.1", port)
+ sock << "\x00" * 1024
assert t.join
+ ensure
+ sock&.close
server.close
end
@@ -1028,14 +1135,17 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
start_server(ignore_listener_error: true) { |port|
ctx = OpenSSL::SSL::SSLContext.new
ctx.set_params
- assert_raise_with_message(OpenSSL::SSL::SSLError, /self signed/) {
+ # OpenSSL <= 1.1.0: "self signed certificate in certificate chain"
+ # OpenSSL >= 3.0.0: "self-signed certificate in certificate chain"
+ assert_raise_with_message(OpenSSL::SSL::SSLError, /self.signed/) {
server_connect(port, ctx)
}
}
ctx_proc = proc { |ctx|
+ now = Time.now
ctx.cert = issue_cert(@svr, @svr_key, 30, [], @ca_cert, @ca_key,
- not_before: Time.now-100, not_after: Time.now-10)
+ not_before: now - 7200, not_after: now - 3600)
}
start_server(ignore_listener_error: true, ctx_proc: ctx_proc) { |port|
store = OpenSSL::X509::Store.new
@@ -1242,46 +1352,51 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end
def test_options_disable_versions
- # Note: Use of these OP_* flags has been deprecated since OpenSSL 1.1.0.
+ # It's recommended to use SSLContext#{min,max}_version= instead in real
+ # applications. The purpose of this test case is to check that SSL options
+ # are properly propagated to OpenSSL library.
supported = check_supported_protocol_versions
+ if !defined?(OpenSSL::SSL::TLS1_3_VERSION) ||
+ !supported.include?(OpenSSL::SSL::TLS1_2_VERSION) ||
+ !supported.include?(OpenSSL::SSL::TLS1_3_VERSION) ||
+ !defined?(OpenSSL::SSL::OP_NO_TLSv1_3) # LibreSSL < 3.4
+ pend "this test case requires both TLS 1.2 and TLS 1.3 to be supported " \
+ "and enabled by default"
+ end
- if supported.include?(OpenSSL::SSL::TLS1_1_VERSION) &&
- supported.include?(OpenSSL::SSL::TLS1_2_VERSION)
- # Server disables ~ TLS 1.1
- ctx_proc = proc { |ctx|
- ctx.options |= OpenSSL::SSL::OP_NO_SSLv2 | OpenSSL::SSL::OP_NO_SSLv3 |
- OpenSSL::SSL::OP_NO_TLSv1 | OpenSSL::SSL::OP_NO_TLSv1_1
- }
- start_server(ctx_proc: ctx_proc, ignore_listener_error: true) { |port|
- # Client only supports TLS 1.1
- ctx1 = OpenSSL::SSL::SSLContext.new
- ctx1.min_version = ctx1.max_version = OpenSSL::SSL::TLS1_1_VERSION
- assert_handshake_error { server_connect(port, ctx1) { } }
+ # Server disables TLS 1.2 and earlier
+ ctx_proc = proc { |ctx|
+ ctx.options |= OpenSSL::SSL::OP_NO_SSLv2 | OpenSSL::SSL::OP_NO_SSLv3 |
+ OpenSSL::SSL::OP_NO_TLSv1 | OpenSSL::SSL::OP_NO_TLSv1_1 |
+ OpenSSL::SSL::OP_NO_TLSv1_2
+ }
+ start_server(ctx_proc: ctx_proc, ignore_listener_error: true) { |port|
+ # Client only supports TLS 1.2
+ ctx1 = OpenSSL::SSL::SSLContext.new
+ ctx1.min_version = ctx1.max_version = OpenSSL::SSL::TLS1_2_VERSION
+ assert_handshake_error { server_connect(port, ctx1) { } }
- # Client only supports TLS 1.2
- ctx2 = OpenSSL::SSL::SSLContext.new
- ctx2.min_version = ctx2.max_version = OpenSSL::SSL::TLS1_2_VERSION
- assert_nothing_raised { server_connect(port, ctx2) { } }
- }
+ # Client only supports TLS 1.3
+ ctx2 = OpenSSL::SSL::SSLContext.new
+ ctx2.min_version = ctx2.max_version = OpenSSL::SSL::TLS1_3_VERSION
+ assert_nothing_raised { server_connect(port, ctx2) { } }
+ }
- # Server only supports TLS 1.1
- ctx_proc = proc { |ctx|
- ctx.min_version = ctx.max_version = OpenSSL::SSL::TLS1_1_VERSION
- }
- start_server(ctx_proc: ctx_proc, ignore_listener_error: true) { |port|
- # Client disables TLS 1.1
- ctx1 = OpenSSL::SSL::SSLContext.new
- ctx1.options |= OpenSSL::SSL::OP_NO_TLSv1_1
- assert_handshake_error { server_connect(port, ctx1) { } }
+ # Server only supports TLS 1.2
+ ctx_proc = proc { |ctx|
+ ctx.min_version = ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION
+ }
+ start_server(ctx_proc: ctx_proc, ignore_listener_error: true) { |port|
+ # Client doesn't support TLS 1.2
+ ctx1 = OpenSSL::SSL::SSLContext.new
+ ctx1.options |= OpenSSL::SSL::OP_NO_TLSv1_2
+ assert_handshake_error { server_connect(port, ctx1) { } }
- # Client disables TLS 1.2
- ctx2 = OpenSSL::SSL::SSLContext.new
- ctx2.options |= OpenSSL::SSL::OP_NO_TLSv1_2
- assert_nothing_raised { server_connect(port, ctx2) { } }
- }
- else
- pend "TLS 1.1 and TLS 1.2 must be supported; skipping"
- end
+ # Client supports TLS 1.2 by default
+ ctx2 = OpenSSL::SSL::SSLContext.new
+ ctx2.options |= OpenSSL::SSL::OP_NO_TLSv1_3
+ assert_nothing_raised { server_connect(port, ctx2) { } }
+ }
end
def test_ssl_methods_constant
@@ -1331,7 +1446,6 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
ctx1 = OpenSSL::SSL::SSLContext.new
ctx1.cert = @svr_cert
ctx1.key = @svr_key
- ctx1.tmp_dh_callback = proc { Fixtures.pkey("dh-1") }
ctx1.alpn_select_cb = -> (protocols) { nil }
ssl1 = OpenSSL::SSL::SSLSocket.new(sock1, ctx1)
@@ -1354,10 +1468,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end
def test_npn_protocol_selection_ary
- pend "TLS 1.2 is not supported" unless tls12_supported?
- pend "NPN is not supported" unless \
- OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb)
- pend "LibreSSL 2.6 has broken NPN functions" if libressl?(2, 6, 1)
+ return unless OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb)
advertised = ["http/1.1", "spdy/2"]
ctx_proc = proc { |ctx| ctx.npn_protocols = advertised }
@@ -1375,10 +1486,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end
def test_npn_protocol_selection_enum
- pend "TLS 1.2 is not supported" unless tls12_supported?
- pend "NPN is not supported" unless \
- OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb)
- pend "LibreSSL 2.6 has broken NPN functions" if libressl?(2, 6, 1)
+ return unless OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb)
advertised = Object.new
def advertised.each
@@ -1400,10 +1508,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end
def test_npn_protocol_selection_cancel
- pend "TLS 1.2 is not supported" unless tls12_supported?
- pend "NPN is not supported" unless \
- OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb)
- pend "LibreSSL 2.6 has broken NPN functions" if libressl?(2, 6, 1)
+ return unless OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb)
ctx_proc = Proc.new { |ctx| ctx.npn_protocols = ["http/1.1"] }
start_server_version(:TLSv1_2, ctx_proc) { |port|
@@ -1414,10 +1519,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end
def test_npn_advertised_protocol_too_long
- pend "TLS 1.2 is not supported" unless tls12_supported?
- pend "NPN is not supported" unless \
- OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb)
- pend "LibreSSL 2.6 has broken NPN functions" if libressl?(2, 6, 1)
+ return unless OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb)
ctx_proc = Proc.new { |ctx| ctx.npn_protocols = ["a" * 256] }
start_server_version(:TLSv1_2, ctx_proc) { |port|
@@ -1428,10 +1530,7 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end
def test_npn_selected_protocol_too_long
- pend "TLS 1.2 is not supported" unless tls12_supported?
- pend "NPN is not supported" unless \
- OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb)
- pend "LibreSSL 2.6 has broken NPN functions" if libressl?(2, 6, 1)
+ return unless OpenSSL::SSL::SSLContext.method_defined?(:npn_select_cb)
ctx_proc = Proc.new { |ctx| ctx.npn_protocols = ["http/1.1"] }
start_server_version(:TLSv1_2, ctx_proc) { |port|
@@ -1469,56 +1568,51 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end
def test_get_ephemeral_key
- if tls12_supported?
- # kRSA
- ctx_proc1 = proc { |ctx|
- ctx.ssl_version = :TLSv1_2
- ctx.ciphers = "kRSA"
- }
- start_server(ctx_proc: ctx_proc1, ignore_listener_error: true) do |port|
- ctx = OpenSSL::SSL::SSLContext.new
- ctx.ssl_version = :TLSv1_2
- ctx.ciphers = "kRSA"
- begin
- server_connect(port, ctx) { |ssl| assert_nil ssl.tmp_key }
- rescue OpenSSL::SSL::SSLError
- # kRSA seems disabled
- raise unless $!.message =~ /no cipher/
- end
+ # kRSA
+ ctx_proc1 = proc { |ctx|
+ ctx.ssl_version = :TLSv1_2
+ ctx.ciphers = "kRSA"
+ }
+ start_server(ctx_proc: ctx_proc1, ignore_listener_error: true) do |port|
+ ctx = OpenSSL::SSL::SSLContext.new
+ ctx.ssl_version = :TLSv1_2
+ ctx.ciphers = "kRSA"
+ begin
+ server_connect(port, ctx) { |ssl| assert_nil ssl.tmp_key }
+ rescue OpenSSL::SSL::SSLError
+ # kRSA seems disabled
+ raise unless $!.message =~ /no cipher/
end
end
- if defined?(OpenSSL::PKey::DH) && tls12_supported?
- # DHE
- # TODO: How to test this with TLS 1.3?
- ctx_proc2 = proc { |ctx|
- ctx.ssl_version = :TLSv1_2
- ctx.ciphers = "EDH"
+ # DHE
+ # TODO: How to test this with TLS 1.3?
+ ctx_proc2 = proc { |ctx|
+ ctx.ssl_version = :TLSv1_2
+ ctx.ciphers = "EDH"
+ ctx.tmp_dh = Fixtures.pkey("dh-1")
+ }
+ start_server(ctx_proc: ctx_proc2) do |port|
+ ctx = OpenSSL::SSL::SSLContext.new
+ ctx.ssl_version = :TLSv1_2
+ ctx.ciphers = "EDH"
+ server_connect(port, ctx) { |ssl|
+ assert_instance_of OpenSSL::PKey::DH, ssl.tmp_key
}
- start_server(ctx_proc: ctx_proc2) do |port|
- ctx = OpenSSL::SSL::SSLContext.new
- ctx.ssl_version = :TLSv1_2
- ctx.ciphers = "EDH"
- server_connect(port, ctx) { |ssl|
- assert_instance_of OpenSSL::PKey::DH, ssl.tmp_key
- }
- end
end
- if defined?(OpenSSL::PKey::EC)
- # ECDHE
- ctx_proc3 = proc { |ctx|
- ctx.ciphers = "DEFAULT:!kRSA:!kEDH"
- ctx.ecdh_curves = "P-256"
+ # ECDHE
+ ctx_proc3 = proc { |ctx|
+ ctx.ciphers = "DEFAULT:!kRSA:!kEDH"
+ ctx.ecdh_curves = "P-256"
+ }
+ start_server(ctx_proc: ctx_proc3) do |port|
+ ctx = OpenSSL::SSL::SSLContext.new
+ ctx.ciphers = "DEFAULT:!kRSA:!kEDH"
+ server_connect(port, ctx) { |ssl|
+ assert_instance_of OpenSSL::PKey::EC, ssl.tmp_key
+ ssl.puts "abc"; assert_equal "abc\n", ssl.gets
}
- start_server(ctx_proc: ctx_proc3) do |port|
- ctx = OpenSSL::SSL::SSLContext.new
- ctx.ciphers = "DEFAULT:!kRSA:!kEDH"
- server_connect(port, ctx) { |ssl|
- assert_instance_of OpenSSL::PKey::EC, ssl.tmp_key
- ssl.puts "abc"; assert_equal "abc\n", ssl.gets
- }
- end
end
end
@@ -1583,13 +1677,11 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end
end
- def test_dh_callback
- pend "TLS 1.2 is not supported" unless tls12_supported?
-
+ def test_tmp_dh_callback
dh = Fixtures.pkey("dh-1")
called = false
ctx_proc = -> ctx {
- ctx.ssl_version = :TLSv1_2
+ ctx.max_version = :TLS1_2
ctx.ciphers = "DH:!NULL"
ctx.tmp_dh_callback = ->(*args) {
called = true
@@ -1604,11 +1696,106 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end
end
- def test_connect_works_when_setting_dh_callback_to_nil
- pend "TLS 1.2 is not supported" unless tls12_supported?
+ def test_ciphersuites_method_tls_connection
+ ssl_ctx = OpenSSL::SSL::SSLContext.new
+ if !tls13_supported? || !ssl_ctx.respond_to?(:ciphersuites=)
+ pend 'TLS 1.3 not supported'
+ end
+
+ csuite = ['TLS_AES_128_GCM_SHA256', 'TLSv1.3', 128, 128]
+ inputs = [csuite[0], [csuite[0]], [csuite]]
+
+ start_server do |port|
+ inputs.each do |input|
+ cli_ctx = OpenSSL::SSL::SSLContext.new
+ cli_ctx.min_version = cli_ctx.max_version = OpenSSL::SSL::TLS1_3_VERSION
+ cli_ctx.ciphersuites = input
+
+ server_connect(port, cli_ctx) do |ssl|
+ assert_equal('TLSv1.3', ssl.ssl_version)
+ if libressl?(3, 4, 0) && !libressl?(3, 5, 0)
+ assert_equal("AEAD-AES128-GCM-SHA256", ssl.cipher[0])
+ else
+ assert_equal(csuite[0], ssl.cipher[0])
+ end
+ ssl.puts('abc'); assert_equal("abc\n", ssl.gets)
+ end
+ end
+ end
+ end
+
+ def test_ciphersuites_method_nil_argument
+ ssl_ctx = OpenSSL::SSL::SSLContext.new
+ pend 'ciphersuites= method is missing' unless ssl_ctx.respond_to?(:ciphersuites=)
+
+ assert_nothing_raised { ssl_ctx.ciphersuites = nil }
+ end
+
+ def test_ciphersuites_method_frozen_object
+ ssl_ctx = OpenSSL::SSL::SSLContext.new
+ pend 'ciphersuites= method is missing' unless ssl_ctx.respond_to?(:ciphersuites=)
+
+ ssl_ctx.freeze
+ assert_raise(FrozenError) { ssl_ctx.ciphersuites = 'TLS_AES_256_GCM_SHA384' }
+ end
+
+ def test_ciphersuites_method_bogus_csuite
+ ssl_ctx = OpenSSL::SSL::SSLContext.new
+ pend 'ciphersuites= method is missing' unless ssl_ctx.respond_to?(:ciphersuites=)
+
+ assert_raise_with_message(
+ OpenSSL::SSL::SSLError,
+ /SSL_CTX_set_ciphersuites: no cipher match/i
+ ) { ssl_ctx.ciphersuites = 'BOGUS' }
+ end
+
+ def test_ciphers_method_tls_connection
+ csuite = ['ECDHE-RSA-AES256-GCM-SHA384', 'TLSv1.2', 256, 256]
+ inputs = [csuite[0], [csuite[0]], [csuite]]
+
+ start_server do |port|
+ inputs.each do |input|
+ cli_ctx = OpenSSL::SSL::SSLContext.new
+ cli_ctx.min_version = cli_ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION
+ cli_ctx.ciphers = input
+
+ server_connect(port, cli_ctx) do |ssl|
+ assert_equal('TLSv1.2', ssl.ssl_version)
+ assert_equal(csuite[0], ssl.cipher[0])
+ ssl.puts('abc'); assert_equal("abc\n", ssl.gets)
+ end
+ end
+ end
+ end
+
+ def test_ciphers_method_nil_argument
+ ssl_ctx = OpenSSL::SSL::SSLContext.new
+ assert_nothing_raised { ssl_ctx.ciphers = nil }
+ end
+ def test_ciphers_method_frozen_object
+ ssl_ctx = OpenSSL::SSL::SSLContext.new
+
+ ssl_ctx.freeze
+ assert_raise(FrozenError) { ssl_ctx.ciphers = 'ECDHE-RSA-AES128-SHA' }
+ end
+
+ def test_ciphers_method_bogus_csuite
+ omit "Old #{OpenSSL::OPENSSL_LIBRARY_VERSION}" if
+ year = OpenSSL::OPENSSL_LIBRARY_VERSION[/\A OpenSSL\s+[01]\..*\s\K\d+\z/x] and
+ year.to_i <= 2018
+
+ ssl_ctx = OpenSSL::SSL::SSLContext.new
+
+ assert_raise_with_message(
+ OpenSSL::SSL::SSLError,
+ /SSL_CTX_set_cipher_list: no cipher match/i
+ ) { ssl_ctx.ciphers = 'BOGUS' }
+ end
+
+ def test_connect_works_when_setting_dh_callback_to_nil
ctx_proc = -> ctx {
- ctx.ssl_version = :TLSv1_2
+ ctx.max_version = :TLS1_2
ctx.ciphers = "DH:!NULL" # use DH
ctx.tmp_dh_callback = nil
}
@@ -1621,9 +1808,21 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end
end
- def test_ecdh_curves_tls12
- pend "EC is disabled" unless defined?(OpenSSL::PKey::EC)
+ def test_tmp_dh
+ dh = Fixtures.pkey("dh-1")
+ ctx_proc = -> ctx {
+ ctx.max_version = :TLS1_2
+ ctx.ciphers = "DH:!NULL" # use DH
+ ctx.tmp_dh = dh
+ }
+ start_server(ctx_proc: ctx_proc) do |port|
+ server_connect(port) { |ssl|
+ assert_equal dh.to_der, ssl.tmp_key.to_der
+ }
+ end
+ end
+ def test_ecdh_curves_tls12
ctx_proc = -> ctx {
# Enable both ECDHE (~ TLS 1.2) cipher suites and TLS 1.3
ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION
@@ -1659,7 +1858,6 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
end
def test_ecdh_curves_tls13
- pend "EC is disabled" unless defined?(OpenSSL::PKey::EC)
pend "TLS 1.3 not supported" unless tls13_supported?
ctx_proc = -> ctx {
@@ -1746,6 +1944,19 @@ class OpenSSL::TestSSL < OpenSSL::SSLTestCase
sock2.close
end
+ def test_export_keying_material
+ start_server do |port|
+ cli_ctx = OpenSSL::SSL::SSLContext.new
+ server_connect(port, cli_ctx) do |ssl|
+ assert_instance_of(String, ssl.export_keying_material('ttls keying material', 64))
+ assert_operator(64, :==, ssl.export_keying_material('ttls keying material', 64).b.length)
+ assert_operator(8, :==, ssl.export_keying_material('ttls keying material', 8).b.length)
+ assert_operator(5, :==, ssl.export_keying_material('test', 5, 'context').b.length)
+ ssl.puts "abc"; ssl.gets # workaround to make tests work on windows
+ end
+ end
+ end
+
private
def start_server_version(version, ctx_proc = nil,
diff --git a/test/openssl/test_ssl_session.rb b/test/openssl/test_ssl_session.rb
index a98efdae2a..89cf672a7b 100644
--- a/test/openssl/test_ssl_session.rb
+++ b/test/openssl/test_ssl_session.rb
@@ -1,12 +1,10 @@
# frozen_string_literal: true
require_relative "utils"
-if defined?(OpenSSL)
+if defined?(OpenSSL::SSL)
class OpenSSL::TestSSLSession < OpenSSL::SSLTestCase
def test_session
- pend "TLS 1.2 is not supported" unless tls12_supported?
-
ctx_proc = proc { |ctx| ctx.ssl_version = :TLSv1_2 }
start_server(ctx_proc: ctx_proc) do |port|
server_connect_with_session(port, nil, nil) { |ssl|
@@ -24,7 +22,7 @@ class OpenSSL::TestSSLSession < OpenSSL::SSLTestCase
assert_match(/\A-----BEGIN SSL SESSION PARAMETERS-----/, pem)
assert_match(/-----END SSL SESSION PARAMETERS-----\Z/, pem)
pem.gsub!(/-----(BEGIN|END) SSL SESSION PARAMETERS-----/, '').gsub!(/[\r\n]+/m, '')
- assert_equal(session.to_der, pem.unpack('m*')[0])
+ assert_equal(session.to_der, pem.unpack1('m'))
assert_not_nil(session.to_text)
}
end
@@ -144,8 +142,6 @@ __EOS__
end
def test_server_session_cache
- pend "TLS 1.2 is not supported" unless tls12_supported?
-
ctx_proc = Proc.new do |ctx|
ctx.ssl_version = :TLSv1_2
ctx.options |= OpenSSL::SSL::OP_NO_TICKET
@@ -224,8 +220,6 @@ __EOS__
TEST_SESSION_REMOVE_CB = ENV["OSSL_TEST_ALL"] == "1"
def test_ctx_client_session_cb
- pend "TLS 1.2 is not supported" unless tls12_supported?
-
ctx_proc = proc { |ctx| ctx.ssl_version = :TLSv1_2 }
start_server(ctx_proc: ctx_proc) do |port|
called = {}
@@ -257,8 +251,6 @@ __EOS__
end
def test_ctx_server_session_cb
- pend "TLS 1.2 is not supported" unless tls12_supported?
-
connections = nil
called = {}
cctx = OpenSSL::SSL::SSLContext.new
diff --git a/test/openssl/test_ts.rb b/test/openssl/test_ts.rb
index 8e31a7d28d..ac0469ad56 100644
--- a/test/openssl/test_ts.rb
+++ b/test/openssl/test_ts.rb
@@ -181,6 +181,12 @@ _end_of_pem_
assert_equal(42, qer2.nonce)
end
+ def test_request_invalid_asn1
+ assert_raise(OpenSSL::Timestamp::TimestampError) do
+ OpenSSL::Timestamp::Request.new("*" * 44)
+ end
+ end
+
def test_response_constants
assert_equal(0, OpenSSL::Timestamp::Response::GRANTED)
assert_equal(1, OpenSSL::Timestamp::Response::GRANTED_WITH_MODS)
@@ -317,6 +323,8 @@ _end_of_pem_
resp = fac.create_timestamp(ee_key, ts_cert_ee, req)
assert_equal(OpenSSL::Timestamp::Response::GRANTED, resp.status)
assert_equal("1.2.3.4.6", resp.token_info.policy_id)
+
+ assert_match(/1\.2\.3\.4\.6/, resp.to_text)
end
def test_response_bad_purpose
@@ -338,6 +346,12 @@ _end_of_pem_
end
end
+ def test_response_invalid_asn1
+ assert_raise(OpenSSL::Timestamp::TimestampError) do
+ OpenSSL::Timestamp::Response.new("*" * 44)
+ end
+ end
+
def test_no_cert_requested
req = OpenSSL::Timestamp::Request.new
req.algorithm = "SHA1"
@@ -590,6 +604,12 @@ _end_of_pem_
assert_equal(123, info.nonce)
end
+ def test_token_info_invalid_asn1
+ assert_raise(OpenSSL::Timestamp::TimestampError) do
+ OpenSSL::Timestamp::TokenInfo.new("*" * 44)
+ end
+ end
+
private
def assert_cert expected, actual
diff --git a/test/openssl/test_x509attr.rb b/test/openssl/test_x509attr.rb
index 2919d23d2d..bec03a1871 100644
--- a/test/openssl/test_x509attr.rb
+++ b/test/openssl/test_x509attr.rb
@@ -48,6 +48,10 @@ class OpenSSL::TestX509Attribute < OpenSSL::TestCase
assert_raise(TypeError) {
attr.value = "1234"
}
+ assert_raise(OpenSSL::X509::AttributeError) {
+ v = OpenSSL::ASN1::Set([OpenSSL::ASN1::UTF8String("1234")], 17, :EXPLICIT)
+ attr.value = v
+ }
assert_equal(test_der, attr.to_der)
assert_raise(OpenSSL::X509::AttributeError) {
attr.oid = "abc123"
diff --git a/test/openssl/test_x509cert.rb b/test/openssl/test_x509cert.rb
index d696b98c0a..85c978f022 100644
--- a/test/openssl/test_x509cert.rb
+++ b/test/openssl/test_x509cert.rb
@@ -173,13 +173,14 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase
end
def test_sign_and_verify_rsa_sha1
- cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil, digest: "sha1")
+ cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil, digest: "SHA1")
assert_equal(false, cert.verify(@rsa1024))
assert_equal(true, cert.verify(@rsa2048))
assert_equal(false, certificate_error_returns_false { cert.verify(@dsa256) })
assert_equal(false, certificate_error_returns_false { cert.verify(@dsa512) })
cert.serial = 2
assert_equal(false, cert.verify(@rsa2048))
+ rescue OpenSSL::X509::CertificateError # RHEL 9 disables SHA1
end
def test_sign_and_verify_rsa_md5
@@ -221,6 +222,29 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase
}
end
+ def test_sign_and_verify_ed25519
+ # See test_ed25519 in test_pkey.rb
+
+ # Ed25519 is not FIPS-approved.
+ omit_on_fips
+
+ begin
+ ed25519 = OpenSSL::PKey::generate_key("ED25519")
+ rescue OpenSSL::PKey::PKeyError => e
+ # OpenSSL < 1.1.1
+ #
+ pend "Ed25519 is not implemented" unless openssl?(1, 1, 1)
+
+ raise e
+ end
+
+ # See ASN1_item_sign_ctx in ChangeLog for 3.8.1: https://github.com/libressl/portable/blob/master/ChangeLog
+ pend 'ASN1 signing with Ed25519 not yet working' unless openssl? or libressl?(3, 8, 1)
+
+ cert = issue_cert(@ca, ed25519, 1, [], nil, nil, digest: nil)
+ assert_equal(true, cert.verify(ed25519))
+ end
+
def test_dsa_with_sha2
cert = issue_cert(@ca, @dsa256, 1, [], nil, nil, digest: "sha256")
assert_equal("dsa_with_SHA256", cert.signature_algorithm)
@@ -229,6 +253,7 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase
# SHA1 is allowed from OpenSSL 1.0.0 (0.9.8 requires DSS1)
cert = issue_cert(@ca, @dsa256, 1, [], nil, nil, digest: "sha1")
assert_equal("dsaWithSHA1", cert.signature_algorithm)
+ rescue OpenSSL::X509::CertificateError # RHEL 9 disables SHA1
end
def test_check_private_key
@@ -320,6 +345,15 @@ class OpenSSL::TestX509Certificate < OpenSSL::TestCase
end
end
+ def test_tbs_precert_bytes
+ pend "LibreSSL < 3.5 does not have i2d_re_X509_tbs" if libressl? && !libressl?(3, 5, 0)
+
+ cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil)
+ seq = OpenSSL::ASN1.decode(cert.tbs_bytes)
+
+ assert_equal 7, seq.value.size
+ end
+
private
def certificate_error_returns_false
diff --git a/test/openssl/test_x509crl.rb b/test/openssl/test_x509crl.rb
index bcdb0a697c..146ee07309 100644
--- a/test/openssl/test_x509crl.rb
+++ b/test/openssl/test_x509crl.rb
@@ -20,7 +20,7 @@ class OpenSSL::TestX509CRL < OpenSSL::TestCase
cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil)
crl = issue_crl([], 1, now, now+1600, [],
- cert, @rsa2048, OpenSSL::Digest.new('SHA1'))
+ cert, @rsa2048, OpenSSL::Digest.new('SHA256'))
assert_equal(1, crl.version)
assert_equal(cert.issuer.to_der, crl.issuer.to_der)
assert_equal(now, crl.last_update)
@@ -57,7 +57,7 @@ class OpenSSL::TestX509CRL < OpenSSL::TestCase
]
cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil)
crl = issue_crl(revoke_info, 1, Time.now, Time.now+1600, [],
- cert, @rsa2048, OpenSSL::Digest.new('SHA1'))
+ cert, @rsa2048, OpenSSL::Digest.new('SHA256'))
revoked = crl.revoked
assert_equal(5, revoked.size)
assert_equal(1, revoked[0].serial)
@@ -98,7 +98,7 @@ class OpenSSL::TestX509CRL < OpenSSL::TestCase
revoke_info = (1..1000).collect{|i| [i, now, 0] }
crl = issue_crl(revoke_info, 1, Time.now, Time.now+1600, [],
- cert, @rsa2048, OpenSSL::Digest.new('SHA1'))
+ cert, @rsa2048, OpenSSL::Digest.new('SHA256'))
revoked = crl.revoked
assert_equal(1000, revoked.size)
assert_equal(1, revoked[0].serial)
@@ -124,7 +124,7 @@ class OpenSSL::TestX509CRL < OpenSSL::TestCase
cert = issue_cert(@ca, @rsa2048, 1, cert_exts, nil, nil)
crl = issue_crl([], 1, Time.now, Time.now+1600, crl_exts,
- cert, @rsa2048, OpenSSL::Digest.new('SHA1'))
+ cert, @rsa2048, OpenSSL::Digest.new('SHA256'))
exts = crl.extensions
assert_equal(3, exts.size)
assert_equal("1", exts[0].value)
@@ -160,24 +160,24 @@ class OpenSSL::TestX509CRL < OpenSSL::TestCase
assert_equal(false, exts[2].critical?)
no_ext_crl = issue_crl([], 1, Time.now, Time.now+1600, [],
- cert, @rsa2048, OpenSSL::Digest.new('SHA1'))
+ cert, @rsa2048, OpenSSL::Digest.new('SHA256'))
assert_equal nil, no_ext_crl.authority_key_identifier
end
def test_crlnumber
cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil)
crl = issue_crl([], 1, Time.now, Time.now+1600, [],
- cert, @rsa2048, OpenSSL::Digest.new('SHA1'))
+ cert, @rsa2048, OpenSSL::Digest.new('SHA256'))
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.new('SHA1'))
+ cert, @rsa2048, OpenSSL::Digest.new('SHA256'))
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.new('SHA1'))
+ cert, @rsa2048, OpenSSL::Digest.new('SHA256'))
assert_match(/X509v3 CRL Number:\s+#{2**100}/m, crl.to_text)
assert_match((2**100).to_s, crl.extensions[0].value)
end
@@ -185,7 +185,7 @@ class OpenSSL::TestX509CRL < OpenSSL::TestCase
def test_sign_and_verify
cert = issue_cert(@ca, @rsa2048, 1, [], nil, nil)
crl = issue_crl([], 1, Time.now, Time.now+1600, [],
- cert, @rsa2048, OpenSSL::Digest.new('SHA1'))
+ cert, @rsa2048, OpenSSL::Digest.new('SHA256'))
assert_equal(false, crl.verify(@rsa1024))
assert_equal(true, crl.verify(@rsa2048))
assert_equal(false, crl_error_returns_false { crl.verify(@dsa256) })
@@ -195,7 +195,7 @@ class OpenSSL::TestX509CRL < OpenSSL::TestCase
cert = issue_cert(@ca, @dsa512, 1, [], nil, nil)
crl = issue_crl([], 1, Time.now, Time.now+1600, [],
- cert, @dsa512, OpenSSL::Digest.new('SHA1'))
+ cert, @dsa512, OpenSSL::Digest.new('SHA256'))
assert_equal(false, crl_error_returns_false { crl.verify(@rsa1024) })
assert_equal(false, crl_error_returns_false { crl.verify(@rsa2048) })
assert_equal(false, crl.verify(@dsa256))
diff --git a/test/openssl/test_x509ext.rb b/test/openssl/test_x509ext.rb
index 7ad010d1ed..59a41ed736 100644
--- a/test/openssl/test_x509ext.rb
+++ b/test/openssl/test_x509ext.rb
@@ -50,24 +50,41 @@ class OpenSSL::TestX509Extension < OpenSSL::TestCase
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)
+ assert_include(cdp.value, "URI:http://www.example.com/crl")
+ assert_include(cdp.value,
+ "URI:ldap://ldap.example.com/cn=ca?certificateRevocationList;binary")
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)
+ assert_include(cdp.value, "URI:http://www.example.com/crl")
+ assert_include(cdp.value,
+ "URI:ldap://ldap.example.com/cn=ca?certificateRevocationList;binary")
cp = ef.create_extension("certificatePolicies", "@certPolicies")
assert_equal(false, cp.critical?)
assert_equal("certificatePolicies", cp.oid)
- assert_match(%r{2.23.140.1.2.1}, cp.value)
- assert_match(%r{http://cps.example.com}, cp.value)
+ assert_include(cp.value, "2.23.140.1.2.1")
+ assert_include(cp.value, "http://cps.example.com")
+ end
+
+ def test_factory_create_extension_sn_ln
+ ef = OpenSSL::X509::ExtensionFactory.new
+ bc_sn = ef.create_extension("basicConstraints", "critical, CA:TRUE, pathlen:2")
+ bc_ln = ef.create_extension("X509v3 Basic Constraints", "critical, CA:TRUE, pathlen:2")
+ assert_equal(@basic_constraints.to_der, bc_sn.to_der)
+ assert_equal(@basic_constraints.to_der, bc_ln.to_der)
+ end
+
+ def test_factory_create_extension_oid
+ ef = OpenSSL::X509::ExtensionFactory.new
+ ef.config = OpenSSL::Config.parse(<<~_end_of_cnf_)
+ [basic_constraints]
+ cA = BOOLEAN:TRUE
+ pathLenConstraint = INTEGER:2
+ _end_of_cnf_
+ bc_oid = ef.create_extension("2.5.29.19", "ASN1:SEQUENCE:basic_constraints", true)
+ assert_equal(@basic_constraints.to_der, bc_oid.to_der)
end
def test_dup
diff --git a/test/openssl/test_x509req.rb b/test/openssl/test_x509req.rb
index ee9c678fbb..b98754b8c8 100644
--- a/test/openssl/test_x509req.rb
+++ b/test/openssl/test_x509req.rb
@@ -23,31 +23,26 @@ class OpenSSL::TestX509Request < OpenSSL::TestCase
end
def test_public_key
- req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA1'))
+ req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA256'))
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.new('SHA1'))
+ req = issue_csr(0, @dn, @dsa512, OpenSSL::Digest.new('SHA256'))
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.new('SHA1'))
+ req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA256'))
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.new('SHA1'))
- 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.new('SHA1'))
+ req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA256'))
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)
@@ -78,9 +73,9 @@ class OpenSSL::TestX509Request < OpenSSL::TestCase
OpenSSL::X509::Attribute.new("msExtReq", attrval),
]
- req0 = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA1'))
+ req0 = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA256'))
attrs.each{|attr| req0.add_attribute(attr) }
- req1 = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA1'))
+ req1 = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA256'))
req1.attributes = attrs
assert_equal(req0.to_der, req1.to_der)
@@ -106,8 +101,9 @@ class OpenSSL::TestX509Request < OpenSSL::TestCase
assert_equal(false, req.verify(@rsa2048))
assert_equal(false, request_error_returns_false { req.verify(@dsa256) })
assert_equal(false, request_error_returns_false { req.verify(@dsa512) })
- req.version = 1
+ req.subject = OpenSSL::X509::Name.parse("/C=JP/CN=FooBarFooBar")
assert_equal(false, req.verify(@rsa1024))
+ rescue OpenSSL::X509::RequestError # RHEL 9 disables SHA1
end
def test_sign_and_verify_rsa_md5
@@ -122,7 +118,7 @@ class OpenSSL::TestX509Request < OpenSSL::TestCase
end
def test_sign_and_verify_dsa
- req = issue_csr(0, @dn, @dsa512, OpenSSL::Digest.new('SHA1'))
+ req = issue_csr(0, @dn, @dsa512, OpenSSL::Digest.new('SHA256'))
assert_equal(false, request_error_returns_false { req.verify(@rsa1024) })
assert_equal(false, request_error_returns_false { req.verify(@rsa2048) })
assert_equal(false, req.verify(@dsa256))
@@ -137,14 +133,14 @@ class OpenSSL::TestX509Request < OpenSSL::TestCase
end
def test_dup
- req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA1'))
+ req = issue_csr(0, @dn, @rsa1024, OpenSSL::Digest.new('SHA256'))
assert_equal(req.to_der, req.dup.to_der)
end
def test_eq
- req1 = issue_csr(0, @dn, @rsa1024, "sha1")
- req2 = issue_csr(0, @dn, @rsa1024, "sha1")
- req3 = issue_csr(0, @dn, @rsa1024, "sha256")
+ req1 = issue_csr(0, @dn, @rsa1024, "sha256")
+ req2 = issue_csr(0, @dn, @rsa1024, "sha256")
+ req3 = issue_csr(0, @dn, @rsa1024, "sha512")
assert_equal false, req1 == 12345
assert_equal true, req1 == req2
diff --git a/test/openssl/ut_eof.rb b/test/openssl/ut_eof.rb
index 7b18f43a79..06aa632a65 100644
--- a/test/openssl/ut_eof.rb
+++ b/test/openssl/ut_eof.rb
@@ -8,6 +8,10 @@ module OpenSSL::TestEOF
open_file("") {|f| assert_nil f.getbyte }
end
+ def test_readbyte_eof
+ open_file("") {|f| assert_raise(EOFError) { f.readbyte } }
+ end
+
def test_eof_0
open_file("") {|f|
assert_equal("", f.read(0))
diff --git a/test/openssl/utils.rb b/test/openssl/utils.rb
index ab5fab4ba3..f6c84eef67 100644
--- a/test/openssl/utils.rb
+++ b/test/openssl/utils.rb
@@ -1,38 +1,13 @@
# frozen_string_literal: true
begin
require "openssl"
-
- # Disable FIPS mode for tests for installations
- # where FIPS mode would be enabled by default.
- # Has no effect on all other installations.
- OpenSSL.fips_mode=false
rescue LoadError
end
-# Compile OpenSSL with crypto-mdebug and run this test suite with OSSL_MDEBUG=1
-# environment variable to enable memory leak check.
-if ENV["OSSL_MDEBUG"] == "1"
- if OpenSSL.respond_to?(:print_mem_leaks)
- OpenSSL.mem_check_start
-
- END {
- GC.start
- case OpenSSL.print_mem_leaks
- when nil
- warn "mdebug: check what is printed"
- when true
- raise "mdebug: memory leaks detected"
- end
- }
- else
- warn "OSSL_MDEBUG=1 is specified but OpenSSL is not built with crypto-mdebug"
- end
-end
-
require "test/unit"
+require "core_assertions"
require "tempfile"
require "socket"
-require "envutil"
if defined?(OpenSSL)
@@ -131,11 +106,12 @@ module OpenSSL::TestUtils
end
end
- def openssl?(major = nil, minor = nil, fix = nil, patch = 0)
+ def openssl?(major = nil, minor = nil, fix = nil, patch = 0, status = 0)
return false if OpenSSL::OPENSSL_VERSION.include?("LibreSSL")
return true unless major
OpenSSL::OPENSSL_VERSION_NUMBER >=
- major * 0x10000000 + minor * 0x100000 + fix * 0x1000 + patch * 0x10
+ major * 0x10000000 + minor * 0x100000 + fix * 0x1000 + patch * 0x10 +
+ status * 0x1
end
def libressl?(major = nil, minor = nil, fix = nil)
@@ -148,6 +124,7 @@ end
class OpenSSL::TestCase < Test::Unit::TestCase
include OpenSSL::TestUtils
extend OpenSSL::TestUtils
+ include Test::Unit::CoreAssertions
def setup
if ENV["OSSL_GC_STRESS"] == "1"
@@ -162,6 +139,30 @@ class OpenSSL::TestCase < Test::Unit::TestCase
# OpenSSL error stack must be empty
assert_equal([], OpenSSL.errors)
end
+
+ # Omit the tests in FIPS.
+ #
+ # For example, the password based encryption used in the PEM format uses MD5
+ # for deriving the encryption key from the password, and MD5 is not
+ # FIPS-approved.
+ #
+ # See https://github.com/openssl/openssl/discussions/21830#discussioncomment-6865636
+ # for details.
+ def omit_on_fips
+ return unless OpenSSL.fips_mode
+
+ omit <<~MESSAGE
+ Only for OpenSSL non-FIPS with the following possible reasons:
+ * A testing logic is non-FIPS specific.
+ * An encryption used in the test is not FIPS-approved.
+ MESSAGE
+ end
+
+ def omit_on_non_fips
+ return if OpenSSL.fips_mode
+
+ omit "Only for OpenSSL FIPS"
+ end
end
class OpenSSL::SSLTestCase < OpenSSL::TestCase
@@ -189,13 +190,6 @@ class OpenSSL::SSLTestCase < OpenSSL::TestCase
@server = nil
end
- def tls12_supported?
- ctx = OpenSSL::SSL::SSLContext.new
- ctx.min_version = ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION
- true
- rescue
- end
-
def tls13_supported?
return false unless defined?(OpenSSL::SSL::TLS1_3_VERSION)
ctx = OpenSSL::SSL::SSLContext.new
@@ -222,7 +216,6 @@ class OpenSSL::SSLTestCase < OpenSSL::TestCase
ctx.cert_store = store
ctx.cert = @svr_cert
ctx.key = @svr_key
- ctx.tmp_dh_callback = proc { Fixtures.pkey("dh-1") }
ctx.verify_mode = verify_mode
ctx_proc.call(ctx) if ctx_proc
@@ -236,9 +229,7 @@ class OpenSSL::SSLTestCase < OpenSSL::TestCase
threads = []
begin
server_thread = Thread.new do
- if Thread.method_defined?(:report_on_exception=) # Ruby >= 2.4
- Thread.current.report_on_exception = false
- end
+ Thread.current.report_on_exception = false
begin
loop do
@@ -254,9 +245,7 @@ class OpenSSL::SSLTestCase < OpenSSL::TestCase
end
th = Thread.new do
- if Thread.method_defined?(:report_on_exception=)
- Thread.current.report_on_exception = false
- end
+ Thread.current.report_on_exception = false
begin
server_proc.call(ctx, ssl)
@@ -273,9 +262,7 @@ class OpenSSL::SSLTestCase < OpenSSL::TestCase
end
client_thread = Thread.new do
- if Thread.method_defined?(:report_on_exception=)
- Thread.current.report_on_exception = false
- end
+ Thread.current.report_on_exception = false
begin
block.call(port)
@@ -312,32 +299,6 @@ class OpenSSL::PKeyTestCase < OpenSSL::TestCase
assert_equal base.send(comp), test.send(comp)
}
end
-
- def dup_public(key)
- case key
- when OpenSSL::PKey::RSA
- rsa = OpenSSL::PKey::RSA.new
- rsa.set_key(key.n, key.e, nil)
- rsa
- when OpenSSL::PKey::DSA
- dsa = OpenSSL::PKey::DSA.new
- dsa.set_pqg(key.p, key.q, key.g)
- dsa.set_key(key.pub_key, nil)
- dsa
- when OpenSSL::PKey::DH
- dh = OpenSSL::PKey::DH.new
- dh.set_pqg(key.p, nil, key.g)
- dh
- else
- if defined?(OpenSSL::PKey::EC) && OpenSSL::PKey::EC === key
- ec = OpenSSL::PKey::EC.new(key.group)
- ec.public_key = key.public_key
- ec
- else
- raise "unknown key type"
- end
- end
- end
end
module OpenSSL::Certs
diff --git a/test/optparse/test_acceptable.rb b/test/optparse/test_acceptable.rb
index 12f7886538..8b578effde 100644
--- a/test/optparse/test_acceptable.rb
+++ b/test/optparse/test_acceptable.rb
@@ -1,13 +1,14 @@
# frozen_string_literal: false
require_relative 'test_optparse'
-class TestOptionParser::Acceptable < TestOptionParser
+class TestOptionParserAcceptable < TestOptionParser
def setup
super
@opt.def_option("--integer VAL", Integer) { |v| @integer = v }
@opt.def_option("--float VAL", Float) { |v| @float = v }
@opt.def_option("--numeric VAL", Numeric) { |v| @numeric = v }
+ @opt.def_option("--array VAL", Array) { |v| @array = v }
@opt.def_option("--decimal-integer VAL",
OptionParser::DecimalInteger) { |i| @decimal_integer = i }
@@ -195,4 +196,10 @@ class TestOptionParser::Acceptable < TestOptionParser
end
end
+ def test_array
+ assert_equal(%w"", no_error {@opt.parse!(%w"--array a,b,c")})
+ assert_equal(%w"a b c", @array)
+ assert_equal(%w"", no_error {@opt.parse!(%w"--array a")})
+ assert_equal(%w"a", @array)
+ end
end
diff --git a/test/optparse/test_autoconf.rb b/test/optparse/test_autoconf.rb
index 45f2ba09b2..ec87744633 100644
--- a/test/optparse/test_autoconf.rb
+++ b/test/optparse/test_autoconf.rb
@@ -2,9 +2,7 @@
require 'test/unit'
require 'optparse/ac'
-class TestOptionParser < Test::Unit::TestCase; end
-
-class TestOptionParser::AutoConf < Test::Unit::TestCase
+class TestOptionParserAutoConf < Test::Unit::TestCase
def setup
@opt = OptionParser::AC.new
@foo = @bar = self.class
diff --git a/test/optparse/test_bash_completion.rb b/test/optparse/test_bash_completion.rb
index 513e986f66..60c82f7136 100644
--- a/test/optparse/test_bash_completion.rb
+++ b/test/optparse/test_bash_completion.rb
@@ -2,9 +2,7 @@
require 'test/unit'
require 'optparse'
-class TestOptionParser < Test::Unit::TestCase
-end
-class TestOptionParser::BashCompletion < Test::Unit::TestCase
+class TestOptionParserBashCompletion < Test::Unit::TestCase
def setup
@opt = OptionParser.new
@opt.define("-z", "zzz") {}
diff --git a/test/optparse/test_cclass.rb b/test/optparse/test_cclass.rb
index ac46f46bb2..0ded61f60e 100644
--- a/test/optparse/test_cclass.rb
+++ b/test/optparse/test_cclass.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: false
require_relative 'test_optparse'
-class TestOptionParser::CClass < TestOptionParser
+class TestOptionParserCClass < TestOptionParser
def test_no_argument
flags = []
@opt.def_option("-[a-z]") {|x| flags << x}
diff --git a/test/optparse/test_did_you_mean.rb b/test/optparse/test_did_you_mean.rb
index 763062586c..3c923922ec 100644
--- a/test/optparse/test_did_you_mean.rb
+++ b/test/optparse/test_did_you_mean.rb
@@ -6,17 +6,21 @@ rescue LoadError
return
end
-class TestOptionParser::DidYouMean < TestOptionParser
+class TestOptionParserDidYouMean < TestOptionParser
def setup
super
@opt.def_option("--foo", Integer) { |v| @foo = v }
@opt.def_option("--bar", Integer) { |v| @bar = v }
@opt.def_option("--baz", Integer) { |v| @baz = v }
@formatter = ::DidYouMean.formatter
- case @formatter
- when ::DidYouMean::PlainFormatter
+ if ::DidYouMean.const_defined?(:Formatter)
+ ::DidYouMean.formatter = ::DidYouMean::Formatter
else
- ::DidYouMean.formatter = ::DidYouMean::PlainFormatter.new
+ case @formatter
+ when ::DidYouMean::PlainFormatter
+ else
+ ::DidYouMean.formatter = ::DidYouMean::PlainFormatter.new
+ end
end
end
@@ -36,15 +40,7 @@ class TestOptionParser::DidYouMean < TestOptionParser
end
end
- def test_verbose
- require 'did_you_mean/formatters/verbose_formatter'
- ::DidYouMean.formatter = ::DidYouMean::VerboseFormatter.new
- assert_raise_with_message(OptionParser::InvalidOption, /invalid option: --baa\n\s+Did you mean\?\s+bar\s+baz\s*\Z/) do
- @opt.permute!(%w"--baa")
- end
- end
-
- def test_ambiguos
+ def test_ambiguous
assert_raise_with_message(OptionParser::AmbiguousOption, /ambiguous option: --ba\nDid you mean\?\s+bar\s+baz\Z/) do
@opt.permute!(%w"--ba")
end
diff --git a/test/optparse/test_getopts.rb b/test/optparse/test_getopts.rb
index 3711e6f269..4a0ae284e7 100644
--- a/test/optparse/test_getopts.rb
+++ b/test/optparse/test_getopts.rb
@@ -2,9 +2,7 @@
require 'test/unit'
require 'optparse'
-class TestOptionParser < Test::Unit::TestCase
-end
-class TestOptionParser::Getopts < Test::Unit::TestCase
+class TestOptionParserGetopts < Test::Unit::TestCase
def setup
@opt = OptionParser.new
end
@@ -13,23 +11,39 @@ class TestOptionParser::Getopts < Test::Unit::TestCase
o = @opt.getopts(%w[-a], "ab")
assert_equal(true, o['a'])
assert_equal(false, o['b'])
+
+ o = @opt.getopts(%w[-a], "ab", symbolize_names: true)
+ 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'])
+
+ o = @opt.getopts(%w[-a1], "a:b:", symbolize_names: true)
+ 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'])
+
+ o = @opt.getopts(%w[--foo], "", "foo", "bar", symbolize_names: true)
+ 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'])
+
+ o = @opt.getopts(%w[--bar ZOT], "", "foo:FOO", "bar:BAR", symbolize_names: true)
+ assert_equal("FOO", o[:foo])
+ assert_equal("ZOT", o[:bar])
end
end
diff --git a/test/optparse/test_kwargs.rb b/test/optparse/test_kwargs.rb
index 78d7e2ee9c..2e826bfd12 100644
--- a/test/optparse/test_kwargs.rb
+++ b/test/optparse/test_kwargs.rb
@@ -3,9 +3,7 @@ require 'test/unit'
require 'optparse'
require 'optparse/kwargs'
-class TestOptionParser < Test::Unit::TestCase
-end
-class TestOptionParser::KwArg < Test::Unit::TestCase
+class TestOptionParserKwArg < Test::Unit::TestCase
class K
def initialize(host:, port: 8080)
@host = host
diff --git a/test/optparse/test_load.rb b/test/optparse/test_load.rb
new file mode 100644
index 0000000000..0ebe855682
--- /dev/null
+++ b/test/optparse/test_load.rb
@@ -0,0 +1,141 @@
+# frozen_string_literal: false
+require 'test/unit'
+require 'optparse'
+require 'tmpdir'
+
+class TestOptionParserLoad < Test::Unit::TestCase
+ def setup
+ @tmpdir = Dir.mktmpdir("optparse_test-")
+ @basename = File.basename($0, '.*')
+ @envs = %w[HOME XDG_CONFIG_HOME XDG_CONFIG_DIRS].each_with_object({}) do |v, h|
+ h[v] = ENV.delete(v)
+ end
+ end
+
+ def teardown
+ ENV.update(@envs)
+ FileUtils.rm_rf(@tmpdir)
+ end
+
+ def new_parser
+ @result = nil
+ OptionParser.new do |opt|
+ opt.on("--test=arg") {|v| @result = v}
+ end
+ end
+
+ def assert_load(result)
+ assert new_parser.load
+ assert_equal(result, @result)
+ assert new_parser.load(into: into = {})
+ assert_equal({test: result}, into)
+ end
+
+ def setup_options(env, dir, suffix = nil)
+ optdir = File.join(@tmpdir, dir)
+ FileUtils.mkdir_p(optdir)
+ file = File.join(optdir, [@basename, suffix].join(""))
+ File.write(file, "--test=#{dir}")
+ ENV.update(env)
+ if block_given?
+ begin
+ yield dir, optdir
+ ensure
+ File.unlink(file)
+ Dir.rmdir(optdir) rescue nil
+ end
+ else
+ return dir, optdir
+ end
+ end
+
+ def setup_options_home(&block)
+ setup_options({'HOME'=>@tmpdir}, ".options", &block)
+ end
+
+ def setup_options_xdg_config_home(&block)
+ setup_options({'XDG_CONFIG_HOME'=>@tmpdir+"/xdg"}, "xdg", ".options", &block)
+ end
+
+ def setup_options_home_config(&block)
+ setup_options({'HOME'=>@tmpdir}, ".config", ".options", &block)
+ end
+
+ def setup_options_xdg_config_dirs(&block)
+ setup_options({'XDG_CONFIG_DIRS'=>@tmpdir+"/xdgconf"}, "xdgconf", ".options", &block)
+ end
+
+ def setup_options_home_config_settings(&block)
+ setup_options({'HOME'=>@tmpdir}, "config/settings", ".options", &block)
+ end
+
+ def test_load_home_options
+ result, = setup_options_home
+ assert_load(result)
+
+ setup_options_xdg_config_home do
+ assert_load(result)
+ end
+
+ setup_options_home_config do
+ assert_load(result)
+ end
+
+ setup_options_xdg_config_dirs do
+ assert_load(result)
+ end
+
+ setup_options_home_config_settings do
+ assert_load(result)
+ end
+ end
+
+ def test_load_xdg_config_home
+ result, = setup_options_xdg_config_home
+ assert_load(result)
+
+ setup_options_home_config do
+ assert_load(result)
+ end
+
+ setup_options_xdg_config_dirs do
+ assert_load(result)
+ end
+
+ setup_options_home_config_settings do
+ assert_load(result)
+ end
+ end
+
+ def test_load_home_config
+ result, = setup_options_home_config
+ assert_load(result)
+
+ setup_options_xdg_config_dirs do
+ assert_load(result)
+ end
+
+ setup_options_home_config_settings do
+ assert_load(result)
+ end
+ end
+
+ def test_load_xdg_config_dirs
+ result, = setup_options_xdg_config_dirs
+ assert_load(result)
+
+ setup_options_home_config_settings do
+ assert_load(result)
+ end
+ end
+
+ def test_load_home_config_settings
+ result, = setup_options_home_config_settings
+ assert_load(result)
+ end
+
+ def test_load_nothing
+ assert !new_parser.load
+ assert_nil @result
+ end
+end
diff --git a/test/optparse/test_noarg.rb b/test/optparse/test_noarg.rb
index 8f20519408..a53399afc2 100644
--- a/test/optparse/test_noarg.rb
+++ b/test/optparse/test_noarg.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: false
require_relative 'test_optparse'
-module TestOptionParser::NoArg
+module TestOptionParserNoArg
def setup
super
@opt.def_option "--with_underscore" do |x| @flag = x end
@@ -9,7 +9,7 @@ module TestOptionParser::NoArg
end
class Def1 < TestOptionParser
- include NoArg
+ include TestOptionParserNoArg
def setup
super
@opt.def_option("-x") {|x| @flag = x}
@@ -17,7 +17,7 @@ module TestOptionParser::NoArg
end
end
class Def2 < TestOptionParser
- include NoArg
+ include TestOptionParserNoArg
def setup
super
@opt.def_option("-x", "--option") {|x| @flag = x}
diff --git a/test/optparse/test_optarg.rb b/test/optparse/test_optarg.rb
index 14584f7e89..f94460527f 100644
--- a/test/optparse/test_optarg.rb
+++ b/test/optparse/test_optarg.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: false
require_relative 'test_optparse'
-class TestOptionParser::OptArg < TestOptionParser
+class TestOptionParserOptArg < TestOptionParser
def setup
super
@opt.def_option("-x[VAL]") {|x| @flag = x}
@@ -9,6 +9,8 @@ class TestOptionParser::OptArg < TestOptionParser
@opt.def_option("--regexp[=REGEXP]", Regexp) {|x| @reopt = x}
@opt.def_option "--with_underscore[=VAL]" do |x| @flag = x end
@opt.def_option "--with-hyphen[=VAL]" do |x| @flag = x end
+ @opt.def_option("--fallback[=VAL]") do |x = "fallback"| @flag = x end
+ @opt.def_option("--lambda[=VAL]", &->(x) {@flag = x})
@reopt = nil
end
@@ -57,4 +59,18 @@ class TestOptionParser::OptArg < TestOptionParser
assert_equal(%w"", no_error {@opt.parse!(%w"--with_hyphen=foo4")})
assert_equal("foo4", @flag)
end
+
+ def test_default_argument
+ assert_equal(%w"", no_error {@opt.parse!(%w"--fallback=val1")})
+ assert_equal("val1", @flag)
+ assert_equal(%w"", no_error {@opt.parse!(%w"--fallback")})
+ assert_equal("fallback", @flag)
+ end
+
+ def test_lambda
+ assert_equal(%w"", no_error {@opt.parse!(%w"--lambda=lambda1")})
+ assert_equal("lambda1", @flag)
+ assert_equal(%w"", no_error {@opt.parse!(%w"--lambda")})
+ assert_equal(nil, @flag)
+ end
end
diff --git a/test/optparse/test_optparse.rb b/test/optparse/test_optparse.rb
index 5f5ea183b0..7f35cb4a8a 100644
--- a/test/optparse/test_optparse.rb
+++ b/test/optparse/test_optparse.rb
@@ -63,6 +63,9 @@ class TestOptionParser < Test::Unit::TestCase
assert_equal(/foo/i, @reopt)
assert_equal(%w"", no_error {@opt.parse!(%w"--regexp=/foo/n")})
assert_equal(/foo/n, @reopt)
+ assert_equal(%w"", no_error {@opt.parse!(%W"--regexp=/\u{3042}/s")})
+ assert_equal(Encoding::Windows_31J, @reopt.encoding)
+ assert_equal("\x82\xa0".force_encoding(Encoding::Windows_31J), @reopt.source)
end
def test_into
@@ -70,10 +73,30 @@ class TestOptionParser < Test::Unit::TestCase
@opt.def_option "-p", "--port=PORT", "port", Integer
@opt.def_option "-v", "--verbose" do @verbose = true end
@opt.def_option "-q", "--quiet" do @quiet = true end
+ @opt.def_option "-o", "--option [OPT]" do |opt| @option = opt end
+ @opt.def_option "-a", "--array [VAL]", Array do |val| val end
result = {}
@opt.parse %w(--host localhost --port 8000 -v), into: result
assert_equal({host: "localhost", port: 8000, verbose: true}, result)
assert_equal(true, @verbose)
+ result = {}
+ @opt.parse %w(--option -q), into: result
+ assert_equal({quiet: true, option: nil}, result)
+ result = {}
+ @opt.parse %w(--option OPTION -v), into: result
+ assert_equal({verbose: true, option: "OPTION"}, result)
+ result = {}
+ @opt.parse %w(-a b,c,d), into: result
+ assert_equal({array: %w(b c d)}, result)
+ result = {}
+ @opt.parse %w(--array b,c,d), into: result
+ assert_equal({array: %w(b c d)}, result)
+ result = {}
+ @opt.parse %w(-a b), into: result
+ assert_equal({array: %w(b)}, result)
+ result = {}
+ @opt.parse %w(--array b), into: result
+ assert_equal({array: %w(b)}, result)
end
def test_require_exact
@@ -85,9 +108,9 @@ class TestOptionParser < Test::Unit::TestCase
end
@opt.require_exact = true
- %w(--zrs -F -Ffoo).each do |arg|
+ [%w(--zrs foo), %w(--zrs=foo), %w(-F foo), %w(-Ffoo)].each do |args|
result = {}
- @opt.parse([arg, 'foo'], into: result)
+ @opt.parse(args, into: result)
assert_equal({zrs: 'foo'}, result)
end
@@ -96,6 +119,55 @@ class TestOptionParser < Test::Unit::TestCase
assert_raise(OptionParser::InvalidOption) {@opt.parse(%w(-zrs foo))}
assert_raise(OptionParser::InvalidOption) {@opt.parse(%w(-zr foo))}
assert_raise(OptionParser::InvalidOption) {@opt.parse(%w(-z foo))}
+
+ @opt.def_option('-f', '--[no-]foo', 'foo') {|arg| @foo = arg}
+ @opt.parse(%w[-f])
+ assert_equal(true, @foo)
+ @opt.parse(%w[--foo])
+ assert_equal(true, @foo)
+ @opt.parse(%w[--no-foo])
+ assert_equal(false, @foo)
+ end
+
+ def test_exact_option
+ @opt.def_option('-F', '--zrs=IRS', 'zrs')
+ %w(--zrs --zr --z -zfoo -z -F -Ffoo).each do |arg|
+ result = {}
+ @opt.parse([arg, 'foo'], into: result)
+ assert_equal({zrs: 'foo'}, result)
+ end
+
+ [%w(--zrs foo), %w(--zrs=foo), %w(-F foo), %w(-Ffoo)].each do |args|
+ result = {}
+ @opt.parse(args, into: result, exact: true)
+ assert_equal({zrs: 'foo'}, result)
+ end
+
+ assert_raise(OptionParser::InvalidOption) {@opt.parse(%w(--zr foo), exact: true)}
+ assert_raise(OptionParser::InvalidOption) {@opt.parse(%w(--z foo), exact: true)}
+ assert_raise(OptionParser::InvalidOption) {@opt.parse(%w(-zrs foo), exact: true)}
+ assert_raise(OptionParser::InvalidOption) {@opt.parse(%w(-zr foo), exact: true)}
+ assert_raise(OptionParser::InvalidOption) {@opt.parse(%w(-z foo), exact: true)}
+
+ @opt.def_option('-f', '--[no-]foo', 'foo') {|arg| @foo = arg}
+ @opt.parse(%w[-f], exact: true)
+ assert_equal(true, @foo)
+ @opt.parse(%w[--foo], exact: true)
+ assert_equal(true, @foo)
+ @opt.parse(%w[--no-foo], exact: true)
+ assert_equal(false, @foo)
+ end
+
+ def test_raise_unknown
+ @opt.def_option('--my-foo [ARG]') {|arg| @foo = arg}
+ assert @opt.raise_unknown
+
+ @opt.raise_unknown = false
+ assert_equal(%w[--my-bar], @opt.parse(%w[--my-foo --my-bar]))
+ assert_nil(@foo)
+
+ assert_equal(%w[--my-bar], @opt.parse(%w[--my-foo x --my-bar]))
+ assert_equal("x", @foo)
end
def test_nonopt_pattern
@@ -105,4 +177,44 @@ class TestOptionParser < Test::Unit::TestCase
e = assert_raise(OptionParser::InvalidOption) {@opt.parse(%w(-t))}
assert_equal(["-t"], e.args)
end
+
+ def test_help_pager
+ require 'tmpdir'
+ Dir.mktmpdir do |dir|
+ File.open(File.join(dir, "options.rb"), "w") do |f|
+ f.puts "#{<<~"begin;"}\n#{<<~'end;'}"
+ begin;
+ stdout = STDOUT.dup
+ def stdout.tty?; true; end
+ Object.__send__(:remove_const, :STDOUT)
+ STDOUT = stdout
+ ARGV.options do |opt|
+ end;
+ 100.times {|i| f.puts " opt.on('--opt-#{i}') {}"}
+ f.puts "#{<<~"begin;"}\n#{<<~'end;'}"
+ begin;
+ opt.parse!
+ end
+ end;
+ end
+
+ optparse = $".find {|path| path.end_with?("/optparse.rb")}
+ args = ["-r#{optparse}", "options.rb", "--help"]
+ cmd = File.join(dir, "pager.cmd")
+ if RbConfig::CONFIG["EXECUTABLE_EXTS"]&.include?(".cmd")
+ command = "@echo off"
+ else # if File.executable?("/bin/sh")
+ # TruffleRuby just calls `posix_spawnp` and no fallback to `/bin/sh`.
+ command = "#!/bin/sh\n"
+ end
+
+ [
+ [{"RUBY_PAGER"=>cmd, "PAGER"=>"echo ng"}, "Executing RUBY_PAGER"],
+ [{"RUBY_PAGER"=>nil, "PAGER"=>cmd}, "Executing PAGER"],
+ ].each do |env, expected|
+ File.write(cmd, "#{command}\n" "echo #{expected}\n", perm: 0o700)
+ assert_in_out_err([env, *args], "", [expected], chdir: dir)
+ end
+ end
+ end
end
diff --git a/test/optparse/test_placearg.rb b/test/optparse/test_placearg.rb
index 8acfdb2161..a8a11e676b 100644
--- a/test/optparse/test_placearg.rb
+++ b/test/optparse/test_placearg.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: false
require_relative 'test_optparse'
-class TestOptionParser::PlaceArg < TestOptionParser
+class TestOptionParserPlaceArg < TestOptionParser
def setup
super
@opt.def_option("-x [VAL]") {|x| @flag = x}
@@ -13,11 +13,15 @@ class TestOptionParser::PlaceArg < TestOptionParser
@reopt = nil
@opt.def_option "--with_underscore=VAL" do |x| @flag = x end
@opt.def_option "--with-hyphen=VAL" do |x| @flag = x end
+ @opt.def_option("--fallback [VAL]") do |x = "fallback"| @flag = x end
+ @opt.def_option("--lambda [VAL]", &->(x) {@flag = x})
end
def test_short
assert_equal(%w"", no_error {@opt.parse!(%w"-x -n")})
assert_equal(nil, @flag)
+ assert_equal(%w"", no_error {@opt.parse!(%w"-x -")})
+ assert_equal("-", @flag)
@flag = false
assert_equal(%w"", no_error {@opt.parse!(%w"-x foo")})
assert_equal("foo", @flag)
@@ -30,6 +34,8 @@ class TestOptionParser::PlaceArg < TestOptionParser
def test_abbrev
assert_equal(%w"", no_error {@opt.parse!(%w"-o -n")})
assert_equal(nil, @flag)
+ assert_equal(%w"", no_error {@opt.parse!(%w"-o -")})
+ assert_equal("-", @flag)
@flag = false
assert_equal(%w"", no_error {@opt.parse!(%w"-o foo")})
assert_equal("foo", @flag)
@@ -42,6 +48,8 @@ class TestOptionParser::PlaceArg < TestOptionParser
def test_long
assert_equal(%w"", no_error {@opt.parse!(%w"--opt -n")})
assert_equal(nil, @flag)
+ assert_equal(%w"", no_error {@opt.parse!(%w"--opt -")})
+ assert_equal("-", @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")})
@@ -67,4 +75,22 @@ class TestOptionParser::PlaceArg < TestOptionParser
assert_equal(%w"te.rb", no_error('[ruby-dev:38333]') {@opt.parse!(%w"-T1 te.rb")})
assert_equal(1, @topt)
end
+
+ def test_default_argument
+ assert_equal(%w"", no_error {@opt.parse!(%w"--fallback=val1")})
+ assert_equal("val1", @flag)
+ assert_equal(%w"", no_error {@opt.parse!(%w"--fallback val2")})
+ assert_equal("val2", @flag)
+ assert_equal(%w"", no_error {@opt.parse!(%w"--fallback")})
+ assert_equal("fallback", @flag)
+ end
+
+ def test_lambda
+ assert_equal(%w"", no_error {@opt.parse!(%w"--lambda=lambda1")})
+ assert_equal("lambda1", @flag)
+ assert_equal(%w"", no_error {@opt.parse!(%w"--lambda lambda2")})
+ assert_equal("lambda2", @flag)
+ assert_equal(%w"", no_error {@opt.parse!(%w"--lambda")})
+ assert_equal(nil, @flag)
+ end
end
diff --git a/test/optparse/test_reqarg.rb b/test/optparse/test_reqarg.rb
index b2e4755f80..31d4fef417 100644
--- a/test/optparse/test_reqarg.rb
+++ b/test/optparse/test_reqarg.rb
@@ -1,15 +1,16 @@
# frozen_string_literal: false
require_relative 'test_optparse'
-module TestOptionParser::ReqArg
+module TestOptionParserReqArg
def setup
super
@opt.def_option "--with_underscore=VAL" do |x| @flag = x end
@opt.def_option "--with-hyphen=VAL" do |x| @flag = x end
+ @opt.def_option("--lambda=VAL", &->(x) {@flag = x})
end
class Def1 < TestOptionParser
- include ReqArg
+ include TestOptionParserReqArg
def setup
super
@opt.def_option("-xVAL") {|x| @flag = x}
@@ -19,21 +20,21 @@ module TestOptionParser::ReqArg
end
end
class Def2 < TestOptionParser
- include ReqArg
+ include TestOptionParserReqArg
def setup
super
@opt.def_option("-x", "--option=VAL") {|x| @flag = x}
end
end
class Def3 < TestOptionParser
- include ReqArg
+ include TestOptionParserReqArg
def setup
super
@opt.def_option("--option=VAL", "-x") {|x| @flag = x}
end
end
class Def4 < TestOptionParser
- include ReqArg
+ include TestOptionParserReqArg
def setup
super
@opt.def_option("-xVAL", "--option=VAL") {|x| @flag = x}
@@ -81,6 +82,11 @@ module TestOptionParser::ReqArg
assert_equal("foo4", @flag)
end
+ def test_lambda
+ assert_equal(%w"", no_error {@opt.parse!(%w"--lambda=lambda1")})
+ assert_equal("lambda1", @flag)
+ end
+
class TestOptionParser::WithPattern < TestOptionParser
def test_pattern
pat = num = nil
diff --git a/test/optparse/test_summary.rb b/test/optparse/test_summary.rb
index 67b05672d4..b5dcb3524e 100644
--- a/test/optparse/test_summary.rb
+++ b/test/optparse/test_summary.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: false
require_relative 'test_optparse'
-class TestOptionParser::SummaryTest < TestOptionParser
+class TestOptionParserSummaryTest < TestOptionParser
def test_short_clash
r = nil
o = OptionParser.new do |opts|
@@ -55,4 +55,27 @@ class TestOptionParser::SummaryTest < TestOptionParser
o.release = "rel"
assert_equal "foo 0.1 (rel)", o.ver
end
+
+ # https://github.com/ruby/optparse/issues/37
+ def test_very_long_without_short
+ o = OptionParser.new do |opts|
+ # This causes TypeError
+ opts.on('', '--long-long-option-param-without-short', "Error desc") { options[:long_long_option_param_without_short] = true }
+ opts.on('', '--long-option-param', "Long desc") { options[:long_option_param_without_short] = true }
+ opts.on('-a', '--long-long-option-param-with-short', "Normal description") { options[:long_long_option_param_with_short] = true }
+
+ opts.on('', '--long-long-option-param-without-short-but-with-desc', 'Description of the long long param') { options[:long_long_option_param_without_short_but_with_desc] = true }
+ end
+
+ s = o.summarize
+
+ assert_match(/^\s*--long-long-option-param-without-short$/, s[0])
+ assert_match(/^\s*Error desc$/, s[1])
+ assert_match(/^\s*--long-option-param\s+Long desc$/, s[2])
+ assert_match(/^\s*-a\s+Normal description$/, s[3])
+ assert_match(/^\s*--long-long-option-param-with-short$/, s[4])
+
+ assert_match(/^\s*--long-long-option-param-without-short-but-with-desc$/, s[5])
+ assert_match(/^\s*Description of the long long param$/, s[6])
+ end
end
diff --git a/test/optparse/test_zsh_completion.rb b/test/optparse/test_zsh_completion.rb
index c548d4af8a..76f0a73f32 100644
--- a/test/optparse/test_zsh_completion.rb
+++ b/test/optparse/test_zsh_completion.rb
@@ -2,9 +2,7 @@
require 'test/unit'
require 'optparse'
-class TestOptionParser < Test::Unit::TestCase
-end
-class TestOptionParser::ZshCompletion < Test::Unit::TestCase
+class TestOptionParserZshCompletion < Test::Unit::TestCase
def setup
@opt = OptionParser.new
@opt.define("-z", "zzz") {}
diff --git a/test/ostruct/test_ostruct.rb b/test/ostruct/test_ostruct.rb
index 1fd7d87811..19bb606145 100644
--- a/test/ostruct/test_ostruct.rb
+++ b/test/ostruct/test_ostruct.rb
@@ -280,6 +280,7 @@ class TC_OpenStruct < Test::Unit::TestCase
os = OpenStruct.new(method: :foo, hash: 42)
assert_equal(os.object_id, os.method!(:object_id).call)
assert_not_equal(42, os.hash!)
+ refute os.methods.include?(:"!~!")
end
def test_override_subclass
@@ -368,6 +369,18 @@ class TC_OpenStruct < Test::Unit::TestCase
RUBY
end if defined?(Ractor)
+ def test_access_methods_from_different_ractor
+ assert_ractor(<<~RUBY, require: 'ostruct')
+ os = OpenStruct.new
+ os.value = 100
+ r = Ractor.new(os) do |x|
+ v = x.value
+ Ractor.yield v
+ end
+ assert 100 == r.take
+ RUBY
+ end if defined?(Ractor)
+
def test_legacy_yaml
s = "--- !ruby/object:OpenStruct\ntable:\n :foo: 42\n"
o = YAML.safe_load(s, permitted_classes: [Symbol, OpenStruct])
@@ -393,4 +406,29 @@ class TC_OpenStruct < Test::Unit::TestCase
o2 = Marshal.load(Marshal.dump(o))
assert_equal o, o2
end
+
+ def test_class
+ os = OpenStruct.new(class: 'my-class', method: 'post')
+ assert_equal('my-class', os.class)
+ assert_equal(OpenStruct, os.class!)
+ end
+
+ has_performance_warnings = begin
+ Warning[:performance]
+ true
+ rescue NoMethodError, ArgumentError
+ false
+ end
+
+ if has_performance_warnings
+ def test_performance_warning
+ assert_in_out_err(
+ %w(-Ilib -rostruct -w -W:performance -e) + ['OpenStruct.new(a: 1)'],
+ "",
+ [],
+ ["-e:1: warning: OpenStruct use is discouraged for performance reasons"],
+ success: true,
+ )
+ end
+ end
end
diff --git a/test/pathname/test_pathname.rb b/test/pathname/test_pathname.rb
index 9e14668c99..a23dc21ae3 100644
--- a/test/pathname/test_pathname.rb
+++ b/test/pathname/test_pathname.rb
@@ -1043,6 +1043,25 @@ class TestPathname < Test::Unit::TestCase
}
end
+ def test_lutime
+ return if !has_symlink?
+ with_tmpchdir('rubytest-pathname') {|dir|
+ open("a", "w") {|f| f.write "abc" }
+ atime = File.atime("a")
+ mtime = File.mtime("a")
+ latime = Time.utc(2000)
+ lmtime = Time.utc(1999)
+ File.symlink("a", "l")
+ Pathname("l").utime(latime, lmtime)
+ s = File.lstat("a")
+ ls = File.lstat("l")
+ assert_equal(atime, s.atime)
+ assert_equal(mtime, s.mtime)
+ assert_equal(latime, ls.atime)
+ assert_equal(lmtime, ls.mtime)
+ }
+ end
+
def test_basename
assert_equal(Pathname("basename"), Pathname("dirname/basename").basename)
assert_equal(Pathname("bar"), Pathname("foo/bar.x").basename(".x"))
@@ -1355,6 +1374,18 @@ class TestPathname < Test::Unit::TestCase
}
end
+ def test_each_entry_enumerator
+ with_tmpchdir('rubytest-pathname') {|dir|
+ open("a", "w") {}
+ open("b", "w") {}
+ a = []
+ e = Pathname(".").each_entry
+ assert_kind_of(Enumerator, e)
+ e.each {|v| a << v }
+ assert_equal([Pathname("."), Pathname(".."), Pathname("a"), Pathname("b")], a.sort)
+ }
+ end
+
def test_mkdir
with_tmpchdir('rubytest-pathname') {|dir|
Pathname("d").mkdir
diff --git a/test/prism/api/command_line_test.rb b/test/prism/api/command_line_test.rb
new file mode 100644
index 0000000000..a8c4355152
--- /dev/null
+++ b/test/prism/api/command_line_test.rb
@@ -0,0 +1,111 @@
+# frozen_string_literal: true
+
+require_relative "../test_helper"
+
+module Prism
+ class CommandLineTest < TestCase
+ def test_command_line_p
+ program = Prism.parse("1", command_line: "p").value
+ statements = program.statements.body
+
+ assert_equal 2, statements.length
+ assert_kind_of CallNode, statements.last
+ assert_equal :print, statements.last.name
+ end
+
+ def test_command_line_n
+ program = Prism.parse("1", command_line: "n").value
+ statements = program.statements.body
+
+ assert_equal 1, statements.length
+ assert_kind_of WhileNode, statements.first
+
+ predicate = statements.first.predicate
+ assert_kind_of CallNode, predicate
+ assert_equal :gets, predicate.name
+
+ arguments = predicate.arguments.arguments
+ assert_equal 1, arguments.length
+ assert_equal :$/, arguments.first.name
+ end
+
+ def test_command_line_a
+ program = Prism.parse("1", command_line: "na").value
+ statements = program.statements.body
+
+ assert_equal 1, statements.length
+ assert_kind_of WhileNode, statements.first
+
+ statement = statements.first.statements.body.first
+ assert_kind_of GlobalVariableWriteNode, statement
+ assert_equal :$F, statement.name
+ end
+
+ def test_command_line_l
+ program = Prism.parse("1", command_line: "nl").value
+ statements = program.statements.body
+
+ assert_equal 1, statements.length
+ assert_kind_of WhileNode, statements.first
+
+ predicate = statements.first.predicate
+ assert_kind_of CallNode, predicate
+ assert_equal :gets, predicate.name
+
+ arguments = predicate.arguments.arguments
+ assert_equal 2, arguments.length
+ assert_equal :$/, arguments.first.name
+ assert_equal "chomp", arguments.last.elements.first.key.unescaped
+ end
+
+ def test_command_line_e
+ result = Prism.parse("1 if 2..3")
+ assert_equal 2, result.warnings.length
+
+ result = Prism.parse("1 if 2..3", command_line: "e")
+ assert_equal 0, result.warnings.length
+ end
+
+ def test_command_line_x_implicit
+ result = Prism.parse_statement(<<~RUBY, main_script: true)
+ #!/bin/bash
+ exit 1
+
+ #!/usr/bin/env ruby
+ 1
+ RUBY
+
+ assert_kind_of IntegerNode, result
+ end
+
+ def test_command_line_x_explicit
+ result = Prism.parse_statement(<<~RUBY, command_line: "x")
+ exit 1
+
+ #!/usr/bin/env ruby
+ 1
+ RUBY
+
+ assert_kind_of IntegerNode, result
+ end
+
+ def test_command_line_x_implicit_fail
+ result = Prism.parse(<<~RUBY, main_script: true)
+ #!/bin/bash
+ exit 1
+ RUBY
+
+ assert_equal 1, result.errors.length
+ assert_equal :load, result.errors.first.level
+ end
+
+ def test_command_line_x_explicit_fail
+ result = Prism.parse(<<~RUBY, command_line: "x")
+ exit 1
+ RUBY
+
+ assert_equal 1, result.errors.length
+ assert_equal :load, result.errors.first.level
+ end
+ end
+end
diff --git a/test/prism/api/dump_test.rb b/test/prism/api/dump_test.rb
new file mode 100644
index 0000000000..941088e159
--- /dev/null
+++ b/test/prism/api/dump_test.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+return if ENV["PRISM_BUILD_MINIMAL"]
+
+require_relative "../test_helper"
+
+module Prism
+ class DumpTest < TestCase
+ Fixture.each do |fixture|
+ define_method(fixture.test_name) { assert_dump(fixture) }
+ end
+
+ def test_dump
+ filepath = __FILE__
+ source = File.read(filepath, binmode: true, external_encoding: Encoding::UTF_8)
+
+ assert_equal Prism.lex(source, filepath: filepath).value, Prism.lex_file(filepath).value
+ assert_equal Prism.dump(source, filepath: filepath), Prism.dump_file(filepath)
+
+ serialized = Prism.dump(source, filepath: filepath)
+ ast1 = Prism.load(source, serialized).value
+ ast2 = Prism.parse(source, filepath: filepath).value
+ ast3 = Prism.parse_file(filepath).value
+
+ assert_equal_nodes ast1, ast2
+ assert_equal_nodes ast2, ast3
+ end
+
+ def test_dump_file
+ assert_nothing_raised do
+ Prism.dump_file(__FILE__)
+ end
+
+ error = assert_raise Errno::ENOENT do
+ Prism.dump_file("idontexist.rb")
+ end
+
+ assert_equal "No such file or directory - idontexist.rb", error.message
+
+ assert_raise TypeError do
+ Prism.dump_file(nil)
+ end
+ end
+
+ private
+
+ def assert_dump(fixture)
+ source = fixture.read
+
+ result = Prism.parse(source, filepath: fixture.path)
+ dumped = Prism.dump(source, filepath: fixture.path)
+
+ assert_equal_nodes(result.value, Prism.load(source, dumped).value)
+ end
+ end
+end
diff --git a/test/prism/api/lex_test.rb b/test/prism/api/lex_test.rb
new file mode 100644
index 0000000000..0b675b215f
--- /dev/null
+++ b/test/prism/api/lex_test.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+require_relative "../test_helper"
+
+module Prism
+ class LexTest < TestCase
+ def test_lex_result
+ result = Prism.lex("")
+ assert_kind_of LexResult, result
+
+ result = Prism.lex_file(__FILE__)
+ assert_kind_of LexResult, result
+ end
+
+ def test_parse_lex_result
+ result = Prism.parse_lex("")
+ assert_kind_of ParseLexResult, result
+
+ result = Prism.parse_lex_file(__FILE__)
+ assert_kind_of ParseLexResult, result
+ end
+ end
+end
diff --git a/test/prism/api/parse_comments_test.rb b/test/prism/api/parse_comments_test.rb
new file mode 100644
index 0000000000..4dbcca1827
--- /dev/null
+++ b/test/prism/api/parse_comments_test.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+require_relative "../test_helper"
+
+module Prism
+ class ParseCommentsTest < TestCase
+ def test_parse_comments
+ comments = Prism.parse_comments("# foo")
+
+ assert_kind_of Array, comments
+ assert_equal 1, comments.length
+ end
+
+ def test_parse_file_comments
+ comments = Prism.parse_file_comments(__FILE__)
+
+ assert_kind_of Array, comments
+ assert_equal 1, comments.length
+ end
+
+ def test_parse_file_comments_error
+ error = assert_raise Errno::ENOENT do
+ Prism.parse_file_comments("idontexist.rb")
+ end
+
+ assert_equal "No such file or directory - idontexist.rb", error.message
+
+ assert_raise TypeError do
+ Prism.parse_file_comments(nil)
+ end
+ end
+ end
+end
diff --git a/test/prism/api/parse_stream_test.rb b/test/prism/api/parse_stream_test.rb
new file mode 100644
index 0000000000..1c068c617c
--- /dev/null
+++ b/test/prism/api/parse_stream_test.rb
@@ -0,0 +1,81 @@
+# frozen_string_literal: true
+
+require_relative "../test_helper"
+
+module Prism
+ class ParseStreamTest < TestCase
+ def test_single_line
+ io = StringIO.new("1 + 2")
+ result = Prism.parse_stream(io)
+
+ assert result.success?
+ assert_kind_of Prism::CallNode, result.statement
+ end
+
+ def test_multi_line
+ io = StringIO.new("1 + 2\n3 + 4")
+ result = Prism.parse_stream(io)
+
+ assert result.success?
+ assert_kind_of Prism::CallNode, result.statement
+ assert_kind_of Prism::CallNode, result.statement
+ end
+
+ def test_multi_read
+ io = StringIO.new("a" * 4096 * 4)
+ result = Prism.parse_stream(io)
+
+ assert result.success?
+ assert_kind_of Prism::CallNode, result.statement
+ end
+
+ def test___END__
+ io = StringIO.new("1 + 2\n3 + 4\n__END__\n5 + 6")
+ result = Prism.parse_stream(io)
+
+ assert result.success?
+ assert_equal 2, result.value.statements.body.length
+ assert_equal "5 + 6", io.read
+ end
+
+ def test_false___END___in_string
+ io = StringIO.new("1 + 2\n3 + 4\n\"\n__END__\n\"\n5 + 6")
+ result = Prism.parse_stream(io)
+
+ assert result.success?
+ assert_equal 4, result.value.statements.body.length
+ end
+
+ def test_false___END___in_regexp
+ io = StringIO.new("1 + 2\n3 + 4\n/\n__END__\n/\n5 + 6")
+ result = Prism.parse_stream(io)
+
+ assert result.success?
+ assert_equal 4, result.value.statements.body.length
+ end
+
+ def test_false___END___in_list
+ io = StringIO.new("1 + 2\n3 + 4\n%w[\n__END__\n]\n5 + 6")
+ result = Prism.parse_stream(io)
+
+ assert result.success?
+ assert_equal 4, result.value.statements.body.length
+ end
+
+ def test_false___END___in_heredoc
+ io = StringIO.new("1 + 2\n3 + 4\n<<-EOF\n__END__\nEOF\n5 + 6")
+ result = Prism.parse_stream(io)
+
+ assert result.success?
+ assert_equal 4, result.value.statements.body.length
+ end
+
+ def test_nul_bytes
+ io = StringIO.new("1 # \0\0\0 \n2 # \0\0\0\n3")
+ result = Prism.parse_stream(io)
+
+ assert result.success?
+ assert_equal 3, result.value.statements.body.length
+ end
+ end
+end
diff --git a/test/prism/api/parse_success_test.rb b/test/prism/api/parse_success_test.rb
new file mode 100644
index 0000000000..2caaa5136e
--- /dev/null
+++ b/test/prism/api/parse_success_test.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+require_relative "../test_helper"
+
+module Prism
+ class ParseSuccessTest < TestCase
+ def test_parse_success?
+ assert Prism.parse_success?("1")
+ refute Prism.parse_success?("<>")
+ end
+
+ def test_parse_file_success?
+ assert Prism.parse_file_success?(__FILE__)
+ end
+ end
+end
diff --git a/test/prism/api/parse_test.rb b/test/prism/api/parse_test.rb
new file mode 100644
index 0000000000..ac8f8c30dc
--- /dev/null
+++ b/test/prism/api/parse_test.rb
@@ -0,0 +1,117 @@
+# frozen_string_literal: true
+
+require_relative "../test_helper"
+
+module Prism
+ class ParseTest < TestCase
+ def test_parse_result
+ result = Prism.parse("")
+ assert_kind_of ParseResult, result
+
+ result = Prism.parse_file(__FILE__)
+ assert_kind_of ParseResult, result
+ end
+
+ def test_parse_empty_string
+ result = Prism.parse("")
+ assert_equal [], result.value.statements.body
+ end
+
+ def test_parse_takes_file_path
+ filepath = "filepath.rb"
+ result = Prism.parse("def foo; __FILE__; end", filepath: filepath)
+
+ assert_equal filepath, find_source_file_node(result.value).filepath
+ end
+
+ def test_parse_takes_line
+ line = 4
+ result = Prism.parse("def foo\n __FILE__\nend", line: line)
+
+ assert_equal line, result.value.location.start_line
+ assert_equal line + 1, find_source_file_node(result.value).location.start_line
+
+ result = Prism.parse_lex("def foo\n __FILE__\nend", line: line)
+ assert_equal line, result.value.first.location.start_line
+ end
+
+ def test_parse_takes_negative_lines
+ line = -2
+ result = Prism.parse("def foo\n __FILE__\nend", line: line)
+
+ assert_equal line, result.value.location.start_line
+ assert_equal line + 1, find_source_file_node(result.value).location.start_line
+
+ result = Prism.parse_lex("def foo\n __FILE__\nend", line: line)
+ assert_equal line, result.value.first.location.start_line
+ end
+
+ def test_parse_file
+ node = Prism.parse_file(__FILE__).value
+ assert_kind_of ProgramNode, node
+
+ error = assert_raise Errno::ENOENT do
+ Prism.parse_file("idontexist.rb")
+ end
+
+ assert_equal "No such file or directory - idontexist.rb", error.message
+
+ assert_raise TypeError do
+ Prism.parse_file(nil)
+ end
+ end
+
+ def test_parse_tempfile
+ Tempfile.create(["test_parse_tempfile", ".rb"]) do |t|
+ t.puts ["begin\n", " end\n"]
+ t.flush
+ Prism.parse_file(t.path)
+ end
+ end
+
+ if RUBY_ENGINE != "truffleruby"
+ def test_parse_nonascii
+ Dir.mktmpdir do |dir|
+ path = File.join(dir, "\u{3042 3044 3046 3048 304a}.rb".encode(Encoding::Windows_31J))
+ File.write(path, "ok")
+ Prism.parse_file(path)
+ end
+ end
+ end
+
+ def test_parse_directory
+ error = nil
+
+ begin
+ Prism.parse_file(__dir__)
+ rescue SystemCallError => error
+ end
+
+ assert_kind_of Errno::EISDIR, error
+ end
+
+ def test_partial_script
+ assert Prism.parse_failure?("break")
+ assert Prism.parse_success?("break", partial_script: true)
+
+ assert Prism.parse_failure?("next")
+ assert Prism.parse_success?("next", partial_script: true)
+
+ assert Prism.parse_failure?("redo")
+ assert Prism.parse_success?("redo", partial_script: true)
+
+ assert Prism.parse_failure?("yield")
+ assert Prism.parse_success?("yield", partial_script: true)
+ end
+
+ private
+
+ def find_source_file_node(program)
+ queue = [program]
+ while (node = queue.shift)
+ return node if node.is_a?(SourceFileNode)
+ queue.concat(node.compact_child_nodes)
+ end
+ end
+ end
+end
diff --git a/test/prism/bom_test.rb b/test/prism/bom_test.rb
new file mode 100644
index 0000000000..890bc4b36c
--- /dev/null
+++ b/test/prism/bom_test.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+# Don't bother checking this on these engines, this is such a specific Ripper
+# test.
+return if RUBY_ENGINE != "ruby"
+
+require_relative "test_helper"
+
+module Prism
+ class BOMTest < TestCase
+ def test_ident
+ assert_bom("foo")
+ end
+
+ def test_back_reference
+ assert_bom("$+")
+ end
+
+ def test_instance_variable
+ assert_bom("@foo")
+ end
+
+ def test_class_variable
+ assert_bom("@@foo")
+ end
+
+ def test_global_variable
+ assert_bom("$foo")
+ end
+
+ def test_numbered_reference
+ assert_bom("$1")
+ end
+
+ def test_percents
+ assert_bom("%i[]")
+ assert_bom("%r[]")
+ assert_bom("%s[]")
+ assert_bom("%q{}")
+ assert_bom("%w[]")
+ assert_bom("%x[]")
+ assert_bom("%I[]")
+ assert_bom("%W[]")
+ assert_bom("%Q{}")
+ end
+
+ def test_string
+ assert_bom("\"\"")
+ assert_bom("''")
+ end
+
+ private
+
+ def assert_bom(source)
+ bommed = "\xEF\xBB\xBF#{source}"
+ assert_equal Prism.lex_ripper(bommed), Prism.lex_compat(bommed).value
+ end
+ end
+end
diff --git a/test/prism/encoding/encodings_test.rb b/test/prism/encoding/encodings_test.rb
new file mode 100644
index 0000000000..4ad2b465cc
--- /dev/null
+++ b/test/prism/encoding/encodings_test.rb
@@ -0,0 +1,101 @@
+# frozen_string_literal: true
+
+return if RUBY_ENGINE != "ruby"
+
+require_relative "../test_helper"
+
+module Prism
+ class EncodingsTest < TestCase
+ class ConstantContext < BasicObject
+ def self.const_missing(const)
+ const
+ end
+ end
+
+ class IdentifierContext < BasicObject
+ def method_missing(name, *)
+ name
+ end
+ end
+
+ # These test that we're correctly parsing codepoints for each alias of each
+ # encoding that prism supports.
+ each_encoding do |encoding, range|
+ (encoding.names - %w[external internal filesystem locale]).each do |name|
+ define_method(:"test_encoding_#{name}") do
+ assert_encoding(encoding, name, range)
+ end
+ end
+ end
+
+ private
+
+ def assert_encoding_constant(name, character)
+ source = "# encoding: #{name}\n#{character}"
+ expected = ConstantContext.new.instance_eval(source)
+
+ result = Prism.parse(source)
+ assert result.success?
+
+ actual = result.value.statements.body.last
+ assert_kind_of ConstantReadNode, actual
+ assert_equal expected, actual.name
+ end
+
+ def assert_encoding_identifier(name, character)
+ source = "# encoding: #{name}\n#{character}"
+ expected = IdentifierContext.new.instance_eval(source)
+
+ result = Prism.parse(source)
+ assert result.success?
+
+ actual = result.value.statements.body.last
+ assert_kind_of CallNode, actual
+ assert_equal expected, actual.name
+ end
+
+ # Check that we can properly parse every codepoint in the given encoding.
+ def assert_encoding(encoding, name, range)
+ # I'm not entirely sure, but I believe these codepoints are incorrect in
+ # their parsing in CRuby. They all report as matching `[[:lower:]]` but
+ # then they are parsed as constants. This is because CRuby determines if
+ # an identifier is a constant or not by case folding it down to lowercase
+ # and checking if there is a difference. And even though they report
+ # themselves as lowercase, their case fold is different. I have reported
+ # this bug upstream.
+ case encoding
+ when Encoding::UTF_8, Encoding::UTF_8_MAC, Encoding::UTF8_DoCoMo, Encoding::UTF8_KDDI, Encoding::UTF8_SoftBank, Encoding::CESU_8
+ range = range.to_a - [
+ 0x01c5, 0x01c8, 0x01cb, 0x01f2, 0x1f88, 0x1f89, 0x1f8a, 0x1f8b,
+ 0x1f8c, 0x1f8d, 0x1f8e, 0x1f8f, 0x1f98, 0x1f99, 0x1f9a, 0x1f9b,
+ 0x1f9c, 0x1f9d, 0x1f9e, 0x1f9f, 0x1fa8, 0x1fa9, 0x1faa, 0x1fab,
+ 0x1fac, 0x1fad, 0x1fae, 0x1faf, 0x1fbc, 0x1fcc, 0x1ffc,
+ ]
+ when Encoding::Windows_1253
+ range = range.to_a - [0xb5]
+ end
+
+ range.each do |codepoint|
+ character = codepoint.chr(encoding)
+
+ if character.match?(/[[:alpha:]]/)
+ if character.match?(/[[:upper:]]/)
+ assert_encoding_constant(name, character)
+ else
+ assert_encoding_identifier(name, character)
+ end
+ elsif character.match?(/[[:alnum:]]/)
+ assert_encoding_identifier(name, "_#{character}")
+ else
+ next if ["/", "{"].include?(character)
+
+ source = "# encoding: #{name}\n/(?##{character})/\n"
+ assert Prism.parse_success?(source), "Expected #{source.inspect} to parse successfully."
+ end
+ rescue RangeError
+ source = "# encoding: #{name}\n\\x#{codepoint.to_s(16)}"
+ assert Prism.parse_failure?(source)
+ end
+ end
+ end
+end
diff --git a/test/prism/encoding/regular_expression_encoding_test.rb b/test/prism/encoding/regular_expression_encoding_test.rb
new file mode 100644
index 0000000000..5d062fe59a
--- /dev/null
+++ b/test/prism/encoding/regular_expression_encoding_test.rb
@@ -0,0 +1,131 @@
+# frozen_string_literal: true
+
+return unless defined?(RubyVM::InstructionSequence)
+return if RubyVM::InstructionSequence.compile("").to_a[4][:parser] == :prism
+
+require_relative "../test_helper"
+
+module Prism
+ class RegularExpressionEncodingTest < TestCase
+ each_encoding do |encoding, _|
+ define_method(:"test_regular_expression_encoding_flags_#{encoding.name}") do
+ assert_regular_expression_encoding_flags(encoding, ["/a/", "/Ä…/", "//"])
+ end
+
+ escapes = ["\\x00", "\\x7F", "\\x80", "\\xFF", "\\u{00}", "\\u{7F}", "\\u{80}", "\\M-\\C-?"]
+ escapes = escapes.concat(escapes.product(escapes).map(&:join))
+
+ define_method(:"test_regular_expression_escape_encoding_flags_#{encoding.name}") do
+ assert_regular_expression_encoding_flags(encoding, escapes.map { |e| "/#{e}/" })
+ end
+
+ ["n", "u", "e", "s"].each do |modifier|
+ define_method(:"test_regular_expression_encoding_modifiers_/#{modifier}_#{encoding.name}") do
+ regexp_sources = ["abc", "garçon", "\\x80", "gar\\xC3\\xA7on", "gar\\u{E7}on", "abc\\u{FFFFFF}", "\\x80\\u{80}" ]
+
+ assert_regular_expression_encoding_flags(
+ encoding,
+ regexp_sources.product(["n", "u", "e", "s"]).map { |r, modifier| "/#{r}/#{modifier}" }
+ )
+ end
+ end
+ end
+
+ private
+
+ def assert_regular_expression_encoding_flags(encoding, regexps)
+ regexps.each do |regexp|
+ regexp_modifier_used = regexp.end_with?("/u") || regexp.end_with?("/e") || regexp.end_with?("/s") || regexp.end_with?("/n")
+ source = "# encoding: #{encoding.name}\n#{regexp}"
+
+ encoding_errors = ["invalid multibyte char", "escaped non ASCII character in UTF-8 regexp", "differs from source encoding"]
+ skipped_errors = ["invalid multibyte escape", "incompatible character encoding", "UTF-8 character in non UTF-8 regexp", "invalid Unicode range", "invalid Unicode list"]
+
+ # TODO (nirvdrum 21-Feb-2024): Prism currently does not handle Regexp validation unless modifiers are used. So, skip processing those errors for now: https://github.com/ruby/prism/issues/2104
+ unless regexp_modifier_used
+ skipped_errors += encoding_errors
+ encoding_errors.clear
+ end
+
+ expected =
+ begin
+ eval(source).encoding
+ rescue SyntaxError => error
+ if encoding_errors.find { |e| error.message.include?(e) }
+ error.message.split("\n").map { |m| m[/: (.+?)$/, 1] }
+ elsif skipped_errors.find { |e| error.message.include?(e) }
+ next
+ else
+ raise
+ end
+ end
+
+ actual =
+ Prism.parse(source).then do |result|
+ if result.success?
+ regexp = result.statement
+
+ actual_encoding = if regexp.forced_utf8_encoding?
+ Encoding::UTF_8
+ elsif regexp.forced_binary_encoding?
+ Encoding::ASCII_8BIT
+ elsif regexp.forced_us_ascii_encoding?
+ Encoding::US_ASCII
+ elsif regexp.ascii_8bit?
+ Encoding::ASCII_8BIT
+ elsif regexp.utf_8?
+ Encoding::UTF_8
+ elsif regexp.euc_jp?
+ Encoding::EUC_JP
+ elsif regexp.windows_31j?
+ Encoding::Windows_31J
+ else
+ encoding
+ end
+
+ if regexp.utf_8? && actual_encoding != Encoding::UTF_8
+ raise "expected regexp encoding to be UTF-8 due to '/u' modifier, but got #{actual_encoding.name}"
+ elsif regexp.ascii_8bit? && (actual_encoding != Encoding::ASCII_8BIT && actual_encoding != Encoding::US_ASCII)
+ raise "expected regexp encoding to be ASCII-8BIT or US-ASCII due to '/n' modifier, but got #{actual_encoding.name}"
+ elsif regexp.euc_jp? && actual_encoding != Encoding::EUC_JP
+ raise "expected regexp encoding to be EUC-JP due to '/e' modifier, but got #{actual_encoding.name}"
+ elsif regexp.windows_31j? && actual_encoding != Encoding::Windows_31J
+ raise "expected regexp encoding to be Windows-31J due to '/s' modifier, but got #{actual_encoding.name}"
+ end
+
+ if regexp.utf_8? && regexp.forced_utf8_encoding?
+ raise "the forced_utf8 flag should not be set when the UTF-8 modifier (/u) is used"
+ elsif regexp.ascii_8bit? && regexp.forced_binary_encoding?
+ raise "the forced_ascii_8bit flag should not be set when the UTF-8 modifier (/u) is used"
+ end
+
+ actual_encoding
+ else
+ errors = result.errors.map(&:message)
+
+ if errors.last&.include?("UTF-8 mixed within")
+ nil
+ else
+ errors
+ end
+ end
+ end
+
+ # TODO (nirvdrum 22-Feb-2024): Remove this workaround once Prism better maps CRuby's error messages.
+ # This class of error message is tricky. The part not being compared is a representation of the regexp.
+ # Depending on the source encoding and any encoding modifiers being used, CRuby alters how the regexp is represented.
+ # Sometimes it's an MBC string. Other times it uses hexadecimal character escapes. And in other cases it uses
+ # the long-form Unicode escape sequences. This short-circuit checks that the error message is mostly correct.
+ if expected.is_a?(Array) && actual.is_a?(Array)
+ if expected.last.start_with?("/.../n has a non escaped non ASCII character in non ASCII-8BIT script:") &&
+ actual.last.start_with?("/.../n has a non escaped non ASCII character in non ASCII-8BIT script:")
+ expected.last.clear
+ actual.last.clear
+ end
+ end
+
+ assert_equal expected, actual
+ end
+ end
+ end
+end
diff --git a/test/prism/encoding/string_encoding_test.rb b/test/prism/encoding/string_encoding_test.rb
new file mode 100644
index 0000000000..6f9d86df3b
--- /dev/null
+++ b/test/prism/encoding/string_encoding_test.rb
@@ -0,0 +1,136 @@
+# frozen_string_literal: true
+
+require_relative "../test_helper"
+
+module Prism
+ class StringEncodingTest < TestCase
+ each_encoding do |encoding, _|
+ define_method(:"test_#{encoding.name}") do
+ assert_encoding(encoding)
+ end
+ end
+
+ def test_coding
+ actual = Prism.parse_statement("# coding: utf-8\n'string'").unescaped.encoding
+ assert_equal Encoding::UTF_8, actual
+ end
+
+ def test_coding_with_whitespace
+ actual = Prism.parse_statement("# coding \t \r \v : \t \v \r ascii-8bit \n'string'").unescaped.encoding
+ assert_equal Encoding::ASCII_8BIT, actual
+ end
+
+ def test_emacs_style
+ actual = Prism.parse_statement("# -*- coding: utf-8 -*-\n'string'").unescaped.encoding
+ assert_equal Encoding::UTF_8, actual
+ end
+
+ def test_utf_8_unix
+ actual = Prism.parse_statement("# coding: utf-8-unix\n'string'").unescaped.encoding
+ assert_equal Encoding::UTF_8, actual
+ end
+
+ def test_utf_8_dos
+ actual = Prism.parse_statement("# coding: utf-8-dos\n'string'").unescaped.encoding
+ assert_equal Encoding::UTF_8, actual
+ end
+
+ def test_utf_8_mac
+ actual = Prism.parse_statement("# coding: utf-8-mac\n'string'").unescaped.encoding
+ assert_equal Encoding::UTF_8, actual
+ end
+
+ def test_utf_8_star
+ actual = Prism.parse_statement("# coding: utf-8-*\n'string'").unescaped.encoding
+ assert_equal Encoding::UTF_8, actual
+ end
+
+ def test_first_lexed_token
+ encoding = Prism.lex("# encoding: ascii-8bit").value[0][0].value.encoding
+ assert_equal Encoding::ASCII_8BIT, encoding
+ end
+
+ if !ENV["PRISM_BUILD_MINIMAL"]
+ # This test may be a little confusing. Basically when we use our strpbrk,
+ # it takes into account the encoding of the file.
+ def test_strpbrk_multibyte
+ result = Prism.parse(<<~RUBY)
+ # encoding: Shift_JIS
+ %w[\x81\x5c]
+ RUBY
+
+ assert(result.errors.empty?)
+ assert_equal(
+ (+"\x81\x5c").force_encoding(Encoding::Shift_JIS),
+ result.statement.elements.first.unescaped
+ )
+ end
+
+ def test_slice_encoding
+ slice = Prism.parse("# encoding: Shift_JIS\nã‚¢").value.slice
+ assert_equal (+"ã‚¢").force_encoding(Encoding::SHIFT_JIS), slice
+ assert_equal Encoding::SHIFT_JIS, slice.encoding
+ end
+
+ def test_multibyte_escapes
+ [
+ ["'", "'"],
+ ["\"", "\""],
+ ["`", "`"],
+ ["/", "/"],
+ ["<<'HERE'\n", "\nHERE"],
+ ["<<-HERE\n", "\nHERE"]
+ ].each do |opening, closing|
+ assert Prism.parse_success?("# encoding: shift_jis\n'\\\x82\xA0'\n")
+ end
+ end
+ end
+
+ private
+
+ def assert_encoding(encoding)
+ escapes = ["\\x00", "\\x7F", "\\x80", "\\xFF", "\\u{00}", "\\u{7F}", "\\u{80}", "\\M-\\C-?"]
+ escapes = escapes.concat(escapes.product(escapes).map(&:join))
+
+ escapes.each do |escaped|
+ source = "# encoding: #{encoding.name}\n\"#{escaped}\""
+
+ expected =
+ begin
+ eval(source).encoding
+ rescue SyntaxError => error
+ if error.message.include?("UTF-8 mixed within")
+ error.message[/UTF-8 mixed within .+? source/]
+ else
+ raise
+ end
+ end
+
+ actual =
+ Prism.parse(source).then do |result|
+ if result.success?
+ string = result.statement
+
+ if string.forced_utf8_encoding?
+ Encoding::UTF_8
+ elsif string.forced_binary_encoding?
+ Encoding::ASCII_8BIT
+ else
+ encoding
+ end
+ else
+ error = result.errors.first
+
+ if error.message.include?("mixed")
+ error.message
+ else
+ raise error.message
+ end
+ end
+ end
+
+ assert_equal expected, actual
+ end
+ end
+ end
+end
diff --git a/test/prism/encoding/symbol_encoding_test.rb b/test/prism/encoding/symbol_encoding_test.rb
new file mode 100644
index 0000000000..20c998a58b
--- /dev/null
+++ b/test/prism/encoding/symbol_encoding_test.rb
@@ -0,0 +1,108 @@
+# frozen_string_literal: true
+
+return if RUBY_ENGINE != "ruby"
+
+require_relative "../test_helper"
+
+module Prism
+ class SymbolEncodingTest < TestCase
+ each_encoding do |encoding, _|
+ define_method(:"test_symbols_#{encoding.name}") do
+ assert_symbols(encoding)
+ end
+
+ define_method(:"test_escapes_#{encoding.name}") do
+ assert_escapes(encoding)
+ end
+ end
+
+ private
+
+ def expected_encoding(source)
+ eval(source).encoding
+ end
+
+ def actual_encoding(source, encoding)
+ result = Prism.parse(source)
+
+ if result.success?
+ symbol = result.statement
+
+ if symbol.forced_utf8_encoding?
+ Encoding::UTF_8
+ elsif symbol.forced_binary_encoding?
+ Encoding::ASCII_8BIT
+ elsif symbol.forced_us_ascii_encoding?
+ Encoding::US_ASCII
+ else
+ encoding
+ end
+ else
+ raise SyntaxError.new(result.errors.map(&:message).join("\n"))
+ end
+ end
+
+ def assert_symbols(encoding)
+ [:a, :Ä…, :+].each do |symbol|
+ source = "# encoding: #{encoding.name}\n#{symbol.inspect}"
+
+ expected =
+ begin
+ expected_encoding(source)
+ rescue SyntaxError => error
+ if error.message.include?("invalid multibyte")
+ "invalid multibyte"
+ else
+ raise
+ end
+ end
+
+ actual =
+ begin
+ actual_encoding(source, encoding)
+ rescue SyntaxError => error
+ if error.message.include?("invalid multibyte")
+ "invalid multibyte"
+ else
+ raise
+ end
+ end
+
+ assert_equal expected, actual
+ end
+ end
+
+ def assert_escapes(encoding)
+ escapes = ["\\x00", "\\x7F", "\\x80", "\\xFF", "\\u{00}", "\\u{7F}", "\\u{80}", "\\M-\\C-?"]
+ escapes = escapes.concat(escapes.product(escapes).map(&:join))
+
+ escapes.each do |escaped|
+ source = "# encoding: #{encoding.name}\n:\"#{escaped}\""
+
+ expected =
+ begin
+ expected_encoding(source)
+ rescue SyntaxError => error
+ if error.message.include?("UTF-8 mixed within")
+ error.message[/UTF-8 mixed within .+? source/]
+ else
+ raise
+ end
+ end
+
+ actual =
+ begin
+ actual_encoding(source, encoding)
+ rescue SyntaxError => error
+ if error.message.include?("mixed")
+ error.message.split("\n", 2).first
+ else
+ raise
+ end
+ end
+
+ assert_equal expected, actual
+ end
+ end
+ end
+end
diff --git a/test/prism/errors/1_2_3.txt b/test/prism/errors/1_2_3.txt
new file mode 100644
index 0000000000..345452911f
--- /dev/null
+++ b/test/prism/errors/1_2_3.txt
@@ -0,0 +1,11 @@
+(1, 2, 3)
+ ^ unexpected ',', expecting end-of-input
+ ^ unexpected ',', ignoring it
+ ^ expected a matching `)`
+ ^ unexpected ',', expecting end-of-input
+ ^ unexpected ',', ignoring it
+ ^ unexpected ',', expecting end-of-input
+ ^ unexpected ',', ignoring it
+ ^ unexpected ')', expecting end-of-input
+ ^ unexpected ')', ignoring it
+
diff --git a/test/prism/errors/aliasing_global_variable_with_global_number_variable.txt b/test/prism/errors/aliasing_global_variable_with_global_number_variable.txt
new file mode 100644
index 0000000000..2f40a6a328
--- /dev/null
+++ b/test/prism/errors/aliasing_global_variable_with_global_number_variable.txt
@@ -0,0 +1,3 @@
+alias $a $1
+ ^~ invalid argument being passed to `alias`; can't make alias for the number variables
+
diff --git a/test/prism/errors/aliasing_global_variable_with_non_global_variable.txt b/test/prism/errors/aliasing_global_variable_with_non_global_variable.txt
new file mode 100644
index 0000000000..b6f013bab5
--- /dev/null
+++ b/test/prism/errors/aliasing_global_variable_with_non_global_variable.txt
@@ -0,0 +1,3 @@
+alias $a b
+ ^ invalid argument being passed to `alias`; expected a bare word, symbol, constant, or global variable
+
diff --git a/test/prism/errors/aliasing_non_global_variable_with_global_variable.txt b/test/prism/errors/aliasing_non_global_variable_with_global_variable.txt
new file mode 100644
index 0000000000..8863f342f0
--- /dev/null
+++ b/test/prism/errors/aliasing_non_global_variable_with_global_variable.txt
@@ -0,0 +1,3 @@
+alias a $b
+ ^~ invalid argument being passed to `alias`; expected a bare word, symbol, constant, or global variable
+
diff --git a/test/prism/errors/alnum_delimiters.txt b/test/prism/errors/alnum_delimiters.txt
new file mode 100644
index 0000000000..c9ed06ae51
--- /dev/null
+++ b/test/prism/errors/alnum_delimiters.txt
@@ -0,0 +1,3 @@
+%qXfooX
+^ unknown type of %string
+
diff --git a/test/prism/errors/alnum_delimiters_2.txt b/test/prism/errors/alnum_delimiters_2.txt
new file mode 100644
index 0000000000..3f78b434d6
--- /dev/null
+++ b/test/prism/errors/alnum_delimiters_2.txt
@@ -0,0 +1,3 @@
+%QXfooX
+^ unknown type of %string
+
diff --git a/test/prism/errors/alnum_delimiters_3.txt b/test/prism/errors/alnum_delimiters_3.txt
new file mode 100644
index 0000000000..55ef8d29a5
--- /dev/null
+++ b/test/prism/errors/alnum_delimiters_3.txt
@@ -0,0 +1,3 @@
+%wXfooX
+^ unknown type of %string
+
diff --git a/test/prism/errors/alnum_delimiters_4.txt b/test/prism/errors/alnum_delimiters_4.txt
new file mode 100644
index 0000000000..603b54debd
--- /dev/null
+++ b/test/prism/errors/alnum_delimiters_4.txt
@@ -0,0 +1,3 @@
+%WxfooX
+^ unknown type of %string
+
diff --git a/test/prism/errors/alnum_delimiters_5.txt b/test/prism/errors/alnum_delimiters_5.txt
new file mode 100644
index 0000000000..31c344ea90
--- /dev/null
+++ b/test/prism/errors/alnum_delimiters_5.txt
@@ -0,0 +1,3 @@
+%iXfooX
+^ unknown type of %string
+
diff --git a/test/prism/errors/alnum_delimiters_6.txt b/test/prism/errors/alnum_delimiters_6.txt
new file mode 100644
index 0000000000..79ffbbb1b8
--- /dev/null
+++ b/test/prism/errors/alnum_delimiters_6.txt
@@ -0,0 +1,3 @@
+%IXfooX
+^ unknown type of %string
+
diff --git a/test/prism/errors/alnum_delimiters_7.txt b/test/prism/errors/alnum_delimiters_7.txt
new file mode 100644
index 0000000000..809192e031
--- /dev/null
+++ b/test/prism/errors/alnum_delimiters_7.txt
@@ -0,0 +1,3 @@
+%xXfooX
+^ unknown type of %string
+
diff --git a/test/prism/errors/alnum_delimiters_8.txt b/test/prism/errors/alnum_delimiters_8.txt
new file mode 100644
index 0000000000..abfcf119c0
--- /dev/null
+++ b/test/prism/errors/alnum_delimiters_8.txt
@@ -0,0 +1,3 @@
+%rXfooX
+^ unknown type of %string
+
diff --git a/test/prism/errors/alnum_delimiters_9.txt b/test/prism/errors/alnum_delimiters_9.txt
new file mode 100644
index 0000000000..ae56d7be4f
--- /dev/null
+++ b/test/prism/errors/alnum_delimiters_9.txt
@@ -0,0 +1,3 @@
+%sXfooX
+^ unknown type of %string
+
diff --git a/test/prism/errors/argument_after_ellipsis.txt b/test/prism/errors/argument_after_ellipsis.txt
new file mode 100644
index 0000000000..3d708648a4
--- /dev/null
+++ b/test/prism/errors/argument_after_ellipsis.txt
@@ -0,0 +1,3 @@
+def foo(...); foo(..., 1); end
+ ^ unexpected argument after `...`
+
diff --git a/test/prism/errors/argument_forwarding_only_effects_its_own_internals.txt b/test/prism/errors/argument_forwarding_only_effects_its_own_internals.txt
new file mode 100644
index 0000000000..9c3f0ae3f7
--- /dev/null
+++ b/test/prism/errors/argument_forwarding_only_effects_its_own_internals.txt
@@ -0,0 +1,3 @@
+def a(...); b(...); end; def c(x, y, z); b(...); end
+ ^~~ unexpected ... when the parent method is not forwarding
+
diff --git a/test/prism/errors/argument_forwarding_when_parent_is_not_forwarding.txt b/test/prism/errors/argument_forwarding_when_parent_is_not_forwarding.txt
new file mode 100644
index 0000000000..017ba7eec9
--- /dev/null
+++ b/test/prism/errors/argument_forwarding_when_parent_is_not_forwarding.txt
@@ -0,0 +1,3 @@
+def a(x, y, z); b(...); end
+ ^~~ unexpected ... when the parent method is not forwarding
+
diff --git a/test/prism/errors/arguments_after_block.txt b/test/prism/errors/arguments_after_block.txt
new file mode 100644
index 0000000000..2d5e06ff77
--- /dev/null
+++ b/test/prism/errors/arguments_after_block.txt
@@ -0,0 +1,3 @@
+a(&block, foo)
+ ^~~ unexpected argument after a block argument
+
diff --git a/test/prism/errors/arguments_binding_power_for_and.txt b/test/prism/errors/arguments_binding_power_for_and.txt
new file mode 100644
index 0000000000..0585a091f4
--- /dev/null
+++ b/test/prism/errors/arguments_binding_power_for_and.txt
@@ -0,0 +1,5 @@
+foo(*bar and baz)
+ ^~~ unexpected 'and'; expected a `)` to close the arguments
+ ^ unexpected ')', expecting end-of-input
+ ^ unexpected ')', ignoring it
+
diff --git a/test/prism/errors/assign_to_numbered_parameter.txt b/test/prism/errors/assign_to_numbered_parameter.txt
new file mode 100644
index 0000000000..74cc0c4032
--- /dev/null
+++ b/test/prism/errors/assign_to_numbered_parameter.txt
@@ -0,0 +1,11 @@
+a in _1
+ ^~ _1 is reserved for numbered parameters
+a => _1
+ ^~ _1 is reserved for numbered parameters
+1 => a, _1
+ ^~ _1 is reserved for numbered parameters
+1 in a, _1
+ ^~ _1 is reserved for numbered parameters
+/(?<_1>)/ =~ a
+ ^~ _1 is reserved for numbered parameters
+
diff --git a/test/prism/errors/bad_arguments.txt b/test/prism/errors/bad_arguments.txt
new file mode 100644
index 0000000000..ea19efd3c8
--- /dev/null
+++ b/test/prism/errors/bad_arguments.txt
@@ -0,0 +1,6 @@
+def foo(A, @a, $A, @@a);end
+ ^ invalid formal argument; formal argument cannot be a constant
+ ^~ invalid formal argument; formal argument cannot be an instance variable
+ ^~ invalid formal argument; formal argument cannot be a global variable
+ ^~~ invalid formal argument; formal argument cannot be a class variable
+
diff --git a/test/prism/errors/begin_at_toplevel.txt b/test/prism/errors/begin_at_toplevel.txt
new file mode 100644
index 0000000000..ce3d3b8d00
--- /dev/null
+++ b/test/prism/errors/begin_at_toplevel.txt
@@ -0,0 +1,3 @@
+def foo; BEGIN {}; end
+ ^~~~~ BEGIN is permitted only at toplevel
+
diff --git a/test/prism/errors/binary_range_with_left_unary_range.txt b/test/prism/errors/binary_range_with_left_unary_range.txt
new file mode 100644
index 0000000000..37e41f3971
--- /dev/null
+++ b/test/prism/errors/binary_range_with_left_unary_range.txt
@@ -0,0 +1,7 @@
+..1..
+ ^~ unexpected range operator; .. and ... are non-associative and cannot be chained
+...1..
+ ^~ unexpected range operator; .. and ... are non-associative and cannot be chained
+ ^~ unexpected .., expecting end-of-input
+ ^~ unexpected .., ignoring it
+
diff --git a/test/prism/errors/block_arg_and_block.txt b/test/prism/errors/block_arg_and_block.txt
new file mode 100644
index 0000000000..c355c40475
--- /dev/null
+++ b/test/prism/errors/block_arg_and_block.txt
@@ -0,0 +1,3 @@
+foo(&1) { }
+ ^~~ both block arg and actual block given; only one block is allowed
+
diff --git a/test/prism/errors/block_beginning_with_brace_and_ending_with_end.txt b/test/prism/errors/block_beginning_with_brace_and_ending_with_end.txt
new file mode 100644
index 0000000000..f0fa964c8a
--- /dev/null
+++ b/test/prism/errors/block_beginning_with_brace_and_ending_with_end.txt
@@ -0,0 +1,6 @@
+x.each { x end
+ ^~~ unexpected 'end', expecting end-of-input
+ ^~~ unexpected 'end', ignoring it
+ ^ unexpected end-of-input, assuming it is closing the parent top level context
+ ^ expected a block beginning with `{` to end with `}`
+
diff --git a/test/prism/errors/break_1.txt b/test/prism/errors/break_1.txt
new file mode 100644
index 0000000000..e7b26ad3a0
--- /dev/null
+++ b/test/prism/errors/break_1.txt
@@ -0,0 +1,4 @@
+break 1,;
+ ^ expected an argument
+^~~~~~~~ Invalid break
+
diff --git a/test/prism/errors/break_1_2_3.txt b/test/prism/errors/break_1_2_3.txt
new file mode 100644
index 0000000000..817207cbfe
--- /dev/null
+++ b/test/prism/errors/break_1_2_3.txt
@@ -0,0 +1,8 @@
+break(1, 2, 3)
+ ^ unexpected ',', expecting end-of-input
+ ^ unexpected ',', ignoring it
+ ^ expected a matching `)`
+ ^ unexpected ')', expecting end-of-input
+ ^ unexpected ')', ignoring it
+^~~~~~~~~~~~~ Invalid break
+
diff --git a/test/prism/errors/call_with_block_and_write.txt b/test/prism/errors/call_with_block_and_write.txt
new file mode 100644
index 0000000000..f63d94770e
--- /dev/null
+++ b/test/prism/errors/call_with_block_and_write.txt
@@ -0,0 +1,4 @@
+foo {} &&= 1
+^~~~~~ unexpected write target
+ ^~~ unexpected operator after a call with a block
+
diff --git a/test/prism/errors/call_with_block_operator_write.txt b/test/prism/errors/call_with_block_operator_write.txt
new file mode 100644
index 0000000000..3c36050b34
--- /dev/null
+++ b/test/prism/errors/call_with_block_operator_write.txt
@@ -0,0 +1,4 @@
+foo {} += 1
+^~~~~~ unexpected write target
+ ^~ unexpected operator after a call with a block
+
diff --git a/test/prism/errors/call_with_block_or_write.txt b/test/prism/errors/call_with_block_or_write.txt
new file mode 100644
index 0000000000..2cced0db75
--- /dev/null
+++ b/test/prism/errors/call_with_block_or_write.txt
@@ -0,0 +1,4 @@
+foo {} ||= 1
+^~~~~~ unexpected write target
+ ^~~ unexpected operator after a call with a block
+
diff --git a/test/prism/errors/cannot_assign_to_a_reserved_numbered_parameter.txt b/test/prism/errors/cannot_assign_to_a_reserved_numbered_parameter.txt
new file mode 100644
index 0000000000..750915fb1f
--- /dev/null
+++ b/test/prism/errors/cannot_assign_to_a_reserved_numbered_parameter.txt
@@ -0,0 +1,14 @@
+begin
+ _1=:a;_2=:a;_3=:a;_4=:a;_5=:a
+ ^~ _1 is reserved for numbered parameters
+ ^~ _2 is reserved for numbered parameters
+ ^~ _3 is reserved for numbered parameters
+ ^~ _4 is reserved for numbered parameters
+ ^~ _5 is reserved for numbered parameters
+ _6=:a;_7=:a;_8=:a;_9=:a;_10=:a
+ ^~ _6 is reserved for numbered parameters
+ ^~ _7 is reserved for numbered parameters
+ ^~ _8 is reserved for numbered parameters
+ ^~ _9 is reserved for numbered parameters
+end
+
diff --git a/test/prism/errors/case_without_clauses.txt b/test/prism/errors/case_without_clauses.txt
new file mode 100644
index 0000000000..3bbbfdd97f
--- /dev/null
+++ b/test/prism/errors/case_without_clauses.txt
@@ -0,0 +1,4 @@
+case :a
+^~~~ expected a `when` or `in` clause after `case`
+end
+
diff --git a/test/prism/errors/case_without_when_clauses_errors_on_else_clause.txt b/test/prism/errors/case_without_when_clauses_errors_on_else_clause.txt
new file mode 100644
index 0000000000..c5a1179fb9
--- /dev/null
+++ b/test/prism/errors/case_without_when_clauses_errors_on_else_clause.txt
@@ -0,0 +1,5 @@
+case :a
+^~~~ expected a `when` or `in` clause after `case`
+else
+end
+
diff --git a/test/prism/errors/check_value_expression.txt b/test/prism/errors/check_value_expression.txt
new file mode 100644
index 0000000000..33a472d94c
--- /dev/null
+++ b/test/prism/errors/check_value_expression.txt
@@ -0,0 +1,20 @@
+1 => ^(return)
+ ^~~~~~ unexpected void value expression
+while true
+ 1 => ^(break)
+ ^~~~~ unexpected void value expression
+ 1 => ^(next)
+ ^~~~ unexpected void value expression
+ 1 => ^(redo)
+ ^~~~ unexpected void value expression
+ 1 => ^(retry)
+ ^~~~~ Invalid retry without rescue
+ ^~~~~ unexpected void value expression
+ 1 => ^(2 => a)
+ ^~~~~~ unexpected void value expression
+end
+1 => ^(if 1; (return) else (return) end)
+ ^~~~~~ unexpected void value expression
+1 => ^(unless 1; (return) else (return) end)
+ ^~~~~~ unexpected void value expression
+
diff --git a/test/prism/errors/class_definition_in_method_body.txt b/test/prism/errors/class_definition_in_method_body.txt
new file mode 100644
index 0000000000..fcdc5746ee
--- /dev/null
+++ b/test/prism/errors/class_definition_in_method_body.txt
@@ -0,0 +1,3 @@
+def foo;class A;end;end
+ ^~~~~ unexpected class definition in method body
+
diff --git a/test/prism/errors/class_definition_in_method_defs.txt b/test/prism/errors/class_definition_in_method_defs.txt
new file mode 100644
index 0000000000..23bee0b6fb
--- /dev/null
+++ b/test/prism/errors/class_definition_in_method_defs.txt
@@ -0,0 +1,7 @@
+def foo(bar = class A;end);end
+ ^~~~~ unexpected class definition in method body
+def foo;rescue;class A;end;end
+ ^~~~~ unexpected class definition in method body
+def foo;ensure;class A;end;end
+ ^~~~~ unexpected class definition in method body
+
diff --git a/test/prism/errors/class_name.txt b/test/prism/errors/class_name.txt
new file mode 100644
index 0000000000..8b75896ddb
--- /dev/null
+++ b/test/prism/errors/class_name.txt
@@ -0,0 +1,3 @@
+class 0.X end
+ ^~~ unexpected constant path after `class`; class/module name must be CONSTANT
+
diff --git a/test/prism/errors/command_call_in.txt b/test/prism/errors/command_call_in.txt
new file mode 100644
index 0000000000..a4357028c6
--- /dev/null
+++ b/test/prism/errors/command_call_in.txt
@@ -0,0 +1,7 @@
+foo 1 in a
+ ^ unexpected `in` keyword in arguments
+ ^ unexpected local variable or method, expecting end-of-input
+a = foo 2 in b
+ ^ unexpected `in` keyword in arguments
+ ^ unexpected local variable or method, expecting end-of-input
+
diff --git a/test/prism/errors/command_calls.txt b/test/prism/errors/command_calls.txt
new file mode 100644
index 0000000000..19812a1d0a
--- /dev/null
+++ b/test/prism/errors/command_calls.txt
@@ -0,0 +1,3 @@
+[a b]
+ ^ unexpected local variable or method; expected a `,` separator for the array elements
+
diff --git a/test/prism/errors/command_calls_10.txt b/test/prism/errors/command_calls_10.txt
new file mode 100644
index 0000000000..f4d9f0fabc
--- /dev/null
+++ b/test/prism/errors/command_calls_10.txt
@@ -0,0 +1,3 @@
++a b
+ ^ unexpected local variable or method, expecting end-of-input
+
diff --git a/test/prism/errors/command_calls_11.txt b/test/prism/errors/command_calls_11.txt
new file mode 100644
index 0000000000..868476c0c3
--- /dev/null
+++ b/test/prism/errors/command_calls_11.txt
@@ -0,0 +1,3 @@
+a + b c
+ ^ unexpected local variable or method, expecting end-of-input
+
diff --git a/test/prism/errors/command_calls_12.txt b/test/prism/errors/command_calls_12.txt
new file mode 100644
index 0000000000..50c9ae88e3
--- /dev/null
+++ b/test/prism/errors/command_calls_12.txt
@@ -0,0 +1,3 @@
+a && b c
+ ^ unexpected local variable or method, expecting end-of-input
+
diff --git a/test/prism/errors/command_calls_13.txt b/test/prism/errors/command_calls_13.txt
new file mode 100644
index 0000000000..50dc4a84a0
--- /dev/null
+++ b/test/prism/errors/command_calls_13.txt
@@ -0,0 +1,3 @@
+a =~ b c
+ ^ unexpected local variable or method, expecting end-of-input
+
diff --git a/test/prism/errors/command_calls_14.txt b/test/prism/errors/command_calls_14.txt
new file mode 100644
index 0000000000..1b16fd3245
--- /dev/null
+++ b/test/prism/errors/command_calls_14.txt
@@ -0,0 +1,3 @@
+a = b, c d
+ ^ unexpected local variable or method, expecting end-of-input
+
diff --git a/test/prism/errors/command_calls_15.txt b/test/prism/errors/command_calls_15.txt
new file mode 100644
index 0000000000..d2409fd002
--- /dev/null
+++ b/test/prism/errors/command_calls_15.txt
@@ -0,0 +1,3 @@
+a = *b c
+ ^ unexpected local variable or method, expecting end-of-input
+
diff --git a/test/prism/errors/command_calls_16.txt b/test/prism/errors/command_calls_16.txt
new file mode 100644
index 0000000000..ceb07dfe30
--- /dev/null
+++ b/test/prism/errors/command_calls_16.txt
@@ -0,0 +1,3 @@
+a, b = c = d f
+ ^ unexpected local variable or method, expecting end-of-input
+
diff --git a/test/prism/errors/command_calls_17.txt b/test/prism/errors/command_calls_17.txt
new file mode 100644
index 0000000000..a78ac0985d
--- /dev/null
+++ b/test/prism/errors/command_calls_17.txt
@@ -0,0 +1,5 @@
+a ? b c : d e
+ ^ expected a `:` after the true expression of a ternary operator
+ ^ unexpected ':', expecting end-of-input
+ ^ unexpected ':', ignoring it
+
diff --git a/test/prism/errors/command_calls_18.txt b/test/prism/errors/command_calls_18.txt
new file mode 100644
index 0000000000..393e7e0ae6
--- /dev/null
+++ b/test/prism/errors/command_calls_18.txt
@@ -0,0 +1,3 @@
+defined? a b
+ ^ unexpected local variable or method, expecting end-of-input
+
diff --git a/test/prism/errors/command_calls_19.txt b/test/prism/errors/command_calls_19.txt
new file mode 100644
index 0000000000..e045187f1e
--- /dev/null
+++ b/test/prism/errors/command_calls_19.txt
@@ -0,0 +1,3 @@
+! ! a b
+ ^ unexpected local variable or method, expecting end-of-input
+
diff --git a/test/prism/errors/command_calls_2.txt b/test/prism/errors/command_calls_2.txt
new file mode 100644
index 0000000000..b0983c015b
--- /dev/null
+++ b/test/prism/errors/command_calls_2.txt
@@ -0,0 +1,6 @@
+{a: b c}
+ ^ expected a `}` to close the hash literal
+ ^ unexpected local variable or method, expecting end-of-input
+ ^ unexpected '}', expecting end-of-input
+ ^ unexpected '}', ignoring it
+
diff --git a/test/prism/errors/command_calls_20.txt b/test/prism/errors/command_calls_20.txt
new file mode 100644
index 0000000000..3058ebce96
--- /dev/null
+++ b/test/prism/errors/command_calls_20.txt
@@ -0,0 +1,3 @@
+def f a = b c; end
+ ^ expected a delimiter to close the parameters
+
diff --git a/test/prism/errors/command_calls_21.txt b/test/prism/errors/command_calls_21.txt
new file mode 100644
index 0000000000..73d8f83539
--- /dev/null
+++ b/test/prism/errors/command_calls_21.txt
@@ -0,0 +1,5 @@
+def f(a = b c); end
+ ^ unexpected local variable or method; expected a `)` to close the parameters
+ ^ unexpected ')', expecting end-of-input
+ ^ unexpected ')', ignoring it
+
diff --git a/test/prism/errors/command_calls_22.txt b/test/prism/errors/command_calls_22.txt
new file mode 100644
index 0000000000..5a234e04e8
--- /dev/null
+++ b/test/prism/errors/command_calls_22.txt
@@ -0,0 +1,3 @@
+a = b rescue c d
+ ^ unexpected local variable or method, expecting end-of-input
+
diff --git a/test/prism/errors/command_calls_23.txt b/test/prism/errors/command_calls_23.txt
new file mode 100644
index 0000000000..db85589ffd
--- /dev/null
+++ b/test/prism/errors/command_calls_23.txt
@@ -0,0 +1,3 @@
+def a = b rescue c d
+ ^ unexpected local variable or method, expecting end-of-input
+
diff --git a/test/prism/errors/command_calls_24.txt b/test/prism/errors/command_calls_24.txt
new file mode 100644
index 0000000000..3046b36dc1
--- /dev/null
+++ b/test/prism/errors/command_calls_24.txt
@@ -0,0 +1,5 @@
+->a=b c{}
+ ^ expected a `do` keyword or a `{` to open the lambda block
+ ^ unexpected end-of-input, assuming it is closing the parent top level context
+ ^ expected a lambda block beginning with `do` to end with `end`
+
diff --git a/test/prism/errors/command_calls_25.txt b/test/prism/errors/command_calls_25.txt
new file mode 100644
index 0000000000..5fddd90fdd
--- /dev/null
+++ b/test/prism/errors/command_calls_25.txt
@@ -0,0 +1,8 @@
+->(a=b c){}
+ ^ expected a matching `)`
+ ^ expected a `do` keyword or a `{` to open the lambda block
+ ^ unexpected ')', expecting end-of-input
+ ^ unexpected ')', ignoring it
+ ^ unexpected end-of-input, assuming it is closing the parent top level context
+ ^ expected a lambda block beginning with `do` to end with `end`
+
diff --git a/test/prism/errors/command_calls_26.txt b/test/prism/errors/command_calls_26.txt
new file mode 100644
index 0000000000..29ed4cb903
--- /dev/null
+++ b/test/prism/errors/command_calls_26.txt
@@ -0,0 +1,3 @@
+case; when a b; end
+ ^ expected a delimiter after the predicates of a `when` clause
+
diff --git a/test/prism/errors/command_calls_27.txt b/test/prism/errors/command_calls_27.txt
new file mode 100644
index 0000000000..8d1c3ee077
--- /dev/null
+++ b/test/prism/errors/command_calls_27.txt
@@ -0,0 +1,3 @@
+case; in a if a b; end
+^~~~ expected a predicate for a case matching statement
+
diff --git a/test/prism/errors/command_calls_28.txt b/test/prism/errors/command_calls_28.txt
new file mode 100644
index 0000000000..4bfe88d67b
--- /dev/null
+++ b/test/prism/errors/command_calls_28.txt
@@ -0,0 +1,3 @@
+case; in a unless a b; end
+^~~~ expected a predicate for a case matching statement
+
diff --git a/test/prism/errors/command_calls_29.txt b/test/prism/errors/command_calls_29.txt
new file mode 100644
index 0000000000..eae012ab44
--- /dev/null
+++ b/test/prism/errors/command_calls_29.txt
@@ -0,0 +1,3 @@
+begin; rescue a b; end
+ ^ expected a closing delimiter for the `rescue` clause
+
diff --git a/test/prism/errors/command_calls_3.txt b/test/prism/errors/command_calls_3.txt
new file mode 100644
index 0000000000..77af72b904
--- /dev/null
+++ b/test/prism/errors/command_calls_3.txt
@@ -0,0 +1,3 @@
+...a b
+ ^ unexpected local variable or method, expecting end-of-input
+
diff --git a/test/prism/errors/command_calls_30.txt b/test/prism/errors/command_calls_30.txt
new file mode 100644
index 0000000000..48e35685cb
--- /dev/null
+++ b/test/prism/errors/command_calls_30.txt
@@ -0,0 +1,3 @@
+begin; rescue a b => c; end
+ ^ expected a closing delimiter for the `rescue` clause
+
diff --git a/test/prism/errors/command_calls_4.txt b/test/prism/errors/command_calls_4.txt
new file mode 100644
index 0000000000..4be14e57e4
--- /dev/null
+++ b/test/prism/errors/command_calls_4.txt
@@ -0,0 +1,3 @@
+if ...a b; end
+ ^ expected `then` or `;` or '\n'
+
diff --git a/test/prism/errors/command_calls_5.txt b/test/prism/errors/command_calls_5.txt
new file mode 100644
index 0000000000..799a6c1136
--- /dev/null
+++ b/test/prism/errors/command_calls_5.txt
@@ -0,0 +1,3 @@
+a b, c d
+ ^ unexpected local variable or method, expecting end-of-input
+
diff --git a/test/prism/errors/command_calls_6.txt b/test/prism/errors/command_calls_6.txt
new file mode 100644
index 0000000000..6f09d36e94
--- /dev/null
+++ b/test/prism/errors/command_calls_6.txt
@@ -0,0 +1,6 @@
+a(b, c d)
+ ^ unexpected local variable or method; expected a `)` to close the arguments
+ ^ unexpected local variable or method, expecting end-of-input
+ ^ unexpected ')', expecting end-of-input
+ ^ unexpected ')', ignoring it
+
diff --git a/test/prism/errors/command_calls_7.txt b/test/prism/errors/command_calls_7.txt
new file mode 100644
index 0000000000..b5d74209fa
--- /dev/null
+++ b/test/prism/errors/command_calls_7.txt
@@ -0,0 +1,6 @@
+a(*b c)
+ ^ unexpected local variable or method; expected a `)` to close the arguments
+ ^ unexpected local variable or method, expecting end-of-input
+ ^ unexpected ')', expecting end-of-input
+ ^ unexpected ')', ignoring it
+
diff --git a/test/prism/errors/command_calls_8.txt b/test/prism/errors/command_calls_8.txt
new file mode 100644
index 0000000000..e574063e72
--- /dev/null
+++ b/test/prism/errors/command_calls_8.txt
@@ -0,0 +1,6 @@
+a(**b c)
+ ^ unexpected local variable or method; expected a `)` to close the arguments
+ ^ unexpected local variable or method, expecting end-of-input
+ ^ unexpected ')', expecting end-of-input
+ ^ unexpected ')', ignoring it
+
diff --git a/test/prism/errors/command_calls_9.txt b/test/prism/errors/command_calls_9.txt
new file mode 100644
index 0000000000..69515d959c
--- /dev/null
+++ b/test/prism/errors/command_calls_9.txt
@@ -0,0 +1,6 @@
+a(&b c)
+ ^ unexpected local variable or method; expected a `)` to close the arguments
+ ^ unexpected local variable or method, expecting end-of-input
+ ^ unexpected ')', expecting end-of-input
+ ^ unexpected ')', ignoring it
+
diff --git a/test/prism/errors/conditional_predicate_closed.txt b/test/prism/errors/conditional_predicate_closed.txt
new file mode 100644
index 0000000000..6655fd2b1c
--- /dev/null
+++ b/test/prism/errors/conditional_predicate_closed.txt
@@ -0,0 +1,6 @@
+if 0 0; elsif 0 0; end
+ ^ expected `then` or `;` or '\n'
+ ^ expected `then` or `;` or '\n'
+unless 0 0; end
+ ^ expected `then` or `;` or '\n'
+
diff --git a/test/prism/errors/constant_assignment_in_method.txt b/test/prism/errors/constant_assignment_in_method.txt
new file mode 100644
index 0000000000..1ee49bffe6
--- /dev/null
+++ b/test/prism/errors/constant_assignment_in_method.txt
@@ -0,0 +1,3 @@
+def foo();A=1;end
+ ^~~ dynamic constant assignment
+
diff --git a/test/prism/errors/constant_path_with_invalid_token_after.txt b/test/prism/errors/constant_path_with_invalid_token_after.txt
new file mode 100644
index 0000000000..acb6dba30a
--- /dev/null
+++ b/test/prism/errors/constant_path_with_invalid_token_after.txt
@@ -0,0 +1,4 @@
+A::$b
+ ^ expected a constant after the `::` operator
+ ^~ unexpected global variable, expecting end-of-input
+
diff --git a/test/prism/errors/content_after_unterminated_heredoc.txt b/test/prism/errors/content_after_unterminated_heredoc.txt
new file mode 100644
index 0000000000..c0446a8c39
--- /dev/null
+++ b/test/prism/errors/content_after_unterminated_heredoc.txt
@@ -0,0 +1,4 @@
+<<~FOO.foo
+ ^~~ unterminated heredoc; can't find string "FOO" anywhere before EOF
+ ^~~ unterminated heredoc; can't find string "FOO" anywhere before EOF
+
diff --git a/test/prism/errors/cr_without_lf_in_percent_expression.txt b/test/prism/errors/cr_without_lf_in_percent_expression.txt
new file mode 100644
index 0000000000..903f8b4b4a
--- /dev/null
+++ b/test/prism/errors/cr_without_lf_in_percent_expression.txt
@@ -0,0 +1,3 @@
+%
+ ^ unterminated string meets end of file
+
diff --git a/test/prism/errors/def_with_empty_expression_receiver.txt b/test/prism/errors/def_with_empty_expression_receiver.txt
new file mode 100644
index 0000000000..153fe8a1c6
--- /dev/null
+++ b/test/prism/errors/def_with_empty_expression_receiver.txt
@@ -0,0 +1,3 @@
+def ().a; end
+ ^ expected a receiver for the method definition
+
diff --git a/test/prism/errors/def_with_expression_receiver_and_no_identifier.txt b/test/prism/errors/def_with_expression_receiver_and_no_identifier.txt
new file mode 100644
index 0000000000..1aefc07f1a
--- /dev/null
+++ b/test/prism/errors/def_with_expression_receiver_and_no_identifier.txt
@@ -0,0 +1,4 @@
+def (a); end
+ ^ expected a `.` or `::` after the receiver in a method definition
+ ^ unexpected ';'; expected a method name
+
diff --git a/test/prism/errors/def_with_multiple_statements_receiver.txt b/test/prism/errors/def_with_multiple_statements_receiver.txt
new file mode 100644
index 0000000000..80c9d4c190
--- /dev/null
+++ b/test/prism/errors/def_with_multiple_statements_receiver.txt
@@ -0,0 +1,10 @@
+def (
+a
+b
+^ expected a matching `)`
+^ expected a `.` or `::` after the receiver in a method definition
+ ^ expected a delimiter to close the parameters
+).c; end
+^ unexpected ')', ignoring it
+ ^ unexpected '.', ignoring it
+
diff --git a/test/prism/errors/defining_numbered_parameter.txt b/test/prism/errors/defining_numbered_parameter.txt
new file mode 100644
index 0000000000..2bf05d9563
--- /dev/null
+++ b/test/prism/errors/defining_numbered_parameter.txt
@@ -0,0 +1,3 @@
+def _1; end
+ ^~ _1 is reserved for numbered parameters
+
diff --git a/test/prism/errors/defining_numbered_parameter_2.txt b/test/prism/errors/defining_numbered_parameter_2.txt
new file mode 100644
index 0000000000..dc4739b126
--- /dev/null
+++ b/test/prism/errors/defining_numbered_parameter_2.txt
@@ -0,0 +1,3 @@
+def self._1; end
+ ^~ _1 is reserved for numbered parameters
+
diff --git a/test/prism/errors/do_not_allow_characters_other_than_0_9_a_f_and_A_F_in_u_Unicode_character_notation.txt b/test/prism/errors/do_not_allow_characters_other_than_0_9_a_f_and_A_F_in_u_Unicode_character_notation.txt
new file mode 100644
index 0000000000..953b9589d1
--- /dev/null
+++ b/test/prism/errors/do_not_allow_characters_other_than_0_9_a_f_and_A_F_in_u_Unicode_character_notation.txt
@@ -0,0 +1,4 @@
+"\u{000z}"
+ ^ invalid Unicode escape sequence
+ ^ unterminated Unicode escape
+
diff --git a/test/prism/errors/do_not_allow_forward_arguments_in_blocks.txt b/test/prism/errors/do_not_allow_forward_arguments_in_blocks.txt
new file mode 100644
index 0000000000..df49557617
--- /dev/null
+++ b/test/prism/errors/do_not_allow_forward_arguments_in_blocks.txt
@@ -0,0 +1,3 @@
+a {|...|}
+ ^~~ unexpected ... when the parent method is not forwarding
+
diff --git a/test/prism/errors/do_not_allow_forward_arguments_in_lambda_literals.txt b/test/prism/errors/do_not_allow_forward_arguments_in_lambda_literals.txt
new file mode 100644
index 0000000000..c2405a5c66
--- /dev/null
+++ b/test/prism/errors/do_not_allow_forward_arguments_in_lambda_literals.txt
@@ -0,0 +1,3 @@
+->(...) {}
+ ^~~ unexpected ... when the parent method is not forwarding
+
diff --git a/test/prism/errors/do_not_allow_more_than_6_hexadecimal_digits_in_u_Unicode_character_notation.txt b/test/prism/errors/do_not_allow_more_than_6_hexadecimal_digits_in_u_Unicode_character_notation.txt
new file mode 100644
index 0000000000..50795c9353
--- /dev/null
+++ b/test/prism/errors/do_not_allow_more_than_6_hexadecimal_digits_in_u_Unicode_character_notation.txt
@@ -0,0 +1,3 @@
+"\u{0000001}"
+ ^~~~~~~ invalid Unicode escape sequence; maximum length is 6 digits
+
diff --git a/test/prism/errors/do_not_allow_multiple_codepoints_in_a_single_character_literal.txt b/test/prism/errors/do_not_allow_multiple_codepoints_in_a_single_character_literal.txt
new file mode 100644
index 0000000000..1a93dc6c69
--- /dev/null
+++ b/test/prism/errors/do_not_allow_multiple_codepoints_in_a_single_character_literal.txt
@@ -0,0 +1,3 @@
+?\u{0001 0002}
+ ^~~ invalid Unicode escape sequence; Multiple codepoints at single character literal are disallowed
+
diff --git a/test/prism/errors/do_not_allow_trailing_commas_in_lambda_parameters.txt b/test/prism/errors/do_not_allow_trailing_commas_in_lambda_parameters.txt
new file mode 100644
index 0000000000..11f23f0345
--- /dev/null
+++ b/test/prism/errors/do_not_allow_trailing_commas_in_lambda_parameters.txt
@@ -0,0 +1,3 @@
+-> (a, b, ) {}
+ ^ unexpected `,` in parameters
+
diff --git a/test/prism/errors/do_not_allow_trailing_commas_in_method_parameters.txt b/test/prism/errors/do_not_allow_trailing_commas_in_method_parameters.txt
new file mode 100644
index 0000000000..c0fec0c704
--- /dev/null
+++ b/test/prism/errors/do_not_allow_trailing_commas_in_method_parameters.txt
@@ -0,0 +1,3 @@
+def foo(a,b,c,);end
+ ^ unexpected `,` in parameters
+
diff --git a/test/prism/errors/dont_allow_return_inside_class_body.txt b/test/prism/errors/dont_allow_return_inside_class_body.txt
new file mode 100644
index 0000000000..286eba2103
--- /dev/null
+++ b/test/prism/errors/dont_allow_return_inside_class_body.txt
@@ -0,0 +1,3 @@
+class A; return; end
+ ^~~~~~ Invalid return in class/module body
+
diff --git a/test/prism/errors/dont_allow_return_inside_module_body.txt b/test/prism/errors/dont_allow_return_inside_module_body.txt
new file mode 100644
index 0000000000..85dd619a93
--- /dev/null
+++ b/test/prism/errors/dont_allow_return_inside_module_body.txt
@@ -0,0 +1,3 @@
+module A; return; end
+ ^~~~~~ Invalid return in class/module body
+
diff --git a/test/prism/errors/dont_allow_return_inside_sclass_body.txt b/test/prism/errors/dont_allow_return_inside_sclass_body.txt
new file mode 100644
index 0000000000..c29fe01728
--- /dev/null
+++ b/test/prism/errors/dont_allow_return_inside_sclass_body.txt
@@ -0,0 +1,3 @@
+class << A; return; end
+ ^~~~~~ Invalid return in class/module body
+
diff --git a/test/prism/errors/dont_allow_setting_to_back_and_nth_reference.txt b/test/prism/errors/dont_allow_setting_to_back_and_nth_reference.txt
new file mode 100644
index 0000000000..71b5b94589
--- /dev/null
+++ b/test/prism/errors/dont_allow_setting_to_back_and_nth_reference.txt
@@ -0,0 +1,7 @@
+begin
+$+ = nil
+^~ Can't set variable $+
+$1466 = nil
+^~~~~ Can't set variable $1466
+end
+
diff --git a/test/prism/errors/double_arguments_forwarding.txt b/test/prism/errors/double_arguments_forwarding.txt
new file mode 100644
index 0000000000..29c78f8c80
--- /dev/null
+++ b/test/prism/errors/double_arguments_forwarding.txt
@@ -0,0 +1,4 @@
+def foo(..., ...)
+ ^~~ unexpected parameter order
+end
+
diff --git a/test/prism/errors/double_scope_numbered_parameters.txt b/test/prism/errors/double_scope_numbered_parameters.txt
new file mode 100644
index 0000000000..0bb9df4ede
--- /dev/null
+++ b/test/prism/errors/double_scope_numbered_parameters.txt
@@ -0,0 +1,3 @@
+-> { _1 + -> { _2 } }
+ ^~ numbered parameter is already used in outer block
+
diff --git a/test/prism/errors/double_splat_followed_by_splat_argument.txt b/test/prism/errors/double_splat_followed_by_splat_argument.txt
new file mode 100644
index 0000000000..b2aec1167e
--- /dev/null
+++ b/test/prism/errors/double_splat_followed_by_splat_argument.txt
@@ -0,0 +1,3 @@
+a(**kwargs, *args)
+ ^~~~~ unexpected `*` splat argument after a `**` keyword splat argument
+
diff --git a/test/prism/errors/duplicate_pattern_capture.txt b/test/prism/errors/duplicate_pattern_capture.txt
new file mode 100644
index 0000000000..4b48fd3118
--- /dev/null
+++ b/test/prism/errors/duplicate_pattern_capture.txt
@@ -0,0 +1,17 @@
+case (); in [a, a]; end
+ ^ duplicated variable name
+case (); in [a, *a]; end
+ ^ duplicated variable name
+case (); in {a: a, b: a}; end
+ ^ duplicated variable name
+case (); in {a: a, **a}; end
+ ^ duplicated variable name
+case (); in [a, {a:}]; end
+ ^ duplicated variable name
+case (); in [a, {a: {a: {a: [a]}}}]; end
+ ^ duplicated variable name
+case (); in a => a; end
+ ^ duplicated variable name
+case (); in [A => a, {a: b => a}]; end
+ ^ duplicated variable name
+
diff --git a/test/prism/errors/duplicate_pattern_hash_key.txt b/test/prism/errors/duplicate_pattern_hash_key.txt
new file mode 100644
index 0000000000..201b51234f
--- /dev/null
+++ b/test/prism/errors/duplicate_pattern_hash_key.txt
@@ -0,0 +1,4 @@
+case (); in {a:, a:}; end
+ ^~ duplicated key name
+ ^ duplicated variable name
+
diff --git a/test/prism/errors/duplicate_pattern_hash_key_2.txt b/test/prism/errors/duplicate_pattern_hash_key_2.txt
new file mode 100644
index 0000000000..66756c454a
--- /dev/null
+++ b/test/prism/errors/duplicate_pattern_hash_key_2.txt
@@ -0,0 +1,3 @@
+case (); in {a:1, a:2}; end
+ ^~ duplicated key name
+
diff --git a/test/prism/errors/duplicated_parameter_names.txt b/test/prism/errors/duplicated_parameter_names.txt
new file mode 100644
index 0000000000..7b82685ca3
--- /dev/null
+++ b/test/prism/errors/duplicated_parameter_names.txt
@@ -0,0 +1,3 @@
+def foo(a,b,a);end
+ ^ duplicated argument name
+
diff --git a/test/prism/errors/duplicated_parameter_names_2.txt b/test/prism/errors/duplicated_parameter_names_2.txt
new file mode 100644
index 0000000000..8396993d56
--- /dev/null
+++ b/test/prism/errors/duplicated_parameter_names_2.txt
@@ -0,0 +1,3 @@
+def foo(a,b,*a);end
+ ^ duplicated argument name
+
diff --git a/test/prism/errors/duplicated_parameter_names_3.txt b/test/prism/errors/duplicated_parameter_names_3.txt
new file mode 100644
index 0000000000..437a6623c3
--- /dev/null
+++ b/test/prism/errors/duplicated_parameter_names_3.txt
@@ -0,0 +1,3 @@
+def foo(a,b,**a);end
+ ^ duplicated argument name
+
diff --git a/test/prism/errors/duplicated_parameter_names_4.txt b/test/prism/errors/duplicated_parameter_names_4.txt
new file mode 100644
index 0000000000..a420dd8a69
--- /dev/null
+++ b/test/prism/errors/duplicated_parameter_names_4.txt
@@ -0,0 +1,3 @@
+def foo(a,b,&a);end
+ ^ duplicated argument name
+
diff --git a/test/prism/errors/duplicated_parameter_names_5.txt b/test/prism/errors/duplicated_parameter_names_5.txt
new file mode 100644
index 0000000000..694d3a668c
--- /dev/null
+++ b/test/prism/errors/duplicated_parameter_names_5.txt
@@ -0,0 +1,3 @@
+def foo(a = 1,b,*c);end
+ ^ unexpected parameter `*`
+
diff --git a/test/prism/errors/ellipsis_in_no_paren_call.txt b/test/prism/errors/ellipsis_in_no_paren_call.txt
new file mode 100644
index 0000000000..87a847d192
--- /dev/null
+++ b/test/prism/errors/ellipsis_in_no_paren_call.txt
@@ -0,0 +1,3 @@
+def foo(...); foo 1, ...; end
+ ^~~ unexpected `...` in an non-parenthesized call
+
diff --git a/test/prism/errors/for_loops_index_missing.txt b/test/prism/errors/for_loops_index_missing.txt
new file mode 100644
index 0000000000..a57c22b044
--- /dev/null
+++ b/test/prism/errors/for_loops_index_missing.txt
@@ -0,0 +1,5 @@
+for in 1..10
+^~~ expected an index after `for`
+i
+end
+
diff --git a/test/prism/errors/for_loops_only_end.txt b/test/prism/errors/for_loops_only_end.txt
new file mode 100644
index 0000000000..94cc5270b5
--- /dev/null
+++ b/test/prism/errors/for_loops_only_end.txt
@@ -0,0 +1,5 @@
+for end
+^~~ expected an index after `for`
+ ^ expected an `in` after the index in a `for` statement
+ ^ expected a collection after the `in` in a `for` statement
+
diff --git a/test/prism/errors/forwarding_arg_after_keyword_rest.txt b/test/prism/errors/forwarding_arg_after_keyword_rest.txt
new file mode 100644
index 0000000000..86fe4aad93
--- /dev/null
+++ b/test/prism/errors/forwarding_arg_after_keyword_rest.txt
@@ -0,0 +1,3 @@
+def f(**,...);end
+ ^~~ unexpected parameter order
+
diff --git a/test/prism/errors/forwarding_arg_and_block.txt b/test/prism/errors/forwarding_arg_and_block.txt
new file mode 100644
index 0000000000..65c75a5d7c
--- /dev/null
+++ b/test/prism/errors/forwarding_arg_and_block.txt
@@ -0,0 +1,3 @@
+def foo(...) = foo(...) { }
+ ^~~ both block arg and actual block given; only one block is allowed
+
diff --git a/test/prism/errors/incomplete_instance_var_string.txt b/test/prism/errors/incomplete_instance_var_string.txt
new file mode 100644
index 0000000000..b28947fc0e
--- /dev/null
+++ b/test/prism/errors/incomplete_instance_var_string.txt
@@ -0,0 +1,4 @@
+%@#@@#
+ ^ '@' without identifiers is not allowed as an instance variable name
+ ^ unexpected instance variable, expecting end-of-input
+
diff --git a/test/prism/errors/index_call_with_block_and_write.txt b/test/prism/errors/index_call_with_block_and_write.txt
new file mode 100644
index 0000000000..3d92fbfea7
--- /dev/null
+++ b/test/prism/errors/index_call_with_block_and_write.txt
@@ -0,0 +1,5 @@
+foo[1] {} &&= 1
+^~~~~~~~~ unexpected write target
+ ^~~ unexpected operator after a call with arguments
+ ^~~ unexpected operator after a call with a block
+
diff --git a/test/prism/errors/index_call_with_block_operator_write.txt b/test/prism/errors/index_call_with_block_operator_write.txt
new file mode 100644
index 0000000000..96c413cd39
--- /dev/null
+++ b/test/prism/errors/index_call_with_block_operator_write.txt
@@ -0,0 +1,5 @@
+foo[1] {} += 1
+^~~~~~~~~ unexpected write target
+ ^~ unexpected operator after a call with arguments
+ ^~ unexpected operator after a call with a block
+
diff --git a/test/prism/errors/index_call_with_block_or_write.txt b/test/prism/errors/index_call_with_block_or_write.txt
new file mode 100644
index 0000000000..2d250fba06
--- /dev/null
+++ b/test/prism/errors/index_call_with_block_or_write.txt
@@ -0,0 +1,5 @@
+foo[1] {} ||= 1
+^~~~~~~~~ unexpected write target
+ ^~~ unexpected operator after a call with arguments
+ ^~~ unexpected operator after a call with a block
+
diff --git a/test/prism/errors/interpolated_regular_expression_with_unknown_regexp_options.txt b/test/prism/errors/interpolated_regular_expression_with_unknown_regexp_options.txt
new file mode 100644
index 0000000000..8e78753b1c
--- /dev/null
+++ b/test/prism/errors/interpolated_regular_expression_with_unknown_regexp_options.txt
@@ -0,0 +1,3 @@
+/#{foo}/AZaz
+ ^~~~~ unknown regexp options - AZaz
+
diff --git a/test/prism/errors/invalid_global_variable_write.txt b/test/prism/errors/invalid_global_variable_write.txt
new file mode 100644
index 0000000000..9d9018bcf1
--- /dev/null
+++ b/test/prism/errors/invalid_global_variable_write.txt
@@ -0,0 +1,4 @@
+$',
+^~ Can't set variable $'
+^~ unexpected write target
+
diff --git a/test/prism/errors/invalid_hex_escape.txt b/test/prism/errors/invalid_hex_escape.txt
new file mode 100644
index 0000000000..4fb847f6d2
--- /dev/null
+++ b/test/prism/errors/invalid_hex_escape.txt
@@ -0,0 +1,3 @@
+"\xx"
+ ^~ invalid hex escape sequence
+
diff --git a/test/prism/errors/invalid_multi_target.txt b/test/prism/errors/invalid_multi_target.txt
new file mode 100644
index 0000000000..9756278b0c
--- /dev/null
+++ b/test/prism/errors/invalid_multi_target.txt
@@ -0,0 +1,3 @@
+foo,
+^~~ unexpected write target
+
diff --git a/test/prism/errors/invalid_multi_target_10.txt b/test/prism/errors/invalid_multi_target_10.txt
new file mode 100644
index 0000000000..0e87b67d36
--- /dev/null
+++ b/test/prism/errors/invalid_multi_target_10.txt
@@ -0,0 +1,3 @@
+Foo,
+^~~ unexpected write target
+
diff --git a/test/prism/errors/invalid_multi_target_11.txt b/test/prism/errors/invalid_multi_target_11.txt
new file mode 100644
index 0000000000..8185cde79e
--- /dev/null
+++ b/test/prism/errors/invalid_multi_target_11.txt
@@ -0,0 +1,3 @@
+::Foo,
+^~~~~ unexpected write target
+
diff --git a/test/prism/errors/invalid_multi_target_12.txt b/test/prism/errors/invalid_multi_target_12.txt
new file mode 100644
index 0000000000..f511a8a76f
--- /dev/null
+++ b/test/prism/errors/invalid_multi_target_12.txt
@@ -0,0 +1,3 @@
+Foo::Foo,
+^~~~~~~~ unexpected write target
+
diff --git a/test/prism/errors/invalid_multi_target_13.txt b/test/prism/errors/invalid_multi_target_13.txt
new file mode 100644
index 0000000000..7c9a3fb4e1
--- /dev/null
+++ b/test/prism/errors/invalid_multi_target_13.txt
@@ -0,0 +1,3 @@
+Foo::foo,
+^~~~~~~~ unexpected write target
+
diff --git a/test/prism/errors/invalid_multi_target_14.txt b/test/prism/errors/invalid_multi_target_14.txt
new file mode 100644
index 0000000000..88dc08de92
--- /dev/null
+++ b/test/prism/errors/invalid_multi_target_14.txt
@@ -0,0 +1,3 @@
+foo[foo],
+^~~~~~~~ unexpected write target
+
diff --git a/test/prism/errors/invalid_multi_target_15.txt b/test/prism/errors/invalid_multi_target_15.txt
new file mode 100644
index 0000000000..c140833467
--- /dev/null
+++ b/test/prism/errors/invalid_multi_target_15.txt
@@ -0,0 +1,3 @@
+(foo, bar)
+^~~~~~~~~~ unexpected write target
+
diff --git a/test/prism/errors/invalid_multi_target_16.txt b/test/prism/errors/invalid_multi_target_16.txt
new file mode 100644
index 0000000000..20ea56331f
--- /dev/null
+++ b/test/prism/errors/invalid_multi_target_16.txt
@@ -0,0 +1,3 @@
+foo((foo, bar))
+ ^~~~~~~~~~ unexpected write target
+
diff --git a/test/prism/errors/invalid_multi_target_17.txt b/test/prism/errors/invalid_multi_target_17.txt
new file mode 100644
index 0000000000..da1ced0c59
--- /dev/null
+++ b/test/prism/errors/invalid_multi_target_17.txt
@@ -0,0 +1,3 @@
+foo((*))
+ ^~~ unexpected write target
+
diff --git a/test/prism/errors/invalid_multi_target_18.txt b/test/prism/errors/invalid_multi_target_18.txt
new file mode 100644
index 0000000000..2beed193b4
--- /dev/null
+++ b/test/prism/errors/invalid_multi_target_18.txt
@@ -0,0 +1,3 @@
+foo(((foo, bar), *))
+ ^~~~~~~~~~~~~~~ unexpected write target
+
diff --git a/test/prism/errors/invalid_multi_target_19.txt b/test/prism/errors/invalid_multi_target_19.txt
new file mode 100644
index 0000000000..b5e3e6999a
--- /dev/null
+++ b/test/prism/errors/invalid_multi_target_19.txt
@@ -0,0 +1,3 @@
+(foo, bar) + 1
+^~~~~~~~~~ unexpected write target
+
diff --git a/test/prism/errors/invalid_multi_target_2.txt b/test/prism/errors/invalid_multi_target_2.txt
new file mode 100644
index 0000000000..68a7bbc305
--- /dev/null
+++ b/test/prism/errors/invalid_multi_target_2.txt
@@ -0,0 +1,3 @@
+foo = 1; foo,
+ ^~~ unexpected write target
+
diff --git a/test/prism/errors/invalid_multi_target_20.txt b/test/prism/errors/invalid_multi_target_20.txt
new file mode 100644
index 0000000000..e800bcf204
--- /dev/null
+++ b/test/prism/errors/invalid_multi_target_20.txt
@@ -0,0 +1,3 @@
+(foo, bar) in baz
+^~~~~~~~~~ unexpected write target
+
diff --git a/test/prism/errors/invalid_multi_target_3.txt b/test/prism/errors/invalid_multi_target_3.txt
new file mode 100644
index 0000000000..51e6207603
--- /dev/null
+++ b/test/prism/errors/invalid_multi_target_3.txt
@@ -0,0 +1,3 @@
+foo.bar,
+^~~~~~~ unexpected write target
+
diff --git a/test/prism/errors/invalid_multi_target_4.txt b/test/prism/errors/invalid_multi_target_4.txt
new file mode 100644
index 0000000000..f4c3599ffe
--- /dev/null
+++ b/test/prism/errors/invalid_multi_target_4.txt
@@ -0,0 +1,3 @@
+*foo,
+^~~~ unexpected write target
+
diff --git a/test/prism/errors/invalid_multi_target_5.txt b/test/prism/errors/invalid_multi_target_5.txt
new file mode 100644
index 0000000000..5d143a3f5d
--- /dev/null
+++ b/test/prism/errors/invalid_multi_target_5.txt
@@ -0,0 +1,3 @@
+@foo,
+^~~~ unexpected write target
+
diff --git a/test/prism/errors/invalid_multi_target_6.txt b/test/prism/errors/invalid_multi_target_6.txt
new file mode 100644
index 0000000000..6d15893f57
--- /dev/null
+++ b/test/prism/errors/invalid_multi_target_6.txt
@@ -0,0 +1,3 @@
+@@foo,
+^~~~~ unexpected write target
+
diff --git a/test/prism/errors/invalid_multi_target_7.txt b/test/prism/errors/invalid_multi_target_7.txt
new file mode 100644
index 0000000000..451f9f0a00
--- /dev/null
+++ b/test/prism/errors/invalid_multi_target_7.txt
@@ -0,0 +1,3 @@
+$foo,
+^~~~ unexpected write target
+
diff --git a/test/prism/errors/invalid_multi_target_8.txt b/test/prism/errors/invalid_multi_target_8.txt
new file mode 100644
index 0000000000..fdbe272f9a
--- /dev/null
+++ b/test/prism/errors/invalid_multi_target_8.txt
@@ -0,0 +1,4 @@
+$1,
+^~ Can't set variable $1
+^~ unexpected write target
+
diff --git a/test/prism/errors/invalid_multi_target_9.txt b/test/prism/errors/invalid_multi_target_9.txt
new file mode 100644
index 0000000000..038f355c5d
--- /dev/null
+++ b/test/prism/errors/invalid_multi_target_9.txt
@@ -0,0 +1,4 @@
+$+,
+^~ Can't set variable $+
+^~ unexpected write target
+
diff --git a/test/prism/errors/invalid_number_underscores.txt b/test/prism/errors/invalid_number_underscores.txt
new file mode 100644
index 0000000000..8fc79ed7a2
--- /dev/null
+++ b/test/prism/errors/invalid_number_underscores.txt
@@ -0,0 +1,3 @@
+1__1
+ ^ invalid underscore placement in number
+
diff --git a/test/prism/errors/invalid_number_underscores_10.txt b/test/prism/errors/invalid_number_underscores_10.txt
new file mode 100644
index 0000000000..53b0cc0719
--- /dev/null
+++ b/test/prism/errors/invalid_number_underscores_10.txt
@@ -0,0 +1,3 @@
+01_1_
+ ^ trailing '_' in number
+
diff --git a/test/prism/errors/invalid_number_underscores_11.txt b/test/prism/errors/invalid_number_underscores_11.txt
new file mode 100644
index 0000000000..469110f86f
--- /dev/null
+++ b/test/prism/errors/invalid_number_underscores_11.txt
@@ -0,0 +1,3 @@
+0d1_1_
+ ^ trailing '_' in number
+
diff --git a/test/prism/errors/invalid_number_underscores_12.txt b/test/prism/errors/invalid_number_underscores_12.txt
new file mode 100644
index 0000000000..a9b63a4b6c
--- /dev/null
+++ b/test/prism/errors/invalid_number_underscores_12.txt
@@ -0,0 +1,3 @@
+0x1_1_
+ ^ trailing '_' in number
+
diff --git a/test/prism/errors/invalid_number_underscores_2.txt b/test/prism/errors/invalid_number_underscores_2.txt
new file mode 100644
index 0000000000..2762e08790
--- /dev/null
+++ b/test/prism/errors/invalid_number_underscores_2.txt
@@ -0,0 +1,3 @@
+0b1__1
+ ^ invalid underscore placement in number
+
diff --git a/test/prism/errors/invalid_number_underscores_3.txt b/test/prism/errors/invalid_number_underscores_3.txt
new file mode 100644
index 0000000000..23f1e0b10b
--- /dev/null
+++ b/test/prism/errors/invalid_number_underscores_3.txt
@@ -0,0 +1,3 @@
+0o1__1
+ ^ invalid underscore placement in number
+
diff --git a/test/prism/errors/invalid_number_underscores_4.txt b/test/prism/errors/invalid_number_underscores_4.txt
new file mode 100644
index 0000000000..ced149752f
--- /dev/null
+++ b/test/prism/errors/invalid_number_underscores_4.txt
@@ -0,0 +1,3 @@
+01__1
+ ^ invalid underscore placement in number
+
diff --git a/test/prism/errors/invalid_number_underscores_5.txt b/test/prism/errors/invalid_number_underscores_5.txt
new file mode 100644
index 0000000000..5e3f2bf682
--- /dev/null
+++ b/test/prism/errors/invalid_number_underscores_5.txt
@@ -0,0 +1,3 @@
+0d1__1
+ ^ invalid underscore placement in number
+
diff --git a/test/prism/errors/invalid_number_underscores_6.txt b/test/prism/errors/invalid_number_underscores_6.txt
new file mode 100644
index 0000000000..225b654248
--- /dev/null
+++ b/test/prism/errors/invalid_number_underscores_6.txt
@@ -0,0 +1,3 @@
+0x1__1
+ ^ invalid underscore placement in number
+
diff --git a/test/prism/errors/invalid_number_underscores_7.txt b/test/prism/errors/invalid_number_underscores_7.txt
new file mode 100644
index 0000000000..d953b4cbc4
--- /dev/null
+++ b/test/prism/errors/invalid_number_underscores_7.txt
@@ -0,0 +1,3 @@
+1_1_
+ ^ trailing '_' in number
+
diff --git a/test/prism/errors/invalid_number_underscores_8.txt b/test/prism/errors/invalid_number_underscores_8.txt
new file mode 100644
index 0000000000..cbdcd95d8f
--- /dev/null
+++ b/test/prism/errors/invalid_number_underscores_8.txt
@@ -0,0 +1,3 @@
+0b1_1_
+ ^ trailing '_' in number
+
diff --git a/test/prism/errors/invalid_number_underscores_9.txt b/test/prism/errors/invalid_number_underscores_9.txt
new file mode 100644
index 0000000000..173282ffb2
--- /dev/null
+++ b/test/prism/errors/invalid_number_underscores_9.txt
@@ -0,0 +1,3 @@
+0o1_1_
+ ^ trailing '_' in number
+
diff --git a/test/prism/errors/invalid_operator_write_dot.txt b/test/prism/errors/invalid_operator_write_dot.txt
new file mode 100644
index 0000000000..666817e60f
--- /dev/null
+++ b/test/prism/errors/invalid_operator_write_dot.txt
@@ -0,0 +1,3 @@
+foo.+= 1
+ ^ unexpected write target
+
diff --git a/test/prism/errors/invalid_operator_write_fcall.txt b/test/prism/errors/invalid_operator_write_fcall.txt
new file mode 100644
index 0000000000..2748bf3291
--- /dev/null
+++ b/test/prism/errors/invalid_operator_write_fcall.txt
@@ -0,0 +1,3 @@
+foo! += 1
+^~~~ unexpected write target
+
diff --git a/test/prism/errors/it_with_ordinary_parameter.txt b/test/prism/errors/it_with_ordinary_parameter.txt
new file mode 100644
index 0000000000..0fc34e9cc8
--- /dev/null
+++ b/test/prism/errors/it_with_ordinary_parameter.txt
@@ -0,0 +1,3 @@
+proc { || it }
+ ^~ `it` is not allowed when an ordinary parameter is defined
+
diff --git a/test/prism/errors/keywords_parameters_before_required_parameters.txt b/test/prism/errors/keywords_parameters_before_required_parameters.txt
new file mode 100644
index 0000000000..42d036e950
--- /dev/null
+++ b/test/prism/errors/keywords_parameters_before_required_parameters.txt
@@ -0,0 +1,4 @@
+def foo(b:, a)
+ ^ unexpected parameter order
+end
+
diff --git a/test/prism/errors/loop_conditional_is_closed.txt b/test/prism/errors/loop_conditional_is_closed.txt
new file mode 100644
index 0000000000..2be1353319
--- /dev/null
+++ b/test/prism/errors/loop_conditional_is_closed.txt
@@ -0,0 +1,4 @@
+while 0 0; foo; end; until 0 0; foo; end
+ ^ expected a predicate expression for the `while` statement
+ ^ expected a predicate expression for the `until` statement
+
diff --git a/test/prism/errors/match_plus.txt b/test/prism/errors/match_plus.txt
new file mode 100644
index 0000000000..5e349a96ad
--- /dev/null
+++ b/test/prism/errors/match_plus.txt
@@ -0,0 +1,7 @@
+a in b + c
+ ^ unexpected '+', expecting end-of-input
+ ^ unexpected '+', ignoring it
+a => b + c
+ ^ unexpected '+', expecting end-of-input
+ ^ unexpected '+', ignoring it
+
diff --git a/test/prism/errors/method_parameters_after_arguments_forwarding.txt b/test/prism/errors/method_parameters_after_arguments_forwarding.txt
new file mode 100644
index 0000000000..ec2aefda1d
--- /dev/null
+++ b/test/prism/errors/method_parameters_after_arguments_forwarding.txt
@@ -0,0 +1,4 @@
+def foo(..., a)
+ ^ unexpected parameter order
+end
+
diff --git a/test/prism/errors/method_parameters_after_block.txt b/test/prism/errors/method_parameters_after_block.txt
new file mode 100644
index 0000000000..6e2091d5d1
--- /dev/null
+++ b/test/prism/errors/method_parameters_after_block.txt
@@ -0,0 +1,4 @@
+def foo(&block, a)
+ ^ unexpected parameter order
+end
+
diff --git a/test/prism/errors/method_with_arguments_after_anonymous_block.txt b/test/prism/errors/method_with_arguments_after_anonymous_block.txt
new file mode 100644
index 0000000000..0d986b3c01
--- /dev/null
+++ b/test/prism/errors/method_with_arguments_after_anonymous_block.txt
@@ -0,0 +1,4 @@
+def foo(&, a)
+ ^ unexpected parameter order
+end
+
diff --git a/test/prism/errors/missing_terminator_in_parentheses.txt b/test/prism/errors/missing_terminator_in_parentheses.txt
new file mode 100644
index 0000000000..af4b698f0c
--- /dev/null
+++ b/test/prism/errors/missing_terminator_in_parentheses.txt
@@ -0,0 +1,3 @@
+(0 0)
+ ^ unexpected integer, expecting end-of-input
+
diff --git a/test/prism/errors/module_definition_in_method_body.txt b/test/prism/errors/module_definition_in_method_body.txt
new file mode 100644
index 0000000000..59900c96dd
--- /dev/null
+++ b/test/prism/errors/module_definition_in_method_body.txt
@@ -0,0 +1,3 @@
+def foo;module A;end;end
+ ^~~~~~ unexpected module definition in method body
+
diff --git a/test/prism/errors/module_definition_in_method_body_within_block.txt b/test/prism/errors/module_definition_in_method_body_within_block.txt
new file mode 100644
index 0000000000..204be35607
--- /dev/null
+++ b/test/prism/errors/module_definition_in_method_body_within_block.txt
@@ -0,0 +1,7 @@
+def foo
+ bar do
+ module Foo;end
+ ^~~~~~ unexpected module definition in method body
+ end
+end
+
diff --git a/test/prism/errors/module_definition_in_method_defs.txt b/test/prism/errors/module_definition_in_method_defs.txt
new file mode 100644
index 0000000000..c5a6a8a2e8
--- /dev/null
+++ b/test/prism/errors/module_definition_in_method_defs.txt
@@ -0,0 +1,7 @@
+def foo(bar = module A;end);end
+ ^~~~~~ unexpected module definition in method body
+def foo;rescue;module A;end;end
+ ^~~~~~ unexpected module definition in method body
+def foo;ensure;module A;end;end
+ ^~~~~~ unexpected module definition in method body
+
diff --git a/test/prism/errors/module_name_recoverable.txt b/test/prism/errors/module_name_recoverable.txt
new file mode 100644
index 0000000000..58a28a60c5
--- /dev/null
+++ b/test/prism/errors/module_name_recoverable.txt
@@ -0,0 +1,4 @@
+module Parent module end
+ ^~~~~~ unexpected constant path after `module`; class/module name must be CONSTANT
+ ^~~ unexpected 'end', assuming it is closing the parent module definition
+
diff --git a/test/prism/errors/multiple_error_in_parameters_order.txt b/test/prism/errors/multiple_error_in_parameters_order.txt
new file mode 100644
index 0000000000..5dae0a105a
--- /dev/null
+++ b/test/prism/errors/multiple_error_in_parameters_order.txt
@@ -0,0 +1,5 @@
+def foo(**args, a, b:)
+ ^ unexpected parameter order
+ ^~ unexpected parameter order
+end
+
diff --git a/test/prism/errors/next_1.txt b/test/prism/errors/next_1.txt
new file mode 100644
index 0000000000..b56b7f6ae6
--- /dev/null
+++ b/test/prism/errors/next_1.txt
@@ -0,0 +1,4 @@
+next 1,;
+ ^ expected an argument
+^~~~~~~ Invalid next
+
diff --git a/test/prism/errors/next_1_2_3.txt b/test/prism/errors/next_1_2_3.txt
new file mode 100644
index 0000000000..7abe577ab3
--- /dev/null
+++ b/test/prism/errors/next_1_2_3.txt
@@ -0,0 +1,8 @@
+next(1, 2, 3)
+ ^ unexpected ',', expecting end-of-input
+ ^ unexpected ',', ignoring it
+ ^ expected a matching `)`
+ ^ unexpected ')', expecting end-of-input
+ ^ unexpected ')', ignoring it
+^~~~~~~~~~~~ Invalid next
+
diff --git a/test/prism/errors/non_assoc_equality.txt b/test/prism/errors/non_assoc_equality.txt
new file mode 100644
index 0000000000..6ce8da88d6
--- /dev/null
+++ b/test/prism/errors/non_assoc_equality.txt
@@ -0,0 +1,19 @@
+1 == 2 == 3
+ ^~ unexpected '==', expecting end-of-input
+ ^~ unexpected '==', ignoring it
+1 != 2 != 3
+ ^~ unexpected '!=', expecting end-of-input
+ ^~ unexpected '!=', ignoring it
+1 === 2 === 3
+ ^~~ unexpected '===', expecting end-of-input
+ ^~~ unexpected '===', ignoring it
+1 =~ 2 =~ 3
+ ^~ unexpected '=~', expecting end-of-input
+ ^~ unexpected '=~', ignoring it
+1 !~ 2 !~ 3
+ ^~ unexpected '!~', expecting end-of-input
+ ^~ unexpected '!~', ignoring it
+1 <=> 2 <=> 3
+ ^~~ unexpected '<=>', expecting end-of-input
+ ^~~ unexpected '<=>', ignoring it
+
diff --git a/test/prism/errors/non_assoc_range.txt b/test/prism/errors/non_assoc_range.txt
new file mode 100644
index 0000000000..072cf6d3c6
--- /dev/null
+++ b/test/prism/errors/non_assoc_range.txt
@@ -0,0 +1,4 @@
+1....2
+ ^ unexpected '.', expecting end-of-input
+ ^ unexpected '.', ignoring it
+
diff --git a/test/prism/errors/numbered_parameters_in_block_arguments.txt b/test/prism/errors/numbered_parameters_in_block_arguments.txt
new file mode 100644
index 0000000000..d01999c53e
--- /dev/null
+++ b/test/prism/errors/numbered_parameters_in_block_arguments.txt
@@ -0,0 +1,3 @@
+foo { |_1| }
+ ^~ _1 is reserved for numbered parameters
+
diff --git a/test/prism/errors/optional_block_parameters_with_unary_operator.txt b/test/prism/errors/optional_block_parameters_with_unary_operator.txt
new file mode 100644
index 0000000000..fd45f12648
--- /dev/null
+++ b/test/prism/errors/optional_block_parameters_with_unary_operator.txt
@@ -0,0 +1,3 @@
+foo { |a = +b| }
+ ^ unexpected '+'; unary calls are not allowed in this context
+
diff --git a/test/prism/errors/optional_block_parameters_with_unary_operator_2.txt b/test/prism/errors/optional_block_parameters_with_unary_operator_2.txt
new file mode 100644
index 0000000000..ba98f36f84
--- /dev/null
+++ b/test/prism/errors/optional_block_parameters_with_unary_operator_2.txt
@@ -0,0 +1,3 @@
+foo { |a = -b| }
+ ^ unexpected '-'; unary calls are not allowed in this context
+
diff --git a/test/prism/errors/optional_block_parameters_with_unary_operator_3.txt b/test/prism/errors/optional_block_parameters_with_unary_operator_3.txt
new file mode 100644
index 0000000000..9770059891
--- /dev/null
+++ b/test/prism/errors/optional_block_parameters_with_unary_operator_3.txt
@@ -0,0 +1,3 @@
+foo { |a = !b| }
+ ^ unexpected '!'; unary calls are not allowed in this context
+
diff --git a/test/prism/errors/optional_block_parameters_with_unary_operator_4.txt b/test/prism/errors/optional_block_parameters_with_unary_operator_4.txt
new file mode 100644
index 0000000000..9bec68d7b3
--- /dev/null
+++ b/test/prism/errors/optional_block_parameters_with_unary_operator_4.txt
@@ -0,0 +1,3 @@
+foo { |a = ~b| }
+ ^ unexpected '~'; unary calls are not allowed in this context
+
diff --git a/test/prism/errors/parameter_name_ending_with_bang_or_question_mark.txt b/test/prism/errors/parameter_name_ending_with_bang_or_question_mark.txt
new file mode 100644
index 0000000000..db4fd6928a
--- /dev/null
+++ b/test/prism/errors/parameter_name_ending_with_bang_or_question_mark.txt
@@ -0,0 +1,4 @@
+def foo(x!,y?); end
+ ^~ unexpected name for a parameter
+ ^~ unexpected name for a parameter
+
diff --git a/test/prism/errors/pre_execution_context.txt b/test/prism/errors/pre_execution_context.txt
new file mode 100644
index 0000000000..18b11bae97
--- /dev/null
+++ b/test/prism/errors/pre_execution_context.txt
@@ -0,0 +1,4 @@
+BEGIN { 1 + }
+ ^ unexpected '}'; expected an expression after the operator
+ ^ unexpected '}', assuming it is closing the parent 'BEGIN' block
+
diff --git a/test/prism/errors/pre_execution_missing_brace.txt b/test/prism/errors/pre_execution_missing_brace.txt
new file mode 100644
index 0000000000..e51cd0732e
--- /dev/null
+++ b/test/prism/errors/pre_execution_missing_brace.txt
@@ -0,0 +1,3 @@
+BEGIN 1 }
+ ^ expected a `{` after `BEGIN`
+
diff --git a/test/prism/errors/range_and_bin_op.txt b/test/prism/errors/range_and_bin_op.txt
new file mode 100644
index 0000000000..4a7a396d0d
--- /dev/null
+++ b/test/prism/errors/range_and_bin_op.txt
@@ -0,0 +1,4 @@
+1..2..3
+ ^~ unexpected .., expecting end-of-input
+ ^~ unexpected .., ignoring it
+
diff --git a/test/prism/errors/range_and_bin_op_2.txt b/test/prism/errors/range_and_bin_op_2.txt
new file mode 100644
index 0000000000..f2a31dcf82
--- /dev/null
+++ b/test/prism/errors/range_and_bin_op_2.txt
@@ -0,0 +1,4 @@
+1..2..
+ ^~ unexpected .., expecting end-of-input
+ ^~ unexpected .., ignoring it
+
diff --git a/test/prism/errors/range_and_bin_op_3.txt b/test/prism/errors/range_and_bin_op_3.txt
new file mode 100644
index 0000000000..34390d0776
--- /dev/null
+++ b/test/prism/errors/range_and_bin_op_3.txt
@@ -0,0 +1,3 @@
+1.. || 2
+ ^ unexpected '|'; expected an expression after the operator
+
diff --git a/test/prism/errors/range_and_bin_op_4.txt b/test/prism/errors/range_and_bin_op_4.txt
new file mode 100644
index 0000000000..56226480cf
--- /dev/null
+++ b/test/prism/errors/range_and_bin_op_4.txt
@@ -0,0 +1,4 @@
+1.. & 2
+ ^ unexpected '&', expecting end-of-input
+ ^ unexpected '&', ignoring it
+
diff --git a/test/prism/errors/range_and_bin_op_5.txt b/test/prism/errors/range_and_bin_op_5.txt
new file mode 100644
index 0000000000..bc8b467914
--- /dev/null
+++ b/test/prism/errors/range_and_bin_op_5.txt
@@ -0,0 +1,5 @@
+1.. * 2
+ ^ unexpected *, expecting end-of-input
+ ^ unexpected write target
+ ^~~ unexpected write target
+
diff --git a/test/prism/errors/range_and_bin_op_6.txt b/test/prism/errors/range_and_bin_op_6.txt
new file mode 100644
index 0000000000..5cdd7a4f44
--- /dev/null
+++ b/test/prism/errors/range_and_bin_op_6.txt
@@ -0,0 +1,3 @@
+1.. / 2
+ ^ unterminated regexp meets end of file; expected a closing delimiter
+
diff --git a/test/prism/errors/range_and_bin_op_7.txt b/test/prism/errors/range_and_bin_op_7.txt
new file mode 100644
index 0000000000..3f91b5e97f
--- /dev/null
+++ b/test/prism/errors/range_and_bin_op_7.txt
@@ -0,0 +1,3 @@
+1.. % 2
+ ^ unterminated string meets end of file
+
diff --git a/test/prism/errors/range_and_bin_op_8.txt b/test/prism/errors/range_and_bin_op_8.txt
new file mode 100644
index 0000000000..afbf3719d5
--- /dev/null
+++ b/test/prism/errors/range_and_bin_op_8.txt
@@ -0,0 +1,4 @@
+1.. ** 2
+ ^~ unexpected **, expecting end-of-input
+ ^~ unexpected **, ignoring it
+
diff --git a/test/prism/errors/rational_number_with_exponential_portion.txt b/test/prism/errors/rational_number_with_exponential_portion.txt
new file mode 100644
index 0000000000..01a03d538f
--- /dev/null
+++ b/test/prism/errors/rational_number_with_exponential_portion.txt
@@ -0,0 +1,4 @@
+1e1r; 1e1ri
+ ^ unexpected local variable or method, expecting end-of-input
+ ^~ unexpected local variable or method, expecting end-of-input
+
diff --git a/test/prism/errors/regexp_unicode_too_short.txt b/test/prism/errors/regexp_unicode_too_short.txt
new file mode 100644
index 0000000000..b6504ec9f9
--- /dev/null
+++ b/test/prism/errors/regexp_unicode_too_short.txt
@@ -0,0 +1,4 @@
+/\u
+ ^~ too short escape sequence: \u
+^ unterminated regexp meets end of file; expected a closing delimiter
+
diff --git a/test/prism/errors/regular_expression_with_unknown_regexp_options.txt b/test/prism/errors/regular_expression_with_unknown_regexp_options.txt
new file mode 100644
index 0000000000..c37291ca40
--- /dev/null
+++ b/test/prism/errors/regular_expression_with_unknown_regexp_options.txt
@@ -0,0 +1,3 @@
+/foo/AZaz
+ ^~~~~ unknown regexp options - AZaz
+
diff --git a/test/prism/errors/repeated_parameter_name_in_destructured_params.txt b/test/prism/errors/repeated_parameter_name_in_destructured_params.txt
new file mode 100644
index 0000000000..766c235325
--- /dev/null
+++ b/test/prism/errors/repeated_parameter_name_in_destructured_params.txt
@@ -0,0 +1,3 @@
+def f(a, (b, (a))); end
+ ^ duplicated argument name
+
diff --git a/test/prism/errors/rest_keywords_parameters_before_required_parameters.txt b/test/prism/errors/rest_keywords_parameters_before_required_parameters.txt
new file mode 100644
index 0000000000..406f326712
--- /dev/null
+++ b/test/prism/errors/rest_keywords_parameters_before_required_parameters.txt
@@ -0,0 +1,4 @@
+def foo(**rest, b:)
+ ^~ unexpected parameter order
+end
+
diff --git a/test/prism/errors/return_1.txt b/test/prism/errors/return_1.txt
new file mode 100644
index 0000000000..b4ce8f1f2a
--- /dev/null
+++ b/test/prism/errors/return_1.txt
@@ -0,0 +1,3 @@
+return 1,;
+ ^ expected an argument
+
diff --git a/test/prism/errors/return_1_2_3.txt b/test/prism/errors/return_1_2_3.txt
new file mode 100644
index 0000000000..8f6dbaf194
--- /dev/null
+++ b/test/prism/errors/return_1_2_3.txt
@@ -0,0 +1,7 @@
+return(1, 2, 3)
+ ^ unexpected ',', expecting end-of-input
+ ^ unexpected ',', ignoring it
+ ^ expected a matching `)`
+ ^ unexpected ')', expecting end-of-input
+ ^ unexpected ')', ignoring it
+
diff --git a/test/prism/errors/returning_to_optional_parameters_multiple_times.txt b/test/prism/errors/returning_to_optional_parameters_multiple_times.txt
new file mode 100644
index 0000000000..83ca731850
--- /dev/null
+++ b/test/prism/errors/returning_to_optional_parameters_multiple_times.txt
@@ -0,0 +1,4 @@
+def foo(a, b = 1, c, d = 2, e)
+ ^ unexpected parameter order
+end
+
diff --git a/test/prism/errors/semicolon_after_inheritance_operator.txt b/test/prism/errors/semicolon_after_inheritance_operator.txt
new file mode 100644
index 0000000000..6b67e6048a
--- /dev/null
+++ b/test/prism/errors/semicolon_after_inheritance_operator.txt
@@ -0,0 +1,3 @@
+class Foo < Bar end
+ ^ unexpected `end`, expecting ';' or '\n'
+
diff --git a/test/prism/errors/setter_method_cannot_be_defined_in_an_endless_method_definition.txt b/test/prism/errors/setter_method_cannot_be_defined_in_an_endless_method_definition.txt
new file mode 100644
index 0000000000..c4440ccc7e
--- /dev/null
+++ b/test/prism/errors/setter_method_cannot_be_defined_in_an_endless_method_definition.txt
@@ -0,0 +1,3 @@
+def a=() = 42
+ ^~ invalid method name; a setter method cannot be defined in an endless method definition
+
diff --git a/test/prism/errors/shadow_args_in_block.txt b/test/prism/errors/shadow_args_in_block.txt
new file mode 100644
index 0000000000..1e7d5f9cd4
--- /dev/null
+++ b/test/prism/errors/shadow_args_in_block.txt
@@ -0,0 +1,3 @@
+tap{|a;a|}
+ ^ duplicated argument name
+
diff --git a/test/prism/errors/shadow_args_in_lambda.txt b/test/prism/errors/shadow_args_in_lambda.txt
new file mode 100644
index 0000000000..2399a0ebd5
--- /dev/null
+++ b/test/prism/errors/shadow_args_in_lambda.txt
@@ -0,0 +1,5 @@
+->a;b{}
+ ^ expected a `do` keyword or a `{` to open the lambda block
+ ^ unexpected end-of-input, assuming it is closing the parent top level context
+ ^ expected a lambda block beginning with `do` to end with `end`
+
diff --git a/test/prism/errors/singleton_method_for_literals.txt b/test/prism/errors/singleton_method_for_literals.txt
new file mode 100644
index 0000000000..6247b4f025
--- /dev/null
+++ b/test/prism/errors/singleton_method_for_literals.txt
@@ -0,0 +1,39 @@
+def (1).g; end
+ ^ cannot define singleton method for literals
+def ((a; 1)).foo; end
+ ^ cannot define singleton method for literals
+def ((return; 1)).bar; end
+ ^ cannot define singleton method for literals
+def (((1))).foo; end
+ ^ cannot define singleton method for literals
+def (__FILE__).foo; end
+ ^~~~~~~~ cannot define singleton method for literals
+def (__ENCODING__).foo; end
+ ^~~~~~~~~~~~ cannot define singleton method for literals
+def (__LINE__).foo; end
+ ^~~~~~~~ cannot define singleton method for literals
+def ("foo").foo; end
+ ^~~~~ cannot define singleton method for literals
+def (3.14).foo; end
+ ^~~~ cannot define singleton method for literals
+def (3.14i).foo; end
+ ^~~~~ cannot define singleton method for literals
+def (:foo).foo; end
+ ^~~~ cannot define singleton method for literals
+def (:'foo').foo; end
+ ^~~~~~ cannot define singleton method for literals
+def (:'f{o}').foo; end
+ ^~~~~~~ cannot define singleton method for literals
+def ('foo').foo; end
+ ^~~~~ cannot define singleton method for literals
+def ("foo").foo; end
+ ^~~~~ cannot define singleton method for literals
+def ("#{fo}o").foo; end
+ ^~~~~~~~ cannot define singleton method for literals
+def (/foo/).foo; end
+ ^~~~~ cannot define singleton method for literals
+def (/f#{oo}/).foo; end
+ ^~~~~~~~ cannot define singleton method for literals
+def ([1]).foo; end
+ ^~~ cannot define singleton method for literals
+
diff --git a/test/prism/errors/splat_argument_after_keyword_argument.txt b/test/prism/errors/splat_argument_after_keyword_argument.txt
new file mode 100644
index 0000000000..fd2dbd0003
--- /dev/null
+++ b/test/prism/errors/splat_argument_after_keyword_argument.txt
@@ -0,0 +1,3 @@
+a(foo: bar, *args)
+ ^~~~~ unexpected `*` splat argument after a `**` keyword splat argument
+
diff --git a/test/prism/errors/statement_at_non_statement.txt b/test/prism/errors/statement_at_non_statement.txt
new file mode 100644
index 0000000000..40fe7d862e
--- /dev/null
+++ b/test/prism/errors/statement_at_non_statement.txt
@@ -0,0 +1,9 @@
+foo(alias x y)
+ ^~~~~ unexpected an `alias` at a non-statement position
+foo(BEGIN { bar })
+ ^~~~~ unexpected a `BEGIN` at a non-statement position
+foo(END { bar })
+ ^~~ unexpected an `END` at a non-statement position
+foo(undef x)
+ ^~~~~ unexpected an `undef` at a non-statement position
+
diff --git a/test/prism/errors/statement_operators.txt b/test/prism/errors/statement_operators.txt
new file mode 100644
index 0000000000..04b7c57477
--- /dev/null
+++ b/test/prism/errors/statement_operators.txt
@@ -0,0 +1,25 @@
+alias x y + 1
+ ^ unexpected '+', expecting end-of-input
+ ^ unexpected '+', ignoring it
+alias x y.z
+ ^ unexpected '.', expecting end-of-input
+ ^ unexpected '.', ignoring it
+BEGIN { bar } + 1
+ ^ unexpected '+', expecting end-of-input
+ ^ unexpected '+', ignoring it
+BEGIN { bar }.z
+ ^ unexpected '.', expecting end-of-input
+ ^ unexpected '.', ignoring it
+END { bar } + 1
+ ^ unexpected '+', expecting end-of-input
+ ^ unexpected '+', ignoring it
+END { bar }.z
+ ^ unexpected '.', expecting end-of-input
+ ^ unexpected '.', ignoring it
+undef x + 1
+ ^ unexpected '+', expecting end-of-input
+ ^ unexpected '+', ignoring it
+undef x.z
+ ^ unexpected '.', expecting end-of-input
+ ^ unexpected '.', ignoring it
+
diff --git a/test/prism/errors/switching_to_named_arguments_twice.txt b/test/prism/errors/switching_to_named_arguments_twice.txt
new file mode 100644
index 0000000000..5dae0a105a
--- /dev/null
+++ b/test/prism/errors/switching_to_named_arguments_twice.txt
@@ -0,0 +1,5 @@
+def foo(**args, a, b:)
+ ^ unexpected parameter order
+ ^~ unexpected parameter order
+end
+
diff --git a/test/prism/errors/switching_to_optional_arguments_twice.txt b/test/prism/errors/switching_to_optional_arguments_twice.txt
new file mode 100644
index 0000000000..5dae0a105a
--- /dev/null
+++ b/test/prism/errors/switching_to_optional_arguments_twice.txt
@@ -0,0 +1,5 @@
+def foo(**args, a, b:)
+ ^ unexpected parameter order
+ ^~ unexpected parameter order
+end
+
diff --git a/test/prism/errors/symbol_in_hash.txt b/test/prism/errors/symbol_in_hash.txt
new file mode 100644
index 0000000000..148040aa61
--- /dev/null
+++ b/test/prism/errors/symbol_in_hash.txt
@@ -0,0 +1,3 @@
+{x:'y':}
+ ^~ unexpected label terminator, expected a string literal terminator
+
diff --git a/test/prism/errors/symbol_in_keyword_parameter.txt b/test/prism/errors/symbol_in_keyword_parameter.txt
new file mode 100644
index 0000000000..22d03cccb2
--- /dev/null
+++ b/test/prism/errors/symbol_in_keyword_parameter.txt
@@ -0,0 +1,3 @@
+def foo(x:'y':); end
+ ^~ unexpected label terminator, expected a string literal terminator
+
diff --git a/test/prism/errors/targeting_numbered_parameter.txt b/test/prism/errors/targeting_numbered_parameter.txt
new file mode 100644
index 0000000000..39c40ad7b9
--- /dev/null
+++ b/test/prism/errors/targeting_numbered_parameter.txt
@@ -0,0 +1,3 @@
+-> { _1, = 0 }
+ ^~ _1 is reserved for numbered parameters
+
diff --git a/test/prism/errors/top_level_constant_starting_with_downcased_identifier.txt b/test/prism/errors/top_level_constant_starting_with_downcased_identifier.txt
new file mode 100644
index 0000000000..b7b54dd74e
--- /dev/null
+++ b/test/prism/errors/top_level_constant_starting_with_downcased_identifier.txt
@@ -0,0 +1,4 @@
+::foo::A
+ ^ expected a constant after the `::` operator
+ ^~~ unexpected local variable or method, expecting end-of-input
+
diff --git a/test/prism/errors/top_level_constant_with_downcased_identifier.txt b/test/prism/errors/top_level_constant_with_downcased_identifier.txt
new file mode 100644
index 0000000000..032bcfaebb
--- /dev/null
+++ b/test/prism/errors/top_level_constant_with_downcased_identifier.txt
@@ -0,0 +1,4 @@
+::foo
+ ^ expected a constant after the `::` operator
+ ^~~ unexpected local variable or method, expecting end-of-input
+
diff --git a/test/prism/errors/trailing_comma_in_calls.txt b/test/prism/errors/trailing_comma_in_calls.txt
new file mode 100644
index 0000000000..44e8a1f0b3
--- /dev/null
+++ b/test/prism/errors/trailing_comma_in_calls.txt
@@ -0,0 +1,3 @@
+foo 1,
+ ^ expected an argument
+
diff --git a/test/prism/errors/unexpected_block.txt b/test/prism/errors/unexpected_block.txt
new file mode 100644
index 0000000000..2c0741cd30
--- /dev/null
+++ b/test/prism/errors/unexpected_block.txt
@@ -0,0 +1,3 @@
+def foo = yield(&:+)
+ ^~~ block argument should not be given
+
diff --git a/test/prism/errors/unterminated_W_list.txt b/test/prism/errors/unterminated_W_list.txt
new file mode 100644
index 0000000000..89cab68abb
--- /dev/null
+++ b/test/prism/errors/unterminated_W_list.txt
@@ -0,0 +1,3 @@
+%w[
+^~~ unterminated list; expected a closing delimiter for the `%w`
+
diff --git a/test/prism/errors/unterminated_argument_expression.txt b/test/prism/errors/unterminated_argument_expression.txt
new file mode 100644
index 0000000000..c250a94bec
--- /dev/null
+++ b/test/prism/errors/unterminated_argument_expression.txt
@@ -0,0 +1,5 @@
+a %
+ ^ unterminated quoted string meets end of file
+ ^ unexpected end-of-input; expected an expression after the operator
+ ^ unexpected end-of-input, assuming it is closing the parent top level context
+
diff --git a/test/prism/errors/unterminated_embdoc.txt b/test/prism/errors/unterminated_embdoc.txt
new file mode 100644
index 0000000000..1dd9ea3ac4
--- /dev/null
+++ b/test/prism/errors/unterminated_embdoc.txt
@@ -0,0 +1,3 @@
+=begin
+^~~~~~ embedded document meets end of file
+
diff --git a/test/prism/errors/unterminated_embdoc_2.txt b/test/prism/errors/unterminated_embdoc_2.txt
new file mode 100644
index 0000000000..1dd9ea3ac4
--- /dev/null
+++ b/test/prism/errors/unterminated_embdoc_2.txt
@@ -0,0 +1,3 @@
+=begin
+^~~~~~ embedded document meets end of file
+
diff --git a/test/prism/errors/unterminated_empty_string.txt b/test/prism/errors/unterminated_empty_string.txt
new file mode 100644
index 0000000000..597102f7ee
--- /dev/null
+++ b/test/prism/errors/unterminated_empty_string.txt
@@ -0,0 +1,3 @@
+"
+ ^ unterminated string meets end of file
+
diff --git a/test/prism/errors/unterminated_global_variable.txt b/test/prism/errors/unterminated_global_variable.txt
new file mode 100644
index 0000000000..ce3e960b2e
--- /dev/null
+++ b/test/prism/errors/unterminated_global_variable.txt
@@ -0,0 +1,3 @@
+$
+^ '$' without identifiers is not allowed as a global variable name
+
diff --git a/test/prism/errors/unterminated_global_variable_2.txt b/test/prism/errors/unterminated_global_variable_2.txt
new file mode 100644
index 0000000000..302293b538
--- /dev/null
+++ b/test/prism/errors/unterminated_global_variable_2.txt
@@ -0,0 +1,3 @@
+$
+^ '$' without identifiers is not allowed as a global variable name
+
diff --git a/test/prism/errors/unterminated_i_list.txt b/test/prism/errors/unterminated_i_list.txt
new file mode 100644
index 0000000000..c48be9971d
--- /dev/null
+++ b/test/prism/errors/unterminated_i_list.txt
@@ -0,0 +1,3 @@
+%i[
+^~~ unterminated list; expected a closing delimiter for the `%i`
+
diff --git a/test/prism/errors/unterminated_interpolated_string.txt b/test/prism/errors/unterminated_interpolated_string.txt
new file mode 100644
index 0000000000..e74a4c9e20
--- /dev/null
+++ b/test/prism/errors/unterminated_interpolated_string.txt
@@ -0,0 +1,3 @@
+"hello
+ ^ unterminated string meets end of file
+
diff --git a/test/prism/errors/unterminated_interpolated_symbol.txt b/test/prism/errors/unterminated_interpolated_symbol.txt
new file mode 100644
index 0000000000..faa7597280
--- /dev/null
+++ b/test/prism/errors/unterminated_interpolated_symbol.txt
@@ -0,0 +1,3 @@
+:"#
+ ^ unterminated symbol; expected a closing delimiter for the interpolated symbol
+
diff --git a/test/prism/errors/unterminated_parenthesized_expression.txt b/test/prism/errors/unterminated_parenthesized_expression.txt
new file mode 100644
index 0000000000..9025eec453
--- /dev/null
+++ b/test/prism/errors/unterminated_parenthesized_expression.txt
@@ -0,0 +1,4 @@
+(1 + 2
+ ^ unexpected end-of-input, assuming it is closing the parent top level context
+ ^ expected a matching `)`
+
diff --git a/test/prism/errors/unterminated_regular_expression.txt b/test/prism/errors/unterminated_regular_expression.txt
new file mode 100644
index 0000000000..48f3a30810
--- /dev/null
+++ b/test/prism/errors/unterminated_regular_expression.txt
@@ -0,0 +1,3 @@
+/hello
+^ unterminated regexp meets end of file; expected a closing delimiter
+
diff --git a/test/prism/errors/unterminated_regular_expression_with_heredoc.txt b/test/prism/errors/unterminated_regular_expression_with_heredoc.txt
new file mode 100644
index 0000000000..d4688d6c9e
--- /dev/null
+++ b/test/prism/errors/unterminated_regular_expression_with_heredoc.txt
@@ -0,0 +1,4 @@
+<<-END + /b
+ ^ unterminated regexp meets end of file; expected a closing delimiter
+END
+
diff --git a/test/prism/errors/unterminated_s_symbol.txt b/test/prism/errors/unterminated_s_symbol.txt
new file mode 100644
index 0000000000..0f4be932b3
--- /dev/null
+++ b/test/prism/errors/unterminated_s_symbol.txt
@@ -0,0 +1,3 @@
+%s[abc
+^~~ unterminated quoted string; expected a closing delimiter for the dynamic symbol
+
diff --git a/test/prism/errors/unterminated_string.txt b/test/prism/errors/unterminated_string.txt
new file mode 100644
index 0000000000..89c0a08b3e
--- /dev/null
+++ b/test/prism/errors/unterminated_string.txt
@@ -0,0 +1,3 @@
+'hello
+^ unterminated string meets end of file
+
diff --git a/test/prism/errors/unterminated_unicode_brackets_should_be_a_syntax_error.txt b/test/prism/errors/unterminated_unicode_brackets_should_be_a_syntax_error.txt
new file mode 100644
index 0000000000..f3ac9f29ab
--- /dev/null
+++ b/test/prism/errors/unterminated_unicode_brackets_should_be_a_syntax_error.txt
@@ -0,0 +1,3 @@
+?\u{3
+ ^~~~ invalid Unicode list: \u{3
+
diff --git a/test/prism/errors/unterminated_xstring.txt b/test/prism/errors/unterminated_xstring.txt
new file mode 100644
index 0000000000..ccd529774c
--- /dev/null
+++ b/test/prism/errors/unterminated_xstring.txt
@@ -0,0 +1,3 @@
+`hello
+^ expected a closing delimiter for the `%x` or backtick string
+
diff --git a/test/prism/errors/void_value_expression_in_arguments.txt b/test/prism/errors/void_value_expression_in_arguments.txt
new file mode 100644
index 0000000000..f57aee1454
--- /dev/null
+++ b/test/prism/errors/void_value_expression_in_arguments.txt
@@ -0,0 +1,17 @@
+foo(return)
+ ^~~~~~ unexpected void value expression
+foo(1, return)
+ ^~~~~~ unexpected void value expression
+foo(*return)
+ ^~~~~~ unexpected void value expression
+foo(**return)
+ ^~~~~~ unexpected void value expression
+foo(&return)
+ ^~~~~~ unexpected void value expression
+foo(return => 1)
+ ^~~~~~ unexpected void value expression
+foo(:a => return)
+ ^~~~~~ unexpected void value expression
+foo(a: return)
+ ^~~~~~ unexpected void value expression
+
diff --git a/test/prism/errors/void_value_expression_in_array.txt b/test/prism/errors/void_value_expression_in_array.txt
new file mode 100644
index 0000000000..a0e86fb135
--- /dev/null
+++ b/test/prism/errors/void_value_expression_in_array.txt
@@ -0,0 +1,15 @@
+[return]
+ ^~~~~~ unexpected void value expression
+[1, return]
+ ^~~~~~ unexpected void value expression
+[ return => 1 ]
+ ^~~~~~ unexpected void value expression
+[ 1 => return ]
+ ^~~~~~ unexpected void value expression
+[ a: return ]
+ ^~~~~~ unexpected void value expression
+[ *return ]
+ ^~~~~~ unexpected void value expression
+[ **return ]
+ ^~~~~~ unexpected void value expression
+
diff --git a/test/prism/errors/void_value_expression_in_assignment.txt b/test/prism/errors/void_value_expression_in_assignment.txt
new file mode 100644
index 0000000000..c651d7f39e
--- /dev/null
+++ b/test/prism/errors/void_value_expression_in_assignment.txt
@@ -0,0 +1,9 @@
+a = return
+ ^~~~~~ unexpected void value expression
+a = 1, return
+ ^~~~~~ unexpected void value expression
+a, b = return, 1
+ ^~~~~~ unexpected void value expression
+a, b = 1, *return
+ ^~~~~~ unexpected void value expression
+
diff --git a/test/prism/errors/void_value_expression_in_begin_statement.txt b/test/prism/errors/void_value_expression_in_begin_statement.txt
new file mode 100644
index 0000000000..4ad40b684d
--- /dev/null
+++ b/test/prism/errors/void_value_expression_in_begin_statement.txt
@@ -0,0 +1,21 @@
+x = return 1
+ ^~~~~~~~ unexpected void value expression
+x = return, 1
+ ^~~~~~ unexpected void value expression
+x = 1, return
+ ^~~~~~ unexpected void value expression
+x, y = return
+ ^~~~~~ unexpected void value expression
+x = begin return ensure end
+ ^~~~~~ unexpected void value expression
+x = begin ensure return end
+ ^~~~~~ unexpected void value expression
+x = begin return ensure return end
+ ^~~~~~ unexpected void value expression
+x = begin return; rescue; return end
+ ^~~~~~ unexpected void value expression
+x = begin return; rescue; return; else return end
+ ^~~~~~ unexpected void value expression
+x = begin; return; rescue; retry; end
+ ^~~~~~ unexpected void value expression
+
diff --git a/test/prism/errors/void_value_expression_in_binary_call.txt b/test/prism/errors/void_value_expression_in_binary_call.txt
new file mode 100644
index 0000000000..096b42be4d
--- /dev/null
+++ b/test/prism/errors/void_value_expression_in_binary_call.txt
@@ -0,0 +1,11 @@
+1 + (return)
+ ^~~~~~ unexpected void value expression
+(return) + 1
+ ^~~~~~ unexpected void value expression
+1 and (return)
+(return) and 1
+ ^~~~~~ unexpected void value expression
+1 or (return)
+(return) or 1
+ ^~~~~~ unexpected void value expression
+
diff --git a/test/prism/errors/void_value_expression_in_call.txt b/test/prism/errors/void_value_expression_in_call.txt
new file mode 100644
index 0000000000..90e6481c4c
--- /dev/null
+++ b/test/prism/errors/void_value_expression_in_call.txt
@@ -0,0 +1,11 @@
+(return).foo
+ ^~~~~~ unexpected void value expression
+(return).(1)
+ ^~~~~~ unexpected void value expression
+(return)[1]
+ ^~~~~~ unexpected void value expression
+(return)[1] = 2
+ ^~~~~~ unexpected void value expression
+(return)::foo
+ ^~~~~~ unexpected void value expression
+
diff --git a/test/prism/errors/void_value_expression_in_constant_path.txt b/test/prism/errors/void_value_expression_in_constant_path.txt
new file mode 100644
index 0000000000..1dab6902a2
--- /dev/null
+++ b/test/prism/errors/void_value_expression_in_constant_path.txt
@@ -0,0 +1,5 @@
+(return)::A
+ ^~~~~~ unexpected void value expression
+class (return)::A; end
+ ^~~~~~ unexpected void value expression
+
diff --git a/test/prism/errors/void_value_expression_in_def.txt b/test/prism/errors/void_value_expression_in_def.txt
new file mode 100644
index 0000000000..fed52a6677
--- /dev/null
+++ b/test/prism/errors/void_value_expression_in_def.txt
@@ -0,0 +1,10 @@
+def (return).x
+ ^~~~~~ unexpected void value expression
+end
+def x(a = return)
+ ^~~~~~ unexpected void value expression
+end
+def x(a: return)
+ ^~~~~~ unexpected void value expression
+end
+
diff --git a/test/prism/errors/void_value_expression_in_expression.txt b/test/prism/errors/void_value_expression_in_expression.txt
new file mode 100644
index 0000000000..f6165a7ba6
--- /dev/null
+++ b/test/prism/errors/void_value_expression_in_expression.txt
@@ -0,0 +1,19 @@
+(return) ? 1 : 1
+ ^~~~~~ unexpected void value expression
+(return)..1
+ ^~~~~~ unexpected void value expression
+1..(return)
+ ^~~~~~ unexpected void value expression
+(return)...1
+ ^~~~~~ unexpected void value expression
+1...(return)
+ ^~~~~~ unexpected void value expression
+(..(return))
+ ^~~~~~ unexpected void value expression
+(...(return))
+ ^~~~~~ unexpected void value expression
+((return)..)
+ ^~~~~~ unexpected void value expression
+((return)...)
+ ^~~~~~ unexpected void value expression
+
diff --git a/test/prism/errors/void_value_expression_in_hash.txt b/test/prism/errors/void_value_expression_in_hash.txt
new file mode 100644
index 0000000000..7795511443
--- /dev/null
+++ b/test/prism/errors/void_value_expression_in_hash.txt
@@ -0,0 +1,9 @@
+{ return => 1 }
+ ^~~~~~ unexpected void value expression
+{ 1 => return }
+ ^~~~~~ unexpected void value expression
+{ a: return }
+ ^~~~~~ unexpected void value expression
+{ **return }
+ ^~~~~~ unexpected void value expression
+
diff --git a/test/prism/errors/void_value_expression_in_modifier.txt b/test/prism/errors/void_value_expression_in_modifier.txt
new file mode 100644
index 0000000000..7d7b444e33
--- /dev/null
+++ b/test/prism/errors/void_value_expression_in_modifier.txt
@@ -0,0 +1,13 @@
+1 if (return)
+ ^~~~~~ unexpected void value expression
+1 unless (return)
+ ^~~~~~ unexpected void value expression
+1 while (return)
+ ^~~~~~ unexpected void value expression
+1 until (return)
+ ^~~~~~ unexpected void value expression
+(return) => a
+ ^~~~~~ unexpected void value expression
+(return) in a
+ ^~~~~~ unexpected void value expression
+
diff --git a/test/prism/errors/void_value_expression_in_statement.txt b/test/prism/errors/void_value_expression_in_statement.txt
new file mode 100644
index 0000000000..87dbfa5cc9
--- /dev/null
+++ b/test/prism/errors/void_value_expression_in_statement.txt
@@ -0,0 +1,26 @@
+if (return)
+ ^~~~~~ unexpected void value expression
+end
+unless (return)
+ ^~~~~~ unexpected void value expression
+end
+while (return)
+ ^~~~~~ unexpected void value expression
+end
+until (return)
+ ^~~~~~ unexpected void value expression
+end
+case (return)
+ ^~~~~~ unexpected void value expression
+when 1
+end
+class A < (return)
+ ^~~~~~ unexpected void value expression
+end
+class << (return)
+ ^~~~~~ unexpected void value expression
+end
+for x in (return)
+ ^~~~~~ unexpected void value expression
+end
+
diff --git a/test/prism/errors/void_value_expression_in_unary_call.txt b/test/prism/errors/void_value_expression_in_unary_call.txt
new file mode 100644
index 0000000000..61e849255c
--- /dev/null
+++ b/test/prism/errors/void_value_expression_in_unary_call.txt
@@ -0,0 +1,5 @@
++(return)
+ ^~~~~~ unexpected void value expression
+not return
+ ^~~~~~ unexpected void value expression
+
diff --git a/test/prism/errors/while_endless_method.txt b/test/prism/errors/while_endless_method.txt
new file mode 100644
index 0000000000..6f062d89d0
--- /dev/null
+++ b/test/prism/errors/while_endless_method.txt
@@ -0,0 +1,5 @@
+while def f = g do end
+ ^ expected a predicate expression for the `while` statement
+ ^ unexpected end-of-input, assuming it is closing the parent top level context
+ ^ expected an `end` to close the `while` statement
+
diff --git a/test/prism/errors/writing_numbered_parameter.txt b/test/prism/errors/writing_numbered_parameter.txt
new file mode 100644
index 0000000000..17dcc6e8f0
--- /dev/null
+++ b/test/prism/errors/writing_numbered_parameter.txt
@@ -0,0 +1,3 @@
+-> { _1 = 0 }
+ ^~ _1 is reserved for numbered parameters
+
diff --git a/test/prism/errors_test.rb b/test/prism/errors_test.rb
new file mode 100644
index 0000000000..f46cb942a2
--- /dev/null
+++ b/test/prism/errors_test.rb
@@ -0,0 +1,101 @@
+# frozen_string_literal: true
+
+require_relative "test_helper"
+
+module Prism
+ class ErrorsTest < TestCase
+ base = File.expand_path("errors", __dir__)
+ filepaths = Dir["*.txt", base: base]
+
+ if RUBY_VERSION < "3.0"
+ filepaths -= [
+ "cannot_assign_to_a_reserved_numbered_parameter.txt",
+ "writing_numbered_parameter.txt",
+ "targeting_numbered_parameter.txt",
+ "defining_numbered_parameter.txt",
+ "defining_numbered_parameter_2.txt",
+ "numbered_parameters_in_block_arguments.txt"
+ ]
+ end
+
+ if RUBY_VERSION < "3.4"
+ filepaths -= ["it_with_ordinary_parameter.txt"]
+ end
+
+ if RUBY_VERSION < "3.4" || RUBY_RELEASE_DATE < "2024-07-24"
+ filepaths -= ["dont_allow_return_inside_sclass_body.txt"]
+ end
+
+ filepaths.each do |filepath|
+ define_method(:"test_#{File.basename(filepath, ".txt")}") do
+ assert_errors(File.join(base, filepath))
+ end
+ end
+
+ def test_embdoc_ending
+ source = <<~RUBY
+ =begin\n=end
+ =begin\n=end\0
+ =begin\n=end\C-d
+ =begin\n=end\C-z
+ RUBY
+
+ source.each_line do |line|
+ assert_valid_syntax(source)
+ assert_predicate Prism.parse(source), :success?
+ end
+ end
+
+ def test_unterminated_string_closing
+ statement = Prism.parse_statement("'hello")
+ assert_equal statement.unescaped, "hello"
+ assert_empty statement.closing
+ end
+
+ def test_unterminated_interpolated_string_closing
+ statement = Prism.parse_statement('"hello')
+ assert_equal statement.unescaped, "hello"
+ assert_empty statement.closing
+ end
+
+ def test_unterminated_empty_string_closing
+ statement = Prism.parse_statement('"')
+ assert_empty statement.unescaped
+ assert_empty statement.closing
+ end
+
+ def test_invalid_message_name
+ assert_equal :"", Prism.parse_statement("+.@foo,+=foo").write_name
+ end
+
+ def test_circular_parameters
+ source = <<~RUBY
+ def foo(bar = bar) = 42
+ def foo(bar: bar) = 42
+ proc { |foo = foo| }
+ proc { |foo: foo| }
+ RUBY
+
+ source.each_line do |line|
+ assert_predicate Prism.parse(line, version: "3.3.0"), :failure?
+ assert_predicate Prism.parse(line), :success?
+ end
+ end
+
+ private
+
+ def assert_errors(filepath)
+ expected = File.read(filepath, binmode: true, external_encoding: Encoding::UTF_8)
+
+ source = expected.lines.grep_v(/^\s*\^/).join.gsub(/\n*\z/, "")
+ refute_valid_syntax(source)
+
+ result = Prism.parse(source)
+ errors = result.errors
+ refute_empty errors, "Expected errors in #{filepath}"
+
+ actual = result.errors_format
+ assert_equal expected, actual, "Expected errors to match for #{filepath}"
+ end
+ end
+end
diff --git a/test/prism/fixtures/alias.txt b/test/prism/fixtures/alias.txt
new file mode 100644
index 0000000000..376dacd7cc
--- /dev/null
+++ b/test/prism/fixtures/alias.txt
@@ -0,0 +1,23 @@
+alias :foo :bar
+
+alias %s[abc] %s[def]
+
+alias :'abc' :'def'
+
+alias :"abc#{1}" :'def'
+
+alias $a $'
+
+alias foo bar
+
+alias $foo $bar
+
+alias foo if
+
+alias foo <=>
+
+alias :== :eql?
+
+alias A B
+
+alias :A :B
diff --git a/test/prism/fixtures/arithmetic.txt b/test/prism/fixtures/arithmetic.txt
new file mode 100644
index 0000000000..b1e1267b95
--- /dev/null
+++ b/test/prism/fixtures/arithmetic.txt
@@ -0,0 +1,13 @@
+foo !bar
+
+-foo*bar
+
++foo**bar
+
+foo ~bar
+
+foo << bar << baz
+
+-1**2
+
+-1.zero?
diff --git a/test/prism/fixtures/arrays.txt b/test/prism/fixtures/arrays.txt
new file mode 100644
index 0000000000..2897189518
--- /dev/null
+++ b/test/prism/fixtures/arrays.txt
@@ -0,0 +1,122 @@
+[*a]
+
+foo[bar, baz] = 1, 2, 3
+
+[a: [:b, :c]]
+
+
+
+[:a, :b,
+:c,1,
+
+
+
+:d,
+]
+
+
+[:a, :b,
+:c,1,
+
+
+
+:d
+
+
+]
+
+[foo => bar]
+
+foo[bar][baz] = qux
+
+foo[bar][baz]
+
+[
+]
+
+foo[bar, baz]
+
+foo[bar, baz] = qux
+
+foo[0], bar[0] = 1, 2
+
+foo[bar[baz] = qux]
+
+foo[bar]
+
+foo[bar] = baz
+
+[**{}]
+
+[**kw]
+
+[1, **kw]
+
+[1, **kw, **{}, **kw]
+
+[
+ foo => bar,
+]
+
+
+%i#one two three#
+
+%w#one two three#
+
+%x#one two three#
+
+
+%i@one two three@
+
+%w@one two three@
+
+%x@one two three@
+
+
+%i{one two three}
+
+%w{one two three}
+
+%x{one two three}
+
+%w[\C:]
+
+foo[] += 1
+
+foo[] ||= 1
+
+foo[] &&= 1
+
+foo.foo[] += 1
+
+foo.foo[] ||= 1
+
+foo.foo[] &&= 1
+
+foo[bar] += 1
+
+foo[bar] ||= 1
+
+foo[bar] &&= 1
+
+foo.foo[bar] += 1
+
+foo.foo[bar] ||= 1
+
+foo.foo[bar] &&= 1
+
+def f(*); a[*]; end
+
+def f(*); a[1, *]; end
+
+def f(*); a[*] = 1; end
+
+def f(*); a[1, *] = 1; end
+
+def f(*); a[*] += 1; end
+
+def f(*); a[1, *] &&= 1; end
+
+def f(*); rescue => a[*]; end
+
+def f(*); rescue => a[1, *]; end
diff --git a/test/prism/fixtures/begin_ensure.txt b/test/prism/fixtures/begin_ensure.txt
new file mode 100644
index 0000000000..6cfb627453
--- /dev/null
+++ b/test/prism/fixtures/begin_ensure.txt
@@ -0,0 +1,21 @@
+begin
+a
+ensure
+b
+end
+
+begin; a; ensure; b; end
+
+begin a
+ ensure b
+ end
+
+begin a; ensure b; end
+
+begin begin:s.l begin ensure Module.new do
+ begin
+ break
+ ensure Module.new do
+ end
+ end
+end end end end
diff --git a/test/prism/fixtures/begin_rescue.txt b/test/prism/fixtures/begin_rescue.txt
new file mode 100644
index 0000000000..0a56fbef9f
--- /dev/null
+++ b/test/prism/fixtures/begin_rescue.txt
@@ -0,0 +1,79 @@
+begin; a; rescue; b; else; c; end
+
+begin; a; rescue; b; else; c; ensure; d; end
+
+begin
+a
+end
+
+begin; a; end
+
+begin a
+ end
+
+begin a; end
+
+begin
+a
+rescue
+b
+rescue
+c
+rescue
+d
+end
+
+begin
+ a
+rescue Exception => ex
+ b
+rescue AnotherException, OneMoreException => ex
+ c
+end
+
+begin
+ a
+rescue Exception => ex
+ b
+ensure
+ b
+end
+
+%!abc!
+
+begin
+a
+rescue
+b
+end
+
+begin;a;rescue;b;end
+
+begin
+a;rescue
+b;end
+
+begin
+a
+rescue Exception
+b
+end
+
+begin
+a
+rescue Exception, CustomException
+b
+end
+
+begin
+ a
+rescue Exception, CustomException => ex
+ b
+end
+
+begin
+ a
+rescue Exception => ex
+ b
+end
+
diff --git a/test/prism/fixtures/blocks.txt b/test/prism/fixtures/blocks.txt
new file mode 100644
index 0000000000..e33d95c150
--- /dev/null
+++ b/test/prism/fixtures/blocks.txt
@@ -0,0 +1,54 @@
+foo[bar] { baz }
+
+foo[bar] do
+baz
+end
+
+x.reduce(0) { |x, memo| memo += x }
+
+foo do end
+
+foo bar, (baz do end)
+
+foo bar do end
+
+foo bar baz do end
+
+foo do |a = b[1]|
+end
+
+foo do
+rescue
+end
+
+foo do
+ bar do
+ baz do
+ end
+ end
+end
+
+foo[bar] { baz }
+
+foo { |x, y = 2, z:| x }
+
+foo { |x| }
+
+fork = 1
+fork do |a|
+end
+
+fork { |a| }
+
+C do
+end
+
+C {}
+
+foo lambda { |
+ a: 1,
+ b: 2
+ |
+}
+
+foo do |bar,| end
diff --git a/test/prism/fixtures/boolean_operators.txt b/test/prism/fixtures/boolean_operators.txt
new file mode 100644
index 0000000000..dd0b9c9f01
--- /dev/null
+++ b/test/prism/fixtures/boolean_operators.txt
@@ -0,0 +1,5 @@
+a &&= b
+
+a += b
+
+a ||= b
diff --git a/test/prism/fixtures/booleans.txt b/test/prism/fixtures/booleans.txt
new file mode 100644
index 0000000000..d9417254b6
--- /dev/null
+++ b/test/prism/fixtures/booleans.txt
@@ -0,0 +1,3 @@
+false
+
+true
diff --git a/test/prism/fixtures/break.txt b/test/prism/fixtures/break.txt
new file mode 100644
index 0000000000..5532322c5c
--- /dev/null
+++ b/test/prism/fixtures/break.txt
@@ -0,0 +1,29 @@
+tap { break }
+
+tap { break (1), (2), (3) }
+
+tap { break 1 }
+
+tap { break 1, 2,
+3 }
+
+tap { break 1, 2, 3 }
+
+tap { break [1, 2, 3] }
+
+tap { break(
+ 1
+ 2
+) }
+
+tap { break() }
+
+tap { break(1) }
+
+foo { break 42 } == 42
+
+foo { |a| break } == 42
+
+while _ && break; end
+
+until _ && break; end
diff --git a/test/prism/fixtures/case.txt b/test/prism/fixtures/case.txt
new file mode 100644
index 0000000000..733e1e54d2
--- /dev/null
+++ b/test/prism/fixtures/case.txt
@@ -0,0 +1,55 @@
+case :hi
+when :hi
+end
+
+case true; when true; puts :hi; when false; puts :bye; end
+
+case; when *foo; end
+
+case :hi
+when :hi
+else
+:b
+end
+
+case this; when FooBar, BazBonk; end
+
+case
+when foo == bar
+end
+
+case
+when a
+else
+ # empty
+end
+
+case type;
+ ;when :b;
+ ; else;
+ end
+
+case ;;;;;;;; when 1; end
+
+case 1 in 2
+when 3
+end
+
+case 1 in 2; when 3; end
+
+case 1 in 2
+in 3
+end
+
+case 1 in 2; in 3; end
+
+case a
+in b if c and d
+ e
+end
+
+1.then do
+ case 1
+ in ^_1
+ end
+end
diff --git a/test/prism/fixtures/classes.txt b/test/prism/fixtures/classes.txt
new file mode 100644
index 0000000000..056cb00e82
--- /dev/null
+++ b/test/prism/fixtures/classes.txt
@@ -0,0 +1,35 @@
+class A a = 1 end
+
+class A; ensure; end
+
+class A; rescue; else; ensure; end
+
+class A < B
+a = 1
+end
+
+class << not foo
+end
+
+class A; class << self; ensure; end; end
+
+class A; class << self; rescue; else; ensure; end; end
+
+class << foo.bar
+end
+
+class << foo.bar;end
+
+class << self
+end
+
+class << self;end
+
+class << self
+1 + 2
+end
+
+class << self;1 + 2;end
+
+class A < B[1]
+end
diff --git a/test/prism/fixtures/command_method_call.txt b/test/prism/fixtures/command_method_call.txt
new file mode 100644
index 0000000000..182b87948b
--- /dev/null
+++ b/test/prism/fixtures/command_method_call.txt
@@ -0,0 +1,41 @@
+foo 1
+
+foo bar 1
+
+foo 1 if bar 2
+
+foo 1 unless bar 2
+
+foo 1 while bar 2
+
+foo 1 until bar 2
+
+foo 1 rescue bar 2
+
+foo[bar 1]
+
+foo 1 and bar 2
+
+foo 1 or bar 2
+
+not foo 1
+
+foo = bar = baz 1
+
+def foo = bar 1
+
+1.foo 2
+
+1.foo.bar 2
+
+1.foo[2].bar 3
+
+1.foo(2).bar 3
+
+1.foo(&2).bar 3
+
+!foo 1 and !bar 2
+
+!foo 1 or !bar 2
+
+not !foo 1
diff --git a/test/prism/fixtures/comments.txt b/test/prism/fixtures/comments.txt
new file mode 100644
index 0000000000..9bd853e927
--- /dev/null
+++ b/test/prism/fixtures/comments.txt
@@ -0,0 +1,24 @@
+a
+ # Comment
+b
+
+c # Comment
+d
+
+e
+# Comment
+ .f
+
+g
+ # Comment
+.h
+
+i # Comment
+.j
+
+k # Comment
+ .l
+
+m
+ # Comment
+ &.n
diff --git a/test/prism/fixtures/constants.txt b/test/prism/fixtures/constants.txt
new file mode 100644
index 0000000000..d86f8d3402
--- /dev/null
+++ b/test/prism/fixtures/constants.txt
@@ -0,0 +1,184 @@
+A::B
+
+A::B::C
+
+a::B
+
+A::B = 1
+
+A = 1
+
+ABC
+
+Foo 1
+
+Foo *bar
+
+Foo **bar
+
+Foo &bar
+
+Foo::Bar *baz
+
+Foo::Bar **baz
+
+Foo::Bar &baz
+
+::A::foo
+
+::A = 1
+
+::A::B = 1
+
+::A::B
+
+::A
+
+A::false
+
+A::B::true
+
+A::&
+
+A::`
+
+A::!
+
+A::!=
+
+A::^
+
+A::==
+
+A::===
+
+A::=~
+
+A::>
+
+A::>=
+
+A::>>
+
+A::<<
+
+A::\
+#
+C
+
+A::alias
+
+A::and
+
+A::begin
+
+A::BEGIN
+
+A::break
+
+A::class
+
+A::def
+
+A::defined
+
+A::do
+
+A::else
+
+A::elsif
+
+A::end
+
+A::END
+
+A::ensure
+
+A::false
+
+A::for
+
+A::if
+
+A::in
+
+A::next
+
+A::nil
+
+A::not
+
+A::or
+
+A::redo
+
+A::rescue
+
+A::retry
+
+A::return
+
+A::self
+
+A::super
+
+A::then
+
+A::true
+
+A::undef
+
+A::unless
+
+A::until
+
+A::when
+
+A::while
+
+A::yield
+
+A::__ENCODING__
+
+A::__FILE__
+
+A::__LINE__
+
+A::<
+
+A::<=>
+
+A::<<
+
+A::-
+
+A::%
+
+A::%i
+
+A::%w
+
+A::%x
+
+A::%I
+
+A::%W
+
+A::|
+
+A::+
+
+A::/
+
+A::*
+
+A::**
+
+A::~
+
+A::_::
+C
+
+A::_..
+
+A::__END__
diff --git a/test/prism/fixtures/dash_heredocs.txt b/test/prism/fixtures/dash_heredocs.txt
new file mode 100644
index 0000000000..3e663fae63
--- /dev/null
+++ b/test/prism/fixtures/dash_heredocs.txt
@@ -0,0 +1,63 @@
+<<-EOF
+ a
+EOF
+
+<<-FIRST + <<-SECOND
+ a
+FIRST
+ b
+SECOND
+
+<<-`EOF`
+ a
+#{b}
+EOF
+
+<<-EOF #comment
+ a
+EOF
+
+<<-EOF
+ a
+ b
+ EOF
+
+<<-"EOF"
+ a
+#{b}
+EOF
+
+<<-EOF
+ a
+#{b}
+EOF
+
+%#abc#
+
+<<-EOF
+ a
+ b
+EOF
+
+<<-''
+
+
+<<-'EOF'
+ a #{1}
+EOF
+
+<<-A + <<-B
+ a
+A
+ b
+ #{2
+ }
+B
+
+<<-A + <<-B
+ a
+A
+ b
+ #{
+ 2}
+B
diff --git a/test/prism/fixtures/defined.txt b/test/prism/fixtures/defined.txt
new file mode 100644
index 0000000000..247fa94e3a
--- /dev/null
+++ b/test/prism/fixtures/defined.txt
@@ -0,0 +1,10 @@
+defined? 1 and defined? 2
+
+defined?(x %= 2)
+
+defined?(foo and bar)
+
+defined? 1
+
+defined?("foo"
+)
diff --git a/test/prism/fixtures/dos_endings.txt b/test/prism/fixtures/dos_endings.txt
new file mode 100644
index 0000000000..c105522fa1
--- /dev/null
+++ b/test/prism/fixtures/dos_endings.txt
@@ -0,0 +1,20 @@
+puts "hi"\
+ "there"
+
+%I{a\
+b}
+
+<<-E
+ 1 \
+ 2
+ 3
+E
+
+x = %
+
+
+
+a = foo(<<~EOF.chop)
+
+ baz
+ EOF
diff --git a/test/prism/fixtures/dstring.txt b/test/prism/fixtures/dstring.txt
new file mode 100644
index 0000000000..085e0c6852
--- /dev/null
+++ b/test/prism/fixtures/dstring.txt
@@ -0,0 +1,29 @@
+"foo
+ bar"
+
+"foo
+ #{bar}"
+
+"fo
+o" "ba
+r"
+
+"
+foo\
+"
+
+"
+foo\\
+"
+
+"
+foo\\\
+"
+
+"
+foo\\\\
+"
+
+"
+foo\\\\\
+"
diff --git a/test/prism/fixtures/dsym_str.txt b/test/prism/fixtures/dsym_str.txt
new file mode 100644
index 0000000000..ee68dde88d
--- /dev/null
+++ b/test/prism/fixtures/dsym_str.txt
@@ -0,0 +1,2 @@
+:"foo
+ bar"
diff --git a/test/prism/fixtures/embdoc_no_newline_at_end.txt b/test/prism/fixtures/embdoc_no_newline_at_end.txt
new file mode 100644
index 0000000000..7dc2e32d73
--- /dev/null
+++ b/test/prism/fixtures/embdoc_no_newline_at_end.txt
@@ -0,0 +1,2 @@
+=begin
+=end \ No newline at end of file
diff --git a/test/prism/fixtures/emoji_method_calls.txt b/test/prism/fixtures/emoji_method_calls.txt
new file mode 100644
index 0000000000..96d0daba33
--- /dev/null
+++ b/test/prism/fixtures/emoji_method_calls.txt
@@ -0,0 +1 @@
+foo.🌊 = 1
diff --git a/test/prism/fixtures/endless_methods.txt b/test/prism/fixtures/endless_methods.txt
new file mode 100644
index 0000000000..8c2f2a30cc
--- /dev/null
+++ b/test/prism/fixtures/endless_methods.txt
@@ -0,0 +1,5 @@
+def foo = 1
+
+def bar = A ""
+
+def method = 1 + 2 + 3
diff --git a/test/prism/fixtures/endless_range_in_conditional.txt b/test/prism/fixtures/endless_range_in_conditional.txt
new file mode 100644
index 0000000000..6048008584
--- /dev/null
+++ b/test/prism/fixtures/endless_range_in_conditional.txt
@@ -0,0 +1,3 @@
+if 1..2 ; end
+if ..1 ; end
+if 1.. ; end
diff --git a/test/prism/fixtures/for.txt b/test/prism/fixtures/for.txt
new file mode 100644
index 0000000000..b6eb2cb24f
--- /dev/null
+++ b/test/prism/fixtures/for.txt
@@ -0,0 +1,19 @@
+for i in 1..10
+i
+end
+
+for i in 1..10; i; end
+
+for i,j in 1..10
+i
+end
+
+for i,j,k in 1..10
+i
+end
+
+for i in 1..10 do
+i
+end
+
+for i in 1..10; i; end
diff --git a/test/prism/fixtures/global_variables.txt b/test/prism/fixtures/global_variables.txt
new file mode 100644
index 0000000000..3dc52722a0
--- /dev/null
+++ b/test/prism/fixtures/global_variables.txt
@@ -0,0 +1,93 @@
+$global_variable
+
+$_
+
+$-w
+
+$LOAD_PATH
+
+$stdin
+
+$stdout
+
+$stderr
+
+$!
+
+$?
+
+$~
+
+$&
+
+$`
+
+$'
+
+$+
+
+$:
+
+$;
+
+$,
+
+$DEBUG
+
+$FILENAME
+
+$0
+
+$-0
+
+$LOADED_FEATURES
+
+$VERBOSE
+
+$-K
+
+:$global_variable
+
+:$_
+
+:$-w
+
+:$LOAD_PATH
+
+:$stdin
+
+:$stdout
+
+:$stderr
+
+:$!
+
+:$?
+
+:$~
+
+:$&
+
+:$`
+
+:$'
+
+:$+
+
+:$:
+
+:$;
+
+:$DEBUG
+
+:$FILENAME
+
+:$0
+
+:$-0
+
+:$LOADED_FEATURES
+
+:$VERBOSE
+
+:$-K
diff --git a/test/prism/fixtures/hashes.txt b/test/prism/fixtures/hashes.txt
new file mode 100644
index 0000000000..0afb8db496
--- /dev/null
+++ b/test/prism/fixtures/hashes.txt
@@ -0,0 +1,28 @@
+{}
+
+{
+}
+
+{ a => b, c => d }
+
+{ a => b, **c }
+
+{
+ a: b,
+ c: d
+
+
+
+ }
+
+{ a: b, c: d, **e, f: g }
+
+{ "a": !b? }
+
+a = 1
+tap do
+ b = 1
+ { a:, b:, c:, D: }
+end
+
+{ a: -1 }
diff --git a/test/prism/fixtures/heredoc.txt b/test/prism/fixtures/heredoc.txt
new file mode 100644
index 0000000000..f94fd912df
--- /dev/null
+++ b/test/prism/fixtures/heredoc.txt
@@ -0,0 +1,2 @@
+<<TEXT
+TEXT
diff --git a/test/prism/fixtures/heredoc_with_carriage_returns.txt b/test/prism/fixtures/heredoc_with_carriage_returns.txt
new file mode 100644
index 0000000000..32a2d87b24
--- /dev/null
+++ b/test/prism/fixtures/heredoc_with_carriage_returns.txt
@@ -0,0 +1,2 @@
+<<TEXT
+TEXT
diff --git a/test/prism/fixtures/heredoc_with_comment.txt b/test/prism/fixtures/heredoc_with_comment.txt
new file mode 100644
index 0000000000..8e7b7275bd
--- /dev/null
+++ b/test/prism/fixtures/heredoc_with_comment.txt
@@ -0,0 +1,3 @@
+<<-TARGET.chomp # the heredoc end token doesn't always precede the comment
+ content makes for an obvious error
+TARGET \ No newline at end of file
diff --git a/test/prism/fixtures/heredoc_with_escaped_newline_at_start.txt b/test/prism/fixtures/heredoc_with_escaped_newline_at_start.txt
new file mode 100644
index 0000000000..81f314e0b3
--- /dev/null
+++ b/test/prism/fixtures/heredoc_with_escaped_newline_at_start.txt
@@ -0,0 +1,7 @@
+<<-TARGET.gsub /^\s{/, ''\
+TARGET
+
+
+<<-TARGET.gsub /^\s{/, ''\
+TARGET
+
diff --git a/test/prism/fixtures/heredoc_with_trailing_newline.txt b/test/prism/fixtures/heredoc_with_trailing_newline.txt
new file mode 100644
index 0000000000..13771bf3ac
--- /dev/null
+++ b/test/prism/fixtures/heredoc_with_trailing_newline.txt
@@ -0,0 +1,2 @@
+<<-END
+END \ No newline at end of file
diff --git a/test/prism/fixtures/heredocs_leading_whitespace.txt b/test/prism/fixtures/heredocs_leading_whitespace.txt
new file mode 100644
index 0000000000..660ecb4543
--- /dev/null
+++ b/test/prism/fixtures/heredocs_leading_whitespace.txt
@@ -0,0 +1,29 @@
+<<-' FOO'
+a
+b
+ FOO
+
+<<-" FOO"
+a
+b
+ FOO
+
+<<-` FOO`
+a
+b
+ FOO
+
+<<-' FOO'
+a
+b
+ FOO
+
+<<~' FOO'
+a
+b
+ FOO
+
+<<~' FOO'
+a
+b
+ FOO
diff --git a/test/prism/fixtures/heredocs_nested.txt b/test/prism/fixtures/heredocs_nested.txt
new file mode 100644
index 0000000000..0802378278
--- /dev/null
+++ b/test/prism/fixtures/heredocs_nested.txt
@@ -0,0 +1,22 @@
+<<~RUBY
+pre
+#{
+<<RUBY
+ hello
+RUBY
+}
+post
+RUBY
+
+# depth greater than PM_LEX_STACK_SIZE
+<<-A
+#{
+<<-B
+#{
+<<-C
+#{3}
+C
+}
+B
+}
+A
diff --git a/test/prism/fixtures/heredocs_with_ignored_newlines.txt b/test/prism/fixtures/heredocs_with_ignored_newlines.txt
new file mode 100644
index 0000000000..8e12546ec7
--- /dev/null
+++ b/test/prism/fixtures/heredocs_with_ignored_newlines.txt
@@ -0,0 +1,14 @@
+<<-HERE\
+HERE
+
+<<~THERE\
+ way over
+ <<HERE
+ not here
+ HERE
+
+ <<~BUT\
+ but
+ BUT
+ there
+THERE
diff --git a/test/prism/fixtures/heredocs_with_ignored_newlines_and_non_empty.txt b/test/prism/fixtures/heredocs_with_ignored_newlines_and_non_empty.txt
new file mode 100644
index 0000000000..aeacbd8126
--- /dev/null
+++ b/test/prism/fixtures/heredocs_with_ignored_newlines_and_non_empty.txt
@@ -0,0 +1,4 @@
+<<-EOE
+ some
+ heredocs
+EOE \ No newline at end of file
diff --git a/test/prism/fixtures/if.txt b/test/prism/fixtures/if.txt
new file mode 100644
index 0000000000..4139bae5ed
--- /dev/null
+++ b/test/prism/fixtures/if.txt
@@ -0,0 +1,42 @@
+if true; 1; end
+
+if true
+1 else 2 end
+
+if true then true elsif false then false elsif nil then nil else self end
+
+1 if true
+
+tap { break if true }
+
+tap { next if true }
+
+return if true
+
+tap { if exit_loop then break 42 end }
+
+if foo
+then bar
+end
+
+a if b if c
+
+if true
+ a b:
+else
+end
+
+if type in 1
+elsif type in B
+end
+
+if f1
+ lambda do |_|
+ end
+elsif f2
+ lambda do |_|
+ end
+else
+ lambda do |_|
+ end
+end
diff --git a/test/prism/fixtures/indented_file_end.txt b/test/prism/fixtures/indented_file_end.txt
new file mode 100644
index 0000000000..5a96dcacf7
--- /dev/null
+++ b/test/prism/fixtures/indented_file_end.txt
@@ -0,0 +1,4 @@
+ def hi
+
+ end # hi there
+ \ No newline at end of file
diff --git a/test/prism/fixtures/integer_operations.txt b/test/prism/fixtures/integer_operations.txt
new file mode 100644
index 0000000000..37163acf30
--- /dev/null
+++ b/test/prism/fixtures/integer_operations.txt
@@ -0,0 +1,63 @@
+!1
+
+~1
+
+1 != 2
+
+1 !~ 2
+
+1 % 2
+
+1 & 2
+
+1 * 2
+
+1**2
+
+1 + 2
+
+1 - 2
+
+1 / 2
+
+1/2/3
+
+1 < 2
+
+1 << 2
+
+1 <= 2
+
+1 <=> 2
+
+1 == 2
+
+1 === 2
+
+1 =~ 2
+
+1 > 2
+
+1 >= 2
+
+1 >> 2
+
+1 ^ 2
+
+1 | 2
+
+1 && 2
+
+1 and 2
+
+1 * 2 ** 3
+
+1 * 2 + 3
+
+1 or 2
+
+1 || 2
+
+1 + 2 * 3
+
+(1 + 1)
diff --git a/test/prism/fixtures/keyword_method_names.txt b/test/prism/fixtures/keyword_method_names.txt
new file mode 100644
index 0000000000..9154469441
--- /dev/null
+++ b/test/prism/fixtures/keyword_method_names.txt
@@ -0,0 +1,29 @@
+def def
+end
+
+def self.ensure
+end
+
+private def foo
+ bar do
+ end
+end
+
+def m(a, **nil)
+end
+
+def __ENCODING__.a
+end
+
+%{abc}
+
+%"abc"
+
+def __FILE__.a
+end
+
+def __LINE__.a
+end
+
+def nil::a
+end
diff --git a/test/prism/fixtures/keywords.txt b/test/prism/fixtures/keywords.txt
new file mode 100644
index 0000000000..6d24a9f476
--- /dev/null
+++ b/test/prism/fixtures/keywords.txt
@@ -0,0 +1,11 @@
+tap { redo }
+
+begin; rescue; retry; end
+
+self
+
+__ENCODING__
+
+__FILE__
+
+__LINE__
diff --git a/test/prism/fixtures/lambda.txt b/test/prism/fixtures/lambda.txt
new file mode 100644
index 0000000000..5c21eafb24
--- /dev/null
+++ b/test/prism/fixtures/lambda.txt
@@ -0,0 +1,11 @@
+->(
+ foo
+) {}
+
+->(x: "b#{a}") { }
+
+->(a: b * 3) {}
+
+-> foo = bar do end
+
+-> foo: bar do end
diff --git a/test/prism/fixtures/method_calls.txt b/test/prism/fixtures/method_calls.txt
new file mode 100644
index 0000000000..987fb3f90f
--- /dev/null
+++ b/test/prism/fixtures/method_calls.txt
@@ -0,0 +1,156 @@
+foo.bar %{baz}
+
+a.b(c, d)
+
+a.b()
+
+foo
+ .bar
+ &.baz
+
+a!
+
+a.()
+
+a.(1, 2, 3)
+
+a::b
+
+a::b c
+
+foo.bar = 1
+
+a?
+
+a(&block)
+
+a(**kwargs)
+
+a.b.c
+
+a(b, c)
+
+a()
+
+a(*args)
+
+a b, c
+
+a.b c, d
+
+foo.foo, bar.bar = 1, 2
+
+a&.b
+
+a&.()
+
+a&.b(c)
+
+a&.b()
+
+foo :a, :b if bar? or baz and qux
+
+foo(:a,
+
+ :b
+)
+
+foo(*rest)
+
+foo(:a, :h => [:x, :y], :a => :b, &:bar)
+
+hi 123, { :there => :friend, **{}, whatup: :dog }
+
+foo :a, b: true do |a, b| puts a end
+
+hi there: :friend
+
+hi :there => :friend, **{}, whatup: :dog
+
+hi(:there => :friend, **{}, whatup: :dog)
+
+foo({ a: true, b: false, }, &:block)
+
+hi :there => :friend
+
+foo(:a,
+:b,
+)
+
+foo(
+:a,
+b: :c,
+)
+
+foo &:block
+
+foo a: true, b: false, &:block
+
+some_func 1, kwarg: 2
+
+Kernel.Integer(10)
+
+x.each { }
+
+foo.map { $& }
+
+A::B::C :foo
+
+A::B::C(:foo)
+
+A::B::C(:foo) { }
+
+foo("a": -1)
+
+foo bar: { baz: qux do end }
+
+foo bar: { **kw do end }
+
+foo "#{bar.map do "baz" end}" do end
+
+foo class Bar baz do end end
+
+foo module Bar baz do end end
+
+foo [baz do end]
+
+p begin 1.times do 1 end end
+
+foo :a,
+ if x
+ bar do |a|
+ a
+ end
+ end
+
+foo :a,
+ while x
+ bar do |a|
+ a
+ end
+ end,
+ until x
+ baz do
+ end
+ end
+
+{} + A {}
+
+{} + A { |a| a }
+
+A {} + A {}
+
+lst << A {}
+
+"#{ join (" ") }"
+
+"#{(v)}"
+
+def f(*); p *; end
+
+foo 1, Bar { 1 }
+
+foo = 1
+foo {}
+
+@a.b "c#{name}": 42
diff --git a/test/prism/fixtures/methods.txt b/test/prism/fixtures/methods.txt
new file mode 100644
index 0000000000..d59196bdfd
--- /dev/null
+++ b/test/prism/fixtures/methods.txt
@@ -0,0 +1,188 @@
+def foo((bar, baz))
+end
+
+def foo((bar, baz), optional = 1, (bin, bag))
+end
+
+
+def a; ensure; end
+
+def (b).a
+end
+
+def (a)::b
+end
+
+def false.a
+end
+
+def a(...)
+end
+
+def $var.a
+end
+
+def a.b
+end
+
+def @var.a
+end
+
+def a b:; end
+
+%,abc,
+
+def a(b:)
+end
+
+def a(**b)
+end
+
+def a(**)
+end
+
+a = 1; def a
+end
+
+def a b, c, d
+end
+
+def nil.a
+end
+
+def a b:, c: 1
+end
+
+def a(b:, c: 1)
+end
+
+def a(b:
+ 1, c:)
+end
+
+%.abc.
+
+def a b = 1, c = 2
+end
+
+def a()
+end
+
+def a b, c = 2
+end
+
+def a b
+end
+
+def a; rescue; else; ensure; end
+
+def a *b
+end
+
+def a(*)
+end
+
+def a
+b = 1
+end
+
+def self.a
+end
+
+def true.a
+end
+
+def a
+end
+
+def hi
+return :hi if true
+:bye
+end
+
+def foo = 1
+def bar = 2
+
+def foo(bar) = 123
+
+def foo = 123
+
+def a(*); b(*); end
+
+def a(...); b(...); end
+
+def a(...); b(1, 2, ...); end
+
+def (c = b).a
+end
+
+def a &b
+end
+
+def a(&)
+end
+
+def @@var.a
+end
+
+def (a = b).C
+end
+
+def self.Array_function; end
+
+Const = 1; def Const.a
+end
+
+def a(...); "foo#{b(...)}"; end
+
+def foo
+ {}.merge **bar, **baz, **qux
+end
+
+def bar(a: (1...10))
+end
+
+def bar(a: (...10))
+end
+
+def bar(a: (1...))
+end
+
+def bar(a = (1...10))
+end
+
+def bar(a = (...10))
+end
+
+def bar(a = (1...))
+end
+
+def method(a)
+ item >> a {}
+end
+
+foo = 1
+def foo.bar; end
+
+def f(*); [*]; end
+
+def f x:-a; end
+
+def f x:+a; end
+
+def f x:!a; end
+
+def foo x:%(xx); end
+
+def foo(...)
+ bar(...)
+end
+
+def foo(bar = (def baz(bar) = bar; 1)) = 2
+
+def (class Foo; end).foo(bar = 1) = 2
+
+module Foo
+ def clone(opts = nil || (return self))
+ end
+end
diff --git a/test/prism/fixtures/modules.txt b/test/prism/fixtures/modules.txt
new file mode 100644
index 0000000000..76bd9bea43
--- /dev/null
+++ b/test/prism/fixtures/modules.txt
@@ -0,0 +1,18 @@
+module A a = 1 end
+
+%Q{aaa #{bbb} ccc}
+
+module m::M
+end
+
+module A
+ x = 1; rescue; end
+
+module ::A
+end
+
+module A[]::B
+end
+
+module A[1]::B
+end
diff --git a/test/prism/fixtures/multi_write.txt b/test/prism/fixtures/multi_write.txt
new file mode 100644
index 0000000000..edbcafb969
--- /dev/null
+++ b/test/prism/fixtures/multi_write.txt
@@ -0,0 +1,4 @@
+foo = 1 rescue nil
+foo, bar = 1 rescue nil
+foo = 1, 2 rescue nil
+foo, bar = 1, 2 rescue nil
diff --git a/test/prism/fixtures/newline_terminated.txt b/test/prism/fixtures/newline_terminated.txt
new file mode 100644
index 0000000000..12f3bda229
--- /dev/null
+++ b/test/prism/fixtures/newline_terminated.txt
Binary files differ
diff --git a/test/prism/fixtures/next.txt b/test/prism/fixtures/next.txt
new file mode 100644
index 0000000000..2ef14c6304
--- /dev/null
+++ b/test/prism/fixtures/next.txt
@@ -0,0 +1,24 @@
+tap { next }
+
+tap { next (1), (2), (3) }
+
+tap { next 1 }
+
+tap { next 1, 2,
+3 }
+
+tap { next 1, 2, 3 }
+
+tap { next [1, 2, 3] }
+
+tap { next(
+ 1
+ 2
+) }
+
+tap { next
+1 }
+
+tap { next() }
+
+tap { next(1) }
diff --git a/test/prism/fixtures/nils.txt b/test/prism/fixtures/nils.txt
new file mode 100644
index 0000000000..8084db2534
--- /dev/null
+++ b/test/prism/fixtures/nils.txt
@@ -0,0 +1,13 @@
+nil
+
+()
+
+(
+;
+;
+)
+
+END { 1 }
+
+BEGIN { 1 }
+
diff --git a/test/prism/fixtures/non_alphanumeric_methods.txt b/test/prism/fixtures/non_alphanumeric_methods.txt
new file mode 100644
index 0000000000..1da3fd852b
--- /dev/null
+++ b/test/prism/fixtures/non_alphanumeric_methods.txt
@@ -0,0 +1,105 @@
+def !
+end
+
+def !=
+end
+
+def !~
+end
+
+def %
+end
+
+def self.+
+end
+
+def &
+end
+
+def *
+end
+
+def **
+end
+
+%|abc|
+
+def + **b
+end
+
+def +()
+end
+
+def + b
+end
+
+def self.+
+end
+
+def +
+end
+
+def +@
+end
+
+def -
+end
+
+def a.-;end
+
+def -@
+end
+
+def /
+end
+
+def <
+end
+
+def <<
+end
+
+def <=
+end
+
+def <=>
+end
+
+def ==
+end
+
+def ===
+end
+
+def =~
+end
+
+def >
+end
+
+def >=
+end
+
+def >>
+end
+
+def []
+end
+
+def []=
+end
+
+def ^
+end
+
+def `
+end
+
+def self.`
+end
+
+def |
+end
+
+def ~
+end
diff --git a/test/prism/fixtures/not.txt b/test/prism/fixtures/not.txt
new file mode 100644
index 0000000000..520b34fa37
--- /dev/null
+++ b/test/prism/fixtures/not.txt
@@ -0,0 +1,37 @@
+not foo and not bar
+
+not(foo and bar)
+
+not foo
+
+not foo and not
+ bar
+
+
+not foo and
+ not
+ bar
+
+
+not foo and
+ not
+
+
+ bar
+
+not(foo
+
+
+)
+
+not(
+
+
+foo
+
+
+ )
+
+not foo .. bar
+
+not (foo .. bar)
diff --git a/test/prism/fixtures/numbers.txt b/test/prism/fixtures/numbers.txt
new file mode 100644
index 0000000000..47f20dcb42
--- /dev/null
+++ b/test/prism/fixtures/numbers.txt
@@ -0,0 +1,67 @@
+0
+
+1
+
+1.0
+
+2
+
+0b0
+
+0b1
+
+0b10
+
+0d0
+
+0d1
+
+0d2
+
+00
+
+01
+
+02
+
+0o0
+
+0o1
+
+0o2
+
+0x0
+
+0x1
+
+0x2
+
+1i
+
+1r
+
+-1
+
+1ri
+
+1.2r
+
+1.2ri
+
+-1ri
+
+-1.2r
+
+-1.2ri
+
+0o1r
+
+0o1i
+
+0o1ri
+
+0d1r
+
+0d1i
+
+0b1ri
diff --git a/test/prism/fixtures/patterns.txt b/test/prism/fixtures/patterns.txt
new file mode 100644
index 0000000000..29f8b4cf80
--- /dev/null
+++ b/test/prism/fixtures/patterns.txt
@@ -0,0 +1,220 @@
+foo => bar
+foo => 1
+foo => 1.0
+foo => 1i
+foo => 1r
+foo => :foo
+foo => %s[foo]
+foo => :"foo"
+foo => /foo/
+foo => `foo`
+foo => %x[foo]
+foo => %i[foo]
+foo => %I[foo]
+foo => %w[foo]
+foo => %W[foo]
+foo => %q[foo]
+foo => %Q[foo]
+foo => "foo"
+foo => nil
+foo => self
+foo => true
+foo => false
+foo => __FILE__
+foo => __LINE__
+foo => __ENCODING__
+foo => -> { bar }
+
+foo => 1 .. 1
+foo => 1.0 .. 1.0
+foo => 1i .. 1i
+foo => 1r .. 1r
+foo => :foo .. :foo
+foo => %s[foo] .. %s[foo]
+foo => :"foo" .. :"foo"
+foo => /foo/ .. /foo/
+foo => `foo` .. `foo`
+foo => %x[foo] .. %x[foo]
+foo => %i[foo] .. %i[foo]
+foo => %I[foo] .. %I[foo]
+foo => %w[foo] .. %w[foo]
+foo => %W[foo] .. %W[foo]
+foo => %q[foo] .. %q[foo]
+foo => %Q[foo] .. %Q[foo]
+foo => "foo" .. "foo"
+foo => nil .. nil
+foo => self .. self
+foo => true .. true
+foo => false .. false
+foo => __FILE__ .. __FILE__
+foo => __LINE__ .. __LINE__
+foo => __ENCODING__ .. __ENCODING__
+foo => -> { bar } .. -> { bar }
+
+bar = 1; foo => ^bar
+foo => ^@bar
+foo => ^@@bar
+foo => ^$bar
+
+foo => ^(1)
+foo => ^(nil)
+foo => ^("bar" + "baz")
+
+foo => Foo
+foo => Foo::Bar::Baz
+foo => ::Foo
+foo => ::Foo::Bar::Baz
+
+foo => Foo()
+foo => Foo(1)
+foo => Foo(1, 2, 3)
+foo => Foo(bar)
+foo => Foo(*bar, baz)
+foo => Foo(bar, *baz)
+foo => Foo(*bar, baz, *qux)
+
+foo => Foo[]
+foo => Foo[1]
+foo => Foo[1, 2, 3]
+foo => Foo[Foo[]]
+foo => Foo[bar]
+foo => Foo[*bar, baz]
+foo => Foo[bar, *baz]
+foo => Foo[*bar, baz, *qux]
+
+foo => *bar
+foo => *bar, baz, qux
+foo => bar, *baz, qux
+foo => bar, baz, *qux
+foo => *bar, baz, *qux
+
+foo => bar,
+
+; # end the previous pattern for ParseTest#test_filepath_patterns.txt which parses the whole file at once
+
+foo => []
+foo => [[[[[]]]]]
+
+foo => [*bar]
+foo => [*bar, baz, qux]
+foo => [bar, *baz, qux]
+foo => [bar, baz, *qux]
+foo => [*bar, baz, *qux]
+
+foo in bar
+foo in 1
+foo in 1.0
+foo in 1i
+foo in 1r
+foo in :foo
+foo in %s[foo]
+foo in :"foo"
+foo in /foo/
+foo in `foo`
+foo in %x[foo]
+foo in %i[foo]
+foo in %I[foo]
+foo in %w[foo]
+foo in %W[foo]
+foo in %q[foo]
+foo in %Q[foo]
+foo in "foo"
+foo in nil
+foo in self
+foo in true
+foo in false
+foo in __FILE__
+foo in __LINE__
+foo in __ENCODING__
+foo in -> { bar }
+
+foo in bar,
+
+; # end the previous pattern for ParseTest#test_filepath_patterns.txt which parses the whole file at once
+
+case foo; in bar then end
+case foo; in 1 then end
+case foo; in 1.0 then end
+case foo; in 1i then end
+case foo; in 1r then end
+case foo; in :foo then end
+case foo; in %s[foo] then end
+case foo; in :"foo" then end
+case foo; in /foo/ then end
+case foo; in `foo` then end
+case foo; in %x[foo] then end
+case foo; in %i[foo] then end
+case foo; in %I[foo] then end
+case foo; in %w[foo] then end
+case foo; in %W[foo] then end
+case foo; in %q[foo] then end
+case foo; in %Q[foo] then end
+case foo; in "foo" then end
+case foo; in nil then end
+case foo; in self then end
+case foo; in true then end
+case foo; in false then end
+case foo; in __FILE__ then end
+case foo; in __LINE__ then end
+case foo; in __ENCODING__ then end
+case foo; in -> { bar } then end
+
+case foo; in bar if baz then end
+case foo; in 1 if baz then end
+case foo; in 1.0 if baz then end
+case foo; in 1i if baz then end
+case foo; in 1r if baz then end
+case foo; in :foo if baz then end
+case foo; in %s[foo] if baz then end
+case foo; in :"foo" if baz then end
+case foo; in /foo/ if baz then end
+case foo; in `foo` if baz then end
+case foo; in %x[foo] if baz then end
+case foo; in %i[foo] if baz then end
+case foo; in %I[foo] if baz then end
+case foo; in %w[foo] if baz then end
+case foo; in %W[foo] if baz then end
+case foo; in %q[foo] if baz then end
+case foo; in %Q[foo] if baz then end
+case foo; in "foo" if baz then end
+case foo; in nil if baz then end
+case foo; in self if baz then end
+case foo; in true if baz then end
+case foo; in false if baz then end
+case foo; in __FILE__ if baz then end
+case foo; in __LINE__ if baz then end
+case foo; in __ENCODING__ if baz then end
+case foo; in -> { bar } if baz then end
+
+if a in []
+end
+
+a => [
+ b
+]
+
+foo in A[
+ bar: B[
+ value: a
+ ]
+]
+
+foo in bar => baz
+foo => bar => baz
+
+foo, bar, baz = 1, 2
+foo do
+ [1, 2] => [foo, bar] => baz
+end
+
+foo => Object[{x:}]
+
+1.then { 1 in ^_1 }
+
+(
+ a,
+ b
+) = c
+
+case (); in [_a, _a]; end
+case (); in [{a:1}, {a:2}]; end
diff --git a/test/prism/fixtures/procs.txt b/test/prism/fixtures/procs.txt
new file mode 100644
index 0000000000..7ffb11e78a
--- /dev/null
+++ b/test/prism/fixtures/procs.txt
@@ -0,0 +1,27 @@
+-> (a; b, c, d) { b }
+
+-> do
+ensure
+end
+
+-> do
+rescue
+else
+ensure
+end
+
+-> { foo }
+
+-> do; foo; end
+
+-> a, b = 1, c:, d:, &e { a }
+
+-> (a, b = 1, *c, d:, e:, **f, &g) { a }
+
+-> (a, b = 1, *c, d:, e:, **f, &g) do
+ a
+end
+
+-> (a) { -> b { a * b } }
+
+-> ((a, b), *c) { }
diff --git a/test/prism/fixtures/range_begin_open_exclusive.txt b/test/prism/fixtures/range_begin_open_exclusive.txt
new file mode 100644
index 0000000000..3b12672b4f
--- /dev/null
+++ b/test/prism/fixtures/range_begin_open_exclusive.txt
@@ -0,0 +1 @@
+...2
diff --git a/test/prism/fixtures/range_begin_open_inclusive.txt b/test/prism/fixtures/range_begin_open_inclusive.txt
new file mode 100644
index 0000000000..052f45900b
--- /dev/null
+++ b/test/prism/fixtures/range_begin_open_inclusive.txt
@@ -0,0 +1 @@
+..2
diff --git a/test/prism/fixtures/range_end_open_exclusive.txt b/test/prism/fixtures/range_end_open_exclusive.txt
new file mode 100644
index 0000000000..2ffd68afdb
--- /dev/null
+++ b/test/prism/fixtures/range_end_open_exclusive.txt
@@ -0,0 +1 @@
+2...
diff --git a/test/prism/fixtures/range_end_open_inclusive.txt b/test/prism/fixtures/range_end_open_inclusive.txt
new file mode 100644
index 0000000000..48445391f6
--- /dev/null
+++ b/test/prism/fixtures/range_end_open_inclusive.txt
@@ -0,0 +1 @@
+2..
diff --git a/test/prism/fixtures/ranges.txt b/test/prism/fixtures/ranges.txt
new file mode 100644
index 0000000000..e2e4136ae9
--- /dev/null
+++ b/test/prism/fixtures/ranges.txt
@@ -0,0 +1,49 @@
+(...2)
+
+(..2)
+
+1...2
+
+foo[...2]
+
+{ foo: ...bar }
+
+(1...)
+
+1..2
+
+{ foo: ..bar }
+
+(1..)
+
+1 .. ..1
+
+1.. && 2
+
+1.. == 2
+
+1.. != 2
+
+1.. === 2
+
+1.. <=> 2
+
+1.. =~ 2
+
+1.. !~ 2
+
+1.. < 2
+
+1.. > 2
+
+1.. <= 2
+
+1.. >= 2
+
+1.. << 2
+
+1.. >> 2
+
+1.. + 2
+
+1.. - 2
diff --git a/test/prism/fixtures/regex.txt b/test/prism/fixtures/regex.txt
new file mode 100644
index 0000000000..4623733f58
--- /dev/null
+++ b/test/prism/fixtures/regex.txt
@@ -0,0 +1,48 @@
+foo /bar/
+
+%r{abc}i
+
+/a\b/
+
+/aaa #$bbb/
+
+/aaa #{bbb} ccc/
+
+[/(?<foo>bar)/ =~ baz, foo]
+
+/abc/i
+
+%r/[a-z$._?][\w$.?#@~]*:/i
+
+%r/([a-z$._?][\w$.?#@~]*)(\s+)(equ)/i
+
+%r/[a-z$._?][\w$.?#@~]*/i
+
+%r(
+(?:[#$%_']|\(\)|\(,\)|\[\]|[0-9])*
+ (?:[#$%_']+)
+)
+
+/(?#\))/ =~ "hi"
+
+%r#pound#
+
+/aaa #{bbb}/o
+
+/(?<a\
+b>)/ =~ ""; ab
+
+/(?<abc>)(?<abc>)/ =~ ""; abc
+
+/(?<a b>)/ =~ ""
+
+a = 1
+tap { /(?<a>)/ =~ to_s }
+
+/(?<foo>)/ =~ ""
+/(?<Foo>)/ =~ ""
+
+/(?<nil>)/ =~ ""
+def foo(nil:) = /(?<nil>)/ =~ ""
+
+/(?-x:#)/x
diff --git a/test/prism/fixtures/regex_char_width.txt b/test/prism/fixtures/regex_char_width.txt
new file mode 100644
index 0000000000..7096b71584
--- /dev/null
+++ b/test/prism/fixtures/regex_char_width.txt
@@ -0,0 +1,3 @@
+# encoding: sjis
+/â…§(?<a>.)â…©(?<b>.)/ =~ 'â…§aâ…©b'
+[a, b]
diff --git a/test/prism/fixtures/regex_escape_encoding.txt b/test/prism/fixtures/regex_escape_encoding.txt
new file mode 100644
index 0000000000..74e1647d67
--- /dev/null
+++ b/test/prism/fixtures/regex_escape_encoding.txt
@@ -0,0 +1,3 @@
+# encoding: US-ASCII
+str = "hello \xFC"
+str =~ /hello \u{fc}/
diff --git a/test/prism/fixtures/repeat_parameters.txt b/test/prism/fixtures/repeat_parameters.txt
new file mode 100644
index 0000000000..9c69e9718a
--- /dev/null
+++ b/test/prism/fixtures/repeat_parameters.txt
@@ -0,0 +1,38 @@
+def foo(a, _)
+end
+
+def foo(a, _, _)
+end
+
+def foo(a, _, _, _b)
+end
+
+def foo(a, _, _, _b, _b)
+end
+
+def foo(a, (b, *_c, d), (e, *_c, f))
+end
+
+def foo(_a, _a, b, c)
+end
+
+def foo((a, *_b, c), (d, *_b, e))
+end
+
+def foo(_a = 1, _a = 2)
+end
+
+def foo(_a:, _a:)
+end
+
+def foo(_a: 1, _a: 2)
+end
+
+def foo(_a, **_a)
+end
+
+def foo(_a, &_a)
+end
+
+def foo(_a, *_a)
+end
diff --git a/test/prism/fixtures/rescue.txt b/test/prism/fixtures/rescue.txt
new file mode 100644
index 0000000000..99170fbe0f
--- /dev/null
+++ b/test/prism/fixtures/rescue.txt
@@ -0,0 +1,35 @@
+foo rescue nil
+
+foo rescue
+nil
+
+tap { break rescue nil }
+
+tap { next rescue nil }
+
+return rescue nil
+
+foo rescue nil || 1
+
+foo rescue nil ? 1 : 2
+
+begin; a; rescue *b; end
+
+foo do |x|
+ bar(y) rescue ArgumentError fail "baz"
+end
+
+if a = foo rescue nil
+ bar
+end
+
+def some_method = other_method 42 rescue nil
+
+def a
+ a b:
+rescue
+end
+
+foo if bar rescue baz
+
+z = x y rescue c d
diff --git a/test/prism/fixtures/return.txt b/test/prism/fixtures/return.txt
new file mode 100644
index 0000000000..a8b5b95fab
--- /dev/null
+++ b/test/prism/fixtures/return.txt
@@ -0,0 +1,24 @@
+return
+
+return (1), (2), (3)
+
+return *1
+
+return 1
+
+return 1, 2,
+3
+
+return 1, 2, 3
+
+return [1, 2, 3]
+
+return(
+ 1
+ 2
+)
+
+return()
+
+return(1)
+
diff --git a/test/prism/fixtures/seattlerb/BEGIN.txt b/test/prism/fixtures/seattlerb/BEGIN.txt
new file mode 100644
index 0000000000..bed5755901
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/BEGIN.txt
@@ -0,0 +1 @@
+BEGIN { 42 }
diff --git a/test/prism/fixtures/seattlerb/README.rdoc b/test/prism/fixtures/seattlerb/README.rdoc
new file mode 100644
index 0000000000..1e5bfbdfe0
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/README.rdoc
@@ -0,0 +1,113 @@
+= ruby_parser
+
+home :: https://github.com/seattlerb/ruby_parser
+bugs :: https://github.com/seattlerb/ruby_parser/issues
+rdoc :: http://docs.seattlerb.org/ruby_parser
+
+== DESCRIPTION:
+
+ruby_parser (RP) is a ruby parser written in pure ruby (utilizing
+racc--which does by default use a C extension). It outputs
+s-expressions which can be manipulated and converted back to ruby via
+the ruby2ruby gem.
+
+As an example:
+
+ def conditional1 arg1
+ return 1 if arg1 == 0
+ return 0
+ end
+
+becomes:
+
+ s(:defn, :conditional1, s(:args, :arg1),
+ s(:if,
+ s(:call, s(:lvar, :arg1), :==, s(:lit, 0)),
+ s(:return, s(:lit, 1)),
+ nil),
+ s(:return, s(:lit, 0)))
+
+Tested against 801,039 files from the latest of all rubygems (as of 2013-05):
+
+* 1.8 parser is at 99.9739% accuracy, 3.651 sigma
+* 1.9 parser is at 99.9940% accuracy, 4.013 sigma
+* 2.0 parser is at 99.9939% accuracy, 4.008 sigma
+* 2.6 parser is at 99.9972% accuracy, 4.191 sigma
+* 3.0 parser has a 100% parse rate.
+ * Tested against 2,672,412 unique ruby files across 167k gems.
+ * As do all the others now, basically.
+
+== FEATURES/PROBLEMS:
+
+* Pure ruby, no compiles.
+* Includes preceding comment data for defn/defs/class/module nodes!
+* Incredibly simple interface.
+* Output is 100% equivalent to ParseTree.
+ * Can utilize PT's SexpProcessor and UnifiedRuby for language processing.
+* Known Issue: Speed is now pretty good, but can always improve:
+ * RP parses a corpus of 3702 files in 125s (avg 108 Kb/s)
+ * MRI+PT parsed the same in 67.38s (avg 200.89 Kb/s)
+* Known Issue: Code is much better, but still has a long way to go.
+* Known Issue: Totally awesome.
+* Known Issue: line number values can be slightly off. Parsing LR sucks.
+
+== SYNOPSIS:
+
+ RubyParser.new.parse "1+1"
+ # => s(:call, s(:lit, 1), :+, s(:lit, 1))
+
+You can also use Ruby19Parser, Ruby18Parser, or RubyParser.for_current_ruby:
+
+ RubyParser.for_current_ruby.parse "1+1"
+ # => s(:call, s(:lit, 1), :+, s(:lit, 1))
+
+== DEVELOPER NOTES:
+
+To add a new version:
+
+* New parser should be generated from lib/ruby_parser[23].yy.
+* Extend lib/ruby_parser[23].yy with new class name.
+* Add new version number to V2/V3 in Rakefile for rule creation.
+* Add new `ruby_parse "x.y.z"` line to Rakefile for rake compare (line ~300).
+* Require generated parser in lib/ruby_parser.rb.
+* Add new V## = ::Ruby##Parser; end to ruby_parser.rb (bottom of file).
+* Add empty TestRubyParserShared##Plus module and TestRubyParserV## to test/test_ruby_parser.rb.
+* Extend Manifest.txt with generated file names.
+* Add new version number to sexp_processor's pt_testcase.rb in all_versions.
+
+Until all of these are done, you won't have a clean test run.
+
+== REQUIREMENTS:
+
+* ruby. woot.
+* sexp_processor for Sexp and SexpProcessor classes, and testing.
+* racc full package for parser development (compiling .y to .rb).
+
+== INSTALL:
+
+* sudo gem install ruby_parser
+
+== LICENSE:
+
+(The MIT License)
+
+Copyright (c) Ryan Davis, seattle.rb
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/test/prism/fixtures/seattlerb/TestRubyParserShared.txt b/test/prism/fixtures/seattlerb/TestRubyParserShared.txt
new file mode 100644
index 0000000000..c55b3e1f70
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/TestRubyParserShared.txt
@@ -0,0 +1,92 @@
+%I[
+
+
+]
+
+%I[
+line2
+line3
+]
+
+%W[
+
+
+]
+
+%W[
+line2
+line3
+]
+
+%i[
+
+
+]
+
+%i[
+line2
+line3
+]
+
+%r[
+
+
+]
+
+%w[
+
+
+]
+
+%w[
+line2
+line3
+]
+
+[
+:line2,
+:line3
+]
+
+class X # line 1
+ def self.y(a, # line 2
+ b) # line 3
+ a + b # line 4
+ end # line 5
+end # line 6
+
+
+class X # line 1
+ class Y # line 2
+ Z = 42 # line 3
+ end # line 4
+end # line 5
+
+
+class X # line 1
+ def y(a, # line 2
+ b) # line 3
+ a + b # line 4
+ end # line 5
+end # line 6
+
+
+module X
+ X = [
+ :line3,
+ :line4,
+ ]
+end
+
+
+module X # line 1
+ module Y # line 2
+ Z = 42 # line 3
+ end # line 4
+end # line 5
+
+
+x(
+:line2,
+:line3
+)
diff --git a/test/prism/fixtures/seattlerb/__ENCODING__.txt b/test/prism/fixtures/seattlerb/__ENCODING__.txt
new file mode 100644
index 0000000000..d6debf2f92
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/__ENCODING__.txt
@@ -0,0 +1 @@
+__ENCODING__
diff --git a/test/prism/fixtures/seattlerb/alias_gvar_backref.txt b/test/prism/fixtures/seattlerb/alias_gvar_backref.txt
new file mode 100644
index 0000000000..016bd94fe0
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/alias_gvar_backref.txt
@@ -0,0 +1 @@
+alias $MATCH $&
diff --git a/test/prism/fixtures/seattlerb/alias_resword.txt b/test/prism/fixtures/seattlerb/alias_resword.txt
new file mode 100644
index 0000000000..63e782614b
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/alias_resword.txt
@@ -0,0 +1 @@
+alias in out
diff --git a/test/prism/fixtures/seattlerb/and_multi.txt b/test/prism/fixtures/seattlerb/and_multi.txt
new file mode 100644
index 0000000000..8902086cac
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/and_multi.txt
@@ -0,0 +1,3 @@
+true and
+not false and
+true
diff --git a/test/prism/fixtures/seattlerb/aref_args_assocs.txt b/test/prism/fixtures/seattlerb/aref_args_assocs.txt
new file mode 100644
index 0000000000..3244eebafc
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/aref_args_assocs.txt
@@ -0,0 +1 @@
+[1 => 2]
diff --git a/test/prism/fixtures/seattlerb/aref_args_lit_assocs.txt b/test/prism/fixtures/seattlerb/aref_args_lit_assocs.txt
new file mode 100644
index 0000000000..0b6ffa7e2c
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/aref_args_lit_assocs.txt
@@ -0,0 +1 @@
+[1, 2 => 3]
diff --git a/test/prism/fixtures/seattlerb/args_kw_block.txt b/test/prism/fixtures/seattlerb/args_kw_block.txt
new file mode 100644
index 0000000000..cb6ab39852
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/args_kw_block.txt
@@ -0,0 +1 @@
+def f(a: 1, &b); end
diff --git a/test/prism/fixtures/seattlerb/array_line_breaks.txt b/test/prism/fixtures/seattlerb/array_line_breaks.txt
new file mode 100644
index 0000000000..be9f2d9cb8
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/array_line_breaks.txt
@@ -0,0 +1,4 @@
+[
+'a',
+'b']
+1
diff --git a/test/prism/fixtures/seattlerb/array_lits_trailing_calls.txt b/test/prism/fixtures/seattlerb/array_lits_trailing_calls.txt
new file mode 100644
index 0000000000..868384a407
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/array_lits_trailing_calls.txt
@@ -0,0 +1,3 @@
+%w[].b
+
+[].b
diff --git a/test/prism/fixtures/seattlerb/assoc__bare.txt b/test/prism/fixtures/seattlerb/assoc__bare.txt
new file mode 100644
index 0000000000..96c2940f31
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/assoc__bare.txt
@@ -0,0 +1 @@
+{ y: }
diff --git a/test/prism/fixtures/seattlerb/assoc_label.txt b/test/prism/fixtures/seattlerb/assoc_label.txt
new file mode 100644
index 0000000000..372dc75031
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/assoc_label.txt
@@ -0,0 +1 @@
+a(b:1)
diff --git a/test/prism/fixtures/seattlerb/attr_asgn_colon_id.txt b/test/prism/fixtures/seattlerb/attr_asgn_colon_id.txt
new file mode 100644
index 0000000000..f63c2f5dcb
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/attr_asgn_colon_id.txt
@@ -0,0 +1 @@
+A::b = 1
diff --git a/test/prism/fixtures/seattlerb/attrasgn_array_arg.txt b/test/prism/fixtures/seattlerb/attrasgn_array_arg.txt
new file mode 100644
index 0000000000..db9e2db063
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/attrasgn_array_arg.txt
@@ -0,0 +1 @@
+a[[1, 2]] = 3
diff --git a/test/prism/fixtures/seattlerb/attrasgn_array_lhs.txt b/test/prism/fixtures/seattlerb/attrasgn_array_lhs.txt
new file mode 100644
index 0000000000..0b8e31632d
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/attrasgn_array_lhs.txt
@@ -0,0 +1 @@
+[1, 2, 3, 4][from .. to] = ["a", "b", "c"]
diff --git a/test/prism/fixtures/seattlerb/attrasgn_primary_dot_constant.txt b/test/prism/fixtures/seattlerb/attrasgn_primary_dot_constant.txt
new file mode 100644
index 0000000000..380a718963
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/attrasgn_primary_dot_constant.txt
@@ -0,0 +1 @@
+a.B = 1
diff --git a/test/prism/fixtures/seattlerb/backticks_interpolation_line.txt b/test/prism/fixtures/seattlerb/backticks_interpolation_line.txt
new file mode 100644
index 0000000000..b3ba31c72a
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/backticks_interpolation_line.txt
@@ -0,0 +1 @@
+x `#{y}`
diff --git a/test/prism/fixtures/seattlerb/bang_eq.txt b/test/prism/fixtures/seattlerb/bang_eq.txt
new file mode 100644
index 0000000000..0283460e46
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/bang_eq.txt
@@ -0,0 +1 @@
+1 != 2
diff --git a/test/prism/fixtures/seattlerb/bdot2.txt b/test/prism/fixtures/seattlerb/bdot2.txt
new file mode 100644
index 0000000000..4fb2692299
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/bdot2.txt
@@ -0,0 +1,3 @@
+..10
+; ..a
+; c
diff --git a/test/prism/fixtures/seattlerb/bdot3.txt b/test/prism/fixtures/seattlerb/bdot3.txt
new file mode 100644
index 0000000000..8079cf9872
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/bdot3.txt
@@ -0,0 +1,3 @@
+...10
+; ...a
+; c
diff --git a/test/prism/fixtures/seattlerb/begin_ensure_no_bodies.txt b/test/prism/fixtures/seattlerb/begin_ensure_no_bodies.txt
new file mode 100644
index 0000000000..51dde02ea3
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/begin_ensure_no_bodies.txt
@@ -0,0 +1,3 @@
+begin
+ensure
+end
diff --git a/test/prism/fixtures/seattlerb/begin_rescue_else_ensure_bodies.txt b/test/prism/fixtures/seattlerb/begin_rescue_else_ensure_bodies.txt
new file mode 100644
index 0000000000..ae6e2c3636
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/begin_rescue_else_ensure_bodies.txt
@@ -0,0 +1,9 @@
+begin
+ 1
+rescue
+ 2
+else
+ 3
+ensure
+ 4
+end
diff --git a/test/prism/fixtures/seattlerb/begin_rescue_else_ensure_no_bodies.txt b/test/prism/fixtures/seattlerb/begin_rescue_else_ensure_no_bodies.txt
new file mode 100644
index 0000000000..456d9a5d6e
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/begin_rescue_else_ensure_no_bodies.txt
@@ -0,0 +1,9 @@
+begin
+
+rescue
+
+else
+
+ensure
+
+end
diff --git a/test/prism/fixtures/seattlerb/begin_rescue_ensure_no_bodies.txt b/test/prism/fixtures/seattlerb/begin_rescue_ensure_no_bodies.txt
new file mode 100644
index 0000000000..896e3c030a
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/begin_rescue_ensure_no_bodies.txt
@@ -0,0 +1,4 @@
+begin
+rescue
+ensure
+end
diff --git a/test/prism/fixtures/seattlerb/block_arg__bare.txt b/test/prism/fixtures/seattlerb/block_arg__bare.txt
new file mode 100644
index 0000000000..6454b00345
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/block_arg__bare.txt
@@ -0,0 +1 @@
+def x(&); end
diff --git a/test/prism/fixtures/seattlerb/block_arg_kwsplat.txt b/test/prism/fixtures/seattlerb/block_arg_kwsplat.txt
new file mode 100644
index 0000000000..a9c255cc66
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/block_arg_kwsplat.txt
@@ -0,0 +1 @@
+a { |**b| }
diff --git a/test/prism/fixtures/seattlerb/block_arg_opt_arg_block.txt b/test/prism/fixtures/seattlerb/block_arg_opt_arg_block.txt
new file mode 100644
index 0000000000..14cb02c68e
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/block_arg_opt_arg_block.txt
@@ -0,0 +1 @@
+a { |b, c=1, d, &e| }
diff --git a/test/prism/fixtures/seattlerb/block_arg_opt_splat.txt b/test/prism/fixtures/seattlerb/block_arg_opt_splat.txt
new file mode 100644
index 0000000000..a077ae1f34
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/block_arg_opt_splat.txt
@@ -0,0 +1 @@
+a { |b, c = 1, *d| }
diff --git a/test/prism/fixtures/seattlerb/block_arg_opt_splat_arg_block_omfg.txt b/test/prism/fixtures/seattlerb/block_arg_opt_splat_arg_block_omfg.txt
new file mode 100644
index 0000000000..5016a7c6b9
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/block_arg_opt_splat_arg_block_omfg.txt
@@ -0,0 +1 @@
+a { |b, c=1, *d, e, &f| }
diff --git a/test/prism/fixtures/seattlerb/block_arg_optional.txt b/test/prism/fixtures/seattlerb/block_arg_optional.txt
new file mode 100644
index 0000000000..966afc5640
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/block_arg_optional.txt
@@ -0,0 +1 @@
+a { |b = 1| }
diff --git a/test/prism/fixtures/seattlerb/block_arg_scope.txt b/test/prism/fixtures/seattlerb/block_arg_scope.txt
new file mode 100644
index 0000000000..2362e08559
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/block_arg_scope.txt
@@ -0,0 +1 @@
+a { |b; c| }
diff --git a/test/prism/fixtures/seattlerb/block_arg_scope2.txt b/test/prism/fixtures/seattlerb/block_arg_scope2.txt
new file mode 100644
index 0000000000..f7222dc7b1
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/block_arg_scope2.txt
@@ -0,0 +1 @@
+a {|b; c, d| }
diff --git a/test/prism/fixtures/seattlerb/block_arg_splat_arg.txt b/test/prism/fixtures/seattlerb/block_arg_splat_arg.txt
new file mode 100644
index 0000000000..d7c31aae6b
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/block_arg_splat_arg.txt
@@ -0,0 +1 @@
+a { |b, *c, d| }
diff --git a/test/prism/fixtures/seattlerb/block_args_kwargs.txt b/test/prism/fixtures/seattlerb/block_args_kwargs.txt
new file mode 100644
index 0000000000..467b577a7e
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/block_args_kwargs.txt
@@ -0,0 +1 @@
+f { |**kwargs| kwargs }
diff --git a/test/prism/fixtures/seattlerb/block_args_no_kwargs.txt b/test/prism/fixtures/seattlerb/block_args_no_kwargs.txt
new file mode 100644
index 0000000000..5c9bfa3a62
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/block_args_no_kwargs.txt
@@ -0,0 +1 @@
+f { |**nil| }
diff --git a/test/prism/fixtures/seattlerb/block_args_opt1.txt b/test/prism/fixtures/seattlerb/block_args_opt1.txt
new file mode 100644
index 0000000000..372689e36a
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/block_args_opt1.txt
@@ -0,0 +1 @@
+f { |a, b = 42| [a, b] }
diff --git a/test/prism/fixtures/seattlerb/block_args_opt2.txt b/test/prism/fixtures/seattlerb/block_args_opt2.txt
new file mode 100644
index 0000000000..10d0746646
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/block_args_opt2.txt
@@ -0,0 +1 @@
+a { | b=1, c=2 | }
diff --git a/test/prism/fixtures/seattlerb/block_args_opt2_2.txt b/test/prism/fixtures/seattlerb/block_args_opt2_2.txt
new file mode 100644
index 0000000000..563a9bf915
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/block_args_opt2_2.txt
@@ -0,0 +1 @@
+f { |a, b = 42, c = 24| [a, b, c] }
diff --git a/test/prism/fixtures/seattlerb/block_args_opt3.txt b/test/prism/fixtures/seattlerb/block_args_opt3.txt
new file mode 100644
index 0000000000..bb5a7c8458
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/block_args_opt3.txt
@@ -0,0 +1 @@
+f { |a, b = 42, c = 24, &d| [a, b, c, d] }
diff --git a/test/prism/fixtures/seattlerb/block_call_defn_call_block_call.txt b/test/prism/fixtures/seattlerb/block_call_defn_call_block_call.txt
new file mode 100644
index 0000000000..ff1b3a4c9f
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/block_call_defn_call_block_call.txt
@@ -0,0 +1,4 @@
+a def b(c)
+ d
+ end
+ e.f do end
diff --git a/test/prism/fixtures/seattlerb/block_call_dot_op2_brace_block.txt b/test/prism/fixtures/seattlerb/block_call_dot_op2_brace_block.txt
new file mode 100644
index 0000000000..63da9ee7af
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/block_call_dot_op2_brace_block.txt
@@ -0,0 +1 @@
+a.b c() do d end.e do |f| g end
diff --git a/test/prism/fixtures/seattlerb/block_call_dot_op2_cmd_args_do_block.txt b/test/prism/fixtures/seattlerb/block_call_dot_op2_cmd_args_do_block.txt
new file mode 100644
index 0000000000..24e7d0f1f1
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/block_call_dot_op2_cmd_args_do_block.txt
@@ -0,0 +1 @@
+a.b c() do d end.e f do |g| h end
diff --git a/test/prism/fixtures/seattlerb/block_call_operation_colon.txt b/test/prism/fixtures/seattlerb/block_call_operation_colon.txt
new file mode 100644
index 0000000000..593b9e1bc0
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/block_call_operation_colon.txt
@@ -0,0 +1 @@
+a.b c do end::d
diff --git a/test/prism/fixtures/seattlerb/block_call_operation_dot.txt b/test/prism/fixtures/seattlerb/block_call_operation_dot.txt
new file mode 100644
index 0000000000..20b8e4fcb8
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/block_call_operation_dot.txt
@@ -0,0 +1 @@
+a.b c do end.d
diff --git a/test/prism/fixtures/seattlerb/block_call_paren_call_block_call.txt b/test/prism/fixtures/seattlerb/block_call_paren_call_block_call.txt
new file mode 100644
index 0000000000..7f8be95100
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/block_call_paren_call_block_call.txt
@@ -0,0 +1,2 @@
+a (b)
+c.d do end
diff --git a/test/prism/fixtures/seattlerb/block_command_operation_colon.txt b/test/prism/fixtures/seattlerb/block_command_operation_colon.txt
new file mode 100644
index 0000000000..db221ad496
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/block_command_operation_colon.txt
@@ -0,0 +1 @@
+a :b do end::c :d
diff --git a/test/prism/fixtures/seattlerb/block_command_operation_dot.txt b/test/prism/fixtures/seattlerb/block_command_operation_dot.txt
new file mode 100644
index 0000000000..56b71677e8
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/block_command_operation_dot.txt
@@ -0,0 +1 @@
+a :b do end.c :d
diff --git a/test/prism/fixtures/seattlerb/block_decomp_anon_splat_arg.txt b/test/prism/fixtures/seattlerb/block_decomp_anon_splat_arg.txt
new file mode 100644
index 0000000000..96f5d5d2ec
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/block_decomp_anon_splat_arg.txt
@@ -0,0 +1 @@
+f { |(*, a)| }
diff --git a/test/prism/fixtures/seattlerb/block_decomp_arg_splat.txt b/test/prism/fixtures/seattlerb/block_decomp_arg_splat.txt
new file mode 100644
index 0000000000..f8db3874de
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/block_decomp_arg_splat.txt
@@ -0,0 +1 @@
+a { |(b, *)| }
diff --git a/test/prism/fixtures/seattlerb/block_decomp_arg_splat_arg.txt b/test/prism/fixtures/seattlerb/block_decomp_arg_splat_arg.txt
new file mode 100644
index 0000000000..e64f4e8c3d
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/block_decomp_arg_splat_arg.txt
@@ -0,0 +1 @@
+f { |(a, *b, c)| }
diff --git a/test/prism/fixtures/seattlerb/block_decomp_splat.txt b/test/prism/fixtures/seattlerb/block_decomp_splat.txt
new file mode 100644
index 0000000000..970f00a626
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/block_decomp_splat.txt
@@ -0,0 +1 @@
+f { |(*a)| }
diff --git a/test/prism/fixtures/seattlerb/block_kw.txt b/test/prism/fixtures/seattlerb/block_kw.txt
new file mode 100644
index 0000000000..bacfd32e80
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/block_kw.txt
@@ -0,0 +1 @@
+blah { |k:42| }
diff --git a/test/prism/fixtures/seattlerb/block_kw__required.txt b/test/prism/fixtures/seattlerb/block_kw__required.txt
new file mode 100644
index 0000000000..b84ab97037
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/block_kw__required.txt
@@ -0,0 +1 @@
+blah do |k:| end
diff --git a/test/prism/fixtures/seattlerb/block_kwarg_lvar.txt b/test/prism/fixtures/seattlerb/block_kwarg_lvar.txt
new file mode 100644
index 0000000000..390b9195e0
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/block_kwarg_lvar.txt
@@ -0,0 +1 @@
+bl { |kw: :val| kw }
diff --git a/test/prism/fixtures/seattlerb/block_kwarg_lvar_multiple.txt b/test/prism/fixtures/seattlerb/block_kwarg_lvar_multiple.txt
new file mode 100644
index 0000000000..df3e4afde8
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/block_kwarg_lvar_multiple.txt
@@ -0,0 +1 @@
+bl { |kw: :val, kw2: :val2 | kw }
diff --git a/test/prism/fixtures/seattlerb/block_opt_arg.txt b/test/prism/fixtures/seattlerb/block_opt_arg.txt
new file mode 100644
index 0000000000..5e312fdf41
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/block_opt_arg.txt
@@ -0,0 +1 @@
+a { |b=1, c| }
diff --git a/test/prism/fixtures/seattlerb/block_opt_splat.txt b/test/prism/fixtures/seattlerb/block_opt_splat.txt
new file mode 100644
index 0000000000..772a3fc412
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/block_opt_splat.txt
@@ -0,0 +1 @@
+a { |b = 1, *c| }
diff --git a/test/prism/fixtures/seattlerb/block_opt_splat_arg_block_omfg.txt b/test/prism/fixtures/seattlerb/block_opt_splat_arg_block_omfg.txt
new file mode 100644
index 0000000000..76466f9d54
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/block_opt_splat_arg_block_omfg.txt
@@ -0,0 +1 @@
+a { |b=1, *c, d, &e| }
diff --git a/test/prism/fixtures/seattlerb/block_optarg.txt b/test/prism/fixtures/seattlerb/block_optarg.txt
new file mode 100644
index 0000000000..a471554da1
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/block_optarg.txt
@@ -0,0 +1 @@
+a { |b = :c| }
diff --git a/test/prism/fixtures/seattlerb/block_paren_splat.txt b/test/prism/fixtures/seattlerb/block_paren_splat.txt
new file mode 100644
index 0000000000..3dd4bba1ed
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/block_paren_splat.txt
@@ -0,0 +1 @@
+a { |(b, *c)| }
diff --git a/test/prism/fixtures/seattlerb/block_reg_optarg.txt b/test/prism/fixtures/seattlerb/block_reg_optarg.txt
new file mode 100644
index 0000000000..c024651f78
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/block_reg_optarg.txt
@@ -0,0 +1 @@
+a { |b, c = :d| }
diff --git a/test/prism/fixtures/seattlerb/block_return.txt b/test/prism/fixtures/seattlerb/block_return.txt
new file mode 100644
index 0000000000..f30ba71d8f
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/block_return.txt
@@ -0,0 +1 @@
+return foo arg do |bar| end
diff --git a/test/prism/fixtures/seattlerb/block_scope.txt b/test/prism/fixtures/seattlerb/block_scope.txt
new file mode 100644
index 0000000000..7a83d8ab87
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/block_scope.txt
@@ -0,0 +1 @@
+a { |;b| }
diff --git a/test/prism/fixtures/seattlerb/block_splat_reg.txt b/test/prism/fixtures/seattlerb/block_splat_reg.txt
new file mode 100644
index 0000000000..58f0619e5d
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/block_splat_reg.txt
@@ -0,0 +1 @@
+a { |*b, c| }
diff --git a/test/prism/fixtures/seattlerb/bug169.txt b/test/prism/fixtures/seattlerb/bug169.txt
new file mode 100644
index 0000000000..db2e5ace5e
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/bug169.txt
@@ -0,0 +1 @@
+m () {}
diff --git a/test/prism/fixtures/seattlerb/bug179.txt b/test/prism/fixtures/seattlerb/bug179.txt
new file mode 100644
index 0000000000..02ae07a3be
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/bug179.txt
@@ -0,0 +1 @@
+p ()..nil
diff --git a/test/prism/fixtures/seattlerb/bug190.txt b/test/prism/fixtures/seattlerb/bug190.txt
new file mode 100644
index 0000000000..861b2d305f
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/bug190.txt
@@ -0,0 +1 @@
+%r'\''
diff --git a/test/prism/fixtures/seattlerb/bug191.txt b/test/prism/fixtures/seattlerb/bug191.txt
new file mode 100644
index 0000000000..03f7fd1228
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/bug191.txt
@@ -0,0 +1,3 @@
+a ? "": b
+
+a ? '': b
diff --git a/test/prism/fixtures/seattlerb/bug202.txt b/test/prism/fixtures/seattlerb/bug202.txt
new file mode 100644
index 0000000000..a3b06ffdfc
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/bug202.txt
@@ -0,0 +1,2 @@
+$测试 = 1
+测试 = 1
diff --git a/test/prism/fixtures/seattlerb/bug236.txt b/test/prism/fixtures/seattlerb/bug236.txt
new file mode 100644
index 0000000000..cefe1eb058
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/bug236.txt
@@ -0,0 +1,3 @@
+x{|a,|}
+
+x{|a|}
diff --git a/test/prism/fixtures/seattlerb/bug290.txt b/test/prism/fixtures/seattlerb/bug290.txt
new file mode 100644
index 0000000000..dbcd28cd48
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/bug290.txt
@@ -0,0 +1,3 @@
+begin
+ foo
+end
diff --git a/test/prism/fixtures/seattlerb/bug_187.txt b/test/prism/fixtures/seattlerb/bug_187.txt
new file mode 100644
index 0000000000..1e1ecd8202
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/bug_187.txt
@@ -0,0 +1,3 @@
+private def f
+a.b do end
+end
diff --git a/test/prism/fixtures/seattlerb/bug_215.txt b/test/prism/fixtures/seattlerb/bug_215.txt
new file mode 100644
index 0000000000..f0d09ba5ff
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/bug_215.txt
@@ -0,0 +1 @@
+undef %s(foo)
diff --git a/test/prism/fixtures/seattlerb/bug_249.txt b/test/prism/fixtures/seattlerb/bug_249.txt
new file mode 100644
index 0000000000..ccccdf5326
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/bug_249.txt
@@ -0,0 +1,4 @@
+mount (Class.new do
+def initialize
+end
+ end).new, :at => 'endpoint'
diff --git a/test/prism/fixtures/seattlerb/bug_and.txt b/test/prism/fixtures/seattlerb/bug_and.txt
new file mode 100644
index 0000000000..6243359a9e
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/bug_and.txt
@@ -0,0 +1,4 @@
+true and
+true
+
+true and []
diff --git a/test/prism/fixtures/seattlerb/bug_args__19.txt b/test/prism/fixtures/seattlerb/bug_args__19.txt
new file mode 100644
index 0000000000..08466554fd
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/bug_args__19.txt
@@ -0,0 +1 @@
+f { |(a, b)| d }
diff --git a/test/prism/fixtures/seattlerb/bug_args_masgn.txt b/test/prism/fixtures/seattlerb/bug_args_masgn.txt
new file mode 100644
index 0000000000..e0a71e9197
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/bug_args_masgn.txt
@@ -0,0 +1 @@
+f { |(a, b), c| }
diff --git a/test/prism/fixtures/seattlerb/bug_args_masgn2.txt b/test/prism/fixtures/seattlerb/bug_args_masgn2.txt
new file mode 100644
index 0000000000..2f12756bfe
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/bug_args_masgn2.txt
@@ -0,0 +1 @@
+f { |((a, b), c), d| }
diff --git a/test/prism/fixtures/seattlerb/bug_args_masgn_outer_parens__19.txt b/test/prism/fixtures/seattlerb/bug_args_masgn_outer_parens__19.txt
new file mode 100644
index 0000000000..a2b0178676
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/bug_args_masgn_outer_parens__19.txt
@@ -0,0 +1 @@
+f { |((k, v), i)| }
diff --git a/test/prism/fixtures/seattlerb/bug_call_arglist_parens.txt b/test/prism/fixtures/seattlerb/bug_call_arglist_parens.txt
new file mode 100644
index 0000000000..4f04368802
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/bug_call_arglist_parens.txt
@@ -0,0 +1,11 @@
+ def f
+ g ( 1), 2
+ end
+
+
+ def f()
+ g (1), 2
+ end
+
+
+g ( 1), 2
diff --git a/test/prism/fixtures/seattlerb/bug_case_when_regexp.txt b/test/prism/fixtures/seattlerb/bug_case_when_regexp.txt
new file mode 100644
index 0000000000..2536696a42
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/bug_case_when_regexp.txt
@@ -0,0 +1 @@
+case :x; when /x/ then end
diff --git a/test/prism/fixtures/seattlerb/bug_comma.txt b/test/prism/fixtures/seattlerb/bug_comma.txt
new file mode 100644
index 0000000000..d86f1ea9dd
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/bug_comma.txt
@@ -0,0 +1 @@
+if test ?d, dir then end
diff --git a/test/prism/fixtures/seattlerb/bug_cond_pct.txt b/test/prism/fixtures/seattlerb/bug_cond_pct.txt
new file mode 100644
index 0000000000..1b4f90058e
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/bug_cond_pct.txt
@@ -0,0 +1 @@
+case; when %r%blahblah%; end
diff --git a/test/prism/fixtures/seattlerb/bug_hash_args.txt b/test/prism/fixtures/seattlerb/bug_hash_args.txt
new file mode 100644
index 0000000000..b815f8a666
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/bug_hash_args.txt
@@ -0,0 +1 @@
+foo(:bar, baz: nil)
diff --git a/test/prism/fixtures/seattlerb/bug_hash_args_trailing_comma.txt b/test/prism/fixtures/seattlerb/bug_hash_args_trailing_comma.txt
new file mode 100644
index 0000000000..6057b245a5
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/bug_hash_args_trailing_comma.txt
@@ -0,0 +1 @@
+foo(:bar, baz: nil,)
diff --git a/test/prism/fixtures/seattlerb/bug_hash_interp_array.txt b/test/prism/fixtures/seattlerb/bug_hash_interp_array.txt
new file mode 100644
index 0000000000..01fe238056
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/bug_hash_interp_array.txt
@@ -0,0 +1 @@
+{ "#{}": [] }
diff --git a/test/prism/fixtures/seattlerb/bug_masgn_right.txt b/test/prism/fixtures/seattlerb/bug_masgn_right.txt
new file mode 100644
index 0000000000..12ea7b8d62
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/bug_masgn_right.txt
@@ -0,0 +1 @@
+f { |a, (b, c)| }
diff --git a/test/prism/fixtures/seattlerb/bug_not_parens.txt b/test/prism/fixtures/seattlerb/bug_not_parens.txt
new file mode 100644
index 0000000000..8847b7bec6
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/bug_not_parens.txt
@@ -0,0 +1 @@
+not(a)
diff --git a/test/prism/fixtures/seattlerb/bug_op_asgn_rescue.txt b/test/prism/fixtures/seattlerb/bug_op_asgn_rescue.txt
new file mode 100644
index 0000000000..6a0b25cbdc
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/bug_op_asgn_rescue.txt
@@ -0,0 +1 @@
+a ||= b rescue nil
diff --git a/test/prism/fixtures/seattlerb/call_and.txt b/test/prism/fixtures/seattlerb/call_and.txt
new file mode 100644
index 0000000000..c17be8f356
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/call_and.txt
@@ -0,0 +1 @@
+1 & 2
diff --git a/test/prism/fixtures/seattlerb/call_arg_assoc.txt b/test/prism/fixtures/seattlerb/call_arg_assoc.txt
new file mode 100644
index 0000000000..376c299be5
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/call_arg_assoc.txt
@@ -0,0 +1 @@
+f(1, 2=>3)
diff --git a/test/prism/fixtures/seattlerb/call_arg_assoc_kwsplat.txt b/test/prism/fixtures/seattlerb/call_arg_assoc_kwsplat.txt
new file mode 100644
index 0000000000..a4be0fb62c
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/call_arg_assoc_kwsplat.txt
@@ -0,0 +1 @@
+f(1, kw: 2, **3)
diff --git a/test/prism/fixtures/seattlerb/call_arg_kwsplat.txt b/test/prism/fixtures/seattlerb/call_arg_kwsplat.txt
new file mode 100644
index 0000000000..4848fd9e8d
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/call_arg_kwsplat.txt
@@ -0,0 +1 @@
+a(b, **1)
diff --git a/test/prism/fixtures/seattlerb/call_args_assoc_quoted.txt b/test/prism/fixtures/seattlerb/call_args_assoc_quoted.txt
new file mode 100644
index 0000000000..0af2259577
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/call_args_assoc_quoted.txt
@@ -0,0 +1,5 @@
+x "#{k}":42
+
+x "k":42
+
+x 'k':42
diff --git a/test/prism/fixtures/seattlerb/call_args_assoc_trailing_comma.txt b/test/prism/fixtures/seattlerb/call_args_assoc_trailing_comma.txt
new file mode 100644
index 0000000000..6ad08f3238
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/call_args_assoc_trailing_comma.txt
@@ -0,0 +1 @@
+f(1, 2=>3,)
diff --git a/test/prism/fixtures/seattlerb/call_args_command.txt b/test/prism/fixtures/seattlerb/call_args_command.txt
new file mode 100644
index 0000000000..dd6df29c7b
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/call_args_command.txt
@@ -0,0 +1 @@
+a.b c.d 1
diff --git a/test/prism/fixtures/seattlerb/call_array_arg.txt b/test/prism/fixtures/seattlerb/call_array_arg.txt
new file mode 100644
index 0000000000..5c724fa328
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/call_array_arg.txt
@@ -0,0 +1 @@
+1 == [:b, :c]
diff --git a/test/prism/fixtures/seattlerb/call_array_block_call.txt b/test/prism/fixtures/seattlerb/call_array_block_call.txt
new file mode 100644
index 0000000000..6d4c1b276e
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/call_array_block_call.txt
@@ -0,0 +1 @@
+a [ nil, b do end ]
diff --git a/test/prism/fixtures/seattlerb/call_array_lambda_block_call.txt b/test/prism/fixtures/seattlerb/call_array_lambda_block_call.txt
new file mode 100644
index 0000000000..dc5b5807b2
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/call_array_lambda_block_call.txt
@@ -0,0 +1,2 @@
+a [->() {}] do
+end
diff --git a/test/prism/fixtures/seattlerb/call_array_lit_inline_hash.txt b/test/prism/fixtures/seattlerb/call_array_lit_inline_hash.txt
new file mode 100644
index 0000000000..daba00947e
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/call_array_lit_inline_hash.txt
@@ -0,0 +1 @@
+a([:b, :c => 1])
diff --git a/test/prism/fixtures/seattlerb/call_assoc.txt b/test/prism/fixtures/seattlerb/call_assoc.txt
new file mode 100644
index 0000000000..2adc1eee1c
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/call_assoc.txt
@@ -0,0 +1 @@
+f(2=>3)
diff --git a/test/prism/fixtures/seattlerb/call_assoc_new.txt b/test/prism/fixtures/seattlerb/call_assoc_new.txt
new file mode 100644
index 0000000000..b8457bfdfc
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/call_assoc_new.txt
@@ -0,0 +1 @@
+f(a:3)
diff --git a/test/prism/fixtures/seattlerb/call_assoc_new_if_multiline.txt b/test/prism/fixtures/seattlerb/call_assoc_new_if_multiline.txt
new file mode 100644
index 0000000000..fe0a37dabb
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/call_assoc_new_if_multiline.txt
@@ -0,0 +1,5 @@
+a(b: if :c
+1
+else
+2
+end)
diff --git a/test/prism/fixtures/seattlerb/call_assoc_trailing_comma.txt b/test/prism/fixtures/seattlerb/call_assoc_trailing_comma.txt
new file mode 100644
index 0000000000..4d86a4541d
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/call_assoc_trailing_comma.txt
@@ -0,0 +1 @@
+f(1=>2,)
diff --git a/test/prism/fixtures/seattlerb/call_bang_command_call.txt b/test/prism/fixtures/seattlerb/call_bang_command_call.txt
new file mode 100644
index 0000000000..4f3ba4b93c
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/call_bang_command_call.txt
@@ -0,0 +1 @@
+! a.b 1
diff --git a/test/prism/fixtures/seattlerb/call_bang_squiggle.txt b/test/prism/fixtures/seattlerb/call_bang_squiggle.txt
new file mode 100644
index 0000000000..d7039f910a
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/call_bang_squiggle.txt
@@ -0,0 +1 @@
+1 !~ 2
diff --git a/test/prism/fixtures/seattlerb/call_begin_call_block_call.txt b/test/prism/fixtures/seattlerb/call_begin_call_block_call.txt
new file mode 100644
index 0000000000..e9b43491fe
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/call_begin_call_block_call.txt
@@ -0,0 +1,3 @@
+a begin
+b.c do end
+end
diff --git a/test/prism/fixtures/seattlerb/call_block_arg_named.txt b/test/prism/fixtures/seattlerb/call_block_arg_named.txt
new file mode 100644
index 0000000000..08fea89d11
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/call_block_arg_named.txt
@@ -0,0 +1 @@
+x(&blk)
diff --git a/test/prism/fixtures/seattlerb/call_carat.txt b/test/prism/fixtures/seattlerb/call_carat.txt
new file mode 100644
index 0000000000..3e88c09837
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/call_carat.txt
@@ -0,0 +1 @@
+1 ^ 2
diff --git a/test/prism/fixtures/seattlerb/call_colon2.txt b/test/prism/fixtures/seattlerb/call_colon2.txt
new file mode 100644
index 0000000000..47aab7e637
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/call_colon2.txt
@@ -0,0 +1 @@
+A::b
diff --git a/test/prism/fixtures/seattlerb/call_colon_parens.txt b/test/prism/fixtures/seattlerb/call_colon_parens.txt
new file mode 100644
index 0000000000..51ed4df11b
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/call_colon_parens.txt
@@ -0,0 +1 @@
+1::()
diff --git a/test/prism/fixtures/seattlerb/call_div.txt b/test/prism/fixtures/seattlerb/call_div.txt
new file mode 100644
index 0000000000..85b4d7b0b0
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/call_div.txt
@@ -0,0 +1 @@
+1 / 2
diff --git a/test/prism/fixtures/seattlerb/call_dot_parens.txt b/test/prism/fixtures/seattlerb/call_dot_parens.txt
new file mode 100644
index 0000000000..0270596a07
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/call_dot_parens.txt
@@ -0,0 +1 @@
+1.()
diff --git a/test/prism/fixtures/seattlerb/call_env.txt b/test/prism/fixtures/seattlerb/call_env.txt
new file mode 100644
index 0000000000..dadc0d3861
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/call_env.txt
@@ -0,0 +1 @@
+a.happy
diff --git a/test/prism/fixtures/seattlerb/call_eq3.txt b/test/prism/fixtures/seattlerb/call_eq3.txt
new file mode 100644
index 0000000000..6a2fb465cb
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/call_eq3.txt
@@ -0,0 +1 @@
+1 === 2
diff --git a/test/prism/fixtures/seattlerb/call_gt.txt b/test/prism/fixtures/seattlerb/call_gt.txt
new file mode 100644
index 0000000000..9d0a1caa90
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/call_gt.txt
@@ -0,0 +1 @@
+1 > 2
diff --git a/test/prism/fixtures/seattlerb/call_kwsplat.txt b/test/prism/fixtures/seattlerb/call_kwsplat.txt
new file mode 100644
index 0000000000..eda700c3e1
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/call_kwsplat.txt
@@ -0,0 +1 @@
+a(**1)
diff --git a/test/prism/fixtures/seattlerb/call_leading_dots.txt b/test/prism/fixtures/seattlerb/call_leading_dots.txt
new file mode 100644
index 0000000000..1e7b2e5179
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/call_leading_dots.txt
@@ -0,0 +1,3 @@
+a
+.b
+.c
diff --git a/test/prism/fixtures/seattlerb/call_leading_dots_comment.txt b/test/prism/fixtures/seattlerb/call_leading_dots_comment.txt
new file mode 100644
index 0000000000..c5deec5642
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/call_leading_dots_comment.txt
@@ -0,0 +1,4 @@
+a
+.b
+#.c
+.d
diff --git a/test/prism/fixtures/seattlerb/call_lt.txt b/test/prism/fixtures/seattlerb/call_lt.txt
new file mode 100644
index 0000000000..17e69c79b5
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/call_lt.txt
@@ -0,0 +1 @@
+1 < 2
diff --git a/test/prism/fixtures/seattlerb/call_lte.txt b/test/prism/fixtures/seattlerb/call_lte.txt
new file mode 100644
index 0000000000..7574027634
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/call_lte.txt
@@ -0,0 +1 @@
+1 <= 2
diff --git a/test/prism/fixtures/seattlerb/call_not.txt b/test/prism/fixtures/seattlerb/call_not.txt
new file mode 100644
index 0000000000..51e4742f55
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/call_not.txt
@@ -0,0 +1 @@
+not 42
diff --git a/test/prism/fixtures/seattlerb/call_pipe.txt b/test/prism/fixtures/seattlerb/call_pipe.txt
new file mode 100644
index 0000000000..1555910665
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/call_pipe.txt
@@ -0,0 +1 @@
+1 | 2
diff --git a/test/prism/fixtures/seattlerb/call_rshift.txt b/test/prism/fixtures/seattlerb/call_rshift.txt
new file mode 100644
index 0000000000..9ff1def4e0
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/call_rshift.txt
@@ -0,0 +1 @@
+1 >> 2
diff --git a/test/prism/fixtures/seattlerb/call_self_brackets.txt b/test/prism/fixtures/seattlerb/call_self_brackets.txt
new file mode 100644
index 0000000000..6533df2ce0
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/call_self_brackets.txt
@@ -0,0 +1 @@
+self[1]
diff --git a/test/prism/fixtures/seattlerb/call_spaceship.txt b/test/prism/fixtures/seattlerb/call_spaceship.txt
new file mode 100644
index 0000000000..905c3a1c46
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/call_spaceship.txt
@@ -0,0 +1 @@
+1 <=> 2
diff --git a/test/prism/fixtures/seattlerb/call_stabby_do_end_with_block.txt b/test/prism/fixtures/seattlerb/call_stabby_do_end_with_block.txt
new file mode 100644
index 0000000000..2d1afdad28
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/call_stabby_do_end_with_block.txt
@@ -0,0 +1 @@
+a -> do 1 end do 2 end
diff --git a/test/prism/fixtures/seattlerb/call_stabby_with_braces_block.txt b/test/prism/fixtures/seattlerb/call_stabby_with_braces_block.txt
new file mode 100644
index 0000000000..0d995a04d1
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/call_stabby_with_braces_block.txt
@@ -0,0 +1 @@
+a -> { 1 } do 2 end
diff --git a/test/prism/fixtures/seattlerb/call_star.txt b/test/prism/fixtures/seattlerb/call_star.txt
new file mode 100644
index 0000000000..096ec022d4
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/call_star.txt
@@ -0,0 +1 @@
+1 * 2
diff --git a/test/prism/fixtures/seattlerb/call_star2.txt b/test/prism/fixtures/seattlerb/call_star2.txt
new file mode 100644
index 0000000000..bef4719d3c
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/call_star2.txt
@@ -0,0 +1 @@
+1 ** 2
diff --git a/test/prism/fixtures/seattlerb/call_trailing_comma.txt b/test/prism/fixtures/seattlerb/call_trailing_comma.txt
new file mode 100644
index 0000000000..e9a3ca35be
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/call_trailing_comma.txt
@@ -0,0 +1 @@
+f(1,)
diff --git a/test/prism/fixtures/seattlerb/call_trailing_dots.txt b/test/prism/fixtures/seattlerb/call_trailing_dots.txt
new file mode 100644
index 0000000000..960cdbb45f
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/call_trailing_dots.txt
@@ -0,0 +1,3 @@
+a.
+b.
+c
diff --git a/test/prism/fixtures/seattlerb/call_unary_bang.txt b/test/prism/fixtures/seattlerb/call_unary_bang.txt
new file mode 100644
index 0000000000..91f702d4a9
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/call_unary_bang.txt
@@ -0,0 +1 @@
+!1
diff --git a/test/prism/fixtures/seattlerb/case_in.txt b/test/prism/fixtures/seattlerb/case_in.txt
new file mode 100644
index 0000000000..0835da0956
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/case_in.txt
@@ -0,0 +1,111 @@
+case :a
+in "b":
+end
+
+case :a
+in %I[a b]
+end
+
+case :a
+in %W[a b]
+end
+
+case :a
+in %i[a b]
+end
+
+case :a
+in %w[a b]
+end
+
+case :a
+in (...10)
+end
+
+case :a
+in (..10)
+end
+
+case :a
+in (1...)
+end
+
+case :a
+in (1...3)
+end
+
+case :a
+in (42)
+end
+
+case :a
+in **nil
+end
+
+case :a
+in /regexp/
+end
+
+case :a
+in :b, *_, :c
+end
+
+case :a
+in :b, [:c]
+end
+
+case :a
+in Symbol()
+end
+
+case :a
+in Symbol(*lhs, x, *rhs)
+end
+
+case :a
+in Symbol[*lhs, x, *rhs]
+end
+
+case :a
+in [->(b) { true }, c]
+end
+
+case :a
+in [:a, b, c, [:d, *e, nil]]
+end
+
+case :a
+in [A, *, B]
+end
+
+case :a
+in [[:b, c], [:d, ^e]]
+end
+
+case :a
+in []
+end
+
+case :a
+in [^(a)]
+end
+
+case :a
+in [^@a, ^$b, ^@@c]
+end
+
+case :a
+in `echo hi`
+end
+
+case :a
+in nil, nil, nil
+end
+
+case :a
+in { "b": }
+end
+
+case :a
+in {}
+end
diff --git a/test/prism/fixtures/seattlerb/case_in_31.txt b/test/prism/fixtures/seattlerb/case_in_31.txt
new file mode 100644
index 0000000000..b9bf25b132
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/case_in_31.txt
@@ -0,0 +1,4 @@
+case :a
+in [:b, *c]
+ :d
+end
diff --git a/test/prism/fixtures/seattlerb/case_in_37.txt b/test/prism/fixtures/seattlerb/case_in_37.txt
new file mode 100644
index 0000000000..25b6fb9261
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/case_in_37.txt
@@ -0,0 +1,4 @@
+case :a
+in { b: [Hash, *] }
+ :c
+end
diff --git a/test/prism/fixtures/seattlerb/case_in_42.txt b/test/prism/fixtures/seattlerb/case_in_42.txt
new file mode 100644
index 0000000000..bc6a2233f5
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/case_in_42.txt
@@ -0,0 +1,3 @@
+case :a
+in :b, *_ then nil
+end
diff --git a/test/prism/fixtures/seattlerb/case_in_42_2.txt b/test/prism/fixtures/seattlerb/case_in_42_2.txt
new file mode 100644
index 0000000000..ce4b65a5d0
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/case_in_42_2.txt
@@ -0,0 +1,3 @@
+case :a
+in A(*list) then nil
+end
diff --git a/test/prism/fixtures/seattlerb/case_in_47.txt b/test/prism/fixtures/seattlerb/case_in_47.txt
new file mode 100644
index 0000000000..60f17ed7ce
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/case_in_47.txt
@@ -0,0 +1,4 @@
+case :a
+in [*, :b, :c]
+ :d
+end
diff --git a/test/prism/fixtures/seattlerb/case_in_67.txt b/test/prism/fixtures/seattlerb/case_in_67.txt
new file mode 100644
index 0000000000..c1c55e68c7
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/case_in_67.txt
@@ -0,0 +1,3 @@
+case :a
+in 1.. then nil
+end
diff --git a/test/prism/fixtures/seattlerb/case_in_86.txt b/test/prism/fixtures/seattlerb/case_in_86.txt
new file mode 100644
index 0000000000..63ba92e533
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/case_in_86.txt
@@ -0,0 +1,3 @@
+case [:a, :b]
+in ::NilClass, * then nil
+end
diff --git a/test/prism/fixtures/seattlerb/case_in_86_2.txt b/test/prism/fixtures/seattlerb/case_in_86_2.txt
new file mode 100644
index 0000000000..4ad16c451a
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/case_in_86_2.txt
@@ -0,0 +1,3 @@
+case [:a, :b]
+in *, ::NilClass then nil
+end
diff --git a/test/prism/fixtures/seattlerb/case_in_array_pat_const.txt b/test/prism/fixtures/seattlerb/case_in_array_pat_const.txt
new file mode 100644
index 0000000000..8551e48e2c
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/case_in_array_pat_const.txt
@@ -0,0 +1,4 @@
+case :a
+in B[c]
+ :d
+end
diff --git a/test/prism/fixtures/seattlerb/case_in_array_pat_const2.txt b/test/prism/fixtures/seattlerb/case_in_array_pat_const2.txt
new file mode 100644
index 0000000000..fca423ea61
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/case_in_array_pat_const2.txt
@@ -0,0 +1,4 @@
+case :a
+in B::C[d]
+ :e
+end
diff --git a/test/prism/fixtures/seattlerb/case_in_array_pat_paren_assign.txt b/test/prism/fixtures/seattlerb/case_in_array_pat_paren_assign.txt
new file mode 100644
index 0000000000..c56f728337
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/case_in_array_pat_paren_assign.txt
@@ -0,0 +1,4 @@
+case :a
+in B(C => d)
+ :d
+end
diff --git a/test/prism/fixtures/seattlerb/case_in_const.txt b/test/prism/fixtures/seattlerb/case_in_const.txt
new file mode 100644
index 0000000000..5b0dcc18e2
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/case_in_const.txt
@@ -0,0 +1,4 @@
+case Array
+in Class
+ :b
+end
diff --git a/test/prism/fixtures/seattlerb/case_in_else.txt b/test/prism/fixtures/seattlerb/case_in_else.txt
new file mode 100644
index 0000000000..6f096862c5
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/case_in_else.txt
@@ -0,0 +1,7 @@
+case Array
+in Class
+ :b
+else
+ :c
+end
+
diff --git a/test/prism/fixtures/seattlerb/case_in_find.txt b/test/prism/fixtures/seattlerb/case_in_find.txt
new file mode 100644
index 0000000000..476fcabe11
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/case_in_find.txt
@@ -0,0 +1,3 @@
+case :a
+ in *a, :+, *b
+end
diff --git a/test/prism/fixtures/seattlerb/case_in_find_array.txt b/test/prism/fixtures/seattlerb/case_in_find_array.txt
new file mode 100644
index 0000000000..5eb4010b7f
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/case_in_find_array.txt
@@ -0,0 +1,3 @@
+case :a
+in [*, :b, c, *]
+end
diff --git a/test/prism/fixtures/seattlerb/case_in_hash_pat.txt b/test/prism/fixtures/seattlerb/case_in_hash_pat.txt
new file mode 100644
index 0000000000..cb012e8d99
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/case_in_hash_pat.txt
@@ -0,0 +1,5 @@
+case :a
+in { b: 'c', d: "e" } then
+ :f
+end
+
diff --git a/test/prism/fixtures/seattlerb/case_in_hash_pat_assign.txt b/test/prism/fixtures/seattlerb/case_in_hash_pat_assign.txt
new file mode 100644
index 0000000000..58fd59ff9c
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/case_in_hash_pat_assign.txt
@@ -0,0 +1,4 @@
+case :a
+in { b: Integer => x, d: "e", f: } then
+ :g
+end
diff --git a/test/prism/fixtures/seattlerb/case_in_hash_pat_paren_assign.txt b/test/prism/fixtures/seattlerb/case_in_hash_pat_paren_assign.txt
new file mode 100644
index 0000000000..de3a10740c
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/case_in_hash_pat_paren_assign.txt
@@ -0,0 +1,4 @@
+case :a
+in B(a: 42)
+ :d
+end
diff --git a/test/prism/fixtures/seattlerb/case_in_hash_pat_paren_true.txt b/test/prism/fixtures/seattlerb/case_in_hash_pat_paren_true.txt
new file mode 100644
index 0000000000..449fd0d4d4
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/case_in_hash_pat_paren_true.txt
@@ -0,0 +1,5 @@
+case :a
+in b: true then
+ :c
+end
+
diff --git a/test/prism/fixtures/seattlerb/case_in_hash_pat_rest.txt b/test/prism/fixtures/seattlerb/case_in_hash_pat_rest.txt
new file mode 100644
index 0000000000..6f67cb1d10
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/case_in_hash_pat_rest.txt
@@ -0,0 +1,3 @@
+case :a
+in b: c, **rest then :d
+end
diff --git a/test/prism/fixtures/seattlerb/case_in_hash_pat_rest_solo.txt b/test/prism/fixtures/seattlerb/case_in_hash_pat_rest_solo.txt
new file mode 100644
index 0000000000..91d0592412
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/case_in_hash_pat_rest_solo.txt
@@ -0,0 +1,3 @@
+case :a
+in **rest then :d
+end
diff --git a/test/prism/fixtures/seattlerb/case_in_if_unless_post_mod.txt b/test/prism/fixtures/seattlerb/case_in_if_unless_post_mod.txt
new file mode 100644
index 0000000000..dbe24a5c8a
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/case_in_if_unless_post_mod.txt
@@ -0,0 +1,6 @@
+case :a
+in A if true
+ :C
+in D unless false
+ :E
+end
diff --git a/test/prism/fixtures/seattlerb/case_in_multiple.txt b/test/prism/fixtures/seattlerb/case_in_multiple.txt
new file mode 100644
index 0000000000..1b6dd06cfe
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/case_in_multiple.txt
@@ -0,0 +1,6 @@
+case :a
+in A::B
+ :C
+in D::E
+ :F
+end
diff --git a/test/prism/fixtures/seattlerb/case_in_or.txt b/test/prism/fixtures/seattlerb/case_in_or.txt
new file mode 100644
index 0000000000..875e37749f
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/case_in_or.txt
@@ -0,0 +1,5 @@
+case :a
+in B | C
+ :d
+end
+
diff --git a/test/prism/fixtures/seattlerb/class_comments.txt b/test/prism/fixtures/seattlerb/class_comments.txt
new file mode 100644
index 0000000000..9701eca7e5
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/class_comments.txt
@@ -0,0 +1,9 @@
+# blah 1
+# blah 2
+
+class X
+ # blah 3
+ def blah
+ # blah 4
+ end
+end
diff --git a/test/prism/fixtures/seattlerb/cond_unary_minus.txt b/test/prism/fixtures/seattlerb/cond_unary_minus.txt
new file mode 100644
index 0000000000..80293115da
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/cond_unary_minus.txt
@@ -0,0 +1 @@
+if -1; end
diff --git a/test/prism/fixtures/seattlerb/const_2_op_asgn_or2.txt b/test/prism/fixtures/seattlerb/const_2_op_asgn_or2.txt
new file mode 100644
index 0000000000..6912c2d76b
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/const_2_op_asgn_or2.txt
@@ -0,0 +1 @@
+::X::Y ||= 1
diff --git a/test/prism/fixtures/seattlerb/const_3_op_asgn_or.txt b/test/prism/fixtures/seattlerb/const_3_op_asgn_or.txt
new file mode 100644
index 0000000000..bbcd25a369
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/const_3_op_asgn_or.txt
@@ -0,0 +1 @@
+::X ||= 1
diff --git a/test/prism/fixtures/seattlerb/const_op_asgn_and1.txt b/test/prism/fixtures/seattlerb/const_op_asgn_and1.txt
new file mode 100644
index 0000000000..3964df0ead
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/const_op_asgn_and1.txt
@@ -0,0 +1 @@
+::X &= 1
diff --git a/test/prism/fixtures/seattlerb/const_op_asgn_and2.txt b/test/prism/fixtures/seattlerb/const_op_asgn_and2.txt
new file mode 100644
index 0000000000..1bef4b4154
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/const_op_asgn_and2.txt
@@ -0,0 +1 @@
+::X &&= 1
diff --git a/test/prism/fixtures/seattlerb/const_op_asgn_or.txt b/test/prism/fixtures/seattlerb/const_op_asgn_or.txt
new file mode 100644
index 0000000000..729e425262
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/const_op_asgn_or.txt
@@ -0,0 +1 @@
+X::Y ||= 1
diff --git a/test/prism/fixtures/seattlerb/defined_eh_parens.txt b/test/prism/fixtures/seattlerb/defined_eh_parens.txt
new file mode 100644
index 0000000000..5ca5d9f4c4
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/defined_eh_parens.txt
@@ -0,0 +1 @@
+defined?(42)
diff --git a/test/prism/fixtures/seattlerb/defn_arg_asplat_arg.txt b/test/prism/fixtures/seattlerb/defn_arg_asplat_arg.txt
new file mode 100644
index 0000000000..f629a5de60
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/defn_arg_asplat_arg.txt
@@ -0,0 +1 @@
+def call(interp, *, args) end
diff --git a/test/prism/fixtures/seattlerb/defn_arg_forward_args.txt b/test/prism/fixtures/seattlerb/defn_arg_forward_args.txt
new file mode 100644
index 0000000000..500e2e1fe0
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/defn_arg_forward_args.txt
@@ -0,0 +1 @@
+def a(x, ...); b(x, ...); end
diff --git a/test/prism/fixtures/seattlerb/defn_args_forward_args.txt b/test/prism/fixtures/seattlerb/defn_args_forward_args.txt
new file mode 100644
index 0000000000..fc1ee138de
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/defn_args_forward_args.txt
@@ -0,0 +1 @@
+def a(x, y, z, ...); b(:get, z, ...); end
diff --git a/test/prism/fixtures/seattlerb/defn_comments.txt b/test/prism/fixtures/seattlerb/defn_comments.txt
new file mode 100644
index 0000000000..04c7ea1a10
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/defn_comments.txt
@@ -0,0 +1,5 @@
+# blah 1
+# blah 2
+
+def blah
+end
diff --git a/test/prism/fixtures/seattlerb/defn_endless_command.txt b/test/prism/fixtures/seattlerb/defn_endless_command.txt
new file mode 100644
index 0000000000..172de2ca6c
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/defn_endless_command.txt
@@ -0,0 +1 @@
+def some_method = other_method 42
diff --git a/test/prism/fixtures/seattlerb/defn_endless_command_rescue.txt b/test/prism/fixtures/seattlerb/defn_endless_command_rescue.txt
new file mode 100644
index 0000000000..05ed392e38
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/defn_endless_command_rescue.txt
@@ -0,0 +1 @@
+def some_method = other_method 42 rescue 24
diff --git a/test/prism/fixtures/seattlerb/defn_forward_args.txt b/test/prism/fixtures/seattlerb/defn_forward_args.txt
new file mode 100644
index 0000000000..46ed199875
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/defn_forward_args.txt
@@ -0,0 +1 @@
+def a(...); b(...); end
diff --git a/test/prism/fixtures/seattlerb/defn_forward_args__no_parens.txt b/test/prism/fixtures/seattlerb/defn_forward_args__no_parens.txt
new file mode 100644
index 0000000000..2d34077c93
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/defn_forward_args__no_parens.txt
@@ -0,0 +1,3 @@
+def f ...
+ m(...)
+end
diff --git a/test/prism/fixtures/seattlerb/defn_kwarg_env.txt b/test/prism/fixtures/seattlerb/defn_kwarg_env.txt
new file mode 100644
index 0000000000..b512677195
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/defn_kwarg_env.txt
@@ -0,0 +1 @@
+def test(**testing) test_splat(**testing) end
diff --git a/test/prism/fixtures/seattlerb/defn_kwarg_kwarg.txt b/test/prism/fixtures/seattlerb/defn_kwarg_kwarg.txt
new file mode 100644
index 0000000000..3962d2645c
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/defn_kwarg_kwarg.txt
@@ -0,0 +1 @@
+def f(a, b: 1, c: 2) end
diff --git a/test/prism/fixtures/seattlerb/defn_kwarg_kwsplat.txt b/test/prism/fixtures/seattlerb/defn_kwarg_kwsplat.txt
new file mode 100644
index 0000000000..bd39819482
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/defn_kwarg_kwsplat.txt
@@ -0,0 +1 @@
+def a(b: 1, **c) end
diff --git a/test/prism/fixtures/seattlerb/defn_kwarg_kwsplat_anon.txt b/test/prism/fixtures/seattlerb/defn_kwarg_kwsplat_anon.txt
new file mode 100644
index 0000000000..aba71cba07
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/defn_kwarg_kwsplat_anon.txt
@@ -0,0 +1 @@
+def a(b: 1, **) end
diff --git a/test/prism/fixtures/seattlerb/defn_kwarg_lvar.txt b/test/prism/fixtures/seattlerb/defn_kwarg_lvar.txt
new file mode 100644
index 0000000000..9eac108cca
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/defn_kwarg_lvar.txt
@@ -0,0 +1 @@
+def fun(kw: :val); kw; end
diff --git a/test/prism/fixtures/seattlerb/defn_kwarg_no_parens.txt b/test/prism/fixtures/seattlerb/defn_kwarg_no_parens.txt
new file mode 100644
index 0000000000..481457bf0e
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/defn_kwarg_no_parens.txt
@@ -0,0 +1,2 @@
+def f a: 1
+end
diff --git a/test/prism/fixtures/seattlerb/defn_kwarg_val.txt b/test/prism/fixtures/seattlerb/defn_kwarg_val.txt
new file mode 100644
index 0000000000..1a2803926f
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/defn_kwarg_val.txt
@@ -0,0 +1 @@
+def f(a, b:1) end
diff --git a/test/prism/fixtures/seattlerb/defn_no_kwargs.txt b/test/prism/fixtures/seattlerb/defn_no_kwargs.txt
new file mode 100644
index 0000000000..857ec8debb
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/defn_no_kwargs.txt
@@ -0,0 +1 @@
+def x(**nil); end
diff --git a/test/prism/fixtures/seattlerb/defn_oneliner.txt b/test/prism/fixtures/seattlerb/defn_oneliner.txt
new file mode 100644
index 0000000000..4aef08ce46
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/defn_oneliner.txt
@@ -0,0 +1 @@
+def exec(cmd) = system(cmd)
diff --git a/test/prism/fixtures/seattlerb/defn_oneliner_eq2.txt b/test/prism/fixtures/seattlerb/defn_oneliner_eq2.txt
new file mode 100644
index 0000000000..1b1ce27a15
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/defn_oneliner_eq2.txt
@@ -0,0 +1,3 @@
+class X
+ def ==(o) = 42
+end
diff --git a/test/prism/fixtures/seattlerb/defn_oneliner_noargs.txt b/test/prism/fixtures/seattlerb/defn_oneliner_noargs.txt
new file mode 100644
index 0000000000..cb4f76d244
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/defn_oneliner_noargs.txt
@@ -0,0 +1 @@
+def exec = system
diff --git a/test/prism/fixtures/seattlerb/defn_oneliner_noargs_parentheses.txt b/test/prism/fixtures/seattlerb/defn_oneliner_noargs_parentheses.txt
new file mode 100644
index 0000000000..c582e896c1
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/defn_oneliner_noargs_parentheses.txt
@@ -0,0 +1 @@
+def exec() = system
diff --git a/test/prism/fixtures/seattlerb/defn_oneliner_rescue.txt b/test/prism/fixtures/seattlerb/defn_oneliner_rescue.txt
new file mode 100644
index 0000000000..ffe2228c9d
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/defn_oneliner_rescue.txt
@@ -0,0 +1,13 @@
+def exec(cmd)
+ system(cmd)
+rescue
+ nil
+end
+
+
+def exec(cmd)
+ system(cmd) rescue nil
+end
+
+
+def exec(cmd) = system(cmd) rescue nil
diff --git a/test/prism/fixtures/seattlerb/defn_opt_last_arg.txt b/test/prism/fixtures/seattlerb/defn_opt_last_arg.txt
new file mode 100644
index 0000000000..91500bf137
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/defn_opt_last_arg.txt
@@ -0,0 +1,2 @@
+def m arg = false
+end
diff --git a/test/prism/fixtures/seattlerb/defn_opt_reg.txt b/test/prism/fixtures/seattlerb/defn_opt_reg.txt
new file mode 100644
index 0000000000..c665674bc4
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/defn_opt_reg.txt
@@ -0,0 +1 @@
+def f(a=nil, b) end
diff --git a/test/prism/fixtures/seattlerb/defn_opt_splat_arg.txt b/test/prism/fixtures/seattlerb/defn_opt_splat_arg.txt
new file mode 100644
index 0000000000..876398b478
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/defn_opt_splat_arg.txt
@@ -0,0 +1 @@
+def f (a = 1, *b, c) end
diff --git a/test/prism/fixtures/seattlerb/defn_powarg.txt b/test/prism/fixtures/seattlerb/defn_powarg.txt
new file mode 100644
index 0000000000..73415f0db9
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/defn_powarg.txt
@@ -0,0 +1 @@
+def f(**opts) end
diff --git a/test/prism/fixtures/seattlerb/defn_reg_opt_reg.txt b/test/prism/fixtures/seattlerb/defn_reg_opt_reg.txt
new file mode 100644
index 0000000000..69f501a38e
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/defn_reg_opt_reg.txt
@@ -0,0 +1 @@
+def f(a, b = :c, d) end
diff --git a/test/prism/fixtures/seattlerb/defn_splat_arg.txt b/test/prism/fixtures/seattlerb/defn_splat_arg.txt
new file mode 100644
index 0000000000..a2a84bed30
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/defn_splat_arg.txt
@@ -0,0 +1 @@
+def f(*, a) end
diff --git a/test/prism/fixtures/seattlerb/defn_unary_not.txt b/test/prism/fixtures/seattlerb/defn_unary_not.txt
new file mode 100644
index 0000000000..fb83c84a13
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/defn_unary_not.txt
@@ -0,0 +1 @@
+def !@; true; end
diff --git a/test/prism/fixtures/seattlerb/defns_reserved.txt b/test/prism/fixtures/seattlerb/defns_reserved.txt
new file mode 100644
index 0000000000..7de9322f0d
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/defns_reserved.txt
@@ -0,0 +1 @@
+def self.return; end
diff --git a/test/prism/fixtures/seattlerb/defs_as_arg_with_do_block_inside.txt b/test/prism/fixtures/seattlerb/defs_as_arg_with_do_block_inside.txt
new file mode 100644
index 0000000000..4d493d73dd
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/defs_as_arg_with_do_block_inside.txt
@@ -0,0 +1 @@
+p def self.b; x.y do; end; end
diff --git a/test/prism/fixtures/seattlerb/defs_comments.txt b/test/prism/fixtures/seattlerb/defs_comments.txt
new file mode 100644
index 0000000000..52b9b4a6b3
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/defs_comments.txt
@@ -0,0 +1,5 @@
+# blah 1
+# blah 2
+
+def self.blah
+end
diff --git a/test/prism/fixtures/seattlerb/defs_endless_command.txt b/test/prism/fixtures/seattlerb/defs_endless_command.txt
new file mode 100644
index 0000000000..3b605657de
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/defs_endless_command.txt
@@ -0,0 +1 @@
+def x.some_method = other_method 42
diff --git a/test/prism/fixtures/seattlerb/defs_endless_command_rescue.txt b/test/prism/fixtures/seattlerb/defs_endless_command_rescue.txt
new file mode 100644
index 0000000000..6ece366db0
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/defs_endless_command_rescue.txt
@@ -0,0 +1 @@
+def x.some_method = other_method 42 rescue 24
diff --git a/test/prism/fixtures/seattlerb/defs_kwarg.txt b/test/prism/fixtures/seattlerb/defs_kwarg.txt
new file mode 100644
index 0000000000..59970a371e
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/defs_kwarg.txt
@@ -0,0 +1,2 @@
+def self.a b: 1
+end
diff --git a/test/prism/fixtures/seattlerb/defs_oneliner.txt b/test/prism/fixtures/seattlerb/defs_oneliner.txt
new file mode 100644
index 0000000000..1867edcfbf
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/defs_oneliner.txt
@@ -0,0 +1 @@
+def self.exec(cmd) = system(cmd)
diff --git a/test/prism/fixtures/seattlerb/defs_oneliner_eq2.txt b/test/prism/fixtures/seattlerb/defs_oneliner_eq2.txt
new file mode 100644
index 0000000000..1e55f68bf3
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/defs_oneliner_eq2.txt
@@ -0,0 +1,3 @@
+class X
+ def self.==(o) = 42
+end
diff --git a/test/prism/fixtures/seattlerb/defs_oneliner_rescue.txt b/test/prism/fixtures/seattlerb/defs_oneliner_rescue.txt
new file mode 100644
index 0000000000..7a04012b8f
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/defs_oneliner_rescue.txt
@@ -0,0 +1,13 @@
+def self.exec(cmd)
+ system(cmd)
+rescue
+ nil
+end
+
+
+def self.exec(cmd)
+ system(cmd) rescue nil
+end
+
+
+def self.exec(cmd) = system(cmd) rescue nil
diff --git a/test/prism/fixtures/seattlerb/difficult0_.txt b/test/prism/fixtures/seattlerb/difficult0_.txt
new file mode 100644
index 0000000000..5c73907cae
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/difficult0_.txt
@@ -0,0 +1,4 @@
+p <<-END+'b
+ a
+ END
+ c'+'d'
diff --git a/test/prism/fixtures/seattlerb/difficult1_line_numbers.txt b/test/prism/fixtures/seattlerb/difficult1_line_numbers.txt
new file mode 100644
index 0000000000..8008127dc9
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/difficult1_line_numbers.txt
@@ -0,0 +1,13 @@
+if true
+ p 1
+ a.b 2
+ c.d 3, 4
+ e.f 5
+ g.h 6, 7
+ p(1)
+ a.b(2)
+ c.d(3, 4)
+ e.f(5)
+ g.h(6, 7)
+end
+
diff --git a/test/prism/fixtures/seattlerb/difficult1_line_numbers2.txt b/test/prism/fixtures/seattlerb/difficult1_line_numbers2.txt
new file mode 100644
index 0000000000..1964562416
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/difficult1_line_numbers2.txt
@@ -0,0 +1,8 @@
+if true then
+ p("a")
+ b = 1
+ p b
+ c =1
+end
+a
+
diff --git a/test/prism/fixtures/seattlerb/difficult2_.txt b/test/prism/fixtures/seattlerb/difficult2_.txt
new file mode 100644
index 0000000000..3259097492
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/difficult2_.txt
@@ -0,0 +1,2 @@
+1 ? b('') : 2
+a d: 3
diff --git a/test/prism/fixtures/seattlerb/difficult3_.txt b/test/prism/fixtures/seattlerb/difficult3_.txt
new file mode 100644
index 0000000000..9f95860b82
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/difficult3_.txt
@@ -0,0 +1 @@
+f { |a, (b, *c)| }
diff --git a/test/prism/fixtures/seattlerb/difficult3_2.txt b/test/prism/fixtures/seattlerb/difficult3_2.txt
new file mode 100644
index 0000000000..8abfe3f634
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/difficult3_2.txt
@@ -0,0 +1 @@
+f { |*a, b| }
diff --git a/test/prism/fixtures/seattlerb/difficult3_3.txt b/test/prism/fixtures/seattlerb/difficult3_3.txt
new file mode 100644
index 0000000000..6f43ab7b1d
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/difficult3_3.txt
@@ -0,0 +1 @@
+f { |*a, b, &c| }
diff --git a/test/prism/fixtures/seattlerb/difficult3_4.txt b/test/prism/fixtures/seattlerb/difficult3_4.txt
new file mode 100644
index 0000000000..7070e1e964
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/difficult3_4.txt
@@ -0,0 +1 @@
+a=b ? true: false
diff --git a/test/prism/fixtures/seattlerb/difficult3_5.txt b/test/prism/fixtures/seattlerb/difficult3_5.txt
new file mode 100644
index 0000000000..6d52692481
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/difficult3_5.txt
@@ -0,0 +1 @@
+f ->() { g do end }
diff --git a/test/prism/fixtures/seattlerb/difficult3__10.txt b/test/prism/fixtures/seattlerb/difficult3__10.txt
new file mode 100644
index 0000000000..89974f5114
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/difficult3__10.txt
@@ -0,0 +1 @@
+f { |a, (*b, c)| }
diff --git a/test/prism/fixtures/seattlerb/difficult3__11.txt b/test/prism/fixtures/seattlerb/difficult3__11.txt
new file mode 100644
index 0000000000..911d037961
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/difficult3__11.txt
@@ -0,0 +1 @@
+f { |a, (*)| }
diff --git a/test/prism/fixtures/seattlerb/difficult3__12.txt b/test/prism/fixtures/seattlerb/difficult3__12.txt
new file mode 100644
index 0000000000..2405a80ec1
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/difficult3__12.txt
@@ -0,0 +1 @@
+f { |a, (*, b)| }
diff --git a/test/prism/fixtures/seattlerb/difficult3__6.txt b/test/prism/fixtures/seattlerb/difficult3__6.txt
new file mode 100644
index 0000000000..3a45ae86fb
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/difficult3__6.txt
@@ -0,0 +1 @@
+f { |a, (b, *c, d)| }
diff --git a/test/prism/fixtures/seattlerb/difficult3__7.txt b/test/prism/fixtures/seattlerb/difficult3__7.txt
new file mode 100644
index 0000000000..55272a1fc4
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/difficult3__7.txt
@@ -0,0 +1 @@
+f { |a, (b, *)| }
diff --git a/test/prism/fixtures/seattlerb/difficult3__8.txt b/test/prism/fixtures/seattlerb/difficult3__8.txt
new file mode 100644
index 0000000000..76740db4ff
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/difficult3__8.txt
@@ -0,0 +1 @@
+f { |a, (b, *, c)| }
diff --git a/test/prism/fixtures/seattlerb/difficult3__9.txt b/test/prism/fixtures/seattlerb/difficult3__9.txt
new file mode 100644
index 0000000000..b65f7fd052
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/difficult3__9.txt
@@ -0,0 +1 @@
+f { |a, (*b)| }
diff --git a/test/prism/fixtures/seattlerb/difficult4__leading_dots.txt b/test/prism/fixtures/seattlerb/difficult4__leading_dots.txt
new file mode 100644
index 0000000000..332dc8225c
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/difficult4__leading_dots.txt
@@ -0,0 +1,2 @@
+a
+.b
diff --git a/test/prism/fixtures/seattlerb/difficult4__leading_dots2.txt b/test/prism/fixtures/seattlerb/difficult4__leading_dots2.txt
new file mode 100644
index 0000000000..fe73f641fe
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/difficult4__leading_dots2.txt
@@ -0,0 +1,2 @@
+1
+..3
diff --git a/test/prism/fixtures/seattlerb/difficult6_.txt b/test/prism/fixtures/seattlerb/difficult6_.txt
new file mode 100644
index 0000000000..7396a9a76f
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/difficult6_.txt
@@ -0,0 +1 @@
+->(a, b=nil) { p [a, b] }
diff --git a/test/prism/fixtures/seattlerb/difficult6__7.txt b/test/prism/fixtures/seattlerb/difficult6__7.txt
new file mode 100644
index 0000000000..048358bbdc
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/difficult6__7.txt
@@ -0,0 +1 @@
+a.b (1) {c}
diff --git a/test/prism/fixtures/seattlerb/difficult6__8.txt b/test/prism/fixtures/seattlerb/difficult6__8.txt
new file mode 100644
index 0000000000..ba1cbc235d
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/difficult6__8.txt
@@ -0,0 +1 @@
+a::b (1) {c}
diff --git a/test/prism/fixtures/seattlerb/difficult7_.txt b/test/prism/fixtures/seattlerb/difficult7_.txt
new file mode 100644
index 0000000000..112b75c5f2
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/difficult7_.txt
@@ -0,0 +1,5 @@
+ {
+ a: lambda { b ? c() : d },
+ e: nil,
+ }
+
diff --git a/test/prism/fixtures/seattlerb/do_bug.txt b/test/prism/fixtures/seattlerb/do_bug.txt
new file mode 100644
index 0000000000..a274e72baf
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/do_bug.txt
@@ -0,0 +1,4 @@
+a 1
+a.b do |c|
+ # do nothing
+end
diff --git a/test/prism/fixtures/seattlerb/do_lambda.txt b/test/prism/fixtures/seattlerb/do_lambda.txt
new file mode 100644
index 0000000000..06d2a38d30
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/do_lambda.txt
@@ -0,0 +1 @@
+->() do end
diff --git a/test/prism/fixtures/seattlerb/dot2_nil__26.txt b/test/prism/fixtures/seattlerb/dot2_nil__26.txt
new file mode 100644
index 0000000000..cc070eb69f
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/dot2_nil__26.txt
@@ -0,0 +1 @@
+a..
diff --git a/test/prism/fixtures/seattlerb/dot3_nil__26.txt b/test/prism/fixtures/seattlerb/dot3_nil__26.txt
new file mode 100644
index 0000000000..7f4aef7af7
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/dot3_nil__26.txt
@@ -0,0 +1 @@
+a...
diff --git a/test/prism/fixtures/seattlerb/dstr_evstr.txt b/test/prism/fixtures/seattlerb/dstr_evstr.txt
new file mode 100644
index 0000000000..5fe4a858c1
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/dstr_evstr.txt
@@ -0,0 +1 @@
+"#{'a'}#{b}"
diff --git a/test/prism/fixtures/seattlerb/dstr_evstr_empty_end.txt b/test/prism/fixtures/seattlerb/dstr_evstr_empty_end.txt
new file mode 100644
index 0000000000..7a55030fa8
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/dstr_evstr_empty_end.txt
@@ -0,0 +1 @@
+:"#{field}"
diff --git a/test/prism/fixtures/seattlerb/dstr_lex_state.txt b/test/prism/fixtures/seattlerb/dstr_lex_state.txt
new file mode 100644
index 0000000000..6cac1d8e95
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/dstr_lex_state.txt
@@ -0,0 +1 @@
+"#{p:a}"
diff --git a/test/prism/fixtures/seattlerb/dstr_str.txt b/test/prism/fixtures/seattlerb/dstr_str.txt
new file mode 100644
index 0000000000..226ce2b191
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/dstr_str.txt
@@ -0,0 +1 @@
+"#{'a'} b"
diff --git a/test/prism/fixtures/seattlerb/dsym_esc_to_sym.txt b/test/prism/fixtures/seattlerb/dsym_esc_to_sym.txt
new file mode 100644
index 0000000000..e5781453c1
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/dsym_esc_to_sym.txt
@@ -0,0 +1 @@
+:"Variet\303\240"
diff --git a/test/prism/fixtures/seattlerb/dsym_to_sym.txt b/test/prism/fixtures/seattlerb/dsym_to_sym.txt
new file mode 100644
index 0000000000..813c90342c
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/dsym_to_sym.txt
@@ -0,0 +1,3 @@
+alias :"<<" :">>"
+
+alias :<< :>>
diff --git a/test/prism/fixtures/seattlerb/eq_begin_line_numbers.txt b/test/prism/fixtures/seattlerb/eq_begin_line_numbers.txt
new file mode 100644
index 0000000000..aae82e1207
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/eq_begin_line_numbers.txt
@@ -0,0 +1,6 @@
+1
+=begin
+comment
+comment
+=end
+2
diff --git a/test/prism/fixtures/seattlerb/eq_begin_why_wont_people_use_their_spacebar.txt b/test/prism/fixtures/seattlerb/eq_begin_why_wont_people_use_their_spacebar.txt
new file mode 100644
index 0000000000..88ff599e91
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/eq_begin_why_wont_people_use_their_spacebar.txt
@@ -0,0 +1,3 @@
+h[k]=begin
+ 42
+ end
diff --git a/test/prism/fixtures/seattlerb/evstr_evstr.txt b/test/prism/fixtures/seattlerb/evstr_evstr.txt
new file mode 100644
index 0000000000..cf0b5ee873
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/evstr_evstr.txt
@@ -0,0 +1 @@
+"#{a}#{b}"
diff --git a/test/prism/fixtures/seattlerb/evstr_str.txt b/test/prism/fixtures/seattlerb/evstr_str.txt
new file mode 100644
index 0000000000..5746909b19
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/evstr_str.txt
@@ -0,0 +1 @@
+"#{a} b"
diff --git a/test/prism/fixtures/seattlerb/expr_not_bang.txt b/test/prism/fixtures/seattlerb/expr_not_bang.txt
new file mode 100644
index 0000000000..6ed80c76d3
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/expr_not_bang.txt
@@ -0,0 +1 @@
+! a b
diff --git a/test/prism/fixtures/seattlerb/f_kw.txt b/test/prism/fixtures/seattlerb/f_kw.txt
new file mode 100644
index 0000000000..4dd42662b8
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/f_kw.txt
@@ -0,0 +1 @@
+def x k:42; end
diff --git a/test/prism/fixtures/seattlerb/f_kw__required.txt b/test/prism/fixtures/seattlerb/f_kw__required.txt
new file mode 100644
index 0000000000..2e1e258ff0
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/f_kw__required.txt
@@ -0,0 +1 @@
+def x k:; end
diff --git a/test/prism/fixtures/seattlerb/flip2_env_lvar.txt b/test/prism/fixtures/seattlerb/flip2_env_lvar.txt
new file mode 100644
index 0000000000..619b2c915e
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/flip2_env_lvar.txt
@@ -0,0 +1 @@
+if a..b then end
diff --git a/test/prism/fixtures/seattlerb/float_with_if_modifier.txt b/test/prism/fixtures/seattlerb/float_with_if_modifier.txt
new file mode 100644
index 0000000000..6a62d4a308
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/float_with_if_modifier.txt
@@ -0,0 +1 @@
+1.0if true
diff --git a/test/prism/fixtures/seattlerb/heredoc__backslash_dos_format.txt b/test/prism/fixtures/seattlerb/heredoc__backslash_dos_format.txt
new file mode 100644
index 0000000000..cfbcb2a11d
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/heredoc__backslash_dos_format.txt
@@ -0,0 +1,5 @@
+str = <<-XXX
+before\
+after
+XXX
+
diff --git a/test/prism/fixtures/seattlerb/heredoc_backslash_nl.txt b/test/prism/fixtures/seattlerb/heredoc_backslash_nl.txt
new file mode 100644
index 0000000000..0cc5b35fd5
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/heredoc_backslash_nl.txt
@@ -0,0 +1,8 @@
+" why would someone do this? \
+ blah
+"
+
+<<-DESC
+ why would someone do this? \
+ blah
+DESC
diff --git a/test/prism/fixtures/seattlerb/heredoc_bad_hex_escape.txt b/test/prism/fixtures/seattlerb/heredoc_bad_hex_escape.txt
new file mode 100644
index 0000000000..2c386cc6a9
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/heredoc_bad_hex_escape.txt
@@ -0,0 +1,3 @@
+s = <<eos
+a\xE9b
+eos
diff --git a/test/prism/fixtures/seattlerb/heredoc_bad_oct_escape.txt b/test/prism/fixtures/seattlerb/heredoc_bad_oct_escape.txt
new file mode 100644
index 0000000000..235a041e90
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/heredoc_bad_oct_escape.txt
@@ -0,0 +1,5 @@
+s = <<-EOS
+a\247b
+cöd
+EOS
+
diff --git a/test/prism/fixtures/seattlerb/heredoc_comma_arg.txt b/test/prism/fixtures/seattlerb/heredoc_comma_arg.txt
new file mode 100644
index 0000000000..c230b12f65
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/heredoc_comma_arg.txt
@@ -0,0 +1,7 @@
+[" some text
+",]
+
+[<<-FILE,
+ some text
+FILE
+]
diff --git a/test/prism/fixtures/seattlerb/heredoc_lineno.txt b/test/prism/fixtures/seattlerb/heredoc_lineno.txt
new file mode 100644
index 0000000000..73a2e3806b
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/heredoc_lineno.txt
@@ -0,0 +1,7 @@
+c = <<'CCC'
+line2
+line3
+line4
+CCC
+
+d = 42
diff --git a/test/prism/fixtures/seattlerb/heredoc_nested.txt b/test/prism/fixtures/seattlerb/heredoc_nested.txt
new file mode 100644
index 0000000000..508d6d3c05
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/heredoc_nested.txt
@@ -0,0 +1,7 @@
+[<<A,
+#{<<B}
+b
+B
+a
+A
+0]
diff --git a/test/prism/fixtures/seattlerb/heredoc_squiggly.txt b/test/prism/fixtures/seattlerb/heredoc_squiggly.txt
new file mode 100644
index 0000000000..e630ff62b4
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/heredoc_squiggly.txt
@@ -0,0 +1,7 @@
+a = <<~"EOF"
+ x
+ y
+ z
+ EOF
+
+
diff --git a/test/prism/fixtures/seattlerb/heredoc_squiggly_blank_line_plus_interpolation.txt b/test/prism/fixtures/seattlerb/heredoc_squiggly_blank_line_plus_interpolation.txt
new file mode 100644
index 0000000000..61b62157db
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/heredoc_squiggly_blank_line_plus_interpolation.txt
@@ -0,0 +1,4 @@
+a = foo(<<~EOF.chop)
+
+ #{bar}baz
+ EOF
diff --git a/test/prism/fixtures/seattlerb/heredoc_squiggly_blank_lines.txt b/test/prism/fixtures/seattlerb/heredoc_squiggly_blank_lines.txt
new file mode 100644
index 0000000000..0d89134c87
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/heredoc_squiggly_blank_lines.txt
@@ -0,0 +1,7 @@
+a = <<~EOF
+ x
+
+ z
+EOF
+
+
diff --git a/test/prism/fixtures/seattlerb/heredoc_squiggly_empty.txt b/test/prism/fixtures/seattlerb/heredoc_squiggly_empty.txt
new file mode 100644
index 0000000000..4602d757fb
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/heredoc_squiggly_empty.txt
@@ -0,0 +1,2 @@
+<<~A
+A
diff --git a/test/prism/fixtures/seattlerb/heredoc_squiggly_interp.txt b/test/prism/fixtures/seattlerb/heredoc_squiggly_interp.txt
new file mode 100644
index 0000000000..47ff3c9070
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/heredoc_squiggly_interp.txt
@@ -0,0 +1,5 @@
+a = <<~EOF
+ w
+ x#{42} y
+ z
+ EOF
diff --git a/test/prism/fixtures/seattlerb/heredoc_squiggly_no_indent.txt b/test/prism/fixtures/seattlerb/heredoc_squiggly_no_indent.txt
new file mode 100644
index 0000000000..7076f6ef71
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/heredoc_squiggly_no_indent.txt
@@ -0,0 +1,3 @@
+<<~A
+a
+A
diff --git a/test/prism/fixtures/seattlerb/heredoc_squiggly_tabs.txt b/test/prism/fixtures/seattlerb/heredoc_squiggly_tabs.txt
new file mode 100644
index 0000000000..b193f0473b
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/heredoc_squiggly_tabs.txt
@@ -0,0 +1,6 @@
+a = <<~"EOF"
+ blah blah
+ blah blah
+ EOF
+
+
diff --git a/test/prism/fixtures/seattlerb/heredoc_squiggly_tabs_extra.txt b/test/prism/fixtures/seattlerb/heredoc_squiggly_tabs_extra.txt
new file mode 100644
index 0000000000..5b75dd2b59
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/heredoc_squiggly_tabs_extra.txt
@@ -0,0 +1,6 @@
+a = <<~"EOF"
+ blah blah
+ blah blah
+ EOF
+
+
diff --git a/test/prism/fixtures/seattlerb/heredoc_squiggly_visually_blank_lines.txt b/test/prism/fixtures/seattlerb/heredoc_squiggly_visually_blank_lines.txt
new file mode 100644
index 0000000000..3f9198296d
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/heredoc_squiggly_visually_blank_lines.txt
@@ -0,0 +1,7 @@
+a = <<~EOF
+ x
+
+ z
+EOF
+
+
diff --git a/test/prism/fixtures/seattlerb/heredoc_trailing_slash_continued_call.txt b/test/prism/fixtures/seattlerb/heredoc_trailing_slash_continued_call.txt
new file mode 100644
index 0000000000..12c8fac126
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/heredoc_trailing_slash_continued_call.txt
@@ -0,0 +1,4 @@
+<<END\
+blah
+END
+.strip
diff --git a/test/prism/fixtures/seattlerb/heredoc_unicode.txt b/test/prism/fixtures/seattlerb/heredoc_unicode.txt
new file mode 100644
index 0000000000..216a5cfe24
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/heredoc_unicode.txt
@@ -0,0 +1,4 @@
+<<OOTPÃœT
+.
+OOTPÃœT
+
diff --git a/test/prism/fixtures/seattlerb/heredoc_with_carriage_return_escapes.txt b/test/prism/fixtures/seattlerb/heredoc_with_carriage_return_escapes.txt
new file mode 100644
index 0000000000..cb4967d154
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/heredoc_with_carriage_return_escapes.txt
@@ -0,0 +1,5 @@
+<<EOS
+foo\rbar
+baz\r
+EOS
+
diff --git a/test/prism/fixtures/seattlerb/heredoc_with_carriage_return_escapes_windows.txt b/test/prism/fixtures/seattlerb/heredoc_with_carriage_return_escapes_windows.txt
new file mode 100644
index 0000000000..75ed936b5d
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/heredoc_with_carriage_return_escapes_windows.txt
@@ -0,0 +1,5 @@
+<<EOS
+foo\rbar
+baz\r
+EOS
+
diff --git a/test/prism/fixtures/seattlerb/heredoc_with_extra_carriage_horrible_mix.txt b/test/prism/fixtures/seattlerb/heredoc_with_extra_carriage_horrible_mix.txt
new file mode 100644
index 0000000000..1c58c05cc5
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/heredoc_with_extra_carriage_horrible_mix.txt
@@ -0,0 +1,4 @@
+<<'eot'
+body
+eot
+
diff --git a/test/prism/fixtures/seattlerb/heredoc_with_extra_carriage_returns.txt b/test/prism/fixtures/seattlerb/heredoc_with_extra_carriage_returns.txt
new file mode 100644
index 0000000000..706cb0d5c0
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/heredoc_with_extra_carriage_returns.txt
@@ -0,0 +1,5 @@
+<<EOS
+foo bar
+baz
+EOS
+
diff --git a/test/prism/fixtures/seattlerb/heredoc_with_extra_carriage_returns_windows.txt b/test/prism/fixtures/seattlerb/heredoc_with_extra_carriage_returns_windows.txt
new file mode 100644
index 0000000000..8ed84799b1
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/heredoc_with_extra_carriage_returns_windows.txt
@@ -0,0 +1,5 @@
+<<EOS
+foo bar
+baz
+EOS
+
diff --git a/test/prism/fixtures/seattlerb/heredoc_with_interpolation_and_carriage_return_escapes.txt b/test/prism/fixtures/seattlerb/heredoc_with_interpolation_and_carriage_return_escapes.txt
new file mode 100644
index 0000000000..250e606f45
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/heredoc_with_interpolation_and_carriage_return_escapes.txt
@@ -0,0 +1,4 @@
+<<EOS
+foo\r#@bar
+EOS
+
diff --git a/test/prism/fixtures/seattlerb/heredoc_with_interpolation_and_carriage_return_escapes_windows.txt b/test/prism/fixtures/seattlerb/heredoc_with_interpolation_and_carriage_return_escapes_windows.txt
new file mode 100644
index 0000000000..12f97aff5e
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/heredoc_with_interpolation_and_carriage_return_escapes_windows.txt
@@ -0,0 +1,4 @@
+<<EOS
+foo\r#@bar
+EOS
+
diff --git a/test/prism/fixtures/seattlerb/heredoc_with_not_global_interpolation.txt b/test/prism/fixtures/seattlerb/heredoc_with_not_global_interpolation.txt
new file mode 100644
index 0000000000..f94c2c9e27
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/heredoc_with_not_global_interpolation.txt
@@ -0,0 +1,3 @@
+<<-HEREDOC
+#${
+HEREDOC
diff --git a/test/prism/fixtures/seattlerb/heredoc_with_only_carriage_returns.txt b/test/prism/fixtures/seattlerb/heredoc_with_only_carriage_returns.txt
new file mode 100644
index 0000000000..468ba85cf7
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/heredoc_with_only_carriage_returns.txt
@@ -0,0 +1,6 @@
+<<EOS
+
+
+\r
+EOS
+
diff --git a/test/prism/fixtures/seattlerb/heredoc_with_only_carriage_returns_windows.txt b/test/prism/fixtures/seattlerb/heredoc_with_only_carriage_returns_windows.txt
new file mode 100644
index 0000000000..e973eff110
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/heredoc_with_only_carriage_returns_windows.txt
@@ -0,0 +1,6 @@
+<<EOS
+
+
+\r
+EOS
+
diff --git a/test/prism/fixtures/seattlerb/if_elsif.txt b/test/prism/fixtures/seattlerb/if_elsif.txt
new file mode 100644
index 0000000000..bc1c0a2b3d
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/if_elsif.txt
@@ -0,0 +1 @@
+if 1; elsif 2; end
diff --git a/test/prism/fixtures/seattlerb/if_symbol.txt b/test/prism/fixtures/seattlerb/if_symbol.txt
new file mode 100644
index 0000000000..8d6e958ede
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/if_symbol.txt
@@ -0,0 +1 @@
+if f :x; end
diff --git a/test/prism/fixtures/seattlerb/in_expr_no_case.txt b/test/prism/fixtures/seattlerb/in_expr_no_case.txt
new file mode 100644
index 0000000000..40db7f868b
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/in_expr_no_case.txt
@@ -0,0 +1 @@
+'woot' in String
diff --git a/test/prism/fixtures/seattlerb/index_0.txt b/test/prism/fixtures/seattlerb/index_0.txt
new file mode 100644
index 0000000000..050d4566ba
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/index_0.txt
@@ -0,0 +1 @@
+a[] = b
diff --git a/test/prism/fixtures/seattlerb/index_0_opasgn.txt b/test/prism/fixtures/seattlerb/index_0_opasgn.txt
new file mode 100644
index 0000000000..7189f0c3ea
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/index_0_opasgn.txt
@@ -0,0 +1 @@
+a[] += b
diff --git a/test/prism/fixtures/seattlerb/integer_with_if_modifier.txt b/test/prism/fixtures/seattlerb/integer_with_if_modifier.txt
new file mode 100644
index 0000000000..bf2f621e92
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/integer_with_if_modifier.txt
@@ -0,0 +1 @@
+1_234if true
diff --git a/test/prism/fixtures/seattlerb/interpolated_symbol_array_line_breaks.txt b/test/prism/fixtures/seattlerb/interpolated_symbol_array_line_breaks.txt
new file mode 100644
index 0000000000..f4c7cb9662
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/interpolated_symbol_array_line_breaks.txt
@@ -0,0 +1,5 @@
+%I(
+a
+b
+)
+1
diff --git a/test/prism/fixtures/seattlerb/interpolated_word_array_line_breaks.txt b/test/prism/fixtures/seattlerb/interpolated_word_array_line_breaks.txt
new file mode 100644
index 0000000000..d52b4789cf
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/interpolated_word_array_line_breaks.txt
@@ -0,0 +1,5 @@
+%W(
+a
+b
+)
+1
diff --git a/test/prism/fixtures/seattlerb/iter_args_1.txt b/test/prism/fixtures/seattlerb/iter_args_1.txt
new file mode 100644
index 0000000000..c890ef62c3
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/iter_args_1.txt
@@ -0,0 +1 @@
+f { |a,b| }
diff --git a/test/prism/fixtures/seattlerb/iter_args_10_1.txt b/test/prism/fixtures/seattlerb/iter_args_10_1.txt
new file mode 100644
index 0000000000..3f558c5392
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/iter_args_10_1.txt
@@ -0,0 +1 @@
+f { |a, b = 42, *c| }
diff --git a/test/prism/fixtures/seattlerb/iter_args_10_2.txt b/test/prism/fixtures/seattlerb/iter_args_10_2.txt
new file mode 100644
index 0000000000..4158e79d14
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/iter_args_10_2.txt
@@ -0,0 +1 @@
+f { |a, b = 42, *c, &d| }
diff --git a/test/prism/fixtures/seattlerb/iter_args_11_1.txt b/test/prism/fixtures/seattlerb/iter_args_11_1.txt
new file mode 100644
index 0000000000..f86175c1a0
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/iter_args_11_1.txt
@@ -0,0 +1 @@
+f { |a, b = 42, *c, d| }
diff --git a/test/prism/fixtures/seattlerb/iter_args_11_2.txt b/test/prism/fixtures/seattlerb/iter_args_11_2.txt
new file mode 100644
index 0000000000..e4b017e44a
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/iter_args_11_2.txt
@@ -0,0 +1 @@
+f { |a, b = 42, *c, d, &e| }
diff --git a/test/prism/fixtures/seattlerb/iter_args_2__19.txt b/test/prism/fixtures/seattlerb/iter_args_2__19.txt
new file mode 100644
index 0000000000..84dd744243
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/iter_args_2__19.txt
@@ -0,0 +1 @@
+f { |(a, b)| }
diff --git a/test/prism/fixtures/seattlerb/iter_args_3.txt b/test/prism/fixtures/seattlerb/iter_args_3.txt
new file mode 100644
index 0000000000..261968ff13
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/iter_args_3.txt
@@ -0,0 +1 @@
+f { |a, (b, c), d| }
diff --git a/test/prism/fixtures/seattlerb/iter_args_4.txt b/test/prism/fixtures/seattlerb/iter_args_4.txt
new file mode 100644
index 0000000000..7db4d43ad3
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/iter_args_4.txt
@@ -0,0 +1 @@
+f { |a, *b, c| }
diff --git a/test/prism/fixtures/seattlerb/iter_args_5.txt b/test/prism/fixtures/seattlerb/iter_args_5.txt
new file mode 100644
index 0000000000..088fcdfcc5
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/iter_args_5.txt
@@ -0,0 +1 @@
+f { |a, &b| }
diff --git a/test/prism/fixtures/seattlerb/iter_args_6.txt b/test/prism/fixtures/seattlerb/iter_args_6.txt
new file mode 100644
index 0000000000..e980ec064b
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/iter_args_6.txt
@@ -0,0 +1 @@
+f { |a, b=42, c| }
diff --git a/test/prism/fixtures/seattlerb/iter_args_7_1.txt b/test/prism/fixtures/seattlerb/iter_args_7_1.txt
new file mode 100644
index 0000000000..e1dbf4b312
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/iter_args_7_1.txt
@@ -0,0 +1 @@
+f { |a = 42, *b| }
diff --git a/test/prism/fixtures/seattlerb/iter_args_7_2.txt b/test/prism/fixtures/seattlerb/iter_args_7_2.txt
new file mode 100644
index 0000000000..e46e78e00e
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/iter_args_7_2.txt
@@ -0,0 +1 @@
+f { |a = 42, *b, &c| }
diff --git a/test/prism/fixtures/seattlerb/iter_args_8_1.txt b/test/prism/fixtures/seattlerb/iter_args_8_1.txt
new file mode 100644
index 0000000000..a0ec82ea5b
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/iter_args_8_1.txt
@@ -0,0 +1 @@
+f { |a = 42, *b, c| }
diff --git a/test/prism/fixtures/seattlerb/iter_args_8_2.txt b/test/prism/fixtures/seattlerb/iter_args_8_2.txt
new file mode 100644
index 0000000000..a1839fe706
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/iter_args_8_2.txt
@@ -0,0 +1 @@
+f { |a = 42, *b, c, &d| }
diff --git a/test/prism/fixtures/seattlerb/iter_args_9_1.txt b/test/prism/fixtures/seattlerb/iter_args_9_1.txt
new file mode 100644
index 0000000000..13e5b20fe7
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/iter_args_9_1.txt
@@ -0,0 +1 @@
+f { |a = 42, b| }
diff --git a/test/prism/fixtures/seattlerb/iter_args_9_2.txt b/test/prism/fixtures/seattlerb/iter_args_9_2.txt
new file mode 100644
index 0000000000..83f6e1e029
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/iter_args_9_2.txt
@@ -0,0 +1 @@
+f { |a = 42, b, &c| }
diff --git a/test/prism/fixtures/seattlerb/iter_kwarg.txt b/test/prism/fixtures/seattlerb/iter_kwarg.txt
new file mode 100644
index 0000000000..d4296cad76
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/iter_kwarg.txt
@@ -0,0 +1 @@
+a { |b: 1| }
diff --git a/test/prism/fixtures/seattlerb/iter_kwarg_kwsplat.txt b/test/prism/fixtures/seattlerb/iter_kwarg_kwsplat.txt
new file mode 100644
index 0000000000..dd0ea13a6f
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/iter_kwarg_kwsplat.txt
@@ -0,0 +1 @@
+a { |b: 1, **c| }
diff --git a/test/prism/fixtures/seattlerb/label_vs_string.txt b/test/prism/fixtures/seattlerb/label_vs_string.txt
new file mode 100644
index 0000000000..27ba8b64de
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/label_vs_string.txt
@@ -0,0 +1,2 @@
+_buf << ':
+'
diff --git a/test/prism/fixtures/seattlerb/lambda_do_vs_brace.txt b/test/prism/fixtures/seattlerb/lambda_do_vs_brace.txt
new file mode 100644
index 0000000000..bbf663a46a
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/lambda_do_vs_brace.txt
@@ -0,0 +1,7 @@
+f -> do end
+
+f -> {}
+
+f ->() do end
+
+f ->() {}
diff --git a/test/prism/fixtures/seattlerb/lasgn_arg_rescue_arg.txt b/test/prism/fixtures/seattlerb/lasgn_arg_rescue_arg.txt
new file mode 100644
index 0000000000..0dad496c28
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/lasgn_arg_rescue_arg.txt
@@ -0,0 +1 @@
+a = 1 rescue 2
diff --git a/test/prism/fixtures/seattlerb/lasgn_call_bracket_rescue_arg.txt b/test/prism/fixtures/seattlerb/lasgn_call_bracket_rescue_arg.txt
new file mode 100644
index 0000000000..3f63c0b748
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/lasgn_call_bracket_rescue_arg.txt
@@ -0,0 +1 @@
+a = b(1) rescue 2
diff --git a/test/prism/fixtures/seattlerb/lasgn_call_nobracket_rescue_arg.txt b/test/prism/fixtures/seattlerb/lasgn_call_nobracket_rescue_arg.txt
new file mode 100644
index 0000000000..0e86f1587d
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/lasgn_call_nobracket_rescue_arg.txt
@@ -0,0 +1 @@
+a = b 1 rescue 2
diff --git a/test/prism/fixtures/seattlerb/lasgn_command.txt b/test/prism/fixtures/seattlerb/lasgn_command.txt
new file mode 100644
index 0000000000..aca35b880c
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/lasgn_command.txt
@@ -0,0 +1 @@
+a = b.c 1
diff --git a/test/prism/fixtures/seattlerb/lasgn_env.txt b/test/prism/fixtures/seattlerb/lasgn_env.txt
new file mode 100644
index 0000000000..aec10273e5
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/lasgn_env.txt
@@ -0,0 +1 @@
+a = 42
diff --git a/test/prism/fixtures/seattlerb/lasgn_ivar_env.txt b/test/prism/fixtures/seattlerb/lasgn_ivar_env.txt
new file mode 100644
index 0000000000..2fa8471c01
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/lasgn_ivar_env.txt
@@ -0,0 +1 @@
+@a = 42
diff --git a/test/prism/fixtures/seattlerb/lasgn_lasgn_command_call.txt b/test/prism/fixtures/seattlerb/lasgn_lasgn_command_call.txt
new file mode 100644
index 0000000000..5147131852
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/lasgn_lasgn_command_call.txt
@@ -0,0 +1 @@
+a = b = c 1
diff --git a/test/prism/fixtures/seattlerb/lasgn_middle_splat.txt b/test/prism/fixtures/seattlerb/lasgn_middle_splat.txt
new file mode 100644
index 0000000000..bb378ca680
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/lasgn_middle_splat.txt
@@ -0,0 +1 @@
+a = b, *c, d
diff --git a/test/prism/fixtures/seattlerb/magic_encoding_comment.txt b/test/prism/fixtures/seattlerb/magic_encoding_comment.txt
new file mode 100644
index 0000000000..a02711ea05
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/magic_encoding_comment.txt
@@ -0,0 +1,4 @@
+# encoding: utf-8
+class ExampleUTF8ClassNameVarietà; def self.è; così = :però; end
+end
+
diff --git a/test/prism/fixtures/seattlerb/masgn_anon_splat_arg.txt b/test/prism/fixtures/seattlerb/masgn_anon_splat_arg.txt
new file mode 100644
index 0000000000..b796a742ed
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/masgn_anon_splat_arg.txt
@@ -0,0 +1 @@
+*, a = b
diff --git a/test/prism/fixtures/seattlerb/masgn_arg_colon_arg.txt b/test/prism/fixtures/seattlerb/masgn_arg_colon_arg.txt
new file mode 100644
index 0000000000..e0919793d4
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/masgn_arg_colon_arg.txt
@@ -0,0 +1 @@
+a, b::c = d
diff --git a/test/prism/fixtures/seattlerb/masgn_arg_ident.txt b/test/prism/fixtures/seattlerb/masgn_arg_ident.txt
new file mode 100644
index 0000000000..45f248d854
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/masgn_arg_ident.txt
@@ -0,0 +1 @@
+a, b.C = d
diff --git a/test/prism/fixtures/seattlerb/masgn_arg_splat_arg.txt b/test/prism/fixtures/seattlerb/masgn_arg_splat_arg.txt
new file mode 100644
index 0000000000..05fe7c4d5f
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/masgn_arg_splat_arg.txt
@@ -0,0 +1 @@
+a, *b, c = d
diff --git a/test/prism/fixtures/seattlerb/masgn_colon2.txt b/test/prism/fixtures/seattlerb/masgn_colon2.txt
new file mode 100644
index 0000000000..4e4f838d7d
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/masgn_colon2.txt
@@ -0,0 +1 @@
+a, b::C = 1, 2
diff --git a/test/prism/fixtures/seattlerb/masgn_colon3.txt b/test/prism/fixtures/seattlerb/masgn_colon3.txt
new file mode 100644
index 0000000000..46098ba8c5
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/masgn_colon3.txt
@@ -0,0 +1 @@
+::A, ::B = 1, 2
diff --git a/test/prism/fixtures/seattlerb/masgn_command_call.txt b/test/prism/fixtures/seattlerb/masgn_command_call.txt
new file mode 100644
index 0000000000..6da01e8a31
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/masgn_command_call.txt
@@ -0,0 +1 @@
+a, = b.c 1
diff --git a/test/prism/fixtures/seattlerb/masgn_double_paren.txt b/test/prism/fixtures/seattlerb/masgn_double_paren.txt
new file mode 100644
index 0000000000..ffac0a85a3
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/masgn_double_paren.txt
@@ -0,0 +1 @@
+((a,b))=c
diff --git a/test/prism/fixtures/seattlerb/masgn_lhs_splat.txt b/test/prism/fixtures/seattlerb/masgn_lhs_splat.txt
new file mode 100644
index 0000000000..2419ef1671
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/masgn_lhs_splat.txt
@@ -0,0 +1 @@
+*a = 1, 2, 3
diff --git a/test/prism/fixtures/seattlerb/masgn_paren.txt b/test/prism/fixtures/seattlerb/masgn_paren.txt
new file mode 100644
index 0000000000..3889b9ff48
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/masgn_paren.txt
@@ -0,0 +1 @@
+(a, b) = c.d
diff --git a/test/prism/fixtures/seattlerb/masgn_splat_arg.txt b/test/prism/fixtures/seattlerb/masgn_splat_arg.txt
new file mode 100644
index 0000000000..a7c91425b0
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/masgn_splat_arg.txt
@@ -0,0 +1 @@
+*a, b = c
diff --git a/test/prism/fixtures/seattlerb/masgn_splat_arg_arg.txt b/test/prism/fixtures/seattlerb/masgn_splat_arg_arg.txt
new file mode 100644
index 0000000000..46196bd703
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/masgn_splat_arg_arg.txt
@@ -0,0 +1 @@
+*a, b, c = d
diff --git a/test/prism/fixtures/seattlerb/masgn_star.txt b/test/prism/fixtures/seattlerb/masgn_star.txt
new file mode 100644
index 0000000000..c5eea37de2
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/masgn_star.txt
@@ -0,0 +1 @@
+* = 1
diff --git a/test/prism/fixtures/seattlerb/masgn_var_star_var.txt b/test/prism/fixtures/seattlerb/masgn_var_star_var.txt
new file mode 100644
index 0000000000..04089c36ac
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/masgn_var_star_var.txt
@@ -0,0 +1 @@
+a, *, b = c
diff --git a/test/prism/fixtures/seattlerb/messy_op_asgn_lineno.txt b/test/prism/fixtures/seattlerb/messy_op_asgn_lineno.txt
new file mode 100644
index 0000000000..a7d1035ae3
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/messy_op_asgn_lineno.txt
@@ -0,0 +1 @@
+a (B::C *= d e)
diff --git a/test/prism/fixtures/seattlerb/method_call_assoc_trailing_comma.txt b/test/prism/fixtures/seattlerb/method_call_assoc_trailing_comma.txt
new file mode 100644
index 0000000000..86f0fbdfc9
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/method_call_assoc_trailing_comma.txt
@@ -0,0 +1 @@
+a.f(1=>2,)
diff --git a/test/prism/fixtures/seattlerb/method_call_trailing_comma.txt b/test/prism/fixtures/seattlerb/method_call_trailing_comma.txt
new file mode 100644
index 0000000000..1a155fba12
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/method_call_trailing_comma.txt
@@ -0,0 +1 @@
+a.f(1,)
diff --git a/test/prism/fixtures/seattlerb/mlhs_back_anonsplat.txt b/test/prism/fixtures/seattlerb/mlhs_back_anonsplat.txt
new file mode 100644
index 0000000000..7389b95563
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/mlhs_back_anonsplat.txt
@@ -0,0 +1 @@
+a, b, c, * = f
diff --git a/test/prism/fixtures/seattlerb/mlhs_back_splat.txt b/test/prism/fixtures/seattlerb/mlhs_back_splat.txt
new file mode 100644
index 0000000000..ec5d23889a
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/mlhs_back_splat.txt
@@ -0,0 +1 @@
+a, b, c, *s = f
diff --git a/test/prism/fixtures/seattlerb/mlhs_front_anonsplat.txt b/test/prism/fixtures/seattlerb/mlhs_front_anonsplat.txt
new file mode 100644
index 0000000000..67e569438c
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/mlhs_front_anonsplat.txt
@@ -0,0 +1 @@
+*, x, y, z = f
diff --git a/test/prism/fixtures/seattlerb/mlhs_front_splat.txt b/test/prism/fixtures/seattlerb/mlhs_front_splat.txt
new file mode 100644
index 0000000000..dabadc382d
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/mlhs_front_splat.txt
@@ -0,0 +1 @@
+*s, x, y, z = f
diff --git a/test/prism/fixtures/seattlerb/mlhs_keyword.txt b/test/prism/fixtures/seattlerb/mlhs_keyword.txt
new file mode 100644
index 0000000000..899e7f8ed3
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/mlhs_keyword.txt
@@ -0,0 +1 @@
+a.!=(true, true)
diff --git a/test/prism/fixtures/seattlerb/mlhs_mid_anonsplat.txt b/test/prism/fixtures/seattlerb/mlhs_mid_anonsplat.txt
new file mode 100644
index 0000000000..a70a7e531b
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/mlhs_mid_anonsplat.txt
@@ -0,0 +1 @@
+a, b, c, *, x, y, z = f
diff --git a/test/prism/fixtures/seattlerb/mlhs_mid_splat.txt b/test/prism/fixtures/seattlerb/mlhs_mid_splat.txt
new file mode 100644
index 0000000000..2d23fd3966
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/mlhs_mid_splat.txt
@@ -0,0 +1 @@
+a, b, c, *s, x, y, z = f
diff --git a/test/prism/fixtures/seattlerb/mlhs_rescue.txt b/test/prism/fixtures/seattlerb/mlhs_rescue.txt
new file mode 100644
index 0000000000..b4c79ae32e
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/mlhs_rescue.txt
@@ -0,0 +1 @@
+a, b = f rescue 42
diff --git a/test/prism/fixtures/seattlerb/module_comments.txt b/test/prism/fixtures/seattlerb/module_comments.txt
new file mode 100644
index 0000000000..cecb717c5b
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/module_comments.txt
@@ -0,0 +1,10 @@
+# blah 1
+
+ # blah 2
+
+module X
+ # blah 3
+ def blah
+ # blah 4
+ end
+end
diff --git a/test/prism/fixtures/seattlerb/multiline_hash_declaration.txt b/test/prism/fixtures/seattlerb/multiline_hash_declaration.txt
new file mode 100644
index 0000000000..21530307d2
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/multiline_hash_declaration.txt
@@ -0,0 +1,8 @@
+f(state:
+ {
+})
+
+f(state: {
+})
+
+f(state: {})
diff --git a/test/prism/fixtures/seattlerb/non_interpolated_symbol_array_line_breaks.txt b/test/prism/fixtures/seattlerb/non_interpolated_symbol_array_line_breaks.txt
new file mode 100644
index 0000000000..1e14673f4e
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/non_interpolated_symbol_array_line_breaks.txt
@@ -0,0 +1,5 @@
+%i(
+a
+b
+)
+1
diff --git a/test/prism/fixtures/seattlerb/non_interpolated_word_array_line_breaks.txt b/test/prism/fixtures/seattlerb/non_interpolated_word_array_line_breaks.txt
new file mode 100644
index 0000000000..79c1418770
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/non_interpolated_word_array_line_breaks.txt
@@ -0,0 +1,5 @@
+%w(
+a
+b
+)
+1
diff --git a/test/prism/fixtures/seattlerb/op_asgn_command_call.txt b/test/prism/fixtures/seattlerb/op_asgn_command_call.txt
new file mode 100644
index 0000000000..92c989cb0d
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/op_asgn_command_call.txt
@@ -0,0 +1 @@
+a ||= b.c 2
diff --git a/test/prism/fixtures/seattlerb/op_asgn_dot_ident_command_call.txt b/test/prism/fixtures/seattlerb/op_asgn_dot_ident_command_call.txt
new file mode 100644
index 0000000000..89cfccda66
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/op_asgn_dot_ident_command_call.txt
@@ -0,0 +1 @@
+A.B ||= c 1
diff --git a/test/prism/fixtures/seattlerb/op_asgn_index_command_call.txt b/test/prism/fixtures/seattlerb/op_asgn_index_command_call.txt
new file mode 100644
index 0000000000..2bfced81fe
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/op_asgn_index_command_call.txt
@@ -0,0 +1 @@
+a[:b] ||= c 1, 2
diff --git a/test/prism/fixtures/seattlerb/op_asgn_primary_colon_const_command_call.txt b/test/prism/fixtures/seattlerb/op_asgn_primary_colon_const_command_call.txt
new file mode 100644
index 0000000000..a567f60e83
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/op_asgn_primary_colon_const_command_call.txt
@@ -0,0 +1 @@
+A::B *= c d
diff --git a/test/prism/fixtures/seattlerb/op_asgn_primary_colon_identifier1.txt b/test/prism/fixtures/seattlerb/op_asgn_primary_colon_identifier1.txt
new file mode 100644
index 0000000000..0784b49167
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/op_asgn_primary_colon_identifier1.txt
@@ -0,0 +1 @@
+A::b += 1
diff --git a/test/prism/fixtures/seattlerb/op_asgn_primary_colon_identifier_command_call.txt b/test/prism/fixtures/seattlerb/op_asgn_primary_colon_identifier_command_call.txt
new file mode 100644
index 0000000000..c0f16eb3c1
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/op_asgn_primary_colon_identifier_command_call.txt
@@ -0,0 +1 @@
+A::b *= c d
diff --git a/test/prism/fixtures/seattlerb/op_asgn_val_dot_ident_command_call.txt b/test/prism/fixtures/seattlerb/op_asgn_val_dot_ident_command_call.txt
new file mode 100644
index 0000000000..69057abf04
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/op_asgn_val_dot_ident_command_call.txt
@@ -0,0 +1 @@
+a.b ||= c 1
diff --git a/test/prism/fixtures/seattlerb/parse_def_special_name.txt b/test/prism/fixtures/seattlerb/parse_def_special_name.txt
new file mode 100644
index 0000000000..8d7d06c688
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_def_special_name.txt
@@ -0,0 +1 @@
+def next; end
diff --git a/test/prism/fixtures/seattlerb/parse_if_not_canonical.txt b/test/prism/fixtures/seattlerb/parse_if_not_canonical.txt
new file mode 100644
index 0000000000..1fd9bb7327
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_if_not_canonical.txt
@@ -0,0 +1,2 @@
+if not var.nil? then 'foo' else 'bar'
+end
diff --git a/test/prism/fixtures/seattlerb/parse_if_not_noncanonical.txt b/test/prism/fixtures/seattlerb/parse_if_not_noncanonical.txt
new file mode 100644
index 0000000000..1fd9bb7327
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_if_not_noncanonical.txt
@@ -0,0 +1,2 @@
+if not var.nil? then 'foo' else 'bar'
+end
diff --git a/test/prism/fixtures/seattlerb/parse_line_block.txt b/test/prism/fixtures/seattlerb/parse_line_block.txt
new file mode 100644
index 0000000000..21664649db
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_line_block.txt
@@ -0,0 +1,2 @@
+a = 42
+p a
diff --git a/test/prism/fixtures/seattlerb/parse_line_block_inline_comment.txt b/test/prism/fixtures/seattlerb/parse_line_block_inline_comment.txt
new file mode 100644
index 0000000000..f55ced714f
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_line_block_inline_comment.txt
@@ -0,0 +1,3 @@
+a
+b # comment
+c
diff --git a/test/prism/fixtures/seattlerb/parse_line_block_inline_comment_leading_newlines.txt b/test/prism/fixtures/seattlerb/parse_line_block_inline_comment_leading_newlines.txt
new file mode 100644
index 0000000000..6f1fee62a0
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_line_block_inline_comment_leading_newlines.txt
@@ -0,0 +1,7 @@
+
+
+
+a
+b # comment
+# another comment
+c
diff --git a/test/prism/fixtures/seattlerb/parse_line_block_inline_multiline_comment.txt b/test/prism/fixtures/seattlerb/parse_line_block_inline_multiline_comment.txt
new file mode 100644
index 0000000000..b00de34dc0
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_line_block_inline_multiline_comment.txt
@@ -0,0 +1,4 @@
+a
+b # comment
+# another comment
+c
diff --git a/test/prism/fixtures/seattlerb/parse_line_call_ivar_arg_no_parens_line_break.txt b/test/prism/fixtures/seattlerb/parse_line_call_ivar_arg_no_parens_line_break.txt
new file mode 100644
index 0000000000..73785eb794
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_line_call_ivar_arg_no_parens_line_break.txt
@@ -0,0 +1,2 @@
+a @b
+
diff --git a/test/prism/fixtures/seattlerb/parse_line_call_ivar_line_break_paren.txt b/test/prism/fixtures/seattlerb/parse_line_call_ivar_line_break_paren.txt
new file mode 100644
index 0000000000..6f136e6d6f
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_line_call_ivar_line_break_paren.txt
@@ -0,0 +1,2 @@
+a(@b
+)
diff --git a/test/prism/fixtures/seattlerb/parse_line_call_no_args.txt b/test/prism/fixtures/seattlerb/parse_line_call_no_args.txt
new file mode 100644
index 0000000000..7900afd4b8
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_line_call_no_args.txt
@@ -0,0 +1,3 @@
+f do |x, y|
+ x + y
+end
diff --git a/test/prism/fixtures/seattlerb/parse_line_defn_complex.txt b/test/prism/fixtures/seattlerb/parse_line_defn_complex.txt
new file mode 100644
index 0000000000..244a8e862b
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_line_defn_complex.txt
@@ -0,0 +1,5 @@
+def x(y)
+ p(y)
+ y *= 2
+ return y;
+end
diff --git a/test/prism/fixtures/seattlerb/parse_line_defn_no_parens.txt b/test/prism/fixtures/seattlerb/parse_line_defn_no_parens.txt
new file mode 100644
index 0000000000..373ca7fbec
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_line_defn_no_parens.txt
@@ -0,0 +1,6 @@
+def f
+
+end
+
+def f
+end
diff --git a/test/prism/fixtures/seattlerb/parse_line_defn_no_parens_args.txt b/test/prism/fixtures/seattlerb/parse_line_defn_no_parens_args.txt
new file mode 100644
index 0000000000..10f004a149
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_line_defn_no_parens_args.txt
@@ -0,0 +1,2 @@
+def f a
+end
diff --git a/test/prism/fixtures/seattlerb/parse_line_dot2.txt b/test/prism/fixtures/seattlerb/parse_line_dot2.txt
new file mode 100644
index 0000000000..61c7554221
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_line_dot2.txt
@@ -0,0 +1,5 @@
+0..
+4
+a..
+b
+c
diff --git a/test/prism/fixtures/seattlerb/parse_line_dot2_open.txt b/test/prism/fixtures/seattlerb/parse_line_dot2_open.txt
new file mode 100644
index 0000000000..b3e1e5aaf9
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_line_dot2_open.txt
@@ -0,0 +1,3 @@
+0..
+; a..
+; c
diff --git a/test/prism/fixtures/seattlerb/parse_line_dot3.txt b/test/prism/fixtures/seattlerb/parse_line_dot3.txt
new file mode 100644
index 0000000000..d1866b41de
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_line_dot3.txt
@@ -0,0 +1,5 @@
+0...
+4
+a...
+b
+c
diff --git a/test/prism/fixtures/seattlerb/parse_line_dot3_open.txt b/test/prism/fixtures/seattlerb/parse_line_dot3_open.txt
new file mode 100644
index 0000000000..38e7634b21
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_line_dot3_open.txt
@@ -0,0 +1,3 @@
+0...
+; a...
+; c
diff --git a/test/prism/fixtures/seattlerb/parse_line_dstr_escaped_newline.txt b/test/prism/fixtures/seattlerb/parse_line_dstr_escaped_newline.txt
new file mode 100644
index 0000000000..29c1754915
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_line_dstr_escaped_newline.txt
@@ -0,0 +1,3 @@
+"a\n#{
+}"
+true
diff --git a/test/prism/fixtures/seattlerb/parse_line_dstr_soft_newline.txt b/test/prism/fixtures/seattlerb/parse_line_dstr_soft_newline.txt
new file mode 100644
index 0000000000..e4dbd7bcb2
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_line_dstr_soft_newline.txt
@@ -0,0 +1,4 @@
+"a
+#{
+}"
+true
diff --git a/test/prism/fixtures/seattlerb/parse_line_evstr_after_break.txt b/test/prism/fixtures/seattlerb/parse_line_evstr_after_break.txt
new file mode 100644
index 0000000000..c1d91a51c4
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_line_evstr_after_break.txt
@@ -0,0 +1,2 @@
+"a"\
+"#{b}"
diff --git a/test/prism/fixtures/seattlerb/parse_line_hash_lit.txt b/test/prism/fixtures/seattlerb/parse_line_hash_lit.txt
new file mode 100644
index 0000000000..25f8c90a06
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_line_hash_lit.txt
@@ -0,0 +1,3 @@
+{
+:s1 => 1,
+}
diff --git a/test/prism/fixtures/seattlerb/parse_line_heredoc.txt b/test/prism/fixtures/seattlerb/parse_line_heredoc.txt
new file mode 100644
index 0000000000..201339534c
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_line_heredoc.txt
@@ -0,0 +1,5 @@
+ string = <<-HEREDOC.strip
+ very long string
+ HEREDOC
+ puts string
+
diff --git a/test/prism/fixtures/seattlerb/parse_line_heredoc_evstr.txt b/test/prism/fixtures/seattlerb/parse_line_heredoc_evstr.txt
new file mode 100644
index 0000000000..d50844db4b
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_line_heredoc_evstr.txt
@@ -0,0 +1,4 @@
+<<-A
+a
+#{b}
+A
diff --git a/test/prism/fixtures/seattlerb/parse_line_heredoc_hardnewline.txt b/test/prism/fixtures/seattlerb/parse_line_heredoc_hardnewline.txt
new file mode 100644
index 0000000000..3fbf0f2c26
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_line_heredoc_hardnewline.txt
@@ -0,0 +1,7 @@
+<<-EOFOO
+\n\n\n\n\n\n\n\n\n
+EOFOO
+
+class Foo
+end
+
diff --git a/test/prism/fixtures/seattlerb/parse_line_heredoc_regexp_chars.txt b/test/prism/fixtures/seattlerb/parse_line_heredoc_regexp_chars.txt
new file mode 100644
index 0000000000..5dab9cf4e7
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_line_heredoc_regexp_chars.txt
@@ -0,0 +1,5 @@
+ string = <<-"^D"
+ very long string
+ ^D
+ puts string
+
diff --git a/test/prism/fixtures/seattlerb/parse_line_iter_call_no_parens.txt b/test/prism/fixtures/seattlerb/parse_line_iter_call_no_parens.txt
new file mode 100644
index 0000000000..bf1b33c8a2
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_line_iter_call_no_parens.txt
@@ -0,0 +1,3 @@
+f a do |x, y|
+ x + y
+end
diff --git a/test/prism/fixtures/seattlerb/parse_line_iter_call_parens.txt b/test/prism/fixtures/seattlerb/parse_line_iter_call_parens.txt
new file mode 100644
index 0000000000..25e9ea1c67
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_line_iter_call_parens.txt
@@ -0,0 +1,3 @@
+f(a) do |x, y|
+ x + y
+end
diff --git a/test/prism/fixtures/seattlerb/parse_line_multiline_str.txt b/test/prism/fixtures/seattlerb/parse_line_multiline_str.txt
new file mode 100644
index 0000000000..cdefb3c9b7
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_line_multiline_str.txt
@@ -0,0 +1,3 @@
+"a
+b"
+1
diff --git a/test/prism/fixtures/seattlerb/parse_line_multiline_str_literal_n.txt b/test/prism/fixtures/seattlerb/parse_line_multiline_str_literal_n.txt
new file mode 100644
index 0000000000..a179ba8c9c
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_line_multiline_str_literal_n.txt
@@ -0,0 +1,2 @@
+"a\nb"
+1
diff --git a/test/prism/fixtures/seattlerb/parse_line_newlines.txt b/test/prism/fixtures/seattlerb/parse_line_newlines.txt
new file mode 100644
index 0000000000..28b0c286e8
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_line_newlines.txt
@@ -0,0 +1,3 @@
+true
+
+
diff --git a/test/prism/fixtures/seattlerb/parse_line_op_asgn.txt b/test/prism/fixtures/seattlerb/parse_line_op_asgn.txt
new file mode 100644
index 0000000000..f2691c2ce4
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_line_op_asgn.txt
@@ -0,0 +1,4 @@
+ foo +=
+ bar
+ baz
+
diff --git a/test/prism/fixtures/seattlerb/parse_line_postexe.txt b/test/prism/fixtures/seattlerb/parse_line_postexe.txt
new file mode 100644
index 0000000000..fd8b318d19
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_line_postexe.txt
@@ -0,0 +1,3 @@
+END {
+foo
+}
diff --git a/test/prism/fixtures/seattlerb/parse_line_preexe.txt b/test/prism/fixtures/seattlerb/parse_line_preexe.txt
new file mode 100644
index 0000000000..b3eda77ebc
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_line_preexe.txt
@@ -0,0 +1,3 @@
+BEGIN {
+foo
+}
diff --git a/test/prism/fixtures/seattlerb/parse_line_rescue.txt b/test/prism/fixtures/seattlerb/parse_line_rescue.txt
new file mode 100644
index 0000000000..a583160ce2
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_line_rescue.txt
@@ -0,0 +1,8 @@
+begin
+ a
+rescue
+ b
+rescue
+ c
+end
+
diff --git a/test/prism/fixtures/seattlerb/parse_line_return.txt b/test/prism/fixtures/seattlerb/parse_line_return.txt
new file mode 100644
index 0000000000..81021c2644
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_line_return.txt
@@ -0,0 +1,6 @@
+ def blah
+ if true then
+ return 42
+ end
+ end
+
diff --git a/test/prism/fixtures/seattlerb/parse_line_str_with_newline_escape.txt b/test/prism/fixtures/seattlerb/parse_line_str_with_newline_escape.txt
new file mode 100644
index 0000000000..b2b6bb8234
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_line_str_with_newline_escape.txt
@@ -0,0 +1 @@
+a("\n", true)
diff --git a/test/prism/fixtures/seattlerb/parse_line_to_ary.txt b/test/prism/fixtures/seattlerb/parse_line_to_ary.txt
new file mode 100644
index 0000000000..590d0abd14
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_line_to_ary.txt
@@ -0,0 +1,3 @@
+a,
+b = c
+d
diff --git a/test/prism/fixtures/seattlerb/parse_line_trailing_newlines.txt b/test/prism/fixtures/seattlerb/parse_line_trailing_newlines.txt
new file mode 100644
index 0000000000..afa826fb50
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_line_trailing_newlines.txt
@@ -0,0 +1,2 @@
+a
+b
diff --git a/test/prism/fixtures/seattlerb/parse_opt_call_args_assocs_comma.txt b/test/prism/fixtures/seattlerb/parse_opt_call_args_assocs_comma.txt
new file mode 100644
index 0000000000..649c109ea1
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_opt_call_args_assocs_comma.txt
@@ -0,0 +1 @@
+1[2=>3,]
diff --git a/test/prism/fixtures/seattlerb/parse_opt_call_args_lit_comma.txt b/test/prism/fixtures/seattlerb/parse_opt_call_args_lit_comma.txt
new file mode 100644
index 0000000000..741cd4ffd1
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_opt_call_args_lit_comma.txt
@@ -0,0 +1 @@
+1[2,]
diff --git a/test/prism/fixtures/seattlerb/parse_pattern_019.txt b/test/prism/fixtures/seattlerb/parse_pattern_019.txt
new file mode 100644
index 0000000000..1e8a75902d
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_pattern_019.txt
@@ -0,0 +1,5 @@
+case 0
+in -1..1
+ true
+end
+
diff --git a/test/prism/fixtures/seattlerb/parse_pattern_044.txt b/test/prism/fixtures/seattlerb/parse_pattern_044.txt
new file mode 100644
index 0000000000..a6a0ac6c1c
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_pattern_044.txt
@@ -0,0 +1,5 @@
+case obj
+in Object[]
+ true
+end
+
diff --git a/test/prism/fixtures/seattlerb/parse_pattern_051.txt b/test/prism/fixtures/seattlerb/parse_pattern_051.txt
new file mode 100644
index 0000000000..b7cf769f50
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_pattern_051.txt
@@ -0,0 +1,5 @@
+case [0, 1, 2]
+in [0, 1,]
+ true
+end
+
diff --git a/test/prism/fixtures/seattlerb/parse_pattern_058.txt b/test/prism/fixtures/seattlerb/parse_pattern_058.txt
new file mode 100644
index 0000000000..bd7537098e
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_pattern_058.txt
@@ -0,0 +1,5 @@
+case {a: 0}
+in {a:, **rest}
+ [a, rest]
+end
+
diff --git a/test/prism/fixtures/seattlerb/parse_pattern_058_2.txt b/test/prism/fixtures/seattlerb/parse_pattern_058_2.txt
new file mode 100644
index 0000000000..eb1b3cd8ab
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_pattern_058_2.txt
@@ -0,0 +1,5 @@
+case {a: 0}
+in {a:, **}
+ [a]
+end
+
diff --git a/test/prism/fixtures/seattlerb/parse_pattern_069.txt b/test/prism/fixtures/seattlerb/parse_pattern_069.txt
new file mode 100644
index 0000000000..f43dff8959
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_pattern_069.txt
@@ -0,0 +1,5 @@
+case :a
+in Object[b: 1]
+ 1
+end
+
diff --git a/test/prism/fixtures/seattlerb/parse_pattern_076.txt b/test/prism/fixtures/seattlerb/parse_pattern_076.txt
new file mode 100644
index 0000000000..bb947605b3
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_pattern_076.txt
@@ -0,0 +1,5 @@
+case {a: 1}
+in {a: 1, **nil}
+ true
+end
+
diff --git a/test/prism/fixtures/seattlerb/parse_until_not_canonical.txt b/test/prism/fixtures/seattlerb/parse_until_not_canonical.txt
new file mode 100644
index 0000000000..4de38968dc
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_until_not_canonical.txt
@@ -0,0 +1,3 @@
+until not var.nil?
+ 'foo'
+end
diff --git a/test/prism/fixtures/seattlerb/parse_until_not_noncanonical.txt b/test/prism/fixtures/seattlerb/parse_until_not_noncanonical.txt
new file mode 100644
index 0000000000..4de38968dc
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_until_not_noncanonical.txt
@@ -0,0 +1,3 @@
+until not var.nil?
+ 'foo'
+end
diff --git a/test/prism/fixtures/seattlerb/parse_while_not_canonical.txt b/test/prism/fixtures/seattlerb/parse_while_not_canonical.txt
new file mode 100644
index 0000000000..5aa464167f
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_while_not_canonical.txt
@@ -0,0 +1,3 @@
+while not var.nil?
+ 'foo'
+end
diff --git a/test/prism/fixtures/seattlerb/parse_while_not_noncanonical.txt b/test/prism/fixtures/seattlerb/parse_while_not_noncanonical.txt
new file mode 100644
index 0000000000..5aa464167f
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/parse_while_not_noncanonical.txt
@@ -0,0 +1,3 @@
+while not var.nil?
+ 'foo'
+end
diff --git a/test/prism/fixtures/seattlerb/pctW_lineno.txt b/test/prism/fixtures/seattlerb/pctW_lineno.txt
new file mode 100644
index 0000000000..b222ff0174
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/pctW_lineno.txt
@@ -0,0 +1,5 @@
+%W(a\nb
+c d
+e\
+f
+gy h\y i\y)
diff --git a/test/prism/fixtures/seattlerb/pct_Q_backslash_nl.txt b/test/prism/fixtures/seattlerb/pct_Q_backslash_nl.txt
new file mode 100644
index 0000000000..4420560d2b
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/pct_Q_backslash_nl.txt
@@ -0,0 +1,2 @@
+%q{ \
+}
diff --git a/test/prism/fixtures/seattlerb/pct_nl.txt b/test/prism/fixtures/seattlerb/pct_nl.txt
new file mode 100644
index 0000000000..2cee1cdd44
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/pct_nl.txt
@@ -0,0 +1,3 @@
+x = %
+
+
diff --git a/test/prism/fixtures/seattlerb/pct_w_heredoc_interp_nested.txt b/test/prism/fixtures/seattlerb/pct_w_heredoc_interp_nested.txt
new file mode 100644
index 0000000000..4e084661bf
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/pct_w_heredoc_interp_nested.txt
@@ -0,0 +1,4 @@
+%W( 1 #{<<A} 3
+2
+A
+ 4 5 )
diff --git a/test/prism/fixtures/seattlerb/pipe_semicolon.txt b/test/prism/fixtures/seattlerb/pipe_semicolon.txt
new file mode 100644
index 0000000000..e692cc434f
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/pipe_semicolon.txt
@@ -0,0 +1 @@
+a.b do | ; c | end
diff --git a/test/prism/fixtures/seattlerb/pipe_space.txt b/test/prism/fixtures/seattlerb/pipe_space.txt
new file mode 100644
index 0000000000..7f0df799b9
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/pipe_space.txt
@@ -0,0 +1 @@
+a.b do | | end
diff --git a/test/prism/fixtures/seattlerb/qWords_space.txt b/test/prism/fixtures/seattlerb/qWords_space.txt
new file mode 100644
index 0000000000..a8299ba3f8
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/qWords_space.txt
@@ -0,0 +1 @@
+%W( )
diff --git a/test/prism/fixtures/seattlerb/qsymbols.txt b/test/prism/fixtures/seattlerb/qsymbols.txt
new file mode 100644
index 0000000000..cb9ff09ae0
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/qsymbols.txt
@@ -0,0 +1 @@
+%I(a b c)
diff --git a/test/prism/fixtures/seattlerb/qsymbols_empty.txt b/test/prism/fixtures/seattlerb/qsymbols_empty.txt
new file mode 100644
index 0000000000..10a3279907
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/qsymbols_empty.txt
@@ -0,0 +1 @@
+%I()
diff --git a/test/prism/fixtures/seattlerb/qsymbols_empty_space.txt b/test/prism/fixtures/seattlerb/qsymbols_empty_space.txt
new file mode 100644
index 0000000000..819f16ad06
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/qsymbols_empty_space.txt
@@ -0,0 +1 @@
+%I( )
diff --git a/test/prism/fixtures/seattlerb/qsymbols_interp.txt b/test/prism/fixtures/seattlerb/qsymbols_interp.txt
new file mode 100644
index 0000000000..2f34883867
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/qsymbols_interp.txt
@@ -0,0 +1 @@
+%I(a b#{1+1} c)
diff --git a/test/prism/fixtures/seattlerb/quoted_symbol_hash_arg.txt b/test/prism/fixtures/seattlerb/quoted_symbol_hash_arg.txt
new file mode 100644
index 0000000000..4f1295ef18
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/quoted_symbol_hash_arg.txt
@@ -0,0 +1 @@
+puts 'a': {}
diff --git a/test/prism/fixtures/seattlerb/quoted_symbol_keys.txt b/test/prism/fixtures/seattlerb/quoted_symbol_keys.txt
new file mode 100644
index 0000000000..c6a946723d
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/quoted_symbol_keys.txt
@@ -0,0 +1 @@
+{ 'a': :b }
diff --git a/test/prism/fixtures/seattlerb/qw_escape.txt b/test/prism/fixtures/seattlerb/qw_escape.txt
new file mode 100644
index 0000000000..a94a0e5dcb
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/qw_escape.txt
@@ -0,0 +1 @@
+%q(\')
diff --git a/test/prism/fixtures/seattlerb/qw_escape_term.txt b/test/prism/fixtures/seattlerb/qw_escape_term.txt
new file mode 100644
index 0000000000..9734fc3421
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/qw_escape_term.txt
@@ -0,0 +1 @@
+%q|blah blah \| blah blah|
diff --git a/test/prism/fixtures/seattlerb/qwords_empty.txt b/test/prism/fixtures/seattlerb/qwords_empty.txt
new file mode 100644
index 0000000000..69cc6679d6
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/qwords_empty.txt
@@ -0,0 +1 @@
+%w()
diff --git a/test/prism/fixtures/seattlerb/read_escape_unicode_curlies.txt b/test/prism/fixtures/seattlerb/read_escape_unicode_curlies.txt
new file mode 100644
index 0000000000..427b94cc4d
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/read_escape_unicode_curlies.txt
@@ -0,0 +1 @@
+?\u{00a0}
diff --git a/test/prism/fixtures/seattlerb/read_escape_unicode_h4.txt b/test/prism/fixtures/seattlerb/read_escape_unicode_h4.txt
new file mode 100644
index 0000000000..71aa7a4347
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/read_escape_unicode_h4.txt
@@ -0,0 +1 @@
+?\u00a0
diff --git a/test/prism/fixtures/seattlerb/regexp.txt b/test/prism/fixtures/seattlerb/regexp.txt
new file mode 100644
index 0000000000..bc06458c5c
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/regexp.txt
@@ -0,0 +1,9 @@
+/wtf/
+
+/wtf/m
+
+/wtf/n
+
+/wtf/nm
+
+/wtf/nmnmnmnm
diff --git a/test/prism/fixtures/seattlerb/regexp_esc_C_slash.txt b/test/prism/fixtures/seattlerb/regexp_esc_C_slash.txt
new file mode 100644
index 0000000000..1fd9207c66
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/regexp_esc_C_slash.txt
@@ -0,0 +1 @@
+/\cC\d/
diff --git a/test/prism/fixtures/seattlerb/regexp_esc_u.txt b/test/prism/fixtures/seattlerb/regexp_esc_u.txt
new file mode 100644
index 0000000000..b91704fb0a
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/regexp_esc_u.txt
@@ -0,0 +1 @@
+/[\u0021-\u0027]/
diff --git a/test/prism/fixtures/seattlerb/regexp_escape_extended.txt b/test/prism/fixtures/seattlerb/regexp_escape_extended.txt
new file mode 100644
index 0000000000..73dcbab69c
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/regexp_escape_extended.txt
@@ -0,0 +1 @@
+/\“/
diff --git a/test/prism/fixtures/seattlerb/regexp_unicode_curlies.txt b/test/prism/fixtures/seattlerb/regexp_unicode_curlies.txt
new file mode 100644
index 0000000000..5a02bd92ca
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/regexp_unicode_curlies.txt
@@ -0,0 +1,3 @@
+/\u{c0de babe}/
+
+/\u{df}/
diff --git a/test/prism/fixtures/seattlerb/required_kwarg_no_value.txt b/test/prism/fixtures/seattlerb/required_kwarg_no_value.txt
new file mode 100644
index 0000000000..453bcbb33b
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/required_kwarg_no_value.txt
@@ -0,0 +1,2 @@
+def x a:, b:
+end
diff --git a/test/prism/fixtures/seattlerb/rescue_do_end_ensure_result.txt b/test/prism/fixtures/seattlerb/rescue_do_end_ensure_result.txt
new file mode 100644
index 0000000000..7049be66c5
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/rescue_do_end_ensure_result.txt
@@ -0,0 +1,5 @@
+proc do
+ :begin
+ensure
+ :ensure
+end.call
diff --git a/test/prism/fixtures/seattlerb/rescue_do_end_no_raise.txt b/test/prism/fixtures/seattlerb/rescue_do_end_no_raise.txt
new file mode 100644
index 0000000000..5f16ec2f15
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/rescue_do_end_no_raise.txt
@@ -0,0 +1,9 @@
+tap do
+ :begin
+rescue
+ :rescue
+else
+ :else
+ensure
+ :ensure
+end
diff --git a/test/prism/fixtures/seattlerb/rescue_do_end_raised.txt b/test/prism/fixtures/seattlerb/rescue_do_end_raised.txt
new file mode 100644
index 0000000000..d04215eb48
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/rescue_do_end_raised.txt
@@ -0,0 +1,5 @@
+tap do
+ raise
+ensure
+ :ensure
+end
diff --git a/test/prism/fixtures/seattlerb/rescue_do_end_rescued.txt b/test/prism/fixtures/seattlerb/rescue_do_end_rescued.txt
new file mode 100644
index 0000000000..4b377511f0
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/rescue_do_end_rescued.txt
@@ -0,0 +1,9 @@
+tap do
+ raise
+rescue
+ :rescue
+else
+ :else
+ensure
+ :ensure
+end
diff --git a/test/prism/fixtures/seattlerb/rescue_in_block.txt b/test/prism/fixtures/seattlerb/rescue_in_block.txt
new file mode 100644
index 0000000000..c6e834aa1e
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/rescue_in_block.txt
@@ -0,0 +1,4 @@
+blah do
+rescue
+ stuff
+end
diff --git a/test/prism/fixtures/seattlerb/rescue_parens.txt b/test/prism/fixtures/seattlerb/rescue_parens.txt
new file mode 100644
index 0000000000..f0eb4db417
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/rescue_parens.txt
@@ -0,0 +1 @@
+a (b rescue c)
diff --git a/test/prism/fixtures/seattlerb/return_call_assocs.txt b/test/prism/fixtures/seattlerb/return_call_assocs.txt
new file mode 100644
index 0000000000..34ea778f17
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/return_call_assocs.txt
@@ -0,0 +1,11 @@
+return 1, :z => 1
+
+return 1, :z => 1, :w => 2
+
+return y :z=>1
+
+return y z:1
+
+return y(z:1)
+
+return y(z=>1)
diff --git a/test/prism/fixtures/seattlerb/rhs_asgn.txt b/test/prism/fixtures/seattlerb/rhs_asgn.txt
new file mode 100644
index 0000000000..ca581031e2
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/rhs_asgn.txt
@@ -0,0 +1 @@
+42 => n
diff --git a/test/prism/fixtures/seattlerb/ruby21_numbers.txt b/test/prism/fixtures/seattlerb/ruby21_numbers.txt
new file mode 100644
index 0000000000..34ceb63a0c
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/ruby21_numbers.txt
@@ -0,0 +1 @@
+[1i, 2r, 3ri]
diff --git a/test/prism/fixtures/seattlerb/safe_attrasgn.txt b/test/prism/fixtures/seattlerb/safe_attrasgn.txt
new file mode 100644
index 0000000000..1279e02cfc
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/safe_attrasgn.txt
@@ -0,0 +1 @@
+a&.b = 1
diff --git a/test/prism/fixtures/seattlerb/safe_attrasgn_constant.txt b/test/prism/fixtures/seattlerb/safe_attrasgn_constant.txt
new file mode 100644
index 0000000000..3a17ac6bcf
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/safe_attrasgn_constant.txt
@@ -0,0 +1 @@
+a&.B = 1
diff --git a/test/prism/fixtures/seattlerb/safe_call.txt b/test/prism/fixtures/seattlerb/safe_call.txt
new file mode 100644
index 0000000000..8ecd27e0fe
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/safe_call.txt
@@ -0,0 +1 @@
+a&.b
diff --git a/test/prism/fixtures/seattlerb/safe_call_after_newline.txt b/test/prism/fixtures/seattlerb/safe_call_after_newline.txt
new file mode 100644
index 0000000000..58e3fba554
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/safe_call_after_newline.txt
@@ -0,0 +1,2 @@
+a
+&.b
diff --git a/test/prism/fixtures/seattlerb/safe_call_dot_parens.txt b/test/prism/fixtures/seattlerb/safe_call_dot_parens.txt
new file mode 100644
index 0000000000..5def076640
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/safe_call_dot_parens.txt
@@ -0,0 +1 @@
+a&.()
diff --git a/test/prism/fixtures/seattlerb/safe_call_newline.txt b/test/prism/fixtures/seattlerb/safe_call_newline.txt
new file mode 100644
index 0000000000..8778b46585
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/safe_call_newline.txt
@@ -0,0 +1,2 @@
+a&.b
+
diff --git a/test/prism/fixtures/seattlerb/safe_call_operator.txt b/test/prism/fixtures/seattlerb/safe_call_operator.txt
new file mode 100644
index 0000000000..f3fe2b0392
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/safe_call_operator.txt
@@ -0,0 +1 @@
+a&.> 1
diff --git a/test/prism/fixtures/seattlerb/safe_call_rhs_newline.txt b/test/prism/fixtures/seattlerb/safe_call_rhs_newline.txt
new file mode 100644
index 0000000000..d3b07b77b2
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/safe_call_rhs_newline.txt
@@ -0,0 +1,2 @@
+c = a&.b
+
diff --git a/test/prism/fixtures/seattlerb/safe_calls.txt b/test/prism/fixtures/seattlerb/safe_calls.txt
new file mode 100644
index 0000000000..eafeace500
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/safe_calls.txt
@@ -0,0 +1 @@
+a&.b&.c(1)
diff --git a/test/prism/fixtures/seattlerb/safe_op_asgn.txt b/test/prism/fixtures/seattlerb/safe_op_asgn.txt
new file mode 100644
index 0000000000..8915a1cccf
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/safe_op_asgn.txt
@@ -0,0 +1 @@
+a&.b += x 1
diff --git a/test/prism/fixtures/seattlerb/safe_op_asgn2.txt b/test/prism/fixtures/seattlerb/safe_op_asgn2.txt
new file mode 100644
index 0000000000..0960b2548b
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/safe_op_asgn2.txt
@@ -0,0 +1,2 @@
+a&.b ||=
+x;
diff --git a/test/prism/fixtures/seattlerb/slashy_newlines_within_string.txt b/test/prism/fixtures/seattlerb/slashy_newlines_within_string.txt
new file mode 100644
index 0000000000..421989c76f
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/slashy_newlines_within_string.txt
@@ -0,0 +1,7 @@
+puts "hello\
+ my\
+ dear\
+ friend"
+
+a + b
+
diff --git a/test/prism/fixtures/seattlerb/stabby_arg_no_paren.txt b/test/prism/fixtures/seattlerb/stabby_arg_no_paren.txt
new file mode 100644
index 0000000000..f16bed4ccf
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/stabby_arg_no_paren.txt
@@ -0,0 +1 @@
+->a{}
diff --git a/test/prism/fixtures/seattlerb/stabby_arg_opt_splat_arg_block_omfg.txt b/test/prism/fixtures/seattlerb/stabby_arg_opt_splat_arg_block_omfg.txt
new file mode 100644
index 0000000000..87a7c5dad3
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/stabby_arg_opt_splat_arg_block_omfg.txt
@@ -0,0 +1 @@
+->(b, c=1, *d, e, &f){}
diff --git a/test/prism/fixtures/seattlerb/stabby_block_iter_call.txt b/test/prism/fixtures/seattlerb/stabby_block_iter_call.txt
new file mode 100644
index 0000000000..5e9e3f5527
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/stabby_block_iter_call.txt
@@ -0,0 +1,4 @@
+x -> () do
+a.b do
+end
+end
diff --git a/test/prism/fixtures/seattlerb/stabby_block_iter_call_no_target_with_arg.txt b/test/prism/fixtures/seattlerb/stabby_block_iter_call_no_target_with_arg.txt
new file mode 100644
index 0000000000..7235394751
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/stabby_block_iter_call_no_target_with_arg.txt
@@ -0,0 +1,4 @@
+x -> () do
+a(1) do
+end
+end
diff --git a/test/prism/fixtures/seattlerb/stabby_block_kw.txt b/test/prism/fixtures/seattlerb/stabby_block_kw.txt
new file mode 100644
index 0000000000..74d9e0a328
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/stabby_block_kw.txt
@@ -0,0 +1 @@
+-> (k:42) { }
diff --git a/test/prism/fixtures/seattlerb/stabby_block_kw__required.txt b/test/prism/fixtures/seattlerb/stabby_block_kw__required.txt
new file mode 100644
index 0000000000..bd16ffa73c
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/stabby_block_kw__required.txt
@@ -0,0 +1 @@
+-> (k:) { }
diff --git a/test/prism/fixtures/seattlerb/stabby_proc_scope.txt b/test/prism/fixtures/seattlerb/stabby_proc_scope.txt
new file mode 100644
index 0000000000..1f7f9ff52b
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/stabby_proc_scope.txt
@@ -0,0 +1 @@
+->(a; b) {}
diff --git a/test/prism/fixtures/seattlerb/str_backslashes.txt b/test/prism/fixtures/seattlerb/str_backslashes.txt
new file mode 100644
index 0000000000..5fd6da361b
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/str_backslashes.txt
@@ -0,0 +1 @@
+x '\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n'
diff --git a/test/prism/fixtures/seattlerb/str_double_double_escaped_newline.txt b/test/prism/fixtures/seattlerb/str_double_double_escaped_newline.txt
new file mode 100644
index 0000000000..2b022a55f6
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/str_double_double_escaped_newline.txt
@@ -0,0 +1 @@
+a "\\n";b
diff --git a/test/prism/fixtures/seattlerb/str_double_escaped_newline.txt b/test/prism/fixtures/seattlerb/str_double_escaped_newline.txt
new file mode 100644
index 0000000000..e439225344
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/str_double_escaped_newline.txt
@@ -0,0 +1 @@
+a "\n";b
diff --git a/test/prism/fixtures/seattlerb/str_double_newline.txt b/test/prism/fixtures/seattlerb/str_double_newline.txt
new file mode 100644
index 0000000000..2d439506ca
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/str_double_newline.txt
@@ -0,0 +1,2 @@
+a "
+";b
diff --git a/test/prism/fixtures/seattlerb/str_evstr.txt b/test/prism/fixtures/seattlerb/str_evstr.txt
new file mode 100644
index 0000000000..86c6d1526d
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/str_evstr.txt
@@ -0,0 +1 @@
+"a #{b}"
diff --git a/test/prism/fixtures/seattlerb/str_evstr_escape.txt b/test/prism/fixtures/seattlerb/str_evstr_escape.txt
new file mode 100644
index 0000000000..517dfd4778
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/str_evstr_escape.txt
@@ -0,0 +1 @@
+"a #{b}\302\275"
diff --git a/test/prism/fixtures/seattlerb/str_heredoc_interp.txt b/test/prism/fixtures/seattlerb/str_heredoc_interp.txt
new file mode 100644
index 0000000000..aa2613008c
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/str_heredoc_interp.txt
@@ -0,0 +1,5 @@
+<<""
+#{x}
+blah2
+
+
diff --git a/test/prism/fixtures/seattlerb/str_interp_ternary_or_label.txt b/test/prism/fixtures/seattlerb/str_interp_ternary_or_label.txt
new file mode 100644
index 0000000000..fe6637678f
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/str_interp_ternary_or_label.txt
@@ -0,0 +1 @@
+"#{a.b? ? ""+a+"": ""}"
diff --git a/test/prism/fixtures/seattlerb/str_lit_concat_bad_encodings.txt b/test/prism/fixtures/seattlerb/str_lit_concat_bad_encodings.txt
new file mode 100644
index 0000000000..f4eb3971bb
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/str_lit_concat_bad_encodings.txt
@@ -0,0 +1,2 @@
+"\xE3\xD3\x8B\xE3\x83\xBC\x83\xE3\x83\xE3\x82\xB3\xA3\x82\x99" \
+ "\xE3\x83\xB3\xE3\x83\x8F\xE3\x82\x9A\xC3\xBD;foo@bar.com"
diff --git a/test/prism/fixtures/seattlerb/str_newline_hash_line_number.txt b/test/prism/fixtures/seattlerb/str_newline_hash_line_number.txt
new file mode 100644
index 0000000000..9c8f702000
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/str_newline_hash_line_number.txt
@@ -0,0 +1,2 @@
+"\n\n\n\n#"
+1
diff --git a/test/prism/fixtures/seattlerb/str_pct_Q_nested.txt b/test/prism/fixtures/seattlerb/str_pct_Q_nested.txt
new file mode 100644
index 0000000000..1f3d0613e5
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/str_pct_Q_nested.txt
@@ -0,0 +1 @@
+%Q[before [#{nest}] after]
diff --git a/test/prism/fixtures/seattlerb/str_pct_nested_nested.txt b/test/prism/fixtures/seattlerb/str_pct_nested_nested.txt
new file mode 100644
index 0000000000..cb12415215
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/str_pct_nested_nested.txt
@@ -0,0 +1 @@
+%{ { #{ "#{1}" } } }
diff --git a/test/prism/fixtures/seattlerb/str_pct_q.txt b/test/prism/fixtures/seattlerb/str_pct_q.txt
new file mode 100644
index 0000000000..65d71197c9
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/str_pct_q.txt
@@ -0,0 +1 @@
+%q{a b c}
diff --git a/test/prism/fixtures/seattlerb/str_single_double_escaped_newline.txt b/test/prism/fixtures/seattlerb/str_single_double_escaped_newline.txt
new file mode 100644
index 0000000000..2ff0aec111
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/str_single_double_escaped_newline.txt
@@ -0,0 +1 @@
+a '\\n';b
diff --git a/test/prism/fixtures/seattlerb/str_single_escaped_newline.txt b/test/prism/fixtures/seattlerb/str_single_escaped_newline.txt
new file mode 100644
index 0000000000..5abb8d6334
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/str_single_escaped_newline.txt
@@ -0,0 +1 @@
+a '\n';b
diff --git a/test/prism/fixtures/seattlerb/str_single_newline.txt b/test/prism/fixtures/seattlerb/str_single_newline.txt
new file mode 100644
index 0000000000..1033cc7e96
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/str_single_newline.txt
@@ -0,0 +1,2 @@
+a '
+';b
diff --git a/test/prism/fixtures/seattlerb/str_str.txt b/test/prism/fixtures/seattlerb/str_str.txt
new file mode 100644
index 0000000000..388d777dc2
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/str_str.txt
@@ -0,0 +1 @@
+"a #{'b'}"
diff --git a/test/prism/fixtures/seattlerb/str_str_str.txt b/test/prism/fixtures/seattlerb/str_str_str.txt
new file mode 100644
index 0000000000..d64e01dc5d
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/str_str_str.txt
@@ -0,0 +1 @@
+"a #{'b'} c"
diff --git a/test/prism/fixtures/seattlerb/super_arg.txt b/test/prism/fixtures/seattlerb/super_arg.txt
new file mode 100644
index 0000000000..1b19ecd51c
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/super_arg.txt
@@ -0,0 +1 @@
+super 42
diff --git a/test/prism/fixtures/seattlerb/symbol_empty.txt b/test/prism/fixtures/seattlerb/symbol_empty.txt
new file mode 100644
index 0000000000..cbb260bb4e
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/symbol_empty.txt
@@ -0,0 +1 @@
+:''
diff --git a/test/prism/fixtures/seattlerb/symbol_list.txt b/test/prism/fixtures/seattlerb/symbol_list.txt
new file mode 100644
index 0000000000..d357195184
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/symbol_list.txt
@@ -0,0 +1 @@
+%I[#{a} #{b}]
diff --git a/test/prism/fixtures/seattlerb/symbols.txt b/test/prism/fixtures/seattlerb/symbols.txt
new file mode 100644
index 0000000000..3ec930ce66
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/symbols.txt
@@ -0,0 +1 @@
+%i(a b c)
diff --git a/test/prism/fixtures/seattlerb/symbols_empty.txt b/test/prism/fixtures/seattlerb/symbols_empty.txt
new file mode 100644
index 0000000000..840948efb2
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/symbols_empty.txt
@@ -0,0 +1 @@
+%i()
diff --git a/test/prism/fixtures/seattlerb/symbols_empty_space.txt b/test/prism/fixtures/seattlerb/symbols_empty_space.txt
new file mode 100644
index 0000000000..16c2e68a2b
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/symbols_empty_space.txt
@@ -0,0 +1 @@
+%i( )
diff --git a/test/prism/fixtures/seattlerb/symbols_interp.txt b/test/prism/fixtures/seattlerb/symbols_interp.txt
new file mode 100644
index 0000000000..63116eb632
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/symbols_interp.txt
@@ -0,0 +1 @@
+%i(a b#{1+1} c)
diff --git a/test/prism/fixtures/seattlerb/thingy.txt b/test/prism/fixtures/seattlerb/thingy.txt
new file mode 100644
index 0000000000..5aa598c4be
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/thingy.txt
@@ -0,0 +1,3 @@
+f.(42)
+
+f::(42)
diff --git a/test/prism/fixtures/seattlerb/uminus_float.txt b/test/prism/fixtures/seattlerb/uminus_float.txt
new file mode 100644
index 0000000000..1344bfd9db
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/uminus_float.txt
@@ -0,0 +1 @@
+-0.0
diff --git a/test/prism/fixtures/seattlerb/unary_minus.txt b/test/prism/fixtures/seattlerb/unary_minus.txt
new file mode 100644
index 0000000000..66af866f85
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/unary_minus.txt
@@ -0,0 +1 @@
+-a
diff --git a/test/prism/fixtures/seattlerb/unary_plus.txt b/test/prism/fixtures/seattlerb/unary_plus.txt
new file mode 100644
index 0000000000..daea40b71e
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/unary_plus.txt
@@ -0,0 +1 @@
++a
diff --git a/test/prism/fixtures/seattlerb/unary_plus_on_literal.txt b/test/prism/fixtures/seattlerb/unary_plus_on_literal.txt
new file mode 100644
index 0000000000..752331df47
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/unary_plus_on_literal.txt
@@ -0,0 +1 @@
++:a
diff --git a/test/prism/fixtures/seattlerb/unary_tilde.txt b/test/prism/fixtures/seattlerb/unary_tilde.txt
new file mode 100644
index 0000000000..f0a507b437
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/unary_tilde.txt
@@ -0,0 +1 @@
+~a
diff --git a/test/prism/fixtures/seattlerb/utf8_bom.txt b/test/prism/fixtures/seattlerb/utf8_bom.txt
new file mode 100644
index 0000000000..c8e9e1cbae
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/utf8_bom.txt
@@ -0,0 +1,3 @@
+#!/usr/bin/env ruby -w
+p 0
+
diff --git a/test/prism/fixtures/seattlerb/when_splat.txt b/test/prism/fixtures/seattlerb/when_splat.txt
new file mode 100644
index 0000000000..6b79f5dad0
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/when_splat.txt
@@ -0,0 +1 @@
+case a; when *b then; end
diff --git a/test/prism/fixtures/seattlerb/words_interp.txt b/test/prism/fixtures/seattlerb/words_interp.txt
new file mode 100644
index 0000000000..f71486495b
--- /dev/null
+++ b/test/prism/fixtures/seattlerb/words_interp.txt
@@ -0,0 +1 @@
+%W(#{1}b)
diff --git a/test/prism/fixtures/single_method_call_with_bang.txt b/test/prism/fixtures/single_method_call_with_bang.txt
new file mode 100644
index 0000000000..929efb3053
--- /dev/null
+++ b/test/prism/fixtures/single_method_call_with_bang.txt
@@ -0,0 +1 @@
+foo!
diff --git a/test/prism/fixtures/single_quote_heredocs.txt b/test/prism/fixtures/single_quote_heredocs.txt
new file mode 100644
index 0000000000..0122b2726c
--- /dev/null
+++ b/test/prism/fixtures/single_quote_heredocs.txt
@@ -0,0 +1,3 @@
+<<-'EOS'
+ cd L:\Work\MG3710IQPro\Develop
+EOS
diff --git a/test/prism/fixtures/spanning_heredoc.txt b/test/prism/fixtures/spanning_heredoc.txt
new file mode 100644
index 0000000000..d09cb11b1f
--- /dev/null
+++ b/test/prism/fixtures/spanning_heredoc.txt
@@ -0,0 +1,63 @@
+# test regex, string, and lists that span a heredoc thanks to an escaped newline
+
+# ripper incorrectly creates a "b\nb" token instead of two separate string tokens
+pp <<-A.gsub(/b\
+a
+A
+b/, "")
+
+# ripper incorrectly creates a "d\nd" token instead of two separate string tokens
+pp <<-A, "d\
+c
+A
+d"
+
+# ripper gets this right
+pp <<-A, %q[f\
+e
+A
+f]
+
+# ripper incorrectly creates a "h\nh" token instead of two separate string tokens
+pp <<-A, %Q[h\
+g
+A
+h]
+
+# ripper can't parse this successfully, though ruby runs it correctly
+pp <<-A, %w[j\
+i
+A
+j]
+
+# ripper can't parse this successfully, though ruby runs it correctly
+# TODO: prism does not include the "\n" in "l\nl" in the AST like ruby does
+pp <<-A, %W[l\
+k
+A
+l]
+
+# ripper can't parse this successfully, though ruby runs it correctly
+pp <<-A, %i[n\
+m
+A
+n]
+
+# ripper gets this one wrong in the same way that prism does ...
+# TODO: prism does not include the "\n" in "p\np" in the AST like ruby does
+pp <<-A, %I[p\
+o
+A
+p]
+
+<<A; /\
+A
+(?<a>)/ =~ ''
+
+<<A; :'a
+A
+b'
+
+<<A; :"a
+A
+b"
diff --git a/test/prism/fixtures/spanning_heredoc_newlines.txt b/test/prism/fixtures/spanning_heredoc_newlines.txt
new file mode 100644
index 0000000000..32c9943aeb
--- /dev/null
+++ b/test/prism/fixtures/spanning_heredoc_newlines.txt
@@ -0,0 +1,23 @@
+<<A+%
+A
+
+
+<<A+%r
+A
+
+
+<<A+%q
+A
+
+
+<<A+%Q
+A
+
+
+<<A+%s
+A
+
+
+<<A+%x
+A
+
diff --git a/test/prism/fixtures/strings.txt b/test/prism/fixtures/strings.txt
new file mode 100644
index 0000000000..2ce8b738a3
--- /dev/null
+++ b/test/prism/fixtures/strings.txt
@@ -0,0 +1,105 @@
+%%abc%
+
+%^abc^
+
+%&abc&
+
+%*abc*
+
+%_abc_
+
+%+abc+
+
+%-abc-
+
+%:abc:
+
+%;abc;
+
+%'abc'
+
+%~abc~
+
+%?abc?
+
+%w{ }
+
+%/abc/
+
+%`abc`
+
+"#@@foo"
+
+%\abc\
+
+%{aaa #{bbb} ccc}
+
+%[foo[]]
+
+"foo" +
+#
+"bar"
+
+%q{abc}
+
+%s[abc]
+
+%{abc}
+
+''
+
+"abc"
+
+"#@---"
+
+"aaa #{bbb} ccc"
+
+'abc'
+
+%w[a b c]
+
+%w[a[] b[[]] c[]]
+
+%w[foo\ bar \#{1}]
+
+%w[foo\ bar baz]
+
+%W[a b#{c}d e]
+
+%W[a b c]
+
+%w[
+ a
+ b
+ c
+]
+
+'\' foo \' bar'
+
+'\\ foo \\ bar'
+
+"#$foo"
+
+"#@foo"
+
+"\x7 \x23 \x61"
+
+"\7 \43 \141"
+
+%[abc]
+
+%(abc)
+
+%@abc@
+
+%$abc$
+
+?a
+
+?a "a"
+
+%Q{abc}
+
+%^#$^#
+
+%@#@#
diff --git a/test/prism/fixtures/super.txt b/test/prism/fixtures/super.txt
new file mode 100644
index 0000000000..cd7aaf992e
--- /dev/null
+++ b/test/prism/fixtures/super.txt
@@ -0,0 +1,17 @@
+super
+
+super()
+
+super(1)
+
+super(1, 2, 3)
+
+super &:foo
+
+super(&:foo)
+
+super {}
+
+super(1, 2, 3) {}
+
+super(1, 2, 3, &:foo)
diff --git a/test/prism/fixtures/symbols.txt b/test/prism/fixtures/symbols.txt
new file mode 100644
index 0000000000..7563eb874f
--- /dev/null
+++ b/test/prism/fixtures/symbols.txt
@@ -0,0 +1,93 @@
+:'abc'
+
+:"#{var}"
+
+:"abc#{1}"
+
+[:Î¥, :ά, :Å—, :Ï]
+
+:-@
+
+:-
+
+:%
+
+:|
+
+:+@
+
+:+
+
+:/
+
+:**
+
+:*
+
+:~@
+
+[1, 1.0, 1r, 1i]
+
+:~
+
+:a
+
+%i[a b c]
+
+%i[a b#{1} #{2}c d#{3}f]
+
+%I[a b#{1} #{2}c d#{3}f]
+
+:@@a
+
+:ðŸ‘
+
+%i[a\b]
+
+:$a
+
+:@a
+
+:do
+
+:&
+
+:`
+
+:!@
+
+:!~
+
+:!
+
+:[]
+
+:[]=
+
+:^
+
+:==
+
+:===
+
+:=~
+
+:>=
+
+:>>
+
+:>
+
+:<=>
+
+:<=
+
+:<<
+
+:<
+
+:__LINE__
+
+:__FILE__
+
+:__ENCODING__
diff --git a/test/prism/fixtures/ternary_operator.txt b/test/prism/fixtures/ternary_operator.txt
new file mode 100644
index 0000000000..79d2d7d837
--- /dev/null
+++ b/test/prism/fixtures/ternary_operator.txt
@@ -0,0 +1,15 @@
+a ? b : c
+
+a ? defined? b : defined? c
+
+empty??true:nil
+
+empty??false:nil
+
+empty??nil:nil
+
+a??nil:nil
+
+a ?var1 : var2
+
+nil??_a =2:1
diff --git a/test/prism/fixtures/tilde_heredocs.txt b/test/prism/fixtures/tilde_heredocs.txt
new file mode 100644
index 0000000000..cca47ef00b
--- /dev/null
+++ b/test/prism/fixtures/tilde_heredocs.txt
@@ -0,0 +1,97 @@
+<<~EOF
+ a
+#{1}
+ a
+EOF
+
+<<~EOF
+ a
+EOF
+
+<<~EOF
+ a
+ b
+ c
+EOF
+
+<<~EOF
+ #{1} a
+EOF
+
+<<~EOF
+ a #{1}
+EOF
+
+<<~EOF
+ a
+ #{1}
+EOF
+
+<<~EOF
+ a
+ #{1}
+EOF
+
+<<~EOF
+ a
+ b
+EOF
+
+<<~EOF
+ a
+ b
+EOF
+
+<<~EOF
+ a
+ b
+EOF
+
+<<~'EOF'
+ a #{1}
+EOF
+
+<<~EOF
+ a
+ b
+EOF
+
+<<~EOF
+ a
+ b
+EOF
+
+<<~EOF
+ a
+ b
+EOF
+
+<<~EOF
+ a
+
+ b
+EOF
+
+<<~EOF
+ a
+
+ b
+EOF
+
+<<~EOF
+ a
+
+
+
+ b
+EOF
+
+<<~EOF
+
+ #{1}a
+ EOF
+
+<<~EOT
+ #{1}
+ b
+EOT
diff --git a/test/prism/fixtures/undef.txt b/test/prism/fixtures/undef.txt
new file mode 100644
index 0000000000..129c349433
--- /dev/null
+++ b/test/prism/fixtures/undef.txt
@@ -0,0 +1,17 @@
+undef a
+
+undef a, b
+
+undef if
+
+undef <=>
+
+undef :a
+
+undef :a, :b, :c
+
+undef :'abc'
+
+undef :"abc#{1}"
+
+undef Constant
diff --git a/test/prism/fixtures/unescaping.txt b/test/prism/fixtures/unescaping.txt
new file mode 100644
index 0000000000..e2da5a696c
--- /dev/null
+++ b/test/prism/fixtures/unescaping.txt
@@ -0,0 +1,9 @@
+["\c#{1}"]
+
+/\c#{1}/
+
+"\c#{1}"
+
+<<~HERE
+ \c#{1}
+HERE
diff --git a/test/prism/fixtures/unless.txt b/test/prism/fixtures/unless.txt
new file mode 100644
index 0000000000..678d58991b
--- /dev/null
+++ b/test/prism/fixtures/unless.txt
@@ -0,0 +1,14 @@
+unless true; 1; end
+
+unless true
+1 else 2 end
+
+1 unless true
+
+tap { break unless true }
+
+tap { next unless true }
+
+return unless true
+
+foo :a, :b unless bar?
diff --git a/test/prism/fixtures/unparser/LICENSE b/test/prism/fixtures/unparser/LICENSE
new file mode 100644
index 0000000000..44863d7afb
--- /dev/null
+++ b/test/prism/fixtures/unparser/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2013 Markus Schirp
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/test/prism/fixtures/unparser/corpus/literal/alias.txt b/test/prism/fixtures/unparser/corpus/literal/alias.txt
new file mode 100644
index 0000000000..fb06a295e8
--- /dev/null
+++ b/test/prism/fixtures/unparser/corpus/literal/alias.txt
@@ -0,0 +1,2 @@
+alias $foo $bar
+alias :foo :bar
diff --git a/test/prism/fixtures/unparser/corpus/literal/assignment.txt b/test/prism/fixtures/unparser/corpus/literal/assignment.txt
new file mode 100644
index 0000000000..84a74e8928
--- /dev/null
+++ b/test/prism/fixtures/unparser/corpus/literal/assignment.txt
@@ -0,0 +1,53 @@
+$a = 1
+($a, $b) = [1, 2]
+((a,), b) = 1
+(*a) = []
+(*foo) = [1, 2]
+(@@a, @@b) = [1, 2]
+(@a, @b) = [1, 2]
+(a, (b, c)) = [1, [2, 3]]
+(a, *) = [1, 2]
+(a, *foo) = [1, 2]
+(a, b) = [1, 2]
+(a, b) = foo
+(a,) = foo
+(a.foo, a.bar) = [1, 2]
+(a[*foo], a[1]) = [1, 2]
+(a[0], a[1]) = [1, 2]
+(*c.foo) = 1
+::Foo = ::Bar
+@@a = 1
+@a = 1
+CONST = 1
+Name::Spaced::CONST = 1
+a = ((b, c) = 1)
+a = 1
+foo = foo()
+foo.[]=()
+foo.[]=(1, 2)
+foo.[]=true
+foo[*index] = value
+foo[1..2] = value
+foo[] = 1
+foo[a, b] = value
+foo[index] = value
+x = %()
+x.x=%()
+x[%()] = bar
+a[%()] ||= bar
+@a ||= %()
+x = <<-HEREDOC
+ #{}
+HEREDOC
+x.x=<<-HEREDOC
+ #{}
+HEREDOC
+x[] = <<-HEREDOC
+ #{}
+HEREDOC
+a[<<-HEREDOC] ||= bar
+ #{}
+HEREDOC
+@a ||= <<-HEREDOC
+ #{}
+HEREDOC
diff --git a/test/prism/fixtures/unparser/corpus/literal/block.txt b/test/prism/fixtures/unparser/corpus/literal/block.txt
new file mode 100644
index 0000000000..b2baf1dc12
--- /dev/null
+++ b/test/prism/fixtures/unparser/corpus/literal/block.txt
@@ -0,0 +1,96 @@
+foo {
+}
+foo { |a|
+}
+foo { |a,|
+}
+foo { |a,; x|
+}
+foo { |a, b|
+}
+foo(1) {
+ nil
+}
+foo { |a, *b|
+ nil
+}
+foo { |a, *|
+ nil
+}
+foo {
+ bar
+}
+foo.bar { |(a, b), c|
+ d
+}
+foo.bar { |*a; b|
+}
+foo.bar { |a; b|
+}
+foo.bar { |; a, b|
+}
+foo.bar { |*|
+ d
+}
+foo.bar { |(*)|
+ d
+}
+foo.bar { |((*))|
+ d
+}
+foo.bar { |(a, (*))|
+ d
+}
+foo.bar { |(a, b)|
+ d
+}
+foo.bar {
+}.baz
+m do
+rescue Exception => e
+end
+m do
+ foo
+rescue Exception => bar
+ bar
+end
+m do
+ bar
+rescue SomeError, *bar
+ baz
+end
+m do
+ bar
+rescue SomeError, *bar => exception
+ baz
+end
+m do
+ bar
+rescue *bar
+ baz
+end
+m do
+ bar
+rescue LoadError
+end
+m do
+ bar
+rescue
+else
+ baz
+end
+m do
+ bar
+rescue *bar => exception
+ baz
+end
+m do
+ensure
+end
+m do
+rescue
+ensure
+end
+bar {
+ _1 + _2
+}
diff --git a/test/prism/fixtures/unparser/corpus/literal/case.txt b/test/prism/fixtures/unparser/corpus/literal/case.txt
new file mode 100644
index 0000000000..c455fd7c39
--- /dev/null
+++ b/test/prism/fixtures/unparser/corpus/literal/case.txt
@@ -0,0 +1,37 @@
+case
+when bar
+ baz
+when baz
+ bar
+end
+case foo
+when bar
+when baz
+ bar
+end
+case foo
+when bar
+ baz
+when baz
+ bar
+end
+case foo
+when bar, baz
+ :other
+end
+case foo
+when *bar
+ :value
+end
+case foo
+when bar
+ baz
+else
+ :foo
+end
+case foo
+when *bar | baz
+end
+case foo
+when *bar.baz=1
+end
diff --git a/test/prism/fixtures/unparser/corpus/literal/class.txt b/test/prism/fixtures/unparser/corpus/literal/class.txt
new file mode 100644
index 0000000000..f0198625e9
--- /dev/null
+++ b/test/prism/fixtures/unparser/corpus/literal/class.txt
@@ -0,0 +1,35 @@
+class A
+end
+
+class << a
+end
+
+class << a
+ b
+end
+
+class A::B
+end
+
+class A::B::C
+end
+
+class A < B
+end
+
+class A < B::C
+end
+
+class A::B < C::D
+end
+
+class A
+ include(B.new)
+
+ def foo
+ :bar
+ end
+end
+
+class ::A
+end
diff --git a/test/prism/fixtures/unparser/corpus/literal/def.txt b/test/prism/fixtures/unparser/corpus/literal/def.txt
new file mode 100644
index 0000000000..61339bd4a6
--- /dev/null
+++ b/test/prism/fixtures/unparser/corpus/literal/def.txt
@@ -0,0 +1,134 @@
+def foo
+ a
+rescue
+ b
+else
+ c
+ensure
+ d
+end
+
+def foo
+ a rescue b
+rescue
+ b
+else
+ c
+ensure
+ d
+end
+
+def foo(bar:, baz:)
+end
+
+def foo
+end
+
+def foo
+ bar
+end
+
+def foo
+ foo
+rescue
+ bar
+ensure
+ baz
+end
+
+def foo
+ bar
+ensure
+ baz
+end
+
+def foo
+ bar
+rescue
+ baz
+end
+
+def foo(bar)
+ bar
+end
+
+def foo(bar, baz)
+ bar
+end
+
+def foo(bar = ())
+ bar
+end
+
+def foo(bar = (baz; nil))
+end
+
+def foo(bar = true)
+ bar
+end
+
+def foo(bar, baz = true)
+ bar
+end
+
+def foo(bar: 1)
+end
+
+def foo(bar: baz)
+end
+
+def foo(bar: bar())
+end
+
+def foo(*)
+ bar
+end
+
+def foo(*bar)
+ bar
+end
+
+def foo(bar, *baz)
+ bar
+end
+
+def foo(baz = true, *bor)
+ bar
+end
+
+def foo(baz = true, *bor, &block)
+ bar
+end
+
+def foo(bar, baz = true, *bor)
+ bar
+end
+
+def foo(&block)
+ bar
+end
+
+def foo(bar, &block)
+ bar
+end
+
+def foo
+ bar
+ baz
+end
+
+def f(((a)))
+end
+
+def foo(bar:, baz: "value")
+end
+
+def f
+ <<-HEREDOC
+ #{}
+ HEREDOC
+end
+
+def f
+ %()
+end
diff --git a/test/prism/fixtures/unparser/corpus/literal/defined.txt b/test/prism/fixtures/unparser/corpus/literal/defined.txt
new file mode 100644
index 0000000000..65e7c370fd
--- /dev/null
+++ b/test/prism/fixtures/unparser/corpus/literal/defined.txt
@@ -0,0 +1,3 @@
+defined?(@foo)
+defined?(Foo)
+defined?(((a, b) = [1, 2]))
diff --git a/test/prism/fixtures/unparser/corpus/literal/defs.txt b/test/prism/fixtures/unparser/corpus/literal/defs.txt
new file mode 100644
index 0000000000..b70aa9efc5
--- /dev/null
+++ b/test/prism/fixtures/unparser/corpus/literal/defs.txt
@@ -0,0 +1,40 @@
+def self.foo
+end
+
+def self.foo
+ bar
+end
+
+def self.foo
+ bar
+ baz
+end
+
+def Foo.bar
+ bar
+end
+
+def (foo { |bar|
+}).bar
+ bar
+end
+
+def (foo(1)).bar
+ bar
+end
+
+def (Foo::Bar.baz).bar
+ baz
+end
+
+def (Foo::Bar).bar
+ baz
+end
+
+def Foo.bar
+ baz
+end
+
+def foo.bar
+ baz
+end
diff --git a/test/prism/fixtures/unparser/corpus/literal/dstr.txt b/test/prism/fixtures/unparser/corpus/literal/dstr.txt
new file mode 100644
index 0000000000..8a912d28ed
--- /dev/null
+++ b/test/prism/fixtures/unparser/corpus/literal/dstr.txt
@@ -0,0 +1,37 @@
+if true
+ "#{}a"
+end
+if true
+ <<-HEREDOC
+a
+#{}a
+b
+ HEREDOC
+ x
+end
+<<-HEREDOC
+\#{}\#{}
+#{}
+#{}
+#{}
+HEREDOC
+<<-HEREDOC rescue nil
+#{}
+a
+HEREDOC
+"a#$1"
+"a#$a"
+"a#@a"
+"a#@@a"
+if true
+ return <<-HEREDOC
+ #{42}
+ HEREDOC
+end
+foo(<<-HEREDOC)
+ #{bar}
+HEREDOC
+foo(<<-HEREDOC) { |x|
+ #{bar}
+HEREDOC
+}
diff --git a/test/prism/fixtures/unparser/corpus/literal/empty.txt b/test/prism/fixtures/unparser/corpus/literal/empty.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/prism/fixtures/unparser/corpus/literal/empty.txt
diff --git a/test/prism/fixtures/unparser/corpus/literal/empty_begin.txt b/test/prism/fixtures/unparser/corpus/literal/empty_begin.txt
new file mode 100644
index 0000000000..6a452c185a
--- /dev/null
+++ b/test/prism/fixtures/unparser/corpus/literal/empty_begin.txt
@@ -0,0 +1 @@
+()
diff --git a/test/prism/fixtures/unparser/corpus/literal/flipflop.txt b/test/prism/fixtures/unparser/corpus/literal/flipflop.txt
new file mode 100644
index 0000000000..139904a53f
--- /dev/null
+++ b/test/prism/fixtures/unparser/corpus/literal/flipflop.txt
@@ -0,0 +1,10 @@
+if ((i == 4)..(i == 4))
+ foo
+end
+if ((i == 4)...(i == 4))
+ foo
+end
+if ..foo
+end
+if foo..;
+end
diff --git a/test/prism/fixtures/unparser/corpus/literal/for.txt b/test/prism/fixtures/unparser/corpus/literal/for.txt
new file mode 100644
index 0000000000..4c19a352d9
--- /dev/null
+++ b/test/prism/fixtures/unparser/corpus/literal/for.txt
@@ -0,0 +1,12 @@
+bar(for a in bar do
+ baz
+end)
+for a in bar do
+ baz
+end
+for (a, *b) in bar do
+ baz
+end
+for (a, b) in bar do
+ baz
+end
diff --git a/test/prism/fixtures/unparser/corpus/literal/hookexe.txt b/test/prism/fixtures/unparser/corpus/literal/hookexe.txt
new file mode 100644
index 0000000000..08f14f47b3
--- /dev/null
+++ b/test/prism/fixtures/unparser/corpus/literal/hookexe.txt
@@ -0,0 +1,7 @@
+BEGIN {
+ foo
+}
+bar
+END {
+ baz
+}
diff --git a/test/prism/fixtures/unparser/corpus/literal/if.txt b/test/prism/fixtures/unparser/corpus/literal/if.txt
new file mode 100644
index 0000000000..0c13801f9e
--- /dev/null
+++ b/test/prism/fixtures/unparser/corpus/literal/if.txt
@@ -0,0 +1,36 @@
+if /foo/
+ bar
+end
+if 3
+ 9
+end
+if 4
+ 5
+else
+ 6
+end
+unless 3
+ nil
+end
+unless 3
+ 9
+end
+if foo
+end
+
+module A
+ foo = bar if foo
+end
+
+module B
+ foo = bar unless foo
+end
+unless foo
+ foo = bar
+end
+if foo { |pair|
+ pair
+}
+ pair = :foo
+ foo
+end
diff --git a/test/prism/fixtures/unparser/corpus/literal/kwbegin.txt b/test/prism/fixtures/unparser/corpus/literal/kwbegin.txt
new file mode 100644
index 0000000000..6cc1e74ca6
--- /dev/null
+++ b/test/prism/fixtures/unparser/corpus/literal/kwbegin.txt
@@ -0,0 +1,80 @@
+begin
+rescue
+end
+
+begin
+ensure
+end
+
+begin
+ a
+end
+
+begin
+ a
+rescue
+ b
+end
+
+begin
+ a
+ b
+rescue
+ b
+end
+
+begin
+rescue A
+end
+
+begin
+rescue A => foo
+end
+
+begin
+ a
+rescue A
+ b
+rescue B
+ c
+ensure
+ d
+end
+
+begin
+ begin
+ foo
+ bar
+ rescue
+ end
+rescue
+ baz
+ bar
+end
+
+begin
+ raise(Exception) rescue foo = bar
+rescue Exception
+end
+
+begin
+ foo
+rescue => bar
+ bar
+end
+
+begin
+ foo
+rescue Exception, Other => bar
+ bar
+end
+
+begin
+ bar
+rescue SomeError, *bar => exception
+ baz
+end
+
+class << self
+ undef :bar rescue nil
+end
diff --git a/test/prism/fixtures/unparser/corpus/literal/lambda.txt b/test/prism/fixtures/unparser/corpus/literal/lambda.txt
new file mode 100644
index 0000000000..4eb722dad1
--- /dev/null
+++ b/test/prism/fixtures/unparser/corpus/literal/lambda.txt
@@ -0,0 +1,13 @@
+lambda {
+}
+lambda { |a, b|
+ a
+}
+->() {
+}
+->(a) {
+}
+->(a, b) {
+}
+->(a, b; c) {
+}
diff --git a/test/prism/fixtures/unparser/corpus/literal/literal.txt b/test/prism/fixtures/unparser/corpus/literal/literal.txt
new file mode 100644
index 0000000000..2fc7cd1d79
--- /dev/null
+++ b/test/prism/fixtures/unparser/corpus/literal/literal.txt
@@ -0,0 +1,91 @@
+{ "foo" => <<-HEREDOC, "bar" => :baz }
+ #{}
+HEREDOC
+{ "foo" => %(), "bar" => :baz }
+["foo", %()]
+a(<<-HEREDOC).a
+ #{}
+HEREDOC
+a(%()).a
+{ "foo" => <<-HEREDOC, **baz }
+ #{}
+HEREDOC
+{ "foo" => %(), **baz }
+"#@a #@@a #$a"
+0
+++1
+1
+1
+1r
+1.5r
+1.3r
+5i
+-5i
+0.6i
+-0.6i
+1000000000000000000000000000000i
+1ri
+"foo" "bar"
+"foobar #{baz}"
+"foo#{1}bar"
+"\\\\#{}"
+"#{}\#{}"
+"\#{}#{}"
+"foo\\\#{@bar}"
+"\""
+"foo bar"
+"foo\nbar"
+`foo`
+`foo#{@bar}`
+`)`
+`\``
+`"`
+:foo
+:"A B"
+:foo
+:"A B"
+:"A\"B"
+:""
+/foo/
+/[^-+',.\/:@[:alnum:]\[\]]+/
+/foo#{@bar}/
+/foo#{@bar}/imx
+/#{"\u0000"}/
+/\n/
+/\n/
+/\n/x
+/\/\//x
+:"foo#{bar}baz"
+:"#{"foo"}"
+(0.0 / 0.0)..1
+1..(0.0 / 0.0)
+(0.0 / 0.0)..100
+-0.1
+0.1
+[1, 2]
+[1, (), n2]
+[1]
+[]
+[1, *@foo]
+[*@foo, 1]
+[*@foo, *@baz]
+{}
+{ () => () }
+{ 1 => 2 }
+{ 1 => 2, 3 => 4 }
+{ a: (1 rescue foo), b: 2 }
+{ a: 1, b: 2 }
+{ a: :a }
+{ :"a b" => 1 }
+{ :-@ => 1 }
+"#{}
+#{}\na"
+foo {
+ "#{}
+#{}\na"
+}
+:"a\\
+b"
+` x
+#{foo}
+#`
diff --git a/test/prism/fixtures/unparser/corpus/literal/module.txt b/test/prism/fixtures/unparser/corpus/literal/module.txt
new file mode 100644
index 0000000000..cec03f3bfd
--- /dev/null
+++ b/test/prism/fixtures/unparser/corpus/literal/module.txt
@@ -0,0 +1,16 @@
+module A
+end
+
+module A::B
+end
+
+module A::B::C
+end
+
+module A
+ include(B.new)
+
+ def foo
+ :bar
+ end
+end
diff --git a/test/prism/fixtures/unparser/corpus/literal/opasgn.txt b/test/prism/fixtures/unparser/corpus/literal/opasgn.txt
new file mode 100644
index 0000000000..5858d773d0
--- /dev/null
+++ b/test/prism/fixtures/unparser/corpus/literal/opasgn.txt
@@ -0,0 +1,24 @@
+a += 2
+a -= 2
+a **= 2
+a *= 2
+a /= 2
+a &&= b
+a ||= 2
+(a ||= 2).bar
+(h ||= {})[k] = v
+a.b += 2
+a.b -= 2
+a.b **= 2
+a.b *= 2
+a.b /= 2
+a.b &&= b
+a.b ||= 2
+a[b] += 2
+a[b] -= 2
+a[b] **= 2
+a[b] *= 2
+a[b] /= 2
+a[b] &&= b
+a[b] ||= 2
+foo.A += 1
diff --git a/test/prism/fixtures/unparser/corpus/literal/pattern.txt b/test/prism/fixtures/unparser/corpus/literal/pattern.txt
new file mode 100644
index 0000000000..7cfaa4dc67
--- /dev/null
+++ b/test/prism/fixtures/unparser/corpus/literal/pattern.txt
@@ -0,0 +1,41 @@
+case foo
+in A[1, 2, *a, 3] then
+ true
+in [1, 2, ] then
+ y
+in A(x:) then
+ true
+in {**a} then
+ true
+in {} if true then
+ true
+in [x, y, *] then
+ true
+in {a: 1, aa: 2} then
+ true
+in {} then
+ true
+in {**nil} then
+ true
+in {"a": 1} then
+ true
+in 1 | 2 then
+ true
+in 1 => a then
+ true
+in ^x then
+ true
+in 1
+in 2 then
+ true
+else
+ true
+end
+case foo
+in A[1, 2, *a, 3]
+end
+case foo
+in A
+else
+end
+1 in [a]
diff --git a/test/prism/fixtures/unparser/corpus/literal/pragma.txt b/test/prism/fixtures/unparser/corpus/literal/pragma.txt
new file mode 100644
index 0000000000..4f6dd71b38
--- /dev/null
+++ b/test/prism/fixtures/unparser/corpus/literal/pragma.txt
@@ -0,0 +1,4 @@
+__ENCODING__
+__FILE__
+__LINE__
+__dir__
diff --git a/test/prism/fixtures/unparser/corpus/literal/range.txt b/test/prism/fixtures/unparser/corpus/literal/range.txt
new file mode 100644
index 0000000000..eb1f3874c0
--- /dev/null
+++ b/test/prism/fixtures/unparser/corpus/literal/range.txt
@@ -0,0 +1,4 @@
+(1..)
+1..2
+(1...)
+1...2
diff --git a/test/prism/fixtures/unparser/corpus/literal/rescue.txt b/test/prism/fixtures/unparser/corpus/literal/rescue.txt
new file mode 100644
index 0000000000..a787816808
--- /dev/null
+++ b/test/prism/fixtures/unparser/corpus/literal/rescue.txt
@@ -0,0 +1,3 @@
+foo rescue bar
+foo rescue return bar
+x = (foo rescue return bar)
diff --git a/test/prism/fixtures/unparser/corpus/literal/send.txt b/test/prism/fixtures/unparser/corpus/literal/send.txt
new file mode 100644
index 0000000000..1e9c2a94be
--- /dev/null
+++ b/test/prism/fixtures/unparser/corpus/literal/send.txt
@@ -0,0 +1,84 @@
+module A
+ foo ||= ((a, _) = b)
+end
+
+module A
+ local = 1
+ local.bar
+end
+class A
+end.bar
+module A
+end.bar
+begin
+rescue
+end.bar
+case (def foo
+end; :bar)
+when bar
+end.baz
+case foo
+when bar
+end.baz
+class << self
+end.bar
+def self.foo
+end.bar
+def foo
+end.bar
+until foo
+end.bar
+while foo
+end.bar
+loop {
+}.bar
+if foo
+end.baz
+(/bar/ =~ :foo).foo
+(1..2).max
+(foo =~ /bar/).foo
+/bar/ =~ :foo
+/bar/ =~ foo
+1..2.max
+A.foo
+FOO()
+a&.b
+a.foo
+foo
+foo << (bar * baz)
+foo =~ /bar/
+foo(&(foo || bar))
+foo(&block)
+foo(*args, &block)
+foo(*arguments)
+foo(1, 2)
+foo(bar)
+foo(bar, *args)
+foo(foo =~ /bar/)
+foo.bar(&baz)
+foo.bar(*arga, foo, *argb)
+foo.bar(*args)
+foo.bar(*args, foo)
+foo.bar(:baz, &baz)
+foo.bar(baz: boz)
+foo.bar(foo, "baz" => boz)
+foo.bar(foo, *args)
+foo.bar(foo, *args, &block)
+foo.bar(foo, {})
+foo.bar({ foo: boz }, boz)
+foo.bar=:baz
+foo(a: b)
+foo.&(a: b)
+foo.&(**a)
+foo[*baz]
+foo[1, 2]
+foo[]
+self.foo
+self.foo=:bar
+(a + b) / (c - d)
+(a + b) / c.-(e, f)
+(a + b) / c.-(*f)
+x(**foo)
+foo&.!
+foo.~(b)
+a&.+(b)
diff --git a/test/prism/fixtures/unparser/corpus/literal/since/27.txt b/test/prism/fixtures/unparser/corpus/literal/since/27.txt
new file mode 100644
index 0000000000..c332f9e48e
--- /dev/null
+++ b/test/prism/fixtures/unparser/corpus/literal/since/27.txt
@@ -0,0 +1,4 @@
+-> {
+ _1 + _2
+}
+(..1)
diff --git a/test/prism/fixtures/unparser/corpus/literal/since/30.txt b/test/prism/fixtures/unparser/corpus/literal/since/30.txt
new file mode 100644
index 0000000000..b73328a4b0
--- /dev/null
+++ b/test/prism/fixtures/unparser/corpus/literal/since/30.txt
@@ -0,0 +1,4 @@
+1 => [a]
+1 => [*]
+1 in [*, 42, *]
+1 in [*, a, *foo]
diff --git a/test/prism/fixtures/unparser/corpus/literal/since/31.txt b/test/prism/fixtures/unparser/corpus/literal/since/31.txt
new file mode 100644
index 0000000000..504eb94d5b
--- /dev/null
+++ b/test/prism/fixtures/unparser/corpus/literal/since/31.txt
@@ -0,0 +1,7 @@
+def foo(&)
+ bar(&)
+end
+
+def foo(a, &)
+ bar(&)
+end
diff --git a/test/prism/fixtures/unparser/corpus/literal/since/32.txt b/test/prism/fixtures/unparser/corpus/literal/since/32.txt
new file mode 100644
index 0000000000..b8e096d8fc
--- /dev/null
+++ b/test/prism/fixtures/unparser/corpus/literal/since/32.txt
@@ -0,0 +1,11 @@
+def foo(argument, **)
+ bar(argument, **)
+end
+
+def foo(argument, *)
+ bar(argument, *)
+end
+
+def foo(**)
+ { default: 1, ** }
+end
diff --git a/test/prism/fixtures/unparser/corpus/literal/singletons.txt b/test/prism/fixtures/unparser/corpus/literal/singletons.txt
new file mode 100644
index 0000000000..496e6a41ce
--- /dev/null
+++ b/test/prism/fixtures/unparser/corpus/literal/singletons.txt
@@ -0,0 +1,4 @@
+false
+nil
+self
+true
diff --git a/test/prism/fixtures/unparser/corpus/literal/super.txt b/test/prism/fixtures/unparser/corpus/literal/super.txt
new file mode 100644
index 0000000000..0e73e6f052
--- /dev/null
+++ b/test/prism/fixtures/unparser/corpus/literal/super.txt
@@ -0,0 +1,21 @@
+super
+super()
+super(a)
+super(a, b)
+super(&block)
+super(a, &block)
+super(a {
+ foo
+})
+super {
+ foo
+}
+super(a) {
+ foo
+}
+super() {
+ foo
+}
+super(a, b) {
+ foo
+}
diff --git a/test/prism/fixtures/unparser/corpus/literal/unary.txt b/test/prism/fixtures/unparser/corpus/literal/unary.txt
new file mode 100644
index 0000000000..6992d86bb0
--- /dev/null
+++ b/test/prism/fixtures/unparser/corpus/literal/unary.txt
@@ -0,0 +1,9 @@
+!1
+!(!1)
+!(!(foo || bar))
+!(!1).baz
+~a
+-a
++a
+-(-a).foo
++(+a).foo
diff --git a/test/prism/fixtures/unparser/corpus/literal/undef.txt b/test/prism/fixtures/unparser/corpus/literal/undef.txt
new file mode 100644
index 0000000000..a65d8d0cc4
--- /dev/null
+++ b/test/prism/fixtures/unparser/corpus/literal/undef.txt
@@ -0,0 +1,2 @@
+undef :foo
+undef :foo, :bar
diff --git a/test/prism/fixtures/unparser/corpus/literal/variables.txt b/test/prism/fixtures/unparser/corpus/literal/variables.txt
new file mode 100644
index 0000000000..1de938f376
--- /dev/null
+++ b/test/prism/fixtures/unparser/corpus/literal/variables.txt
@@ -0,0 +1,10 @@
+a
+@a
+@@a
+$a
+$1
+$`
+CONST
+SCOPED::CONST
+::TOPLEVEL
+::TOPLEVEL::CONST
diff --git a/test/prism/fixtures/unparser/corpus/literal/while.txt b/test/prism/fixtures/unparser/corpus/literal/while.txt
new file mode 100644
index 0000000000..19a60ef5ff
--- /dev/null
+++ b/test/prism/fixtures/unparser/corpus/literal/while.txt
@@ -0,0 +1,73 @@
+module A
+ foo { |bar|
+ while foo
+ foo = bar
+ end
+ }
+end
+
+def foo
+ foo = bar while foo != baz
+end
+
+module A
+ foo = bar while foo
+end
+
+module A
+ foo = bar until foo
+end
+
+module A
+ while foo
+ foo = bar
+ end
+end
+
+module A
+ each { |baz|
+ while foo
+ foo = bar
+ end
+ }
+end
+
+module A
+ each { |foo|
+ while foo
+ foo = bar
+ end
+ }
+end
+x = (begin
+ foo
+end while baz)
+begin
+ foo
+end while baz
+begin
+ foo
+ bar
+end until baz
+begin
+ foo
+ bar
+end while baz
+while false
+end
+while false
+ 3
+end
+while (foo {
+})
+ :body
+end
+until false
+end
+until false
+ 3
+end
+until (foo {
+})
+ :body
+end
diff --git a/test/prism/fixtures/unparser/corpus/semantic/and.txt b/test/prism/fixtures/unparser/corpus/semantic/and.txt
new file mode 100644
index 0000000000..43d1712445
--- /dev/null
+++ b/test/prism/fixtures/unparser/corpus/semantic/and.txt
@@ -0,0 +1,8 @@
+a...b or c...d
+a...b and c...d
+
+if a...b or c...d
+end
+
+if a...b and c...d
+end
diff --git a/test/prism/fixtures/unparser/corpus/semantic/block.txt b/test/prism/fixtures/unparser/corpus/semantic/block.txt
new file mode 100644
index 0000000000..5891690025
--- /dev/null
+++ b/test/prism/fixtures/unparser/corpus/semantic/block.txt
@@ -0,0 +1,26 @@
+foo do
+end
+
+foo do
+rescue
+end
+
+foo do
+ nil rescue nil
+ nil
+end
+
+foo do |a|
+end
+
+foo(<<-DOC) do |a|
+ b
+DOC
+ a
+end
+
+foo(<<-DOC) do
+ b
+DOC
+ a
+end
diff --git a/test/prism/fixtures/unparser/corpus/semantic/def.txt b/test/prism/fixtures/unparser/corpus/semantic/def.txt
new file mode 100644
index 0000000000..7574619392
--- /dev/null
+++ b/test/prism/fixtures/unparser/corpus/semantic/def.txt
@@ -0,0 +1,7 @@
+def foo
+ (a - b)
+end
+
+def foo
+ a rescue Exception
+end
diff --git a/test/prism/fixtures/unparser/corpus/semantic/dstr.txt b/test/prism/fixtures/unparser/corpus/semantic/dstr.txt
new file mode 100644
index 0000000000..919e736077
--- /dev/null
+++ b/test/prism/fixtures/unparser/corpus/semantic/dstr.txt
@@ -0,0 +1,127 @@
+<<DOC
+DOC
+
+<<'DOC'
+DOC
+
+<<~DOC
+DOC
+
+<<~'DOC'
+DOC
+
+<<DOC
+ a
+DOC
+
+<<'DOC'
+ a
+DOC
+
+<<DOC
+ a
+ #{}
+DOC
+
+<<~DOC
+ a
+ #{}
+DOC
+
+<<~DOC
+ a
+ #{}
+ b
+DOC
+
+<<~DOC
+ a
+ b
+DOC
+
+<<'DOC'
+a
+
+b
+DOC
+
+<<'DOC'
+ a
+
+ b
+DOC
+
+<<'DOC'
+ a\nb
+DOC
+
+<<DOC
+#{}a
+ #{}a
+DOC
+
+<<DOC
+ #{}
+ \#{}
+DOC
+
+<<DOC
+ a#{}b
+ c
+DOC
+
+<<~DOC
+ #{}
+DOC
+
+if true
+ <<~DOC
+ #{}
+ DOC
+end
+
+if true
+ <<~DOC
+ b#{}
+ DOC
+end
+
+if true
+ <<~DOC
+ #{}a
+ DOC
+end
+
+if true
+ <<-'DOC'
+ a
+
+ b
+ DOC
+end
+
+"#{}a"
+
+%(\n"#{}"\n)
+
+%Q(-\n"#{}"\n)
+
+"a
+#{}
+b"
+
+"a\n#{}
+b"
+
+"a
+#{}\nb"
+
+'a' \
+"#{}"
+
+"" "" ""
+
+"a#{@a}" "b"
+"a#@a" "b"
+"a#$a" "b"
+"a#@@a" "b"
diff --git a/test/prism/fixtures/unparser/corpus/semantic/kwbegin.txt b/test/prism/fixtures/unparser/corpus/semantic/kwbegin.txt
new file mode 100644
index 0000000000..d275a96a5c
--- /dev/null
+++ b/test/prism/fixtures/unparser/corpus/semantic/kwbegin.txt
@@ -0,0 +1,42 @@
+begin
+rescue
+end
+
+begin
+rescue
+else
+end
+
+begin
+ a
+end
+
+begin
+ a
+rescue
+ b
+end
+
+begin
+ a
+ b
+rescue
+ b
+end
+
+begin
+rescue A
+else
+end
+
+begin; rescue A; else; end
+
+begin
+ a
+rescue A
+ b
+rescue B
+ c
+ensure
+ d
+end
diff --git a/test/prism/fixtures/unparser/corpus/semantic/literal.txt b/test/prism/fixtures/unparser/corpus/semantic/literal.txt
new file mode 100644
index 0000000000..c424db5a53
--- /dev/null
+++ b/test/prism/fixtures/unparser/corpus/semantic/literal.txt
@@ -0,0 +1,14 @@
+1.0r
+-0r
+0x1
+1_000
+1e10
+10e10000000000
+-10e10000000000
+?c
+%r(/)
+%r(\))
+%r(#{@bar}baz)
+10.2e10000000000
+-10.2e10000000000
+w(foo bar)
diff --git a/test/prism/fixtures/unparser/corpus/semantic/opasgn.txt b/test/prism/fixtures/unparser/corpus/semantic/opasgn.txt
new file mode 100644
index 0000000000..8b4bc5d239
--- /dev/null
+++ b/test/prism/fixtures/unparser/corpus/semantic/opasgn.txt
@@ -0,0 +1 @@
+y["#{42}\n"] += "#{42}\n"
diff --git a/test/prism/fixtures/unparser/corpus/semantic/send.txt b/test/prism/fixtures/unparser/corpus/semantic/send.txt
new file mode 100644
index 0000000000..a65b27d2f2
--- /dev/null
+++ b/test/prism/fixtures/unparser/corpus/semantic/send.txt
@@ -0,0 +1,6 @@
+foo
+foo(1)
+
+a.===(b).c == d
+
+a == d.c.===(c)
diff --git a/test/prism/fixtures/unparser/corpus/semantic/undef.txt b/test/prism/fixtures/unparser/corpus/semantic/undef.txt
new file mode 100644
index 0000000000..47debc3114
--- /dev/null
+++ b/test/prism/fixtures/unparser/corpus/semantic/undef.txt
@@ -0,0 +1,2 @@
+undef foo
+undef foo, bar
diff --git a/test/prism/fixtures/unparser/corpus/semantic/while.txt b/test/prism/fixtures/unparser/corpus/semantic/while.txt
new file mode 100644
index 0000000000..a55dcc52fc
--- /dev/null
+++ b/test/prism/fixtures/unparser/corpus/semantic/while.txt
@@ -0,0 +1,25 @@
+a until b? {}
+
+until b? {}
+ a
+end
+
+foo = bar while foo
+
+a until b && a { }
+
+while a = b
+ a
+end
+
+a until b(<<-FOO) do
+FOO
+ c
+end
+
+module A
+ foo = exp
+ while foo
+ foo = bar
+ end
+end
diff --git a/test/prism/fixtures/until.txt b/test/prism/fixtures/until.txt
new file mode 100644
index 0000000000..652fc8c5a7
--- /dev/null
+++ b/test/prism/fixtures/until.txt
@@ -0,0 +1,13 @@
+until true; 1; end
+
+1 until true
+
+tap { break until true }
+
+tap { next until true }
+
+return until true
+
+foo :a, :b until bar?
+
+foo while bar in baz
diff --git a/test/prism/fixtures/variables.txt b/test/prism/fixtures/variables.txt
new file mode 100644
index 0000000000..1545c30c80
--- /dev/null
+++ b/test/prism/fixtures/variables.txt
@@ -0,0 +1,47 @@
+@@abc
+
+@@abc = 1
+
+@@foo, @@bar = 1
+
+@@foo = 1, 2
+
+$abc = 1
+
+$abc
+
+@abc
+
+@abc = 1
+
+a
+
+abc = 1
+
+$foo, $bar = 1
+
+$foo = 1, 2
+
+@foo, @bar = 1
+
+@foo = 1, 2
+
+foo = 1; foo = 1, 2
+
+foo = 1, 2
+
+foo, * = 1, 2
+
+foo, = 1, 2
+
+foo, *bar = 1, 2
+
+foo, (bar, baz) = 1, [2, 3]
+
+foo = *bar
+
+Foo = 1, 2
+
+(a; b; c)
+
+a, (b, c), d = []
diff --git a/test/prism/fixtures/while.txt b/test/prism/fixtures/while.txt
new file mode 100644
index 0000000000..b776f755ee
--- /dev/null
+++ b/test/prism/fixtures/while.txt
@@ -0,0 +1,23 @@
+while true; 1; end
+
+1 while true
+
+tap { break while true }
+
+tap { next while true }
+
+return while true
+
+foo :a, :b while bar?
+
+tap { while def self.foo a = tap do end; end; break; end }
+
+tap { while class Foo a = tap do end; end; break; end }
+
+tap { while class << self; tap do end; end; break; end }
+
+tap { while class << self; a = tap do end; end; break; end }
+
+while def foo = bar do end; end
+
+foo while bar in baz
diff --git a/test/prism/fixtures/whitequark/LICENSE b/test/prism/fixtures/whitequark/LICENSE
new file mode 100644
index 0000000000..971310e3d6
--- /dev/null
+++ b/test/prism/fixtures/whitequark/LICENSE
@@ -0,0 +1,25 @@
+Copyright (c) 2013-2016 whitequark <whitequark@whitequark.org>
+
+Parts of the source are derived from ruby_parser:
+Copyright (c) Ryan Davis, seattle.rb
+
+MIT License
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/test/prism/fixtures/whitequark/__ENCODING__.txt b/test/prism/fixtures/whitequark/__ENCODING__.txt
new file mode 100644
index 0000000000..d6debf2f92
--- /dev/null
+++ b/test/prism/fixtures/whitequark/__ENCODING__.txt
@@ -0,0 +1 @@
+__ENCODING__
diff --git a/test/prism/fixtures/whitequark/__ENCODING___legacy_.txt b/test/prism/fixtures/whitequark/__ENCODING___legacy_.txt
new file mode 100644
index 0000000000..d6debf2f92
--- /dev/null
+++ b/test/prism/fixtures/whitequark/__ENCODING___legacy_.txt
@@ -0,0 +1 @@
+__ENCODING__
diff --git a/test/prism/fixtures/whitequark/alias.txt b/test/prism/fixtures/whitequark/alias.txt
new file mode 100644
index 0000000000..e33b120022
--- /dev/null
+++ b/test/prism/fixtures/whitequark/alias.txt
@@ -0,0 +1 @@
+alias :foo bar
diff --git a/test/prism/fixtures/whitequark/alias_gvar.txt b/test/prism/fixtures/whitequark/alias_gvar.txt
new file mode 100644
index 0000000000..b975d97f8e
--- /dev/null
+++ b/test/prism/fixtures/whitequark/alias_gvar.txt
@@ -0,0 +1,3 @@
+alias $a $+
+
+alias $a $b
diff --git a/test/prism/fixtures/whitequark/ambiuous_quoted_label_in_ternary_operator.txt b/test/prism/fixtures/whitequark/ambiuous_quoted_label_in_ternary_operator.txt
new file mode 100644
index 0000000000..9b2e3afad5
--- /dev/null
+++ b/test/prism/fixtures/whitequark/ambiuous_quoted_label_in_ternary_operator.txt
@@ -0,0 +1 @@
+a ? b & '': nil
diff --git a/test/prism/fixtures/whitequark/and.txt b/test/prism/fixtures/whitequark/and.txt
new file mode 100644
index 0000000000..43fa6a65cd
--- /dev/null
+++ b/test/prism/fixtures/whitequark/and.txt
@@ -0,0 +1,3 @@
+foo && bar
+
+foo and bar
diff --git a/test/prism/fixtures/whitequark/and_asgn.txt b/test/prism/fixtures/whitequark/and_asgn.txt
new file mode 100644
index 0000000000..a979265914
--- /dev/null
+++ b/test/prism/fixtures/whitequark/and_asgn.txt
@@ -0,0 +1,3 @@
+foo.a &&= 1
+
+foo[0, 1] &&= 2
diff --git a/test/prism/fixtures/whitequark/and_or_masgn.txt b/test/prism/fixtures/whitequark/and_or_masgn.txt
new file mode 100644
index 0000000000..e346041604
--- /dev/null
+++ b/test/prism/fixtures/whitequark/and_or_masgn.txt
@@ -0,0 +1,3 @@
+foo && (a, b = bar)
+
+foo || (a, b = bar)
diff --git a/test/prism/fixtures/whitequark/anonymous_blockarg.txt b/test/prism/fixtures/whitequark/anonymous_blockarg.txt
new file mode 100644
index 0000000000..e3eaaad6ce
--- /dev/null
+++ b/test/prism/fixtures/whitequark/anonymous_blockarg.txt
@@ -0,0 +1 @@
+def foo(&); bar(&); end
diff --git a/test/prism/fixtures/whitequark/arg.txt b/test/prism/fixtures/whitequark/arg.txt
new file mode 100644
index 0000000000..b1984ad5c4
--- /dev/null
+++ b/test/prism/fixtures/whitequark/arg.txt
@@ -0,0 +1,3 @@
+def f(foo); end
+
+def f(foo, bar); end
diff --git a/test/prism/fixtures/whitequark/arg_duplicate_ignored.txt b/test/prism/fixtures/whitequark/arg_duplicate_ignored.txt
new file mode 100644
index 0000000000..0f5cc33961
--- /dev/null
+++ b/test/prism/fixtures/whitequark/arg_duplicate_ignored.txt
@@ -0,0 +1,3 @@
+def foo(_, _); end
+
+def foo(_a, _a); end
diff --git a/test/prism/fixtures/whitequark/arg_label.txt b/test/prism/fixtures/whitequark/arg_label.txt
new file mode 100644
index 0000000000..82db416cb4
--- /dev/null
+++ b/test/prism/fixtures/whitequark/arg_label.txt
@@ -0,0 +1,6 @@
+def foo
+ a:b end
+
+def foo() a:b end
+
+f { || a:b }
diff --git a/test/prism/fixtures/whitequark/arg_scope.txt b/test/prism/fixtures/whitequark/arg_scope.txt
new file mode 100644
index 0000000000..6c67ab72e3
--- /dev/null
+++ b/test/prism/fixtures/whitequark/arg_scope.txt
@@ -0,0 +1 @@
+lambda{|;a|a}
diff --git a/test/prism/fixtures/whitequark/args.txt b/test/prism/fixtures/whitequark/args.txt
new file mode 100644
index 0000000000..773be477d3
--- /dev/null
+++ b/test/prism/fixtures/whitequark/args.txt
@@ -0,0 +1,63 @@
+def f &b; end
+
+def f (((a))); end
+
+def f ((*)); end
+
+def f ((*, p)); end
+
+def f ((*r)); end
+
+def f ((*r, p)); end
+
+def f ((a, *)); end
+
+def f ((a, *, p)); end
+
+def f ((a, *r)); end
+
+def f ((a, *r, p)); end
+
+def f ((a, a1)); end
+
+def f (foo: 1, &b); end
+
+def f (foo: 1, bar: 2, **baz, &b); end
+
+def f **baz, &b; end
+
+def f *, **; end
+
+def f *r, &b; end
+
+def f *r, p, &b; end
+
+def f ; end
+
+def f a, &b; end
+
+def f a, *r, &b; end
+
+def f a, *r, p, &b; end
+
+def f a, o=1, &b; end
+
+def f a, o=1, *r, &b; end
+
+def f a, o=1, *r, p, &b; end
+
+def f a, o=1, p, &b; end
+
+def f foo:
+; end
+
+def f foo: -1
+; end
+
+def f o=1, &b; end
+
+def f o=1, *r, &b; end
+
+def f o=1, *r, p, &b; end
+
+def f o=1, p, &b; end
diff --git a/test/prism/fixtures/whitequark/args_args_assocs.txt b/test/prism/fixtures/whitequark/args_args_assocs.txt
new file mode 100644
index 0000000000..445f899442
--- /dev/null
+++ b/test/prism/fixtures/whitequark/args_args_assocs.txt
@@ -0,0 +1,3 @@
+fun(foo, :foo => 1)
+
+fun(foo, :foo => 1, &baz)
diff --git a/test/prism/fixtures/whitequark/args_args_assocs_comma.txt b/test/prism/fixtures/whitequark/args_args_assocs_comma.txt
new file mode 100644
index 0000000000..b566a59037
--- /dev/null
+++ b/test/prism/fixtures/whitequark/args_args_assocs_comma.txt
@@ -0,0 +1 @@
+foo[bar, :baz => 1,]
diff --git a/test/prism/fixtures/whitequark/args_args_comma.txt b/test/prism/fixtures/whitequark/args_args_comma.txt
new file mode 100644
index 0000000000..80770716dd
--- /dev/null
+++ b/test/prism/fixtures/whitequark/args_args_comma.txt
@@ -0,0 +1 @@
+foo[bar,]
diff --git a/test/prism/fixtures/whitequark/args_args_star.txt b/test/prism/fixtures/whitequark/args_args_star.txt
new file mode 100644
index 0000000000..d4dc9cc579
--- /dev/null
+++ b/test/prism/fixtures/whitequark/args_args_star.txt
@@ -0,0 +1,3 @@
+fun(foo, *bar)
+
+fun(foo, *bar, &baz)
diff --git a/test/prism/fixtures/whitequark/args_assocs_comma.txt b/test/prism/fixtures/whitequark/args_assocs_comma.txt
new file mode 100644
index 0000000000..15e5cd65dc
--- /dev/null
+++ b/test/prism/fixtures/whitequark/args_assocs_comma.txt
@@ -0,0 +1 @@
+foo[:baz => 1,]
diff --git a/test/prism/fixtures/whitequark/args_block_pass.txt b/test/prism/fixtures/whitequark/args_block_pass.txt
new file mode 100644
index 0000000000..35d7d23885
--- /dev/null
+++ b/test/prism/fixtures/whitequark/args_block_pass.txt
@@ -0,0 +1 @@
+fun(&bar)
diff --git a/test/prism/fixtures/whitequark/args_cmd.txt b/test/prism/fixtures/whitequark/args_cmd.txt
new file mode 100644
index 0000000000..dd0c8891d0
--- /dev/null
+++ b/test/prism/fixtures/whitequark/args_cmd.txt
@@ -0,0 +1 @@
+fun(f bar)
diff --git a/test/prism/fixtures/whitequark/args_star.txt b/test/prism/fixtures/whitequark/args_star.txt
new file mode 100644
index 0000000000..ce1e6f8465
--- /dev/null
+++ b/test/prism/fixtures/whitequark/args_star.txt
@@ -0,0 +1,3 @@
+fun(*bar)
+
+fun(*bar, &baz)
diff --git a/test/prism/fixtures/whitequark/array_assocs.txt b/test/prism/fixtures/whitequark/array_assocs.txt
new file mode 100644
index 0000000000..fcecfcdefc
--- /dev/null
+++ b/test/prism/fixtures/whitequark/array_assocs.txt
@@ -0,0 +1,3 @@
+[ 1 => 2 ]
+
+[ 1, 2 => 3 ]
diff --git a/test/prism/fixtures/whitequark/array_plain.txt b/test/prism/fixtures/whitequark/array_plain.txt
new file mode 100644
index 0000000000..44e2ace7e5
--- /dev/null
+++ b/test/prism/fixtures/whitequark/array_plain.txt
@@ -0,0 +1 @@
+[1, 2]
diff --git a/test/prism/fixtures/whitequark/array_splat.txt b/test/prism/fixtures/whitequark/array_splat.txt
new file mode 100644
index 0000000000..144c1eb124
--- /dev/null
+++ b/test/prism/fixtures/whitequark/array_splat.txt
@@ -0,0 +1,5 @@
+[*foo]
+
+[1, *foo, 2]
+
+[1, *foo]
diff --git a/test/prism/fixtures/whitequark/array_symbols.txt b/test/prism/fixtures/whitequark/array_symbols.txt
new file mode 100644
index 0000000000..a9f9df0404
--- /dev/null
+++ b/test/prism/fixtures/whitequark/array_symbols.txt
@@ -0,0 +1 @@
+%i[foo bar]
diff --git a/test/prism/fixtures/whitequark/array_symbols_empty.txt b/test/prism/fixtures/whitequark/array_symbols_empty.txt
new file mode 100644
index 0000000000..da3a89ee9b
--- /dev/null
+++ b/test/prism/fixtures/whitequark/array_symbols_empty.txt
@@ -0,0 +1,3 @@
+%I()
+
+%i[]
diff --git a/test/prism/fixtures/whitequark/array_symbols_interp.txt b/test/prism/fixtures/whitequark/array_symbols_interp.txt
new file mode 100644
index 0000000000..d4950d0c05
--- /dev/null
+++ b/test/prism/fixtures/whitequark/array_symbols_interp.txt
@@ -0,0 +1,3 @@
+%I[foo #{bar}]
+
+%I[foo#{bar}]
diff --git a/test/prism/fixtures/whitequark/array_words.txt b/test/prism/fixtures/whitequark/array_words.txt
new file mode 100644
index 0000000000..a07380cadc
--- /dev/null
+++ b/test/prism/fixtures/whitequark/array_words.txt
@@ -0,0 +1 @@
+%w[foo bar]
diff --git a/test/prism/fixtures/whitequark/array_words_empty.txt b/test/prism/fixtures/whitequark/array_words_empty.txt
new file mode 100644
index 0000000000..7568263f4a
--- /dev/null
+++ b/test/prism/fixtures/whitequark/array_words_empty.txt
@@ -0,0 +1,3 @@
+%W()
+
+%w[]
diff --git a/test/prism/fixtures/whitequark/array_words_interp.txt b/test/prism/fixtures/whitequark/array_words_interp.txt
new file mode 100644
index 0000000000..1460f7dc03
--- /dev/null
+++ b/test/prism/fixtures/whitequark/array_words_interp.txt
@@ -0,0 +1,3 @@
+%W[foo #{bar}]
+
+%W[foo #{bar}foo#@baz]
diff --git a/test/prism/fixtures/whitequark/asgn_cmd.txt b/test/prism/fixtures/whitequark/asgn_cmd.txt
new file mode 100644
index 0000000000..81f8cc1c8d
--- /dev/null
+++ b/test/prism/fixtures/whitequark/asgn_cmd.txt
@@ -0,0 +1,3 @@
+foo = bar = m foo
+
+foo = m foo
diff --git a/test/prism/fixtures/whitequark/asgn_mrhs.txt b/test/prism/fixtures/whitequark/asgn_mrhs.txt
new file mode 100644
index 0000000000..f0b0055e55
--- /dev/null
+++ b/test/prism/fixtures/whitequark/asgn_mrhs.txt
@@ -0,0 +1,5 @@
+foo = *bar
+
+foo = bar, 1
+
+foo = baz, *bar
diff --git a/test/prism/fixtures/whitequark/back_ref.txt b/test/prism/fixtures/whitequark/back_ref.txt
new file mode 100644
index 0000000000..03166e10ee
--- /dev/null
+++ b/test/prism/fixtures/whitequark/back_ref.txt
@@ -0,0 +1 @@
+$+
diff --git a/test/prism/fixtures/whitequark/bang.txt b/test/prism/fixtures/whitequark/bang.txt
new file mode 100644
index 0000000000..6cf9410cf5
--- /dev/null
+++ b/test/prism/fixtures/whitequark/bang.txt
@@ -0,0 +1 @@
+!foo
diff --git a/test/prism/fixtures/whitequark/bang_cmd.txt b/test/prism/fixtures/whitequark/bang_cmd.txt
new file mode 100644
index 0000000000..0a5252c001
--- /dev/null
+++ b/test/prism/fixtures/whitequark/bang_cmd.txt
@@ -0,0 +1 @@
+!m foo
diff --git a/test/prism/fixtures/whitequark/begin_cmdarg.txt b/test/prism/fixtures/whitequark/begin_cmdarg.txt
new file mode 100644
index 0000000000..a5873668e9
--- /dev/null
+++ b/test/prism/fixtures/whitequark/begin_cmdarg.txt
@@ -0,0 +1 @@
+p begin 1.times do 1 end end
diff --git a/test/prism/fixtures/whitequark/beginless_erange_after_newline.txt b/test/prism/fixtures/whitequark/beginless_erange_after_newline.txt
new file mode 100644
index 0000000000..ae6c75564a
--- /dev/null
+++ b/test/prism/fixtures/whitequark/beginless_erange_after_newline.txt
@@ -0,0 +1,2 @@
+foo
+...100
diff --git a/test/prism/fixtures/whitequark/beginless_irange_after_newline.txt b/test/prism/fixtures/whitequark/beginless_irange_after_newline.txt
new file mode 100644
index 0000000000..bfc8d5e5e8
--- /dev/null
+++ b/test/prism/fixtures/whitequark/beginless_irange_after_newline.txt
@@ -0,0 +1,2 @@
+foo
+..100
diff --git a/test/prism/fixtures/whitequark/beginless_range.txt b/test/prism/fixtures/whitequark/beginless_range.txt
new file mode 100644
index 0000000000..ef52703b8a
--- /dev/null
+++ b/test/prism/fixtures/whitequark/beginless_range.txt
@@ -0,0 +1,3 @@
+...100
+
+..100
diff --git a/test/prism/fixtures/whitequark/blockarg.txt b/test/prism/fixtures/whitequark/blockarg.txt
new file mode 100644
index 0000000000..63552e97be
--- /dev/null
+++ b/test/prism/fixtures/whitequark/blockarg.txt
@@ -0,0 +1 @@
+def f(&block); end
diff --git a/test/prism/fixtures/whitequark/blockargs.txt b/test/prism/fixtures/whitequark/blockargs.txt
new file mode 100644
index 0000000000..cdd2c4f331
--- /dev/null
+++ b/test/prism/fixtures/whitequark/blockargs.txt
@@ -0,0 +1,71 @@
+f{ }
+
+f{ | | }
+
+f{ |&b| }
+
+f{ |**baz, &b| }
+
+f{ |*, &b| }
+
+f{ |*r, p, &b| }
+
+f{ |*s, &b| }
+
+f{ |*s| }
+
+f{ |*| }
+
+f{ |;
+a
+| }
+
+f{ |;a| }
+
+f{ |a, &b| }
+
+f{ |a, *, &b| }
+
+f{ |a, *r, p, &b| }
+
+f{ |a, *s, &b| }
+
+f{ |a, *s| }
+
+f{ |a, *| }
+
+f{ |a, b,| }
+
+f{ |a, c| }
+
+f{ |a, o=1, &b| }
+
+f{ |a, o=1, *r, p, &b| }
+
+f{ |a, o=1, o1=2, *r, &b| }
+
+f{ |a, o=1, p, &b| }
+
+f{ |a,| }
+
+f{ |a| }
+
+f{ |a| }
+
+f{ |a| }
+
+f{ |foo: 1, &b| }
+
+f{ |foo: 1, bar: 2, **baz, &b| }
+
+f{ |foo:| }
+
+f{ |o=1, &b| }
+
+f{ |o=1, *r, &b| }
+
+f{ |o=1, *r, p, &b| }
+
+f{ |o=1, p, &b| }
+
+f{ || }
diff --git a/test/prism/fixtures/whitequark/bug_435.txt b/test/prism/fixtures/whitequark/bug_435.txt
new file mode 100644
index 0000000000..3e4e0d5abd
--- /dev/null
+++ b/test/prism/fixtures/whitequark/bug_435.txt
@@ -0,0 +1 @@
+"#{-> foo {}}"
diff --git a/test/prism/fixtures/whitequark/bug_447.txt b/test/prism/fixtures/whitequark/bug_447.txt
new file mode 100644
index 0000000000..7da59bbc2f
--- /dev/null
+++ b/test/prism/fixtures/whitequark/bug_447.txt
@@ -0,0 +1,3 @@
+m [] do end
+
+m [], 1 do end
diff --git a/test/prism/fixtures/whitequark/bug_452.txt b/test/prism/fixtures/whitequark/bug_452.txt
new file mode 100644
index 0000000000..8b41dd6027
--- /dev/null
+++ b/test/prism/fixtures/whitequark/bug_452.txt
@@ -0,0 +1 @@
+td (1_500).toString(); td.num do; end
diff --git a/test/prism/fixtures/whitequark/bug_466.txt b/test/prism/fixtures/whitequark/bug_466.txt
new file mode 100644
index 0000000000..ad02ad38ae
--- /dev/null
+++ b/test/prism/fixtures/whitequark/bug_466.txt
@@ -0,0 +1 @@
+foo "#{(1+1).to_i}" do; end
diff --git a/test/prism/fixtures/whitequark/bug_473.txt b/test/prism/fixtures/whitequark/bug_473.txt
new file mode 100644
index 0000000000..0d2ea883a1
--- /dev/null
+++ b/test/prism/fixtures/whitequark/bug_473.txt
@@ -0,0 +1 @@
+m "#{[]}"
diff --git a/test/prism/fixtures/whitequark/bug_480.txt b/test/prism/fixtures/whitequark/bug_480.txt
new file mode 100644
index 0000000000..0558b2c957
--- /dev/null
+++ b/test/prism/fixtures/whitequark/bug_480.txt
@@ -0,0 +1 @@
+m "#{}#{()}"
diff --git a/test/prism/fixtures/whitequark/bug_481.txt b/test/prism/fixtures/whitequark/bug_481.txt
new file mode 100644
index 0000000000..6328e9dbbd
--- /dev/null
+++ b/test/prism/fixtures/whitequark/bug_481.txt
@@ -0,0 +1 @@
+m def x(); end; 1.tap do end
diff --git a/test/prism/fixtures/whitequark/bug_ascii_8bit_in_literal.txt b/test/prism/fixtures/whitequark/bug_ascii_8bit_in_literal.txt
new file mode 100644
index 0000000000..85399bd19a
--- /dev/null
+++ b/test/prism/fixtures/whitequark/bug_ascii_8bit_in_literal.txt
@@ -0,0 +1,2 @@
+# coding:utf-8
+ "\xD0\xBF\xD1\x80\xD0\xBE\xD0\xB2\xD0\xB5\xD1\x80\xD0\xBA\xD0\xB0"
diff --git a/test/prism/fixtures/whitequark/bug_cmd_string_lookahead.txt b/test/prism/fixtures/whitequark/bug_cmd_string_lookahead.txt
new file mode 100644
index 0000000000..7e9e54c518
--- /dev/null
+++ b/test/prism/fixtures/whitequark/bug_cmd_string_lookahead.txt
@@ -0,0 +1 @@
+desc "foo" do end
diff --git a/test/prism/fixtures/whitequark/bug_cmdarg.txt b/test/prism/fixtures/whitequark/bug_cmdarg.txt
new file mode 100644
index 0000000000..0281cd6668
--- /dev/null
+++ b/test/prism/fixtures/whitequark/bug_cmdarg.txt
@@ -0,0 +1,5 @@
+assert do: true
+
+assert dogs
+
+f x: -> do meth do end end
diff --git a/test/prism/fixtures/whitequark/bug_def_no_paren_eql_begin.txt b/test/prism/fixtures/whitequark/bug_def_no_paren_eql_begin.txt
new file mode 100644
index 0000000000..615dc88217
--- /dev/null
+++ b/test/prism/fixtures/whitequark/bug_def_no_paren_eql_begin.txt
@@ -0,0 +1,4 @@
+def foo
+=begin
+=end
+end
diff --git a/test/prism/fixtures/whitequark/bug_do_block_in_call_args.txt b/test/prism/fixtures/whitequark/bug_do_block_in_call_args.txt
new file mode 100644
index 0000000000..21340fd6e8
--- /dev/null
+++ b/test/prism/fixtures/whitequark/bug_do_block_in_call_args.txt
@@ -0,0 +1 @@
+bar def foo; self.each do end end
diff --git a/test/prism/fixtures/whitequark/bug_do_block_in_cmdarg.txt b/test/prism/fixtures/whitequark/bug_do_block_in_cmdarg.txt
new file mode 100644
index 0000000000..7dece50408
--- /dev/null
+++ b/test/prism/fixtures/whitequark/bug_do_block_in_cmdarg.txt
@@ -0,0 +1 @@
+tap (proc do end)
diff --git a/test/prism/fixtures/whitequark/bug_do_block_in_hash_brace.txt b/test/prism/fixtures/whitequark/bug_do_block_in_hash_brace.txt
new file mode 100644
index 0000000000..6c4dd205d2
--- /dev/null
+++ b/test/prism/fixtures/whitequark/bug_do_block_in_hash_brace.txt
@@ -0,0 +1,9 @@
+p :foo, {"a": proc do end, b: proc do end}
+
+p :foo, {** proc do end, b: proc do end}
+
+p :foo, {:a => proc do end, b: proc do end}
+
+p :foo, {a: proc do end, b: proc do end}
+
+p :foo, {proc do end => proc do end, b: proc do end}
diff --git a/test/prism/fixtures/whitequark/bug_heredoc_do.txt b/test/prism/fixtures/whitequark/bug_heredoc_do.txt
new file mode 100644
index 0000000000..06fef0a99f
--- /dev/null
+++ b/test/prism/fixtures/whitequark/bug_heredoc_do.txt
@@ -0,0 +1,3 @@
+f <<-TABLE do
+TABLE
+end
diff --git a/test/prism/fixtures/whitequark/bug_interp_single.txt b/test/prism/fixtures/whitequark/bug_interp_single.txt
new file mode 100644
index 0000000000..be0b1a8542
--- /dev/null
+++ b/test/prism/fixtures/whitequark/bug_interp_single.txt
@@ -0,0 +1,3 @@
+"#{1}"
+
+%W"#{1}"
diff --git a/test/prism/fixtures/whitequark/bug_lambda_leakage.txt b/test/prism/fixtures/whitequark/bug_lambda_leakage.txt
new file mode 100644
index 0000000000..372b36929a
--- /dev/null
+++ b/test/prism/fixtures/whitequark/bug_lambda_leakage.txt
@@ -0,0 +1 @@
+->(scope) {}; scope
diff --git a/test/prism/fixtures/whitequark/bug_regex_verification.txt b/test/prism/fixtures/whitequark/bug_regex_verification.txt
new file mode 100644
index 0000000000..f8483c8b10
--- /dev/null
+++ b/test/prism/fixtures/whitequark/bug_regex_verification.txt
@@ -0,0 +1 @@
+/#)/x
diff --git a/test/prism/fixtures/whitequark/bug_rescue_empty_else.txt b/test/prism/fixtures/whitequark/bug_rescue_empty_else.txt
new file mode 100644
index 0000000000..e8c81edc57
--- /dev/null
+++ b/test/prism/fixtures/whitequark/bug_rescue_empty_else.txt
@@ -0,0 +1 @@
+begin; rescue LoadError; else; end
diff --git a/test/prism/fixtures/whitequark/bug_while_not_parens_do.txt b/test/prism/fixtures/whitequark/bug_while_not_parens_do.txt
new file mode 100644
index 0000000000..628c36ef13
--- /dev/null
+++ b/test/prism/fixtures/whitequark/bug_while_not_parens_do.txt
@@ -0,0 +1 @@
+while not (true) do end
diff --git a/test/prism/fixtures/whitequark/case_cond.txt b/test/prism/fixtures/whitequark/case_cond.txt
new file mode 100644
index 0000000000..a236b27ebd
--- /dev/null
+++ b/test/prism/fixtures/whitequark/case_cond.txt
@@ -0,0 +1 @@
+case; when foo; 'foo'; end
diff --git a/test/prism/fixtures/whitequark/case_cond_else.txt b/test/prism/fixtures/whitequark/case_cond_else.txt
new file mode 100644
index 0000000000..06eefa4a1b
--- /dev/null
+++ b/test/prism/fixtures/whitequark/case_cond_else.txt
@@ -0,0 +1 @@
+case; when foo; 'foo'; else 'bar'; end
diff --git a/test/prism/fixtures/whitequark/case_expr.txt b/test/prism/fixtures/whitequark/case_expr.txt
new file mode 100644
index 0000000000..472672c781
--- /dev/null
+++ b/test/prism/fixtures/whitequark/case_expr.txt
@@ -0,0 +1 @@
+case foo; when 'bar'; bar; end
diff --git a/test/prism/fixtures/whitequark/case_expr_else.txt b/test/prism/fixtures/whitequark/case_expr_else.txt
new file mode 100644
index 0000000000..3c55826134
--- /dev/null
+++ b/test/prism/fixtures/whitequark/case_expr_else.txt
@@ -0,0 +1 @@
+case foo; when 'bar'; bar; else baz; end
diff --git a/test/prism/fixtures/whitequark/casgn_scoped.txt b/test/prism/fixtures/whitequark/casgn_scoped.txt
new file mode 100644
index 0000000000..964d0f4c9b
--- /dev/null
+++ b/test/prism/fixtures/whitequark/casgn_scoped.txt
@@ -0,0 +1 @@
+Bar::Foo = 10
diff --git a/test/prism/fixtures/whitequark/casgn_toplevel.txt b/test/prism/fixtures/whitequark/casgn_toplevel.txt
new file mode 100644
index 0000000000..047a3b6745
--- /dev/null
+++ b/test/prism/fixtures/whitequark/casgn_toplevel.txt
@@ -0,0 +1 @@
+::Foo = 10
diff --git a/test/prism/fixtures/whitequark/casgn_unscoped.txt b/test/prism/fixtures/whitequark/casgn_unscoped.txt
new file mode 100644
index 0000000000..5632cf64ee
--- /dev/null
+++ b/test/prism/fixtures/whitequark/casgn_unscoped.txt
@@ -0,0 +1 @@
+Foo = 10
diff --git a/test/prism/fixtures/whitequark/character.txt b/test/prism/fixtures/whitequark/character.txt
new file mode 100644
index 0000000000..b22ffbb71a
--- /dev/null
+++ b/test/prism/fixtures/whitequark/character.txt
@@ -0,0 +1 @@
+?a
diff --git a/test/prism/fixtures/whitequark/class.txt b/test/prism/fixtures/whitequark/class.txt
new file mode 100644
index 0000000000..a30a248e96
--- /dev/null
+++ b/test/prism/fixtures/whitequark/class.txt
@@ -0,0 +1,3 @@
+class Foo end
+
+class Foo; end
diff --git a/test/prism/fixtures/whitequark/class_super.txt b/test/prism/fixtures/whitequark/class_super.txt
new file mode 100644
index 0000000000..8829d82d36
--- /dev/null
+++ b/test/prism/fixtures/whitequark/class_super.txt
@@ -0,0 +1 @@
+class Foo < Bar; end
diff --git a/test/prism/fixtures/whitequark/class_super_label.txt b/test/prism/fixtures/whitequark/class_super_label.txt
new file mode 100644
index 0000000000..5d47897ab6
--- /dev/null
+++ b/test/prism/fixtures/whitequark/class_super_label.txt
@@ -0,0 +1 @@
+class Foo < a:b; end
diff --git a/test/prism/fixtures/whitequark/comments_before_leading_dot__27.txt b/test/prism/fixtures/whitequark/comments_before_leading_dot__27.txt
new file mode 100644
index 0000000000..208f2d87fe
--- /dev/null
+++ b/test/prism/fixtures/whitequark/comments_before_leading_dot__27.txt
@@ -0,0 +1,19 @@
+a #
+ #
+&.foo
+
+
+a #
+ #
+.foo
+
+
+a #
+#
+&.foo
+
+
+a #
+#
+.foo
+
diff --git a/test/prism/fixtures/whitequark/complex.txt b/test/prism/fixtures/whitequark/complex.txt
new file mode 100644
index 0000000000..1dbf2c13f4
--- /dev/null
+++ b/test/prism/fixtures/whitequark/complex.txt
@@ -0,0 +1,7 @@
+42.1i
+
+42.1ri
+
+42i
+
+42ri
diff --git a/test/prism/fixtures/whitequark/cond_begin.txt b/test/prism/fixtures/whitequark/cond_begin.txt
new file mode 100644
index 0000000000..49d709b79c
--- /dev/null
+++ b/test/prism/fixtures/whitequark/cond_begin.txt
@@ -0,0 +1 @@
+if (bar); foo; end
diff --git a/test/prism/fixtures/whitequark/cond_begin_masgn.txt b/test/prism/fixtures/whitequark/cond_begin_masgn.txt
new file mode 100644
index 0000000000..f9b65026b4
--- /dev/null
+++ b/test/prism/fixtures/whitequark/cond_begin_masgn.txt
@@ -0,0 +1 @@
+if (bar; a, b = foo); end
diff --git a/test/prism/fixtures/whitequark/cond_eflipflop.txt b/test/prism/fixtures/whitequark/cond_eflipflop.txt
new file mode 100644
index 0000000000..1236c2dbb5
--- /dev/null
+++ b/test/prism/fixtures/whitequark/cond_eflipflop.txt
@@ -0,0 +1,3 @@
+!(foo...bar)
+
+if foo...bar; end
diff --git a/test/prism/fixtures/whitequark/cond_eflipflop_with_beginless_range.txt b/test/prism/fixtures/whitequark/cond_eflipflop_with_beginless_range.txt
new file mode 100644
index 0000000000..757863b12b
--- /dev/null
+++ b/test/prism/fixtures/whitequark/cond_eflipflop_with_beginless_range.txt
@@ -0,0 +1 @@
+if ...bar; end
diff --git a/test/prism/fixtures/whitequark/cond_eflipflop_with_endless_range.txt b/test/prism/fixtures/whitequark/cond_eflipflop_with_endless_range.txt
new file mode 100644
index 0000000000..8a3b815ec9
--- /dev/null
+++ b/test/prism/fixtures/whitequark/cond_eflipflop_with_endless_range.txt
@@ -0,0 +1 @@
+if foo...; end
diff --git a/test/prism/fixtures/whitequark/cond_iflipflop.txt b/test/prism/fixtures/whitequark/cond_iflipflop.txt
new file mode 100644
index 0000000000..84bee71a74
--- /dev/null
+++ b/test/prism/fixtures/whitequark/cond_iflipflop.txt
@@ -0,0 +1,3 @@
+!(foo..bar)
+
+if foo..bar; end
diff --git a/test/prism/fixtures/whitequark/cond_iflipflop_with_beginless_range.txt b/test/prism/fixtures/whitequark/cond_iflipflop_with_beginless_range.txt
new file mode 100644
index 0000000000..4ff5b09690
--- /dev/null
+++ b/test/prism/fixtures/whitequark/cond_iflipflop_with_beginless_range.txt
@@ -0,0 +1 @@
+if ..bar; end
diff --git a/test/prism/fixtures/whitequark/cond_iflipflop_with_endless_range.txt b/test/prism/fixtures/whitequark/cond_iflipflop_with_endless_range.txt
new file mode 100644
index 0000000000..2739ad0e2a
--- /dev/null
+++ b/test/prism/fixtures/whitequark/cond_iflipflop_with_endless_range.txt
@@ -0,0 +1 @@
+if foo..; end
diff --git a/test/prism/fixtures/whitequark/cond_match_current_line.txt b/test/prism/fixtures/whitequark/cond_match_current_line.txt
new file mode 100644
index 0000000000..21878c7bd8
--- /dev/null
+++ b/test/prism/fixtures/whitequark/cond_match_current_line.txt
@@ -0,0 +1,3 @@
+!/wat/
+
+if /wat/; end
diff --git a/test/prism/fixtures/whitequark/const_op_asgn.txt b/test/prism/fixtures/whitequark/const_op_asgn.txt
new file mode 100644
index 0000000000..e72e7adee8
--- /dev/null
+++ b/test/prism/fixtures/whitequark/const_op_asgn.txt
@@ -0,0 +1,9 @@
+::A += 1
+
+A += 1
+
+B::A += 1
+
+def x; ::A ||= 1; end
+
+def x; self::A ||= 1; end
diff --git a/test/prism/fixtures/whitequark/const_scoped.txt b/test/prism/fixtures/whitequark/const_scoped.txt
new file mode 100644
index 0000000000..4b03d85fc0
--- /dev/null
+++ b/test/prism/fixtures/whitequark/const_scoped.txt
@@ -0,0 +1 @@
+Bar::Foo
diff --git a/test/prism/fixtures/whitequark/const_toplevel.txt b/test/prism/fixtures/whitequark/const_toplevel.txt
new file mode 100644
index 0000000000..f783ae752b
--- /dev/null
+++ b/test/prism/fixtures/whitequark/const_toplevel.txt
@@ -0,0 +1 @@
+::Foo
diff --git a/test/prism/fixtures/whitequark/const_unscoped.txt b/test/prism/fixtures/whitequark/const_unscoped.txt
new file mode 100644
index 0000000000..bc56c4d894
--- /dev/null
+++ b/test/prism/fixtures/whitequark/const_unscoped.txt
@@ -0,0 +1 @@
+Foo
diff --git a/test/prism/fixtures/whitequark/cpath.txt b/test/prism/fixtures/whitequark/cpath.txt
new file mode 100644
index 0000000000..a4041692d1
--- /dev/null
+++ b/test/prism/fixtures/whitequark/cpath.txt
@@ -0,0 +1,3 @@
+module ::Foo; end
+
+module Bar::Foo; end
diff --git a/test/prism/fixtures/whitequark/cvar.txt b/test/prism/fixtures/whitequark/cvar.txt
new file mode 100644
index 0000000000..4997896e4a
--- /dev/null
+++ b/test/prism/fixtures/whitequark/cvar.txt
@@ -0,0 +1 @@
+@@foo
diff --git a/test/prism/fixtures/whitequark/cvasgn.txt b/test/prism/fixtures/whitequark/cvasgn.txt
new file mode 100644
index 0000000000..8f7e19c4fe
--- /dev/null
+++ b/test/prism/fixtures/whitequark/cvasgn.txt
@@ -0,0 +1 @@
+@@var = 10
diff --git a/test/prism/fixtures/whitequark/dedenting_heredoc.txt b/test/prism/fixtures/whitequark/dedenting_heredoc.txt
new file mode 100644
index 0000000000..84937d84ab
--- /dev/null
+++ b/test/prism/fixtures/whitequark/dedenting_heredoc.txt
@@ -0,0 +1,75 @@
+p <<~"E"
+ x
+ #{" y"}
+E
+
+p <<~"E"
+ x
+ #{foo}
+E
+
+p <<~E
+ x
+ y
+E
+
+p <<~E
+ x
+ y
+E
+
+p <<~E
+ x
+ y
+E
+
+p <<~E
+ x
+ y
+E
+
+p <<~E
+ x
+ \ y
+E
+
+p <<~E
+ x
+ \ y
+E
+
+p <<~E
+ E
+
+p <<~E
+ x
+
+y
+E
+
+p <<~E
+ x
+
+ y
+E
+
+p <<~E
+ x
+ y
+E
+
+p <<~E
+ x
+E
+
+p <<~E
+ ð
+E
+
+p <<~E
+E
+
+p <<~`E`
+ x
+ #{foo}
+E
diff --git a/test/prism/fixtures/whitequark/dedenting_interpolating_heredoc_fake_line_continuation.txt b/test/prism/fixtures/whitequark/dedenting_interpolating_heredoc_fake_line_continuation.txt
new file mode 100644
index 0000000000..0427715d61
--- /dev/null
+++ b/test/prism/fixtures/whitequark/dedenting_interpolating_heredoc_fake_line_continuation.txt
@@ -0,0 +1,4 @@
+<<~'FOO'
+ baz\\
+ qux
+FOO
diff --git a/test/prism/fixtures/whitequark/dedenting_non_interpolating_heredoc_line_continuation.txt b/test/prism/fixtures/whitequark/dedenting_non_interpolating_heredoc_line_continuation.txt
new file mode 100644
index 0000000000..fd7bc02419
--- /dev/null
+++ b/test/prism/fixtures/whitequark/dedenting_non_interpolating_heredoc_line_continuation.txt
@@ -0,0 +1,4 @@
+<<~'FOO'
+ baz\
+ qux
+FOO
diff --git a/test/prism/fixtures/whitequark/def.txt b/test/prism/fixtures/whitequark/def.txt
new file mode 100644
index 0000000000..d96a4238b3
--- /dev/null
+++ b/test/prism/fixtures/whitequark/def.txt
@@ -0,0 +1,11 @@
+def BEGIN; end
+
+def END; end
+
+def String; end
+
+def String=; end
+
+def foo; end
+
+def until; end
diff --git a/test/prism/fixtures/whitequark/defined.txt b/test/prism/fixtures/whitequark/defined.txt
new file mode 100644
index 0000000000..5cf93e22e3
--- /dev/null
+++ b/test/prism/fixtures/whitequark/defined.txt
@@ -0,0 +1,5 @@
+defined? @foo
+
+defined? foo
+
+defined?(foo)
diff --git a/test/prism/fixtures/whitequark/defs.txt b/test/prism/fixtures/whitequark/defs.txt
new file mode 100644
index 0000000000..e0b7aa86eb
--- /dev/null
+++ b/test/prism/fixtures/whitequark/defs.txt
@@ -0,0 +1,9 @@
+def (foo).foo; end
+
+def String.foo; end
+
+def String::foo; end
+
+def self.foo; end
+
+def self::foo; end
diff --git a/test/prism/fixtures/whitequark/empty_stmt.txt b/test/prism/fixtures/whitequark/empty_stmt.txt
new file mode 100644
index 0000000000..8b13789179
--- /dev/null
+++ b/test/prism/fixtures/whitequark/empty_stmt.txt
@@ -0,0 +1 @@
+
diff --git a/test/prism/fixtures/whitequark/endless_comparison_method.txt b/test/prism/fixtures/whitequark/endless_comparison_method.txt
new file mode 100644
index 0000000000..e10c3a6ced
--- /dev/null
+++ b/test/prism/fixtures/whitequark/endless_comparison_method.txt
@@ -0,0 +1,11 @@
+def !=(other) = do_something
+
+def !=(other) = do_something
+
+def <=(other) = do_something
+
+def ==(other) = do_something
+
+def ===(other) = do_something
+
+def >=(other) = do_something
diff --git a/test/prism/fixtures/whitequark/endless_method.txt b/test/prism/fixtures/whitequark/endless_method.txt
new file mode 100644
index 0000000000..7002526229
--- /dev/null
+++ b/test/prism/fixtures/whitequark/endless_method.txt
@@ -0,0 +1,7 @@
+def foo() = 42
+
+def inc(x) = x + 1
+
+def obj.foo() = 42
+
+def obj.inc(x) = x + 1
diff --git a/test/prism/fixtures/whitequark/endless_method_command_syntax.txt b/test/prism/fixtures/whitequark/endless_method_command_syntax.txt
new file mode 100644
index 0000000000..d9dad2d747
--- /dev/null
+++ b/test/prism/fixtures/whitequark/endless_method_command_syntax.txt
@@ -0,0 +1,15 @@
+def foo = puts "Hello"
+
+def foo() = puts "Hello"
+
+def foo(x) = puts x
+
+def obj.foo = puts "Hello"
+
+def obj.foo() = puts "Hello"
+
+def obj.foo(x) = puts x
+
+def rescued(x) = raise "to be caught" rescue "instance #{x}"
+
+def self.rescued(x) = raise "to be caught" rescue "class #{x}"
diff --git a/test/prism/fixtures/whitequark/endless_method_forwarded_args_legacy.txt b/test/prism/fixtures/whitequark/endless_method_forwarded_args_legacy.txt
new file mode 100644
index 0000000000..5955e40b5b
--- /dev/null
+++ b/test/prism/fixtures/whitequark/endless_method_forwarded_args_legacy.txt
@@ -0,0 +1 @@
+def foo(...) = bar(...)
diff --git a/test/prism/fixtures/whitequark/endless_method_with_rescue_mod.txt b/test/prism/fixtures/whitequark/endless_method_with_rescue_mod.txt
new file mode 100644
index 0000000000..93dc63a45d
--- /dev/null
+++ b/test/prism/fixtures/whitequark/endless_method_with_rescue_mod.txt
@@ -0,0 +1,3 @@
+def m() = 1 rescue 2
+
+def self.m() = 1 rescue 2
diff --git a/test/prism/fixtures/whitequark/endless_method_without_args.txt b/test/prism/fixtures/whitequark/endless_method_without_args.txt
new file mode 100644
index 0000000000..90ea8f7c6d
--- /dev/null
+++ b/test/prism/fixtures/whitequark/endless_method_without_args.txt
@@ -0,0 +1,7 @@
+def foo = 42
+
+def foo = 42 rescue nil
+
+def self.foo = 42
+
+def self.foo = 42 rescue nil
diff --git a/test/prism/fixtures/whitequark/ensure.txt b/test/prism/fixtures/whitequark/ensure.txt
new file mode 100644
index 0000000000..6c4b47c63c
--- /dev/null
+++ b/test/prism/fixtures/whitequark/ensure.txt
@@ -0,0 +1 @@
+begin; meth; ensure; bar; end
diff --git a/test/prism/fixtures/whitequark/ensure_empty.txt b/test/prism/fixtures/whitequark/ensure_empty.txt
new file mode 100644
index 0000000000..39a175c371
--- /dev/null
+++ b/test/prism/fixtures/whitequark/ensure_empty.txt
@@ -0,0 +1 @@
+begin ensure end
diff --git a/test/prism/fixtures/whitequark/false.txt b/test/prism/fixtures/whitequark/false.txt
new file mode 100644
index 0000000000..c508d5366f
--- /dev/null
+++ b/test/prism/fixtures/whitequark/false.txt
@@ -0,0 +1 @@
+false
diff --git a/test/prism/fixtures/whitequark/float.txt b/test/prism/fixtures/whitequark/float.txt
new file mode 100644
index 0000000000..8c7592a192
--- /dev/null
+++ b/test/prism/fixtures/whitequark/float.txt
@@ -0,0 +1,3 @@
+-1.33
+
+1.33
diff --git a/test/prism/fixtures/whitequark/for.txt b/test/prism/fixtures/whitequark/for.txt
new file mode 100644
index 0000000000..a27ae578da
--- /dev/null
+++ b/test/prism/fixtures/whitequark/for.txt
@@ -0,0 +1,3 @@
+for a in foo do p a; end
+
+for a in foo; p a; end
diff --git a/test/prism/fixtures/whitequark/for_mlhs.txt b/test/prism/fixtures/whitequark/for_mlhs.txt
new file mode 100644
index 0000000000..53cd5229a4
--- /dev/null
+++ b/test/prism/fixtures/whitequark/for_mlhs.txt
@@ -0,0 +1 @@
+for a, b in foo; p a, b; end
diff --git a/test/prism/fixtures/whitequark/forward_arg.txt b/test/prism/fixtures/whitequark/forward_arg.txt
new file mode 100644
index 0000000000..c7590a8d53
--- /dev/null
+++ b/test/prism/fixtures/whitequark/forward_arg.txt
@@ -0,0 +1 @@
+def foo(...); bar(...); end
diff --git a/test/prism/fixtures/whitequark/forward_arg_with_open_args.txt b/test/prism/fixtures/whitequark/forward_arg_with_open_args.txt
new file mode 100644
index 0000000000..fd4c06bcb5
--- /dev/null
+++ b/test/prism/fixtures/whitequark/forward_arg_with_open_args.txt
@@ -0,0 +1,27 @@
+(def foo ...
+ bar(...)
+end)
+
+(def foo ...; bar(...); end)
+
+def foo ...
+end
+
+def foo ...; bar(...); end
+
+def foo a, ...
+ bar(...)
+end
+
+def foo a, ...; bar(...); end
+
+def foo a, b = 1, ...
+end
+
+def foo b = 1, ...
+ bar(...)
+end
+
+def foo b = 1, ...; bar(...); end
+
+def foo(a, ...) bar(...) end
diff --git a/test/prism/fixtures/whitequark/forward_args_legacy.txt b/test/prism/fixtures/whitequark/forward_args_legacy.txt
new file mode 100644
index 0000000000..0d9162457f
--- /dev/null
+++ b/test/prism/fixtures/whitequark/forward_args_legacy.txt
@@ -0,0 +1,5 @@
+def foo(...); bar(...); end
+
+def foo(...); end
+
+def foo(...); super(...); end
diff --git a/test/prism/fixtures/whitequark/forwarded_argument_with_kwrestarg.txt b/test/prism/fixtures/whitequark/forwarded_argument_with_kwrestarg.txt
new file mode 100644
index 0000000000..7dbf472232
--- /dev/null
+++ b/test/prism/fixtures/whitequark/forwarded_argument_with_kwrestarg.txt
@@ -0,0 +1 @@
+def foo(argument, **); bar(argument, **); end
diff --git a/test/prism/fixtures/whitequark/forwarded_argument_with_restarg.txt b/test/prism/fixtures/whitequark/forwarded_argument_with_restarg.txt
new file mode 100644
index 0000000000..f734bfd9ec
--- /dev/null
+++ b/test/prism/fixtures/whitequark/forwarded_argument_with_restarg.txt
@@ -0,0 +1 @@
+def foo(argument, *); bar(argument, *); end
diff --git a/test/prism/fixtures/whitequark/forwarded_kwrestarg.txt b/test/prism/fixtures/whitequark/forwarded_kwrestarg.txt
new file mode 100644
index 0000000000..16cd8b2913
--- /dev/null
+++ b/test/prism/fixtures/whitequark/forwarded_kwrestarg.txt
@@ -0,0 +1 @@
+def foo(**); bar(**); end
diff --git a/test/prism/fixtures/whitequark/forwarded_kwrestarg_with_additional_kwarg.txt b/test/prism/fixtures/whitequark/forwarded_kwrestarg_with_additional_kwarg.txt
new file mode 100644
index 0000000000..52759b838f
--- /dev/null
+++ b/test/prism/fixtures/whitequark/forwarded_kwrestarg_with_additional_kwarg.txt
@@ -0,0 +1 @@
+def foo(**); bar(**, from_foo: true); end
diff --git a/test/prism/fixtures/whitequark/forwarded_restarg.txt b/test/prism/fixtures/whitequark/forwarded_restarg.txt
new file mode 100644
index 0000000000..65ac2cc1ed
--- /dev/null
+++ b/test/prism/fixtures/whitequark/forwarded_restarg.txt
@@ -0,0 +1 @@
+def foo(*); bar(*); end
diff --git a/test/prism/fixtures/whitequark/gvar.txt b/test/prism/fixtures/whitequark/gvar.txt
new file mode 100644
index 0000000000..bbf13489ad
--- /dev/null
+++ b/test/prism/fixtures/whitequark/gvar.txt
@@ -0,0 +1 @@
+$foo
diff --git a/test/prism/fixtures/whitequark/gvasgn.txt b/test/prism/fixtures/whitequark/gvasgn.txt
new file mode 100644
index 0000000000..2bcc22cdd1
--- /dev/null
+++ b/test/prism/fixtures/whitequark/gvasgn.txt
@@ -0,0 +1 @@
+$var = 10
diff --git a/test/prism/fixtures/whitequark/hash_empty.txt b/test/prism/fixtures/whitequark/hash_empty.txt
new file mode 100644
index 0000000000..ffcd4415b0
--- /dev/null
+++ b/test/prism/fixtures/whitequark/hash_empty.txt
@@ -0,0 +1 @@
+{ }
diff --git a/test/prism/fixtures/whitequark/hash_hashrocket.txt b/test/prism/fixtures/whitequark/hash_hashrocket.txt
new file mode 100644
index 0000000000..2cbb3bd96d
--- /dev/null
+++ b/test/prism/fixtures/whitequark/hash_hashrocket.txt
@@ -0,0 +1,3 @@
+{ 1 => 2 }
+
+{ 1 => 2, :foo => "bar" }
diff --git a/test/prism/fixtures/whitequark/hash_kwsplat.txt b/test/prism/fixtures/whitequark/hash_kwsplat.txt
new file mode 100644
index 0000000000..921aa97c7c
--- /dev/null
+++ b/test/prism/fixtures/whitequark/hash_kwsplat.txt
@@ -0,0 +1 @@
+{ foo: 2, **bar }
diff --git a/test/prism/fixtures/whitequark/hash_label.txt b/test/prism/fixtures/whitequark/hash_label.txt
new file mode 100644
index 0000000000..3aacae4b69
--- /dev/null
+++ b/test/prism/fixtures/whitequark/hash_label.txt
@@ -0,0 +1 @@
+{ foo: 2 }
diff --git a/test/prism/fixtures/whitequark/hash_label_end.txt b/test/prism/fixtures/whitequark/hash_label_end.txt
new file mode 100644
index 0000000000..ac9f7c4b41
--- /dev/null
+++ b/test/prism/fixtures/whitequark/hash_label_end.txt
@@ -0,0 +1,5 @@
+f(a ? "a":1)
+
+{ 'foo': 2 }
+
+{ 'foo': 2, 'bar': {}}
diff --git a/test/prism/fixtures/whitequark/hash_pair_value_omission.txt b/test/prism/fixtures/whitequark/hash_pair_value_omission.txt
new file mode 100644
index 0000000000..9d8ccb5877
--- /dev/null
+++ b/test/prism/fixtures/whitequark/hash_pair_value_omission.txt
@@ -0,0 +1,5 @@
+{BAR:}
+
+{a:, b:}
+
+{puts:}
diff --git a/test/prism/fixtures/whitequark/heredoc.txt b/test/prism/fixtures/whitequark/heredoc.txt
new file mode 100644
index 0000000000..1bfc963f94
--- /dev/null
+++ b/test/prism/fixtures/whitequark/heredoc.txt
@@ -0,0 +1,14 @@
+<<'HERE'
+foo
+bar
+HERE
+
+<<HERE
+foo
+bar
+HERE
+
+<<`HERE`
+foo
+bar
+HERE
diff --git a/test/prism/fixtures/whitequark/if.txt b/test/prism/fixtures/whitequark/if.txt
new file mode 100644
index 0000000000..3de3525286
--- /dev/null
+++ b/test/prism/fixtures/whitequark/if.txt
@@ -0,0 +1,3 @@
+if foo then bar; end
+
+if foo; bar; end
diff --git a/test/prism/fixtures/whitequark/if_else.txt b/test/prism/fixtures/whitequark/if_else.txt
new file mode 100644
index 0000000000..62bab8138c
--- /dev/null
+++ b/test/prism/fixtures/whitequark/if_else.txt
@@ -0,0 +1,3 @@
+if foo then bar; else baz; end
+
+if foo; bar; else baz; end
diff --git a/test/prism/fixtures/whitequark/if_elsif.txt b/test/prism/fixtures/whitequark/if_elsif.txt
new file mode 100644
index 0000000000..4d71e82214
--- /dev/null
+++ b/test/prism/fixtures/whitequark/if_elsif.txt
@@ -0,0 +1 @@
+if foo; bar; elsif baz; 1; else 2; end
diff --git a/test/prism/fixtures/whitequark/if_masgn__24.txt b/test/prism/fixtures/whitequark/if_masgn__24.txt
new file mode 100644
index 0000000000..0c2c8bb04f
--- /dev/null
+++ b/test/prism/fixtures/whitequark/if_masgn__24.txt
@@ -0,0 +1 @@
+if (a, b = foo); end
diff --git a/test/prism/fixtures/whitequark/if_mod.txt b/test/prism/fixtures/whitequark/if_mod.txt
new file mode 100644
index 0000000000..da177b5606
--- /dev/null
+++ b/test/prism/fixtures/whitequark/if_mod.txt
@@ -0,0 +1 @@
+bar if foo
diff --git a/test/prism/fixtures/whitequark/if_nl_then.txt b/test/prism/fixtures/whitequark/if_nl_then.txt
new file mode 100644
index 0000000000..b68107bad2
--- /dev/null
+++ b/test/prism/fixtures/whitequark/if_nl_then.txt
@@ -0,0 +1,2 @@
+if foo
+then bar end
diff --git a/test/prism/fixtures/whitequark/int.txt b/test/prism/fixtures/whitequark/int.txt
new file mode 100644
index 0000000000..6d419918c6
--- /dev/null
+++ b/test/prism/fixtures/whitequark/int.txt
@@ -0,0 +1,5 @@
++42
+
+-42
+
+42
diff --git a/test/prism/fixtures/whitequark/int___LINE__.txt b/test/prism/fixtures/whitequark/int___LINE__.txt
new file mode 100644
index 0000000000..05dcf7afe0
--- /dev/null
+++ b/test/prism/fixtures/whitequark/int___LINE__.txt
@@ -0,0 +1 @@
+__LINE__
diff --git a/test/prism/fixtures/whitequark/interp_digit_var.txt b/test/prism/fixtures/whitequark/interp_digit_var.txt
new file mode 100644
index 0000000000..1ae5a2e3e0
--- /dev/null
+++ b/test/prism/fixtures/whitequark/interp_digit_var.txt
@@ -0,0 +1,87 @@
+ "#@1"
+
+ "#@@1"
+
+ %I[#@1]
+
+ %I[#@@1]
+
+ %Q{#@1}
+
+ %Q{#@@1}
+
+ %W[#@1]
+
+ %W[#@@1]
+
+ %i[ #@1 ]
+
+ %i[ #@@1 ]
+
+ %q{#@1}
+
+ %q{#@@1}
+
+ %r{#@1}
+
+ %r{#@@1}
+
+ %s{#@1}
+
+ %s{#@@1}
+
+ %w[ #@1 ]
+
+ %w[ #@@1 ]
+
+ %x{#@1}
+
+ %x{#@@1}
+
+ %{#@1}
+
+ %{#@@1}
+
+ '#@1'
+
+ '#@@1'
+
+ /#@1/
+
+ /#@@1/
+
+ :"#@1"
+
+ :"#@@1"
+
+ :'#@1'
+
+ :'#@@1'
+
+ `#@1`
+
+ `#@@1`
+
+<<-"HERE"
+#@1
+HERE
+
+<<-"HERE"
+#@@1
+HERE
+
+<<-'HERE'
+#@1
+HERE
+
+<<-'HERE'
+#@@1
+HERE
+
+<<-`HERE`
+#@1
+HERE
+
+<<-`HERE`
+#@@1
+HERE
diff --git a/test/prism/fixtures/whitequark/ivar.txt b/test/prism/fixtures/whitequark/ivar.txt
new file mode 100644
index 0000000000..9149fc67f9
--- /dev/null
+++ b/test/prism/fixtures/whitequark/ivar.txt
@@ -0,0 +1 @@
+@foo
diff --git a/test/prism/fixtures/whitequark/ivasgn.txt b/test/prism/fixtures/whitequark/ivasgn.txt
new file mode 100644
index 0000000000..ac291799db
--- /dev/null
+++ b/test/prism/fixtures/whitequark/ivasgn.txt
@@ -0,0 +1 @@
+@var = 10
diff --git a/test/prism/fixtures/whitequark/keyword_argument_omission.txt b/test/prism/fixtures/whitequark/keyword_argument_omission.txt
new file mode 100644
index 0000000000..47883dc9a5
--- /dev/null
+++ b/test/prism/fixtures/whitequark/keyword_argument_omission.txt
@@ -0,0 +1 @@
+foo(a:, b:)
diff --git a/test/prism/fixtures/whitequark/kwarg.txt b/test/prism/fixtures/whitequark/kwarg.txt
new file mode 100644
index 0000000000..ca02a1fd2a
--- /dev/null
+++ b/test/prism/fixtures/whitequark/kwarg.txt
@@ -0,0 +1 @@
+def f(foo:); end
diff --git a/test/prism/fixtures/whitequark/kwbegin_compstmt.txt b/test/prism/fixtures/whitequark/kwbegin_compstmt.txt
new file mode 100644
index 0000000000..33ceff2489
--- /dev/null
+++ b/test/prism/fixtures/whitequark/kwbegin_compstmt.txt
@@ -0,0 +1 @@
+begin foo!; bar! end
diff --git a/test/prism/fixtures/whitequark/kwnilarg.txt b/test/prism/fixtures/whitequark/kwnilarg.txt
new file mode 100644
index 0000000000..8fc482d5af
--- /dev/null
+++ b/test/prism/fixtures/whitequark/kwnilarg.txt
@@ -0,0 +1,5 @@
+->(**nil) {}
+
+def f(**nil); end
+
+m { |**nil| }
diff --git a/test/prism/fixtures/whitequark/kwoptarg.txt b/test/prism/fixtures/whitequark/kwoptarg.txt
new file mode 100644
index 0000000000..dc3ce728d6
--- /dev/null
+++ b/test/prism/fixtures/whitequark/kwoptarg.txt
@@ -0,0 +1 @@
+def f(foo: 1); end
diff --git a/test/prism/fixtures/whitequark/kwoptarg_with_kwrestarg_and_forwarded_args.txt b/test/prism/fixtures/whitequark/kwoptarg_with_kwrestarg_and_forwarded_args.txt
new file mode 100644
index 0000000000..99dcc7239b
--- /dev/null
+++ b/test/prism/fixtures/whitequark/kwoptarg_with_kwrestarg_and_forwarded_args.txt
@@ -0,0 +1 @@
+def f(a: nil, **); b(**) end
diff --git a/test/prism/fixtures/whitequark/kwrestarg_named.txt b/test/prism/fixtures/whitequark/kwrestarg_named.txt
new file mode 100644
index 0000000000..e17a661001
--- /dev/null
+++ b/test/prism/fixtures/whitequark/kwrestarg_named.txt
@@ -0,0 +1 @@
+def f(**foo); end
diff --git a/test/prism/fixtures/whitequark/kwrestarg_unnamed.txt b/test/prism/fixtures/whitequark/kwrestarg_unnamed.txt
new file mode 100644
index 0000000000..1b26b1d2ac
--- /dev/null
+++ b/test/prism/fixtures/whitequark/kwrestarg_unnamed.txt
@@ -0,0 +1 @@
+def f(**); end
diff --git a/test/prism/fixtures/whitequark/lbrace_arg_after_command_args.txt b/test/prism/fixtures/whitequark/lbrace_arg_after_command_args.txt
new file mode 100644
index 0000000000..277c200c9f
--- /dev/null
+++ b/test/prism/fixtures/whitequark/lbrace_arg_after_command_args.txt
@@ -0,0 +1 @@
+let (:a) { m do; end }
diff --git a/test/prism/fixtures/whitequark/lparenarg_after_lvar__since_25.txt b/test/prism/fixtures/whitequark/lparenarg_after_lvar__since_25.txt
new file mode 100644
index 0000000000..dc3a98b1c8
--- /dev/null
+++ b/test/prism/fixtures/whitequark/lparenarg_after_lvar__since_25.txt
@@ -0,0 +1,3 @@
+foo (-1.3).abs
+
+meth (-1.3).abs
diff --git a/test/prism/fixtures/whitequark/lvar.txt b/test/prism/fixtures/whitequark/lvar.txt
new file mode 100644
index 0000000000..257cc5642c
--- /dev/null
+++ b/test/prism/fixtures/whitequark/lvar.txt
@@ -0,0 +1 @@
+foo
diff --git a/test/prism/fixtures/whitequark/lvar_injecting_match.txt b/test/prism/fixtures/whitequark/lvar_injecting_match.txt
new file mode 100644
index 0000000000..ba814a1088
--- /dev/null
+++ b/test/prism/fixtures/whitequark/lvar_injecting_match.txt
@@ -0,0 +1 @@
+/(?<match>bar)/ =~ 'bar'; match
diff --git a/test/prism/fixtures/whitequark/lvasgn.txt b/test/prism/fixtures/whitequark/lvasgn.txt
new file mode 100644
index 0000000000..330b8eff27
--- /dev/null
+++ b/test/prism/fixtures/whitequark/lvasgn.txt
@@ -0,0 +1 @@
+var = 10; var
diff --git a/test/prism/fixtures/whitequark/masgn.txt b/test/prism/fixtures/whitequark/masgn.txt
new file mode 100644
index 0000000000..032124287c
--- /dev/null
+++ b/test/prism/fixtures/whitequark/masgn.txt
@@ -0,0 +1,5 @@
+(foo, bar) = 1, 2
+
+foo, bar = 1, 2
+
+foo, bar, baz = 1, 2
diff --git a/test/prism/fixtures/whitequark/masgn_attr.txt b/test/prism/fixtures/whitequark/masgn_attr.txt
new file mode 100644
index 0000000000..91a703ef44
--- /dev/null
+++ b/test/prism/fixtures/whitequark/masgn_attr.txt
@@ -0,0 +1,5 @@
+self.A, foo = foo
+
+self.a, self[1, 2] = foo
+
+self::a, foo = foo
diff --git a/test/prism/fixtures/whitequark/masgn_cmd.txt b/test/prism/fixtures/whitequark/masgn_cmd.txt
new file mode 100644
index 0000000000..18e096f1ee
--- /dev/null
+++ b/test/prism/fixtures/whitequark/masgn_cmd.txt
@@ -0,0 +1 @@
+foo, bar = m foo
diff --git a/test/prism/fixtures/whitequark/masgn_const.txt b/test/prism/fixtures/whitequark/masgn_const.txt
new file mode 100644
index 0000000000..3b6fba588a
--- /dev/null
+++ b/test/prism/fixtures/whitequark/masgn_const.txt
@@ -0,0 +1,3 @@
+::A, foo = foo
+
+self::A, foo = foo
diff --git a/test/prism/fixtures/whitequark/masgn_nested.txt b/test/prism/fixtures/whitequark/masgn_nested.txt
new file mode 100644
index 0000000000..a1ccf4e385
--- /dev/null
+++ b/test/prism/fixtures/whitequark/masgn_nested.txt
@@ -0,0 +1,3 @@
+((b, )) = foo
+
+a, (b, c) = foo
diff --git a/test/prism/fixtures/whitequark/masgn_splat.txt b/test/prism/fixtures/whitequark/masgn_splat.txt
new file mode 100644
index 0000000000..a15dab10f2
--- /dev/null
+++ b/test/prism/fixtures/whitequark/masgn_splat.txt
@@ -0,0 +1,19 @@
+* = bar
+
+*, c, d = bar
+
+*b = bar
+
+*b, c = bar
+
+@foo, @@bar = *foo
+
+a, * = bar
+
+a, *, c = bar
+
+a, *b = bar
+
+a, *b, c = bar
+
+a, b = *foo, bar
diff --git a/test/prism/fixtures/whitequark/method_definition_in_while_cond.txt b/test/prism/fixtures/whitequark/method_definition_in_while_cond.txt
new file mode 100644
index 0000000000..6ec38906a1
--- /dev/null
+++ b/test/prism/fixtures/whitequark/method_definition_in_while_cond.txt
@@ -0,0 +1,7 @@
+while def foo a = tap do end; end; break; end
+
+while def foo; tap do end; end; break; end
+
+while def self.foo a = tap do end; end; break; end
+
+while def self.foo; tap do end; end; break; end
diff --git a/test/prism/fixtures/whitequark/module.txt b/test/prism/fixtures/whitequark/module.txt
new file mode 100644
index 0000000000..f999df3791
--- /dev/null
+++ b/test/prism/fixtures/whitequark/module.txt
@@ -0,0 +1 @@
+module Foo; end
diff --git a/test/prism/fixtures/whitequark/multiple_pattern_matches.txt b/test/prism/fixtures/whitequark/multiple_pattern_matches.txt
new file mode 100644
index 0000000000..54a4bb4774
--- /dev/null
+++ b/test/prism/fixtures/whitequark/multiple_pattern_matches.txt
@@ -0,0 +1,5 @@
+{a: 0} => a:
+{a: 0} => a:
+
+{a: 0} in a:
+{a: 0} in a:
diff --git a/test/prism/fixtures/whitequark/newline_in_hash_argument.txt b/test/prism/fixtures/whitequark/newline_in_hash_argument.txt
new file mode 100644
index 0000000000..1681844331
--- /dev/null
+++ b/test/prism/fixtures/whitequark/newline_in_hash_argument.txt
@@ -0,0 +1,14 @@
+case foo
+in a:
+0
+true
+in "b":
+0
+true
+end
+
+obj.set "foo":
+1
+
+obj.set foo:
+1
diff --git a/test/prism/fixtures/whitequark/nil.txt b/test/prism/fixtures/whitequark/nil.txt
new file mode 100644
index 0000000000..607602cfc6
--- /dev/null
+++ b/test/prism/fixtures/whitequark/nil.txt
@@ -0,0 +1 @@
+nil
diff --git a/test/prism/fixtures/whitequark/nil_expression.txt b/test/prism/fixtures/whitequark/nil_expression.txt
new file mode 100644
index 0000000000..aabf53f005
--- /dev/null
+++ b/test/prism/fixtures/whitequark/nil_expression.txt
@@ -0,0 +1,3 @@
+()
+
+begin end
diff --git a/test/prism/fixtures/whitequark/non_lvar_injecting_match.txt b/test/prism/fixtures/whitequark/non_lvar_injecting_match.txt
new file mode 100644
index 0000000000..f1eb7d3c2c
--- /dev/null
+++ b/test/prism/fixtures/whitequark/non_lvar_injecting_match.txt
@@ -0,0 +1 @@
+/#{1}(?<match>bar)/ =~ 'bar'
diff --git a/test/prism/fixtures/whitequark/not.txt b/test/prism/fixtures/whitequark/not.txt
new file mode 100644
index 0000000000..d87f68f48c
--- /dev/null
+++ b/test/prism/fixtures/whitequark/not.txt
@@ -0,0 +1,5 @@
+not foo
+
+not()
+
+not(foo)
diff --git a/test/prism/fixtures/whitequark/not_cmd.txt b/test/prism/fixtures/whitequark/not_cmd.txt
new file mode 100644
index 0000000000..685ec209ee
--- /dev/null
+++ b/test/prism/fixtures/whitequark/not_cmd.txt
@@ -0,0 +1 @@
+not m foo
diff --git a/test/prism/fixtures/whitequark/not_masgn__24.txt b/test/prism/fixtures/whitequark/not_masgn__24.txt
new file mode 100644
index 0000000000..cb93b9103d
--- /dev/null
+++ b/test/prism/fixtures/whitequark/not_masgn__24.txt
@@ -0,0 +1 @@
+!(a, b = foo)
diff --git a/test/prism/fixtures/whitequark/nth_ref.txt b/test/prism/fixtures/whitequark/nth_ref.txt
new file mode 100644
index 0000000000..16ef65b105
--- /dev/null
+++ b/test/prism/fixtures/whitequark/nth_ref.txt
@@ -0,0 +1 @@
+$10
diff --git a/test/prism/fixtures/whitequark/numbered_args_after_27.txt b/test/prism/fixtures/whitequark/numbered_args_after_27.txt
new file mode 100644
index 0000000000..96fe7a32e2
--- /dev/null
+++ b/test/prism/fixtures/whitequark/numbered_args_after_27.txt
@@ -0,0 +1,7 @@
+-> do _1 + _9 end
+
+-> { _1 + _9}
+
+m do _1 + _9 end
+
+m { _1 + _9 }
diff --git a/test/prism/fixtures/whitequark/numparam_outside_block.txt b/test/prism/fixtures/whitequark/numparam_outside_block.txt
new file mode 100644
index 0000000000..37cbce182d
--- /dev/null
+++ b/test/prism/fixtures/whitequark/numparam_outside_block.txt
@@ -0,0 +1,9 @@
+_1
+
+class << foo; _1; end
+
+class A; _1; end
+
+def self.m; _1; end
+
+module A; _1; end
diff --git a/test/prism/fixtures/whitequark/numparam_ruby_bug_19025.txt b/test/prism/fixtures/whitequark/numparam_ruby_bug_19025.txt
new file mode 100644
index 0000000000..f9ffd4329a
--- /dev/null
+++ b/test/prism/fixtures/whitequark/numparam_ruby_bug_19025.txt
@@ -0,0 +1 @@
+p { [_1 **2] }
diff --git a/test/prism/fixtures/whitequark/op_asgn.txt b/test/prism/fixtures/whitequark/op_asgn.txt
new file mode 100644
index 0000000000..a5a28b1010
--- /dev/null
+++ b/test/prism/fixtures/whitequark/op_asgn.txt
@@ -0,0 +1,5 @@
+foo.A += 1
+
+foo.a += 1
+
+foo::a += 1
diff --git a/test/prism/fixtures/whitequark/op_asgn_cmd.txt b/test/prism/fixtures/whitequark/op_asgn_cmd.txt
new file mode 100644
index 0000000000..017aa9bef7
--- /dev/null
+++ b/test/prism/fixtures/whitequark/op_asgn_cmd.txt
@@ -0,0 +1,7 @@
+foo.A += m foo
+
+foo.a += m foo
+
+foo::A += m foo
+
+foo::a += m foo
diff --git a/test/prism/fixtures/whitequark/op_asgn_index.txt b/test/prism/fixtures/whitequark/op_asgn_index.txt
new file mode 100644
index 0000000000..92cfb225fc
--- /dev/null
+++ b/test/prism/fixtures/whitequark/op_asgn_index.txt
@@ -0,0 +1 @@
+foo[0, 1] += 2
diff --git a/test/prism/fixtures/whitequark/op_asgn_index_cmd.txt b/test/prism/fixtures/whitequark/op_asgn_index_cmd.txt
new file mode 100644
index 0000000000..161b244bd4
--- /dev/null
+++ b/test/prism/fixtures/whitequark/op_asgn_index_cmd.txt
@@ -0,0 +1 @@
+foo[0, 1] += m foo
diff --git a/test/prism/fixtures/whitequark/optarg.txt b/test/prism/fixtures/whitequark/optarg.txt
new file mode 100644
index 0000000000..9d60609961
--- /dev/null
+++ b/test/prism/fixtures/whitequark/optarg.txt
@@ -0,0 +1,3 @@
+def f foo = 1; end
+
+def f(foo=1, bar=2); end
diff --git a/test/prism/fixtures/whitequark/or.txt b/test/prism/fixtures/whitequark/or.txt
new file mode 100644
index 0000000000..c2042ebb41
--- /dev/null
+++ b/test/prism/fixtures/whitequark/or.txt
@@ -0,0 +1,3 @@
+foo or bar
+
+foo || bar
diff --git a/test/prism/fixtures/whitequark/or_asgn.txt b/test/prism/fixtures/whitequark/or_asgn.txt
new file mode 100644
index 0000000000..6e4ecc9f93
--- /dev/null
+++ b/test/prism/fixtures/whitequark/or_asgn.txt
@@ -0,0 +1,3 @@
+foo.a ||= 1
+
+foo[0, 1] ||= 2
diff --git a/test/prism/fixtures/whitequark/parser_bug_272.txt b/test/prism/fixtures/whitequark/parser_bug_272.txt
new file mode 100644
index 0000000000..2f2f2b84d2
--- /dev/null
+++ b/test/prism/fixtures/whitequark/parser_bug_272.txt
@@ -0,0 +1 @@
+a @b do |c|;end
diff --git a/test/prism/fixtures/whitequark/parser_bug_490.txt b/test/prism/fixtures/whitequark/parser_bug_490.txt
new file mode 100644
index 0000000000..cf544b1ff6
--- /dev/null
+++ b/test/prism/fixtures/whitequark/parser_bug_490.txt
@@ -0,0 +1,5 @@
+def m; class << self; A = nil; end; end
+
+def m; class << self; class C; end; end; end
+
+def m; class << self; module M; end; end; end
diff --git a/test/prism/fixtures/whitequark/parser_bug_507.txt b/test/prism/fixtures/whitequark/parser_bug_507.txt
new file mode 100644
index 0000000000..bf616b85c8
--- /dev/null
+++ b/test/prism/fixtures/whitequark/parser_bug_507.txt
@@ -0,0 +1 @@
+m = -> *args do end
diff --git a/test/prism/fixtures/whitequark/parser_bug_518.txt b/test/prism/fixtures/whitequark/parser_bug_518.txt
new file mode 100644
index 0000000000..22f4afe3c8
--- /dev/null
+++ b/test/prism/fixtures/whitequark/parser_bug_518.txt
@@ -0,0 +1,2 @@
+class A < B
+end
diff --git a/test/prism/fixtures/whitequark/parser_bug_525.txt b/test/prism/fixtures/whitequark/parser_bug_525.txt
new file mode 100644
index 0000000000..59d0e735b4
--- /dev/null
+++ b/test/prism/fixtures/whitequark/parser_bug_525.txt
@@ -0,0 +1 @@
+m1 :k => m2 do; m3() do end; end
diff --git a/test/prism/fixtures/whitequark/parser_bug_604.txt b/test/prism/fixtures/whitequark/parser_bug_604.txt
new file mode 100644
index 0000000000..7eb91c2f46
--- /dev/null
+++ b/test/prism/fixtures/whitequark/parser_bug_604.txt
@@ -0,0 +1 @@
+m a + b do end
diff --git a/test/prism/fixtures/whitequark/parser_bug_640.txt b/test/prism/fixtures/whitequark/parser_bug_640.txt
new file mode 100644
index 0000000000..fb62ded04c
--- /dev/null
+++ b/test/prism/fixtures/whitequark/parser_bug_640.txt
@@ -0,0 +1,4 @@
+<<~FOO
+ baz\
+ qux
+FOO
diff --git a/test/prism/fixtures/whitequark/parser_bug_645.txt b/test/prism/fixtures/whitequark/parser_bug_645.txt
new file mode 100644
index 0000000000..cb1e5a0dcf
--- /dev/null
+++ b/test/prism/fixtures/whitequark/parser_bug_645.txt
@@ -0,0 +1 @@
+-> (arg={}) {}
diff --git a/test/prism/fixtures/whitequark/parser_bug_830.txt b/test/prism/fixtures/whitequark/parser_bug_830.txt
new file mode 100644
index 0000000000..e5865e960d
--- /dev/null
+++ b/test/prism/fixtures/whitequark/parser_bug_830.txt
@@ -0,0 +1 @@
+/\(/
diff --git a/test/prism/fixtures/whitequark/parser_bug_989.txt b/test/prism/fixtures/whitequark/parser_bug_989.txt
new file mode 100644
index 0000000000..b7b99612b4
--- /dev/null
+++ b/test/prism/fixtures/whitequark/parser_bug_989.txt
@@ -0,0 +1,3 @@
+ <<-HERE
+ content
+ HERE
diff --git a/test/prism/fixtures/whitequark/parser_drops_truncated_parts_of_squiggly_heredoc.txt b/test/prism/fixtures/whitequark/parser_drops_truncated_parts_of_squiggly_heredoc.txt
new file mode 100644
index 0000000000..bddae8e153
--- /dev/null
+++ b/test/prism/fixtures/whitequark/parser_drops_truncated_parts_of_squiggly_heredoc.txt
@@ -0,0 +1,3 @@
+<<~HERE
+ #{}
+HERE
diff --git a/test/prism/fixtures/whitequark/parser_slash_slash_n_escaping_in_literals.txt b/test/prism/fixtures/whitequark/parser_slash_slash_n_escaping_in_literals.txt
new file mode 100644
index 0000000000..564cebdd74
--- /dev/null
+++ b/test/prism/fixtures/whitequark/parser_slash_slash_n_escaping_in_literals.txt
@@ -0,0 +1,62 @@
+"a\
+b"
+
+%I{a\
+b}
+
+%Q{a\
+b}
+
+%W{a\
+b}
+
+%i{a\
+b}
+
+%q{a\
+b}
+
+%r{a\
+b}
+
+%s{a\
+b}
+
+%w{a\
+b}
+
+%x{a\
+b}
+
+%{a\
+b}
+
+'a\
+b'
+
+/a\
+b/
+
+:"a\
+b"
+
+:'a\
+b'
+
+<<-"HERE"
+a\
+b
+HERE
+
+<<-'HERE'
+a\
+b
+HERE
+
+<<-`HERE`
+a\
+b
+HERE
+
+`a\
+b`
diff --git a/test/prism/fixtures/whitequark/pattern_matching__FILE__LINE_literals.txt b/test/prism/fixtures/whitequark/pattern_matching__FILE__LINE_literals.txt
new file mode 100644
index 0000000000..fe0edaed55
--- /dev/null
+++ b/test/prism/fixtures/whitequark/pattern_matching__FILE__LINE_literals.txt
@@ -0,0 +1,4 @@
+ case [__FILE__, __LINE__ + 1, __ENCODING__]
+ in [__FILE__, __LINE__, __ENCODING__]
+ end
+
diff --git a/test/prism/fixtures/whitequark/pattern_matching_blank_else.txt b/test/prism/fixtures/whitequark/pattern_matching_blank_else.txt
new file mode 100644
index 0000000000..6bf059af41
--- /dev/null
+++ b/test/prism/fixtures/whitequark/pattern_matching_blank_else.txt
@@ -0,0 +1 @@
+case 1; in 2; 3; else; end
diff --git a/test/prism/fixtures/whitequark/pattern_matching_else.txt b/test/prism/fixtures/whitequark/pattern_matching_else.txt
new file mode 100644
index 0000000000..29f14c91ab
--- /dev/null
+++ b/test/prism/fixtures/whitequark/pattern_matching_else.txt
@@ -0,0 +1 @@
+case 1; in 2; 3; else; 4; end
diff --git a/test/prism/fixtures/whitequark/pattern_matching_single_line.txt b/test/prism/fixtures/whitequark/pattern_matching_single_line.txt
new file mode 100644
index 0000000000..12279afa24
--- /dev/null
+++ b/test/prism/fixtures/whitequark/pattern_matching_single_line.txt
@@ -0,0 +1,3 @@
+1 => [a]; a
+
+1 in [a]; a
diff --git a/test/prism/fixtures/whitequark/pattern_matching_single_line_allowed_omission_of_parentheses.txt b/test/prism/fixtures/whitequark/pattern_matching_single_line_allowed_omission_of_parentheses.txt
new file mode 100644
index 0000000000..1e429335d0
--- /dev/null
+++ b/test/prism/fixtures/whitequark/pattern_matching_single_line_allowed_omission_of_parentheses.txt
@@ -0,0 +1,11 @@
+[1, 2] => a, b; a
+
+[1, 2] in a, b; a
+
+{a: 1} => a:; a
+
+{a: 1} in a:; a
+
+{key: :value} => key: value; value
+
+{key: :value} in key: value; value
diff --git a/test/prism/fixtures/whitequark/postexe.txt b/test/prism/fixtures/whitequark/postexe.txt
new file mode 100644
index 0000000000..baee33af66
--- /dev/null
+++ b/test/prism/fixtures/whitequark/postexe.txt
@@ -0,0 +1 @@
+END { 1 }
diff --git a/test/prism/fixtures/whitequark/preexe.txt b/test/prism/fixtures/whitequark/preexe.txt
new file mode 100644
index 0000000000..9e802f3f4e
--- /dev/null
+++ b/test/prism/fixtures/whitequark/preexe.txt
@@ -0,0 +1 @@
+BEGIN { 1 }
diff --git a/test/prism/fixtures/whitequark/procarg0.txt b/test/prism/fixtures/whitequark/procarg0.txt
new file mode 100644
index 0000000000..74cae2c2eb
--- /dev/null
+++ b/test/prism/fixtures/whitequark/procarg0.txt
@@ -0,0 +1,3 @@
+m { |(foo, bar)| }
+
+m { |foo| }
diff --git a/test/prism/fixtures/whitequark/range_exclusive.txt b/test/prism/fixtures/whitequark/range_exclusive.txt
new file mode 100644
index 0000000000..9e07faed27
--- /dev/null
+++ b/test/prism/fixtures/whitequark/range_exclusive.txt
@@ -0,0 +1 @@
+1...2
diff --git a/test/prism/fixtures/whitequark/range_inclusive.txt b/test/prism/fixtures/whitequark/range_inclusive.txt
new file mode 100644
index 0000000000..8c12abf7de
--- /dev/null
+++ b/test/prism/fixtures/whitequark/range_inclusive.txt
@@ -0,0 +1 @@
+1..2
diff --git a/test/prism/fixtures/whitequark/rational.txt b/test/prism/fixtures/whitequark/rational.txt
new file mode 100644
index 0000000000..e11cacc742
--- /dev/null
+++ b/test/prism/fixtures/whitequark/rational.txt
@@ -0,0 +1,3 @@
+42.1r
+
+42r
diff --git a/test/prism/fixtures/whitequark/regex_interp.txt b/test/prism/fixtures/whitequark/regex_interp.txt
new file mode 100644
index 0000000000..f9ad7fcbc8
--- /dev/null
+++ b/test/prism/fixtures/whitequark/regex_interp.txt
@@ -0,0 +1 @@
+/foo#{bar}baz/
diff --git a/test/prism/fixtures/whitequark/regex_plain.txt b/test/prism/fixtures/whitequark/regex_plain.txt
new file mode 100644
index 0000000000..b86faecf98
--- /dev/null
+++ b/test/prism/fixtures/whitequark/regex_plain.txt
@@ -0,0 +1 @@
+/source/im
diff --git a/test/prism/fixtures/whitequark/resbody_list.txt b/test/prism/fixtures/whitequark/resbody_list.txt
new file mode 100644
index 0000000000..e40d45fc45
--- /dev/null
+++ b/test/prism/fixtures/whitequark/resbody_list.txt
@@ -0,0 +1 @@
+begin; meth; rescue Exception; bar; end
diff --git a/test/prism/fixtures/whitequark/resbody_list_mrhs.txt b/test/prism/fixtures/whitequark/resbody_list_mrhs.txt
new file mode 100644
index 0000000000..92b8bb2c02
--- /dev/null
+++ b/test/prism/fixtures/whitequark/resbody_list_mrhs.txt
@@ -0,0 +1 @@
+begin; meth; rescue Exception, foo; bar; end
diff --git a/test/prism/fixtures/whitequark/resbody_list_var.txt b/test/prism/fixtures/whitequark/resbody_list_var.txt
new file mode 100644
index 0000000000..0a2fb90b6d
--- /dev/null
+++ b/test/prism/fixtures/whitequark/resbody_list_var.txt
@@ -0,0 +1 @@
+begin; meth; rescue foo => ex; bar; end
diff --git a/test/prism/fixtures/whitequark/resbody_var.txt b/test/prism/fixtures/whitequark/resbody_var.txt
new file mode 100644
index 0000000000..2104ac58e7
--- /dev/null
+++ b/test/prism/fixtures/whitequark/resbody_var.txt
@@ -0,0 +1,3 @@
+begin; meth; rescue => @ex; bar; end
+
+begin; meth; rescue => ex; bar; end
diff --git a/test/prism/fixtures/whitequark/rescue.txt b/test/prism/fixtures/whitequark/rescue.txt
new file mode 100644
index 0000000000..2d3be9dc56
--- /dev/null
+++ b/test/prism/fixtures/whitequark/rescue.txt
@@ -0,0 +1 @@
+begin; meth; rescue; foo; end
diff --git a/test/prism/fixtures/whitequark/rescue_else.txt b/test/prism/fixtures/whitequark/rescue_else.txt
new file mode 100644
index 0000000000..a22f8d100e
--- /dev/null
+++ b/test/prism/fixtures/whitequark/rescue_else.txt
@@ -0,0 +1 @@
+begin; meth; rescue; foo; else; bar; end
diff --git a/test/prism/fixtures/whitequark/rescue_else_ensure.txt b/test/prism/fixtures/whitequark/rescue_else_ensure.txt
new file mode 100644
index 0000000000..167eee194a
--- /dev/null
+++ b/test/prism/fixtures/whitequark/rescue_else_ensure.txt
@@ -0,0 +1 @@
+begin; meth; rescue; baz; else foo; ensure; bar end
diff --git a/test/prism/fixtures/whitequark/rescue_ensure.txt b/test/prism/fixtures/whitequark/rescue_ensure.txt
new file mode 100644
index 0000000000..8237257c41
--- /dev/null
+++ b/test/prism/fixtures/whitequark/rescue_ensure.txt
@@ -0,0 +1 @@
+begin; meth; rescue; baz; ensure; bar; end
diff --git a/test/prism/fixtures/whitequark/rescue_in_lambda_block.txt b/test/prism/fixtures/whitequark/rescue_in_lambda_block.txt
new file mode 100644
index 0000000000..ccd8ed72c5
--- /dev/null
+++ b/test/prism/fixtures/whitequark/rescue_in_lambda_block.txt
@@ -0,0 +1 @@
+-> do rescue; end
diff --git a/test/prism/fixtures/whitequark/rescue_mod.txt b/test/prism/fixtures/whitequark/rescue_mod.txt
new file mode 100644
index 0000000000..06375d3e9b
--- /dev/null
+++ b/test/prism/fixtures/whitequark/rescue_mod.txt
@@ -0,0 +1 @@
+meth rescue bar
diff --git a/test/prism/fixtures/whitequark/rescue_mod_asgn.txt b/test/prism/fixtures/whitequark/rescue_mod_asgn.txt
new file mode 100644
index 0000000000..abf7cd9a3d
--- /dev/null
+++ b/test/prism/fixtures/whitequark/rescue_mod_asgn.txt
@@ -0,0 +1 @@
+foo = meth rescue bar
diff --git a/test/prism/fixtures/whitequark/rescue_mod_masgn.txt b/test/prism/fixtures/whitequark/rescue_mod_masgn.txt
new file mode 100644
index 0000000000..0716eb1f67
--- /dev/null
+++ b/test/prism/fixtures/whitequark/rescue_mod_masgn.txt
@@ -0,0 +1 @@
+foo, bar = meth rescue [1, 2]
diff --git a/test/prism/fixtures/whitequark/rescue_mod_op_assign.txt b/test/prism/fixtures/whitequark/rescue_mod_op_assign.txt
new file mode 100644
index 0000000000..178efa3a20
--- /dev/null
+++ b/test/prism/fixtures/whitequark/rescue_mod_op_assign.txt
@@ -0,0 +1 @@
+foo += meth rescue bar
diff --git a/test/prism/fixtures/whitequark/rescue_without_begin_end.txt b/test/prism/fixtures/whitequark/rescue_without_begin_end.txt
new file mode 100644
index 0000000000..8416569e2c
--- /dev/null
+++ b/test/prism/fixtures/whitequark/rescue_without_begin_end.txt
@@ -0,0 +1 @@
+meth do; foo; rescue; bar; end
diff --git a/test/prism/fixtures/whitequark/restarg_named.txt b/test/prism/fixtures/whitequark/restarg_named.txt
new file mode 100644
index 0000000000..355cd8f493
--- /dev/null
+++ b/test/prism/fixtures/whitequark/restarg_named.txt
@@ -0,0 +1 @@
+def f(*foo); end
diff --git a/test/prism/fixtures/whitequark/restarg_unnamed.txt b/test/prism/fixtures/whitequark/restarg_unnamed.txt
new file mode 100644
index 0000000000..c9932dd30c
--- /dev/null
+++ b/test/prism/fixtures/whitequark/restarg_unnamed.txt
@@ -0,0 +1 @@
+def f(*); end
diff --git a/test/prism/fixtures/whitequark/return.txt b/test/prism/fixtures/whitequark/return.txt
new file mode 100644
index 0000000000..e3d966bda0
--- /dev/null
+++ b/test/prism/fixtures/whitequark/return.txt
@@ -0,0 +1,7 @@
+return
+
+return foo
+
+return()
+
+return(foo)
diff --git a/test/prism/fixtures/whitequark/return_block.txt b/test/prism/fixtures/whitequark/return_block.txt
new file mode 100644
index 0000000000..00723a7517
--- /dev/null
+++ b/test/prism/fixtures/whitequark/return_block.txt
@@ -0,0 +1 @@
+return fun foo do end
diff --git a/test/prism/fixtures/whitequark/ruby_bug_10279.txt b/test/prism/fixtures/whitequark/ruby_bug_10279.txt
new file mode 100644
index 0000000000..4d0fb213d8
--- /dev/null
+++ b/test/prism/fixtures/whitequark/ruby_bug_10279.txt
@@ -0,0 +1 @@
+{a: if true then 42 end}
diff --git a/test/prism/fixtures/whitequark/ruby_bug_10653.txt b/test/prism/fixtures/whitequark/ruby_bug_10653.txt
new file mode 100644
index 0000000000..51354a1f70
--- /dev/null
+++ b/test/prism/fixtures/whitequark/ruby_bug_10653.txt
@@ -0,0 +1,5 @@
+false ? raise do end : tap do end
+
+false ? raise {} : tap {}
+
+true ? 1.tap do |n| p n end : 0
diff --git a/test/prism/fixtures/whitequark/ruby_bug_11107.txt b/test/prism/fixtures/whitequark/ruby_bug_11107.txt
new file mode 100644
index 0000000000..1f28cb06f6
--- /dev/null
+++ b/test/prism/fixtures/whitequark/ruby_bug_11107.txt
@@ -0,0 +1 @@
+p ->() do a() do end end
diff --git a/test/prism/fixtures/whitequark/ruby_bug_11380.txt b/test/prism/fixtures/whitequark/ruby_bug_11380.txt
new file mode 100644
index 0000000000..1631548e3a
--- /dev/null
+++ b/test/prism/fixtures/whitequark/ruby_bug_11380.txt
@@ -0,0 +1 @@
+p -> { :hello }, a: 1 do end
diff --git a/test/prism/fixtures/whitequark/ruby_bug_11873.txt b/test/prism/fixtures/whitequark/ruby_bug_11873.txt
new file mode 100644
index 0000000000..a25aa9e267
--- /dev/null
+++ b/test/prism/fixtures/whitequark/ruby_bug_11873.txt
@@ -0,0 +1,23 @@
+a b(c d), "x" do end
+
+a b(c d), /x/ do end
+
+a b(c d), /x/m do end
+
+a b(c(d)), "x" do end
+
+a b(c(d)), /x/ do end
+
+a b(c(d)), /x/m do end
+
+a b{c d}, "x" do end
+
+a b{c d}, /x/ do end
+
+a b{c d}, /x/m do end
+
+a b{c(d)}, "x" do end
+
+a b{c(d)}, /x/ do end
+
+a b{c(d)}, /x/m do end
diff --git a/test/prism/fixtures/whitequark/ruby_bug_11873_a.txt b/test/prism/fixtures/whitequark/ruby_bug_11873_a.txt
new file mode 100644
index 0000000000..1856235ce5
--- /dev/null
+++ b/test/prism/fixtures/whitequark/ruby_bug_11873_a.txt
@@ -0,0 +1,39 @@
+a b(c d), 1 do end
+
+a b(c d), 1.0 do end
+
+a b(c d), 1.0i do end
+
+a b(c d), 1.0r do end
+
+a b(c d), :e do end
+
+a b(c(d)), 1 do end
+
+a b(c(d)), 1.0 do end
+
+a b(c(d)), 1.0i do end
+
+a b(c(d)), 1.0r do end
+
+a b(c(d)), :e do end
+
+a b{c d}, 1 do end
+
+a b{c d}, 1.0 do end
+
+a b{c d}, 1.0i do end
+
+a b{c d}, 1.0r do end
+
+a b{c d}, :e do end
+
+a b{c(d)}, 1 do end
+
+a b{c(d)}, 1.0 do end
+
+a b{c(d)}, 1.0i do end
+
+a b{c(d)}, 1.0r do end
+
+a b{c(d)}, :e do end
diff --git a/test/prism/fixtures/whitequark/ruby_bug_11873_b.txt b/test/prism/fixtures/whitequark/ruby_bug_11873_b.txt
new file mode 100644
index 0000000000..1b86662008
--- /dev/null
+++ b/test/prism/fixtures/whitequark/ruby_bug_11873_b.txt
@@ -0,0 +1 @@
+p p{p(p);p p}, tap do end
diff --git a/test/prism/fixtures/whitequark/ruby_bug_11989.txt b/test/prism/fixtures/whitequark/ruby_bug_11989.txt
new file mode 100644
index 0000000000..d49b8614ed
--- /dev/null
+++ b/test/prism/fixtures/whitequark/ruby_bug_11989.txt
@@ -0,0 +1,3 @@
+p <<~"E"
+ x\n y
+E
diff --git a/test/prism/fixtures/whitequark/ruby_bug_11990.txt b/test/prism/fixtures/whitequark/ruby_bug_11990.txt
new file mode 100644
index 0000000000..d0fe7b2739
--- /dev/null
+++ b/test/prism/fixtures/whitequark/ruby_bug_11990.txt
@@ -0,0 +1,3 @@
+p <<~E " y"
+ x
+E
diff --git a/test/prism/fixtures/whitequark/ruby_bug_12073.txt b/test/prism/fixtures/whitequark/ruby_bug_12073.txt
new file mode 100644
index 0000000000..b2e3784422
--- /dev/null
+++ b/test/prism/fixtures/whitequark/ruby_bug_12073.txt
@@ -0,0 +1,3 @@
+a = 1; a b: 1
+
+def foo raise; raise A::B, ''; end
diff --git a/test/prism/fixtures/whitequark/ruby_bug_12402.txt b/test/prism/fixtures/whitequark/ruby_bug_12402.txt
new file mode 100644
index 0000000000..060d5d95a1
--- /dev/null
+++ b/test/prism/fixtures/whitequark/ruby_bug_12402.txt
@@ -0,0 +1,27 @@
+foo += raise bar rescue nil
+
+foo += raise(bar) rescue nil
+
+foo = raise bar rescue nil
+
+foo = raise(bar) rescue nil
+
+foo.C += raise bar rescue nil
+
+foo.C += raise(bar) rescue nil
+
+foo.m += raise bar rescue nil
+
+foo.m += raise(bar) rescue nil
+
+foo::C ||= raise bar rescue nil
+
+foo::C ||= raise(bar) rescue nil
+
+foo::m += raise bar rescue nil
+
+foo::m += raise(bar) rescue nil
+
+foo[0] += raise bar rescue nil
+
+foo[0] += raise(bar) rescue nil
diff --git a/test/prism/fixtures/whitequark/ruby_bug_12669.txt b/test/prism/fixtures/whitequark/ruby_bug_12669.txt
new file mode 100644
index 0000000000..cd89689446
--- /dev/null
+++ b/test/prism/fixtures/whitequark/ruby_bug_12669.txt
@@ -0,0 +1,7 @@
+a += b += raise :x
+
+a += b = raise :x
+
+a = b += raise :x
+
+a = b = raise :x
diff --git a/test/prism/fixtures/whitequark/ruby_bug_12686.txt b/test/prism/fixtures/whitequark/ruby_bug_12686.txt
new file mode 100644
index 0000000000..7742e791b8
--- /dev/null
+++ b/test/prism/fixtures/whitequark/ruby_bug_12686.txt
@@ -0,0 +1 @@
+f (g rescue nil)
diff --git a/test/prism/fixtures/whitequark/ruby_bug_13547.txt b/test/prism/fixtures/whitequark/ruby_bug_13547.txt
new file mode 100644
index 0000000000..29eafc3a4c
--- /dev/null
+++ b/test/prism/fixtures/whitequark/ruby_bug_13547.txt
@@ -0,0 +1 @@
+meth[] {}
diff --git a/test/prism/fixtures/whitequark/ruby_bug_14690.txt b/test/prism/fixtures/whitequark/ruby_bug_14690.txt
new file mode 100644
index 0000000000..b73b1d8aad
--- /dev/null
+++ b/test/prism/fixtures/whitequark/ruby_bug_14690.txt
@@ -0,0 +1 @@
+let () { m(a) do; end }
diff --git a/test/prism/fixtures/whitequark/ruby_bug_15789.txt b/test/prism/fixtures/whitequark/ruby_bug_15789.txt
new file mode 100644
index 0000000000..6324db5110
--- /dev/null
+++ b/test/prism/fixtures/whitequark/ruby_bug_15789.txt
@@ -0,0 +1,3 @@
+m ->(a = ->{_1}) {a}
+
+m ->(a: ->{_1}) {a}
diff --git a/test/prism/fixtures/whitequark/ruby_bug_9669.txt b/test/prism/fixtures/whitequark/ruby_bug_9669.txt
new file mode 100644
index 0000000000..60dfa09d51
--- /dev/null
+++ b/test/prism/fixtures/whitequark/ruby_bug_9669.txt
@@ -0,0 +1,8 @@
+def a b:
+return
+end
+
+o = {
+a:
+1
+}
diff --git a/test/prism/fixtures/whitequark/sclass.txt b/test/prism/fixtures/whitequark/sclass.txt
new file mode 100644
index 0000000000..e6aadaef21
--- /dev/null
+++ b/test/prism/fixtures/whitequark/sclass.txt
@@ -0,0 +1 @@
+class << foo; nil; end
diff --git a/test/prism/fixtures/whitequark/self.txt b/test/prism/fixtures/whitequark/self.txt
new file mode 100644
index 0000000000..31f9efa4a1
--- /dev/null
+++ b/test/prism/fixtures/whitequark/self.txt
@@ -0,0 +1 @@
+self
diff --git a/test/prism/fixtures/whitequark/send_attr_asgn.txt b/test/prism/fixtures/whitequark/send_attr_asgn.txt
new file mode 100644
index 0000000000..b477966b2a
--- /dev/null
+++ b/test/prism/fixtures/whitequark/send_attr_asgn.txt
@@ -0,0 +1,7 @@
+foo.A = 1
+
+foo.a = 1
+
+foo::A = 1
+
+foo::a = 1
diff --git a/test/prism/fixtures/whitequark/send_attr_asgn_conditional.txt b/test/prism/fixtures/whitequark/send_attr_asgn_conditional.txt
new file mode 100644
index 0000000000..1279e02cfc
--- /dev/null
+++ b/test/prism/fixtures/whitequark/send_attr_asgn_conditional.txt
@@ -0,0 +1 @@
+a&.b = 1
diff --git a/test/prism/fixtures/whitequark/send_binary_op.txt b/test/prism/fixtures/whitequark/send_binary_op.txt
new file mode 100644
index 0000000000..3e3e9300b3
--- /dev/null
+++ b/test/prism/fixtures/whitequark/send_binary_op.txt
@@ -0,0 +1,41 @@
+foo != 1
+
+foo !~ 1
+
+foo % 1
+
+foo & 1
+
+foo * 1
+
+foo ** 1
+
+foo + 1
+
+foo - 1
+
+foo / 1
+
+foo < 1
+
+foo << 1
+
+foo <= 1
+
+foo <=> 1
+
+foo == 1
+
+foo === 1
+
+foo =~ 1
+
+foo > 1
+
+foo >= 1
+
+foo >> 1
+
+foo ^ 1
+
+foo | 1
diff --git a/test/prism/fixtures/whitequark/send_block_chain_cmd.txt b/test/prism/fixtures/whitequark/send_block_chain_cmd.txt
new file mode 100644
index 0000000000..c6fe1aab0e
--- /dev/null
+++ b/test/prism/fixtures/whitequark/send_block_chain_cmd.txt
@@ -0,0 +1,13 @@
+meth 1 do end.fun bar
+
+meth 1 do end.fun bar do end
+
+meth 1 do end.fun {}
+
+meth 1 do end.fun(bar)
+
+meth 1 do end.fun(bar) {}
+
+meth 1 do end::fun bar
+
+meth 1 do end::fun(bar)
diff --git a/test/prism/fixtures/whitequark/send_block_conditional.txt b/test/prism/fixtures/whitequark/send_block_conditional.txt
new file mode 100644
index 0000000000..dcc8361762
--- /dev/null
+++ b/test/prism/fixtures/whitequark/send_block_conditional.txt
@@ -0,0 +1 @@
+foo&.bar {}
diff --git a/test/prism/fixtures/whitequark/send_call.txt b/test/prism/fixtures/whitequark/send_call.txt
new file mode 100644
index 0000000000..99701270bb
--- /dev/null
+++ b/test/prism/fixtures/whitequark/send_call.txt
@@ -0,0 +1,3 @@
+foo.(1)
+
+foo::(1)
diff --git a/test/prism/fixtures/whitequark/send_conditional.txt b/test/prism/fixtures/whitequark/send_conditional.txt
new file mode 100644
index 0000000000..8ecd27e0fe
--- /dev/null
+++ b/test/prism/fixtures/whitequark/send_conditional.txt
@@ -0,0 +1 @@
+a&.b
diff --git a/test/prism/fixtures/whitequark/send_index.txt b/test/prism/fixtures/whitequark/send_index.txt
new file mode 100644
index 0000000000..f9c4dafc4e
--- /dev/null
+++ b/test/prism/fixtures/whitequark/send_index.txt
@@ -0,0 +1 @@
+foo[1, 2]
diff --git a/test/prism/fixtures/whitequark/send_index_asgn.txt b/test/prism/fixtures/whitequark/send_index_asgn.txt
new file mode 100644
index 0000000000..e232fa3b96
--- /dev/null
+++ b/test/prism/fixtures/whitequark/send_index_asgn.txt
@@ -0,0 +1 @@
+foo[1, 2] = 3
diff --git a/test/prism/fixtures/whitequark/send_index_asgn_legacy.txt b/test/prism/fixtures/whitequark/send_index_asgn_legacy.txt
new file mode 100644
index 0000000000..e232fa3b96
--- /dev/null
+++ b/test/prism/fixtures/whitequark/send_index_asgn_legacy.txt
@@ -0,0 +1 @@
+foo[1, 2] = 3
diff --git a/test/prism/fixtures/whitequark/send_index_cmd.txt b/test/prism/fixtures/whitequark/send_index_cmd.txt
new file mode 100644
index 0000000000..32090e7536
--- /dev/null
+++ b/test/prism/fixtures/whitequark/send_index_cmd.txt
@@ -0,0 +1 @@
+foo[m bar]
diff --git a/test/prism/fixtures/whitequark/send_index_legacy.txt b/test/prism/fixtures/whitequark/send_index_legacy.txt
new file mode 100644
index 0000000000..f9c4dafc4e
--- /dev/null
+++ b/test/prism/fixtures/whitequark/send_index_legacy.txt
@@ -0,0 +1 @@
+foo[1, 2]
diff --git a/test/prism/fixtures/whitequark/send_lambda.txt b/test/prism/fixtures/whitequark/send_lambda.txt
new file mode 100644
index 0000000000..eadd6c9c03
--- /dev/null
+++ b/test/prism/fixtures/whitequark/send_lambda.txt
@@ -0,0 +1,5 @@
+-> * { }
+
+-> do end
+
+->{ }
diff --git a/test/prism/fixtures/whitequark/send_lambda_args.txt b/test/prism/fixtures/whitequark/send_lambda_args.txt
new file mode 100644
index 0000000000..68392f2f34
--- /dev/null
+++ b/test/prism/fixtures/whitequark/send_lambda_args.txt
@@ -0,0 +1,3 @@
+-> (a) { }
+
+->(a) { }
diff --git a/test/prism/fixtures/whitequark/send_lambda_args_noparen.txt b/test/prism/fixtures/whitequark/send_lambda_args_noparen.txt
new file mode 100644
index 0000000000..c0ae077f95
--- /dev/null
+++ b/test/prism/fixtures/whitequark/send_lambda_args_noparen.txt
@@ -0,0 +1,3 @@
+-> a: 1 { }
+
+-> a: { }
diff --git a/test/prism/fixtures/whitequark/send_lambda_args_shadow.txt b/test/prism/fixtures/whitequark/send_lambda_args_shadow.txt
new file mode 100644
index 0000000000..230f35ab89
--- /dev/null
+++ b/test/prism/fixtures/whitequark/send_lambda_args_shadow.txt
@@ -0,0 +1 @@
+->(a; foo, bar) { }
diff --git a/test/prism/fixtures/whitequark/send_lambda_legacy.txt b/test/prism/fixtures/whitequark/send_lambda_legacy.txt
new file mode 100644
index 0000000000..a509407c43
--- /dev/null
+++ b/test/prism/fixtures/whitequark/send_lambda_legacy.txt
@@ -0,0 +1 @@
+->{ }
diff --git a/test/prism/fixtures/whitequark/send_op_asgn_conditional.txt b/test/prism/fixtures/whitequark/send_op_asgn_conditional.txt
new file mode 100644
index 0000000000..906088dcd1
--- /dev/null
+++ b/test/prism/fixtures/whitequark/send_op_asgn_conditional.txt
@@ -0,0 +1 @@
+a&.b &&= 1
diff --git a/test/prism/fixtures/whitequark/send_plain.txt b/test/prism/fixtures/whitequark/send_plain.txt
new file mode 100644
index 0000000000..ebaf1d18c7
--- /dev/null
+++ b/test/prism/fixtures/whitequark/send_plain.txt
@@ -0,0 +1,5 @@
+foo.fun
+
+foo::Fun()
+
+foo::fun
diff --git a/test/prism/fixtures/whitequark/send_plain_cmd.txt b/test/prism/fixtures/whitequark/send_plain_cmd.txt
new file mode 100644
index 0000000000..e3fd63f272
--- /dev/null
+++ b/test/prism/fixtures/whitequark/send_plain_cmd.txt
@@ -0,0 +1,5 @@
+foo.fun bar
+
+foo::Fun bar
+
+foo::fun bar
diff --git a/test/prism/fixtures/whitequark/send_self.txt b/test/prism/fixtures/whitequark/send_self.txt
new file mode 100644
index 0000000000..f084b9bca7
--- /dev/null
+++ b/test/prism/fixtures/whitequark/send_self.txt
@@ -0,0 +1,5 @@
+fun
+
+fun!
+
+fun(1)
diff --git a/test/prism/fixtures/whitequark/send_self_block.txt b/test/prism/fixtures/whitequark/send_self_block.txt
new file mode 100644
index 0000000000..1cd6703c82
--- /dev/null
+++ b/test/prism/fixtures/whitequark/send_self_block.txt
@@ -0,0 +1,7 @@
+fun do end
+
+fun { }
+
+fun() { }
+
+fun(1) { }
diff --git a/test/prism/fixtures/whitequark/send_unary_op.txt b/test/prism/fixtures/whitequark/send_unary_op.txt
new file mode 100644
index 0000000000..73814d199f
--- /dev/null
+++ b/test/prism/fixtures/whitequark/send_unary_op.txt
@@ -0,0 +1,5 @@
++foo
+
+-foo
+
+~foo
diff --git a/test/prism/fixtures/whitequark/slash_newline_in_heredocs.txt b/test/prism/fixtures/whitequark/slash_newline_in_heredocs.txt
new file mode 100644
index 0000000000..4962a058ea
--- /dev/null
+++ b/test/prism/fixtures/whitequark/slash_newline_in_heredocs.txt
@@ -0,0 +1,13 @@
+<<-E
+ 1 \
+ 2
+ 3
+E
+
+
+<<~E
+ 1 \
+ 2
+ 3
+E
+
diff --git a/test/prism/fixtures/whitequark/space_args_arg.txt b/test/prism/fixtures/whitequark/space_args_arg.txt
new file mode 100644
index 0000000000..47957cba54
--- /dev/null
+++ b/test/prism/fixtures/whitequark/space_args_arg.txt
@@ -0,0 +1 @@
+fun (1)
diff --git a/test/prism/fixtures/whitequark/space_args_arg_block.txt b/test/prism/fixtures/whitequark/space_args_arg_block.txt
new file mode 100644
index 0000000000..5560a82818
--- /dev/null
+++ b/test/prism/fixtures/whitequark/space_args_arg_block.txt
@@ -0,0 +1,5 @@
+foo.fun (1) {}
+
+foo::fun (1) {}
+
+fun (1) {}
diff --git a/test/prism/fixtures/whitequark/space_args_arg_call.txt b/test/prism/fixtures/whitequark/space_args_arg_call.txt
new file mode 100644
index 0000000000..3b0ae831fe
--- /dev/null
+++ b/test/prism/fixtures/whitequark/space_args_arg_call.txt
@@ -0,0 +1 @@
+fun (1).to_i
diff --git a/test/prism/fixtures/whitequark/space_args_arg_newline.txt b/test/prism/fixtures/whitequark/space_args_arg_newline.txt
new file mode 100644
index 0000000000..a6cdac6ed1
--- /dev/null
+++ b/test/prism/fixtures/whitequark/space_args_arg_newline.txt
@@ -0,0 +1,2 @@
+fun (1
+)
diff --git a/test/prism/fixtures/whitequark/space_args_block.txt b/test/prism/fixtures/whitequark/space_args_block.txt
new file mode 100644
index 0000000000..555a097605
--- /dev/null
+++ b/test/prism/fixtures/whitequark/space_args_block.txt
@@ -0,0 +1 @@
+fun () {}
diff --git a/test/prism/fixtures/whitequark/space_args_cmd.txt b/test/prism/fixtures/whitequark/space_args_cmd.txt
new file mode 100644
index 0000000000..a749695cb7
--- /dev/null
+++ b/test/prism/fixtures/whitequark/space_args_cmd.txt
@@ -0,0 +1 @@
+fun (f bar)
diff --git a/test/prism/fixtures/whitequark/string___FILE__.txt b/test/prism/fixtures/whitequark/string___FILE__.txt
new file mode 100644
index 0000000000..4815727d05
--- /dev/null
+++ b/test/prism/fixtures/whitequark/string___FILE__.txt
@@ -0,0 +1 @@
+__FILE__
diff --git a/test/prism/fixtures/whitequark/string_concat.txt b/test/prism/fixtures/whitequark/string_concat.txt
new file mode 100644
index 0000000000..30cc4f8116
--- /dev/null
+++ b/test/prism/fixtures/whitequark/string_concat.txt
@@ -0,0 +1 @@
+"foo#@a" "bar"
diff --git a/test/prism/fixtures/whitequark/string_dvar.txt b/test/prism/fixtures/whitequark/string_dvar.txt
new file mode 100644
index 0000000000..bbe5b617b2
--- /dev/null
+++ b/test/prism/fixtures/whitequark/string_dvar.txt
@@ -0,0 +1 @@
+"#@a #@@a #$a"
diff --git a/test/prism/fixtures/whitequark/string_interp.txt b/test/prism/fixtures/whitequark/string_interp.txt
new file mode 100644
index 0000000000..5fdd803341
--- /dev/null
+++ b/test/prism/fixtures/whitequark/string_interp.txt
@@ -0,0 +1 @@
+"foo#{bar}baz"
diff --git a/test/prism/fixtures/whitequark/string_plain.txt b/test/prism/fixtures/whitequark/string_plain.txt
new file mode 100644
index 0000000000..4aca78decb
--- /dev/null
+++ b/test/prism/fixtures/whitequark/string_plain.txt
@@ -0,0 +1,3 @@
+%q(foobar)
+
+'foobar'
diff --git a/test/prism/fixtures/whitequark/super.txt b/test/prism/fixtures/whitequark/super.txt
new file mode 100644
index 0000000000..9e68a9e988
--- /dev/null
+++ b/test/prism/fixtures/whitequark/super.txt
@@ -0,0 +1,5 @@
+super foo
+
+super()
+
+super(foo)
diff --git a/test/prism/fixtures/whitequark/super_block.txt b/test/prism/fixtures/whitequark/super_block.txt
new file mode 100644
index 0000000000..05a7d7fdd8
--- /dev/null
+++ b/test/prism/fixtures/whitequark/super_block.txt
@@ -0,0 +1,3 @@
+super do end
+
+super foo, bar do end
diff --git a/test/prism/fixtures/whitequark/symbol_interp.txt b/test/prism/fixtures/whitequark/symbol_interp.txt
new file mode 100644
index 0000000000..d5011b270d
--- /dev/null
+++ b/test/prism/fixtures/whitequark/symbol_interp.txt
@@ -0,0 +1 @@
+:"foo#{bar}baz"
diff --git a/test/prism/fixtures/whitequark/symbol_plain.txt b/test/prism/fixtures/whitequark/symbol_plain.txt
new file mode 100644
index 0000000000..fd1fd0017c
--- /dev/null
+++ b/test/prism/fixtures/whitequark/symbol_plain.txt
@@ -0,0 +1,3 @@
+:'foo'
+
+:foo
diff --git a/test/prism/fixtures/whitequark/ternary.txt b/test/prism/fixtures/whitequark/ternary.txt
new file mode 100644
index 0000000000..3a149d4e1c
--- /dev/null
+++ b/test/prism/fixtures/whitequark/ternary.txt
@@ -0,0 +1 @@
+foo ? 1 : 2
diff --git a/test/prism/fixtures/whitequark/ternary_ambiguous_symbol.txt b/test/prism/fixtures/whitequark/ternary_ambiguous_symbol.txt
new file mode 100644
index 0000000000..19aa523c07
--- /dev/null
+++ b/test/prism/fixtures/whitequark/ternary_ambiguous_symbol.txt
@@ -0,0 +1 @@
+t=1;(foo)?t:T
diff --git a/test/prism/fixtures/whitequark/trailing_forward_arg.txt b/test/prism/fixtures/whitequark/trailing_forward_arg.txt
new file mode 100644
index 0000000000..043870ade2
--- /dev/null
+++ b/test/prism/fixtures/whitequark/trailing_forward_arg.txt
@@ -0,0 +1 @@
+def foo(a, b, ...); bar(a, 42, ...); end
diff --git a/test/prism/fixtures/whitequark/true.txt b/test/prism/fixtures/whitequark/true.txt
new file mode 100644
index 0000000000..27ba77ddaf
--- /dev/null
+++ b/test/prism/fixtures/whitequark/true.txt
@@ -0,0 +1 @@
+true
diff --git a/test/prism/fixtures/whitequark/unary_num_pow_precedence.txt b/test/prism/fixtures/whitequark/unary_num_pow_precedence.txt
new file mode 100644
index 0000000000..f0343e3c8b
--- /dev/null
+++ b/test/prism/fixtures/whitequark/unary_num_pow_precedence.txt
@@ -0,0 +1,5 @@
++2.0 ** 10
+
+-2 ** 10
+
+-2.0 ** 10
diff --git a/test/prism/fixtures/whitequark/undef.txt b/test/prism/fixtures/whitequark/undef.txt
new file mode 100644
index 0000000000..3e88ec7084
--- /dev/null
+++ b/test/prism/fixtures/whitequark/undef.txt
@@ -0,0 +1 @@
+undef foo, :bar, :"foo#{1}"
diff --git a/test/prism/fixtures/whitequark/unless.txt b/test/prism/fixtures/whitequark/unless.txt
new file mode 100644
index 0000000000..d04043ed90
--- /dev/null
+++ b/test/prism/fixtures/whitequark/unless.txt
@@ -0,0 +1,3 @@
+unless foo then bar; end
+
+unless foo; bar; end
diff --git a/test/prism/fixtures/whitequark/unless_else.txt b/test/prism/fixtures/whitequark/unless_else.txt
new file mode 100644
index 0000000000..8243d42031
--- /dev/null
+++ b/test/prism/fixtures/whitequark/unless_else.txt
@@ -0,0 +1,3 @@
+unless foo then bar; else baz; end
+
+unless foo; bar; else baz; end
diff --git a/test/prism/fixtures/whitequark/unless_mod.txt b/test/prism/fixtures/whitequark/unless_mod.txt
new file mode 100644
index 0000000000..2d0376a310
--- /dev/null
+++ b/test/prism/fixtures/whitequark/unless_mod.txt
@@ -0,0 +1 @@
+bar unless foo
diff --git a/test/prism/fixtures/whitequark/until.txt b/test/prism/fixtures/whitequark/until.txt
new file mode 100644
index 0000000000..06082233cb
--- /dev/null
+++ b/test/prism/fixtures/whitequark/until.txt
@@ -0,0 +1,3 @@
+until foo do meth end
+
+until foo; meth end
diff --git a/test/prism/fixtures/whitequark/until_mod.txt b/test/prism/fixtures/whitequark/until_mod.txt
new file mode 100644
index 0000000000..46a85d2ba9
--- /dev/null
+++ b/test/prism/fixtures/whitequark/until_mod.txt
@@ -0,0 +1 @@
+meth until foo
diff --git a/test/prism/fixtures/whitequark/until_post.txt b/test/prism/fixtures/whitequark/until_post.txt
new file mode 100644
index 0000000000..988e43b665
--- /dev/null
+++ b/test/prism/fixtures/whitequark/until_post.txt
@@ -0,0 +1 @@
+begin meth end until foo
diff --git a/test/prism/fixtures/whitequark/var_and_asgn.txt b/test/prism/fixtures/whitequark/var_and_asgn.txt
new file mode 100644
index 0000000000..25502968f9
--- /dev/null
+++ b/test/prism/fixtures/whitequark/var_and_asgn.txt
@@ -0,0 +1 @@
+a &&= 1
diff --git a/test/prism/fixtures/whitequark/var_op_asgn.txt b/test/prism/fixtures/whitequark/var_op_asgn.txt
new file mode 100644
index 0000000000..402d818a7e
--- /dev/null
+++ b/test/prism/fixtures/whitequark/var_op_asgn.txt
@@ -0,0 +1,7 @@
+@@var |= 10
+
+@a |= 1
+
+a += 1
+
+def a; @@var |= 10; end
diff --git a/test/prism/fixtures/whitequark/var_op_asgn_cmd.txt b/test/prism/fixtures/whitequark/var_op_asgn_cmd.txt
new file mode 100644
index 0000000000..33f4bc0e73
--- /dev/null
+++ b/test/prism/fixtures/whitequark/var_op_asgn_cmd.txt
@@ -0,0 +1 @@
+foo += m foo
diff --git a/test/prism/fixtures/whitequark/var_or_asgn.txt b/test/prism/fixtures/whitequark/var_or_asgn.txt
new file mode 100644
index 0000000000..aa30b3d5ca
--- /dev/null
+++ b/test/prism/fixtures/whitequark/var_or_asgn.txt
@@ -0,0 +1 @@
+a ||= 1
diff --git a/test/prism/fixtures/whitequark/when_multi.txt b/test/prism/fixtures/whitequark/when_multi.txt
new file mode 100644
index 0000000000..b4fbd33125
--- /dev/null
+++ b/test/prism/fixtures/whitequark/when_multi.txt
@@ -0,0 +1 @@
+case foo; when 'bar', 'baz'; bar; end
diff --git a/test/prism/fixtures/whitequark/when_splat.txt b/test/prism/fixtures/whitequark/when_splat.txt
new file mode 100644
index 0000000000..695e5da34e
--- /dev/null
+++ b/test/prism/fixtures/whitequark/when_splat.txt
@@ -0,0 +1 @@
+case foo; when 1, *baz; bar; when *foo; end
diff --git a/test/prism/fixtures/whitequark/when_then.txt b/test/prism/fixtures/whitequark/when_then.txt
new file mode 100644
index 0000000000..63293452b3
--- /dev/null
+++ b/test/prism/fixtures/whitequark/when_then.txt
@@ -0,0 +1 @@
+case foo; when 'bar' then bar; end
diff --git a/test/prism/fixtures/whitequark/while.txt b/test/prism/fixtures/whitequark/while.txt
new file mode 100644
index 0000000000..28b204f247
--- /dev/null
+++ b/test/prism/fixtures/whitequark/while.txt
@@ -0,0 +1,3 @@
+while foo do meth end
+
+while foo; meth end
diff --git a/test/prism/fixtures/whitequark/while_mod.txt b/test/prism/fixtures/whitequark/while_mod.txt
new file mode 100644
index 0000000000..ce3cf01d14
--- /dev/null
+++ b/test/prism/fixtures/whitequark/while_mod.txt
@@ -0,0 +1 @@
+meth while foo
diff --git a/test/prism/fixtures/whitequark/while_post.txt b/test/prism/fixtures/whitequark/while_post.txt
new file mode 100644
index 0000000000..ac6e05008b
--- /dev/null
+++ b/test/prism/fixtures/whitequark/while_post.txt
@@ -0,0 +1 @@
+begin meth end while foo
diff --git a/test/prism/fixtures/whitequark/xstring_interp.txt b/test/prism/fixtures/whitequark/xstring_interp.txt
new file mode 100644
index 0000000000..dfede8123f
--- /dev/null
+++ b/test/prism/fixtures/whitequark/xstring_interp.txt
@@ -0,0 +1 @@
+`foo#{bar}baz`
diff --git a/test/prism/fixtures/whitequark/xstring_plain.txt b/test/prism/fixtures/whitequark/xstring_plain.txt
new file mode 100644
index 0000000000..fce255049d
--- /dev/null
+++ b/test/prism/fixtures/whitequark/xstring_plain.txt
@@ -0,0 +1 @@
+`foobar`
diff --git a/test/prism/fixtures/whitequark/zsuper.txt b/test/prism/fixtures/whitequark/zsuper.txt
new file mode 100644
index 0000000000..16f5c2d3aa
--- /dev/null
+++ b/test/prism/fixtures/whitequark/zsuper.txt
@@ -0,0 +1 @@
+super
diff --git a/test/prism/fixtures/xstring.txt b/test/prism/fixtures/xstring.txt
new file mode 100644
index 0000000000..7ec09468d8
--- /dev/null
+++ b/test/prism/fixtures/xstring.txt
@@ -0,0 +1,13 @@
+%x[foo]
+
+`foo #{bar} baz`
+
+`foo`
+
+%x{
+ foo
+}
+
+``
+
+%x{}
diff --git a/test/prism/fixtures/xstring_with_backslash.txt b/test/prism/fixtures/xstring_with_backslash.txt
new file mode 100644
index 0000000000..b51bb0f6f9
--- /dev/null
+++ b/test/prism/fixtures/xstring_with_backslash.txt
@@ -0,0 +1 @@
+`f\oo`
diff --git a/test/prism/fixtures/yield.txt b/test/prism/fixtures/yield.txt
new file mode 100644
index 0000000000..752ba27a2e
--- /dev/null
+++ b/test/prism/fixtures/yield.txt
@@ -0,0 +1,7 @@
+def foo; yield; end
+
+def foo; yield(); end
+
+def foo; yield(1); end
+
+def foo; yield(1, 2, 3); end
diff --git a/test/prism/fixtures_test.rb b/test/prism/fixtures_test.rb
new file mode 100644
index 0000000000..7225b4ac66
--- /dev/null
+++ b/test/prism/fixtures_test.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+return if RUBY_VERSION < "3.2.0"
+
+require_relative "test_helper"
+
+module Prism
+ class FixturesTest < TestCase
+ except = []
+
+ # Ruby < 3.3.0 cannot parse heredocs where there are leading whitespace
+ # characters in the heredoc start.
+ # Example: <<~' EOF' or <<-' EOF'
+ # https://bugs.ruby-lang.org/issues/19539
+ except << "heredocs_leading_whitespace.txt" if RUBY_VERSION < "3.3.0"
+
+ Fixture.each(except: except) do |fixture|
+ define_method(fixture.test_name) { assert_valid_syntax(fixture.read) }
+ end
+ end
+end
diff --git a/test/prism/fuzzer_test.rb b/test/prism/fuzzer_test.rb
new file mode 100644
index 0000000000..4927478bdc
--- /dev/null
+++ b/test/prism/fuzzer_test.rb
@@ -0,0 +1,67 @@
+# frozen_string_literal: true
+
+require_relative "test_helper"
+
+module Prism
+ # These tests are simply to exercise snippets found by the fuzzer that caused
+ # invalid memory access.
+ class FuzzerTest < TestCase
+ def self.snippet(name, source)
+ define_method(:"test_fuzzer_#{name}") { Prism.profile(source) }
+ end
+
+ snippet "incomplete global variable", "$"
+ snippet "incomplete symbol", ":"
+ snippet "incomplete escaped string", '"\\'
+ snippet "trailing comment", "1\n#\n"
+ snippet "comment followed by whitespace at end of file", "1\n#\n "
+ snippet "trailing asterisk", "a *"
+ snippet "incomplete decimal number", "0d"
+ snippet "incomplete binary number", "0b"
+ snippet "incomplete octal number", "0o"
+ snippet "incomplete hex number", "0x"
+ snippet "incomplete escaped list", "%w[\\"
+ snippet "incomplete escaped regex", "/a\\"
+ snippet "unterminated heredoc with unterminated escape at end of file", "<<A\n\\"
+ snippet "escaped octal at end of file 1", '"\\3'
+ snippet "escaped octal at end of file 2", '"\\33'
+ snippet "escaped hex at end of file 1", '"\\x'
+ snippet "escaped hex at end of file 2", '"\\x3'
+ snippet "escaped unicode at end of file 1", '"\\u{3'
+ snippet "escaped unicode at end of file 2", '"\\u{33'
+ snippet "escaped unicode at end of file 3", '"\\u{333'
+ snippet "escaped unicode at end of file 4", '"\\u{3333'
+ snippet "escaped unicode at end of file 5", '"\\u{33333'
+ snippet "escaped unicode at end of file 6", '"\\u{333333'
+ snippet "escaped unicode at end of file 7", '"\\u3'
+ snippet "escaped unicode at end of file 8", '"\\u33'
+ snippet "escaped unicode at end of file 9", '"\\u333'
+ snippet "float suffix at end of file", "1e"
+ snippet "parameter name that is zero length", "a { |b;"
+
+ snippet "statements node with multiple heredocs", <<~EOF
+ for <<A + <<B
+ A
+ B
+ EOF
+
+ snippet "create a binary call node with arg before receiver", <<~EOF
+ <<-A.g/{/
+ A
+ /, ""\\
+ EOF
+
+ snippet "regular expression with start and end out of order", <<~RUBY
+ <<-A.g//,
+ A
+ /{/, ''\\
+ RUBY
+
+ snippet "interpolated regular expression with start and end out of order", <<~RUBY
+ <<-A.g/{/,
+ A
+ a
+ /{/, ''\\
+ RUBY
+ end
+end
diff --git a/test/prism/heredoc_dedent_test.rb b/test/prism/heredoc_dedent_test.rb
new file mode 100644
index 0000000000..4e7a3c0a14
--- /dev/null
+++ b/test/prism/heredoc_dedent_test.rb
@@ -0,0 +1,134 @@
+# frozen_string_literal: true
+
+require_relative "test_helper"
+
+module Prism
+ class HeredocDedentTest < TestCase
+ def test_content_dedented_interpolation_content
+ assert_heredoc_dedent(
+ " a\n" "1\n" " a\n",
+ "<<~EOF\n" " a\n" "\#{1}\n" " a\n" "EOF\n"
+ )
+ end
+
+ def test_content
+ assert_heredoc_dedent(
+ "a\n",
+ "<<~EOF\n" " a\n" "EOF\n"
+ )
+ end
+
+ def test_tabs_dedent_spaces
+ assert_heredoc_dedent(
+ "\ta\n" "b\n" "\t\tc\n",
+ "<<~EOF\n" "\ta\n" " b\n" "\t\tc\n" "EOF\n"
+ )
+ end
+
+ def test_interpolation_then_content
+ assert_heredoc_dedent(
+ "1 a\n",
+ "<<~EOF\n" " \#{1} a\n" "EOF\n"
+ )
+ end
+
+ def test_content_then_interpolation
+ assert_heredoc_dedent(
+ "a 1\n",
+ "<<~EOF\n" " a \#{1}\n" "EOF\n"
+ )
+ end
+
+ def test_content_dedented_interpolation
+ assert_heredoc_dedent(
+ " a\n" "1\n",
+ "<<~EOF\n" " a\n" " \#{1}\n" "EOF\n"
+ )
+ end
+
+ def test_content_interpolation
+ assert_heredoc_dedent(
+ "a\n" "1\n",
+ "<<~EOF\n" " a\n" " \#{1}\n" "EOF\n"
+ )
+ end
+
+ def test_content_content
+ assert_heredoc_dedent(
+ "a\n" "b\n",
+ "<<~EOF\n" " a\n" " b\n" "EOF\n"
+ )
+ end
+
+ def test_content_indented_content
+ assert_heredoc_dedent(
+ "a\n" " b\n",
+ "<<~EOF\n" " a\n" " b\n" "EOF\n"
+ )
+ end
+
+ def test_content_dedented_content
+ assert_heredoc_dedent(
+ "\ta\n" "b\n",
+ "<<~EOF\n" "\t\t\ta\n" "\t\tb\n" "EOF\n"
+ )
+ end
+
+ def test_single_quote
+ assert_heredoc_dedent(
+ "a \#{1}\n",
+ "<<~'EOF'\n" "a \#{1}\n" "EOF\n"
+ )
+ end
+
+ def test_mixed_indentation
+ assert_heredoc_dedent(
+ "a\n" " b\n",
+ "<<~EOF\n" "\ta\n" "\t b\n" "EOF\n"
+ )
+ end
+
+ def test_indented_content_content
+ assert_heredoc_dedent(
+ " a\n" "b\n",
+ "<<~EOF\n" "\t a\n" "\tb\n" "EOF\n"
+ )
+ end
+
+ def test_indent_size
+ assert_heredoc_dedent(
+ "a\n" " b\n",
+ "<<~EOF\n" "\ta\n" " b\n" "EOF\n"
+ )
+ end
+
+ def test_blank_lines
+ assert_heredoc_dedent(
+ "a\n" "\n" "b\n",
+ "<<~EOF\n" " a\n" "\n" " b\n" "EOF\n"
+ )
+ end
+
+ def test_many_blank_lines
+ assert_heredoc_dedent(
+ "a\n" "\n" "\n" "\n" "\n" "b\n",
+ "<<~EOF\n" " a\n" "\n" "\n" "\n" "\n" " b\n" "EOF\n"
+ )
+ end
+
+ private
+
+ def assert_heredoc_dedent(expected, source)
+ node = Prism.parse_statement(source)
+
+ if node.is_a?(StringNode)
+ actual = node.unescaped
+ else
+ actual = node.parts.map { |part| part.is_a?(StringNode) ? part.unescaped : "1" }.join
+ end
+
+ assert_equal(expected, actual)
+ assert_equal(eval(source), actual)
+ end
+ end
+end
diff --git a/test/prism/lex_test.rb b/test/prism/lex_test.rb
new file mode 100644
index 0000000000..7eac677ef7
--- /dev/null
+++ b/test/prism/lex_test.rb
@@ -0,0 +1,90 @@
+# frozen_string_literal: true
+
+return if !(RUBY_ENGINE == "ruby" && RUBY_VERSION >= "3.2.0")
+
+require_relative "test_helper"
+
+module Prism
+ class LexTest < TestCase
+ except = [
+ # It seems like there are some oddities with nested heredocs and ripper.
+ # Waiting for feedback on https://bugs.ruby-lang.org/issues/19838.
+ "seattlerb/heredoc_nested.txt",
+ "whitequark/dedenting_heredoc.txt",
+ # Ripper seems to have a bug that the regex portions before and after
+ # the heredoc are combined into a single token. See
+ # https://bugs.ruby-lang.org/issues/19838.
+ "spanning_heredoc.txt",
+ "spanning_heredoc_newlines.txt"
+ ]
+
+ if RUBY_VERSION < "3.3.0"
+ # This file has changed behavior in Ripper in Ruby 3.3, so we skip it if
+ # we're on an earlier version.
+ except << "seattlerb/pct_w_heredoc_interp_nested.txt"
+
+ # Ruby < 3.3.0 cannot parse heredocs where there are leading whitespace
+ # characters in the heredoc start.
+ # Example: <<~' EOF' or <<-' EOF'
+ # https://bugs.ruby-lang.org/issues/19539
+ except << "heredocs_leading_whitespace.txt"
+ end
+
+ Fixture.each(except: except) do |fixture|
+ define_method(fixture.test_name) { assert_lex(fixture) }
+ end
+
+ def test_lex_file
+ assert_nothing_raised do
+ Prism.lex_file(__FILE__)
+ end
+
+ error = assert_raise Errno::ENOENT do
+ Prism.lex_file("idontexist.rb")
+ end
+
+ assert_equal "No such file or directory - idontexist.rb", error.message
+
+ assert_raise TypeError do
+ Prism.lex_file(nil)
+ end
+ end
+
+ def test_parse_lex
+ node, tokens = Prism.parse_lex("def foo; end").value
+
+ assert_kind_of ProgramNode, node
+ assert_equal 5, tokens.length
+ end
+
+ def test_parse_lex_file
+ node, tokens = Prism.parse_lex_file(__FILE__).value
+
+ assert_kind_of ProgramNode, node
+ refute_empty tokens
+
+ error = assert_raise Errno::ENOENT do
+ Prism.parse_lex_file("idontexist.rb")
+ end
+
+ assert_equal "No such file or directory - idontexist.rb", error.message
+
+ assert_raise TypeError do
+ Prism.parse_lex_file(nil)
+ end
+ end
+
+ private
+
+ def assert_lex(fixture)
+ source = fixture.read
+
+ result = Prism.lex_compat(source)
+ assert_equal [], result.errors
+
+ Prism.lex_ripper(source).zip(result.value).each do |(ripper, prism)|
+ assert_equal ripper, prism
+ end
+ end
+ end
+end
diff --git a/test/prism/library_symbols_test.rb b/test/prism/library_symbols_test.rb
new file mode 100644
index 0000000000..44f225478b
--- /dev/null
+++ b/test/prism/library_symbols_test.rb
@@ -0,0 +1,104 @@
+# frozen_string_literal: true
+
+require_relative "test_helper"
+
+return if RUBY_PLATFORM !~ /linux/
+return if RUBY_PLATFORM =~ /powerpc64le/
+
+module Prism
+ #
+ # examine a prism dll or static archive for expected external symbols.
+ # these tests only work on a linux system right now.
+ #
+ class LibrarySymbolsTest < TestCase
+ def setup
+ super
+
+ @libprism_a = File.expand_path("../../build/libprism.a", __dir__)
+ @libprism_so = File.expand_path("../../build/libprism.so", __dir__)
+ @prism_so = File.expand_path("../../lib/prism/prism.so", __dir__)
+ end
+
+ # objdump runner and helpers
+ def objdump(path)
+ assert_path_exist(path)
+ %x(objdump --section=.text --syms #{path}).split("\n")
+ end
+
+ def global_objdump_symbols(path)
+ objdump(path).select { |line| line[17] == "g" }
+ end
+
+ def hidden_global_objdump_symbols(path)
+ global_objdump_symbols(path).select { |line| line =~ / \.hidden / }
+ end
+
+ def visible_global_objdump_symbols(path)
+ global_objdump_symbols(path).reject { |line| line =~ / \.hidden / }
+ end
+
+ # nm runner and helpers
+ def nm(path)
+ assert_path_exist(path)
+ %x(nm #{path}).split("\n")
+ end
+
+ def global_nm_symbols(path)
+ nm(path).select { |line| line[17] == "T" }
+ end
+
+ def local_nm_symbols(path)
+ nm(path).select { |line| line[17] == "t" }
+ end
+
+ # dig the symbol name out of each line. works for both `objdump` and `nm` output.
+ def names(symbol_lines)
+ symbol_lines.map { |line| line.split(/\s+/).last }
+ end
+
+ #
+ # static archive - libprism.a
+ #
+ def test_libprism_a_contains_nothing_globally_visible
+ omit("libprism.a is not built") unless File.exist?(@libprism_a)
+
+ assert_empty(names(visible_global_objdump_symbols(@libprism_a)))
+ end
+
+ def test_libprism_a_contains_hidden_pm_symbols
+ omit("libprism.a is not built") unless File.exist?(@libprism_a)
+
+ names(hidden_global_objdump_symbols(@libprism_a)).tap do |symbols|
+ assert_includes(symbols, "pm_parse")
+ assert_includes(symbols, "pm_version")
+ end
+ end
+
+ #
+ # shared object - libprism.so
+ #
+ def test_libprism_so_exports_only_the_necessary_functions
+ omit("libprism.so is not built") unless File.exist?(@libprism_so)
+
+ names(global_nm_symbols(@libprism_so)).tap do |symbols|
+ assert_includes(symbols, "pm_parse")
+ assert_includes(symbols, "pm_version")
+ end
+ names(local_nm_symbols(@libprism_so)).tap do |symbols|
+ assert_includes(symbols, "pm_encoding_utf_8_isupper_char")
+ end
+ # TODO: someone who uses this library needs to finish this test
+ end
+
+ #
+ # shared object - prism.so
+ #
+ def test_prism_so_exports_only_the_C_extension_init_function
+ omit("prism.so is not built") unless File.exist?(@prism_so)
+
+ names(global_nm_symbols(@prism_so)).tap do |symbols|
+ assert_equal(["Init_prism"], symbols)
+ end
+ end
+ end
+end
diff --git a/test/prism/locals_test.rb b/test/prism/locals_test.rb
new file mode 100644
index 0000000000..2c0036289c
--- /dev/null
+++ b/test/prism/locals_test.rb
@@ -0,0 +1,238 @@
+# frozen_string_literal: true
+
+# This test is going to use the RubyVM::InstructionSequence class to compile
+# local tables and compare against them to ensure we have the same locals in the
+# same order. This is important to guarantee that we compile indices correctly
+# on CRuby (in terms of compatibility).
+#
+# There have also been changes made in other versions of Ruby, so we only want
+# to test on the most recent versions.
+return if !defined?(RubyVM::InstructionSequence) || RUBY_VERSION < "3.4.0"
+
+# If we're on Ruby 3.4.0 and the default parser is Prism, then there is no point
+# in comparing the locals because they will be the same.
+return if RubyVM::InstructionSequence.compile("").to_a[4][:parser] == :prism
+
+# In Ruby 3.4.0, the local table for method forwarding changed. But 3.4.0 can
+# refer to the dev version, so while 3.4.0 still isn't released, we need to
+# check if we have a high enough revision.
+return if RubyVM::InstructionSequence.compile("def foo(...); end").to_a[13][2][2][10].length != 1
+
+# Omit tests if running on a 32-bit machine because there is a bug with how
+# Ruby is handling large ISeqs on 32-bit machines
+return if RUBY_PLATFORM =~ /i686/
+
+require_relative "test_helper"
+
+module Prism
+ class LocalsTest < TestCase
+ except = [
+ # Skip this fixture because it has a different number of locals because
+ # CRuby is eliminating dead code.
+ "whitequark/ruby_bug_10653.txt"
+ ]
+
+ Fixture.each(except: except) do |fixture|
+ define_method(fixture.test_name) { assert_locals(fixture) }
+ end
+
+ def setup
+ @previous_default_external = Encoding.default_external
+ ignore_warnings { Encoding.default_external = Encoding::UTF_8 }
+ end
+
+ def teardown
+ ignore_warnings { Encoding.default_external = @previous_default_external }
+ end
+
+ private
+
+ def assert_locals(fixture)
+ source = fixture.read
+
+ expected = cruby_locals(source)
+ actual = prism_locals(source)
+
+ assert_equal(expected, actual)
+ end
+
+ # A wrapper around a RubyVM::InstructionSequence that provides a more
+ # convenient interface for accessing parts of the iseq.
+ class ISeq
+ attr_reader :parts
+
+ def initialize(parts)
+ @parts = parts
+ end
+
+ def type
+ parts[0]
+ end
+
+ def local_table
+ parts[10]
+ end
+
+ def instructions
+ parts[13]
+ end
+
+ def each_child
+ instructions.each do |instruction|
+ # Only look at arrays. Other instructions are line numbers or
+ # tracepoint events.
+ next unless instruction.is_a?(Array)
+
+ instruction.each do |opnd|
+ # Only look at arrays. Other operands are literals.
+ next unless opnd.is_a?(Array)
+
+ # Only look at instruction sequences. Other operands are literals.
+ next unless opnd[0] == "YARVInstructionSequence/SimpleDataFormat"
+
+ yield ISeq.new(opnd)
+ end
+ end
+ end
+ end
+
+ # Used to hold the place of a local that will be in the local table but
+ # cannot be accessed directly from the source code. For example, the
+ # iteration variable in a for loop or the positional parameter on a method
+ # definition that is destructured.
+ AnonymousLocal = Object.new
+
+ # For the given source, compiles with CRuby and returns a list of all of the
+ # sets of local variables that were encountered.
+ def cruby_locals(source)
+ locals = [] #: Array[Array[Symbol | Integer]]
+ stack = [ISeq.new(ignore_warnings { RubyVM::InstructionSequence.compile(source) }.to_a)]
+
+ while (iseq = stack.pop)
+ names = [*iseq.local_table]
+ names.map!.with_index do |name, index|
+ # When an anonymous local variable is present in the iseq's local
+ # table, it is represented as the stack offset from the top.
+ # However, when these are dumped to binary and read back in, they
+ # are replaced with the symbol :#arg_rest. To consistently handle
+ # this, we replace them here with their index.
+ if name == :"#arg_rest"
+ names.length - index + 1
+ else
+ name
+ end
+ end
+
+ locals << names
+ iseq.each_child { |child| stack << child }
+ end
+
+ locals
+ end
+
+ # For the given source, parses with prism and returns a list of all of the
+ # sets of local variables that were encountered.
+ def prism_locals(source)
+ locals = [] #: Array[Array[Symbol | Integer]]
+ stack = [Prism.parse(source).value] #: Array[Prism::node]
+
+ while (node = stack.pop)
+ case node
+ when BlockNode, DefNode, LambdaNode
+ names = node.locals
+ params =
+ if node.is_a?(DefNode)
+ node.parameters
+ elsif node.parameters.is_a?(NumberedParametersNode)
+ nil
+ else
+ node.parameters&.parameters
+ end
+
+ # prism places parameters in the same order that they appear in the
+ # source. CRuby places them in the order that they need to appear
+ # according to their own internal calling convention. We mimic that
+ # order here so that we can compare properly.
+ if params
+ sorted = [
+ *params.requireds.map do |required|
+ if required.is_a?(RequiredParameterNode)
+ required.name
+ else
+ AnonymousLocal
+ end
+ end,
+ *params.optionals.map(&:name),
+ *((params.rest.name || :*) if params.rest && !params.rest.is_a?(ImplicitRestNode)),
+ *params.posts.map do |post|
+ if post.is_a?(RequiredParameterNode)
+ post.name
+ else
+ AnonymousLocal
+ end
+ end,
+ *params.keywords.grep(RequiredKeywordParameterNode).map(&:name),
+ *params.keywords.grep(OptionalKeywordParameterNode).map(&:name),
+ ]
+
+ sorted << AnonymousLocal if params.keywords.any?
+
+ if params.keyword_rest.is_a?(ForwardingParameterNode)
+ if sorted.length == 0
+ sorted.push(:"...")
+ else
+ sorted.push(:*, :**, :&, :"...")
+ end
+ elsif params.keyword_rest.is_a?(KeywordRestParameterNode)
+ sorted << (params.keyword_rest.name || :**)
+ end
+
+ # Recurse down the parameter tree to find any destructured
+ # parameters and add them after the other parameters.
+ param_stack = params.requireds.concat(params.posts).grep(MultiTargetNode).reverse
+ while (param = param_stack.pop)
+ case param
+ when MultiTargetNode
+ param_stack.concat(param.rights.reverse)
+ param_stack << param.rest if param.rest&.expression && !sorted.include?(param.rest.expression.name)
+ param_stack.concat(param.lefts.reverse)
+ when RequiredParameterNode
+ sorted << param.name
+ when SplatNode
+ sorted << param.expression.name
+ end
+ end
+
+ if params.block
+ sorted << (params.block.name || :&)
+ end
+
+ names = sorted.concat(names - sorted)
+ end
+
+ names.map!.with_index do |name, index|
+ if name == AnonymousLocal
+ names.length - index + 1
+ else
+ name
+ end
+ end
+
+ locals << names
+ when ClassNode, ModuleNode, ProgramNode, SingletonClassNode
+ locals << node.locals
+ when ForNode
+ locals << [2]
+ when PostExecutionNode
+ locals.push([], [])
+ when InterpolatedRegularExpressionNode
+ locals << [] if node.once?
+ end
+
+ stack.concat(node.compact_child_nodes)
+ end
+
+ locals
+ end
+ end
+end
diff --git a/test/prism/magic_comment_test.rb b/test/prism/magic_comment_test.rb
new file mode 100644
index 0000000000..14653fb0f8
--- /dev/null
+++ b/test/prism/magic_comment_test.rb
@@ -0,0 +1,110 @@
+# frozen_string_literal: true
+
+require_relative "test_helper"
+
+module Prism
+ class MagicCommentTest < TestCase
+ if RUBY_ENGINE == "ruby"
+ class MagicCommentRipper < Ripper
+ attr_reader :magic_comments
+
+ def initialize(*)
+ super
+ @magic_comments = []
+ end
+
+ def on_magic_comment(key, value)
+ @magic_comments << [key, value]
+ super
+ end
+ end
+
+ Fixture.each do |fixture|
+ define_method(fixture.test_name) { assert_magic_comments(fixture) }
+ end
+ end
+
+ def test_encoding
+ assert_magic_encoding(Encoding::US_ASCII, "# encoding: ascii")
+ end
+
+ def test_coding
+ assert_magic_encoding(Encoding::US_ASCII, "# coding: ascii")
+ end
+
+ def test_eNcOdInG
+ assert_magic_encoding(Encoding::US_ASCII, "# eNcOdInG: ascii")
+ end
+
+ def test_CoDiNg
+ assert_magic_encoding(Encoding::US_ASCII, "# CoDiNg: ascii")
+ end
+
+ def test_encoding_whitespace
+ assert_magic_encoding(Encoding::US_ASCII, "# \s\t\v encoding \s\t\v : \s\t\v ascii \s\t\v")
+ end
+
+ def test_emacs_encoding
+ assert_magic_encoding(Encoding::US_ASCII, "# -*- encoding: ascii -*-")
+ end
+
+ def test_emacs_coding
+ assert_magic_encoding(Encoding::US_ASCII, "# -*- coding: ascii -*-")
+ end
+
+ def test_emacs_eNcOdInG
+ assert_magic_encoding(Encoding::US_ASCII, "# -*- eNcOdInG: ascii -*-")
+ end
+
+ def test_emacs_CoDiNg
+ assert_magic_encoding(Encoding::US_ASCII, "# -*- CoDiNg: ascii -*-")
+ end
+
+ def test_emacs_whitespace
+ assert_magic_encoding(Encoding::US_ASCII, "# -*- \s\t\v encoding \s\t\v : \s\t\v ascii \s\t\v -*-")
+ end
+
+ def test_emacs_multiple
+ assert_magic_encoding(Encoding::US_ASCII, "# -*- foo: bar; encoding: ascii -*-")
+ end
+
+ def test_coding_whitespace
+ assert_magic_encoding(Encoding::ASCII_8BIT, "# coding \t \r \v : \t \v \r ascii-8bit")
+ end
+
+ def test_vim
+ assert_magic_encoding(Encoding::Windows_31J, "# vim: filetype=ruby, fileencoding=windows-31j, tabsize=3, shiftwidth=3")
+ end
+
+ private
+
+ def assert_magic_encoding(expected, line)
+ source = %Q{#{line}\n""}
+ actual = Prism.parse(source).encoding
+
+ # Compare against our expectation.
+ assert_equal expected, actual
+
+ # Compare against Ruby's expectation.
+ if defined?(RubyVM::InstructionSequence)
+ expected = RubyVM::InstructionSequence.compile(source).eval.encoding
+ assert_equal expected, actual
+ end
+ end
+
+ def assert_magic_comments(fixture)
+ source = fixture.read
+
+ # Check that we get the correct number of magic comments when lexing with
+ # ripper.
+ expected = MagicCommentRipper.new(source).tap(&:parse).magic_comments
+ actual = Prism.parse(source).magic_comments
+
+ assert_equal expected.length, actual.length
+ expected.zip(actual).each do |(expected_key, expected_value), magic_comment|
+ assert_equal expected_key, magic_comment.key
+ assert_equal expected_value, magic_comment.value
+ end
+ end
+ end
+end
diff --git a/test/prism/newline_offsets_test.rb b/test/prism/newline_offsets_test.rb
new file mode 100644
index 0000000000..99b808b1df
--- /dev/null
+++ b/test/prism/newline_offsets_test.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+require_relative "test_helper"
+
+module Prism
+ class NewlineOffsetsTest < TestCase
+ Fixture.each do |fixture|
+ define_method(fixture.test_name) { assert_newline_offsets(fixture) }
+ end
+
+ private
+
+ def assert_newline_offsets(fixture)
+ source = fixture.read
+
+ expected = [0]
+ source.b.scan("\n") { expected << $~.offset(0)[0] + 1 }
+
+ assert_equal expected, Prism.parse(source).source.offsets
+ end
+ end
+end
diff --git a/test/prism/newline_test.rb b/test/prism/newline_test.rb
new file mode 100644
index 0000000000..fefe9def91
--- /dev/null
+++ b/test/prism/newline_test.rb
@@ -0,0 +1,98 @@
+# frozen_string_literal: true
+
+require_relative "test_helper"
+
+return unless defined?(RubyVM::InstructionSequence)
+
+module Prism
+ class NewlineTest < TestCase
+ skips = %w[
+ errors_test.rb
+ locals_test.rb
+ regexp_test.rb
+ test_helper.rb
+ unescape_test.rb
+ encoding/regular_expression_encoding_test.rb
+ encoding/string_encoding_test.rb
+ result/breadth_first_search_test.rb
+ result/static_literals_test.rb
+ result/warnings_test.rb
+ ruby/parser_test.rb
+ ruby/ruby_parser_test.rb
+ ]
+
+ base = __dir__
+ (Dir["{,api/,encoding/,result/,ruby/}*.rb", base: base] - skips).each do |relative|
+ define_method(:"test_#{relative}") do
+ assert_newlines(base, relative)
+ end
+ end
+
+ private
+
+ def assert_newlines(base, relative)
+ filepath = File.join(base, relative)
+ source = File.read(filepath, binmode: true, external_encoding: Encoding::UTF_8)
+ expected = rubyvm_lines(source)
+
+ result = Prism.parse_file(filepath)
+ assert_empty result.errors
+ actual = prism_lines(result)
+
+ source.each_line.with_index(1) do |line, line_number|
+ # Lines like `while (foo = bar)` result in two line flags in the
+ # bytecode but only one newline flag in the AST. We need to remove the
+ # extra line flag from the bytecode to make the test pass.
+ if line.match?(/while \(/)
+ index = expected.index(line_number)
+ expected.delete_at(index) if index
+ end
+
+ # Lines like `foo =` where the value is on the next line result in
+ # another line flag in the bytecode but only one newline flag in the
+ # AST.
+ if line.match?(/^\s+\w+ =$/)
+ if source.lines[line_number].match?(/^\s+case/)
+ actual[actual.index(line_number)] += 1
+ else
+ actual.delete_at(actual.index(line_number))
+ end
+ end
+
+ if line.match?(/^\s+\w+ = \[$/)
+ if !expected.include?(line_number) && !expected.include?(line_number + 2)
+ actual[actual.index(line_number)] += 1
+ end
+ end
+ end
+
+ assert_equal expected, actual
+ end
+
+ def rubyvm_lines(source)
+ queue = [ignore_warnings { RubyVM::InstructionSequence.compile(source) }]
+ lines = []
+
+ while iseq = queue.shift
+ lines.concat(iseq.trace_points.filter_map { |line, event| line if event == :line })
+ iseq.each_child { |insn| queue << insn unless insn.label.start_with?("ensure in ") }
+ end
+
+ lines.sort
+ end
+
+ def prism_lines(result)
+ result.mark_newlines!
+
+ queue = [result.value]
+ newlines = []
+
+ while node = queue.shift
+ queue.concat(node.compact_child_nodes)
+ newlines << result.source.line(node.location.start_offset) if node&.newline_flag?
+ end
+
+ newlines.sort
+ end
+ end
+end
diff --git a/test/prism/onigmo_test.rb b/test/prism/onigmo_test.rb
new file mode 100644
index 0000000000..03f44c4e4c
--- /dev/null
+++ b/test/prism/onigmo_test.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: true
+
+return if RUBY_ENGINE != "ruby"
+
+require_relative "test_helper"
+
+begin
+ require "onigmo"
+rescue LoadError
+ # In CRuby's CI, we're not going to test against the parser gem because we
+ # don't want to have to install it. So in this case we'll just skip this test.
+ return
+end
+
+module Prism
+ class OnigmoTest < TestCase
+ def test_ONIGERR_PARSE_DEPTH_LIMIT_OVER
+ assert_error(%Q{#{"(" * 4096}a#{")" * 4096}}, "parse depth limit over")
+ end
+
+ def test_ONIGERR_EMPTY_CHAR_CLASS
+ assert_error("[]", "empty char-class")
+ end
+
+ def test_ONIGERR_TARGET_OF_REPEAT_OPERATOR_NOT_SPECIFIED
+ assert_error("*", "target of repeat operator is not specified")
+ assert_error("+", "target of repeat operator is not specified")
+ assert_error("?", "target of repeat operator is not specified")
+ end
+
+ def test_ONIGERR_EMPTY_GROUP_NAME
+ assert_error("(?<>)", "group name is empty")
+ end
+
+ def test_ONIGERR_END_PATTERN_WITH_UNMATCHED_PARENTHESIS
+ assert_error("(", "end pattern with unmatched parenthesis")
+ assert_error("(|", "end pattern with unmatched parenthesis")
+ assert_error("(?<", "end pattern with unmatched parenthesis")
+ end
+
+ def test_ONIGERR_END_PATTERN_IN_GROUP
+ assert_error("(?", "end pattern in group")
+ assert_error("(?#", "end pattern in group")
+ end
+
+ def test_ONIGERR_UNDEFINED_GROUP_OPTION
+ assert_error("(?P", "undefined group option")
+ end
+
+ def test_ONIGERR_UNMATCHED_CLOSE_PARENTHESIS
+ assert_error(")", "unmatched close parenthesis")
+ end
+
+ private
+
+ def assert_error(source, message)
+ result = Prism.parse("/#{source}/")
+
+ assert result.failure?, "Expected #{source.inspect} to error"
+ assert_equal message, result.errors.first.message
+
+ error = assert_raise(ArgumentError) { Onigmo.parse(source) }
+ assert_equal message, error.message
+ end
+ end
+end
diff --git a/test/prism/regexp_test.rb b/test/prism/regexp_test.rb
new file mode 100644
index 0000000000..297020fc72
--- /dev/null
+++ b/test/prism/regexp_test.rb
@@ -0,0 +1,261 @@
+# frozen_string_literal: true
+
+require_relative "test_helper"
+
+module Prism
+ class RegexpTest < TestCase
+ ############################################################################
+ # These tests test the actual use case of extracting named capture groups
+ ############################################################################
+
+ def test_named_captures_with_arrows
+ assert_equal([:foo], named_captures("(?<foo>bar)"))
+ end
+
+ def test_named_captures_with_single_quotes
+ assert_equal([:foo], named_captures("(?'foo'bar)"))
+ end
+
+ def test_nested_named_captures_with_arrows
+ assert_equal([:foo, :bar], named_captures("(?<foo>(?<bar>baz))"))
+ end
+
+ def test_nested_named_captures_with_single_quotes
+ assert_equal([:foo, :bar], named_captures("(?'foo'(?'bar'baz))"))
+ end
+
+ def test_allows_duplicate_named_captures
+ assert_equal([:foo], named_captures("(?<foo>bar)(?<foo>baz)"))
+ end
+
+ def test_named_capture_inside_fake_range_quantifier
+ assert_equal([:foo], named_captures("foo{1, (?<foo>2)}"))
+ end
+
+ def test_fake_named_captures_inside_character_sets
+ assert_equal([], named_captures("[a-z(?<foo>)]"))
+ end
+
+ def test_fake_named_capture_inside_character_set_with_escaped_ending
+ assert_equal([], named_captures("[a-z\\](?<foo>)]"))
+ end
+
+ ############################################################################
+ # These tests test the rest of the AST. They are not exhaustive, but they
+ # should cover the most common cases. We test these to make sure we don't
+ # accidentally regress and stop being able to extract named captures.
+ ############################################################################
+
+ def test_alternation
+ assert_valid_regexp("foo|bar")
+ end
+
+ def test_anchors
+ assert_valid_regexp("^foo$")
+ end
+
+ def test_any
+ assert_valid_regexp(".")
+ end
+
+ def test_posix_character_classes
+ assert_valid_regexp("[[:digit:]]")
+ end
+
+ def test_negated_posix_character_classes
+ assert_valid_regexp("[[:^digit:]]")
+ end
+
+ def test_invalid_posix_character_classes_should_fall_back_to_regular_classes
+ assert_valid_regexp("[[:foo]]")
+ end
+
+ def test_character_sets
+ assert_valid_regexp("[abc]")
+ end
+
+ def test_nested_character_sets
+ assert_valid_regexp("[[abc]]")
+ end
+
+ def test_nested_character_sets_with_operators
+ assert_valid_regexp("[[abc] && [def]]")
+ end
+
+ def test_named_capture_inside_nested_character_set
+ assert_equal([], named_captures("[foo (?<foo>bar)]"))
+ end
+
+ def test_negated_character_sets
+ assert_valid_regexp("[^abc]")
+ end
+
+ def test_character_ranges
+ assert_valid_regexp("[a-z]")
+ end
+
+ def test_negated_character_ranges
+ assert_valid_regexp("[^a-z]")
+ end
+
+ def test_comments
+ assert_valid_regexp("(?#foo)")
+ end
+
+ def test_comments_with_escaped_parentheses
+ assert_valid_regexp("(?#foo\\)\\))")
+ end
+
+ def test_non_capturing_groups
+ assert_valid_regexp("(?:foo)")
+ end
+
+ def test_positive_lookaheads
+ assert_valid_regexp("(?=foo)")
+ end
+
+ def test_negative_lookaheads
+ assert_valid_regexp("(?!foo)")
+ end
+
+ def test_positive_lookbehinds
+ assert_valid_regexp("(?<=foo)")
+ end
+
+ def test_negative_lookbehinds
+ assert_valid_regexp("(?<!foo)")
+ end
+
+ def test_atomic_groups
+ assert_valid_regexp("(?>foo)")
+ end
+
+ def test_absence_operator
+ assert_valid_regexp("(?~foo)")
+ end
+
+ def test_conditional_expression_with_index
+ assert_valid_regexp("(?(1)foo)")
+ end
+
+ def test_conditional_expression_with_name
+ assert_valid_regexp("(?(foo)bar)")
+ end
+
+ def test_conditional_expression_with_group
+ assert_valid_regexp("(?(<foo>)bar)")
+ end
+
+ def test_options_on_groups
+ assert_valid_regexp("(?imxdau:foo)")
+ end
+
+ def test_options_on_groups_getting_turned_off
+ assert_valid_regexp("(?-imx:foo)")
+ end
+
+ def test_options_on_groups_some_getting_turned_on_some_getting_turned_off
+ assert_valid_regexp("(?im-x:foo)")
+ end
+
+ def test_star_quantifier
+ assert_valid_regexp("foo*")
+ end
+
+ def test_plus_quantifier
+ assert_valid_regexp("foo+")
+ end
+
+ def test_question_mark_quantifier
+ assert_valid_regexp("foo?")
+ end
+
+ def test_endless_range_quantifier
+ assert_valid_regexp("foo{1,}")
+ end
+
+ def test_beginless_range_quantifier
+ assert_valid_regexp("foo{,1}")
+ end
+
+ def test_range_quantifier
+ assert_valid_regexp("foo{1,2}")
+ end
+
+ def test_fake_range_quantifier_because_of_spaces
+ assert_valid_regexp("foo{1, 2}")
+ end
+
+ ############################################################################
+ # These test that flag values are correct.
+ ############################################################################
+
+ def test_flag_ignorecase
+ assert_equal(Regexp::IGNORECASE, options("i"))
+ end
+
+ def test_flag_extended
+ assert_equal(Regexp::EXTENDED, options("x"))
+ end
+
+ def test_flag_multiline
+ assert_equal(Regexp::MULTILINE, options("m"))
+ end
+
+ def test_flag_fixedencoding
+ assert_equal(Regexp::FIXEDENCODING, options("e"))
+ assert_equal(Regexp::FIXEDENCODING, options("u"))
+ assert_equal(Regexp::FIXEDENCODING, options("s"))
+ end
+
+ def test_flag_noencoding
+ assert_equal(Regexp::NOENCODING, options("n"))
+ end
+
+ def test_flag_once
+ assert_equal(0, options("o"))
+ end
+
+ def test_flag_combined
+ value = Regexp::IGNORECASE | Regexp::MULTILINE | Regexp::EXTENDED
+ assert_equal(value, options("mix"))
+ end
+
+ def test_last_encoding_option_wins
+ regex = "/foo/nu"
+ option = Prism.parse_statement(regex).options
+
+ assert_equal Regexp::FIXEDENCODING, option
+
+ regex = "/foo/un"
+ option = Prism.parse_statement(regex).options
+
+ assert_equal Regexp::NOENCODING, option
+ end
+
+ private
+
+ def assert_valid_regexp(source)
+ assert Prism.parse_success?("/#{source}/ =~ \"\"")
+ end
+
+ def named_captures(source)
+ Prism.parse("/#{source}/ =~ \"\"").value.locals
+ end
+
+ def options(flags)
+ options =
+ ["/foo/#{flags}", "/foo\#{1}/#{flags}"].map do |source|
+ Prism.parse_statement(source).options
+ end
+
+ # Check that we get the same set of options from both regular expressions
+ # and interpolated regular expressions.
+ assert_equal(1, options.uniq.length)
+
+ # Return the options from the first regular expression since we know they
+ # are the same.
+ options.first
+ end
+ end
+end
diff --git a/test/prism/result/attribute_write_test.rb b/test/prism/result/attribute_write_test.rb
new file mode 100644
index 0000000000..8f2e352738
--- /dev/null
+++ b/test/prism/result/attribute_write_test.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+require_relative "../test_helper"
+
+module Prism
+ class AttributeWriteTest < TestCase
+ module Target
+ def self.value
+ 2
+ end
+
+ def self.value=(value)
+ 2
+ end
+
+ def self.[]=(index, value)
+ 2
+ end
+ end
+
+ def test_named_call_with_operator
+ assert_attribute_write("Target.value = 1")
+ end
+
+ def test_named_call_without_operator
+ assert_attribute_write("Target.value=(1)")
+ end
+
+ def test_indexed_call_with_operator
+ assert_attribute_write("Target[0] = 1")
+ end
+
+ def test_indexed_call_without_operator
+ refute_attribute_write("Target.[]=(0, 1)")
+ end
+
+ def test_comparison_operators
+ refute_attribute_write("Target.value == 1")
+ refute_attribute_write("Target.value === 1")
+ end
+
+ private
+
+ def assert_attribute_write(source)
+ call = Prism.parse_statement(source)
+ assert(call.attribute_write?)
+ assert_equal(1, eval(source))
+ end
+
+ def refute_attribute_write(source)
+ call = Prism.parse_statement(source)
+ refute(call.attribute_write?)
+ refute_equal(1, eval(source))
+ end
+ end
+end
diff --git a/test/prism/result/breadth_first_search_test.rb b/test/prism/result/breadth_first_search_test.rb
new file mode 100644
index 0000000000..e2e043a902
--- /dev/null
+++ b/test/prism/result/breadth_first_search_test.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+require_relative "../test_helper"
+
+module Prism
+ class BreadthFirstSearchTest < TestCase
+ def test_breadth_first_search
+ result = Prism.parse("[1 + 2, 2]")
+ found =
+ result.value.breadth_first_search do |node|
+ node.is_a?(IntegerNode) && node.value == 2
+ end
+
+ refute_nil found
+ assert_equal 8, found.start_offset
+ end
+ end
+end
diff --git a/test/prism/result/comments_test.rb b/test/prism/result/comments_test.rb
new file mode 100644
index 0000000000..178623a75f
--- /dev/null
+++ b/test/prism/result/comments_test.rb
@@ -0,0 +1,138 @@
+# frozen_string_literal: true
+
+require_relative "../test_helper"
+
+module Prism
+ class CommentsTest < TestCase
+ def test_comment_inline
+ source = "# comment"
+ assert_equal [0], Prism.parse(source).source.offsets
+
+ assert_comment(
+ source,
+ InlineComment,
+ start_offset: 0,
+ end_offset: 9,
+ start_line: 1,
+ end_line: 1,
+ start_column: 0,
+ end_column: 9
+ )
+ end
+
+ def test_comment_inline_def
+ source = <<~RUBY
+ def foo
+ # a comment
+ end
+ RUBY
+
+ assert_comment(
+ source,
+ InlineComment,
+ start_offset: 10,
+ end_offset: 21,
+ start_line: 2,
+ end_line: 2,
+ start_column: 2,
+ end_column: 13
+ )
+ end
+
+ def test___END__
+ result = Prism.parse(<<~RUBY)
+ __END__
+ comment
+ RUBY
+
+ data_loc = result.data_loc
+ assert_equal 0, data_loc.start_offset
+ assert_equal 16, data_loc.end_offset
+ end
+
+ def test___END__crlf
+ result = Prism.parse("__END__\r\ncomment\r\n")
+
+ data_loc = result.data_loc
+ assert_equal 0, data_loc.start_offset
+ assert_equal 18, data_loc.end_offset
+ end
+
+ def test_comment_embedded_document
+ source = <<~RUBY
+ =begin
+ comment
+ =end
+ RUBY
+
+ assert_comment(
+ source,
+ EmbDocComment,
+ start_offset: 0,
+ end_offset: 20,
+ start_line: 1,
+ end_line: 4,
+ start_column: 0,
+ end_column: 0
+ )
+ end
+
+ def test_comment_embedded_document_with_content_on_same_line
+ source = <<~RUBY
+ =begin other stuff
+ =end
+ RUBY
+
+ assert_comment(
+ source,
+ EmbDocComment,
+ start_offset: 0,
+ end_offset: 24,
+ start_line: 1,
+ end_line: 3,
+ start_column: 0,
+ end_column: 0
+ )
+ end
+
+ def test_attaching_comments
+ source = <<~RUBY
+ # Foo class
+ class Foo
+ # bar method
+ def bar
+ # baz invocation
+ baz
+ end # bar end
+ end # Foo end
+ RUBY
+
+ result = Prism.parse(source)
+ result.attach_comments!
+ tree = result.value
+ class_node = tree.statements.body.first
+ method_node = class_node.body.body.first
+ call_node = method_node.body.body.first
+
+ assert_equal("# Foo class\n# Foo end", class_node.location.comments.map { |c| c.location.slice }.join("\n"))
+ assert_equal("# bar method\n# bar end", method_node.location.comments.map { |c| c.location.slice }.join("\n"))
+ assert_equal("# baz invocation", call_node.location.comments.map { |c| c.location.slice }.join("\n"))
+ end
+
+ private
+
+ def assert_comment(source, type, start_offset:, end_offset:, start_line:, end_line:, start_column:, end_column:)
+ result = Prism.parse(source)
+ assert result.errors.empty?, result.errors.map(&:message).join("\n")
+ assert_kind_of type, result.comments.first
+
+ location = result.comments.first.location
+ assert_equal start_offset, location.start_offset, -> { "Expected start_offset to be #{start_offset}" }
+ assert_equal end_offset, location.end_offset, -> { "Expected end_offset to be #{end_offset}" }
+ assert_equal start_line, location.start_line, -> { "Expected start_line to be #{start_line}" }
+ assert_equal end_line, location.end_line, -> { "Expected end_line to be #{end_line}" }
+ assert_equal start_column, location.start_column, -> { "Expected start_column to be #{start_column}" }
+ assert_equal end_column, location.end_column, -> { "Expected end_column to be #{end_column}" }
+ end
+ end
+end
diff --git a/test/prism/result/constant_path_node_test.rb b/test/prism/result/constant_path_node_test.rb
new file mode 100644
index 0000000000..75925600ca
--- /dev/null
+++ b/test/prism/result/constant_path_node_test.rb
@@ -0,0 +1,91 @@
+# frozen_string_literal: true
+
+require_relative "../test_helper"
+
+module Prism
+ class ConstantPathNodeTest < TestCase
+ def test_full_name_for_constant_path
+ source = <<~RUBY
+ Foo:: # comment
+ Bar::Baz::
+ Qux
+ RUBY
+
+ constant_path = Prism.parse_statement(source)
+ assert_equal("Foo::Bar::Baz::Qux", constant_path.full_name)
+ end
+
+ def test_full_name_for_constant_path_with_self
+ source = <<~RUBY
+ self:: # comment
+ Bar::Baz::
+ Qux
+ RUBY
+
+ constant_path = Prism.parse_statement(source)
+ assert_raise(ConstantPathNode::DynamicPartsInConstantPathError) do
+ constant_path.full_name
+ end
+ end
+
+ def test_full_name_for_constant_path_with_variable
+ source = <<~RUBY
+ foo:: # comment
+ Bar::Baz::
+ Qux
+ RUBY
+
+ constant_path = Prism.parse_statement(source)
+
+ assert_raise(ConstantPathNode::DynamicPartsInConstantPathError) do
+ constant_path.full_name
+ end
+ end
+
+ def test_full_name_for_constant_path_target
+ source = <<~RUBY
+ Foo:: # comment
+ Bar::Baz::
+ Qux, Something = [1, 2]
+ RUBY
+
+ node = Prism.parse_statement(source)
+ assert_equal("Foo::Bar::Baz::Qux", node.lefts.first.full_name)
+ end
+
+ def test_full_name_for_constant_path_with_stovetop_start
+ source = <<~RUBY
+ ::Foo:: # comment
+ Bar::Baz::
+ Qux, Something = [1, 2]
+ RUBY
+
+ node = Prism.parse_statement(source)
+ assert_equal("::Foo::Bar::Baz::Qux", node.lefts.first.full_name)
+ end
+
+ def test_full_name_for_constant_path_target_with_non_constant_parent
+ source = <<~RUBY
+ self::Foo, Bar = [1, 2]
+ RUBY
+
+ constant_target = Prism.parse_statement(source)
+ dynamic, static = constant_target.lefts
+
+ assert_raise(ConstantPathNode::DynamicPartsInConstantPathError) do
+ dynamic.full_name
+ end
+
+ assert_equal("Bar", static.full_name)
+ end
+
+ def test_full_name_for_constant_read_node
+ source = <<~RUBY
+ Bar
+ RUBY
+
+ constant = Prism.parse_statement(source)
+ assert_equal("Bar", constant.full_name)
+ end
+ end
+end
diff --git a/test/prism/result/equality_test.rb b/test/prism/result/equality_test.rb
new file mode 100644
index 0000000000..4f6e665a88
--- /dev/null
+++ b/test/prism/result/equality_test.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+require_relative "../test_helper"
+
+module Prism
+ class EqualityTest < TestCase
+ def test_equality
+ assert_operator Prism.parse_statement("1"), :===, Prism.parse_statement("1")
+ assert_operator Prism.parse("1").value, :===, Prism.parse("1").value
+
+ complex_source = "class Something; @var = something.else { _1 }; end"
+ assert_operator Prism.parse_statement(complex_source), :===, Prism.parse_statement(complex_source)
+
+ refute_operator Prism.parse_statement("1"), :===, Prism.parse_statement("2")
+ refute_operator Prism.parse_statement("1"), :===, Prism.parse_statement("0x1")
+
+ complex_source_1 = "class Something; @var = something.else { _1 }; end"
+ complex_source_2 = "class Something; @var = something.else { _2 }; end"
+ refute_operator Prism.parse_statement(complex_source_1), :===, Prism.parse_statement(complex_source_2)
+ end
+ end
+end
diff --git a/test/prism/result/heredoc_test.rb b/test/prism/result/heredoc_test.rb
new file mode 100644
index 0000000000..7913c04a88
--- /dev/null
+++ b/test/prism/result/heredoc_test.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+require_relative "../test_helper"
+
+module Prism
+ class HeredocTest < TestCase
+ def test_heredoc?
+ refute Prism.parse_statement("\"foo\"").heredoc?
+ refute Prism.parse_statement("\"foo \#{1}\"").heredoc?
+ refute Prism.parse_statement("`foo`").heredoc?
+ refute Prism.parse_statement("`foo \#{1}`").heredoc?
+
+ assert Prism.parse_statement("<<~HERE\nfoo\nHERE\n").heredoc?
+ assert Prism.parse_statement("<<~HERE\nfoo \#{1}\nHERE\n").heredoc?
+ assert Prism.parse_statement("<<~`HERE`\nfoo\nHERE\n").heredoc?
+ assert Prism.parse_statement("<<~`HERE`\nfoo \#{1}\nHERE\n").heredoc?
+ end
+ end
+end
diff --git a/test/prism/result/implicit_array_test.rb b/test/prism/result/implicit_array_test.rb
new file mode 100644
index 0000000000..e7ddde70aa
--- /dev/null
+++ b/test/prism/result/implicit_array_test.rb
@@ -0,0 +1,59 @@
+# frozen_string_literal: true
+
+require_relative "../test_helper"
+
+module Prism
+ class ImplicitArrayTest < TestCase
+ def test_call_node
+ assert_implicit_array("a.a = *b")
+ assert_implicit_array("a.a = 1, 2, 3")
+ assert_implicit_array("a[a] = *b")
+ assert_implicit_array("a[a] = 1, 2, 3")
+ end
+
+ def test_class_variable_write_node
+ assert_implicit_array("@@a = *b")
+ assert_implicit_array("@@a = 1, 2, 3")
+ end
+
+ def test_constant_path_write_node
+ assert_implicit_array("A::A = *b")
+ assert_implicit_array("A::A = 1, 2, 3")
+ end
+
+ def test_constant_write_node
+ assert_implicit_array("A = *b")
+ assert_implicit_array("A = 1, 2, 3")
+ end
+
+ def test_global_variable_write_node
+ assert_implicit_array("$a = *b")
+ assert_implicit_array("$a = 1, 2, 3")
+ end
+
+ def test_instance_variable_write_node
+ assert_implicit_array("@a = *b")
+ assert_implicit_array("@a = 1, 2, 3")
+ end
+
+ def test_local_variable_write_node
+ assert_implicit_array("a = *b")
+ assert_implicit_array("a = 1, 2, 3")
+ end
+
+ def test_multi_write_node
+ assert_implicit_array("a, b, c = *b")
+ assert_implicit_array("a, b, c = 1, 2, 3")
+ end
+
+ private
+
+ def assert_implicit_array(source)
+ assert Prism.parse_success?(source)
+ assert Prism.parse_failure?("if #{source} then end")
+
+ assert_valid_syntax(source)
+ refute_valid_syntax("if #{source} then end")
+ end
+ end
+end
diff --git a/test/prism/result/index_write_test.rb b/test/prism/result/index_write_test.rb
new file mode 100644
index 0000000000..0d5383b601
--- /dev/null
+++ b/test/prism/result/index_write_test.rb
@@ -0,0 +1,89 @@
+# frozen_string_literal: true
+
+require_relative "../test_helper"
+
+module Prism
+ class IndexWriteTest < TestCase
+ def test_keywords_3_3
+ assert_parse_success(<<~RUBY, "3.3.0")
+ foo[bar: 1] = 1
+ foo[bar: 1] &&= 1
+ foo[bar: 1] ||= 1
+ foo[bar: 1] += 1
+ RUBY
+
+ assert_parse_success(<<~RUBY, "3.3.0")
+ def foo(**)
+ bar[**] = 1
+ bar[**] &&= 1
+ bar[**] ||= 1
+ bar[**] += 1
+ end
+ RUBY
+ end
+
+ def test_block_3_3
+ assert_parse_success(<<~RUBY, "3.3.0")
+ foo[&bar] = 1
+ foo[&bar] &&= 1
+ foo[&bar] ||= 1
+ foo[&bar] += 1
+ RUBY
+
+ assert_parse_success(<<~RUBY, "3.3.0")
+ def foo(&)
+ bar[&] = 1
+ bar[&] &&= 1
+ bar[&] ||= 1
+ bar[&] += 1
+ end
+ RUBY
+ end
+
+ def test_keywords_latest
+ assert_parse_failure(<<~RUBY)
+ foo[bar: 1] = 1
+ foo[bar: 1] &&= 1
+ foo[bar: 1] ||= 1
+ foo[bar: 1] += 1
+ RUBY
+
+ assert_parse_failure(<<~RUBY)
+ def foo(**)
+ bar[**] = 1
+ bar[**] &&= 1
+ bar[**] ||= 1
+ bar[**] += 1
+ end
+ RUBY
+ end
+
+ def test_block_latest
+ assert_parse_failure(<<~RUBY)
+ foo[&bar] = 1
+ foo[&bar] &&= 1
+ foo[&bar] ||= 1
+ foo[&bar] += 1
+ RUBY
+
+ assert_parse_failure(<<~RUBY)
+ def foo(&)
+ bar[&] = 1
+ bar[&] &&= 1
+ bar[&] ||= 1
+ bar[&] += 1
+ end
+ RUBY
+ end
+
+ private
+
+ def assert_parse_success(source, version = "latest")
+ assert Prism.parse_success?(source, version: version)
+ end
+
+ def assert_parse_failure(source, version = "latest")
+ assert Prism.parse_failure?(source, version: version)
+ end
+ end
+end
diff --git a/test/prism/result/integer_base_flags_test.rb b/test/prism/result/integer_base_flags_test.rb
new file mode 100644
index 0000000000..e3ab8c6910
--- /dev/null
+++ b/test/prism/result/integer_base_flags_test.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+require_relative "../test_helper"
+
+module Prism
+ class IntegerBaseFlagsTest < TestCase
+ # Through some bit hackery, we want to allow consumers to use the integer
+ # base flags as the base itself. It has a nice property that the current
+ # alignment provides them in the correct order. So here we test that our
+ # assumption holds so that it doesn't change out from under us.
+ #
+ # In C, this would look something like:
+ #
+ # ((flags & ~DECIMAL) >> 1) || 10
+ #
+ # We have to do some other work in Ruby because 0 is truthy and ~ on an
+ # integer doesn't have a fixed width.
+ def test_flags
+ assert_equal 2, base("0b1")
+ assert_equal 8, base("0o1")
+ assert_equal 10, base("0d1")
+ assert_equal 16, base("0x1")
+ end
+
+ private
+
+ def base(source)
+ node = Prism.parse_statement(source)
+ value = (node.send(:flags) & (0b111100 - IntegerBaseFlags::DECIMAL)) >> 1
+ value == 0 ? 10 : value
+ end
+ end
+end
diff --git a/test/prism/result/integer_parse_test.rb b/test/prism/result/integer_parse_test.rb
new file mode 100644
index 0000000000..7b5ce98bb6
--- /dev/null
+++ b/test/prism/result/integer_parse_test.rb
@@ -0,0 +1,41 @@
+# frozen_string_literal: true
+
+require_relative "../test_helper"
+
+module Prism
+ class IntegerParseTest < TestCase
+ def test_integer_parse
+ assert_integer_parse(1)
+ assert_integer_parse(50)
+ assert_integer_parse(100)
+ assert_integer_parse(100, "1_0_0")
+ assert_integer_parse(8, "0_1_0")
+
+ assert_integer_parse(10, "0b1010")
+ assert_integer_parse(10, "0B1010")
+ assert_integer_parse(10, "0o12")
+ assert_integer_parse(10, "0O12")
+ assert_integer_parse(10, "012")
+ assert_integer_parse(10, "0d10")
+ assert_integer_parse(10, "0D10")
+ assert_integer_parse(10, "0xA")
+ assert_integer_parse(10, "0XA")
+
+ assert_integer_parse(2**32)
+ assert_integer_parse(2**64 + 2**32)
+ assert_integer_parse(2**128 + 2**64 + 2**32)
+
+ num = 99 ** 99
+ assert_integer_parse(num, "0b#{num.to_s(2)}")
+ assert_integer_parse(num, "0o#{num.to_s(8)}")
+ assert_integer_parse(num, "0d#{num.to_s(10)}")
+ assert_integer_parse(num, "0x#{num.to_s(16)}")
+ end
+
+ private
+
+ def assert_integer_parse(expected, source = expected.to_s)
+ assert_equal expected, Prism.parse_statement(source).value
+ end
+ end
+end
diff --git a/test/prism/result/node_id_test.rb b/test/prism/result/node_id_test.rb
new file mode 100644
index 0000000000..59b79bc574
--- /dev/null
+++ b/test/prism/result/node_id_test.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+require_relative "../test_helper"
+
+module Prism
+ class NodeIdTest < TestCase
+ Fixture.each do |fixture|
+ define_method(fixture.test_name) { assert_node_ids(fixture.read) }
+ end
+
+ private
+
+ def assert_node_ids(source)
+ queue = [Prism.parse(source).value]
+ node_ids = []
+
+ while (node = queue.shift)
+ node_ids << node.node_id
+ queue.concat(node.compact_child_nodes)
+ end
+
+ node_ids.sort!
+ refute_includes node_ids, 0
+ assert_equal node_ids, node_ids.uniq
+ end
+ end
+end
diff --git a/test/prism/result/numeric_value_test.rb b/test/prism/result/numeric_value_test.rb
new file mode 100644
index 0000000000..5c89230a1f
--- /dev/null
+++ b/test/prism/result/numeric_value_test.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require_relative "../test_helper"
+
+module Prism
+ class NumericValueTest < TestCase
+ def test_numeric_value
+ assert_equal 123, Prism.parse_statement("123").value
+ assert_equal 3.14, Prism.parse_statement("3.14").value
+ assert_equal 42i, Prism.parse_statement("42i").value
+ assert_equal 42.1ri, Prism.parse_statement("42.1ri").value
+ assert_equal 3.14i, Prism.parse_statement("3.14i").value
+ assert_equal 42r, Prism.parse_statement("42r").value
+ assert_equal 0.5r, Prism.parse_statement("0.5r").value
+ assert_equal 42ri, Prism.parse_statement("42ri").value
+ assert_equal 0.5ri, Prism.parse_statement("0.5ri").value
+ assert_equal 0xFFr, Prism.parse_statement("0xFFr").value
+ assert_equal 0xFFri, Prism.parse_statement("0xFFri").value
+ end
+ end
+end
diff --git a/test/prism/result/overlap_test.rb b/test/prism/result/overlap_test.rb
new file mode 100644
index 0000000000..155bc870d3
--- /dev/null
+++ b/test/prism/result/overlap_test.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+require_relative "../test_helper"
+
+module Prism
+ class OverlapTest < TestCase
+ Fixture.each do |fixture|
+ define_method(fixture.test_name) { assert_overlap(fixture) }
+ end
+
+ private
+
+ # Check that the location ranges of each node in the tree are a superset of
+ # their respective child nodes.
+ def assert_overlap(fixture)
+ queue = [Prism.parse_file(fixture.full_path).value]
+
+ while (current = queue.shift)
+ # We only want to compare parent/child location overlap in the case that
+ # we are not looking at a heredoc. That's because heredoc locations are
+ # special in that they only use the declaration of the heredoc.
+ compare = !(current.is_a?(StringNode) ||
+ current.is_a?(XStringNode) ||
+ current.is_a?(InterpolatedStringNode) ||
+ current.is_a?(InterpolatedXStringNode)) ||
+ !current.opening&.start_with?("<<")
+
+ current.child_nodes.each do |child|
+ # child_nodes can return nil values, so we need to skip those.
+ next unless child
+
+ # Now that we know we have a child node, add that to the queue.
+ queue << child
+
+ if compare
+ assert_operator current.location.start_offset, :<=, child.location.start_offset
+ assert_operator current.location.end_offset, :>=, child.location.end_offset
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/test/prism/result/regular_expression_options_test.rb b/test/prism/result/regular_expression_options_test.rb
new file mode 100644
index 0000000000..ff6e20526f
--- /dev/null
+++ b/test/prism/result/regular_expression_options_test.rb
@@ -0,0 +1,25 @@
+# frozen_string_literal: true
+
+require_relative "../test_helper"
+
+module Prism
+ class RegularExpressionOptionsTest < TestCase
+ def test_options
+ assert_equal "", Prism.parse_statement("__FILE__").filepath
+ assert_equal "foo.rb", Prism.parse_statement("__FILE__", filepath: "foo.rb").filepath
+
+ assert_equal 1, Prism.parse_statement("foo").location.start_line
+ assert_equal 10, Prism.parse_statement("foo", line: 10).location.start_line
+
+ refute Prism.parse_statement("\"foo\"").frozen?
+ assert Prism.parse_statement("\"foo\"", frozen_string_literal: true).frozen?
+ refute Prism.parse_statement("\"foo\"", frozen_string_literal: false).frozen?
+
+ assert_kind_of CallNode, Prism.parse_statement("foo")
+ assert_kind_of LocalVariableReadNode, Prism.parse_statement("foo", scopes: [[:foo]])
+ assert_equal 1, Prism.parse_statement("foo", scopes: [[:foo], []]).depth
+
+ assert_equal [:foo], Prism.parse("foo", scopes: [[:foo]]).value.locals
+ end
+ end
+end
diff --git a/test/prism/result/source_location_test.rb b/test/prism/result/source_location_test.rb
new file mode 100644
index 0000000000..7bdc707658
--- /dev/null
+++ b/test/prism/result/source_location_test.rb
@@ -0,0 +1,950 @@
+# frozen_string_literal: true
+
+require_relative "../test_helper"
+
+module Prism
+ class SourceLocationTest < TestCase
+ def test_AliasGlobalVariableNode
+ assert_location(AliasGlobalVariableNode, "alias $foo $bar")
+ end
+
+ def test_AliasMethodNode
+ assert_location(AliasMethodNode, "alias foo bar")
+ end
+
+ def test_AlternationPatternNode
+ assert_location(AlternationPatternNode, "foo => bar | baz", 7...16, &:pattern)
+ end
+
+ def test_AndNode
+ assert_location(AndNode, "foo and bar")
+ assert_location(AndNode, "foo && bar")
+ end
+
+ def test_ArgumentsNode
+ assert_location(ArgumentsNode, "foo(bar, baz, qux)", 4...17, &:arguments)
+ end
+
+ def test_ArrayNode
+ assert_location(ArrayNode, "[foo, bar, baz]")
+ assert_location(ArrayNode, "%i[foo bar baz]")
+ assert_location(ArrayNode, "%I[foo bar baz]")
+ assert_location(ArrayNode, "%w[foo bar baz]")
+ assert_location(ArrayNode, "%W[foo bar baz]")
+ end
+
+ def test_ArrayPatternNode
+ assert_location(ArrayPatternNode, "foo => bar, baz", 7...15, &:pattern)
+ assert_location(ArrayPatternNode, "foo => [bar, baz]", 7...17, &:pattern)
+ assert_location(ArrayPatternNode, "foo => *bar", 7...11, &:pattern)
+ assert_location(ArrayPatternNode, "foo => []", 7...9, &:pattern)
+ assert_location(ArrayPatternNode, "foo => Foo[]", 7...12, &:pattern)
+ assert_location(ArrayPatternNode, "foo => Foo[bar]", 7...15, &:pattern)
+ end
+
+ def test_AssocNode
+ assert_location(AssocNode, "{ '': 1 }", 2...7) { |node| node.elements.first }
+ assert_location(AssocNode, "{ foo: :bar }", 2...11) { |node| node.elements.first }
+ assert_location(AssocNode, "{ :foo => :bar }", 2...14) { |node| node.elements.first }
+ assert_location(AssocNode, "foo(bar: :baz)", 4...13) { |node| node.arguments.arguments.first.elements.first }
+ end
+
+ def test_AssocSplatNode
+ assert_location(AssocSplatNode, "{ **foo }", 2...7) { |node| node.elements.first }
+ assert_location(AssocSplatNode, "foo(**bar)", 4...9) { |node| node.arguments.arguments.first.elements.first }
+ end
+
+ def test_BackReferenceReadNode
+ assert_location(BackReferenceReadNode, "$+")
+ end
+
+ def test_BeginNode
+ assert_location(BeginNode, "begin foo end")
+ assert_location(BeginNode, "begin foo rescue bar end")
+ assert_location(BeginNode, "begin foo; rescue bar\nelse baz end")
+ assert_location(BeginNode, "begin foo; rescue bar\nelse baz\nensure qux end")
+
+ assert_location(BeginNode, "class Foo\nrescue then end", 0..25, &:body)
+ assert_location(BeginNode, "module Foo\nrescue then end", 0..26, &:body)
+ end
+
+ def test_BlockArgumentNode
+ assert_location(BlockArgumentNode, "foo(&bar)", 4...8, &:block)
+ end
+
+ def test_BlockLocalVariableNode
+ assert_location(BlockLocalVariableNode, "foo { |;bar| }", 8...11) do |node|
+ node.block.parameters.locals.first
+ end
+ end
+
+ def test_BlockNode
+ assert_location(BlockNode, "foo {}", 4...6, &:block)
+ assert_location(BlockNode, "foo do end", 4...10, &:block)
+ end
+
+ def test_BlockParameterNode
+ assert_location(BlockParameterNode, "def foo(&bar) end", 8...12) { |node| node.parameters.block }
+ end
+
+ def test_BlockParametersNode
+ assert_location(BlockParametersNode, "foo { || }", 6...8) { |node| node.block.parameters }
+ assert_location(BlockParametersNode, "foo { |bar| baz }", 6...11) { |node| node.block.parameters }
+ assert_location(BlockParametersNode, "foo { |bar; baz| baz }", 6...16) { |node| node.block.parameters }
+
+ assert_location(BlockParametersNode, "-> () {}", 3...5, &:parameters)
+ assert_location(BlockParametersNode, "-> (bar) { baz }", 3...8, &:parameters)
+ assert_location(BlockParametersNode, "-> (bar; baz) { baz }", 3...13, &:parameters)
+ end
+
+ def test_BreakNode
+ assert_location(BreakNode, "tap { break }", 6...11) { |node| node.block.body.body.first }
+ assert_location(BreakNode, "tap { break foo }", 6...15) { |node| node.block.body.body.first }
+ assert_location(BreakNode, "tap { break foo, bar }", 6...20) { |node| node.block.body.body.first }
+ assert_location(BreakNode, "tap { break(foo) }", 6...16) { |node| node.block.body.body.first }
+ end
+
+ def test_CallNode
+ assert_location(CallNode, "foo")
+ assert_location(CallNode, "foo?")
+ assert_location(CallNode, "foo!")
+
+ assert_location(CallNode, "foo()")
+ assert_location(CallNode, "foo?()")
+ assert_location(CallNode, "foo!()")
+
+ assert_location(CallNode, "foo(bar)")
+ assert_location(CallNode, "foo?(bar)")
+ assert_location(CallNode, "foo!(bar)")
+
+ assert_location(CallNode, "!foo")
+ assert_location(CallNode, "~foo")
+ assert_location(CallNode, "+foo")
+ assert_location(CallNode, "-foo")
+
+ assert_location(CallNode, "not foo")
+ assert_location(CallNode, "not(foo)")
+ assert_location(CallNode, "not()")
+
+ assert_location(CallNode, "foo + bar")
+ assert_location(CallNode, "foo -\n bar")
+
+ assert_location(CallNode, "Foo()")
+ assert_location(CallNode, "Foo(bar)")
+
+ assert_location(CallNode, "Foo::Bar()")
+ assert_location(CallNode, "Foo::Bar(baz)")
+
+ assert_location(CallNode, "Foo::bar")
+ assert_location(CallNode, "Foo::bar()")
+ assert_location(CallNode, "Foo::bar(baz)")
+
+ assert_location(CallNode, "Foo.bar")
+ assert_location(CallNode, "Foo.bar()")
+ assert_location(CallNode, "Foo.bar(baz)")
+
+ assert_location(CallNode, "foo::bar")
+ assert_location(CallNode, "foo::bar()")
+ assert_location(CallNode, "foo::bar(baz)")
+
+ assert_location(CallNode, "foo.bar")
+ assert_location(CallNode, "foo.bar()")
+ assert_location(CallNode, "foo.bar(baz)")
+
+ assert_location(CallNode, "foo&.bar")
+ assert_location(CallNode, "foo&.bar()")
+ assert_location(CallNode, "foo&.bar(baz)")
+
+ assert_location(CallNode, "foo[]")
+ assert_location(CallNode, "foo[bar]")
+ assert_location(CallNode, "foo[bar, baz]")
+
+ assert_location(CallNode, "foo[] = 1")
+ assert_location(CallNode, "foo[bar] = 1")
+ assert_location(CallNode, "foo[bar, baz] = 1")
+
+ assert_location(CallNode, "foo.()")
+ assert_location(CallNode, "foo.(bar)")
+
+ assert_location(CallNode, "foo&.()")
+ assert_location(CallNode, "foo&.(bar)")
+
+ assert_location(CallNode, "foo::()")
+ assert_location(CallNode, "foo::(bar)")
+ assert_location(CallNode, "foo::(bar, baz)")
+
+ assert_location(CallNode, "foo bar baz")
+ assert_location(CallNode, "foo bar('baz')")
+ end
+
+ def test_CallAndWriteNode
+ assert_location(CallAndWriteNode, "foo.foo &&= bar")
+ end
+
+ def test_CallOperatorWriteNode
+ assert_location(CallOperatorWriteNode, "foo.foo += bar")
+ end
+
+ def test_CallOrWriteNode
+ assert_location(CallOrWriteNode, "foo.foo ||= bar")
+ end
+
+ def test_CallTargetNode
+ assert_location(CallTargetNode, "foo.bar, = baz", 0...7) do |node|
+ node.lefts.first
+ end
+ end
+
+ def test_CapturePatternNode
+ assert_location(CapturePatternNode, "case foo; in bar => baz; end", 13...23) do |node|
+ node.conditions.first.pattern
+ end
+ end
+
+ def test_CaseNode
+ assert_location(CaseNode, "case foo; when bar; end")
+ assert_location(CaseNode, "case foo; when bar; else; end")
+ assert_location(CaseNode, "case foo; when bar; when baz; end")
+ assert_location(CaseNode, "case foo; when bar; when baz; else; end")
+ end
+
+ def test_CaseMatchNode
+ assert_location(CaseMatchNode, "case foo; in bar; end")
+ assert_location(CaseMatchNode, "case foo; in bar; else; end")
+ assert_location(CaseMatchNode, "case foo; in bar; in baz; end")
+ assert_location(CaseMatchNode, "case foo; in bar; in baz; else; end")
+ end
+
+ def test_ClassNode
+ assert_location(ClassNode, "class Foo end")
+ assert_location(ClassNode, "class Foo < Bar; end")
+ end
+
+ def test_ClassVariableAndWriteNode
+ assert_location(ClassVariableAndWriteNode, "@@foo &&= bar")
+ end
+
+ def test_ClassVariableOperatorWriteNode
+ assert_location(ClassVariableOperatorWriteNode, "@@foo += bar")
+ end
+
+ def test_ClassVariableOrWriteNode
+ assert_location(ClassVariableOrWriteNode, "@@foo ||= bar")
+ end
+
+ def test_ClassVariableReadNode
+ assert_location(ClassVariableReadNode, "@@foo")
+ end
+
+ def test_ClassVariableTargetNode
+ assert_location(ClassVariableTargetNode, "@@foo, @@bar = baz", 0...5) do |node|
+ node.lefts.first
+ end
+ end
+
+ def test_ClassVariableWriteNode
+ assert_location(ClassVariableWriteNode, "@@foo = bar")
+ end
+
+ def test_ConstantPathAndWriteNode
+ assert_location(ConstantPathAndWriteNode, "Parent::Child &&= bar")
+ end
+
+ def test_ConstantPathNode
+ assert_location(ConstantPathNode, "Foo::Bar")
+ assert_location(ConstantPathNode, "::Foo")
+ assert_location(ConstantPathNode, "::Foo::Bar")
+ end
+
+ def test_ConstantPathOperatorWriteNode
+ assert_location(ConstantPathOperatorWriteNode, "Parent::Child += bar")
+ end
+
+ def test_ConstantPathOrWriteNode
+ assert_location(ConstantPathOrWriteNode, "Parent::Child ||= bar")
+ end
+
+ def test_ConstantPathTargetNode
+ assert_location(ConstantPathTargetNode, "::Foo, ::Bar = baz", 0...5) do |node|
+ node.lefts.first
+ end
+ end
+
+ def test_ConstantPathWriteNode
+ assert_location(ConstantPathWriteNode, "Foo::Bar = baz")
+ assert_location(ConstantPathWriteNode, "::Foo = bar")
+ assert_location(ConstantPathWriteNode, "::Foo::Bar = baz")
+ end
+
+ def test_ConstantAndWriteNode
+ assert_location(ConstantAndWriteNode, "Foo &&= bar")
+ end
+
+ def test_ConstantOperatorWriteNode
+ assert_location(ConstantOperatorWriteNode, "Foo += bar")
+ end
+
+ def test_ConstantOrWriteNode
+ assert_location(ConstantOrWriteNode, "Foo ||= bar")
+ end
+
+ def test_ConstantReadNode
+ assert_location(ConstantReadNode, "Foo")
+ end
+
+ def test_ConstantTargetNode
+ assert_location(ConstantTargetNode, "Foo, Bar = baz", 0...3) do |node|
+ node.lefts.first
+ end
+ end
+
+ def test_ConstantWriteNode
+ assert_location(ConstantWriteNode, "Foo = bar")
+ end
+
+ def test_DefNode
+ assert_location(DefNode, "def foo; bar; end")
+ assert_location(DefNode, "def foo = bar")
+ assert_location(DefNode, "def foo.bar; baz; end")
+ assert_location(DefNode, "def foo.bar = baz")
+ end
+
+ def test_DefinedNode
+ assert_location(DefinedNode, "defined? foo")
+ assert_location(DefinedNode, "defined?(foo)")
+ end
+
+ def test_ElseNode
+ assert_location(ElseNode, "if foo; bar; else; baz; end", 13...27, &:subsequent)
+ assert_location(ElseNode, "foo ? bar : baz", 10...15, &:subsequent)
+ end
+
+ def test_EmbeddedStatementsNode
+ assert_location(EmbeddedStatementsNode, '"foo #{bar} baz"', 5...11) { |node| node.parts[1] }
+ end
+
+ def test_EmbeddedVariableNode
+ assert_location(EmbeddedVariableNode, '"foo #@@bar baz"', 5...11) { |node| node.parts[1] }
+ end
+
+ def test_EnsureNode
+ assert_location(EnsureNode, "begin; foo; ensure; bar; end", 12...28, &:ensure_clause)
+ end
+
+ def test_FalseNode
+ assert_location(FalseNode, "false")
+ end
+
+ def test_FindPatternNode
+ assert_location(FindPatternNode, "case foo; in *, bar, *; end", 13...22) do |node|
+ node.conditions.first.pattern
+ end
+ end
+
+ def test_FlipFlopNode
+ assert_location(FlipFlopNode, "if foo..bar; end", 3..11, &:predicate)
+ end
+
+ def test_FloatNode
+ assert_location(FloatNode, "0.0")
+ assert_location(FloatNode, "1.0")
+ assert_location(FloatNode, "1.0e10")
+ assert_location(FloatNode, "1.0e-10")
+ end
+
+ def test_ForNode
+ assert_location(ForNode, "for foo in bar; end")
+ assert_location(ForNode, "for foo, bar in baz do end")
+ end
+
+ def test_ForwardingArgumentsNode
+ assert_location(ForwardingArgumentsNode, "def foo(...); bar(...); end", 18...21) do |node|
+ node.body.body.first.arguments.arguments.first
+ end
+ end
+
+ def test_ForwardingParameterNode
+ assert_location(ForwardingParameterNode, "def foo(...); end", 8...11) do |node|
+ node.parameters.keyword_rest
+ end
+ end
+
+ def test_ForwardingSuperNode
+ assert_location(ForwardingSuperNode, "super")
+ assert_location(ForwardingSuperNode, "super {}")
+ end
+
+ def test_GlobalVariableAndWriteNode
+ assert_location(GlobalVariableAndWriteNode, "$foo &&= bar")
+ end
+
+ def test_GlobalVariableOperatorWriteNode
+ assert_location(GlobalVariableOperatorWriteNode, "$foo += bar")
+ end
+
+ def test_GlobalVariableOrWriteNode
+ assert_location(GlobalVariableOrWriteNode, "$foo ||= bar")
+ end
+
+ def test_GlobalVariableReadNode
+ assert_location(GlobalVariableReadNode, "$foo")
+ end
+
+ def test_GlobalVariableTargetNode
+ assert_location(GlobalVariableTargetNode, "$foo, $bar = baz", 0...4) do |node|
+ node.lefts.first
+ end
+ end
+
+ def test_GlobalVariableWriteNode
+ assert_location(GlobalVariableWriteNode, "$foo = bar")
+ end
+
+ def test_HashNode
+ assert_location(HashNode, "{ foo: 2 }")
+ assert_location(HashNode, "{ \nfoo: 2, \nbar: 3 \n}")
+ end
+
+ def test_HashPatternNode
+ assert_location(HashPatternNode, "case foo; in bar: baz; end", 13...21) do |node|
+ node.conditions.first.pattern
+ end
+ end
+
+ def test_IfNode
+ assert_location(IfNode, "if type in 1;elsif type in B;end")
+ end
+
+ def test_ImaginaryNode
+ assert_location(ImaginaryNode, "1i")
+ assert_location(ImaginaryNode, "1ri")
+ end
+
+ def test_ImplicitNode
+ assert_location(ImplicitNode, "{ foo: }", 2...6) do |node|
+ node.elements.first.value
+ end
+
+ assert_location(ImplicitNode, "{ Foo: }", 2..6) do |node|
+ node.elements.first.value
+ end
+
+ assert_location(ImplicitNode, "foo = 1; { foo: }", 11..15) do |node|
+ node.elements.first.value
+ end
+ end
+
+ def test_ImplicitRestNode
+ assert_location(ImplicitRestNode, "foo, = bar", 3..4, &:rest)
+
+ assert_location(ImplicitRestNode, "for foo, in bar do end", 7..8) do |node|
+ node.index.rest
+ end
+
+ assert_location(ImplicitRestNode, "foo { |bar,| }", 10..11) do |node|
+ node.block.parameters.parameters.rest
+ end
+
+ assert_location(ImplicitRestNode, "foo in [bar,]", 11..12) do |node|
+ node.pattern.rest
+ end
+ end
+
+ def test_InNode
+ assert_location(InNode, "case foo; in bar; end", 10...16) do |node|
+ node.conditions.first
+ end
+ end
+
+ def test_IndexAndWriteNode
+ assert_location(IndexAndWriteNode, "foo[foo] &&= bar")
+ end
+
+ def test_IndexOperatorWriteNode
+ assert_location(IndexOperatorWriteNode, "foo[foo] += bar")
+ end
+
+ def test_IndexOrWriteNode
+ assert_location(IndexOrWriteNode, "foo[foo] ||= bar")
+ end
+
+ def test_IndexTargetNode
+ assert_location(IndexTargetNode, "foo[bar], = qux", 0...8) do |node|
+ node.lefts.first
+ end
+ end
+
+ def test_InstanceVariableAndWriteNode
+ assert_location(InstanceVariableAndWriteNode, "@foo &&= bar")
+ end
+
+ def test_InstanceVariableOperatorWriteNode
+ assert_location(InstanceVariableOperatorWriteNode, "@foo += bar")
+ end
+
+ def test_InstanceVariableOrWriteNode
+ assert_location(InstanceVariableOrWriteNode, "@foo ||= bar")
+ end
+
+ def test_InstanceVariableReadNode
+ assert_location(InstanceVariableReadNode, "@foo")
+ end
+
+ def test_InstanceVariableTargetNode
+ assert_location(InstanceVariableTargetNode, "@foo, @bar = baz", 0...4) do |node|
+ node.lefts.first
+ end
+ end
+
+ def test_InstanceVariableWriteNode
+ assert_location(InstanceVariableWriteNode, "@foo = bar")
+ end
+
+ def test_IntegerNode
+ assert_location(IntegerNode, "0")
+ assert_location(IntegerNode, "1")
+ assert_location(IntegerNode, "1_000")
+ assert_location(IntegerNode, "0x1")
+ assert_location(IntegerNode, "0x1_000")
+ assert_location(IntegerNode, "0b1")
+ assert_location(IntegerNode, "0b1_000")
+ assert_location(IntegerNode, "0o1")
+ assert_location(IntegerNode, "0o1_000")
+ end
+
+ def test_InterpolatedMatchLastLineNode
+ assert_location(InterpolatedMatchLastLineNode, "if /foo \#{bar}/ then end", 3...15, &:predicate)
+ end
+
+ def test_InterpolatedRegularExpressionNode
+ assert_location(InterpolatedRegularExpressionNode, "/\#{foo}/")
+ assert_location(InterpolatedRegularExpressionNode, "/\#{foo}/io")
+ end
+
+ def test_InterpolatedStringNode
+ assert_location(InterpolatedStringNode, "\"foo \#@bar baz\"")
+ assert_location(InterpolatedStringNode, "<<~A\nhello \#{1} world\nA", 0...4)
+ assert_location(InterpolatedStringNode, '"foo" "bar"')
+ end
+
+ def test_InterpolatedSymbolNode
+ assert_location(InterpolatedSymbolNode, ':"#{foo}bar"')
+ end
+
+ def test_InterpolatedXStringNode
+ assert_location(InterpolatedXStringNode, '`foo #{bar} baz`')
+ end
+
+ def test_ItLocalVariableReadNode
+ assert_location(ItLocalVariableReadNode, "-> { it }", 5...7) do |node|
+ node.body.body.first
+ end
+
+ assert_location(ItLocalVariableReadNode, "foo { it }", 6...8) do |node|
+ node.block.body.body.first
+ end
+
+ assert_location(CallNode, "-> { it }", 5...7, version: "3.3.0") do |node|
+ node.body.body.first
+ end
+
+ assert_location(ItLocalVariableReadNode, "-> { it }", 5...7, version: "3.4.0") do |node|
+ node.body.body.first
+ end
+ end
+
+ def test_ItParametersNode
+ assert_location(ItParametersNode, "-> { it }", &:parameters)
+ end
+
+ def test_KeywordHashNode
+ assert_location(KeywordHashNode, "foo(a, b: 1)", 7...11) { |node| node.arguments.arguments[1] }
+ end
+
+ def test_KeywordRestParameterNode
+ assert_location(KeywordRestParameterNode, "def foo(**); end", 8...10) do |node|
+ node.parameters.keyword_rest
+ end
+
+ assert_location(KeywordRestParameterNode, "def foo(**bar); end", 8...13) do |node|
+ node.parameters.keyword_rest
+ end
+ end
+
+ def test_LambdaNode
+ assert_location(LambdaNode, "-> { foo }")
+ assert_location(LambdaNode, "-> do foo end")
+ end
+
+ def test_LocalVariableAndWriteNode
+ assert_location(LocalVariableAndWriteNode, "foo &&= bar")
+ assert_location(LocalVariableAndWriteNode, "foo = 1; foo &&= bar", 9...20)
+ end
+
+ def test_LocalVariableOperatorWriteNode
+ assert_location(LocalVariableOperatorWriteNode, "foo += bar")
+ assert_location(LocalVariableOperatorWriteNode, "foo = 1; foo += bar", 9...19)
+ end
+
+ def test_LocalVariableOrWriteNode
+ assert_location(LocalVariableOrWriteNode, "foo ||= bar")
+ assert_location(LocalVariableOrWriteNode, "foo = 1; foo ||= bar", 9...20)
+ end
+
+ def test_LocalVariableReadNode
+ assert_location(LocalVariableReadNode, "foo = 1; foo", 9...12)
+ end
+
+ def test_LocalVariableTargetNode
+ assert_location(LocalVariableTargetNode, "foo, bar = baz", 0...3) do |node|
+ node.lefts.first
+ end
+ end
+
+ def test_LocalVariableWriteNode
+ assert_location(LocalVariableWriteNode, "foo = bar")
+ end
+
+ def test_MatchLastLineNode
+ assert_location(MatchLastLineNode, "if /foo/ then end", 3...8, &:predicate)
+ end
+
+ def test_MatchPredicateNode
+ assert_location(MatchPredicateNode, "foo in bar")
+ end
+
+ def test_MatchRequiredNode
+ assert_location(MatchRequiredNode, "foo => bar")
+ end
+
+ def test_MatchWriteNode
+ assert_location(MatchWriteNode, "/(?<foo>)/ =~ foo")
+ end
+
+ def test_ModuleNode
+ assert_location(ModuleNode, "module Foo end")
+ end
+
+ def test_MultiTargetNode
+ assert_location(MultiTargetNode, "for foo, bar in baz do end", 4...12, &:index)
+ assert_location(MultiTargetNode, "foo, (bar, baz) = qux", 5...15) { |node| node.lefts.last }
+ assert_location(MultiTargetNode, "def foo((bar)); end", 8...13) do |node|
+ node.parameters.requireds.first
+ end
+ end
+
+ def test_MultiWriteNode
+ assert_location(MultiWriteNode, "foo, bar = baz")
+ assert_location(MultiWriteNode, "(foo, bar) = baz")
+ assert_location(MultiWriteNode, "((foo, bar)) = baz")
+ end
+
+ def test_NextNode
+ assert_location(NextNode, "tap { next }", 6...10) { |node| node.block.body.body.first }
+ assert_location(NextNode, "tap { next foo }", 6...14) { |node| node.block.body.body.first }
+ assert_location(NextNode, "tap { next foo, bar }", 6...19) { |node| node.block.body.body.first }
+ assert_location(NextNode, "tap { next(foo) }", 6...15) { |node| node.block.body.body.first }
+ end
+
+ def test_NilNode
+ assert_location(NilNode, "nil")
+ end
+
+ def test_NoKeywordsParameterNode
+ assert_location(NoKeywordsParameterNode, "def foo(**nil); end", 8...13) { |node| node.parameters.keyword_rest }
+ end
+
+ def test_NumberedParametersNode
+ assert_location(NumberedParametersNode, "-> { _1 }", &:parameters)
+ assert_location(NumberedParametersNode, "foo { _1 }", 4...10) { |node| node.block.parameters }
+ end
+
+ def test_NumberedReferenceReadNode
+ assert_location(NumberedReferenceReadNode, "$1")
+ end
+
+ def test_OptionalKeywordParameterNode
+ assert_location(OptionalKeywordParameterNode, "def foo(bar: nil); end", 8...16) do |node|
+ node.parameters.keywords.first
+ end
+ end
+
+ def test_OptionalParameterNode
+ assert_location(OptionalParameterNode, "def foo(bar = nil); end", 8...17) do |node|
+ node.parameters.optionals.first
+ end
+ end
+
+ def test_OrNode
+ assert_location(OrNode, "foo || bar")
+ assert_location(OrNode, "foo or bar")
+ end
+
+ def test_ParametersNode
+ assert_location(ParametersNode, "def foo(bar, baz); end", 8...16, &:parameters)
+ end
+
+ def test_ParenthesesNode
+ assert_location(ParenthesesNode, "()")
+ assert_location(ParenthesesNode, "(foo)")
+ assert_location(ParenthesesNode, "foo (bar), baz", 4...9) { |node| node.arguments.arguments.first }
+ assert_location(ParenthesesNode, "def (foo).bar; end", 4...9, &:receiver)
+ end
+
+ def test_PinnedExpressionNode
+ assert_location(PinnedExpressionNode, "foo in ^(bar)", 7...13, &:pattern)
+ end
+
+ def test_PinnedVariableNode
+ assert_location(PinnedVariableNode, "bar = 1; foo in ^bar", 16...20, &:pattern)
+ assert_location(PinnedVariableNode, "proc { 1 in ^it }.call(1)", 12...15) do |node|
+ node.receiver.block.body.body.first.pattern
+ end
+ end
+
+ def test_PostExecutionNode
+ assert_location(PostExecutionNode, "END {}")
+ assert_location(PostExecutionNode, "END { foo }")
+ end
+
+ def test_PreExecutionNode
+ assert_location(PreExecutionNode, "BEGIN {}")
+ assert_location(PreExecutionNode, "BEGIN { foo }")
+ end
+
+ def test_RangeNode
+ assert_location(RangeNode, "1..2")
+ assert_location(RangeNode, "1...2")
+
+ assert_location(RangeNode, "..2")
+ assert_location(RangeNode, "...2")
+
+ assert_location(RangeNode, "1..")
+ assert_location(RangeNode, "1...")
+ end
+
+ def test_RationalNode
+ assert_location(RationalNode, "1r")
+ assert_location(RationalNode, "1.0r")
+ end
+
+ def test_RedoNode
+ assert_location(RedoNode, "tap { redo }", 6...10) { |node| node.block.body.body.first }
+ end
+
+ def test_RegularExpressionNode
+ assert_location(RegularExpressionNode, "/foo/")
+ assert_location(RegularExpressionNode, "/foo/io")
+ end
+
+ def test_RequiredKeywordParameterNode
+ assert_location(RequiredKeywordParameterNode, "def foo(bar:); end", 8...12) do |node|
+ node.parameters.keywords.first
+ end
+ end
+
+ def test_RequiredParameterNode
+ assert_location(RequiredParameterNode, "def foo(bar); end", 8...11) do |node|
+ node.parameters.requireds.first
+ end
+ end
+
+ def test_RescueNode
+ code = <<~RUBY
+ begin
+ body
+ rescue TypeError
+ rescue ArgumentError
+ end
+ RUBY
+ assert_location(RescueNode, code, 13...50) { |node| node.rescue_clause }
+ assert_location(RescueNode, code, 30...50) { |node| node.rescue_clause.subsequent }
+ end
+
+ def test_RescueModifierNode
+ assert_location(RescueModifierNode, "foo rescue bar")
+ end
+
+ def test_RestParameterNode
+ assert_location(RestParameterNode, "def foo(*bar); end", 8...12) do |node|
+ node.parameters.rest
+ end
+ end
+
+ def test_RetryNode
+ assert_location(RetryNode, "begin; rescue; retry; end", 15...20) { |node| node.rescue_clause.statements.body.first }
+ end
+
+ def test_ReturnNode
+ assert_location(ReturnNode, "return")
+ assert_location(ReturnNode, "return foo")
+ assert_location(ReturnNode, "return foo, bar")
+ assert_location(ReturnNode, "return(foo)")
+ end
+
+ def test_SelfNode
+ assert_location(SelfNode, "self")
+ end
+
+ def test_ShareableConstantNode
+ source = <<~RUBY
+ # shareable_constant_value: literal
+ C = { foo: 1 }
+ RUBY
+
+ assert_location(ShareableConstantNode, source, 36...50)
+ end
+
+ def test_SingletonClassNode
+ assert_location(SingletonClassNode, "class << self; end")
+ end
+
+ def test_SourceEncodingNode
+ assert_location(SourceEncodingNode, "__ENCODING__")
+ end
+
+ def test_SourceFileNode
+ assert_location(SourceFileNode, "__FILE__")
+ end
+
+ def test_SourceLineNode
+ assert_location(SourceLineNode, "__LINE__")
+ end
+
+ def test_SplatNode
+ assert_location(SplatNode, "*foo = bar", 0...4, &:rest)
+ end
+
+ def test_StatementsNode
+ assert_location(StatementsNode, "foo { 1 }", 6...7) { |node| node.block.body }
+
+ assert_location(StatementsNode, "(1)", 1...2, &:body)
+
+ assert_location(StatementsNode, "def foo; 1; end", 9...10, &:body)
+ assert_location(StatementsNode, "def foo = 1", 10...11, &:body)
+ assert_location(StatementsNode, "def foo; 1\n2; end", 9...12, &:body)
+
+ assert_location(StatementsNode, "if foo; bar; end", 8...11, &:statements)
+ assert_location(StatementsNode, "foo if bar", 0...3, &:statements)
+
+ assert_location(StatementsNode, "if foo; foo; elsif bar; bar; end", 24...27) { |node| node.subsequent.statements }
+ assert_location(StatementsNode, "if foo; foo; else; bar; end", 19...22) { |node| node.subsequent.statements }
+
+ assert_location(StatementsNode, "unless foo; bar; end", 12...15, &:statements)
+ assert_location(StatementsNode, "foo unless bar", 0...3, &:statements)
+
+ assert_location(StatementsNode, "case; when foo; bar; end", 16...19) { |node| node.conditions.first.statements }
+
+ assert_location(StatementsNode, "while foo; bar; end", 11...14, &:statements)
+ assert_location(StatementsNode, "foo while bar", 0...3, &:statements)
+
+ assert_location(StatementsNode, "until foo; bar; end", 11...14, &:statements)
+ assert_location(StatementsNode, "foo until bar", 0...3, &:statements)
+
+ assert_location(StatementsNode, "for foo in bar; baz; end", 16...19, &:statements)
+
+ assert_location(StatementsNode, "begin; foo; end", 7...10, &:statements)
+ assert_location(StatementsNode, "begin; rescue; foo; end", 15...18) { |node| node.rescue_clause.statements }
+ assert_location(StatementsNode, "begin; ensure; foo; end", 15...18) { |node| node.ensure_clause.statements }
+ assert_location(StatementsNode, "begin; rescue; else; foo; end", 21...24) { |node| node.else_clause.statements }
+
+ assert_location(StatementsNode, "class Foo; foo; end", 11...14, &:body)
+ assert_location(StatementsNode, "module Foo; foo; end", 12...15, &:body)
+ assert_location(StatementsNode, "class << self; foo; end", 15...18, &:body)
+
+ assert_location(StatementsNode, "-> { foo }", 5...8, &:body)
+ assert_location(StatementsNode, "BEGIN { foo }", 8...11, &:statements)
+ assert_location(StatementsNode, "END { foo }", 6...9, &:statements)
+
+ assert_location(StatementsNode, "\"\#{foo}\"", 3...6) { |node| node.parts.first.statements }
+ end
+
+ def test_StringNode
+ assert_location(StringNode, '"foo"')
+ assert_location(StringNode, '%q[foo]')
+ end
+
+ def test_SuperNode
+ assert_location(SuperNode, "super foo")
+ assert_location(SuperNode, "super foo, bar")
+
+ assert_location(SuperNode, "super()")
+ assert_location(SuperNode, "super(foo)")
+ assert_location(SuperNode, "super(foo, bar)")
+
+ assert_location(SuperNode, "super() {}")
+ end
+
+ def test_SymbolNode
+ assert_location(SymbolNode, ":foo")
+ end
+
+ def test_TrueNode
+ assert_location(TrueNode, "true")
+ end
+
+ def test_UndefNode
+ assert_location(UndefNode, "undef foo")
+ assert_location(UndefNode, "undef foo, bar")
+ end
+
+ def test_UnlessNode
+ assert_location(UnlessNode, "foo unless bar")
+ assert_location(UnlessNode, "unless bar; foo; end")
+ end
+
+ def test_UntilNode
+ assert_location(UntilNode, "foo = bar until baz")
+ assert_location(UntilNode, "until bar;baz;end")
+ end
+
+ def test_WhenNode
+ assert_location(WhenNode, "case foo; when bar; end", 10...18) { |node| node.conditions.first }
+ end
+
+ def test_WhileNode
+ assert_location(WhileNode, "foo = bar while foo != baz")
+ assert_location(WhileNode, "while a;bar;baz;end")
+ end
+
+ def test_XStringNode
+ assert_location(XStringNode, "`foo`")
+ assert_location(XStringNode, "%x[foo]")
+ end
+
+ def test_YieldNode
+ assert_location(YieldNode, "def test; yield; end", 10...15) { |node| node.body.body.first }
+ assert_location(YieldNode, "def test; yield foo; end", 10...19) { |node| node.body.body.first }
+ assert_location(YieldNode, "def test; yield foo, bar; end", 10...24) { |node| node.body.body.first }
+ assert_location(YieldNode, "def test; yield(foo); end", 10...20) { |node| node.body.body.first }
+ end
+
+ def test_all_tested
+ expected = Prism.constants.grep(/.Node$/).sort - %i[MissingNode ProgramNode]
+ actual = SourceLocationTest.instance_methods(false).grep(/.Node$/).map { |name| name[5..].to_sym }.sort
+ assert_equal expected, actual
+ end
+
+ private
+
+ def assert_location(kind, source, expected = 0...source.length, **options)
+ result = Prism.parse(source, **options)
+ assert result.success?
+
+ node = result.value.statements.body.last
+ node = yield node if block_given?
+
+ if expected.begin == 0
+ assert_equal 0, node.location.start_column
+ end
+
+ if expected.end == source.length
+ assert_equal source.split("\n").last.length, node.location.end_column
+ end
+
+ assert_kind_of kind, node
+ assert_equal expected.begin, node.location.start_offset
+ assert_equal expected.end, node.location.end_offset
+ end
+ end
+end
diff --git a/test/prism/result/static_inspect_test.rb b/test/prism/result/static_inspect_test.rb
new file mode 100644
index 0000000000..cf8cef3298
--- /dev/null
+++ b/test/prism/result/static_inspect_test.rb
@@ -0,0 +1,89 @@
+# frozen_string_literal: true
+
+require_relative "../test_helper"
+
+module Prism
+ class StaticInspectTest < TestCase
+ def test_false
+ assert_equal "false", static_inspect("false")
+ end
+
+ def test_float
+ assert_equal "0.25", static_inspect("0.25")
+ assert_equal "5.125", static_inspect("5.125")
+
+ assert_equal "0.0", static_inspect("0.0")
+ assert_equal "-0.0", static_inspect("-0.0")
+
+ assert_equal "1.0e+100", static_inspect("1e100")
+ assert_equal "-1.0e+100", static_inspect("-1e100")
+
+ assert_equal "Infinity", static_inspect("1e1000")
+ assert_equal "-Infinity", static_inspect("-1e1000")
+ end
+
+ def test_imaginary
+ assert_equal "(0+1i)", static_inspect("1i")
+ assert_equal "(0-1i)", static_inspect("-1i")
+ end
+
+ def test_integer
+ assert_equal "1000", static_inspect("1_0_0_0")
+ assert_equal "10000000000000000000000000000", static_inspect("1_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0")
+ end
+
+ def test_nil
+ assert_equal "nil", static_inspect("nil")
+ end
+
+ def test_rational
+ assert_equal "(0/1)", static_inspect("0r")
+ assert_equal "(1/1)", static_inspect("1r")
+ assert_equal "(1/1)", static_inspect("1.0r")
+ assert_equal "(77777/1000)", static_inspect("77.777r")
+ end
+
+ def test_regular_expression
+ assert_equal "/.*/", static_inspect("/.*/")
+ assert_equal "/.*/i", static_inspect("/.*/i")
+ assert_equal "/.*/", static_inspect("/.*/u")
+ assert_equal "/.*/n", static_inspect("/.*/un")
+ end
+
+ def test_source_encoding
+ assert_equal "#<Encoding:UTF-8>", static_inspect("__ENCODING__")
+ assert_equal "#<Encoding:Windows-31J>", static_inspect("__ENCODING__", encoding: "Windows-31J")
+ end
+
+ def test_source_file
+ assert_equal __FILE__.inspect, static_inspect("__FILE__", filepath: __FILE__, frozen_string_literal: true)
+ end
+
+ def test_source_line
+ assert_equal "1", static_inspect("__LINE__")
+ assert_equal "5", static_inspect("__LINE__", line: 5)
+ end
+
+ def test_string
+ assert_equal "\"\"", static_inspect('""', frozen_string_literal: true)
+ assert_equal "\"Hello, World!\"", static_inspect('"Hello, World!"', frozen_string_literal: true)
+ assert_equal "\"\\a\"", static_inspect("\"\\a\"", frozen_string_literal: true)
+ end
+
+ def test_symbol
+ assert_equal ":foo", static_inspect(":foo")
+ assert_equal ":foo", static_inspect("%s[foo]")
+ end
+
+ def test_true
+ assert_equal "true", static_inspect("true")
+ end
+
+ private
+
+ def static_inspect(source, **options)
+ warnings = Prism.parse("{ #{source} => 1, #{source} => 1 }", **options).warnings
+ warnings.last.message[/^key (.+) is duplicated and overwritten on line \d/, 1]
+ end
+ end
+end
diff --git a/test/prism/result/static_literals_test.rb b/test/prism/result/static_literals_test.rb
new file mode 100644
index 0000000000..dcfc692897
--- /dev/null
+++ b/test/prism/result/static_literals_test.rb
@@ -0,0 +1,92 @@
+# frozen_string_literal: true
+
+require_relative "../test_helper"
+
+module Prism
+ class StaticLiteralsTest < TestCase
+ def test_static_literals
+ assert_warning("1")
+ assert_warning("0xA", "10", "10")
+ assert_warning("0o10", "8", "8")
+ assert_warning("0b10", "2", "2")
+ assert_warning("1_000", "1000", "1000")
+ assert_warning((2**32).to_s(10), "0x#{(2**32).to_s(16)}", (2**32).to_s(10))
+ assert_warning((2**64).to_s(10), "0x#{(2**64).to_s(16)}", (2**64).to_s(10))
+
+ refute_warning("1", "-1")
+ refute_warning((2**32).to_s(10), "-0x#{(2**32).to_s(16)}")
+ refute_warning((2**64).to_s(10), "-0x#{(2**64).to_s(16)}")
+
+ assert_warning("__LINE__", "2", "2")
+ assert_warning("3", "__LINE__", "3")
+
+ assert_warning("1.0")
+ assert_warning("1e2", "100.0", "100.0")
+
+ assert_warning("1r", "1r", "(1/1)")
+ assert_warning("1.0r", "1.0r", "(1/1)")
+
+ assert_warning("1i", "1i", "(0+1i)")
+ assert_warning("1.0i", "1.0i", "(0+1.0i)")
+
+ assert_warning("1ri", "1ri", "(0+(1/1)*i)")
+ assert_warning("1.0ri", "1.0ri", "(0+(1/1)*i)")
+
+ assert_warning("__FILE__", "\"#{__FILE__}\"", __FILE__)
+ assert_warning("\"#{__FILE__}\"")
+ assert_warning("\"foo\"")
+
+ assert_warning("/foo/")
+
+ refute_warning("/foo/", "/foo/i")
+
+ assert_warning(":foo")
+ assert_warning("%s[foo]", ":foo", ":foo")
+
+ assert_warning("true")
+ assert_warning("false")
+ assert_warning("nil")
+ assert_warning("__ENCODING__", "__ENCODING__", "#<Encoding:UTF-8>")
+ end
+
+ private
+
+ class NullWarning
+ def message
+ ""
+ end
+ end
+
+ def parse_warnings(left, right)
+ warnings = []
+
+ warnings << (Prism.parse(<<~RUBY, filepath: __FILE__).warnings.first || NullWarning.new)
+ {
+ #{left} => 1,
+ #{right} => 2
+ }
+ RUBY
+
+ warnings << (Prism.parse(<<~RUBY, filepath: __FILE__).warnings.first || NullWarning.new)
+ case foo
+ when #{left}
+ when #{right}
+ end
+ RUBY
+
+ warnings
+ end
+
+ def assert_warning(left, right = left, message = left)
+ hash_keys, when_clauses = parse_warnings(left, right)
+
+ assert_include hash_keys.message, message
+ assert_include hash_keys.message, "line 3"
+ assert_include when_clauses.message, "line 3"
+ end
+
+ def refute_warning(left, right)
+ assert_empty parse_warnings(left, right).grep_v(NullWarning)
+ end
+ end
+end
diff --git a/test/prism/result/warnings_test.rb b/test/prism/result/warnings_test.rb
new file mode 100644
index 0000000000..5cff2d2d2b
--- /dev/null
+++ b/test/prism/result/warnings_test.rb
@@ -0,0 +1,430 @@
+# frozen_string_literal: true
+
+return if RUBY_VERSION < "3.1"
+
+require_relative "../test_helper"
+
+module Prism
+ class WarningsTest < TestCase
+ def test_ambiguous_uminus
+ assert_warning("a -b", "ambiguous first argument")
+ end
+
+ def test_ambiguous_uplus
+ assert_warning("a +b", "ambiguous first argument")
+ end
+
+ def test_ambiguous_ustar
+ assert_warning("a *b", "argument prefix")
+ end
+
+ def test_ambiguous_regexp
+ assert_warning("a /b/", "wrap regexp in parentheses")
+ end
+
+ def test_ambiguous_ampersand
+ assert_warning("a &b", "argument prefix")
+ assert_warning("a &:+", "argument prefix")
+
+ refute_warning("a &:b")
+ refute_warning("a &:'b'")
+ refute_warning("a &:\"b\"")
+ end
+
+ def test_binary_operator
+ [
+ [:**, "argument prefix"],
+ [:*, "argument prefix"],
+ [:<<, "here document"],
+ [:&, "argument prefix"],
+ [:+, "unary operator"],
+ [:-, "unary operator"],
+ [:/, "regexp literal"],
+ [:%, "string literal"]
+ ].each do |(operator, warning)|
+ assert_warning("puts 1 #{operator}0", warning)
+ assert_warning("puts :a #{operator}0", warning)
+ assert_warning("m = 1; puts m #{operator}0", warning)
+ end
+ end
+
+ def test_equal_in_conditional
+ assert_warning("if a = 1; end; a = a", "should be ==")
+ end
+
+ def test_dot_dot_dot_eol
+ assert_warning("_ = foo...", "... at EOL")
+ assert_warning("def foo(...) = bar ...", "... at EOL")
+
+ assert_warning("_ = foo... #", "... at EOL")
+ assert_warning("_ = foo... \t\v\f\n", "... at EOL")
+
+ refute_warning("p foo...bar")
+ refute_warning("p foo... bar")
+ end
+
+ def test_END_in_method
+ assert_warning("def foo; END {}; end", "END in method")
+ end
+
+ def test_duplicated_hash_key
+ assert_warning("{ a: 1, a: 2 }", "duplicated and overwritten")
+ assert_warning("{ a: 1, **{ a: 2 } }", "duplicated and overwritten")
+ end
+
+ def test_duplicated_when_clause
+ assert_warning("case 1; when 1, 1; end", "when' clause")
+ end
+
+ def test_float_out_of_range
+ assert_warning("_ = 1.0e100000", "out of range")
+ end
+
+ def test_indentation_mismatch
+ assert_warning("if true\n end", "mismatched indentations at 'end' with 'if'")
+ assert_warning("if true\n elsif true\nend", "mismatched indentations at 'elsif' with 'if'")
+ assert_warning("if true\n else\nend", "mismatched indentations at 'else' with 'if'", "mismatched indentations at 'end' with 'else'")
+
+ assert_warning("unless true\n end", "mismatched indentations at 'end' with 'unless'")
+ assert_warning("unless true\n else\nend", "mismatched indentations at 'else' with 'unless'", "mismatched indentations at 'end' with 'else'")
+
+ assert_warning("while true\n end", "mismatched indentations at 'end' with 'while'")
+ assert_warning("until true\n end", "mismatched indentations at 'end' with 'until'")
+
+ assert_warning("begin\n end", "mismatched indentations at 'end' with 'begin'")
+ assert_warning("begin\n rescue\nend", "mismatched indentations at 'rescue' with 'begin'")
+ assert_warning("begin\n ensure\nend", "mismatched indentations at 'ensure' with 'begin'")
+ assert_warning("begin\nrescue\n else\nend", "mismatched indentations at 'else' with 'begin'", "mismatched indentations at 'end' with 'else'")
+ assert_warning("begin\n rescue\n ensure\n end", "mismatched indentations at 'rescue' with 'begin'", "mismatched indentations at 'ensure' with 'begin'", "mismatched indentations at 'end' with 'begin'");
+
+ assert_warning("def foo\n end", "mismatched indentations at 'end' with 'def'")
+ assert_warning("def foo\n rescue\nend", "mismatched indentations at 'rescue' with 'def'")
+ assert_warning("def foo\n ensure\nend", "mismatched indentations at 'ensure' with 'def'")
+ assert_warning("def foo\nrescue\n else\nend", "mismatched indentations at 'else' with 'def'", "mismatched indentations at 'end' with 'else'")
+ assert_warning("def foo\n rescue\n ensure\n end", "mismatched indentations at 'rescue' with 'def'", "mismatched indentations at 'ensure' with 'def'", "mismatched indentations at 'end' with 'def'");
+
+ assert_warning("class Foo\n end", "mismatched indentations at 'end' with 'class'")
+ assert_warning("class Foo\n rescue\nend", "mismatched indentations at 'rescue' with 'class'")
+ assert_warning("class Foo\n ensure\nend", "mismatched indentations at 'ensure' with 'class'")
+ assert_warning("class Foo\nrescue\n else\nend", "mismatched indentations at 'else' with 'class'", "mismatched indentations at 'end' with 'else'")
+ assert_warning("class Foo\n rescue\n ensure\n end", "mismatched indentations at 'rescue' with 'class'", "mismatched indentations at 'ensure' with 'class'", "mismatched indentations at 'end' with 'class'");
+
+ assert_warning("module Foo\n end", "mismatched indentations at 'end' with 'module'")
+ assert_warning("module Foo\n rescue\nend", "mismatched indentations at 'rescue' with 'module'")
+ assert_warning("module Foo\n ensure\nend", "mismatched indentations at 'ensure' with 'module'")
+ assert_warning("module Foo\nrescue\n else\nend", "mismatched indentations at 'else' with 'module'", "mismatched indentations at 'end' with 'else'")
+ assert_warning("module Foo\n rescue\n ensure\n end", "mismatched indentations at 'rescue' with 'module'", "mismatched indentations at 'ensure' with 'module'", "mismatched indentations at 'end' with 'module'");
+
+ assert_warning("class << foo\n end", "mismatched indentations at 'end' with 'class'")
+ assert_warning("class << foo\n rescue\nend", "mismatched indentations at 'rescue' with 'class'")
+ assert_warning("class << foo\n ensure\nend", "mismatched indentations at 'ensure' with 'class'")
+ assert_warning("class << foo\nrescue\n else\nend", "mismatched indentations at 'else' with 'class'", "mismatched indentations at 'end' with 'else'")
+ assert_warning("class << foo\n rescue\n ensure\n end", "mismatched indentations at 'rescue' with 'class'", "mismatched indentations at 'ensure' with 'class'", "mismatched indentations at 'end' with 'class'");
+
+ assert_warning("case 1; when 2\n end", "mismatched indentations at 'end' with 'case'")
+ assert_warning("case 1; in 2\n end", "mismatched indentations at 'end' with 'case'")
+
+ assert_warning(" case 1\nwhen 2\n end", "mismatched indentations at 'when' with 'case'")
+ refute_warning("case 1\n when 2\n when 3\nend") # case/when allows more indentation
+
+ assert_warning("-> {\n }", "mismatched indentations at '}' with '->'")
+ assert_warning("-> do\n end", "mismatched indentations at 'end' with '->'")
+ assert_warning("-> do\n rescue\nend", "mismatched indentations at 'rescue' with '->'")
+ assert_warning("-> do\n ensure\nend", "mismatched indentations at 'ensure' with '->'")
+ assert_warning("-> do\nrescue\n else\nend", "mismatched indentations at 'else' with '->'", "mismatched indentations at 'end' with 'else'")
+ assert_warning("-> do\n rescue\n ensure\n end", "mismatched indentations at 'rescue' with '->'", "mismatched indentations at 'ensure' with '->'", "mismatched indentations at 'end' with '->'");
+ assert_warning("foo do\nrescue\n else\nend", "mismatched indentations at 'end' with 'else'")
+
+ refute_warning("class Foo; end") # same line
+ refute_warning("; class Foo\nend") # non whitespace on opening line
+ refute_warning("\tclass Foo\n end") # tab stop matches space
+ refute_warning(" \tclass Foo\n end") # tab stop matches space
+ end
+
+ def test_integer_in_flip_flop
+ assert_warning("1 if 2..foo", "integer")
+ end
+
+ def test_literal_in_conditionals
+ sources = [
+ "if (a = 2); a; end",
+ "if ($a = 2); end",
+ "if (@a = 2); end",
+ "if a; elsif b = 2; b end",
+ "unless (a = 2); a; end",
+ "unless ($a = 2); end",
+ "unless (@a = 2); end",
+ "while (a = 2); a; end",
+ "while ($a = 2); end",
+ "while (@a = 2); end",
+ "until (a = 2); a; end",
+ "until ($a = 2); end",
+ "until (@a = 2); end",
+ "foo if (a, b = 2); [a, b]",
+ "foo if a = 2 and a",
+ "(@foo = 1) ? a : b",
+ "!(a = 2) and a",
+ "not a = 2 and a"
+ ]
+
+ if RUBY_VERSION >= "3.3"
+ sources.push(
+ "if (@@a = 2); end",
+ "unless (@@a = 2); end",
+ "while (@@a = 2); end",
+ "until (@@a = 2); end"
+ )
+ end
+
+ sources.each do |source|
+ assert_warning(source, "= literal' in conditional, should be ==")
+ end
+ end
+
+ def test_keyword_eol
+ assert_warning("if\ntrue; end", "end of line")
+ assert_warning("if true\nelsif\nfalse; end", "end of line")
+ end
+
+ def test_numbered_reference
+ assert_warning("_ = _ = $999999999999999999999", "too big for a number variable, always nil")
+ end
+
+ def test_shareable_constant_value
+ assert_warning("foo # shareable_constant_value: none", "ignored")
+ assert_warning("\v # shareable_constant_value: none", "ignored")
+
+ refute_warning("# shareable_constant_value: none")
+ refute_warning(" # shareable_constant_value: none")
+ refute_warning("\t\t# shareable_constant_value: none")
+ end
+
+ def test_string_in_predicate
+ assert_warning("if 'foo'; end", "string")
+ assert_warning("if \"\#{foo}\"; end", "string")
+ assert_warning("if __FILE__; end", "string")
+ end
+
+ def test_symbol_in_predicate
+ assert_warning("if :foo; end", "symbol")
+ assert_warning("if :\"\#{foo}\"; end", "symbol")
+ end
+
+ def test_literal_in_predicate
+ assert_warning("if __LINE__; end", "literal")
+ assert_warning("if __ENCODING__; end", "literal")
+ assert_warning("if 1; end", "literal")
+ assert_warning("if 1.0; end", "literal")
+ assert_warning("if 1r; end", "literal")
+ assert_warning("if 1i; end", "literal")
+ end
+
+ def test_regexp_in_predicate
+ assert_warning("if /foo/; end", "regex")
+ assert_warning("if /foo\#{bar}/; end", "regex")
+ end
+
+ def test_unused_local_variables
+ assert_warning("foo = 1", "unused")
+
+ refute_warning("foo = 1", compare: false, command_line: "e")
+ refute_warning("foo = 1", compare: false, scopes: [[]])
+
+ assert_warning("def foo; bar = 1; end", "unused")
+ assert_warning("def foo; bar, = 1; end", "unused")
+
+ refute_warning("def foo; bar &&= 1; end")
+ refute_warning("def foo; bar ||= 1; end")
+ refute_warning("def foo; bar += 1; end")
+
+ refute_warning("def foo; bar = bar; end")
+ refute_warning("def foo; bar = bar = 1; end")
+ refute_warning("def foo; bar = (bar = 1); end")
+ refute_warning("def foo; bar = begin; bar = 1; end; end")
+ refute_warning("def foo; bar = (qux; bar = 1); end")
+ refute_warning("def foo; bar, = bar = 1; end")
+ refute_warning("def foo; bar, = 1, bar = 1; end")
+
+ refute_warning("def foo(bar); end")
+ refute_warning("def foo(bar = 1); end")
+ refute_warning("def foo((bar)); end")
+ refute_warning("def foo(*bar); end")
+ refute_warning("def foo(*, bar); end")
+ refute_warning("def foo(*, (bar)); end")
+ refute_warning("def foo(bar:); end")
+ refute_warning("def foo(**bar); end")
+ refute_warning("def foo(&bar); end")
+ refute_warning("->(bar) {}")
+ refute_warning("->(; bar) {}", compare: false)
+
+ refute_warning("def foo; bar = 1; tap { bar }; end")
+ refute_warning("def foo; bar = 1; tap { baz = bar; baz }; end")
+ end
+
+ def test_void_statements
+ assert_warning("foo = 1; foo", "a variable in void")
+ assert_warning("@foo", "a variable in void")
+ assert_warning("@@foo", "a variable in void")
+ assert_warning("$foo", "a variable in void")
+ assert_warning("$+", "a variable in void")
+ assert_warning("$1", "a variable in void")
+
+ assert_warning("self", "self in void")
+ assert_warning("nil", "nil in void")
+ assert_warning("true", "true in void")
+ assert_warning("false", "false in void")
+
+ assert_warning("1", "literal in void")
+ assert_warning("1.0", "literal in void")
+ assert_warning("1r", "literal in void")
+ assert_warning("1i", "literal in void")
+ assert_warning(":foo", "literal in void")
+ assert_warning("\"foo\"", "literal in void")
+ assert_warning("\"foo\#{1}\"", "literal in void")
+ assert_warning("/foo/", "literal in void")
+ assert_warning("/foo\#{1}/", "literal in void")
+
+ assert_warning("Foo", "constant in void")
+ assert_warning("::Foo", ":: in void")
+ assert_warning("Foo::Bar", ":: in void")
+
+ assert_warning("1..2", ".. in void")
+ assert_warning("1..", ".. in void")
+ assert_warning("..2", ".. in void")
+ assert_warning("1...2", "... in void")
+ assert_warning("1...;", "... in void")
+ assert_warning("...2", "... in void")
+
+ assert_warning("defined?(foo)", "defined? in void")
+
+ assert_warning("1 + 1", "+ in void")
+ assert_warning("1 - 1", "- in void")
+ assert_warning("1 * 1", "* in void")
+ assert_warning("1 / 1", "/ in void")
+ assert_warning("1 % 1", "% in void")
+ assert_warning("1 | 1", "| in void")
+ assert_warning("1 ^ 1", "^ in void")
+ assert_warning("1 & 1", "& in void")
+ assert_warning("1 > 1", "> in void")
+ assert_warning("1 < 1", "< in void")
+
+ assert_warning("1 ** 1", "** in void")
+ assert_warning("1 <= 1", "<= in void")
+ assert_warning("1 >= 1", ">= in void")
+ assert_warning("1 != 1", "!= in void")
+ assert_warning("1 == 1", "== in void")
+ assert_warning("1 <=> 1", "<=> in void")
+
+ assert_warning("+foo", "+@ in void")
+ assert_warning("-foo", "-@ in void")
+
+ assert_warning("def foo; @bar; @baz; end", "variable in void")
+ refute_warning("def foo; @bar; end")
+ refute_warning("@foo", compare: false, scopes: [[]])
+ end
+
+ def test_unreachable_statement
+ assert_warning("begin; rescue; retry; foo; end", "statement not reached")
+
+ assert_warning("return; foo", "statement not reached")
+
+ assert_warning("tap { break; foo }", "statement not reached")
+ assert_warning("tap { break 1; foo }", "statement not reached")
+
+ assert_warning("tap { next; foo }", "statement not reached")
+ assert_warning("tap { next 1; foo }", "statement not reached")
+
+ assert_warning("tap { redo; foo }", "statement not reached")
+ end
+
+ if RbConfig::CONFIG["host_os"].match?(/bccwin|cygwin|djgpp|mingw|mswin|wince/i)
+ def test_shebang_ending_with_carriage_return
+ refute_warning("#!ruby\r\np(123)\n", compare: false)
+ end
+ else
+ def test_shebang_ending_with_carriage_return
+ msg = "shebang line ending with \\r may cause problems"
+
+ assert_warning(<<~RUBY, msg, compare: false, main_script: true)
+ #!ruby\r
+ p(123)
+ RUBY
+
+ assert_warning(<<~RUBY, msg, compare: false, main_script: true)
+ #!ruby \r
+ p(123)
+ RUBY
+
+ assert_warning(<<~RUBY, msg, compare: false, main_script: true)
+ #!ruby -Eutf-8\r
+ p(123)
+ RUBY
+
+ # Used with the `-x` object, to ignore the script up until the first
+ # shebang that mentioned "ruby".
+ assert_warning(<<~SCRIPT, msg, compare: false, main_script: true)
+ #!/usr/bin/env bash
+ # Some initial shell script or other content
+ # that Ruby should ignore
+ echo "This is shell script part"
+ exit 0
+
+ #! /usr/bin/env ruby -Eutf-8\r
+ # Ruby script starts here
+ puts "Hello from Ruby!"
+ SCRIPT
+
+ refute_warning("#ruby not_a_shebang\r\n", compare: false, main_script: true)
+
+ # CRuby doesn't emit the warning if a malformed file only has `\r` and
+ # not `\n`. https://bugs.ruby-lang.org/issues/20700.
+ refute_warning("#!ruby\r", compare: false, main_script: true)
+ end
+ end
+
+ def test_warnings_verbosity
+ warning = Prism.parse("def foo; END { }; end").warnings.first
+ assert_equal "END in method; use at_exit", warning.message
+ assert_equal :default, warning.level
+
+ warning = Prism.parse("foo /regexp/").warnings.first
+ assert_equal "ambiguous `/`; wrap regexp in parentheses or add a space after `/` operator", warning.message
+ assert_equal :verbose, warning.level
+ end
+
+ private
+
+ def assert_warning(source, *messages, compare: true, **options)
+ warnings = Prism.parse(source, **options).warnings
+ assert_equal messages.length, warnings.length, "Expected #{messages.length} warning(s) in #{source.inspect}, got #{warnings.map(&:message).inspect}"
+
+ warnings.zip(messages).each do |warning, message|
+ assert_include warning.message, message
+ end
+
+ if compare && defined?(RubyVM::AbstractSyntaxTree)
+ stderr = capture_stderr { RubyVM::AbstractSyntaxTree.parse(source) }
+ messages.each { |message| assert_include stderr, message }
+ end
+ end
+
+ def refute_warning(source, compare: true, **options)
+ assert_empty Prism.parse(source, **options).warnings
+
+ if compare && defined?(RubyVM::AbstractSyntaxTree)
+ assert_empty capture_stderr { RubyVM::AbstractSyntaxTree.parse(source) }
+ end
+ end
+
+ def capture_stderr
+ stderr, $stderr, verbose, $VERBOSE = $stderr, StringIO.new, $VERBOSE, true
+
+ begin
+ yield
+ $stderr.string
+ ensure
+ $stderr, $VERBOSE = stderr, verbose
+ end
+ end
+ end
+end
diff --git a/test/prism/ruby/compiler_test.rb b/test/prism/ruby/compiler_test.rb
new file mode 100644
index 0000000000..35ccfd5950
--- /dev/null
+++ b/test/prism/ruby/compiler_test.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+# typed: ignore
+
+require_relative "../test_helper"
+
+module Prism
+ class CompilerTest < TestCase
+ class SExpressions < Prism::Compiler
+ def visit_arguments_node(node)
+ [:arguments, super]
+ end
+
+ def visit_call_node(node)
+ [:call, super]
+ end
+
+ def visit_integer_node(node)
+ [:integer]
+ end
+
+ def visit_program_node(node)
+ [:program, super]
+ end
+ end
+
+ def test_compiler
+ expected = [:program, [[[:call, [[:integer], [:arguments, [[:integer]]]]]]]]
+ assert_equal expected, Prism.parse("1 + 2").value.accept(SExpressions.new)
+ end
+ end
+end
diff --git a/test/prism/ruby/desugar_compiler_test.rb b/test/prism/ruby/desugar_compiler_test.rb
new file mode 100644
index 0000000000..fe9a25e030
--- /dev/null
+++ b/test/prism/ruby/desugar_compiler_test.rb
@@ -0,0 +1,80 @@
+# frozen_string_literal: true
+
+require_relative "../test_helper"
+
+module Prism
+ class DesugarCompilerTest < TestCase
+ def test_and_write
+ assert_desugars("(AndNode (ClassVariableReadNode) (ClassVariableWriteNode (CallNode)))", "@@foo &&= bar")
+ assert_not_desugared("Foo::Bar &&= baz", "Desugaring would execute Foo twice or need temporary variables")
+ assert_desugars("(AndNode (ConstantReadNode) (ConstantWriteNode (CallNode)))", "Foo &&= bar")
+ assert_desugars("(AndNode (GlobalVariableReadNode) (GlobalVariableWriteNode (CallNode)))", "$foo &&= bar")
+ assert_desugars("(AndNode (InstanceVariableReadNode) (InstanceVariableWriteNode (CallNode)))", "@foo &&= bar")
+ assert_desugars("(AndNode (LocalVariableReadNode) (LocalVariableWriteNode (CallNode)))", "foo &&= bar")
+ assert_desugars("(AndNode (LocalVariableReadNode) (LocalVariableWriteNode (CallNode)))", "foo = 1; foo &&= bar")
+ end
+
+ def test_or_write
+ assert_desugars("(IfNode (DefinedNode (ClassVariableReadNode)) (StatementsNode (ClassVariableReadNode)) (ElseNode (StatementsNode (ClassVariableWriteNode (CallNode)))))", "@@foo ||= bar")
+ assert_not_desugared("Foo::Bar ||= baz", "Desugaring would execute Foo twice or need temporary variables")
+ assert_desugars("(IfNode (DefinedNode (ConstantReadNode)) (StatementsNode (ConstantReadNode)) (ElseNode (StatementsNode (ConstantWriteNode (CallNode)))))", "Foo ||= bar")
+ assert_desugars("(IfNode (DefinedNode (GlobalVariableReadNode)) (StatementsNode (GlobalVariableReadNode)) (ElseNode (StatementsNode (GlobalVariableWriteNode (CallNode)))))", "$foo ||= bar")
+ assert_desugars("(OrNode (InstanceVariableReadNode) (InstanceVariableWriteNode (CallNode)))", "@foo ||= bar")
+ assert_desugars("(OrNode (LocalVariableReadNode) (LocalVariableWriteNode (CallNode)))", "foo ||= bar")
+ assert_desugars("(OrNode (LocalVariableReadNode) (LocalVariableWriteNode (CallNode)))", "foo = 1; foo ||= bar")
+ end
+
+ def test_operator_write
+ assert_desugars("(ClassVariableWriteNode (CallNode (ClassVariableReadNode) (ArgumentsNode (CallNode))))", "@@foo += bar")
+ assert_not_desugared("Foo::Bar += baz", "Desugaring would execute Foo twice or need temporary variables")
+ assert_desugars("(ConstantWriteNode (CallNode (ConstantReadNode) (ArgumentsNode (CallNode))))", "Foo += bar")
+ assert_desugars("(GlobalVariableWriteNode (CallNode (GlobalVariableReadNode) (ArgumentsNode (CallNode))))", "$foo += bar")
+ assert_desugars("(InstanceVariableWriteNode (CallNode (InstanceVariableReadNode) (ArgumentsNode (CallNode))))", "@foo += bar")
+ assert_desugars("(LocalVariableWriteNode (CallNode (LocalVariableReadNode) (ArgumentsNode (CallNode))))", "foo += bar")
+ assert_desugars("(LocalVariableWriteNode (CallNode (LocalVariableReadNode) (ArgumentsNode (CallNode))))", "foo = 1; foo += bar")
+ end
+
+ private
+
+ def ast_inspect(node)
+ parts = [node.class.name.split("::").last]
+
+ node.deconstruct_keys(nil).each do |_, value|
+ case value
+ when Node
+ parts << ast_inspect(value)
+ when Array
+ parts.concat(value.map { |element| ast_inspect(element) })
+ end
+ end
+
+ "(#{parts.join(" ")})"
+ end
+
+ # Ensure every node is only present once in the AST.
+ # If the same node is present twice it would most likely indicate it is executed twice, which is invalid semantically.
+ # This also acts as a sanity check that Node#child_nodes returns only nodes or nil (which caught a couple bugs).
+ def ensure_every_node_once_in_ast(node, all_nodes = {}.compare_by_identity)
+ if all_nodes.include?(node)
+ raise "#{node.inspect} is present multiple times in the desugared AST and likely executed multiple times"
+ else
+ all_nodes[node] = true
+ end
+ node.child_nodes.each do |child|
+ ensure_every_node_once_in_ast(child, all_nodes) unless child.nil?
+ end
+ end
+
+ def assert_desugars(expected, source)
+ ast = Prism.parse(source).value.accept(DesugarCompiler.new)
+ assert_equal expected, ast_inspect(ast.statements.body.last)
+
+ ensure_every_node_once_in_ast(ast)
+ end
+
+ def assert_not_desugared(source, reason)
+ ast = Prism.parse(source).value
+ assert_equal_nodes(ast, ast.accept(DesugarCompiler.new))
+ end
+ end
+end
diff --git a/test/prism/ruby/dispatcher_test.rb b/test/prism/ruby/dispatcher_test.rb
new file mode 100644
index 0000000000..1b6d7f4117
--- /dev/null
+++ b/test/prism/ruby/dispatcher_test.rb
@@ -0,0 +1,46 @@
+# frozen_string_literal: true
+
+require_relative "../test_helper"
+
+module Prism
+ class DispatcherTest < TestCase
+ class TestListener
+ attr_reader :events_received
+
+ def initialize
+ @events_received = []
+ end
+
+ def on_call_node_enter(node)
+ events_received << :on_call_node_enter
+ end
+
+ def on_call_node_leave(node)
+ events_received << :on_call_node_leave
+ end
+
+ def on_integer_node_enter(node)
+ events_received << :on_integer_node_enter
+ end
+ end
+
+ def test_dispatching_events
+ listener = TestListener.new
+ dispatcher = Dispatcher.new
+ dispatcher.register(listener, :on_call_node_enter, :on_call_node_leave, :on_integer_node_enter)
+
+ root = Prism.parse(<<~RUBY).value
+ def foo
+ something(1, 2, 3)
+ end
+ RUBY
+
+ dispatcher.dispatch(root)
+ assert_equal([:on_call_node_enter, :on_integer_node_enter, :on_integer_node_enter, :on_integer_node_enter, :on_call_node_leave], listener.events_received)
+
+ listener.events_received.clear
+ dispatcher.dispatch_once(root.statements.body.first.body.body.first)
+ assert_equal([:on_call_node_enter, :on_call_node_leave], listener.events_received)
+ end
+ end
+end
diff --git a/test/prism/ruby/location_test.rb b/test/prism/ruby/location_test.rb
new file mode 100644
index 0000000000..fc80a5b875
--- /dev/null
+++ b/test/prism/ruby/location_test.rb
@@ -0,0 +1,173 @@
+# frozen_string_literal: true
+
+require_relative "../test_helper"
+
+module Prism
+ class LocationTest < TestCase
+ def test_join
+ call = Prism.parse_statement("1234 + 567")
+ receiver = call.receiver
+ argument = call.arguments.arguments.first
+
+ joined = receiver.location.join(argument.location)
+ assert_equal 0, joined.start_offset
+ assert_equal 10, joined.length
+
+ assert_raise(RuntimeError, "Incompatible locations") do
+ argument.location.join(receiver.location)
+ end
+
+ other_argument = Prism.parse_statement("1234 + 567").arguments.arguments.first
+
+ assert_raise(RuntimeError, "Incompatible sources") do
+ other_argument.location.join(receiver.location)
+ end
+
+ assert_raise(RuntimeError, "Incompatible sources") do
+ receiver.location.join(other_argument.location)
+ end
+ end
+
+ def test_character_offsets
+ program = Prism.parse("😀 + 😀\n😠||= ðŸ˜").value
+
+ # first 😀
+ location = program.statements.body.first.receiver.location
+ assert_equal 0, location.start_character_offset
+ assert_equal 1, location.end_character_offset
+ assert_equal 0, location.start_character_column
+ assert_equal 1, location.end_character_column
+
+ # second 😀
+ location = program.statements.body.first.arguments.arguments.first.location
+ assert_equal 4, location.start_character_offset
+ assert_equal 5, location.end_character_offset
+ assert_equal 4, location.start_character_column
+ assert_equal 5, location.end_character_column
+
+ # first ðŸ˜
+ location = program.statements.body.last.name_loc
+ assert_equal 6, location.start_character_offset
+ assert_equal 7, location.end_character_offset
+ assert_equal 0, location.start_character_column
+ assert_equal 1, location.end_character_column
+
+ # second ðŸ˜
+ location = program.statements.body.last.value.location
+ assert_equal 12, location.start_character_offset
+ assert_equal 13, location.end_character_offset
+ assert_equal 6, location.start_character_column
+ assert_equal 7, location.end_character_column
+ end
+
+ def test_code_units
+ program = Prism.parse("😀 + 😀\n😠||= ðŸ˜").value
+
+ # first 😀
+ location = program.statements.body.first.receiver.location
+
+ assert_equal 0, location.start_code_units_offset(Encoding::UTF_8)
+ assert_equal 0, location.start_code_units_offset(Encoding::UTF_16LE)
+ assert_equal 0, location.start_code_units_offset(Encoding::UTF_32LE)
+
+ assert_equal 1, location.end_code_units_offset(Encoding::UTF_8)
+ assert_equal 2, location.end_code_units_offset(Encoding::UTF_16LE)
+ assert_equal 1, location.end_code_units_offset(Encoding::UTF_32LE)
+
+ assert_equal 0, location.start_code_units_column(Encoding::UTF_8)
+ assert_equal 0, location.start_code_units_column(Encoding::UTF_16LE)
+ assert_equal 0, location.start_code_units_column(Encoding::UTF_32LE)
+
+ assert_equal 1, location.end_code_units_column(Encoding::UTF_8)
+ assert_equal 2, location.end_code_units_column(Encoding::UTF_16LE)
+ assert_equal 1, location.end_code_units_column(Encoding::UTF_32LE)
+
+ # second 😀
+ location = program.statements.body.first.arguments.arguments.first.location
+
+ assert_equal 4, location.start_code_units_offset(Encoding::UTF_8)
+ assert_equal 5, location.start_code_units_offset(Encoding::UTF_16LE)
+ assert_equal 4, location.start_code_units_offset(Encoding::UTF_32LE)
+
+ assert_equal 5, location.end_code_units_offset(Encoding::UTF_8)
+ assert_equal 7, location.end_code_units_offset(Encoding::UTF_16LE)
+ assert_equal 5, location.end_code_units_offset(Encoding::UTF_32LE)
+
+ assert_equal 4, location.start_code_units_column(Encoding::UTF_8)
+ assert_equal 5, location.start_code_units_column(Encoding::UTF_16LE)
+ assert_equal 4, location.start_code_units_column(Encoding::UTF_32LE)
+
+ assert_equal 5, location.end_code_units_column(Encoding::UTF_8)
+ assert_equal 7, location.end_code_units_column(Encoding::UTF_16LE)
+ assert_equal 5, location.end_code_units_column(Encoding::UTF_32LE)
+
+ # first ðŸ˜
+ location = program.statements.body.last.name_loc
+
+ assert_equal 6, location.start_code_units_offset(Encoding::UTF_8)
+ assert_equal 8, location.start_code_units_offset(Encoding::UTF_16LE)
+ assert_equal 6, location.start_code_units_offset(Encoding::UTF_32LE)
+
+ assert_equal 7, location.end_code_units_offset(Encoding::UTF_8)
+ assert_equal 10, location.end_code_units_offset(Encoding::UTF_16LE)
+ assert_equal 7, location.end_code_units_offset(Encoding::UTF_32LE)
+
+ assert_equal 0, location.start_code_units_column(Encoding::UTF_8)
+ assert_equal 0, location.start_code_units_column(Encoding::UTF_16LE)
+ assert_equal 0, location.start_code_units_column(Encoding::UTF_32LE)
+
+ assert_equal 1, location.end_code_units_column(Encoding::UTF_8)
+ assert_equal 2, location.end_code_units_column(Encoding::UTF_16LE)
+ assert_equal 1, location.end_code_units_column(Encoding::UTF_32LE)
+
+ # second ðŸ˜
+ location = program.statements.body.last.value.location
+
+ assert_equal 12, location.start_code_units_offset(Encoding::UTF_8)
+ assert_equal 15, location.start_code_units_offset(Encoding::UTF_16LE)
+ assert_equal 12, location.start_code_units_offset(Encoding::UTF_32LE)
+
+ assert_equal 13, location.end_code_units_offset(Encoding::UTF_8)
+ assert_equal 17, location.end_code_units_offset(Encoding::UTF_16LE)
+ assert_equal 13, location.end_code_units_offset(Encoding::UTF_32LE)
+
+ assert_equal 6, location.start_code_units_column(Encoding::UTF_8)
+ assert_equal 7, location.start_code_units_column(Encoding::UTF_16LE)
+ assert_equal 6, location.start_code_units_column(Encoding::UTF_32LE)
+
+ assert_equal 7, location.end_code_units_column(Encoding::UTF_8)
+ assert_equal 9, location.end_code_units_column(Encoding::UTF_16LE)
+ assert_equal 7, location.end_code_units_column(Encoding::UTF_32LE)
+ end
+
+ def test_chop
+ location = Prism.parse("foo").value.location
+
+ assert_equal "fo", location.chop.slice
+ assert_equal "", location.chop.chop.chop.slice
+
+ # Check that we don't go negative.
+ 10.times { location = location.chop }
+ assert_equal "", location.slice
+ end
+
+ def test_slice_lines
+ method = Prism.parse_statement("\nprivate def foo\nend\n").arguments.arguments.first
+
+ assert_equal "private def foo\nend\n", method.slice_lines
+ end
+
+ def test_adjoin
+ program = Prism.parse("foo.bar = 1").value
+
+ location = program.statements.body.first.message_loc
+ adjoined = location.adjoin("=")
+
+ assert_kind_of Location, adjoined
+ refute_equal location, adjoined
+
+ assert_equal 4, adjoined.start_offset
+ assert_equal 9, adjoined.end_offset
+ end
+ end
+end
diff --git a/test/prism/ruby/parameters_signature_test.rb b/test/prism/ruby/parameters_signature_test.rb
new file mode 100644
index 0000000000..9256bcc070
--- /dev/null
+++ b/test/prism/ruby/parameters_signature_test.rb
@@ -0,0 +1,91 @@
+# frozen_string_literal: true
+
+return if RUBY_VERSION < "3.2"
+
+require_relative "../test_helper"
+
+module Prism
+ class ParametersSignatureTest < TestCase
+ def test_req
+ assert_parameters([[:req, :a]], "a")
+ end
+
+ def test_req_destructure
+ assert_parameters([[:req]], "(a, b)")
+ end
+
+ def test_opt
+ assert_parameters([[:opt, :a]], "a = 1")
+ end
+
+ def test_rest
+ assert_parameters([[:rest, :a]], "*a")
+ end
+
+ def test_rest_anonymous
+ assert_parameters([[:rest, :*]], "*")
+ end
+
+ def test_post
+ assert_parameters([[:rest, :a], [:req, :b]], "*a, b")
+ end
+
+ def test_post_destructure
+ assert_parameters([[:rest, :a], [:req]], "*a, (b, c)")
+ end
+
+ def test_keyreq
+ assert_parameters([[:keyreq, :a]], "a:")
+ end
+
+ def test_key
+ assert_parameters([[:key, :a]], "a: 1")
+ end
+
+ def test_keyrest
+ assert_parameters([[:keyrest, :a]], "**a")
+ end
+
+ def test_nokey
+ assert_parameters([[:nokey]], "**nil")
+ end
+
+ def test_keyrest_anonymous
+ assert_parameters([[:keyrest, :**]], "**")
+ end
+
+ def test_key_ordering
+ omit("TruffleRuby returns keys in order they were declared") if RUBY_ENGINE == "truffleruby"
+ assert_parameters([[:keyreq, :a], [:keyreq, :b], [:key, :c], [:key, :d]], "a:, c: 1, b:, d: 2")
+ end
+
+ def test_block
+ assert_parameters([[:block, :a]], "&a")
+ end
+
+ def test_block_anonymous
+ assert_parameters([[:block, :&]], "&")
+ end
+
+ def test_forwarding
+ assert_parameters([[:rest, :*], [:keyrest, :**], [:block, :&]], "...")
+ end
+
+ private
+
+ def assert_parameters(expected, source)
+ # Compare against our expectation.
+ assert_equal(expected, signature(source))
+
+ # Compare against Ruby's expectation.
+ object = Object.new
+ eval("def object.m(#{source}); end")
+ assert_equal(expected, object.method(:m).parameters)
+ end
+
+ def signature(source)
+ program = Prism.parse("def m(#{source}); end").value
+ program.statements.body.first.parameters.signature
+ end
+ end
+end
diff --git a/test/prism/ruby/parser_test.rb b/test/prism/ruby/parser_test.rb
new file mode 100644
index 0000000000..606a0e54f6
--- /dev/null
+++ b/test/prism/ruby/parser_test.rb
@@ -0,0 +1,291 @@
+# frozen_string_literal: true
+
+require_relative "../test_helper"
+
+begin
+ verbose, $VERBOSE = $VERBOSE, nil
+ require "parser/ruby33"
+ require "prism/translation/parser33"
+rescue LoadError
+ # In CRuby's CI, we're not going to test against the parser gem because we
+ # don't want to have to install it. So in this case we'll just skip this test.
+ return
+ensure
+ $VERBOSE = verbose
+end
+
+# First, opt in to every AST feature.
+Parser::Builders::Default.modernize
+
+# Modify the source map == check so that it doesn't check against the node
+# itself so we don't get into a recursive loop.
+Parser::Source::Map.prepend(
+ Module.new {
+ def ==(other)
+ self.class == other.class &&
+ (instance_variables - %i[@node]).map do |ivar|
+ instance_variable_get(ivar) == other.instance_variable_get(ivar)
+ end.reduce(:&)
+ end
+ }
+)
+
+# Next, ensure that we're comparing the nodes and also comparing the source
+# ranges so that we're getting all of the necessary information.
+Parser::AST::Node.prepend(
+ Module.new {
+ def ==(other)
+ super && (location == other.location)
+ end
+ }
+)
+
+module Prism
+ class ParserTest < TestCase
+ # These files contain code that is being parsed incorrectly by the parser
+ # gem, and therefore we don't want to compare against our translation.
+ skip_incorrect = [
+ # https://github.com/whitequark/parser/issues/1017
+ "spanning_heredoc.txt",
+ "spanning_heredoc_newlines.txt",
+
+ # https://github.com/whitequark/parser/issues/1021
+ "seattlerb/heredoc_nested.txt",
+
+ # https://github.com/whitequark/parser/issues/1016
+ "whitequark/unary_num_pow_precedence.txt"
+ ]
+
+ # These files are either failing to parse or failing to translate, so we'll
+ # skip them for now.
+ skip_all = skip_incorrect | [
+ "regex.txt",
+ "unescaping.txt",
+ "seattlerb/bug190.txt",
+ "seattlerb/heredoc_with_extra_carriage_returns_windows.txt",
+ "seattlerb/heredoc_with_only_carriage_returns_windows.txt",
+ "seattlerb/heredoc_with_only_carriage_returns.txt",
+ "seattlerb/parse_line_heredoc_hardnewline.txt",
+ "seattlerb/pctW_lineno.txt",
+ "seattlerb/regexp_esc_C_slash.txt",
+ "unparser/corpus/literal/literal.txt",
+ "unparser/corpus/semantic/dstr.txt",
+ "whitequark/dedenting_interpolating_heredoc_fake_line_continuation.txt",
+ "whitequark/parser_slash_slash_n_escaping_in_literals.txt",
+ "whitequark/ruby_bug_11989.txt"
+ ]
+
+ # Not sure why these files are failing on JRuby, but skipping them for now.
+ if RUBY_ENGINE == "jruby"
+ skip_all.push("emoji_method_calls.txt", "symbols.txt")
+ end
+
+ # These files are failing to translate their lexer output into the lexer
+ # output expected by the parser gem, so we'll skip them for now.
+ skip_tokens = [
+ "comments.txt",
+ "dash_heredocs.txt",
+ "dos_endings.txt",
+ "embdoc_no_newline_at_end.txt",
+ "heredoc_with_comment.txt",
+ "heredocs_with_ignored_newlines.txt",
+ "indented_file_end.txt",
+ "methods.txt",
+ "strings.txt",
+ "tilde_heredocs.txt",
+ "xstring_with_backslash.txt",
+ "seattlerb/backticks_interpolation_line.txt",
+ "seattlerb/bug169.txt",
+ "seattlerb/case_in.txt",
+ "seattlerb/class_comments.txt",
+ "seattlerb/difficult4__leading_dots2.txt",
+ "seattlerb/difficult6__7.txt",
+ "seattlerb/difficult6__8.txt",
+ "seattlerb/dsym_esc_to_sym.txt",
+ "seattlerb/heredoc__backslash_dos_format.txt",
+ "seattlerb/heredoc_backslash_nl.txt",
+ "seattlerb/heredoc_comma_arg.txt",
+ "seattlerb/heredoc_squiggly_blank_line_plus_interpolation.txt",
+ "seattlerb/heredoc_squiggly_blank_lines.txt",
+ "seattlerb/heredoc_squiggly_interp.txt",
+ "seattlerb/heredoc_squiggly_tabs_extra.txt",
+ "seattlerb/heredoc_squiggly_tabs.txt",
+ "seattlerb/heredoc_squiggly_visually_blank_lines.txt",
+ "seattlerb/heredoc_squiggly.txt",
+ "seattlerb/heredoc_unicode.txt",
+ "seattlerb/heredoc_with_carriage_return_escapes_windows.txt",
+ "seattlerb/heredoc_with_carriage_return_escapes.txt",
+ "seattlerb/heredoc_with_interpolation_and_carriage_return_escapes_windows.txt",
+ "seattlerb/heredoc_with_interpolation_and_carriage_return_escapes.txt",
+ "seattlerb/interpolated_symbol_array_line_breaks.txt",
+ "seattlerb/interpolated_word_array_line_breaks.txt",
+ "seattlerb/label_vs_string.txt",
+ "seattlerb/module_comments.txt",
+ "seattlerb/non_interpolated_symbol_array_line_breaks.txt",
+ "seattlerb/non_interpolated_word_array_line_breaks.txt",
+ "seattlerb/parse_line_block_inline_comment_leading_newlines.txt",
+ "seattlerb/parse_line_block_inline_comment.txt",
+ "seattlerb/parse_line_block_inline_multiline_comment.txt",
+ "seattlerb/parse_line_dstr_escaped_newline.txt",
+ "seattlerb/parse_line_heredoc.txt",
+ "seattlerb/parse_line_multiline_str_literal_n.txt",
+ "seattlerb/parse_line_str_with_newline_escape.txt",
+ "seattlerb/pct_w_heredoc_interp_nested.txt",
+ "seattlerb/qsymbols_empty_space.txt",
+ "seattlerb/qw_escape_term.txt",
+ "seattlerb/qWords_space.txt",
+ "seattlerb/read_escape_unicode_curlies.txt",
+ "seattlerb/read_escape_unicode_h4.txt",
+ "seattlerb/required_kwarg_no_value.txt",
+ "seattlerb/slashy_newlines_within_string.txt",
+ "seattlerb/str_double_escaped_newline.txt",
+ "seattlerb/str_double_newline.txt",
+ "seattlerb/str_evstr_escape.txt",
+ "seattlerb/str_newline_hash_line_number.txt",
+ "seattlerb/str_single_newline.txt",
+ "seattlerb/symbols_empty_space.txt",
+ "seattlerb/TestRubyParserShared.txt",
+ "unparser/corpus/literal/assignment.txt",
+ "unparser/corpus/literal/dstr.txt",
+ "unparser/corpus/semantic/opasgn.txt",
+ "whitequark/args.txt",
+ "whitequark/beginless_erange_after_newline.txt",
+ "whitequark/beginless_irange_after_newline.txt",
+ "whitequark/bug_ascii_8bit_in_literal.txt",
+ "whitequark/bug_def_no_paren_eql_begin.txt",
+ "whitequark/dedenting_heredoc.txt",
+ "whitequark/dedenting_non_interpolating_heredoc_line_continuation.txt",
+ "whitequark/forward_arg_with_open_args.txt",
+ "whitequark/interp_digit_var.txt",
+ "whitequark/lbrace_arg_after_command_args.txt",
+ "whitequark/multiple_pattern_matches.txt",
+ "whitequark/newline_in_hash_argument.txt",
+ "whitequark/parser_bug_640.txt",
+ "whitequark/parser_drops_truncated_parts_of_squiggly_heredoc.txt",
+ "whitequark/ruby_bug_11990.txt",
+ "whitequark/ruby_bug_14690.txt",
+ "whitequark/ruby_bug_9669.txt",
+ "whitequark/slash_newline_in_heredocs.txt",
+ "whitequark/space_args_arg_block.txt",
+ "whitequark/space_args_block.txt"
+ ]
+
+ Fixture.each do |fixture|
+ define_method(fixture.test_name) do
+ assert_equal_parses(
+ fixture,
+ compare_asts: !skip_all.include?(fixture.path),
+ compare_tokens: !skip_tokens.include?(fixture.path),
+ compare_comments: fixture.path != "embdoc_no_newline_at_end.txt"
+ )
+ end
+ end
+
+ private
+
+ def assert_equal_parses(fixture, compare_asts: true, compare_tokens: true, compare_comments: true)
+ buffer = Parser::Source::Buffer.new(fixture.path, 1)
+ buffer.source = fixture.read
+
+ parser = Parser::Ruby33.new
+ parser.diagnostics.consumer = ->(*) {}
+ parser.diagnostics.all_errors_are_fatal = true
+
+ expected_ast, expected_comments, expected_tokens =
+ begin
+ ignore_warnings { parser.tokenize(buffer) }
+ rescue ArgumentError, Parser::SyntaxError
+ return
+ end
+
+ actual_ast, actual_comments, actual_tokens =
+ ignore_warnings { Prism::Translation::Parser33.new.tokenize(buffer) }
+
+ if expected_ast == actual_ast
+ if !compare_asts
+ puts "#{fixture.path} is now passing"
+ end
+
+ assert_equal expected_ast, actual_ast, -> { assert_equal_asts_message(expected_ast, actual_ast) }
+
+ begin
+ assert_equal_tokens(expected_tokens, actual_tokens)
+ rescue Test::Unit::AssertionFailedError
+ raise if compare_tokens
+ else
+ puts "#{fixture.path} is now passing" if !compare_tokens
+ end
+
+ assert_equal_comments(expected_comments, actual_comments) if compare_comments
+ elsif compare_asts
+ assert_equal expected_ast, actual_ast, -> { assert_equal_asts_message(expected_ast, actual_ast) }
+ end
+ end
+
+ def assert_equal_asts_message(expected_ast, actual_ast)
+ queue = [[expected_ast, actual_ast]]
+
+ while (left, right = queue.shift)
+ if left.type != right.type
+ return "expected: #{left.type}\nactual: #{right.type}"
+ end
+
+ if left.location != right.location
+ return "expected:\n#{left.inspect}\n#{left.location.inspect}\nactual:\n#{right.inspect}\n#{right.location.inspect}"
+ end
+
+ if left.type == :str && left.children[0] != right.children[0]
+ return "expected: #{left.inspect}\nactual: #{right.inspect}"
+ end
+
+ left.children.zip(right.children).each do |left_child, right_child|
+ queue << [left_child, right_child] if left_child.is_a?(Parser::AST::Node)
+ end
+ end
+
+ "expected: #{expected_ast.inspect}\nactual: #{actual_ast.inspect}"
+ end
+
+ def assert_equal_tokens(expected_tokens, actual_tokens)
+ if expected_tokens != actual_tokens
+ expected_index = 0
+ actual_index = 0
+
+ while expected_index < expected_tokens.length
+ expected_token = expected_tokens[expected_index]
+ actual_token = actual_tokens.fetch(actual_index, [])
+
+ expected_index += 1
+ actual_index += 1
+
+ # The parser gem always has a space before a string end in list
+ # literals, but we don't. So we'll skip over the space.
+ if expected_token[0] == :tSPACE && actual_token[0] == :tSTRING_END
+ expected_index += 1
+ next
+ end
+
+ # There are a lot of tokens that have very specific meaning according
+ # to the context of the parser. We don't expose that information in
+ # prism, so we need to normalize these tokens a bit.
+ if expected_token[0] == :kDO_BLOCK && actual_token[0] == :kDO
+ actual_token[0] = expected_token[0]
+ end
+
+ # Now we can assert that the tokens are actually equal.
+ assert_equal expected_token, actual_token, -> {
+ "expected: #{expected_token.inspect}\n" \
+ "actual: #{actual_token.inspect}"
+ }
+ end
+ end
+ end
+
+ def assert_equal_comments(expected_comments, actual_comments)
+ assert_equal expected_comments, actual_comments, -> {
+ "expected: #{expected_comments.inspect}\n" \
+ "actual: #{actual_comments.inspect}"
+ }
+ end
+ end
+end
diff --git a/test/prism/ruby/pattern_test.rb b/test/prism/ruby/pattern_test.rb
new file mode 100644
index 0000000000..23f512fc1c
--- /dev/null
+++ b/test/prism/ruby/pattern_test.rb
@@ -0,0 +1,132 @@
+# frozen_string_literal: true
+
+require_relative "../test_helper"
+
+module Prism
+ class PatternTest < TestCase
+ def test_invalid_syntax
+ assert_raise(Pattern::CompilationError) { scan("", "<>") }
+ end
+
+ def test_invalid_constant
+ assert_raise(Pattern::CompilationError) { scan("", "Foo") }
+ end
+
+ def test_invalid_nested_constant
+ assert_raise(Pattern::CompilationError) { scan("", "Foo::Bar") }
+ end
+
+ def test_regexp_with_interpolation
+ assert_raise(Pattern::CompilationError) { scan("", "/\#{foo}/") }
+ end
+
+ def test_string_with_interpolation
+ assert_raise(Pattern::CompilationError) { scan("", '"#{foo}"') }
+ end
+
+ def test_symbol_with_interpolation
+ assert_raise(Pattern::CompilationError) { scan("", ":\"\#{foo}\"") }
+ end
+
+ def test_invalid_node
+ assert_raise(Pattern::CompilationError) { scan("", "IntegerNode[^foo]") }
+ end
+
+ def test_self
+ assert_raise(Pattern::CompilationError) { scan("", "self") }
+ end
+
+ def test_array_pattern_no_constant
+ results = scan("1 + 2", "[IntegerNode]")
+
+ assert_equal 1, results.length
+ end
+
+ def test_array_pattern
+ results = scan("1 + 2", "CallNode[name: :+, receiver: IntegerNode, arguments: [IntegerNode]]")
+
+ assert_equal 1, results.length
+ end
+
+ def test_alternation_pattern
+ results = scan("Foo + Bar + 1", "ConstantReadNode | IntegerNode")
+
+ assert_equal 3, results.length
+ assert_equal 1, results.grep(IntegerNode).first.value
+ end
+
+ def test_constant_read_node
+ results = scan("Foo + Bar + Baz", "ConstantReadNode")
+
+ assert_equal 3, results.length
+ assert_equal %w[Bar Baz Foo], results.map(&:slice).sort
+ end
+
+ def test_object_const
+ results = scan("1 + 2 + 3", "IntegerNode[]")
+
+ assert_equal 3, results.length
+ end
+
+ def test_constant_path
+ results = scan("Foo + Bar + Baz", "Prism::ConstantReadNode")
+
+ assert_equal 3, results.length
+ end
+
+ def test_hash_pattern_no_constant
+ results = scan("Foo + Bar + Baz", "{ name: :+ }")
+
+ assert_equal 2, results.length
+ end
+
+ def test_hash_pattern_regexp
+ results = scan("Foo + Bar + Baz", "{ name: /^[[:punct:]]$/ }")
+
+ assert_equal 2, results.length
+ assert_equal ["Prism::CallNode"], results.map { |node| node.class.name }.uniq
+ end
+
+ def test_nil
+ results = scan("foo", "{ receiver: nil }")
+
+ assert_equal 1, results.length
+ end
+
+ def test_regexp_options
+ results = scan("@foo + @bar + @baz", "InstanceVariableReadNode[name: /^@B/i]")
+
+ assert_equal 2, results.length
+ end
+
+ def test_string_empty
+ results = scan("", "''")
+
+ assert_empty results
+ end
+
+ def test_symbol_empty
+ results = scan("", ":''")
+
+ assert_empty results
+ end
+
+ def test_symbol_plain
+ results = scan("@foo", "{ name: :\"@foo\" }")
+
+ assert_equal 1, results.length
+ end
+
+ def test_symbol
+ results = scan("@foo", "{ name: :@foo }")
+
+ assert_equal 1, results.length
+ end
+
+ private
+
+ def scan(source, query)
+ Prism::Pattern.new(query).scan(Prism.parse(source).value).to_a
+ end
+ end
+end
diff --git a/test/prism/ruby/reflection_test.rb b/test/prism/ruby/reflection_test.rb
new file mode 100644
index 0000000000..3ac462e1ac
--- /dev/null
+++ b/test/prism/ruby/reflection_test.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+require_relative "../test_helper"
+
+module Prism
+ class ReflectionTest < TestCase
+ def test_fields_for
+ fields = Reflection.fields_for(CallNode)
+ methods = CallNode.instance_methods(false)
+
+ fields.each do |field|
+ if field.is_a?(Reflection::FlagsField)
+ field.flags.each do |flag|
+ assert_includes methods, flag
+ end
+ else
+ assert_includes methods, field.name
+ end
+ end
+ end
+ end
+end
diff --git a/test/prism/ruby/ripper_test.rb b/test/prism/ruby/ripper_test.rb
new file mode 100644
index 0000000000..8db47da3d3
--- /dev/null
+++ b/test/prism/ruby/ripper_test.rb
@@ -0,0 +1,62 @@
+# frozen_string_literal: true
+
+return if RUBY_VERSION < "3.3"
+
+require_relative "../test_helper"
+
+module Prism
+ class RipperTest < TestCase
+ # Skip these tests that Ripper is reporting the wrong results for.
+ incorrect = [
+ # Ripper incorrectly attributes the block to the keyword.
+ "seattlerb/block_break.txt",
+ "seattlerb/block_next.txt",
+ "seattlerb/block_return.txt",
+ "whitequark/break_block.txt",
+ "whitequark/next_block.txt",
+ "whitequark/return_block.txt",
+
+ # Ripper is not accounting for locals created by patterns using the **
+ # operator within an `in` clause.
+ "seattlerb/parse_pattern_058.txt",
+
+ # Ripper cannot handle named capture groups in regular expressions.
+ "regex.txt",
+ "regex_char_width.txt",
+ "whitequark/lvar_injecting_match.txt",
+
+ # Ripper fails to understand some structures that span across heredocs.
+ "spanning_heredoc.txt"
+ ]
+
+ # Skip these tests that we haven't implemented yet.
+ omitted = [
+ "dos_endings.txt",
+ "heredocs_with_ignored_newlines.txt",
+ "seattlerb/block_call_dot_op2_brace_block.txt",
+ "seattlerb/block_command_operation_colon.txt",
+ "seattlerb/block_command_operation_dot.txt",
+ "seattlerb/heredoc__backslash_dos_format.txt",
+ "seattlerb/heredoc_backslash_nl.txt",
+ "seattlerb/heredoc_nested.txt",
+ "seattlerb/heredoc_squiggly_blank_line_plus_interpolation.txt",
+ "tilde_heredocs.txt",
+ "unparser/corpus/semantic/dstr.txt",
+ "whitequark/dedenting_heredoc.txt",
+ "whitequark/parser_drops_truncated_parts_of_squiggly_heredoc.txt",
+ "whitequark/parser_slash_slash_n_escaping_in_literals.txt",
+ "whitequark/send_block_chain_cmd.txt",
+ "whitequark/slash_newline_in_heredocs.txt"
+ ]
+
+ Fixture.each(except: incorrect | omitted) do |fixture|
+ define_method(fixture.test_name) { assert_ripper(fixture.read) }
+ end
+
+ private
+
+ def assert_ripper(source)
+ assert_equal Ripper.sexp_raw(source), Prism::Translation::Ripper.sexp_raw(source)
+ end
+ end
+end
diff --git a/test/prism/ruby/ruby_parser_test.rb b/test/prism/ruby/ruby_parser_test.rb
new file mode 100644
index 0000000000..a13daeeb84
--- /dev/null
+++ b/test/prism/ruby/ruby_parser_test.rb
@@ -0,0 +1,127 @@
+# frozen_string_literal: true
+
+return if RUBY_ENGINE == "jruby"
+
+require_relative "../test_helper"
+
+begin
+ require "ruby_parser"
+rescue LoadError
+ # In CRuby's CI, we're not going to test against the ruby_parser gem because
+ # we don't want to have to install it. So in this case we'll just skip this
+ # test.
+ return
+end
+
+# We want to also compare lines and files to make sure we're setting them
+# correctly.
+Sexp.prepend(
+ Module.new do
+ def ==(other)
+ super && line == other.line && file == other.file # && line_max == other.line_max
+ end
+ end
+)
+
+module Prism
+ class RubyParserTest < TestCase
+ todos = [
+ "newline_terminated.txt",
+ "regex_char_width.txt",
+ "seattlerb/bug169.txt",
+ "seattlerb/masgn_colon3.txt",
+ "seattlerb/messy_op_asgn_lineno.txt",
+ "seattlerb/op_asgn_primary_colon_const_command_call.txt",
+ "seattlerb/regexp_esc_C_slash.txt",
+ "seattlerb/str_lit_concat_bad_encodings.txt",
+ "unescaping.txt",
+ "unparser/corpus/literal/kwbegin.txt",
+ "unparser/corpus/literal/send.txt",
+ "whitequark/masgn_const.txt",
+ "whitequark/ruby_bug_12402.txt",
+ "whitequark/ruby_bug_14690.txt",
+ "whitequark/space_args_block.txt"
+ ]
+
+ # https://github.com/seattlerb/ruby_parser/issues/344
+ failures = [
+ "alias.txt",
+ "dos_endings.txt",
+ "heredocs_with_ignored_newlines.txt",
+ "method_calls.txt",
+ "methods.txt",
+ "multi_write.txt",
+ "not.txt",
+ "patterns.txt",
+ "regex.txt",
+ "seattlerb/and_multi.txt",
+ "seattlerb/heredoc__backslash_dos_format.txt",
+ "seattlerb/heredoc_bad_hex_escape.txt",
+ "seattlerb/heredoc_bad_oct_escape.txt",
+ "seattlerb/heredoc_with_extra_carriage_horrible_mix.txt",
+ "seattlerb/heredoc_with_extra_carriage_returns_windows.txt",
+ "seattlerb/heredoc_with_only_carriage_returns_windows.txt",
+ "seattlerb/heredoc_with_only_carriage_returns.txt",
+ "spanning_heredoc_newlines.txt",
+ "spanning_heredoc.txt",
+ "tilde_heredocs.txt",
+ "unparser/corpus/literal/literal.txt",
+ "while.txt",
+ "whitequark/cond_eflipflop.txt",
+ "whitequark/cond_iflipflop.txt",
+ "whitequark/cond_match_current_line.txt",
+ "whitequark/dedenting_heredoc.txt",
+ "whitequark/lvar_injecting_match.txt",
+ "whitequark/not.txt",
+ "whitequark/numparam_ruby_bug_19025.txt",
+ "whitequark/op_asgn_cmd.txt",
+ "whitequark/parser_bug_640.txt",
+ "whitequark/parser_slash_slash_n_escaping_in_literals.txt",
+ "whitequark/pattern_matching_single_line_allowed_omission_of_parentheses.txt",
+ "whitequark/pattern_matching_single_line.txt",
+ "whitequark/ruby_bug_11989.txt",
+ "whitequark/slash_newline_in_heredocs.txt"
+ ]
+
+ Fixture.each(except: failures) do |fixture|
+ define_method(fixture.test_name) do
+ assert_ruby_parser(fixture, todos.include?(fixture.path))
+ end
+ end
+
+ private
+
+ def assert_ruby_parser(fixture, allowed_failure)
+ source = fixture.read
+ expected = ignore_warnings { ::RubyParser.new.parse(source, fixture.path) }
+ actual = Prism::Translation::RubyParser.new.parse(source, fixture.path)
+
+ if !allowed_failure
+ assert_equal(expected, actual, -> { message(expected, actual) })
+ elsif expected == actual
+ puts "#{name} now passes"
+ end
+ end
+
+ def message(expected, actual)
+ if expected == actual
+ nil
+ elsif expected.is_a?(Sexp) && actual.is_a?(Sexp)
+ if expected.line != actual.line
+ "expected: (#{expected.inspect} line=#{expected.line}), actual: (#{actual.inspect} line=#{actual.line})"
+ elsif expected.file != actual.file
+ "expected: (#{expected.inspect} file=#{expected.file}), actual: (#{actual.inspect} file=#{actual.file})"
+ elsif expected.length != actual.length
+ "expected: (#{expected.inspect} length=#{expected.length}), actual: (#{actual.inspect} length=#{actual.length})"
+ else
+ expected.zip(actual).find do |expected_field, actual_field|
+ result = message(expected_field, actual_field)
+ break result if result
+ end
+ end
+ else
+ "expected: #{expected.inspect}, actual: #{actual.inspect}"
+ end
+ end
+ end
+end
diff --git a/test/prism/ruby/tunnel_test.rb b/test/prism/ruby/tunnel_test.rb
new file mode 100644
index 0000000000..0214681604
--- /dev/null
+++ b/test/prism/ruby/tunnel_test.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+require_relative "../test_helper"
+
+module Prism
+ class TunnelTest < TestCase
+ def test_tunnel
+ program = Prism.parse("foo(1) +\n bar(2, 3) +\n baz(3, 4, 5)").value
+
+ tunnel = program.tunnel(1, 4).last
+ assert_kind_of IntegerNode, tunnel
+ assert_equal 1, tunnel.value
+
+ tunnel = program.tunnel(2, 6).last
+ assert_kind_of IntegerNode, tunnel
+ assert_equal 2, tunnel.value
+
+ tunnel = program.tunnel(3, 9).last
+ assert_kind_of IntegerNode, tunnel
+ assert_equal 4, tunnel.value
+
+ tunnel = program.tunnel(3, 8)
+ assert_equal [ProgramNode, StatementsNode, CallNode, ArgumentsNode, CallNode, ArgumentsNode], tunnel.map(&:class)
+ end
+ end
+end
diff --git a/test/prism/snippets_test.rb b/test/prism/snippets_test.rb
new file mode 100644
index 0000000000..26847da184
--- /dev/null
+++ b/test/prism/snippets_test.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+require_relative "test_helper"
+
+module Prism
+ class SnippetsTest < TestCase
+ except = [
+ "newline_terminated.txt",
+ "seattlerb/begin_rescue_else_ensure_no_bodies.txt",
+ "seattlerb/case_in.txt",
+ "seattlerb/parse_line_defn_no_parens.txt",
+ "seattlerb/pct_nl.txt",
+ "seattlerb/str_heredoc_interp.txt",
+ "spanning_heredoc_newlines.txt",
+ "unparser/corpus/semantic/dstr.txt",
+ "whitequark/dedenting_heredoc.txt",
+ "whitequark/multiple_pattern_matches.txt"
+ ]
+
+ Fixture.each(except: except) do |fixture|
+ define_method(fixture.test_name) { assert_snippets(fixture) }
+ end
+
+ private
+
+ # We test every snippet (separated by \n\n) in isolation to ensure the
+ # parser does not try to read bytes further than the end of each snippet.
+ def assert_snippets(fixture)
+ fixture.read.split(/(?<=\S)\n\n(?=\S)/).each do |snippet|
+ snippet = snippet.rstrip
+
+ result = Prism.parse(snippet, filepath: fixture.path)
+ assert result.success?
+
+ if !ENV["PRISM_BUILD_MINIMAL"]
+ dumped = Prism.dump(snippet, filepath: fixture.path)
+ assert_equal_nodes(result.value, Prism.load(snippet, dumped).value)
+ end
+ end
+ end
+ end
+end
diff --git a/test/prism/test_helper.rb b/test/prism/test_helper.rb
new file mode 100644
index 0000000000..b848500283
--- /dev/null
+++ b/test/prism/test_helper.rb
@@ -0,0 +1,323 @@
+# frozen_string_literal: true
+
+require "prism"
+require "pp"
+require "ripper"
+require "stringio"
+require "test/unit"
+require "tempfile"
+
+puts "Using prism backend: #{Prism::BACKEND}" if ENV["PRISM_FFI_BACKEND"]
+
+# It is useful to have a diff even if the strings to compare are big
+# However, ruby/ruby does not have a version of Test::Unit with access to
+# max_diff_target_string_size
+if defined?(Test::Unit::Assertions::AssertionMessage)
+ Test::Unit::Assertions::AssertionMessage.max_diff_target_string_size = 5000
+end
+
+module Prism
+ # A convenience method for retrieving the first statement in the source string
+ # parsed by Prism.
+ def self.parse_statement(source, **options)
+ parse(source, **options).value.statements.body.first
+ end
+
+ class ParseResult < Result
+ # Returns the first statement in the body of the parsed source.
+ def statement
+ value.statements.body.first
+ end
+ end
+
+ class TestCase < ::Test::Unit::TestCase
+ # We have a set of fixtures that we use to test various aspects of the
+ # parser. They are all represented as .txt files under the
+ # test/prism/fixtures directory. Typically in test files you will find calls
+ # to Fixture.each which yields Fixture objects to the given block. These
+ # are used to define test methods that assert against each fixture in some
+ # way.
+ class Fixture
+ BASE = File.join(__dir__, "fixtures")
+
+ attr_reader :path
+
+ def initialize(path)
+ @path = path
+ end
+
+ def read
+ File.read(full_path, binmode: true, external_encoding: Encoding::UTF_8)
+ end
+
+ def full_path
+ File.join(BASE, path)
+ end
+
+ def snapshot_path
+ File.join(__dir__, "snapshots", path)
+ end
+
+ def test_name
+ :"test_#{path}"
+ end
+
+ def self.each(except: [], &block)
+ paths = Dir[ENV.fetch("FOCUS") { File.join("**", "*.txt") }, base: BASE] - except
+ paths.each { |path| yield Fixture.new(path) }
+ end
+ end
+
+ # Yield each encoding that we want to test, along with a range of the
+ # codepoints that should be tested.
+ def self.each_encoding
+ codepoints_1byte = 0...0x100
+
+ yield Encoding::ASCII_8BIT, codepoints_1byte
+ yield Encoding::US_ASCII, codepoints_1byte
+
+ if !ENV["PRISM_BUILD_MINIMAL"]
+ yield Encoding::Windows_1253, codepoints_1byte
+ end
+
+ # By default we don't test every codepoint in these encodings because it
+ # takes a very long time.
+ return unless ENV["PRISM_TEST_ALL_ENCODINGS"]
+
+ yield Encoding::CP850, codepoints_1byte
+ yield Encoding::CP852, codepoints_1byte
+ yield Encoding::CP855, codepoints_1byte
+ yield Encoding::GB1988, codepoints_1byte
+ yield Encoding::IBM437, codepoints_1byte
+ yield Encoding::IBM720, codepoints_1byte
+ yield Encoding::IBM737, codepoints_1byte
+ yield Encoding::IBM775, codepoints_1byte
+ yield Encoding::IBM852, codepoints_1byte
+ yield Encoding::IBM855, codepoints_1byte
+ yield Encoding::IBM857, codepoints_1byte
+ yield Encoding::IBM860, codepoints_1byte
+ yield Encoding::IBM861, codepoints_1byte
+ yield Encoding::IBM862, codepoints_1byte
+ yield Encoding::IBM863, codepoints_1byte
+ yield Encoding::IBM864, codepoints_1byte
+ yield Encoding::IBM865, codepoints_1byte
+ yield Encoding::IBM866, codepoints_1byte
+ yield Encoding::IBM869, codepoints_1byte
+ yield Encoding::ISO_8859_1, codepoints_1byte
+ yield Encoding::ISO_8859_2, codepoints_1byte
+ yield Encoding::ISO_8859_3, codepoints_1byte
+ yield Encoding::ISO_8859_4, codepoints_1byte
+ yield Encoding::ISO_8859_5, codepoints_1byte
+ yield Encoding::ISO_8859_6, codepoints_1byte
+ yield Encoding::ISO_8859_7, codepoints_1byte
+ yield Encoding::ISO_8859_8, codepoints_1byte
+ yield Encoding::ISO_8859_9, codepoints_1byte
+ yield Encoding::ISO_8859_10, codepoints_1byte
+ yield Encoding::ISO_8859_11, codepoints_1byte
+ yield Encoding::ISO_8859_13, codepoints_1byte
+ yield Encoding::ISO_8859_14, codepoints_1byte
+ yield Encoding::ISO_8859_15, codepoints_1byte
+ yield Encoding::ISO_8859_16, codepoints_1byte
+ yield Encoding::KOI8_R, codepoints_1byte
+ yield Encoding::KOI8_U, codepoints_1byte
+ yield Encoding::MACCENTEURO, codepoints_1byte
+ yield Encoding::MACCROATIAN, codepoints_1byte
+ yield Encoding::MACCYRILLIC, codepoints_1byte
+ yield Encoding::MACGREEK, codepoints_1byte
+ yield Encoding::MACICELAND, codepoints_1byte
+ yield Encoding::MACROMAN, codepoints_1byte
+ yield Encoding::MACROMANIA, codepoints_1byte
+ yield Encoding::MACTHAI, codepoints_1byte
+ yield Encoding::MACTURKISH, codepoints_1byte
+ yield Encoding::MACUKRAINE, codepoints_1byte
+ yield Encoding::TIS_620, codepoints_1byte
+ yield Encoding::Windows_1250, codepoints_1byte
+ yield Encoding::Windows_1251, codepoints_1byte
+ yield Encoding::Windows_1252, codepoints_1byte
+ yield Encoding::Windows_1254, codepoints_1byte
+ yield Encoding::Windows_1255, codepoints_1byte
+ yield Encoding::Windows_1256, codepoints_1byte
+ yield Encoding::Windows_1257, codepoints_1byte
+ yield Encoding::Windows_1258, codepoints_1byte
+ yield Encoding::Windows_874, codepoints_1byte
+
+ codepoints_2bytes = 0...0x10000
+
+ yield Encoding::Big5, codepoints_2bytes
+ yield Encoding::Big5_HKSCS, codepoints_2bytes
+ yield Encoding::Big5_UAO, codepoints_2bytes
+ yield Encoding::CP949, codepoints_2bytes
+ yield Encoding::CP950, codepoints_2bytes
+ yield Encoding::CP951, codepoints_2bytes
+ yield Encoding::EUC_KR, codepoints_2bytes
+ yield Encoding::GBK, codepoints_2bytes
+ yield Encoding::GB12345, codepoints_2bytes
+ yield Encoding::GB2312, codepoints_2bytes
+ yield Encoding::MACJAPANESE, codepoints_2bytes
+ yield Encoding::Shift_JIS, codepoints_2bytes
+ yield Encoding::SJIS_DoCoMo, codepoints_2bytes
+ yield Encoding::SJIS_KDDI, codepoints_2bytes
+ yield Encoding::SJIS_SoftBank, codepoints_2bytes
+ yield Encoding::Windows_31J, codepoints_2bytes
+
+ codepoints_unicode = (0...0x110000)
+
+ yield Encoding::UTF_8, codepoints_unicode
+ yield Encoding::UTF8_MAC, codepoints_unicode
+ yield Encoding::UTF8_DoCoMo, codepoints_unicode
+ yield Encoding::UTF8_KDDI, codepoints_unicode
+ yield Encoding::UTF8_SoftBank, codepoints_unicode
+ yield Encoding::CESU_8, codepoints_unicode
+
+ codepoints_eucjp = [
+ *(0...0x10000),
+ *(0...0x10000).map { |bytes| bytes | 0x8F0000 }
+ ]
+
+ yield Encoding::CP51932, codepoints_eucjp
+ yield Encoding::EUC_JP, codepoints_eucjp
+ yield Encoding::EUCJP_MS, codepoints_eucjp
+ yield Encoding::EUC_JIS_2004, codepoints_eucjp
+
+ codepoints_emacs_mule = [
+ *(0...0x80),
+ *((0x81...0x90).flat_map { |byte1| (0x90...0x100).map { |byte2| byte1 << 8 | byte2 } }),
+ *((0x90...0x9C).flat_map { |byte1| (0xA0...0x100).flat_map { |byte2| (0xA0...0x100).flat_map { |byte3| byte1 << 16 | byte2 << 8 | byte3 } } }),
+ *((0xF0...0xF5).flat_map { |byte2| (0xA0...0x100).flat_map { |byte3| (0xA0...0x100).flat_map { |byte4| 0x9C << 24 | byte3 << 16 | byte3 << 8 | byte4 } } }),
+ ]
+
+ yield Encoding::EMACS_MULE, codepoints_emacs_mule
+ yield Encoding::STATELESS_ISO_2022_JP, codepoints_emacs_mule
+ yield Encoding::STATELESS_ISO_2022_JP_KDDI, codepoints_emacs_mule
+
+ codepoints_gb18030 = [
+ *(0...0x80),
+ *((0x81..0xFE).flat_map { |byte1| (0x40...0x100).map { |byte2| byte1 << 8 | byte2 } }),
+ *((0x81..0xFE).flat_map { |byte1| (0x30...0x40).flat_map { |byte2| (0x81..0xFE).flat_map { |byte3| (0x2F...0x41).map { |byte4| byte1 << 24 | byte2 << 16 | byte3 << 8 | byte4 } } } }),
+ ]
+
+ yield Encoding::GB18030, codepoints_gb18030
+
+ codepoints_euc_tw = [
+ *(0..0x7F),
+ *(0xA1..0xFF).flat_map { |byte1| (0xA1..0xFF).map { |byte2| (byte1 << 8) | byte2 } },
+ *(0xA1..0xB0).flat_map { |byte2| (0xA1..0xFF).flat_map { |byte3| (0xA1..0xFF).flat_map { |byte4| 0x8E << 24 | byte2 << 16 | byte3 << 8 | byte4 } } }
+ ]
+
+ yield Encoding::EUC_TW, codepoints_euc_tw
+ end
+
+ private
+
+ if RUBY_ENGINE == "ruby" && RubyVM::InstructionSequence.compile("").to_a[4][:parser] != :prism
+ # Check that the given source is valid syntax by compiling it with RubyVM.
+ def check_syntax(source)
+ ignore_warnings { RubyVM::InstructionSequence.compile(source) }
+ end
+
+ # Assert that the given source is valid Ruby syntax by attempting to
+ # compile it, and then implicitly checking that it does not raise an
+ # syntax errors.
+ def assert_valid_syntax(source)
+ check_syntax(source)
+ end
+
+ # Refute that the given source is invalid Ruby syntax by attempting to
+ # compile it and asserting that it raises a SyntaxError.
+ def refute_valid_syntax(source)
+ assert_raise(SyntaxError) { check_syntax(source) }
+ end
+ else
+ def assert_valid_syntax(source)
+ end
+
+ def refute_valid_syntax(source)
+ end
+ end
+
+ # CRuby has this same method, so define it so that we don't accidentally
+ # break CRuby CI.
+ def assert_raises(*args, &block)
+ raise "Use assert_raise instead"
+ end
+
+ def assert_equal_nodes(expected, actual, compare_location: true, parent: nil)
+ assert_equal expected.class, actual.class
+
+ case expected
+ when Array
+ assert_equal(
+ expected.size,
+ actual.size,
+ -> { "Arrays were different sizes. Parent: #{parent.pretty_inspect}" }
+ )
+
+ expected.zip(actual).each do |(expected_element, actual_element)|
+ assert_equal_nodes(
+ expected_element,
+ actual_element,
+ compare_location: compare_location,
+ parent: actual
+ )
+ end
+ when SourceFileNode
+ expected_deconstruct = expected.deconstruct_keys(nil)
+ actual_deconstruct = actual.deconstruct_keys(nil)
+ assert_equal expected_deconstruct.keys, actual_deconstruct.keys
+
+ # Filepaths can be different if test suites were run on different
+ # machines. We accommodate for this by comparing the basenames, and not
+ # the absolute filepaths.
+ expected_filepath = expected_deconstruct.delete(:filepath)
+ actual_filepath = actual_deconstruct.delete(:filepath)
+
+ assert_equal expected_deconstruct, actual_deconstruct
+ assert_equal File.basename(expected_filepath), File.basename(actual_filepath)
+ when Node
+ deconstructed_expected = expected.deconstruct_keys(nil)
+ deconstructed_actual = actual.deconstruct_keys(nil)
+ assert_equal deconstructed_expected.keys, deconstructed_actual.keys
+
+ deconstructed_expected.each_key do |key|
+ assert_equal_nodes(
+ deconstructed_expected[key],
+ deconstructed_actual[key],
+ compare_location: compare_location,
+ parent: actual
+ )
+ end
+ when Location
+ assert_operator actual.start_offset, :<=, actual.end_offset, -> {
+ "start_offset > end_offset for #{actual.inspect}, parent is #{parent.pretty_inspect}"
+ }
+
+ if compare_location
+ assert_equal(
+ expected.start_offset,
+ actual.start_offset,
+ -> { "Start locations were different. Parent: #{parent.pretty_inspect}" }
+ )
+
+ assert_equal(
+ expected.end_offset,
+ actual.end_offset,
+ -> { "End locations were different. Parent: #{parent.pretty_inspect}" }
+ )
+ end
+ else
+ assert_equal expected, actual
+ end
+ end
+
+ def ignore_warnings
+ previous = $VERBOSE
+ $VERBOSE = nil
+
+ begin
+ yield
+ ensure
+ $VERBOSE = previous
+ end
+ end
+ end
+end
diff --git a/test/prism/unescape_test.rb b/test/prism/unescape_test.rb
new file mode 100644
index 0000000000..f9e5a60e45
--- /dev/null
+++ b/test/prism/unescape_test.rb
@@ -0,0 +1,240 @@
+# frozen_string_literal: true
+
+require_relative "test_helper"
+
+return if RUBY_VERSION < "3.1.0" || Prism::BACKEND == :FFI
+
+module Prism
+ class UnescapeTest < TestCase
+ module Context
+ class Base
+ attr_reader :left, :right
+
+ def initialize(left, right)
+ @left = left
+ @right = right
+ end
+
+ def name
+ "#{left}#{right}".delete("\n")
+ end
+
+ private
+
+ def code(escape)
+ "#{left}\\#{escape}#{right}".b
+ end
+
+ def ruby(escape)
+ previous, $VERBOSE = $VERBOSE, nil
+
+ begin
+ yield eval(code(escape))
+ rescue SyntaxError
+ :error
+ ensure
+ $VERBOSE = previous
+ end
+ end
+
+ def prism(escape)
+ result = Prism.parse(code(escape), encoding: "binary")
+
+ if result.success?
+ yield result.statement
+ else
+ :error
+ end
+ end
+
+ def `(command)
+ command
+ end
+ end
+
+ class List < Base
+ def ruby_result(escape)
+ ruby(escape) { |value| value.first.to_s }
+ end
+
+ def prism_result(escape)
+ prism(escape) { |node| node.elements.first.unescaped }
+ end
+ end
+
+ class Symbol < Base
+ def ruby_result(escape)
+ ruby(escape, &:to_s)
+ end
+
+ def prism_result(escape)
+ prism(escape, &:unescaped)
+ end
+ end
+
+ class String < Base
+ def ruby_result(escape)
+ ruby(escape, &:itself)
+ end
+
+ def prism_result(escape)
+ prism(escape, &:unescaped)
+ end
+ end
+
+ class Heredoc < Base
+ def ruby_result(escape)
+ ruby(escape, &:itself)
+ end
+
+ def prism_result(escape)
+ prism(escape) do |node|
+ case node.type
+ when :interpolated_string_node, :interpolated_x_string_node
+ node.parts.flat_map(&:unescaped).join
+ else
+ node.unescaped
+ end
+ end
+ end
+ end
+
+ class RegExp < Base
+ def ruby_result(escape)
+ ruby(escape, &:source)
+ end
+
+ def prism_result(escape)
+ prism(escape, &:unescaped)
+ end
+ end
+ end
+
+ def test_char; assert_context(Context::String.new("?", "")); end
+ def test_sqte; assert_context(Context::String.new("'", "'")); end
+ def test_dqte; assert_context(Context::String.new("\"", "\"")); end
+ def test_lwrq; assert_context(Context::String.new("%q[", "]")); end
+ def test_uprq; assert_context(Context::String.new("%Q[", "]")); end
+ def test_dstr; assert_context(Context::String.new("%[", "]")); end
+ def test_xstr; assert_context(Context::String.new("`", "`")); end
+ def test_lwrx; assert_context(Context::String.new("%x[", "]")); end
+ def test_h0_1; assert_context(Context::String.new("<<H\n", "\nH")); end
+ def test_h0_2; assert_context(Context::String.new("<<'H'\n", "\nH")); end
+ def test_h0_3; assert_context(Context::String.new("<<\"H\"\n", "\nH")); end
+ def test_h0_4; assert_context(Context::String.new("<<`H`\n", "\nH")); end
+ def test_hd_1; assert_context(Context::String.new("<<-H\n", "\nH")); end
+ def test_hd_2; assert_context(Context::String.new("<<-'H'\n", "\nH")); end
+ def test_hd_3; assert_context(Context::String.new("<<-\"H\"\n", "\nH")); end
+ def test_hd_4; assert_context(Context::String.new("<<-`H`\n", "\nH")); end
+ def test_ht_1; assert_context(Context::Heredoc.new("<<~H\n", "\nH")); end
+ def test_ht_2; assert_context(Context::Heredoc.new("<<~'H'\n", "\nH")); end
+ def test_ht_3; assert_context(Context::Heredoc.new("<<~\"H\"\n", "\nH")); end
+ def test_ht_4; assert_context(Context::Heredoc.new("<<~`H`\n", "\nH")); end
+ def test_pw_1; assert_context(Context::List.new("%w[", "]")); end
+ def test_pw_2; assert_context(Context::List.new("%w<", ">")); end
+ def test_uprw; assert_context(Context::List.new("%W[", "]")); end
+ def test_lwri; assert_context(Context::List.new("%i[", "]")); end
+ def test_upri; assert_context(Context::List.new("%I[", "]")); end
+ def test_lwrs; assert_context(Context::Symbol.new("%s[", "]")); end
+ def test_sym1; assert_context(Context::Symbol.new(":'", "'")); end
+ def test_sym2; assert_context(Context::Symbol.new(":\"", "\"")); end
+ def test_reg1; assert_context(Context::RegExp.new("/", "/")); end
+ def test_reg2; assert_context(Context::RegExp.new("%r[", "]")); end
+ def test_reg3; assert_context(Context::RegExp.new("%r<", ">")); end
+ def test_reg4; assert_context(Context::RegExp.new("%r{", "}")); end
+ def test_reg5; assert_context(Context::RegExp.new("%r(", ")")); end
+ def test_reg6; assert_context(Context::RegExp.new("%r|", "|")); end
+
+ private
+
+ def assert_context(context)
+ octal = [*("0".."7")]
+ hex = [*("a".."f"), *("A".."F"), *("0".."9")]
+
+ (0...256).each do |ord|
+ # I think this might be a bug in Ruby.
+ next if context.name == "?" && ord == 0xFF
+
+ # We don't currently support scanning for the number of capture groups
+ # to validate backreferences so these are all going to fail.
+ next if (context.name == "//" || context.name.start_with?("%r")) && ord.chr.start_with?(/\d/)
+
+ # \u is passed directly on to the regular expression engine and it is
+ # responsible for handling syntax errors. In this case we do not check
+ # it because it would require going through the compiler.
+ next if context.is_a?(Context::RegExp) && ord.chr == "u"
+
+ # \a \b \c ...
+ assert_unescape(context, ord.chr)
+ end
+
+ # \\r\n
+ assert_unescape(context, "\r\n")
+
+ # We don't currently support scanning for the number of capture groups to
+ # validate backreferences so these are all going to fail.
+ if context.name != "//" && !context.name.start_with?("%r")
+ # \00 \01 \02 ...
+ octal.product(octal).each { |digits| assert_unescape(context, digits.join) }
+
+ # \000 \001 \002 ...
+ octal.product(octal).product(octal).each { |digits| assert_unescape(context, digits.join) }
+ end
+
+ # \x0 \x1 \x2 ...
+ hex.each { |digit| assert_unescape(context, "x#{digit}") }
+
+ # \x00 \x01 \x02 ...
+ hex.product(hex).each { |digits| assert_unescape(context, "x#{digits.join}") }
+
+ # \u0000 \u0001 \u0002 ...
+ assert_unescape(context, "u#{["5"].concat(hex.sample(3)).join}")
+
+ # The behavior of whitespace in the middle of these escape sequences
+ # changed in Ruby 3.3.0, so we only want to test against latest.
+ if RUBY_VERSION >= "3.3.0"
+ # \u{00 00} ...
+ assert_unescape(context, "u{00#{["5"].concat(hex.sample(3)).join} \t\v 00#{["5"].concat(hex.sample(3)).join}}")
+ end
+
+ (0...128).each do |ord|
+ chr = ord.chr
+ next if chr == "\\" || !chr.match?(/[[:print:]]/)
+
+ # \C-a \C-b \C-c ...
+ assert_unescape(context, "C-#{chr}")
+
+ # \ca \cb \cc ...
+ assert_unescape(context, "c#{chr}")
+
+ # \M-a \M-b \M-c ...
+ assert_unescape(context, "M-#{chr}")
+
+ # \M-\C-a \M-\C-b \M-\C-c ...
+ assert_unescape(context, "M-\\C-#{chr}")
+
+ # \M-\ca \M-\cb \M-\cc ...
+ assert_unescape(context, "M-\\c#{chr}")
+
+ # \c\M-a \c\M-b \c\M-c ...
+ assert_unescape(context, "c\\M-#{chr}")
+ end
+ end
+
+ def assert_unescape(context, escape)
+ expected = context.ruby_result(escape)
+ actual = context.prism_result(escape)
+
+ message = -> do
+ "Expected #{context.name} to unescape #{escape.inspect} to " \
+ "#{expected.inspect}, but got #{actual.inspect}"
+ end
+
+ if expected == :error || actual == :error
+ assert_equal expected, actual, message
+ else
+ assert_equal expected.bytes, actual.bytes, message
+ end
+ end
+ end
+end
diff --git a/test/prism/version_test.rb b/test/prism/version_test.rb
new file mode 100644
index 0000000000..29ee6b224c
--- /dev/null
+++ b/test/prism/version_test.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require_relative "test_helper"
+
+module Prism
+ class VersionTest < TestCase
+ def test_version_is_set
+ refute_nil VERSION
+ end
+ end
+end
diff --git a/test/psych/helper.rb b/test/psych/helper.rb
index 0643139d8c..4e82887c6d 100644
--- a/test/psych/helper.rb
+++ b/test/psych/helper.rb
@@ -51,7 +51,7 @@ module Psych
:UseVersion => true, :UseHeader => true, :SortKeys => true
)
))
- rescue Psych::DisallowedClass, Psych::BadAlias
+ rescue Psych::DisallowedClass, Psych::BadAlias, Psych::AliasesNotEnabled
assert_to_yaml obj, yaml, :unsafe_load
end
@@ -61,7 +61,7 @@ module Psych
def assert_parse_only( obj, yaml )
begin
assert_equal obj, Psych::load( yaml )
- rescue Psych::DisallowedClass, Psych::BadAlias
+ rescue Psych::DisallowedClass, Psych::BadAlias, Psych::AliasesNotEnabled
assert_equal obj, Psych::unsafe_load( yaml )
end
assert_equal obj, Psych::parse( yaml ).transform
@@ -79,7 +79,7 @@ module Psych
assert_equal(obj, Psych.load(v.tree.yaml))
assert_equal(obj, Psych::load(Psych.dump(obj)))
assert_equal(obj, Psych::load(obj.to_yaml))
- rescue Psych::DisallowedClass, Psych::BadAlias
+ rescue Psych::DisallowedClass, Psych::BadAlias, Psych::AliasesNotEnabled
assert_equal(obj, Psych.unsafe_load(v.tree.yaml))
assert_equal(obj, Psych::unsafe_load(Psych.dump(obj)))
assert_equal(obj, Psych::unsafe_load(obj.to_yaml))
diff --git a/test/psych/test_array.rb b/test/psych/test_array.rb
index 28b76da785..0dc82439d4 100644
--- a/test/psych/test_array.rb
+++ b/test/psych/test_array.rb
@@ -57,6 +57,22 @@ module Psych
assert_cycle(@list)
end
+ def test_recursive_array
+ @list << @list
+
+ loaded = Psych.load(Psych.dump(@list), aliases: true)
+
+ assert_same loaded, loaded.last
+ end
+
+ def test_recursive_array_uses_alias
+ @list << @list
+
+ assert_raise(AliasesNotEnabled) do
+ Psych.load(Psych.dump(@list), aliases: false)
+ end
+ end
+
def test_cycle
assert_cycle(@list)
end
diff --git a/test/psych/test_coder.rb b/test/psych/test_coder.rb
index b2be0a4109..a6f5ad7f36 100644
--- a/test/psych/test_coder.rb
+++ b/test/psych/test_coder.rb
@@ -220,6 +220,8 @@ module Psych
end
def test_coder_style_map_any
+ pend "Failing on JRuby" if RUBY_PLATFORM =~ /java/
+
foo = Psych.dump CustomEncode.new \
map: {a: 1, b: 2},
style: Psych::Nodes::Mapping::ANY,
@@ -228,6 +230,8 @@ module Psych
end
def test_coder_style_map_block
+ pend "Failing on JRuby" if RUBY_PLATFORM =~ /java/
+
foo = Psych.dump CustomEncode.new \
map: {a: 1, b: 2},
style: Psych::Nodes::Mapping::BLOCK,
@@ -236,6 +240,8 @@ module Psych
end
def test_coder_style_map_flow
+ pend "Failing on JRuby" if RUBY_PLATFORM =~ /java/
+
foo = Psych.dump CustomEncode.new \
map: { a: 1, b: 2 },
style: Psych::Nodes::Mapping::FLOW,
diff --git a/test/psych/test_date_time.rb b/test/psych/test_date_time.rb
index 6f1e8b509e..3379bd24bf 100644
--- a/test/psych/test_date_time.rb
+++ b/test/psych/test_date_time.rb
@@ -44,6 +44,26 @@ module Psych
assert_match(/12:00:00-05:00/, cycled.last.to_s)
end
+ def test_julian_date
+ d = Date.new(1582, 10, 4, Date::GREGORIAN)
+ assert_cycle d
+ end
+
+ def test_proleptic_gregorian_date
+ d = Date.new(1582, 10, 14, Date::GREGORIAN)
+ assert_cycle d
+ end
+
+ def test_julian_datetime
+ dt = DateTime.new(1582, 10, 4, 23, 58, 59, 0, Date::GREGORIAN)
+ assert_cycle dt
+ end
+
+ def test_proleptic_gregorian_datetime
+ dt = DateTime.new(1582, 10, 14, 23, 58, 59, 0, Date::GREGORIAN)
+ assert_cycle dt
+ end
+
def test_invalid_date
assert_cycle "2013-10-31T10:40:07-000000000000033"
end
diff --git a/test/psych/test_encoding.rb b/test/psych/test_encoding.rb
index e5831c9045..1867d59ea6 100644
--- a/test/psych/test_encoding.rb
+++ b/test/psych/test_encoding.rb
@@ -13,13 +13,13 @@ module Psych
(Handler.instance_methods(true) -
Object.instance_methods).each do |m|
- class_eval %{
+ class_eval <<~RUBY, __FILE__, __LINE__ + 1
def #{m} *args
@strings += args.flatten.find_all { |a|
String === a
}
end
- }
+ RUBY
end
end
@@ -119,6 +119,8 @@ module Psych
end
def test_emit_alias
+ pend "Failing on JRuby" if RUBY_PLATFORM =~ /java/
+
@emitter.start_stream Psych::Parser::UTF8
@emitter.start_document [], [], true
e = assert_raise(RuntimeError) do
@@ -151,6 +153,7 @@ module Psych
@emitter.end_mapping
@emitter.end_document false
@emitter.end_stream
+ pend "Failing on JRuby" if RUBY_PLATFORM =~ /java/
@parser.parse @buffer.string
assert_encodings @utf8, @handler.strings
@@ -170,6 +173,7 @@ module Psych
@emitter.end_sequence
@emitter.end_document false
@emitter.end_stream
+ pend "Failing on JRuby" if RUBY_PLATFORM =~ /java/
@parser.parse @buffer.string
assert_encodings @utf8, @handler.strings
@@ -187,6 +191,7 @@ module Psych
@emitter.scalar 'foo', nil, nil, true, false, Nodes::Scalar::ANY
@emitter.end_document false
@emitter.end_stream
+ pend "Failing on JRuby" if RUBY_PLATFORM =~ /java/
@parser.parse @buffer.string
assert_encodings @utf8, @handler.strings
@@ -263,6 +268,8 @@ module Psych
end
def test_dump_non_ascii_string_to_file
+ pend "Failing on JRuby" if RUBY_PLATFORM =~ /java/
+
Tempfile.create(['utf8', 'yml'], :encoding => 'UTF-8') do |t|
h = {'one' => 'ã„ã¡'}
Psych.dump(h, t)
diff --git a/test/psych/test_hash.rb b/test/psych/test_hash.rb
index 5374781339..31eba8580b 100644
--- a/test/psych/test_hash.rb
+++ b/test/psych/test_hash.rb
@@ -102,26 +102,66 @@ module Psych
end
def test_ref_append
- hash = Psych.unsafe_load(<<-eoyml)
----
-foo: &foo
- hello: world
-bar:
- <<: *foo
-eoyml
+ hash = Psych.unsafe_load(<<~eoyml)
+ ---
+ foo: &foo
+ hello: world
+ bar:
+ <<: *foo
+ eoyml
assert_equal({"foo"=>{"hello"=>"world"}, "bar"=>{"hello"=>"world"}}, hash)
end
+ def test_anchor_reuse
+ hash = Psych.unsafe_load(<<~eoyml)
+ ---
+ foo: &foo
+ hello: world
+ bar: *foo
+ eoyml
+ assert_equal({"foo"=>{"hello"=>"world"}, "bar"=>{"hello"=>"world"}}, hash)
+ assert_same(hash.fetch("foo"), hash.fetch("bar"))
+ end
+
+ def test_raises_if_anchor_not_defined
+ assert_raise(Psych::AnchorNotDefined) do
+ Psych.unsafe_load(<<~eoyml)
+ ---
+ foo: &foo
+ hello: world
+ bar: *not_foo
+ eoyml
+ end
+ end
+
+ def test_recursive_hash
+ h = { }
+ h["recursive_reference"] = h
+
+ loaded = Psych.load(Psych.dump(h), aliases: true)
+
+ assert_same loaded, loaded.fetch("recursive_reference")
+ end
+
+ def test_recursive_hash_uses_alias
+ h = { }
+ h["recursive_reference"] = h
+
+ assert_raise(AliasesNotEnabled) do
+ Psych.load(Psych.dump(h), aliases: false)
+ end
+ end
+
def test_key_deduplication
unless String.method_defined?(:-@) && (-("a" * 20)).equal?((-("a" * 20)))
pend "This Ruby implementation doesn't support string deduplication"
end
- hashes = Psych.load(<<-eoyml)
----
-- unique_identifier: 1
-- unique_identifier: 2
-eoyml
+ hashes = Psych.load(<<~eoyml)
+ ---
+ - unique_identifier: 1
+ - unique_identifier: 2
+ eoyml
assert_same hashes[0].keys.first, hashes[1].keys.first
end
diff --git a/test/psych/test_merge_keys.rb b/test/psych/test_merge_keys.rb
index dcf4f1fce3..2f55a1ed8e 100644
--- a/test/psych/test_merge_keys.rb
+++ b/test/psych/test_merge_keys.rb
@@ -117,7 +117,7 @@ development:
bar:
<< : *foo
eoyml
- exp = assert_raise(Psych::BadAlias) { Psych.load yaml }
+ exp = assert_raise(Psych::AnchorNotDefined) { Psych.load(yaml, aliases: true) }
assert_match 'foo', exp.message
end
diff --git a/test/psych/test_numeric.rb b/test/psych/test_numeric.rb
index 8c3dcd173c..4c012e4562 100644
--- a/test/psych/test_numeric.rb
+++ b/test/psych/test_numeric.rb
@@ -1,6 +1,9 @@
# frozen_string_literal: true
require_relative 'helper'
-require 'bigdecimal'
+begin
+ require 'bigdecimal'
+rescue LoadError
+end
module Psych
###
@@ -29,13 +32,13 @@ module Psych
def test_big_decimal_tag
decimal = BigDecimal("12.34")
assert_match "!ruby/object:BigDecimal", Psych.dump(decimal)
- end
+ end if defined?(BigDecimal)
def test_big_decimal_round_trip
decimal = BigDecimal("12.34")
$DEBUG = false
assert_cycle decimal
- end
+ end if defined?(BigDecimal)
def test_does_not_attempt_numeric
str = Psych.load('--- 4 roses')
@@ -43,5 +46,16 @@ module Psych
str = Psych.load('--- 1.1.1')
assert_equal '1.1.1', str
end
+
+ # This behavior is not to YML spec, but is kept for backwards compatibility
+ def test_string_with_commas
+ number = Psych.load('--- 12,34,56')
+ assert_equal 123456, number
+ end
+
+ def test_string_with_commas_with_strict_integer
+ str = Psych.load('--- 12,34,56', strict_integer: true)
+ assert_equal '12,34,56', str
+ end
end
end
diff --git a/test/psych/test_object.rb b/test/psych/test_object.rb
index 0faf6b244d..21c27794ea 100644
--- a/test/psych/test_object.rb
+++ b/test/psych/test_object.rb
@@ -36,10 +36,19 @@ module Psych
def test_cyclic_references
foo = Foo.new(nil)
foo.parent = foo
- loaded = Psych.unsafe_load Psych.dump foo
+ loaded = Psych.load(Psych.dump(foo), permitted_classes: [Foo], aliases: true)
assert_instance_of(Foo, loaded)
- assert_equal loaded, loaded.parent
+ assert_same loaded, loaded.parent
+ end
+
+ def test_cyclic_reference_uses_alias
+ foo = Foo.new(nil)
+ foo.parent = foo
+
+ assert_raise(AliasesNotEnabled) do
+ Psych.load(Psych.dump(foo), permitted_classes: [Foo], aliases: false)
+ end
end
end
end
diff --git a/test/psych/test_object_references.rb b/test/psych/test_object_references.rb
index 269d72242e..86bb9034b9 100644
--- a/test/psych/test_object_references.rb
+++ b/test/psych/test_object_references.rb
@@ -39,7 +39,7 @@ module Psych
rescue Psych::DisallowedClass
data = Psych.unsafe_load yml
end
- assert_equal data.first.object_id, data.last.object_id
+ assert_same data.first, data.last
end
def test_float_references
@@ -49,7 +49,7 @@ module Psych
- *name
eoyml
assert_equal data.first, data.last
- assert_equal data.first.object_id, data.last.object_id
+ assert_same data.first, data.last
end
def test_binary_references
@@ -60,7 +60,7 @@ module Psych
- *name
eoyml
assert_equal data.first, data.last
- assert_equal data.first.object_id, data.last.object_id
+ assert_same data.first, data.last
end
def test_regexp_references
@@ -70,7 +70,7 @@ module Psych
- *name
eoyml
assert_equal data.first, data.last
- assert_equal data.first.object_id, data.last.object_id
+ assert_same data.first, data.last
end
end
end
diff --git a/test/psych/test_parser.rb b/test/psych/test_parser.rb
index 3604e7c985..c1e0abb89d 100644
--- a/test/psych/test_parser.rb
+++ b/test/psych/test_parser.rb
@@ -16,13 +16,13 @@ module Psych
(Handler.instance_methods(true) -
Object.instance_methods).each do |m|
- class_eval %{
+ class_eval <<~RUBY, __FILE__, __LINE__ + 1
def #{m} *args
super
@marks << @parser.mark if @parser
@calls << [:#{m}, args]
end
- }
+ RUBY
end
end
@@ -85,6 +85,8 @@ module Psych
def test_line_numbers
assert_equal 0, @parser.mark.line
+ pend "Failing on JRuby" if RUBY_PLATFORM =~ /java/
+
@parser.parse "---\n- hello\n- world"
line_calls = @handler.marks.map(&:line).zip(@handler.calls.map(&:first))
assert_equal [
@@ -110,6 +112,8 @@ module Psych
def test_column_numbers
assert_equal 0, @parser.mark.column
+ pend "Failing on JRuby" if RUBY_PLATFORM =~ /java/
+
@parser.parse "---\n- hello\n- world"
col_calls = @handler.marks.map(&:column).zip(@handler.calls.map(&:first))
assert_equal [
@@ -135,6 +139,8 @@ module Psych
def test_index_numbers
assert_equal 0, @parser.mark.index
+ pend "Failing on JRuby" if RUBY_PLATFORM =~ /java/
+
@parser.parse "---\n- hello\n- world"
idx_calls = @handler.marks.map(&:index).zip(@handler.calls.map(&:first))
assert_equal [
@@ -352,6 +358,8 @@ module Psych
end
def test_event_location
+ pend "Failing on JRuby" if RUBY_PLATFORM =~ /java/
+
@parser.parse "foo:\n" \
" barbaz: [1, 2]"
@@ -376,6 +384,25 @@ module Psych
[:end_stream, [2, 0, 2, 0]]], events
end
+ if Psych::Parser.method_defined?(:code_point_limit)
+ def test_code_point_limit
+ yaml = "foo: bar\n" * 500_000
+ assert_raise(org.snakeyaml.engine.v2.exceptions.YamlEngineException) do
+ Psych.load(yaml)
+ end
+
+ assert_nothing_raised do
+ begin
+ old_code_point_limit, Psych::Parser.code_point_limit = Psych::Parser::code_point_limit, 5_000_000
+
+ Psych.load(yaml)
+ ensure
+ Psych::Parser.code_point_limit = old_code_point_limit
+ end
+ end
+ end
+ end
+
def assert_called call, with = nil, parser = @parser
if with
call = parser.handler.calls.find { |x|
diff --git a/test/psych/test_psych.rb b/test/psych/test_psych.rb
index 1abd69ceca..42586a8779 100644
--- a/test/psych/test_psych.rb
+++ b/test/psych/test_psych.rb
@@ -419,12 +419,41 @@ eoyml
end
def test_safe_dump_symbols
+ assert_equal Psych.dump(:foo), Psych.safe_dump(:foo, permitted_classes: [Symbol])
+ assert_equal Psych.dump(:foo), Psych.safe_dump(:foo, permitted_symbols: [:foo])
+
error = assert_raise Psych::DisallowedClass do
- Psych.safe_dump(:foo, permitted_classes: [Symbol])
+ Psych.safe_dump(:foo)
end
assert_equal "Tried to dump unspecified class: Symbol(:foo)", error.message
- assert_match(/\A--- :foo\n(?:\.\.\.\n)?\z/, Psych.safe_dump(:foo, permitted_classes: [Symbol], permitted_symbols: [:foo]))
+ assert_match(/\A--- :foo\n(?:\.\.\.\n)?\z/, Psych.safe_dump(:foo, permitted_symbols: [:foo]))
+ end
+
+ def test_safe_dump_stringify_names
+ yaml = <<-eoyml
+---
+foo:
+ bar: bar
+ 'no': special escapes
+ 123: number
+eoyml
+
+ payload = Psych.safe_dump({
+ foo: {
+ bar: "bar",
+ no: "special escapes",
+ 123 => "number"
+ }
+ }, stringify_names: true)
+ assert_equal yaml, payload
+
+ assert_equal("---\nfoo: :bar\n", Psych.safe_dump({foo: :bar}, stringify_names: true, permitted_symbols: [:bar]))
+
+ error = assert_raise Psych::DisallowedClass do
+ Psych.safe_dump({foo: :bar}, stringify_names: true)
+ end
+ assert_equal "Tried to dump unspecified class: Symbol(:bar)", error.message
end
def test_safe_dump_aliases
diff --git a/test/psych/test_safe_load.rb b/test/psych/test_safe_load.rb
index b52d6048b3..a9ed737528 100644
--- a/test/psych/test_safe_load.rb
+++ b/test/psych/test_safe_load.rb
@@ -19,18 +19,31 @@ module Psych
end
end
- def test_no_recursion
- x = []
- x << x
- assert_raise(Psych::BadAlias) do
- Psych.safe_load Psych.dump(x)
+ def test_raises_when_alias_found_if_alias_parsing_not_enabled
+ yaml_with_aliases = <<~YAML
+ ---
+ a: &ABC
+ k1: v1
+ k2: v2
+ b: *ABC
+ YAML
+
+ assert_raise(Psych::AliasesNotEnabled) do
+ Psych.safe_load(yaml_with_aliases)
end
end
- def test_explicit_recursion
- x = []
- x << x
- assert_equal(x, Psych.safe_load(Psych.dump(x), permitted_classes: [], permitted_symbols: [], aliases: true))
+ def test_aliases_are_parsed_when_alias_parsing_is_enabled
+ yaml_with_aliases = <<~YAML
+ ---
+ a: &ABC
+ k1: v1
+ k2: v2
+ b: *ABC
+ YAML
+
+ result = Psych.safe_load(yaml_with_aliases, aliases: true)
+ assert_same result.fetch("a"), result.fetch("b")
end
def test_permitted_symbol
diff --git a/test/psych/test_scalar_scanner.rb b/test/psych/test_scalar_scanner.rb
index ebc9fbdcd2..8907d1255a 100644
--- a/test/psych/test_scalar_scanner.rb
+++ b/test/psych/test_scalar_scanner.rb
@@ -126,6 +126,19 @@ module Psych
assert_equal '100_', ss.tokenize('100_')
end
+ def test_scan_strings_with_legacy_int_delimiters
+ assert_equal '0x_,_', ss.tokenize('0x_,_')
+ assert_equal '+0__,,', ss.tokenize('+0__,,')
+ assert_equal '-0b,_,', ss.tokenize('-0b,_,')
+ end
+
+ def test_scan_strings_with_strict_int_delimiters
+ scanner = Psych::ScalarScanner.new ClassLoader.new, strict_integer: true
+ assert_equal '0x___', scanner.tokenize('0x___')
+ assert_equal '+0____', scanner.tokenize('+0____')
+ assert_equal '-0b___', scanner.tokenize('-0b___')
+ end
+
def test_scan_int_commas_and_underscores
# NB: This test is to ensure backward compatibility with prior Psych versions,
# not to test against any actual YAML specification.
@@ -149,6 +162,31 @@ module Psych
assert_equal 0x123456789abcdef, ss.tokenize('0x12_,34,_56,_789abcdef__')
end
+ def test_scan_strict_int_commas_and_underscores
+ # this test is to ensure adherence to YML spec using the 'strict_integer' option
+ scanner = Psych::ScalarScanner.new ClassLoader.new, strict_integer: true
+ assert_equal 123_456_789, scanner.tokenize('123_456_789')
+ assert_equal '123,456,789', scanner.tokenize('123,456,789')
+ assert_equal '1_2,3,4_5,6_789', scanner.tokenize('1_2,3,4_5,6_789')
+
+ assert_equal 1, scanner.tokenize('1')
+ assert_equal 1, scanner.tokenize('+1')
+ assert_equal(-1, scanner.tokenize('-1'))
+
+ assert_equal 0b010101010, scanner.tokenize('0b010101010')
+ assert_equal 0b010101010, scanner.tokenize('0b01_01_01_010')
+ assert_equal '0b0,1_0,1_,0,1_01,0', scanner.tokenize('0b0,1_0,1_,0,1_01,0')
+
+ assert_equal 01234567, scanner.tokenize('01234567')
+ assert_equal '0_,,,1_2,_34567', scanner.tokenize('0_,,,1_2,_34567')
+
+ assert_equal 0x123456789abcdef, scanner.tokenize('0x123456789abcdef')
+ assert_equal 0x123456789abcdef, scanner.tokenize('0x12_34_56_789abcdef')
+ assert_equal '0x12_,34,_56,_789abcdef', scanner.tokenize('0x12_,34,_56,_789abcdef')
+ assert_equal '0x_12_,34,_56,_789abcdef', scanner.tokenize('0x_12_,34,_56,_789abcdef')
+ assert_equal '0x12_,34,_56,_789abcdef__', scanner.tokenize('0x12_,34,_56,_789abcdef__')
+ end
+
def test_scan_dot
assert_equal '.', ss.tokenize('.')
end
diff --git a/test/psych/test_set.rb b/test/psych/test_set.rb
index 87944d839e..b4968d3425 100644
--- a/test/psych/test_set.rb
+++ b/test/psych/test_set.rb
@@ -46,5 +46,12 @@ bar: baz
@set['self'] = @set
assert_cycle(@set)
end
+
+ def test_stringify_names
+ @set[:symbol] = :value
+
+ assert_match(/^:symbol: :value/, Psych.dump(@set))
+ assert_match(/^symbol: :value/, Psych.dump(@set, stringify_names: true))
+ end
end
end
diff --git a/test/psych/test_string.rb b/test/psych/test_string.rb
index 0dc34b3083..84ae5cbb45 100644
--- a/test/psych/test_string.rb
+++ b/test/psych/test_string.rb
@@ -17,17 +17,17 @@ module Psych
end
end
- # 'y' and 'n' are kind of ambiguous. Syck treated y and n literals in
+ # 'y', 'Y', 'n', 'N' are kind of ambiguous. Syck treated those literals in
# YAML documents as strings. But this is not what the YAML 1.1 spec says.
# YAML 1.1 says they should be treated as booleans. When we're dumping
# documents, we know it's a string, so adding quotes will eliminate the
# "ambiguity" in the emitted document
- def test_y_is_quoted
- assert_match(/"y"/, Psych.dump("y"))
- end
- def test_n_is_quoted
- assert_match(/"n"/, Psych.dump("n"))
+ def test_all_yaml_1_1_booleans_are_quoted
+ yaml_1_1_booleans = %w[y Y yes Yes YES n N no No NO true True TRUE false False FALSE on On ON off Off OFF] # from https://yaml.org/type/bool.html
+ yaml_1_1_booleans.each do |boolean|
+ assert_match(/"#{boolean}"|'#{boolean}'/, Psych.dump(boolean))
+ end
end
def test_string_with_newline
diff --git a/test/psych/test_yaml.rb b/test/psych/test_yaml.rb
index e12b9769fe..812a15dfcc 100644
--- a/test/psych/test_yaml.rb
+++ b/test/psych/test_yaml.rb
@@ -1,8 +1,6 @@
# -*- coding: us-ascii; mode: ruby; ruby-indent-level: 4; tab-width: 4 -*-
# frozen_string_literal: true
-# vim:sw=4:ts=4
-# $Id$
-#
+
require_relative 'helper'
require 'ostruct'
@@ -34,32 +32,32 @@ class Psych_Unit_Tests < Psych::TestCase
# [ruby-core:34969]
def test_regexp_with_n
- assert_cycle(Regexp.new('',0,'n'))
- end
- #
- # Tests modified from 00basic.t in Psych.pm
- #
- def test_basic_map
- # Simple map
- assert_parse_only(
- { 'one' => 'foo', 'three' => 'baz', 'two' => 'bar' }, <<EOY
+ assert_cycle(Regexp.new('',Regexp::NOENCODING))
+ end
+ #
+ # Tests modified from 00basic.t in Psych.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 => 'Psych\'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
+ )
+ 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 => 'Psych\'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'
@@ -76,44 +74,44 @@ EOY
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
+ )
+ 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
+ )
+ end
- def test_spec_simple_implicit_map
- # Simple implicit map
- assert_to_yaml(
- { 'hr' => 65, 'avg' => 0.278, 'rbi' => 147 }, <<EOY
+ 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
+ )
+ 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
@@ -123,16 +121,16 @@ national:
- 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
+ )
+ 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
@@ -142,38 +140,38 @@ EOY
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
+ )
+ 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
+ )
+ 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
+ )
+ end
def test_ambiguous_comments
# [ruby-talk:88012]
@@ -182,11 +180,11 @@ EOY
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
+ 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
@@ -195,16 +193,16 @@ rbi:
- 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
+ )
+ 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
@@ -214,7 +212,7 @@ rbi:
- *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
@@ -223,8 +221,8 @@ EOY
&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 }
+ - { *F : MADF, *C : AUD, *D : SYD, *A : MEL }
+ - { *F : DFSF, *C : USD, *D : JFK, *A : MCO }
EOY
)
@@ -233,31 +231,31 @@ EOY
---
ALIASES: [&f fareref, &c currency, &d departure, &a arrival]
FARES:
-- *f: DOGMA
- *c: GBP
- *d: LAX
- *a: EDI
+- *f : DOGMA
+ *c : GBP
+ *d : LAX
+ *a : EDI
-- *f: MADF
- *c: AUD
- *d: SYD
- *a: MEL
+- *f : MADF
+ *c : AUD
+ *d : SYD
+ *a : MEL
-- *f: DFSF
- *c: USD
- *d: JFK
- *a: MCO
+- *f : DFSF
+ *c : USD
+ *d : JFK
+ *a : MCO
EOY
)
- end
+ end
- def test_spec_mapping_between_sequences
- # Complex key #1
- 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
+ def test_spec_mapping_between_sequences
+ # Complex key #1
+ 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
@@ -269,16 +267,16 @@ EOY
: [ 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
+ )
+
+ # 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
@@ -292,17 +290,17 @@ EOY
:
- 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
+ )
+ 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
@@ -314,8 +312,8 @@ product:
- item : Big Shoes
quantity: 1
EOY
- )
- end
+ )
+ end
def test_spec_sequence_in_sequence_shortcut
# Seq-in-seq
@@ -351,31 +349,31 @@ EOY
EOY
end
- def test_spec_single_literal
- # Literal scalar block
- assert_parse_only( [ "\\/|\\/|\n/ | |_\n" ], <<EOY )
+ def test_spec_single_literal
+ # Literal scalar block
+ assert_parse_only( [ "\\/|\\/|\n/ | |_\n" ], <<EOY )
- |
\\/|\\/|
/ | |_
EOY
- end
+ end
- def test_spec_single_folded
- # Folded scalar block
- assert_parse_only(
- [ "Mark McGwire's year was crippled by a knee injury.\n" ], <<EOY
+ 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
+ )
+ 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
+ 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.
@@ -385,13 +383,13 @@ EOY
What a year!
EOY
- )
- end
+ )
+ 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
+ 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
@@ -400,14 +398,14 @@ 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
+ )
+ 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.
@@ -415,19 +413,19 @@ quoted: "\\
So does this quoted
scalar.\\n"
EOY
- )
- end
+ )
+ end
- def test_spec_type_int
- assert_parse_only(
- { 'canonical' => 12345, 'decimal' => 12345, 'octal' => '014'.oct, 'hexadecimal' => '0xC'.hex }, <<EOY
+ 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(
+ )
+ assert_parse_only(
{ 'canonical' => 685230, 'decimal' => 685230, 'octal' => 02472256, 'hexadecimal' => 0x0A74AE, 'sexagesimal' => 685230 }, <<EOY)
canonical: 685230
decimal: +685,230
@@ -435,48 +433,48 @@ octal: 02472256
hexadecimal: 0x0A,74,AE
sexagesimal: 190:20:30
EOY
- end
+ 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)
+ 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 = Psych::load( <<EOY )
+ nan = Psych::load( <<EOY )
not a number: .NaN
EOY
- assert( nan['not a number'].nan? )
- end
+ assert( nan['not a number'].nan? )
+ end
- def test_spec_type_misc
- assert_parse_only(
- { nil => nil, true => true, false => false, 'string' => '12345' }, <<EOY
+ 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
+ )
+ 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
@@ -507,12 +505,12 @@ comments: >
Backup contact is Nancy
Billsmer @ 338-4338.
EOY
- )
- end
+ )
+ end
- def test_spec_log_file
- doc_ct = 0
- Psych::load_stream( <<EOY
+ def test_spec_log_file
+ doc_ct = 0
+ Psych::load_stream( <<EOY
---
Time: 2001-11-23 15:01:42 -05:00
User: ed
@@ -540,52 +538,52 @@ Stack:
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 = Psych::load( <<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 = Psych::load( <<EOY
---
This Psych 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 Psych 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." )
- end
+ )
+ assert_equal( y, "This Psych 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." )
+ end
- def test_spec_root_mapping
- y = Psych::unsafe_load( <<EOY
+ def test_spec_root_mapping
+ y = Psych::unsafe_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
+ )
+ assert_equal( y, { 'invoice' => 34843, 'date' => Date.new( 2001, 1, 23 ), 'total' => 4443.52 } )
+ end
- def test_spec_oneline_docs
- doc_ct = 0
- Psych::load_stream( <<EOY
+ def test_spec_oneline_docs
+ doc_ct = 0
+ Psych::load_stream( <<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.
@@ -593,21 +591,21 @@ EOY
--- [ ]
--- ''
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
+ ) { |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
_, _, type = type.split( ':', 3 )
@@ -619,7 +617,7 @@ EOY
}
Psych.add_domain_type( "domain.tld/2002", 'invoice', &customer_proc )
Psych.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
+ 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'.
@@ -632,12 +630,12 @@ invoice: !domain.tld/2002:invoice
given : Chris
family : Dumars
EOY
- )
- end
+ )
+ 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
+ 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). ###
@@ -649,19 +647,19 @@ this: | # Comments may trail lines.
# These are three throwaway comment
# lines (the first line is empty).
EOY
- )
- end
+ )
+ end
- def test_spec_force_implicit
- # Force implicit
- assert_parse_only(
- { 'integer' => 12, 'also int' => 12, 'string' => '12' }, <<EOY
+ 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
+ )
+ end
###
# Commenting out this test. This line:
@@ -672,44 +670,44 @@ EOY
#
# http://yaml.org/spec/1.1/#id896876
#
-# def test_spec_url_escaping
-# Psych.add_domain_type( "domain.tld,2002", "type0" ) { |type, val|
-# "ONE: #{val}"
-# }
-# Psych.add_domain_type( "domain.tld,2002", "type%30" ) { |type, val|
-# "TWO: #{val}"
-# }
-# assert_parse_only(
-# { 'same' => [ 'ONE: value', 'ONE: value' ], 'different' => [ 'TWO: value' ] }, <<EOY
+# def test_spec_url_escaping
+# Psych.add_domain_type( "domain.tld,2002", "type0" ) { |type, val|
+# "ONE: #{val}"
+# }
+# Psych.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 Psych 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
+# )
+# 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
+ )
+ end
- def test_spec_explicit_families
+ def test_spec_explicit_families
Psych.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
+ 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
@@ -721,34 +719,34 @@ 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
- Psych.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
+ )
+ end
+
+ def test_spec_application_family
+ # Testing the clarkevans.com graphs
+ Psych.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
- }
- Psych.add_domain_type( "clarkevans.com/2002", 'graph/circle', &one_shape_proc )
- Psych.add_domain_type( "clarkevans.com/2002", 'graph/line', &one_shape_proc )
- Psych.add_domain_type( "clarkevans.com/2002", 'graph/text', &one_shape_proc )
+ val['TYPE'] = "Shape: #{type[2]}"
+ val
+ else
+ raise ArgumentError, "Invalid graph of type #{val.class}: " + val.inspect
+ end
+ }
+ Psych.add_domain_type( "clarkevans.com/2002", 'graph/circle', &one_shape_proc )
+ Psych.add_domain_type( "clarkevans.com/2002", 'graph/line', &one_shape_proc )
+ Psych.add_domain_type( "clarkevans.com/2002", 'graph/text', &one_shape_proc )
# MODIFIED to remove invalid Psych
- 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
+ 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
- !/graph/circle
center: &ORIGIN {x: 73, y: 129}
@@ -761,12 +759,12 @@ EOY
color: 0xFFEEBB
value: Pretty vector drawing.
EOY
- )
- end
+ )
+ end
- def test_spec_float_explicit
- assert_parse_only(
- [ 10.0, 10.0, 10.0, 10.0 ], <<EOY
+ 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
@@ -776,15 +774,15 @@ EOY
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
+ )
+ 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
@@ -798,24 +796,24 @@ nested:
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
+ )
+ 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 }
@@ -860,13 +858,13 @@ nested:
# :
# with a: mapping value.
EOY
- )
- end
+ )
+ 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
+ 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: |
@@ -900,15 +898,15 @@ also written as: |-2
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
+ )
+
+ 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.
@@ -925,11 +923,11 @@ kept: |+
same as "kept" above: "This has two newlines.\\n\\n"
EOY
- )
- end
+ )
+ 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
+ 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.'
@@ -940,11 +938,11 @@ span: 'this contains
line break'
is same as: "this contains six spaces\\nand one line break"
EOY
- )
- end
+ )
+ 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
+ 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."
@@ -954,29 +952,29 @@ span: "this contains
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
+ )
+ 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
+ )
+ 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\\
@@ -997,19 +995,19 @@ 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
+ )
+ 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
+ )
+ end
#
# Test of Ranges
@@ -1033,15 +1031,15 @@ EOY
end
- def test_ruby_struct
- Struct.send(:remove_const, :MyBookStruct) if Struct.const_defined?(:MyBookStruct)
- # Ruby structures
- book_struct = Struct::new( "MyBookStruct", :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
+ def test_ruby_struct
+ Struct.send(:remove_const, :MyBookStruct) if Struct.const_defined?(:MyBookStruct)
+ # Ruby structures
+ book_struct = Struct::new( "MyBookStruct", :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:MyBookStruct
author: Yukihiro Matsumoto
title: Ruby in a Nutshell
@@ -1059,64 +1057,64 @@ EOY
year: 2002
isbn: None
EOY
- )
+ )
assert_to_yaml( Psych_Tests::StructTest.new( 123 ), <<EOY )
--- !ruby/struct:Psych_Tests::StructTest
c: 123
EOY
- end
+ end
- def test_ruby_rational
- assert_to_yaml( Rational(1, 2), <<EOY )
+ def test_ruby_rational
+ assert_to_yaml( Rational(1, 2), <<EOY )
--- !ruby/object:Rational
numerator: 1
denominator: 2
EOY
- # Read Psych dumped by the ruby 1.8.3.
- assert_to_yaml( Rational(1, 2), "!ruby/object:Rational 1/2\n" )
- assert_raise( ArgumentError ) { Psych.unsafe_load("!ruby/object:Rational INVALID/RATIONAL\n") }
- end
+ # Read Psych dumped by the ruby 1.8.3.
+ assert_to_yaml( Rational(1, 2), "!ruby/object:Rational 1/2\n" )
+ assert_raise( ArgumentError ) { Psych.unsafe_load("!ruby/object:Rational INVALID/RATIONAL\n") }
+ end
- def test_ruby_complex
- assert_to_yaml( Complex(3, 4), <<EOY )
+ def test_ruby_complex
+ assert_to_yaml( Complex(3, 4), <<EOY )
--- !ruby/object:Complex
image: 4
real: 3
EOY
- # Read Psych dumped by the ruby 1.8.3.
- assert_to_yaml( Complex(3, 4), "!ruby/object:Complex 3+4i\n" )
- assert_raise( ArgumentError ) { Psych.unsafe_load("!ruby/object:Complex INVALID+COMPLEXi\n") }
- end
+ # Read Psych dumped by the ruby 1.8.3.
+ assert_to_yaml( Complex(3, 4), "!ruby/object:Complex 3+4i\n" )
+ assert_raise( ArgumentError ) { Psych.unsafe_load("!ruby/object:Complex INVALID+COMPLEXi\n") }
+ end
- def test_emitting_indicators
- assert_to_yaml( "Hi, from Object 1. You passed: please, pretty please", <<EOY
+ 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 Psych::Stream class -- INACTIVE at the moment
- ##
- #def test_document
- # y = Psych::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
+ )
+ end
+
+ ##
+ ## Test the Psych::Stream class -- INACTIVE at the moment
+ ##
+ #def test_document
+ # y = Psych::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
diff --git a/test/psych/visitors/test_emitter.rb b/test/psych/visitors/test_emitter.rb
index 70adbb9ca0..8bcf5491ca 100644
--- a/test/psych/visitors/test_emitter.rb
+++ b/test/psych/visitors/test_emitter.rb
@@ -61,9 +61,9 @@ module Psych
@visitor.accept s
- assert_match(/key: value/, @io.string)
+ assert_include(@io.string, "key: value")
assert_equal @io.string, s.yaml
- assert(/\.\.\./ !~ s.yaml)
+ assert_not_include(s.yaml, "...")
end
def test_scalar
@@ -76,7 +76,7 @@ module Psych
@visitor.accept s
- assert_match(/hello/, @io.string)
+ assert_include(@io.string, "hello")
assert_equal @io.string, s.yaml
end
@@ -90,8 +90,8 @@ module Psych
@visitor.accept s
- assert_match(/str/, @io.string)
- assert_match(/hello/, @io.string)
+ assert_include(@io.string, "str")
+ assert_include(@io.string, "hello")
assert_equal @io.string, s.yaml
end
@@ -107,7 +107,7 @@ module Psych
@visitor.accept s
- assert_match(/- hello/, @io.string)
+ assert_include(@io.string, "- hello")
assert_equal @io.string, s.yaml
end
@@ -122,7 +122,7 @@ module Psych
@visitor.accept s
- assert_match(/key: value/, @io.string)
+ assert_include(@io.string, "key: value")
assert_equal @io.string, s.yaml
end
@@ -137,7 +137,7 @@ module Psych
@visitor.accept s
- assert_match(/&A key: \*A/, @io.string)
+ assert_include(@io.string, "&A key: \*A")
assert_equal @io.string, s.yaml
end
end
diff --git a/test/psych/visitors/test_to_ruby.rb b/test/psych/visitors/test_to_ruby.rb
index 3d4608b903..89c3676651 100644
--- a/test/psych/visitors/test_to_ruby.rb
+++ b/test/psych/visitors/test_to_ruby.rb
@@ -319,7 +319,7 @@ description:
list = seq.to_ruby
assert_equal %w{ foo foo }, list
- assert_equal list[0].object_id, list[1].object_id
+ assert_same list[0], list[1]
end
def test_mapping_with_str_tag
diff --git a/test/psych/visitors/test_yaml_tree.rb b/test/psych/visitors/test_yaml_tree.rb
index 4c48670f2f..01e685134a 100644
--- a/test/psych/visitors/test_yaml_tree.rb
+++ b/test/psych/visitors/test_yaml_tree.rb
@@ -34,7 +34,7 @@ module Psych
v << "hello world"
v.finish
- assert_match "hello world", io.string
+ assert_include io.string, "hello world"
end
def test_binary_formatting
@@ -167,9 +167,9 @@ module Psych
end
def test_string
- assert_match(/'017'/, Psych.dump({'a' => '017'}))
- assert_match(/'019'/, Psych.dump({'a' => '019'}))
- assert_match(/'01818'/, Psych.dump({'a' => '01818'}))
+ assert_include(Psych.dump({'a' => '017'}), "'017'")
+ assert_include(Psych.dump({'a' => '019'}), "'019'")
+ assert_include(Psych.dump({'a' => '01818'}), "'01818'")
end
# http://yaml.org/type/null.html
diff --git a/test/racc/assets/cadenza.y b/test/racc/assets/cadenza.y
deleted file mode 100644
index 1940ead225..0000000000
--- a/test/racc/assets/cadenza.y
+++ /dev/null
@@ -1,170 +0,0 @@
-# This grammar is released under an MIT license
-# Author: William Howard (http://github.com/whoward)
-# Source: https://github.com/whoward/cadenza/blob/master/src/cadenza.y
-
-class Cadenza::RaccParser
-
-/* expect this many shift/reduce conflicts */
-expect 37
-
-rule
- target
- : document
- | /* none */ { result = nil }
- ;
-
- parameter_list
- : logical_expression { result = [val[0]] }
- | parameter_list ',' logical_expression { result = val[0].push(val[2]) }
- ;
-
- /* this has a shift/reduce conflict but since Racc will shift in this case it is the correct behavior */
- primary_expression
- : IDENTIFIER { result = VariableNode.new(val[0].value) }
- | IDENTIFIER parameter_list { result = VariableNode.new(val[0].value, val[1]) }
- | INTEGER { result = ConstantNode.new(val[0].value) }
- | REAL { result = ConstantNode.new(val[0].value) }
- | STRING { result = ConstantNode.new(val[0].value) }
- | '(' filtered_expression ')' { result = val[1] }
- ;
-
- multiplicative_expression
- : primary_expression
- | multiplicative_expression '*' primary_expression { result = OperationNode.new(val[0], "*", val[2]) }
- | multiplicative_expression '/' primary_expression { result = OperationNode.new(val[0], "/", val[2]) }
- ;
-
- additive_expression
- : multiplicative_expression
- | additive_expression '+' multiplicative_expression { result = OperationNode.new(val[0], "+", val[2]) }
- | additive_expression '-' multiplicative_expression { result = OperationNode.new(val[0], "-", val[2]) }
- ;
-
- boolean_expression
- : additive_expression
- | boolean_expression OP_EQ additive_expression { result = OperationNode.new(val[0], "==", val[2]) }
- | boolean_expression OP_NEQ additive_expression { result = OperationNode.new(val[0], "!=", val[2]) }
- | boolean_expression OP_LEQ additive_expression { result = OperationNode.new(val[0], "<=", val[2]) }
- | boolean_expression OP_GEQ additive_expression { result = OperationNode.new(val[0], ">=", val[2]) }
- | boolean_expression '>' additive_expression { result = OperationNode.new(val[0], ">", val[2]) }
- | boolean_expression '<' additive_expression { result = OperationNode.new(val[0], "<", val[2]) }
- ;
-
- inverse_expression
- : boolean_expression
- | NOT boolean_expression { result = BooleanInverseNode.new(val[1]) }
- ;
-
- logical_expression
- : inverse_expression
- | logical_expression AND inverse_expression { result = OperationNode.new(val[0], "and", val[2]) }
- | logical_expression OR inverse_expression { result = OperationNode.new(val[0], "or", val[2]) }
- ;
-
- filter
- : IDENTIFIER { result = FilterNode.new(val[0].value) }
- | IDENTIFIER ':' parameter_list { result = FilterNode.new(val[0].value, val[2]) }
- ;
-
- filter_list
- : filter { result = [val[0]] }
- | filter_list '|' filter { result = val[0].push(val[2]) }
- ;
-
- filtered_expression
- : logical_expression
- | logical_expression '|' filter_list { result = FilteredValueNode.new(val[0], val[2]) }
- ;
-
- inject_statement
- : VAR_OPEN filtered_expression VAR_CLOSE { result = val[1] }
- ;
-
- if_tag
- : STMT_OPEN IF logical_expression STMT_CLOSE { open_scope!; result = val[2] }
- | STMT_OPEN UNLESS logical_expression STMT_CLOSE { open_scope!; result = BooleanInverseNode.new(val[2]) }
- ;
-
- else_tag
- : STMT_OPEN ELSE STMT_CLOSE { result = close_scope!; open_scope! }
- ;
-
- end_if_tag
- : STMT_OPEN ENDIF STMT_CLOSE { result = close_scope! }
- | STMT_OPEN ENDUNLESS STMT_CLOSE { result = close_scope! }
- ;
-
- if_block
- : if_tag end_if_tag { result = IfNode.new(val[0], val[1]) }
- | if_tag document end_if_tag { result = IfNode.new(val[0], val[2]) }
- | if_tag else_tag document end_if_tag { result = IfNode.new(val[0], val[1], val[3]) }
- | if_tag document else_tag end_if_tag { result = IfNode.new(val[0], val[2], val[3]) }
- | if_tag document else_tag document end_if_tag { result = IfNode.new(val[0], val[2], val[4]) }
- ;
-
- for_tag
- : STMT_OPEN FOR IDENTIFIER IN filtered_expression STMT_CLOSE { open_scope!; result = [val[2].value, val[4]] }
- ;
-
- end_for_tag
- : STMT_OPEN ENDFOR STMT_CLOSE { result = close_scope! }
- ;
-
- /* this has a shift/reduce conflict but since Racc will shift in this case it is the correct behavior */
- for_block
- : for_tag end_for_tag { result = ForNode.new(VariableNode.new(val[0].first), val[0].last, val[1]) }
- | for_tag document end_for_tag { result = ForNode.new(VariableNode.new(val[0].first), val[0].last, val[2]) }
- ;
-
- block_tag
- : STMT_OPEN BLOCK IDENTIFIER STMT_CLOSE { result = open_block_scope!(val[2].value) }
- ;
-
- end_block_tag
- : STMT_OPEN ENDBLOCK STMT_CLOSE { result = close_block_scope! }
- ;
-
- /* this has a shift/reduce conflict but since Racc will shift in this case it is the correct behavior */
- block_block
- : block_tag end_block_tag { result = BlockNode.new(val[0], val[1]) }
- | block_tag document end_block_tag { result = BlockNode.new(val[0], val[2]) }
- ;
-
- generic_block_tag
- : STMT_OPEN IDENTIFIER STMT_CLOSE { open_scope!; result = [val[1].value, []] }
- | STMT_OPEN IDENTIFIER parameter_list STMT_CLOSE { open_scope!; result = [val[1].value, val[2]] }
- ;
-
- end_generic_block_tag
- : STMT_OPEN END STMT_CLOSE { result = close_scope! }
- ;
-
- generic_block
- : generic_block_tag document end_generic_block_tag { result = GenericBlockNode.new(val[0].first, val[2], val[0].last) }
- ;
-
- extends_statement
- : STMT_OPEN EXTENDS STRING STMT_CLOSE { result = val[2].value }
- | STMT_OPEN EXTENDS IDENTIFIER STMT_CLOSE { result = VariableNode.new(val[2].value) }
- ;
-
- document_component
- : TEXT_BLOCK { result = TextNode.new(val[0].value) }
- | inject_statement
- | if_block
- | for_block
- | generic_block
- | block_block
- ;
-
- document
- : document_component { push val[0] }
- | document document_component { push val[1] }
- | extends_statement { document.extends = val[0] }
- | document extends_statement { document.extends = val[1] }
- ;
-
----- header ----
-# racc_parser.rb : generated by racc
-
----- inner ----
diff --git a/test/racc/assets/cast.y b/test/racc/assets/cast.y
deleted file mode 100644
index d180c09e14..0000000000
--- a/test/racc/assets/cast.y
+++ /dev/null
@@ -1,926 +0,0 @@
-# The MIT License
-#
-# Copyright (c) George Ogata
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-class C::Parser
-# shift/reduce conflict on "if (c) if (c) ; else ; else ;"
-expect 1
-rule
-
-# A.2.4 External definitions
-
-# Returns TranslationUnit
-translation_unit
- : external_declaration {result = TranslationUnit.new_at(val[0].pos, NodeChain[val[0]])}
- | translation_unit external_declaration {result = val[0]; result.entities << val[1]}
-
-# Returns Declaration|FunctionDef
-external_declaration
- : function_definition {result = val[0]}
- | declaration {result = val[0]}
-
-# Returns FunctionDef
-function_definition
- : declaration_specifiers declarator declaration_list compound_statement {result = make_function_def(val[0][0], val[0][1], val[1], val[2], val[3])}
- | declaration_specifiers declarator compound_statement {result = make_function_def(val[0][0], val[0][1], val[1], nil , val[2])}
-
-# Returns [Declaration]
-declaration_list
- : declaration {result = [val[0]]}
- | declaration_list declaration {result = val[0] << val[1]}
-
-# A.2.3 Statements
-
-# Returns Statement
-statement
- : labeled_statement {result = val[0]}
- | compound_statement {result = val[0]}
- | expression_statement {result = val[0]}
- | selection_statement {result = val[0]}
- | iteration_statement {result = val[0]}
- | jump_statement {result = val[0]}
-
-# Returns Statement
-labeled_statement
- : identifier COLON statement {val[2].labels.unshift(PlainLabel.new_at(val[0].pos, val[0].val)); result = val[2]}
- | CASE constant_expression COLON statement {val[3].labels.unshift(Case .new_at(val[0].pos, val[1] )); result = val[3]}
- | DEFAULT COLON statement {val[2].labels.unshift(Default .new_at(val[0].pos )); result = val[2]}
- # type names can also be used as labels
- | typedef_name COLON statement {val[2].labels.unshift(PlainLabel.new_at(val[0].pos, val[0].name)); result = val[2]}
-
-# Returns Block
-compound_statement
- : LBRACE block_item_list RBRACE {result = Block.new_at(val[0].pos, val[1])}
- | LBRACE RBRACE {result = Block.new_at(val[0].pos )}
-
-# Returns NodeChain[Declaration|Statement]
-block_item_list
- : block_item {result = NodeChain[val[0]]}
- | block_item_list block_item {result = val[0] << val[1]}
-
-# Returns Declaration|Statement
-block_item
- : declaration {result = val[0]}
- | statement {result = val[0]}
-
-# Returns ExpressionStatement
-expression_statement
- : expression SEMICOLON {result = ExpressionStatement.new_at(val[0].pos, val[0])}
- | SEMICOLON {result = ExpressionStatement.new_at(val[0].pos )}
-
-# Returns Statement
-selection_statement
- : IF LPAREN expression RPAREN statement {result = If .new_at(val[0].pos, val[2], val[4] )}
- | IF LPAREN expression RPAREN statement ELSE statement {result = If .new_at(val[0].pos, val[2], val[4], val[6])}
- | SWITCH LPAREN expression RPAREN statement {result = Switch.new_at(val[0].pos, val[2], val[4] )}
-
-# Returns Statement
-iteration_statement
- : WHILE LPAREN expression RPAREN statement {result = While.new_at(val[0].pos, val[2], val[4] )}
- | DO statement WHILE LPAREN expression RPAREN SEMICOLON {result = While.new_at(val[0].pos, val[4], val[1], :do => true )}
- | FOR LPAREN expression SEMICOLON expression SEMICOLON expression RPAREN statement {result = For.new_at(val[0].pos, val[2], val[4], val[6], val[8])}
- | FOR LPAREN expression SEMICOLON expression SEMICOLON RPAREN statement {result = For.new_at(val[0].pos, val[2], val[4], nil , val[7])}
- | FOR LPAREN expression SEMICOLON SEMICOLON expression RPAREN statement {result = For.new_at(val[0].pos, val[2], nil , val[5], val[7])}
- | FOR LPAREN expression SEMICOLON SEMICOLON RPAREN statement {result = For.new_at(val[0].pos, val[2], nil , nil , val[6])}
- | FOR LPAREN SEMICOLON expression SEMICOLON expression RPAREN statement {result = For.new_at(val[0].pos, nil , val[3], val[5], val[7])}
- | FOR LPAREN SEMICOLON expression SEMICOLON RPAREN statement {result = For.new_at(val[0].pos, nil , val[3], nil , val[6])}
- | FOR LPAREN SEMICOLON SEMICOLON expression RPAREN statement {result = For.new_at(val[0].pos, nil , nil , val[4], val[6])}
- | FOR LPAREN SEMICOLON SEMICOLON RPAREN statement {result = For.new_at(val[0].pos, nil , nil , nil , val[5])}
- | FOR LPAREN declaration expression SEMICOLON expression RPAREN statement {result = For.new_at(val[0].pos, val[2], val[3], val[5], val[7])}
- | FOR LPAREN declaration expression SEMICOLON RPAREN statement {result = For.new_at(val[0].pos, val[2], val[3], nil , val[6])}
- | FOR LPAREN declaration SEMICOLON expression RPAREN statement {result = For.new_at(val[0].pos, val[2], nil , val[4], val[6])}
- | FOR LPAREN declaration SEMICOLON RPAREN statement {result = For.new_at(val[0].pos, val[2], nil , nil , val[5])}
-
-# Returns Statement
-jump_statement
- : GOTO identifier SEMICOLON {result = Goto .new_at(val[0].pos, val[1].val)}
- | CONTINUE SEMICOLON {result = Continue.new_at(val[0].pos )}
- | BREAK SEMICOLON {result = Break .new_at(val[0].pos )}
- | RETURN expression SEMICOLON {result = Return .new_at(val[0].pos, val[1] )}
- | RETURN SEMICOLON {result = Return .new_at(val[0].pos )}
- # type names can also be used as labels
- | GOTO typedef_name SEMICOLON {result = Goto .new_at(val[0].pos, val[1].name)}
-
-# A.2.2 Declarations
-
-# Returns Declaration
-declaration
- : declaration_specifiers init_declarator_list SEMICOLON {result = make_declaration(val[0][0], val[0][1], val[1])}
- | declaration_specifiers SEMICOLON {result = make_declaration(val[0][0], val[0][1], NodeArray[])}
-
-# Returns {Pos, [Symbol]}
-declaration_specifiers
- : storage_class_specifier declaration_specifiers {val[1][1] << val[0][1]; result = val[1]}
- | storage_class_specifier {result = [val[0][0], [val[0][1]]]}
- | type_specifier declaration_specifiers {val[1][1] << val[0][1]; result = val[1]}
- | type_specifier {result = [val[0][0], [val[0][1]]]}
- | type_qualifier declaration_specifiers {val[1][1] << val[0][1]; result = val[1]}
- | type_qualifier {result = [val[0][0], [val[0][1]]]}
- | function_specifier declaration_specifiers {val[1][1] << val[0][1]; result = val[1]}
- | function_specifier {result = [val[0][0], [val[0][1]]]}
-
-# Returns NodeArray[Declarator]
-init_declarator_list
- : init_declarator {result = NodeArray[val[0]]}
- | init_declarator_list COMMA init_declarator {result = val[0] << val[2]}
-
-# Returns Declarator
-init_declarator
- : declarator {result = val[0]}
- | declarator EQ initializer {val[0].init = val[2]; result = val[0]}
-
-# Returns [Pos, Symbol]
-storage_class_specifier
- : TYPEDEF {result = [val[0].pos, :typedef ]}
- | EXTERN {result = [val[0].pos, :extern ]}
- | STATIC {result = [val[0].pos, :static ]}
- | AUTO {result = [val[0].pos, :auto ]}
- | REGISTER {result = [val[0].pos, :register]}
-
-# Returns [Pos, Type|Symbol]
-type_specifier
- : VOID {result = [val[0].pos, :void ]}
- | CHAR {result = [val[0].pos, :char ]}
- | SHORT {result = [val[0].pos, :short ]}
- | INT {result = [val[0].pos, :int ]}
- | LONG {result = [val[0].pos, :long ]}
- | FLOAT {result = [val[0].pos, :float ]}
- | DOUBLE {result = [val[0].pos, :double ]}
- | SIGNED {result = [val[0].pos, :signed ]}
- | UNSIGNED {result = [val[0].pos, :unsigned ]}
- | BOOL {result = [val[0].pos, :_Bool ]}
- | COMPLEX {result = [val[0].pos, :_Complex ]}
- | IMAGINARY {result = [val[0].pos, :_Imaginary]}
- | struct_or_union_specifier {result = [val[0].pos, val[0] ]}
- | enum_specifier {result = [val[0].pos, val[0] ]}
- | typedef_name {result = [val[0].pos, val[0] ]}
-
-# Returns Struct|Union
-struct_or_union_specifier
- : struct_or_union identifier LBRACE struct_declaration_list RBRACE {result = val[0][1].new_at(val[0][0], val[1].val, val[3])}
- | struct_or_union LBRACE struct_declaration_list RBRACE {result = val[0][1].new_at(val[0][0], nil , val[2])}
- | struct_or_union identifier {result = val[0][1].new_at(val[0][0], val[1].val, nil )}
- # type names can also be used as struct identifiers
- | struct_or_union typedef_name LBRACE struct_declaration_list RBRACE {result = val[0][1].new_at(val[0][0], val[1].name, val[3])}
- | struct_or_union typedef_name {result = val[0][1].new_at(val[0][0], val[1].name, nil )}
-
-# Returns [Pos, Class]
-struct_or_union
- : STRUCT {result = [val[0].pos, Struct]}
- | UNION {result = [val[0].pos, Union ]}
-
-# Returns NodeArray[Declaration]
-struct_declaration_list
- : struct_declaration {result = NodeArray[val[0]]}
- | struct_declaration_list struct_declaration {val[0] << val[1]; result = val[0]}
-
-# Returns Declaration
-struct_declaration
- : specifier_qualifier_list struct_declarator_list SEMICOLON {result = make_declaration(val[0][0], val[0][1], val[1])}
-
-# Returns {Pos, [Symbol]}
-specifier_qualifier_list
- : type_specifier specifier_qualifier_list {val[1][1] << val[0][1]; result = val[1]}
- | type_specifier {result = [val[0][0], [val[0][1]]]}
- | type_qualifier specifier_qualifier_list {val[1][1] << val[0][1]; result = val[1]}
- | type_qualifier {result = [val[0][0], [val[0][1]]]}
-
-# Returns NodeArray[Declarator]
-struct_declarator_list
- : struct_declarator {result = NodeArray[val[0]]}
- | struct_declarator_list COMMA struct_declarator {result = val[0] << val[2]}
-
-# Returns Declarator
-struct_declarator
- : declarator {result = val[0]}
- | declarator COLON constant_expression {result = val[0]; val[0].num_bits = val[2]}
- | COLON constant_expression {result = Declarator.new_at(val[0].pos, :num_bits => val[1])}
-
-# Returns Enum
-enum_specifier
- : ENUM identifier LBRACE enumerator_list RBRACE {result = Enum.new_at(val[0].pos, val[1].val, val[3])}
- | ENUM LBRACE enumerator_list RBRACE {result = Enum.new_at(val[0].pos, nil , val[2])}
- | ENUM identifier LBRACE enumerator_list COMMA RBRACE {result = Enum.new_at(val[0].pos, val[1].val, val[3])}
- | ENUM LBRACE enumerator_list COMMA RBRACE {result = Enum.new_at(val[0].pos, nil , val[2])}
- | ENUM identifier {result = Enum.new_at(val[0].pos, val[1].val, nil )}
- # type names can also be used as enum names
- | ENUM typedef_name LBRACE enumerator_list RBRACE {result = Enum.new_at(val[0].pos, val[1].name, val[3])}
- | ENUM typedef_name LBRACE enumerator_list COMMA RBRACE {result = Enum.new_at(val[0].pos, val[1].name, val[3])}
- | ENUM typedef_name {result = Enum.new_at(val[0].pos, val[1].name, nil )}
-
-# Returns NodeArray[Enumerator]
-enumerator_list
- : enumerator {result = NodeArray[val[0]]}
- | enumerator_list COMMA enumerator {result = val[0] << val[2]}
-
-# Returns Enumerator
-enumerator
- : enumeration_constant {result = Enumerator.new_at(val[0].pos, val[0].val, nil )}
- | enumeration_constant EQ constant_expression {result = Enumerator.new_at(val[0].pos, val[0].val, val[2])}
-
-# Returns [Pos, Symbol]
-type_qualifier
- : CONST {result = [val[0].pos, :const ]}
- | RESTRICT {result = [val[0].pos, :restrict]}
- | VOLATILE {result = [val[0].pos, :volatile]}
-
-# Returns [Pos, Symbol]
-function_specifier
- : INLINE {result = [val[0].pos, :inline]}
-
-# Returns Declarator
-declarator
- : pointer direct_declarator {result = add_decl_type(val[1], val[0])}
- | direct_declarator {result = val[0]}
-
-# Returns Declarator
-direct_declarator
- : identifier {result = Declarator.new_at(val[0].pos, nil, val[0].val)}
- | LPAREN declarator RPAREN {result = val[1]}
- | direct_declarator LBRACKET type_qualifier_list assignment_expression RBRACKET {result = add_decl_type(val[0], Array.new_at(val[0].pos ))} # TODO
- | direct_declarator LBRACKET type_qualifier_list RBRACKET {result = add_decl_type(val[0], Array.new_at(val[0].pos ))} # TODO
- | direct_declarator LBRACKET assignment_expression RBRACKET {result = add_decl_type(val[0], Array.new_at(val[0].pos, nil, val[2]))}
- | direct_declarator LBRACKET RBRACKET {result = add_decl_type(val[0], Array.new_at(val[0].pos ))}
- | direct_declarator LBRACKET STATIC type_qualifier_list assignment_expression RBRACKET {result = add_decl_type(val[0], Array.new_at(val[0].pos ))} # TODO
- | direct_declarator LBRACKET STATIC assignment_expression RBRACKET {result = add_decl_type(val[0], Array.new_at(val[0].pos ))} # TODO
- | direct_declarator LBRACKET type_qualifier_list STATIC assignment_expression RBRACKET {result = add_decl_type(val[0], Array.new_at(val[0].pos ))} # TODO
- | direct_declarator LBRACKET type_qualifier_list MUL RBRACKET {result = add_decl_type(val[0], Array.new_at(val[0].pos ))} # TODO
- | direct_declarator LBRACKET MUL RBRACKET {result = add_decl_type(val[0], Array.new_at(val[0].pos ))} # TODO
- | direct_declarator LPAREN parameter_type_list RPAREN {result = add_decl_type(val[0], Function.new_at(val[0].pos, nil, param_list(*val[2]), :var_args => val[2][1]))}
- | direct_declarator LPAREN identifier_list RPAREN {result = add_decl_type(val[0], Function.new_at(val[0].pos, nil, val[2]))}
- | direct_declarator LPAREN RPAREN {result = add_decl_type(val[0], Function.new_at(val[0].pos ))}
-
-# Returns Pointer
-pointer
- : MUL type_qualifier_list {result = add_type_quals(Pointer.new_at(val[0].pos), val[1][1]) }
- | MUL {result = Pointer.new_at(val[0].pos) }
- | MUL type_qualifier_list pointer {p = add_type_quals(Pointer.new_at(val[0].pos), val[1][1]); val[2].direct_type = p; result = val[2]}
- | MUL pointer {p = Pointer.new_at(val[0].pos) ; val[1].direct_type = p; result = val[1]}
-
-# Returns {Pos, [Symbol]}
-type_qualifier_list
- : type_qualifier {result = [val[0][0], [val[0][1]]]}
- | type_qualifier_list type_qualifier {val[0][1] << val[1][1]; result = val[0]}
-
-# Returns [NodeArray[Parameter], var_args?]
-parameter_type_list
- : parameter_list {result = [val[0], false]}
- | parameter_list COMMA ELLIPSIS {result = [val[0], true ]}
-
-# Returns NodeArray[Parameter]
-parameter_list
- : parameter_declaration {result = NodeArray[val[0]]}
- | parameter_list COMMA parameter_declaration {result = val[0] << val[2]}
-
-# Returns Parameter
-parameter_declaration
- : declaration_specifiers declarator {ind_type = val[1].indirect_type and ind_type.detach
- result = make_parameter(val[0][0], val[0][1], ind_type, val[1].name)}
- | declaration_specifiers abstract_declarator {result = make_parameter(val[0][0], val[0][1], val[1] , nil )}
- | declaration_specifiers {result = make_parameter(val[0][0], val[0][1], nil , nil )}
-
-# Returns NodeArray[Parameter]
-identifier_list
- : identifier {result = NodeArray[Parameter.new_at(val[0].pos, nil, val[0].val)]}
- | identifier_list COMMA identifier {result = val[0] << Parameter.new_at(val[2].pos, nil, val[2].val)}
-
-# Returns Type
-type_name
- : specifier_qualifier_list abstract_declarator {val[1].direct_type = make_direct_type(val[0][0], val[0][1]); result = val[1]}
- | specifier_qualifier_list {result = make_direct_type(val[0][0], val[0][1]) }
-
-# Returns Type
-abstract_declarator
- : pointer {result = val[0]}
- | pointer direct_abstract_declarator {val[1].direct_type = val[0]; result = val[1]}
- | direct_abstract_declarator {result = val[0]}
-
-# Returns Type
-direct_abstract_declarator
- : LPAREN abstract_declarator RPAREN {result = val[1]}
- | direct_abstract_declarator LBRACKET assignment_expression RBRACKET {val[0].direct_type = Array.new_at(val[0].pos, nil, val[2]); result = val[0]}
- | direct_abstract_declarator LBRACKET RBRACKET {val[0].direct_type = Array.new_at(val[0].pos, nil, nil ); result = val[0]}
- | LBRACKET assignment_expression RBRACKET {result = Array.new_at(val[0].pos, nil, val[1])}
- | LBRACKET RBRACKET {result = Array.new_at(val[0].pos )}
- | direct_abstract_declarator LBRACKET MUL RBRACKET {val[0].direct_type = Array.new_at(val[0].pos); result = val[0]} # TODO
- | LBRACKET MUL RBRACKET {result = Array.new_at(val[0].pos)} # TODO
- | direct_abstract_declarator LPAREN parameter_type_list RPAREN {val[0].direct_type = Function.new_at(val[0].pos, nil, param_list(*val[2]), val[2][1]); result = val[0]}
- | direct_abstract_declarator LPAREN RPAREN {val[0].direct_type = Function.new_at(val[0].pos ); result = val[0]}
- | LPAREN parameter_type_list RPAREN {result = Function.new_at(val[0].pos, nil, param_list(*val[1]), val[1][1])}
- | LPAREN RPAREN {result = Function.new_at(val[0].pos )}
-
-# Returns CustomType
-typedef_name
- #: identifier -- insufficient since we must distinguish between type
- # names and var names (otherwise we have a conflict)
- : TYPENAME {result = CustomType.new_at(val[0].pos, val[0].val)}
-
-# Returns Expression
-initializer
- : assignment_expression {result = val[0]}
- | LBRACE initializer_list RBRACE {result = CompoundLiteral.new_at(val[0].pos, nil, val[1])}
- | LBRACE initializer_list COMMA RBRACE {result = CompoundLiteral.new_at(val[0].pos, nil, val[1])}
-
-# Returns NodeArray[MemberInit]
-initializer_list
- : designation initializer {result = NodeArray[MemberInit.new_at(val[0][0] , val[0][1], val[1])]}
- | initializer {result = NodeArray[MemberInit.new_at(val[0].pos, nil , val[0])]}
- | initializer_list COMMA designation initializer {result = val[0] << MemberInit.new_at(val[2][0] , val[2][1], val[3])}
- | initializer_list COMMA initializer {result = val[0] << MemberInit.new_at(val[2].pos, nil , val[2])}
-
-# Returns {Pos, NodeArray[Expression|Token]}
-designation
- : designator_list EQ {result = val[0]}
-
-# Returns {Pos, NodeArray[Expression|Token]}
-designator_list
- : designator {result = val[0]; val[0][1] = NodeArray[val[0][1]]}
- | designator_list designator {result = val[0]; val[0][1] << val[1][1]}
-
-# Returns {Pos, Expression|Member}
-designator
- : LBRACKET constant_expression RBRACKET {result = [val[1].pos, val[1] ]}
- | DOT identifier {result = [val[1].pos, Member.new_at(val[1].pos, val[1].val)]}
-
-# A.2.1 Expressions
-
-# Returns Expression
-primary_expression
- : identifier {result = Variable.new_at(val[0].pos, val[0].val)}
- | constant {result = val[0]}
- | string_literal {result = val[0]}
- # GCC EXTENSION: allow a compound statement in parentheses as an expression
- | LPAREN expression RPAREN {result = val[1]}
- | LPAREN compound_statement RPAREN {block_expressions_enabled? or parse_error val[0].pos, "compound statement found where expression expected"
- result = BlockExpression.new(val[1]); result.pos = val[0].pos}
-
-# Returns Expression
-postfix_expression
- : primary_expression {result = val[0]}
- | postfix_expression LBRACKET expression RBRACKET {result = Index .new_at(val[0].pos, val[0], val[2])}
- | postfix_expression LPAREN argument_expression_list RPAREN {result = Call .new_at(val[0].pos, val[0], val[2] )}
- | postfix_expression LPAREN RPAREN {result = Call .new_at(val[0].pos, val[0], NodeArray[])}
- | postfix_expression DOT identifier {result = Dot .new_at(val[0].pos, val[0], Member.new(val[2].val))}
- | postfix_expression ARROW identifier {result = Arrow .new_at(val[0].pos, val[0], Member.new(val[2].val))}
- | postfix_expression INC {result = PostInc .new_at(val[0].pos, val[0] )}
- | postfix_expression DEC {result = PostDec .new_at(val[0].pos, val[0] )}
- | LPAREN type_name RPAREN LBRACE initializer_list RBRACE {result = CompoundLiteral.new_at(val[0].pos, val[1], val[4])}
- | LPAREN type_name RPAREN LBRACE initializer_list COMMA RBRACE {result = CompoundLiteral.new_at(val[0].pos, val[1], val[4])}
-
-# Returns [Expression|Type]
-argument_expression_list
- : argument_expression {result = NodeArray[val[0]]}
- | argument_expression_list COMMA argument_expression {result = val[0] << val[2]}
-
-# Returns Expression|Type -- EXTENSION: allow type names here too, to support some standard library macros (e.g., va_arg [7.15.1.1])
-argument_expression
- : assignment_expression {result = val[0]}
- | type_name {result = val[0]}
-
-# Returns Expression
-unary_expression
- : postfix_expression {result = val[0]}
- | INC unary_expression {result = PreInc.new_at(val[0].pos, val[1])}
- | DEC unary_expression {result = PreDec.new_at(val[0].pos, val[1])}
- | unary_operator cast_expression {result = val[0][0].new_at(val[0][1], val[1])}
- | SIZEOF unary_expression {result = Sizeof.new_at(val[0].pos, val[1])}
- | SIZEOF LPAREN type_name RPAREN {result = Sizeof.new_at(val[0].pos, val[2])}
-
-# Returns [Class, Pos]
-unary_operator
- : AND {result = [Address , val[0].pos]}
- | MUL {result = [Dereference, val[0].pos]}
- | ADD {result = [Positive , val[0].pos]}
- | SUB {result = [Negative , val[0].pos]}
- | NOT {result = [BitNot , val[0].pos]}
- | BANG {result = [Not , val[0].pos]}
-
-# Returns Expression
-cast_expression
- : unary_expression {result = val[0]}
- | LPAREN type_name RPAREN cast_expression {result = Cast.new_at(val[0].pos, val[1], val[3])}
-
-# Returns Expression
-multiplicative_expression
- : cast_expression {result = val[0]}
- | multiplicative_expression MUL cast_expression {result = Multiply.new_at(val[0].pos, val[0], val[2])}
- | multiplicative_expression DIV cast_expression {result = Divide .new_at(val[0].pos, val[0], val[2])}
- | multiplicative_expression MOD cast_expression {result = Mod .new_at(val[0].pos, val[0], val[2])}
-
-# Returns Expression
-additive_expression
- : multiplicative_expression {result = val[0]}
- | additive_expression ADD multiplicative_expression {result = Add .new_at(val[0].pos, val[0], val[2])}
- | additive_expression SUB multiplicative_expression {result = Subtract.new_at(val[0].pos, val[0], val[2])}
-
-# Returns Expression
-shift_expression
- : additive_expression {result = val[0]}
- | shift_expression LSHIFT additive_expression {result = ShiftLeft .new_at(val[0].pos, val[0], val[2])}
- | shift_expression RSHIFT additive_expression {result = ShiftRight.new_at(val[0].pos, val[0], val[2])}
-
-# Returns Expression
-relational_expression
- : shift_expression {result = val[0]}
- | relational_expression LT shift_expression {result = Less.new_at(val[0].pos, val[0], val[2])}
- | relational_expression GT shift_expression {result = More.new_at(val[0].pos, val[0], val[2])}
- | relational_expression LEQ shift_expression {result = LessOrEqual.new_at(val[0].pos, val[0], val[2])}
- | relational_expression GEQ shift_expression {result = MoreOrEqual.new_at(val[0].pos, val[0], val[2])}
-
-# Returns Expression
-equality_expression
- : relational_expression {result = val[0]}
- | equality_expression EQEQ relational_expression {result = Equal .new_at(val[0].pos, val[0], val[2])}
- | equality_expression NEQ relational_expression {result = NotEqual.new_at(val[0].pos, val[0], val[2])}
-
-# Returns Expression
-and_expression
- : equality_expression {result = val[0]}
- | and_expression AND equality_expression {result = BitAnd.new_at(val[0].pos, val[0], val[2])}
-
-# Returns Expression
-exclusive_or_expression
- : and_expression {result = val[0]}
- | exclusive_or_expression XOR and_expression {result = BitXor.new_at(val[0].pos, val[0], val[2])}
-
-# Returns Expression
-inclusive_or_expression
- : exclusive_or_expression {result = val[0]}
- | inclusive_or_expression OR exclusive_or_expression {result = BitOr.new_at(val[0].pos, val[0], val[2])}
-
-# Returns Expression
-logical_and_expression
- : inclusive_or_expression {result = val[0]}
- | logical_and_expression ANDAND inclusive_or_expression {result = And.new_at(val[0].pos, val[0], val[2])}
-
-# Returns Expression
-logical_or_expression
- : logical_and_expression {result = val[0]}
- | logical_or_expression OROR logical_and_expression {result = Or.new_at(val[0].pos, val[0], val[2])}
-
-# Returns Expression
-conditional_expression
- : logical_or_expression {result = val[0]}
- | logical_or_expression QUESTION expression COLON conditional_expression {result = Conditional.new_at(val[0].pos, val[0], val[2], val[4])}
-
-# Returns Expression
-assignment_expression
- : conditional_expression {result = val[0]}
- | unary_expression assignment_operator assignment_expression {result = val[1].new_at(val[0].pos, val[0], val[2])}
-
-# Returns Class
-assignment_operator
- : EQ {result = Assign}
- | MULEQ {result = MultiplyAssign}
- | DIVEQ {result = DivideAssign}
- | MODEQ {result = ModAssign}
- | ADDEQ {result = AddAssign}
- | SUBEQ {result = SubtractAssign}
- | LSHIFTEQ {result = ShiftLeftAssign}
- | RSHIFTEQ {result = ShiftRightAssign}
- | ANDEQ {result = BitAndAssign}
- | XOREQ {result = BitXorAssign}
- | OREQ {result = BitOrAssign}
-
-# Returns Expression
-expression
- : assignment_expression {result = val[0]}
- | expression COMMA assignment_expression {
- if val[0].is_a? Comma
- if val[2].is_a? Comma
- val[0].exprs.push(*val[2].exprs)
- else
- val[0].exprs << val[2]
- end
- result = val[0]
- else
- if val[2].is_a? Comma
- val[2].exprs.unshift(val[0])
- val[2].pos = val[0].pos
- result = val[2]
- else
- result = Comma.new_at(val[0].pos, NodeArray[val[0], val[2]])
- end
- end
- }
-
-# Returns Expression
-constant_expression
- : conditional_expression {result = val[0]}
-
-# A.1.1 -- Lexical elements
-#
-# token
-# : keyword (raw string)
-# | identifier expanded below
-# | constant expanded below
-# | string_literal expanded below
-# | punctuator (raw string)
-#
-# preprocessing-token (skip)
-
-# Returns Token
-identifier
- : ID {result = val[0]}
-
-# Returns Literal
-constant
- : ICON {result = val[0].val; result.pos = val[0].pos}
- | FCON {result = val[0].val; result.pos = val[0].pos}
- #| enumeration_constant -- these are parsed as identifiers at all
- # places the `constant' nonterminal appears
- | CCON {result = val[0].val; result.pos = val[0].pos}
-
-# Returns Token
-enumeration_constant
- : ID {result = val[0]}
-
-# Returns StringLiteral
-# Also handles string literal concatenation (6.4.5.4)
-string_literal
- : string_literal SCON {val[0].val << val[1].val.val; result = val[0]}
- | SCON { result = val[0].val; result.pos = val[0].pos }
-
----- inner
- # A.1.9 -- Preprocessing numbers -- skip
- # A.1.8 -- Header names -- skip
-
- # A.1.7 -- Puncuators -- we don't bother with {##,#,%:,%:%:} since
- # we don't do preprocessing
- @@punctuators = %r'\+\+|-[->]|&&|\|\||\.\.\.|(?:<<|>>|[<>=!*/%+\-&^|])=?|[\[\](){}.~?:;,]'
- @@digraphs = %r'<[:%]|[:%]>'
-
- # A.1.6 -- String Literals -- simple for us because we don't decode
- # the string (and indeed accept some illegal strings)
- @@string_literal = %r'L?"(?:[^\\]|\\.)*?"'m
-
- # A.1.5 -- Constants
- @@decimal_floating_constant = %r'(?:(?:\d*\.\d+|\d+\.)(?:e[-+]?\d+)?|\d+e[-+]?\d+)[fl]?'i
- @@hexadecimal_floating_constant = %r'0x(?:(?:[0-9a-f]*\.[0-9a-f]+|[0-9a-f]+\.)|[0-9a-f]+)p[-+]?\d+[fl]?'i
-
- @@integer_constant = %r'(?:[1-9][0-9]*|0x[0-9a-f]+|0[0-7]*)(?:ul?l?|ll?u?)?'i
- @@floating_constant = %r'#{@@decimal_floating_constant}|#{@@hexadecimal_floating_constant}'
- @@enumeration_constant = %r'[a-zA-Z_\\][a-zA-Z_\\0-9]*'
- @@character_constant = %r"L?'(?:[^\\]|\\.)+?'"
- # (note that as with string-literals, we accept some illegal
- # character-constants)
-
- # A.1.4 -- Universal character names -- skip
-
- # A.1.3 -- Identifiers -- skip, since an identifier is lexically
- # identical to an enumeration constant
-
- # A.1.2 Keywords
- keywords = %w'auto break case char const continue default do
-double else enum extern float for goto if inline int long register
-restrict return short signed sizeof static struct switch typedef union
- unsigned void volatile while _Bool _Complex _Imaginary'
- @@keywords = %r"#{keywords.join('|')}"
-
- def initialize
- @type_names = ::Set.new
-
- @warning_proc = lambda{}
- @pos = C::Node::Pos.new(nil, 1, 0)
- end
- def initialize_copy(x)
- @pos = x.pos.dup
- @type_names = x.type_names.dup
- end
- attr_accessor :pos, :type_names
-
- def parse(str)
- if str.respond_to? :read
- str = str.read
- end
- @str = str
- begin
- prepare_lexer(str)
- return do_parse
- rescue ParseError => e
- e.set_backtrace(caller)
- raise
- end
- end
-
- #
- # Error handler, as used by racc.
- #
- def on_error(error_token_id, error_value, value_stack)
- if error_value == '$'
- parse_error @pos, "unexpected EOF"
- else
- parse_error(error_value.pos,
- "parse error on #{token_to_str(error_token_id)} (#{error_value.val})")
- end
- end
-
- def self.feature(name)
- attr_writer "#{name}_enabled"
- class_eval <<-EOS
- def enable_#{name}
- @#{name}_enabled = true
- end
- def #{name}_enabled?
- @#{name}_enabled
- end
- EOS
- end
- private_class_method :feature
-
- #
- # Allow blocks in parentheses as expressions, as per the gcc
- # extension. [http://rubyurl.com/iB7]
- #
- feature :block_expressions
-
- private # ---------------------------------------------------------
-
- class Token
- attr_accessor :pos, :val
- def initialize(pos, val)
- @pos = pos
- @val = val
- end
- end
- def eat(str)
- lines = str.split(/\r\n|[\r\n]/, -1)
- if lines.length == 1
- @pos.col_num += lines[0].length
- else
- @pos.line_num += lines.length - 1
- @pos.col_num = lines[-1].length
- end
- end
-
- #
- # Make a Declaration from the given specs and declarators.
- #
- def make_declaration(pos, specs, declarators)
- specs.all?{|x| x.is_a?(Symbol) || x.is_a?(Type)} or raise specs.map{|x| x.class}.inspect
- decl = Declaration.new_at(pos, nil, declarators)
-
- # set storage class
- storage_classes = specs.find_all do |x|
- [:typedef, :extern, :static, :auto, :register].include? x
- end
- # 6.7.1p2: at most, one storage-class specifier may be given in
- # the declaration specifiers in a declaration
- storage_classes.length <= 1 or
- begin
- if declarators.length == 0
- for_name = ''
- else
- for_name = "for `#{declarators[0].name}'"
- end
- parse_error pos, "multiple or duplicate storage classes given #{for_name}'"
- end
- decl.storage = storage_classes[0]
-
- # set type (specifiers, qualifiers)
- decl.type = make_direct_type(pos, specs)
-
- # set function specifiers
- decl.inline = specs.include?(:inline)
-
- # look for new type names
- if decl.typedef?
- decl.declarators.each do |d|
- if d.name
- @type_names << d.name
- end
- end
- end
-
- return decl
- end
-
- def make_function_def(pos, specs, func_declarator, decl_list, defn)
- add_decl_type(func_declarator, make_direct_type(pos, specs))
-
- # get types from decl_list if necessary
- function = func_declarator.indirect_type
- function.is_a? Function or
- parse_error pos, "non function type for function `#{func_declarator.name}'"
- params = function.params
- if decl_list
- params.all?{|p| p.type.nil?} or
- parse_error pos, "both prototype and declaration list given for `#{func_declarator.name}'"
- decl_list.each do |declaration|
- declaration.declarators.each do |declarator|
- param = params.find{|p| p.name == declarator.name} or
- parse_error pos, "no parameter named #{declarator.name}"
- if declarator.indirect_type
- param.type = declarator.indirect_type
- param.type.direct_type = declaration.type.dup
- else
- param.type = declaration.type.dup
- end
- end
- end
- params.all?{|p| p.type} or
- begin
- s = params.find_all{|p| p.type.nil?}.map{|p| "`#{p.name}'"}.join(' and ')
- parse_error pos, "types missing for parameters #{s}"
- end
- end
-
- fd = FunctionDef.new_at(pos,
- function.detach,
- func_declarator.name,
- defn,
- :no_prototype => !decl_list.nil?)
-
- # set storage class
- # 6.9.1p4: only extern or static allowed
- specs.each do |s|
- [:typedef, :auto, :register].include?(s) and
- "`#{s}' illegal for function"
- end
- storage_classes = specs.find_all do |s|
- s == :extern || s == :static
- end
- # 6.7.1p2: at most, one storage-class specifier may be given in
- # the declaration specifiers in a declaration
- storage_classes.length <= 1 or
- "multiple or duplicate storage classes given for `#{func_declarator.name}'"
- fd.storage = storage_classes[0] if storage_classes[0]
-
- # set function specifiers
- # 6.7.4p5 'inline' can be repeated
- fd.inline = specs.include?(:inline)
-
- return fd
- end
-
- #
- # Make a direct type from the list of type specifiers and type
- # qualifiers.
- #
- def make_direct_type(pos, specs)
- specs_order = [:signed, :unsigned, :short, :long, :double, :void,
- :char, :int, :float, :_Bool, :_Complex, :_Imaginary]
-
- type_specs = specs.find_all do |x|
- specs_order.include?(x) || !x.is_a?(Symbol)
- end
- type_specs.sort! do |a, b|
- (specs_order.index(a)||100) <=> (specs_order.index(b)||100)
- end
-
- # set type specifiers
- # 6.7.2p2: the specifier list should be one of these
- type =
- case type_specs
- when [:void]
- Void.new
- when [:char]
- Char.new
- when [:signed, :char]
- Char.new :signed => true
- when [:unsigned, :char]
- Char.new :signed => false
- when [:short], [:signed, :short], [:short, :int],
- [:signed, :short, :int]
- Int.new :longness => -1
- when [:unsigned, :short], [:unsigned, :short, :int]
- Int.new :unsigned => true, :longness => -1
- when [:int], [:signed], [:signed, :int]
- Int.new
- when [:unsigned], [:unsigned, :int]
- Int.new :unsigned => true
- when [:long], [:signed, :long], [:long, :int],
- [:signed, :long, :int]
- Int.new :longness => 1
- when [:unsigned, :long], [:unsigned, :long, :int]
- Int.new :longness => 1, :unsigned => true
- when [:long, :long], [:signed, :long, :long],
- [:long, :long, :int], [:signed, :long, :long, :int]
- Int.new :longness => 2
- when [:unsigned, :long, :long], [:unsigned, :long, :long, :int]
- Int.new :longness => 2, :unsigned => true
- when [:float]
- Float.new
- when [:double]
- Float.new :longness => 1
- when [:long, :double]
- Float.new :longness => 2
- when [:_Bool]
- Bool.new
- when [:float, :_Complex]
- Complex.new
- when [:double, :_Complex]
- Complex.new :longness => 1
- when [:long, :double, :_Complex]
- Complex.new :longness => 2
- when [:float, :_Imaginary]
- Imaginary.new
- when [:double, :_Imaginary]
- Imaginary.new :longness => 1
- when [:long, :double, :_Imaginary]
- Imaginary.new :longness => 2
- else
- if type_specs.length == 1 &&
- [CustomType, Struct, Union, Enum].any?{|c| type_specs[0].is_a? c}
- type_specs[0]
- else
- if type_specs == []
- parse_error pos, "no type specifiers given"
- else
- parse_error pos, "invalid type specifier combination: #{type_specs.join(' ')}"
- end
- end
- end
- type.pos ||= pos
-
- # set type qualifiers
- # 6.7.3p4: type qualifiers can be repeated
- type.const = specs.any?{|x| x.equal? :const }
- type.restrict = specs.any?{|x| x.equal? :restrict}
- type.volatile = specs.any?{|x| x.equal? :volatile}
-
- return type
- end
-
- def make_parameter(pos, specs, indirect_type, name)
- type = indirect_type
- if type
- type.direct_type = make_direct_type(pos, specs)
- else
- type = make_direct_type(pos, specs)
- end
- [:typedef, :extern, :static, :auto, :inline].each do |sym|
- specs.include? sym and
- parse_error pos, "parameter `#{declarator.name}' declared `#{sym}'"
- end
- return Parameter.new_at(pos, type, name,
- :register => specs.include?(:register))
- end
-
- def add_type_quals(type, quals)
- type.const = quals.include?(:const )
- type.restrict = quals.include?(:restrict)
- type.volatile = quals.include?(:volatile)
- return type
- end
-
- #
- # Add te given type as the "most direct" type to the given
- # declarator. Return the declarator.
- #
- def add_decl_type(declarator, type)
- if declarator.indirect_type
- declarator.indirect_type.direct_type = type
- else
- declarator.indirect_type = type
- end
- return declarator
- end
-
- def param_list(params, var_args)
- if params.length == 1 &&
- params[0].type.is_a?(Void) &&
- params[0].name.nil?
- return NodeArray[]
- elsif params.empty?
- return nil
- else
- return params
- end
- end
-
- def parse_error(pos, str)
- raise ParseError, "#{pos}: #{str}"
- end
-
----- header
-
-require 'set'
-
-# Error classes
-module C
- class ParseError < StandardError; end
-end
-
-# Local variables:
-# mode: ruby
-# end:
diff --git a/test/racc/assets/chk.y b/test/racc/assets/chk.y
deleted file mode 100644
index 7e0ee20f1e..0000000000
--- a/test/racc/assets/chk.y
+++ /dev/null
@@ -1,126 +0,0 @@
-#
-# racc tester
-#
-
-class Calcp
-
- prechigh
- left '*' '/'
- left '+' '-'
- preclow
-
- convert
- NUMBER 'Number'
- end
-
-rule
-
- target : exp | /* none */ { result = 0 } ;
-
- exp : exp '+' exp { result += val[2]; @plus = 'plus' }
- | exp '-' exp { result -= val[2]; @str = "string test" }
- | exp '*' exp { result *= val[2] }
- | exp '/' exp { result /= val[2] }
- | '(' { $emb = true } exp ')'
- {
- raise 'must not happen' unless $emb
- result = val[2]
- }
- | '-' NUMBER { result = -val[1] }
- | NUMBER
- ;
-
-end
-
-----header
-
-class Number; end
-
-----inner
-
- def parse( src )
- $emb = false
- @plus = nil
- @str = nil
- @src = src
- result = do_parse
- if @plus
- raise 'string parse failed' unless @plus == 'plus'
- end
- if @str
- raise 'string parse failed' unless @str == 'string test'
- end
- result
- end
-
- def next_token
- @src.shift
- end
-
- def initialize
- @yydebug = true
- end
-
-----footer
-
-$parser = Calcp.new
-$test_number = 1
-
-def chk( src, ans )
- result = $parser.parse(src)
- raise "test #{$test_number} fail" unless result == ans
- $test_number += 1
-end
-
-chk(
- [ [Number, 9],
- [false, false],
- [false, false] ], 9
-)
-
-chk(
- [ [Number, 5],
- ['*', nil],
- [Number, 1],
- ['-', nil],
- [Number, 1],
- ['*', nil],
- [Number, 8],
- [false, false],
- [false, false] ], -3
-)
-
-chk(
- [ [Number, 5],
- ['+', nil],
- [Number, 2],
- ['-', nil],
- [Number, 5],
- ['+', nil],
- [Number, 2],
- ['-', nil],
- [Number, 5],
- [false, false],
- [false, false] ], -1
-)
-
-chk(
- [ ['-', nil],
- [Number, 4],
- [false, false],
- [false, false] ], -4
-)
-
-chk(
- [ [Number, 7],
- ['*', nil],
- ['(', nil],
- [Number, 4],
- ['+', nil],
- [Number, 3],
- [')', nil],
- ['-', nil],
- [Number, 9],
- [false, false],
- [false, false] ], 40
-)
diff --git a/test/racc/assets/conf.y b/test/racc/assets/conf.y
deleted file mode 100644
index de9de71d28..0000000000
--- a/test/racc/assets/conf.y
+++ /dev/null
@@ -1,16 +0,0 @@
-
-class A
-rule
-
-a: A c C expr;
-
-b: A B; # useless
-
-c: A;
-c: A;
-
-expr: expr '+' expr
-expr: expr '-' expr
-expr: NUMBER
-
-end
diff --git a/test/racc/assets/csspool.y b/test/racc/assets/csspool.y
deleted file mode 100644
index 3d6af25d85..0000000000
--- a/test/racc/assets/csspool.y
+++ /dev/null
@@ -1,729 +0,0 @@
-class CSSPool::CSS::Parser
-
-token CHARSET_SYM IMPORT_SYM STRING SEMI IDENT S COMMA LBRACE RBRACE STAR HASH
-token LSQUARE RSQUARE EQUAL INCLUDES DASHMATCH LPAREN RPAREN FUNCTION GREATER PLUS
-token SLASH NUMBER MINUS LENGTH PERCENTAGE ANGLE TIME FREQ URI
-token IMPORTANT_SYM MEDIA_SYM NOT ONLY AND NTH_PSEUDO_CLASS
-token DOCUMENT_QUERY_SYM FUNCTION_NO_QUOTE
-token TILDE
-token PREFIXMATCH SUFFIXMATCH SUBSTRINGMATCH
-token NOT_PSEUDO_CLASS
-token KEYFRAMES_SYM
-token MATCHES_PSEUDO_CLASS
-token NAMESPACE_SYM
-token MOZ_PSEUDO_ELEMENT
-token RESOLUTION
-token COLON
-token SUPPORTS_SYM
-token OR
-token VARIABLE_NAME
-token CALC_SYM
-token FONTFACE_SYM
-token UNICODE_RANGE
-token RATIO
-
-rule
- document
- : { @handler.start_document }
- stylesheet
- { @handler.end_document }
- ;
- stylesheet
- : charset stylesheet
- | import stylesheet
- | namespace stylesheet
- | charset
- | import
- | namespace
- | body
- |
- ;
- charset
- : CHARSET_SYM STRING SEMI { @handler.charset interpret_string(val[1]), {} }
- ;
- import
- : IMPORT_SYM import_location medium SEMI {
- @handler.import_style val[2], val[1]
- }
- | IMPORT_SYM import_location SEMI {
- @handler.import_style [], val[1]
- }
- ;
- import_location
- : import_location S
- | STRING { result = Terms::String.new interpret_string val.first }
- | URI { result = Terms::URI.new interpret_uri val.first }
- ;
- namespace
- : NAMESPACE_SYM ident import_location SEMI {
- @handler.namespace val[1], val[2]
- }
- | NAMESPACE_SYM import_location SEMI {
- @handler.namespace nil, val[1]
- }
- ;
- medium
- : medium COMMA IDENT {
- result = val[0] << MediaType.new(val[2])
- }
- | IDENT {
- result = [MediaType.new(val[0])]
- }
- ;
- media_query_list
- : media_query { result = MediaQueryList.new([ val[0] ]) }
- | media_query_list COMMA media_query { result = val[0] << val[2] }
- | { result = MediaQueryList.new }
- ;
- media_query
- : optional_only_or_not media_type optional_and_exprs { result = MediaQuery.new(val[0], val[1], val[2]) }
- | media_expr optional_and_exprs { result = MediaQuery.new(nil, val[0], val[1]) }
- ;
- optional_only_or_not
- : ONLY { result = :only }
- | NOT { result = :not }
- | { result = nil }
- ;
- media_type
- : IDENT { result = MediaType.new(val[0]) }
- ;
- media_expr
- : LPAREN optional_space IDENT optional_space RPAREN { result = MediaType.new(val[2]) }
- | LPAREN optional_space IDENT optional_space COLON optional_space expr RPAREN { result = MediaFeature.new(val[2], val[6][0]) }
- ;
- optional_space
- : S { result = val[0] }
- | { result = nil }
- ;
- optional_and_exprs
- : optional_and_exprs AND media_expr { result = val[0] << val[2] }
- | { result = [] }
- ;
- resolution
- : RESOLUTION {
- unit = val.first.gsub(/[\s\d.]/, '')
- number = numeric(val.first)
- result = Terms::Resolution.new(number, unit)
- }
- ;
- body
- : ruleset body
- | conditional_rule body
- | keyframes_rule body
- | fontface_rule body
- | ruleset
- | conditional_rule
- | keyframes_rule
- | fontface_rule
- ;
- conditional_rule
- : media
- | document_query
- | supports
- ;
- body_in_media
- : body
- | empty_ruleset
- ;
- media
- : start_media body_in_media RBRACE { @handler.end_media val.first }
- ;
- start_media
- : MEDIA_SYM media_query_list LBRACE {
- result = val[1]
- @handler.start_media result
- }
- ;
- document_query
- : start_document_query body RBRACE { @handler.end_document_query(before_pos(val), after_pos(val)) }
- | start_document_query RBRACE { @handler.end_document_query(before_pos(val), after_pos(val)) }
- ;
- start_document_query
- : start_document_query_pos url_match_fns LBRACE {
- @handler.start_document_query(val[1], after_pos(val))
- }
- ;
- start_document_query_pos
- : DOCUMENT_QUERY_SYM {
- @handler.node_start_pos = before_pos(val)
- }
- ;
- url_match_fns
- : url_match_fn COMMA url_match_fns {
- result = [val[0], val[2]].flatten
- }
- | url_match_fn {
- result = val
- }
- ;
- url_match_fn
- : function_no_quote
- | function
- | uri
- ;
- supports
- : start_supports body RBRACE { @handler.end_supports }
- | start_supports RBRACE { @handler.end_supports }
- ;
- start_supports
- : SUPPORTS_SYM supports_condition_root LBRACE {
- @handler.start_supports val[1]
- }
- ;
- supports_condition_root
- : supports_negation { result = val.join('') }
- | supports_conjunction_or_disjunction { result = val.join('') }
- | supports_condition_in_parens { result = val.join('') }
- ;
- supports_condition
- : supports_negation { result = val.join('') }
- | supports_conjunction_or_disjunction { result = val.join('') }
- | supports_condition_in_parens { result = val.join('') }
- ;
- supports_condition_in_parens
- : LPAREN supports_condition RPAREN { result = val.join('') }
- | supports_declaration_condition { result = val.join('') }
- ;
- supports_negation
- : NOT supports_condition_in_parens { result = val.join('') }
- ;
- supports_conjunction_or_disjunction
- : supports_conjunction
- | supports_disjunction
- ;
- supports_conjunction
- : supports_condition_in_parens AND supports_condition_in_parens { result = val.join('') }
- | supports_conjunction_or_disjunction AND supports_condition_in_parens { result = val.join('') }
- ;
- supports_disjunction
- : supports_condition_in_parens OR supports_condition_in_parens { result = val.join('') }
- | supports_conjunction_or_disjunction OR supports_condition_in_parens { result = val.join('') }
- ;
- supports_declaration_condition
- : LPAREN declaration_internal RPAREN { result = val.join('') }
- | LPAREN S declaration_internal RPAREN { result = val.join('') }
- ;
- keyframes_rule
- : start_keyframes_rule keyframes_blocks RBRACE
- | start_keyframes_rule RBRACE
- ;
- start_keyframes_rule
- : KEYFRAMES_SYM IDENT LBRACE {
- @handler.start_keyframes_rule val[1]
- }
- ;
- keyframes_blocks
- : keyframes_block keyframes_blocks
- | keyframes_block
- ;
- keyframes_block
- : start_keyframes_block declarations RBRACE { @handler.end_keyframes_block }
- | start_keyframes_block RBRACE { @handler.end_keyframes_block }
- ;
- start_keyframes_block
- : keyframes_selectors LBRACE {
- @handler.start_keyframes_block val[0]
- }
- ;
- keyframes_selectors
- | keyframes_selector COMMA keyframes_selectors {
- result = val[0] + ', ' + val[2]
- }
- | keyframes_selector
- ;
- keyframes_selector
- : IDENT
- | PERCENTAGE { result = val[0].strip }
- ;
- fontface_rule
- : start_fontface_rule declarations RBRACE { @handler.end_fontface_rule }
- | start_fontface_rule RBRACE { @handler.end_fontface_rule }
- ;
- start_fontface_rule
- : FONTFACE_SYM LBRACE {
- @handler.start_fontface_rule
- }
- ;
- ruleset
- : start_selector declarations RBRACE {
- @handler.end_selector val.first
- }
- | start_selector RBRACE {
- @handler.end_selector val.first
- }
- ;
- empty_ruleset
- : optional_space {
- start = @handler.start_selector([])
- @handler.end_selector(start)
- }
- ;
- start_selector
- : S start_selector { result = val.last }
- | selectors LBRACE {
- @handler.start_selector val.first
- }
- ;
- selectors
- : selector COMMA selectors
- {
- sel = Selector.new(val.first, {})
- result = [sel].concat(val[2])
- }
- | selector
- {
- result = [Selector.new(val.first, {})]
- }
- ;
- selector
- : simple_selector combinator selector
- {
- val.flatten!
- val[2].combinator = val.delete_at 1
- result = val
- }
- | simple_selector
- ;
- combinator
- : S { result = :s }
- | GREATER { result = :> }
- | PLUS { result = :+ }
- | TILDE { result = :~ }
- ;
- simple_selector
- : element_name hcap {
- selector = val.first
- selector.additional_selectors = val.last
- result = [selector]
- }
- | element_name { result = val }
- | hcap
- {
- ss = Selectors::Simple.new nil, nil
- ss.additional_selectors = val.flatten
- result = [ss]
- }
- ;
- simple_selectors
- : simple_selector COMMA simple_selectors { result = [val[0], val[2]].flatten }
- | simple_selector
- ;
- ident_with_namespace
- : IDENT { result = [interpret_identifier(val[0]), nil] }
- | IDENT '|' IDENT { result = [interpret_identifier(val[2]), interpret_identifier(val[0])] }
- | '|' IDENT { result = [interpret_identifier(val[1]), nil] }
- | STAR '|' IDENT { result = [interpret_identifier(val[2]), '*'] }
- ;
- element_name
- : ident_with_namespace { result = Selectors::Type.new val.first[0], nil, val.first[1] }
- | STAR { result = Selectors::Universal.new val.first }
- | '|' STAR { result = Selectors::Universal.new val[1] }
- | STAR '|' STAR { result = Selectors::Universal.new val[2], nil, val[0] }
- | IDENT '|' STAR { result = Selectors::Universal.new val[2], nil, interpret_identifier(val[0]) }
- ;
- hcap
- : hash { result = val }
- | class { result = val }
- | attrib { result = val }
- | pseudo { result = val }
- | hash hcap { result = val.flatten }
- | class hcap { result = val.flatten }
- | attrib hcap { result = val.flatten }
- | pseudo hcap { result = val.flatten }
- ;
- hash
- : HASH {
- result = Selectors::Id.new interpret_identifier val.first.sub(/^#/, '')
- }
- class
- : '.' IDENT {
- result = Selectors::Class.new interpret_identifier val.last
- }
- ;
- attrib
- : LSQUARE ident_with_namespace EQUAL IDENT RSQUARE {
- result = Selectors::Attribute.new(
- val[1][0],
- interpret_identifier(val[3]),
- Selectors::Attribute::EQUALS,
- val[1][1]
- )
- }
- | LSQUARE ident_with_namespace EQUAL STRING RSQUARE {
- result = Selectors::Attribute.new(
- val[1][0],
- interpret_string(val[3]),
- Selectors::Attribute::EQUALS,
- val[1][1]
- )
- }
- | LSQUARE ident_with_namespace INCLUDES STRING RSQUARE {
- result = Selectors::Attribute.new(
- val[1][0],
- interpret_string(val[3]),
- Selectors::Attribute::INCLUDES,
- val[1][1]
- )
- }
- | LSQUARE ident_with_namespace INCLUDES IDENT RSQUARE {
- result = Selectors::Attribute.new(
- val[1][0],
- interpret_identifier(val[3]),
- Selectors::Attribute::INCLUDES,
- val[1][1]
- )
- }
- | LSQUARE ident_with_namespace DASHMATCH IDENT RSQUARE {
- result = Selectors::Attribute.new(
- val[1][0],
- interpret_identifier(val[3]),
- Selectors::Attribute::DASHMATCH,
- val[1][1]
- )
- }
- | LSQUARE ident_with_namespace DASHMATCH STRING RSQUARE {
- result = Selectors::Attribute.new(
- val[1][0],
- interpret_string(val[3]),
- Selectors::Attribute::DASHMATCH,
- val[1][1]
- )
- }
- | LSQUARE ident_with_namespace PREFIXMATCH IDENT RSQUARE {
- result = Selectors::Attribute.new(
- val[1][0],
- interpret_identifier(val[3]),
- Selectors::Attribute::PREFIXMATCH,
- val[1][1]
- )
- }
- | LSQUARE ident_with_namespace PREFIXMATCH STRING RSQUARE {
- result = Selectors::Attribute.new(
- val[1][0],
- interpret_string(val[3]),
- Selectors::Attribute::PREFIXMATCH,
- val[1][1]
- )
- }
- | LSQUARE ident_with_namespace SUFFIXMATCH IDENT RSQUARE {
- result = Selectors::Attribute.new(
- val[1][0],
- interpret_identifier(val[3]),
- Selectors::Attribute::SUFFIXMATCH,
- val[1][1]
- )
- }
- | LSQUARE ident_with_namespace SUFFIXMATCH STRING RSQUARE {
- result = Selectors::Attribute.new(
- val[1][0],
- interpret_string(val[3]),
- Selectors::Attribute::SUFFIXMATCH,
- val[1][1]
- )
- }
- | LSQUARE ident_with_namespace SUBSTRINGMATCH IDENT RSQUARE {
- result = Selectors::Attribute.new(
- val[1][0],
- interpret_identifier(val[3]),
- Selectors::Attribute::SUBSTRINGMATCH,
- val[1][1]
- )
- }
- | LSQUARE ident_with_namespace SUBSTRINGMATCH STRING RSQUARE {
- result = Selectors::Attribute.new(
- val[1][0],
- interpret_string(val[3]),
- Selectors::Attribute::SUBSTRINGMATCH,
- val[1][1]
- )
- }
- | LSQUARE ident_with_namespace RSQUARE {
- result = Selectors::Attribute.new(
- val[1][0],
- nil,
- Selectors::Attribute::SET,
- val[1][1]
- )
- }
- ;
- pseudo
- : COLON IDENT {
- result = Selectors::pseudo interpret_identifier(val[1])
- }
- | COLON COLON IDENT {
- result = Selectors::PseudoElement.new(
- interpret_identifier(val[2])
- )
- }
- | COLON FUNCTION RPAREN {
- result = Selectors::PseudoClass.new(
- interpret_identifier(val[1].sub(/\($/, '')),
- ''
- )
- }
- | COLON FUNCTION IDENT RPAREN {
- result = Selectors::PseudoClass.new(
- interpret_identifier(val[1].sub(/\($/, '')),
- interpret_identifier(val[2])
- )
- }
- | COLON NOT_PSEUDO_CLASS simple_selector RPAREN {
- result = Selectors::PseudoClass.new(
- 'not',
- val[2].first.to_s
- )
- }
- | COLON NTH_PSEUDO_CLASS {
- result = Selectors::PseudoClass.new(
- interpret_identifier(val[1].sub(/\(.*/, '')),
- interpret_identifier(val[1].sub(/.*\(/, '').sub(/\).*/, ''))
- )
- }
- | COLON MATCHES_PSEUDO_CLASS simple_selectors RPAREN {
- result = Selectors::PseudoClass.new(
- val[1].split('(').first.strip,
- val[2].join(', ')
- )
- }
- | COLON MOZ_PSEUDO_ELEMENT optional_space any_number_of_idents optional_space RPAREN {
- result = Selectors::PseudoElement.new(
- interpret_identifier(val[1].sub(/\($/, ''))
- )
- }
- | COLON COLON MOZ_PSEUDO_ELEMENT optional_space any_number_of_idents optional_space RPAREN {
- result = Selectors::PseudoElement.new(
- interpret_identifier(val[2].sub(/\($/, ''))
- )
- }
- ;
- any_number_of_idents
- :
- | multiple_idents
- ;
- multiple_idents
- : IDENT
- | IDENT COMMA multiple_idents
- ;
- # declarations can be separated by one *or more* semicolons. semi-colons at the start or end of a ruleset are also allowed
- one_or_more_semis
- : SEMI
- | SEMI one_or_more_semis
- ;
- declarations
- : declaration one_or_more_semis declarations
- | one_or_more_semis declarations
- | declaration one_or_more_semis
- | declaration
- | one_or_more_semis
- ;
- declaration
- : declaration_internal { @handler.property val.first }
- ;
- declaration_internal
- : property COLON expr prio
- { result = Declaration.new(val.first, val[2], val[3]) }
- | property COLON S expr prio
- { result = Declaration.new(val.first, val[3], val[4]) }
- | property S COLON expr prio
- { result = Declaration.new(val.first, val[3], val[4]) }
- | property S COLON S expr prio
- { result = Declaration.new(val.first, val[4], val[5]) }
- ;
- prio
- : IMPORTANT_SYM { result = true }
- | { result = false }
- ;
- property
- : IDENT { result = interpret_identifier val[0] }
- | STAR IDENT { result = interpret_identifier val.join }
- | VARIABLE_NAME { result = interpret_identifier val[0] }
- ;
- operator
- : COMMA
- | SLASH
- | EQUAL
- ;
- expr
- : term operator expr {
- result = [val.first, val.last].flatten
- val.last.first.operator = val[1]
- }
- | term expr { result = val.flatten }
- | term { result = val }
- ;
- term
- : ident
- | ratio
- | numeric
- | string
- | uri
- | hexcolor
- | calc
- | function
- | resolution
- | VARIABLE_NAME
- | uranges
- ;
- function
- : function S { result = val.first }
- | FUNCTION expr RPAREN {
- name = interpret_identifier val.first.sub(/\($/, '')
- if name == 'rgb'
- result = Terms::Rgb.new(*val[1])
- else
- result = Terms::Function.new name, val[1]
- end
- }
- | FUNCTION RPAREN {
- name = interpret_identifier val.first.sub(/\($/, '')
- result = Terms::Function.new name
- }
- ;
- function_no_quote
- : function_no_quote S { result = val.first }
- | FUNCTION_NO_QUOTE {
- parts = val.first.split('(')
- name = interpret_identifier parts.first
- result = Terms::Function.new(name, [Terms::String.new(interpret_string_no_quote(parts.last))])
- }
- ;
- uranges
- : UNICODE_RANGE COMMA uranges
- | UNICODE_RANGE
- ;
- calc
- : CALC_SYM calc_sum RPAREN optional_space {
- result = Terms::Math.new(val.first.split('(').first, val[1])
- }
- ;
- # plus and minus are supposed to have whitespace around them, per http://dev.w3.org/csswg/css-values/#calc-syntax, but the numbers are eating trailing whitespace, so we inject it back in
- calc_sum
- : calc_product
- | calc_product PLUS calc_sum { val.insert(1, ' '); result = val.join('') }
- | calc_product MINUS calc_sum { val.insert(1, ' '); result = val.join('') }
- ;
- calc_product
- : calc_value
- | calc_value optional_space STAR calc_value { result = val.join('') }
- | calc_value optional_space SLASH calc_value { result = val.join('') }
- ;
- calc_value
- : numeric { result = val.join('') }
- | function { result = val.join('') } # for var() variable references
- | LPAREN calc_sum RPAREN { result = val.join('') }
- ;
- hexcolor
- : hexcolor S { result = val.first }
- | HASH { result = Terms::Hash.new val.first.sub(/^#/, '') }
- ;
- uri
- : uri S { result = val.first }
- | URI { result = Terms::URI.new interpret_uri val.first }
- ;
- string
- : string S { result = val.first }
- | STRING { result = Terms::String.new interpret_string val.first }
- ;
- numeric
- : unary_operator numeric {
- result = val[1]
- val[1].unary_operator = val.first
- }
- | NUMBER {
- result = Terms::Number.new numeric val.first
- }
- | PERCENTAGE {
- result = Terms::Number.new numeric(val.first), nil, '%'
- }
- | LENGTH {
- unit = val.first.gsub(/[\s\d.]/, '')
- result = Terms::Number.new numeric(val.first), nil, unit
- }
- | ANGLE {
- unit = val.first.gsub(/[\s\d.]/, '')
- result = Terms::Number.new numeric(val.first), nil, unit
- }
- | TIME {
- unit = val.first.gsub(/[\s\d.]/, '')
- result = Terms::Number.new numeric(val.first), nil, unit
- }
- | FREQ {
- unit = val.first.gsub(/[\s\d.]/, '')
- result = Terms::Number.new numeric(val.first), nil, unit
- }
- ;
- ratio
- : RATIO {
- result = Terms::Ratio.new(val[0], val[1])
- }
- ;
- unary_operator
- : MINUS { result = :minus }
- | PLUS { result = :plus }
- ;
- ident
- : ident S { result = val.first }
- | IDENT { result = Terms::Ident.new interpret_identifier val.first }
- ;
-
----- inner
-
-def numeric thing
- thing = thing.gsub(/[^\d.]/, '')
- Integer(thing) rescue Float(thing)
-end
-
-def interpret_identifier s
- interpret_escapes s
-end
-
-def interpret_uri s
- interpret_escapes s.match(/^url\((.*)\)$/mui)[1].strip.match(/^(['"]?)((?:\\.|.)*)\1$/mu)[2]
-end
-
-def interpret_string_no_quote s
- interpret_escapes s.match(/^(.*)\)$/mu)[1].strip.match(/^(['"]?)((?:\\.|.)*)\1$/mu)[2]
-end
-
-def interpret_string s
- interpret_escapes s.match(/^(['"])((?:\\.|.)*)\1$/mu)[2]
-end
-
-def interpret_escapes s
- token_exp = /\\(?:([0-9a-fA-F]{1,6}(?:\r\n|\s)?)|(.))/mu
- return s.gsub(token_exp) do |escape_sequence|
- if !$1.nil?
- code = $1.chomp.to_i 16
- code = 0xFFFD if code > 0x10FFFF
- next [code].pack('U')
- end
- next '' if $2 == "\n"
- next $2
- end
-end
-
-# override racc's on_error so we can have context in our error messages
-def on_error(t, val, vstack)
- errcontext = (@ss.pre_match[-10..-1] || @ss.pre_match) +
- @ss.matched + @ss.post_match[0..9]
- line_number = @ss.pre_match.lines.count
- raise ParseError, sprintf("parse error on value %s (%s) " +
- "on line %s around \"%s\"",
- val.inspect, token_to_str(t) || '?',
- line_number, errcontext)
-end
-
-def before_pos(val)
- # don't include leading whitespace
- return current_pos - val.last.length + val.last[/\A\s*/].size
-end
-
-def after_pos(val)
- # don't include trailing whitespace
- return current_pos - val.last[/\s*\z/].size
-end
-
-# charpos will work with multibyte strings but is not available until ruby 2
-def current_pos
- @ss.respond_to?('charpos') ? @ss.charpos : @ss.pos
-end
diff --git a/test/racc/assets/digraph.y b/test/racc/assets/digraph.y
deleted file mode 100644
index 17a034ee54..0000000000
--- a/test/racc/assets/digraph.y
+++ /dev/null
@@ -1,29 +0,0 @@
-# ? detect digraph bug
-
-class P
- token A B C D
-rule
- target : a b c d
- a : A
- |
- b : B
- |
- c : C
- |
- d : D
- |
-end
-
----- inner
-
- def parse
- do_parse
- end
-
- def next_token
- [false, '$']
- end
-
----- footer
-
-P.new.parse
diff --git a/test/racc/assets/echk.y b/test/racc/assets/echk.y
deleted file mode 100644
index 0fda2685aa..0000000000
--- a/test/racc/assets/echk.y
+++ /dev/null
@@ -1,118 +0,0 @@
-#
-# racc tester
-#
-
-class Calcp
-
- prechigh
- left '*' '/'
- left '+' '-'
- preclow
-
- convert
- NUMBER 'Number'
- end
-
-rule
-
- target : exp | /* none */ { result = 0 } ;
-
- exp : exp '+' exp { result += val[2]; a = 'plus' }
- | exp '-' exp { result -= val[2]; "string test" }
- | exp '*' exp { result *= val[2] }
- | exp '/' exp { result /= val[2] }
- | '(' { $emb = true } exp ')'
- {
- raise 'must not happen' unless $emb
- result = val[2]
- }
- | '-' NUMBER { result = -val[1] }
- | NUMBER
- ;
-
-end
-
-----header
-
-class Number ; end
-
-----inner
-
- def parse( src )
- @src = src
- do_parse
- end
-
- def next_token
- @src.shift
- end
-
- def initialize
- @yydebug = true
- end
-
-----footer
-
-$parser = Calcp.new
-$tidx = 1
-
-def chk( src, ans )
- ret = $parser.parse( src )
- unless ret == ans then
- bug! "test #{$tidx} fail"
- end
- $tidx += 1
-end
-
-chk(
- [ [Number, 9],
- [false, false],
- [false, false] ], 9
-)
-
-chk(
- [ [Number, 5],
- ['*', nil],
- [Number, 1],
- ['-', nil],
- [Number, 1],
- ['*', nil],
- [Number, 8],
- [false, false],
- [false, false] ], -3
-)
-
-chk(
- [ [Number, 5],
- ['+', nil],
- [Number, 2],
- ['-', nil],
- [Number, 5],
- ['+', nil],
- [Number, 2],
- ['-', nil],
- [Number, 5],
- [false, false],
- [false, false] ], -1
-)
-
-chk(
- [ ['-', nil],
- [Number, 4],
- [false, false],
- [false, false] ], -4
-)
-
-chk(
- [ [Number, 7],
- ['*', nil],
- ['(', nil],
- [Number, 4],
- ['+', nil],
- [Number, 3],
- [')', nil],
- ['-', nil],
- [Number, 9],
- [false, false],
- [false, false] ], 40
-)
diff --git a/test/racc/assets/edtf.y b/test/racc/assets/edtf.y
deleted file mode 100644
index 4f5f6bb4fd..0000000000
--- a/test/racc/assets/edtf.y
+++ /dev/null
@@ -1,583 +0,0 @@
-# -*- racc -*-
-
-# Copyright 2011 Sylvester Keil. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#
-# 1. Redistributions of source code must retain the above copyright notice,
-# this list of conditions and the following disclaimer.
-#
-# 2. Redistributions in binary form must reproduce the above copyright notice,
-# this list of conditions and the following disclaimer in the documentation
-# and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-# EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
-# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
-# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
-# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-# The views and conclusions contained in the software and documentation are
-# those of the authors and should not be interpreted as representing official
-# policies, either expressed or implied, of the copyright holder.
-
-class EDTF::Parser
-
-token T Z E X U UNKNOWN OPEN LONGYEAR UNMATCHED DOTS UA PUA
-
-expect 0
-
-rule
-
- edtf : level_0_expression
- | level_1_expression
- | level_2_expression
- ;
-
- # ---- Level 0 / ISO 8601 Rules ----
-
- # NB: level 0 intervals are covered by the level 1 interval rules
- level_0_expression : date
- | date_time
- ;
-
- date : positive_date
- | negative_date
- ;
-
- positive_date :
- year { result = Date.new(val[0]).year_precision! }
- | year_month { result = Date.new(*val.flatten).month_precision! }
- | year_month_day { result = Date.new(*val.flatten).day_precision! }
- ;
-
- negative_date : '-' positive_date { result = -val[1] }
-
-
- date_time : date T time {
- result = DateTime.new(val[0].year, val[0].month, val[0].day, *val[2])
- result.skip_timezone = (val[2].length == 3)
- }
-
- time : base_time
- | base_time zone_offset { result = val.flatten }
-
- base_time : hour ':' minute ':' second { result = val.values_at(0, 2, 4) }
- | midnight
-
- midnight : '2' '4' ':' '0' '0' ':' '0' '0' { result = [24, 0, 0] }
-
- zone_offset : Z { result = 0 }
- | '-' zone_offset_hour { result = -1 * val[1] }
- | '+' positive_zone_offset { result = val[1] }
- ;
-
- positive_zone_offset : zone_offset_hour
- | '0' '0' ':' '0' '0' { result = 0 }
- ;
-
-
- zone_offset_hour : d01_13 ':' minute { result = Rational(val[0] * 60 + val[2], 1440) }
- | '1' '4' ':' '0' '0' { result = Rational(840, 1440) }
- | '0' '0' ':' d01_59 { result = Rational(val[3], 1440) }
- ;
-
- year : digit digit digit digit {
- result = val.zip([1000,100,10,1]).reduce(0) { |s,(a,b)| s += a * b }
- }
-
- month : d01_12
- day : d01_31
-
- year_month : year '-' month { result = [val[0], val[2]] }
-
- # We raise an exception if there are two many days for the month, but
- # do not consider leap years, as the EDTF BNF did not either.
- # NB: an exception will be raised regardless, because the Ruby Date
- # implementation calculates leap years.
- year_month_day : year_month '-' day {
- result = val[0] << val[2]
- if result[2] > 31 || (result[2] > 30 && [2,4,6,9,11].include?(result[1])) || (result[2] > 29 && result[1] == 2)
- raise ArgumentError, "invalid date (invalid days #{result[2]} for month #{result[1]})"
- end
- }
-
- hour : d00_23
- minute : d00_59
- second : d00_59
-
- # Completely covered by level_1_interval
- # level_0_interval : date '/' date { result = Interval.new(val[0], val[1]) }
-
-
- # ---- Level 1 Extension Rules ----
-
- # NB: Uncertain/approximate Dates are covered by the Level 2 rules
- level_1_expression : unspecified | level_1_interval | long_year_simple | season
-
- # uncertain_or_approximate_date : date UA { result = uoa(val[0], val[1]) }
-
- unspecified : unspecified_year
- {
- result = Date.new(val[0][0]).year_precision!
- result.unspecified.year[2,2] = val[0][1]
- }
- | unspecified_month
- | unspecified_day
- | unspecified_day_and_month
- ;
-
- unspecified_year :
- digit digit digit U
- {
- result = [val[0,3].zip([1000,100,10]).reduce(0) { |s,(a,b)| s += a * b }, [false,true]]
- }
- | digit digit U U
- {
- result = [val[0,2].zip([1000,100]).reduce(0) { |s,(a,b)| s += a * b }, [true, true]]
- }
-
- unspecified_month : year '-' U U {
- result = Date.new(val[0]).unspecified!(:month)
- result.precision = :month
- }
-
- unspecified_day : year_month '-' U U {
- result = Date.new(*val[0]).unspecified!(:day)
- }
-
- unspecified_day_and_month : year '-' U U '-' U U {
- result = Date.new(val[0]).unspecified!([:day,:month])
- }
-
-
- level_1_interval : level_1_start '/' level_1_end {
- result = Interval.new(val[0], val[2])
- }
-
- level_1_start : date | partial_uncertain_or_approximate | unspecified | partial_unspecified | UNKNOWN
-
- level_1_end : level_1_start | OPEN
-
-
- long_year_simple :
- LONGYEAR long_year
- {
- result = Date.new(val[1])
- result.precision = :year
- }
- | LONGYEAR '-' long_year
- {
- result = Date.new(-1 * val[2])
- result.precision = :year
- }
- ;
-
- long_year :
- positive_digit digit digit digit digit {
- result = val.zip([10000,1000,100,10,1]).reduce(0) { |s,(a,b)| s += a * b }
- }
- | long_year digit { result = 10 * val[0] + val[1] }
- ;
-
-
- season : year '-' season_number ua {
- result = Season.new(val[0], val[2])
- val[3].each { |ua| result.send(ua) }
- }
-
- season_number : '2' '1' { result = 21 }
- | '2' '2' { result = 22 }
- | '2' '3' { result = 23 }
- | '2' '4' { result = 24 }
- ;
-
-
- # ---- Level 2 Extension Rules ----
-
- # NB: Level 2 Intervals are covered by the Level 1 Interval rules.
- level_2_expression : season_qualified
- | partial_uncertain_or_approximate
- | partial_unspecified
- | choice_list
- | inclusive_list
- | masked_precision
- | date_and_calendar
- | long_year_scientific
- ;
-
-
- season_qualified : season '^' { result = val[0]; result.qualifier = val[1] }
-
-
- long_year_scientific :
- long_year_simple E integer
- {
- result = Date.new(val[0].year * 10 ** val[2]).year_precision!
- }
- | LONGYEAR int1_4 E integer
- {
- result = Date.new(val[1] * 10 ** val[3]).year_precision!
- }
- | LONGYEAR '-' int1_4 E integer
- {
- result = Date.new(-1 * val[2] * 10 ** val[4]).year_precision!
- }
- ;
-
-
- date_and_calendar : date '^' { result = val[0]; result.calendar = val[1] }
-
-
- masked_precision :
- digit digit digit X
- {
- d = val[0,3].zip([1000,100,10]).reduce(0) { |s,(a,b)| s += a * b }
- result = EDTF::Decade.new(d)
- }
- | digit digit X X
- {
- d = val[0,2].zip([1000,100]).reduce(0) { |s,(a,b)| s += a * b }
- result = EDTF::Century.new(d)
- }
- ;
-
-
- choice_list : '[' list ']' { result = val[1].choice! }
-
- inclusive_list : '{' list '}' { result = val[1] }
-
- list : earlier { result = EDTF::Set.new(val[0]).earlier! }
- | earlier ',' list_elements ',' later { result = EDTF::Set.new([val[0]] + val[2] + [val[4]]).earlier!.later! }
- | earlier ',' list_elements { result = EDTF::Set.new([val[0]] + val[2]).earlier! }
- | earlier ',' later { result = EDTF::Set.new([val[0]] + [val[2]]).earlier!.later! }
- | list_elements ',' later { result = EDTF::Set.new(val[0] + [val[2]]).later! }
- | list_elements { result = EDTF::Set.new(*val[0]) }
- | later { result = EDTF::Set.new(val[0]).later! }
- ;
-
- list_elements : list_element { result = [val[0]].flatten }
- | list_elements ',' list_element { result = val[0] + [val[2]].flatten }
- ;
-
- list_element : atomic
- | consecutives
- ;
-
- atomic : date
- | partial_uncertain_or_approximate
- | unspecified
- ;
-
- earlier : DOTS date { result = val[1] }
-
- later : year_month_day DOTS { result = Date.new(*val[0]).year_precision! }
- | year_month DOTS { result = Date.new(*val[0]).month_precision! }
- | year DOTS { result = Date.new(val[0]).year_precision! }
- ;
-
- consecutives : year_month_day DOTS year_month_day { result = (Date.new(val[0]).day_precision! .. Date.new(val[2]).day_precision!) }
- | year_month DOTS year_month { result = (Date.new(val[0]).month_precision! .. Date.new(val[2]).month_precision!) }
- | year DOTS year { result = (Date.new(val[0]).year_precision! .. Date.new(val[2]).year_precision!) }
- ;
-
- partial_unspecified :
- unspecified_year '-' month '-' day
- {
- result = Date.new(val[0][0], val[2], val[4])
- result.unspecified.year[2,2] = val[0][1]
- }
- | unspecified_year '-' U U '-' day
- {
- result = Date.new(val[0][0], 1, val[5])
- result.unspecified.year[2,2] = val[0][1]
- result.unspecified!(:month)
- }
- | unspecified_year '-' U U '-' U U
- {
- result = Date.new(val[0][0], 1, 1)
- result.unspecified.year[2,2] = val[0][1]
- result.unspecified!([:month, :day])
- }
- | unspecified_year '-' month '-' U U
- {
- result = Date.new(val[0][0], val[2], 1)
- result.unspecified.year[2,2] = val[0][1]
- result.unspecified!(:day)
- }
- | year '-' U U '-' day
- {
- result = Date.new(val[0], 1, val[5])
- result.unspecified!(:month)
- }
- ;
-
-
- partial_uncertain_or_approximate : pua_base
- | '(' pua_base ')' UA { result = uoa(val[1], val[3]) }
-
- pua_base :
- pua_year { result = val[0].year_precision! }
- | pua_year_month { result = val[0][0].month_precision! }
- | pua_year_month_day { result = val[0].day_precision! }
-
- pua_year : year UA { result = uoa(Date.new(val[0]), val[1], :year) }
-
- pua_year_month :
- pua_year '-' month ua {
- result = [uoa(val[0].change(:month => val[2]), val[3], [:month, :year])]
- }
- | year '-' month UA {
- result = [uoa(Date.new(val[0], val[2]), val[3], [:year, :month])]
- }
- | year '-(' month ')' UA {
- result = [uoa(Date.new(val[0], val[2]), val[4], [:month]), true]
- }
- | pua_year '-(' month ')' UA {
- result = [uoa(val[0].change(:month => val[2]), val[4], [:month]), true]
- }
- ;
-
- pua_year_month_day :
- pua_year_month '-' day ua {
- result = uoa(val[0][0].change(:day => val[2]), val[3], val[0][1] ? [:day] : nil)
- }
- | pua_year_month '-(' day ')' UA {
- result = uoa(val[0][0].change(:day => val[2]), val[4], [:day])
- }
- | year '-(' month ')' UA day ua {
- result = uoa(uoa(Date.new(val[0], val[2], val[5]), val[4], :month), val[6], :day)
- }
- | year_month '-' day UA {
- result = uoa(Date.new(val[0][0], val[0][1], val[2]), val[3])
- }
- | year_month '-(' day ')' UA {
- result = uoa(Date.new(val[0][0], val[0][1], val[2]), val[4], [:day])
- }
- | year '-(' month '-' day ')' UA {
- result = uoa(Date.new(val[0], val[2], val[4]), val[6], [:month, :day])
- }
- | year '-(' month '-(' day ')' UA ')' UA {
- result = Date.new(val[0], val[2], val[4])
- result = uoa(result, val[6], [:day])
- result = uoa(result, val[8], [:month, :day])
- }
- | pua_year '-(' month '-' day ')' UA {
- result = val[0].change(:month => val[2], :day => val[4])
- result = uoa(result, val[6], [:month, :day])
- }
- | pua_year '-(' month '-(' day ')' UA ')' UA {
- result = val[0].change(:month => val[2], :day => val[4])
- result = uoa(result, val[6], [:day])
- result = uoa(result, val[8], [:month, :day])
- }
- # | '(' pua_year '-(' month ')' UA ')' UA '-' day ua {
- # result = val[1].change(:month => val[3], :day => val[9])
- # result = uoa(result, val[5], [:month])
- # result = [uoa(result, val[7], [:year]), true]
- # }
- ;
-
- ua : { result = [] } | UA
-
- # ---- Auxiliary Rules ----
-
- digit : '0' { result = 0 }
- | positive_digit
- ;
-
- positive_digit : '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
-
- d01_12 : '0' positive_digit { result = val[1] }
- | '1' '0' { result = 10 }
- | '1' '1' { result = 11 }
- | '1' '2' { result = 12 }
- ;
-
- d01_13 : d01_12
- | '1' '3' { result = 13 }
- ;
-
- d01_23 : '0' positive_digit { result = val[1] }
- | '1' digit { result = 10 + val[1] }
- | '2' '0' { result = 20 }
- | '2' '1' { result = 21 }
- | '2' '2' { result = 22 }
- | '2' '3' { result = 23 }
- ;
-
- d00_23 : '0' '0'
- | d01_23
- ;
-
- d01_29 : d01_23
- | '2' '4' { result = 24 }
- | '2' '5' { result = 25 }
- | '2' '6' { result = 26 }
- | '2' '7' { result = 27 }
- | '2' '8' { result = 28 }
- | '2' '9' { result = 29 }
- ;
-
- d01_30 : d01_29
- | '3' '0' { result = 30 }
- ;
-
- d01_31 : d01_30
- | '3' '1' { result = 31 }
- ;
-
- d01_59 : d01_29
- | '3' digit { result = 30 + val[1] }
- | '4' digit { result = 40 + val[1] }
- | '5' digit { result = 50 + val[1] }
- ;
-
- d00_59 : '0' '0'
- | d01_59
- ;
-
- int1_4 : positive_digit { result = val[0] }
- | positive_digit digit { result = 10 * val[0] + val[1] }
- | positive_digit digit digit
- {
- result = val.zip([100,10,1]).reduce(0) { |s,(a,b)| s += a * b }
- }
- | positive_digit digit digit digit
- {
- result = val.zip([1000,100,10,1]).reduce(0) { |s,(a,b)| s += a * b }
- }
- ;
-
- integer : positive_digit { result = val[0] }
- | integer digit { result = 10 * val[0] + val[1] }
- ;
-
-
-
----- header
-require 'strscan'
-
----- inner
-
- @defaults = {
- :level => 2,
- :debug => false
- }.freeze
-
- class << self; attr_reader :defaults; end
-
- attr_reader :options
-
- def initialize(options = {})
- @options = Parser.defaults.merge(options)
- end
-
- def debug?
- !!(options[:debug] || ENV['DEBUG'])
- end
-
- def parse(input)
- parse!(input)
- rescue => e
- warn e.message if debug?
- nil
- end
-
- def parse!(input)
- @yydebug = debug?
- @src = StringScanner.new(input)
- do_parse
- end
-
- def on_error(tid, value, stack)
- raise ArgumentError,
- "failed to parse date: unexpected '#{value}' at #{stack.inspect}"
- end
-
- def apply_uncertainty(date, uncertainty, scope = nil)
- uncertainty.each do |u|
- scope.nil? ? date.send(u) : date.send(u, scope)
- end
- date
- end
-
- alias uoa apply_uncertainty
-
- def next_token
- case
- when @src.eos?
- nil
- # when @src.scan(/\s+/)
- # ignore whitespace
- when @src.scan(/\(/)
- ['(', @src.matched]
- # when @src.scan(/\)\?~-/)
- # [:PUA, [:uncertain!, :approximate!]]
- # when @src.scan(/\)\?-/)
- # [:PUA, [:uncertain!]]
- # when @src.scan(/\)~-/)
- # [:PUA, [:approximate!]]
- when @src.scan(/\)/)
- [')', @src.matched]
- when @src.scan(/\[/)
- ['[', @src.matched]
- when @src.scan(/\]/)
- [']', @src.matched]
- when @src.scan(/\{/)
- ['{', @src.matched]
- when @src.scan(/\}/)
- ['}', @src.matched]
- when @src.scan(/T/)
- [:T, @src.matched]
- when @src.scan(/Z/)
- [:Z, @src.matched]
- when @src.scan(/\?~/)
- [:UA, [:uncertain!, :approximate!]]
- when @src.scan(/\?/)
- [:UA, [:uncertain!]]
- when @src.scan(/~/)
- [:UA, [:approximate!]]
- when @src.scan(/open/i)
- [:OPEN, :open]
- when @src.scan(/unkn?own/i) # matches 'unkown' typo too
- [:UNKNOWN, :unknown]
- when @src.scan(/u/)
- [:U, @src.matched]
- when @src.scan(/x/i)
- [:X, @src.matched]
- when @src.scan(/y/)
- [:LONGYEAR, @src.matched]
- when @src.scan(/e/)
- [:E, @src.matched]
- when @src.scan(/\+/)
- ['+', @src.matched]
- when @src.scan(/-\(/)
- ['-(', @src.matched]
- when @src.scan(/-/)
- ['-', @src.matched]
- when @src.scan(/:/)
- [':', @src.matched]
- when @src.scan(/\//)
- ['/', @src.matched]
- when @src.scan(/\s*\.\.\s*/)
- [:DOTS, '..']
- when @src.scan(/\s*,\s*/)
- [',', ',']
- when @src.scan(/\^\w+/)
- ['^', @src.matched[1..-1]]
- when @src.scan(/\d/)
- [@src.matched, @src.matched.to_i]
- else @src.scan(/./)
- [:UNMATCHED, @src.rest]
- end
- end
-
-
-# -*- racc -*-
diff --git a/test/racc/assets/err.y b/test/racc/assets/err.y
deleted file mode 100644
index ae280957cc..0000000000
--- a/test/racc/assets/err.y
+++ /dev/null
@@ -1,60 +0,0 @@
-
-class ErrTestp
-
-rule
-
-target: lines
- ;
-
-lines: line
- | lines line
- ;
-
-line: A B C D E
- | error E
- ;
-
-end
-
----- inner
-
-def initialize
- @yydebug = false
- @q = [
- [:A, 'a'],
- # [:B, 'b'],
- [:C, 'c'],
- [:D, 'd'],
- [:E, 'e'],
-
- [:A, 'a'],
- [:B, 'b'],
- [:C, 'c'],
- [:D, 'd'],
- [:E, 'e'],
-
- [:A, 'a'],
- [:B, 'b'],
- # [:C, 'c'],
- [:D, 'd'],
- [:E, 'e'],
- [false, nil]
- ]
-end
-
-def next_token
- @q.shift
-end
-
-def on_error( t, val, values )
- $stderr.puts "error on token '#{val}'(#{t})"
-end
-
-def parse
- do_parse
-end
-
----- footer
-
-p = ErrTestp.new
-p.parse
diff --git a/test/racc/assets/error_recovery.y b/test/racc/assets/error_recovery.y
deleted file mode 100644
index 1fd21ac7d0..0000000000
--- a/test/racc/assets/error_recovery.y
+++ /dev/null
@@ -1,35 +0,0 @@
-# Regression test case for the bug discussed here:
-# https://github.com/whitequark/parser/issues/93
-# In short, a Racc-generated parser could go into an infinite loop when
-# attempting error recovery at EOF
-
-class InfiniteLoop
-
-rule
-
- stmts: stmt
- | error stmt
-
- stmt: '%' stmt
-
-end
-
----- inner
-
- def parse
- @errors = []
- do_parse
- end
-
- def next_token
- nil
- end
-
- def on_error(error_token, error_value, value_stack)
- # oh my, an error
- @errors << [error_token, error_value]
- end
-
----- footer
-
-InfiniteLoop.new.parse \ No newline at end of file
diff --git a/test/racc/assets/expect.y b/test/racc/assets/expect.y
deleted file mode 100644
index 24c27443e2..0000000000
--- a/test/racc/assets/expect.y
+++ /dev/null
@@ -1,7 +0,0 @@
-class E
- expect 1
-rule
- list: inlist inlist
- inlist:
- | A
-end
diff --git a/test/racc/assets/firstline.y b/test/racc/assets/firstline.y
deleted file mode 100644
index ab0692e543..0000000000
--- a/test/racc/assets/firstline.y
+++ /dev/null
@@ -1,4 +0,0 @@
-class T
-rule
- a: A B C
-end
diff --git a/test/racc/assets/huia.y b/test/racc/assets/huia.y
deleted file mode 100644
index de9d45150c..0000000000
--- a/test/racc/assets/huia.y
+++ /dev/null
@@ -1,318 +0,0 @@
-# Copyright (c) 2014 James Harton
-#
-# MIT License
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-class Huia::Parser
-
- token
- IDENTIFIER EQUAL PLUS MINUS ASTERISK FWD_SLASH COLON FLOAT INTEGER STRING
- EXPO INDENT OUTDENT OPAREN CPAREN DOT SIGNATURE NL EOF PIPE COMMA NIL TRUE
- FALSE EQUALITY CALL SELF CONSTANT CHAR DOUBLE_TICK_STRING
- DOUBLE_TICK_STRING_END INTERPOLATE_START INTERPOLATE_END BOX LSQUARE
- RSQUARE FACES LFACE RFACE BANG TILDE RETURN NOT_EQUALITY OR AND GT LT
- GTE LTE AT
-
- prechigh
- left EXPO
- left BANG TILDE
- left ASTERISK FWD_SLASH PERCENT
- left PLUS MINUS
-
- right EQUAL
- preclow
-
- rule
- statements: statement
- | statements statement { return scope }
-
- statement: expr eol { return scope.append val[0] }
- | expr { return scope.append val[0] }
- | eol { return scope }
-
- eol: NL | EOF
- nlq: NL |
-
- expr: literal
- | grouped_expr
- | binary_op
- | unary_op
- | method_call
- | constant
- | variable
- | array
- | hash
- | return
-
- return: return_expr
- | return_nil
- return_expr: RETURN expr { return n(:Return, val[1]) }
- return_nil: RETURN { return n(:Return, n(:Nil)) }
-
- array: empty_array
- | array_list
-
- empty_array: BOX { return n :Array }
-
- array_list: LSQUARE array_items RSQUARE { return val[1] }
- array_items: expr { return n :Array, [val[0]] }
- | array_items COMMA expr { val[0].append(val[2]); return val[0] }
-
- hash: empty_hash
- | hash_list
- empty_hash: FACES { return n :Hash }
- hash_list: LFACE hash_items RFACE { return val[1] }
- hash_items: hash_item { return n :Hash, val[0] }
- | hash_items COMMA hash_item { val[0].append(val[2]); return val[0] }
- hash_item: expr COLON expr { return n :HashItem, val[0], val[2] }
-
- constant: CONSTANT { return constant val[0] }
-
- indented: indented_w_stmts
- | indented_w_expr
- | indented_wo_stmts
- indented_w_stmts: indent statements outdent { return val[0] }
- indented_w_expr: indent expr outdent { return val[0].append(val[1]) }
- indented_wo_stmts: indent outdent { return val[0] }
- outdent: OUTDENT { return pop_scope }
-
-
- indent_w_args: indent_pipe indent_args PIPE nlq INDENT { return val[0] }
- indent_pipe: PIPE { return push_scope }
- indent_wo_args: INDENT { return push_scope }
- indent: indent_w_args
- | indent_wo_args
-
- indent_args: indent_arg
- | indent_args COMMA indent_arg
- indent_arg: arg_var { return scope.add_argument val[0] }
- | arg_var EQUAL expr { return n :Assignment, val[0], val[2] }
- arg_var: IDENTIFIER { return n :Variable, val[0] }
-
- method_call: method_call_on_object
- | method_call_on_self
- | method_call_on_closure
- method_call_on_object: expr DOT call_signature { return n :MethodCall, val[0], val[2] }
- | expr DOT IDENTIFIER { return n :MethodCall, val[0], n(:CallSignature, val[2]) }
- method_call_on_self: call_signature { return n :MethodCall, scope_instance, val[0] }
-
- method_call_on_closure: AT call_signature { return n :MethodCall, this_closure, val[1] }
- | AT IDENTIFIER { return n :MethodCall, this_closure, n(:CallSignature, val[1]) }
-
- call_signature: call_arguments
- | call_simple_name
- call_simple_name: CALL { return n :CallSignature, val[0] }
- call_argument: SIGNATURE call_passed_arg { return n :CallSignature, val[0], [val[1]] }
- call_passed_arg: call_passed_simple
- | call_passed_indented
- call_passed_simple: expr
- | expr NL
- call_passed_indented: indented
- | indented NL
- call_arguments: call_argument { return val[0] }
- | call_arguments call_argument { return val[0].concat_signature val[1] }
-
- grouped_expr: OPAREN expr CPAREN { return n :Expression, val[1] }
-
- variable: IDENTIFIER { return allocate_local val[0] }
-
- binary_op: assignment
- | addition
- | subtraction
- | multiplication
- | division
- | exponentiation
- | modulo
- | equality
- | not_equality
- | logical_or
- | logical_and
- | greater_than
- | less_than
- | greater_or_eq
- | less_or_eq
-
- assignment: IDENTIFIER EQUAL expr { return allocate_local_assignment val[0], val[2] }
- addition: expr PLUS expr { return binary val[0], val[2], 'plus:' }
- subtraction: expr MINUS expr { return binary val[0], val[2], 'minus:' }
- multiplication: expr ASTERISK expr { return binary val[0], val[2], 'multiplyBy:' }
- division: expr FWD_SLASH expr { return binary val[0], val[2], 'divideBy:' }
- exponentiation: expr EXPO expr { return binary val[0], val[2], 'toThePowerOf:' }
- modulo: expr PERCENT expr { return binary val[0], val[2], 'moduloOf:' }
- equality: expr EQUALITY expr { return binary val[0], val[2], 'isEqualTo:' }
- not_equality: expr NOT_EQUALITY expr { return binary val[0], val[2], 'isNotEqualTo:' }
- logical_or: expr OR expr { return binary val[0], val[2], 'logicalOr:' }
- logical_and: expr AND expr { return binary val[0], val[2], 'logicalAnd:' }
- greater_than: expr GT expr { return binary val[0], val[2], 'isGreaterThan:' }
- less_than: expr LT expr { return binary val[0], val[2], 'isLessThan:' }
- greater_or_eq: expr GTE expr { return binary val[0], val[2], 'isGreaterOrEqualTo:' }
- less_or_eq: expr LTE expr { return binary val[0], val[2], 'isLessOrEqualTo:' }
-
- unary_op: unary_not
- | unary_plus
- | unary_minus
- | unary_complement
-
- unary_not: BANG expr { return unary val[1], 'unaryNot' }
- unary_plus: PLUS expr { return unary val[1], 'unaryPlus' }
- unary_minus: MINUS expr { return unary val[1], 'unaryMinus' }
- unary_complement: TILDE expr { return unary val[1], 'unaryComplement' }
-
- literal: integer
- | float
- | string
- | nil
- | true
- | false
- | self
-
- float: FLOAT { return n :Float, val[0] }
- integer: INTEGER { return n :Integer, val[0] }
- nil: NIL { return n :Nil }
- true: TRUE { return n :True }
- false: FALSE { return n :False }
- self: SELF { return n :Self }
-
- string: STRING { return n :String, val[0] }
- | interpolated_string
- | empty_string
-
- interpolated_string: DOUBLE_TICK_STRING interpolated_string_contents DOUBLE_TICK_STRING_END { return val[1] }
- interpolation: INTERPOLATE_START expr INTERPOLATE_END { return val[1] }
- interpolated_string_contents: interpolated_string_chunk { return n :InterpolatedString, val[0] }
- | interpolated_string_contents interpolated_string_chunk { val[0].append(val[1]); return val[0] }
- interpolated_string_chunk: chars { return val[0] }
- | interpolation { return to_string(val[0]) }
- empty_string: DOUBLE_TICK_STRING DOUBLE_TICK_STRING_END { return n :String, '' }
-
- chars: CHAR { return n :String, val[0] }
- | chars CHAR { val[0].append(val[1]); return val[0] }
-end
-
----- inner
-
-attr_accessor :lexer, :scopes, :state
-
-def initialize lexer
- @lexer = lexer
- @state = []
- @scopes = []
- push_scope
-end
-
-def ast
- @ast ||= do_parse
- @scopes.first
-end
-
-def on_error t, val, vstack
- line = lexer.line
- col = lexer.column
- message = "Unexpected #{token_to_str t} at #{lexer.filename} line #{line}:#{col}:\n\n"
-
- start = line - 5 > 0 ? line - 5 : 0
- i_size = line.to_s.size
- (start..(start + 5)).each do |i|
- message << sprintf("\t%#{i_size}d: %s\n", i, lexer.get_line(i))
- message << "\t#{' ' * i_size} #{'-' * (col - 1)}^\n" if i == line
- end
-
- raise SyntaxError, message
-end
-
-def next_token
- nt = lexer.next_computed_token
- # just use a state stack for now, we'll have to do something
- # more sophisticated soon.
- if nt && nt.first == :state
- if nt.last
- state.push << nt.last
- else
- state.pop
- end
- next_token
- else
- nt
- end
-end
-
-def push_scope
- new_scope = Huia::AST::Scope.new scope
- new_scope.file = lexer.filename
- new_scope.line = lexer.line
- new_scope.column = lexer.column
- scopes.push new_scope
- new_scope
-end
-
-def pop_scope
- scopes.pop
-end
-
-def scope
- scopes.last
-end
-
-def binary left, right, method
- node(:MethodCall, left, node(:CallSignature, method, [right]))
-end
-
-def unary left, method
- node(:MethodCall, left, node(:CallSignature, method))
-end
-
-def node type, *args
- Huia::AST.const_get(type).new(*args).tap do |n|
- n.file = lexer.filename
- n.line = lexer.line
- n.column = lexer.column
- end
-end
-alias n node
-
-def allocate_local name
- node(:Variable, name).tap do |n|
- scope.allocate_local n
- end
-end
-
-def allocate_local_assignment name, value
- node(:Assignment, name, value).tap do |n|
- scope.allocate_local n
- end
-end
-
-def this_closure
- allocate_local('@')
-end
-
-def scope_instance
- node(:ScopeInstance, scope)
-end
-
-def constant name
- return scope_instance if name == 'self'
- node(:Constant, name)
-end
-
-def to_string expr
- node(:MethodCall, expr, node(:CallSignature, 'toString'))
-end
diff --git a/test/racc/assets/ichk.y b/test/racc/assets/ichk.y
deleted file mode 100644
index 1d359df83e..0000000000
--- a/test/racc/assets/ichk.y
+++ /dev/null
@@ -1,102 +0,0 @@
-class Calculator
-
- prechigh
- left '*' '/'
- left '+' '-'
- preclow
-
- convert
- NUMBER 'Number'
- end
-
-rule
-
- target : exp
- | /* none */ { result = 0 }
-
- exp : exp '+' exp { result += val[2]; a = 'plus' }
- | exp '-' exp { result -= val[2]; a = "string test" }
- | exp '*' exp { result *= val[2] }
- | exp '/' exp { result /= val[2] }
- | '(' { $emb = true } exp ')'
- {
- raise 'must not happen' unless $emb
- result = val[2]
- }
- | '-' NUMBER { result = -val[1] }
- | NUMBER
-
-----header
-
-class Number
-end
-
-----inner
-
- def initialize
- @racc_debug_out = $stdout
- @yydebug = false
- end
-
- def validate(expected, src)
- result = parse(src)
- unless result == expected
- raise "test #{@test_number} fail"
- end
- @test_number += 1
- end
-
- def parse(src)
- @src = src
- @test_number = 1
- yyparse self, :scan
- end
-
- def scan(&block)
- @src.each(&block)
- end
-
-----footer
-
-calc = Calculator.new
-
-calc.validate(9, [[Number, 9], nil])
-
-calc.validate(-3,
- [[Number, 5],
- ['*', '*'],
- [Number, 1],
- ['-', '*'],
- [Number, 1],
- ['*', '*'],
- [Number, 8],
- nil])
-
-calc.validate(-1,
- [[Number, 5],
- ['+', '+'],
- [Number, 2],
- ['-', '-'],
- [Number, 5],
- ['+', '+'],
- [Number, 2],
- ['-', '-'],
- [Number, 5],
- nil])
-
-calc.validate(-4,
- [['-', 'UMINUS'],
- [Number, 4],
- nil])
-
-calc.validate(40,
- [[Number, 7],
- ['*', '*'],
- ['(', '('],
- [Number, 4],
- ['+', '+'],
- [Number, 3],
- [')', ')'],
- ['-', '-'],
- [Number, 9],
- nil])
diff --git a/test/racc/assets/ifelse.y b/test/racc/assets/ifelse.y
deleted file mode 100644
index 18dbe4b1a7..0000000000
--- a/test/racc/assets/ifelse.y
+++ /dev/null
@@ -1,14 +0,0 @@
-class C::Parser
-token tSOMETHING
-rule
- statement
- : tSOMETHING
- | 'if' statement 'then' statement
- | 'if' statement 'then' statement 'else' statement
- ;
-
- dummy
- : tSOMETHING '+' tSOMETHING
- | tSOMETHING '-' tSOMETHING
- ;
-
diff --git a/test/racc/assets/intp.y b/test/racc/assets/intp.y
deleted file mode 100644
index 39e42afd74..0000000000
--- a/test/racc/assets/intp.y
+++ /dev/null
@@ -1,546 +0,0 @@
-#
-# intp
-#
-
-class Intp::Parser
-
-prechigh
- nonassoc UMINUS
- left '*' '/'
- left '+' '-'
- nonassoc EQ
-preclow
-
-rule
-
- program : stmt_list
- {
- result = RootNode.new( val[0] )
- }
-
- stmt_list :
- {
- result = []
- }
- | stmt_list stmt EOL
- {
- result.push val[1]
- }
- | stmt_list EOL
-
- stmt : expr
- | assign
- | IDENT realprim
- {
- result = FuncallNode.new( @fname, val[0][0],
- val[0][1], [val[1]] )
- }
- | if_stmt
- | while_stmt
- | defun
-
- if_stmt : IF stmt THEN EOL stmt_list else_stmt END
- {
- result = IfNode.new( @fname, val[0][0],
- val[1], val[4], val[5] )
- }
-
- else_stmt : ELSE EOL stmt_list
- {
- result = val[2]
- }
- |
- {
- result = nil
- }
-
- while_stmt: WHILE stmt DO EOL stmt_list END
- {
- result = WhileNode.new(@fname, val[0][0],
- val[1], val[4])
- }
-
- defun : DEF IDENT param EOL stmt_list END
- {
- result = DefNode.new(@fname, val[0][0], val[1][1],
- Function.new(@fname, val[0][0], val[2], val[4]))
- }
-
- param : '(' name_list ')'
- {
- result = val[1]
- }
- | '(' ')'
- {
- result = []
- }
- |
- {
- result = []
- }
-
- name_list : IDENT
- {
- result = [ val[0][1] ]
- }
- | name_list ',' IDENT
- {
- result.push val[2][1]
- }
-
- assign : IDENT '=' expr
- {
- result = AssignNode.new(@fname, val[0][0], val[0][1], val[2])
- }
-
- expr : expr '+' expr
- {
- result = FuncallNode.new(@fname, val[0].lineno, '+', [val[0], val[2]])
- }
- | expr '-' expr
- {
- result = FuncallNode.new(@fname, val[0].lineno, '-', [val[0], val[2]])
- }
- | expr '*' expr
- {
- result = FuncallNode.new(@fname, val[0].lineno, '*', [val[0], val[2]])
- }
- | expr '/' expr
- {
- result = FuncallNode.new(@fname, val[0].lineno,
- '/', [val[0], val[2]])
- }
- | expr EQ expr
- {
- result = FuncallNode.new(@fname, val[0].lineno, '==', [val[0], val[2]])
- }
- | primary
-
- primary : realprim
- | '(' expr ')'
- {
- result = val[1]
- }
- | '-' expr =UMINUS
- {
- result = FuncallNode.new(@fname, val[0][0], '-@', [val[1]])
- }
-
- realprim : IDENT
- {
- result = VarRefNode.new(@fname, val[0][0],
- val[0][1])
- }
- | NUMBER
- {
- result = LiteralNode.new(@fname, *val[0])
- }
- | STRING
- {
- result = StringNode.new(@fname, *val[0])
- }
- | TRUE
- {
- result = LiteralNode.new(@fname, *val[0])
- }
- | FALSE
- {
- result = LiteralNode.new(@fname, *val[0])
- }
- | NIL
- {
- result = LiteralNode.new(@fname, *val[0])
- }
- | funcall
-
- funcall : IDENT '(' args ')'
- {
- result = FuncallNode.new(@fname, val[0][0], val[0][1], val[2])
- }
- | IDENT '(' ')'
- {
- result = FuncallNode.new(@fname, val[0][0], val[0][1], [])
- }
-
- args : expr
- {
- result = val
- }
- | args ',' expr
- {
- result.push val[2]
- }
-
-end
-
----- header
-#
-# intp/parser.rb
-#
-
----- inner
-
- def initialize
- @scope = {}
- end
-
- RESERVED = {
- 'if' => :IF,
- 'else' => :ELSE,
- 'while' => :WHILE,
- 'then' => :THEN,
- 'do' => :DO,
- 'def' => :DEF,
- 'true' => :TRUE,
- 'false' => :FALSE,
- 'nil' => :NIL,
- 'end' => :END
- }
-
- RESERVED_V = {
- 'true' => true,
- 'false' => false,
- 'nil' => nil
- }
-
- def parse(f, fname)
- @q = []
- @fname = fname
- lineno = 1
- f.each do |line|
- line.strip!
- until line.empty?
- case line
- when /\A\s+/, /\A\#.*/
- ;
- when /\A[a-zA-Z_]\w*/
- word = $&
- @q.push [(RESERVED[word] || :IDENT),
- [lineno, RESERVED_V.key?(word) ? RESERVED_V[word] : word.intern]]
- when /\A\d+/
- @q.push [:NUMBER, [lineno, $&.to_i]]
- when /\A"(?:[^"\\]+|\\.)*"/, /\A'(?:[^'\\]+|\\.)*'/
- @q.push [:STRING, [lineno, eval($&)]]
- when /\A==/
- @q.push [:EQ, [lineno, '==']]
- when /\A./
- @q.push [$&, [lineno, $&]]
- else
- raise RuntimeError, 'must not happen'
- end
- line = $'
- end
- @q.push [:EOL, [lineno, nil]]
- lineno += 1
- end
- @q.push [false, '$']
- do_parse
- end
-
- def next_token
- @q.shift
- end
-
- def on_error(t, v, values)
- if v
- line = v[0]
- v = v[1]
- else
- line = 'last'
- end
- raise Racc::ParseError, "#{@fname}:#{line}: syntax error on #{v.inspect}"
- end
-
----- footer
-# intp/node.rb
-
-module Intp
-
- class IntpError < StandardError; end
- class IntpArgumentError < IntpError; end
-
- class Core
-
- def initialize
- @ftab = {}
- @obj = Object.new
- @stack = []
- @stack.push Frame.new '(toplevel)'
- end
-
- def frame
- @stack[-1]
- end
-
- def define_function(fname, node)
- raise IntpError, "function #{fname} defined twice" if @ftab.key?(fname)
- @ftab[fname] = node
- end
-
- def call_function_or(fname, args)
- call_intp_function_or(fname, args) {
- call_ruby_toplevel_or(fname, args) {
- yield
- }
- }
- end
-
- def call_intp_function_or(fname, args)
- if func = @ftab[fname]
- frame = Frame.new(fname)
- @stack.push frame
- func.call self, frame, args
- @stack.pop
- else
- yield
- end
- end
-
- def call_ruby_toplevel_or(fname, args)
- if @obj.respond_to? fname, true
- @obj.send fname, *args
- else
- yield
- end
- end
-
- end
-
- class Frame
-
- def initialize(fname)
- @fname = fname
- @lvars = {}
- end
-
- attr :fname
-
- def lvar?(name)
- @lvars.key? name
- end
-
- def [](key)
- @lvars[key]
- end
-
- def []=(key, val)
- @lvars[key] = val
- end
-
- end
-
-
- class Node
-
- def initialize(fname, lineno)
- @filename = fname
- @lineno = lineno
- end
-
- attr_reader :filename
- attr_reader :lineno
-
- def exec_list(intp, nodes)
- v = nil
- nodes.each {|i| v = i.evaluate(intp) }
- v
- end
-
- def intp_error!(msg)
- raise IntpError, "in #{filename}:#{lineno}: #{msg}"
- end
-
- def inspect
- "#{self.class.name}/#{lineno}"
- end
-
- end
-
-
- class RootNode < Node
-
- def initialize(tree)
- super nil, nil
- @tree = tree
- end
-
- def evaluate
- exec_list Core.new, @tree
- end
-
- end
-
-
- class DefNode < Node
-
- def initialize(file, lineno, fname, func)
- super file, lineno
- @funcname = fname
- @funcobj = func
- end
-
- def evaluate(intp)
- intp.define_function @funcname, @funcobj
- end
-
- end
-
- class FuncallNode < Node
-
- def initialize(file, lineno, func, args)
- super file, lineno
- @funcname = func
- @args = args
- end
-
- def evaluate(intp)
- args = @args.map {|i| i.evaluate intp }
- begin
- intp.call_intp_function_or(@funcname, args) {
- if args.empty? or not args[0].respond_to?(@funcname)
- intp.call_ruby_toplevel_or(@funcname, args) {
- intp_error! "undefined function #{@funcname.id2name}"
- }
- else
- recv = args.shift
- recv.send @funcname, *args
- end
- }
- rescue IntpArgumentError, ArgumentError
- intp_error! $!.message
- end
- end
-
- end
-
- class Function < Node
-
- def initialize(file, lineno, params, body)
- super file, lineno
- @params = params
- @body = body
- end
-
- def call(intp, frame, args)
- unless args.size == @params.size
- raise IntpArgumentError,
- "wrong # of arg for #{frame.fname}() (#{args.size} for #{@params.size})"
- end
- args.each_with_index do |v,i|
- frame[@params[i]] = v
- end
- exec_list intp, @body
- end
-
- end
-
-
- class IfNode < Node
-
- def initialize(fname, lineno, cond, tstmt, fstmt)
- super fname, lineno
- @condition = cond
- @tstmt = tstmt
- @fstmt = fstmt
- end
-
- def evaluate(intp)
- if @condition.evaluate(intp)
- exec_list intp, @tstmt
- else
- exec_list intp, @fstmt if @fstmt
- end
- end
-
- end
-
- class WhileNode < Node
-
- def initialize(fname, lineno, cond, body)
- super fname, lineno
- @condition = cond
- @body = body
- end
-
- def evaluate(intp)
- while @condition.evaluate(intp)
- exec_list intp, @body
- end
- end
-
- end
-
-
- class AssignNode < Node
-
- def initialize(fname, lineno, vname, val)
- super fname, lineno
- @vname = vname
- @val = val
- end
-
- def evaluate(intp)
- intp.frame[@vname] = @val.evaluate(intp)
- end
-
- end
-
- class VarRefNode < Node
-
- def initialize(fname, lineno, vname)
- super fname, lineno
- @vname = vname
- end
-
- def evaluate(intp)
- if intp.frame.lvar?(@vname)
- intp.frame[@vname]
- else
- intp.call_function_or(@vname, []) {
- intp_error! "unknown method or local variable #{@vname.id2name}"
- }
- end
- end
-
- end
-
- class StringNode < Node
-
- def initialize(fname, lineno, str)
- super fname, lineno
- @val = str
- end
-
- def evaluate(intp)
- @val.dup
- end
-
- end
-
- class LiteralNode < Node
-
- def initialize(fname, lineno, val)
- super fname, lineno
- @val = val
- end
-
- def evaluate(intp)
- @val
- end
-
- end
-
-end # module Intp
-
-begin
- tree = nil
- fname = 'src.intp'
- File.open(fname) {|f|
- tree = Intp::Parser.new.parse(f, fname)
- }
- tree.evaluate
-rescue Racc::ParseError, Intp::IntpError, Errno::ENOENT
- raise ####
- $stderr.puts "#{File.basename $0}: #{$!}"
- exit 1
-end
diff --git a/test/racc/assets/journey.y b/test/racc/assets/journey.y
deleted file mode 100644
index c2640f3339..0000000000
--- a/test/racc/assets/journey.y
+++ /dev/null
@@ -1,47 +0,0 @@
-class Journey::Parser
-
-token SLASH LITERAL SYMBOL LPAREN RPAREN DOT STAR OR
-
-rule
- expressions
- : expressions expression { result = Cat.new(val.first, val.last) }
- | expression { result = val.first }
- | or
- ;
- expression
- : terminal
- | group
- | star
- ;
- group
- : LPAREN expressions RPAREN { result = Group.new(val[1]) }
- ;
- or
- : expressions OR expression { result = Or.new([val.first, val.last]) }
- ;
- star
- : STAR { result = Star.new(Symbol.new(val.last)) }
- ;
- terminal
- : symbol
- | literal
- | slash
- | dot
- ;
- slash
- : SLASH { result = Slash.new('/') }
- ;
- symbol
- : SYMBOL { result = Symbol.new(val.first) }
- ;
- literal
- : LITERAL { result = Literal.new(val.first) }
- dot
- : DOT { result = Dot.new(val.first) }
- ;
-
-end
-
----- header
-
-require 'journey/parser_extras'
diff --git a/test/racc/assets/liquor.y b/test/racc/assets/liquor.y
deleted file mode 100644
index 8045a072a4..0000000000
--- a/test/racc/assets/liquor.y
+++ /dev/null
@@ -1,313 +0,0 @@
-# Copyright (c) 2012-2013 Peter Zotov <whitequark@whitequark.org>
-# 2012 Yaroslav Markin <yaroslav@markin.net>
-# 2012 Nate Gadgibalaev <nat@xnsv.ru>
-#
-# MIT License
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-class Liquor::Parser
- token comma dot endtag ident integer keyword lblock lblock2 lbracket
- linterp lparen op_div op_eq op_gt op_geq op_lt op_leq op_minus
- op_mod op_mul op_neq op_not op_plus pipe plaintext rblock
- rbracket rinterp rparen string tag_ident
-
- prechigh
- left dot
- nonassoc op_uminus op_not
- left op_mul op_div op_mod
- left op_plus op_minus
- left op_eq op_neq op_lt op_leq op_gt op_geq
- left op_and
- left op_or
- preclow
-
- expect 15
-
- start block
-
-rule
- block: /* empty */
- { result = [] }
- | plaintext block
- { result = [ val[0], *val[1] ] }
- | interp block
- { result = [ val[0], *val[1] ] }
- | tag block
- { result = [ val[0], *val[1] ] }
-
- interp:
- linterp expr rinterp
- { result = [ :interp, retag(val), val[1] ] }
- | linterp filter_chain rinterp
- { result = [ :interp, retag(val), val[1] ] }
-
- primary_expr:
- ident
- | lparen expr rparen
- { result = [ val[1][0], retag(val), *val[1][2..-1] ] }
-
- expr:
- integer
- | string
- | tuple
- | ident function_args
- { result = [ :call, retag(val), val[0], val[1] ] }
- | expr lbracket expr rbracket
- { result = [ :index, retag(val), val[0], val[2] ] }
- | expr dot ident function_args
- { result = [ :external, retag(val), val[0], val[2], val[3] ] }
- | expr dot ident
- { result = [ :external, retag(val), val[0], val[2], nil ] }
- | op_minus expr =op_uminus
- { result = [ :uminus, retag(val), val[1] ] }
- | op_not expr
- { result = [ :not, retag(val), val[1] ] }
- | expr op_mul expr
- { result = [ :mul, retag(val), val[0], val[2] ] }
- | expr op_div expr
- { result = [ :div, retag(val), val[0], val[2] ] }
- | expr op_mod expr
- { result = [ :mod, retag(val), val[0], val[2] ] }
- | expr op_plus expr
- { result = [ :plus, retag(val), val[0], val[2] ] }
- | expr op_minus expr
- { result = [ :minus, retag(val), val[0], val[2] ] }
- | expr op_eq expr
- { result = [ :eq, retag(val), val[0], val[2] ] }
- | expr op_neq expr
- { result = [ :neq, retag(val), val[0], val[2] ] }
- | expr op_lt expr
- { result = [ :lt, retag(val), val[0], val[2] ] }
- | expr op_leq expr
- { result = [ :leq, retag(val), val[0], val[2] ] }
- | expr op_gt expr
- { result = [ :gt, retag(val), val[0], val[2] ] }
- | expr op_geq expr
- { result = [ :geq, retag(val), val[0], val[2] ] }
- | expr op_and expr
- { result = [ :and, retag(val), val[0], val[2] ] }
- | expr op_or expr
- { result = [ :or, retag(val), val[0], val[2] ] }
- | primary_expr
-
- tuple:
- lbracket tuple_content rbracket
- { result = [ :tuple, retag(val), val[1].compact ] }
-
- tuple_content:
- expr comma tuple_content
- { result = [ val[0], *val[2] ] }
- | expr
- { result = [ val[0] ] }
- | /* empty */
- { result = [ ] }
-
- function_args:
- lparen function_args_inside rparen
- { result = [ :args, retag(val), *val[1] ] }
-
- function_args_inside:
- expr function_keywords
- { result = [ val[0], val[1][2] ] }
- | function_keywords
- { result = [ nil, val[0][2] ] }
-
- function_keywords:
- keyword expr function_keywords
- { name = val[0][2].to_sym
- tail = val[2][2]
- loc = retag([ val[0], val[1] ])
-
- if tail.include? name
- @errors << SyntaxError.new("duplicate keyword argument `#{val[0][2]}'",
- tail[name][1])
- end
-
- hash = {
- name => [ val[1][0], loc, *val[1][2..-1] ]
- }.merge(tail)
-
- result = [ :keywords, retag([ loc, val[2] ]), hash ]
- }
- | /* empty */
- { result = [ :keywords, nil, {} ] }
-
- filter_chain:
- expr pipe filter_chain_cont
- { result = [ val[0], *val[2] ].
- reduce { |tree, node| node[3][2] = tree; node }
- }
-
- filter_chain_cont:
- filter_call pipe filter_chain_cont
- { result = [ val[0], *val[2] ] }
- | filter_call
- { result = [ val[0] ] }
-
- filter_call:
- ident function_keywords
- { ident_loc = val[0][1]
- empty_args_loc = { line: ident_loc[:line],
- start: ident_loc[:end] + 1,
- end: ident_loc[:end] + 1, }
- result = [ :call, val[0][1], val[0],
- [ :args, val[1][1] || empty_args_loc, nil, val[1][2] ] ]
- }
-
- tag:
- lblock ident expr tag_first_cont
- { result = [ :tag, retag(val), val[1], val[2], *reduce_tag_args(val[3][2]) ] }
- | lblock ident tag_first_cont
- { result = [ :tag, retag(val), val[1], nil, *reduce_tag_args(val[2][2]) ] }
-
- # Racc cannot do lookahead across rules. I had to add states
- # explicitly to avoid S/R conflicts. You are not expected to
- # understand this.
-
- tag_first_cont:
- rblock
- { result = [ :cont, retag(val), [] ] }
- | keyword tag_first_cont2
- { result = [ :cont, retag(val), [ val[0], *val[1][2] ] ] }
-
- tag_first_cont2:
- rblock block lblock2 tag_next_cont
- { result = [ :cont2, val[0][1], [ [:block, val[0][1], val[1] ], *val[3] ] ] }
- | expr tag_first_cont
- { result = [ :cont2, retag(val), [ val[0], *val[1][2] ] ] }
-
- tag_next_cont:
- endtag rblock
- { result = [] }
- | keyword tag_next_cont2
- { result = [ val[0], *val[1] ] }
-
- tag_next_cont2:
- rblock block lblock2 tag_next_cont
- { result = [ [:block, val[0][1], val[1] ], *val[3] ] }
- | expr keyword tag_next_cont3
- { result = [ val[0], val[1], *val[2] ] }
-
- tag_next_cont3:
- rblock block lblock2 tag_next_cont
- { result = [ [:block, val[0][1], val[1] ], *val[3] ] }
- | expr tag_next_cont
- { result = [ val[0], *val[1] ] }
-
----- inner
- attr_reader :errors, :ast
-
- def initialize(tags={})
- super()
-
- @errors = []
- @ast = nil
- @tags = tags
- end
-
- def success?
- @errors.empty?
- end
-
- def parse(string, name='(code)')
- @errors.clear
- @name = name
- @ast = nil
-
- begin
- @stream = Lexer.lex(string, @name, @tags)
- @ast = do_parse
- rescue Liquor::SyntaxError => e
- @errors << e
- end
-
- success?
- end
-
- def next_token
- tok = @stream.shift
- [ tok[0], tok ] if tok
- end
-
- TOKEN_NAME_MAP = {
- :comma => ',',
- :dot => '.',
- :lblock => '{%',
- :rblock => '%}',
- :linterp => '{{',
- :rinterp => '}}',
- :lbracket => '[',
- :rbracket => ']',
- :lparen => '(',
- :rparen => ')',
- :pipe => '|',
- :op_not => '!',
- :op_mul => '*',
- :op_div => '/',
- :op_mod => '%',
- :op_plus => '+',
- :op_minus => '-',
- :op_eq => '==',
- :op_neq => '!=',
- :op_lt => '<',
- :op_leq => '<=',
- :op_gt => '>',
- :op_geq => '>=',
- :keyword => 'keyword argument name',
- :kwarg => 'keyword argument',
- :ident => 'identifier',
- }
-
- def on_error(error_token_id, error_token, value_stack)
- if token_to_str(error_token_id) == "$end"
- raise Liquor::SyntaxError.new("unexpected end of program", {
- file: @name
- })
- else
- type, (loc, value) = error_token
- type = TOKEN_NAME_MAP[type] || type
-
- raise Liquor::SyntaxError.new("unexpected token `#{type}'", loc)
- end
- end
-
- def retag(nodes)
- loc = nodes.map { |node| node[1] }.compact
- first, *, last = loc
- return first if last.nil?
-
- {
- file: first[:file],
- line: first[:line],
- start: first[:start],
- end: last[:end],
- }
- end
-
- def reduce_tag_args(list)
- list.each_slice(2).reduce([]) { |args, (k, v)|
- if v[0] == :block
- args << [ :blockarg, retag([ k, v ]), k, v[2] || [] ]
- else
- args << [ :kwarg, retag([ k, v ]), k, v ]
- end
- }
- end \ No newline at end of file
diff --git a/test/racc/assets/machete.y b/test/racc/assets/machete.y
deleted file mode 100644
index ea92d47a69..0000000000
--- a/test/racc/assets/machete.y
+++ /dev/null
@@ -1,423 +0,0 @@
-# Copyright (c) 2011 SUSE
-#
-# Permission is hereby granted, free of charge, to any person
-# obtaining a copy of this software and associated documentation
-# files (the "Software"), to deal in the Software without
-# restriction, including without limitation the rights to use,
-# copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the
-# Software is furnished to do so, subject to the following
-# conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-# OTHER DEALINGS IN THE SOFTWARE.
-
-class Machete::Parser
-
-token NIL
-token TRUE
-token FALSE
-token INTEGER
-token SYMBOL
-token STRING
-token REGEXP
-token ANY
-token EVEN
-token ODD
-token METHOD_NAME
-token CLASS_NAME
-
-start expression
-
-rule
-
-expression : primary
- | expression "|" primary {
- result = if val[0].is_a?(ChoiceMatcher)
- ChoiceMatcher.new(val[0].alternatives << val[2])
- else
- ChoiceMatcher.new([val[0], val[2]])
- end
- }
-
-primary : node
- | array
- | literal
- | any
-
-node : CLASS_NAME {
- result = NodeMatcher.new(val[0].to_sym)
- }
- | CLASS_NAME "<" attrs ">" {
- result = NodeMatcher.new(val[0].to_sym, val[2])
- }
-
-attrs : attr
- | attrs "," attr { result = val[0].merge(val[2]) }
-
-attr : method_name "=" expression { result = { val[0].to_sym => val[2] } }
- | method_name "^=" SYMBOL {
- result = {
- val[0].to_sym => SymbolRegexpMatcher.new(
- Regexp.new("^" + Regexp.escape(symbol_value(val[2]).to_s))
- )
- }
- }
- | method_name "$=" SYMBOL {
- result = {
- val[0].to_sym => SymbolRegexpMatcher.new(
- Regexp.new(Regexp.escape(symbol_value(val[2]).to_s) + "$")
- )
- }
- }
- | method_name "*=" SYMBOL {
- result = {
- val[0].to_sym => SymbolRegexpMatcher.new(
- Regexp.new(Regexp.escape(symbol_value(val[2]).to_s))
- )
- }
- }
- | method_name "^=" STRING {
- result = {
- val[0].to_sym => StringRegexpMatcher.new(
- Regexp.new("^" + Regexp.escape(string_value(val[2])))
- )
- }
- }
- | method_name "$=" STRING {
- result = {
- val[0].to_sym => StringRegexpMatcher.new(
- Regexp.new(Regexp.escape(string_value(val[2])) + "$")
- )
- }
- }
- | method_name "*=" STRING {
- result = {
- val[0].to_sym => StringRegexpMatcher.new(
- Regexp.new(Regexp.escape(string_value(val[2])))
- )
- }
- }
- | method_name "*=" REGEXP {
- result = {
- val[0].to_sym => IndifferentRegexpMatcher.new(
- Regexp.new(regexp_value(val[2]))
- )
- }
- }
-
-# Hack to overcome the fact that some tokens will lex as simple tokens, not
-# METHOD_NAME tokens, and that "reserved words" will lex as separate kinds of
-# tokens.
-method_name : METHOD_NAME
- | NIL
- | TRUE
- | FALSE
- | ANY
- | EVEN
- | ODD
- | "*"
- | "+"
- | "<"
- | ">"
- | "^"
- | "|"
-
-array : "[" items_opt "]" { result = ArrayMatcher.new(val[1]) }
-
-items_opt : /* empty */ { result = [] }
- | items
-
-items : item { result = [val[0]] }
- | items "," item { result = val[0] << val[2] }
-
-item : expression
- | expression quantifier { result = Quantifier.new(val[0], *val[1]) }
-
-quantifier : "*" { result = [0, nil, 1] }
- | "+" { result = [1, nil, 1] }
- | "?" { result = [0, 1, 1] }
- | "{" INTEGER "}" {
- result = [integer_value(val[1]), integer_value(val[1]), 1]
- }
- | "{" INTEGER "," "}" {
- result = [integer_value(val[1]), nil, 1]
- }
- | "{" "," INTEGER "}" {
- result = [0, integer_value(val[2]), 1]
- }
- | "{" INTEGER "," INTEGER "}" {
- result = [integer_value(val[1]), integer_value(val[3]), 1]
- }
- | "{" EVEN "}" { result = [0, nil, 2] }
- | "{" ODD "}" { result = [1, nil, 2] }
-
-literal : NIL { result = LiteralMatcher.new(nil) }
- | TRUE { result = LiteralMatcher.new(true) }
- | FALSE { result = LiteralMatcher.new(false) }
- | INTEGER { result = LiteralMatcher.new(integer_value(val[0])) }
- | SYMBOL { result = LiteralMatcher.new(symbol_value(val[0])) }
- | STRING { result = LiteralMatcher.new(string_value(val[0])) }
- | REGEXP { result = LiteralMatcher.new(regexp_value(val[0])) }
-
-any : ANY { result = AnyMatcher.new }
-
----- inner
-
-include Matchers
-
-class SyntaxError < StandardError; end
-
-def parse(input)
- @input = input
- @pos = 0
-
- do_parse
-end
-
-private
-
-def integer_value(value)
- if value =~ /^0[bB]/
- value[2..-1].to_i(2)
- elsif value =~ /^0[oO]/
- value[2..-1].to_i(8)
- elsif value =~ /^0[dD]/
- value[2..-1].to_i(10)
- elsif value =~ /^0[xX]/
- value[2..-1].to_i(16)
- elsif value =~ /^0/
- value.to_i(8)
- else
- value.to_i
- end
-end
-
-def symbol_value(value)
- value[1..-1].to_sym
-end
-
-def string_value(value)
- quote = value[0..0]
- if quote == "'"
- value[1..-2].gsub("\\\\", "\\").gsub("\\'", "'")
- elsif quote == '"'
- value[1..-2].
- gsub("\\\\", "\\").
- gsub('\\"', '"').
- gsub("\\n", "\n").
- gsub("\\t", "\t").
- gsub("\\r", "\r").
- gsub("\\f", "\f").
- gsub("\\v", "\v").
- gsub("\\a", "\a").
- gsub("\\e", "\e").
- gsub("\\b", "\b").
- gsub("\\s", "\s").
- gsub(/\\([0-7]{1,3})/) { $1.to_i(8).chr }.
- gsub(/\\x([0-9a-fA-F]{1,2})/) { $1.to_i(16).chr }
- else
- raise "Unknown quote: #{quote.inspect}."
- end
-end
-
-REGEXP_OPTIONS = {
- 'i' => Regexp::IGNORECASE,
- 'm' => Regexp::MULTILINE,
- 'x' => Regexp::EXTENDED
-}
-
-def regexp_value(value)
- /\A\/(.*)\/([imx]*)\z/ =~ value
- pattern, options = $1, $2
-
- Regexp.new(pattern, options.chars.map { |ch| REGEXP_OPTIONS[ch] }.inject(:|))
-end
-
-# "^" needs to be here because if it were among operators recognized by
-# METHOD_NAME, "^=" would be recognized as two tokens.
-SIMPLE_TOKENS = [
- "|",
- "<",
- ">",
- ",",
- "=",
- "^=",
- "^",
- "$=",
- "[",
- "]",
- "*=",
- "*",
- "+",
- "?",
- "{",
- "}"
-]
-
-COMPLEX_TOKENS = [
- [:NIL, /^nil/],
- [:TRUE, /^true/],
- [:FALSE, /^false/],
- # INTEGER needs to be before METHOD_NAME, otherwise e.g. "+1" would be
- # recognized as two tokens.
- [
- :INTEGER,
- /^
- [+-]? # sign
- (
- 0[bB][01]+(_[01]+)* # binary (prefixed)
- |
- 0[oO][0-7]+(_[0-7]+)* # octal (prefixed)
- |
- 0[dD]\d+(_\d+)* # decimal (prefixed)
- |
- 0[xX][0-9a-fA-F]+(_[0-9a-fA-F]+)* # hexadecimal (prefixed)
- |
- 0[0-7]*(_[0-7]+)* # octal (unprefixed)
- |
- [1-9]\d*(_\d+)* # decimal (unprefixed)
- )
- /x
- ],
- [
- :SYMBOL,
- /^
- :
- (
- # class name
- [A-Z][a-zA-Z0-9_]*
- |
- # regular method name
- [a-z_][a-zA-Z0-9_]*[?!=]?
- |
- # instance variable name
- @[a-zA-Z_][a-zA-Z0-9_]*
- |
- # class variable name
- @@[a-zA-Z_][a-zA-Z0-9_]*
- |
- # operator (sorted by length, then alphabetically)
- (<=>|===|\[\]=|\*\*|\+@|-@|<<|<=|==|=~|>=|>>|\[\]|[%&*+\-\/<>^`|~])
- )
- /x
- ],
- [
- :STRING,
- /^
- (
- ' # sinqle-quoted string
- (
- \\[\\'] # escape
- |
- [^'] # regular character
- )*
- '
- |
- " # double-quoted string
- (
- \\ # escape
- (
- [\\"ntrfvaebs] # one-character escape
- |
- [0-7]{1,3} # octal number escape
- |
- x[0-9a-fA-F]{1,2} # hexadecimal number escape
- )
- |
- [^"] # regular character
- )*
- "
- )
- /x
- ],
- [
- :REGEXP,
- /^
- \/
- (
- \\ # escape
- (
- [\\\/ntrfvaebs\(\)\[\]\{\}\-\.\?\*\+\|\^\$] # one-character escape
- |
- [0-7]{2,3} # octal number escape
- |
- x[0-9a-fA-F]{1,2} # hexadecimal number escape
- )
- |
- [^\/] # regular character
- )*
- \/
- [imx]*
- /x
- ],
- # ANY, EVEN and ODD need to be before METHOD_NAME, otherwise they would be
- # recognized as method names.
- [:ANY, /^any/],
- [:EVEN, /^even/],
- [:ODD, /^odd/],
- # We exclude "*", "+", "<", ">", "^" and "|" from method names since they are
- # lexed as simple tokens. This is because they have also other meanings in
- # Machette patterns beside Ruby method names.
- [
- :METHOD_NAME,
- /^
- (
- # regular name
- [a-z_][a-zA-Z0-9_]*[?!=]?
- |
- # operator (sorted by length, then alphabetically)
- (<=>|===|\[\]=|\*\*|\+@|-@|<<|<=|==|=~|>=|>>|\[\]|[%&\-\/`~])
- )
- /x
- ],
- [:CLASS_NAME, /^[A-Z][a-zA-Z0-9_]*/]
-]
-
-def next_token
- skip_whitespace
-
- return false if remaining_input.empty?
-
- # Complex tokens need to be before simple tokens, otherwise e.g. "<<" would be
- # recognized as two tokens.
-
- COMPLEX_TOKENS.each do |type, regexp|
- if remaining_input =~ regexp
- @pos += $&.length
- return [type, $&]
- end
- end
-
- SIMPLE_TOKENS.each do |token|
- if remaining_input[0...token.length] == token
- @pos += token.length
- return [token, token]
- end
- end
-
- raise SyntaxError, "Unexpected character: #{remaining_input[0..0].inspect}."
-end
-
-def skip_whitespace
- if remaining_input =~ /\A^[ \t\r\n]+/
- @pos += $&.length
- end
-end
-
-def remaining_input
- @input[@pos..-1]
-end
-
-def on_error(error_token_id, error_value, value_stack)
- raise SyntaxError, "Unexpected token: #{error_value.inspect}."
-end
diff --git a/test/racc/assets/macruby.y b/test/racc/assets/macruby.y
deleted file mode 100644
index 5ede008308..0000000000
--- a/test/racc/assets/macruby.y
+++ /dev/null
@@ -1,2197 +0,0 @@
-# Copyright (c) 2013 Peter Zotov <whitequark@whitequark.org>
-#
-# Parts of the source are derived from ruby_parser:
-# Copyright (c) Ryan Davis, seattle.rb
-#
-# MIT License
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-class Parser::MacRuby
-
-token kCLASS kMODULE kDEF kUNDEF kBEGIN kRESCUE kENSURE kEND kIF kUNLESS
- kTHEN kELSIF kELSE kCASE kWHEN kWHILE kUNTIL kFOR kBREAK kNEXT
- kREDO kRETRY kIN kDO kDO_COND kDO_BLOCK kDO_LAMBDA kRETURN kYIELD kSUPER
- kSELF kNIL kTRUE kFALSE kAND kOR kNOT kIF_MOD kUNLESS_MOD kWHILE_MOD
- kUNTIL_MOD kRESCUE_MOD kALIAS kDEFINED klBEGIN klEND k__LINE__
- k__FILE__ k__ENCODING__ tIDENTIFIER tFID tGVAR tIVAR tCONSTANT
- tLABEL tCVAR tNTH_REF tBACK_REF tSTRING_CONTENT tINTEGER tFLOAT
- tREGEXP_END tUPLUS tUMINUS tUMINUS_NUM tPOW tCMP tEQ tEQQ tNEQ
- tGEQ tLEQ tANDOP tOROP tMATCH tNMATCH tDOT tDOT2 tDOT3 tAREF
- tASET tLSHFT tRSHFT tCOLON2 tCOLON3 tOP_ASGN tASSOC tLPAREN
- tLPAREN2 tRPAREN tLPAREN_ARG tLBRACK tLBRACK2 tRBRACK tLBRACE
- tLBRACE_ARG tSTAR tSTAR2 tAMPER tAMPER2 tTILDE tPERCENT tDIVIDE
- tPLUS tMINUS tLT tGT tPIPE tBANG tCARET tLCURLY tRCURLY
- tBACK_REF2 tSYMBEG tSTRING_BEG tXSTRING_BEG tREGEXP_BEG tREGEXP_OPT
- tWORDS_BEG tQWORDS_BEG tSTRING_DBEG tSTRING_DVAR tSTRING_END
- tSTRING tSYMBOL tNL tEH tCOLON tCOMMA tSPACE tSEMI tLAMBDA tLAMBEG
- tCHARACTER
-
-prechigh
- right tBANG tTILDE tUPLUS
- right tPOW
- right tUMINUS_NUM tUMINUS
- left tSTAR2 tDIVIDE tPERCENT
- left tPLUS tMINUS
- left tLSHFT tRSHFT
- left tAMPER2
- left tPIPE tCARET
- left tGT tGEQ tLT tLEQ
- nonassoc tCMP tEQ tEQQ tNEQ tMATCH tNMATCH
- left tANDOP
- left tOROP
- nonassoc tDOT2 tDOT3
- right tEH tCOLON
- left kRESCUE_MOD
- right tEQL tOP_ASGN
- nonassoc kDEFINED
- right kNOT
- left kOR kAND
- nonassoc kIF_MOD kUNLESS_MOD kWHILE_MOD kUNTIL_MOD
- nonassoc tLBRACE_ARG
- nonassoc tLOWEST
-preclow
-
-rule
-
- program: top_compstmt
-
- top_compstmt: top_stmts opt_terms
- {
- result = @builder.compstmt(val[0])
- }
-
- top_stmts: # nothing
- {
- result = []
- }
- | top_stmt
- {
- result = [ val[0] ]
- }
- | top_stmts terms top_stmt
- {
- result = val[0] << val[2]
- }
- | error top_stmt
- {
- result = [ val[1] ]
- }
-
- top_stmt: stmt
- | klBEGIN tLCURLY top_compstmt tRCURLY
- {
- result = @builder.preexe(val[0], val[1], val[2], val[3])
- }
-
- bodystmt: compstmt opt_rescue opt_else opt_ensure
- {
- rescue_bodies = val[1]
- else_t, else_ = val[2]
- ensure_t, ensure_ = val[3]
-
- if rescue_bodies.empty? && !else_.nil?
- diagnostic :warning, :useless_else, nil, else_t
- end
-
- result = @builder.begin_body(val[0],
- rescue_bodies,
- else_t, else_,
- ensure_t, ensure_)
- }
-
- compstmt: stmts opt_terms
- {
- result = @builder.compstmt(val[0])
- }
-
- stmts: # nothing
- {
- result = []
- }
- | stmt
- {
- result = [ val[0] ]
- }
- | stmts terms stmt
- {
- result = val[0] << val[2]
- }
- | error stmt
- {
- result = [ val[1] ]
- }
-
- stmt: kALIAS fitem
- {
- @lexer.state = :expr_fname
- }
- fitem
- {
- result = @builder.alias(val[0], val[1], val[3])
- }
- | kALIAS tGVAR tGVAR
- {
- result = @builder.alias(val[0],
- @builder.gvar(val[1]),
- @builder.gvar(val[2]))
- }
- | kALIAS tGVAR tBACK_REF
- {
- result = @builder.alias(val[0],
- @builder.gvar(val[1]),
- @builder.back_ref(val[2]))
- }
- | kALIAS tGVAR tNTH_REF
- {
- diagnostic :error, :nth_ref_alias, nil, val[2]
- }
- | kUNDEF undef_list
- {
- result = @builder.undef_method(val[0], val[1])
- }
- | stmt kIF_MOD expr_value
- {
- result = @builder.condition_mod(val[0], nil,
- val[1], val[2])
- }
- | stmt kUNLESS_MOD expr_value
- {
- result = @builder.condition_mod(nil, val[0],
- val[1], val[2])
- }
- | stmt kWHILE_MOD expr_value
- {
- result = @builder.loop_mod(:while, val[0], val[1], val[2])
- }
- | stmt kUNTIL_MOD expr_value
- {
- result = @builder.loop_mod(:until, val[0], val[1], val[2])
- }
- | stmt kRESCUE_MOD stmt
- {
- rescue_body = @builder.rescue_body(val[1],
- nil, nil, nil,
- nil, val[2])
-
- result = @builder.begin_body(val[0], [ rescue_body ])
- }
- | klEND tLCURLY compstmt tRCURLY
- {
- result = @builder.postexe(val[0], val[1], val[2], val[3])
- }
- | lhs tEQL command_call
- {
- result = @builder.assign(val[0], val[1], val[2])
- }
- | mlhs tEQL command_call
- {
- result = @builder.multi_assign(val[0], val[1], val[2])
- }
- | var_lhs tOP_ASGN command_call
- {
- result = @builder.op_assign(val[0], val[1], val[2])
- }
- | primary_value tLBRACK2 opt_call_args rbracket tOP_ASGN command_call
- {
- result = @builder.op_assign(
- @builder.index(
- val[0], val[1], val[2], val[3]),
- val[4], val[5])
- }
- | primary_value tDOT tIDENTIFIER tOP_ASGN command_call
- {
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
- }
- | primary_value tDOT tCONSTANT tOP_ASGN command_call
- {
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
- }
- | primary_value tCOLON2 tCONSTANT tOP_ASGN command_call
- {
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
- }
- | primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_call
- {
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
- }
- | backref tOP_ASGN command_call
- {
- @builder.op_assign(val[0], val[1], val[2])
- }
- | lhs tEQL mrhs
- {
- result = @builder.assign(val[0], val[1],
- @builder.array(nil, val[2], nil))
- }
- | mlhs tEQL arg_value
- {
- result = @builder.multi_assign(val[0], val[1], val[2])
- }
- | mlhs tEQL mrhs
- {
- result = @builder.multi_assign(val[0], val[1],
- @builder.array(nil, val[2], nil))
- }
- | expr
-
- expr: command_call
- | expr kAND expr
- {
- result = @builder.logical_op(:and, val[0], val[1], val[2])
- }
- | expr kOR expr
- {
- result = @builder.logical_op(:or, val[0], val[1], val[2])
- }
- | kNOT opt_nl expr
- {
- result = @builder.not_op(val[0], nil, val[2], nil)
- }
- | tBANG command_call
- {
- result = @builder.not_op(val[0], nil, val[1], nil)
- }
- | arg
-
- expr_value: expr
-
- command_call: command
- | block_command
-
- block_command: block_call
- | block_call tDOT operation2 command_args
- {
- result = @builder.call_method(val[0], val[1], val[2],
- *val[3])
- }
- | block_call tCOLON2 operation2 command_args
- {
- result = @builder.call_method(val[0], val[1], val[2],
- *val[3])
- }
-
- cmd_brace_block: tLBRACE_ARG
- {
- @static_env.extend_dynamic
- }
- opt_block_param compstmt tRCURLY
- {
- result = [ val[0], val[2], val[3], val[4] ]
-
- @static_env.unextend
- }
-
- command: operation command_args =tLOWEST
- {
- result = @builder.call_method(nil, nil, val[0],
- *val[1])
- }
- | operation command_args cmd_brace_block
- {
- method_call = @builder.call_method(nil, nil, val[0],
- *val[1])
-
- begin_t, args, body, end_t = val[2]
- result = @builder.block(method_call,
- begin_t, args, body, end_t)
- }
- | primary_value tDOT operation2 command_args =tLOWEST
- {
- result = @builder.call_method(val[0], val[1], val[2],
- *val[3])
- }
- | primary_value tDOT operation2 command_args cmd_brace_block
- {
- method_call = @builder.call_method(val[0], val[1], val[2],
- *val[3])
-
- begin_t, args, body, end_t = val[4]
- result = @builder.block(method_call,
- begin_t, args, body, end_t)
- }
- | primary_value tCOLON2 operation2 command_args =tLOWEST
- {
- result = @builder.call_method(val[0], val[1], val[2],
- *val[3])
- }
- | primary_value tCOLON2 operation2 command_args cmd_brace_block
- {
- method_call = @builder.call_method(val[0], val[1], val[2],
- *val[3])
-
- begin_t, args, body, end_t = val[4]
- result = @builder.block(method_call,
- begin_t, args, body, end_t)
- }
- | kSUPER command_args
- {
- result = @builder.keyword_cmd(:super, val[0],
- *val[1])
- }
- | kYIELD command_args
- {
- result = @builder.keyword_cmd(:yield, val[0],
- *val[1])
- }
- | kRETURN call_args
- {
- result = @builder.keyword_cmd(:return, val[0],
- nil, val[1], nil)
- }
- | kBREAK call_args
- {
- result = @builder.keyword_cmd(:break, val[0],
- nil, val[1], nil)
- }
- | kNEXT call_args
- {
- result = @builder.keyword_cmd(:next, val[0],
- nil, val[1], nil)
- }
-
- mlhs: mlhs_basic
- {
- result = @builder.multi_lhs(nil, val[0], nil)
- }
- | tLPAREN mlhs_inner rparen
- {
- result = @builder.begin(val[0], val[1], val[2])
- }
-
- mlhs_inner: mlhs_basic
- {
- result = @builder.multi_lhs(nil, val[0], nil)
- }
- | tLPAREN mlhs_inner rparen
- {
- result = @builder.multi_lhs(val[0], val[1], val[2])
- }
-
- mlhs_basic: mlhs_head
- | mlhs_head mlhs_item
- {
- result = val[0].
- push(val[1])
- }
- | mlhs_head tSTAR mlhs_node
- {
- result = val[0].
- push(@builder.splat(val[1], val[2]))
- }
- | mlhs_head tSTAR mlhs_node tCOMMA mlhs_post
- {
- result = val[0].
- push(@builder.splat(val[1], val[2])).
- concat(val[4])
- }
- | mlhs_head tSTAR
- {
- result = val[0].
- push(@builder.splat(val[1]))
- }
- | mlhs_head tSTAR tCOMMA mlhs_post
- {
- result = val[0].
- push(@builder.splat(val[1])).
- concat(val[3])
- }
- | tSTAR mlhs_node
- {
- result = [ @builder.splat(val[0], val[1]) ]
- }
- | tSTAR mlhs_node tCOMMA mlhs_post
- {
- result = [ @builder.splat(val[0], val[1]),
- *val[3] ]
- }
- | tSTAR
- {
- result = [ @builder.splat(val[0]) ]
- }
- | tSTAR tCOMMA mlhs_post
- {
- result = [ @builder.splat(val[0]),
- *val[2] ]
- }
-
- mlhs_item: mlhs_node
- | tLPAREN mlhs_inner rparen
- {
- result = @builder.begin(val[0], val[1], val[2])
- }
-
- mlhs_head: mlhs_item tCOMMA
- {
- result = [ val[0] ]
- }
- | mlhs_head mlhs_item tCOMMA
- {
- result = val[0] << val[1]
- }
-
- mlhs_post: mlhs_item
- {
- result = [ val[0] ]
- }
- | mlhs_post tCOMMA mlhs_item
- {
- result = val[0] << val[2]
- }
-
- mlhs_node: variable
- {
- result = @builder.assignable(val[0])
- }
- | primary_value tLBRACK2 opt_call_args rbracket
- {
- result = @builder.index_asgn(val[0], val[1], val[2], val[3])
- }
- | primary_value tDOT tIDENTIFIER
- {
- result = @builder.attr_asgn(val[0], val[1], val[2])
- }
- | primary_value tCOLON2 tIDENTIFIER
- {
- result = @builder.attr_asgn(val[0], val[1], val[2])
- }
- | primary_value tDOT tCONSTANT
- {
- result = @builder.attr_asgn(val[0], val[1], val[2])
- }
- | primary_value tCOLON2 tCONSTANT
- {
- result = @builder.assignable(
- @builder.const_fetch(val[0], val[1], val[2]))
- }
- | tCOLON3 tCONSTANT
- {
- result = @builder.assignable(
- @builder.const_global(val[0], val[1]))
- }
- | backref
- {
- result = @builder.assignable(val[0])
- }
-
- lhs: variable
- {
- result = @builder.assignable(val[0])
- }
- | primary_value tLBRACK2 opt_call_args rbracket
- {
- result = @builder.index_asgn(val[0], val[1], val[2], val[3])
- }
- | primary_value tDOT tIDENTIFIER
- {
- result = @builder.attr_asgn(val[0], val[1], val[2])
- }
- | primary_value tCOLON2 tIDENTIFIER
- {
- result = @builder.attr_asgn(val[0], val[1], val[2])
- }
- | primary_value tDOT tCONSTANT
- {
- result = @builder.attr_asgn(val[0], val[1], val[2])
- }
- | primary_value tCOLON2 tCONSTANT
- {
- result = @builder.assignable(
- @builder.const_fetch(val[0], val[1], val[2]))
- }
- | tCOLON3 tCONSTANT
- {
- result = @builder.assignable(
- @builder.const_global(val[0], val[1]))
- }
- | backref
- {
- result = @builder.assignable(val[0])
- }
-
- cname: tIDENTIFIER
- {
- diagnostic :error, :module_name_const, nil, val[0]
- }
- | tCONSTANT
-
- cpath: tCOLON3 cname
- {
- result = @builder.const_global(val[0], val[1])
- }
- | cname
- {
- result = @builder.const(val[0])
- }
- | primary_value tCOLON2 cname
- {
- result = @builder.const_fetch(val[0], val[1], val[2])
- }
-
- fname: tIDENTIFIER | tCONSTANT | tFID
- | op
- | reswords
-
- fsym: fname
- {
- result = @builder.symbol(val[0])
- }
- | symbol
-
- fitem: fsym
- | dsym
-
- undef_list: fitem
- {
- result = [ val[0] ]
- }
- | undef_list tCOMMA
- {
- @lexer.state = :expr_fname
- }
- fitem
- {
- result = val[0] << val[3]
- }
-
- op: tPIPE | tCARET | tAMPER2 | tCMP | tEQ | tEQQ
- | tMATCH | tNMATCH | tGT | tGEQ | tLT | tLEQ
- | tNEQ | tLSHFT | tRSHFT | tPLUS | tMINUS | tSTAR2
- | tSTAR | tDIVIDE | tPERCENT | tPOW | tBANG | tTILDE
- | tUPLUS | tUMINUS | tAREF | tASET | tBACK_REF2
-
- reswords: k__LINE__ | k__FILE__ | k__ENCODING__ | klBEGIN | klEND
- | kALIAS | kAND | kBEGIN | kBREAK | kCASE
- | kCLASS | kDEF | kDEFINED | kDO | kELSE
- | kELSIF | kEND | kENSURE | kFALSE | kFOR
- | kIN | kMODULE | kNEXT | kNIL | kNOT
- | kOR | kREDO | kRESCUE | kRETRY | kRETURN
- | kSELF | kSUPER | kTHEN | kTRUE | kUNDEF
- | kWHEN | kYIELD | kIF | kUNLESS | kWHILE
- | kUNTIL
-
- arg: lhs tEQL arg
- {
- result = @builder.assign(val[0], val[1], val[2])
- }
- | lhs tEQL arg kRESCUE_MOD arg
- {
- rescue_body = @builder.rescue_body(val[3],
- nil, nil, nil,
- nil, val[4])
-
- rescue_ = @builder.begin_body(val[2], [ rescue_body ])
-
- result = @builder.assign(val[0], val[1], rescue_)
- }
- | var_lhs tOP_ASGN arg
- {
- result = @builder.op_assign(val[0], val[1], val[2])
- }
- | var_lhs tOP_ASGN arg kRESCUE_MOD arg
- {
- rescue_body = @builder.rescue_body(val[3],
- nil, nil, nil,
- nil, val[4])
-
- rescue_ = @builder.begin_body(val[2], [ rescue_body ])
-
- result = @builder.op_assign(val[0], val[1], rescue_)
- }
- | primary_value tLBRACK2 opt_call_args rbracket tOP_ASGN arg
- {
- result = @builder.op_assign(
- @builder.index(
- val[0], val[1], val[2], val[3]),
- val[4], val[5])
- }
- | primary_value tDOT tIDENTIFIER tOP_ASGN arg
- {
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
- }
- | primary_value tDOT tCONSTANT tOP_ASGN arg
- {
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
- }
- | primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg
- {
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
- }
- | primary_value tCOLON2 tCONSTANT tOP_ASGN arg
- {
- diagnostic :error, :dynamic_const, nil, val[2], [ val[3] ]
- }
- | tCOLON3 tCONSTANT tOP_ASGN arg
- {
- diagnostic :error, :dynamic_const, nil, val[1], [ val[2] ]
- }
- | backref tOP_ASGN arg
- {
- result = @builder.op_assign(val[0], val[1], val[2])
- }
- | arg tDOT2 arg
- {
- result = @builder.range_inclusive(val[0], val[1], val[2])
- }
- | arg tDOT3 arg
- {
- result = @builder.range_exclusive(val[0], val[1], val[2])
- }
- | arg tPLUS arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tMINUS arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tSTAR2 arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tDIVIDE arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tPERCENT arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tPOW arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | tUMINUS_NUM tINTEGER tPOW arg
- {
- result = @builder.unary_op(val[0],
- @builder.binary_op(
- @builder.integer(val[1]),
- val[2], val[3]))
- }
- | tUMINUS_NUM tFLOAT tPOW arg
- {
- result = @builder.unary_op(val[0],
- @builder.binary_op(
- @builder.float(val[1]),
- val[2], val[3]))
- }
- | tUPLUS arg
- {
- result = @builder.unary_op(val[0], val[1])
- }
- | tUMINUS arg
- {
- result = @builder.unary_op(val[0], val[1])
- }
- | arg tPIPE arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tCARET arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tAMPER2 arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tCMP arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tGT arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tGEQ arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tLT arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tLEQ arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tEQ arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tEQQ arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tNEQ arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tMATCH arg
- {
- result = @builder.match_op(val[0], val[1], val[2])
- }
- | arg tNMATCH arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | tBANG arg
- {
- result = @builder.not_op(val[0], nil, val[1], nil)
- }
- | tTILDE arg
- {
- result = @builder.unary_op(val[0], val[1])
- }
- | arg tLSHFT arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tRSHFT arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tANDOP arg
- {
- result = @builder.logical_op(:and, val[0], val[1], val[2])
- }
- | arg tOROP arg
- {
- result = @builder.logical_op(:or, val[0], val[1], val[2])
- }
- | kDEFINED opt_nl arg
- {
- result = @builder.keyword_cmd(:defined?, val[0], nil, [ val[2] ], nil)
- }
-
- | arg tEH arg opt_nl tCOLON arg
- {
- result = @builder.ternary(val[0], val[1],
- val[2], val[4], val[5])
- }
- | primary
-
- arg_value: arg
-
- aref_args: none
- | args trailer
- | args tCOMMA assocs trailer
- {
- result = val[0] << @builder.associate(nil, val[2], nil)
- }
- | assocs trailer
- {
- result = [ @builder.associate(nil, val[0], nil) ]
- }
-
- paren_args: tLPAREN2 opt_call_args rparen
- {
- result = val
- }
-
- opt_paren_args: # nothing
- {
- result = [ nil, [], nil ]
- }
- | paren_args
-
- opt_call_args: # nothing
- {
- result = []
- }
- | call_args
-
- call_args: command
- {
- result = [ val[0] ]
- }
- | args opt_block_arg
- {
- result = val[0].concat(val[1])
- }
- | assocs opt_block_arg
- {
- result = [ @builder.associate(nil, val[0], nil) ]
- result.concat(val[1])
- }
- | args tCOMMA assocs opt_block_arg
- {
- assocs = @builder.associate(nil, val[2], nil)
- result = val[0] << assocs
- result.concat(val[3])
- }
- | args tCOMMA assocs tCOMMA args opt_block_arg
- {
- val[2][-1] = @builder.objc_varargs(val[2][-1], val[4])
- assocs = @builder.associate(nil, val[2], nil)
- result = val[0] << assocs
- result.concat(val[5])
- }
- | block_arg
- {
- result = [ val[0] ]
- }
-
- call_args2: arg_value tCOMMA args opt_block_arg
- {
- result = [ val[0], *val[2].concat(val[3]) ]
- }
- | arg_value tCOMMA block_arg
- {
- result = [ val[0], val[2] ]
- }
- | assocs opt_block_arg
- {
- result = [ @builder.associate(nil, val[0], nil),
- *val[1] ]
- }
- | arg_value tCOMMA assocs opt_block_arg
- {
- result = [ val[0],
- @builder.associate(nil, val[2], nil),
- *val[3] ]
- }
- | arg_value tCOMMA args tCOMMA assocs opt_block_arg
- {
- result = [ val[0],
- *val[2].
- push(@builder.associate(nil, val[4], nil)).
- concat(val[5]) ]
- }
- | block_arg
- {
- result = [ val[0] ]
- }
-
- command_args: {
- result = @lexer.cmdarg.dup
- @lexer.cmdarg.push(true)
- }
- open_args
- {
- @lexer.cmdarg = val[0]
-
- result = val[1]
- }
-
- open_args: call_args
- {
- result = [ nil, val[0], nil ]
- }
- | tLPAREN_ARG
- {
- @lexer.state = :expr_endarg
- }
- rparen
- {
- result = [ val[0], [], val[2] ]
- }
- | tLPAREN_ARG call_args2
- {
- @lexer.state = :expr_endarg
- }
- rparen
- {
- result = [ val[0], val[1], val[3] ]
- }
-
- block_arg: tAMPER arg_value
- {
- result = @builder.block_pass(val[0], val[1])
- }
-
- opt_block_arg: tCOMMA block_arg
- {
- result = [ val[1] ]
- }
- | tCOMMA
- {
- result = []
- }
- | # nothing
- {
- result = []
- }
-
- args: arg_value
- {
- result = [ val[0] ]
- }
- | tSTAR arg_value
- {
- result = [ @builder.splat(val[0], val[1]) ]
- }
- | args tCOMMA arg_value
- {
- result = val[0] << val[2]
- }
- | args tCOMMA tSTAR arg_value
- {
- result = val[0] << @builder.splat(val[2], val[3])
- }
-
- mrhs: args tCOMMA arg_value
- {
- result = val[0] << val[2]
- }
- | args tCOMMA tSTAR arg_value
- {
- result = val[0] << @builder.splat(val[2], val[3])
- }
- | tSTAR arg_value
- {
- result = [ @builder.splat(val[0], val[1]) ]
- }
-
- primary: literal
- | strings
- | xstring
- | regexp
- | words
- | qwords
- | var_ref
- | backref
- | tFID
- {
- result = @builder.call_method(nil, nil, val[0])
- }
- | kBEGIN bodystmt kEND
- {
- result = @builder.begin_keyword(val[0], val[1], val[2])
- }
- | tLPAREN_ARG expr
- {
- @lexer.state = :expr_endarg
- }
- rparen
- {
- result = @builder.begin(val[0], val[1], val[3])
- }
- | tLPAREN compstmt tRPAREN
- {
- result = @builder.begin(val[0], val[1], val[2])
- }
- | primary_value tCOLON2 tCONSTANT
- {
- result = @builder.const_fetch(val[0], val[1], val[2])
- }
- | tCOLON3 tCONSTANT
- {
- result = @builder.const_global(val[0], val[1])
- }
- | tLBRACK aref_args tRBRACK
- {
- result = @builder.array(val[0], val[1], val[2])
- }
- | tLBRACE assoc_list tRCURLY
- {
- result = @builder.associate(val[0], val[1], val[2])
- }
- | kRETURN
- {
- result = @builder.keyword_cmd(:return, val[0])
- }
- | kYIELD tLPAREN2 call_args rparen
- {
- result = @builder.keyword_cmd(:yield, val[0], val[1], val[2], val[3])
- }
- | kYIELD tLPAREN2 rparen
- {
- result = @builder.keyword_cmd(:yield, val[0], val[1], [], val[2])
- }
- | kYIELD
- {
- result = @builder.keyword_cmd(:yield, val[0])
- }
- | kDEFINED opt_nl tLPAREN2 expr rparen
- {
- result = @builder.keyword_cmd(:defined?, val[0],
- val[2], [ val[3] ], val[4])
- }
- | kNOT tLPAREN2 expr rparen
- {
- result = @builder.not_op(val[0], val[1], val[2], val[3])
- }
- | kNOT tLPAREN2 rparen
- {
- result = @builder.not_op(val[0], val[1], nil, val[2])
- }
- | operation brace_block
- {
- method_call = @builder.call_method(nil, nil, val[0])
-
- begin_t, args, body, end_t = val[1]
- result = @builder.block(method_call,
- begin_t, args, body, end_t)
- }
- | method_call
- | method_call brace_block
- {
- begin_t, args, body, end_t = val[1]
- result = @builder.block(val[0],
- begin_t, args, body, end_t)
- }
- | tLAMBDA lambda
- {
- lambda_call = @builder.call_lambda(val[0])
-
- args, (begin_t, body, end_t) = val[1]
- result = @builder.block(lambda_call,
- begin_t, args, body, end_t)
- }
- | kIF expr_value then compstmt if_tail kEND
- {
- else_t, else_ = val[4]
- result = @builder.condition(val[0], val[1], val[2],
- val[3], else_t,
- else_, val[5])
- }
- | kUNLESS expr_value then compstmt opt_else kEND
- {
- else_t, else_ = val[4]
- result = @builder.condition(val[0], val[1], val[2],
- else_, else_t,
- val[3], val[5])
- }
- | kWHILE
- {
- @lexer.cond.push(true)
- }
- expr_value do
- {
- @lexer.cond.pop
- }
- compstmt kEND
- {
- result = @builder.loop(:while, val[0], val[2], val[3],
- val[5], val[6])
- }
- | kUNTIL
- {
- @lexer.cond.push(true)
- }
- expr_value do
- {
- @lexer.cond.pop
- }
- compstmt kEND
- {
- result = @builder.loop(:until, val[0], val[2], val[3],
- val[5], val[6])
- }
- | kCASE expr_value opt_terms case_body kEND
- {
- *when_bodies, (else_t, else_body) = *val[3]
-
- result = @builder.case(val[0], val[1],
- when_bodies, else_t, else_body,
- val[4])
- }
- | kCASE opt_terms case_body kEND
- {
- *when_bodies, (else_t, else_body) = *val[2]
-
- result = @builder.case(val[0], nil,
- when_bodies, else_t, else_body,
- val[3])
- }
- | kFOR for_var kIN
- {
- @lexer.cond.push(true)
- }
- expr_value do
- {
- @lexer.cond.pop
- }
- compstmt kEND
- {
- result = @builder.for(val[0], val[1],
- val[2], val[4],
- val[5], val[7], val[8])
- }
- | kCLASS cpath superclass
- {
- @static_env.extend_static
- @lexer.push_cmdarg
- }
- bodystmt kEND
- {
- if in_def?
- diagnostic :error, :class_in_def, nil, val[0]
- end
-
- lt_t, superclass = val[2]
- result = @builder.def_class(val[0], val[1],
- lt_t, superclass,
- val[4], val[5])
-
- @lexer.pop_cmdarg
- @static_env.unextend
- }
- | kCLASS tLSHFT expr term
- {
- result = @def_level
- @def_level = 0
-
- @static_env.extend_static
- @lexer.push_cmdarg
- }
- bodystmt kEND
- {
- result = @builder.def_sclass(val[0], val[1], val[2],
- val[5], val[6])
-
- @lexer.pop_cmdarg
- @static_env.unextend
-
- @def_level = val[4]
- }
- | kMODULE cpath
- {
- @static_env.extend_static
- @lexer.push_cmdarg
- }
- bodystmt kEND
- {
- if in_def?
- diagnostic :error, :module_in_def, nil, val[0]
- end
-
- result = @builder.def_module(val[0], val[1],
- val[3], val[4])
-
- @lexer.pop_cmdarg
- @static_env.unextend
- }
- | kDEF fname
- {
- @def_level += 1
- @static_env.extend_static
- @lexer.push_cmdarg
- }
- f_arglist bodystmt kEND
- {
- result = @builder.def_method(val[0], val[1],
- val[3], val[4], val[5])
-
- @lexer.pop_cmdarg
- @static_env.unextend
- @def_level -= 1
- }
- | kDEF singleton dot_or_colon
- {
- @lexer.state = :expr_fname
- }
- fname
- {
- @def_level += 1
- @static_env.extend_static
- @lexer.push_cmdarg
- }
- f_arglist bodystmt kEND
- {
- result = @builder.def_singleton(val[0], val[1], val[2],
- val[4], val[6], val[7], val[8])
-
- @lexer.pop_cmdarg
- @static_env.unextend
- @def_level -= 1
- }
- | kBREAK
- {
- result = @builder.keyword_cmd(:break, val[0])
- }
- | kNEXT
- {
- result = @builder.keyword_cmd(:next, val[0])
- }
- | kREDO
- {
- result = @builder.keyword_cmd(:redo, val[0])
- }
- | kRETRY
- {
- result = @builder.keyword_cmd(:retry, val[0])
- }
-
- primary_value: primary
-
- then: term
- | kTHEN
- | term kTHEN
- {
- result = val[1]
- }
-
- do: term
- | kDO_COND
-
- if_tail: opt_else
- | kELSIF expr_value then compstmt if_tail
- {
- else_t, else_ = val[4]
- result = [ val[0],
- @builder.condition(val[0], val[1], val[2],
- val[3], else_t,
- else_, nil),
- ]
- }
-
- opt_else: none
- | kELSE compstmt
- {
- result = val
- }
-
- for_var: lhs
- | mlhs
-
- f_marg: f_norm_arg
- | tLPAREN f_margs rparen
- {
- result = @builder.multi_lhs(val[0], val[1], val[2])
- }
-
- f_marg_list: f_marg
- {
- result = [ val[0] ]
- }
- | f_marg_list tCOMMA f_marg
- {
- result = val[0] << val[2]
- }
-
- f_margs: f_marg_list
- | f_marg_list tCOMMA tSTAR f_norm_arg
- {
- result = val[0].
- push(@builder.objc_restarg(val[2], val[3]))
- }
- | f_marg_list tCOMMA tSTAR f_norm_arg tCOMMA f_marg_list
- {
- result = val[0].
- push(@builder.objc_restarg(val[2], val[3])).
- concat(val[5])
- }
- | f_marg_list tCOMMA tSTAR
- {
- result = val[0].
- push(@builder.objc_restarg(val[2]))
- }
- | f_marg_list tCOMMA tSTAR tCOMMA f_marg_list
- {
- result = val[0].
- push(@builder.objc_restarg(val[2])).
- concat(val[4])
- }
- | tSTAR f_norm_arg
- {
- result = [ @builder.objc_restarg(val[0], val[1]) ]
- }
- | tSTAR f_norm_arg tCOMMA f_marg_list
- {
- result = [ @builder.objc_restarg(val[0], val[1]),
- *val[3] ]
- }
- | tSTAR
- {
- result = [ @builder.objc_restarg(val[0]) ]
- }
- | tSTAR tCOMMA f_marg_list
- {
- result = [ @builder.objc_restarg(val[0]),
- *val[2] ]
- }
-
- block_param: f_arg tCOMMA f_block_optarg tCOMMA f_rest_arg opt_f_block_arg
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
- }
- | f_arg tCOMMA f_block_optarg tCOMMA f_rest_arg tCOMMA f_arg opt_f_block_arg
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[6]).
- concat(val[7])
- }
- | f_arg tCOMMA f_block_optarg opt_f_block_arg
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | f_arg tCOMMA f_block_optarg tCOMMA f_arg opt_f_block_arg
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
- }
- | f_arg tCOMMA f_rest_arg opt_f_block_arg
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | f_arg tCOMMA
- | f_arg tCOMMA f_rest_arg tCOMMA f_arg opt_f_block_arg
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
- }
- | f_arg opt_f_block_arg
- {
- result = val[0].concat(val[1])
- }
- | f_block_optarg tCOMMA f_rest_arg opt_f_block_arg
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | f_block_optarg tCOMMA f_rest_arg tCOMMA f_arg opt_f_block_arg
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
- }
- | f_block_optarg opt_f_block_arg
- {
- result = val[0].
- concat(val[1])
- }
- | f_block_optarg tCOMMA f_arg opt_f_block_arg
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | f_rest_arg opt_f_block_arg
- {
- result = val[0].
- concat(val[1])
- }
- | f_rest_arg tCOMMA f_arg opt_f_block_arg
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | f_block_arg
- {
- result = [ val[0] ]
- }
-
- opt_block_param: # nothing
- {
- result = @builder.args(nil, [], nil)
- }
- | block_param_def
- {
- @lexer.state = :expr_value
- }
-
- block_param_def: tPIPE opt_bv_decl tPIPE
- {
- result = @builder.args(val[0], val[1], val[2])
- }
- | tOROP
- {
- result = @builder.args(val[0], [], val[0])
- }
- | tPIPE block_param opt_bv_decl tPIPE
- {
- result = @builder.args(val[0], val[1].concat(val[2]), val[3])
- }
-
- opt_bv_decl: # nothing
- {
- result = []
- }
- | tSEMI bv_decls
- {
- result = val[1]
- }
-
- bv_decls: bvar
- {
- result = [ val[0] ]
- }
- | bv_decls tCOMMA bvar
- {
- result = val[0] << val[2]
- }
-
- bvar: tIDENTIFIER
- {
- result = @builder.shadowarg(val[0])
- }
- | f_bad_arg
-
- lambda: {
- @static_env.extend_dynamic
- }
- f_larglist lambda_body
- {
- result = [ val[1], val[2] ]
-
- @static_env.unextend
- }
-
- f_larglist: tLPAREN2 f_args opt_bv_decl rparen
- {
- result = @builder.args(val[0], val[1].concat(val[2]), val[3])
- }
- | f_args
- {
- result = @builder.args(nil, val[0], nil)
- }
-
- lambda_body: tLAMBEG compstmt tRCURLY
- {
- result = [ val[0], val[1], val[2] ]
- }
- | kDO_LAMBDA compstmt kEND
- {
- result = [ val[0], val[1], val[2] ]
- }
-
- do_block: kDO_BLOCK
- {
- @static_env.extend_dynamic
- }
- opt_block_param compstmt kEND
- {
- result = [ val[0], val[2], val[3], val[4] ]
-
- @static_env.unextend
- }
-
- block_call: command do_block
- {
- begin_t, block_args, body, end_t = val[1]
- result = @builder.block(val[0],
- begin_t, block_args, body, end_t)
- }
- | block_call tDOT operation2 opt_paren_args
- {
- lparen_t, args, rparen_t = val[3]
- result = @builder.call_method(val[0], val[1], val[2],
- lparen_t, args, rparen_t)
- }
- | block_call tCOLON2 operation2 opt_paren_args
- {
- lparen_t, args, rparen_t = val[3]
- result = @builder.call_method(val[0], val[1], val[2],
- lparen_t, args, rparen_t)
- }
-
- method_call: operation paren_args
- {
- lparen_t, args, rparen_t = val[1]
- result = @builder.call_method(nil, nil, val[0],
- lparen_t, args, rparen_t)
- }
- | primary_value tDOT operation2 opt_paren_args
- {
- lparen_t, args, rparen_t = val[3]
- result = @builder.call_method(val[0], val[1], val[2],
- lparen_t, args, rparen_t)
- }
- | primary_value tCOLON2 operation2 paren_args
- {
- lparen_t, args, rparen_t = val[3]
- result = @builder.call_method(val[0], val[1], val[2],
- lparen_t, args, rparen_t)
- }
- | primary_value tCOLON2 operation3
- {
- result = @builder.call_method(val[0], val[1], val[2])
- }
- | primary_value tDOT paren_args
- {
- lparen_t, args, rparen_t = val[2]
- result = @builder.call_method(val[0], val[1], nil,
- lparen_t, args, rparen_t)
- }
- | primary_value tCOLON2 paren_args
- {
- lparen_t, args, rparen_t = val[2]
- result = @builder.call_method(val[0], val[1], nil,
- lparen_t, args, rparen_t)
- }
- | kSUPER paren_args
- {
- lparen_t, args, rparen_t = val[1]
- result = @builder.keyword_cmd(:super, val[0],
- lparen_t, args, rparen_t)
- }
- | kSUPER
- {
- result = @builder.keyword_cmd(:zsuper, val[0])
- }
- | primary_value tLBRACK2 opt_call_args rbracket
- {
- result = @builder.index(val[0], val[1], val[2], val[3])
- }
-
- brace_block: tLCURLY
- {
- @static_env.extend_dynamic
- }
- opt_block_param compstmt tRCURLY
- {
- result = [ val[0], val[2], val[3], val[4] ]
-
- @static_env.unextend
- }
- | kDO
- {
- @static_env.extend_dynamic
- }
- opt_block_param compstmt kEND
- {
- result = [ val[0], val[2], val[3], val[4] ]
-
- @static_env.unextend
- }
-
- case_body: kWHEN args then compstmt cases
- {
- result = [ @builder.when(val[0], val[1], val[2], val[3]),
- *val[4] ]
- }
-
- cases: opt_else
- {
- result = [ val[0] ]
- }
- | case_body
-
- opt_rescue: kRESCUE exc_list exc_var then compstmt opt_rescue
- {
- assoc_t, exc_var = val[2]
-
- if val[1]
- exc_list = @builder.array(nil, val[1], nil)
- end
-
- result = [ @builder.rescue_body(val[0],
- exc_list, assoc_t, exc_var,
- val[3], val[4]),
- *val[5] ]
- }
- |
- {
- result = []
- }
-
- exc_list: arg_value
- {
- result = [ val[0] ]
- }
- | mrhs
- | none
-
- exc_var: tASSOC lhs
- {
- result = [ val[0], val[1] ]
- }
- | none
-
- opt_ensure: kENSURE compstmt
- {
- result = [ val[0], val[1] ]
- }
- | none
-
- literal: numeric
- | symbol
- | dsym
-
- strings: string
- {
- result = @builder.string_compose(nil, val[0], nil)
- }
-
- string: string1
- {
- result = [ val[0] ]
- }
- | string string1
- {
- result = val[0] << val[1]
- }
-
- string1: tSTRING_BEG string_contents tSTRING_END
- {
- result = @builder.string_compose(val[0], val[1], val[2])
- }
- | tSTRING
- {
- result = @builder.string(val[0])
- }
- | tCHARACTER
- {
- result = @builder.character(val[0])
- }
-
- xstring: tXSTRING_BEG xstring_contents tSTRING_END
- {
- result = @builder.xstring_compose(val[0], val[1], val[2])
- }
-
- regexp: tREGEXP_BEG regexp_contents tSTRING_END tREGEXP_OPT
- {
- opts = @builder.regexp_options(val[3])
- result = @builder.regexp_compose(val[0], val[1], val[2], opts)
- }
-
- words: tWORDS_BEG word_list tSTRING_END
- {
- result = @builder.words_compose(val[0], val[1], val[2])
- }
-
- word_list: # nothing
- {
- result = []
- }
- | word_list word tSPACE
- {
- result = val[0] << @builder.word(val[1])
- }
-
- word: string_content
- {
- result = [ val[0] ]
- }
- | word string_content
- {
- result = val[0] << val[1]
- }
-
- qwords: tQWORDS_BEG qword_list tSTRING_END
- {
- result = @builder.words_compose(val[0], val[1], val[2])
- }
-
- qword_list: # nothing
- {
- result = []
- }
- | qword_list tSTRING_CONTENT tSPACE
- {
- result = val[0] << @builder.string_internal(val[1])
- }
-
- string_contents: # nothing
- {
- result = []
- }
- | string_contents string_content
- {
- result = val[0] << val[1]
- }
-
-xstring_contents: # nothing
- {
- result = []
- }
- | xstring_contents string_content
- {
- result = val[0] << val[1]
- }
-
-regexp_contents: # nothing
- {
- result = []
- }
- | regexp_contents string_content
- {
- result = val[0] << val[1]
- }
-
- string_content: tSTRING_CONTENT
- {
- result = @builder.string_internal(val[0])
- }
- | tSTRING_DVAR string_dvar
- {
- result = val[1]
- }
- | tSTRING_DBEG
- {
- @lexer.cond.push(false)
- @lexer.cmdarg.push(false)
- }
- compstmt tRCURLY
- {
- @lexer.cond.lexpop
- @lexer.cmdarg.lexpop
-
- result = @builder.begin(val[0], val[2], val[3])
- }
-
- string_dvar: tGVAR
- {
- result = @builder.gvar(val[0])
- }
- | tIVAR
- {
- result = @builder.ivar(val[0])
- }
- | tCVAR
- {
- result = @builder.cvar(val[0])
- }
- | backref
-
-
- symbol: tSYMBOL
- {
- result = @builder.symbol(val[0])
- }
-
- dsym: tSYMBEG xstring_contents tSTRING_END
- {
- result = @builder.symbol_compose(val[0], val[1], val[2])
- }
-
- numeric: tINTEGER
- {
- result = @builder.integer(val[0])
- }
- | tFLOAT
- {
- result = @builder.float(val[0])
- }
- | tUMINUS_NUM tINTEGER =tLOWEST
- {
- result = @builder.negate(val[0],
- @builder.integer(val[1]))
- }
- | tUMINUS_NUM tFLOAT =tLOWEST
- {
- result = @builder.negate(val[0],
- @builder.float(val[1]))
- }
-
- variable: tIDENTIFIER
- {
- result = @builder.ident(val[0])
- }
- | tIVAR
- {
- result = @builder.ivar(val[0])
- }
- | tGVAR
- {
- result = @builder.gvar(val[0])
- }
- | tCONSTANT
- {
- result = @builder.const(val[0])
- }
- | tCVAR
- {
- result = @builder.cvar(val[0])
- }
- | kNIL
- {
- result = @builder.nil(val[0])
- }
- | kSELF
- {
- result = @builder.self(val[0])
- }
- | kTRUE
- {
- result = @builder.true(val[0])
- }
- | kFALSE
- {
- result = @builder.false(val[0])
- }
- | k__FILE__
- {
- result = @builder.__FILE__(val[0])
- }
- | k__LINE__
- {
- result = @builder.__LINE__(val[0])
- }
- | k__ENCODING__
- {
- result = @builder.__ENCODING__(val[0])
- }
-
- var_ref: variable
- {
- result = @builder.accessible(val[0])
- }
-
- var_lhs: variable
- {
- result = @builder.assignable(val[0])
- }
-
- backref: tNTH_REF
- {
- result = @builder.nth_ref(val[0])
- }
- | tBACK_REF
- {
- result = @builder.back_ref(val[0])
- }
-
- superclass: term
- {
- result = nil
- }
- | tLT expr_value term
- {
- result = [ val[0], val[1] ]
- }
- | error term
- {
- yyerrok
- result = nil
- }
-
- f_arglist: tLPAREN2 f_args rparen
- {
- result = @builder.args(val[0], val[1], val[2])
-
- @lexer.state = :expr_value
- }
- | f_args term
- {
- result = @builder.args(nil, val[0], nil)
- }
-
- f_args: f_arg tCOMMA f_optarg tCOMMA f_rest_arg opt_f_block_arg
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
- }
- | f_arg tCOMMA f_optarg tCOMMA f_rest_arg tCOMMA f_arg opt_f_block_arg
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[6]).
- concat(val[7])
- }
- | f_arg tCOMMA f_optarg opt_f_block_arg
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | f_arg tCOMMA f_optarg tCOMMA f_arg opt_f_block_arg
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
- }
- | f_arg tCOMMA f_rest_arg opt_f_block_arg
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | f_arg tCOMMA f_rest_arg tCOMMA f_arg opt_f_block_arg
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
- }
- | f_arg opt_f_block_arg
- {
- result = val[0].
- concat(val[1])
- }
- | f_optarg tCOMMA f_rest_arg opt_f_block_arg
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | f_optarg tCOMMA f_rest_arg tCOMMA f_arg opt_f_block_arg
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
- }
- | f_optarg opt_f_block_arg
- {
- result = val[0].
- concat(val[1])
- }
- | f_optarg tCOMMA f_arg opt_f_block_arg
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | f_rest_arg opt_f_block_arg
- {
- result = val[0].
- concat(val[1])
- }
- | f_rest_arg tCOMMA f_arg opt_f_block_arg
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | f_block_arg
- {
- result = [ val[0] ]
- }
- | # nothing
- {
- result = []
- }
-
- f_bad_arg: tCONSTANT
- {
- diagnostic :error, :argument_const, nil, val[0]
- }
- | tIVAR
- {
- diagnostic :error, :argument_ivar, nil, val[0]
- }
- | tGVAR
- {
- diagnostic :error, :argument_gvar, nil, val[0]
- }
- | tCVAR
- {
- diagnostic :error, :argument_cvar, nil, val[0]
- }
-
- f_norm_arg: f_bad_arg
- | tIDENTIFIER
- {
- @static_env.declare val[0][0]
-
- result = @builder.arg(val[0])
- }
- | tIDENTIFIER tASSOC tIDENTIFIER
- {
- @static_env.declare val[2][0]
-
- result = @builder.objc_kwarg(val[0], val[1], val[2])
- }
- | tLABEL tIDENTIFIER
- {
- @static_env.declare val[1][0]
-
- result = @builder.objc_kwarg(val[0], nil, val[1])
- }
-
- f_arg_item: f_norm_arg
- | tLPAREN f_margs rparen
- {
- result = @builder.multi_lhs(val[0], val[1], val[2])
- }
-
- f_arg: f_arg_item
- {
- result = [ val[0] ]
- }
- | f_arg tCOMMA f_arg_item
- {
- result = val[0] << val[2]
- }
-
- f_opt: tIDENTIFIER tEQL arg_value
- {
- @static_env.declare val[0][0]
-
- result = @builder.optarg(val[0], val[1], val[2])
- }
-
- f_block_opt: tIDENTIFIER tEQL primary_value
- {
- @static_env.declare val[0][0]
-
- result = @builder.optarg(val[0], val[1], val[2])
- }
-
- f_block_optarg: f_block_opt
- {
- result = [ val[0] ]
- }
- | f_block_optarg tCOMMA f_block_opt
- {
- result = val[0] << val[2]
- }
-
- f_optarg: f_opt
- {
- result = [ val[0] ]
- }
- | f_optarg tCOMMA f_opt
- {
- result = val[0] << val[2]
- }
-
- restarg_mark: tSTAR2 | tSTAR
-
- f_rest_arg: restarg_mark tIDENTIFIER
- {
- @static_env.declare val[1][0]
-
- result = [ @builder.restarg(val[0], val[1]) ]
- }
- | restarg_mark
- {
- result = [ @builder.restarg(val[0]) ]
- }
-
- blkarg_mark: tAMPER2 | tAMPER
-
- f_block_arg: blkarg_mark tIDENTIFIER
- {
- @static_env.declare val[1][0]
-
- result = @builder.blockarg(val[0], val[1])
- }
-
- opt_f_block_arg: tCOMMA f_block_arg
- {
- result = [ val[1] ]
- }
- | # nothing
- {
- result = []
- }
-
- singleton: var_ref
- | tLPAREN2 expr rparen
- {
- result = val[1]
- }
-
- assoc_list: # nothing
- {
- result = []
- }
- | assocs trailer
-
- assocs: assoc
- {
- result = [ val[0] ]
- }
- | assocs tCOMMA assoc
- {
- result = val[0] << val[2]
- }
-
- assoc: arg_value tASSOC arg_value
- {
- result = @builder.pair(val[0], val[1], val[2])
- }
- | tLABEL arg_value
- {
- result = @builder.pair_keyword(val[0], val[1])
- }
-
- operation: tIDENTIFIER | tCONSTANT | tFID
- operation2: tIDENTIFIER | tCONSTANT | tFID | op
- operation3: tIDENTIFIER | tFID | op
- dot_or_colon: tDOT | tCOLON2
- opt_terms: | terms
- opt_nl: | tNL
- rparen: opt_nl tRPAREN
- {
- result = val[1]
- }
- rbracket: opt_nl tRBRACK
- {
- result = val[1]
- }
- trailer: | tNL | tCOMMA
-
- term: tSEMI
- {
- yyerrok
- }
- | tNL
-
- terms: term
- | terms tSEMI
-
- none: # nothing
- {
- result = nil
- }
-end
-
----- header
-
-require 'parser'
-
-Parser.check_for_encoding_support
-
----- inner
-
- def version
- 19 # closest released match: v1_9_0_2
- end
-
- def default_encoding
- Encoding::BINARY
- end
diff --git a/test/racc/assets/mailp.y b/test/racc/assets/mailp.y
deleted file mode 100644
index eb7d4d529d..0000000000
--- a/test/racc/assets/mailp.y
+++ /dev/null
@@ -1,437 +0,0 @@
-#
-# mailp for test
-#
-
-class Testp
-
-rule
-
- content : DateH datetime { @field.date = val[1] }
- | RecvH received
- | RetpathH returnpath
- | MaddrH addrs { @field.addrs.replace val[1] }
- | SaddrH addr { @field.addr = val[1] }
- | MmboxH mboxes { @field.addrs.replace val[1] }
- | SmboxH mbox { @field.addr = val[1] }
- | MsgidH msgid { @field.msgid = val[1] }
- | KeyH keys { @field.keys.replace val[1] }
- | EncH enc
- | VersionH version
- | CTypeH ctype
- | CEncodingH cencode
- | CDispositionH cdisp
- | Mbox mbox
- {
- mb = val[1]
- @field.phrase = mb.phrase
- @field.setroute mb.route
- @field.local = mb.local
- @field.domain = mb.domain
- }
- | Spec spec
- {
- mb = val[1]
- @field.local = mb.local
- @field.domain = mb.domain
- }
- ;
-
- datetime : day DIGIT ATOM DIGIT hour zone
- # 0 1 2 3 4 5
- # day month year
- {
- t = Time.gm( val[3].to_i, val[2], val[1].to_i, 0, 0, 0 )
- result = (t + val[4] - val[5]).localtime
- }
- ;
-
- day : /* none */
- | ATOM ','
- ;
-
- hour : DIGIT ':' DIGIT
- {
- result = (result.to_i * 60 * 60) + (val[2].to_i * 60)
- }
- | DIGIT ':' DIGIT ':' DIGIT
- {
- result = (result.to_i * 60 * 60) +
- (val[2].to_i * 60)
- + val[4].to_i
- }
- ;
-
- zone : ATOM
- {
- result = ::TMail.zonestr2i( val[0] ) * 60
- }
- ;
-
- received : from by via with id for recvdatetime
- ;
-
- from : /* none */
- | FROM domain
- {
- @field.from = Address.join( val[1] )
- }
- | FROM domain '@' domain
- {
- @field.from = Address.join( val[3] )
- }
- | FROM domain DOMLIT
- {
- @field.from = Address.join( val[1] )
- }
- ;
-
- by : /* none */
- | BY domain
- {
- @field.by = Address.join( val[1] )
- }
- ;
-
- via : /* none */
- | VIA ATOM
- {
- @field.via = val[1]
- }
- ;
-
- with : /* none */
- | WITH ATOM
- {
- @field.with.push val[1]
- }
- ;
-
- id : /* none */
- | ID msgid
- {
- @field.msgid = val[1]
- }
- | ID ATOM
- {
- @field.msgid = val[1]
- }
- ;
-
- for : /* none */
- | FOR addr
- {
- @field.for_ = val[1].address
- }
- ;
-
- recvdatetime
- : /* none */
- | ';' datetime
- {
- @field.date = val[1]
- }
- ;
-
- returnpath: '<' '>'
- | routeaddr
- {
- @field.route.replace result.route
- @field.addr = result.addr
- }
- ;
-
- addrs : addr { result = val }
- | addrs ',' addr { result.push val[2] }
- ;
-
- addr : mbox
- | group
- ;
-
- mboxes : mbox
- {
- result = val
- }
- | mboxes ',' mbox
- {
- result.push val[2]
- }
- ;
-
- mbox : spec
- | routeaddr
- | phrase routeaddr
- {
- val[1].phrase = HFdecoder.decode( result )
- result = val[1]
- }
- ;
-
- group : phrase ':' mboxes ';'
- {
- result = AddressGroup.new( result, val[2] )
- }
- # | phrase ':' ';' { result = AddressGroup.new( result ) }
- ;
-
- routeaddr : '<' route spec '>'
- {
- result = val[2]
- result.route = val[1]
- }
- | '<' spec '>'
- {
- result = val[1]
- }
- ;
-
- route : at_domains ':'
- ;
-
- at_domains: '@' domain { result = [ val[1] ] }
- | at_domains ',' '@' domain { result.push val[3] }
- ;
-
- spec : local '@' domain { result = Address.new( val[0], val[2] ) }
- | local { result = Address.new( result, nil ) }
- ;
-
- local : word { result = val }
- | local '.' word { result.push val[2] }
- ;
-
- domain : domword { result = val }
- | domain '.' domword { result.push val[2] }
- ;
-
- domword : atom
- | DOMLIT
- | DIGIT
- ;
-
- msgid : '<' spec '>'
- {
- val[1] = val[1].addr
- result = val.join('')
- }
- ;
-
- phrase : word
- | phrase word { result << ' ' << val[1] }
- ;
-
- word : atom
- | QUOTED
- | DIGIT
- ;
-
- keys : phrase
- | keys ',' phrase
- ;
-
- enc : word
- {
- @field.encrypter = val[0]
- }
- | word word
- {
- @field.encrypter = val[0]
- @field.keyword = val[1]
- }
- ;
-
- version : DIGIT '.' DIGIT
- {
- @field.major = val[0].to_i
- @field.minor = val[2].to_i
- }
- ;
-
- ctype : TOKEN '/' TOKEN params
- {
- @field.main = val[0]
- @field.sub = val[2]
- }
- | TOKEN params
- {
- @field.main = val[0]
- @field.sub = ''
- }
- ;
-
- params : /* none */
- | params ';' TOKEN '=' value
- {
- @field.params[ val[2].downcase ] = val[4]
- }
- ;
-
- value : TOKEN
- | QUOTED
- ;
-
- cencode : TOKEN
- {
- @field.encoding = val[0]
- }
- ;
-
- cdisp : TOKEN disp_params
- {
- @field.disposition = val[0]
- }
- ;
-
- disp_params
- : /* none */
- | disp_params ';' disp_param
- ;
-
- disp_param: /* none */
- | TOKEN '=' value
- {
- @field.params[ val[0].downcase ] = val[2]
- }
- ;
-
- atom : ATOM
- | FROM
- | BY
- | VIA
- | WITH
- | ID
- | FOR
- ;
-
-end
-
-
----- header
-#
-# mailp for test
-#
-
-require 'tmail/mails'
-
-
-module TMail
-
----- inner
-
- MAILP_DEBUG = false
-
- def initialize
- self.debug = MAILP_DEBUG
- end
-
- def debug=( flag )
- @yydebug = flag && Racc_debug_parser
- @scanner_debug = flag
- end
-
- def debug
- @yydebug
- end
-
-
- def Mailp.parse( str, obj, ident )
- new.parse( str, obj, ident )
- end
-
-
- NATIVE_ROUTINE = {
- 'TMail::MsgidH' => :msgid_parse,
- 'TMail::RefH' => :refs_parse
- }
-
- def parse( str, obj, ident )
- return if /\A\s*\z/ === str
-
- @field = obj
-
- if mid = NATIVE_ROUTINE[ obj.type.name ] then
- send mid, str
- else
- unless ident then
- ident = obj.type.name.split('::')[-1].to_s
- cmt = []
- obj.comments.replace cmt
- else
- cmt = nil
- end
-
- @scanner = MailScanner.new( str, ident, cmt )
- @scanner.debug = @scanner_debug
- @first = [ ident.intern, ident ]
- @pass_array = [nil, nil]
-
- do_parse
- end
- end
-
-
- private
-
-
- def next_token
- if @first then
- ret = @first
- @first = nil
- ret
- else
- @scanner.scan @pass_array
- end
- end
-
- def on_error( tok, val, vstack )
- raise ParseError,
- "\nparse error in '#{@field.name}' header, on token #{val.inspect}"
- end
-
-
-
- def refs_parse( str )
- arr = []
-
- while mdata = ::TMail::MSGID.match( str ) do
- str = mdata.post_match
-
- pre = mdata.pre_match
- pre.strip!
- proc_phrase pre, arr unless pre.empty?
- arr.push mdata.to_s
- end
- str.strip!
- proc_phrase str, arr if not pre or pre.empty?
-
- @field.refs.replace arr
- end
-
- def proc_phrase( str, arr )
- while mdata = /"([^\\]*(?:\\.[^"\\]*)*)"/.match( str ) do
- str = mdata.post_match
-
- pre = mdata.pre_match
- pre.strip!
- arr.push pre unless pre.empty?
- arr.push mdata[1]
- end
- str.strip!
- arr.push unless str.empty?
- end
-
-
- def msgid_parse( str )
- if mdata = ::TMail::MSGID.match( str ) then
- @field.msgid = mdata.to_s
- else
- raise ParseError, "wrong Message-ID format: #{str}"
- end
- end
-
----- footer
-
-end # module TMail
-
-mp = TMail::Testp.new
-mp.parse
diff --git a/test/racc/assets/mediacloth.y b/test/racc/assets/mediacloth.y
deleted file mode 100644
index 94cc411ea7..0000000000
--- a/test/racc/assets/mediacloth.y
+++ /dev/null
@@ -1,599 +0,0 @@
-# Copyright (c) 2006 Pluron Inc.
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-# The parser for the MediaWiki language.
-#
-# Usage together with a lexer:
-# inputFile = File.new("data/input1", "r")
-# input = inputFile.read
-# parser = MediaWikiParser.new
-# parser.lexer = MediaWikiLexer.new
-# parser.parse(input)
-
-class MediaWikiParser
-
-token TEXT BOLD_START BOLD_END ITALIC_START ITALIC_END LINK_START LINK_END LINKSEP
- INTLINK_START INTLINK_END INTLINKSEP RESOURCESEP CHAR_ENT
- PRE_START PRE_END PREINDENT_START PREINDENT_END
- SECTION_START SECTION_END HLINE SIGNATURE_NAME SIGNATURE_DATE SIGNATURE_FULL
- PARA_START PARA_END UL_START UL_END OL_START OL_END LI_START LI_END
- DL_START DL_END DT_START DT_END DD_START DD_END TAG_START TAG_END ATTR_NAME ATTR_VALUE
- TABLE_START TABLE_END ROW_START ROW_END HEAD_START HEAD_END CELL_START CELL_END
- KEYWORD TEMPLATE_START TEMPLATE_END CATEGORY PASTE_START PASTE_END
-
-
-rule
-
-wiki:
- repeated_contents
- {
- @nodes.push WikiAST.new(0, @wiki_ast_length)
- #@nodes.last.children.insert(0, val[0])
- #puts val[0]
- @nodes.last.children += val[0]
- }
- ;
-
-contents:
- text
- {
- result = val[0]
- }
- | bulleted_list
- {
- result = val[0]
- }
- | numbered_list
- {
- result = val[0]
- }
- | dictionary_list
- {
- list = ListAST.new(@ast_index, @ast_length)
- list.list_type = :Dictionary
- list.children = val[0]
- result = list
- }
- | preformatted
- {
- result = val[0]
- }
- | section
- {
- result = val[0]
- }
- | tag
- {
- result = val[0]
- }
- | template
- {
- result = val[0]
- }
- | KEYWORD
- {
- k = KeywordAST.new(@ast_index, @ast_length)
- k.text = val[0]
- result = k
- }
- | PARA_START para_contents PARA_END
- {
- p = ParagraphAST.new(@ast_index, @ast_length)
- p.children = val[1]
- result = p
- }
- | LINK_START link_contents LINK_END
- {
- l = LinkAST.new(@ast_index, @ast_length)
- l.link_type = val[0]
- l.url = val[1][0]
- l.children += val[1][1..-1] if val[1].length > 1
- result = l
- }
- | PASTE_START para_contents PASTE_END
- {
- p = PasteAST.new(@ast_index, @ast_length)
- p.children = val[1]
- result = p
- }
- | INTLINK_START TEXT RESOURCESEP TEXT reslink_repeated_contents INTLINK_END
- {
- l = ResourceLinkAST.new(@ast_index, @ast_length)
- l.prefix = val[1]
- l.locator = val[3]
- l.children = val[4] unless val[4].nil? or val[4].empty?
- result = l
- }
- | INTLINK_START TEXT intlink_repeated_contents INTLINK_END
- {
- l = InternalLinkAST.new(@ast_index, @ast_length)
- l.locator = val[1]
- l.children = val[2] unless val[2].nil? or val[2].empty?
- result = l
- }
- | INTLINK_START CATEGORY TEXT cat_sort_contents INTLINK_END
- {
- l = CategoryAST.new(@ast_index, @ast_length)
- l.locator = val[2]
- l.sort_as = val[3]
- result = l
- }
- | INTLINK_START RESOURCESEP CATEGORY TEXT intlink_repeated_contents INTLINK_END
- {
- l = CategoryLinkAST.new(@ast_index, @ast_length)
- l.locator = val[3]
- l.children = val[4] unless val[4].nil? or val[4].empty?
- result = l
- }
- | table
- ;
-
-para_contents:
- {
- result = nil
- }
- | repeated_contents
- {
- result = val[0]
- }
- ;
-
-tag:
- TAG_START tag_attributes TAG_END
- {
- if val[0] != val[2]
- raise Racc::ParseError.new("XHTML end tag #{val[2]} does not match start tag #{val[0]}")
- end
- elem = ElementAST.new(@ast_index, @ast_length)
- elem.name = val[0]
- elem.attributes = val[1]
- result = elem
- }
- | TAG_START tag_attributes repeated_contents TAG_END
- {
- if val[0] != val[3]
- raise Racc::ParseError.new("XHTML end tag #{val[3]} does not match start tag #{val[0]}")
- end
- elem = ElementAST.new(@ast_index, @ast_length)
- elem.name = val[0]
- elem.attributes = val[1]
- elem.children += val[2]
- result = elem
- }
- ;
-
-tag_attributes:
- {
- result = nil
- }
- | ATTR_NAME tag_attributes
- {
- attr_map = val[2] ? val[2] : {}
- attr_map[val[0]] = true
- result = attr_map
- }
- | ATTR_NAME ATTR_VALUE tag_attributes
- {
- attr_map = val[2] ? val[2] : {}
- attr_map[val[0]] = val[1]
- result = attr_map
- }
- ;
-
-
-link_contents:
- TEXT
- {
- result = val
- }
- | TEXT LINKSEP link_repeated_contents
- {
- result = [val[0]]
- result += val[2]
- }
- ;
-
-
-link_repeated_contents:
- repeated_contents
- {
- result = val[0]
- }
- | repeated_contents LINKSEP link_repeated_contents
- {
- result = val[0]
- result += val[2] if val[2]
- }
- ;
-
-
-intlink_repeated_contents:
- {
- result = nil
- }
- | INTLINKSEP repeated_contents
- {
- result = val[1]
- }
- ;
-
-cat_sort_contents:
- {
- result = nil
- }
- | INTLINKSEP TEXT
- {
- result = val[1]
- }
- ;
-
-reslink_repeated_contents:
- {
- result = nil
- }
- | INTLINKSEP reslink_repeated_contents
- {
- result = val[1]
- }
- | INTLINKSEP repeated_contents reslink_repeated_contents
- {
- i = InternalLinkItemAST.new(@ast_index, @ast_length)
- i.children = val[1]
- result = [i]
- result += val[2] if val[2]
- }
- ;
-
-repeated_contents: contents
- {
- result = []
- result << val[0]
- }
- | repeated_contents contents
- {
- result = []
- result += val[0]
- result << val[1]
- }
- ;
-
-text: element
- {
- p = TextAST.new(@ast_index, @ast_length)
- p.formatting = val[0][0]
- p.contents = val[0][1]
- result = p
- }
- | formatted_element
- {
- result = val[0]
- }
- ;
-
-table:
- TABLE_START table_contents TABLE_END
- {
- table = TableAST.new(@ast_index, @ast_length)
- table.children = val[1] unless val[1].nil? or val[1].empty?
- result = table
- }
- | TABLE_START TEXT table_contents TABLE_END
- {
- table = TableAST.new(@ast_index, @ast_length)
- table.options = val[1]
- table.children = val[2] unless val[2].nil? or val[2].empty?
- result = table
- }
-
-table_contents:
- {
- result = nil
- }
- | ROW_START row_contents ROW_END table_contents
- {
- row = TableRowAST.new(@ast_index, @ast_length)
- row.children = val[1] unless val[1].nil? or val[1].empty?
- result = [row]
- result += val[3] unless val[3].nil? or val[3].empty?
- }
- | ROW_START TEXT row_contents ROW_END table_contents
- {
- row = TableRowAST.new(@ast_index, @ast_length)
- row.children = val[2] unless val[2].nil? or val[2].empty?
- row.options = val[1]
- result = [row]
- result += val[4] unless val[4].nil? or val[4].empty?
- }
-
-row_contents:
- {
- result = nil
- }
- | HEAD_START HEAD_END row_contents
- {
- cell = TableCellAST.new(@ast_index, @ast_length)
- cell.type = :head
- result = [cell]
- result += val[2] unless val[2].nil? or val[2].empty?
- }
- | HEAD_START repeated_contents HEAD_END row_contents
- {
- cell = TableCellAST.new(@ast_index, @ast_length)
- cell.children = val[1] unless val[1].nil? or val[1].empty?
- cell.type = :head
- result = [cell]
- result += val[3] unless val[3].nil? or val[3].empty?
- }
- | CELL_START CELL_END row_contents
- {
- cell = TableCellAST.new(@ast_index, @ast_length)
- cell.type = :body
- result = [cell]
- result += val[2] unless val[2].nil? or val[2].empty?
- }
- | CELL_START repeated_contents CELL_END row_contents
- {
- if val[2] == 'attributes'
- result = []
- else
- cell = TableCellAST.new(@ast_index, @ast_length)
- cell.children = val[1] unless val[1].nil? or val[1].empty?
- cell.type = :body
- result = [cell]
- end
- result += val[3] unless val[3].nil? or val[3].empty?
- if val[2] == 'attributes' and val[3] and val[3].first.class == TableCellAST
- val[3].first.attributes = val[1]
- end
- result
- }
-
-
-element:
- TEXT
- { return [:None, val[0]] }
- | HLINE
- { return [:HLine, val[0]] }
- | CHAR_ENT
- { return [:CharacterEntity, val[0]] }
- | SIGNATURE_DATE
- { return [:SignatureDate, val[0]] }
- | SIGNATURE_NAME
- { return [:SignatureName, val[0]] }
- | SIGNATURE_FULL
- { return [:SignatureFull, val[0]] }
- ;
-
-formatted_element:
- BOLD_START BOLD_END
- {
- result = FormattedAST.new(@ast_index, @ast_length)
- result.formatting = :Bold
- result
- }
- | ITALIC_START ITALIC_END
- {
- result = FormattedAST.new(@ast_index, @ast_length)
- result.formatting = :Italic
- result
- }
- | BOLD_START repeated_contents BOLD_END
- {
- p = FormattedAST.new(@ast_index, @ast_length)
- p.formatting = :Bold
- p.children += val[1]
- result = p
- }
- | ITALIC_START repeated_contents ITALIC_END
- {
- p = FormattedAST.new(@ast_index, @ast_length)
- p.formatting = :Italic
- p.children += val[1]
- result = p
- }
- ;
-
-bulleted_list: UL_START list_item list_contents UL_END
- {
- list = ListAST.new(@ast_index, @ast_length)
- list.list_type = :Bulleted
- list.children << val[1]
- list.children += val[2]
- result = list
- }
- ;
-
-numbered_list: OL_START list_item list_contents OL_END
- {
- list = ListAST.new(@ast_index, @ast_length)
- list.list_type = :Numbered
- list.children << val[1]
- list.children += val[2]
- result = list
- }
- ;
-
-list_contents:
- { result = [] }
- list_item list_contents
- {
- result << val[1]
- result += val[2]
- }
- |
- { result = [] }
- ;
-
-list_item:
- LI_START LI_END
- {
- result = ListItemAST.new(@ast_index, @ast_length)
- }
- | LI_START repeated_contents LI_END
- {
- li = ListItemAST.new(@ast_index, @ast_length)
- li.children += val[1]
- result = li
- }
- ;
-
-dictionary_list:
- DL_START dictionary_term dictionary_contents DL_END
- {
- result = [val[1]]
- result += val[2]
- }
- | DL_START dictionary_contents DL_END
- {
- result = val[1]
- }
- ;
-
-dictionary_term:
- DT_START DT_END
- {
- result = ListTermAST.new(@ast_index, @ast_length)
- }
- | DT_START repeated_contents DT_END
- {
- term = ListTermAST.new(@ast_index, @ast_length)
- term.children += val[1]
- result = term
- }
-
-dictionary_contents:
- dictionary_definition dictionary_contents
- {
- result = [val[0]]
- result += val[1] if val[1]
- }
- |
- {
- result = []
- }
-
-dictionary_definition:
- DD_START DD_END
- {
- result = ListDefinitionAST.new(@ast_index, @ast_length)
- }
- | DD_START repeated_contents DD_END
- {
- term = ListDefinitionAST.new(@ast_index, @ast_length)
- term.children += val[1]
- result = term
- }
-
-preformatted: PRE_START repeated_contents PRE_END
- {
- p = PreformattedAST.new(@ast_index, @ast_length)
- p.children += val[1]
- result = p
- }
- | PREINDENT_START repeated_contents PREINDENT_END
- {
- p = PreformattedAST.new(@ast_index, @ast_length)
- p.indented = true
- p.children += val[1]
- result = p
- }
- ;
-
-section: SECTION_START repeated_contents SECTION_END
- { result = [val[1], val[0].length]
- s = SectionAST.new(@ast_index, @ast_length)
- s.children = val[1]
- s.level = val[0].length
- result = s
- }
- ;
-
-template: TEMPLATE_START TEXT template_parameters TEMPLATE_END
- {
- t = TemplateAST.new(@ast_index, @ast_length)
- t.template_name = val[1]
- t.children = val[2] unless val[2].nil? or val[2].empty?
- result = t
- }
- ;
-
-template_parameters:
- {
- result = nil
- }
- | INTLINKSEP TEXT template_parameters
- {
- p = TemplateParameterAST.new(@ast_index, @ast_length)
- p.parameter_value = val[1]
- result = [p]
- result += val[2] if val[2]
- }
- | INTLINKSEP template template_parameters
- {
- p = TemplateParameterAST.new(@ast_index, @ast_length)
- p.children << val[1]
- result = [p]
- result += val[2] if val[2]
- }
- ;
-
-end
-
----- header ----
-require 'mediacloth/mediawikiast'
-
----- inner ----
-
-attr_accessor :lexer
-
-def initialize
- @nodes = []
- @context = []
- @wiki_ast_length = 0
- super
-end
-
-#Tokenizes input string and parses it.
-def parse(input)
- @yydebug=true
- lexer.tokenize(input)
- do_parse
- return @nodes.last
-end
-
-#Asks the lexer to return the next token.
-def next_token
- token = @lexer.lex
- if token[0].to_s.upcase.include? "_START"
- @context << token[2..3]
- elsif token[0].to_s.upcase.include? "_END"
- @ast_index = @context.last[0]
- @ast_length = token[2] + token[3] - @context.last[0]
- @context.pop
- else
- @ast_index = token[2]
- @ast_length = token[3]
- end
-
- @wiki_ast_length += token[3]
-
- return token[0..1]
-end
diff --git a/test/racc/assets/mof.y b/test/racc/assets/mof.y
deleted file mode 100644
index 2e83c79b6f..0000000000
--- a/test/racc/assets/mof.y
+++ /dev/null
@@ -1,649 +0,0 @@
-# Distributed under the Ruby license
-# See http://www.ruby-lang.org/en/LICENSE.txt for the full license text
-# Copyright (c) 2010 Klaus Kämpf <kkaempf@suse.de>
-
-/*
- * According to appendix A of
- * http://www.dmtf.org/standards/cim/cim_spec_v22
- */
-
-class MOF::Parser
- prechigh
-/* nonassoc UMINUS */
- left '*' '/'
- left '+' '-'
- preclow
-
- token PRAGMA INCLUDE IDENTIFIER CLASS ASSOCIATION INDICATION
- AMENDED ENABLEOVERRIDE DISABLEOVERRIDE RESTRICTED TOSUBCLASS TOINSTANCE
- TRANSLATABLE QUALIFIER SCOPE SCHEMA PROPERTY REFERENCE
- METHOD PARAMETER FLAVOR INSTANCE
- AS REF ANY OF
- DT_VOID
- DT_UINT8 DT_SINT8 DT_UINT16 DT_SINT16 DT_UINT32 DT_SINT32
- DT_UINT64 DT_SINT64 DT_REAL32 DT_REAL64 DT_CHAR16 DT_STR
- DT_BOOLEAN DT_DATETIME
- positiveDecimalValue
- stringValue
- realValue
- charValue
- booleanValue
- nullValue
- binaryValue
- octalValue
- decimalValue
- hexValue
-
-rule
-
- /* Returns a Hash of filename and MofResult */
- mofSpecification
- : /* empty */
- { result = Hash.new }
- | mofProduction
- { result = { @name => @result } }
- | mofSpecification mofProduction
- { result = val[0]
- result[@name] = @result
- }
- ;
-
- mofProduction
- : compilerDirective
- | classDeclaration
- { #puts "Class '#{val[0].name}'"
- @result.classes << val[0]
- }
- | qualifierDeclaration
- { @result.qualifiers << val[0]
- @qualifiers[val[0].name.downcase] = val[0]
- }
- | instanceDeclaration
- { @result.instances << val[0] }
- ;
-
-/***
- * compilerDirective
- *
- */
-
- compilerDirective
- : "#" PRAGMA INCLUDE pragmaParameters_opt
- { raise MOF::Helper::Error.new(@name,@lineno,@line,"Missing filename after '#pragma include'") unless val[3]
- open val[3], :pragma
- }
- | "#" PRAGMA pragmaName pragmaParameters_opt
- | "#" INCLUDE pragmaParameters_opt
- { raise StyleError.new(@name,@lineno,@line,"Use '#pragma include' instead of '#include'") unless @style == :wmi
- raise MOF::Helper::Error.new(@name,@lineno,@line,"Missing filename after '#include'") unless val[2]
- open val[2], :pragma
- }
- ;
-
- pragmaName
- : IDENTIFIER
- ;
-
- pragmaParameters_opt
- : /* empty */
- { raise StyleError.new(@name,@lineno,@line,"#pragma parameter missing") unless @style == :wmi }
- | "(" pragmaParameterValues ")"
- { result = val[1] }
- ;
-
- pragmaParameterValues
- : pragmaParameterValue
- | pragmaParameterValues "," pragmaParameterValue
- ;
-
- pragmaParameterValue
- : string
- | integerValue
- { raise StyleError.new(@name,@lineno,@line,"#pragma parameter missing") unless @style == :wmi }
- | IDENTIFIER
- ;
-
-/***
- * classDeclaration
- *
- */
-
- classDeclaration
- : qualifierList_opt CLASS className alias_opt superClass_opt "{" classFeatures "}" ";"
- { qualifiers = val[0]
- features = val[6]
- # FIXME: features must not include references
- result = CIM::Class.new(val[2],qualifiers,val[3],val[4],features)
- }
- ;
-
- classFeatures
- : /* empty */
- { result = [] }
- | classFeatures classFeature
- { result = val[0] << val[1] }
- ;
-
- classFeature
- : propertyDeclaration
- | methodDeclaration
- | referenceDeclaration /* must have association qualifier */
- ;
-
-
- qualifierList_opt
- : /* empty */
- | qualifierList
- { result = CIM::QualifierSet.new val[0] }
- ;
-
- qualifierList
- : "[" qualifier qualifiers "]"
- { result = val[2]
- result.unshift val[1] if val[1] }
- ;
-
- qualifiers
- : /* empty */
- { result = [] }
- | qualifiers "," qualifier
- { result = val[0]
- result << val[2] if val[2]
- }
- ;
-
- qualifier
- : qualifierName qualifierParameter_opt flavor_opt
- { # Get qualifier decl
- qualifier = case val[0]
- when CIM::Qualifier then val[0].definition
- when CIM::QualifierDeclaration then val[0]
- when String then @qualifiers[val[0].downcase]
- else
- nil
- end
- raise MOF::Helper::Error.new(@name,@lineno,@line,"'#{val[0]}' is not a valid qualifier") unless qualifier
- value = val[1]
- raise MOF::Helper::Error.new(@name,@lineno,@line,"#{value.inspect} does not match qualifier type '#{qualifier.type}'") unless qualifier.type.matches?(value)||@style == :wmi
- # Don't propagate a boolean 'false'
- if qualifier.type == :boolean && value == false
- result = nil
- else
- result = CIM::Qualifier.new(qualifier,value,val[2])
- end
- }
- ;
-
- flavor_opt
- : /* empty */
- | ":" flavor
- { result = CIM::QualifierFlavors.new val[1] }
- ;
-
- qualifierParameter_opt
- : /* empty */
- | qualifierParameter
- ;
-
- qualifierParameter
- : "(" constantValue ")"
- { result = val[1] }
- | arrayInitializer
- ;
-
- /* CIM::Flavors */
- flavor
- : AMENDED | ENABLEOVERRIDE | DISABLEOVERRIDE | RESTRICTED | TOSUBCLASS | TRANSLATABLE | TOINSTANCE
- { case val[0].to_sym
- when :amended, :toinstance
- raise StyleError.new(@name,@lineno,@line,"'#{val[0]}' is not a valid flavor") unless @style == :wmi
- end
- }
- ;
-
- alias_opt
- : /* empty */
- | alias
- ;
-
- superClass_opt
- : /* empty */
- | superClass
- ;
-
- className
- : IDENTIFIER /* must be <schema>_<classname> in CIM v2.x */
- { raise ParseError.new("Class name must be prefixed by '<schema>_'") unless val[0].include?("_") || @style == :wmi }
- ;
-
- alias
- : AS aliasIdentifier
- { result = val[1] }
- ;
-
- aliasIdentifier
- : "$" IDENTIFIER /* NO whitespace ! */
- { result = val[1] }
- ;
-
- superClass
- : ":" className
- { result = val[1] }
- ;
-
-
- propertyDeclaration
- : qualifierList_opt dataType propertyName array_opt defaultValue_opt ";"
- { if val[3]
- type = CIM::Array.new val[3],val[1]
- else
- type = val[1]
- end
- result = CIM::Property.new(type,val[2],val[0],val[4])
- }
- ;
-
- referenceDeclaration
- : qualifierList_opt objectRef referenceName array_opt defaultValue_opt ";"
- { if val[4]
- raise StyleError.new(@name,@lineno,@line,"Array not allowed in reference declaration") unless @style == :wmi
- end
- result = CIM::Reference.new(val[1],val[2],val[0],val[4]) }
- ;
-
- methodDeclaration
- : qualifierList_opt dataType methodName "(" parameterList_opt ")" ";"
- { result = CIM::Method.new(val[1],val[2],val[0],val[4]) }
- ;
-
- propertyName
- : IDENTIFIER
- | PROPERTY
- { # tmplprov.mof has 'string Property;'
- raise StyleError.new(@name,@lineno,@line,"Invalid keyword '#{val[0]}' used for property name") unless @style == :wmi
- }
- ;
-
- referenceName
- : IDENTIFIER
- | INDICATION
- { result = "Indication" }
- ;
-
- methodName
- : IDENTIFIER
- ;
-
- dataType
- : DT_UINT8
- | DT_SINT8
- | DT_UINT16
- | DT_SINT16
- | DT_UINT32
- | DT_SINT32
- | DT_UINT64
- | DT_SINT64
- | DT_REAL32
- | DT_REAL64
- | DT_CHAR16
- | DT_STR
- | DT_BOOLEAN
- | DT_DATETIME
- | DT_VOID
- { raise StyleError.new(@name,@lineno,@line,"'void' is not a valid datatype") unless @style == :wmi }
- ;
-
- objectRef
- : className
- { # WMI uses class names as data types (without REF ?!)
- raise StyleError.new(@name,@lineno,@line,"Expected 'ref' keyword after classname '#{val[0]}'") unless @style == :wmi
- result = CIM::ReferenceType.new val[0]
- }
-
- | className REF
- { result = CIM::ReferenceType.new val[0] }
- ;
-
- parameterList_opt
- : /* empty */
- | parameterList
- ;
-
- parameterList
- : parameter parameters
- { result = val[1].unshift val[0] }
- ;
-
- parameters
- : /* empty */
- { result = [] }
- | parameters "," parameter
- { result = val[0] << val[2] }
- ;
-
- parameter
- : qualifierList_opt typespec parameterName array_opt parameterValue_opt
- { if val[3]
- type = CIM::Array.new val[3], val[1]
- else
- type = val[1]
- end
- result = CIM::Property.new(type,val[2],val[0])
- }
- ;
-
- typespec
- : dataType
- | objectRef
- ;
-
- parameterName
- : IDENTIFIER
- ;
-
- array_opt
- : /* empty */
- | array
- ;
-
- parameterValue_opt
- : /* empty */
- | defaultValue
- { raise "Default parameter value not allowed in syntax style '{@style}'" unless @style == :wmi }
- ;
-
- array
- : "[" positiveDecimalValue_opt "]"
- { result = val[1] }
- ;
-
- positiveDecimalValue_opt
- : /* empty */
- { result = -1 }
- | positiveDecimalValue
- ;
-
- defaultValue_opt
- : /* empty */
- | defaultValue
- ;
-
- defaultValue
- : "=" initializer
- { result = val[1] }
- ;
-
- initializer
- : constantValue
- | arrayInitializer
- | referenceInitializer
- ;
-
- arrayInitializer
- : "{" constantValues "}"
- { result = val[1] }
- ;
-
- constantValues
- : /* empty */
- | constantValue
- { result = [ val[0] ] }
- | constantValues "," constantValue
- { result = val[0] << val[2] }
- ;
-
- constantValue
- : integerValue
- | realValue
- | charValue
- | string
- | booleanValue
- | nullValue
- | instance
- { raise "Instance as property value not allowed in syntax style '{@style}'" unless @style == :wmi }
- ;
-
- integerValue
- : binaryValue
- | octalValue
- | decimalValue
- | positiveDecimalValue
- | hexValue
- ;
-
- string
- : stringValue
- | string stringValue
- { result = val[0] + val[1] }
- ;
-
- referenceInitializer
- : objectHandle
- | aliasIdentifier
- ;
-
- objectHandle
- : namespace_opt modelPath
- ;
-
- namespace_opt
- : /* empty */
- | namespaceHandle ":"
- ;
-
- namespaceHandle
- : IDENTIFIER
- ;
-
- /*
- * Note
- : structure depends on type of namespace
- */
-
- modelPath
- : className "." keyValuePairList
- ;
-
- keyValuePairList
- : keyValuePair keyValuePairs
- ;
-
- keyValuePairs
- : /* empty */
- | keyValuePairs "," keyValuePair
- ;
-
- keyValuePair
- : keyname "=" initializer
- ;
-
- keyname
- : propertyName | referenceName
- ;
-
-/***
- * qualifierDeclaration
- *
- */
-
- qualifierDeclaration
- /* 0 1 2 3 4 */
- : QUALIFIER qualifierName qualifierType scope defaultFlavor_opt ";"
- { result = CIM::QualifierDeclaration.new( val[1], val[2][0], val[2][1], val[3], val[4]) }
- ;
-
- defaultFlavor_opt
- : /* empty */
- | defaultFlavor
- ;
-
- qualifierName
- : IDENTIFIER
- | ASSOCIATION /* meta qualifier */
- | INDICATION /* meta qualifier */
- | REFERENCE /* Added in DSP0004 2.7.0 */
- | SCHEMA
- ;
-
- /* [type, value] */
- qualifierType
- : ":" dataType array_opt defaultValue_opt
- { type = val[2].nil? ? val[1] : CIM::Array.new(val[2],val[1])
- result = [ type, val[3] ]
- }
- ;
-
- scope
- : "," SCOPE "(" metaElements ")"
- { result = CIM::QualifierScopes.new(val[3]) }
- ;
-
- metaElements
- : metaElement
- { result = [ val[0] ] }
- | metaElements "," metaElement
- { result = val[0] << val[2] }
- ;
-
- metaElement
- : SCHEMA
- | CLASS
- | ASSOCIATION
- | INDICATION
- | QUALIFIER
- | PROPERTY
- | REFERENCE
- | METHOD
- | PARAMETER
- | ANY
- ;
-
- defaultFlavor
- : "," FLAVOR "(" flavors ")"
- { result = CIM::QualifierFlavors.new val[3] }
- ;
-
- flavors
- : flavor
- { result = [ val[0] ] }
- | flavors "," flavor
- { result = val[0] << val[2] }
- ;
-
-/***
- * instanceDeclaration
- *
- */
-
- instanceDeclaration
- : instance ";"
- ;
-
- instance
- : qualifierList_opt INSTANCE OF className alias_opt "{" valueInitializers "}"
- ;
-
- valueInitializers
- : valueInitializer
- | valueInitializers valueInitializer
- ;
-
- valueInitializer
- : qualifierList_opt keyname "=" initializer ";"
- | qualifierList_opt keyname ";"
- { raise "Instance property '#{val[1]} must have a value" unless @style == :wmi }
- ;
-
-end # class Parser
-
----- header ----
-
-# parser.rb - generated by racc
-
-require 'strscan'
-require 'rubygems'
-require 'cim'
-require File.join(__dir__, 'result')
-require File.join(__dir__, 'scanner')
-require File.join(__dir__, 'case')
-
----- inner ----
-
-#
-# Initialize MOF::Parser
-# MOF::Parser.new options = {}
-#
-# options -> Hash of options
-# :debug -> boolean
-# :includes -> array of include dirs
-# :style -> :cim or :wmi
-#
-def initialize options = {}
- @yydebug = options[:debug]
- @includes = options[:includes] || []
- @quiet = options[:quiet]
- @style = options[:style] || :cim # default to style CIM v2.2 syntax
-
- @lineno = 1
- @file = nil
- @iconv = nil
- @eol = "\n"
- @fname = nil
- @fstack = []
- @in_comment = false
- @seen_files = []
- @qualifiers = {}
-end
-
-#
-# Make options hash from argv
-#
-# returns [ files, options ]
-#
-
- def self.argv_handler name, argv
- files = []
- options = { :namespace => "" }
- while argv.size > 0
- case opt = argv.shift
- when "-h"
- $stderr.puts "Ruby MOF compiler"
- $stderr.puts "#{name} [-h] [-d] [-I <dir>] [<moffiles>]"
- $stderr.puts "Compiles <moffile>"
- $stderr.puts "\t-d debug"
- $stderr.puts "\t-h this help"
- $stderr.puts "\t-I <dir> include dir"
- $stderr.puts "\t-f force"
- $stderr.puts "\t-n <namespace>"
- $stderr.puts "\t-o <output>"
- $stderr.puts "\t-s <style> syntax style (wmi,cim)"
- $stderr.puts "\t-q quiet"
- $stderr.puts "\t<moffiles> file(s) to read (else use $stdin)"
- exit 0
- when "-f" then options[:force] = true
- when "-s" then options[:style] = argv.shift.to_sym
- when "-d" then options[:debug] = true
- when "-q" then options[:quiet] = true
- when "-I"
- options[:includes] ||= []
- dirname = argv.shift
- unless File.directory?(dirname)
- files << dirname
- dirname = File.dirname(dirname)
- end
- options[:includes] << Pathname.new(dirname)
- when "-n" then options[:namespace] = argv.shift
- when "-o" then options[:output] = argv.shift
- when /^-.+/
- $stderr.puts "Undefined option #{opt}"
- else
- files << opt
- end
- end
- [ files, options ]
- end
-
-include Helper
-include Scanner
-
----- footer ----
diff --git a/test/racc/assets/namae.y b/test/racc/assets/namae.y
deleted file mode 100644
index 0378345fef..0000000000
--- a/test/racc/assets/namae.y
+++ /dev/null
@@ -1,302 +0,0 @@
-# -*- ruby -*-
-# vi: set ft=ruby :
-
-# Copyright (C) 2012 President and Fellows of Harvard College
-# Copyright (C) 2013-2014 Sylvester Keil
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#
-# 1. Redistributions of source code must retain the above copyright notice,
-# this list of conditions and the following disclaimer.
-#
-# 2. Redistributions in binary form must reproduce the above copyright notice,
-# this list of conditions and the following disclaimer in the documentation
-# and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-# EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
-# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
-# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
-# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-# The views and conclusions contained in the software and documentation are
-# those of the authors and should not be interpreted as representing official
-# policies, either expressed or implied, of the copyright holder.
-
-class Namae::Parser
-
-token COMMA UWORD LWORD PWORD NICK AND APPELLATION TITLE SUFFIX
-
-expect 0
-
-rule
-
- names : { result = [] }
- | name { result = [val[0]] }
- | names AND name { result = val[0] << val[2] }
-
- name : word { result = Name.new(:given => val[0]) }
- | display_order
- | honorific word { result = val[0].merge(:family => val[1]) }
- | honorific display_order { result = val[1].merge(val[0]) }
- | sort_order
-
- honorific : APPELLATION { result = Name.new(:appellation => val[0]) }
- | TITLE { result = Name.new(:title => val[0]) }
-
- display_order : u_words word opt_suffices opt_titles
- {
- result = Name.new(:given => val[0], :family => val[1],
- :suffix => val[2], :title => val[3])
- }
- | u_words NICK last opt_suffices opt_titles
- {
- result = Name.new(:given => val[0], :nick => val[1],
- :family => val[2], :suffix => val[3], :title => val[4])
- }
- | u_words NICK von last opt_suffices opt_titles
- {
- result = Name.new(:given => val[0], :nick => val[1],
- :particle => val[2], :family => val[3],
- :suffix => val[4], :title => val[5])
- }
- | u_words von last
- {
- result = Name.new(:given => val[0], :particle => val[1],
- :family => val[2])
- }
- | von last
- {
- result = Name.new(:particle => val[0], :family => val[1])
- }
-
- sort_order : last COMMA first
- {
- result = Name.new({ :family => val[0], :suffix => val[2][0],
- :given => val[2][1] }, !!val[2][0])
- }
- | von last COMMA first
- {
- result = Name.new({ :particle => val[0], :family => val[1],
- :suffix => val[3][0], :given => val[3][1] }, !!val[3][0])
- }
- | u_words von last COMMA first
- {
- result = Name.new({ :particle => val[0,2].join(' '), :family => val[2],
- :suffix => val[4][0], :given => val[4][1] }, !!val[4][0])
- }
- ;
-
- von : LWORD
- | von LWORD { result = val.join(' ') }
- | von u_words LWORD { result = val.join(' ') }
-
- last : LWORD | u_words
-
- first : opt_words { result = [nil,val[0]] }
- | words opt_comma suffices { result = [val[2],val[0]] }
- | suffices { result = [val[0],nil] }
- | suffices COMMA words { result = [val[0],val[2]] }
-
- u_words : u_word
- | u_words u_word { result = val.join(' ') }
-
- u_word : UWORD | PWORD
-
- words : word
- | words word { result = val.join(' ') }
-
- opt_comma : /* empty */ | COMMA
- opt_words : /* empty */ | words
-
- word : LWORD | UWORD | PWORD
-
- opt_suffices : /* empty */ | suffices
-
- suffices : SUFFIX
- | suffices SUFFIX { result = val.join(' ') }
-
- opt_titles : /* empty */ | titles
-
- titles : TITLE
- | titles TITLE { result = val.join(' ') }
-
----- header
-require 'singleton'
-require 'strscan'
-
----- inner
-
- include Singleton
-
- attr_reader :options, :input
-
- def initialize
- @input, @options = StringScanner.new(''), {
- :debug => false,
- :prefer_comma_as_separator => false,
- :comma => ',',
- :stops => ',;',
- :separator => /\s*(\band\b|\&|;)\s*/i,
- :title => /\s*\b(sir|lord|count(ess)?|(gen|adm|col|maj|capt|cmdr|lt|sgt|cpl|pvt|prof|dr|md|ph\.?d)\.?)(\s+|$)/i,
- :suffix => /\s*\b(JR|Jr|jr|SR|Sr|sr|[IVX]{2,})(\.|\b)/,
- :appellation => /\s*\b((mrs?|ms|fr|hr)\.?|miss|herr|frau)(\s+|$)/i
- }
- end
-
- def debug?
- options[:debug] || ENV['DEBUG']
- end
-
- def separator
- options[:separator]
- end
-
- def comma
- options[:comma]
- end
-
- def stops
- options[:stops]
- end
-
- def title
- options[:title]
- end
-
- def suffix
- options[:suffix]
- end
-
- def appellation
- options[:appellation]
- end
-
- def prefer_comma_as_separator?
- options[:prefer_comma_as_separator]
- end
-
- def parse(input)
- parse!(input)
- rescue => e
- warn e.message if debug?
- []
- end
-
- def parse!(string)
- input.string = normalize(string)
- reset
- do_parse
- end
-
- def normalize(string)
- string = string.strip
- string
- end
-
- def reset
- @commas, @words, @initials, @suffices, @yydebug = 0, 0, 0, 0, debug?
- self
- end
-
- private
-
- def stack
- @vstack || @racc_vstack || []
- end
-
- def last_token
- stack[-1]
- end
-
- def consume_separator
- return next_token if seen_separator?
- @commas, @words, @initials, @suffices = 0, 0, 0, 0
- [:AND, :AND]
- end
-
- def consume_comma
- @commas += 1
- [:COMMA, :COMMA]
- end
-
- def consume_word(type, word)
- @words += 1
-
- case type
- when :UWORD
- @initials += 1 if word =~ /^[[:upper:]]+\b/
- when :SUFFIX
- @suffices += 1
- end
-
- [type, word]
- end
-
- def seen_separator?
- !stack.empty? && last_token == :AND
- end
-
- def suffix?
- !@suffices.zero? || will_see_suffix?
- end
-
- def will_see_suffix?
- input.peek(8).to_s.strip.split(/\s+/)[0] =~ suffix
- end
-
- def will_see_initial?
- input.peek(6).to_s.strip.split(/\s+/)[0] =~ /^[[:upper:]]+\b/
- end
-
- def seen_full_name?
- prefer_comma_as_separator? && @words > 1 &&
- (@initials > 0 || !will_see_initial?) && !will_see_suffix?
- end
-
- def next_token
- case
- when input.nil?, input.eos?
- nil
- when input.scan(separator)
- consume_separator
- when input.scan(/\s*#{comma}\s*/)
- if @commas.zero? && !seen_full_name? || @commas == 1 && suffix?
- consume_comma
- else
- consume_separator
- end
- when input.scan(/\s+/)
- next_token
- when input.scan(title)
- consume_word(:TITLE, input.matched.strip)
- when input.scan(suffix)
- consume_word(:SUFFIX, input.matched.strip)
- when input.scan(appellation)
- [:APPELLATION, input.matched.strip]
- when input.scan(/((\\\w+)?\{[^\}]*\})*[[:upper:]][^\s#{stops}]*/)
- consume_word(:UWORD, input.matched)
- when input.scan(/((\\\w+)?\{[^\}]*\})*[[:lower:]][^\s#{stops}]*/)
- consume_word(:LWORD, input.matched)
- when input.scan(/(\\\w+)?\{[^\}]*\}[^\s#{stops}]*/)
- consume_word(:PWORD, input.matched)
- when input.scan(/('[^'\n]+')|("[^"\n]+")/)
- consume_word(:NICK, input.matched[1...-1])
- else
- raise ArgumentError,
- "Failed to parse name #{input.string.inspect}: unmatched data at offset #{input.pos}"
- end
- end
-
- def on_error(tid, value, stack)
- raise ArgumentError,
- "Failed to parse name: unexpected '#{value}' at #{stack.inspect}"
- end
-
-# -*- racc -*-
diff --git a/test/racc/assets/nasl.y b/test/racc/assets/nasl.y
deleted file mode 100644
index c7b8e46551..0000000000
--- a/test/racc/assets/nasl.y
+++ /dev/null
@@ -1,626 +0,0 @@
-################################################################################
-# Copyright (c) 2011-2014, Tenable Network Security
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#
-# 1. Redistributions of source code must retain the above copyright notice, this
-# list of conditions and the following disclaimer.
-#
-# 2. Redistributions in binary form must reproduce the above copyright notice,
-# this list of conditions and the following disclaimer in the documentation
-# and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-################################################################################
-
-class Nasl::Grammar
-
-preclow
- right ASS_EQ ADD_EQ SUB_EQ MUL_EQ DIV_EQ MOD_EQ SLL_EQ SRA_EQ SRL_EQ
- left OR
- left AND
- left CMP_LT CMP_GT CMP_EQ CMP_NE CMP_GE CMP_LE SUBSTR_EQ SUBSTR_NE REGEX_EQ REGEX_NE
- left BIT_OR
- left BIT_XOR
- left AMPERSAND
- left BIT_SRA BIT_SRL BIT_SLL
- left ADD SUB
- left MUL DIV MOD
- right NOT
- right UMINUS BIT_NOT
- right EXP
- right INCR DECR
-prechigh
-
-# Tell the parser generator that we don't wish to use the result variable in the
-# action section of rules. Instead, the result of the rule will be the value of
-# evaluating the action block.
-options no_result_var
-
-# Tell the parser generator that we expect one shift/reduce conflict due to the
-# well-known dangling else problem. We could make the grammar solve this
-# problem, but this is how the NASL YACC file solves it, so we'll follow suit.
-expect 1
-
-rule
- ##############################################################################
- # Aggregate Statements
- ##############################################################################
-
- start : roots
- { val[0] }
- | /* Blank */
- { [] }
- ;
-
- roots : root roots
- { [val[0]] + val[1] }
- | root
- { [val[0]] }
- ;
-
- root : COMMENT export
- { c(*val) }
- | export
- { val[0] }
- | COMMENT function
- { c(*val) }
- | function
- { val[0] }
- | statement
- { val[0] }
- ;
-
- statement : simple
- { val[0] }
- | compound
- { val[0] }
- ;
-
- ##############################################################################
- # Root Statements
- ##############################################################################
-
- export : EXPORT function
- { n(:Export, *val) }
- ;
-
- function : FUNCTION ident LPAREN params RPAREN block
- { n(:Function, *val) }
- | FUNCTION ident LPAREN RPAREN block
- { n(:Function, *val) }
- ;
-
- simple : assign
- { val[0] }
- | break
- { val[0] }
- | call
- { val[0] }
- | continue
- { val[0] }
- | decr
- { val[0] }
- | empty
- { val[0] }
- | COMMENT global
- { c(*val) }
- | global
- { val[0] }
- | import
- { val[0] }
- | include
- { val[0] }
- | incr
- { val[0] }
- | local
- { val[0] }
- | rep
- { val[0] }
- | return
- { val[0] }
- ;
-
- compound : block
- { val[0] }
- | for
- { val[0] }
- | foreach
- { val[0] }
- | if
- { val[0] }
- | repeat
- { val[0] }
- | while
- { val[0] }
- ;
-
- ##############################################################################
- # Simple Statements
- ##############################################################################
-
- assign : assign_exp SEMICOLON
- { val[0] }
- ;
-
- break : BREAK SEMICOLON
- { n(:Break, *val) }
- ;
-
- call : call_exp SEMICOLON
- { val[0] }
- ;
-
- continue : CONTINUE SEMICOLON
- { n(:Continue, *val) }
- ;
-
- decr : decr_exp SEMICOLON
- { val[0] }
- ;
-
- empty : SEMICOLON
- { n(:Empty, *val) }
- ;
-
- global : GLOBAL var_decls SEMICOLON
- { n(:Global, *val) }
- ;
-
- incr : incr_exp SEMICOLON
- { val[0] }
- ;
-
- import : IMPORT LPAREN string RPAREN SEMICOLON
- { n(:Import, *val) }
- ;
-
- include : INCLUDE LPAREN string RPAREN SEMICOLON
- { n(:Include, *val) }
- ;
-
- local : LOCAL var_decls SEMICOLON
- { n(:Local, *val) }
- ;
-
- rep : call_exp REP expr SEMICOLON
- { n(:Repetition, *val[0..-1]) }
- ;
-
- return : RETURN expr SEMICOLON
- { n(:Return, *val) }
- | RETURN ref SEMICOLON
- { n(:Return, *val) }
- | RETURN SEMICOLON
- { n(:Return, *val) }
- ;
-
- ##############################################################################
- # Compound Statements
- ##############################################################################
-
- block : LBRACE statements RBRACE
- { n(:Block, *val) }
- | LBRACE RBRACE
- { n(:Block, *val) }
- ;
-
- for : FOR LPAREN field SEMICOLON expr SEMICOLON field RPAREN statement
- { n(:For, *val) }
- ;
-
- foreach : FOREACH ident LPAREN expr RPAREN statement
- { n(:Foreach, val[0], val[1], val[3], val[5]) }
- | FOREACH LPAREN ident IN expr RPAREN statement
- { n(:Foreach, val[0], val[2], val[4], val[6]) }
- ;
-
- if : IF LPAREN expr RPAREN statement
- { n(:If, *val) }
- | IF LPAREN expr RPAREN statement ELSE statement
- { n(:If, *val) }
- ;
-
- repeat : REPEAT statement UNTIL expr SEMICOLON
- { n(:Repeat, *val) }
- ;
-
- while : WHILE LPAREN expr RPAREN statement
- { n(:While, *val) }
- ;
-
- ##############################################################################
- # Expressions
- ##############################################################################
-
- assign_exp : lval ASS_EQ expr
- { n(:Assignment, *val) }
- | lval ASS_EQ ref
- { n(:Assignment, *val) }
- | lval ADD_EQ expr
- { n(:Assignment, *val) }
- | lval SUB_EQ expr
- { n(:Assignment, *val) }
- | lval MUL_EQ expr
- { n(:Assignment, *val) }
- | lval DIV_EQ expr
- { n(:Assignment, *val) }
- | lval MOD_EQ expr
- { n(:Assignment, *val) }
- | lval SRL_EQ expr
- { n(:Assignment, *val) }
- | lval SRA_EQ expr
- { n(:Assignment, *val) }
- | lval SLL_EQ expr
- { n(:Assignment, *val) }
- ;
-
- call_exp : lval LPAREN args RPAREN
- { n(:Call, *val) }
- | lval LPAREN RPAREN
- { n(:Call, *val) }
- ;
-
- decr_exp : DECR lval
- { n(:Decrement, val[0]) }
- | lval DECR
- { n(:Decrement, val[0]) }
- ;
-
- incr_exp : INCR lval
- { n(:Increment, val[0]) }
- | lval INCR
- { n(:Increment, val[0]) }
- ;
-
- expr : LPAREN expr RPAREN
- { n(:Expression, *val) }
- | expr AND expr
- { n(:Expression, *val) }
- | NOT expr
- { n(:Expression, *val) }
- | expr OR expr
- { n(:Expression, *val) }
- | expr ADD expr
- { n(:Expression, *val) }
- | expr SUB expr
- { n(:Expression, *val) }
- | SUB expr =UMINUS
- { n(:Expression, *val) }
- | BIT_NOT expr
- { n(:Expression, *val) }
- | expr MUL expr
- { n(:Expression, *val) }
- | expr EXP expr
- { n(:Expression, *val) }
- | expr DIV expr
- { n(:Expression, *val) }
- | expr MOD expr
- { n(:Expression, *val) }
- | expr AMPERSAND expr
- { n(:Expression, *val) }
- | expr BIT_XOR expr
- { n(:Expression, *val) }
- | expr BIT_OR expr
- { n(:Expression, *val) }
- | expr BIT_SRA expr
- { n(:Expression, *val) }
- | expr BIT_SRL expr
- { n(:Expression, *val) }
- | expr BIT_SLL expr
- { n(:Expression, *val) }
- | incr_exp
- { val[0] }
- | decr_exp
- { val[0] }
- | expr SUBSTR_EQ expr
- { n(:Expression, *val) }
- | expr SUBSTR_NE expr
- { n(:Expression, *val) }
- | expr REGEX_EQ expr
- { n(:Expression, *val) }
- | expr REGEX_NE expr
- { n(:Expression, *val) }
- | expr CMP_LT expr
- { n(:Expression, *val) }
- | expr CMP_GT expr
- { n(:Expression, *val) }
- | expr CMP_EQ expr
- { n(:Expression, *val) }
- | expr CMP_NE expr
- { n(:Expression, *val) }
- | expr CMP_GE expr
- { n(:Expression, *val) }
- | expr CMP_LE expr
- { n(:Expression, *val) }
- | assign_exp
- { val[0] }
- | string
- { val[0] }
- | call_exp
- { val[0] }
- | lval
- { val[0] }
- | ip
- { val[0] }
- | int
- { val[0] }
- | undef
- { val[0] }
- | list_expr
- { val[0] }
- | array_expr
- { val[0] }
- ;
-
- ##############################################################################
- # Named Components
- ##############################################################################
-
- arg : ident COLON expr
- { n(:Argument, *val) }
- | ident COLON ref
- { n(:Argument, *val) }
- | expr
- { n(:Argument, *val) }
- | ref
- { n(:Argument, *val) }
- ;
-
- kv_pair : string COLON expr
- { n(:KeyValuePair, *val) }
- | int COLON expr
- { n(:KeyValuePair, *val) }
- | ident COLON expr
- { n(:KeyValuePair, *val) }
- | string COLON ref
- { n(:KeyValuePair, *val) }
- | int COLON ref
- { n(:KeyValuePair, *val) }
- | ident COLON ref
- { n(:KeyValuePair, *val) }
- ;
-
- kv_pairs : kv_pair COMMA kv_pairs
- { [val[0]] + val[2] }
- | kv_pair COMMA
- { [val[0]] }
- | kv_pair
- { [val[0]] }
- ;
-
- lval : ident indexes
- { n(:Lvalue, *val) }
- | ident
- { n(:Lvalue, *val) }
- ;
-
- ref : AT_SIGN ident
- { n(:Reference, val[1]) }
- ;
-
- ##############################################################################
- # Anonymous Components
- ##############################################################################
-
- args : arg COMMA args
- { [val[0]] + val[2] }
- | arg
- { [val[0]] }
- ;
-
- array_expr : LBRACE kv_pairs RBRACE
- { n(:Array, *val) }
- | LBRACE RBRACE
- { n(:Array, *val) }
- ;
-
- field : assign_exp
- { val[0] }
- | call_exp
- { val[0] }
- | decr_exp
- { val[0] }
- | incr_exp
- { val[0] }
- | /* Blank */
- { nil }
- ;
-
- index : LBRACK expr RBRACK
- { val[1] }
- | PERIOD ident
- { val[1] }
- ;
-
- indexes : index indexes
- { [val[0]] + val[1] }
- | index
- { [val[0]] }
- ;
-
- list_elem : expr
- { val[0] }
- | ref
- { val[0] }
- ;
-
- list_elems : list_elem COMMA list_elems
- { [val[0]] + val[2] }
- | list_elem
- { [val[0]] }
- ;
-
- list_expr : LBRACK list_elems RBRACK
- { n(:List, *val) }
- | LBRACK RBRACK
- { n(:List, *val) }
- ;
-
- param : AMPERSAND ident
- { n(:Parameter, val[1], 'reference') }
- | ident
- { n(:Parameter, val[0], 'value') }
- ;
-
- params : param COMMA params
- { [val[0]] + val[2] }
- | param
- { [val[0]] }
- ;
-
- statements : statement statements
- { [val[0]] + val[1] }
- | statement
- { [val[0]] }
- ;
-
- var_decl : ident ASS_EQ expr
- { n(:Assignment, *val) }
- | ident ASS_EQ ref
- { n(:Assignment, *val) }
- | ident
- { val[0] }
- ;
-
- var_decls : var_decl COMMA var_decls
- { [val[0]] + val[2] }
- | var_decl
- { [val[0]] }
- ;
-
- ##############################################################################
- # Literals
- ##############################################################################
-
- ident : IDENT
- { n(:Identifier, *val) }
- | REP
- { n(:Identifier, *val) }
- | IN
- { n(:Identifier, *val) }
- ;
-
- int : INT_DEC
- { n(:Integer, *val) }
- | INT_HEX
- { n(:Integer, *val) }
- | INT_OCT
- { n(:Integer, *val) }
- | FALSE
- { n(:Integer, *val) }
- | TRUE
- { n(:Integer, *val) }
- ;
-
- ip : int PERIOD int PERIOD int PERIOD int
- { n(:Ip, *val) }
-
- string : DATA
- { n(:String, *val) }
- | STRING
- { n(:String, *val) }
- ;
-
- undef : UNDEF
- { n(:Undefined, *val) }
- ;
-end
-
----- header ----
-
-require 'nasl/parser/tree'
-
-require 'nasl/parser/argument'
-require 'nasl/parser/array'
-require 'nasl/parser/assigment'
-require 'nasl/parser/block'
-require 'nasl/parser/break'
-require 'nasl/parser/call'
-require 'nasl/parser/comment'
-require 'nasl/parser/continue'
-require 'nasl/parser/decrement'
-require 'nasl/parser/empty'
-require 'nasl/parser/export'
-require 'nasl/parser/expression'
-require 'nasl/parser/for'
-require 'nasl/parser/foreach'
-require 'nasl/parser/function'
-require 'nasl/parser/global'
-require 'nasl/parser/identifier'
-require 'nasl/parser/if'
-require 'nasl/parser/import'
-require 'nasl/parser/include'
-require 'nasl/parser/increment'
-require 'nasl/parser/integer'
-require 'nasl/parser/ip'
-require 'nasl/parser/key_value_pair'
-require 'nasl/parser/list'
-require 'nasl/parser/local'
-require 'nasl/parser/lvalue'
-require 'nasl/parser/parameter'
-require 'nasl/parser/reference'
-require 'nasl/parser/repeat'
-require 'nasl/parser/repetition'
-require 'nasl/parser/return'
-require 'nasl/parser/string'
-require 'nasl/parser/undefined'
-require 'nasl/parser/while'
-
----- inner ----
-
-def n(cls, *args)
- begin
- Nasl.const_get(cls).new(@tree, *args)
- rescue
- puts "An exception occurred during the creation of a #{cls} instance."
- puts
- puts "The arguments passed to the constructor were:"
- puts args
- puts
- puts @tok.last.context
- puts
- raise
- end
-end
-
-def c(*args)
- n(:Comment, *args)
- args[1]
-end
-
-def on_error(type, value, stack)
- raise ParseException, "The language's grammar does not permit #{value.name} to appear here", value.context
-end
-
-def next_token
- @tok = @tkz.get_token
-
- if @first && @tok.first == :COMMENT
- n(:Comment, @tok.last)
- @tok = @tkz.get_token
- end
- @first = false
-
- return @tok
-end
-
-def parse(env, code, path)
- @first = true
- @tree = Tree.new(env)
- @tkz = Tokenizer.new(code, path)
- @tree.concat(do_parse)
-end
-
----- footer ----
diff --git a/test/racc/assets/newsyn.y b/test/racc/assets/newsyn.y
deleted file mode 100644
index 5b670c966a..0000000000
--- a/test/racc/assets/newsyn.y
+++ /dev/null
@@ -1,25 +0,0 @@
-
-class A
-
- preclow
- left preclow prechigh right left nonassoc token
- right preclow prechigh right left nonassoc token
- nonassoc preclow prechigh right left nonassoc token
- prechigh
-
- convert
- left 'a'
- right 'b'
- preclow 'c'
- nonassoc 'd'
- preclow 'e'
- prechigh 'f'
- end
-
-rule
-
- left: right nonassoc preclow prechigh
-
- right: A B C
-
-end
diff --git a/test/racc/assets/noend.y b/test/racc/assets/noend.y
deleted file mode 100644
index 5aa0670be0..0000000000
--- a/test/racc/assets/noend.y
+++ /dev/null
@@ -1,4 +0,0 @@
-class MyParser
-rule
-input: A B C
-end
diff --git a/test/racc/assets/nokogiri-css.y b/test/racc/assets/nokogiri-css.y
deleted file mode 100644
index 24dfbf3b1b..0000000000
--- a/test/racc/assets/nokogiri-css.y
+++ /dev/null
@@ -1,255 +0,0 @@
-class Nokogiri::CSS::Parser
-
-token FUNCTION INCLUDES DASHMATCH LBRACE HASH PLUS GREATER S STRING IDENT
-token COMMA NUMBER PREFIXMATCH SUFFIXMATCH SUBSTRINGMATCH TILDE NOT_EQUAL
-token SLASH DOUBLESLASH NOT EQUAL RPAREN LSQUARE RSQUARE HAS
-
-rule
- selector
- : selector COMMA simple_selector_1toN {
- result = [val.first, val.last].flatten
- }
- | prefixless_combinator_selector { result = val.flatten }
- | optional_S simple_selector_1toN { result = [val.last].flatten }
- ;
- combinator
- : PLUS { result = :DIRECT_ADJACENT_SELECTOR }
- | GREATER { result = :CHILD_SELECTOR }
- | TILDE { result = :FOLLOWING_SELECTOR }
- | DOUBLESLASH { result = :DESCENDANT_SELECTOR }
- | SLASH { result = :CHILD_SELECTOR }
- ;
- simple_selector
- : element_name hcap_0toN {
- result = if val[1].nil?
- val.first
- else
- Node.new(:CONDITIONAL_SELECTOR, [val.first, val[1]])
- end
- }
- | function
- | function pseudo {
- result = Node.new(:CONDITIONAL_SELECTOR, val)
- }
- | function attrib {
- result = Node.new(:CONDITIONAL_SELECTOR, val)
- }
- | hcap_1toN {
- result = Node.new(:CONDITIONAL_SELECTOR,
- [Node.new(:ELEMENT_NAME, ['*']), val.first]
- )
- }
- ;
- prefixless_combinator_selector
- : combinator simple_selector_1toN {
- result = Node.new(val.first, [nil, val.last])
- }
- ;
- simple_selector_1toN
- : simple_selector combinator simple_selector_1toN {
- result = Node.new(val[1], [val.first, val.last])
- }
- | simple_selector S simple_selector_1toN {
- result = Node.new(:DESCENDANT_SELECTOR, [val.first, val.last])
- }
- | simple_selector
- ;
- class
- : '.' IDENT { result = Node.new(:CLASS_CONDITION, [val[1]]) }
- ;
- element_name
- : namespaced_ident
- | '*' { result = Node.new(:ELEMENT_NAME, val) }
- ;
- namespaced_ident
- : namespace '|' IDENT {
- result = Node.new(:ELEMENT_NAME,
- [[val.first, val.last].compact.join(':')]
- )
- }
- | IDENT {
- name = @namespaces.key?('xmlns') ? "xmlns:#{val.first}" : val.first
- result = Node.new(:ELEMENT_NAME, [name])
- }
- ;
- namespace
- : IDENT { result = val[0] }
- |
- ;
- attrib
- : LSQUARE attrib_name attrib_val_0or1 RSQUARE {
- result = Node.new(:ATTRIBUTE_CONDITION,
- [val[1]] + (val[2] || [])
- )
- }
- | LSQUARE function attrib_val_0or1 RSQUARE {
- result = Node.new(:ATTRIBUTE_CONDITION,
- [val[1]] + (val[2] || [])
- )
- }
- | LSQUARE NUMBER RSQUARE {
- # Non standard, but hpricot supports it.
- result = Node.new(:PSEUDO_CLASS,
- [Node.new(:FUNCTION, ['nth-child(', val[1]])]
- )
- }
- ;
- attrib_name
- : namespace '|' IDENT {
- result = Node.new(:ELEMENT_NAME,
- [[val.first, val.last].compact.join(':')]
- )
- }
- | IDENT {
- # Default namespace is not applied to attributes.
- # So we don't add prefix "xmlns:" as in namespaced_ident.
- result = Node.new(:ELEMENT_NAME, [val.first])
- }
- ;
- function
- : FUNCTION RPAREN {
- result = Node.new(:FUNCTION, [val.first.strip])
- }
- | FUNCTION expr RPAREN {
- result = Node.new(:FUNCTION, [val.first.strip, val[1]].flatten)
- }
- | FUNCTION nth RPAREN {
- result = Node.new(:FUNCTION, [val.first.strip, val[1]].flatten)
- }
- | NOT expr RPAREN {
- result = Node.new(:FUNCTION, [val.first.strip, val[1]].flatten)
- }
- | HAS selector RPAREN {
- result = Node.new(:FUNCTION, [val.first.strip, val[1]].flatten)
- }
- ;
- expr
- : NUMBER COMMA expr { result = [val.first, val.last] }
- | STRING COMMA expr { result = [val.first, val.last] }
- | IDENT COMMA expr { result = [val.first, val.last] }
- | NUMBER
- | STRING
- | IDENT # even, odd
- {
- case val[0]
- when 'even'
- result = Node.new(:NTH, ['2','n','+','0'])
- when 'odd'
- result = Node.new(:NTH, ['2','n','+','1'])
- when 'n'
- result = Node.new(:NTH, ['1','n','+','0'])
- else
- # This is not CSS standard. It allows us to support this:
- # assert_xpath("//a[foo(., @href)]", @parser.parse('a:foo(@href)'))
- # assert_xpath("//a[foo(., @a, b)]", @parser.parse('a:foo(@a, b)'))
- # assert_xpath("//a[foo(., a, 10)]", @parser.parse('a:foo(a, 10)'))
- result = val
- end
- }
- ;
- nth
- : NUMBER IDENT PLUS NUMBER # 5n+3 -5n+3
- {
- if val[1] == 'n'
- result = Node.new(:NTH, val)
- else
- raise Racc::ParseError, "parse error on IDENT '#{val[1]}'"
- end
- }
- | IDENT PLUS NUMBER { # n+3, -n+3
- if val[0] == 'n'
- val.unshift("1")
- result = Node.new(:NTH, val)
- elsif val[0] == '-n'
- val[0] = 'n'
- val.unshift("-1")
- result = Node.new(:NTH, val)
- else
- raise Racc::ParseError, "parse error on IDENT '#{val[1]}'"
- end
- }
- | NUMBER IDENT { # 5n, -5n, 10n-1
- n = val[1]
- if n[0, 2] == 'n-'
- val[1] = 'n'
- val << "-"
- # b is contained in n as n is the string "n-b"
- val << n[2, n.size]
- result = Node.new(:NTH, val)
- elsif n == 'n'
- val << "+"
- val << "0"
- result = Node.new(:NTH, val)
- else
- raise Racc::ParseError, "parse error on IDENT '#{val[1]}'"
- end
- }
- ;
- pseudo
- : ':' function {
- result = Node.new(:PSEUDO_CLASS, [val[1]])
- }
- | ':' IDENT { result = Node.new(:PSEUDO_CLASS, [val[1]]) }
- ;
- hcap_0toN
- : hcap_1toN
- |
- ;
- hcap_1toN
- : attribute_id hcap_1toN {
- result = Node.new(:COMBINATOR, val)
- }
- | class hcap_1toN {
- result = Node.new(:COMBINATOR, val)
- }
- | attrib hcap_1toN {
- result = Node.new(:COMBINATOR, val)
- }
- | pseudo hcap_1toN {
- result = Node.new(:COMBINATOR, val)
- }
- | negation hcap_1toN {
- result = Node.new(:COMBINATOR, val)
- }
- | attribute_id
- | class
- | attrib
- | pseudo
- | negation
- ;
- attribute_id
- : HASH { result = Node.new(:ID, val) }
- ;
- attrib_val_0or1
- : eql_incl_dash IDENT { result = [val.first, val[1]] }
- | eql_incl_dash STRING { result = [val.first, val[1]] }
- |
- ;
- eql_incl_dash
- : EQUAL { result = :equal }
- | PREFIXMATCH { result = :prefix_match }
- | SUFFIXMATCH { result = :suffix_match }
- | SUBSTRINGMATCH { result = :substring_match }
- | NOT_EQUAL { result = :not_equal }
- | INCLUDES { result = :includes }
- | DASHMATCH { result = :dash_match }
- ;
- negation
- : NOT negation_arg RPAREN {
- result = Node.new(:NOT, [val[1]])
- }
- ;
- negation_arg
- : element_name
- | element_name hcap_1toN
- | hcap_1toN
- ;
- optional_S
- : S
- |
- ;
-end
-
----- header
-
-require 'nokogiri/css/parser_extras'
diff --git a/test/racc/assets/nonass.y b/test/racc/assets/nonass.y
deleted file mode 100644
index b9a35a2626..0000000000
--- a/test/racc/assets/nonass.y
+++ /dev/null
@@ -1,41 +0,0 @@
-#
-# nonassoc test
-#
-
-class P
-
-preclow
- nonassoc N
- left P
-prechigh
-
-rule
-
-target : exp
-exp : exp N exp
- | exp P exp
- | T
-
-end
-
----- inner
-
- def parse
- @src = [[:T,'T'], [:N,'N'], [:T,'T'], [:N,'N'], [:T,'T']]
- do_parse
- end
-
- def next_token
- @src.shift
- end
-
----- footer
-
-begin
- P.new.parse
-rescue ParseError
- exit 0
-else
- $stderr.puts 'parse error not raised: nonassoc not work'
- exit 1
-end
diff --git a/test/racc/assets/normal.y b/test/racc/assets/normal.y
deleted file mode 100644
index 96ae352c82..0000000000
--- a/test/racc/assets/normal.y
+++ /dev/null
@@ -1,27 +0,0 @@
-
-class Testp
-
- convert
- A '2'
- B '3'
- end
-
- prechigh
- left B
- preclow
-
-rule
-
-/* comment */
- target: A B C nonterminal { action "string" == /regexp/o
- 1 /= 3 }
- ; # comment
-
- nonterminal: A '+' B = A;
-
-/* end */
-end
-
----- driver
-
- # driver is old name
diff --git a/test/racc/assets/norule.y b/test/racc/assets/norule.y
deleted file mode 100644
index e50a4b3472..0000000000
--- a/test/racc/assets/norule.y
+++ /dev/null
@@ -1,4 +0,0 @@
-
-class A
-rule
-end
diff --git a/test/racc/assets/nullbug1.y b/test/racc/assets/nullbug1.y
deleted file mode 100644
index 4b267ba0ea..0000000000
--- a/test/racc/assets/nullbug1.y
+++ /dev/null
@@ -1,25 +0,0 @@
-#
-# number of conflicts must be ZERO.
-#
-
-class T
-
-rule
-
-targ : dummy
- | a b c
-
-dummy : V v
-
-V : E e
- | F f
- |
- ;
-
-E :
- ;
-
-F :
- ;
-
-end
diff --git a/test/racc/assets/nullbug2.y b/test/racc/assets/nullbug2.y
deleted file mode 100644
index 0c1d43bf3e..0000000000
--- a/test/racc/assets/nullbug2.y
+++ /dev/null
@@ -1,15 +0,0 @@
-#
-# number of conflicts must be ZERO.
-#
-
-class A
-rule
- targ: operation voidhead
- | variable
-
- voidhead : void B
- void:
-
- operation: A
- variable : A
-end
diff --git a/test/racc/assets/opal.y b/test/racc/assets/opal.y
deleted file mode 100644
index ae6a5a6bdd..0000000000
--- a/test/racc/assets/opal.y
+++ /dev/null
@@ -1,1807 +0,0 @@
-# Copyright (C) 2013 by Adam Beynon
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-# THE SOFTWARE.
-
-class Opal::Parser
-
-token kCLASS kMODULE kDEF kUNDEF kBEGIN kRESCUE kENSURE kEND kIF kUNLESS
- kTHEN kELSIF kELSE kCASE kWHEN kWHILE kUNTIL kFOR kBREAK kNEXT
- kREDO kRETRY kIN kDO kDO_COND kDO_BLOCK kDO_LAMBDA kRETURN kYIELD kSUPER
- kSELF kNIL kTRUE kFALSE kAND kOR kNOT kIF_MOD kUNLESS_MOD kWHILE_MOD
- kUNTIL_MOD kRESCUE_MOD kALIAS kDEFINED klBEGIN klEND k__LINE__
- k__FILE__ k__ENCODING__ tIDENTIFIER tFID tGVAR tIVAR tCONSTANT
- tLABEL tCVAR tNTH_REF tBACK_REF tSTRING_CONTENT tINTEGER tFLOAT
- tREGEXP_END tUPLUS tUMINUS tUMINUS_NUM tPOW tCMP tEQ tEQQ tNEQ tGEQ tLEQ tANDOP
- tOROP tMATCH tNMATCH tJSDOT tDOT tDOT2 tDOT3 tAREF tASET tLSHFT tRSHFT
- tCOLON2 tCOLON3 tOP_ASGN tASSOC tLPAREN tLPAREN2 tRPAREN tLPAREN_ARG
- ARRAY_BEG tRBRACK tLBRACE tLBRACE_ARG tSTAR tSTAR2 tAMPER tAMPER2
- tTILDE tPERCENT tDIVIDE tPLUS tMINUS tLT tGT tPIPE tBANG tCARET
- tLCURLY tRCURLY tBACK_REF2 tSYMBEG tSTRING_BEG tXSTRING_BEG tREGEXP_BEG
- tWORDS_BEG tAWORDS_BEG tSTRING_DBEG tSTRING_DVAR tSTRING_END tSTRING
- tSYMBOL tNL tEH tCOLON tCOMMA tSPACE tSEMI tLAMBDA tLAMBEG
- tLBRACK2 tLBRACK tJSLBRACK tDSTAR
-
-prechigh
- right tBANG tTILDE tUPLUS
- right tPOW
- right tUMINUS_NUM tUMINUS
- left tSTAR2 tDIVIDE tPERCENT
- left tPLUS tMINUS
- left tLSHFT tRSHFT
- left tAMPER2
- left tPIPE tCARET
- left tGT tGEQ tLT tLEQ
- nonassoc tCMP tEQ tEQQ tNEQ tMATCH tNMATCH
- left tANDOP
- left tOROP
- nonassoc tDOT2 tDOT3
- right tEH tCOLON
- left kRESCUE_MOD
- right tEQL tOP_ASGN
- nonassoc kDEFINED
- right kNOT
- left kOR kAND
- nonassoc kIF_MOD kUNLESS_MOD kWHILE_MOD kUNTIL_MOD
- nonassoc tLBRACE_ARG
- nonassoc tLOWEST
-preclow
-
-rule
-
- program: top_compstmt
-
- top_compstmt: top_stmts opt_terms
- {
- result = new_compstmt val[0]
- }
-
- top_stmts: # none
- {
- result = new_block
- }
- | top_stmt
- {
- result = new_block val[0]
- }
- | top_stmts terms top_stmt
- {
- val[0] << val[2]
- result = val[0]
- }
-
- top_stmt: stmt
- | klBEGIN tLCURLY top_compstmt tRCURLY
- {
- result = val[2]
- }
-
- bodystmt: compstmt opt_rescue opt_else opt_ensure
- {
- result = new_body(val[0], val[1], val[2], val[3])
- }
-
- compstmt: stmts opt_terms
- {
- result = new_compstmt val[0]
- }
-
- stmts: # none
- {
- result = new_block
- }
- | stmt
- {
- result = new_block val[0]
- }
- | stmts terms stmt
- {
- val[0] << val[2]
- result = val[0]
- }
-
- stmt: kALIAS fitem
- {
- lexer.lex_state = :expr_fname
- }
- fitem
- {
- result = new_alias(val[0], val[1], val[3])
- }
- | kALIAS tGVAR tGVAR
- {
- result = s(:valias, value(val[1]).to_sym, value(val[2]).to_sym)
- }
- | kALIAS tGVAR tBACK_REF
- | kALIAS tGVAR tNTH_REF
- {
- result = s(:valias, value(val[1]).to_sym, value(val[2]).to_sym)
- }
- | kUNDEF undef_list
- {
- result = val[1]
- }
- | stmt kIF_MOD expr_value
- {
- result = new_if(val[1], val[2], val[0], nil)
- }
- | stmt kUNLESS_MOD expr_value
- {
- result = new_if(val[1], val[2], nil, val[0])
- }
- | stmt kWHILE_MOD expr_value
- {
- result = new_while(val[1], val[2], val[0])
- }
- | stmt kUNTIL_MOD expr_value
- {
- result = new_until(val[1], val[2], val[0])
- }
- | stmt kRESCUE_MOD stmt
- {
- result = new_rescue_mod(val[1], val[0], val[2])
- }
- | klEND tLCURLY compstmt tRCURLY
- | lhs tEQL command_call
- {
- result = new_assign(val[0], val[1], val[2])
- }
- | mlhs tEQL command_call
- {
- result = s(:masgn, val[0], s(:to_ary, val[2]))
- }
- | var_lhs tOP_ASGN command_call
- {
- result = new_op_asgn val[1], val[0], val[2]
- }
- | primary_value tLBRACK2 aref_args tRBRACK tOP_ASGN command_call
- | primary_value tJSLBRACK aref_args tRBRACK tOP_ASGN command_call
- | primary_value tDOT tIDENTIFIER tOP_ASGN command_call
- {
- result = s(:op_asgn2, val[0], op_to_setter(val[2]), value(val[3]).to_sym, val[4])
- }
- | primary_value tDOT tCONSTANT tOP_ASGN command_call
- | primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_call
- | backref tOP_ASGN command_call
- | lhs tEQL mrhs
- {
- result = new_assign val[0], val[1], s(:svalue, val[2])
- }
- | mlhs tEQL arg_value
- {
- result = s(:masgn, val[0], s(:to_ary, val[2]))
- }
- | mlhs tEQL mrhs
- {
- result = s(:masgn, val[0], val[2])
- }
- | expr
-
- expr: command_call
- | expr kAND expr
- {
- result = s(:and, val[0], val[2])
- }
- | expr kOR expr
- {
- result = s(:or, val[0], val[2])
- }
- | kNOT expr
- {
- result = new_unary_call(['!', []], val[1])
- }
- | tBANG command_call
- {
- result = new_unary_call(val[0], val[1])
- }
- | arg
-
- expr_value: expr
-
- command_call: command
- | block_command
- | kRETURN call_args
- {
- result = new_return(val[0], val[1])
- }
- | kBREAK call_args
- {
- result = new_break(val[0], val[1])
- }
- | kNEXT call_args
- {
- result = new_next(val[0], val[1])
- }
-
- block_command: block_call
- | block_call tJSDOT operation2 command_args
- | block_call tDOT operation2 command_args
- | block_call tCOLON2 operation2 command_args
-
- cmd_brace_block: tLBRACE_ARG opt_block_var compstmt tRCURLY
-
- command: operation command_args =tLOWEST
- {
- result = new_call(nil, val[0], val[1])
- }
- | operation command_args cmd_brace_block
- | primary_value tJSDOT operation2 command_args =tLOWEST
- {
- result = new_js_call(val[0], val[2], val[3])
- }
- | primary_value tJSDOT operation2 command_args cmd_brace_block
- | primary_value tDOT operation2 command_args =tLOWEST
- {
- result = new_call(val[0], val[2], val[3])
- }
- | primary_value tDOT operation2 command_args cmd_brace_block
- | primary_value tCOLON2 operation2 command_args =tLOWEST
- {
- result = new_call(val[0], val[2], val[3])
- }
- | primary_value tCOLON2 operation2 command_args cmd_brace_block
- | kSUPER command_args
- {
- result = new_super(val[0], val[1])
- }
- | kYIELD command_args
- {
- result = new_yield val[1]
- }
-
- mlhs: mlhs_basic
- {
- result = val[0]
- }
- | tLPAREN mlhs_entry tRPAREN
- {
- result = val[1]
- }
-
- mlhs_entry: mlhs_basic
- {
- result = val[0]
- }
- | tLPAREN mlhs_entry tRPAREN
- {
- result = val[1]
- }
-
- mlhs_basic: mlhs_head
- {
- result = val[0]
- }
- | mlhs_head mlhs_item
- {
- result = val[0] << val[1]
- }
- | mlhs_head tSTAR mlhs_node
- {
- result = val[0] << s(:splat, val[2])
- }
- | mlhs_head tSTAR mlhs_node tCOMMA mlhs_post
- | mlhs_head tSTAR
- {
- result = val[0] << s(:splat)
- }
- | mlhs_head tSTAR tCOMMA mlhs_post
- | tSTAR mlhs_node
- {
- result = s(:array, s(:splat, val[1]))
- }
- | tSTAR
- {
- result = s(:array, s(:splat))
- }
- | tSTAR tCOMMA mlhs_post
-
- mlhs_item: mlhs_node
- {
- result = val[0]
- }
- | tLPAREN mlhs_entry tRPAREN
- {
- result = val[1]
- }
-
- mlhs_head: mlhs_item tCOMMA
- {
- result = s(:array, val[0])
- }
- | mlhs_head mlhs_item tCOMMA
- {
- result = val[0] << val[1]
- }
-
- mlhs_post: mlhs_item
- | mlhs_post tCOMMA mlhs_item
-
- mlhs_node: variable
- {
- result = new_assignable val[0]
- }
- | primary_value tLBRACK2 aref_args tRBRACK
- {
- args = val[2] ? val[2] : []
- result = s(:attrasgn, val[0], :[]=, s(:arglist, *args))
- }
- | primary_value tDOT tIDENTIFIER
- {
- result = new_call val[0], val[2], []
- }
- | primary_value tCOLON2 tIDENTIFIER
- | primary_value tDOT tCONSTANT
- | primary_value tCOLON2 tCONSTANT
- | tCOLON3 tCONSTANT
- | backref
-
- lhs: variable
- {
- result = new_assignable val[0]
- }
- | primary_value tJSLBRACK aref_args tRBRACK
- {
- result = new_js_attrasgn(val[0], val[2])
- }
- | primary_value tLBRACK2 aref_args tRBRACK
- {
- result = new_attrasgn(val[0], :[]=, val[2])
- }
- | primary_value tDOT tIDENTIFIER
- {
- result = new_attrasgn(val[0], op_to_setter(val[2]))
- }
- | primary_value tCOLON2 tIDENTIFIER
- {
- result = new_attrasgn(val[0], op_to_setter(val[2]))
- }
- | primary_value tDOT tCONSTANT
- {
- result = new_attrasgn(val[0], op_to_setter(val[2]))
- }
- | primary_value tCOLON2 tCONSTANT
- {
- result = new_colon2(val[0], val[1], val[2])
- }
- | tCOLON3 tCONSTANT
- {
- result = new_colon3(val[0], val[1])
- }
- | backref
-
- cname: tCONSTANT
-
- cpath: tCOLON3 cname
- {
- result = new_colon3(val[0], val[1])
- }
- | cname
- {
- result = new_const(val[0])
- }
- | primary_value tCOLON2 cname
- {
- result = new_colon2(val[0], val[1], val[2])
- }
-
- fname: tIDENTIFIER
- | tCONSTANT
- | tFID
- | op
- {
- lexer.lex_state = :expr_end
- result = val[0]
- }
- | reswords
- {
- lexer.lex_state = :expr_end
- result = val[0]
- }
-
- fitem: fname
- {
- result = new_sym(val[0])
- }
- | symbol
-
- undef_list: fitem
- {
- result = s(:undef, val[0])
- }
- | undef_list tCOMMA fitem
- {
- result = val[0] << val[2]
- }
-
- op: tPIPE | tCARET | tAMPER2 | tCMP | tEQ | tEQQ
- | tMATCH | tNMATCH | tGT | tGEQ | tLT | tLEQ
- | tNEQ | tLSHFT | tRSHFT | tPLUS | tMINUS | tSTAR2
- | tSTAR | tDIVIDE | tPERCENT | tPOW | tBANG | tTILDE
- | tUPLUS | tUMINUS | tAREF | tASET | tBACK_REF2
-
- reswords: k__LINE__ | k__FILE__ | klBEGIN | klEND | kALIAS | kAND
- | kBEGIN | kBREAK | kCASE | kCLASS | kDEF | kDEFINED
- | kDO | kELSE | kELSIF | kEND | kENSURE | kFALSE
- | kFOR | kIN | kMODULE | kNEXT | kNIL | kNOT
- | kOR | kREDO | kRESCUE | kRETRY | kRETURN | kSELF
- | kSUPER | kTHEN | kTRUE | kUNDEF | kWHEN | kYIELD
- | kIF_MOD | kUNLESS_MOD | kWHILE_MOD | kUNTIL_MOD | kRESCUE_MOD
- | kIF | kWHILE | kUNTIL | kUNLESS
-
- arg: lhs tEQL arg
- {
- result = new_assign(val[0], val[1], val[2])
- }
- | lhs tEQL arg kRESCUE_MOD arg
- {
- result = new_assign val[0], val[1], s(:rescue_mod, val[2], val[4])
- }
- | var_lhs tOP_ASGN arg
- {
- result = new_op_asgn val[1], val[0], val[2]
- }
- | primary_value tLBRACK2 aref_args tRBRACK tOP_ASGN arg
- {
- result = new_op_asgn1(val[0], val[2], val[4], val[5])
- }
- | primary_value tJSLBRACK aref_args tRBRACK tOP_ASGN arg
- {
- raise ".JS[...] #{val[4]} is not supported"
- }
- | primary_value tDOT tIDENTIFIER tOP_ASGN arg
- {
- result = s(:op_asgn2, val[0], op_to_setter(val[2]), value(val[3]).to_sym, val[4])
- }
- | primary_value tDOT tCONSTANT tOP_ASGN arg
- | primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg
- | primary_value tCOLON2 tCONSTANT tOP_ASGN arg
- | tCOLON3 tCONSTANT tOP_ASGN arg
- | backref tOP_ASGN arg
- | arg tDOT2 arg
- {
- result = new_irange(val[0], val[1], val[2])
- }
- | arg tDOT3 arg
- {
- result = new_erange(val[0], val[1], val[2])
- }
- | arg tPLUS arg
- {
- result = new_binary_call(val[0], val[1], val[2])
- }
- | arg tMINUS arg
- {
- result = new_binary_call(val[0], val[1], val[2])
- }
- | arg tSTAR2 arg
- {
- result = new_binary_call(val[0], val[1], val[2])
- }
- | arg tDIVIDE arg
- {
- result = new_binary_call(val[0], val[1], val[2])
- }
- | arg tPERCENT arg
- {
- result = new_binary_call(val[0], val[1], val[2])
- }
- | arg tPOW arg
- {
- result = new_binary_call(val[0], val[1], val[2])
- }
- | '-@NUM' tINTEGER tPOW arg
- {
- result = new_call new_binary_call(new_int(val[1]), val[2], val[3]), [:"-@", []], []
- }
- | '-@NUM' tFLOAT tPOW arg
- {
- result = new_call new_binary_call(new_float(val[1]), val[2], val[3]), [:"-@", []], []
- }
- | tUPLUS arg
- {
- result = new_call val[1], [:"+@", []], []
- if [:int, :float].include? val[1].type
- result = val[1]
- end
- }
- | tUMINUS arg
- {
- result = new_call val[1], [:"-@", []], []
- if val[1].type == :int
- val[1][1] = -val[1][1]
- result = val[1]
- elsif val[1].type == :float
- val[1][1] = -val[1][1].to_f
- result = val[1]
- end
- }
- | arg tPIPE arg
- {
- result = new_binary_call(val[0], val[1], val[2])
- }
- | arg tCARET arg
- {
- result = new_binary_call(val[0], val[1], val[2])
- }
- | arg tAMPER2 arg
- {
- result = new_binary_call(val[0], val[1], val[2])
- }
- | arg tCMP arg
- {
- result = new_binary_call(val[0], val[1], val[2])
- }
- | arg tGT arg
- {
- result = new_binary_call(val[0], val[1], val[2])
- }
- | arg tGEQ arg
- {
- result = new_binary_call(val[0], val[1], val[2])
- }
- | arg tLT arg
- {
- result = new_binary_call(val[0], val[1], val[2])
- }
- | arg tLEQ arg
- {
- result = new_binary_call(val[0], val[1], val[2])
- }
- | arg tEQ arg
- {
- result = new_binary_call(val[0], val[1], val[2])
- }
- | arg tEQQ arg
- {
- result = new_binary_call(val[0], val[1], val[2])
- }
- | arg tNEQ arg
- {
- result = new_binary_call(val[0], val[1], val[2])
- }
- | arg tMATCH arg
- {
- result = new_binary_call(val[0], val[1], val[2])
- }
- | arg tNMATCH arg
- {
- result = new_binary_call(val[0], val[1], val[2])
- }
- | tBANG arg
- {
- result = new_unary_call(val[0], val[1])
- }
- | tTILDE arg
- {
- result = new_unary_call(val[0], val[1])
- }
- | arg tLSHFT arg
- {
- result = new_binary_call(val[0], val[1], val[2])
- }
- | arg tRSHFT arg
- {
- result = new_binary_call(val[0], val[1], val[2])
- }
- | arg tANDOP arg
- {
- result = new_and(val[0], val[1], val[2])
- }
- | arg tOROP arg
- {
- result = new_or(val[0], val[1], val[2])
- }
- | kDEFINED opt_nl arg
- {
- result = s(:defined, val[2])
- }
- | arg tEH arg tCOLON arg
- {
- result = new_if(val[1], val[0], val[2], val[4])
- }
- | primary
-
- arg_value: arg
-
- aref_args: none
- {
- result = nil
- }
- | command opt_nl
- {
- result = [val[0]]
- }
- | args trailer
- {
- result = val[0]
- }
- | args tCOMMA assocs trailer
- {
- val[0] << s(:hash, *val[2])
- result = val[0]
- }
- | assocs trailer
- {
- result = [s(:hash, *val[0])]
- }
-
- paren_args: tLPAREN2 opt_call_args rparen
- {
- result = val[1]
- }
-
- rparen: opt_nl tRPAREN
-
- opt_paren_args: none
- {
- result = []
- }
- | paren_args
-
- opt_call_args: none
- {
- result = []
- }
- | call_args
- | args tCOMMA
- {
- result = val[0]
- }
- | args tCOMMA assocs tCOMMA
- {
- result = val[0]
- result << new_hash(nil, val[2], nil)
- }
- | assocs tCOMMA
- {
- result = [new_hash(nil, val[0], nil)]
- }
-
- call_args: command
- {
- result = [val[0]]
- }
- | args opt_block_arg
- {
- result = val[0]
- add_block_pass val[0], val[1]
- }
- | assocs opt_block_arg
- {
- result = [new_hash(nil, val[0], nil)]
- add_block_pass result, val[1]
- }
- | args tCOMMA assocs opt_block_arg
- {
- result = val[0]
- result << new_hash(nil, val[2], nil)
- result << val[3] if val[3]
- }
- | block_arg
- {
- result = []
- add_block_pass result, val[0]
- }
-
- call_args2: arg_value tCOMMA args opt_block_arg
- | block_arg
-
- command_args: {
- lexer.cmdarg_push 1
- }
- open_args
- {
- lexer.cmdarg_pop
- result = val[1]
- }
-
- open_args: call_args
- | tLPAREN_ARG tRPAREN
- {
- result = nil
- }
- | tLPAREN_ARG call_args2 tRPAREN
- {
- result = val[1]
- }
-
- block_arg: tAMPER arg_value
- {
- result = new_block_pass(val[0], val[1])
- }
-
- opt_block_arg: tCOMMA block_arg
- {
- result = val[1]
- }
- | # none
- {
- result = nil
- }
-
- args: arg_value
- {
- result = [val[0]]
- }
- | tSTAR arg_value
- {
- result = [new_splat(val[0], val[1])]
- }
- | args tCOMMA arg_value
- {
- result = val[0] << val[2]
- }
- | args tCOMMA tSTAR arg_value
- {
- result = val[0] << new_splat(val[2], val[3])
- }
-
- mrhs: args tCOMMA arg_value
- {
- val[0] << val[2]
- result = s(:array, *val[0])
- }
- | args tCOMMA tSTAR arg_value
- {
- val[0] << s(:splat, val[3])
- result = s(:array, *val[0])
- }
- | tSTAR arg_value
- {
- result = s(:splat, val[1])
- }
-
- primary: literal
- | strings
- | xstring
- | regexp
- | words
- | awords
- | var_ref
- | backref
- | tFID
- | kBEGIN
- {
- result = lexer.line
- }
- bodystmt kEND
- {
- result = s(:begin, val[2])
- }
- | tLPAREN_ARG expr opt_nl tRPAREN
- {
- result = val[1]
- }
- | tLPAREN compstmt tRPAREN
- {
- result = new_paren(val[0], val[1], val[2])
- }
- | primary_value tCOLON2 tCONSTANT
- {
- result = new_colon2(val[0], val[1], val[2])
- }
- | tCOLON3 tCONSTANT
- {
- result = new_colon3(val[0], val[1])
- }
- | primary_value tLBRACK2 aref_args tRBRACK
- {
- result = new_call val[0], [:[], []], val[2]
- }
- | primary_value tJSLBRACK aref_args tRBRACK
- {
- result = new_js_call val[0], [:[], []], val[2]
- }
- | tLBRACK aref_args tRBRACK
- {
- result = new_array(val[0], val[1], val[2])
- }
- | tLBRACE assoc_list tRCURLY
- {
- result = new_hash(val[0], val[1], val[2])
- }
- | kRETURN
- {
- result = new_return(val[0])
- }
- | kYIELD tLPAREN2 call_args tRPAREN
- {
- result = new_yield val[2]
- }
- | kYIELD tLPAREN2 tRPAREN
- {
- result = s(:yield)
- }
- | kYIELD
- {
- result = s(:yield)
- }
- | kDEFINED opt_nl tLPAREN2 expr tRPAREN
- {
- result = s(:defined, val[3])
- }
- | kNOT tLPAREN2 expr tRPAREN
- {
- result = new_unary_call(['!', []], val[2])
- }
- | kNOT tLPAREN2 tRPAREN
- {
- result = new_unary_call(['!', []], new_nil(val[0]))
- }
- | operation brace_block
- {
- result = new_call(nil, val[0], [])
- result << val[1]
- }
- | method_call
- | method_call brace_block
- {
- val[0] << val[1]
- result = val[0]
- }
- | tLAMBDA lambda
- {
- result = val[1]
- }
- | kIF expr_value then compstmt if_tail kEND
- {
- result = new_if(val[0], val[1], val[3], val[4])
- }
- | kUNLESS expr_value then compstmt opt_else kEND
- {
- result = new_if(val[0], val[1], val[4], val[3])
- }
- | kWHILE
- {
- lexer.cond_push 1
- result = lexer.line
- }
- expr_value do
- {
- lexer.cond_pop
- }
- compstmt kEND
- {
- result = s(:while, val[2], val[5])
- }
- | kUNTIL
- {
- lexer.cond_push 1
- result = lexer.line
- }
- expr_value do
- {
- lexer.cond_pop
- }
- compstmt kEND
- {
- result = s(:until, val[2], val[5])
- }
- | kCASE expr_value opt_terms case_body kEND
- {
- result = s(:case, val[1], *val[3])
- }
- | kCASE opt_terms case_body kEND
- {
- result = s(:case, nil, *val[2])
- }
- | kCASE opt_terms kELSE compstmt kEND
- {
- result = s(:case, nil, val[3])
- }
- | kFOR for_var kIN
- {
- lexer.cond_push 1
- result = lexer.line
- }
- expr_value do
- {
- lexer.cond_pop
- }
- compstmt kEND
- {
- result = s(:for, val[4], val[1], val[7])
- }
- | kCLASS cpath superclass
- {
- # ...
- }
- bodystmt kEND
- {
- result = new_class val[0], val[1], val[2], val[4], val[5]
- }
- | kCLASS tLSHFT
- {
- result = lexer.line
- }
- expr term
- {
- # ...
- }
- bodystmt kEND
- {
- result = new_sclass(val[0], val[3], val[6], val[7])
- }
- | kMODULE
- {
- result = lexer.line
- }
- cpath
- {
- # ...
- }
- bodystmt kEND
- {
- result = new_module(val[0], val[2], val[4], val[5])
- }
- | kDEF fname
- {
- push_scope
- lexer.lex_state = :expr_endfn
- }
- f_arglist bodystmt kEND
- {
- result = new_def(val[0], nil, val[1], val[3], val[4], val[5])
- pop_scope
- }
- | kDEF singleton dot_or_colon
- {
- lexer.lex_state = :expr_fname
- }
- fname
- {
- push_scope
- lexer.lex_state = :expr_endfn
- }
- f_arglist bodystmt kEND
- {
- result = new_def(val[0], val[1], val[4], val[6], val[7], val[8])
- pop_scope
- }
- | kBREAK
- {
- result = new_break(val[0])
- }
- | kNEXT
- {
- result = s(:next)
- }
- | kREDO
- {
- result = s(:redo)
- }
- | kRETRY
-
- primary_value: primary
-
- then: term
- | tCOLON
- | kTHEN
- | term kTHEN
-
- do: term
- | tCOLON
- | kDO_COND
-
- lambda: f_larglist lambda_body
- {
- result = new_call nil, [:lambda, []], []
- result << new_iter(val[0], val[1])
- }
-
- f_larglist: tLPAREN2 block_param tRPAREN
- {
- result = val[1]
- }
- | tLPAREN2 tRPAREN
- {
- result = nil
- }
- | block_param
- | none
-
- lambda_body: tLAMBEG compstmt tRCURLY
- {
- result = val[1]
- }
- | kDO_LAMBDA compstmt kEND
- {
- result = val[1]
- }
-
- if_tail: opt_else
- {
- result = val[0]
- }
- | kELSIF expr_value then compstmt if_tail
- {
- result = new_if(val[0], val[1], val[3], val[4])
- }
-
- opt_else: none
- | kELSE compstmt
- {
- result = val[1]
- }
-
- f_block_optarg: f_block_opt
- {
- result = s(:block, val[0])
- }
- | f_block_optarg tCOMMA f_block_opt
- {
- val[0] << val[2]
- result = val[0]
- }
-
- f_block_opt: tIDENTIFIER tEQL primary_value
- {
- result = new_assign(new_assignable(new_ident(
- val[0])), val[1], val[2])
- }
-
- opt_block_var: none
- | tPIPE tPIPE
- {
- result = nil
- }
- | tOROP
- {
- result = nil
- }
- | tPIPE block_param tPIPE
- {
- result = val[1]
- }
-
- block_args_tail: f_block_arg
- {
- result = val[0]
- }
-
-opt_block_args_tail: tCOMMA block_args_tail
- {
- result = val[1]
- }
- | none
- {
- nil
- }
-
- block_param: f_arg tCOMMA f_block_optarg tCOMMA f_rest_arg opt_block_args_tail
- {
- result = new_block_args(val[0], val[2], val[4], val[5])
- }
- | f_arg tCOMMA f_block_optarg opt_block_args_tail
- {
- result = new_block_args(val[0], val[2], nil, val[3])
- }
- | f_arg tCOMMA f_rest_arg opt_block_args_tail
- {
- result = new_block_args(val[0], nil, val[2], val[3])
- }
- | f_arg tCOMMA
- {
- result = new_block_args(val[0], nil, nil, nil)
- }
- | f_arg opt_block_args_tail
- {
- result = new_block_args(val[0], nil, nil, val[1])
- }
- | f_block_optarg tCOMMA f_rest_arg opt_block_args_tail
- {
- result = new_block_args(nil, val[0], val[2], val[3])
- }
- | f_block_optarg opt_block_args_tail
- {
- result = new_block_args(nil, val[0], nil, val[1])
- }
- | f_rest_arg opt_block_args_tail
- {
- result = new_block_args(nil, nil, val[0], val[1])
- }
- | block_args_tail
- {
- result = new_block_args(nil, nil, nil, val[0])
- }
-
- do_block: kDO_BLOCK
- {
- push_scope :block
- result = lexer.line
- }
- opt_block_var compstmt kEND
- {
- result = new_iter val[2], val[3]
- pop_scope
- }
-
- block_call: command do_block
- {
- val[0] << val[1]
- result = val[0]
- }
- | block_call tJSDOT operation2 opt_paren_args
- | block_call tDOT operation2 opt_paren_args
- | block_call tCOLON2 operation2 opt_paren_args
-
- method_call: operation paren_args
- {
- result = new_call(nil, val[0], val[1])
- }
- | primary_value tDOT operation2 opt_paren_args
- {
- result = new_call(val[0], val[2], val[3])
- }
- | primary_value tJSDOT operation2 opt_paren_args
- {
- result = new_js_call(val[0], val[2], val[3])
- }
- | primary_value tDOT paren_args
- {
- result = new_call(val[0], [:call, []], val[2])
- }
- | primary_value tCOLON2 operation2 paren_args
- {
- result = new_call(val[0], val[2], val[3])
- }
- | primary_value tCOLON2 operation3
- {
- result = new_call(val[0], val[2])
- }
- | kSUPER paren_args
- {
- result = new_super(val[0], val[1])
- }
- | kSUPER
- {
- result = new_super(val[0], nil)
- }
-
- brace_block: tLCURLY
- {
- push_scope :block
- result = lexer.line
- }
- opt_block_var compstmt tRCURLY
- {
- result = new_iter val[2], val[3]
- pop_scope
- }
- | kDO
- {
- push_scope :block
- result = lexer.line
- }
- opt_block_var compstmt kEND
- {
- result = new_iter val[2], val[3]
- pop_scope
- }
-
- case_body: kWHEN
- {
- result = lexer.line
- }
- args then compstmt cases
- {
- part = s(:when, s(:array, *val[2]), val[4])
- result = [part]
- result.push(*val[5]) if val[5]
- }
-
- cases: opt_else
- {
- result = [val[0]]
- }
- | case_body
-
- opt_rescue: kRESCUE exc_list exc_var then compstmt opt_rescue
- {
- exc = val[1] || s(:array)
- exc << new_assign(val[2], val[2], s(:gvar, '$!'.intern)) if val[2]
- result = [s(:resbody, exc, val[4])]
- result.push val[5].first if val[5]
- }
- | # none
- {
- result = nil
- }
-
- exc_list: arg_value
- {
- result = s(:array, val[0])
- }
- | mrhs
- | none
-
- exc_var: tASSOC lhs
- {
- result = val[1]
- }
- | none
- {
- result = nil
- }
-
- opt_ensure: kENSURE compstmt
- {
- result = val[1].nil? ? s(:nil) : val[1]
- }
- | none
-
- literal: numeric
- | symbol
- | dsym
-
- strings: string
- {
- result = new_str val[0]
- }
-
- string: string1
- | string string1
- {
- result = str_append val[0], val[1]
- }
-
- string1: tSTRING_BEG string_contents tSTRING_END
- {
- result = val[1]
- }
- | tSTRING
- {
- result = s(:str, value(val[0]))
- }
-
- xstring: tXSTRING_BEG xstring_contents tSTRING_END
- {
- result = new_xstr(val[0], val[1], val[2])
- }
-
- regexp: tREGEXP_BEG xstring_contents tREGEXP_END
- {
- result = new_regexp val[1], val[2]
- }
-
- words: tWORDS_BEG tSPACE tSTRING_END
- {
- result = s(:array)
- }
- | tWORDS_BEG word_list tSTRING_END
- {
- result = val[1]
- }
-
- word_list: none
- {
- result = s(:array)
- }
- | word_list word tSPACE
- {
- part = val[1]
- part = s(:dstr, "", val[1]) if part.type == :evstr
- result = val[0] << part
- }
-
- word: string_content
- {
- result = val[0]
- }
- | word string_content
- {
- result = val[0].concat([val[1]])
- }
-
- awords: tAWORDS_BEG tSPACE tSTRING_END
- {
- result = s(:array)
- }
- | tAWORDS_BEG qword_list tSTRING_END
- {
- result = val[1]
- }
-
- qword_list: none
- {
- result = s(:array)
- }
- | qword_list tSTRING_CONTENT tSPACE
- {
- result = val[0] << s(:str, value(val[1]))
- }
-
- string_contents: none
- {
- result = nil
- }
- | string_contents string_content
- {
- result = str_append val[0], val[1]
- }
-
-xstring_contents: none
- {
- result = nil
- }
- | xstring_contents string_content
- {
- result = str_append val[0], val[1]
- }
-
- string_content: tSTRING_CONTENT
- {
- result = new_str_content(val[0])
- }
- | tSTRING_DVAR
- {
- result = lexer.strterm
- lexer.strterm = nil
- }
- string_dvar
- {
- lexer.strterm = val[1]
- result = new_evstr(val[2])
- }
- | tSTRING_DBEG
- {
- lexer.cond_push 0
- lexer.cmdarg_push 0
- result = lexer.strterm
- lexer.strterm = nil
- lexer.lex_state = :expr_beg
- }
- compstmt tRCURLY
- {
- lexer.strterm = val[1]
- lexer.cond_lexpop
- lexer.cmdarg_lexpop
- result = new_evstr(val[2])
- }
-
- string_dvar: tGVAR
- {
- result = new_gvar(val[0])
- }
- | tIVAR
- {
- result = new_ivar(val[0])
- }
- | tCVAR
- {
- result = new_cvar(val[0])
- }
- | backref
-
-
- symbol: tSYMBEG sym
- {
- result = new_sym(val[1])
- lexer.lex_state = :expr_end
- }
- | tSYMBOL
- {
- result = new_sym(val[0])
- }
-
- sym: fname
- | tIVAR
- | tGVAR
- | tCVAR
-
- dsym: tSYMBEG xstring_contents tSTRING_END
- {
- result = new_dsym val[1]
- }
-
- numeric: tINTEGER
- {
- result = new_int(val[0])
- }
- | tFLOAT
- {
- result = new_float(val[0])
- }
- | '-@NUM' tINTEGER =tLOWEST
- {
- result = negate_num(new_int(val[1]))
- }
- | '-@NUM' tFLOAT =tLOWEST
- {
- result = negate_num(new_float(val[1]))
- }
- | '+@NUM' tINTEGER =tLOWEST
- {
- result = new_int(val[1])
- }
- | '+@NUM' tFLOAT =tLOWEST
- {
- result = new_float(val[1])
- }
-
- variable: tIDENTIFIER
- {
- result = new_ident(val[0])
- }
- | tIVAR
- {
- result = new_ivar(val[0])
- }
- | tGVAR
- {
- result = new_gvar(val[0])
- }
- | tCONSTANT
- {
- result = new_const(val[0])
- }
- | tCVAR
- {
- result = new_cvar(val[0])
- }
- | kNIL
- {
- result = new_nil(val[0])
- }
- | kSELF
- {
- result = new_self(val[0])
- }
- | kTRUE
- {
- result = new_true(val[0])
- }
- | kFALSE
- {
- result = new_false(val[0])
- }
- | k__FILE__
- {
- result = new___FILE__(val[0])
- }
- | k__LINE__
- {
- result = new___LINE__(val[0])
- }
-
- var_ref: variable
- {
- result = new_var_ref(val[0])
- }
-
- var_lhs: variable
- {
- result = new_assignable val[0]
- }
-
- backref: tNTH_REF
- {
- result = s(:nth_ref, value(val[0]))
- }
- | tBACK_REF
-
- superclass: term
- {
- result = nil
- }
- | tLT expr_value term
- {
- result = val[1]
- }
- | error term
- {
- result = nil
- }
-
- f_arglist: tLPAREN2 f_args opt_nl tRPAREN
- {
- result = val[1]
- lexer.lex_state = :expr_beg
- }
- | f_args term
- {
- result = val[0]
- lexer.lex_state = :expr_beg
- }
-
- kwrest_mark: tPOW
- | tDSTAR
-
- f_kwrest: kwrest_mark tIDENTIFIER
- {
- result = new_kwrestarg(val[1])
- }
- | kwrest_mark
- {
- result = new_kwrestarg()
- }
-
- f_label: tLABEL
- {
- result = new_sym(val[0])
- }
-
- f_kw: f_label arg_value
- {
- result = new_kwoptarg(val[0], val[1])
- }
- | f_label
- {
- result = new_kwarg(val[0])
- }
-
- f_kwarg: f_kw
- {
- result = [val[0]]
- }
- | f_kwarg tCOMMA f_kw
- {
- result = val[0]
- result << val[2]
- }
-
- args_tail: f_kwarg tCOMMA f_kwrest opt_f_block_arg
- {
- result = new_args_tail(val[0], val[2], val[3])
- }
- | f_kwarg opt_f_block_arg
- {
- result = new_args_tail(val[0], nil, val[1])
- }
- | f_kwrest opt_f_block_arg
- {
- result = new_args_tail(nil, val[0], val[1])
- }
- | f_block_arg
- {
- result = new_args_tail(nil, nil, val[0])
- }
-
- opt_args_tail: tCOMMA args_tail
- {
- result = val[1]
- }
- | # none
- {
- result = new_args_tail(nil, nil, nil)
- }
-
- f_args: f_arg tCOMMA f_optarg tCOMMA f_rest_arg opt_args_tail
- {
- result = new_args(val[0], val[2], val[4], val[5])
- }
- | f_arg tCOMMA f_optarg opt_args_tail
- {
- result = new_args(val[0], val[2], nil, val[3])
- }
- | f_arg tCOMMA f_rest_arg opt_args_tail
- {
- result = new_args(val[0], nil, val[2], val[3])
- }
- | f_arg opt_args_tail
- {
- result = new_args(val[0], nil, nil, val[1])
- }
- | f_optarg tCOMMA f_rest_arg opt_args_tail
- {
- result = new_args(nil, val[0], val[2], val[3])
- }
- | f_optarg opt_args_tail
- {
- result = new_args(nil, val[0], nil, val[1])
- }
- | f_rest_arg opt_args_tail
- {
- result = new_args(nil, nil, val[0], val[1])
- }
- | args_tail
- {
- result = new_args(nil, nil, nil, val[0])
- }
- | # none
- {
- result = new_args(nil, nil, nil, nil)
- }
-
- f_norm_arg: f_bad_arg
- | tIDENTIFIER
- {
- result = value(val[0]).to_sym
- scope.add_local result
- }
-
- f_bad_arg: tCONSTANT
- {
- raise 'formal argument cannot be a constant'
- }
- | tIVAR
- {
- raise 'formal argument cannot be an instance variable'
- }
- | tCVAR
- {
- raise 'formal argument cannot be a class variable'
- }
- | tGVAR
- {
- raise 'formal argument cannot be a global variable'
- }
-
- f_arg_item: f_norm_arg
- {
- result = val[0]
- }
- | tLPAREN f_margs tRPAREN
- {
- result = val[1]
- }
-
- for_var: lhs
- | mlhs
-
- f_marg: f_norm_arg
- {
- result = s(:lasgn, val[0])
- }
- | tLPAREN f_margs tRPAREN
-
- f_marg_list: f_marg
- {
- result = s(:array, val[0])
- }
- | f_marg_list tCOMMA f_marg
- {
- val[0] << val[2]
- result = val[0]
- }
-
- f_margs: f_marg_list
- | f_marg_list tCOMMA tSTAR f_norm_arg
- | f_marg_list tCOMMA tSTAR
- | tSTAR f_norm_arg
- | tSTAR
-
- f_arg: f_arg_item
- {
- result = [val[0]]
- }
- | f_arg tCOMMA f_arg_item
- {
- val[0] << val[2]
- result = val[0]
- }
-
- f_opt: tIDENTIFIER tEQL arg_value
- {
- result = new_assign(new_assignable(new_ident(val[0])), val[1], val[2])
- }
-
- f_optarg: f_opt
- {
- result = s(:block, val[0])
- }
- | f_optarg tCOMMA f_opt
- {
- result = val[0]
- val[0] << val[2]
- }
-
- restarg_mark: tSTAR2
- | tSTAR
-
- f_rest_arg: restarg_mark tIDENTIFIER
- {
- result = "*#{value(val[1])}".to_sym
- }
- | restarg_mark
- {
- result = :"*"
- }
-
- blkarg_mark: tAMPER2
- | tAMPER
-
- f_block_arg: blkarg_mark tIDENTIFIER
- {
- result = "&#{value(val[1])}".to_sym
- }
-
- opt_f_block_arg: tCOMMA f_block_arg
- {
- result = val[1]
- }
- | # none
- {
- result = nil
- }
-
- singleton: var_ref
- {
- result = val[0]
- }
- | tLPAREN2 expr opt_nl tRPAREN
- {
- result = val[1]
- }
-
- assoc_list: # none
- {
- result = []
- }
- | assocs trailer
- {
- result = val[0]
- }
-
- assocs: assoc
- {
- result = val[0]
- }
- | assocs tCOMMA assoc
- {
- result = val[0].push(*val[2])
- }
-
- assoc: arg_value tASSOC arg_value
- {
- result = [val[0], val[2]]
- }
- | tLABEL arg_value
- {
- result = [new_sym(val[0]), val[1]]
- }
-
- operation: tIDENTIFIER
- | tCONSTANT
- | tFID
-
- operation2: tIDENTIFIER
- | tCONSTANT
- | tFID
- | op
-
- operation3: tIDENTIFIER
- | tFID
- | op
-
- dot_or_colon: tDOT
- | tCOLON2
-
- opt_terms: # none
- | terms
-
- opt_nl: # none
- | tNL
-
- trailer: # none
- | tNL
- | tCOMMA
-
- term: tSEMI
- | tNL
-
- terms: term
- | terms tSEMI
-
- none: # none
- {
- result = nil
- }
-end
-
----- inner
diff --git a/test/racc/assets/opt.y b/test/racc/assets/opt.y
deleted file mode 100644
index a011953a51..0000000000
--- a/test/racc/assets/opt.y
+++ /dev/null
@@ -1,123 +0,0 @@
-#
-# check options working
-#
-
-class Calcp
-
- prechigh
- left '*' '/'
- left '+' '-'
- preclow
-
- convert
- NUMBER 'Number'
- end
-
- options no_omit_action_call no_result_var
-
-rule
-
- target : exp | /* none */ { 0 } ;
-
- exp : exp '+' exp { chk(val[0] + val[2]) }
- | exp '-' exp { chk(val[0] - val[2]) }
- | exp '*' exp { chk(val[0] * val[2]) }
- | exp '/' exp { chk(val[0] / val[2]) }
- | '(' { $emb = true } exp ')'
- {
- raise 'must not happen' unless $emb
- val[2]
- }
- | '-' NUMBER { -val[1] }
- | NUMBER
- ;
-
-end
-
-----header
-
-class Number; end
-
-----inner
-
- def parse( src )
- @src = src
- do_parse
- end
-
- def next_token
- @src.shift
- end
-
- def initialize
- @yydebug = true
- end
-
- def chk( i )
- # p i
- i
- end
-
-----footer
-
-$parser = Calcp.new
-$test_number = 1
-
-def chk( src, ans )
- result = $parser.parse(src)
- raise "test #{$test_number} failed" unless result == ans
- $test_number += 1
-end
-
-chk(
- [ [Number, 9],
- [false, false],
- [false, false] ], 9
-)
-
-chk(
- [ [Number, 5],
- ['*', nil],
- [Number, 1],
- ['-', nil],
- [Number, 1],
- ['*', nil],
- [Number, 8],
- [false, false],
- [false, false] ], -3
-)
-
-chk(
- [ [Number, 5],
- ['+', nil],
- [Number, 2],
- ['-', nil],
- [Number, 5],
- ['+', nil],
- [Number, 2],
- ['-', nil],
- [Number, 5],
- [false, false],
- [false, false] ], -1
-)
-
-chk(
- [ ['-', nil],
- [Number, 4],
- [false, false],
- [false, false] ], -4
-)
-
-chk(
- [ [Number, 7],
- ['*', nil],
- ['(', nil],
- [Number, 4],
- ['+', nil],
- [Number, 3],
- [')', nil],
- ['-', nil],
- [Number, 9],
- [false, false],
- [false, false] ], 40
-)
diff --git a/test/racc/assets/percent.y b/test/racc/assets/percent.y
deleted file mode 100644
index 68d63583ca..0000000000
--- a/test/racc/assets/percent.y
+++ /dev/null
@@ -1,35 +0,0 @@
-class ScannerChecker
-rule
- target: A
- {
- i = 7
- i %= 4
- raise 'assert failed' unless i == 3
- tmp = %-This is percent string.-
- raise 'assert failed' unless tmp == 'This is percent string.'
- a = 5; b = 3
- assert_equal(2,(a%b)) #A
- # assert_equal(2,(a %b)) # is %-string
- assert_equal(2,(a% b)) #B
- assert_equal(2,(a % b)) #C
- }
-end
-
----- inner ----
-
- def parse
- @q = [[:A, 'A'], [false, '$']]
- do_parse
- end
-
- def next_token
- @q.shift
- end
-
- def assert_equal( expect, real )
- raise "expect #{expect.inspect} but #{real.inspect}" unless expect == real
- end
-
----- footer ----
-
-parser = ScannerChecker.new.parse
diff --git a/test/racc/assets/php_serialization.y b/test/racc/assets/php_serialization.y
deleted file mode 100644
index 99f78f2081..0000000000
--- a/test/racc/assets/php_serialization.y
+++ /dev/null
@@ -1,98 +0,0 @@
-# MIT License
-# See https://github.com/divoxx/ruby-php-serialization/blob/master/LICENSE.txt
-
-class PhpSerialization::Unserializer
-rule
-
- data : null ';' { @object = val[0] }
- | bool ';' { @object = val[0] }
- | integer ';' { @object = val[0] }
- | double ';' { @object = val[0] }
- | string ';' { @object = val[0] }
- | assoc_array { @object = val[0] }
- | object { @object = val[0] }
- ;
-
- null : 'N' { result = nil }
- ;
-
- bool : 'b' ':' NUMBER { result = Integer(val[2]) > 0 }
- ;
-
- integer : 'i' ':' NUMBER { result = Integer(val[2]) }
- ;
-
- double : 'd' ':' NUMBER { result = Float(val[2]) }
- ;
-
- string : 's' ':' NUMBER ':' STRING { result = val[4] }
- ;
-
- object : 'O' ':' NUMBER ':' STRING ':' NUMBER ':' '{' attribute_list '}'
- {
- if eval("defined?(#{val[4]})")
- result = Object.const_get(val[4]).new
-
- val[9].each do |(attr_name, value)|
- # Protected and private attributes will have a \0..\0 prefix
- attr_name = attr_name.gsub(/\A\\0[^\\]+\\0/, '')
- result.instance_variable_set("@#{attr_name}", value)
- end
- else
- klass_name = val[4].gsub(/^Struct::/, '')
- attr_names, values = [], []
-
- val[9].each do |(attr_name, value)|
- # Protected and private attributes will have a \0..\0 prefix
- attr_names << attr_name.gsub(/\A\\0[^\\]+\\0/, '')
- values << value
- end
-
- result = Struct.new(klass_name, *attr_names).new(*values)
- result.instance_variable_set("@_php_class", klass_name)
- end
- }
- ;
-
- attribute_list : attribute_list attribute { result = val[0] << val[1] }
- | { result = [] }
- ;
-
- attribute : data data { result = val }
- ;
-
- assoc_array : 'a' ':' NUMBER ':' '{' attribute_list '}'
- {
- # Checks if the keys are a sequence of integers
- idx = -1
- arr = val[5].all? { |(k,v)| k == (idx += 1) }
-
- if arr
- result = val[5].map { |(k,v)| v }
- else
- result = Hash[val[5]]
- end
- }
- ;
-
-end
-
----- header ----
-require 'php_serialization/tokenizer'
-
----- inner ----
- def initialize(tokenizer_klass = Tokenizer)
- @tokenizer_klass = tokenizer_klass
- end
-
- def run(string)
- @tokenizer = @tokenizer_klass.new(string)
- yyparse(@tokenizer, :each)
- return @object
- ensure
- @tokenizer = nil
- end
-
- def next_token
- @tokenizer.next_token
- end
diff --git a/test/racc/assets/recv.y b/test/racc/assets/recv.y
deleted file mode 100644
index b6e849dda9..0000000000
--- a/test/racc/assets/recv.y
+++ /dev/null
@@ -1,97 +0,0 @@
-# s/r 5, r/r 10
-class A
-rule
-
- content: RecvH received
- ;
-
- datetime: day
- ;
-
- msgid: '<' spec '>';
-
- day:
- | ATOM ','
- ;
-
- received: recvitem_list recvdatetime
- ;
-
- recvitem_list:
- | recvitem_list recvitem
- ;
-
- recvitem: by | via | with | for ;
-
- by:
- | BY domain
- ;
-
- via:
- | VIA ATOM
- ;
-
- with: WITH ATOM
- ;
-
- for:
- | FOR addr
- ;
-
- recvdatetime:
- | ';' datetime
- ;
-
- addr: mbox | group ;
-
- mboxes: mbox
- | mboxes ',' mbox
- ;
-
- mbox: spec
- | routeaddr
- | phrase routeaddr
- ;
-
- group: phrase ':' mboxes ';'
- ;
-
- routeaddr: '<' route spec '>'
- | '<' spec '>'
- ;
-
- route: at_domains ':' ;
-
- at_domains: '@' domain
- | at_domains ',' '@' domain
- ;
-
- spec: local '@' domain
- | local
- ;
-
- local: word
- | local '.' word
- ;
-
- domain: domword
- | domain '.' domword
- ;
-
- domword: atom
- | DOMLIT
- | DIGIT
- ;
-
- phrase: word
- | phrase word
- ;
-
- word: atom
- | QUOTED
- | DIGIT
- ;
-
- atom: ATOM | FROM | BY | VIA | WITH | ID | FOR ;
-
-end
diff --git a/test/racc/assets/riml.y b/test/racc/assets/riml.y
deleted file mode 100644
index 1d99b0fdb8..0000000000
--- a/test/racc/assets/riml.y
+++ /dev/null
@@ -1,665 +0,0 @@
-# Copyright (c) 2012-2014 by Luke Gruber
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be included
-# in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-class Riml::Parser
-
-token IF ELSE ELSEIF THEN UNLESS END
-token WHILE UNTIL BREAK CONTINUE
-token TRY CATCH FINALLY
-token FOR IN
-token DEF DEF_BANG SPLAT_PARAM SPLAT_ARG CALL BUILTIN_COMMAND # such as echo "hi"
-token CLASS NEW DEFM DEFM_BANG SUPER
-token RIML_FILE_COMMAND RIML_CLASS_COMMAND
-token RETURN
-token NEWLINE
-token NUMBER
-token STRING_D STRING_S # single- and double-quoted
-token EX_LITERAL
-token REGEXP
-token TRUE FALSE
-token LET UNLET UNLET_BANG IDENTIFIER
-token DICT_VAL # like dict.key, 'key' is a DICT_VAL
-token SCOPE_MODIFIER SCOPE_MODIFIER_LITERAL SPECIAL_VAR_PREFIX
-token FINISH
-
-prechigh
- right '!'
- left '*' '/' '%'
- left '+' '-' '.'
- left '>' '>#' '>?' '<' '<#' '<?' '>=' '>=#' '>=?' '<=' '<=#' '<=?'
- left '==' '==?' '==#' '=~' '=~?' '=~#' '!~' '!~?' '!~#' '!=' '!=?' '!=#'
- left IS ISNOT
- left '&&'
- left '||'
- right '?'
- right '=' '+=' '-=' '.='
- left ','
- left IF UNLESS
-preclow
-
-# All rules
-rule
-
- Root:
- /* nothing */ { result = make_node(val) { |_| Riml::Nodes.new([]) } }
- | Terminator { result = make_node(val) { |_| Riml::Nodes.new([]) } }
- | Statements { result = val[0] }
- ;
-
- # any list of expressions
- Statements:
- Statement { result = make_node(val) { |v| Riml::Nodes.new([ v[0] ]) } }
- | Statements Terminator Statement { result = val[0] << val[2] }
- | Statements Terminator { result = val[0] }
- | Terminator Statements { result = make_node(val) { |v| Riml::Nodes.new(v[1]) } }
- ;
-
- # All types of expressions in Riml
- Statement:
- ExplicitCall { result = val[0] }
- | Def { result = val[0] }
- | Return { result = val[0] }
- | UnletVariable { result = val[0] }
- | ExLiteral { result = val[0] }
- | For { result = val[0] }
- | While { result = val[0] }
- | Until { result = val[0] }
- | Try { result = val[0] }
- | ClassDefinition { result = val[0] }
- | LoopKeyword { result = val[0] }
- | EndScript { result = val[0] }
- | RimlFileCommand { result = val[0] }
- | RimlClassCommand { result = val[0] }
- | MultiAssign { result = val[0] }
- | If { result = val[0] }
- | Unless { result = val[0] }
- | Expression { result = val[0] }
- ;
-
- Expression:
- ExpressionWithoutDictLiteral { result = val[0] }
- | Dictionary { result = val[0] }
- | Dictionary DictGetWithDotLiteral { result = make_node(val) { |v| Riml::DictGetDotNode.new(v[0], v[1]) } }
- | BinaryOperator { result = val[0] }
- | Ternary { result = val[0] }
- | Assign { result = val[0] }
- | Super { result = val[0] }
- | '(' Expression ')' { result = make_node(val) { |v| Riml::WrapInParensNode.new(v[1]) } }
- ;
-
- ExpressionWithoutDictLiteral:
- UnaryOperator { result = val[0] }
- | DictGet { result = val[0] }
- | ListOrDictGet { result = val[0] }
- | AllVariableRetrieval { result = val[0] }
- | LiteralWithoutDictLiteral { result = val[0] }
- | Call { result = val[0] }
- | ObjectInstantiation { result = val[0] }
- | '(' ExpressionWithoutDictLiteral ')' { result = make_node(val) { |v| Riml::WrapInParensNode.new(v[1]) } }
- ;
-
- # for inside curly-brace variable names
- PossibleStringValue:
- String { result = val[0] }
- | DictGet { result = val[0] }
- | ListOrDictGet { result = val[0] }
- | AllVariableRetrieval { result = val[0] }
- | BinaryOperator { result = val[0] }
- | Ternary { result = val[0] }
- | Call { result = val[0] }
- ;
-
- Terminator:
- NEWLINE { result = nil }
- | ';' { result = nil }
- ;
-
- LiteralWithoutDictLiteral:
- Number { result = val[0] }
- | String { result = val[0] }
- | Regexp { result = val[0] }
- | List { result = val[0] }
- | ScopeModifierLiteral { result = val[0] }
- | TRUE { result = make_node(val) { |_| Riml::TrueNode.new } }
- | FALSE { result = make_node(val) { |_| Riml::FalseNode.new } }
- ;
-
- Number:
- NUMBER { result = make_node(val) { |v| Riml::NumberNode.new(v[0]) } }
- ;
-
- String:
- STRING_S { result = make_node(val) { |v| Riml::StringNode.new(v[0], :s) } }
- | STRING_D { result = make_node(val) { |v| Riml::StringNode.new(v[0], :d) } }
- | String STRING_S { result = make_node(val) { |v| Riml::StringLiteralConcatNode.new(v[0], Riml::StringNode.new(v[1], :s)) } }
- | String STRING_D { result = make_node(val) { |v| Riml::StringLiteralConcatNode.new(v[0], Riml::StringNode.new(v[1], :d)) } }
- ;
-
- Regexp:
- REGEXP { result = make_node(val) { |v| Riml::RegexpNode.new(v[0]) } }
- ;
-
- ScopeModifierLiteral:
- SCOPE_MODIFIER_LITERAL { result = make_node(val) { |v| Riml::ScopeModifierLiteralNode.new(v[0]) } }
- ;
-
- List:
- ListLiteral { result = make_node(val) { |v| Riml::ListNode.new(v[0]) } }
- ;
-
- ListUnpack:
- '[' ListItems ';' Expression ']' { result = make_node(val) { |v| Riml::ListUnpackNode.new(v[1] << v[3]) } }
- ;
-
- ListLiteral:
- '[' ListItems ']' { result = val[1] }
- | '[' ListItems ',' ']' { result = val[1] }
- ;
-
- ListItems:
- /* nothing */ { result = [] }
- | Expression { result = [val[0]] }
- | ListItems ',' Expression { result = val[0] << val[2] }
- ;
-
- Dictionary:
- DictionaryLiteral { result = make_node(val) { |v| Riml::DictionaryNode.new(v[0]) } }
- ;
-
- # {'key': 'value', 'key2': 'value2'}
- # Save as [['key', 'value'], ['key2', 'value2']] because ruby-1.8.7 offers
- # no guarantee for key-value pair ordering.
- DictionaryLiteral:
- '{' DictItems '}' { result = val[1] }
- | '{' DictItems ',' '}' { result = val[1] }
- ;
-
- # [[key, value], [key, value]]
- DictItems:
- /* nothing */ { result = [] }
- | DictItem { result = val }
- | DictItems ',' DictItem { result = val[0] << val[2] }
- ;
-
- # [key, value]
- DictItem:
- Expression ':' Expression { result = [val[0], val[2]] }
- ;
-
- DictGet:
- AllVariableRetrieval DictGetWithDot { result = make_node(val) { |v| Riml::DictGetDotNode.new(v[0], v[1]) } }
- | ListOrDictGet DictGetWithDot { result = make_node(val) { |v| Riml::DictGetDotNode.new(v[0], v[1]) } }
- | Call DictGetWithDot { result = make_node(val) { |v| Riml::DictGetDotNode.new(v[0], v[1]) } }
- | '(' Expression ')' DictGetWithDot { result = make_node(val) { |v| Riml::DictGetDotNode.new(Riml::WrapInParensNode.new(v[1]), v[3]) } }
- ;
-
- ListOrDictGet:
- ExpressionWithoutDictLiteral ListOrDictGetWithBrackets { result = make_node(val) { |v| Riml::ListOrDictGetNode.new(v[0], v[1]) } }
- | '(' Expression ')' ListOrDictGetWithBrackets { result = make_node(val) { |v| Riml::ListOrDictGetNode.new(Riml::WrapInParensNode.new(v[1]), v[3]) } }
- ;
-
- ListOrDictGetAssign:
- ExpressionWithoutDictLiteral ListOrDictGetWithBrackets { result = make_node(val) { |v| Riml::ListOrDictGetNode.new(v[0], v[1]) } }
- ;
-
- ListOrDictGetWithBrackets:
- '[' Expression ']' { result = [val[1]] }
- | '[' SubList ']' { result = [val[1]] }
- | ListOrDictGetWithBrackets '[' Expression ']' { result = val[0] << val[2] }
- | ListOrDictGetWithBrackets '[' SubList ']' { result = val[0] << val[2] }
- ;
-
- SubList:
- Expression ':' Expression { result = make_node(val) { |v| Riml::SublistNode.new([v[0], Riml::LiteralNode.new(' : '), v[2]]) } }
- | Expression ':' { result = make_node(val) { |v| Riml::SublistNode.new([v[0], Riml::LiteralNode.new(' :')]) } }
- | ':' Expression { result = make_node(val) { |v| Riml::SublistNode.new([Riml::LiteralNode.new(': '), v[1]]) } }
- | ':' { result = make_node(val) { |_| Riml::SublistNode.new([Riml::LiteralNode.new(':')]) } }
- ;
-
- DictGetWithDot:
- DICT_VAL { result = [val[0]] }
- | DictGetWithDot DICT_VAL { result = val[0] << val[1] }
- ;
-
- DictGetWithDotLiteral:
- '.' IDENTIFIER { result = [val[1]] }
- | DictGetWithDotLiteral DICT_VAL { result = val[0] << val[1] }
- ;
-
- Call:
- Scope DefCallIdentifier '(' ArgList ')' { result = make_node(val) { |v| Riml::CallNode.new(v[0], v[1], v[3]) } }
- | DictGet '(' ArgList ')' { result = make_node(val) { |v| Riml::CallNode.new(nil, v[0], v[2]) } }
- | BUILTIN_COMMAND '(' ArgList ')' { result = make_node(val) { |v| Riml::CallNode.new(nil, v[0], v[2]) } }
- | BUILTIN_COMMAND ArgListWithoutNothing { result = make_node(val) { |v| Riml::CallNode.new(nil, v[0], v[1]) } }
- | BUILTIN_COMMAND NEWLINE { result = make_node(val) { |v| Riml::CallNode.new(nil, v[0], []) } }
- | CALL '(' ArgList ')' { result = make_node(val) { |v| Riml::ExplicitCallNode.new(nil, nil, v[2]) } }
- ;
-
- ObjectInstantiationCall:
- Scope DefCallIdentifier '(' ArgList ')' { result = make_node(val) { |v| Riml::CallNode.new(v[0], v[1], v[3]) } }
- | Scope DefCallIdentifier { result = make_node(val) { |v| Riml::CallNode.new(v[0], v[1], []) } }
- ;
-
- RimlFileCommand:
- RIML_FILE_COMMAND '(' ArgList ')' { result = make_node(val) { |v| Riml::RimlFileCommandNode.new(nil, v[0], v[2]) } }
- | RIML_FILE_COMMAND ArgList { result = make_node(val) { |v| Riml::RimlFileCommandNode.new(nil, v[0], v[1]) } }
- ;
-
- RimlClassCommand:
- RIML_CLASS_COMMAND '(' ClassArgList ')' { result = make_node(val) { |v| Riml::RimlClassCommandNode.new(nil, v[0], v[2]) } }
- | RIML_CLASS_COMMAND ClassArgList { result = make_node(val) { |v| Riml::RimlClassCommandNode.new(nil, v[0], v[1]) } }
- ;
-
- ClassArgList:
- Scope IDENTIFIER { result = ["#{val[0]}#{val[1]}"] }
- | String { result = val }
- | ClassArgList ',' Scope IDENTIFIER { result = val[0].concat ["#{val[2]}#{val[3]}"] }
- ;
-
- ExplicitCall:
- CALL Scope DefCallIdentifier '(' ArgList ')' { result = make_node(val) { |v| Riml::ExplicitCallNode.new(v[1], v[2], v[4]) } }
- | CALL DictGet '(' ArgList ')' { result = make_node(val) { |v| Riml::ExplicitCallNode.new(nil, v[1], v[3]) } }
- ;
-
- Scope:
- SCOPE_MODIFIER { result = val[0] }
- | /* nothing */ { result = nil }
- ;
-
- # [SID, scope_modifier]
- SIDAndScope:
- Scope { result = [ nil, val[0] ] }
- | '<' IDENTIFIER '>' Scope { result = [ make_node(val) { |v| Riml::SIDNode.new(v[1]) }, val[3] ] }
- ;
-
- ArgList:
- /* nothing */ { result = [] }
- | ArgListWithoutNothingWithSplat { result = val[0] }
- ;
-
- ArgListWithSplat:
- /* nothing */ { result = [] }
- | ArgListWithoutNothingWithSplat { result = val[0] }
- ;
-
- ArgListWithoutNothingWithSplat:
- Expression { result = val }
- | SPLAT_ARG Expression { result = [ make_node(val) { |v| Riml::SplatNode.new(v[1]) } ] }
- | ArgListWithoutNothingWithSplat "," Expression { result = val[0] << val[2] }
- | ArgListWithoutNothingWithSplat "," SPLAT_ARG Expression { result = val[0] << make_node(val) { |v| Riml::SplatNode.new(v[3]) } }
- ;
-
- ArgListWithoutNothing:
- Expression { result = val }
- | ArgListWithoutNothing "," Expression { result = val[0] << val[2] }
- ;
-
- BinaryOperator:
- Expression '||' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
- | Expression '&&' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
-
- | Expression '==' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
- | Expression '==#' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
- | Expression '==?' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
-
- # added by riml
- | Expression '===' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
-
- | Expression '!=' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
- | Expression '!=#' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
- | Expression '!=?' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
-
- | Expression '=~' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
- | Expression '=~#' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
- | Expression '=~?' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
-
- | Expression '!~' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
- | Expression '!~#' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
- | Expression '!~?' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
-
- | Expression '>' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
- | Expression '>#' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
- | Expression '>?' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
-
- | Expression '>=' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
- | Expression '>=#' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
- | Expression '>=?' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
-
- | Expression '<' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
- | Expression '<#' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
- | Expression '<?' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
-
- | Expression '<=' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
- | Expression '<=#' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
- | Expression '<=?' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
-
- | Expression '+' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
- | Expression '-' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
- | Expression '*' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
- | Expression '/' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
- | Expression '.' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
- | Expression '%' Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
-
- | Expression IS Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
- | Expression ISNOT Expression { result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) } }
- ;
-
- UnaryOperator:
- '!' Expression { result = make_node(val) { |v| Riml::UnaryOperatorNode.new(val[0], [val[1]]) } }
- | '+' Expression { result = make_node(val) { |v| Riml::UnaryOperatorNode.new(val[0], [val[1]]) } }
- | '-' Expression { result = make_node(val) { |v| Riml::UnaryOperatorNode.new(val[0], [val[1]]) } }
- ;
-
- # ['=', LHS, RHS]
- Assign:
- LET AssignExpression { result = make_node(val) { |v| Riml::AssignNode.new(v[1][0], v[1][1], v[1][2]) } }
- | AssignExpression { result = make_node(val) { |v| Riml::AssignNode.new(v[0][0], v[0][1], v[0][2]) } }
- ;
-
- MultiAssign:
- Assign ',' Assign { result = make_node(val) { |v| Riml::MultiAssignNode.new([v[0], v[2]]) } }
- | MultiAssign ',' Assign { val[0].assigns << val[2]; result = val[0] }
- ;
-
- # ['=', AssignLHS, Expression]
- AssignExpression:
- AssignLHS '=' Expression { result = [val[1], val[0], val[2]] }
- | AssignLHS '+=' Expression { result = [val[1], val[0], val[2]] }
- | AssignLHS '-=' Expression { result = [val[1], val[0], val[2]] }
- | AssignLHS '.=' Expression { result = [val[1], val[0], val[2]] }
- ;
-
- AssignLHS:
- AllVariableRetrieval { result = val[0] }
- | List { result = val[0] }
- | ListUnpack { result = val[0] }
- | DictGet { result = val[0] }
- | ListOrDictGetAssign { result = val[0] }
- ;
-
- # retrieving the value of a variable
- VariableRetrieval:
- SimpleVariableRetrieval { result = val[0] }
- | SPECIAL_VAR_PREFIX IDENTIFIER { result = make_node(val) { |v| Riml::GetSpecialVariableNode.new(v[0], v[1]) } }
- | ScopeModifierLiteral ListOrDictGetWithBrackets { result = make_node(val) { |v| Riml::GetVariableByScopeAndDictNameNode.new(v[0], v[1]) } }
- ;
-
- SimpleVariableRetrieval:
- Scope IDENTIFIER { result = make_node(val) { |v| Riml::GetVariableNode.new(v[0], v[1]) } }
- ;
-
- AllVariableRetrieval:
- VariableRetrieval { result = val[0] }
- | Scope CurlyBraceName { result = make_node(val) { |v| Riml::GetCurlyBraceNameNode.new(v[0], v[1]) } }
- ;
-
- UnletVariable:
- UNLET VariableRetrieval { result = make_node(val) { |v| Riml::UnletVariableNode.new('!', [ v[1] ]) } }
- | UNLET_BANG VariableRetrieval { result = make_node(val) { |v| Riml::UnletVariableNode.new('!', [ v[1] ]) } }
- | UnletVariable VariableRetrieval { result = val[0] << val[1] }
- ;
-
- CurlyBraceName:
- CurlyBraceVarPart { result = make_node(val) { |v| Riml::CurlyBraceVariable.new([ v[0] ]) } }
- | IDENTIFIER CurlyBraceName { result = make_node(val) { |v| Riml::CurlyBraceVariable.new([ Riml::CurlyBracePart.new(v[0]), v[1] ]) } }
- | CurlyBraceName IDENTIFIER { result = val[0] << make_node(val) { |v| Riml::CurlyBracePart.new(v[1]) } }
- | CurlyBraceName CurlyBraceVarPart { result = val[0] << val[1] }
- ;
-
- CurlyBraceVarPart:
- '{' PossibleStringValue '}' { result = make_node(val) { |v| Riml::CurlyBracePart.new(v[1]) } }
- | '{' PossibleStringValue CurlyBraceVarPart '}' { result = make_node(val) { |v| Riml::CurlyBracePart.new([v[1], v[2]]) } }
- | '{' CurlyBraceVarPart PossibleStringValue '}' { result = make_node(val) { |v| Riml::CurlyBracePart.new([v[1], v[2]]) } }
- ;
-
- # Method definition
- # [SID, scope_modifier, name, parameters, keyword, expressions]
- Def:
- FunctionType SIDAndScope DefCallIdentifier DefKeywords Block END { result = make_node(val) { |v| Riml.const_get(val[0]).new('!', v[1][0], v[1][1], v[2], [], v[3], v[4]) } }
- | FunctionType SIDAndScope DefCallIdentifier '(' ParamList ')' DefKeywords Block END { result = make_node(val) { |v| Riml.const_get(val[0]).new('!', v[1][0], v[1][1], v[2], v[4], v[6], v[7]) } }
- | FunctionType SIDAndScope DefCallIdentifier '(' SPLAT_PARAM ')' DefKeywords Block END { result = make_node(val) { |v| Riml.const_get(val[0]).new('!', v[1][0], v[1][1], v[2], [v[4]], v[6], v[7]) } }
- | FunctionType SIDAndScope DefCallIdentifier '(' ParamList ',' SPLAT_PARAM ')' DefKeywords Block END { result = make_node(val) { |v| Riml.const_get(val[0]).new('!', v[1][0], v[1][1], v[2], v[4] << v[6], v[8], v[9]) } }
- ;
-
- FunctionType:
- DEF { result = "DefNode" }
- | DEF_BANG { result = "DefNode" }
- | DEFM { result = "DefMethodNode" }
- ;
-
- DefCallIdentifier:
- # use '' for first argument instead of nil in order to avoid a double scope-modifier
- CurlyBraceName { result = make_node(val) { |v| Riml::GetCurlyBraceNameNode.new('', v[0]) } }
- | IDENTIFIER { result = val[0] }
- ;
-
- # Example: 'range', 'dict' or 'abort' after function definition
- DefKeywords:
- IDENTIFIER { result = [val[0]] }
- | DefKeywords IDENTIFIER { result = val[0] << val[1] }
- | /* nothing */ { result = nil }
- ;
-
- ParamList:
- /* nothing */ { result = [] }
- | IDENTIFIER { result = val }
- | DefaultParam { result = val }
- | ParamList ',' IDENTIFIER { result = val[0] << val[2] }
- | ParamList ',' DefaultParam { result = val[0] << val[2] }
- ;
-
- DefaultParam:
- IDENTIFIER '=' Expression { result = make_node(val) { |v| Riml::DefaultParamNode.new(v[0], v[2]) } }
- ;
-
- Return:
- RETURN Returnable { result = make_node(val) { |v| Riml::ReturnNode.new(v[1]) } }
- | RETURN Returnable IF Expression { result = make_node(val) { |v| Riml::IfNode.new(v[3], Nodes.new([ReturnNode.new(v[1])])) } }
- | RETURN Returnable UNLESS Expression { result = make_node(val) { |v| Riml::UnlessNode.new(v[3], Nodes.new([ReturnNode.new(v[1])])) } }
- ;
-
- Returnable:
- /* nothing */ { result = nil }
- | Expression { result = val[0] }
- ;
-
- EndScript:
- FINISH { result = make_node(val) { |_| Riml::FinishNode.new } }
- ;
-
- # [expression, expressions]
- If:
- IF Expression IfBlock END { result = make_node(val) { |v| Riml::IfNode.new(v[1], v[2]) } }
- | IF Expression THEN Expression END { result = make_node(val) { |v| Riml::IfNode.new(v[1], Riml::Nodes.new([v[3]])) } }
- | Expression IF Expression { result = make_node(val) { |v| Riml::IfNode.new(v[2], Riml::Nodes.new([v[0]])) } }
- ;
-
- Unless:
- UNLESS Expression IfBlock END { result = make_node(val) { |v| Riml::UnlessNode.new(v[1], v[2]) } }
- | UNLESS Expression THEN Expression END { result = make_node(val) { |v| Riml::UnlessNode.new(v[1], Riml::Nodes.new([v[3]])) } }
- | Expression UNLESS Expression { result = make_node(val) { |v| Riml::UnlessNode.new(v[2], Riml::Nodes.new([v[0]])) } }
- ;
-
- Ternary:
- Expression '?' Expression ':' Expression { result = make_node(val) { |v| Riml::TernaryOperatorNode.new([v[0], v[2], v[4]]) } }
- ;
-
- While:
- WHILE Expression Block END { result = make_node(val) { |v| Riml::WhileNode.new(v[1], v[2]) } }
- ;
-
- LoopKeyword:
- BREAK { result = make_node(val) { |_| Riml::BreakNode.new } }
- | CONTINUE { result = make_node(val) { |_| Riml::ContinueNode.new } }
- ;
-
- Until:
- UNTIL Expression Block END { result = make_node(val) { |v| Riml::UntilNode.new(v[1], v[2]) } }
- ;
-
- For:
- FOR SimpleVariableRetrieval IN Expression Block END { result = make_node(val) { |v| Riml::ForNode.new(v[1], v[3], v[4]) } }
- | FOR List IN Expression Block END { result = make_node(val) { |v| Riml::ForNode.new(v[1], v[3], v[4]) } }
- | FOR ListUnpack IN Expression Block END { result = make_node(val) { |v| Riml::ForNode.new(v[1], v[3], v[4]) } }
- ;
-
- Try:
- TRY Block END { result = make_node(val) { |v| Riml::TryNode.new(v[1], nil, nil) } }
- | TRY Block Catch END { result = make_node(val) { |v| Riml::TryNode.new(v[1], v[2], nil) } }
- | TRY Block Catch FINALLY Block END { result = make_node(val) { |v| Riml::TryNode.new(v[1], v[2], v[4]) } }
- ;
-
- Catch:
- /* nothing */ { result = nil }
- | CATCH Block { result = [ make_node(val) { |v| Riml::CatchNode.new(nil, v[1]) } ] }
- | CATCH Catchable Block { result = [ make_node(val) { |v| Riml::CatchNode.new(v[1], v[2]) } ] }
- | Catch CATCH Block { result = val[0] << make_node(val) { |v| Riml::CatchNode.new(nil, v[2]) } }
- | Catch CATCH Catchable Block { result = val[0] << make_node(val) { |v| Riml::CatchNode.new(v[2], v[3]) } }
- ;
-
- Catchable:
- Regexp { result = val[0] }
- | String { result = val[0] }
- ;
-
- # [expressions]
- # expressions list could contain an ElseNode, which contains expressions
- # itself
- Block:
- NEWLINE Statements { result = val[1] }
- | NEWLINE { result = make_node(val) { |_| Riml::Nodes.new([]) } }
- ;
-
- IfBlock:
- Block { result = val[0] }
- | NEWLINE Statements ElseBlock { result = val[1] << val[2] }
- | NEWLINE Statements ElseifBlock { result = val[1] << val[2] }
- | NEWLINE Statements ElseifBlock ElseBlock { result = val[1] << val[2] << val[3] }
- ;
-
- ElseBlock:
- ELSE NEWLINE Statements { result = make_node(val) { |v| Riml::ElseNode.new(v[2]) } }
- ;
-
- ElseifBlock:
- ELSEIF Expression NEWLINE Statements { result = make_node(val) { |v| Riml::Nodes.new([Riml::ElseifNode.new(v[1], v[3])]) } }
- | ElseifBlock ELSEIF Expression NEWLINE Statements { result = val[0] << make_node(val) { |v| Riml::ElseifNode.new(v[2], v[4]) } }
- ;
-
- ClassDefinition:
- CLASS Scope IDENTIFIER Block END { result = make_node(val) { |v| Riml::ClassDefinitionNode.new(v[1], v[2], nil, v[3]) } }
- | CLASS Scope IDENTIFIER '<' Scope IDENTIFIER Block END { result = make_node(val) { |v| Riml::ClassDefinitionNode.new(v[1], v[2], (v[4] || ClassDefinitionNode::DEFAULT_SCOPE_MODIFIER) + v[5], v[6]) } }
- ;
-
- ObjectInstantiation:
- NEW ObjectInstantiationCall { result = make_node(val) { |v| Riml::ObjectInstantiationNode.new(v[1]) } }
- ;
-
- Super:
- SUPER '(' ArgListWithSplat ')' { result = make_node(val) { |v| Riml::SuperNode.new(v[2], true) } }
- | SUPER { result = make_node(val) { |_| Riml::SuperNode.new([], false) } }
- ;
-
- ExLiteral:
- EX_LITERAL { result = make_node(val) { |v| Riml::ExLiteralNode.new(v[0]) } }
- ;
-end
-
----- header
- require File.expand_path("../lexer", __FILE__)
- require File.expand_path("../nodes", __FILE__)
- require File.expand_path("../errors", __FILE__)
- require File.expand_path("../ast_rewriter", __FILE__)
----- inner
- # This code will be put as-is in the parser class
-
- attr_accessor :ast_rewriter
- attr_writer :options
-
- # The Parser and AST_Rewriter share this same hash of options
- def options
- @options ||= {}
- end
-
- def self.ast_cache
- @ast_cache
- end
- @ast_cache = {}
-
- # parses tokens or code into output nodes
- def parse(object, ast_rewriter = Riml::AST_Rewriter.new, filename = nil, included = false)
- if (ast = self.class.ast_cache[filename])
- else
- if tokens?(object)
- @tokens = object
- elsif code?(object)
- @lexer = Riml::Lexer.new(object, filename, true)
- end
-
- begin
- ast = do_parse
- rescue Racc::ParseError => e
- raise unless @lexer
- if (invalid_token = @lexer.prev_token_is_keyword?)
- warning = "#{invalid_token.inspect} is a keyword, and cannot " \
- "be used as a variable name"
- end
- error_msg = e.message
- error_msg << "\nWARNING: #{warning}" if warning
- error = Riml::ParseError.new(error_msg, @lexer.filename, @lexer.lineno)
- raise error
- end
- self.class.ast_cache[filename] = ast if filename
- end
- @ast_rewriter ||= ast_rewriter
- return ast unless @ast_rewriter
- @ast_rewriter.ast = ast.dup
- @ast_rewriter.options ||= options
- @ast_rewriter.rewrite(filename, included)
- @ast_rewriter.ast
- end
-
- # get the next token from either the list of tokens provided, or
- # the lexer getting the next token
- def next_token
- return @tokens.shift unless @lexer
- token = @lexer.next_token
- if token && @lexer.parser_info
- @current_parser_info = token.pop
- end
- token
- end
-
- private
-
- def tokens?(object)
- Array === object
- end
-
- def code?(object)
- String === object
- end
-
- def make_node(racc_val)
- node = yield racc_val
- node.parser_info = @current_parser_info
- node
- end
diff --git a/test/racc/assets/rrconf.y b/test/racc/assets/rrconf.y
deleted file mode 100644
index baf9249a77..0000000000
--- a/test/racc/assets/rrconf.y
+++ /dev/null
@@ -1,14 +0,0 @@
-# 1 s/r conflict and 1 r/r conflict
-
-class A
-rule
-
-target: a
-
-a :
- | a list
-
-list :
- | list ITEM
-
-end
diff --git a/test/racc/assets/ruby18.y b/test/racc/assets/ruby18.y
deleted file mode 100644
index eceb253298..0000000000
--- a/test/racc/assets/ruby18.y
+++ /dev/null
@@ -1,1943 +0,0 @@
-# Copyright (c) 2013 Peter Zotov <whitequark@whitequark.org>
-#
-# Parts of the source are derived from ruby_parser:
-# Copyright (c) Ryan Davis, seattle.rb
-#
-# MIT License
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-class Parser::Ruby18
-
-token kCLASS kMODULE kDEF kUNDEF kBEGIN kRESCUE kENSURE kEND kIF kUNLESS
- kTHEN kELSIF kELSE kCASE kWHEN kWHILE kUNTIL kFOR kBREAK kNEXT
- kREDO kRETRY kIN kDO kDO_COND kDO_BLOCK kRETURN kYIELD kSUPER
- kSELF kNIL kTRUE kFALSE kAND kOR kNOT kIF_MOD kUNLESS_MOD kWHILE_MOD
- kUNTIL_MOD kRESCUE_MOD kALIAS kDEFINED klBEGIN klEND k__LINE__
- k__FILE__ tIDENTIFIER tFID tGVAR tIVAR tCONSTANT tCVAR tNTH_REF
- tBACK_REF tSTRING_CONTENT tINTEGER tFLOAT tREGEXP_END tUPLUS
- tUMINUS tUMINUS_NUM tPOW tCMP tEQ tEQQ tNEQ tGEQ tLEQ tANDOP
- tOROP tMATCH tNMATCH tDOT tDOT2 tDOT3 tAREF tASET tLSHFT tRSHFT
- tCOLON2 tCOLON3 tOP_ASGN tASSOC tLPAREN tLPAREN2 tRPAREN tLPAREN_ARG
- tLBRACK tLBRACK2 tRBRACK tLBRACE tLBRACE_ARG tSTAR tSTAR2 tAMPER tAMPER2
- tTILDE tPERCENT tDIVIDE tPLUS tMINUS tLT tGT tPIPE tBANG tCARET
- tLCURLY tRCURLY tBACK_REF2 tSYMBEG tSTRING_BEG tXSTRING_BEG tREGEXP_BEG
- tWORDS_BEG tQWORDS_BEG tSTRING_DBEG tSTRING_DVAR tSTRING_END tSTRING
- tSYMBOL tREGEXP_OPT tNL tEH tCOLON tCOMMA tSPACE tSEMI
-
-prechigh
- right tBANG tTILDE tUPLUS
- right tPOW
- right tUMINUS_NUM tUMINUS
- left tSTAR2 tDIVIDE tPERCENT
- left tPLUS tMINUS
- left tLSHFT tRSHFT
- left tAMPER2
- left tPIPE tCARET
- left tGT tGEQ tLT tLEQ
- nonassoc tCMP tEQ tEQQ tNEQ tMATCH tNMATCH
- left tANDOP
- left tOROP
- nonassoc tDOT2 tDOT3
- right tEH tCOLON
- left kRESCUE_MOD
- right tEQL tOP_ASGN
- nonassoc kDEFINED
- right kNOT
- left kOR kAND
- nonassoc kIF_MOD kUNLESS_MOD kWHILE_MOD kUNTIL_MOD
- nonassoc tLBRACE_ARG
- nonassoc tLOWEST
-preclow
-
-rule
-
- program: compstmt
- {
- result = val[0]
- }
-
- bodystmt: compstmt opt_rescue opt_else opt_ensure
- {
- rescue_bodies = val[1]
- else_t, else_ = val[2]
- ensure_t, ensure_ = val[3]
-
- if rescue_bodies.empty? && !else_.nil?
- diagnostic :warning, :useless_else, nil, else_t
- end
-
- result = @builder.begin_body(val[0],
- rescue_bodies,
- else_t, else_,
- ensure_t, ensure_)
- }
-
- compstmt: stmts opt_terms
- {
- result = @builder.compstmt(val[0])
- }
-
- stmts: # nothing
- {
- result = []
- }
- | stmt
- {
- result = [ val[0] ]
- }
- | error stmt
- {
- result = [ val[1] ]
- }
- | stmts terms stmt
- {
- result = val[0] << val[2]
- }
-
- stmt: kALIAS fitem
- {
- @lexer.state = :expr_fname
- }
- fitem
- {
- result = @builder.alias(val[0], val[1], val[3])
- }
- | kALIAS tGVAR tGVAR
- {
- result = @builder.alias(val[0],
- @builder.gvar(val[1]),
- @builder.gvar(val[2]))
- }
- | kALIAS tGVAR tBACK_REF
- {
- result = @builder.alias(val[0],
- @builder.gvar(val[1]),
- @builder.back_ref(val[2]))
- }
- | kALIAS tGVAR tNTH_REF
- {
- diagnostic :error, :nth_ref_alias, nil, val[2]
- }
- | kUNDEF undef_list
- {
- result = @builder.undef_method(val[0], val[1])
- }
- | stmt kIF_MOD expr_value
- {
- result = @builder.condition_mod(val[0], nil,
- val[1], val[2])
- }
- | stmt kUNLESS_MOD expr_value
- {
- result = @builder.condition_mod(nil, val[0],
- val[1], val[2])
- }
- | stmt kWHILE_MOD expr_value
- {
- result = @builder.loop_mod(:while, val[0], val[1], val[2])
- }
- | stmt kUNTIL_MOD expr_value
- {
- result = @builder.loop_mod(:until, val[0], val[1], val[2])
- }
- | stmt kRESCUE_MOD stmt
- {
- rescue_body = @builder.rescue_body(val[1],
- nil, nil, nil,
- nil, val[2])
-
- result = @builder.begin_body(val[0], [ rescue_body ])
- }
- | klBEGIN tLCURLY compstmt tRCURLY
- {
- if in_def?
- diagnostic :error, :begin_in_method, nil, val[0]
- end
-
- result = @builder.preexe(val[0], val[1], val[2], val[3])
- }
- | klEND tLCURLY compstmt tRCURLY
- {
- result = @builder.postexe(val[0], val[1], val[2], val[3])
- }
- | lhs tEQL command_call
- {
- result = @builder.assign(val[0], val[1], val[2])
- }
- | mlhs tEQL command_call
- {
- result = @builder.multi_assign(val[0], val[1], val[2])
- }
- | var_lhs tOP_ASGN command_call
- {
- result = @builder.op_assign(val[0], val[1], val[2])
- }
- | primary_value tLBRACK2 aref_args tRBRACK tOP_ASGN command_call
- {
- result = @builder.op_assign(
- @builder.index(
- val[0], val[1], val[2], val[3]),
- val[4], val[5])
- }
- | primary_value tDOT tIDENTIFIER tOP_ASGN command_call
- {
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
- }
- | primary_value tDOT tCONSTANT tOP_ASGN command_call
- {
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
- }
- | primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_call
- {
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
- }
- | backref tOP_ASGN command_call
- {
- @builder.op_assign(val[0], val[1], val[2])
- }
- | lhs tEQL mrhs
- {
- result = @builder.assign(val[0], val[1],
- @builder.array(nil, val[2], nil))
- }
- | mlhs tEQL arg_value
- {
- result = @builder.multi_assign(val[0], val[1], val[2])
- }
- | mlhs tEQL mrhs
- {
- result = @builder.multi_assign(val[0], val[1],
- @builder.array(nil, val[2], nil))
- }
- | expr
-
- expr: command_call
- | expr kAND expr
- {
- result = @builder.logical_op(:and, val[0], val[1], val[2])
- }
- | expr kOR expr
- {
- result = @builder.logical_op(:or, val[0], val[1], val[2])
- }
- | kNOT expr
- {
- result = @builder.not_op(val[0], nil, val[1], nil)
- }
- | tBANG command_call
- {
- result = @builder.not_op(val[0], nil, val[1], nil)
- }
- | arg
-
- expr_value: expr
-
- command_call: command
- | block_command
- | kRETURN call_args
- {
- result = @builder.keyword_cmd(:return, val[0],
- nil, val[1], nil)
- }
- | kBREAK call_args
- {
- result = @builder.keyword_cmd(:break, val[0],
- nil, val[1], nil)
- }
- | kNEXT call_args
- {
- result = @builder.keyword_cmd(:next, val[0],
- nil, val[1], nil)
- }
-
- block_command: block_call
- | block_call tDOT operation2 command_args
- {
- lparen_t, args, rparen_t = val[3]
- result = @builder.call_method(val[0], val[1], val[2],
- lparen_t, args, rparen_t)
- }
- | block_call tCOLON2 operation2 command_args
- {
- lparen_t, args, rparen_t = val[3]
- result = @builder.call_method(val[0], val[1], val[2],
- lparen_t, args, rparen_t)
- }
-
- cmd_brace_block: tLBRACE_ARG
- {
- @static_env.extend_dynamic
- }
- opt_block_var compstmt tRCURLY
- {
- result = [ val[0], val[2], val[3], val[4] ]
-
- @static_env.unextend
- }
-
- command: operation command_args =tLOWEST
- {
- lparen_t, args, rparen_t = val[1]
- result = @builder.call_method(nil, nil, val[0],
- lparen_t, args, rparen_t)
- }
- | operation command_args cmd_brace_block
- {
- lparen_t, args, rparen_t = val[1]
- method_call = @builder.call_method(nil, nil, val[0],
- lparen_t, args, rparen_t)
-
- begin_t, block_args, body, end_t = val[2]
- result = @builder.block(method_call,
- begin_t, block_args, body, end_t)
- }
- | primary_value tDOT operation2 command_args =tLOWEST
- {
- lparen_t, args, rparen_t = val[3]
- result = @builder.call_method(val[0], val[1], val[2],
- lparen_t, args, rparen_t)
-
- }
- | primary_value tDOT operation2 command_args cmd_brace_block
- {
- lparen_t, args, rparen_t = val[3]
- method_call = @builder.call_method(val[0], val[1], val[2],
- lparen_t, args, rparen_t)
-
- begin_t, block_args, body, end_t = val[4]
- result = @builder.block(method_call,
- begin_t, block_args, body, end_t)
- }
- | primary_value tCOLON2 operation2 command_args =tLOWEST
- {
- lparen_t, args, rparen_t = val[3]
- result = @builder.call_method(val[0], val[1], val[2],
- lparen_t, args, rparen_t)
- }
- | primary_value tCOLON2 operation2 command_args cmd_brace_block
- {
- lparen_t, args, rparen_t = val[3]
- method_call = @builder.call_method(val[0], val[1], val[2],
- lparen_t, args, rparen_t)
-
- begin_t, block_args, body, end_t = val[4]
- result = @builder.block(method_call,
- begin_t, block_args, body, end_t)
- }
- | kSUPER command_args
- {
- lparen_t, args, rparen_t = val[1]
- result = @builder.keyword_cmd(:super, val[0],
- lparen_t, args, rparen_t)
- }
- | kYIELD command_args
- {
- lparen_t, args, rparen_t = val[1]
- result = @builder.keyword_cmd(:yield, val[0],
- lparen_t, args, rparen_t)
- }
-
- mlhs: mlhs_basic
- {
- result = @builder.multi_lhs(nil, val[0], nil)
- }
- | tLPAREN mlhs_entry tRPAREN
- {
- result = @builder.begin(val[0], val[1], val[2])
- }
-
- mlhs_entry: mlhs_basic
- {
- result = @builder.multi_lhs(nil, val[0], nil)
- }
- | tLPAREN mlhs_entry tRPAREN
- {
- result = @builder.multi_lhs(val[0], val[1], val[2])
- }
-
- mlhs_basic: mlhs_head
- {
- result = val[0]
- }
- | mlhs_head mlhs_item
- {
- result = val[0] << val[1]
- }
- | mlhs_head tSTAR mlhs_node
- {
- result = val[0] << @builder.splat(val[1], val[2])
- }
- | mlhs_head tSTAR
- {
- result = val[0] << @builder.splat(val[1])
- }
- | tSTAR mlhs_node
- {
- result = [ @builder.splat(val[0], val[1]) ]
- }
- | tSTAR
- {
- result = [ @builder.splat(val[0]) ]
- }
-
- mlhs_item: mlhs_node
- | tLPAREN mlhs_entry tRPAREN
- {
- result = @builder.begin(val[0], val[1], val[2])
- }
-
- mlhs_head: mlhs_item tCOMMA
- {
- result = [ val[0] ]
- }
- | mlhs_head mlhs_item tCOMMA
- {
- result = val[0] << val[1]
- }
-
- mlhs_node: variable
- {
- result = @builder.assignable(val[0])
- }
- | primary_value tLBRACK2 aref_args tRBRACK
- {
- result = @builder.index_asgn(val[0], val[1], val[2], val[3])
- }
- | primary_value tDOT tIDENTIFIER
- {
- result = @builder.attr_asgn(val[0], val[1], val[2])
- }
- | primary_value tCOLON2 tIDENTIFIER
- {
- result = @builder.attr_asgn(val[0], val[1], val[2])
- }
- | primary_value tDOT tCONSTANT
- {
- result = @builder.attr_asgn(val[0], val[1], val[2])
- }
- | primary_value tCOLON2 tCONSTANT
- {
- result = @builder.assignable(
- @builder.const_fetch(val[0], val[1], val[2]))
- }
- | tCOLON3 tCONSTANT
- {
- result = @builder.assignable(
- @builder.const_global(val[0], val[1]))
- }
- | backref
- {
- result = @builder.assignable(val[0])
- }
-
- lhs: variable
- {
- result = @builder.assignable(val[0])
- }
- | primary_value tLBRACK2 aref_args tRBRACK
- {
- result = @builder.index_asgn(val[0], val[1], val[2], val[3])
- }
- | primary_value tDOT tIDENTIFIER
- {
- result = @builder.attr_asgn(val[0], val[1], val[2])
- }
- | primary_value tCOLON2 tIDENTIFIER
- {
- result = @builder.attr_asgn(val[0], val[1], val[2])
- }
- | primary_value tDOT tCONSTANT
- {
- result = @builder.attr_asgn(val[0], val[1], val[2])
- }
- | primary_value tCOLON2 tCONSTANT
- {
- result = @builder.assignable(
- @builder.const_fetch(val[0], val[1], val[2]))
- }
- | tCOLON3 tCONSTANT
- {
- result = @builder.assignable(
- @builder.const_global(val[0], val[1]))
- }
- | backref
- {
- result = @builder.assignable(val[0])
- }
-
- cname: tIDENTIFIER
- {
- diagnostic :error, :module_name_const, nil, val[0]
- }
- | tCONSTANT
-
- cpath: tCOLON3 cname
- {
- result = @builder.const_global(val[0], val[1])
- }
- | cname
- {
- result = @builder.const(val[0])
- }
- | primary_value tCOLON2 cname
- {
- result = @builder.const_fetch(val[0], val[1], val[2])
- }
-
- fname: tIDENTIFIER | tCONSTANT | tFID
- | op
- | reswords
-
- fsym: fname
- {
- result = @builder.symbol(val[0])
- }
- | symbol
-
- fitem: fsym
- | dsym
-
- undef_list: fitem
- {
- result = [ val[0] ]
- }
- | undef_list tCOMMA
- {
- @lexer.state = :expr_fname
- }
- fitem
- {
- result = val[0] << val[3]
- }
-
- op: tPIPE | tCARET | tAMPER2 | tCMP | tEQ | tEQQ
- | tMATCH | tGT | tGEQ | tLT | tLEQ | tLSHFT
- | tRSHFT | tPLUS | tMINUS | tSTAR2 | tSTAR | tDIVIDE
- | tPERCENT | tPOW | tTILDE | tUPLUS | tUMINUS | tAREF
- | tASET | tBACK_REF2
-
- reswords: k__LINE__ | k__FILE__ | klBEGIN | klEND | kALIAS | kAND
- | kBEGIN | kBREAK | kCASE | kCLASS | kDEF | kDEFINED
- | kDO | kELSE | kELSIF | kEND | kENSURE | kFALSE
- | kFOR | kIN | kMODULE | kNEXT | kNIL | kNOT
- | kOR | kREDO | kRESCUE | kRETRY | kRETURN | kSELF
- | kSUPER | kTHEN | kTRUE | kUNDEF | kWHEN | kYIELD
- | kIF | kUNLESS | kWHILE | kUNTIL
-
- arg: lhs tEQL arg
- {
- result = @builder.assign(val[0], val[1], val[2])
- }
- | lhs tEQL arg kRESCUE_MOD arg
- {
- rescue_body = @builder.rescue_body(val[3],
- nil, nil, nil,
- nil, val[4])
-
- rescue_ = @builder.begin_body(val[2], [ rescue_body ])
-
- result = @builder.assign(val[0], val[1], rescue_)
- }
- | var_lhs tOP_ASGN arg
- {
- result = @builder.op_assign(val[0], val[1], val[2])
- }
- | primary_value tLBRACK2 aref_args tRBRACK tOP_ASGN arg
- {
- result = @builder.op_assign(
- @builder.index(
- val[0], val[1], val[2], val[3]),
- val[4], val[5])
- }
- | primary_value tDOT tIDENTIFIER tOP_ASGN arg
- {
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
- }
- | primary_value tDOT tCONSTANT tOP_ASGN arg
- {
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
- }
- | primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg
- {
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
- }
- | primary_value tCOLON2 tCONSTANT tOP_ASGN arg
- {
- diagnostic :error, :dynamic_const, nil, val[2], [ val[3] ]
- }
- | tCOLON3 tCONSTANT tOP_ASGN arg
- {
- diagnostic :error, :dynamic_const, nil, val[1], [ val[2] ]
- }
- | backref tOP_ASGN arg
- {
- result = @builder.op_assign(val[0], val[1], val[2])
- }
- | arg tDOT2 arg
- {
- result = @builder.range_inclusive(val[0], val[1], val[2])
- }
- | arg tDOT3 arg
- {
- result = @builder.range_exclusive(val[0], val[1], val[2])
- }
- | arg tPLUS arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tMINUS arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tSTAR2 arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tDIVIDE arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tPERCENT arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tPOW arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | tUMINUS_NUM tINTEGER tPOW arg
- {
- result = @builder.unary_op(val[0],
- @builder.binary_op(
- @builder.integer(val[1]),
- val[2], val[3]))
- }
- | tUMINUS_NUM tFLOAT tPOW arg
- {
- result = @builder.unary_op(val[0],
- @builder.binary_op(
- @builder.float(val[1]),
- val[2], val[3]))
- }
- | tUPLUS arg
- {
- result = @builder.unary_op(val[0], val[1])
- }
- | tUMINUS arg
- {
- result = @builder.unary_op(val[0], val[1])
- }
- | arg tPIPE arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tCARET arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tAMPER2 arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tCMP arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tGT arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tGEQ arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tLT arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tLEQ arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tEQ arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tEQQ arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tNEQ arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tMATCH arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tNMATCH arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | tBANG arg
- {
- result = @builder.not_op(val[0], nil, val[1], nil)
- }
- | tTILDE arg
- {
- result = @builder.unary_op(val[0], val[1])
- }
- | arg tLSHFT arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tRSHFT arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tANDOP arg
- {
- result = @builder.logical_op(:and, val[0], val[1], val[2])
- }
- | arg tOROP arg
- {
- result = @builder.logical_op(:or, val[0], val[1], val[2])
- }
- | kDEFINED opt_nl arg
- {
- result = @builder.keyword_cmd(:defined?, val[0], nil, [ val[2] ], nil)
- }
- | arg tEH arg tCOLON arg
- {
- result = @builder.ternary(val[0], val[1],
- val[2], val[3], val[4])
- }
- | primary
-
- arg_value: arg
-
- aref_args: none
- | command opt_nl
- {
- result = [ val[0] ]
- }
- | args trailer
- {
- result = val[0]
- }
- | args tCOMMA tSTAR arg opt_nl
- {
- result = val[0] << @builder.splat(val[2], val[3])
- }
- | assocs trailer
- {
- result = [ @builder.associate(nil, val[0], nil) ]
- }
- | tSTAR arg opt_nl
- {
- result = [ @builder.splat(val[0], val[1]) ]
- }
-
- paren_args: tLPAREN2 none tRPAREN
- {
- result = [ val[0], [], val[2] ]
- }
- | tLPAREN2 call_args opt_nl tRPAREN
- {
- result = [ val[0], val[1], val[3] ]
- }
- | tLPAREN2 block_call opt_nl tRPAREN
- {
- result = [ val[0], [ val[1] ], val[3] ]
- }
- | tLPAREN2 args tCOMMA block_call opt_nl tRPAREN
- {
- result = [ val[0], val[1] << val[3], val[5] ]
- }
-
- opt_paren_args: # nothing
- {
- result = [ nil, [], nil ]
- }
- | paren_args
-
- call_args: command
- {
- result = [ val[0] ]
- }
- | args opt_block_arg
- {
- result = val[0].concat(val[1])
- }
- | args tCOMMA tSTAR arg_value opt_block_arg
- {
- result = val[0].concat(
- [ @builder.splat(val[2], val[3]),
- *val[4] ])
- }
- | assocs opt_block_arg
- {
- result = [ @builder.associate(nil, val[0], nil),
- *val[1] ]
- }
- | assocs tCOMMA tSTAR arg_value opt_block_arg
- {
- result = [ @builder.associate(nil, val[0], nil),
- @builder.splat(val[2], val[3]),
- *val[4] ]
- }
- | args tCOMMA assocs opt_block_arg
- {
- result = val[0].concat(
- [ @builder.associate(nil, val[2], nil),
- *val[3] ])
- }
- | args tCOMMA assocs tCOMMA tSTAR arg opt_block_arg
- {
- result = val[0].concat(
- [ @builder.associate(nil, val[2], nil),
- @builder.splat(val[4], val[5]),
- *val[6] ])
- }
- | tSTAR arg_value opt_block_arg
- {
- result = [ @builder.splat(val[0], val[1]),
- *val[2] ]
- }
- | block_arg
- {
- result = [ val[0] ]
- }
-
- call_args2: arg_value tCOMMA args opt_block_arg
- {
- result = [ val[0], *val[2].concat(val[3]) ]
- }
- | arg_value tCOMMA block_arg
- {
- result = [ val[0], val[2] ]
- }
- | arg_value tCOMMA tSTAR arg_value opt_block_arg
- {
- result = [ val[0],
- @builder.splat(val[2], val[3]),
- *val[4] ]
- }
- | arg_value tCOMMA args tCOMMA tSTAR arg_value opt_block_arg
- {
- result = [ val[0],
- *val[2].
- push(@builder.splat(val[4], val[5])).
- concat(val[6]) ]
- }
- | assocs opt_block_arg
- {
- result = [ @builder.associate(nil, val[0], nil),
- *val[1] ]
- }
- | assocs tCOMMA tSTAR arg_value opt_block_arg
- {
- result = [ @builder.associate(nil, val[0], nil),
- @builder.splat(val[2], val[3]),
- *val[4] ]
- }
- | arg_value tCOMMA assocs opt_block_arg
- {
- result = [ val[0],
- @builder.associate(nil, val[2], nil),
- *val[3] ]
- }
- | arg_value tCOMMA args tCOMMA assocs opt_block_arg
- {
- result = [ val[0],
- *val[2].
- push(@builder.associate(nil, val[4], nil)).
- concat(val[5]) ]
- }
- | arg_value tCOMMA assocs tCOMMA tSTAR arg_value opt_block_arg
- {
- result = [ val[0],
- @builder.associate(nil, val[2], nil),
- @builder.splat(val[4], val[5]),
- *val[6] ]
- }
- | arg_value tCOMMA args tCOMMA assocs tCOMMA tSTAR arg_value opt_block_arg
- {
- result = [ val[0],
- *val[2].
- push(@builder.associate(nil, val[4], nil)).
- push(@builder.splat(val[6], val[7])).
- concat(val[8]) ]
- }
- | tSTAR arg_value opt_block_arg
- {
- result = [ @builder.splat(val[0], val[1]),
- *val[2] ]
- }
- | block_arg
- {
- result = [ val[0] ]
- }
-
- command_args: {
- result = @lexer.cmdarg.dup
- @lexer.cmdarg.push(true)
- }
- open_args
- {
- @lexer.cmdarg = val[0]
-
- result = val[1]
- }
-
- open_args: call_args
- {
- result = [ nil, val[0], nil ]
- }
- | tLPAREN_ARG
- {
- @lexer.state = :expr_endarg
- }
- tRPAREN
- {
- result = [ val[0], [], val[2] ]
- }
- | tLPAREN_ARG call_args2
- {
- @lexer.state = :expr_endarg
- }
- tRPAREN
- {
- result = [ val[0], val[1], val[3] ]
- }
-
- block_arg: tAMPER arg_value
- {
- result = @builder.block_pass(val[0], val[1])
- }
-
- opt_block_arg: tCOMMA block_arg
- {
- result = [ val[1] ]
- }
- | # nothing
- {
- result = []
- }
-
- args: arg_value
- {
- result = [ val[0] ]
- }
- | args tCOMMA arg_value
- {
- result = val[0] << val[2]
- }
-
- mrhs: args tCOMMA arg_value
- {
- result = val[0] << val[2]
- }
- | args tCOMMA tSTAR arg_value
- {
- result = val[0] << @builder.splat(val[2], val[3])
- }
- | tSTAR arg_value
- {
- result = [ @builder.splat(val[0], val[1]) ]
- }
-
- primary: literal
- | strings
- | xstring
- | regexp
- | words
- | qwords
- | var_ref
- | backref
- | tFID
- {
- result = @builder.call_method(nil, nil, val[0])
- }
- | kBEGIN bodystmt kEND
- {
- result = @builder.begin_keyword(val[0], val[1], val[2])
- }
- | tLPAREN_ARG expr
- {
- @lexer.state = :expr_endarg
- }
- opt_nl tRPAREN
- {
- result = @builder.begin(val[0], val[1], val[4])
- }
- | tLPAREN compstmt tRPAREN
- {
- result = @builder.begin(val[0], val[1], val[2])
- }
- | primary_value tCOLON2 tCONSTANT
- {
- result = @builder.const_fetch(val[0], val[1], val[2])
- }
- | tCOLON3 tCONSTANT
- {
- result = @builder.const_global(val[0], val[1])
- }
- | primary_value tLBRACK2 aref_args tRBRACK
- {
- result = @builder.index(val[0], val[1], val[2], val[3])
- }
- | tLBRACK aref_args tRBRACK
- {
- result = @builder.array(val[0], val[1], val[2])
- }
- | tLBRACE assoc_list tRCURLY
- {
- result = @builder.associate(val[0], val[1], val[2])
- }
- | kRETURN
- {
- result = @builder.keyword_cmd(:return, val[0])
- }
- | kYIELD tLPAREN2 call_args tRPAREN
- {
- result = @builder.keyword_cmd(:yield, val[0], val[1], val[2], val[3])
- }
- | kYIELD tLPAREN2 tRPAREN
- {
- result = @builder.keyword_cmd(:yield, val[0], val[1], [], val[2])
- }
- | kYIELD
- {
- result = @builder.keyword_cmd(:yield, val[0])
- }
- | kDEFINED opt_nl tLPAREN2 expr tRPAREN
- {
- result = @builder.keyword_cmd(:defined?, val[0],
- val[2], [ val[3] ], val[4])
- }
- | operation brace_block
- {
- method_call = @builder.call_method(nil, nil, val[0])
-
- begin_t, args, body, end_t = val[1]
- result = @builder.block(method_call,
- begin_t, args, body, end_t)
- }
- | method_call
- | method_call brace_block
- {
- begin_t, args, body, end_t = val[1]
- result = @builder.block(val[0],
- begin_t, args, body, end_t)
- }
- | kIF expr_value then compstmt if_tail kEND
- {
- else_t, else_ = val[4]
- result = @builder.condition(val[0], val[1], val[2],
- val[3], else_t,
- else_, val[5])
- }
- | kUNLESS expr_value then compstmt opt_else kEND
- {
- else_t, else_ = val[4]
- result = @builder.condition(val[0], val[1], val[2],
- else_, else_t,
- val[3], val[5])
- }
- | kWHILE
- {
- @lexer.cond.push(true)
- }
- expr_value do
- {
- @lexer.cond.pop
- }
- compstmt kEND
- {
- result = @builder.loop(:while, val[0], val[2], val[3],
- val[5], val[6])
- }
- | kUNTIL
- {
- @lexer.cond.push(true)
- }
- expr_value do
- {
- @lexer.cond.pop
- }
- compstmt kEND
- {
- result = @builder.loop(:until, val[0], val[2], val[3],
- val[5], val[6])
- }
- | kCASE expr_value opt_terms case_body kEND
- {
- when_bodies = val[3][0..-2]
- else_t, else_body = val[3][-1]
-
- result = @builder.case(val[0], val[1],
- when_bodies, else_t, else_body,
- val[4])
- }
- | kCASE opt_terms case_body kEND
- {
- when_bodies = val[2][0..-2]
- else_t, else_body = val[2][-1]
-
- result = @builder.case(val[0], nil,
- when_bodies, else_t, else_body,
- val[3])
- }
- | kCASE opt_terms kELSE compstmt kEND
- {
- result = @builder.case(val[0], nil,
- [], val[2], val[3],
- val[4])
- }
- | kFOR for_var kIN
- {
- @lexer.cond.push(true)
- }
- expr_value do
- {
- @lexer.cond.pop
- }
- compstmt kEND
- {
- result = @builder.for(val[0], val[1],
- val[2], val[4],
- val[5], val[7], val[8])
- }
- | kCLASS cpath superclass
- {
- @static_env.extend_static
- }
- bodystmt kEND
- {
- if in_def?
- diagnostic :error, :class_in_def, nil, val[0]
- end
-
- lt_t, superclass = val[2]
- result = @builder.def_class(val[0], val[1],
- lt_t, superclass,
- val[4], val[5])
-
- @static_env.unextend
- }
- | kCLASS tLSHFT expr term
- {
- result = @def_level
- @def_level = 0
-
- @static_env.extend_static
- }
- bodystmt kEND
- {
- result = @builder.def_sclass(val[0], val[1], val[2],
- val[5], val[6])
-
- @static_env.unextend
-
- @def_level = val[4]
- }
- | kMODULE cpath
- {
- @static_env.extend_static
- }
- bodystmt kEND
- {
- if in_def?
- diagnostic :error, :module_in_def, nil, val[0]
- end
-
- result = @builder.def_module(val[0], val[1],
- val[3], val[4])
-
- @static_env.unextend
- }
- | kDEF fname
- {
- @def_level += 1
- @static_env.extend_static
- }
- f_arglist bodystmt kEND
- {
- result = @builder.def_method(val[0], val[1],
- val[3], val[4], val[5])
-
- @static_env.unextend
- @def_level -= 1
- }
- | kDEF singleton dot_or_colon
- {
- @lexer.state = :expr_fname
- }
- fname
- {
- @def_level += 1
- @static_env.extend_static
- }
- f_arglist bodystmt kEND
- {
- result = @builder.def_singleton(val[0], val[1], val[2],
- val[4], val[6], val[7], val[8])
-
- @static_env.unextend
- @def_level -= 1
- }
- | kBREAK
- {
- result = @builder.keyword_cmd(:break, val[0])
- }
- | kNEXT
- {
- result = @builder.keyword_cmd(:next, val[0])
- }
- | kREDO
- {
- result = @builder.keyword_cmd(:redo, val[0])
- }
- | kRETRY
- {
- result = @builder.keyword_cmd(:retry, val[0])
- }
-
- primary_value: primary
-
- then: term
- | tCOLON
- | kTHEN
- | term kTHEN
- {
- result = val[1]
- }
-
- do: term
- | tCOLON
- | kDO_COND
-
- if_tail: opt_else
- | kELSIF expr_value then compstmt if_tail
- {
- else_t, else_ = val[4]
- result = [ val[0],
- @builder.condition(val[0], val[1], val[2],
- val[3], else_t,
- else_, nil),
- ]
- }
-
- opt_else: none
- | kELSE compstmt
- {
- result = val
- }
-
- for_var: lhs
- | mlhs
-
- block_par: mlhs_item
- {
- result = [ @builder.arg_expr(val[0]) ]
- }
- | block_par tCOMMA mlhs_item
- {
- result = val[0] << @builder.arg_expr(val[2])
- }
-
- block_var: block_par
- | block_par tCOMMA
- | block_par tCOMMA tAMPER lhs
- {
- result = val[0].
- push(@builder.blockarg_expr(val[2], val[3]))
- }
- | block_par tCOMMA tSTAR lhs tCOMMA tAMPER lhs
- {
- result = val[0].
- push(@builder.restarg_expr(val[2], val[3])).
- push(@builder.blockarg_expr(val[5], val[6]))
- }
- | block_par tCOMMA tSTAR tCOMMA tAMPER lhs
- {
- result = val[0].
- push(@builder.restarg_expr(val[2])).
- push(@builder.blockarg_expr(val[4], val[5]))
- }
- | block_par tCOMMA tSTAR lhs
- {
- result = val[0].
- push(@builder.restarg_expr(val[2], val[3]))
- }
- | block_par tCOMMA tSTAR
- {
- result = val[0].
- push(@builder.restarg_expr(val[2]))
- }
- | tSTAR lhs tCOMMA tAMPER lhs
- {
- result = [ @builder.restarg_expr(val[0], val[1]),
- @builder.blockarg_expr(val[3], val[4]) ]
- }
- | tSTAR tCOMMA tAMPER lhs
- {
- result = [ @builder.restarg_expr(val[0]),
- @builder.blockarg_expr(val[2], val[3]) ]
- }
- | tSTAR lhs
- {
- result = [ @builder.restarg_expr(val[0], val[1]) ]
- }
- | tSTAR
- {
- result = [ @builder.restarg_expr(val[0]) ]
- }
- | tAMPER lhs
- {
- result = [ @builder.blockarg_expr(val[0], val[1]) ]
- }
- ;
-
- opt_block_var: # nothing
- {
- result = @builder.args(nil, [], nil)
- }
- | tPIPE tPIPE
- {
- result = @builder.args(val[0], [], val[1])
- }
- | tOROP
- {
- result = @builder.args(val[0], [], val[0])
- }
- | tPIPE block_var tPIPE
- {
- result = @builder.args(val[0], val[1], val[2], false)
- }
-
- do_block: kDO_BLOCK
- {
- @static_env.extend_dynamic
- }
- opt_block_var compstmt kEND
- {
- result = [ val[0], val[2], val[3], val[4] ]
-
- @static_env.unextend
- }
-
- block_call: command do_block
- {
- begin_t, block_args, body, end_t = val[1]
- result = @builder.block(val[0],
- begin_t, block_args, body, end_t)
- }
- | block_call tDOT operation2 opt_paren_args
- {
- lparen_t, args, rparen_t = val[3]
- result = @builder.call_method(val[0], val[1], val[2],
- lparen_t, args, rparen_t)
- }
- | block_call tCOLON2 operation2 opt_paren_args
- {
- lparen_t, args, rparen_t = val[3]
- result = @builder.call_method(val[0], val[1], val[2],
- lparen_t, args, rparen_t)
- }
-
- method_call: operation paren_args
- {
- lparen_t, args, rparen_t = val[1]
- result = @builder.call_method(nil, nil, val[0],
- lparen_t, args, rparen_t)
- }
- | primary_value tDOT operation2 opt_paren_args
- {
- lparen_t, args, rparen_t = val[3]
- result = @builder.call_method(val[0], val[1], val[2],
- lparen_t, args, rparen_t)
- }
- | primary_value tCOLON2 operation2 paren_args
- {
- lparen_t, args, rparen_t = val[3]
- result = @builder.call_method(val[0], val[1], val[2],
- lparen_t, args, rparen_t)
- }
- | primary_value tCOLON2 operation3
- {
- result = @builder.call_method(val[0], val[1], val[2])
- }
- | kSUPER paren_args
- {
- lparen_t, args, rparen_t = val[1]
- result = @builder.keyword_cmd(:super, val[0],
- lparen_t, args, rparen_t)
- }
- | kSUPER
- {
- result = @builder.keyword_cmd(:zsuper, val[0])
- }
-
- brace_block: tLCURLY
- {
- @static_env.extend_dynamic
- }
- opt_block_var compstmt tRCURLY
- {
- result = [ val[0], val[2], val[3], val[4] ]
-
- @static_env.unextend
- }
- | kDO
- {
- @static_env.extend_dynamic
- }
- opt_block_var compstmt kEND
- {
- result = [ val[0], val[2], val[3], val[4] ]
-
- @static_env.unextend
- }
-
- case_body: kWHEN when_args then compstmt cases
- {
- result = [ @builder.when(val[0], val[1], val[2], val[3]),
- *val[4] ]
- }
-
- when_args: args
- | args tCOMMA tSTAR arg_value
- {
- result = val[0] << @builder.splat(val[2], val[3])
- }
- | tSTAR arg_value
- {
- result = [ @builder.splat(val[0], val[1]) ]
- }
-
- cases: opt_else
- {
- result = [ val[0] ]
- }
- | case_body
-
- opt_rescue: kRESCUE exc_list exc_var then compstmt opt_rescue
- {
- assoc_t, exc_var = val[2]
-
- if val[1]
- exc_list = @builder.array(nil, val[1], nil)
- end
-
- result = [ @builder.rescue_body(val[0],
- exc_list, assoc_t, exc_var,
- val[3], val[4]),
- *val[5] ]
- }
- | # nothing
- {
- result = []
- }
-
- exc_list: arg_value
- {
- result = [ val[0] ]
- }
- | mrhs
- | none
-
- exc_var: tASSOC lhs
- {
- result = [ val[0], val[1] ]
- }
- | none
-
- opt_ensure: kENSURE compstmt
- {
- result = [ val[0], val[1] ]
- }
- | none
-
- literal: numeric
- | symbol
- | dsym
-
- strings: string
- {
- result = @builder.string_compose(nil, val[0], nil)
- }
-
- string: string1
- {
- result = [ val[0] ]
- }
- | string string1
- {
- result = val[0] << val[1]
- }
-
- string1: tSTRING_BEG string_contents tSTRING_END
- {
- result = @builder.string_compose(val[0], val[1], val[2])
- }
- | tSTRING
- {
- result = @builder.string(val[0])
- }
-
- xstring: tXSTRING_BEG xstring_contents tSTRING_END
- {
- result = @builder.xstring_compose(val[0], val[1], val[2])
- }
-
- regexp: tREGEXP_BEG xstring_contents tSTRING_END tREGEXP_OPT
- {
- opts = @builder.regexp_options(val[3])
- result = @builder.regexp_compose(val[0], val[1], val[2], opts)
- }
-
- words: tWORDS_BEG word_list tSTRING_END
- {
- result = @builder.words_compose(val[0], val[1], val[2])
- }
-
- word_list: # nothing
- {
- result = []
- }
- | word_list word tSPACE
- {
- result = val[0] << @builder.word(val[1])
- }
-
- word: string_content
- {
- result = [ val[0] ]
- }
- | word string_content
- {
- result = val[0] << val[1]
- }
-
- qwords: tQWORDS_BEG qword_list tSTRING_END
- {
- result = @builder.words_compose(val[0], val[1], val[2])
- }
-
- qword_list: # nothing
- {
- result = []
- }
- | qword_list tSTRING_CONTENT tSPACE
- {
- result = val[0] << @builder.string_internal(val[1])
- }
-
- string_contents: # nothing
- {
- result = []
- }
- | string_contents string_content
- {
- result = val[0] << val[1]
- }
-
-xstring_contents: # nothing
- {
- result = []
- }
- | xstring_contents string_content
- {
- result = val[0] << val[1]
- }
-
- string_content: tSTRING_CONTENT
- {
- result = @builder.string_internal(val[0])
- }
- | tSTRING_DVAR string_dvar
- {
- result = val[1]
- }
- | tSTRING_DBEG
- {
- @lexer.cond.push(false)
- @lexer.cmdarg.push(false)
- }
- compstmt tRCURLY
- {
- @lexer.cond.lexpop
- @lexer.cmdarg.lexpop
-
- result = @builder.begin(val[0], val[2], val[3])
- }
-
- string_dvar: tGVAR
- {
- result = @builder.gvar(val[0])
- }
- | tIVAR
- {
- result = @builder.ivar(val[0])
- }
- | tCVAR
- {
- result = @builder.cvar(val[0])
- }
- | backref
-
-
- symbol: tSYMBOL
- {
- result = @builder.symbol(val[0])
- }
-
- dsym: tSYMBEG xstring_contents tSTRING_END
- {
- result = @builder.symbol_compose(val[0], val[1], val[2])
- }
-
- numeric: tINTEGER
- {
- result = @builder.integer(val[0])
- }
- | tFLOAT
- {
- result = @builder.float(val[0])
- }
- | tUMINUS_NUM tINTEGER =tLOWEST
- {
- result = @builder.negate(val[0],
- @builder.integer(val[1]))
- }
- | tUMINUS_NUM tFLOAT =tLOWEST
- {
- result = @builder.negate(val[0],
- @builder.float(val[1]))
- }
-
- variable: tIDENTIFIER
- {
- result = @builder.ident(val[0])
- }
- | tIVAR
- {
- result = @builder.ivar(val[0])
- }
- | tGVAR
- {
- result = @builder.gvar(val[0])
- }
- | tCVAR
- {
- result = @builder.cvar(val[0])
- }
- | tCONSTANT
- {
- result = @builder.const(val[0])
- }
- | kNIL
- {
- result = @builder.nil(val[0])
- }
- | kSELF
- {
- result = @builder.self(val[0])
- }
- | kTRUE
- {
- result = @builder.true(val[0])
- }
- | kFALSE
- {
- result = @builder.false(val[0])
- }
- | k__FILE__
- {
- result = @builder.__FILE__(val[0])
- }
- | k__LINE__
- {
- result = @builder.__LINE__(val[0])
- }
-
- var_ref: variable
- {
- result = @builder.accessible(val[0])
- }
-
- var_lhs: variable
- {
- result = @builder.assignable(val[0])
- }
-
- backref: tNTH_REF
- {
- result = @builder.nth_ref(val[0])
- }
- | tBACK_REF
- {
- result = @builder.back_ref(val[0])
- }
-
- superclass: term
- {
- result = nil
- }
- | tLT expr_value term
- {
- result = [ val[0], val[1] ]
- }
- | error term
- {
- yyerrok
- result = nil
- }
-
- f_arglist: tLPAREN2 f_args opt_nl tRPAREN
- {
- result = @builder.args(val[0], val[1], val[3])
-
- @lexer.state = :expr_beg
- }
- | f_args term
- {
- result = @builder.args(nil, val[0], nil)
- }
-
- f_args: f_arg tCOMMA f_optarg tCOMMA f_rest_arg opt_f_block_arg
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
- }
- | f_arg tCOMMA f_optarg opt_f_block_arg
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | f_arg tCOMMA f_rest_arg opt_f_block_arg
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | f_arg opt_f_block_arg
- {
- result = val[0].
- concat(val[1])
- }
- | f_optarg tCOMMA f_rest_arg opt_f_block_arg
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | f_optarg opt_f_block_arg
- {
- result = val[0].
- concat(val[1])
- }
- | f_rest_arg opt_f_block_arg
- {
- result = val[0].
- concat(val[1])
- }
- | f_block_arg
- {
- result = [ val[0] ]
- }
- | # nothing
- {
- result = []
- }
-
- f_norm_arg: tCONSTANT
- {
- diagnostic :error, :argument_const, nil, val[0]
- }
- | tIVAR
- {
- diagnostic :error, :argument_ivar, nil, val[0]
- }
- | tGVAR
- {
- diagnostic :error, :argument_gvar, nil, val[0]
- }
- | tCVAR
- {
- diagnostic :error, :argument_cvar, nil, val[0]
- }
- | tIDENTIFIER
- {
- @static_env.declare val[0][0]
-
- result = @builder.arg(val[0])
- }
-
- f_arg: f_norm_arg
- {
- result = [ val[0] ]
- }
- | f_arg tCOMMA f_norm_arg
- {
- result = val[0] << val[2]
- }
-
- f_opt: tIDENTIFIER tEQL arg_value
- {
- @static_env.declare val[0][0]
-
- result = @builder.optarg(val[0], val[1], val[2])
- }
-
- f_optarg: f_opt
- {
- result = [ val[0] ]
- }
- | f_optarg tCOMMA f_opt
- {
- result = val[0] << val[2]
- }
-
- restarg_mark: tSTAR2 | tSTAR
-
- f_rest_arg: restarg_mark tIDENTIFIER
- {
- @static_env.declare val[1][0]
-
- result = [ @builder.restarg(val[0], val[1]) ]
- }
- | restarg_mark
- {
- result = [ @builder.restarg(val[0]) ]
- }
-
- blkarg_mark: tAMPER2 | tAMPER
-
- f_block_arg: blkarg_mark tIDENTIFIER
- {
- @static_env.declare val[1][0]
-
- result = @builder.blockarg(val[0], val[1])
- }
-
- opt_f_block_arg: tCOMMA f_block_arg
- {
- result = [ val[1] ]
- }
- | # nothing
- {
- result = []
- }
-
- singleton: var_ref
- | tLPAREN2 expr opt_nl tRPAREN
- {
- result = val[1]
- }
-
- assoc_list: # nothing
- {
- result = []
- }
- | assocs trailer
- {
- result = val[0]
- }
- | args trailer
- {
- result = @builder.pair_list_18(val[0])
- }
-
- assocs: assoc
- {
- result = [ val[0] ]
- }
- | assocs tCOMMA assoc
- {
- result = val[0] << val[2]
- }
-
- assoc: arg_value tASSOC arg_value
- {
- result = @builder.pair(val[0], val[1], val[2])
- }
-
- operation: tIDENTIFIER | tCONSTANT | tFID
- operation2: tIDENTIFIER | tCONSTANT | tFID | op
- operation3: tIDENTIFIER | tFID | op
- dot_or_colon: tDOT | tCOLON2
- opt_terms: | terms
- opt_nl: | tNL
- trailer: | tNL | tCOMMA
-
- term: tSEMI
- {
- yyerrok
- }
- | tNL
-
- terms: term
- | terms tSEMI
-
- none: # nothing
- {
- result = nil
- }
-
-end
-
----- header
-
-require 'parser'
-
----- inner
-
- def version
- 18
- end
-
- def default_encoding
- Encoding::BINARY if defined? Encoding
- end
diff --git a/test/racc/assets/ruby19.y b/test/racc/assets/ruby19.y
deleted file mode 100644
index b405c952e7..0000000000
--- a/test/racc/assets/ruby19.y
+++ /dev/null
@@ -1,2174 +0,0 @@
-# Copyright (c) 2013 Peter Zotov <whitequark@whitequark.org>
-#
-# Parts of the source are derived from ruby_parser:
-# Copyright (c) Ryan Davis, seattle.rb
-#
-# MIT License
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-class Parser::Ruby19
-
-token kCLASS kMODULE kDEF kUNDEF kBEGIN kRESCUE kENSURE kEND kIF kUNLESS
- kTHEN kELSIF kELSE kCASE kWHEN kWHILE kUNTIL kFOR kBREAK kNEXT
- kREDO kRETRY kIN kDO kDO_COND kDO_BLOCK kDO_LAMBDA kRETURN kYIELD kSUPER
- kSELF kNIL kTRUE kFALSE kAND kOR kNOT kIF_MOD kUNLESS_MOD kWHILE_MOD
- kUNTIL_MOD kRESCUE_MOD kALIAS kDEFINED klBEGIN klEND k__LINE__
- k__FILE__ k__ENCODING__ tIDENTIFIER tFID tGVAR tIVAR tCONSTANT
- tLABEL tCVAR tNTH_REF tBACK_REF tSTRING_CONTENT tINTEGER tFLOAT
- tREGEXP_END tUPLUS tUMINUS tUMINUS_NUM tPOW tCMP tEQ tEQQ tNEQ
- tGEQ tLEQ tANDOP tOROP tMATCH tNMATCH tDOT tDOT2 tDOT3 tAREF
- tASET tLSHFT tRSHFT tCOLON2 tCOLON3 tOP_ASGN tASSOC tLPAREN
- tLPAREN2 tRPAREN tLPAREN_ARG tLBRACK tLBRACK2 tRBRACK tLBRACE
- tLBRACE_ARG tSTAR tSTAR2 tAMPER tAMPER2 tTILDE tPERCENT tDIVIDE
- tPLUS tMINUS tLT tGT tPIPE tBANG tCARET tLCURLY tRCURLY
- tBACK_REF2 tSYMBEG tSTRING_BEG tXSTRING_BEG tREGEXP_BEG tREGEXP_OPT
- tWORDS_BEG tQWORDS_BEG tSTRING_DBEG tSTRING_DVAR tSTRING_END
- tSTRING tSYMBOL tNL tEH tCOLON tCOMMA tSPACE tSEMI tLAMBDA tLAMBEG
- tCHARACTER
-
-prechigh
- right tBANG tTILDE tUPLUS
- right tPOW
- right tUMINUS_NUM tUMINUS
- left tSTAR2 tDIVIDE tPERCENT
- left tPLUS tMINUS
- left tLSHFT tRSHFT
- left tAMPER2
- left tPIPE tCARET
- left tGT tGEQ tLT tLEQ
- nonassoc tCMP tEQ tEQQ tNEQ tMATCH tNMATCH
- left tANDOP
- left tOROP
- nonassoc tDOT2 tDOT3
- right tEH tCOLON
- left kRESCUE_MOD
- right tEQL tOP_ASGN
- nonassoc kDEFINED
- right kNOT
- left kOR kAND
- nonassoc kIF_MOD kUNLESS_MOD kWHILE_MOD kUNTIL_MOD
- nonassoc tLBRACE_ARG
- nonassoc tLOWEST
-preclow
-
-rule
-
- program: top_compstmt
-
- top_compstmt: top_stmts opt_terms
- {
- result = @builder.compstmt(val[0])
- }
-
- top_stmts: # nothing
- {
- result = []
- }
- | top_stmt
- {
- result = [ val[0] ]
- }
- | top_stmts terms top_stmt
- {
- result = val[0] << val[2]
- }
- | error top_stmt
- {
- result = [ val[1] ]
- }
-
- top_stmt: stmt
- | klBEGIN tLCURLY top_compstmt tRCURLY
- {
- result = @builder.preexe(val[0], val[1], val[2], val[3])
- }
-
- bodystmt: compstmt opt_rescue opt_else opt_ensure
- {
- rescue_bodies = val[1]
- else_t, else_ = val[2]
- ensure_t, ensure_ = val[3]
-
- if rescue_bodies.empty? && !else_.nil?
- diagnostic :warning, :useless_else, nil, else_t
- end
-
- result = @builder.begin_body(val[0],
- rescue_bodies,
- else_t, else_,
- ensure_t, ensure_)
- }
-
- compstmt: stmts opt_terms
- {
- result = @builder.compstmt(val[0])
- }
-
- stmts: # nothing
- {
- result = []
- }
- | stmt
- {
- result = [ val[0] ]
- }
- | stmts terms stmt
- {
- result = val[0] << val[2]
- }
- | error stmt
- {
- result = [ val[1] ]
- }
-
- stmt: kALIAS fitem
- {
- @lexer.state = :expr_fname
- }
- fitem
- {
- result = @builder.alias(val[0], val[1], val[3])
- }
- | kALIAS tGVAR tGVAR
- {
- result = @builder.alias(val[0],
- @builder.gvar(val[1]),
- @builder.gvar(val[2]))
- }
- | kALIAS tGVAR tBACK_REF
- {
- result = @builder.alias(val[0],
- @builder.gvar(val[1]),
- @builder.back_ref(val[2]))
- }
- | kALIAS tGVAR tNTH_REF
- {
- diagnostic :error, :nth_ref_alias, nil, val[2]
- }
- | kUNDEF undef_list
- {
- result = @builder.undef_method(val[0], val[1])
- }
- | stmt kIF_MOD expr_value
- {
- result = @builder.condition_mod(val[0], nil,
- val[1], val[2])
- }
- | stmt kUNLESS_MOD expr_value
- {
- result = @builder.condition_mod(nil, val[0],
- val[1], val[2])
- }
- | stmt kWHILE_MOD expr_value
- {
- result = @builder.loop_mod(:while, val[0], val[1], val[2])
- }
- | stmt kUNTIL_MOD expr_value
- {
- result = @builder.loop_mod(:until, val[0], val[1], val[2])
- }
- | stmt kRESCUE_MOD stmt
- {
- rescue_body = @builder.rescue_body(val[1],
- nil, nil, nil,
- nil, val[2])
-
- result = @builder.begin_body(val[0], [ rescue_body ])
- }
- | klEND tLCURLY compstmt tRCURLY
- {
- result = @builder.postexe(val[0], val[1], val[2], val[3])
- }
- | command_asgn
- | mlhs tEQL command_call
- {
- result = @builder.multi_assign(val[0], val[1], val[2])
- }
- | var_lhs tOP_ASGN command_call
- {
- result = @builder.op_assign(val[0], val[1], val[2])
- }
- | primary_value tLBRACK2 opt_call_args rbracket tOP_ASGN command_call
- {
- result = @builder.op_assign(
- @builder.index(
- val[0], val[1], val[2], val[3]),
- val[4], val[5])
- }
- | primary_value tDOT tIDENTIFIER tOP_ASGN command_call
- {
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
- }
- | primary_value tDOT tCONSTANT tOP_ASGN command_call
- {
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
- }
- | primary_value tCOLON2 tCONSTANT tOP_ASGN command_call
- {
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
- }
- | primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_call
- {
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
- }
- | backref tOP_ASGN command_call
- {
- @builder.op_assign(val[0], val[1], val[2])
- }
- | lhs tEQL mrhs
- {
- result = @builder.assign(val[0], val[1],
- @builder.array(nil, val[2], nil))
- }
- | mlhs tEQL arg_value
- {
- result = @builder.multi_assign(val[0], val[1], val[2])
- }
- | mlhs tEQL mrhs
- {
- result = @builder.multi_assign(val[0], val[1],
- @builder.array(nil, val[2], nil))
- }
- | expr
-
- command_asgn: lhs tEQL command_call
- {
- result = @builder.assign(val[0], val[1], val[2])
- }
- | lhs tEQL command_asgn
- {
- result = @builder.assign(val[0], val[1], val[2])
- }
-
- expr: command_call
- | expr kAND expr
- {
- result = @builder.logical_op(:and, val[0], val[1], val[2])
- }
- | expr kOR expr
- {
- result = @builder.logical_op(:or, val[0], val[1], val[2])
- }
- | kNOT opt_nl expr
- {
- result = @builder.not_op(val[0], nil, val[2], nil)
- }
- | tBANG command_call
- {
- result = @builder.not_op(val[0], nil, val[1], nil)
- }
- | arg
-
- expr_value: expr
-
- command_call: command
- | block_command
-
- block_command: block_call
- | block_call tDOT operation2 command_args
- {
- result = @builder.call_method(val[0], val[1], val[2],
- nil, val[3], nil)
- }
- | block_call tCOLON2 operation2 command_args
- {
- result = @builder.call_method(val[0], val[1], val[2],
- nil, val[3], nil)
- }
-
- cmd_brace_block: tLBRACE_ARG
- {
- @static_env.extend_dynamic
- }
- opt_block_param compstmt tRCURLY
- {
- result = [ val[0], val[2], val[3], val[4] ]
-
- @static_env.unextend
- }
-
- command: operation command_args =tLOWEST
- {
- result = @builder.call_method(nil, nil, val[0],
- nil, val[1], nil)
- }
- | operation command_args cmd_brace_block
- {
- method_call = @builder.call_method(nil, nil, val[0],
- nil, val[1], nil)
-
- begin_t, args, body, end_t = val[2]
- result = @builder.block(method_call,
- begin_t, args, body, end_t)
- }
- | primary_value tDOT operation2 command_args =tLOWEST
- {
- result = @builder.call_method(val[0], val[1], val[2],
- nil, val[3], nil)
- }
- | primary_value tDOT operation2 command_args cmd_brace_block
- {
- method_call = @builder.call_method(val[0], val[1], val[2],
- nil, val[3], nil)
-
- begin_t, args, body, end_t = val[4]
- result = @builder.block(method_call,
- begin_t, args, body, end_t)
- }
- | primary_value tCOLON2 operation2 command_args =tLOWEST
- {
- result = @builder.call_method(val[0], val[1], val[2],
- nil, val[3], nil)
- }
- | primary_value tCOLON2 operation2 command_args cmd_brace_block
- {
- method_call = @builder.call_method(val[0], val[1], val[2],
- nil, val[3], nil)
-
- begin_t, args, body, end_t = val[4]
- result = @builder.block(method_call,
- begin_t, args, body, end_t)
- }
- | kSUPER command_args
- {
- result = @builder.keyword_cmd(:super, val[0],
- nil, val[1], nil)
- }
- | kYIELD command_args
- {
- result = @builder.keyword_cmd(:yield, val[0],
- nil, val[1], nil)
- }
- | kRETURN call_args
- {
- result = @builder.keyword_cmd(:return, val[0],
- nil, val[1], nil)
- }
- | kBREAK call_args
- {
- result = @builder.keyword_cmd(:break, val[0],
- nil, val[1], nil)
- }
- | kNEXT call_args
- {
- result = @builder.keyword_cmd(:next, val[0],
- nil, val[1], nil)
- }
-
- mlhs: mlhs_basic
- {
- result = @builder.multi_lhs(nil, val[0], nil)
- }
- | tLPAREN mlhs_inner rparen
- {
- result = @builder.begin(val[0], val[1], val[2])
- }
-
- mlhs_inner: mlhs_basic
- {
- result = @builder.multi_lhs(nil, val[0], nil)
- }
- | tLPAREN mlhs_inner rparen
- {
- result = @builder.multi_lhs(val[0], val[1], val[2])
- }
-
- mlhs_basic: mlhs_head
- | mlhs_head mlhs_item
- {
- result = val[0].
- push(val[1])
- }
- | mlhs_head tSTAR mlhs_node
- {
- result = val[0].
- push(@builder.splat(val[1], val[2]))
- }
- | mlhs_head tSTAR mlhs_node tCOMMA mlhs_post
- {
- result = val[0].
- push(@builder.splat(val[1], val[2])).
- concat(val[4])
- }
- | mlhs_head tSTAR
- {
- result = val[0].
- push(@builder.splat(val[1]))
- }
- | mlhs_head tSTAR tCOMMA mlhs_post
- {
- result = val[0].
- push(@builder.splat(val[1])).
- concat(val[3])
- }
- | tSTAR mlhs_node
- {
- result = [ @builder.splat(val[0], val[1]) ]
- }
- | tSTAR mlhs_node tCOMMA mlhs_post
- {
- result = [ @builder.splat(val[0], val[1]),
- *val[3] ]
- }
- | tSTAR
- {
- result = [ @builder.splat(val[0]) ]
- }
- | tSTAR tCOMMA mlhs_post
- {
- result = [ @builder.splat(val[0]),
- *val[2] ]
- }
-
- mlhs_item: mlhs_node
- | tLPAREN mlhs_inner rparen
- {
- result = @builder.begin(val[0], val[1], val[2])
- }
-
- mlhs_head: mlhs_item tCOMMA
- {
- result = [ val[0] ]
- }
- | mlhs_head mlhs_item tCOMMA
- {
- result = val[0] << val[1]
- }
-
- mlhs_post: mlhs_item
- {
- result = [ val[0] ]
- }
- | mlhs_post tCOMMA mlhs_item
- {
- result = val[0] << val[2]
- }
-
- mlhs_node: user_variable
- {
- result = @builder.assignable(val[0])
- }
- | keyword_variable
- {
- result = @builder.assignable(val[0])
- }
- | primary_value tLBRACK2 opt_call_args rbracket
- {
- result = @builder.index_asgn(val[0], val[1], val[2], val[3])
- }
- | primary_value tDOT tIDENTIFIER
- {
- result = @builder.attr_asgn(val[0], val[1], val[2])
- }
- | primary_value tCOLON2 tIDENTIFIER
- {
- result = @builder.attr_asgn(val[0], val[1], val[2])
- }
- | primary_value tDOT tCONSTANT
- {
- result = @builder.attr_asgn(val[0], val[1], val[2])
- }
- | primary_value tCOLON2 tCONSTANT
- {
- result = @builder.assignable(
- @builder.const_fetch(val[0], val[1], val[2]))
- }
- | tCOLON3 tCONSTANT
- {
- result = @builder.assignable(
- @builder.const_global(val[0], val[1]))
- }
- | backref
- {
- result = @builder.assignable(val[0])
- }
-
- lhs: user_variable
- {
- result = @builder.assignable(val[0])
- }
- | keyword_variable
- {
- result = @builder.assignable(val[0])
- }
- | primary_value tLBRACK2 opt_call_args rbracket
- {
- result = @builder.index_asgn(val[0], val[1], val[2], val[3])
- }
- | primary_value tDOT tIDENTIFIER
- {
- result = @builder.attr_asgn(val[0], val[1], val[2])
- }
- | primary_value tCOLON2 tIDENTIFIER
- {
- result = @builder.attr_asgn(val[0], val[1], val[2])
- }
- | primary_value tDOT tCONSTANT
- {
- result = @builder.attr_asgn(val[0], val[1], val[2])
- }
- | primary_value tCOLON2 tCONSTANT
- {
- result = @builder.assignable(
- @builder.const_fetch(val[0], val[1], val[2]))
- }
- | tCOLON3 tCONSTANT
- {
- result = @builder.assignable(
- @builder.const_global(val[0], val[1]))
- }
- | backref
- {
- result = @builder.assignable(val[0])
- }
-
- cname: tIDENTIFIER
- {
- diagnostic :error, :module_name_const, nil, val[0]
- }
- | tCONSTANT
-
- cpath: tCOLON3 cname
- {
- result = @builder.const_global(val[0], val[1])
- }
- | cname
- {
- result = @builder.const(val[0])
- }
- | primary_value tCOLON2 cname
- {
- result = @builder.const_fetch(val[0], val[1], val[2])
- }
-
- fname: tIDENTIFIER | tCONSTANT | tFID
- | op
- | reswords
-
- fsym: fname
- {
- result = @builder.symbol(val[0])
- }
- | symbol
-
- fitem: fsym
- | dsym
-
- undef_list: fitem
- {
- result = [ val[0] ]
- }
- | undef_list tCOMMA
- {
- @lexer.state = :expr_fname
- }
- fitem
- {
- result = val[0] << val[3]
- }
-
- op: tPIPE | tCARET | tAMPER2 | tCMP | tEQ | tEQQ
- | tMATCH | tNMATCH | tGT | tGEQ | tLT | tLEQ
- | tNEQ | tLSHFT | tRSHFT | tPLUS | tMINUS | tSTAR2
- | tSTAR | tDIVIDE | tPERCENT | tPOW | tBANG | tTILDE
- | tUPLUS | tUMINUS | tAREF | tASET | tBACK_REF2
-
- reswords: k__LINE__ | k__FILE__ | k__ENCODING__ | klBEGIN | klEND
- | kALIAS | kAND | kBEGIN | kBREAK | kCASE
- | kCLASS | kDEF | kDEFINED | kDO | kELSE
- | kELSIF | kEND | kENSURE | kFALSE | kFOR
- | kIN | kMODULE | kNEXT | kNIL | kNOT
- | kOR | kREDO | kRESCUE | kRETRY | kRETURN
- | kSELF | kSUPER | kTHEN | kTRUE | kUNDEF
- | kWHEN | kYIELD | kIF | kUNLESS | kWHILE
- | kUNTIL
-
- arg: lhs tEQL arg
- {
- result = @builder.assign(val[0], val[1], val[2])
- }
- | lhs tEQL arg kRESCUE_MOD arg
- {
- rescue_body = @builder.rescue_body(val[3],
- nil, nil, nil,
- nil, val[4])
-
- rescue_ = @builder.begin_body(val[2], [ rescue_body ])
-
- result = @builder.assign(val[0], val[1], rescue_)
- }
- | var_lhs tOP_ASGN arg
- {
- result = @builder.op_assign(val[0], val[1], val[2])
- }
- | var_lhs tOP_ASGN arg kRESCUE_MOD arg
- {
- rescue_body = @builder.rescue_body(val[3],
- nil, nil, nil,
- nil, val[4])
-
- rescue_ = @builder.begin_body(val[2], [ rescue_body ])
-
- result = @builder.op_assign(val[0], val[1], rescue_)
- }
- | primary_value tLBRACK2 opt_call_args rbracket tOP_ASGN arg
- {
- result = @builder.op_assign(
- @builder.index(
- val[0], val[1], val[2], val[3]),
- val[4], val[5])
- }
- | primary_value tDOT tIDENTIFIER tOP_ASGN arg
- {
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
- }
- | primary_value tDOT tCONSTANT tOP_ASGN arg
- {
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
- }
- | primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg
- {
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
- }
- | primary_value tCOLON2 tCONSTANT tOP_ASGN arg
- {
- diagnostic :error, :dynamic_const, nil, val[2], [ val[3] ]
- }
- | tCOLON3 tCONSTANT tOP_ASGN arg
- {
- diagnostic :error, :dynamic_const, nil, val[1], [ val[2] ]
- }
- | backref tOP_ASGN arg
- {
- result = @builder.op_assign(val[0], val[1], val[2])
- }
- | arg tDOT2 arg
- {
- result = @builder.range_inclusive(val[0], val[1], val[2])
- }
- | arg tDOT3 arg
- {
- result = @builder.range_exclusive(val[0], val[1], val[2])
- }
- | arg tPLUS arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tMINUS arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tSTAR2 arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tDIVIDE arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tPERCENT arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tPOW arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | tUMINUS_NUM tINTEGER tPOW arg
- {
- result = @builder.unary_op(val[0],
- @builder.binary_op(
- @builder.integer(val[1]),
- val[2], val[3]))
- }
- | tUMINUS_NUM tFLOAT tPOW arg
- {
- result = @builder.unary_op(val[0],
- @builder.binary_op(
- @builder.float(val[1]),
- val[2], val[3]))
- }
- | tUPLUS arg
- {
- result = @builder.unary_op(val[0], val[1])
- }
- | tUMINUS arg
- {
- result = @builder.unary_op(val[0], val[1])
- }
- | arg tPIPE arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tCARET arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tAMPER2 arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tCMP arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tGT arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tGEQ arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tLT arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tLEQ arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tEQ arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tEQQ arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tNEQ arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tMATCH arg
- {
- result = @builder.match_op(val[0], val[1], val[2])
- }
- | arg tNMATCH arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | tBANG arg
- {
- result = @builder.not_op(val[0], nil, val[1], nil)
- }
- | tTILDE arg
- {
- result = @builder.unary_op(val[0], val[1])
- }
- | arg tLSHFT arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tRSHFT arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tANDOP arg
- {
- result = @builder.logical_op(:and, val[0], val[1], val[2])
- }
- | arg tOROP arg
- {
- result = @builder.logical_op(:or, val[0], val[1], val[2])
- }
- | kDEFINED opt_nl arg
- {
- result = @builder.keyword_cmd(:defined?, val[0], nil, [ val[2] ], nil)
- }
-
- | arg tEH arg opt_nl tCOLON arg
- {
- result = @builder.ternary(val[0], val[1],
- val[2], val[4], val[5])
- }
- | primary
-
- arg_value: arg
-
- aref_args: none
- | args trailer
- | args tCOMMA assocs trailer
- {
- result = val[0] << @builder.associate(nil, val[2], nil)
- }
- | assocs trailer
- {
- result = [ @builder.associate(nil, val[0], nil) ]
- }
-
- paren_args: tLPAREN2 opt_call_args rparen
- {
- result = val
- }
-
- opt_paren_args: # nothing
- {
- result = [ nil, [], nil ]
- }
- | paren_args
-
- opt_call_args: # nothing
- {
- result = []
- }
- | call_args
- | args tCOMMA
- | args tCOMMA assocs tCOMMA
- {
- result = val[0] << @builder.associate(nil, val[2], nil)
- }
- | assocs tCOMMA
- {
- result = [ @builder.associate(nil, val[0], nil) ]
- }
-
- call_args: command
- {
- result = [ val[0] ]
- }
- | args opt_block_arg
- {
- result = val[0].concat(val[1])
- }
- | assocs opt_block_arg
- {
- result = [ @builder.associate(nil, val[0], nil) ]
- result.concat(val[1])
- }
- | args tCOMMA assocs opt_block_arg
- {
- assocs = @builder.associate(nil, val[2], nil)
- result = val[0] << assocs
- result.concat(val[3])
- }
- | block_arg
- {
- result = [ val[0] ]
- }
-
- command_args: {
- result = @lexer.cmdarg.dup
- @lexer.cmdarg.push(true)
- }
- call_args
- {
- @lexer.cmdarg = val[0]
-
- result = val[1]
- }
-
- block_arg: tAMPER arg_value
- {
- result = @builder.block_pass(val[0], val[1])
- }
-
- opt_block_arg: tCOMMA block_arg
- {
- result = [ val[1] ]
- }
- | # nothing
- {
- result = []
- }
-
- args: arg_value
- {
- result = [ val[0] ]
- }
- | tSTAR arg_value
- {
- result = [ @builder.splat(val[0], val[1]) ]
- }
- | args tCOMMA arg_value
- {
- result = val[0] << val[2]
- }
- | args tCOMMA tSTAR arg_value
- {
- result = val[0] << @builder.splat(val[2], val[3])
- }
-
- mrhs: args tCOMMA arg_value
- {
- result = val[0] << val[2]
- }
- | args tCOMMA tSTAR arg_value
- {
- result = val[0] << @builder.splat(val[2], val[3])
- }
- | tSTAR arg_value
- {
- result = [ @builder.splat(val[0], val[1]) ]
- }
-
- primary: literal
- | strings
- | xstring
- | regexp
- | words
- | qwords
- | var_ref
- | backref
- | tFID
- {
- result = @builder.call_method(nil, nil, val[0])
- }
- | kBEGIN bodystmt kEND
- {
- result = @builder.begin_keyword(val[0], val[1], val[2])
- }
- | tLPAREN_ARG
- {
- result = @lexer.cmdarg.dup
- @lexer.cmdarg.clear
- }
- expr
- {
- @lexer.state = :expr_endarg
- }
- opt_nl tRPAREN
- {
- @lexer.cmdarg = val[1]
-
- result = @builder.begin(val[0], val[2], val[5])
- }
- | tLPAREN compstmt tRPAREN
- {
- result = @builder.begin(val[0], val[1], val[2])
- }
- | primary_value tCOLON2 tCONSTANT
- {
- result = @builder.const_fetch(val[0], val[1], val[2])
- }
- | tCOLON3 tCONSTANT
- {
- result = @builder.const_global(val[0], val[1])
- }
- | tLBRACK aref_args tRBRACK
- {
- result = @builder.array(val[0], val[1], val[2])
- }
- | tLBRACE assoc_list tRCURLY
- {
- result = @builder.associate(val[0], val[1], val[2])
- }
- | kRETURN
- {
- result = @builder.keyword_cmd(:return, val[0])
- }
- | kYIELD tLPAREN2 call_args rparen
- {
- result = @builder.keyword_cmd(:yield, val[0], val[1], val[2], val[3])
- }
- | kYIELD tLPAREN2 rparen
- {
- result = @builder.keyword_cmd(:yield, val[0], val[1], [], val[2])
- }
- | kYIELD
- {
- result = @builder.keyword_cmd(:yield, val[0])
- }
- | kDEFINED opt_nl tLPAREN2 expr rparen
- {
- result = @builder.keyword_cmd(:defined?, val[0],
- val[2], [ val[3] ], val[4])
- }
- | kNOT tLPAREN2 expr rparen
- {
- result = @builder.not_op(val[0], val[1], val[2], val[3])
- }
- | kNOT tLPAREN2 rparen
- {
- result = @builder.not_op(val[0], val[1], nil, val[2])
- }
- | operation brace_block
- {
- method_call = @builder.call_method(nil, nil, val[0])
-
- begin_t, args, body, end_t = val[1]
- result = @builder.block(method_call,
- begin_t, args, body, end_t)
- }
- | method_call
- | method_call brace_block
- {
- begin_t, args, body, end_t = val[1]
- result = @builder.block(val[0],
- begin_t, args, body, end_t)
- }
- | tLAMBDA lambda
- {
- lambda_call = @builder.call_lambda(val[0])
-
- args, (begin_t, body, end_t) = val[1]
- result = @builder.block(lambda_call,
- begin_t, args, body, end_t)
- }
- | kIF expr_value then compstmt if_tail kEND
- {
- else_t, else_ = val[4]
- result = @builder.condition(val[0], val[1], val[2],
- val[3], else_t,
- else_, val[5])
- }
- | kUNLESS expr_value then compstmt opt_else kEND
- {
- else_t, else_ = val[4]
- result = @builder.condition(val[0], val[1], val[2],
- else_, else_t,
- val[3], val[5])
- }
- | kWHILE
- {
- @lexer.cond.push(true)
- }
- expr_value do
- {
- @lexer.cond.pop
- }
- compstmt kEND
- {
- result = @builder.loop(:while, val[0], val[2], val[3],
- val[5], val[6])
- }
- | kUNTIL
- {
- @lexer.cond.push(true)
- }
- expr_value do
- {
- @lexer.cond.pop
- }
- compstmt kEND
- {
- result = @builder.loop(:until, val[0], val[2], val[3],
- val[5], val[6])
- }
- | kCASE expr_value opt_terms case_body kEND
- {
- *when_bodies, (else_t, else_body) = *val[3]
-
- result = @builder.case(val[0], val[1],
- when_bodies, else_t, else_body,
- val[4])
- }
- | kCASE opt_terms case_body kEND
- {
- *when_bodies, (else_t, else_body) = *val[2]
-
- result = @builder.case(val[0], nil,
- when_bodies, else_t, else_body,
- val[3])
- }
- | kFOR for_var kIN
- {
- @lexer.cond.push(true)
- }
- expr_value do
- {
- @lexer.cond.pop
- }
- compstmt kEND
- {
- result = @builder.for(val[0], val[1],
- val[2], val[4],
- val[5], val[7], val[8])
- }
- | kCLASS cpath superclass
- {
- @static_env.extend_static
- @lexer.push_cmdarg
- }
- bodystmt kEND
- {
- if in_def?
- diagnostic :error, :class_in_def, nil, val[0]
- end
-
- lt_t, superclass = val[2]
- result = @builder.def_class(val[0], val[1],
- lt_t, superclass,
- val[4], val[5])
-
- @lexer.pop_cmdarg
- @static_env.unextend
- }
- | kCLASS tLSHFT expr term
- {
- result = @def_level
- @def_level = 0
-
- @static_env.extend_static
- @lexer.push_cmdarg
- }
- bodystmt kEND
- {
- result = @builder.def_sclass(val[0], val[1], val[2],
- val[5], val[6])
-
- @lexer.pop_cmdarg
- @static_env.unextend
-
- @def_level = val[4]
- }
- | kMODULE cpath
- {
- @static_env.extend_static
- @lexer.push_cmdarg
- }
- bodystmt kEND
- {
- if in_def?
- diagnostic :error, :module_in_def, nil, val[0]
- end
-
- result = @builder.def_module(val[0], val[1],
- val[3], val[4])
-
- @lexer.pop_cmdarg
- @static_env.unextend
- }
- | kDEF fname
- {
- @def_level += 1
- @static_env.extend_static
- @lexer.push_cmdarg
- }
- f_arglist bodystmt kEND
- {
- result = @builder.def_method(val[0], val[1],
- val[3], val[4], val[5])
-
- @lexer.pop_cmdarg
- @static_env.unextend
- @def_level -= 1
- }
- | kDEF singleton dot_or_colon
- {
- @lexer.state = :expr_fname
- }
- fname
- {
- @def_level += 1
- @static_env.extend_static
- @lexer.push_cmdarg
- }
- f_arglist bodystmt kEND
- {
- result = @builder.def_singleton(val[0], val[1], val[2],
- val[4], val[6], val[7], val[8])
-
- @lexer.pop_cmdarg
- @static_env.unextend
- @def_level -= 1
- }
- | kBREAK
- {
- result = @builder.keyword_cmd(:break, val[0])
- }
- | kNEXT
- {
- result = @builder.keyword_cmd(:next, val[0])
- }
- | kREDO
- {
- result = @builder.keyword_cmd(:redo, val[0])
- }
- | kRETRY
- {
- result = @builder.keyword_cmd(:retry, val[0])
- }
-
- primary_value: primary
-
- then: term
- | kTHEN
- | term kTHEN
- {
- result = val[1]
- }
-
- do: term
- | kDO_COND
-
- if_tail: opt_else
- | kELSIF expr_value then compstmt if_tail
- {
- else_t, else_ = val[4]
- result = [ val[0],
- @builder.condition(val[0], val[1], val[2],
- val[3], else_t,
- else_, nil),
- ]
- }
-
- opt_else: none
- | kELSE compstmt
- {
- result = val
- }
-
- for_var: lhs
- | mlhs
-
- f_marg: f_norm_arg
- {
- @static_env.declare val[0][0]
-
- result = @builder.arg(val[0])
- }
- | tLPAREN f_margs rparen
- {
- result = @builder.multi_lhs(val[0], val[1], val[2])
- }
-
- f_marg_list: f_marg
- {
- result = [ val[0] ]
- }
- | f_marg_list tCOMMA f_marg
- {
- result = val[0] << val[2]
- }
-
- f_margs: f_marg_list
- | f_marg_list tCOMMA tSTAR f_norm_arg
- {
- @static_env.declare val[3][0]
-
- result = val[0].
- push(@builder.restarg(val[2], val[3]))
- }
- | f_marg_list tCOMMA tSTAR f_norm_arg tCOMMA f_marg_list
- {
- @static_env.declare val[3][0]
-
- result = val[0].
- push(@builder.restarg(val[2], val[3])).
- concat(val[5])
- }
- | f_marg_list tCOMMA tSTAR
- {
- result = val[0].
- push(@builder.restarg(val[2]))
- }
- | f_marg_list tCOMMA tSTAR tCOMMA f_marg_list
- {
- result = val[0].
- push(@builder.restarg(val[2])).
- concat(val[4])
- }
- | tSTAR f_norm_arg
- {
- @static_env.declare val[1][0]
-
- result = [ @builder.restarg(val[0], val[1]) ]
- }
- | tSTAR f_norm_arg tCOMMA f_marg_list
- {
- @static_env.declare val[1][0]
-
- result = [ @builder.restarg(val[0], val[1]),
- *val[3] ]
- }
- | tSTAR
- {
- result = [ @builder.restarg(val[0]) ]
- }
- | tSTAR tCOMMA f_marg_list
- {
- result = [ @builder.restarg(val[0]),
- *val[2] ]
- }
-
- block_param: f_arg tCOMMA f_block_optarg tCOMMA f_rest_arg opt_f_block_arg
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
- }
- | f_arg tCOMMA f_block_optarg tCOMMA f_rest_arg tCOMMA f_arg opt_f_block_arg
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[6]).
- concat(val[7])
- }
- | f_arg tCOMMA f_block_optarg opt_f_block_arg
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | f_arg tCOMMA f_block_optarg tCOMMA f_arg opt_f_block_arg
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
- }
- | f_arg tCOMMA f_rest_arg opt_f_block_arg
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | f_arg tCOMMA
- | f_arg tCOMMA f_rest_arg tCOMMA f_arg opt_f_block_arg
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
- }
- | f_arg opt_f_block_arg
- {
- result = val[0].concat(val[1])
- }
- | f_block_optarg tCOMMA f_rest_arg opt_f_block_arg
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | f_block_optarg tCOMMA f_rest_arg tCOMMA f_arg opt_f_block_arg
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
- }
- | f_block_optarg opt_f_block_arg
- {
- result = val[0].
- concat(val[1])
- }
- | f_block_optarg tCOMMA f_arg opt_f_block_arg
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | f_rest_arg opt_f_block_arg
- {
- result = val[0].
- concat(val[1])
- }
- | f_rest_arg tCOMMA f_arg opt_f_block_arg
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | f_block_arg
- {
- result = [ val[0] ]
- }
-
- opt_block_param: # nothing
- {
- result = @builder.args(nil, [], nil)
- }
- | block_param_def
- {
- @lexer.state = :expr_value
- }
-
- block_param_def: tPIPE opt_bv_decl tPIPE
- {
- result = @builder.args(val[0], val[1], val[2])
- }
- | tOROP
- {
- result = @builder.args(val[0], [], val[0])
- }
- | tPIPE block_param opt_bv_decl tPIPE
- {
- result = @builder.args(val[0], val[1].concat(val[2]), val[3])
- }
-
- opt_bv_decl: # nothing
- {
- result = []
- }
- | tSEMI bv_decls
- {
- result = val[1]
- }
-
- bv_decls: bvar
- {
- result = [ val[0] ]
- }
- | bv_decls tCOMMA bvar
- {
- result = val[0] << val[2]
- }
-
- bvar: tIDENTIFIER
- {
- result = @builder.shadowarg(val[0])
- }
- | f_bad_arg
-
- lambda: {
- @static_env.extend_dynamic
- }
- f_larglist lambda_body
- {
- result = [ val[1], val[2] ]
-
- @static_env.unextend
- }
-
- f_larglist: tLPAREN2 f_args opt_bv_decl rparen
- {
- result = @builder.args(val[0], val[1].concat(val[2]), val[3])
- }
- | f_args
- {
- result = @builder.args(nil, val[0], nil)
- }
-
- lambda_body: tLAMBEG compstmt tRCURLY
- {
- result = [ val[0], val[1], val[2] ]
- }
- | kDO_LAMBDA compstmt kEND
- {
- result = [ val[0], val[1], val[2] ]
- }
-
- do_block: kDO_BLOCK
- {
- @static_env.extend_dynamic
- }
- opt_block_param compstmt kEND
- {
- result = [ val[0], val[2], val[3], val[4] ]
-
- @static_env.unextend
- }
-
- block_call: command do_block
- {
- begin_t, block_args, body, end_t = val[1]
- result = @builder.block(val[0],
- begin_t, block_args, body, end_t)
- }
- | block_call tDOT operation2 opt_paren_args
- {
- lparen_t, args, rparen_t = val[3]
- result = @builder.call_method(val[0], val[1], val[2],
- lparen_t, args, rparen_t)
- }
- | block_call tCOLON2 operation2 opt_paren_args
- {
- lparen_t, args, rparen_t = val[3]
- result = @builder.call_method(val[0], val[1], val[2],
- lparen_t, args, rparen_t)
- }
-
- method_call: operation paren_args
- {
- lparen_t, args, rparen_t = val[1]
- result = @builder.call_method(nil, nil, val[0],
- lparen_t, args, rparen_t)
- }
- | primary_value tDOT operation2 opt_paren_args
- {
- lparen_t, args, rparen_t = val[3]
- result = @builder.call_method(val[0], val[1], val[2],
- lparen_t, args, rparen_t)
- }
- | primary_value tCOLON2 operation2 paren_args
- {
- lparen_t, args, rparen_t = val[3]
- result = @builder.call_method(val[0], val[1], val[2],
- lparen_t, args, rparen_t)
- }
- | primary_value tCOLON2 operation3
- {
- result = @builder.call_method(val[0], val[1], val[2])
- }
- | primary_value tDOT paren_args
- {
- lparen_t, args, rparen_t = val[2]
- result = @builder.call_method(val[0], val[1], nil,
- lparen_t, args, rparen_t)
- }
- | primary_value tCOLON2 paren_args
- {
- lparen_t, args, rparen_t = val[2]
- result = @builder.call_method(val[0], val[1], nil,
- lparen_t, args, rparen_t)
- }
- | kSUPER paren_args
- {
- lparen_t, args, rparen_t = val[1]
- result = @builder.keyword_cmd(:super, val[0],
- lparen_t, args, rparen_t)
- }
- | kSUPER
- {
- result = @builder.keyword_cmd(:zsuper, val[0])
- }
- | primary_value tLBRACK2 opt_call_args rbracket
- {
- result = @builder.index(val[0], val[1], val[2], val[3])
- }
-
- brace_block: tLCURLY
- {
- @static_env.extend_dynamic
- }
- opt_block_param compstmt tRCURLY
- {
- result = [ val[0], val[2], val[3], val[4] ]
-
- @static_env.unextend
- }
- | kDO
- {
- @static_env.extend_dynamic
- }
- opt_block_param compstmt kEND
- {
- result = [ val[0], val[2], val[3], val[4] ]
-
- @static_env.unextend
- }
-
- case_body: kWHEN args then compstmt cases
- {
- result = [ @builder.when(val[0], val[1], val[2], val[3]),
- *val[4] ]
- }
-
- cases: opt_else
- {
- result = [ val[0] ]
- }
- | case_body
-
- opt_rescue: kRESCUE exc_list exc_var then compstmt opt_rescue
- {
- assoc_t, exc_var = val[2]
-
- if val[1]
- exc_list = @builder.array(nil, val[1], nil)
- end
-
- result = [ @builder.rescue_body(val[0],
- exc_list, assoc_t, exc_var,
- val[3], val[4]),
- *val[5] ]
- }
- |
- {
- result = []
- }
-
- exc_list: arg_value
- {
- result = [ val[0] ]
- }
- | mrhs
- | none
-
- exc_var: tASSOC lhs
- {
- result = [ val[0], val[1] ]
- }
- | none
-
- opt_ensure: kENSURE compstmt
- {
- result = [ val[0], val[1] ]
- }
- | none
-
- literal: numeric
- | symbol
- | dsym
-
- strings: string
- {
- result = @builder.string_compose(nil, val[0], nil)
- }
-
- string: string1
- {
- result = [ val[0] ]
- }
- | string string1
- {
- result = val[0] << val[1]
- }
-
- string1: tSTRING_BEG string_contents tSTRING_END
- {
- result = @builder.string_compose(val[0], val[1], val[2])
- }
- | tSTRING
- {
- result = @builder.string(val[0])
- }
- | tCHARACTER
- {
- result = @builder.character(val[0])
- }
-
- xstring: tXSTRING_BEG xstring_contents tSTRING_END
- {
- result = @builder.xstring_compose(val[0], val[1], val[2])
- }
-
- regexp: tREGEXP_BEG regexp_contents tSTRING_END tREGEXP_OPT
- {
- opts = @builder.regexp_options(val[3])
- result = @builder.regexp_compose(val[0], val[1], val[2], opts)
- }
-
- words: tWORDS_BEG word_list tSTRING_END
- {
- result = @builder.words_compose(val[0], val[1], val[2])
- }
-
- word_list: # nothing
- {
- result = []
- }
- | word_list word tSPACE
- {
- result = val[0] << @builder.word(val[1])
- }
-
- word: string_content
- {
- result = [ val[0] ]
- }
- | word string_content
- {
- result = val[0] << val[1]
- }
-
- qwords: tQWORDS_BEG qword_list tSTRING_END
- {
- result = @builder.words_compose(val[0], val[1], val[2])
- }
-
- qword_list: # nothing
- {
- result = []
- }
- | qword_list tSTRING_CONTENT tSPACE
- {
- result = val[0] << @builder.string_internal(val[1])
- }
-
- string_contents: # nothing
- {
- result = []
- }
- | string_contents string_content
- {
- result = val[0] << val[1]
- }
-
-xstring_contents: # nothing
- {
- result = []
- }
- | xstring_contents string_content
- {
- result = val[0] << val[1]
- }
-
-regexp_contents: # nothing
- {
- result = []
- }
- | regexp_contents string_content
- {
- result = val[0] << val[1]
- }
-
- string_content: tSTRING_CONTENT
- {
- result = @builder.string_internal(val[0])
- }
- | tSTRING_DVAR string_dvar
- {
- result = val[1]
- }
- | tSTRING_DBEG
- {
- @lexer.cond.push(false)
- @lexer.cmdarg.push(false)
- }
- compstmt tRCURLY
- {
- @lexer.cond.lexpop
- @lexer.cmdarg.lexpop
-
- result = @builder.begin(val[0], val[2], val[3])
- }
-
- string_dvar: tGVAR
- {
- result = @builder.gvar(val[0])
- }
- | tIVAR
- {
- result = @builder.ivar(val[0])
- }
- | tCVAR
- {
- result = @builder.cvar(val[0])
- }
- | backref
-
-
- symbol: tSYMBOL
- {
- result = @builder.symbol(val[0])
- }
-
- dsym: tSYMBEG xstring_contents tSTRING_END
- {
- result = @builder.symbol_compose(val[0], val[1], val[2])
- }
-
- numeric: tINTEGER
- {
- result = @builder.integer(val[0])
- }
- | tFLOAT
- {
- result = @builder.float(val[0])
- }
- | tUMINUS_NUM tINTEGER =tLOWEST
- {
- result = @builder.negate(val[0],
- @builder.integer(val[1]))
- }
- | tUMINUS_NUM tFLOAT =tLOWEST
- {
- result = @builder.negate(val[0],
- @builder.float(val[1]))
- }
-
- user_variable: tIDENTIFIER
- {
- result = @builder.ident(val[0])
- }
- | tIVAR
- {
- result = @builder.ivar(val[0])
- }
- | tGVAR
- {
- result = @builder.gvar(val[0])
- }
- | tCONSTANT
- {
- result = @builder.const(val[0])
- }
- | tCVAR
- {
- result = @builder.cvar(val[0])
- }
-
-keyword_variable: kNIL
- {
- result = @builder.nil(val[0])
- }
- | kSELF
- {
- result = @builder.self(val[0])
- }
- | kTRUE
- {
- result = @builder.true(val[0])
- }
- | kFALSE
- {
- result = @builder.false(val[0])
- }
- | k__FILE__
- {
- result = @builder.__FILE__(val[0])
- }
- | k__LINE__
- {
- result = @builder.__LINE__(val[0])
- }
- | k__ENCODING__
- {
- result = @builder.__ENCODING__(val[0])
- }
-
- var_ref: user_variable
- {
- result = @builder.accessible(val[0])
- }
- | keyword_variable
- {
- result = @builder.accessible(val[0])
- }
-
- var_lhs: user_variable
- {
- result = @builder.assignable(val[0])
- }
- | keyword_variable
- {
- result = @builder.assignable(val[0])
- }
-
- backref: tNTH_REF
- {
- result = @builder.nth_ref(val[0])
- }
- | tBACK_REF
- {
- result = @builder.back_ref(val[0])
- }
-
- superclass: term
- {
- result = nil
- }
- | tLT expr_value term
- {
- result = [ val[0], val[1] ]
- }
- | error term
- {
- yyerrok
- result = nil
- }
-
- f_arglist: tLPAREN2 f_args rparen
- {
- result = @builder.args(val[0], val[1], val[2])
-
- @lexer.state = :expr_value
- }
- | f_args term
- {
- result = @builder.args(nil, val[0], nil)
- }
-
- f_args: f_arg tCOMMA f_optarg tCOMMA f_rest_arg opt_f_block_arg
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
- }
- | f_arg tCOMMA f_optarg tCOMMA f_rest_arg tCOMMA f_arg opt_f_block_arg
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[6]).
- concat(val[7])
- }
- | f_arg tCOMMA f_optarg opt_f_block_arg
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | f_arg tCOMMA f_optarg tCOMMA f_arg opt_f_block_arg
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
- }
- | f_arg tCOMMA f_rest_arg opt_f_block_arg
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | f_arg tCOMMA f_rest_arg tCOMMA f_arg opt_f_block_arg
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
- }
- | f_arg opt_f_block_arg
- {
- result = val[0].
- concat(val[1])
- }
- | f_optarg tCOMMA f_rest_arg opt_f_block_arg
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | f_optarg tCOMMA f_rest_arg tCOMMA f_arg opt_f_block_arg
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
- }
- | f_optarg opt_f_block_arg
- {
- result = val[0].
- concat(val[1])
- }
- | f_optarg tCOMMA f_arg opt_f_block_arg
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | f_rest_arg opt_f_block_arg
- {
- result = val[0].
- concat(val[1])
- }
- | f_rest_arg tCOMMA f_arg opt_f_block_arg
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | f_block_arg
- {
- result = [ val[0] ]
- }
- | # nothing
- {
- result = []
- }
-
- f_bad_arg: tCONSTANT
- {
- diagnostic :error, :argument_const, nil, val[0]
- }
- | tIVAR
- {
- diagnostic :error, :argument_ivar, nil, val[0]
- }
- | tGVAR
- {
- diagnostic :error, :argument_gvar, nil, val[0]
- }
- | tCVAR
- {
- diagnostic :error, :argument_cvar, nil, val[0]
- }
-
- f_norm_arg: f_bad_arg
- | tIDENTIFIER
-
- f_arg_item: f_norm_arg
- {
- @static_env.declare val[0][0]
-
- result = @builder.arg(val[0])
- }
- | tLPAREN f_margs rparen
- {
- result = @builder.multi_lhs(val[0], val[1], val[2])
- }
-
- f_arg: f_arg_item
- {
- result = [ val[0] ]
- }
- | f_arg tCOMMA f_arg_item
- {
- result = val[0] << val[2]
- }
-
- f_opt: tIDENTIFIER tEQL arg_value
- {
- @static_env.declare val[0][0]
-
- result = @builder.optarg(val[0], val[1], val[2])
- }
-
- f_block_opt: tIDENTIFIER tEQL primary_value
- {
- @static_env.declare val[0][0]
-
- result = @builder.optarg(val[0], val[1], val[2])
- }
-
- f_block_optarg: f_block_opt
- {
- result = [ val[0] ]
- }
- | f_block_optarg tCOMMA f_block_opt
- {
- result = val[0] << val[2]
- }
-
- f_optarg: f_opt
- {
- result = [ val[0] ]
- }
- | f_optarg tCOMMA f_opt
- {
- result = val[0] << val[2]
- }
-
- restarg_mark: tSTAR2 | tSTAR
-
- f_rest_arg: restarg_mark tIDENTIFIER
- {
- @static_env.declare val[1][0]
-
- result = [ @builder.restarg(val[0], val[1]) ]
- }
- | restarg_mark
- {
- result = [ @builder.restarg(val[0]) ]
- }
-
- blkarg_mark: tAMPER2 | tAMPER
-
- f_block_arg: blkarg_mark tIDENTIFIER
- {
- @static_env.declare val[1][0]
-
- result = @builder.blockarg(val[0], val[1])
- }
-
- opt_f_block_arg: tCOMMA f_block_arg
- {
- result = [ val[1] ]
- }
- | # nothing
- {
- result = []
- }
-
- singleton: var_ref
- | tLPAREN2 expr rparen
- {
- result = val[1]
- }
-
- assoc_list: # nothing
- {
- result = []
- }
- | assocs trailer
-
- assocs: assoc
- {
- result = [ val[0] ]
- }
- | assocs tCOMMA assoc
- {
- result = val[0] << val[2]
- }
-
- assoc: arg_value tASSOC arg_value
- {
- result = @builder.pair(val[0], val[1], val[2])
- }
- | tLABEL arg_value
- {
- result = @builder.pair_keyword(val[0], val[1])
- }
-
- operation: tIDENTIFIER | tCONSTANT | tFID
- operation2: tIDENTIFIER | tCONSTANT | tFID | op
- operation3: tIDENTIFIER | tFID | op
- dot_or_colon: tDOT | tCOLON2
- opt_terms: | terms
- opt_nl: | tNL
- rparen: opt_nl tRPAREN
- {
- result = val[1]
- }
- rbracket: opt_nl tRBRACK
- {
- result = val[1]
- }
- trailer: | tNL | tCOMMA
-
- term: tSEMI
- {
- yyerrok
- }
- | tNL
-
- terms: term
- | terms tSEMI
-
- none: # nothing
- {
- result = nil
- }
-end
-
----- header
-
-require 'parser'
-
-Parser.check_for_encoding_support
-
----- inner
-
- def version
- 19
- end
-
- def default_encoding
- Encoding::BINARY
- end
diff --git a/test/racc/assets/ruby20.y b/test/racc/assets/ruby20.y
deleted file mode 100644
index 6e07734778..0000000000
--- a/test/racc/assets/ruby20.y
+++ /dev/null
@@ -1,2350 +0,0 @@
-# Copyright (c) 2013 Peter Zotov <whitequark@whitequark.org>
-#
-# Parts of the source are derived from ruby_parser:
-# Copyright (c) Ryan Davis, seattle.rb
-#
-# MIT License
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-class Parser::Ruby20
-
-token kCLASS kMODULE kDEF kUNDEF kBEGIN kRESCUE kENSURE kEND kIF kUNLESS
- kTHEN kELSIF kELSE kCASE kWHEN kWHILE kUNTIL kFOR kBREAK kNEXT
- kREDO kRETRY kIN kDO kDO_COND kDO_BLOCK kDO_LAMBDA kRETURN kYIELD kSUPER
- kSELF kNIL kTRUE kFALSE kAND kOR kNOT kIF_MOD kUNLESS_MOD kWHILE_MOD
- kUNTIL_MOD kRESCUE_MOD kALIAS kDEFINED klBEGIN klEND k__LINE__
- k__FILE__ k__ENCODING__ tIDENTIFIER tFID tGVAR tIVAR tCONSTANT
- tLABEL tCVAR tNTH_REF tBACK_REF tSTRING_CONTENT tINTEGER tFLOAT
- tREGEXP_END tUPLUS tUMINUS tUMINUS_NUM tPOW tCMP tEQ tEQQ tNEQ
- tGEQ tLEQ tANDOP tOROP tMATCH tNMATCH tDOT tDOT2 tDOT3 tAREF
- tASET tLSHFT tRSHFT tCOLON2 tCOLON3 tOP_ASGN tASSOC tLPAREN
- tLPAREN2 tRPAREN tLPAREN_ARG tLBRACK tLBRACK2 tRBRACK tLBRACE
- tLBRACE_ARG tSTAR tSTAR2 tAMPER tAMPER2 tTILDE tPERCENT tDIVIDE
- tDSTAR tPLUS tMINUS tLT tGT tPIPE tBANG tCARET tLCURLY tRCURLY
- tBACK_REF2 tSYMBEG tSTRING_BEG tXSTRING_BEG tREGEXP_BEG tREGEXP_OPT
- tWORDS_BEG tQWORDS_BEG tSYMBOLS_BEG tQSYMBOLS_BEG tSTRING_DBEG
- tSTRING_DVAR tSTRING_END tSTRING_DEND tSTRING tSYMBOL
- tNL tEH tCOLON tCOMMA tSPACE tSEMI tLAMBDA tLAMBEG tCHARACTER
-
-prechigh
- right tBANG tTILDE tUPLUS
- right tPOW
- right tUMINUS_NUM tUMINUS
- left tSTAR2 tDIVIDE tPERCENT
- left tPLUS tMINUS
- left tLSHFT tRSHFT
- left tAMPER2
- left tPIPE tCARET
- left tGT tGEQ tLT tLEQ
- nonassoc tCMP tEQ tEQQ tNEQ tMATCH tNMATCH
- left tANDOP
- left tOROP
- nonassoc tDOT2 tDOT3
- right tEH tCOLON
- left kRESCUE_MOD
- right tEQL tOP_ASGN
- nonassoc kDEFINED
- right kNOT
- left kOR kAND
- nonassoc kIF_MOD kUNLESS_MOD kWHILE_MOD kUNTIL_MOD
- nonassoc tLBRACE_ARG
- nonassoc tLOWEST
-preclow
-
-rule
-
- program: top_compstmt
-
- top_compstmt: top_stmts opt_terms
- {
- result = @builder.compstmt(val[0])
- }
-
- top_stmts: # nothing
- {
- result = []
- }
- | top_stmt
- {
- result = [ val[0] ]
- }
- | top_stmts terms top_stmt
- {
- result = val[0] << val[2]
- }
- | error top_stmt
- {
- result = [ val[1] ]
- }
-
- top_stmt: stmt
- | klBEGIN tLCURLY top_compstmt tRCURLY
- {
- result = @builder.preexe(val[0], val[1], val[2], val[3])
- }
-
- bodystmt: compstmt opt_rescue opt_else opt_ensure
- {
- rescue_bodies = val[1]
- else_t, else_ = val[2]
- ensure_t, ensure_ = val[3]
-
- if rescue_bodies.empty? && !else_.nil?
- diagnostic :warning, :useless_else, nil, else_t
- end
-
- result = @builder.begin_body(val[0],
- rescue_bodies,
- else_t, else_,
- ensure_t, ensure_)
- }
-
- compstmt: stmts opt_terms
- {
- result = @builder.compstmt(val[0])
- }
-
- stmts: # nothing
- {
- result = []
- }
- | stmt_or_begin
- {
- result = [ val[0] ]
- }
- | stmts terms stmt_or_begin
- {
- result = val[0] << val[2]
- }
- | error stmt
- {
- result = [ val[1] ]
- }
-
- stmt_or_begin: stmt
- | klBEGIN tLCURLY top_compstmt tRCURLY
- {
- if in_def?
- diagnostic :error, :begin_in_method, nil, val[0]
- end
-
- result = @builder.preexe(val[0], val[1], val[2], val[3])
- }
-
- stmt: kALIAS fitem
- {
- @lexer.state = :expr_fname
- }
- fitem
- {
- result = @builder.alias(val[0], val[1], val[3])
- }
- | kALIAS tGVAR tGVAR
- {
- result = @builder.alias(val[0],
- @builder.gvar(val[1]),
- @builder.gvar(val[2]))
- }
- | kALIAS tGVAR tBACK_REF
- {
- result = @builder.alias(val[0],
- @builder.gvar(val[1]),
- @builder.back_ref(val[2]))
- }
- | kALIAS tGVAR tNTH_REF
- {
- diagnostic :error, :nth_ref_alias, nil, val[2]
- }
- | kUNDEF undef_list
- {
- result = @builder.undef_method(val[0], val[1])
- }
- | stmt kIF_MOD expr_value
- {
- result = @builder.condition_mod(val[0], nil,
- val[1], val[2])
- }
- | stmt kUNLESS_MOD expr_value
- {
- result = @builder.condition_mod(nil, val[0],
- val[1], val[2])
- }
- | stmt kWHILE_MOD expr_value
- {
- result = @builder.loop_mod(:while, val[0], val[1], val[2])
- }
- | stmt kUNTIL_MOD expr_value
- {
- result = @builder.loop_mod(:until, val[0], val[1], val[2])
- }
- | stmt kRESCUE_MOD stmt
- {
- rescue_body = @builder.rescue_body(val[1],
- nil, nil, nil,
- nil, val[2])
-
- result = @builder.begin_body(val[0], [ rescue_body ])
- }
- | klEND tLCURLY compstmt tRCURLY
- {
- result = @builder.postexe(val[0], val[1], val[2], val[3])
- }
- | command_asgn
- | mlhs tEQL command_call
- {
- result = @builder.multi_assign(val[0], val[1], val[2])
- }
- | var_lhs tOP_ASGN command_call
- {
- result = @builder.op_assign(val[0], val[1], val[2])
- }
- | primary_value tLBRACK2 opt_call_args rbracket tOP_ASGN command_call
- {
- result = @builder.op_assign(
- @builder.index(
- val[0], val[1], val[2], val[3]),
- val[4], val[5])
- }
- | primary_value tDOT tIDENTIFIER tOP_ASGN command_call
- {
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
- }
- | primary_value tDOT tCONSTANT tOP_ASGN command_call
- {
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
- }
- | primary_value tCOLON2 tCONSTANT tOP_ASGN command_call
- {
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
- }
- | primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_call
- {
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
- }
- | backref tOP_ASGN command_call
- {
- @builder.op_assign(val[0], val[1], val[2])
- }
- | lhs tEQL mrhs
- {
- result = @builder.assign(val[0], val[1],
- @builder.array(nil, val[2], nil))
- }
- | mlhs tEQL arg_value
- {
- result = @builder.multi_assign(val[0], val[1], val[2])
- }
- | mlhs tEQL mrhs
- {
- result = @builder.multi_assign(val[0], val[1],
- @builder.array(nil, val[2], nil))
- }
- | expr
-
- command_asgn: lhs tEQL command_call
- {
- result = @builder.assign(val[0], val[1], val[2])
- }
- | lhs tEQL command_asgn
- {
- result = @builder.assign(val[0], val[1], val[2])
- }
-
- expr: command_call
- | expr kAND expr
- {
- result = @builder.logical_op(:and, val[0], val[1], val[2])
- }
- | expr kOR expr
- {
- result = @builder.logical_op(:or, val[0], val[1], val[2])
- }
- | kNOT opt_nl expr
- {
- result = @builder.not_op(val[0], nil, val[2], nil)
- }
- | tBANG command_call
- {
- result = @builder.not_op(val[0], nil, val[1], nil)
- }
- | arg
-
- expr_value: expr
-
- command_call: command
- | block_command
-
- block_command: block_call
- | block_call dot_or_colon operation2 command_args
- {
- result = @builder.call_method(val[0], val[1], val[2],
- nil, val[3], nil)
- }
-
- cmd_brace_block: tLBRACE_ARG
- {
- @static_env.extend_dynamic
- }
- opt_block_param compstmt tRCURLY
- {
- result = [ val[0], val[2], val[3], val[4] ]
-
- @static_env.unextend
- }
-
- fcall: operation
-
- command: fcall command_args =tLOWEST
- {
- result = @builder.call_method(nil, nil, val[0],
- nil, val[1], nil)
- }
- | fcall command_args cmd_brace_block
- {
- method_call = @builder.call_method(nil, nil, val[0],
- nil, val[1], nil)
-
- begin_t, args, body, end_t = val[2]
- result = @builder.block(method_call,
- begin_t, args, body, end_t)
- }
- | primary_value tDOT operation2 command_args =tLOWEST
- {
- result = @builder.call_method(val[0], val[1], val[2],
- nil, val[3], nil)
- }
- | primary_value tDOT operation2 command_args cmd_brace_block
- {
- method_call = @builder.call_method(val[0], val[1], val[2],
- nil, val[3], nil)
-
- begin_t, args, body, end_t = val[4]
- result = @builder.block(method_call,
- begin_t, args, body, end_t)
- }
- | primary_value tCOLON2 operation2 command_args =tLOWEST
- {
- result = @builder.call_method(val[0], val[1], val[2],
- nil, val[3], nil)
- }
- | primary_value tCOLON2 operation2 command_args cmd_brace_block
- {
- method_call = @builder.call_method(val[0], val[1], val[2],
- nil, val[3], nil)
-
- begin_t, args, body, end_t = val[4]
- result = @builder.block(method_call,
- begin_t, args, body, end_t)
- }
- | kSUPER command_args
- {
- result = @builder.keyword_cmd(:super, val[0],
- nil, val[1], nil)
- }
- | kYIELD command_args
- {
- result = @builder.keyword_cmd(:yield, val[0],
- nil, val[1], nil)
- }
- | kRETURN call_args
- {
- result = @builder.keyword_cmd(:return, val[0],
- nil, val[1], nil)
- }
- | kBREAK call_args
- {
- result = @builder.keyword_cmd(:break, val[0],
- nil, val[1], nil)
- }
- | kNEXT call_args
- {
- result = @builder.keyword_cmd(:next, val[0],
- nil, val[1], nil)
- }
-
- mlhs: mlhs_basic
- {
- result = @builder.multi_lhs(nil, val[0], nil)
- }
- | tLPAREN mlhs_inner rparen
- {
- result = @builder.begin(val[0], val[1], val[2])
- }
-
- mlhs_inner: mlhs_basic
- {
- result = @builder.multi_lhs(nil, val[0], nil)
- }
- | tLPAREN mlhs_inner rparen
- {
- result = @builder.multi_lhs(val[0], val[1], val[2])
- }
-
- mlhs_basic: mlhs_head
- | mlhs_head mlhs_item
- {
- result = val[0].
- push(val[1])
- }
- | mlhs_head tSTAR mlhs_node
- {
- result = val[0].
- push(@builder.splat(val[1], val[2]))
- }
- | mlhs_head tSTAR mlhs_node tCOMMA mlhs_post
- {
- result = val[0].
- push(@builder.splat(val[1], val[2])).
- concat(val[4])
- }
- | mlhs_head tSTAR
- {
- result = val[0].
- push(@builder.splat(val[1]))
- }
- | mlhs_head tSTAR tCOMMA mlhs_post
- {
- result = val[0].
- push(@builder.splat(val[1])).
- concat(val[3])
- }
- | tSTAR mlhs_node
- {
- result = [ @builder.splat(val[0], val[1]) ]
- }
- | tSTAR mlhs_node tCOMMA mlhs_post
- {
- result = [ @builder.splat(val[0], val[1]),
- *val[3] ]
- }
- | tSTAR
- {
- result = [ @builder.splat(val[0]) ]
- }
- | tSTAR tCOMMA mlhs_post
- {
- result = [ @builder.splat(val[0]),
- *val[2] ]
- }
-
- mlhs_item: mlhs_node
- | tLPAREN mlhs_inner rparen
- {
- result = @builder.begin(val[0], val[1], val[2])
- }
-
- mlhs_head: mlhs_item tCOMMA
- {
- result = [ val[0] ]
- }
- | mlhs_head mlhs_item tCOMMA
- {
- result = val[0] << val[1]
- }
-
- mlhs_post: mlhs_item
- {
- result = [ val[0] ]
- }
- | mlhs_post tCOMMA mlhs_item
- {
- result = val[0] << val[2]
- }
-
- mlhs_node: user_variable
- {
- result = @builder.assignable(val[0])
- }
- | keyword_variable
- {
- result = @builder.assignable(val[0])
- }
- | primary_value tLBRACK2 opt_call_args rbracket
- {
- result = @builder.index_asgn(val[0], val[1], val[2], val[3])
- }
- | primary_value tDOT tIDENTIFIER
- {
- result = @builder.attr_asgn(val[0], val[1], val[2])
- }
- | primary_value tCOLON2 tIDENTIFIER
- {
- result = @builder.attr_asgn(val[0], val[1], val[2])
- }
- | primary_value tDOT tCONSTANT
- {
- result = @builder.attr_asgn(val[0], val[1], val[2])
- }
- | primary_value tCOLON2 tCONSTANT
- {
- result = @builder.assignable(
- @builder.const_fetch(val[0], val[1], val[2]))
- }
- | tCOLON3 tCONSTANT
- {
- result = @builder.assignable(
- @builder.const_global(val[0], val[1]))
- }
- | backref
- {
- result = @builder.assignable(val[0])
- }
-
- lhs: user_variable
- {
- result = @builder.assignable(val[0])
- }
- | keyword_variable
- {
- result = @builder.assignable(val[0])
- }
- | primary_value tLBRACK2 opt_call_args rbracket
- {
- result = @builder.index_asgn(val[0], val[1], val[2], val[3])
- }
- | primary_value tDOT tIDENTIFIER
- {
- result = @builder.attr_asgn(val[0], val[1], val[2])
- }
- | primary_value tCOLON2 tIDENTIFIER
- {
- result = @builder.attr_asgn(val[0], val[1], val[2])
- }
- | primary_value tDOT tCONSTANT
- {
- result = @builder.attr_asgn(val[0], val[1], val[2])
- }
- | primary_value tCOLON2 tCONSTANT
- {
- result = @builder.assignable(
- @builder.const_fetch(val[0], val[1], val[2]))
- }
- | tCOLON3 tCONSTANT
- {
- result = @builder.assignable(
- @builder.const_global(val[0], val[1]))
- }
- | backref
- {
- result = @builder.assignable(val[0])
- }
-
- cname: tIDENTIFIER
- {
- diagnostic :error, :module_name_const, nil, val[0]
- }
- | tCONSTANT
-
- cpath: tCOLON3 cname
- {
- result = @builder.const_global(val[0], val[1])
- }
- | cname
- {
- result = @builder.const(val[0])
- }
- | primary_value tCOLON2 cname
- {
- result = @builder.const_fetch(val[0], val[1], val[2])
- }
-
- fname: tIDENTIFIER | tCONSTANT | tFID
- | op
- | reswords
-
- fsym: fname
- {
- result = @builder.symbol(val[0])
- }
- | symbol
-
- fitem: fsym
- | dsym
-
- undef_list: fitem
- {
- result = [ val[0] ]
- }
- | undef_list tCOMMA
- {
- @lexer.state = :expr_fname
- }
- fitem
- {
- result = val[0] << val[3]
- }
-
- op: tPIPE | tCARET | tAMPER2 | tCMP | tEQ | tEQQ
- | tMATCH | tNMATCH | tGT | tGEQ | tLT | tLEQ
- | tNEQ | tLSHFT | tRSHFT | tPLUS | tMINUS | tSTAR2
- | tSTAR | tDIVIDE | tPERCENT | tPOW | tBANG | tTILDE
- | tUPLUS | tUMINUS | tAREF | tASET | tDSTAR | tBACK_REF2
-
- reswords: k__LINE__ | k__FILE__ | k__ENCODING__ | klBEGIN | klEND
- | kALIAS | kAND | kBEGIN | kBREAK | kCASE
- | kCLASS | kDEF | kDEFINED | kDO | kELSE
- | kELSIF | kEND | kENSURE | kFALSE | kFOR
- | kIN | kMODULE | kNEXT | kNIL | kNOT
- | kOR | kREDO | kRESCUE | kRETRY | kRETURN
- | kSELF | kSUPER | kTHEN | kTRUE | kUNDEF
- | kWHEN | kYIELD | kIF | kUNLESS | kWHILE
- | kUNTIL
-
- arg: lhs tEQL arg
- {
- result = @builder.assign(val[0], val[1], val[2])
- }
- | lhs tEQL arg kRESCUE_MOD arg
- {
- rescue_body = @builder.rescue_body(val[3],
- nil, nil, nil,
- nil, val[4])
-
- rescue_ = @builder.begin_body(val[2], [ rescue_body ])
-
- result = @builder.assign(val[0], val[1], rescue_)
- }
- | var_lhs tOP_ASGN arg
- {
- result = @builder.op_assign(val[0], val[1], val[2])
- }
- | var_lhs tOP_ASGN arg kRESCUE_MOD arg
- {
- rescue_body = @builder.rescue_body(val[3],
- nil, nil, nil,
- nil, val[4])
-
- rescue_ = @builder.begin_body(val[2], [ rescue_body ])
-
- result = @builder.op_assign(val[0], val[1], rescue_)
- }
- | primary_value tLBRACK2 opt_call_args rbracket tOP_ASGN arg
- {
- result = @builder.op_assign(
- @builder.index(
- val[0], val[1], val[2], val[3]),
- val[4], val[5])
- }
- | primary_value tDOT tIDENTIFIER tOP_ASGN arg
- {
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
- }
- | primary_value tDOT tCONSTANT tOP_ASGN arg
- {
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
- }
- | primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg
- {
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
- }
- | primary_value tCOLON2 tCONSTANT tOP_ASGN arg
- {
- const = @builder.const_op_assignable(
- @builder.const_fetch(val[0], val[1], val[2]))
- result = @builder.op_assign(const, val[3], val[4])
- }
- | tCOLON3 tCONSTANT tOP_ASGN arg
- {
- const = @builder.const_op_assignable(
- @builder.const_global(val[0], val[1]))
- result = @builder.op_assign(const, val[2], val[3])
- }
- | backref tOP_ASGN arg
- {
- result = @builder.op_assign(val[0], val[1], val[2])
- }
- | arg tDOT2 arg
- {
- result = @builder.range_inclusive(val[0], val[1], val[2])
- }
- | arg tDOT3 arg
- {
- result = @builder.range_exclusive(val[0], val[1], val[2])
- }
- | arg tPLUS arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tMINUS arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tSTAR2 arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tDIVIDE arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tPERCENT arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tPOW arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | tUMINUS_NUM tINTEGER tPOW arg
- {
- result = @builder.unary_op(val[0],
- @builder.binary_op(
- @builder.integer(val[1]),
- val[2], val[3]))
- }
- | tUMINUS_NUM tFLOAT tPOW arg
- {
- result = @builder.unary_op(val[0],
- @builder.binary_op(
- @builder.float(val[1]),
- val[2], val[3]))
- }
- | tUPLUS arg
- {
- result = @builder.unary_op(val[0], val[1])
- }
- | tUMINUS arg
- {
- result = @builder.unary_op(val[0], val[1])
- }
- | arg tPIPE arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tCARET arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tAMPER2 arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tCMP arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tGT arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tGEQ arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tLT arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tLEQ arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tEQ arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tEQQ arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tNEQ arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tMATCH arg
- {
- result = @builder.match_op(val[0], val[1], val[2])
- }
- | arg tNMATCH arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | tBANG arg
- {
- result = @builder.not_op(val[0], nil, val[1], nil)
- }
- | tTILDE arg
- {
- result = @builder.unary_op(val[0], val[1])
- }
- | arg tLSHFT arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tRSHFT arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tANDOP arg
- {
- result = @builder.logical_op(:and, val[0], val[1], val[2])
- }
- | arg tOROP arg
- {
- result = @builder.logical_op(:or, val[0], val[1], val[2])
- }
- | kDEFINED opt_nl arg
- {
- result = @builder.keyword_cmd(:defined?, val[0], nil, [ val[2] ], nil)
- }
-
- | arg tEH arg opt_nl tCOLON arg
- {
- result = @builder.ternary(val[0], val[1],
- val[2], val[4], val[5])
- }
- | primary
-
- arg_value: arg
-
- aref_args: none
- | args trailer
- | args tCOMMA assocs trailer
- {
- result = val[0] << @builder.associate(nil, val[2], nil)
- }
- | assocs trailer
- {
- result = [ @builder.associate(nil, val[0], nil) ]
- }
-
- paren_args: tLPAREN2 opt_call_args rparen
- {
- result = val
- }
-
- opt_paren_args: # nothing
- {
- result = [ nil, [], nil ]
- }
- | paren_args
-
- opt_call_args: # nothing
- {
- result = []
- }
- | call_args
- | args tCOMMA
- | args tCOMMA assocs tCOMMA
- {
- result = val[0] << @builder.associate(nil, val[2], nil)
- }
- | assocs tCOMMA
- {
- result = [ @builder.associate(nil, val[0], nil) ]
- }
-
- call_args: command
- {
- result = [ val[0] ]
- }
- | args opt_block_arg
- {
- result = val[0].concat(val[1])
- }
- | assocs opt_block_arg
- {
- result = [ @builder.associate(nil, val[0], nil) ]
- result.concat(val[1])
- }
- | args tCOMMA assocs opt_block_arg
- {
- assocs = @builder.associate(nil, val[2], nil)
- result = val[0] << assocs
- result.concat(val[3])
- }
- | block_arg
- {
- result = [ val[0] ]
- }
-
- command_args: {
- result = @lexer.cmdarg.dup
- @lexer.cmdarg.push(true)
- }
- call_args
- {
- @lexer.cmdarg = val[0]
-
- result = val[1]
- }
-
- block_arg: tAMPER arg_value
- {
- result = @builder.block_pass(val[0], val[1])
- }
-
- opt_block_arg: tCOMMA block_arg
- {
- result = [ val[1] ]
- }
- | # nothing
- {
- result = []
- }
-
- args: arg_value
- {
- result = [ val[0] ]
- }
- | tSTAR arg_value
- {
- result = [ @builder.splat(val[0], val[1]) ]
- }
- | args tCOMMA arg_value
- {
- result = val[0] << val[2]
- }
- | args tCOMMA tSTAR arg_value
- {
- result = val[0] << @builder.splat(val[2], val[3])
- }
-
- mrhs: args tCOMMA arg_value
- {
- result = val[0] << val[2]
- }
- | args tCOMMA tSTAR arg_value
- {
- result = val[0] << @builder.splat(val[2], val[3])
- }
- | tSTAR arg_value
- {
- result = [ @builder.splat(val[0], val[1]) ]
- }
-
- primary: literal
- | strings
- | xstring
- | regexp
- | words
- | qwords
- | symbols
- | qsymbols
- | var_ref
- | backref
- | tFID
- {
- result = @builder.call_method(nil, nil, val[0])
- }
- | kBEGIN
- {
- result = @lexer.cmdarg.dup
- @lexer.cmdarg.clear
- }
- bodystmt kEND
- {
- @lexer.cmdarg = val[1]
-
- result = @builder.begin_keyword(val[0], val[2], val[3])
- }
- | tLPAREN_ARG
- {
- result = @lexer.cmdarg.dup
- @lexer.cmdarg.clear
- }
- expr
- {
- @lexer.state = :expr_endarg
- }
- opt_nl tRPAREN
- {
- @lexer.cmdarg = val[1]
-
- result = @builder.begin(val[0], val[2], val[5])
- }
- | tLPAREN_ARG
- {
- @lexer.state = :expr_endarg
- }
- opt_nl tRPAREN
- {
- result = @builder.begin(val[0], nil, val[3])
- }
- | tLPAREN compstmt tRPAREN
- {
- result = @builder.begin(val[0], val[1], val[2])
- }
- | primary_value tCOLON2 tCONSTANT
- {
- result = @builder.const_fetch(val[0], val[1], val[2])
- }
- | tCOLON3 tCONSTANT
- {
- result = @builder.const_global(val[0], val[1])
- }
- | tLBRACK aref_args tRBRACK
- {
- result = @builder.array(val[0], val[1], val[2])
- }
- | tLBRACE assoc_list tRCURLY
- {
- result = @builder.associate(val[0], val[1], val[2])
- }
- | kRETURN
- {
- result = @builder.keyword_cmd(:return, val[0])
- }
- | kYIELD tLPAREN2 call_args rparen
- {
- result = @builder.keyword_cmd(:yield, val[0], val[1], val[2], val[3])
- }
- | kYIELD tLPAREN2 rparen
- {
- result = @builder.keyword_cmd(:yield, val[0], val[1], [], val[2])
- }
- | kYIELD
- {
- result = @builder.keyword_cmd(:yield, val[0])
- }
- | kDEFINED opt_nl tLPAREN2 expr rparen
- {
- result = @builder.keyword_cmd(:defined?, val[0],
- val[2], [ val[3] ], val[4])
- }
- | kNOT tLPAREN2 expr rparen
- {
- result = @builder.not_op(val[0], val[1], val[2], val[3])
- }
- | kNOT tLPAREN2 rparen
- {
- result = @builder.not_op(val[0], val[1], nil, val[2])
- }
- | fcall brace_block
- {
- method_call = @builder.call_method(nil, nil, val[0])
-
- begin_t, args, body, end_t = val[1]
- result = @builder.block(method_call,
- begin_t, args, body, end_t)
- }
- | method_call
- | method_call brace_block
- {
- begin_t, args, body, end_t = val[1]
- result = @builder.block(val[0],
- begin_t, args, body, end_t)
- }
- | tLAMBDA lambda
- {
- lambda_call = @builder.call_lambda(val[0])
-
- args, (begin_t, body, end_t) = val[1]
- result = @builder.block(lambda_call,
- begin_t, args, body, end_t)
- }
- | kIF expr_value then compstmt if_tail kEND
- {
- else_t, else_ = val[4]
- result = @builder.condition(val[0], val[1], val[2],
- val[3], else_t,
- else_, val[5])
- }
- | kUNLESS expr_value then compstmt opt_else kEND
- {
- else_t, else_ = val[4]
- result = @builder.condition(val[0], val[1], val[2],
- else_, else_t,
- val[3], val[5])
- }
- | kWHILE
- {
- @lexer.cond.push(true)
- }
- expr_value do
- {
- @lexer.cond.pop
- }
- compstmt kEND
- {
- result = @builder.loop(:while, val[0], val[2], val[3],
- val[5], val[6])
- }
- | kUNTIL
- {
- @lexer.cond.push(true)
- }
- expr_value do
- {
- @lexer.cond.pop
- }
- compstmt kEND
- {
- result = @builder.loop(:until, val[0], val[2], val[3],
- val[5], val[6])
- }
- | kCASE expr_value opt_terms case_body kEND
- {
- *when_bodies, (else_t, else_body) = *val[3]
-
- result = @builder.case(val[0], val[1],
- when_bodies, else_t, else_body,
- val[4])
- }
- | kCASE opt_terms case_body kEND
- {
- *when_bodies, (else_t, else_body) = *val[2]
-
- result = @builder.case(val[0], nil,
- when_bodies, else_t, else_body,
- val[3])
- }
- | kFOR for_var kIN
- {
- @lexer.cond.push(true)
- }
- expr_value do
- {
- @lexer.cond.pop
- }
- compstmt kEND
- {
- result = @builder.for(val[0], val[1],
- val[2], val[4],
- val[5], val[7], val[8])
- }
- | kCLASS cpath superclass
- {
- @static_env.extend_static
- @lexer.push_cmdarg
- }
- bodystmt kEND
- {
- if in_def?
- diagnostic :error, :class_in_def, nil, val[0]
- end
-
- lt_t, superclass = val[2]
- result = @builder.def_class(val[0], val[1],
- lt_t, superclass,
- val[4], val[5])
-
- @lexer.pop_cmdarg
- @static_env.unextend
- }
- | kCLASS tLSHFT expr term
- {
- result = @def_level
- @def_level = 0
-
- @static_env.extend_static
- @lexer.push_cmdarg
- }
- bodystmt kEND
- {
- result = @builder.def_sclass(val[0], val[1], val[2],
- val[5], val[6])
-
- @lexer.pop_cmdarg
- @static_env.unextend
-
- @def_level = val[4]
- }
- | kMODULE cpath
- {
- @static_env.extend_static
- @lexer.push_cmdarg
- }
- bodystmt kEND
- {
- if in_def?
- diagnostic :error, :module_in_def, nil, val[0]
- end
-
- result = @builder.def_module(val[0], val[1],
- val[3], val[4])
-
- @lexer.pop_cmdarg
- @static_env.unextend
- }
- | kDEF fname
- {
- @def_level += 1
- @static_env.extend_static
- @lexer.push_cmdarg
- }
- f_arglist bodystmt kEND
- {
- result = @builder.def_method(val[0], val[1],
- val[3], val[4], val[5])
-
- @lexer.pop_cmdarg
- @static_env.unextend
- @def_level -= 1
- }
- | kDEF singleton dot_or_colon
- {
- @lexer.state = :expr_fname
- }
- fname
- {
- @def_level += 1
- @static_env.extend_static
- @lexer.push_cmdarg
- }
- f_arglist bodystmt kEND
- {
- result = @builder.def_singleton(val[0], val[1], val[2],
- val[4], val[6], val[7], val[8])
-
- @lexer.pop_cmdarg
- @static_env.unextend
- @def_level -= 1
- }
- | kBREAK
- {
- result = @builder.keyword_cmd(:break, val[0])
- }
- | kNEXT
- {
- result = @builder.keyword_cmd(:next, val[0])
- }
- | kREDO
- {
- result = @builder.keyword_cmd(:redo, val[0])
- }
- | kRETRY
- {
- result = @builder.keyword_cmd(:retry, val[0])
- }
-
- primary_value: primary
-
- then: term
- | kTHEN
- | term kTHEN
- {
- result = val[1]
- }
-
- do: term
- | kDO_COND
-
- if_tail: opt_else
- | kELSIF expr_value then compstmt if_tail
- {
- else_t, else_ = val[4]
- result = [ val[0],
- @builder.condition(val[0], val[1], val[2],
- val[3], else_t,
- else_, nil),
- ]
- }
-
- opt_else: none
- | kELSE compstmt
- {
- result = val
- }
-
- for_var: lhs
- | mlhs
-
- f_marg: f_norm_arg
- {
- @static_env.declare val[0][0]
-
- result = @builder.arg(val[0])
- }
- | tLPAREN f_margs rparen
- {
- result = @builder.multi_lhs(val[0], val[1], val[2])
- }
-
- f_marg_list: f_marg
- {
- result = [ val[0] ]
- }
- | f_marg_list tCOMMA f_marg
- {
- result = val[0] << val[2]
- }
-
- f_margs: f_marg_list
- | f_marg_list tCOMMA tSTAR f_norm_arg
- {
- @static_env.declare val[3][0]
-
- result = val[0].
- push(@builder.restarg(val[2], val[3]))
- }
- | f_marg_list tCOMMA tSTAR f_norm_arg tCOMMA f_marg_list
- {
- @static_env.declare val[3][0]
-
- result = val[0].
- push(@builder.restarg(val[2], val[3])).
- concat(val[5])
- }
- | f_marg_list tCOMMA tSTAR
- {
- result = val[0].
- push(@builder.restarg(val[2]))
- }
- | f_marg_list tCOMMA tSTAR tCOMMA f_marg_list
- {
- result = val[0].
- push(@builder.restarg(val[2])).
- concat(val[4])
- }
- | tSTAR f_norm_arg
- {
- @static_env.declare val[1][0]
-
- result = [ @builder.restarg(val[0], val[1]) ]
- }
- | tSTAR f_norm_arg tCOMMA f_marg_list
- {
- @static_env.declare val[1][0]
-
- result = [ @builder.restarg(val[0], val[1]),
- *val[3] ]
- }
- | tSTAR
- {
- result = [ @builder.restarg(val[0]) ]
- }
- | tSTAR tCOMMA f_marg_list
- {
- result = [ @builder.restarg(val[0]),
- *val[2] ]
- }
-
- block_args_tail: f_block_kwarg tCOMMA f_kwrest opt_f_block_arg
- {
- result = val[0].concat(val[2]).concat(val[3])
- }
- | f_block_kwarg opt_f_block_arg
- {
- result = val[0].concat(val[1])
- }
- | f_kwrest opt_f_block_arg
- {
- result = val[0].concat(val[1])
- }
- | f_block_arg
- {
- result = [ val[0] ]
- }
-
-opt_block_args_tail:
- tCOMMA block_args_tail
- {
- result = val[1]
- }
- | # nothing
- {
- result = []
- }
-
- block_param: f_arg tCOMMA f_block_optarg tCOMMA f_rest_arg opt_block_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
- }
- | f_arg tCOMMA f_block_optarg tCOMMA f_rest_arg tCOMMA f_arg opt_block_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[6]).
- concat(val[7])
- }
- | f_arg tCOMMA f_block_optarg opt_block_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | f_arg tCOMMA f_block_optarg tCOMMA f_arg opt_block_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
- }
- | f_arg tCOMMA f_rest_arg opt_block_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | f_arg tCOMMA
- | f_arg tCOMMA f_rest_arg tCOMMA f_arg opt_block_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
- }
- | f_arg opt_block_args_tail
- {
- result = val[0].concat(val[1])
- }
- | f_block_optarg tCOMMA f_rest_arg opt_block_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | f_block_optarg tCOMMA f_rest_arg tCOMMA f_arg opt_block_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
- }
- | f_block_optarg opt_block_args_tail
- {
- result = val[0].
- concat(val[1])
- }
- | f_block_optarg tCOMMA f_arg opt_block_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | f_rest_arg opt_block_args_tail
- {
- result = val[0].
- concat(val[1])
- }
- | f_rest_arg tCOMMA f_arg opt_block_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | block_args_tail
-
- opt_block_param: # nothing
- {
- result = @builder.args(nil, [], nil)
- }
- | block_param_def
- {
- @lexer.state = :expr_value
- }
-
- block_param_def: tPIPE opt_bv_decl tPIPE
- {
- result = @builder.args(val[0], val[1], val[2])
- }
- | tOROP
- {
- result = @builder.args(val[0], [], val[0])
- }
- | tPIPE block_param opt_bv_decl tPIPE
- {
- result = @builder.args(val[0], val[1].concat(val[2]), val[3])
- }
-
- opt_bv_decl: opt_nl
- {
- result = []
- }
- | opt_nl tSEMI bv_decls opt_nl
- {
- result = val[2]
- }
-
- bv_decls: bvar
- {
- result = [ val[0] ]
- }
- | bv_decls tCOMMA bvar
- {
- result = val[0] << val[2]
- }
-
- bvar: tIDENTIFIER
- {
- result = @builder.shadowarg(val[0])
- }
- | f_bad_arg
-
- lambda: {
- @static_env.extend_dynamic
- }
- f_larglist lambda_body
- {
- result = [ val[1], val[2] ]
-
- @static_env.unextend
- }
-
- f_larglist: tLPAREN2 f_args opt_bv_decl tRPAREN
- {
- result = @builder.args(val[0], val[1].concat(val[2]), val[3])
- }
- | f_args
- {
- result = @builder.args(nil, val[0], nil)
- }
-
- lambda_body: tLAMBEG compstmt tRCURLY
- {
- result = [ val[0], val[1], val[2] ]
- }
- | kDO_LAMBDA compstmt kEND
- {
- result = [ val[0], val[1], val[2] ]
- }
-
- do_block: kDO_BLOCK
- {
- @static_env.extend_dynamic
- }
- opt_block_param compstmt kEND
- {
- result = [ val[0], val[2], val[3], val[4] ]
-
- @static_env.unextend
- }
-
- block_call: command do_block
- {
- begin_t, block_args, body, end_t = val[1]
- result = @builder.block(val[0],
- begin_t, block_args, body, end_t)
- }
- | block_call dot_or_colon operation2 opt_paren_args
- {
- lparen_t, args, rparen_t = val[3]
- result = @builder.call_method(val[0], val[1], val[2],
- lparen_t, args, rparen_t)
- }
- | block_call dot_or_colon operation2 opt_paren_args brace_block
- {
- lparen_t, args, rparen_t = val[3]
- method_call = @builder.call_method(val[0], val[1], val[2],
- lparen_t, args, rparen_t)
-
- begin_t, args, body, end_t = val[4]
- result = @builder.block(method_call,
- begin_t, args, body, end_t)
- }
- | block_call dot_or_colon operation2 command_args do_block
- {
- method_call = @builder.call_method(val[0], val[1], val[2],
- nil, val[3], nil)
-
- begin_t, args, body, end_t = val[4]
- result = @builder.block(method_call,
- begin_t, args, body, end_t)
- }
-
- method_call: fcall paren_args
- {
- lparen_t, args, rparen_t = val[1]
- result = @builder.call_method(nil, nil, val[0],
- lparen_t, args, rparen_t)
- }
- | primary_value tDOT operation2 opt_paren_args
- {
- lparen_t, args, rparen_t = val[3]
- result = @builder.call_method(val[0], val[1], val[2],
- lparen_t, args, rparen_t)
- }
- | primary_value tCOLON2 operation2 paren_args
- {
- lparen_t, args, rparen_t = val[3]
- result = @builder.call_method(val[0], val[1], val[2],
- lparen_t, args, rparen_t)
- }
- | primary_value tCOLON2 operation3
- {
- result = @builder.call_method(val[0], val[1], val[2])
- }
- | primary_value tDOT paren_args
- {
- lparen_t, args, rparen_t = val[2]
- result = @builder.call_method(val[0], val[1], nil,
- lparen_t, args, rparen_t)
- }
- | primary_value tCOLON2 paren_args
- {
- lparen_t, args, rparen_t = val[2]
- result = @builder.call_method(val[0], val[1], nil,
- lparen_t, args, rparen_t)
- }
- | kSUPER paren_args
- {
- lparen_t, args, rparen_t = val[1]
- result = @builder.keyword_cmd(:super, val[0],
- lparen_t, args, rparen_t)
- }
- | kSUPER
- {
- result = @builder.keyword_cmd(:zsuper, val[0])
- }
- | primary_value tLBRACK2 opt_call_args rbracket
- {
- result = @builder.index(val[0], val[1], val[2], val[3])
- }
-
- brace_block: tLCURLY
- {
- @static_env.extend_dynamic
- }
- opt_block_param compstmt tRCURLY
- {
- result = [ val[0], val[2], val[3], val[4] ]
-
- @static_env.unextend
- }
- | kDO
- {
- @static_env.extend_dynamic
- }
- opt_block_param compstmt kEND
- {
- result = [ val[0], val[2], val[3], val[4] ]
-
- @static_env.unextend
- }
-
- case_body: kWHEN args then compstmt cases
- {
- result = [ @builder.when(val[0], val[1], val[2], val[3]),
- *val[4] ]
- }
-
- cases: opt_else
- {
- result = [ val[0] ]
- }
- | case_body
-
- opt_rescue: kRESCUE exc_list exc_var then compstmt opt_rescue
- {
- assoc_t, exc_var = val[2]
-
- if val[1]
- exc_list = @builder.array(nil, val[1], nil)
- end
-
- result = [ @builder.rescue_body(val[0],
- exc_list, assoc_t, exc_var,
- val[3], val[4]),
- *val[5] ]
- }
- |
- {
- result = []
- }
-
- exc_list: arg_value
- {
- result = [ val[0] ]
- }
- | mrhs
- | none
-
- exc_var: tASSOC lhs
- {
- result = [ val[0], val[1] ]
- }
- | none
-
- opt_ensure: kENSURE compstmt
- {
- result = [ val[0], val[1] ]
- }
- | none
-
- literal: numeric
- | symbol
- | dsym
-
- strings: string
- {
- result = @builder.string_compose(nil, val[0], nil)
- }
-
- string: string1
- {
- result = [ val[0] ]
- }
- | string string1
- {
- result = val[0] << val[1]
- }
-
- string1: tSTRING_BEG string_contents tSTRING_END
- {
- result = @builder.string_compose(val[0], val[1], val[2])
- }
- | tSTRING
- {
- result = @builder.string(val[0])
- }
- | tCHARACTER
- {
- result = @builder.character(val[0])
- }
-
- xstring: tXSTRING_BEG xstring_contents tSTRING_END
- {
- result = @builder.xstring_compose(val[0], val[1], val[2])
- }
-
- regexp: tREGEXP_BEG regexp_contents tSTRING_END tREGEXP_OPT
- {
- opts = @builder.regexp_options(val[3])
- result = @builder.regexp_compose(val[0], val[1], val[2], opts)
- }
-
- words: tWORDS_BEG word_list tSTRING_END
- {
- result = @builder.words_compose(val[0], val[1], val[2])
- }
-
- word_list: # nothing
- {
- result = []
- }
- | word_list word tSPACE
- {
- result = val[0] << @builder.word(val[1])
- }
-
- word: string_content
- {
- result = [ val[0] ]
- }
- | word string_content
- {
- result = val[0] << val[1]
- }
-
- symbols: tSYMBOLS_BEG symbol_list tSTRING_END
- {
- result = @builder.symbols_compose(val[0], val[1], val[2])
- }
-
- symbol_list: # nothing
- {
- result = []
- }
- | symbol_list word tSPACE
- {
- result = val[0] << @builder.word(val[1])
- }
-
- qwords: tQWORDS_BEG qword_list tSTRING_END
- {
- result = @builder.words_compose(val[0], val[1], val[2])
- }
-
- qsymbols: tQSYMBOLS_BEG qsym_list tSTRING_END
- {
- result = @builder.symbols_compose(val[0], val[1], val[2])
- }
-
- qword_list: # nothing
- {
- result = []
- }
- | qword_list tSTRING_CONTENT tSPACE
- {
- result = val[0] << @builder.string_internal(val[1])
- }
-
- qsym_list: # nothing
- {
- result = []
- }
- | qsym_list tSTRING_CONTENT tSPACE
- {
- result = val[0] << @builder.symbol_internal(val[1])
- }
-
- string_contents: # nothing
- {
- result = []
- }
- | string_contents string_content
- {
- result = val[0] << val[1]
- }
-
-xstring_contents: # nothing
- {
- result = []
- }
- | xstring_contents string_content
- {
- result = val[0] << val[1]
- }
-
-regexp_contents: # nothing
- {
- result = []
- }
- | regexp_contents string_content
- {
- result = val[0] << val[1]
- }
-
- string_content: tSTRING_CONTENT
- {
- result = @builder.string_internal(val[0])
- }
- | tSTRING_DVAR string_dvar
- {
- result = val[1]
- }
- | tSTRING_DBEG
- {
- @lexer.cond.push(false)
- @lexer.cmdarg.push(false)
- }
- compstmt tSTRING_DEND
- {
- @lexer.cond.lexpop
- @lexer.cmdarg.lexpop
-
- result = @builder.begin(val[0], val[2], val[3])
- }
-
- string_dvar: tGVAR
- {
- result = @builder.gvar(val[0])
- }
- | tIVAR
- {
- result = @builder.ivar(val[0])
- }
- | tCVAR
- {
- result = @builder.cvar(val[0])
- }
- | backref
-
-
- symbol: tSYMBOL
- {
- result = @builder.symbol(val[0])
- }
-
- dsym: tSYMBEG xstring_contents tSTRING_END
- {
- result = @builder.symbol_compose(val[0], val[1], val[2])
- }
-
- numeric: tINTEGER
- {
- result = @builder.integer(val[0])
- }
- | tFLOAT
- {
- result = @builder.float(val[0])
- }
- | tUMINUS_NUM tINTEGER =tLOWEST
- {
- result = @builder.negate(val[0],
- @builder.integer(val[1]))
- }
- | tUMINUS_NUM tFLOAT =tLOWEST
- {
- result = @builder.negate(val[0],
- @builder.float(val[1]))
- }
-
- user_variable: tIDENTIFIER
- {
- result = @builder.ident(val[0])
- }
- | tIVAR
- {
- result = @builder.ivar(val[0])
- }
- | tGVAR
- {
- result = @builder.gvar(val[0])
- }
- | tCONSTANT
- {
- result = @builder.const(val[0])
- }
- | tCVAR
- {
- result = @builder.cvar(val[0])
- }
-
-keyword_variable: kNIL
- {
- result = @builder.nil(val[0])
- }
- | kSELF
- {
- result = @builder.self(val[0])
- }
- | kTRUE
- {
- result = @builder.true(val[0])
- }
- | kFALSE
- {
- result = @builder.false(val[0])
- }
- | k__FILE__
- {
- result = @builder.__FILE__(val[0])
- }
- | k__LINE__
- {
- result = @builder.__LINE__(val[0])
- }
- | k__ENCODING__
- {
- result = @builder.__ENCODING__(val[0])
- }
-
- var_ref: user_variable
- {
- result = @builder.accessible(val[0])
- }
- | keyword_variable
- {
- result = @builder.accessible(val[0])
- }
-
- var_lhs: user_variable
- {
- result = @builder.assignable(val[0])
- }
- | keyword_variable
- {
- result = @builder.assignable(val[0])
- }
-
- backref: tNTH_REF
- {
- result = @builder.nth_ref(val[0])
- }
- | tBACK_REF
- {
- result = @builder.back_ref(val[0])
- }
-
- superclass: term
- {
- result = nil
- }
- | tLT
- {
- @lexer.state = :expr_value
- }
- expr_value term
- {
- result = [ val[0], val[2] ]
- }
- | error term
- {
- yyerrok
- result = nil
- }
-
- f_arglist: tLPAREN2 f_args rparen
- {
- result = @builder.args(val[0], val[1], val[2])
-
- @lexer.state = :expr_value
- }
- | f_args term
- {
- result = @builder.args(nil, val[0], nil)
- }
-
- args_tail: f_kwarg tCOMMA f_kwrest opt_f_block_arg
- {
- result = val[0].concat(val[2]).concat(val[3])
- }
- | f_kwarg opt_f_block_arg
- {
- result = val[0].concat(val[1])
- }
- | f_kwrest opt_f_block_arg
- {
- result = val[0].concat(val[1])
- }
- | f_block_arg
- {
- result = [ val[0] ]
- }
-
- opt_args_tail: tCOMMA args_tail
- {
- result = val[1]
- }
- | # nothing
- {
- result = []
- }
-
- f_args: f_arg tCOMMA f_optarg tCOMMA f_rest_arg opt_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
- }
- | f_arg tCOMMA f_optarg tCOMMA f_rest_arg tCOMMA f_arg opt_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[6]).
- concat(val[7])
- }
- | f_arg tCOMMA f_optarg opt_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | f_arg tCOMMA f_optarg tCOMMA f_arg opt_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
- }
- | f_arg tCOMMA f_rest_arg opt_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | f_arg tCOMMA f_rest_arg tCOMMA f_arg opt_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
- }
- | f_arg opt_args_tail
- {
- result = val[0].
- concat(val[1])
- }
- | f_optarg tCOMMA f_rest_arg opt_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | f_optarg tCOMMA f_rest_arg tCOMMA f_arg opt_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
- }
- | f_optarg opt_args_tail
- {
- result = val[0].
- concat(val[1])
- }
- | f_optarg tCOMMA f_arg opt_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | f_rest_arg opt_args_tail
- {
- result = val[0].
- concat(val[1])
- }
- | f_rest_arg tCOMMA f_arg opt_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | args_tail
- {
- result = val[0]
- }
- | # nothing
- {
- result = []
- }
-
- f_bad_arg: tCONSTANT
- {
- diagnostic :error, :argument_const, nil, val[0]
- }
- | tIVAR
- {
- diagnostic :error, :argument_ivar, nil, val[0]
- }
- | tGVAR
- {
- diagnostic :error, :argument_gvar, nil, val[0]
- }
- | tCVAR
- {
- diagnostic :error, :argument_cvar, nil, val[0]
- }
-
- f_norm_arg: f_bad_arg
- | tIDENTIFIER
-
- f_arg_item: f_norm_arg
- {
- @static_env.declare val[0][0]
-
- result = @builder.arg(val[0])
- }
- | tLPAREN f_margs rparen
- {
- result = @builder.multi_lhs(val[0], val[1], val[2])
- }
-
- f_arg: f_arg_item
- {
- result = [ val[0] ]
- }
- | f_arg tCOMMA f_arg_item
- {
- result = val[0] << val[2]
- }
-
- f_kw: tLABEL arg_value
- {
- check_kwarg_name(val[0])
-
- @static_env.declare val[0][0]
-
- result = @builder.kwoptarg(val[0], val[1])
- }
-
- f_block_kw: tLABEL primary_value
- {
- check_kwarg_name(val[0])
-
- @static_env.declare val[0][0]
-
- result = @builder.kwoptarg(val[0], val[1])
- }
-
- f_block_kwarg: f_block_kw
- {
- result = [ val[0] ]
- }
- | f_block_kwarg tCOMMA f_block_kw
- {
- result = val[0] << val[2]
- }
-
- f_kwarg: f_kw
- {
- result = [ val[0] ]
- }
- | f_kwarg tCOMMA f_kw
- {
- result = val[0] << val[2]
- }
-
- kwrest_mark: tPOW | tDSTAR
-
- f_kwrest: kwrest_mark tIDENTIFIER
- {
- @static_env.declare val[1][0]
-
- result = [ @builder.kwrestarg(val[0], val[1]) ]
- }
- | kwrest_mark
- {
- result = [ @builder.kwrestarg(val[0]) ]
- }
-
- f_opt: tIDENTIFIER tEQL arg_value
- {
- @static_env.declare val[0][0]
-
- result = @builder.optarg(val[0], val[1], val[2])
- }
-
- f_block_opt: tIDENTIFIER tEQL primary_value
- {
- @static_env.declare val[0][0]
-
- result = @builder.optarg(val[0], val[1], val[2])
- }
-
- f_block_optarg: f_block_opt
- {
- result = [ val[0] ]
- }
- | f_block_optarg tCOMMA f_block_opt
- {
- result = val[0] << val[2]
- }
-
- f_optarg: f_opt
- {
- result = [ val[0] ]
- }
- | f_optarg tCOMMA f_opt
- {
- result = val[0] << val[2]
- }
-
- restarg_mark: tSTAR2 | tSTAR
-
- f_rest_arg: restarg_mark tIDENTIFIER
- {
- @static_env.declare val[1][0]
-
- result = [ @builder.restarg(val[0], val[1]) ]
- }
- | restarg_mark
- {
- result = [ @builder.restarg(val[0]) ]
- }
-
- blkarg_mark: tAMPER2 | tAMPER
-
- f_block_arg: blkarg_mark tIDENTIFIER
- {
- @static_env.declare val[1][0]
-
- result = @builder.blockarg(val[0], val[1])
- }
-
- opt_f_block_arg: tCOMMA f_block_arg
- {
- result = [ val[1] ]
- }
- |
- {
- result = []
- }
-
- singleton: var_ref
- | tLPAREN2 expr rparen
- {
- result = val[1]
- }
-
- assoc_list: # nothing
- {
- result = []
- }
- | assocs trailer
-
- assocs: assoc
- {
- result = [ val[0] ]
- }
- | assocs tCOMMA assoc
- {
- result = val[0] << val[2]
- }
-
- assoc: arg_value tASSOC arg_value
- {
- result = @builder.pair(val[0], val[1], val[2])
- }
- | tLABEL arg_value
- {
- result = @builder.pair_keyword(val[0], val[1])
- }
- | tDSTAR arg_value
- {
- result = @builder.kwsplat(val[0], val[1])
- }
-
- operation: tIDENTIFIER | tCONSTANT | tFID
- operation2: tIDENTIFIER | tCONSTANT | tFID | op
- operation3: tIDENTIFIER | tFID | op
- dot_or_colon: tDOT | tCOLON2
- opt_terms: | terms
- opt_nl: | tNL
- rparen: opt_nl tRPAREN
- {
- result = val[1]
- }
- rbracket: opt_nl tRBRACK
- {
- result = val[1]
- }
- trailer: | tNL | tCOMMA
-
- term: tSEMI
- {
- yyerrok
- }
- | tNL
-
- terms: term
- | terms tSEMI
-
- none: # nothing
- {
- result = nil
- }
-end
-
----- header
-
-require 'parser'
-
-Parser.check_for_encoding_support
-
----- inner
-
- def version
- 20
- end
-
- def default_encoding
- Encoding::UTF_8
- end
diff --git a/test/racc/assets/ruby21.y b/test/racc/assets/ruby21.y
deleted file mode 100644
index 2ac94afb0c..0000000000
--- a/test/racc/assets/ruby21.y
+++ /dev/null
@@ -1,2359 +0,0 @@
-# Copyright (c) 2013 Peter Zotov <whitequark@whitequark.org>
-#
-# Parts of the source are derived from ruby_parser:
-# Copyright (c) Ryan Davis, seattle.rb
-#
-# MIT License
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-class Parser::Ruby21
-
-token kCLASS kMODULE kDEF kUNDEF kBEGIN kRESCUE kENSURE kEND kIF kUNLESS
- kTHEN kELSIF kELSE kCASE kWHEN kWHILE kUNTIL kFOR kBREAK kNEXT
- kREDO kRETRY kIN kDO kDO_COND kDO_BLOCK kDO_LAMBDA kRETURN kYIELD kSUPER
- kSELF kNIL kTRUE kFALSE kAND kOR kNOT kIF_MOD kUNLESS_MOD kWHILE_MOD
- kUNTIL_MOD kRESCUE_MOD kALIAS kDEFINED klBEGIN klEND k__LINE__
- k__FILE__ k__ENCODING__ tIDENTIFIER tFID tGVAR tIVAR tCONSTANT
- tLABEL tCVAR tNTH_REF tBACK_REF tSTRING_CONTENT tINTEGER tFLOAT
- tREGEXP_END tUPLUS tUMINUS tUMINUS_NUM tPOW tCMP tEQ tEQQ tNEQ
- tGEQ tLEQ tANDOP tOROP tMATCH tNMATCH tDOT tDOT2 tDOT3 tAREF
- tASET tLSHFT tRSHFT tCOLON2 tCOLON3 tOP_ASGN tASSOC tLPAREN
- tLPAREN2 tRPAREN tLPAREN_ARG tLBRACK tLBRACK2 tRBRACK tLBRACE
- tLBRACE_ARG tSTAR tSTAR2 tAMPER tAMPER2 tTILDE tPERCENT tDIVIDE
- tDSTAR tPLUS tMINUS tLT tGT tPIPE tBANG tCARET tLCURLY tRCURLY
- tBACK_REF2 tSYMBEG tSTRING_BEG tXSTRING_BEG tREGEXP_BEG tREGEXP_OPT
- tWORDS_BEG tQWORDS_BEG tSYMBOLS_BEG tQSYMBOLS_BEG tSTRING_DBEG
- tSTRING_DVAR tSTRING_END tSTRING_DEND tSTRING tSYMBOL
- tNL tEH tCOLON tCOMMA tSPACE tSEMI tLAMBDA tLAMBEG tCHARACTER
- tRATIONAL tIMAGINARY
-
-prechigh
- right tBANG tTILDE tUPLUS
- right tPOW
- right tUMINUS_NUM tUMINUS
- left tSTAR2 tDIVIDE tPERCENT
- left tPLUS tMINUS
- left tLSHFT tRSHFT
- left tAMPER2
- left tPIPE tCARET
- left tGT tGEQ tLT tLEQ
- nonassoc tCMP tEQ tEQQ tNEQ tMATCH tNMATCH
- left tANDOP
- left tOROP
- nonassoc tDOT2 tDOT3
- right tEH tCOLON
- left kRESCUE_MOD
- right tEQL tOP_ASGN
- nonassoc kDEFINED
- right kNOT
- left kOR kAND
- nonassoc kIF_MOD kUNLESS_MOD kWHILE_MOD kUNTIL_MOD
- nonassoc tLBRACE_ARG
- nonassoc tLOWEST
-preclow
-
-rule
-
- program: top_compstmt
-
- top_compstmt: top_stmts opt_terms
- {
- result = @builder.compstmt(val[0])
- }
-
- top_stmts: # nothing
- {
- result = []
- }
- | top_stmt
- {
- result = [ val[0] ]
- }
- | top_stmts terms top_stmt
- {
- result = val[0] << val[2]
- }
- | error top_stmt
- {
- result = [ val[1] ]
- }
-
- top_stmt: stmt
- | klBEGIN tLCURLY top_compstmt tRCURLY
- {
- result = @builder.preexe(val[0], val[1], val[2], val[3])
- }
-
- bodystmt: compstmt opt_rescue opt_else opt_ensure
- {
- rescue_bodies = val[1]
- else_t, else_ = val[2]
- ensure_t, ensure_ = val[3]
-
- if rescue_bodies.empty? && !else_.nil?
- diagnostic :warning, :useless_else, nil, else_t
- end
-
- result = @builder.begin_body(val[0],
- rescue_bodies,
- else_t, else_,
- ensure_t, ensure_)
- }
-
- compstmt: stmts opt_terms
- {
- result = @builder.compstmt(val[0])
- }
-
- stmts: # nothing
- {
- result = []
- }
- | stmt_or_begin
- {
- result = [ val[0] ]
- }
- | stmts terms stmt_or_begin
- {
- result = val[0] << val[2]
- }
- | error stmt
- {
- result = [ val[1] ]
- }
-
- stmt_or_begin: stmt
- | klBEGIN tLCURLY top_compstmt tRCURLY
- {
- diagnostic :error, :begin_in_method, nil, val[0]
- }
-
- stmt: kALIAS fitem
- {
- @lexer.state = :expr_fname
- }
- fitem
- {
- result = @builder.alias(val[0], val[1], val[3])
- }
- | kALIAS tGVAR tGVAR
- {
- result = @builder.alias(val[0],
- @builder.gvar(val[1]),
- @builder.gvar(val[2]))
- }
- | kALIAS tGVAR tBACK_REF
- {
- result = @builder.alias(val[0],
- @builder.gvar(val[1]),
- @builder.back_ref(val[2]))
- }
- | kALIAS tGVAR tNTH_REF
- {
- diagnostic :error, :nth_ref_alias, nil, val[2]
- }
- | kUNDEF undef_list
- {
- result = @builder.undef_method(val[0], val[1])
- }
- | stmt kIF_MOD expr_value
- {
- result = @builder.condition_mod(val[0], nil,
- val[1], val[2])
- }
- | stmt kUNLESS_MOD expr_value
- {
- result = @builder.condition_mod(nil, val[0],
- val[1], val[2])
- }
- | stmt kWHILE_MOD expr_value
- {
- result = @builder.loop_mod(:while, val[0], val[1], val[2])
- }
- | stmt kUNTIL_MOD expr_value
- {
- result = @builder.loop_mod(:until, val[0], val[1], val[2])
- }
- | stmt kRESCUE_MOD stmt
- {
- rescue_body = @builder.rescue_body(val[1],
- nil, nil, nil,
- nil, val[2])
-
- result = @builder.begin_body(val[0], [ rescue_body ])
- }
- | klEND tLCURLY compstmt tRCURLY
- {
- result = @builder.postexe(val[0], val[1], val[2], val[3])
- }
- | command_asgn
- | mlhs tEQL command_call
- {
- result = @builder.multi_assign(val[0], val[1], val[2])
- }
- | var_lhs tOP_ASGN command_call
- {
- result = @builder.op_assign(val[0], val[1], val[2])
- }
- | primary_value tLBRACK2 opt_call_args rbracket tOP_ASGN command_call
- {
- result = @builder.op_assign(
- @builder.index(
- val[0], val[1], val[2], val[3]),
- val[4], val[5])
- }
- | primary_value tDOT tIDENTIFIER tOP_ASGN command_call
- {
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
- }
- | primary_value tDOT tCONSTANT tOP_ASGN command_call
- {
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
- }
- | primary_value tCOLON2 tCONSTANT tOP_ASGN command_call
- {
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
- }
- | primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_call
- {
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
- }
- | backref tOP_ASGN command_call
- {
- @builder.op_assign(val[0], val[1], val[2])
- }
- | lhs tEQL mrhs
- {
- result = @builder.assign(val[0], val[1],
- @builder.array(nil, val[2], nil))
- }
- | mlhs tEQL mrhs_arg
- {
- result = @builder.multi_assign(val[0], val[1], val[2])
- }
- | expr
-
- command_asgn: lhs tEQL command_call
- {
- result = @builder.assign(val[0], val[1], val[2])
- }
- | lhs tEQL command_asgn
- {
- result = @builder.assign(val[0], val[1], val[2])
- }
-
- expr: command_call
- | expr kAND expr
- {
- result = @builder.logical_op(:and, val[0], val[1], val[2])
- }
- | expr kOR expr
- {
- result = @builder.logical_op(:or, val[0], val[1], val[2])
- }
- | kNOT opt_nl expr
- {
- result = @builder.not_op(val[0], nil, val[2], nil)
- }
- | tBANG command_call
- {
- result = @builder.not_op(val[0], nil, val[1], nil)
- }
- | arg
-
- expr_value: expr
-
- command_call: command
- | block_command
-
- block_command: block_call
- | block_call dot_or_colon operation2 command_args
- {
- result = @builder.call_method(val[0], val[1], val[2],
- nil, val[3], nil)
- }
-
- cmd_brace_block: tLBRACE_ARG
- {
- @static_env.extend_dynamic
- }
- opt_block_param compstmt tRCURLY
- {
- result = [ val[0], val[2], val[3], val[4] ]
-
- @static_env.unextend
- }
-
- fcall: operation
-
- command: fcall command_args =tLOWEST
- {
- result = @builder.call_method(nil, nil, val[0],
- nil, val[1], nil)
- }
- | fcall command_args cmd_brace_block
- {
- method_call = @builder.call_method(nil, nil, val[0],
- nil, val[1], nil)
-
- begin_t, args, body, end_t = val[2]
- result = @builder.block(method_call,
- begin_t, args, body, end_t)
- }
- | primary_value tDOT operation2 command_args =tLOWEST
- {
- result = @builder.call_method(val[0], val[1], val[2],
- nil, val[3], nil)
- }
- | primary_value tDOT operation2 command_args cmd_brace_block
- {
- method_call = @builder.call_method(val[0], val[1], val[2],
- nil, val[3], nil)
-
- begin_t, args, body, end_t = val[4]
- result = @builder.block(method_call,
- begin_t, args, body, end_t)
- }
- | primary_value tCOLON2 operation2 command_args =tLOWEST
- {
- result = @builder.call_method(val[0], val[1], val[2],
- nil, val[3], nil)
- }
- | primary_value tCOLON2 operation2 command_args cmd_brace_block
- {
- method_call = @builder.call_method(val[0], val[1], val[2],
- nil, val[3], nil)
-
- begin_t, args, body, end_t = val[4]
- result = @builder.block(method_call,
- begin_t, args, body, end_t)
- }
- | kSUPER command_args
- {
- result = @builder.keyword_cmd(:super, val[0],
- nil, val[1], nil)
- }
- | kYIELD command_args
- {
- result = @builder.keyword_cmd(:yield, val[0],
- nil, val[1], nil)
- }
- | kRETURN call_args
- {
- result = @builder.keyword_cmd(:return, val[0],
- nil, val[1], nil)
- }
- | kBREAK call_args
- {
- result = @builder.keyword_cmd(:break, val[0],
- nil, val[1], nil)
- }
- | kNEXT call_args
- {
- result = @builder.keyword_cmd(:next, val[0],
- nil, val[1], nil)
- }
-
- mlhs: mlhs_basic
- {
- result = @builder.multi_lhs(nil, val[0], nil)
- }
- | tLPAREN mlhs_inner rparen
- {
- result = @builder.begin(val[0], val[1], val[2])
- }
-
- mlhs_inner: mlhs_basic
- {
- result = @builder.multi_lhs(nil, val[0], nil)
- }
- | tLPAREN mlhs_inner rparen
- {
- result = @builder.multi_lhs(val[0], val[1], val[2])
- }
-
- mlhs_basic: mlhs_head
- | mlhs_head mlhs_item
- {
- result = val[0].
- push(val[1])
- }
- | mlhs_head tSTAR mlhs_node
- {
- result = val[0].
- push(@builder.splat(val[1], val[2]))
- }
- | mlhs_head tSTAR mlhs_node tCOMMA mlhs_post
- {
- result = val[0].
- push(@builder.splat(val[1], val[2])).
- concat(val[4])
- }
- | mlhs_head tSTAR
- {
- result = val[0].
- push(@builder.splat(val[1]))
- }
- | mlhs_head tSTAR tCOMMA mlhs_post
- {
- result = val[0].
- push(@builder.splat(val[1])).
- concat(val[3])
- }
- | tSTAR mlhs_node
- {
- result = [ @builder.splat(val[0], val[1]) ]
- }
- | tSTAR mlhs_node tCOMMA mlhs_post
- {
- result = [ @builder.splat(val[0], val[1]),
- *val[3] ]
- }
- | tSTAR
- {
- result = [ @builder.splat(val[0]) ]
- }
- | tSTAR tCOMMA mlhs_post
- {
- result = [ @builder.splat(val[0]),
- *val[2] ]
- }
-
- mlhs_item: mlhs_node
- | tLPAREN mlhs_inner rparen
- {
- result = @builder.begin(val[0], val[1], val[2])
- }
-
- mlhs_head: mlhs_item tCOMMA
- {
- result = [ val[0] ]
- }
- | mlhs_head mlhs_item tCOMMA
- {
- result = val[0] << val[1]
- }
-
- mlhs_post: mlhs_item
- {
- result = [ val[0] ]
- }
- | mlhs_post tCOMMA mlhs_item
- {
- result = val[0] << val[2]
- }
-
- mlhs_node: user_variable
- {
- result = @builder.assignable(val[0])
- }
- | keyword_variable
- {
- result = @builder.assignable(val[0])
- }
- | primary_value tLBRACK2 opt_call_args rbracket
- {
- result = @builder.index_asgn(val[0], val[1], val[2], val[3])
- }
- | primary_value tDOT tIDENTIFIER
- {
- result = @builder.attr_asgn(val[0], val[1], val[2])
- }
- | primary_value tCOLON2 tIDENTIFIER
- {
- result = @builder.attr_asgn(val[0], val[1], val[2])
- }
- | primary_value tDOT tCONSTANT
- {
- result = @builder.attr_asgn(val[0], val[1], val[2])
- }
- | primary_value tCOLON2 tCONSTANT
- {
- result = @builder.assignable(
- @builder.const_fetch(val[0], val[1], val[2]))
- }
- | tCOLON3 tCONSTANT
- {
- result = @builder.assignable(
- @builder.const_global(val[0], val[1]))
- }
- | backref
- {
- result = @builder.assignable(val[0])
- }
-
- lhs: user_variable
- {
- result = @builder.assignable(val[0])
- }
- | keyword_variable
- {
- result = @builder.assignable(val[0])
- }
- | primary_value tLBRACK2 opt_call_args rbracket
- {
- result = @builder.index_asgn(val[0], val[1], val[2], val[3])
- }
- | primary_value tDOT tIDENTIFIER
- {
- result = @builder.attr_asgn(val[0], val[1], val[2])
- }
- | primary_value tCOLON2 tIDENTIFIER
- {
- result = @builder.attr_asgn(val[0], val[1], val[2])
- }
- | primary_value tDOT tCONSTANT
- {
- result = @builder.attr_asgn(val[0], val[1], val[2])
- }
- | primary_value tCOLON2 tCONSTANT
- {
- result = @builder.assignable(
- @builder.const_fetch(val[0], val[1], val[2]))
- }
- | tCOLON3 tCONSTANT
- {
- result = @builder.assignable(
- @builder.const_global(val[0], val[1]))
- }
- | backref
- {
- result = @builder.assignable(val[0])
- }
-
- cname: tIDENTIFIER
- {
- diagnostic :error, :module_name_const, nil, val[0]
- }
- | tCONSTANT
-
- cpath: tCOLON3 cname
- {
- result = @builder.const_global(val[0], val[1])
- }
- | cname
- {
- result = @builder.const(val[0])
- }
- | primary_value tCOLON2 cname
- {
- result = @builder.const_fetch(val[0], val[1], val[2])
- }
-
- fname: tIDENTIFIER | tCONSTANT | tFID
- | op
- | reswords
-
- fsym: fname
- {
- result = @builder.symbol(val[0])
- }
- | symbol
-
- fitem: fsym
- | dsym
-
- undef_list: fitem
- {
- result = [ val[0] ]
- }
- | undef_list tCOMMA
- {
- @lexer.state = :expr_fname
- }
- fitem
- {
- result = val[0] << val[3]
- }
-
- op: tPIPE | tCARET | tAMPER2 | tCMP | tEQ | tEQQ
- | tMATCH | tNMATCH | tGT | tGEQ | tLT | tLEQ
- | tNEQ | tLSHFT | tRSHFT | tPLUS | tMINUS | tSTAR2
- | tSTAR | tDIVIDE | tPERCENT | tPOW | tBANG | tTILDE
- | tUPLUS | tUMINUS | tAREF | tASET | tDSTAR | tBACK_REF2
-
- reswords: k__LINE__ | k__FILE__ | k__ENCODING__ | klBEGIN | klEND
- | kALIAS | kAND | kBEGIN | kBREAK | kCASE
- | kCLASS | kDEF | kDEFINED | kDO | kELSE
- | kELSIF | kEND | kENSURE | kFALSE | kFOR
- | kIN | kMODULE | kNEXT | kNIL | kNOT
- | kOR | kREDO | kRESCUE | kRETRY | kRETURN
- | kSELF | kSUPER | kTHEN | kTRUE | kUNDEF
- | kWHEN | kYIELD | kIF | kUNLESS | kWHILE
- | kUNTIL
-
- arg: lhs tEQL arg
- {
- result = @builder.assign(val[0], val[1], val[2])
- }
- | lhs tEQL arg kRESCUE_MOD arg
- {
- rescue_body = @builder.rescue_body(val[3],
- nil, nil, nil,
- nil, val[4])
-
- rescue_ = @builder.begin_body(val[2], [ rescue_body ])
-
- result = @builder.assign(val[0], val[1], rescue_)
- }
- | var_lhs tOP_ASGN arg
- {
- result = @builder.op_assign(val[0], val[1], val[2])
- }
- | var_lhs tOP_ASGN arg kRESCUE_MOD arg
- {
- rescue_body = @builder.rescue_body(val[3],
- nil, nil, nil,
- nil, val[4])
-
- rescue_ = @builder.begin_body(val[2], [ rescue_body ])
-
- result = @builder.op_assign(val[0], val[1], rescue_)
- }
- | primary_value tLBRACK2 opt_call_args rbracket tOP_ASGN arg
- {
- result = @builder.op_assign(
- @builder.index(
- val[0], val[1], val[2], val[3]),
- val[4], val[5])
- }
- | primary_value tDOT tIDENTIFIER tOP_ASGN arg
- {
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
- }
- | primary_value tDOT tCONSTANT tOP_ASGN arg
- {
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
- }
- | primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg
- {
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
- }
- | primary_value tCOLON2 tCONSTANT tOP_ASGN arg
- {
- const = @builder.const_op_assignable(
- @builder.const_fetch(val[0], val[1], val[2]))
- result = @builder.op_assign(const, val[3], val[4])
- }
- | tCOLON3 tCONSTANT tOP_ASGN arg
- {
- const = @builder.const_op_assignable(
- @builder.const_global(val[0], val[1]))
- result = @builder.op_assign(const, val[2], val[3])
- }
- | backref tOP_ASGN arg
- {
- result = @builder.op_assign(val[0], val[1], val[2])
- }
- | arg tDOT2 arg
- {
- result = @builder.range_inclusive(val[0], val[1], val[2])
- }
- | arg tDOT3 arg
- {
- result = @builder.range_exclusive(val[0], val[1], val[2])
- }
- | arg tPLUS arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tMINUS arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tSTAR2 arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tDIVIDE arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tPERCENT arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tPOW arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | tUMINUS_NUM simple_numeric tPOW arg
- {
- result = @builder.unary_op(val[0],
- @builder.binary_op(
- val[1], val[2], val[3]))
- }
- | tUPLUS arg
- {
- result = @builder.unary_op(val[0], val[1])
- }
- | tUMINUS arg
- {
- result = @builder.unary_op(val[0], val[1])
- }
- | arg tPIPE arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tCARET arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tAMPER2 arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tCMP arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tGT arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tGEQ arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tLT arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tLEQ arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tEQ arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tEQQ arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tNEQ arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tMATCH arg
- {
- result = @builder.match_op(val[0], val[1], val[2])
- }
- | arg tNMATCH arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | tBANG arg
- {
- result = @builder.not_op(val[0], nil, val[1], nil)
- }
- | tTILDE arg
- {
- result = @builder.unary_op(val[0], val[1])
- }
- | arg tLSHFT arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tRSHFT arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tANDOP arg
- {
- result = @builder.logical_op(:and, val[0], val[1], val[2])
- }
- | arg tOROP arg
- {
- result = @builder.logical_op(:or, val[0], val[1], val[2])
- }
- | kDEFINED opt_nl arg
- {
- result = @builder.keyword_cmd(:defined?, val[0], nil, [ val[2] ], nil)
- }
-
- | arg tEH arg opt_nl tCOLON arg
- {
- result = @builder.ternary(val[0], val[1],
- val[2], val[4], val[5])
- }
- | primary
-
- arg_value: arg
-
- aref_args: none
- | args trailer
- | args tCOMMA assocs trailer
- {
- result = val[0] << @builder.associate(nil, val[2], nil)
- }
- | assocs trailer
- {
- result = [ @builder.associate(nil, val[0], nil) ]
- }
-
- paren_args: tLPAREN2 opt_call_args rparen
- {
- result = val
- }
-
- opt_paren_args: # nothing
- {
- result = [ nil, [], nil ]
- }
- | paren_args
-
- opt_call_args: # nothing
- {
- result = []
- }
- | call_args
- | args tCOMMA
- | args tCOMMA assocs tCOMMA
- {
- result = val[0] << @builder.associate(nil, val[2], nil)
- }
- | assocs tCOMMA
- {
- result = [ @builder.associate(nil, val[0], nil) ]
- }
-
- call_args: command
- {
- result = [ val[0] ]
- }
- | args opt_block_arg
- {
- result = val[0].concat(val[1])
- }
- | assocs opt_block_arg
- {
- result = [ @builder.associate(nil, val[0], nil) ]
- result.concat(val[1])
- }
- | args tCOMMA assocs opt_block_arg
- {
- assocs = @builder.associate(nil, val[2], nil)
- result = val[0] << assocs
- result.concat(val[3])
- }
- | block_arg
- {
- result = [ val[0] ]
- }
-
- command_args: {
- result = @lexer.cmdarg.dup
- @lexer.cmdarg.push(true)
- }
- call_args
- {
- @lexer.cmdarg = val[0]
-
- result = val[1]
- }
-
- block_arg: tAMPER arg_value
- {
- result = @builder.block_pass(val[0], val[1])
- }
-
- opt_block_arg: tCOMMA block_arg
- {
- result = [ val[1] ]
- }
- | # nothing
- {
- result = []
- }
-
- args: arg_value
- {
- result = [ val[0] ]
- }
- | tSTAR arg_value
- {
- result = [ @builder.splat(val[0], val[1]) ]
- }
- | args tCOMMA arg_value
- {
- result = val[0] << val[2]
- }
- | args tCOMMA tSTAR arg_value
- {
- result = val[0] << @builder.splat(val[2], val[3])
- }
-
- mrhs_arg: mrhs
- {
- result = @builder.array(nil, val[0], nil)
- }
- | arg_value
-
- mrhs: args tCOMMA arg_value
- {
- result = val[0] << val[2]
- }
- | args tCOMMA tSTAR arg_value
- {
- result = val[0] << @builder.splat(val[2], val[3])
- }
- | tSTAR arg_value
- {
- result = [ @builder.splat(val[0], val[1]) ]
- }
-
- primary: literal
- | strings
- | xstring
- | regexp
- | words
- | qwords
- | symbols
- | qsymbols
- | var_ref
- | backref
- | tFID
- {
- result = @builder.call_method(nil, nil, val[0])
- }
- | kBEGIN
- {
- result = @lexer.cmdarg.dup
- @lexer.cmdarg.clear
- }
- bodystmt kEND
- {
- @lexer.cmdarg = val[1]
-
- result = @builder.begin_keyword(val[0], val[2], val[3])
- }
- | tLPAREN_ARG
- {
- result = @lexer.cmdarg.dup
- @lexer.cmdarg.clear
- }
- expr
- {
- @lexer.state = :expr_endarg
- }
- opt_nl tRPAREN
- {
- @lexer.cmdarg = val[1]
-
- result = @builder.begin(val[0], val[2], val[5])
- }
- | tLPAREN_ARG
- {
- @lexer.state = :expr_endarg
- }
- opt_nl tRPAREN
- {
- result = @builder.begin(val[0], nil, val[3])
- }
- | tLPAREN compstmt tRPAREN
- {
- result = @builder.begin(val[0], val[1], val[2])
- }
- | primary_value tCOLON2 tCONSTANT
- {
- result = @builder.const_fetch(val[0], val[1], val[2])
- }
- | tCOLON3 tCONSTANT
- {
- result = @builder.const_global(val[0], val[1])
- }
- | tLBRACK aref_args tRBRACK
- {
- result = @builder.array(val[0], val[1], val[2])
- }
- | tLBRACE assoc_list tRCURLY
- {
- result = @builder.associate(val[0], val[1], val[2])
- }
- | kRETURN
- {
- result = @builder.keyword_cmd(:return, val[0])
- }
- | kYIELD tLPAREN2 call_args rparen
- {
- result = @builder.keyword_cmd(:yield, val[0], val[1], val[2], val[3])
- }
- | kYIELD tLPAREN2 rparen
- {
- result = @builder.keyword_cmd(:yield, val[0], val[1], [], val[2])
- }
- | kYIELD
- {
- result = @builder.keyword_cmd(:yield, val[0])
- }
- | kDEFINED opt_nl tLPAREN2 expr rparen
- {
- result = @builder.keyword_cmd(:defined?, val[0],
- val[2], [ val[3] ], val[4])
- }
- | kNOT tLPAREN2 expr rparen
- {
- result = @builder.not_op(val[0], val[1], val[2], val[3])
- }
- | kNOT tLPAREN2 rparen
- {
- result = @builder.not_op(val[0], val[1], nil, val[2])
- }
- | fcall brace_block
- {
- method_call = @builder.call_method(nil, nil, val[0])
-
- begin_t, args, body, end_t = val[1]
- result = @builder.block(method_call,
- begin_t, args, body, end_t)
- }
- | method_call
- | method_call brace_block
- {
- begin_t, args, body, end_t = val[1]
- result = @builder.block(val[0],
- begin_t, args, body, end_t)
- }
- | tLAMBDA lambda
- {
- lambda_call = @builder.call_lambda(val[0])
-
- args, (begin_t, body, end_t) = val[1]
- result = @builder.block(lambda_call,
- begin_t, args, body, end_t)
- }
- | kIF expr_value then compstmt if_tail kEND
- {
- else_t, else_ = val[4]
- result = @builder.condition(val[0], val[1], val[2],
- val[3], else_t,
- else_, val[5])
- }
- | kUNLESS expr_value then compstmt opt_else kEND
- {
- else_t, else_ = val[4]
- result = @builder.condition(val[0], val[1], val[2],
- else_, else_t,
- val[3], val[5])
- }
- | kWHILE
- {
- @lexer.cond.push(true)
- }
- expr_value do
- {
- @lexer.cond.pop
- }
- compstmt kEND
- {
- result = @builder.loop(:while, val[0], val[2], val[3],
- val[5], val[6])
- }
- | kUNTIL
- {
- @lexer.cond.push(true)
- }
- expr_value do
- {
- @lexer.cond.pop
- }
- compstmt kEND
- {
- result = @builder.loop(:until, val[0], val[2], val[3],
- val[5], val[6])
- }
- | kCASE expr_value opt_terms case_body kEND
- {
- *when_bodies, (else_t, else_body) = *val[3]
-
- result = @builder.case(val[0], val[1],
- when_bodies, else_t, else_body,
- val[4])
- }
- | kCASE opt_terms case_body kEND
- {
- *when_bodies, (else_t, else_body) = *val[2]
-
- result = @builder.case(val[0], nil,
- when_bodies, else_t, else_body,
- val[3])
- }
- | kFOR for_var kIN
- {
- @lexer.cond.push(true)
- }
- expr_value do
- {
- @lexer.cond.pop
- }
- compstmt kEND
- {
- result = @builder.for(val[0], val[1],
- val[2], val[4],
- val[5], val[7], val[8])
- }
- | kCLASS cpath superclass
- {
- @static_env.extend_static
- @lexer.push_cmdarg
- }
- bodystmt kEND
- {
- if in_def?
- diagnostic :error, :class_in_def, nil, val[0]
- end
-
- lt_t, superclass = val[2]
- result = @builder.def_class(val[0], val[1],
- lt_t, superclass,
- val[4], val[5])
-
- @lexer.pop_cmdarg
- @static_env.unextend
- }
- | kCLASS tLSHFT expr term
- {
- result = @def_level
- @def_level = 0
-
- @static_env.extend_static
- @lexer.push_cmdarg
- }
- bodystmt kEND
- {
- result = @builder.def_sclass(val[0], val[1], val[2],
- val[5], val[6])
-
- @lexer.pop_cmdarg
- @static_env.unextend
-
- @def_level = val[4]
- }
- | kMODULE cpath
- {
- @static_env.extend_static
- @lexer.push_cmdarg
- }
- bodystmt kEND
- {
- if in_def?
- diagnostic :error, :module_in_def, nil, val[0]
- end
-
- result = @builder.def_module(val[0], val[1],
- val[3], val[4])
-
- @lexer.pop_cmdarg
- @static_env.unextend
- }
- | kDEF fname
- {
- @def_level += 1
- @static_env.extend_static
- @lexer.push_cmdarg
- }
- f_arglist bodystmt kEND
- {
- result = @builder.def_method(val[0], val[1],
- val[3], val[4], val[5])
-
- @lexer.pop_cmdarg
- @static_env.unextend
- @def_level -= 1
- }
- | kDEF singleton dot_or_colon
- {
- @lexer.state = :expr_fname
- }
- fname
- {
- @def_level += 1
- @static_env.extend_static
- @lexer.push_cmdarg
- }
- f_arglist bodystmt kEND
- {
- result = @builder.def_singleton(val[0], val[1], val[2],
- val[4], val[6], val[7], val[8])
-
- @lexer.pop_cmdarg
- @static_env.unextend
- @def_level -= 1
- }
- | kBREAK
- {
- result = @builder.keyword_cmd(:break, val[0])
- }
- | kNEXT
- {
- result = @builder.keyword_cmd(:next, val[0])
- }
- | kREDO
- {
- result = @builder.keyword_cmd(:redo, val[0])
- }
- | kRETRY
- {
- result = @builder.keyword_cmd(:retry, val[0])
- }
-
- primary_value: primary
-
- then: term
- | kTHEN
- | term kTHEN
- {
- result = val[1]
- }
-
- do: term
- | kDO_COND
-
- if_tail: opt_else
- | kELSIF expr_value then compstmt if_tail
- {
- else_t, else_ = val[4]
- result = [ val[0],
- @builder.condition(val[0], val[1], val[2],
- val[3], else_t,
- else_, nil),
- ]
- }
-
- opt_else: none
- | kELSE compstmt
- {
- result = val
- }
-
- for_var: lhs
- | mlhs
-
- f_marg: f_norm_arg
- {
- result = @builder.arg(val[0])
- }
- | tLPAREN f_margs rparen
- {
- result = @builder.multi_lhs(val[0], val[1], val[2])
- }
-
- f_marg_list: f_marg
- {
- result = [ val[0] ]
- }
- | f_marg_list tCOMMA f_marg
- {
- result = val[0] << val[2]
- }
-
- f_margs: f_marg_list
- | f_marg_list tCOMMA tSTAR f_norm_arg
- {
- result = val[0].
- push(@builder.restarg(val[2], val[3]))
- }
- | f_marg_list tCOMMA tSTAR f_norm_arg tCOMMA f_marg_list
- {
- result = val[0].
- push(@builder.restarg(val[2], val[3])).
- concat(val[5])
- }
- | f_marg_list tCOMMA tSTAR
- {
- result = val[0].
- push(@builder.restarg(val[2]))
- }
- | f_marg_list tCOMMA tSTAR tCOMMA f_marg_list
- {
- result = val[0].
- push(@builder.restarg(val[2])).
- concat(val[4])
- }
- | tSTAR f_norm_arg
- {
- result = [ @builder.restarg(val[0], val[1]) ]
- }
- | tSTAR f_norm_arg tCOMMA f_marg_list
- {
- result = [ @builder.restarg(val[0], val[1]),
- *val[3] ]
- }
- | tSTAR
- {
- result = [ @builder.restarg(val[0]) ]
- }
- | tSTAR tCOMMA f_marg_list
- {
- result = [ @builder.restarg(val[0]),
- *val[2] ]
- }
-
- block_args_tail: f_block_kwarg tCOMMA f_kwrest opt_f_block_arg
- {
- result = val[0].concat(val[2]).concat(val[3])
- }
- | f_block_kwarg opt_f_block_arg
- {
- result = val[0].concat(val[1])
- }
- | f_kwrest opt_f_block_arg
- {
- result = val[0].concat(val[1])
- }
- | f_block_arg
- {
- result = [ val[0] ]
- }
-
-opt_block_args_tail:
- tCOMMA block_args_tail
- {
- result = val[1]
- }
- | # nothing
- {
- result = []
- }
-
- block_param: f_arg tCOMMA f_block_optarg tCOMMA f_rest_arg opt_block_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
- }
- | f_arg tCOMMA f_block_optarg tCOMMA f_rest_arg tCOMMA f_arg opt_block_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[6]).
- concat(val[7])
- }
- | f_arg tCOMMA f_block_optarg opt_block_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | f_arg tCOMMA f_block_optarg tCOMMA f_arg opt_block_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
- }
- | f_arg tCOMMA f_rest_arg opt_block_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | f_arg tCOMMA
- | f_arg tCOMMA f_rest_arg tCOMMA f_arg opt_block_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
- }
- | f_arg opt_block_args_tail
- {
- result = val[0].concat(val[1])
- }
- | f_block_optarg tCOMMA f_rest_arg opt_block_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | f_block_optarg tCOMMA f_rest_arg tCOMMA f_arg opt_block_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
- }
- | f_block_optarg opt_block_args_tail
- {
- result = val[0].
- concat(val[1])
- }
- | f_block_optarg tCOMMA f_arg opt_block_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | f_rest_arg opt_block_args_tail
- {
- result = val[0].
- concat(val[1])
- }
- | f_rest_arg tCOMMA f_arg opt_block_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | block_args_tail
-
- opt_block_param: # nothing
- {
- result = @builder.args(nil, [], nil)
- }
- | block_param_def
- {
- @lexer.state = :expr_value
- }
-
- block_param_def: tPIPE opt_bv_decl tPIPE
- {
- result = @builder.args(val[0], val[1], val[2])
- }
- | tOROP
- {
- result = @builder.args(val[0], [], val[0])
- }
- | tPIPE block_param opt_bv_decl tPIPE
- {
- result = @builder.args(val[0], val[1].concat(val[2]), val[3])
- }
-
- opt_bv_decl: opt_nl
- {
- result = []
- }
- | opt_nl tSEMI bv_decls opt_nl
- {
- result = val[2]
- }
-
- bv_decls: bvar
- {
- result = [ val[0] ]
- }
- | bv_decls tCOMMA bvar
- {
- result = val[0] << val[2]
- }
-
- bvar: tIDENTIFIER
- {
- result = @builder.shadowarg(val[0])
- }
- | f_bad_arg
-
- lambda: {
- @static_env.extend_dynamic
- }
- f_larglist
- {
- result = @lexer.cmdarg.dup
- @lexer.cmdarg.clear
- }
- lambda_body
- {
- @lexer.cmdarg = val[2]
- @lexer.cmdarg.lexpop
-
- result = [ val[1], val[3] ]
-
- @static_env.unextend
- }
-
- f_larglist: tLPAREN2 f_args opt_bv_decl tRPAREN
- {
- result = @builder.args(val[0], val[1].concat(val[2]), val[3])
- }
- | f_args
- {
- result = @builder.args(nil, val[0], nil)
- }
-
- lambda_body: tLAMBEG compstmt tRCURLY
- {
- result = [ val[0], val[1], val[2] ]
- }
- | kDO_LAMBDA compstmt kEND
- {
- result = [ val[0], val[1], val[2] ]
- }
-
- do_block: kDO_BLOCK
- {
- @static_env.extend_dynamic
- }
- opt_block_param compstmt kEND
- {
- result = [ val[0], val[2], val[3], val[4] ]
-
- @static_env.unextend
- }
-
- block_call: command do_block
- {
- begin_t, block_args, body, end_t = val[1]
- result = @builder.block(val[0],
- begin_t, block_args, body, end_t)
- }
- | block_call dot_or_colon operation2 opt_paren_args
- {
- lparen_t, args, rparen_t = val[3]
- result = @builder.call_method(val[0], val[1], val[2],
- lparen_t, args, rparen_t)
- }
- | block_call dot_or_colon operation2 opt_paren_args brace_block
- {
- lparen_t, args, rparen_t = val[3]
- method_call = @builder.call_method(val[0], val[1], val[2],
- lparen_t, args, rparen_t)
-
- begin_t, args, body, end_t = val[4]
- result = @builder.block(method_call,
- begin_t, args, body, end_t)
- }
- | block_call dot_or_colon operation2 command_args do_block
- {
- method_call = @builder.call_method(val[0], val[1], val[2],
- nil, val[3], nil)
-
- begin_t, args, body, end_t = val[4]
- result = @builder.block(method_call,
- begin_t, args, body, end_t)
- }
-
- method_call: fcall paren_args
- {
- lparen_t, args, rparen_t = val[1]
- result = @builder.call_method(nil, nil, val[0],
- lparen_t, args, rparen_t)
- }
- | primary_value tDOT operation2 opt_paren_args
- {
- lparen_t, args, rparen_t = val[3]
- result = @builder.call_method(val[0], val[1], val[2],
- lparen_t, args, rparen_t)
- }
- | primary_value tCOLON2 operation2 paren_args
- {
- lparen_t, args, rparen_t = val[3]
- result = @builder.call_method(val[0], val[1], val[2],
- lparen_t, args, rparen_t)
- }
- | primary_value tCOLON2 operation3
- {
- result = @builder.call_method(val[0], val[1], val[2])
- }
- | primary_value tDOT paren_args
- {
- lparen_t, args, rparen_t = val[2]
- result = @builder.call_method(val[0], val[1], nil,
- lparen_t, args, rparen_t)
- }
- | primary_value tCOLON2 paren_args
- {
- lparen_t, args, rparen_t = val[2]
- result = @builder.call_method(val[0], val[1], nil,
- lparen_t, args, rparen_t)
- }
- | kSUPER paren_args
- {
- lparen_t, args, rparen_t = val[1]
- result = @builder.keyword_cmd(:super, val[0],
- lparen_t, args, rparen_t)
- }
- | kSUPER
- {
- result = @builder.keyword_cmd(:zsuper, val[0])
- }
- | primary_value tLBRACK2 opt_call_args rbracket
- {
- result = @builder.index(val[0], val[1], val[2], val[3])
- }
-
- brace_block: tLCURLY
- {
- @static_env.extend_dynamic
- }
- opt_block_param compstmt tRCURLY
- {
- result = [ val[0], val[2], val[3], val[4] ]
-
- @static_env.unextend
- }
- | kDO
- {
- @static_env.extend_dynamic
- }
- opt_block_param compstmt kEND
- {
- result = [ val[0], val[2], val[3], val[4] ]
-
- @static_env.unextend
- }
-
- case_body: kWHEN args then compstmt cases
- {
- result = [ @builder.when(val[0], val[1], val[2], val[3]),
- *val[4] ]
- }
-
- cases: opt_else
- {
- result = [ val[0] ]
- }
- | case_body
-
- opt_rescue: kRESCUE exc_list exc_var then compstmt opt_rescue
- {
- assoc_t, exc_var = val[2]
-
- if val[1]
- exc_list = @builder.array(nil, val[1], nil)
- end
-
- result = [ @builder.rescue_body(val[0],
- exc_list, assoc_t, exc_var,
- val[3], val[4]),
- *val[5] ]
- }
- |
- {
- result = []
- }
-
- exc_list: arg_value
- {
- result = [ val[0] ]
- }
- | mrhs
- | none
-
- exc_var: tASSOC lhs
- {
- result = [ val[0], val[1] ]
- }
- | none
-
- opt_ensure: kENSURE compstmt
- {
- result = [ val[0], val[1] ]
- }
- | none
-
- literal: numeric
- | symbol
- | dsym
-
- strings: string
- {
- result = @builder.string_compose(nil, val[0], nil)
- }
-
- string: string1
- {
- result = [ val[0] ]
- }
- | string string1
- {
- result = val[0] << val[1]
- }
-
- string1: tSTRING_BEG string_contents tSTRING_END
- {
- result = @builder.string_compose(val[0], val[1], val[2])
- }
- | tSTRING
- {
- result = @builder.string(val[0])
- }
- | tCHARACTER
- {
- result = @builder.character(val[0])
- }
-
- xstring: tXSTRING_BEG xstring_contents tSTRING_END
- {
- result = @builder.xstring_compose(val[0], val[1], val[2])
- }
-
- regexp: tREGEXP_BEG regexp_contents tSTRING_END tREGEXP_OPT
- {
- opts = @builder.regexp_options(val[3])
- result = @builder.regexp_compose(val[0], val[1], val[2], opts)
- }
-
- words: tWORDS_BEG word_list tSTRING_END
- {
- result = @builder.words_compose(val[0], val[1], val[2])
- }
-
- word_list: # nothing
- {
- result = []
- }
- | word_list word tSPACE
- {
- result = val[0] << @builder.word(val[1])
- }
-
- word: string_content
- {
- result = [ val[0] ]
- }
- | word string_content
- {
- result = val[0] << val[1]
- }
-
- symbols: tSYMBOLS_BEG symbol_list tSTRING_END
- {
- result = @builder.symbols_compose(val[0], val[1], val[2])
- }
-
- symbol_list: # nothing
- {
- result = []
- }
- | symbol_list word tSPACE
- {
- result = val[0] << @builder.word(val[1])
- }
-
- qwords: tQWORDS_BEG qword_list tSTRING_END
- {
- result = @builder.words_compose(val[0], val[1], val[2])
- }
-
- qsymbols: tQSYMBOLS_BEG qsym_list tSTRING_END
- {
- result = @builder.symbols_compose(val[0], val[1], val[2])
- }
-
- qword_list: # nothing
- {
- result = []
- }
- | qword_list tSTRING_CONTENT tSPACE
- {
- result = val[0] << @builder.string_internal(val[1])
- }
-
- qsym_list: # nothing
- {
- result = []
- }
- | qsym_list tSTRING_CONTENT tSPACE
- {
- result = val[0] << @builder.symbol_internal(val[1])
- }
-
- string_contents: # nothing
- {
- result = []
- }
- | string_contents string_content
- {
- result = val[0] << val[1]
- }
-
-xstring_contents: # nothing
- {
- result = []
- }
- | xstring_contents string_content
- {
- result = val[0] << val[1]
- }
-
-regexp_contents: # nothing
- {
- result = []
- }
- | regexp_contents string_content
- {
- result = val[0] << val[1]
- }
-
- string_content: tSTRING_CONTENT
- {
- result = @builder.string_internal(val[0])
- }
- | tSTRING_DVAR string_dvar
- {
- result = val[1]
- }
- | tSTRING_DBEG
- {
- @lexer.cond.push(false)
- @lexer.cmdarg.push(false)
- }
- compstmt tSTRING_DEND
- {
- @lexer.cond.lexpop
- @lexer.cmdarg.lexpop
-
- result = @builder.begin(val[0], val[2], val[3])
- }
-
- string_dvar: tGVAR
- {
- result = @builder.gvar(val[0])
- }
- | tIVAR
- {
- result = @builder.ivar(val[0])
- }
- | tCVAR
- {
- result = @builder.cvar(val[0])
- }
- | backref
-
-
- symbol: tSYMBOL
- {
- result = @builder.symbol(val[0])
- }
-
- dsym: tSYMBEG xstring_contents tSTRING_END
- {
- result = @builder.symbol_compose(val[0], val[1], val[2])
- }
-
- numeric: simple_numeric
- {
- result = val[0]
- }
- | tUMINUS_NUM simple_numeric =tLOWEST
- {
- result = @builder.negate(val[0], val[1])
- }
-
- simple_numeric: tINTEGER
- {
- result = @builder.integer(val[0])
- }
- | tFLOAT
- {
- result = @builder.float(val[0])
- }
- | tRATIONAL
- {
- result = @builder.rational(val[0])
- }
- | tIMAGINARY
- {
- result = @builder.complex(val[0])
- }
-
- user_variable: tIDENTIFIER
- {
- result = @builder.ident(val[0])
- }
- | tIVAR
- {
- result = @builder.ivar(val[0])
- }
- | tGVAR
- {
- result = @builder.gvar(val[0])
- }
- | tCONSTANT
- {
- result = @builder.const(val[0])
- }
- | tCVAR
- {
- result = @builder.cvar(val[0])
- }
-
-keyword_variable: kNIL
- {
- result = @builder.nil(val[0])
- }
- | kSELF
- {
- result = @builder.self(val[0])
- }
- | kTRUE
- {
- result = @builder.true(val[0])
- }
- | kFALSE
- {
- result = @builder.false(val[0])
- }
- | k__FILE__
- {
- result = @builder.__FILE__(val[0])
- }
- | k__LINE__
- {
- result = @builder.__LINE__(val[0])
- }
- | k__ENCODING__
- {
- result = @builder.__ENCODING__(val[0])
- }
-
- var_ref: user_variable
- {
- result = @builder.accessible(val[0])
- }
- | keyword_variable
- {
- result = @builder.accessible(val[0])
- }
-
- var_lhs: user_variable
- {
- result = @builder.assignable(val[0])
- }
- | keyword_variable
- {
- result = @builder.assignable(val[0])
- }
-
- backref: tNTH_REF
- {
- result = @builder.nth_ref(val[0])
- }
- | tBACK_REF
- {
- result = @builder.back_ref(val[0])
- }
-
- superclass: term
- {
- result = nil
- }
- | tLT
- {
- @lexer.state = :expr_value
- }
- expr_value term
- {
- result = [ val[0], val[2] ]
- }
- | error term
- {
- yyerrok
- result = nil
- }
-
- f_arglist: tLPAREN2 f_args rparen
- {
- result = @builder.args(val[0], val[1], val[2])
-
- @lexer.state = :expr_value
- }
- | {
- result = @lexer.in_kwarg
- @lexer.in_kwarg = true
- }
- f_args term
- {
- @lexer.in_kwarg = val[0]
- result = @builder.args(nil, val[1], nil)
- }
-
-
- args_tail: f_kwarg tCOMMA f_kwrest opt_f_block_arg
- {
- result = val[0].concat(val[2]).concat(val[3])
- }
- | f_kwarg opt_f_block_arg
- {
- result = val[0].concat(val[1])
- }
- | f_kwrest opt_f_block_arg
- {
- result = val[0].concat(val[1])
- }
- | f_block_arg
- {
- result = [ val[0] ]
- }
-
- opt_args_tail: tCOMMA args_tail
- {
- result = val[1]
- }
- | # nothing
- {
- result = []
- }
-
- f_args: f_arg tCOMMA f_optarg tCOMMA f_rest_arg opt_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
- }
- | f_arg tCOMMA f_optarg tCOMMA f_rest_arg tCOMMA f_arg opt_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[6]).
- concat(val[7])
- }
- | f_arg tCOMMA f_optarg opt_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | f_arg tCOMMA f_optarg tCOMMA f_arg opt_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
- }
- | f_arg tCOMMA f_rest_arg opt_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | f_arg tCOMMA f_rest_arg tCOMMA f_arg opt_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
- }
- | f_arg opt_args_tail
- {
- result = val[0].
- concat(val[1])
- }
- | f_optarg tCOMMA f_rest_arg opt_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | f_optarg tCOMMA f_rest_arg tCOMMA f_arg opt_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
- }
- | f_optarg opt_args_tail
- {
- result = val[0].
- concat(val[1])
- }
- | f_optarg tCOMMA f_arg opt_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | f_rest_arg opt_args_tail
- {
- result = val[0].
- concat(val[1])
- }
- | f_rest_arg tCOMMA f_arg opt_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | args_tail
- {
- result = val[0]
- }
- | # nothing
- {
- result = []
- }
-
- f_bad_arg: tCONSTANT
- {
- diagnostic :error, :argument_const, nil, val[0]
- }
- | tIVAR
- {
- diagnostic :error, :argument_ivar, nil, val[0]
- }
- | tGVAR
- {
- diagnostic :error, :argument_gvar, nil, val[0]
- }
- | tCVAR
- {
- diagnostic :error, :argument_cvar, nil, val[0]
- }
-
- f_norm_arg: f_bad_arg
- | tIDENTIFIER
- {
- @static_env.declare val[0][0]
-
- result = val[0]
- }
-
- f_arg_item: f_norm_arg
- {
- result = @builder.arg(val[0])
- }
- | tLPAREN f_margs rparen
- {
- result = @builder.multi_lhs(val[0], val[1], val[2])
- }
-
- f_arg: f_arg_item
- {
- result = [ val[0] ]
- }
- | f_arg tCOMMA f_arg_item
- {
- result = val[0] << val[2]
- }
-
- f_label: tLABEL
- {
- check_kwarg_name(val[0])
-
- @static_env.declare val[0][0]
-
- result = val[0]
- }
-
- f_kw: f_label arg_value
- {
- result = @builder.kwoptarg(val[0], val[1])
- }
- | f_label
- {
- result = @builder.kwarg(val[0])
- }
-
- f_block_kw: f_label primary_value
- {
- result = @builder.kwoptarg(val[0], val[1])
- }
- | f_label
- {
- result = @builder.kwarg(val[0])
- }
-
- f_block_kwarg: f_block_kw
- {
- result = [ val[0] ]
- }
- | f_block_kwarg tCOMMA f_block_kw
- {
- result = val[0] << val[2]
- }
-
- f_kwarg: f_kw
- {
- result = [ val[0] ]
- }
- | f_kwarg tCOMMA f_kw
- {
- result = val[0] << val[2]
- }
-
- kwrest_mark: tPOW | tDSTAR
-
- f_kwrest: kwrest_mark tIDENTIFIER
- {
- @static_env.declare val[1][0]
-
- result = [ @builder.kwrestarg(val[0], val[1]) ]
- }
- | kwrest_mark
- {
- result = [ @builder.kwrestarg(val[0]) ]
- }
-
- f_opt: f_norm_arg tEQL arg_value
- {
- result = @builder.optarg(val[0], val[1], val[2])
- }
-
- f_block_opt: f_norm_arg tEQL primary_value
- {
- result = @builder.optarg(val[0], val[1], val[2])
- }
-
- f_block_optarg: f_block_opt
- {
- result = [ val[0] ]
- }
- | f_block_optarg tCOMMA f_block_opt
- {
- result = val[0] << val[2]
- }
-
- f_optarg: f_opt
- {
- result = [ val[0] ]
- }
- | f_optarg tCOMMA f_opt
- {
- result = val[0] << val[2]
- }
-
- restarg_mark: tSTAR2 | tSTAR
-
- f_rest_arg: restarg_mark tIDENTIFIER
- {
- @static_env.declare val[1][0]
-
- result = [ @builder.restarg(val[0], val[1]) ]
- }
- | restarg_mark
- {
- result = [ @builder.restarg(val[0]) ]
- }
-
- blkarg_mark: tAMPER2 | tAMPER
-
- f_block_arg: blkarg_mark tIDENTIFIER
- {
- @static_env.declare val[1][0]
-
- result = @builder.blockarg(val[0], val[1])
- }
-
- opt_f_block_arg: tCOMMA f_block_arg
- {
- result = [ val[1] ]
- }
- |
- {
- result = []
- }
-
- singleton: var_ref
- | tLPAREN2 expr rparen
- {
- result = val[1]
- }
-
- assoc_list: # nothing
- {
- result = []
- }
- | assocs trailer
-
- assocs: assoc
- {
- result = [ val[0] ]
- }
- | assocs tCOMMA assoc
- {
- result = val[0] << val[2]
- }
-
- assoc: arg_value tASSOC arg_value
- {
- result = @builder.pair(val[0], val[1], val[2])
- }
- | tLABEL arg_value
- {
- result = @builder.pair_keyword(val[0], val[1])
- }
- | tDSTAR arg_value
- {
- result = @builder.kwsplat(val[0], val[1])
- }
-
- operation: tIDENTIFIER | tCONSTANT | tFID
- operation2: tIDENTIFIER | tCONSTANT | tFID | op
- operation3: tIDENTIFIER | tFID | op
- dot_or_colon: tDOT | tCOLON2
- opt_terms: | terms
- opt_nl: | tNL
- rparen: opt_nl tRPAREN
- {
- result = val[1]
- }
- rbracket: opt_nl tRBRACK
- {
- result = val[1]
- }
- trailer: | tNL | tCOMMA
-
- term: tSEMI
- {
- yyerrok
- }
- | tNL
-
- terms: term
- | terms tSEMI
-
- none: # nothing
- {
- result = nil
- }
-end
-
----- header
-
-require 'parser'
-
-Parser.check_for_encoding_support
-
----- inner
-
- def version
- 21
- end
-
- def default_encoding
- Encoding::UTF_8
- end
diff --git a/test/racc/assets/ruby22.y b/test/racc/assets/ruby22.y
deleted file mode 100644
index 751c0e866b..0000000000
--- a/test/racc/assets/ruby22.y
+++ /dev/null
@@ -1,2381 +0,0 @@
-# Copyright (c) 2013 Peter Zotov <whitequark@whitequark.org>
-#
-# Parts of the source are derived from ruby_parser:
-# Copyright (c) Ryan Davis, seattle.rb
-#
-# MIT License
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be
-# included in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-class Parser::Ruby22
-
-token kCLASS kMODULE kDEF kUNDEF kBEGIN kRESCUE kENSURE kEND kIF kUNLESS
- kTHEN kELSIF kELSE kCASE kWHEN kWHILE kUNTIL kFOR kBREAK kNEXT
- kREDO kRETRY kIN kDO kDO_COND kDO_BLOCK kDO_LAMBDA kRETURN kYIELD kSUPER
- kSELF kNIL kTRUE kFALSE kAND kOR kNOT kIF_MOD kUNLESS_MOD kWHILE_MOD
- kUNTIL_MOD kRESCUE_MOD kALIAS kDEFINED klBEGIN klEND k__LINE__
- k__FILE__ k__ENCODING__ tIDENTIFIER tFID tGVAR tIVAR tCONSTANT
- tLABEL tCVAR tNTH_REF tBACK_REF tSTRING_CONTENT tINTEGER tFLOAT
- tREGEXP_END tUPLUS tUMINUS tUMINUS_NUM tPOW tCMP tEQ tEQQ tNEQ
- tGEQ tLEQ tANDOP tOROP tMATCH tNMATCH tDOT tDOT2 tDOT3 tAREF
- tASET tLSHFT tRSHFT tCOLON2 tCOLON3 tOP_ASGN tASSOC tLPAREN
- tLPAREN2 tRPAREN tLPAREN_ARG tLBRACK tLBRACK2 tRBRACK tLBRACE
- tLBRACE_ARG tSTAR tSTAR2 tAMPER tAMPER2 tTILDE tPERCENT tDIVIDE
- tDSTAR tPLUS tMINUS tLT tGT tPIPE tBANG tCARET tLCURLY tRCURLY
- tBACK_REF2 tSYMBEG tSTRING_BEG tXSTRING_BEG tREGEXP_BEG tREGEXP_OPT
- tWORDS_BEG tQWORDS_BEG tSYMBOLS_BEG tQSYMBOLS_BEG tSTRING_DBEG
- tSTRING_DVAR tSTRING_END tSTRING_DEND tSTRING tSYMBOL
- tNL tEH tCOLON tCOMMA tSPACE tSEMI tLAMBDA tLAMBEG tCHARACTER
- tRATIONAL tIMAGINARY tLABEL_END
-
-prechigh
- right tBANG tTILDE tUPLUS
- right tPOW
- right tUMINUS_NUM tUMINUS
- left tSTAR2 tDIVIDE tPERCENT
- left tPLUS tMINUS
- left tLSHFT tRSHFT
- left tAMPER2
- left tPIPE tCARET
- left tGT tGEQ tLT tLEQ
- nonassoc tCMP tEQ tEQQ tNEQ tMATCH tNMATCH
- left tANDOP
- left tOROP
- nonassoc tDOT2 tDOT3
- right tEH tCOLON
- left kRESCUE_MOD
- right tEQL tOP_ASGN
- nonassoc kDEFINED
- right kNOT
- left kOR kAND
- nonassoc kIF_MOD kUNLESS_MOD kWHILE_MOD kUNTIL_MOD
- nonassoc tLBRACE_ARG
- nonassoc tLOWEST
-preclow
-
-rule
-
- program: top_compstmt
-
- top_compstmt: top_stmts opt_terms
- {
- result = @builder.compstmt(val[0])
- }
-
- top_stmts: # nothing
- {
- result = []
- }
- | top_stmt
- {
- result = [ val[0] ]
- }
- | top_stmts terms top_stmt
- {
- result = val[0] << val[2]
- }
- | error top_stmt
- {
- result = [ val[1] ]
- }
-
- top_stmt: stmt
- | klBEGIN tLCURLY top_compstmt tRCURLY
- {
- result = @builder.preexe(val[0], val[1], val[2], val[3])
- }
-
- bodystmt: compstmt opt_rescue opt_else opt_ensure
- {
- rescue_bodies = val[1]
- else_t, else_ = val[2]
- ensure_t, ensure_ = val[3]
-
- if rescue_bodies.empty? && !else_.nil?
- diagnostic :warning, :useless_else, nil, else_t
- end
-
- result = @builder.begin_body(val[0],
- rescue_bodies,
- else_t, else_,
- ensure_t, ensure_)
- }
-
- compstmt: stmts opt_terms
- {
- result = @builder.compstmt(val[0])
- }
-
- stmts: # nothing
- {
- result = []
- }
- | stmt_or_begin
- {
- result = [ val[0] ]
- }
- | stmts terms stmt_or_begin
- {
- result = val[0] << val[2]
- }
- | error stmt
- {
- result = [ val[1] ]
- }
-
- stmt_or_begin: stmt
- | klBEGIN tLCURLY top_compstmt tRCURLY
- {
- diagnostic :error, :begin_in_method, nil, val[0]
- }
-
- stmt: kALIAS fitem
- {
- @lexer.state = :expr_fname
- }
- fitem
- {
- result = @builder.alias(val[0], val[1], val[3])
- }
- | kALIAS tGVAR tGVAR
- {
- result = @builder.alias(val[0],
- @builder.gvar(val[1]),
- @builder.gvar(val[2]))
- }
- | kALIAS tGVAR tBACK_REF
- {
- result = @builder.alias(val[0],
- @builder.gvar(val[1]),
- @builder.back_ref(val[2]))
- }
- | kALIAS tGVAR tNTH_REF
- {
- diagnostic :error, :nth_ref_alias, nil, val[2]
- }
- | kUNDEF undef_list
- {
- result = @builder.undef_method(val[0], val[1])
- }
- | stmt kIF_MOD expr_value
- {
- result = @builder.condition_mod(val[0], nil,
- val[1], val[2])
- }
- | stmt kUNLESS_MOD expr_value
- {
- result = @builder.condition_mod(nil, val[0],
- val[1], val[2])
- }
- | stmt kWHILE_MOD expr_value
- {
- result = @builder.loop_mod(:while, val[0], val[1], val[2])
- }
- | stmt kUNTIL_MOD expr_value
- {
- result = @builder.loop_mod(:until, val[0], val[1], val[2])
- }
- | stmt kRESCUE_MOD stmt
- {
- rescue_body = @builder.rescue_body(val[1],
- nil, nil, nil,
- nil, val[2])
-
- result = @builder.begin_body(val[0], [ rescue_body ])
- }
- | klEND tLCURLY compstmt tRCURLY
- {
- result = @builder.postexe(val[0], val[1], val[2], val[3])
- }
- | command_asgn
- | mlhs tEQL command_call
- {
- result = @builder.multi_assign(val[0], val[1], val[2])
- }
- | var_lhs tOP_ASGN command_call
- {
- result = @builder.op_assign(val[0], val[1], val[2])
- }
- | primary_value tLBRACK2 opt_call_args rbracket tOP_ASGN command_call
- {
- result = @builder.op_assign(
- @builder.index(
- val[0], val[1], val[2], val[3]),
- val[4], val[5])
- }
- | primary_value tDOT tIDENTIFIER tOP_ASGN command_call
- {
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
- }
- | primary_value tDOT tCONSTANT tOP_ASGN command_call
- {
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
- }
- | primary_value tCOLON2 tCONSTANT tOP_ASGN command_call
- {
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
- }
- | primary_value tCOLON2 tIDENTIFIER tOP_ASGN command_call
- {
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
- }
- | backref tOP_ASGN command_call
- {
- @builder.op_assign(val[0], val[1], val[2])
- }
- | lhs tEQL mrhs
- {
- result = @builder.assign(val[0], val[1],
- @builder.array(nil, val[2], nil))
- }
- | mlhs tEQL mrhs_arg
- {
- result = @builder.multi_assign(val[0], val[1], val[2])
- }
- | expr
-
- command_asgn: lhs tEQL command_call
- {
- result = @builder.assign(val[0], val[1], val[2])
- }
- | lhs tEQL command_asgn
- {
- result = @builder.assign(val[0], val[1], val[2])
- }
-
- expr: command_call
- | expr kAND expr
- {
- result = @builder.logical_op(:and, val[0], val[1], val[2])
- }
- | expr kOR expr
- {
- result = @builder.logical_op(:or, val[0], val[1], val[2])
- }
- | kNOT opt_nl expr
- {
- result = @builder.not_op(val[0], nil, val[2], nil)
- }
- | tBANG command_call
- {
- result = @builder.not_op(val[0], nil, val[1], nil)
- }
- | arg
-
- expr_value: expr
-
- command_call: command
- | block_command
-
- block_command: block_call
- | block_call dot_or_colon operation2 command_args
- {
- result = @builder.call_method(val[0], val[1], val[2],
- nil, val[3], nil)
- }
-
- cmd_brace_block: tLBRACE_ARG
- {
- @static_env.extend_dynamic
- }
- opt_block_param compstmt tRCURLY
- {
- result = [ val[0], val[2], val[3], val[4] ]
-
- @static_env.unextend
- }
-
- fcall: operation
-
- command: fcall command_args =tLOWEST
- {
- result = @builder.call_method(nil, nil, val[0],
- nil, val[1], nil)
- }
- | fcall command_args cmd_brace_block
- {
- method_call = @builder.call_method(nil, nil, val[0],
- nil, val[1], nil)
-
- begin_t, args, body, end_t = val[2]
- result = @builder.block(method_call,
- begin_t, args, body, end_t)
- }
- | primary_value tDOT operation2 command_args =tLOWEST
- {
- result = @builder.call_method(val[0], val[1], val[2],
- nil, val[3], nil)
- }
- | primary_value tDOT operation2 command_args cmd_brace_block
- {
- method_call = @builder.call_method(val[0], val[1], val[2],
- nil, val[3], nil)
-
- begin_t, args, body, end_t = val[4]
- result = @builder.block(method_call,
- begin_t, args, body, end_t)
- }
- | primary_value tCOLON2 operation2 command_args =tLOWEST
- {
- result = @builder.call_method(val[0], val[1], val[2],
- nil, val[3], nil)
- }
- | primary_value tCOLON2 operation2 command_args cmd_brace_block
- {
- method_call = @builder.call_method(val[0], val[1], val[2],
- nil, val[3], nil)
-
- begin_t, args, body, end_t = val[4]
- result = @builder.block(method_call,
- begin_t, args, body, end_t)
- }
- | kSUPER command_args
- {
- result = @builder.keyword_cmd(:super, val[0],
- nil, val[1], nil)
- }
- | kYIELD command_args
- {
- result = @builder.keyword_cmd(:yield, val[0],
- nil, val[1], nil)
- }
- | kRETURN call_args
- {
- result = @builder.keyword_cmd(:return, val[0],
- nil, val[1], nil)
- }
- | kBREAK call_args
- {
- result = @builder.keyword_cmd(:break, val[0],
- nil, val[1], nil)
- }
- | kNEXT call_args
- {
- result = @builder.keyword_cmd(:next, val[0],
- nil, val[1], nil)
- }
-
- mlhs: mlhs_basic
- {
- result = @builder.multi_lhs(nil, val[0], nil)
- }
- | tLPAREN mlhs_inner rparen
- {
- result = @builder.begin(val[0], val[1], val[2])
- }
-
- mlhs_inner: mlhs_basic
- {
- result = @builder.multi_lhs(nil, val[0], nil)
- }
- | tLPAREN mlhs_inner rparen
- {
- result = @builder.multi_lhs(val[0], val[1], val[2])
- }
-
- mlhs_basic: mlhs_head
- | mlhs_head mlhs_item
- {
- result = val[0].
- push(val[1])
- }
- | mlhs_head tSTAR mlhs_node
- {
- result = val[0].
- push(@builder.splat(val[1], val[2]))
- }
- | mlhs_head tSTAR mlhs_node tCOMMA mlhs_post
- {
- result = val[0].
- push(@builder.splat(val[1], val[2])).
- concat(val[4])
- }
- | mlhs_head tSTAR
- {
- result = val[0].
- push(@builder.splat(val[1]))
- }
- | mlhs_head tSTAR tCOMMA mlhs_post
- {
- result = val[0].
- push(@builder.splat(val[1])).
- concat(val[3])
- }
- | tSTAR mlhs_node
- {
- result = [ @builder.splat(val[0], val[1]) ]
- }
- | tSTAR mlhs_node tCOMMA mlhs_post
- {
- result = [ @builder.splat(val[0], val[1]),
- *val[3] ]
- }
- | tSTAR
- {
- result = [ @builder.splat(val[0]) ]
- }
- | tSTAR tCOMMA mlhs_post
- {
- result = [ @builder.splat(val[0]),
- *val[2] ]
- }
-
- mlhs_item: mlhs_node
- | tLPAREN mlhs_inner rparen
- {
- result = @builder.begin(val[0], val[1], val[2])
- }
-
- mlhs_head: mlhs_item tCOMMA
- {
- result = [ val[0] ]
- }
- | mlhs_head mlhs_item tCOMMA
- {
- result = val[0] << val[1]
- }
-
- mlhs_post: mlhs_item
- {
- result = [ val[0] ]
- }
- | mlhs_post tCOMMA mlhs_item
- {
- result = val[0] << val[2]
- }
-
- mlhs_node: user_variable
- {
- result = @builder.assignable(val[0])
- }
- | keyword_variable
- {
- result = @builder.assignable(val[0])
- }
- | primary_value tLBRACK2 opt_call_args rbracket
- {
- result = @builder.index_asgn(val[0], val[1], val[2], val[3])
- }
- | primary_value tDOT tIDENTIFIER
- {
- result = @builder.attr_asgn(val[0], val[1], val[2])
- }
- | primary_value tCOLON2 tIDENTIFIER
- {
- result = @builder.attr_asgn(val[0], val[1], val[2])
- }
- | primary_value tDOT tCONSTANT
- {
- result = @builder.attr_asgn(val[0], val[1], val[2])
- }
- | primary_value tCOLON2 tCONSTANT
- {
- result = @builder.assignable(
- @builder.const_fetch(val[0], val[1], val[2]))
- }
- | tCOLON3 tCONSTANT
- {
- result = @builder.assignable(
- @builder.const_global(val[0], val[1]))
- }
- | backref
- {
- result = @builder.assignable(val[0])
- }
-
- lhs: user_variable
- {
- result = @builder.assignable(val[0])
- }
- | keyword_variable
- {
- result = @builder.assignable(val[0])
- }
- | primary_value tLBRACK2 opt_call_args rbracket
- {
- result = @builder.index_asgn(val[0], val[1], val[2], val[3])
- }
- | primary_value tDOT tIDENTIFIER
- {
- result = @builder.attr_asgn(val[0], val[1], val[2])
- }
- | primary_value tCOLON2 tIDENTIFIER
- {
- result = @builder.attr_asgn(val[0], val[1], val[2])
- }
- | primary_value tDOT tCONSTANT
- {
- result = @builder.attr_asgn(val[0], val[1], val[2])
- }
- | primary_value tCOLON2 tCONSTANT
- {
- result = @builder.assignable(
- @builder.const_fetch(val[0], val[1], val[2]))
- }
- | tCOLON3 tCONSTANT
- {
- result = @builder.assignable(
- @builder.const_global(val[0], val[1]))
- }
- | backref
- {
- result = @builder.assignable(val[0])
- }
-
- cname: tIDENTIFIER
- {
- diagnostic :error, :module_name_const, nil, val[0]
- }
- | tCONSTANT
-
- cpath: tCOLON3 cname
- {
- result = @builder.const_global(val[0], val[1])
- }
- | cname
- {
- result = @builder.const(val[0])
- }
- | primary_value tCOLON2 cname
- {
- result = @builder.const_fetch(val[0], val[1], val[2])
- }
-
- fname: tIDENTIFIER | tCONSTANT | tFID
- | op
- | reswords
-
- fsym: fname
- {
- result = @builder.symbol(val[0])
- }
- | symbol
-
- fitem: fsym
- | dsym
-
- undef_list: fitem
- {
- result = [ val[0] ]
- }
- | undef_list tCOMMA
- {
- @lexer.state = :expr_fname
- }
- fitem
- {
- result = val[0] << val[3]
- }
-
- op: tPIPE | tCARET | tAMPER2 | tCMP | tEQ | tEQQ
- | tMATCH | tNMATCH | tGT | tGEQ | tLT | tLEQ
- | tNEQ | tLSHFT | tRSHFT | tPLUS | tMINUS | tSTAR2
- | tSTAR | tDIVIDE | tPERCENT | tPOW | tBANG | tTILDE
- | tUPLUS | tUMINUS | tAREF | tASET | tDSTAR | tBACK_REF2
-
- reswords: k__LINE__ | k__FILE__ | k__ENCODING__ | klBEGIN | klEND
- | kALIAS | kAND | kBEGIN | kBREAK | kCASE
- | kCLASS | kDEF | kDEFINED | kDO | kELSE
- | kELSIF | kEND | kENSURE | kFALSE | kFOR
- | kIN | kMODULE | kNEXT | kNIL | kNOT
- | kOR | kREDO | kRESCUE | kRETRY | kRETURN
- | kSELF | kSUPER | kTHEN | kTRUE | kUNDEF
- | kWHEN | kYIELD | kIF | kUNLESS | kWHILE
- | kUNTIL
-
- arg: lhs tEQL arg
- {
- result = @builder.assign(val[0], val[1], val[2])
- }
- | lhs tEQL arg kRESCUE_MOD arg
- {
- rescue_body = @builder.rescue_body(val[3],
- nil, nil, nil,
- nil, val[4])
-
- rescue_ = @builder.begin_body(val[2], [ rescue_body ])
-
- result = @builder.assign(val[0], val[1], rescue_)
- }
- | var_lhs tOP_ASGN arg
- {
- result = @builder.op_assign(val[0], val[1], val[2])
- }
- | var_lhs tOP_ASGN arg kRESCUE_MOD arg
- {
- rescue_body = @builder.rescue_body(val[3],
- nil, nil, nil,
- nil, val[4])
-
- rescue_ = @builder.begin_body(val[2], [ rescue_body ])
-
- result = @builder.op_assign(val[0], val[1], rescue_)
- }
- | primary_value tLBRACK2 opt_call_args rbracket tOP_ASGN arg
- {
- result = @builder.op_assign(
- @builder.index(
- val[0], val[1], val[2], val[3]),
- val[4], val[5])
- }
- | primary_value tDOT tIDENTIFIER tOP_ASGN arg
- {
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
- }
- | primary_value tDOT tCONSTANT tOP_ASGN arg
- {
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
- }
- | primary_value tCOLON2 tIDENTIFIER tOP_ASGN arg
- {
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
- }
- | primary_value tCOLON2 tCONSTANT tOP_ASGN arg
- {
- const = @builder.const_op_assignable(
- @builder.const_fetch(val[0], val[1], val[2]))
- result = @builder.op_assign(const, val[3], val[4])
- }
- | tCOLON3 tCONSTANT tOP_ASGN arg
- {
- const = @builder.const_op_assignable(
- @builder.const_global(val[0], val[1]))
- result = @builder.op_assign(const, val[2], val[3])
- }
- | backref tOP_ASGN arg
- {
- result = @builder.op_assign(val[0], val[1], val[2])
- }
- | arg tDOT2 arg
- {
- result = @builder.range_inclusive(val[0], val[1], val[2])
- }
- | arg tDOT3 arg
- {
- result = @builder.range_exclusive(val[0], val[1], val[2])
- }
- | arg tPLUS arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tMINUS arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tSTAR2 arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tDIVIDE arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tPERCENT arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tPOW arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | tUMINUS_NUM simple_numeric tPOW arg
- {
- result = @builder.unary_op(val[0],
- @builder.binary_op(
- val[1], val[2], val[3]))
- }
- | tUPLUS arg
- {
- result = @builder.unary_op(val[0], val[1])
- }
- | tUMINUS arg
- {
- result = @builder.unary_op(val[0], val[1])
- }
- | arg tPIPE arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tCARET arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tAMPER2 arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tCMP arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tGT arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tGEQ arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tLT arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tLEQ arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tEQ arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tEQQ arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tNEQ arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tMATCH arg
- {
- result = @builder.match_op(val[0], val[1], val[2])
- }
- | arg tNMATCH arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | tBANG arg
- {
- result = @builder.not_op(val[0], nil, val[1], nil)
- }
- | tTILDE arg
- {
- result = @builder.unary_op(val[0], val[1])
- }
- | arg tLSHFT arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tRSHFT arg
- {
- result = @builder.binary_op(val[0], val[1], val[2])
- }
- | arg tANDOP arg
- {
- result = @builder.logical_op(:and, val[0], val[1], val[2])
- }
- | arg tOROP arg
- {
- result = @builder.logical_op(:or, val[0], val[1], val[2])
- }
- | kDEFINED opt_nl arg
- {
- result = @builder.keyword_cmd(:defined?, val[0], nil, [ val[2] ], nil)
- }
-
- # Note: MRI eventually came to rely on disambiguation based on
- # the lexer state, but it is too contrived with the Ragel lexer,
- # so we kept this approach. See ruby/ruby@b0c03f63e5 for
- # the initial commit, and ruby/ruby@23352f62a for MRI revert,
- # which we decided not to track.
- | arg tEH
- {
- @lexer.push_cond
- @lexer.cond.push(true)
- }
- arg opt_nl tCOLON
- {
- @lexer.pop_cond
- }
- arg
- {
- result = @builder.ternary(val[0], val[1],
- val[3], val[5], val[7])
- }
- | primary
-
- arg_value: arg
-
- aref_args: none
- | args trailer
- | args tCOMMA assocs trailer
- {
- result = val[0] << @builder.associate(nil, val[2], nil)
- }
- | assocs trailer
- {
- result = [ @builder.associate(nil, val[0], nil) ]
- }
-
- paren_args: tLPAREN2 opt_call_args rparen
- {
- result = val
- }
-
- opt_paren_args: # nothing
- {
- result = [ nil, [], nil ]
- }
- | paren_args
-
- opt_call_args: # nothing
- {
- result = []
- }
- | call_args
- | args tCOMMA
- | args tCOMMA assocs tCOMMA
- {
- result = val[0] << @builder.associate(nil, val[2], nil)
- }
- | assocs tCOMMA
- {
- result = [ @builder.associate(nil, val[0], nil) ]
- }
-
- call_args: command
- {
- result = [ val[0] ]
- }
- | args opt_block_arg
- {
- result = val[0].concat(val[1])
- }
- | assocs opt_block_arg
- {
- result = [ @builder.associate(nil, val[0], nil) ]
- result.concat(val[1])
- }
- | args tCOMMA assocs opt_block_arg
- {
- assocs = @builder.associate(nil, val[2], nil)
- result = val[0] << assocs
- result.concat(val[3])
- }
- | block_arg
- {
- result = [ val[0] ]
- }
-
- command_args: {
- result = @lexer.cmdarg.dup
- @lexer.cmdarg.push(true)
- }
- call_args
- {
- @lexer.cmdarg = val[0]
-
- result = val[1]
- }
-
- block_arg: tAMPER arg_value
- {
- result = @builder.block_pass(val[0], val[1])
- }
-
- opt_block_arg: tCOMMA block_arg
- {
- result = [ val[1] ]
- }
- | # nothing
- {
- result = []
- }
-
- args: arg_value
- {
- result = [ val[0] ]
- }
- | tSTAR arg_value
- {
- result = [ @builder.splat(val[0], val[1]) ]
- }
- | args tCOMMA arg_value
- {
- result = val[0] << val[2]
- }
- | args tCOMMA tSTAR arg_value
- {
- result = val[0] << @builder.splat(val[2], val[3])
- }
-
- mrhs_arg: mrhs
- {
- result = @builder.array(nil, val[0], nil)
- }
- | arg_value
-
- mrhs: args tCOMMA arg_value
- {
- result = val[0] << val[2]
- }
- | args tCOMMA tSTAR arg_value
- {
- result = val[0] << @builder.splat(val[2], val[3])
- }
- | tSTAR arg_value
- {
- result = [ @builder.splat(val[0], val[1]) ]
- }
-
- primary: literal
- | strings
- | xstring
- | regexp
- | words
- | qwords
- | symbols
- | qsymbols
- | var_ref
- | backref
- | tFID
- {
- result = @builder.call_method(nil, nil, val[0])
- }
- | kBEGIN
- {
- result = @lexer.cmdarg.dup
- @lexer.cmdarg.clear
- }
- bodystmt kEND
- {
- @lexer.cmdarg = val[1]
-
- result = @builder.begin_keyword(val[0], val[2], val[3])
- }
- | tLPAREN_ARG
- {
- result = @lexer.cmdarg.dup
- @lexer.cmdarg.clear
- }
- expr
- {
- @lexer.state = :expr_endarg
- }
- opt_nl tRPAREN
- {
- @lexer.cmdarg = val[1]
-
- result = @builder.begin(val[0], val[2], val[5])
- }
- | tLPAREN_ARG
- {
- @lexer.state = :expr_endarg
- }
- opt_nl tRPAREN
- {
- result = @builder.begin(val[0], nil, val[3])
- }
- | tLPAREN compstmt tRPAREN
- {
- result = @builder.begin(val[0], val[1], val[2])
- }
- | primary_value tCOLON2 tCONSTANT
- {
- result = @builder.const_fetch(val[0], val[1], val[2])
- }
- | tCOLON3 tCONSTANT
- {
- result = @builder.const_global(val[0], val[1])
- }
- | tLBRACK aref_args tRBRACK
- {
- result = @builder.array(val[0], val[1], val[2])
- }
- | tLBRACE assoc_list tRCURLY
- {
- result = @builder.associate(val[0], val[1], val[2])
- }
- | kRETURN
- {
- result = @builder.keyword_cmd(:return, val[0])
- }
- | kYIELD tLPAREN2 call_args rparen
- {
- result = @builder.keyword_cmd(:yield, val[0], val[1], val[2], val[3])
- }
- | kYIELD tLPAREN2 rparen
- {
- result = @builder.keyword_cmd(:yield, val[0], val[1], [], val[2])
- }
- | kYIELD
- {
- result = @builder.keyword_cmd(:yield, val[0])
- }
- | kDEFINED opt_nl tLPAREN2 expr rparen
- {
- result = @builder.keyword_cmd(:defined?, val[0],
- val[2], [ val[3] ], val[4])
- }
- | kNOT tLPAREN2 expr rparen
- {
- result = @builder.not_op(val[0], val[1], val[2], val[3])
- }
- | kNOT tLPAREN2 rparen
- {
- result = @builder.not_op(val[0], val[1], nil, val[2])
- }
- | fcall brace_block
- {
- method_call = @builder.call_method(nil, nil, val[0])
-
- begin_t, args, body, end_t = val[1]
- result = @builder.block(method_call,
- begin_t, args, body, end_t)
- }
- | method_call
- | method_call brace_block
- {
- begin_t, args, body, end_t = val[1]
- result = @builder.block(val[0],
- begin_t, args, body, end_t)
- }
- | tLAMBDA lambda
- {
- lambda_call = @builder.call_lambda(val[0])
-
- args, (begin_t, body, end_t) = val[1]
- result = @builder.block(lambda_call,
- begin_t, args, body, end_t)
- }
- | kIF expr_value then compstmt if_tail kEND
- {
- else_t, else_ = val[4]
- result = @builder.condition(val[0], val[1], val[2],
- val[3], else_t,
- else_, val[5])
- }
- | kUNLESS expr_value then compstmt opt_else kEND
- {
- else_t, else_ = val[4]
- result = @builder.condition(val[0], val[1], val[2],
- else_, else_t,
- val[3], val[5])
- }
- | kWHILE
- {
- @lexer.cond.push(true)
- }
- expr_value do
- {
- @lexer.cond.pop
- }
- compstmt kEND
- {
- result = @builder.loop(:while, val[0], val[2], val[3],
- val[5], val[6])
- }
- | kUNTIL
- {
- @lexer.cond.push(true)
- }
- expr_value do
- {
- @lexer.cond.pop
- }
- compstmt kEND
- {
- result = @builder.loop(:until, val[0], val[2], val[3],
- val[5], val[6])
- }
- | kCASE expr_value opt_terms case_body kEND
- {
- *when_bodies, (else_t, else_body) = *val[3]
-
- result = @builder.case(val[0], val[1],
- when_bodies, else_t, else_body,
- val[4])
- }
- | kCASE opt_terms case_body kEND
- {
- *when_bodies, (else_t, else_body) = *val[2]
-
- result = @builder.case(val[0], nil,
- when_bodies, else_t, else_body,
- val[3])
- }
- | kFOR for_var kIN
- {
- @lexer.cond.push(true)
- }
- expr_value do
- {
- @lexer.cond.pop
- }
- compstmt kEND
- {
- result = @builder.for(val[0], val[1],
- val[2], val[4],
- val[5], val[7], val[8])
- }
- | kCLASS cpath superclass
- {
- @static_env.extend_static
- @lexer.push_cmdarg
- }
- bodystmt kEND
- {
- if in_def?
- diagnostic :error, :class_in_def, nil, val[0]
- end
-
- lt_t, superclass = val[2]
- result = @builder.def_class(val[0], val[1],
- lt_t, superclass,
- val[4], val[5])
-
- @lexer.pop_cmdarg
- @static_env.unextend
- }
- | kCLASS tLSHFT expr term
- {
- result = @def_level
- @def_level = 0
-
- @static_env.extend_static
- @lexer.push_cmdarg
- }
- bodystmt kEND
- {
- result = @builder.def_sclass(val[0], val[1], val[2],
- val[5], val[6])
-
- @lexer.pop_cmdarg
- @static_env.unextend
-
- @def_level = val[4]
- }
- | kMODULE cpath
- {
- @static_env.extend_static
- @lexer.push_cmdarg
- }
- bodystmt kEND
- {
- if in_def?
- diagnostic :error, :module_in_def, nil, val[0]
- end
-
- result = @builder.def_module(val[0], val[1],
- val[3], val[4])
-
- @lexer.pop_cmdarg
- @static_env.unextend
- }
- | kDEF fname
- {
- @def_level += 1
- @static_env.extend_static
- @lexer.push_cmdarg
- }
- f_arglist bodystmt kEND
- {
- result = @builder.def_method(val[0], val[1],
- val[3], val[4], val[5])
-
- @lexer.pop_cmdarg
- @static_env.unextend
- @def_level -= 1
- }
- | kDEF singleton dot_or_colon
- {
- @lexer.state = :expr_fname
- }
- fname
- {
- @def_level += 1
- @static_env.extend_static
- @lexer.push_cmdarg
- }
- f_arglist bodystmt kEND
- {
- result = @builder.def_singleton(val[0], val[1], val[2],
- val[4], val[6], val[7], val[8])
-
- @lexer.pop_cmdarg
- @static_env.unextend
- @def_level -= 1
- }
- | kBREAK
- {
- result = @builder.keyword_cmd(:break, val[0])
- }
- | kNEXT
- {
- result = @builder.keyword_cmd(:next, val[0])
- }
- | kREDO
- {
- result = @builder.keyword_cmd(:redo, val[0])
- }
- | kRETRY
- {
- result = @builder.keyword_cmd(:retry, val[0])
- }
-
- primary_value: primary
-
- then: term
- | kTHEN
- | term kTHEN
- {
- result = val[1]
- }
-
- do: term
- | kDO_COND
-
- if_tail: opt_else
- | kELSIF expr_value then compstmt if_tail
- {
- else_t, else_ = val[4]
- result = [ val[0],
- @builder.condition(val[0], val[1], val[2],
- val[3], else_t,
- else_, nil),
- ]
- }
-
- opt_else: none
- | kELSE compstmt
- {
- result = val
- }
-
- for_var: lhs
- | mlhs
-
- f_marg: f_norm_arg
- {
- result = @builder.arg(val[0])
- }
- | tLPAREN f_margs rparen
- {
- result = @builder.multi_lhs(val[0], val[1], val[2])
- }
-
- f_marg_list: f_marg
- {
- result = [ val[0] ]
- }
- | f_marg_list tCOMMA f_marg
- {
- result = val[0] << val[2]
- }
-
- f_margs: f_marg_list
- | f_marg_list tCOMMA tSTAR f_norm_arg
- {
- result = val[0].
- push(@builder.restarg(val[2], val[3]))
- }
- | f_marg_list tCOMMA tSTAR f_norm_arg tCOMMA f_marg_list
- {
- result = val[0].
- push(@builder.restarg(val[2], val[3])).
- concat(val[5])
- }
- | f_marg_list tCOMMA tSTAR
- {
- result = val[0].
- push(@builder.restarg(val[2]))
- }
- | f_marg_list tCOMMA tSTAR tCOMMA f_marg_list
- {
- result = val[0].
- push(@builder.restarg(val[2])).
- concat(val[4])
- }
- | tSTAR f_norm_arg
- {
- result = [ @builder.restarg(val[0], val[1]) ]
- }
- | tSTAR f_norm_arg tCOMMA f_marg_list
- {
- result = [ @builder.restarg(val[0], val[1]),
- *val[3] ]
- }
- | tSTAR
- {
- result = [ @builder.restarg(val[0]) ]
- }
- | tSTAR tCOMMA f_marg_list
- {
- result = [ @builder.restarg(val[0]),
- *val[2] ]
- }
-
- block_args_tail: f_block_kwarg tCOMMA f_kwrest opt_f_block_arg
- {
- result = val[0].concat(val[2]).concat(val[3])
- }
- | f_block_kwarg opt_f_block_arg
- {
- result = val[0].concat(val[1])
- }
- | f_kwrest opt_f_block_arg
- {
- result = val[0].concat(val[1])
- }
- | f_block_arg
- {
- result = [ val[0] ]
- }
-
-opt_block_args_tail:
- tCOMMA block_args_tail
- {
- result = val[1]
- }
- | # nothing
- {
- result = []
- }
-
- block_param: f_arg tCOMMA f_block_optarg tCOMMA f_rest_arg opt_block_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
- }
- | f_arg tCOMMA f_block_optarg tCOMMA f_rest_arg tCOMMA f_arg opt_block_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[6]).
- concat(val[7])
- }
- | f_arg tCOMMA f_block_optarg opt_block_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | f_arg tCOMMA f_block_optarg tCOMMA f_arg opt_block_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
- }
- | f_arg tCOMMA f_rest_arg opt_block_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | f_arg tCOMMA
- | f_arg tCOMMA f_rest_arg tCOMMA f_arg opt_block_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
- }
- | f_arg opt_block_args_tail
- {
- result = val[0].concat(val[1])
- }
- | f_block_optarg tCOMMA f_rest_arg opt_block_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | f_block_optarg tCOMMA f_rest_arg tCOMMA f_arg opt_block_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
- }
- | f_block_optarg opt_block_args_tail
- {
- result = val[0].
- concat(val[1])
- }
- | f_block_optarg tCOMMA f_arg opt_block_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | f_rest_arg opt_block_args_tail
- {
- result = val[0].
- concat(val[1])
- }
- | f_rest_arg tCOMMA f_arg opt_block_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | block_args_tail
-
- opt_block_param: # nothing
- {
- result = @builder.args(nil, [], nil)
- }
- | block_param_def
- {
- @lexer.state = :expr_value
- }
-
- block_param_def: tPIPE opt_bv_decl tPIPE
- {
- result = @builder.args(val[0], val[1], val[2])
- }
- | tOROP
- {
- result = @builder.args(val[0], [], val[0])
- }
- | tPIPE block_param opt_bv_decl tPIPE
- {
- result = @builder.args(val[0], val[1].concat(val[2]), val[3])
- }
-
- opt_bv_decl: opt_nl
- {
- result = []
- }
- | opt_nl tSEMI bv_decls opt_nl
- {
- result = val[2]
- }
-
- bv_decls: bvar
- {
- result = [ val[0] ]
- }
- | bv_decls tCOMMA bvar
- {
- result = val[0] << val[2]
- }
-
- bvar: tIDENTIFIER
- {
- result = @builder.shadowarg(val[0])
- }
- | f_bad_arg
-
- lambda: {
- @static_env.extend_dynamic
- }
- f_larglist
- {
- result = @lexer.cmdarg.dup
- @lexer.cmdarg.clear
- }
- lambda_body
- {
- @lexer.cmdarg = val[2]
- @lexer.cmdarg.lexpop
-
- result = [ val[1], val[3] ]
-
- @static_env.unextend
- }
-
- f_larglist: tLPAREN2 f_args opt_bv_decl tRPAREN
- {
- result = @builder.args(val[0], val[1].concat(val[2]), val[3])
- }
- | f_args
- {
- result = @builder.args(nil, val[0], nil)
- }
-
- lambda_body: tLAMBEG compstmt tRCURLY
- {
- result = [ val[0], val[1], val[2] ]
- }
- | kDO_LAMBDA compstmt kEND
- {
- result = [ val[0], val[1], val[2] ]
- }
-
- do_block: kDO_BLOCK
- {
- @static_env.extend_dynamic
- }
- opt_block_param compstmt kEND
- {
- result = [ val[0], val[2], val[3], val[4] ]
-
- @static_env.unextend
- }
-
- block_call: command do_block
- {
- begin_t, block_args, body, end_t = val[1]
- result = @builder.block(val[0],
- begin_t, block_args, body, end_t)
- }
- | block_call dot_or_colon operation2 opt_paren_args
- {
- lparen_t, args, rparen_t = val[3]
- result = @builder.call_method(val[0], val[1], val[2],
- lparen_t, args, rparen_t)
- }
- | block_call dot_or_colon operation2 opt_paren_args brace_block
- {
- lparen_t, args, rparen_t = val[3]
- method_call = @builder.call_method(val[0], val[1], val[2],
- lparen_t, args, rparen_t)
-
- begin_t, args, body, end_t = val[4]
- result = @builder.block(method_call,
- begin_t, args, body, end_t)
- }
- | block_call dot_or_colon operation2 command_args do_block
- {
- method_call = @builder.call_method(val[0], val[1], val[2],
- nil, val[3], nil)
-
- begin_t, args, body, end_t = val[4]
- result = @builder.block(method_call,
- begin_t, args, body, end_t)
- }
-
- method_call: fcall paren_args
- {
- lparen_t, args, rparen_t = val[1]
- result = @builder.call_method(nil, nil, val[0],
- lparen_t, args, rparen_t)
- }
- | primary_value tDOT operation2 opt_paren_args
- {
- lparen_t, args, rparen_t = val[3]
- result = @builder.call_method(val[0], val[1], val[2],
- lparen_t, args, rparen_t)
- }
- | primary_value tCOLON2 operation2 paren_args
- {
- lparen_t, args, rparen_t = val[3]
- result = @builder.call_method(val[0], val[1], val[2],
- lparen_t, args, rparen_t)
- }
- | primary_value tCOLON2 operation3
- {
- result = @builder.call_method(val[0], val[1], val[2])
- }
- | primary_value tDOT paren_args
- {
- lparen_t, args, rparen_t = val[2]
- result = @builder.call_method(val[0], val[1], nil,
- lparen_t, args, rparen_t)
- }
- | primary_value tCOLON2 paren_args
- {
- lparen_t, args, rparen_t = val[2]
- result = @builder.call_method(val[0], val[1], nil,
- lparen_t, args, rparen_t)
- }
- | kSUPER paren_args
- {
- lparen_t, args, rparen_t = val[1]
- result = @builder.keyword_cmd(:super, val[0],
- lparen_t, args, rparen_t)
- }
- | kSUPER
- {
- result = @builder.keyword_cmd(:zsuper, val[0])
- }
- | primary_value tLBRACK2 opt_call_args rbracket
- {
- result = @builder.index(val[0], val[1], val[2], val[3])
- }
-
- brace_block: tLCURLY
- {
- @static_env.extend_dynamic
- }
- opt_block_param compstmt tRCURLY
- {
- result = [ val[0], val[2], val[3], val[4] ]
-
- @static_env.unextend
- }
- | kDO
- {
- @static_env.extend_dynamic
- }
- opt_block_param compstmt kEND
- {
- result = [ val[0], val[2], val[3], val[4] ]
-
- @static_env.unextend
- }
-
- case_body: kWHEN args then compstmt cases
- {
- result = [ @builder.when(val[0], val[1], val[2], val[3]),
- *val[4] ]
- }
-
- cases: opt_else
- {
- result = [ val[0] ]
- }
- | case_body
-
- opt_rescue: kRESCUE exc_list exc_var then compstmt opt_rescue
- {
- assoc_t, exc_var = val[2]
-
- if val[1]
- exc_list = @builder.array(nil, val[1], nil)
- end
-
- result = [ @builder.rescue_body(val[0],
- exc_list, assoc_t, exc_var,
- val[3], val[4]),
- *val[5] ]
- }
- |
- {
- result = []
- }
-
- exc_list: arg_value
- {
- result = [ val[0] ]
- }
- | mrhs
- | none
-
- exc_var: tASSOC lhs
- {
- result = [ val[0], val[1] ]
- }
- | none
-
- opt_ensure: kENSURE compstmt
- {
- result = [ val[0], val[1] ]
- }
- | none
-
- literal: numeric
- | symbol
- | dsym
-
- strings: string
- {
- result = @builder.string_compose(nil, val[0], nil)
- }
-
- string: string1
- {
- result = [ val[0] ]
- }
- | string string1
- {
- result = val[0] << val[1]
- }
-
- string1: tSTRING_BEG string_contents tSTRING_END
- {
- result = @builder.string_compose(val[0], val[1], val[2])
- }
- | tSTRING
- {
- result = @builder.string(val[0])
- }
- | tCHARACTER
- {
- result = @builder.character(val[0])
- }
-
- xstring: tXSTRING_BEG xstring_contents tSTRING_END
- {
- result = @builder.xstring_compose(val[0], val[1], val[2])
- }
-
- regexp: tREGEXP_BEG regexp_contents tSTRING_END tREGEXP_OPT
- {
- opts = @builder.regexp_options(val[3])
- result = @builder.regexp_compose(val[0], val[1], val[2], opts)
- }
-
- words: tWORDS_BEG word_list tSTRING_END
- {
- result = @builder.words_compose(val[0], val[1], val[2])
- }
-
- word_list: # nothing
- {
- result = []
- }
- | word_list word tSPACE
- {
- result = val[0] << @builder.word(val[1])
- }
-
- word: string_content
- {
- result = [ val[0] ]
- }
- | word string_content
- {
- result = val[0] << val[1]
- }
-
- symbols: tSYMBOLS_BEG symbol_list tSTRING_END
- {
- result = @builder.symbols_compose(val[0], val[1], val[2])
- }
-
- symbol_list: # nothing
- {
- result = []
- }
- | symbol_list word tSPACE
- {
- result = val[0] << @builder.word(val[1])
- }
-
- qwords: tQWORDS_BEG qword_list tSTRING_END
- {
- result = @builder.words_compose(val[0], val[1], val[2])
- }
-
- qsymbols: tQSYMBOLS_BEG qsym_list tSTRING_END
- {
- result = @builder.symbols_compose(val[0], val[1], val[2])
- }
-
- qword_list: # nothing
- {
- result = []
- }
- | qword_list tSTRING_CONTENT tSPACE
- {
- result = val[0] << @builder.string_internal(val[1])
- }
-
- qsym_list: # nothing
- {
- result = []
- }
- | qsym_list tSTRING_CONTENT tSPACE
- {
- result = val[0] << @builder.symbol_internal(val[1])
- }
-
- string_contents: # nothing
- {
- result = []
- }
- | string_contents string_content
- {
- result = val[0] << val[1]
- }
-
-xstring_contents: # nothing
- {
- result = []
- }
- | xstring_contents string_content
- {
- result = val[0] << val[1]
- }
-
-regexp_contents: # nothing
- {
- result = []
- }
- | regexp_contents string_content
- {
- result = val[0] << val[1]
- }
-
- string_content: tSTRING_CONTENT
- {
- result = @builder.string_internal(val[0])
- }
- | tSTRING_DVAR string_dvar
- {
- result = val[1]
- }
- | tSTRING_DBEG
- {
- @lexer.cond.push(false)
- @lexer.cmdarg.push(false)
- }
- compstmt tSTRING_DEND
- {
- @lexer.cond.lexpop
- @lexer.cmdarg.lexpop
-
- result = @builder.begin(val[0], val[2], val[3])
- }
-
- string_dvar: tGVAR
- {
- result = @builder.gvar(val[0])
- }
- | tIVAR
- {
- result = @builder.ivar(val[0])
- }
- | tCVAR
- {
- result = @builder.cvar(val[0])
- }
- | backref
-
-
- symbol: tSYMBOL
- {
- result = @builder.symbol(val[0])
- }
-
- dsym: tSYMBEG xstring_contents tSTRING_END
- {
- result = @builder.symbol_compose(val[0], val[1], val[2])
- }
-
- numeric: simple_numeric
- {
- result = val[0]
- }
- | tUMINUS_NUM simple_numeric =tLOWEST
- {
- result = @builder.negate(val[0], val[1])
- }
-
- simple_numeric: tINTEGER
- {
- result = @builder.integer(val[0])
- }
- | tFLOAT
- {
- result = @builder.float(val[0])
- }
- | tRATIONAL
- {
- result = @builder.rational(val[0])
- }
- | tIMAGINARY
- {
- result = @builder.complex(val[0])
- }
-
- user_variable: tIDENTIFIER
- {
- result = @builder.ident(val[0])
- }
- | tIVAR
- {
- result = @builder.ivar(val[0])
- }
- | tGVAR
- {
- result = @builder.gvar(val[0])
- }
- | tCONSTANT
- {
- result = @builder.const(val[0])
- }
- | tCVAR
- {
- result = @builder.cvar(val[0])
- }
-
-keyword_variable: kNIL
- {
- result = @builder.nil(val[0])
- }
- | kSELF
- {
- result = @builder.self(val[0])
- }
- | kTRUE
- {
- result = @builder.true(val[0])
- }
- | kFALSE
- {
- result = @builder.false(val[0])
- }
- | k__FILE__
- {
- result = @builder.__FILE__(val[0])
- }
- | k__LINE__
- {
- result = @builder.__LINE__(val[0])
- }
- | k__ENCODING__
- {
- result = @builder.__ENCODING__(val[0])
- }
-
- var_ref: user_variable
- {
- result = @builder.accessible(val[0])
- }
- | keyword_variable
- {
- result = @builder.accessible(val[0])
- }
-
- var_lhs: user_variable
- {
- result = @builder.assignable(val[0])
- }
- | keyword_variable
- {
- result = @builder.assignable(val[0])
- }
-
- backref: tNTH_REF
- {
- result = @builder.nth_ref(val[0])
- }
- | tBACK_REF
- {
- result = @builder.back_ref(val[0])
- }
-
- superclass: term
- {
- result = nil
- }
- | tLT
- {
- @lexer.state = :expr_value
- }
- expr_value term
- {
- result = [ val[0], val[2] ]
- }
- | error term
- {
- yyerrok
- result = nil
- }
-
- f_arglist: tLPAREN2 f_args rparen
- {
- result = @builder.args(val[0], val[1], val[2])
-
- @lexer.state = :expr_value
- }
- | {
- result = @lexer.in_kwarg
- @lexer.in_kwarg = true
- }
- f_args term
- {
- @lexer.in_kwarg = val[0]
- result = @builder.args(nil, val[1], nil)
- }
-
- args_tail: f_kwarg tCOMMA f_kwrest opt_f_block_arg
- {
- result = val[0].concat(val[2]).concat(val[3])
- }
- | f_kwarg opt_f_block_arg
- {
- result = val[0].concat(val[1])
- }
- | f_kwrest opt_f_block_arg
- {
- result = val[0].concat(val[1])
- }
- | f_block_arg
- {
- result = [ val[0] ]
- }
-
- opt_args_tail: tCOMMA args_tail
- {
- result = val[1]
- }
- | # nothing
- {
- result = []
- }
-
- f_args: f_arg tCOMMA f_optarg tCOMMA f_rest_arg opt_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
- }
- | f_arg tCOMMA f_optarg tCOMMA f_rest_arg tCOMMA f_arg opt_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[6]).
- concat(val[7])
- }
- | f_arg tCOMMA f_optarg opt_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | f_arg tCOMMA f_optarg tCOMMA f_arg opt_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
- }
- | f_arg tCOMMA f_rest_arg opt_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | f_arg tCOMMA f_rest_arg tCOMMA f_arg opt_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
- }
- | f_arg opt_args_tail
- {
- result = val[0].
- concat(val[1])
- }
- | f_optarg tCOMMA f_rest_arg opt_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | f_optarg tCOMMA f_rest_arg tCOMMA f_arg opt_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
- }
- | f_optarg opt_args_tail
- {
- result = val[0].
- concat(val[1])
- }
- | f_optarg tCOMMA f_arg opt_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | f_rest_arg opt_args_tail
- {
- result = val[0].
- concat(val[1])
- }
- | f_rest_arg tCOMMA f_arg opt_args_tail
- {
- result = val[0].
- concat(val[2]).
- concat(val[3])
- }
- | args_tail
- {
- result = val[0]
- }
- | # nothing
- {
- result = []
- }
-
- f_bad_arg: tCONSTANT
- {
- diagnostic :error, :argument_const, nil, val[0]
- }
- | tIVAR
- {
- diagnostic :error, :argument_ivar, nil, val[0]
- }
- | tGVAR
- {
- diagnostic :error, :argument_gvar, nil, val[0]
- }
- | tCVAR
- {
- diagnostic :error, :argument_cvar, nil, val[0]
- }
-
- f_norm_arg: f_bad_arg
- | tIDENTIFIER
- {
- @static_env.declare val[0][0]
-
- result = val[0]
- }
-
- f_arg_asgn: f_norm_arg
- {
- result = val[0]
- }
-
- f_arg_item: f_arg_asgn
- {
- result = @builder.arg(val[0])
- }
- | tLPAREN f_margs rparen
- {
- result = @builder.multi_lhs(val[0], val[1], val[2])
- }
-
- f_arg: f_arg_item
- {
- result = [ val[0] ]
- }
- | f_arg tCOMMA f_arg_item
- {
- result = val[0] << val[2]
- }
-
- f_label: tLABEL
- {
- check_kwarg_name(val[0])
-
- @static_env.declare val[0][0]
-
- result = val[0]
- }
-
- f_kw: f_label arg_value
- {
- result = @builder.kwoptarg(val[0], val[1])
- }
- | f_label
- {
- result = @builder.kwarg(val[0])
- }
-
- f_block_kw: f_label primary_value
- {
- result = @builder.kwoptarg(val[0], val[1])
- }
- | f_label
- {
- result = @builder.kwarg(val[0])
- }
-
- f_block_kwarg: f_block_kw
- {
- result = [ val[0] ]
- }
- | f_block_kwarg tCOMMA f_block_kw
- {
- result = val[0] << val[2]
- }
-
- f_kwarg: f_kw
- {
- result = [ val[0] ]
- }
- | f_kwarg tCOMMA f_kw
- {
- result = val[0] << val[2]
- }
-
- kwrest_mark: tPOW | tDSTAR
-
- f_kwrest: kwrest_mark tIDENTIFIER
- {
- @static_env.declare val[1][0]
-
- result = [ @builder.kwrestarg(val[0], val[1]) ]
- }
- | kwrest_mark
- {
- result = [ @builder.kwrestarg(val[0]) ]
- }
-
- f_opt: f_arg_asgn tEQL arg_value
- {
- result = @builder.optarg(val[0], val[1], val[2])
- }
-
- f_block_opt: f_arg_asgn tEQL primary_value
- {
- result = @builder.optarg(val[0], val[1], val[2])
- }
-
- f_block_optarg: f_block_opt
- {
- result = [ val[0] ]
- }
- | f_block_optarg tCOMMA f_block_opt
- {
- result = val[0] << val[2]
- }
-
- f_optarg: f_opt
- {
- result = [ val[0] ]
- }
- | f_optarg tCOMMA f_opt
- {
- result = val[0] << val[2]
- }
-
- restarg_mark: tSTAR2 | tSTAR
-
- f_rest_arg: restarg_mark tIDENTIFIER
- {
- @static_env.declare val[1][0]
-
- result = [ @builder.restarg(val[0], val[1]) ]
- }
- | restarg_mark
- {
- result = [ @builder.restarg(val[0]) ]
- }
-
- blkarg_mark: tAMPER2 | tAMPER
-
- f_block_arg: blkarg_mark tIDENTIFIER
- {
- @static_env.declare val[1][0]
-
- result = @builder.blockarg(val[0], val[1])
- }
-
- opt_f_block_arg: tCOMMA f_block_arg
- {
- result = [ val[1] ]
- }
- |
- {
- result = []
- }
-
- singleton: var_ref
- | tLPAREN2 expr rparen
- {
- result = val[1]
- }
-
- assoc_list: # nothing
- {
- result = []
- }
- | assocs trailer
-
- assocs: assoc
- {
- result = [ val[0] ]
- }
- | assocs tCOMMA assoc
- {
- result = val[0] << val[2]
- }
-
- assoc: arg_value tASSOC arg_value
- {
- result = @builder.pair(val[0], val[1], val[2])
- }
- | tLABEL arg_value
- {
- result = @builder.pair_keyword(val[0], val[1])
- }
- | tSTRING_BEG string_contents tLABEL_END arg_value
- {
- result = @builder.pair_quoted(val[0], val[1], val[2], val[3])
- }
- | tDSTAR arg_value
- {
- result = @builder.kwsplat(val[0], val[1])
- }
-
- operation: tIDENTIFIER | tCONSTANT | tFID
- operation2: tIDENTIFIER | tCONSTANT | tFID | op
- operation3: tIDENTIFIER | tFID | op
- dot_or_colon: tDOT | tCOLON2
- opt_terms: | terms
- opt_nl: | tNL
- rparen: opt_nl tRPAREN
- {
- result = val[1]
- }
- rbracket: opt_nl tRBRACK
- {
- result = val[1]
- }
- trailer: | tNL | tCOMMA
-
- term: tSEMI
- {
- yyerrok
- }
- | tNL
-
- terms: term
- | terms tSEMI
-
- none: # nothing
- {
- result = nil
- }
-end
-
----- header
-
-require 'parser'
-
-Parser.check_for_encoding_support
-
----- inner
-
- def version
- 22
- end
-
- def default_encoding
- Encoding::UTF_8
- end
diff --git a/test/racc/assets/scan.y b/test/racc/assets/scan.y
deleted file mode 100644
index 709254ed66..0000000000
--- a/test/racc/assets/scan.y
+++ /dev/null
@@ -1,72 +0,0 @@
-class P
-
-rule
-
- a: A
- {
- # comment test
-
- # comment test
-
- # string
- @sstring = 'squote string'
- @dstring = 'dquote string'
-
- # regexp
- @regexp = /some regexp with spaces/
-
- # gvar
- /regexp/ === 'some regexp matches to this string'
- @pre_match = $`
- @matched = $&
- @post_match = $'
- @m = $~
-
- # braces
- @array = []
- [1,2,3].each {|i|
- @array.push i
- }
- 3.times { @array.push 10 }
- }
-
-end
-
----- inner
-
- def parse
- @sstring = @dstring = nil
- @regexp = nil
- @pre_match = @matched = @post_match = @m = nil
-
- @src = [[:A, 'A'], [false, '$']]
- do_parse
-
- assert_equal 'squote string', @sstring
- assert_equal 'dquote string', @dstring
- assert_equal(/some regexp with spaces/, @regexp)
- assert_equal 'some ', @pre_match
- assert_equal 'regexp', @matched
- assert_equal ' matches to this string', @post_match
- assert_instance_of MatchData, @m
- end
-
- def assert_equal(ok, data)
- unless ok == data
- raise "expected <#{ok.inspect}> but is <#{data.inspect}>"
- end
- end
-
- def assert_instance_of(klass, obj)
- unless obj.instance_of?(klass)
- raise "expected #{klass} but is #{obj.class}"
- end
- end
-
- def next_token
- @src.shift
- end
-
----- footer
-
-P.new.parse
diff --git a/test/racc/assets/syntax.y b/test/racc/assets/syntax.y
deleted file mode 100644
index 727f74a29d..0000000000
--- a/test/racc/assets/syntax.y
+++ /dev/null
@@ -1,50 +0,0 @@
-#
-# racc syntax checker
-#
-
-class M1::M2::ParserClass < S1::S2::SuperClass
-
- token A
- | B C
-
- convert
- A '5'
- end
-
- prechigh
- left B
- preclow
-
- start target
-
- expect 0
-
-rule
-
- target: A B C
- {
- print 'abc'
- }
- | B C A
- | C B A
- {
- print 'cba'
- }
- | cont
-
- cont : A c2 B c2 C
-
- c2 : C C C C C
-
-end
-
----- inner
-
- junk code !!!!
-
-kjaljlajrlaolanbla /// %%% (*((( token rule
-akiurtlajluealjflaj @@@@ end end end end __END__
- laieu2o879urkq96ga(Q#*&%Q#
- #&lkji END
-
- q395q?/// liutjqlkr7
diff --git a/test/racc/assets/tp_plus.y b/test/racc/assets/tp_plus.y
deleted file mode 100644
index 388ed1302d..0000000000
--- a/test/racc/assets/tp_plus.y
+++ /dev/null
@@ -1,622 +0,0 @@
-# Released under an MIT License (http://www.opensource.org/licenses/MIT)
-# By Jay Strybis (https://github.com/unreal)
-
-class TPPlus::Parser
-token ASSIGN AT_SYM COMMENT JUMP IO_METHOD INPUT OUTPUT
-token NUMREG POSREG VREG SREG TIME_SEGMENT ARG UALM
-token MOVE DOT TO AT TERM OFFSET SKIP GROUP
-token SEMICOLON NEWLINE STRING
-token REAL DIGIT WORD EQUAL
-token EEQUAL NOTEQUAL GTE LTE LT GT BANG
-token PLUS MINUS STAR SLASH DIV AND OR MOD
-token IF ELSE END UNLESS FOR IN WHILE
-token WAIT_FOR WAIT_UNTIL TIMEOUT AFTER
-token FANUC_USE SET_SKIP_CONDITION NAMESPACE
-token CASE WHEN INDIRECT POSITION
-token EVAL TIMER TIMER_METHOD RAISE ABORT
-token POSITION_DATA TRUE_FALSE RUN TP_HEADER PAUSE
-token LPAREN RPAREN COLON COMMA LBRACK RBRACK LBRACE RBRACE
-token LABEL ADDRESS
-token false
-
-prechigh
- right BANG
- left STAR SLASH DIV MOD
- left PLUS MINUS
- left GT GTE LT LTE
- left EEQUAL NOTEQUAL
- left AND
- left OR
- right EQUAL
-preclow
-
-rule
- program
- #: statements { @interpreter.nodes = val[0].flatten }
- : statements { @interpreter.nodes = val[0] }
- |
- ;
-
-
- statements
- : statement terminator {
- result = [val[0]]
- result << val[1] unless val[1].nil?
- }
- | statements statement terminator {
- result = val[0] << val[1]
- result << val[2] unless val[2].nil?
- }
- ;
-
- block
- : NEWLINE statements { result = val[1] }
- ;
-
- optional_newline
- : NEWLINE
- |
- ;
-
- statement
- : comment
- | definition
- | namespace
- #| assignment
- | motion_statement
- #| jump
- #| io_method
- | label_definition
- | address
- | conditional
- | inline_conditional
- | forloop
- | while_loop
- #| program_call
- | use_statement
- | set_skip_statement
- | wait_statement
- | case_statement
- | fanuc_eval
- | timer_method
- | position_data
- | raise
- | tp_header_definition
- | empty_stmt
- | PAUSE { result = PauseNode.new }
- | ABORT { result = AbortNode.new }
- ;
-
- empty_stmt
- : NEWLINE { result = EmptyStmtNode.new() }
- ;
-
- tp_header_definition
- : TP_HEADER EQUAL tp_header_value { result = HeaderNode.new(val[0],val[2]) }
- ;
-
- tp_header_value
- : STRING
- | TRUE_FALSE
- ;
-
- raise
- : RAISE var_or_indirect { result = RaiseNode.new(val[1]) }
- ;
-
- timer_method
- : TIMER_METHOD var_or_indirect { result = TimerMethodNode.new(val[0],val[1]) }
- ;
-
- fanuc_eval
- : EVAL STRING { result = EvalNode.new(val[1]) }
- ;
-
- wait_statement
- : WAIT_FOR LPAREN indirectable COMMA STRING RPAREN
- { result = WaitForNode.new(val[2], val[4]) }
- | WAIT_UNTIL LPAREN expression RPAREN
- { result = WaitUntilNode.new(val[2], nil) }
- | WAIT_UNTIL LPAREN expression RPAREN DOT wait_modifier
- { result = WaitUntilNode.new(val[2],val[5]) }
- | WAIT_UNTIL LPAREN expression RPAREN DOT wait_modifier DOT wait_modifier
- { result = WaitUntilNode.new(val[2],val[5].merge(val[7])) }
- ;
-
- wait_modifier
- : timeout_modifier
- | after_modifier
- ;
-
- timeout_modifier
- : swallow_newlines TIMEOUT LPAREN label RPAREN
- { result = { label: val[3] } }
- ;
-
- after_modifier
- : swallow_newlines AFTER LPAREN indirectable COMMA STRING RPAREN
- { result = { timeout: [val[3],val[5]] } }
- ;
-
- label
- : LABEL { result = val[0] }
- ;
-
- use_statement
- : FANUC_USE indirectable { result = UseNode.new(val[0],val[1]) }
- ;
-
- # set_skip_condition x
- set_skip_statement
- : SET_SKIP_CONDITION expression { result = SetSkipNode.new(val[1]) }
- ;
-
- program_call
- : WORD LPAREN args RPAREN { result = CallNode.new(val[0],val[2]) }
- | RUN WORD LPAREN args RPAREN { result = CallNode.new(val[1],val[3],async: true) }
- ;
-
- args
- : arg { result = [val[0]] }
- | args COMMA arg { result = val[0] << val[2] }
- | { result = [] }
- ;
-
- arg
- : number
- | var
- | string
- | address
- ;
-
- string
- : STRING { result = StringNode.new(val[0]) }
- ;
-
- io_method
- : IO_METHOD var_or_indirect { result = IOMethodNode.new(val[0],val[1]) }
- | IO_METHOD LPAREN var_or_indirect RPAREN
- { result = IOMethodNode.new(val[0],val[2]) }
- | IO_METHOD LPAREN var_or_indirect COMMA number COMMA STRING RPAREN
- { result = IOMethodNode.new(val[0],val[2],{ pulse_time: val[4], pulse_units: val[6] }) }
- ;
-
- var_or_indirect
- : var
- | indirect_thing
- ;
-
-
- jump
- : JUMP label { result = JumpNode.new(val[1]) }
- ;
-
- conditional
- : IF expression block else_block END
- { result = ConditionalNode.new("if",val[1],val[2],val[3]) }
- | UNLESS expression block else_block END
- { result = ConditionalNode.new("unless",val[1],val[2],val[3]) }
- ;
-
- forloop
- : FOR var IN LPAREN minmax_val TO minmax_val RPAREN block END
- { result = ForNode.new(val[1],val[4],val[6],val[8]) }
- ;
-
- while_loop
- : WHILE expression block END { result = WhileNode.new(val[1],val[2]) }
- ;
-
- minmax_val
- : integer
- | var
- ;
-
- namespace
- : NAMESPACE WORD block END { result = NamespaceNode.new(val[1],val[2]) }
- ;
-
- case_statement
- : CASE var swallow_newlines
- case_conditions
- case_else
- END { result = CaseNode.new(val[1],val[3],val[4]) }
- ;
-
- case_conditions
- : case_condition { result = val }
- | case_conditions case_condition
- { result = val[0] << val[1] << val[2] }
- ;
-
- case_condition
- : WHEN case_allowed_condition swallow_newlines case_allowed_statement
- terminator { result = CaseConditionNode.new(val[1],val[3]) }
- ;
-
- case_allowed_condition
- : number
- | var
- ;
-
- case_else
- : ELSE swallow_newlines case_allowed_statement terminator
- { result = CaseConditionNode.new(nil,val[2]) }
- |
- ;
-
- case_allowed_statement
- : program_call
- | jump
- ;
-
- inline_conditional
- : inlineable
- | inlineable IF expression { result = InlineConditionalNode.new(val[1], val[2], val[0]) }
- | inlineable UNLESS expression { result = InlineConditionalNode.new(val[1], val[2], val[0]) }
- ;
-
- inlineable
- : jump
- | assignment
- | io_method
- | program_call
- ;
-
- else_block
- : ELSE block { result = val[1] }
- | { result = [] }
- ;
-
- motion_statement
- : MOVE DOT swallow_newlines TO LPAREN var RPAREN motion_modifiers
- { result = MotionNode.new(val[0],val[5],val[7]) }
- ;
-
- motion_modifiers
- : motion_modifier { result = val }
- | motion_modifiers motion_modifier
- { result = val[0] << val[1] }
- ;
-
- motion_modifier
- : DOT swallow_newlines AT LPAREN speed RPAREN
- { result = SpeedNode.new(val[4]) }
- | DOT swallow_newlines TERM LPAREN valid_terminations RPAREN
- { result = TerminationNode.new(val[4]) }
- | DOT swallow_newlines OFFSET LPAREN var RPAREN
- { result = OffsetNode.new(val[2],val[4]) }
- | DOT swallow_newlines TIME_SEGMENT LPAREN time COMMA time_seg_actions RPAREN
- { result = TimeNode.new(val[2],val[4],val[6]) }
- | DOT swallow_newlines SKIP LPAREN label optional_lpos_arg RPAREN
- { result = SkipNode.new(val[4],val[5]) }
- ;
-
- valid_terminations
- : integer
- | var
- | MINUS DIGIT {
- raise Racc::ParseError, sprintf("\ninvalid termination type: (%s)", val[1]) if val[1] != 1
-
- result = DigitNode.new(val[1].to_i * -1)
- }
- ;
-
- optional_lpos_arg
- : COMMA var { result = val[1] }
- |
- ;
-
- indirectable
- : number
- | var
- ;
-
- time_seg_actions
- : program_call
- | io_method
- ;
-
- time
- : var
- | number
- ;
-
- speed
- : indirectable COMMA STRING { result = { speed: val[0], units: val[2] } }
- | STRING { result = { speed: val[0], units: nil } }
- ;
-
- label_definition
- : label { result = LabelDefinitionNode.new(val[0]) }#@interpreter.add_label(val[1]) }
- ;
-
- definition
- : WORD ASSIGN definable { result = DefinitionNode.new(val[0],val[2]) }
- ;
-
- assignment
- : var_or_indirect EQUAL expression { result = AssignmentNode.new(val[0],val[2]) }
- | var_or_indirect PLUS EQUAL expression { result = AssignmentNode.new(
- val[0],
- ExpressionNode.new(val[0],"+",val[3])
- )
- }
- | var_or_indirect MINUS EQUAL expression { result = AssignmentNode.new(
- val[0],
- ExpressionNode.new(val[0],"-",val[3])
- )
- }
- ;
-
- var
- : var_without_namespaces
- | var_with_namespaces
- ;
-
- var_without_namespaces
- : WORD { result = VarNode.new(val[0]) }
- | WORD var_method_modifiers { result = VarMethodNode.new(val[0],val[1]) }
- ;
-
- var_with_namespaces
- : namespaces var_without_namespaces
- { result = NamespacedVarNode.new(val[0],val[1]) }
- ;
-
- var_method_modifiers
- : var_method_modifier { result = val[0] }
- | var_method_modifiers var_method_modifier
- { result = val[0].merge(val[1]) }
- ;
-
- var_method_modifier
- : DOT swallow_newlines WORD { result = { method: val[2] } }
- | DOT swallow_newlines GROUP LPAREN integer RPAREN
- { result = { group: val[4] } }
- ;
-
- namespaces
- : ns { result = [val[0]] }
- | namespaces ns { result = val[0] << val[1] }
- ;
-
- ns
- : WORD COLON COLON { result = val[0] }
- ;
-
-
- expression
- : unary_expression
- | binary_expression
- ;
-
- unary_expression
- : factor { result = val[0] }
- | address
- | BANG factor { result = ExpressionNode.new(val[1], "!", nil) }
- ;
-
- binary_expression
- : expression operator expression
- { result = ExpressionNode.new(val[0], val[1], val[2]) }
- ;
-
- operator
- : EEQUAL { result = "==" }
- | NOTEQUAL { result = "<>" }
- | LT { result = "<" }
- | GT { result = ">" }
- | GTE { result = ">=" }
- | LTE { result = "<=" }
- | PLUS { result = "+" }
- | MINUS { result = "-" }
- | OR { result = "||" }
- | STAR { result = "*" }
- | SLASH { result = "/" }
- | DIV { result = "DIV" }
- | MOD { result = "%" }
- | AND { result = "&&" }
- ;
-
- factor
- : number
- | signed_number
- | var
- | indirect_thing
- | paren_expr
- ;
-
- paren_expr
- : LPAREN expression RPAREN { result = ParenExpressionNode.new(val[1]) }
- ;
-
- indirect_thing
- : INDIRECT LPAREN STRING COMMA indirectable RPAREN
- { result = IndirectNode.new(val[2].to_sym, val[4]) }
- ;
-
- signed_number
- : sign DIGIT {
- val[1] = val[1].to_i * -1 if val[0] == "-"
- result = DigitNode.new(val[1])
- }
- | sign REAL { val[1] = val[1].to_f * -1 if val[0] == "-"; result = RealNode.new(val[1]) }
- ;
-
- sign
- : MINUS { result = "-" }
- ;
-
- number
- : integer
- | REAL { result = RealNode.new(val[0]) }
- ;
-
- integer
- : DIGIT { result = DigitNode.new(val[0]) }
- ;
-
- definable
- : numreg
- | output
- | input
- | posreg
- | position
- | vreg
- | number
- | signed_number
- | argument
- | timer
- | ualm
- | sreg
- ;
-
-
- sreg
- : SREG LBRACK DIGIT RBRACK { result = StringRegisterNode.new(val[2].to_i) }
- ;
-
- ualm
- : UALM LBRACK DIGIT RBRACK { result = UserAlarmNode.new(val[2].to_i) }
- ;
-
- timer
- : TIMER LBRACK DIGIT RBRACK { result = TimerNode.new(val[2].to_i) }
- ;
-
- argument
- : ARG LBRACK DIGIT RBRACK { result = ArgumentNode.new(val[2].to_i) }
- ;
-
- vreg
- : VREG LBRACK DIGIT RBRACK { result = VisionRegisterNode.new(val[2].to_i) }
- ;
-
- position
- : POSITION LBRACK DIGIT RBRACK { result = PositionNode.new(val[2].to_i) }
- ;
-
- numreg
- : NUMREG LBRACK DIGIT RBRACK { result = NumregNode.new(val[2].to_i) }
- ;
-
- posreg
- : POSREG LBRACK DIGIT RBRACK { result = PosregNode.new(val[2].to_i) }
- ;
-
- output
- : OUTPUT LBRACK DIGIT RBRACK { result = IONode.new(val[0], val[2].to_i) }
- ;
-
- input
- : INPUT LBRACK DIGIT RBRACK { result = IONode.new(val[0], val[2].to_i) }
- ;
-
- address
- : ADDRESS { result = AddressNode.new(val[0]) }
- ;
-
- comment
- : COMMENT { result = CommentNode.new(val[0]) }
- ;
-
- terminator
- : NEWLINE { result = TerminatorNode.new }
- | comment optional_newline { result = val[0] }
- # ^-- consume newlines or else we will get an extra space from EmptyStmt in the output
- | false
- |
- ;
-
- swallow_newlines
- : NEWLINE { result = TerminatorNode.new }
- |
- ;
-
- position_data
- : POSITION_DATA sn hash sn END
- { result = PositionDataNode.new(val[2]) }
- ;
-
- sn
- : swallow_newlines
- ;
-
- hash
- : LBRACE sn hash_attributes sn RBRACE { result = val[2] }
- | LBRACE sn RBRACE { result = {} }
- ;
-
- hash_attributes
- : hash_attribute { result = val[0] }
- | hash_attributes COMMA sn hash_attribute
- { result = val[0].merge(val[3]) }
- ;
-
- hash_attribute
- : STRING COLON hash_value { result = { val[0].to_sym => val[2] } }
- ;
-
- hash_value
- : STRING
- | hash
- | array
- | optional_sign DIGIT { val[1] = val[1].to_i * -1 if val[0] == "-"; result = val[1] }
- | optional_sign REAL { val[1] = val[1].to_f * -1 if val[0] == "-"; result = val[1] }
- | TRUE_FALSE { result = val[0] == "true" }
- ;
-
- optional_sign
- : sign
- |
- ;
-
- array
- : LBRACK sn array_values sn RBRACK { result = val[2] }
- ;
-
- array_values
- : array_value { result = val }
- | array_values COMMA sn array_value { result = val[0] << val[3] }
- ;
-
- array_value
- : hash_value
- ;
-
-
-end
-
----- inner
-
- include TPPlus::Nodes
-
- attr_reader :interpreter
- def initialize(scanner, interpreter = TPPlus::Interpreter.new)
- @scanner = scanner
- @interpreter = interpreter
- super()
- end
-
- def next_token
- t = @scanner.next_token
- @interpreter.line_count += 1 if t && t[0] == :NEWLINE
-
- #puts t.inspect
- t
- end
-
- def parse
- #@yydebug =true
-
- do_parse
- @interpreter
- end
-
- def on_error(t, val, vstack)
- raise ParseError, sprintf("Parse error on line #{@scanner.tok_line} column #{@scanner.tok_col}: %s (%s)",
- val.inspect, token_to_str(t) || '?')
- end
-
- class ParseError < StandardError ; end
diff --git a/test/racc/assets/twowaysql.y b/test/racc/assets/twowaysql.y
deleted file mode 100644
index d3bc748d3a..0000000000
--- a/test/racc/assets/twowaysql.y
+++ /dev/null
@@ -1,278 +0,0 @@
-# Copyright 2008-2015 Takuto Wada
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-class TwoWaySQL::Parser
-
-rule
-
-sql : stmt_list
- {
- result = RootNode.new( val[0] )
- }
-
-stmt_list :
- {
- result = []
- }
- | stmt_list stmt
- {
- result.push val[1]
- }
-
-stmt : primary
- | if_stmt
- | begin_stmt
-
-begin_stmt : BEGIN stmt_list END
- {
- result = BeginNode.new( val[1] )
- }
-
-if_stmt : IF sub_stmt else_stmt END
- {
- result = IfNode.new( val[0][1], val[1], val[2] )
- }
-
-else_stmt : ELSE sub_stmt
- {
- result = val[1]
- }
- |
- {
- result = nil
- }
-
-sub_stmt : and_stmt
- | or_stmt
- | stmt_list
-
-and_stmt : AND stmt_list
- {
- result = SubStatementNode.new( val[0][1], val[1] )
- }
-
-or_stmt : OR stmt_list
- {
- result = SubStatementNode.new( val[0][1], val[1] )
- }
-
-primary : IDENT
- {
- result = LiteralNode.new( val[0][1] )
- }
- | STRING_LITERAL
- {
- result = LiteralNode.new( val[0][1] )
- }
- | AND
- {
- result = LiteralNode.new( val[0][1] )
- }
- | OR
- {
- result = LiteralNode.new( val[0][1] )
- }
- | SPACES
- {
- result = WhiteSpaceNode.new( val[0][1], @preserve_space )
- }
- | COMMA
- {
- result = LiteralNode.new( val[0][1] )
- }
- | LPAREN
- {
- result = LiteralNode.new( val[0][1] )
- }
- | RPAREN
- {
- result = LiteralNode.new( val[0][1] )
- }
- | QUESTION
- {
- @num_questions += 1
- result = QuestionNode.new( @num_questions )
- }
- | ACTUAL_COMMENT
- {
- result = ActualCommentNode.new( val[0][1] , val[0][2] )
- }
- | bind_var
- | embed_var
-
-bind_var : BIND_VARIABLE STRING_LITERAL
- {
- result = BindVariableNode.new( val[0][1] )
- }
- | BIND_VARIABLE SPACES STRING_LITERAL
- {
- result = BindVariableNode.new( val[0][1] )
- }
- | BIND_VARIABLE IDENT
- {
- result = BindVariableNode.new( val[0][1] )
- }
- | BIND_VARIABLE SPACES IDENT
- {
- result = BindVariableNode.new( val[0][1] )
- }
- | PAREN_BIND_VARIABLE
- {
- result = ParenBindVariableNode.new( val[0][1] )
- }
-
-embed_var : EMBED_VARIABLE IDENT
- {
- result = EmbedVariableNode.new( val[0][1] )
- }
- | EMBED_VARIABLE SPACES IDENT
- {
- result = EmbedVariableNode.new( val[0][1] )
- }
-
-end
-
-
----- inner
-
-require 'strscan'
-
-def initialize(opts={})
- opts = {
- :debug => false,
- :preserve_space => true,
- :preserve_comment => false
- }.merge(opts)
- @yydebug = opts[:debug]
- @preserve_space = opts[:preserve_space]
- @preserve_comment = opts[:preserve_comment]
- @num_questions = 0
-end
-
-
-PAREN_EXAMPLE = '\([^\)]+\)'
-BEGIN_BIND_VARIABLE = '(\/|\#)\*([^\*]+)\*\1'
-BIND_VARIABLE_PATTERN = /\A#{BEGIN_BIND_VARIABLE}\s*/
-PAREN_BIND_VARIABLE_PATTERN = /\A#{BEGIN_BIND_VARIABLE}\s*#{PAREN_EXAMPLE}/
-EMBED_VARIABLE_PATTERN = /\A(\/|\#)\*\$([^\*]+)\*\1\s*/
-
-CONDITIONAL_PATTERN = /\A(\/|\#)\*(IF)\s+([^\*]+)\s*\*\1/
-BEGIN_END_PATTERN = /\A(\/|\#)\*(BEGIN|END)\s*\*\1/
-STRING_LITERAL_PATTERN = /\A(\'(?:[^\']+|\'\')*\')/ ## quoted string
-SPLIT_TOKEN_PATTERN = /\A(\S+?)(?=\s*(?:(?:\/|\#)\*|-{2,}|\(|\)|\,))/ ## stop on delimiters --,/*,#*,',',(,)
-LITERAL_PATTERN = /\A([^;\s]+)/
-SPACES_PATTERN = /\A(\s+)/
-QUESTION_PATTERN = /\A\?/
-COMMA_PATTERN = /\A\,/
-LPAREN_PATTERN = /\A\(/
-RPAREN_PATTERN = /\A\)/
-ACTUAL_COMMENT_PATTERN = /\A(\/|\#)\*(\s{1,}(?:.*?))\*\1/m ## start with spaces
-SEMICOLON_AT_INPUT_END_PATTERN = /\A\;\s*\Z/
-UNMATCHED_COMMENT_START_PATTERN = /\A(?:(?:\/|\#)\*)/
-
-#TODO: remove trailing spaces for S2Dao compatibility, but this spec sometimes causes SQL bugs...
-ELSE_PATTERN = /\A\-{2,}\s*ELSE\s*/
-AND_PATTERN = /\A(\ *AND)\b/i
-OR_PATTERN = /\A(\ *OR)\b/i
-
-
-def parse( io )
- @q = []
- io.each_line(nil) do |whole|
- @s = StringScanner.new(whole)
- end
- scan_str
-
- # @q.push [ false, nil ]
- @q.push [ false, [@s.pos, nil] ]
-
- ## call racc's private parse method
- do_parse
-end
-
-
-## called by racc
-def next_token
- @q.shift
-end
-
-
-def scan_str
- until @s.eos? do
- case
- when @s.scan(AND_PATTERN)
- @q.push [ :AND, [@s.pos, @s[1]] ]
- when @s.scan(OR_PATTERN)
- @q.push [ :OR, [@s.pos, @s[1]] ]
- when @s.scan(SPACES_PATTERN)
- @q.push [ :SPACES, [@s.pos, @s[1]] ]
- when @s.scan(QUESTION_PATTERN)
- @q.push [ :QUESTION, [@s.pos, nil] ]
- when @s.scan(COMMA_PATTERN)
- @q.push [ :COMMA, [@s.pos, ','] ]
- when @s.scan(LPAREN_PATTERN)
- @q.push [ :LPAREN, [@s.pos, '('] ]
- when @s.scan(RPAREN_PATTERN)
- @q.push [ :RPAREN, [@s.pos, ')'] ]
- when @s.scan(ELSE_PATTERN)
- @q.push [ :ELSE, [@s.pos, nil] ]
- when @s.scan(ACTUAL_COMMENT_PATTERN)
- @q.push [ :ACTUAL_COMMENT, [@s.pos, @s[1], @s[2]] ] if @preserve_comment
- when @s.scan(BEGIN_END_PATTERN)
- @q.push [ @s[2].intern, [@s.pos, nil] ]
- when @s.scan(CONDITIONAL_PATTERN)
- @q.push [ @s[2].intern, [@s.pos, @s[3]] ]
- when @s.scan(EMBED_VARIABLE_PATTERN)
- @q.push [ :EMBED_VARIABLE, [@s.pos, @s[2]] ]
- when @s.scan(PAREN_BIND_VARIABLE_PATTERN)
- @q.push [ :PAREN_BIND_VARIABLE, [@s.pos, @s[2]] ]
- when @s.scan(BIND_VARIABLE_PATTERN)
- @q.push [ :BIND_VARIABLE, [@s.pos, @s[2]] ]
- when @s.scan(STRING_LITERAL_PATTERN)
- @q.push [ :STRING_LITERAL, [@s.pos, @s[1]] ]
- when @s.scan(SPLIT_TOKEN_PATTERN)
- @q.push [ :IDENT, [@s.pos, @s[1]] ]
- when @s.scan(UNMATCHED_COMMENT_START_PATTERN) ## unmatched comment start, '/*','#*'
- raise Racc::ParseError, "unmatched comment. line:[#{line_no(@s.pos)}], str:[#{@s.rest}]"
- when @s.scan(LITERAL_PATTERN) ## other string token
- @q.push [ :IDENT, [@s.pos, @s[1]] ]
- when @s.scan(SEMICOLON_AT_INPUT_END_PATTERN)
- #drop semicolon at input end
- else
- raise Racc::ParseError, "syntax error at or near line:[#{line_no(@s.pos)}], str:[#{@s.rest}]"
- end
- end
-end
-
-
-## override racc's default on_error method
-def on_error(t, v, vstack)
- ## cursor in value-stack is an array of two items,
- ## that have position value as 0th item. like [731, "ctx[:limit] "]
- cursor = vstack.find do |tokens|
- tokens.size == 2 and tokens[0].kind_of?(Fixnum)
- end
- pos = cursor[0]
- line = line_no(pos)
- rest = @s.string[pos .. -1]
- raise Racc::ParseError, "syntax error at or near line:[#{line}], str:[#{rest}]"
-end
-
-
-def line_no(pos)
- lines = 0
- scanned = @s.string[0..(pos)]
- scanned.each_line { lines += 1 }
- lines
-end
diff --git a/test/racc/assets/unterm.y b/test/racc/assets/unterm.y
deleted file mode 100644
index 518acc7f31..0000000000
--- a/test/racc/assets/unterm.y
+++ /dev/null
@@ -1,5 +0,0 @@
-# unterminated action
-
-class A
-rule
- a: A {
diff --git a/test/racc/assets/useless.y b/test/racc/assets/useless.y
deleted file mode 100644
index 3f172e341c..0000000000
--- a/test/racc/assets/useless.y
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-class A
-token A B C X
-rule
-
-targ : A list B
- | A B C
-
-list: list X
-
-end
diff --git a/test/racc/assets/yyerr.y b/test/racc/assets/yyerr.y
deleted file mode 100644
index 9faae89a79..0000000000
--- a/test/racc/assets/yyerr.y
+++ /dev/null
@@ -1,46 +0,0 @@
-#
-# yyerror/yyerrok/yyaccept test
-#
-
-class A
-rule
-
-target: a b c
-
-a:
- {
- yyerror
- raise ArgumentError, "yyerror failed"
- }
- | error
-
-b:
- {
- yyerrok
- }
-
-c:
- {
- yyaccept
- raise ArgumentError, "yyaccept failed"
- }
-
-end
-
----- inner
-
- def parse
- do_parse
- end
-
- def next_token
- [false, '$end']
- end
-
- def on_error( *args )
- $stderr.puts "on_error called: args=#{args.inspect}"
- end
-
----- footer
-
-A.new.parse
diff --git a/test/racc/bench.y b/test/racc/bench.y
deleted file mode 100644
index c6ba136201..0000000000
--- a/test/racc/bench.y
+++ /dev/null
@@ -1,36 +0,0 @@
-class BenchmarkParser
-
-rule
-
- target: a a a a a a a a a a;
- a: b b b b b b b b b b;
- b: c c c c c c c c c c;
- c: d d d d d d d d d d;
- d: e e e e e e e e e e;
-
-end
-
----- inner
-
-def initialize
- @old = [ :e, 'e' ]
- @i = 0
-end
-
-def next_token
- return [false, '$'] if @i >= 10_0000
- @i += 1
- @old
-end
-
-def parse
- do_parse
-end
-
----- footer
-
-require 'benchmark'
-
-Benchmark.bm do |x|
- x.report { BenchmarkParser.new.parse }
-end
diff --git a/test/racc/case.rb b/test/racc/case.rb
deleted file mode 100644
index f4240bfd21..0000000000
--- a/test/racc/case.rb
+++ /dev/null
@@ -1,110 +0,0 @@
-verbose = $VERBOSE
-$VERBOSE = true
-begin
-
-require 'test/unit'
-require 'racc/static'
-require 'fileutils'
-require 'tempfile'
-require 'timeout'
-
-module Racc
- class TestCase < Test::Unit::TestCase
- PROJECT_DIR = File.expand_path(File.join(__dir__, '..'))
-
- test_dir = File.join(PROJECT_DIR, 'test')
- test_dir = File.join(PROJECT_DIR, 'racc') unless File.exist?(test_dir)
- TEST_DIR = test_dir
- racc = File.join(PROJECT_DIR, 'bin', 'racc')
- racc = File.join(PROJECT_DIR, '..', 'libexec', 'racc') unless File.exist?(racc)
- RACC = racc
- ASSET_DIR = File.join(TEST_DIR, 'assets') # test grammars
- REGRESS_DIR = File.join(TEST_DIR, 'regress') # known-good generated outputs
-
- INC = [
- File.join(PROJECT_DIR, 'lib'),
- File.join(PROJECT_DIR, 'ext'),
- ].join(':')
-
- def setup
- @TEMP_DIR = Dir.mktmpdir("racc")
- @OUT_DIR = File.join(@TEMP_DIR, 'out')
- @TAB_DIR = File.join(@TEMP_DIR, 'tab') # generated parsers go here
- @LOG_DIR = File.join(@TEMP_DIR, 'log')
- @ERR_DIR = File.join(@TEMP_DIR, 'err')
- FileUtils.mkdir_p([@OUT_DIR, @TAB_DIR, @LOG_DIR, @ERR_DIR])
- FileUtils.cp File.join(TEST_DIR, "src.intp"), @TEMP_DIR
- end
-
- def teardown
- FileUtils.rm_f(File.join(@TEMP_DIR, "src.intp"))
- FileUtils.rm_rf([@OUT_DIR, @TAB_DIR, @LOG_DIR, @ERR_DIR, @TEMP_DIR])
- end
-
- def assert_compile(asset, args = [], **opt)
- file = File.basename(asset, '.y')
- args = ([args].flatten) + [
- "#{ASSET_DIR}/#{file}.y",
- '-Do',
- "-O#{@OUT_DIR}/#{file}",
- "-o#{@TAB_DIR}/#{file}",
- ]
- racc(*args, **opt)
- end
-
- def assert_debugfile(asset, ok)
- file = File.basename(asset, '.y')
- Dir.chdir(@LOG_DIR) do
- File.foreach("#{file}.y") do |line|
- line.strip!
- case line
- when /sr/ then assert_equal "sr#{ok[0]}", line
- when /rr/ then assert_equal "rr#{ok[1]}", line
- when /un/ then assert_equal "un#{ok[2]}", line
- when /ur/ then assert_equal "ur#{ok[3]}", line
- when /ex/ then assert_equal "ex#{ok[4]}", line
- else
- raise TestFailed, 'racc outputs unknown debug report???'
- end
- end
- end
- end
-
- def assert_exec(asset)
- lib_path = File.expand_path("../../lib", __FILE__)
- file = File.basename(asset, '.y')
- ruby "-I#{lib_path}", "#{@TAB_DIR}/#{file}"
- end
-
- def strip_version(source)
- source.sub(/This file is automatically generated by Racc \d+\.\d+\.\d+/, '')
- end
-
- def assert_output_unchanged(asset)
- file = File.basename(asset, '.y')
-
- # Code to re-generate the expectation files
- # File.write("#{REGRESS_DIR}/#{file}", File.read("#{@TAB_DIR}/#{file}"))
-
- expected = File.read("#{REGRESS_DIR}/#{file}")
- actual = File.read("#{@TAB_DIR}/#{file}")
- result = (strip_version(expected) == strip_version(actual))
-
- assert(result, "Output of test/assets/#{file}.y differed from " \
- "expectation. Try compiling it and diff with test/regress/#{file}.")
- end
-
- def racc(*arg, **opt)
- lib_path = File.expand_path("../../lib", __FILE__)
- ruby "-I#{lib_path}", "-S", RACC, *arg, **opt
- end
-
- def ruby(*arg, **opt)
- assert_ruby_status(["-C", @TEMP_DIR, *arg], **opt)
- end
- end
-end
-
-ensure
-$VERBOSE = verbose
-end
diff --git a/test/racc/infini.y b/test/racc/infini.y
deleted file mode 100644
index 88b1e1e93b..0000000000
--- a/test/racc/infini.y
+++ /dev/null
@@ -1,8 +0,0 @@
-
-class I
-
-rule
-
-list: list X
-
-end
diff --git a/test/racc/regress/README.txt b/test/racc/regress/README.txt
deleted file mode 100644
index dcab73260d..0000000000
--- a/test/racc/regress/README.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-These files are "known-good" compiler output, generated from a stable version of
-Racc. Whenever Racc is refactored, or changes are made which should not affect the
-compiler output, running "rake test" checks that the compiler output is exactly
-the same as these files.
-
-If a change is made which *should* change the compiler output, these files will
-have to be regenerated from the source in test/assets, and the results committed.
diff --git a/test/racc/regress/cadenza b/test/racc/regress/cadenza
deleted file mode 100644
index dafce3c9f3..0000000000
--- a/test/racc/regress/cadenza
+++ /dev/null
@@ -1,796 +0,0 @@
-#
-# DO NOT MODIFY!!!!
-# This file is automatically generated by Racc 1.5.0
-# from Racc grammar file "".
-#
-
-require 'racc/parser.rb'
-
-# racc_parser.rb : generated by racc
-
-module Cadenza
- class RaccParser < Racc::Parser
-
-module_eval(<<'...end cadenza.y/module_eval...', 'cadenza.y', 171)
-
-...end cadenza.y/module_eval...
-##### State transition tables begin ###
-
-racc_action_table = [
- 37, 89, 65, 66, 20, 21, 22, 23, 24, 17,
- 106, 37, 3, 76, 4, 3, 75, 4, 50, 37,
- 29, 68, 65, 66, 33, 67, 34, 110, 9, 74,
- 35, 9, 37, 36, 71, 33, 38, 34, 77, 78,
- 79, 35, 72, 33, 36, 34, 37, 38, 3, 35,
- 39, 83, 36, 54, 55, 38, 33, 89, 34, 37,
- 90, 3, 35, 43, 9, 36, 85, 103, 38, 108,
- 33, 109, 34, 56, 57, 111, 35, 9, 3, 36,
- 46, 122, 38, 33, 112, 34, 113, 78, 79, 35,
- 114, 3, 36, 4, 9, 38, 20, 21, 22, 23,
- 24, 20, 21, 22, 23, 24, 115, 9, 65, 66,
- 65, 66, 29, 54, 55, 120, 107, 29, 20, 21,
- 22, 23, 24, 20, 21, 22, 23, 24, 20, 21,
- 22, 23, 24, 3, 29, 39, 3, 121, 4, 29,
- 3, 3, 43, 46, 29, 3, 124, 87, 125, 9,
- 54, 55, 9, 56, 57, 128, 9, 9, 3, 103,
- 116, 9, 20, 21, 22, 23, 24, 20, 21, 22,
- 23, 24, 131, 3, 9, 116, 56, 57, 29, 3,
- 89, 116, nil, 29, 20, 21, 22, 23, 24, 9,
- 20, 21, 22, 23, 24, 9, 56, 57, 56, 57,
- 29, 20, 21, 22, 23, 24, 29, 58, 59, 60,
- 61, 62, 63, 56, 57, 56, 57, 29, 58, 59,
- 60, 61, 62, 63, 20, 21, 22, 23, 24, 20,
- 21, 22, 23, 24, 20, 21, 22, 23, 24, 20,
- 21, 22, 23, 24, 20, 21, 22, 23, 24, 20,
- 21, 22, 23, 24, 20, 21, 22, 23, 24, 20,
- 21, 22, 23, 24, 20, 21, 22, 23, 24, 20,
- 21, 22, 23, 24, 20, 21, 22, 23, 24, 65,
- 66 ]
-
-racc_action_check = [
- 4, 73, 69, 69, 37, 37, 37, 37, 37, 1,
- 69, 39, 0, 38, 0, 2, 38, 2, 17, 43,
- 37, 32, 31, 31, 4, 31, 4, 73, 0, 37,
- 4, 2, 46, 4, 35, 39, 4, 39, 39, 39,
- 39, 39, 36, 43, 39, 43, 87, 39, 5, 43,
- 5, 43, 43, 26, 26, 43, 46, 52, 46, 116,
- 53, 6, 46, 6, 5, 46, 46, 67, 46, 71,
- 87, 72, 87, 27, 27, 75, 87, 6, 7, 87,
- 7, 87, 87, 116, 76, 116, 77, 116, 116, 116,
- 78, 8, 116, 8, 7, 116, 3, 3, 3, 3,
- 3, 20, 20, 20, 20, 20, 79, 8, 70, 70,
- 51, 51, 3, 93, 93, 83, 70, 20, 24, 24,
- 24, 24, 24, 33, 33, 33, 33, 33, 34, 34,
- 34, 34, 34, 41, 24, 41, 42, 85, 42, 33,
- 45, 48, 45, 48, 34, 49, 103, 49, 105, 41,
- 94, 94, 42, 95, 95, 122, 45, 48, 81, 125,
- 81, 49, 65, 65, 65, 65, 65, 66, 66, 66,
- 66, 66, 126, 82, 81, 82, 96, 96, 65, 118,
- 129, 118, nil, 66, 89, 89, 89, 89, 89, 82,
- 108, 108, 108, 108, 108, 118, 97, 97, 98, 98,
- 89, 124, 124, 124, 124, 124, 108, 28, 28, 28,
- 28, 28, 28, 99, 99, 100, 100, 124, 64, 64,
- 64, 64, 64, 64, 29, 29, 29, 29, 29, 54,
- 54, 54, 54, 54, 55, 55, 55, 55, 55, 56,
- 56, 56, 56, 56, 57, 57, 57, 57, 57, 58,
- 58, 58, 58, 58, 59, 59, 59, 59, 59, 60,
- 60, 60, 60, 60, 61, 61, 61, 61, 61, 62,
- 62, 62, 62, 62, 63, 63, 63, 63, 63, 123,
- 123 ]
-
-racc_action_pointer = [
- -12, 9, -9, 93, -3, 24, 37, 54, 67, nil,
- nil, nil, nil, nil, nil, nil, nil, 18, nil, nil,
- 98, nil, nil, nil, 115, nil, 44, 62, 194, 221,
- nil, 2, -4, 120, 125, 31, 39, 1, 10, 8,
- nil, 109, 112, 16, nil, 116, 29, nil, 117, 121,
- nil, 90, 55, 52, 226, 231, 236, 241, 246, 251,
- 256, 261, 266, 271, 205, 159, 164, 64, nil, -18,
- 88, 35, 43, -1, nil, 47, 56, 58, 62, 78,
- nil, 134, 149, 87, nil, 109, nil, 43, nil, 181,
- nil, nil, nil, 104, 141, 142, 165, 185, 187, 202,
- 204, nil, nil, 124, nil, 125, nil, nil, 187, nil,
- nil, nil, nil, nil, nil, nil, 56, nil, 155, nil,
- nil, nil, 127, 259, 198, 156, 144, nil, nil, 178,
- nil, nil ]
-
-racc_action_default = [
- -2, -70, -1, -70, -70, -70, -70, -70, -70, -60,
- -61, -62, -63, -64, -65, -66, -68, -70, -67, -69,
- -5, -7, -8, -9, -70, -11, -14, -17, -24, -70,
- -26, -33, -70, -70, -70, -70, -70, -70, -70, -70,
- -41, -70, -70, -70, -48, -70, -70, -52, -70, -70,
- 132, -3, -6, -70, -70, -70, -70, -70, -70, -70,
- -70, -70, -70, -70, -25, -70, -70, -70, -35, -70,
- -70, -70, -70, -70, -54, -70, -70, -70, -70, -70,
- -42, -70, -70, -70, -49, -70, -53, -70, -57, -70,
- -10, -12, -13, -15, -16, -18, -19, -20, -21, -22,
- -23, -27, -28, -29, -31, -34, -36, -37, -70, -50,
- -55, -58, -59, -38, -39, -40, -70, -44, -70, -43,
- -47, -51, -70, -4, -70, -70, -70, -45, -56, -30,
- -32, -46 ]
-
-racc_goto_table = [
- 19, 40, 18, 32, 104, 52, 51, 1, 2, 64,
- 47, 91, 92, 41, 45, 48, 49, 44, 42, 69,
- 70, 105, 73, 51, 53, 95, 96, 97, 98, 99,
- 100, 93, 94, 101, 102, 88, nil, 80, nil, 19,
- nil, 18, nil, 19, nil, 18, 19, 19, 18, 18,
- 82, 86, nil, nil, 81, nil, 84, nil, nil, nil,
- nil, nil, 130, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 123, nil, 117, 119, nil,
- 19, nil, 18, nil, nil, nil, nil, nil, nil, 118,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 126, 129,
- 51, nil, nil, nil, 127, nil, 19, nil, 18 ]
-
-racc_goto_check = [
- 27, 16, 28, 6, 11, 3, 4, 1, 2, 9,
- 22, 5, 5, 2, 2, 2, 2, 19, 15, 4,
- 4, 12, 3, 4, 6, 8, 8, 8, 8, 8,
- 8, 7, 7, 10, 10, 25, nil, 16, nil, 27,
- nil, 28, nil, 27, nil, 28, 27, 27, 28, 28,
- 2, 22, nil, nil, 15, nil, 19, nil, nil, nil,
- nil, nil, 11, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 4, nil, 16, 16, nil,
- 27, nil, 28, nil, nil, nil, nil, nil, nil, 2,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 6, 3,
- 4, nil, nil, nil, 16, nil, 27, nil, 28 ]
-
-racc_goto_pointer = [
- nil, 7, 8, -15, -14, -43, 0, -25, -33, -20,
- -32, -63, -46, nil, nil, 13, -4, nil, nil, 11,
- nil, nil, 3, nil, nil, -14, nil, -2, 0 ]
-
-racc_goto_default = [
- nil, nil, nil, nil, 31, 25, nil, 26, 27, 28,
- 30, nil, nil, 10, 5, nil, nil, 11, 6, nil,
- 12, 7, nil, 14, 8, nil, 13, 16, 15 ]
-
-racc_reduce_table = [
- 0, 0, :racc_error,
- 1, 42, :_reduce_none,
- 0, 42, :_reduce_2,
- 1, 44, :_reduce_3,
- 3, 44, :_reduce_4,
- 1, 46, :_reduce_5,
- 2, 46, :_reduce_6,
- 1, 46, :_reduce_7,
- 1, 46, :_reduce_8,
- 1, 46, :_reduce_9,
- 3, 46, :_reduce_10,
- 1, 48, :_reduce_none,
- 3, 48, :_reduce_12,
- 3, 48, :_reduce_13,
- 1, 49, :_reduce_none,
- 3, 49, :_reduce_15,
- 3, 49, :_reduce_16,
- 1, 50, :_reduce_none,
- 3, 50, :_reduce_18,
- 3, 50, :_reduce_19,
- 3, 50, :_reduce_20,
- 3, 50, :_reduce_21,
- 3, 50, :_reduce_22,
- 3, 50, :_reduce_23,
- 1, 51, :_reduce_none,
- 2, 51, :_reduce_25,
- 1, 45, :_reduce_none,
- 3, 45, :_reduce_27,
- 3, 45, :_reduce_28,
- 1, 52, :_reduce_29,
- 3, 52, :_reduce_30,
- 1, 53, :_reduce_31,
- 3, 53, :_reduce_32,
- 1, 47, :_reduce_none,
- 3, 47, :_reduce_34,
- 3, 54, :_reduce_35,
- 4, 55, :_reduce_36,
- 4, 55, :_reduce_37,
- 3, 56, :_reduce_38,
- 3, 57, :_reduce_39,
- 3, 57, :_reduce_40,
- 2, 58, :_reduce_41,
- 3, 58, :_reduce_42,
- 4, 58, :_reduce_43,
- 4, 58, :_reduce_44,
- 5, 58, :_reduce_45,
- 6, 59, :_reduce_46,
- 3, 60, :_reduce_47,
- 2, 61, :_reduce_48,
- 3, 61, :_reduce_49,
- 4, 62, :_reduce_50,
- 3, 63, :_reduce_51,
- 2, 64, :_reduce_52,
- 3, 64, :_reduce_53,
- 3, 65, :_reduce_54,
- 4, 65, :_reduce_55,
- 3, 66, :_reduce_56,
- 3, 67, :_reduce_57,
- 4, 68, :_reduce_58,
- 4, 68, :_reduce_59,
- 1, 69, :_reduce_60,
- 1, 69, :_reduce_none,
- 1, 69, :_reduce_none,
- 1, 69, :_reduce_none,
- 1, 69, :_reduce_none,
- 1, 69, :_reduce_none,
- 1, 43, :_reduce_66,
- 2, 43, :_reduce_67,
- 1, 43, :_reduce_68,
- 2, 43, :_reduce_69 ]
-
-racc_reduce_n = 70
-
-racc_shift_n = 132
-
-racc_token_table = {
- false => 0,
- :error => 1,
- "," => 2,
- :IDENTIFIER => 3,
- :INTEGER => 4,
- :REAL => 5,
- :STRING => 6,
- "(" => 7,
- ")" => 8,
- "*" => 9,
- "/" => 10,
- "+" => 11,
- "-" => 12,
- :OP_EQ => 13,
- :OP_NEQ => 14,
- :OP_LEQ => 15,
- :OP_GEQ => 16,
- ">" => 17,
- "<" => 18,
- :NOT => 19,
- :AND => 20,
- :OR => 21,
- ":" => 22,
- "|" => 23,
- :VAR_OPEN => 24,
- :VAR_CLOSE => 25,
- :STMT_OPEN => 26,
- :IF => 27,
- :STMT_CLOSE => 28,
- :UNLESS => 29,
- :ELSE => 30,
- :ENDIF => 31,
- :ENDUNLESS => 32,
- :FOR => 33,
- :IN => 34,
- :ENDFOR => 35,
- :BLOCK => 36,
- :ENDBLOCK => 37,
- :END => 38,
- :EXTENDS => 39,
- :TEXT_BLOCK => 40 }
-
-racc_nt_base = 41
-
-racc_use_result_var = true
-
-Racc_arg = [
- racc_action_table,
- racc_action_check,
- racc_action_default,
- racc_action_pointer,
- racc_goto_table,
- racc_goto_check,
- racc_goto_default,
- racc_goto_pointer,
- racc_nt_base,
- racc_reduce_table,
- racc_token_table,
- racc_shift_n,
- racc_reduce_n,
- racc_use_result_var ]
-
-Racc_token_to_s_table = [
- "$end",
- "error",
- "\",\"",
- "IDENTIFIER",
- "INTEGER",
- "REAL",
- "STRING",
- "\"(\"",
- "\")\"",
- "\"*\"",
- "\"/\"",
- "\"+\"",
- "\"-\"",
- "OP_EQ",
- "OP_NEQ",
- "OP_LEQ",
- "OP_GEQ",
- "\">\"",
- "\"<\"",
- "NOT",
- "AND",
- "OR",
- "\":\"",
- "\"|\"",
- "VAR_OPEN",
- "VAR_CLOSE",
- "STMT_OPEN",
- "IF",
- "STMT_CLOSE",
- "UNLESS",
- "ELSE",
- "ENDIF",
- "ENDUNLESS",
- "FOR",
- "IN",
- "ENDFOR",
- "BLOCK",
- "ENDBLOCK",
- "END",
- "EXTENDS",
- "TEXT_BLOCK",
- "$start",
- "target",
- "document",
- "parameter_list",
- "logical_expression",
- "primary_expression",
- "filtered_expression",
- "multiplicative_expression",
- "additive_expression",
- "boolean_expression",
- "inverse_expression",
- "filter",
- "filter_list",
- "inject_statement",
- "if_tag",
- "else_tag",
- "end_if_tag",
- "if_block",
- "for_tag",
- "end_for_tag",
- "for_block",
- "block_tag",
- "end_block_tag",
- "block_block",
- "generic_block_tag",
- "end_generic_block_tag",
- "generic_block",
- "extends_statement",
- "document_component" ]
-
-Racc_debug_parser = false
-
-##### State transition tables end #####
-
-# reduce 0 omitted
-
-# reduce 1 omitted
-
-module_eval(<<'.,.,', 'cadenza.y', 12)
- def _reduce_2(val, _values, result)
- result = nil
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 16)
- def _reduce_3(val, _values, result)
- result = [val[0]]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 17)
- def _reduce_4(val, _values, result)
- result = val[0].push(val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 22)
- def _reduce_5(val, _values, result)
- result = VariableNode.new(val[0].value)
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 23)
- def _reduce_6(val, _values, result)
- result = VariableNode.new(val[0].value, val[1])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 24)
- def _reduce_7(val, _values, result)
- result = ConstantNode.new(val[0].value)
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 25)
- def _reduce_8(val, _values, result)
- result = ConstantNode.new(val[0].value)
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 26)
- def _reduce_9(val, _values, result)
- result = ConstantNode.new(val[0].value)
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 27)
- def _reduce_10(val, _values, result)
- result = val[1]
- result
- end
-.,.,
-
-# reduce 11 omitted
-
-module_eval(<<'.,.,', 'cadenza.y', 32)
- def _reduce_12(val, _values, result)
- result = OperationNode.new(val[0], "*", val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 33)
- def _reduce_13(val, _values, result)
- result = OperationNode.new(val[0], "/", val[2])
- result
- end
-.,.,
-
-# reduce 14 omitted
-
-module_eval(<<'.,.,', 'cadenza.y', 38)
- def _reduce_15(val, _values, result)
- result = OperationNode.new(val[0], "+", val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 39)
- def _reduce_16(val, _values, result)
- result = OperationNode.new(val[0], "-", val[2])
- result
- end
-.,.,
-
-# reduce 17 omitted
-
-module_eval(<<'.,.,', 'cadenza.y', 44)
- def _reduce_18(val, _values, result)
- result = OperationNode.new(val[0], "==", val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 45)
- def _reduce_19(val, _values, result)
- result = OperationNode.new(val[0], "!=", val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 46)
- def _reduce_20(val, _values, result)
- result = OperationNode.new(val[0], "<=", val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 47)
- def _reduce_21(val, _values, result)
- result = OperationNode.new(val[0], ">=", val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 48)
- def _reduce_22(val, _values, result)
- result = OperationNode.new(val[0], ">", val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 49)
- def _reduce_23(val, _values, result)
- result = OperationNode.new(val[0], "<", val[2])
- result
- end
-.,.,
-
-# reduce 24 omitted
-
-module_eval(<<'.,.,', 'cadenza.y', 54)
- def _reduce_25(val, _values, result)
- result = BooleanInverseNode.new(val[1])
- result
- end
-.,.,
-
-# reduce 26 omitted
-
-module_eval(<<'.,.,', 'cadenza.y', 59)
- def _reduce_27(val, _values, result)
- result = OperationNode.new(val[0], "and", val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 60)
- def _reduce_28(val, _values, result)
- result = OperationNode.new(val[0], "or", val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 64)
- def _reduce_29(val, _values, result)
- result = FilterNode.new(val[0].value)
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 65)
- def _reduce_30(val, _values, result)
- result = FilterNode.new(val[0].value, val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 69)
- def _reduce_31(val, _values, result)
- result = [val[0]]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 70)
- def _reduce_32(val, _values, result)
- result = val[0].push(val[2])
- result
- end
-.,.,
-
-# reduce 33 omitted
-
-module_eval(<<'.,.,', 'cadenza.y', 75)
- def _reduce_34(val, _values, result)
- result = FilteredValueNode.new(val[0], val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 79)
- def _reduce_35(val, _values, result)
- result = val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 83)
- def _reduce_36(val, _values, result)
- open_scope!; result = val[2]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 84)
- def _reduce_37(val, _values, result)
- open_scope!; result = BooleanInverseNode.new(val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 88)
- def _reduce_38(val, _values, result)
- result = close_scope!; open_scope!
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 92)
- def _reduce_39(val, _values, result)
- result = close_scope!
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 93)
- def _reduce_40(val, _values, result)
- result = close_scope!
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 97)
- def _reduce_41(val, _values, result)
- result = IfNode.new(val[0], val[1])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 98)
- def _reduce_42(val, _values, result)
- result = IfNode.new(val[0], val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 99)
- def _reduce_43(val, _values, result)
- result = IfNode.new(val[0], val[1], val[3])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 100)
- def _reduce_44(val, _values, result)
- result = IfNode.new(val[0], val[2], val[3])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 101)
- def _reduce_45(val, _values, result)
- result = IfNode.new(val[0], val[2], val[4])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 105)
- def _reduce_46(val, _values, result)
- open_scope!; result = [val[2].value, val[4]]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 109)
- def _reduce_47(val, _values, result)
- result = close_scope!
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 114)
- def _reduce_48(val, _values, result)
- result = ForNode.new(VariableNode.new(val[0].first), val[0].last, val[1])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 115)
- def _reduce_49(val, _values, result)
- result = ForNode.new(VariableNode.new(val[0].first), val[0].last, val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 119)
- def _reduce_50(val, _values, result)
- result = open_block_scope!(val[2].value)
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 123)
- def _reduce_51(val, _values, result)
- result = close_block_scope!
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 128)
- def _reduce_52(val, _values, result)
- result = BlockNode.new(val[0], val[1])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 129)
- def _reduce_53(val, _values, result)
- result = BlockNode.new(val[0], val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 133)
- def _reduce_54(val, _values, result)
- open_scope!; result = [val[1].value, []]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 134)
- def _reduce_55(val, _values, result)
- open_scope!; result = [val[1].value, val[2]]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 138)
- def _reduce_56(val, _values, result)
- result = close_scope!
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 142)
- def _reduce_57(val, _values, result)
- result = GenericBlockNode.new(val[0].first, val[2], val[0].last)
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 146)
- def _reduce_58(val, _values, result)
- result = val[2].value
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 147)
- def _reduce_59(val, _values, result)
- result = VariableNode.new(val[2].value)
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 151)
- def _reduce_60(val, _values, result)
- result = TextNode.new(val[0].value)
- result
- end
-.,.,
-
-# reduce 61 omitted
-
-# reduce 62 omitted
-
-# reduce 63 omitted
-
-# reduce 64 omitted
-
-# reduce 65 omitted
-
-module_eval(<<'.,.,', 'cadenza.y', 160)
- def _reduce_66(val, _values, result)
- push val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 161)
- def _reduce_67(val, _values, result)
- push val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 162)
- def _reduce_68(val, _values, result)
- document.extends = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cadenza.y', 163)
- def _reduce_69(val, _values, result)
- document.extends = val[1]
- result
- end
-.,.,
-
-def _reduce_none(val, _values, result)
- val[0]
-end
-
- end # class RaccParser
-end # module Cadenza
diff --git a/test/racc/regress/cast b/test/racc/regress/cast
deleted file mode 100644
index 60e92a0abd..0000000000
--- a/test/racc/regress/cast
+++ /dev/null
@@ -1,3945 +0,0 @@
-#
-# DO NOT MODIFY!!!!
-# This file is automatically generated by Racc 1.5.2
-# from Racc grammar file "".
-#
-
-require 'racc/parser.rb'
-
-
-require 'set'
-
-# Error classes
-module C
- class ParseError < StandardError; end
-end
-
-# Local variables:
-# mode: ruby
-# end:
-module C
- class Parser < Racc::Parser
-
-module_eval(<<'...end cast.y/module_eval...', 'cast.y', 564)
- # A.1.9 -- Preprocessing numbers -- skip
- # A.1.8 -- Header names -- skip
-
- # A.1.7 -- Puncuators -- we don't bother with {##,#,%:,%:%:} since
- # we don't do preprocessing
- @@punctuators = %r'\+\+|-[->]|&&|\|\||\.\.\.|(?:<<|>>|[<>=!*/%+\-&^|])=?|[\[\](){}.~?:;,]'
- @@digraphs = %r'<[:%]|[:%]>'
-
- # A.1.6 -- String Literals -- simple for us because we don't decode
- # the string (and indeed accept some illegal strings)
- @@string_literal = %r'L?"(?:[^\\]|\\.)*?"'m
-
- # A.1.5 -- Constants
- @@decimal_floating_constant = %r'(?:(?:\d*\.\d+|\d+\.)(?:e[-+]?\d+)?|\d+e[-+]?\d+)[fl]?'i
- @@hexadecimal_floating_constant = %r'0x(?:(?:[0-9a-f]*\.[0-9a-f]+|[0-9a-f]+\.)|[0-9a-f]+)p[-+]?\d+[fl]?'i
-
- @@integer_constant = %r'(?:[1-9][0-9]*|0x[0-9a-f]+|0[0-7]*)(?:ul?l?|ll?u?)?'i
- @@floating_constant = %r'#{@@decimal_floating_constant}|#{@@hexadecimal_floating_constant}'
- @@enumeration_constant = %r'[a-zA-Z_\\][a-zA-Z_\\0-9]*'
- @@character_constant = %r"L?'(?:[^\\]|\\.)+?'"
- # (note that as with string-literals, we accept some illegal
- # character-constants)
-
- # A.1.4 -- Universal character names -- skip
-
- # A.1.3 -- Identifiers -- skip, since an identifier is lexically
- # identical to an enumeration constant
-
- # A.1.2 Keywords
- keywords = %w'auto break case char const continue default do
-double else enum extern float for goto if inline int long register
-restrict return short signed sizeof static struct switch typedef union
- unsigned void volatile while _Bool _Complex _Imaginary'
- @@keywords = %r"#{keywords.join('|')}"
-
- def initialize
- @type_names = ::Set.new
-
- @warning_proc = lambda{}
- @pos = C::Node::Pos.new(nil, 1, 0)
- end
- def initialize_copy(x)
- @pos = x.pos.dup
- @type_names = x.type_names.dup
- end
- attr_accessor :pos, :type_names
-
- def parse(str)
- if str.respond_to? :read
- str = str.read
- end
- @str = str
- begin
- prepare_lexer(str)
- return do_parse
- rescue ParseError => e
- e.set_backtrace(caller)
- raise
- end
- end
-
- #
- # Error handler, as used by racc.
- #
- def on_error(error_token_id, error_value, value_stack)
- if error_value == '$'
- parse_error @pos, "unexpected EOF"
- else
- parse_error(error_value.pos,
- "parse error on #{token_to_str(error_token_id)} (#{error_value.val})")
- end
- end
-
- def self.feature(name)
- attr_writer "#{name}_enabled"
- class_eval <<-EOS
- def enable_#{name}
- @#{name}_enabled = true
- end
- def #{name}_enabled?
- @#{name}_enabled
- end
- EOS
- end
- private_class_method :feature
-
- #
- # Allow blocks in parentheses as expressions, as per the gcc
- # extension. [http://rubyurl.com/iB7]
- #
- feature :block_expressions
-
- private # ---------------------------------------------------------
-
- class Token
- attr_accessor :pos, :val
- def initialize(pos, val)
- @pos = pos
- @val = val
- end
- end
- def eat(str)
- lines = str.split(/\r\n|[\r\n]/, -1)
- if lines.length == 1
- @pos.col_num += lines[0].length
- else
- @pos.line_num += lines.length - 1
- @pos.col_num = lines[-1].length
- end
- end
-
- #
- # Make a Declaration from the given specs and declarators.
- #
- def make_declaration(pos, specs, declarators)
- specs.all?{|x| x.is_a?(Symbol) || x.is_a?(Type)} or raise specs.map{|x| x.class}.inspect
- decl = Declaration.new_at(pos, nil, declarators)
-
- # set storage class
- storage_classes = specs.find_all do |x|
- [:typedef, :extern, :static, :auto, :register].include? x
- end
- # 6.7.1p2: at most, one storage-class specifier may be given in
- # the declaration specifiers in a declaration
- storage_classes.length <= 1 or
- begin
- if declarators.length == 0
- for_name = ''
- else
- for_name = "for `#{declarators[0].name}'"
- end
- parse_error pos, "multiple or duplicate storage classes given #{for_name}'"
- end
- decl.storage = storage_classes[0]
-
- # set type (specifiers, qualifiers)
- decl.type = make_direct_type(pos, specs)
-
- # set function specifiers
- decl.inline = specs.include?(:inline)
-
- # look for new type names
- if decl.typedef?
- decl.declarators.each do |d|
- if d.name
- @type_names << d.name
- end
- end
- end
-
- return decl
- end
-
- def make_function_def(pos, specs, func_declarator, decl_list, defn)
- add_decl_type(func_declarator, make_direct_type(pos, specs))
-
- # get types from decl_list if necessary
- function = func_declarator.indirect_type
- function.is_a? Function or
- parse_error pos, "non function type for function `#{func_declarator.name}'"
- params = function.params
- if decl_list
- params.all?{|p| p.type.nil?} or
- parse_error pos, "both prototype and declaration list given for `#{func_declarator.name}'"
- decl_list.each do |declaration|
- declaration.declarators.each do |declarator|
- param = params.find{|p| p.name == declarator.name} or
- parse_error pos, "no parameter named #{declarator.name}"
- if declarator.indirect_type
- param.type = declarator.indirect_type
- param.type.direct_type = declaration.type.dup
- else
- param.type = declaration.type.dup
- end
- end
- end
- params.all?{|p| p.type} or
- begin
- s = params.find_all{|p| p.type.nil?}.map{|p| "`#{p.name}'"}.join(' and ')
- parse_error pos, "types missing for parameters #{s}"
- end
- end
-
- fd = FunctionDef.new_at(pos,
- function.detach,
- func_declarator.name,
- defn,
- :no_prototype => !decl_list.nil?)
-
- # set storage class
- # 6.9.1p4: only extern or static allowed
- specs.each do |s|
- [:typedef, :auto, :register].include?(s) and
- "`#{s}' illegal for function"
- end
- storage_classes = specs.find_all do |s|
- s == :extern || s == :static
- end
- # 6.7.1p2: at most, one storage-class specifier may be given in
- # the declaration specifiers in a declaration
- storage_classes.length <= 1 or
- "multiple or duplicate storage classes given for `#{func_declarator.name}'"
- fd.storage = storage_classes[0] if storage_classes[0]
-
- # set function specifiers
- # 6.7.4p5 'inline' can be repeated
- fd.inline = specs.include?(:inline)
-
- return fd
- end
-
- #
- # Make a direct type from the list of type specifiers and type
- # qualifiers.
- #
- def make_direct_type(pos, specs)
- specs_order = [:signed, :unsigned, :short, :long, :double, :void,
- :char, :int, :float, :_Bool, :_Complex, :_Imaginary]
-
- type_specs = specs.find_all do |x|
- specs_order.include?(x) || !x.is_a?(Symbol)
- end
- type_specs.sort! do |a, b|
- (specs_order.index(a)||100) <=> (specs_order.index(b)||100)
- end
-
- # set type specifiers
- # 6.7.2p2: the specifier list should be one of these
- type =
- case type_specs
- when [:void]
- Void.new
- when [:char]
- Char.new
- when [:signed, :char]
- Char.new :signed => true
- when [:unsigned, :char]
- Char.new :signed => false
- when [:short], [:signed, :short], [:short, :int],
- [:signed, :short, :int]
- Int.new :longness => -1
- when [:unsigned, :short], [:unsigned, :short, :int]
- Int.new :unsigned => true, :longness => -1
- when [:int], [:signed], [:signed, :int]
- Int.new
- when [:unsigned], [:unsigned, :int]
- Int.new :unsigned => true
- when [:long], [:signed, :long], [:long, :int],
- [:signed, :long, :int]
- Int.new :longness => 1
- when [:unsigned, :long], [:unsigned, :long, :int]
- Int.new :longness => 1, :unsigned => true
- when [:long, :long], [:signed, :long, :long],
- [:long, :long, :int], [:signed, :long, :long, :int]
- Int.new :longness => 2
- when [:unsigned, :long, :long], [:unsigned, :long, :long, :int]
- Int.new :longness => 2, :unsigned => true
- when [:float]
- Float.new
- when [:double]
- Float.new :longness => 1
- when [:long, :double]
- Float.new :longness => 2
- when [:_Bool]
- Bool.new
- when [:float, :_Complex]
- Complex.new
- when [:double, :_Complex]
- Complex.new :longness => 1
- when [:long, :double, :_Complex]
- Complex.new :longness => 2
- when [:float, :_Imaginary]
- Imaginary.new
- when [:double, :_Imaginary]
- Imaginary.new :longness => 1
- when [:long, :double, :_Imaginary]
- Imaginary.new :longness => 2
- else
- if type_specs.length == 1 &&
- [CustomType, Struct, Union, Enum].any?{|c| type_specs[0].is_a? c}
- type_specs[0]
- else
- if type_specs == []
- parse_error pos, "no type specifiers given"
- else
- parse_error pos, "invalid type specifier combination: #{type_specs.join(' ')}"
- end
- end
- end
- type.pos ||= pos
-
- # set type qualifiers
- # 6.7.3p4: type qualifiers can be repeated
- type.const = specs.any?{|x| x.equal? :const }
- type.restrict = specs.any?{|x| x.equal? :restrict}
- type.volatile = specs.any?{|x| x.equal? :volatile}
-
- return type
- end
-
- def make_parameter(pos, specs, indirect_type, name)
- type = indirect_type
- if type
- type.direct_type = make_direct_type(pos, specs)
- else
- type = make_direct_type(pos, specs)
- end
- [:typedef, :extern, :static, :auto, :inline].each do |sym|
- specs.include? sym and
- parse_error pos, "parameter `#{declarator.name}' declared `#{sym}'"
- end
- return Parameter.new_at(pos, type, name,
- :register => specs.include?(:register))
- end
-
- def add_type_quals(type, quals)
- type.const = quals.include?(:const )
- type.restrict = quals.include?(:restrict)
- type.volatile = quals.include?(:volatile)
- return type
- end
-
- #
- # Add te given type as the "most direct" type to the given
- # declarator. Return the declarator.
- #
- def add_decl_type(declarator, type)
- if declarator.indirect_type
- declarator.indirect_type.direct_type = type
- else
- declarator.indirect_type = type
- end
- return declarator
- end
-
- def param_list(params, var_args)
- if params.length == 1 &&
- params[0].type.is_a?(Void) &&
- params[0].name.nil?
- return NodeArray[]
- elsif params.empty?
- return nil
- else
- return params
- end
- end
-
- def parse_error(pos, str)
- raise ParseError, "#{pos}: #{str}"
- end
-
-...end cast.y/module_eval...
-##### State transition tables begin ###
-
-racc_action_table = [
- 99, 100, 65, 103, 108, 109, 120, 312, 61, 110,
- 111, 112, 113, 114, 115, 116, 117, 77, 48, 10,
- 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
- 21, 22, 23, 24, 25, 26, 31, 32, 33, 34,
- 35, 36, 37, 72, 281, 128, 49, 38, 196, 391,
- 123, 124, 126, 127, 129, 130, 131, 132, 183, 277,
- 83, 273, 84, 238, 288, 293, 88, 196, 72, 290,
- 38, 274, 184, 372, 373, 386, 239, 240, 289, 294,
- 71, 241, 242, 50, 147, 148, 149, 150, 99, 100,
- 65, 193, 108, 109, 120, 50, 281, 110, 111, 112,
- 113, 114, 115, 116, 117, 71, 50, 10, 11, 12,
- 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
- 23, 24, 25, 26, 31, 32, 33, 34, 35, 36,
- 37, 56, 366, 128, 89, 38, 50, 169, 123, 124,
- 126, 127, 129, 130, 131, 132, 99, 100, 65, 88,
- 108, 109, 120, 88, 88, 110, 111, 112, 113, 114,
- 115, 116, 117, 346, 349, 238, 59, 68, 48, 365,
- 195, 50, 147, 148, 149, 150, 38, 347, 239, 240,
- 69, 178, 283, 196, 312, 366, 243, 244, 48, 262,
- 88, 128, 185, 38, 263, 284, 123, 124, 126, 127,
- 129, 130, 131, 132, 99, 100, 65, 49, 108, 109,
- 120, 38, 50, 110, 111, 112, 113, 114, 115, 116,
- 117, 281, 365, 309, 440, 249, 250, 49, 238, 50,
- 147, 148, 149, 150, 313, 379, 196, 227, 439, 178,
- 413, 239, 240, 88, 196, 50, 48, 50, 196, 128,
- 187, 38, 191, 196, 123, 124, 126, 127, 129, 130,
- 131, 132, 99, 100, 65, 50, 108, 109, 120, 416,
- 428, 110, 111, 112, 113, 114, 115, 116, 117, 255,
- 256, 192, 196, 196, 197, 49, 198, 50, 147, 148,
- 149, 150, 228, 229, 230, 231, 232, 233, 234, 235,
- 236, 237, 43, 199, 48, 241, 242, 128, 202, 38,
- 241, 242, 123, 124, 126, 127, 129, 130, 131, 132,
- 99, 100, 65, 50, 108, 109, 120, 375, 376, 110,
- 111, 112, 113, 114, 115, 116, 117, 196, 196, 205,
- 377, 387, 427, 49, 433, 50, 147, 148, 149, 150,
- 196, 388, 196, 437, 196, 206, 445, 209, 447, 450,
- 43, 251, 48, 196, 252, 128, 196, 38, 196, 196,
- 123, 124, 126, 127, 129, 130, 131, 132, 99, 100,
- 65, 50, 108, 109, 120, 454, 253, 110, 111, 112,
- 113, 114, 115, 116, 117, 196, 34, 35, 36, 243,
- 244, 49, 49, 50, 147, 148, 149, 150, 34, 35,
- 36, 243, 244, 254, 49, 245, 246, 247, 248, 67,
- 48, 243, 244, 128, 268, 38, 243, 244, 123, 124,
- 126, 127, 129, 130, 131, 132, 99, 100, 65, 50,
- 108, 109, 120, 249, 250, 110, 111, 112, 113, 114,
- 115, 116, 117, 245, 246, 247, 248, 271, 272, 49,
- 275, 50, 147, 148, 149, 150, 245, 246, 247, 248,
- 285, 296, 192, 303, 307, 308, 314, 315, 277, 50,
- 50, 128, 50, 38, 353, 355, 123, 124, 126, 127,
- 129, 130, 131, 132, 99, 100, 65, 50, 108, 109,
- 120, 357, 50, 110, 111, 112, 113, 114, 115, 116,
- 117, 378, 389, 390, 251, 281, 252, 49, 253, 50,
- 147, 148, 149, 150, 254, 395, 396, 397, 398, 399,
- 405, 406, 384, 384, 423, 424, 425, 426, 442, 128,
- nil, 38, nil, nil, 123, 124, 126, 127, 129, 130,
- 131, 132, 99, 100, 65, 50, 108, 109, 120, nil,
- nil, 110, 111, 112, 113, 114, 115, 116, 117, nil,
- nil, nil, nil, nil, nil, nil, nil, 50, 147, 148,
- 149, 150, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 128, nil, 38,
- nil, nil, 123, 124, 126, 127, 129, 130, 131, 132,
- 99, 100, 65, nil, 108, 109, 120, nil, nil, 110,
- 111, 112, 113, 114, 115, 116, 117, nil, nil, nil,
- nil, nil, nil, nil, nil, 50, 147, 148, 149, 150,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 128, nil, 38, nil, nil,
- 123, 124, 126, 127, 129, 130, 131, 132, 99, 100,
- 65, nil, 108, 109, 120, nil, nil, 110, 111, 112,
- 113, 114, 115, 116, 117, nil, nil, nil, nil, nil,
- nil, nil, nil, 50, 147, 148, 149, 150, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 128, nil, 38, nil, nil, 123, 124,
- 126, 127, 129, 130, 131, 132, 99, 100, 65, nil,
- 108, 109, 120, nil, nil, 110, 111, 112, 113, 114,
- 115, 116, 117, nil, nil, nil, nil, nil, nil, nil,
- nil, 50, 147, 148, 149, 150, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 128, nil, 38, nil, nil, 123, 124, 126, 127,
- 129, 130, 131, 132, 99, 100, 65, nil, 108, 109,
- 120, nil, nil, 110, 111, 112, 113, 114, 115, 116,
- 117, nil, nil, nil, nil, nil, nil, nil, nil, 50,
- 147, 148, 149, 150, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 128,
- nil, 38, nil, nil, 123, 124, 126, 127, 129, 130,
- 131, 132, 99, 100, 65, nil, 108, 109, 120, nil,
- nil, 110, 111, 112, 113, 114, 115, 116, 117, nil,
- nil, nil, nil, nil, nil, nil, nil, 50, 147, 148,
- 149, 150, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 128, nil, 38,
- nil, nil, 123, 124, 126, 127, 129, 130, 131, 132,
- 99, 100, 65, nil, 108, 109, 120, nil, nil, 110,
- 111, 112, 113, 114, 115, 116, 117, nil, nil, nil,
- nil, nil, nil, nil, nil, 50, 147, 148, 149, 150,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 128, nil, 38, nil, nil,
- 123, 124, 126, 127, 129, 130, 131, 132, 99, 100,
- 65, nil, 108, 109, 120, nil, nil, 110, 111, 112,
- 113, 114, 115, 116, 117, nil, nil, nil, nil, nil,
- nil, nil, nil, 50, 147, 148, 149, 150, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 128, nil, 38, nil, nil, 123, 124,
- 126, 127, 129, 130, 131, 132, 99, 100, 65, nil,
- 108, 109, 120, nil, nil, 110, 111, 112, 113, 114,
- 115, 116, 117, nil, nil, nil, nil, nil, nil, nil,
- nil, 50, 147, 148, 149, 150, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 128, nil, 38, nil, nil, 123, 124, 126, 127,
- 129, 130, 131, 132, 99, 100, 65, nil, 108, 109,
- 120, nil, nil, 110, 111, 112, 113, 114, 115, 116,
- 117, nil, nil, nil, nil, nil, nil, nil, nil, 50,
- 147, 148, 149, 150, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 128,
- nil, 38, nil, nil, 123, 124, 126, 127, 129, 130,
- 131, 132, 99, 100, 65, nil, 108, 109, 120, nil,
- nil, 110, 111, 112, 113, 114, 115, 116, 117, nil,
- nil, nil, nil, nil, nil, nil, nil, 50, 147, 148,
- 149, 150, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 128, nil, 38,
- nil, nil, 123, 124, 126, 127, 129, 130, 131, 132,
- 99, 100, 65, nil, 108, 109, 120, nil, nil, 110,
- 111, 112, 113, 114, 115, 116, 117, nil, nil, nil,
- nil, nil, nil, nil, nil, 50, 147, 148, 149, 150,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 128, nil, 38, nil, nil,
- 123, 124, 126, 127, 129, 130, 131, 132, 99, 100,
- 65, nil, 108, 109, 120, nil, nil, 110, 111, 112,
- 113, 114, 115, 116, 117, nil, nil, nil, nil, nil,
- nil, nil, nil, 50, 147, 148, 149, 150, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 128, nil, 38, nil, nil, 123, 124,
- 126, 127, 129, 130, 131, 132, 99, 100, 65, nil,
- 108, 109, 120, nil, nil, 110, 111, 112, 113, 114,
- 115, 116, 117, 154, nil, nil, nil, 120, nil, nil,
- nil, 50, 147, 148, 149, 150, nil, nil, nil, nil,
- nil, nil, 215, nil, nil, nil, nil, nil, nil, nil,
- nil, 128, nil, 38, nil, nil, 123, 124, 126, 127,
- 129, 130, 131, 132, nil, nil, 128, nil, nil, nil,
- nil, 123, 124, 126, 127, 129, 130, 131, 132, 214,
- nil, nil, nil, nil, 216, 217, 218, 219, nil, 50,
- 147, 148, 149, 150, 65, nil, nil, nil, 120, nil,
- nil, nil, nil, nil, 50, 147, 148, 149, 150, 154,
- nil, nil, nil, 120, nil, nil, 15, 16, 17, 18,
- 19, 20, 21, 22, 23, 24, 25, 26, 31, 32,
- 33, 34, 35, 36, nil, nil, nil, 128, nil, 38,
- nil, nil, 123, 124, 126, 127, 129, 130, 131, 132,
- 262, nil, 128, nil, nil, 263, nil, 123, 124, 126,
- 127, 129, 130, 131, 132, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 50, 147, 148, 149, 150,
- 65, nil, nil, nil, 120, nil, nil, nil, nil, nil,
- 50, 147, 148, 149, 150, nil, nil, nil, nil, nil,
- nil, nil, 15, 16, 17, 18, 19, 20, 21, 22,
- 23, 24, 25, 26, 31, 32, 33, 34, 35, 36,
- nil, nil, nil, 128, nil, 38, nil, nil, 123, 124,
- 126, 127, 129, 130, 131, 132, nil, nil, nil, nil,
- nil, nil, nil, nil, 65, nil, nil, nil, 120, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 50, 147, 148, 149, 150, 15, 16, 17, 18,
- 19, 20, 21, 22, 23, 24, 25, 26, 31, 32,
- 33, 34, 35, 36, nil, nil, nil, 128, nil, 38,
- nil, nil, 123, 124, 126, 127, 129, 130, 131, 132,
- 154, nil, nil, nil, 120, nil, nil, nil, nil, nil,
- nil, nil, nil, 384, nil, nil, nil, 120, nil, nil,
- nil, nil, nil, nil, nil, 50, 147, 148, 149, 150,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 128, nil, nil, nil, nil, 123, 124,
- 126, 127, 129, 130, 131, 132, 128, nil, nil, nil,
- nil, 123, 124, 126, 127, 129, 130, 131, 132, 154,
- 392, nil, nil, 120, nil, nil, nil, nil, nil, nil,
- nil, 50, 147, 148, 149, 150, 154, nil, nil, nil,
- 120, nil, nil, nil, 50, 147, 148, 149, 150, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 262, nil, 128, nil, nil, 263, nil, 123, 124, 126,
- 127, 129, 130, 131, 132, nil, nil, 262, nil, 128,
- nil, nil, 263, nil, 123, 124, 126, 127, 129, 130,
- 131, 132, 154, nil, nil, nil, 120, nil, nil, nil,
- 50, 147, 148, 149, 150, nil, nil, 154, 453, nil,
- nil, 120, nil, nil, nil, nil, nil, 50, 147, 148,
- 149, 150, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 128, nil, nil, nil, nil,
- 123, 124, 126, 127, 129, 130, 131, 132, 262, nil,
- 128, nil, 208, 263, 120, 123, 124, 126, 127, 129,
- 130, 131, 132, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 50, 147, 148, 149, 150, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 50, 147,
- 148, 149, 150, 128, nil, nil, nil, nil, 123, 124,
- 126, 127, 129, 130, 131, 132, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 305, nil, 120, nil, nil, nil, nil, nil, nil,
- nil, 50, 147, 148, 149, 150, 10, 11, 12, 13,
- 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
- 24, 25, 26, 31, 32, 33, 34, 35, 36, 37,
- nil, nil, 128, nil, 38, nil, nil, 123, 124, 126,
- 127, 129, 130, 131, 132, 381, nil, 120, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 383, nil,
- 120, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 50, 147, 148, 149, 150, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 128, nil, nil, nil,
- nil, 123, 124, 126, 127, 129, 130, 131, 132, 128,
- nil, 412, nil, 120, 123, 124, 126, 127, 129, 130,
- 131, 132, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 50, 147, 148, 149, 150, nil,
- nil, nil, nil, nil, nil, nil, nil, 50, 147, 148,
- 149, 150, 128, nil, nil, nil, nil, 123, 124, 126,
- 127, 129, 130, 131, 132, 120, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 120, nil,
- 160, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 50, 147, 148, 149, 150, nil, nil, nil, 34, 35,
- 36, nil, nil, 159, 161, nil, nil, nil, nil, 123,
- 124, 126, 127, 129, 130, 131, 132, 128, nil, nil,
- nil, 220, 123, 124, 126, 127, 129, 130, 131, 132,
- nil, nil, nil, nil, 220, nil, nil, nil, nil, nil,
- nil, nil, 50, 147, 148, 149, 150, nil, nil, nil,
- nil, nil, nil, nil, nil, 50, 147, 148, 149, 150,
- 128, nil, nil, nil, nil, 123, 124, 126, 127, 129,
- 130, 131, 132, 128, nil, nil, nil, 120, 123, 124,
- 126, 127, 129, 130, 131, 132, nil, nil, nil, nil,
- 224, nil, nil, nil, nil, nil, nil, nil, 50, 147,
- 148, 149, 150, nil, nil, nil, nil, nil, nil, nil,
- nil, 50, 147, 148, 149, 150, 128, nil, nil, nil,
- nil, 123, 124, 126, 127, 129, 130, 131, 132, 128,
- nil, nil, nil, nil, 123, 124, 126, 127, 129, 130,
- 131, 132, nil, nil, 120, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 50, 147, 148, 149, 150, 266,
- nil, nil, nil, 120, nil, nil, nil, 50, 147, 148,
- 149, 150, nil, nil, nil, nil, nil, 34, 35, 36,
- nil, nil, 265, 267, nil, nil, nil, 120, 123, 124,
- 126, 127, 129, 130, 131, 132, 34, 35, 36, nil,
- nil, nil, 128, nil, nil, nil, 120, 123, 124, 126,
- 127, 129, 130, 131, 132, nil, nil, nil, nil, nil,
- nil, 50, 147, 148, 149, 150, 128, nil, nil, nil,
- 120, 123, 124, 126, 127, 129, 130, 131, 132, nil,
- 50, 147, 148, 149, 150, 128, nil, nil, nil, 120,
- 123, 124, 126, 127, 129, 130, 131, 132, nil, nil,
- nil, nil, nil, nil, 50, 147, 148, 149, 150, 128,
- nil, nil, nil, 120, 123, 124, 126, 127, 129, 130,
- 131, 132, nil, 50, 147, 148, 149, 150, 128, nil,
- nil, nil, 120, 123, 124, 126, 127, 129, 130, 131,
- 132, nil, nil, nil, nil, nil, nil, 50, 147, 148,
- 149, 150, 128, nil, nil, nil, 120, 123, 124, 126,
- 127, 129, 130, 131, 132, nil, 50, 147, 148, 149,
- 150, 128, nil, nil, nil, nil, 123, 124, 126, 127,
- 129, 130, 131, 132, nil, nil, nil, nil, nil, nil,
- 50, 147, 148, 149, 150, 128, nil, nil, nil, nil,
- 123, 124, 126, 127, 129, 130, 131, 132, nil, 50,
- 147, 148, 149, 150, nil, nil, nil, nil, nil, nil,
- 120, 318, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 50, 147, 148, 149, 150, 15, 16,
- 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
- 31, 32, 33, 34, 35, 36, nil, nil, nil, 128,
- nil, 38, nil, 120, 123, 124, 126, 127, 129, 130,
- 131, 132, nil, nil, nil, nil, 120, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 50, 147, 148,
- 149, 150, 128, nil, nil, nil, nil, 123, 124, 126,
- 127, 129, 130, 131, 132, 128, nil, nil, nil, 120,
- 123, 124, 126, 127, 129, 130, 131, 132, nil, nil,
- nil, nil, 120, nil, nil, nil, nil, nil, nil, nil,
- 50, 147, 148, 149, 150, nil, nil, nil, nil, nil,
- nil, nil, nil, 50, 147, 148, 149, 150, 128, nil,
- nil, nil, nil, 123, 124, 126, 127, 129, 130, 131,
- 132, 128, nil, nil, nil, 120, 123, 124, 126, 127,
- 129, 130, 131, 132, nil, nil, nil, nil, 120, nil,
- nil, nil, nil, nil, nil, nil, 50, 147, 148, 149,
- 150, nil, nil, nil, nil, nil, nil, nil, nil, 50,
- 147, 148, 149, 150, 128, nil, nil, nil, nil, 123,
- 124, 126, 127, 129, 130, 131, 132, 128, nil, nil,
- nil, 120, 123, 124, 126, 127, 129, 130, 131, 132,
- nil, nil, nil, nil, 120, nil, nil, nil, nil, nil,
- nil, nil, 50, 147, 148, 149, 150, nil, nil, nil,
- nil, nil, nil, nil, nil, 50, 147, 148, 149, 150,
- 128, nil, nil, nil, nil, 123, 124, 126, 127, 129,
- 130, 131, 132, 128, nil, nil, nil, 120, 123, 124,
- 126, 127, 129, 130, 131, 132, nil, nil, nil, nil,
- 120, nil, nil, nil, nil, nil, nil, nil, 50, 147,
- 148, 149, 150, nil, nil, nil, nil, nil, nil, nil,
- nil, 50, 147, 148, 149, 150, 128, nil, nil, nil,
- nil, 123, 124, 126, 127, 129, 130, 131, 132, 128,
- nil, nil, nil, 120, 123, 124, 126, 127, 129, 130,
- 131, 132, nil, nil, nil, nil, 120, nil, nil, nil,
- nil, nil, nil, nil, 50, 147, 148, 149, 150, nil,
- nil, nil, nil, nil, nil, nil, nil, 50, 147, 148,
- 149, 150, 128, nil, nil, nil, nil, 123, 124, 126,
- 127, 129, 130, 131, 132, 128, nil, nil, nil, 120,
- 123, 124, 126, 127, 129, 130, 131, 132, nil, nil,
- nil, nil, 120, nil, nil, nil, nil, nil, nil, nil,
- 50, 147, 148, 149, 150, nil, nil, nil, nil, nil,
- nil, nil, nil, 50, 147, 148, 149, 150, 128, nil,
- nil, nil, nil, 123, 124, 126, 127, 129, 130, 131,
- 132, 128, nil, nil, nil, 120, 123, 124, 126, 127,
- 129, 130, 131, 132, nil, nil, nil, nil, 120, nil,
- nil, nil, nil, nil, nil, nil, 50, 147, 148, 149,
- 150, nil, nil, nil, nil, nil, nil, nil, nil, 50,
- 147, 148, 149, 150, 128, nil, nil, nil, nil, 123,
- 124, 126, 127, 129, 130, 131, 132, 128, nil, nil,
- nil, 120, 123, 124, 126, 127, 129, 130, 131, 132,
- nil, nil, nil, nil, 120, nil, nil, nil, nil, nil,
- nil, nil, 50, 147, 148, 149, 150, nil, nil, nil,
- nil, nil, nil, nil, nil, 50, 147, 148, 149, 150,
- 128, nil, nil, nil, nil, 123, 124, 126, 127, 129,
- 130, 131, 132, 128, nil, nil, nil, 120, 123, 124,
- 126, 127, 129, 130, 131, 132, nil, nil, nil, nil,
- 120, nil, nil, nil, nil, nil, nil, nil, 50, 147,
- 148, 149, 150, nil, nil, nil, nil, nil, nil, nil,
- nil, 50, 147, 148, 149, 150, 128, nil, nil, nil,
- nil, 123, 124, 126, 127, 129, 130, 131, 132, 128,
- nil, nil, nil, 120, 123, 124, 126, 127, 129, 130,
- 131, 132, nil, nil, nil, nil, 120, nil, nil, nil,
- nil, nil, nil, nil, 50, 147, 148, 149, 150, nil,
- nil, nil, nil, nil, nil, nil, nil, 50, 147, 148,
- 149, 150, 128, nil, nil, nil, nil, 123, 124, 126,
- 127, 129, 130, 131, 132, 128, nil, nil, nil, nil,
- 123, 124, 126, 127, 129, 130, 131, 132, 120, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 50, 147, 148, 149, 150, 120, nil, nil, nil, nil,
- nil, nil, nil, 50, 147, 148, 149, 150, nil, nil,
- nil, 34, 35, 36, nil, nil, nil, 128, nil, nil,
- nil, nil, 123, 124, 126, 127, 129, 130, 131, 132,
- nil, nil, nil, 368, 369, nil, nil, nil, 120, 123,
- 124, 126, 127, 129, 130, 131, 132, nil, nil, nil,
- nil, nil, 120, nil, nil, 50, 147, 148, 149, 150,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 50, 147, 148, 149, 150, 128, nil, nil,
- nil, nil, 123, 124, 126, 127, 129, 130, 131, 132,
- 401, 402, nil, nil, nil, 120, 123, 124, 126, 127,
- 129, 130, 131, 132, nil, nil, nil, nil, 120, 415,
- nil, nil, nil, nil, nil, 50, 147, 148, 149, 150,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 50,
- 147, 148, 149, 150, 128, nil, nil, nil, nil, 123,
- 124, 126, 127, 129, 130, 131, 132, 128, nil, nil,
- nil, nil, 123, 124, 126, 127, 129, 130, 131, 132,
- 120, 418, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 50, 147, 148, 149, 150, nil, nil, nil,
- nil, nil, nil, nil, nil, 50, 147, 148, 149, 150,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 128,
- nil, nil, nil, nil, 123, 124, 126, 127, 129, 130,
- 131, 132, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 120, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 50, 147, 148,
- 149, 150, 15, 16, 17, 18, 19, 20, 21, 22,
- 23, 24, 25, 26, 31, 32, 33, 34, 35, 36,
- nil, nil, nil, 128, nil, 38, nil, 120, 123, 124,
- 126, 127, 129, 130, 131, 132, nil, nil, nil, nil,
- 120, 430, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 50, 147, 148, 149, 150, 128, nil, nil, nil,
- nil, 123, 124, 126, 127, 129, 130, 131, 132, 128,
- nil, nil, nil, nil, 123, 124, 126, 127, 129, 130,
- 131, 132, 120, 432, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 50, 147, 148, 149, 150, 120,
- 436, nil, nil, nil, nil, nil, nil, 50, 147, 148,
- 149, 150, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 128, nil, nil, nil, nil, 123, 124, 126, 127,
- 129, 130, 131, 132, nil, nil, nil, nil, 128, nil,
- nil, nil, nil, 123, 124, 126, 127, 129, 130, 131,
- 132, 120, 444, nil, nil, nil, nil, nil, nil, 50,
- 147, 148, 149, 150, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 50, 147, 148, 149,
- 150, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 128, nil, nil, nil, nil, 123, 124, 126, 127, 129,
- 130, 131, 132, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 277, 364, nil, nil, nil, nil, nil, nil, 50, 147,
- 148, 149, 150, 10, 11, 12, 13, 14, 15, 16,
- 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
- 31, 32, 33, 34, 35, 36, 37, 281, 164, 49,
- nil, 38, nil, nil, nil, nil, nil, nil, nil, nil,
- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
- 20, 21, 22, 23, 24, 25, 26, 31, 32, 33,
- 34, 35, 36, 37, nil, nil, nil, 50, 38, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 39, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 50, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
- 25, 26, 31, 32, 33, 34, 35, 36, 37, 65,
- nil, nil, nil, 38, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 67, 10, 11, 12, 13,
- 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
- 24, 25, 26, 31, 32, 33, 34, 35, 36, 37,
- 65, nil, nil, nil, 38, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 10, 11, 12,
- 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
- 23, 24, 25, 26, 31, 32, 33, 34, 35, 36,
- 37, 173, nil, nil, nil, 38, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 15, 16, 17, 18, 19, 20, 21, 22,
- 23, 24, 25, 26, 31, 32, 33, 34, 35, 36,
- 282, nil, nil, nil, nil, 38, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 15, 16, 17, 18, 19, 20, 21, 22, 23,
- 24, 25, 26, 31, 32, 33, 34, 35, 36, 287,
- nil, nil, nil, nil, 38, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
- 25, 26, 31, 32, 33, 34, 35, 36, 312, 364,
- nil, nil, nil, 38, nil, nil, nil, nil, nil, nil,
- nil, 10, 11, 12, 13, 14, 15, 16, 17, 18,
- 19, 20, 21, 22, 23, 24, 25, 26, 31, 32,
- 33, 34, 35, 36, 37, 281, 404, 49, nil, 38,
- nil, nil, nil, nil, nil, nil, nil, nil, 10, 11,
- 12, 13, 14, 15, 16, 17, 18, 19, 20, 21,
- 22, 23, 24, 25, 26, 31, 32, 33, 34, 35,
- 36, 37, nil, nil, nil, nil, 38, 10, 11, 12,
- 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
- 23, 24, 25, 26, 31, 32, 33, 34, 35, 36,
- 37, nil, nil, nil, nil, 38, 10, 11, 12, 13,
- 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
- 24, 25, 26, 31, 32, 33, 34, 35, 36, 37,
- nil, nil, nil, nil, 38, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
- 25, 26, 31, 32, 33, 34, 35, 36, 37, nil,
- nil, nil, nil, 38, 10, 11, 12, 13, 14, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
- 26, 31, 32, 33, 34, 35, 36, 37, nil, nil,
- nil, nil, 38, 10, 11, 12, 13, 14, 15, 16,
- 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
- 31, 32, 33, 34, 35, 36, 37, nil, nil, nil,
- nil, 38, 10, 11, 12, 13, 14, 15, 16, 17,
- 18, 19, 20, 21, 22, 23, 24, 25, 26, 31,
- 32, 33, 34, 35, 36, 37, nil, nil, nil, 359,
- 38, 15, 16, 17, 18, 19, 20, 21, 22, 23,
- 24, 25, 26, 31, 32, 33, 34, 35, 36, nil,
- nil, nil, nil, nil, 38, 15, 16, 17, 18, 19,
- 20, 21, 22, 23, 24, 25, 26, 31, 32, 33,
- 34, 35, 36, nil, nil, nil, nil, nil, 38, 15,
- 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
- 26, 31, 32, 33, 34, 35, 36, nil, nil, nil,
- nil, nil, 38, 15, 16, 17, 18, 19, 20, 21,
- 22, 23, 24, 25, 26, 31, 32, 33, 34, 35,
- 36, nil, nil, nil, nil, nil, 38, 15, 16, 17,
- 18, 19, 20, 21, 22, 23, 24, 25, 26, 31,
- 32, 33, 34, 35, 36, nil, nil, nil, nil, nil,
- 38 ]
-
-racc_action_check = [
- 65, 65, 65, 65, 65, 65, 65, 210, 39, 65,
- 65, 65, 65, 65, 65, 65, 65, 55, 45, 65,
- 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
- 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
- 65, 65, 65, 46, 210, 65, 210, 65, 316, 345,
- 65, 65, 65, 65, 65, 65, 65, 65, 85, 276,
- 57, 163, 58, 135, 182, 186, 59, 345, 70, 184,
- 114, 163, 85, 289, 294, 316, 135, 135, 182, 186,
- 46, 136, 136, 65, 65, 65, 65, 65, 102, 102,
- 102, 102, 102, 102, 102, 45, 276, 102, 102, 102,
- 102, 102, 102, 102, 102, 70, 114, 102, 102, 102,
- 102, 102, 102, 102, 102, 102, 102, 102, 102, 102,
- 102, 102, 102, 102, 102, 102, 102, 102, 102, 102,
- 102, 30, 280, 102, 60, 102, 276, 73, 102, 102,
- 102, 102, 102, 102, 102, 102, 112, 112, 112, 184,
- 112, 112, 112, 289, 294, 112, 112, 112, 112, 112,
- 112, 112, 112, 257, 260, 330, 33, 42, 48, 280,
- 107, 102, 102, 102, 102, 102, 30, 257, 330, 330,
- 42, 80, 175, 107, 311, 361, 137, 137, 80, 260,
- 84, 112, 87, 112, 260, 175, 112, 112, 112, 112,
- 112, 112, 112, 112, 187, 187, 187, 48, 187, 187,
- 187, 33, 30, 187, 187, 187, 187, 187, 187, 187,
- 187, 311, 361, 207, 419, 139, 139, 80, 331, 112,
- 112, 112, 112, 112, 211, 304, 207, 133, 419, 284,
- 380, 331, 331, 89, 211, 48, 284, 33, 304, 187,
- 98, 187, 100, 380, 187, 187, 187, 187, 187, 187,
- 187, 187, 191, 191, 191, 80, 191, 191, 191, 382,
- 411, 191, 191, 191, 191, 191, 191, 191, 191, 144,
- 144, 101, 382, 411, 109, 284, 110, 187, 187, 187,
- 187, 187, 133, 133, 133, 133, 133, 133, 133, 133,
- 133, 133, 5, 111, 5, 332, 332, 191, 113, 191,
- 333, 333, 191, 191, 191, 191, 191, 191, 191, 191,
- 192, 192, 192, 284, 192, 192, 192, 300, 301, 192,
- 192, 192, 192, 192, 192, 192, 192, 300, 301, 115,
- 302, 317, 410, 5, 414, 191, 191, 191, 191, 191,
- 302, 317, 410, 417, 414, 116, 429, 119, 431, 435,
- 66, 140, 66, 417, 141, 192, 429, 192, 431, 435,
- 192, 192, 192, 192, 192, 192, 192, 192, 296, 296,
- 296, 5, 296, 296, 296, 443, 142, 296, 296, 296,
- 296, 296, 296, 296, 296, 443, 49, 49, 49, 334,
- 334, 66, 49, 192, 192, 192, 192, 192, 74, 74,
- 74, 335, 335, 143, 74, 138, 138, 138, 138, 151,
- 69, 336, 336, 296, 158, 296, 337, 337, 296, 296,
- 296, 296, 296, 296, 296, 296, 375, 375, 375, 66,
- 375, 375, 375, 340, 340, 375, 375, 375, 375, 375,
- 375, 375, 375, 338, 338, 338, 338, 161, 162, 69,
- 165, 296, 296, 296, 296, 296, 339, 339, 339, 339,
- 177, 188, 200, 201, 203, 204, 212, 213, 167, 216,
- 217, 375, 263, 375, 264, 267, 375, 375, 375, 375,
- 375, 375, 375, 375, 376, 376, 376, 69, 376, 376,
- 376, 270, 274, 376, 376, 376, 376, 376, 376, 376,
- 376, 303, 324, 325, 341, 167, 342, 167, 343, 375,
- 375, 375, 375, 375, 344, 351, 354, 356, 362, 363,
- 367, 369, 389, 390, 400, 402, 403, 407, 427, 376,
- nil, 376, nil, nil, 376, 376, 376, 376, 376, 376,
- 376, 376, 377, 377, 377, 167, 377, 377, 377, nil,
- nil, 377, 377, 377, 377, 377, 377, 377, 377, nil,
- nil, nil, nil, nil, nil, nil, nil, 376, 376, 376,
- 376, 376, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 377, nil, 377,
- nil, nil, 377, 377, 377, 377, 377, 377, 377, 377,
- 415, 415, 415, nil, 415, 415, 415, nil, nil, 415,
- 415, 415, 415, 415, 415, 415, 415, nil, nil, nil,
- nil, nil, nil, nil, nil, 377, 377, 377, 377, 377,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 415, nil, 415, nil, nil,
- 415, 415, 415, 415, 415, 415, 415, 415, 418, 418,
- 418, nil, 418, 418, 418, nil, nil, 418, 418, 418,
- 418, 418, 418, 418, 418, nil, nil, nil, nil, nil,
- nil, nil, nil, 415, 415, 415, 415, 415, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 418, nil, 418, nil, nil, 418, 418,
- 418, 418, 418, 418, 418, 418, 426, 426, 426, nil,
- 426, 426, 426, nil, nil, 426, 426, 426, 426, 426,
- 426, 426, 426, nil, nil, nil, nil, nil, nil, nil,
- nil, 418, 418, 418, 418, 418, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 426, nil, 426, nil, nil, 426, 426, 426, 426,
- 426, 426, 426, 426, 430, 430, 430, nil, 430, 430,
- 430, nil, nil, 430, 430, 430, 430, 430, 430, 430,
- 430, nil, nil, nil, nil, nil, nil, nil, nil, 426,
- 426, 426, 426, 426, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 430,
- nil, 430, nil, nil, 430, 430, 430, 430, 430, 430,
- 430, 430, 432, 432, 432, nil, 432, 432, 432, nil,
- nil, 432, 432, 432, 432, 432, 432, 432, 432, nil,
- nil, nil, nil, nil, nil, nil, nil, 430, 430, 430,
- 430, 430, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 432, nil, 432,
- nil, nil, 432, 432, 432, 432, 432, 432, 432, 432,
- 433, 433, 433, nil, 433, 433, 433, nil, nil, 433,
- 433, 433, 433, 433, 433, 433, 433, nil, nil, nil,
- nil, nil, nil, nil, nil, 432, 432, 432, 432, 432,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 433, nil, 433, nil, nil,
- 433, 433, 433, 433, 433, 433, 433, 433, 436, 436,
- 436, nil, 436, 436, 436, nil, nil, 436, 436, 436,
- 436, 436, 436, 436, 436, nil, nil, nil, nil, nil,
- nil, nil, nil, 433, 433, 433, 433, 433, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 436, nil, 436, nil, nil, 436, 436,
- 436, 436, 436, 436, 436, 436, 437, 437, 437, nil,
- 437, 437, 437, nil, nil, 437, 437, 437, 437, 437,
- 437, 437, 437, nil, nil, nil, nil, nil, nil, nil,
- nil, 436, 436, 436, 436, 436, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 437, nil, 437, nil, nil, 437, 437, 437, 437,
- 437, 437, 437, 437, 444, 444, 444, nil, 444, 444,
- 444, nil, nil, 444, 444, 444, 444, 444, 444, 444,
- 444, nil, nil, nil, nil, nil, nil, nil, nil, 437,
- 437, 437, 437, 437, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 444,
- nil, 444, nil, nil, 444, 444, 444, 444, 444, 444,
- 444, 444, 445, 445, 445, nil, 445, 445, 445, nil,
- nil, 445, 445, 445, 445, 445, 445, 445, 445, nil,
- nil, nil, nil, nil, nil, nil, nil, 444, 444, 444,
- 444, 444, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 445, nil, 445,
- nil, nil, 445, 445, 445, 445, 445, 445, 445, 445,
- 447, 447, 447, nil, 447, 447, 447, nil, nil, 447,
- 447, 447, 447, 447, 447, 447, 447, nil, nil, nil,
- nil, nil, nil, nil, nil, 445, 445, 445, 445, 445,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 447, nil, 447, nil, nil,
- 447, 447, 447, 447, 447, 447, 447, 447, 450, 450,
- 450, nil, 450, 450, 450, nil, nil, 450, 450, 450,
- 450, 450, 450, 450, 450, nil, nil, nil, nil, nil,
- nil, nil, nil, 447, 447, 447, 447, 447, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 450, nil, 450, nil, nil, 450, 450,
- 450, 450, 450, 450, 450, 450, 454, 454, 454, nil,
- 454, 454, 454, nil, nil, 454, 454, 454, 454, 454,
- 454, 454, 454, 67, nil, nil, nil, 67, nil, nil,
- nil, 450, 450, 450, 450, 450, nil, nil, nil, nil,
- nil, nil, 122, nil, nil, nil, nil, nil, nil, nil,
- nil, 454, nil, 454, nil, nil, 454, 454, 454, 454,
- 454, 454, 454, 454, nil, nil, 67, nil, nil, nil,
- nil, 67, 67, 67, 67, 67, 67, 67, 67, 122,
- nil, nil, nil, nil, 122, 122, 122, 122, nil, 454,
- 454, 454, 454, 454, 120, nil, nil, nil, 120, nil,
- nil, nil, nil, nil, 67, 67, 67, 67, 67, 154,
- nil, nil, nil, 154, nil, nil, 120, 120, 120, 120,
- 120, 120, 120, 120, 120, 120, 120, 120, 120, 120,
- 120, 120, 120, 120, nil, nil, nil, 120, nil, 120,
- nil, nil, 120, 120, 120, 120, 120, 120, 120, 120,
- 154, nil, 154, nil, nil, 154, nil, 154, 154, 154,
- 154, 154, 154, 154, 154, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 120, 120, 120, 120, 120,
- 220, nil, nil, nil, 220, nil, nil, nil, nil, nil,
- 154, 154, 154, 154, 154, nil, nil, nil, nil, nil,
- nil, nil, 220, 220, 220, 220, 220, 220, 220, 220,
- 220, 220, 220, 220, 220, 220, 220, 220, 220, 220,
- nil, nil, nil, 220, nil, 220, nil, nil, 220, 220,
- 220, 220, 220, 220, 220, 220, nil, nil, nil, nil,
- nil, nil, nil, nil, 224, nil, nil, nil, 224, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 220, 220, 220, 220, 220, 224, 224, 224, 224,
- 224, 224, 224, 224, 224, 224, 224, 224, 224, 224,
- 224, 224, 224, 224, nil, nil, nil, 224, nil, 224,
- nil, nil, 224, 224, 224, 224, 224, 224, 224, 224,
- 258, nil, nil, nil, 258, nil, nil, nil, nil, nil,
- nil, nil, nil, 315, nil, nil, nil, 315, nil, nil,
- nil, nil, nil, nil, nil, 224, 224, 224, 224, 224,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 258, nil, nil, nil, nil, 258, 258,
- 258, 258, 258, 258, 258, 258, 315, nil, nil, nil,
- nil, 315, 315, 315, 315, 315, 315, 315, 315, 347,
- 347, nil, nil, 347, nil, nil, nil, nil, nil, nil,
- nil, 258, 258, 258, 258, 258, 384, nil, nil, nil,
- 384, nil, nil, nil, 315, 315, 315, 315, 315, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 347, nil, 347, nil, nil, 347, nil, 347, 347, 347,
- 347, 347, 347, 347, 347, nil, nil, 384, nil, 384,
- nil, nil, 384, nil, 384, 384, 384, 384, 384, 384,
- 384, 384, 393, nil, nil, nil, 393, nil, nil, nil,
- 347, 347, 347, 347, 347, nil, nil, 439, 439, nil,
- nil, 439, nil, nil, nil, nil, nil, 384, 384, 384,
- 384, 384, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 393, nil, nil, nil, nil,
- 393, 393, 393, 393, 393, 393, 393, 393, 439, nil,
- 439, nil, 117, 439, 117, 439, 439, 439, 439, 439,
- 439, 439, 439, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 393, 393, 393, 393, 393, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 439, 439,
- 439, 439, 439, 117, nil, nil, nil, nil, 117, 117,
- 117, 117, 117, 117, 117, 117, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 202, nil, 202, nil, nil, nil, nil, nil, nil,
- nil, 117, 117, 117, 117, 117, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202, 202, 202,
- nil, nil, 202, nil, 202, nil, nil, 202, 202, 202,
- 202, 202, 202, 202, 202, 305, nil, 305, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 306, nil,
- 306, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 202, 202, 202, 202, 202, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 305, nil, nil, nil,
- nil, 305, 305, 305, 305, 305, 305, 305, 305, 306,
- nil, 379, nil, 379, 306, 306, 306, 306, 306, 306,
- 306, 306, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 305, 305, 305, 305, 305, nil,
- nil, nil, nil, nil, nil, nil, nil, 306, 306, 306,
- 306, 306, 379, nil, nil, nil, nil, 379, 379, 379,
- 379, 379, 379, 379, 379, 71, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 99, nil,
- 71, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 379, 379, 379, 379, 379, nil, nil, nil, 71, 71,
- 71, nil, nil, 71, 71, nil, nil, nil, nil, 71,
- 71, 71, 71, 71, 71, 71, 71, 99, nil, nil,
- nil, 123, 99, 99, 99, 99, 99, 99, 99, 99,
- nil, nil, nil, nil, 124, nil, nil, nil, nil, nil,
- nil, nil, 71, 71, 71, 71, 71, nil, nil, nil,
- nil, nil, nil, nil, nil, 99, 99, 99, 99, 99,
- 123, nil, nil, nil, nil, 123, 123, 123, 123, 123,
- 123, 123, 123, 124, nil, nil, nil, 125, 124, 124,
- 124, 124, 124, 124, 124, 124, nil, nil, nil, nil,
- 126, nil, nil, nil, nil, nil, nil, nil, 123, 123,
- 123, 123, 123, nil, nil, nil, nil, nil, nil, nil,
- nil, 124, 124, 124, 124, 124, 125, nil, nil, nil,
- nil, 125, 125, 125, 125, 125, 125, 125, 125, 126,
- nil, nil, nil, nil, 126, 126, 126, 126, 126, 126,
- 126, 126, nil, nil, 157, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 125, 125, 125, 125, 125, 157,
- nil, nil, nil, 160, nil, nil, nil, 126, 126, 126,
- 126, 126, nil, nil, nil, nil, nil, 157, 157, 157,
- nil, nil, 157, 157, nil, nil, nil, 178, 157, 157,
- 157, 157, 157, 157, 157, 157, 160, 160, 160, nil,
- nil, nil, 160, nil, nil, nil, 185, 160, 160, 160,
- 160, 160, 160, 160, 160, nil, nil, nil, nil, nil,
- nil, 157, 157, 157, 157, 157, 178, nil, nil, nil,
- 196, 178, 178, 178, 178, 178, 178, 178, 178, nil,
- 160, 160, 160, 160, 160, 185, nil, nil, nil, 197,
- 185, 185, 185, 185, 185, 185, 185, 185, nil, nil,
- nil, nil, nil, nil, 178, 178, 178, 178, 178, 196,
- nil, nil, nil, 198, 196, 196, 196, 196, 196, 196,
- 196, 196, nil, 185, 185, 185, 185, 185, 197, nil,
- nil, nil, 199, 197, 197, 197, 197, 197, 197, 197,
- 197, nil, nil, nil, nil, nil, nil, 196, 196, 196,
- 196, 196, 198, nil, nil, nil, 214, 198, 198, 198,
- 198, 198, 198, 198, 198, nil, 197, 197, 197, 197,
- 197, 199, nil, nil, nil, nil, 199, 199, 199, 199,
- 199, 199, 199, 199, nil, nil, nil, nil, nil, nil,
- 198, 198, 198, 198, 198, 214, nil, nil, nil, nil,
- 214, 214, 214, 214, 214, 214, 214, 214, nil, 199,
- 199, 199, 199, 199, nil, nil, nil, nil, nil, nil,
- 215, 215, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 214, 214, 214, 214, 214, 215, 215,
- 215, 215, 215, 215, 215, 215, 215, 215, 215, 215,
- 215, 215, 215, 215, 215, 215, nil, nil, nil, 215,
- nil, 215, nil, 226, 215, 215, 215, 215, 215, 215,
- 215, 215, nil, nil, nil, nil, 238, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 215, 215, 215,
- 215, 215, 226, nil, nil, nil, nil, 226, 226, 226,
- 226, 226, 226, 226, 226, 238, nil, nil, nil, 239,
- 238, 238, 238, 238, 238, 238, 238, 238, nil, nil,
- nil, nil, 240, nil, nil, nil, nil, nil, nil, nil,
- 226, 226, 226, 226, 226, nil, nil, nil, nil, nil,
- nil, nil, nil, 238, 238, 238, 238, 238, 239, nil,
- nil, nil, nil, 239, 239, 239, 239, 239, 239, 239,
- 239, 240, nil, nil, nil, 241, 240, 240, 240, 240,
- 240, 240, 240, 240, nil, nil, nil, nil, 242, nil,
- nil, nil, nil, nil, nil, nil, 239, 239, 239, 239,
- 239, nil, nil, nil, nil, nil, nil, nil, nil, 240,
- 240, 240, 240, 240, 241, nil, nil, nil, nil, 241,
- 241, 241, 241, 241, 241, 241, 241, 242, nil, nil,
- nil, 243, 242, 242, 242, 242, 242, 242, 242, 242,
- nil, nil, nil, nil, 244, nil, nil, nil, nil, nil,
- nil, nil, 241, 241, 241, 241, 241, nil, nil, nil,
- nil, nil, nil, nil, nil, 242, 242, 242, 242, 242,
- 243, nil, nil, nil, nil, 243, 243, 243, 243, 243,
- 243, 243, 243, 244, nil, nil, nil, 245, 244, 244,
- 244, 244, 244, 244, 244, 244, nil, nil, nil, nil,
- 246, nil, nil, nil, nil, nil, nil, nil, 243, 243,
- 243, 243, 243, nil, nil, nil, nil, nil, nil, nil,
- nil, 244, 244, 244, 244, 244, 245, nil, nil, nil,
- nil, 245, 245, 245, 245, 245, 245, 245, 245, 246,
- nil, nil, nil, 247, 246, 246, 246, 246, 246, 246,
- 246, 246, nil, nil, nil, nil, 248, nil, nil, nil,
- nil, nil, nil, nil, 245, 245, 245, 245, 245, nil,
- nil, nil, nil, nil, nil, nil, nil, 246, 246, 246,
- 246, 246, 247, nil, nil, nil, nil, 247, 247, 247,
- 247, 247, 247, 247, 247, 248, nil, nil, nil, 249,
- 248, 248, 248, 248, 248, 248, 248, 248, nil, nil,
- nil, nil, 250, nil, nil, nil, nil, nil, nil, nil,
- 247, 247, 247, 247, 247, nil, nil, nil, nil, nil,
- nil, nil, nil, 248, 248, 248, 248, 248, 249, nil,
- nil, nil, nil, 249, 249, 249, 249, 249, 249, 249,
- 249, 250, nil, nil, nil, 251, 250, 250, 250, 250,
- 250, 250, 250, 250, nil, nil, nil, nil, 252, nil,
- nil, nil, nil, nil, nil, nil, 249, 249, 249, 249,
- 249, nil, nil, nil, nil, nil, nil, nil, nil, 250,
- 250, 250, 250, 250, 251, nil, nil, nil, nil, 251,
- 251, 251, 251, 251, 251, 251, 251, 252, nil, nil,
- nil, 253, 252, 252, 252, 252, 252, 252, 252, 252,
- nil, nil, nil, nil, 254, nil, nil, nil, nil, nil,
- nil, nil, 251, 251, 251, 251, 251, nil, nil, nil,
- nil, nil, nil, nil, nil, 252, 252, 252, 252, 252,
- 253, nil, nil, nil, nil, 253, 253, 253, 253, 253,
- 253, 253, 253, 254, nil, nil, nil, 255, 254, 254,
- 254, 254, 254, 254, 254, 254, nil, nil, nil, nil,
- 256, nil, nil, nil, nil, nil, nil, nil, 253, 253,
- 253, 253, 253, nil, nil, nil, nil, nil, nil, nil,
- nil, 254, 254, 254, 254, 254, 255, nil, nil, nil,
- nil, 255, 255, 255, 255, 255, 255, 255, 255, 256,
- nil, nil, nil, 262, 256, 256, 256, 256, 256, 256,
- 256, 256, nil, nil, nil, nil, 266, nil, nil, nil,
- nil, nil, nil, nil, 255, 255, 255, 255, 255, nil,
- nil, nil, nil, nil, nil, nil, nil, 256, 256, 256,
- 256, 256, 262, nil, nil, nil, nil, 262, 262, 262,
- 262, 262, 262, 262, 262, 266, nil, nil, nil, nil,
- 266, 266, 266, 266, 266, 266, 266, 266, 269, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 262, 262, 262, 262, 262, 281, nil, nil, nil, nil,
- nil, nil, nil, 266, 266, 266, 266, 266, nil, nil,
- nil, 269, 269, 269, nil, nil, nil, 269, nil, nil,
- nil, nil, 269, 269, 269, 269, 269, 269, 269, 269,
- nil, nil, nil, 281, 281, nil, nil, nil, 285, 281,
- 281, 281, 281, 281, 281, 281, 281, nil, nil, nil,
- nil, nil, 365, nil, nil, 269, 269, 269, 269, 269,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 281, 281, 281, 281, 281, 285, nil, nil,
- nil, nil, 285, 285, 285, 285, 285, 285, 285, 285,
- 365, 365, nil, nil, nil, 378, 365, 365, 365, 365,
- 365, 365, 365, 365, nil, nil, nil, nil, 381, 381,
- nil, nil, nil, nil, nil, 285, 285, 285, 285, 285,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 365,
- 365, 365, 365, 365, 378, nil, nil, nil, nil, 378,
- 378, 378, 378, 378, 378, 378, 378, 381, nil, nil,
- nil, nil, 381, 381, 381, 381, 381, 381, 381, 381,
- 383, 383, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 378, 378, 378, 378, 378, nil, nil, nil,
- nil, nil, nil, nil, nil, 381, 381, 381, 381, 381,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 383,
- nil, nil, nil, nil, 383, 383, 383, 383, 383, 383,
- 383, 383, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 388, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 383, 383, 383,
- 383, 383, 388, 388, 388, 388, 388, 388, 388, 388,
- 388, 388, 388, 388, 388, 388, 388, 388, 388, 388,
- nil, nil, nil, 388, nil, 388, nil, 391, 388, 388,
- 388, 388, 388, 388, 388, 388, nil, nil, nil, nil,
- 412, 412, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 388, 388, 388, 388, 388, 391, nil, nil, nil,
- nil, 391, 391, 391, 391, 391, 391, 391, 391, 412,
- nil, nil, nil, nil, 412, 412, 412, 412, 412, 412,
- 412, 412, 413, 413, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 391, 391, 391, 391, 391, 416,
- 416, nil, nil, nil, nil, nil, nil, 412, 412, 412,
- 412, 412, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 413, nil, nil, nil, nil, 413, 413, 413, 413,
- 413, 413, 413, 413, nil, nil, nil, nil, 416, nil,
- nil, nil, nil, 416, 416, 416, 416, 416, 416, 416,
- 416, 428, 428, nil, nil, nil, nil, nil, nil, 413,
- 413, 413, 413, 413, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 416, 416, 416, 416,
- 416, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 428, nil, nil, nil, nil, 428, 428, 428, 428, 428,
- 428, 428, 428, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 277, 277, nil, nil, nil, nil, nil, nil, 428, 428,
- 428, 428, 428, 277, 277, 277, 277, 277, 277, 277,
- 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
- 277, 277, 277, 277, 277, 277, 277, 277, 72, 277,
- nil, 277, nil, nil, nil, nil, nil, nil, nil, nil,
- 72, 72, 72, 72, 72, 72, 72, 72, 72, 72,
- 72, 72, 72, 72, 72, 72, 72, 72, 72, 72,
- 72, 72, 72, 72, nil, nil, nil, 277, 72, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 1, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 72, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 41,
- nil, nil, nil, 1, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 41, 41, 41, 41, 41,
- 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
- 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
- 62, nil, nil, nil, 41, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 62, 62, 62,
- 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
- 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
- 62, 78, nil, nil, nil, 62, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 78, 78, 78, 78, 78, 78, 78, 78,
- 78, 78, 78, 78, 78, 78, 78, 78, 78, 78,
- 172, nil, nil, nil, nil, 78, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 172, 172, 172, 172, 172, 172, 172, 172, 172,
- 172, 172, 172, 172, 172, 172, 172, 172, 172, 181,
- nil, nil, nil, nil, 172, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 181, 181, 181, 181, 181, 181, 181, 181, 181, 181,
- 181, 181, 181, 181, 181, 181, 181, 181, 312, 312,
- nil, nil, nil, 181, nil, nil, nil, nil, nil, nil,
- nil, 312, 312, 312, 312, 312, 312, 312, 312, 312,
- 312, 312, 312, 312, 312, 312, 312, 312, 312, 312,
- 312, 312, 312, 312, 312, 312, 366, 312, nil, 312,
- nil, nil, nil, nil, nil, nil, nil, nil, 366, 366,
- 366, 366, 366, 366, 366, 366, 366, 366, 366, 366,
- 366, 366, 366, 366, 366, 366, 366, 366, 366, 366,
- 366, 366, nil, nil, nil, nil, 366, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, nil, nil, nil, nil, 0, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- nil, nil, nil, nil, 6, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, nil,
- nil, nil, nil, 7, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, nil, nil,
- nil, nil, 8, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, nil, nil, nil,
- nil, 9, 275, 275, 275, 275, 275, 275, 275, 275,
- 275, 275, 275, 275, 275, 275, 275, 275, 275, 275,
- 275, 275, 275, 275, 275, 275, nil, nil, nil, 275,
- 275, 56, 56, 56, 56, 56, 56, 56, 56, 56,
- 56, 56, 56, 56, 56, 56, 56, 56, 56, nil,
- nil, nil, nil, nil, 56, 77, 77, 77, 77, 77,
- 77, 77, 77, 77, 77, 77, 77, 77, 77, 77,
- 77, 77, 77, nil, nil, nil, nil, nil, 77, 81,
- 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
- 81, 81, 81, 81, 81, 81, 81, nil, nil, nil,
- nil, nil, 81, 82, 82, 82, 82, 82, 82, 82,
- 82, 82, 82, 82, 82, 82, 82, 82, 82, 82,
- 82, nil, nil, nil, nil, nil, 82, 83, 83, 83,
- 83, 83, 83, 83, 83, 83, 83, 83, 83, 83,
- 83, 83, 83, 83, 83, nil, nil, nil, nil, nil,
- 83 ]
-
-racc_action_pointer = [
- 4005, 3703, nil, nil, nil, 295, 4034, 4063, 4092, 4121,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 126, nil, nil, 161, nil, nil, nil, nil, nil, 8,
- nil, 3744, 160, nil, nil, 9, 34, nil, 159, 354,
- nil, nil, nil, nil, nil, 12, 4174, 55, 57, -20,
- 129, nil, 3785, nil, nil, -3, 353, 1318, nil, 411,
- 59, 2026, 3638, 127, 366, nil, nil, 4198, 3825, nil,
- 179, 4222, 4246, 4270, 104, 52, nil, 171, nil, 157,
- nil, nil, nil, nil, nil, nil, nil, nil, 248, 2039,
- 250, 279, 85, nil, nil, nil, nil, 163, nil, 275,
- 277, 294, 143, 299, 20, 332, 348, 1795, nil, 267,
- 1389, nil, 1333, 2082, 2095, 2138, 2151, nil, nil, nil,
- nil, nil, nil, 216, nil, 15, 24, 123, 350, 156,
- 305, 293, 314, 340, 205, nil, nil, nil, nil, nil,
- nil, 398, nil, nil, 1404, nil, nil, 2205, 377, nil,
- 2224, 410, 448, 51, nil, 440, nil, 469, nil, nil,
- nil, nil, 3864, nil, nil, 175, nil, 468, 2248, nil,
- nil, 3903, 58, nil, 63, 2267, 59, 201, 469, nil,
- nil, 259, 317, nil, nil, nil, 2291, 2310, 2334, 2353,
- 470, 460, 1864, 467, 468, nil, nil, 216, nil, nil,
- -2, 224, 466, 467, 2377, 2441, 393, 394, nil, nil,
- 1475, nil, nil, nil, 1539, nil, 2484, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 2497, 2540,
- 2553, 2596, 2609, 2652, 2665, 2708, 2721, 2764, 2777, 2820,
- 2833, 2876, 2889, 2932, 2945, 2988, 3001, 157, 1595, nil,
- 143, nil, 3044, 396, 437, nil, 3057, 438, nil, 3109,
- 454, nil, nil, nil, 416, 4150, 50, 3601, nil, nil,
- 123, 3126, nil, nil, 237, 3169, nil, nil, nil, 67,
- nil, nil, nil, nil, 68, nil, 375, nil, nil, nil,
- 317, 318, 330, 502, 228, 1918, 1931, nil, nil, nil,
- nil, 175, 3939, nil, nil, 1608, 28, 331, nil, nil,
- nil, nil, nil, nil, 502, 503, nil, nil, nil, nil,
- 117, 180, 248, 253, 336, 348, 358, 363, 388, 401,
- 374, 458, 445, 446, 451, 47, nil, 1664, nil, nil,
- nil, 478, nil, nil, 479, nil, 480, nil, nil, nil,
- nil, 176, 518, 519, nil, 3183, 3976, 483, nil, 484,
- nil, nil, nil, nil, nil, 433, 491, 549, 3226, 1974,
- 233, 3239, 262, 3291, 1681, nil, nil, nil, 3355, 527,
- 528, 3398, nil, 1737, nil, nil, nil, nil, nil, nil,
- 487, nil, 488, 526, nil, nil, nil, 526, nil, nil,
- 332, 263, 3411, 3463, 334, 607, 3480, 343, 665, 218,
- nil, nil, nil, nil, nil, nil, 723, 531, 3532, 346,
- 781, 348, 839, 897, nil, 349, 955, 1013, nil, 1752,
- nil, nil, nil, 375, 1071, 1129, nil, 1187, nil, nil,
- 1245, nil, nil, nil, 1303, nil, nil, nil, nil, nil ]
-
-racc_action_default = [
- -265, -265, -1, -3, -4, -265, -53, -55, -57, -59,
- -64, -65, -66, -67, -68, -69, -70, -71, -72, -73,
- -74, -75, -76, -77, -78, -79, -80, -81, -82, -83,
- -265, -89, -90, -265, -115, -116, -117, -118, -166, -265,
- -2, -62, -265, -51, -60, -265, -120, -121, -265, -136,
- -258, -52, -54, -56, -58, -86, -265, -88, -107, -265,
- -110, 460, -265, -6, -7, -265, -265, -265, -50, -265,
- -119, -265, -265, -265, -135, -138, -139, -265, -265, -91,
- -265, -95, -97, -265, -265, -265, -111, -113, -262, -265,
- -5, -8, -9, -10, -11, -12, -13, -14, -179, -265,
- -265, -83, -265, -20, -21, -23, -24, -265, -26, -265,
- -265, -265, -265, -265, -265, -265, -265, -265, -180, -181,
- -265, -184, -198, -265, -265, -265, -265, -204, -205, -206,
- -207, -208, -209, -210, -212, -216, -219, -222, -227, -230,
- -232, -234, -236, -238, -240, -242, -255, -259, -260, -261,
- -264, -62, -63, -167, -265, -179, -61, -265, -265, -126,
- -265, -205, -265, -265, -134, -141, -143, -147, -148, -122,
- -137, -140, -265, -85, -92, -265, -98, -100, -265, -94,
- -96, -265, -265, -104, -265, -265, -265, -265, -265, -210,
- -257, -265, -265, -19, -22, -25, -265, -265, -265, -265,
- -265, -265, -265, -265, -265, -45, -46, -265, -48, -263,
- -151, -265, -265, -265, -265, -265, -265, -265, -190, -191,
- -265, -199, -200, -201, -265, -202, -265, -244, -245, -246,
- -247, -248, -249, -250, -251, -252, -253, -254, -265, -265,
- -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
- -265, -265, -265, -265, -265, -265, -265, -265, -265, -171,
- -265, -175, -265, -265, -265, -124, -265, -205, -125, -265,
- -265, -131, -132, -133, -265, -265, -152, -265, -145, -146,
- -154, -265, -84, -93, -265, -265, -102, -87, -103, -265,
- -106, -112, -114, -108, -265, -15, -265, -17, -18, -256,
- -265, -265, -265, -265, -265, -265, -265, -44, -49, -47,
- -150, -152, -265, -182, -183, -265, -265, -265, -187, -194,
- -196, -197, -188, -189, -265, -265, -243, -213, -214, -215,
- -217, -218, -220, -221, -223, -224, -225, -226, -228, -229,
- -231, -233, -235, -237, -239, -265, -168, -265, -170, -174,
- -176, -265, -178, -123, -265, -130, -265, -128, -149, -142,
- -144, -153, -265, -265, -165, -265, -265, -265, -159, -205,
- -99, -101, -105, -109, -16, -265, -265, -265, -265, -265,
- -265, -265, -265, -265, -265, -211, -185, -186, -265, -265,
- -203, -265, -169, -265, -173, -177, -129, -127, -155, -164,
- -265, -157, -205, -265, -163, -158, -161, -27, -29, -30,
- -265, -265, -265, -265, -265, -265, -265, -265, -265, -265,
- -195, -241, -172, -156, -160, -162, -265, -265, -265, -265,
- -265, -265, -265, -265, -39, -265, -265, -265, -43, -265,
- -192, -28, -31, -265, -265, -265, -35, -265, -37, -38,
- -265, -41, -42, -193, -265, -33, -34, -36, -40, -32 ]
-
-racc_goto_table = [
- 47, 152, 57, 162, 75, 60, 70, 319, 153, 5,
- 5, 257, 158, 176, 174, 51, 52, 53, 54, 76,
- 393, 291, 279, 361, 74, 55, 82, 1, 58, 170,
- 62, 104, 179, 180, 190, 223, 63, 101, 102, 41,
- 47, 76, 188, 47, 171, 64, 157, 82, 82, 78,
- 156, 82, 82, 82, 213, 85, 175, 90, 361, 163,
- 98, 47, 2, 40, 47, 310, 91, 168, 194, 105,
- 172, 210, 330, 331, 101, 47, 181, 332, 333, 360,
- 182, 167, 338, 339, 200, 186, 204, 350, 317, 340,
- 82, 334, 335, 336, 337, 153, 341, 98, 264, 342,
- 151, 270, 343, 151, 344, 226, 105, 98, 174, 203,
- nil, nil, 393, 190, 177, 212, nil, 174, nil, 81,
- 190, 286, 276, nil, nil, nil, 291, 171, 292, nil,
- 76, 291, nil, nil, nil, 269, nil, 299, nil, nil,
- 81, 81, 82, nil, 81, 81, 81, nil, 327, 328,
- 329, 82, nil, nil, 324, nil, 320, nil, 325, 200,
- nil, nil, 47, 200, 200, 311, 210, 326, nil, nil,
- 201, 210, nil, nil, nil, 210, nil, nil, nil, nil,
- 420, nil, 98, 81, nil, 82, 98, 98, nil, nil,
- 82, nil, 348, nil, 82, nil, nil, 190, nil, 153,
- nil, 278, nil, nil, nil, 351, 306, 354, nil, nil,
- 356, 322, 323, nil, nil, 212, nil, 370, nil, 212,
- 190, nil, 367, nil, nil, 385, nil, nil, 371, nil,
- nil, nil, 276, nil, nil, 81, nil, 70, nil, 171,
- nil, 419, nil, nil, 81, 295, nil, nil, nil, 297,
- 298, nil, nil, nil, nil, nil, nil, nil, 352, nil,
- nil, nil, nil, nil, nil, nil, nil, 311, 200, 358,
- nil, 47, 47, nil, nil, nil, nil, nil, 81, 47,
- nil, 394, nil, 81, 167, nil, 167, 81, 153, nil,
- nil, 98, nil, nil, nil, nil, nil, 403, nil, nil,
- nil, nil, nil, nil, 207, nil, 400, 211, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 177, nil,
- nil, 167, nil, nil, nil, 153, 421, 422, nil, 320,
- nil, nil, nil, nil, 153, nil, nil, nil, nil, 210,
- nil, nil, nil, nil, nil, nil, nil, 200, 200, 200,
- nil, nil, nil, nil, 374, nil, nil, nil, 82, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 98, 98, 98, 394, nil, 167, nil, nil, nil, nil,
- 153, nil, nil, nil, 300, 301, 302, 200, nil, 304,
- 200, nil, nil, nil, nil, nil, nil, nil, 200, nil,
- nil, 316, 200, nil, 200, 200, nil, 211, 200, 200,
- 98, 211, nil, 98, nil, nil, 200, 200, nil, 200,
- nil, 98, 200, nil, nil, 98, 200, 98, 98, nil,
- nil, 98, 98, 407, 408, 409, nil, nil, 189, 98,
- 98, nil, 98, 345, nil, 98, nil, nil, nil, 98,
- nil, 81, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 221, 222, 189, 225, nil, nil, nil, nil,
- nil, nil, nil, 434, nil, nil, 438, nil, nil, nil,
- nil, nil, nil, nil, 441, nil, nil, nil, 446, nil,
- 448, 449, 380, 382, 451, 452, nil, nil, nil, nil,
- nil, nil, 455, 456, nil, 457, nil, nil, 458, nil,
- nil, nil, 459, nil, nil, nil, nil, 189, nil, nil,
- nil, nil, nil, nil, 189, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 410, 411, nil, 414, nil,
- 417, nil, nil, nil, nil, nil, nil, 189, 189, 189,
- 189, 189, 189, 189, 189, 189, 189, 189, 189, 189,
- 189, 189, 189, 189, 189, nil, nil, nil, nil, 429,
- 431, 189, nil, 435, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 443, nil, nil, nil, nil,
- nil, nil, nil, nil, 189, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 189, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 189 ]
-
-racc_goto_check = [
- 15, 27, 17, 43, 39, 17, 40, 59, 42, 5,
- 5, 50, 42, 35, 32, 5, 5, 5, 5, 24,
- 51, 37, 47, 49, 41, 15, 24, 1, 15, 39,
- 7, 19, 33, 33, 73, 62, 8, 17, 18, 6,
- 15, 24, 16, 15, 24, 4, 41, 24, 24, 31,
- 26, 24, 24, 24, 48, 36, 34, 8, 49, 44,
- 15, 15, 2, 2, 15, 47, 4, 15, 19, 4,
- 31, 33, 63, 63, 17, 15, 31, 64, 64, 46,
- 36, 5, 66, 66, 17, 36, 17, 53, 58, 67,
- 24, 65, 65, 65, 65, 42, 68, 15, 42, 69,
- 6, 42, 70, 6, 71, 74, 4, 15, 32, 15,
- nil, nil, 51, 73, 6, 8, nil, 32, nil, 23,
- 73, 16, 39, nil, nil, nil, 37, 24, 16, nil,
- 24, 37, nil, nil, nil, 41, nil, 42, nil, nil,
- 23, 23, 24, nil, 23, 23, 23, nil, 62, 62,
- 62, 24, nil, nil, 48, nil, 42, nil, 48, 17,
- nil, nil, 15, 17, 17, 39, 33, 42, nil, nil,
- 9, 33, nil, nil, nil, 33, nil, nil, nil, nil,
- 59, nil, 15, 23, nil, 24, 15, 15, nil, nil,
- 24, nil, 27, nil, 24, nil, nil, 73, nil, 42,
- nil, 6, nil, nil, nil, 16, 4, 42, nil, nil,
- 42, 15, 15, nil, nil, 8, nil, 35, nil, 8,
- 73, nil, 42, nil, nil, 62, nil, nil, 16, nil,
- nil, nil, 39, nil, nil, 23, nil, 40, nil, 24,
- nil, 50, nil, nil, 23, 9, nil, nil, nil, 9,
- 9, nil, nil, nil, nil, nil, nil, nil, 15, nil,
- nil, nil, nil, nil, nil, nil, nil, 39, 17, 15,
- nil, 15, 15, nil, nil, nil, nil, nil, 23, 15,
- nil, 27, nil, 23, 5, nil, 5, 23, 42, nil,
- nil, 15, nil, nil, nil, nil, nil, 43, nil, nil,
- nil, nil, nil, nil, 20, nil, 42, 20, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 6, nil,
- nil, 5, nil, nil, nil, 42, 73, 27, nil, 42,
- nil, nil, nil, nil, 42, nil, nil, nil, nil, 33,
- nil, nil, nil, nil, nil, nil, nil, 17, 17, 17,
- nil, nil, nil, nil, 9, nil, nil, nil, 24, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 15, 15, 15, 27, nil, 5, nil, nil, nil, nil,
- 42, nil, nil, nil, 20, 20, 20, 17, nil, 20,
- 17, nil, nil, nil, nil, nil, nil, nil, 17, nil,
- nil, 20, 17, nil, 17, 17, nil, 20, 17, 17,
- 15, 20, nil, 15, nil, nil, 17, 17, nil, 17,
- nil, 15, 17, nil, nil, 15, 17, 15, 15, nil,
- nil, 15, 15, 9, 9, 9, nil, nil, 60, 15,
- 15, nil, 15, 20, nil, 15, nil, nil, nil, 15,
- nil, 23, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 60, 60, 60, 60, nil, nil, nil, nil,
- nil, nil, nil, 9, nil, nil, 9, nil, nil, nil,
- nil, nil, nil, nil, 9, nil, nil, nil, 9, nil,
- 9, 9, 20, 20, 9, 9, nil, nil, nil, nil,
- nil, nil, 9, 9, nil, 9, nil, nil, 9, nil,
- nil, nil, 9, nil, nil, nil, nil, 60, nil, nil,
- nil, nil, nil, nil, 60, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 20, 20, nil, 20, nil,
- 20, nil, nil, nil, nil, nil, nil, 60, 60, 60,
- 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
- 60, 60, 60, 60, 60, nil, nil, nil, nil, 20,
- 20, 60, nil, 20, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 20, nil, nil, nil, nil,
- nil, nil, nil, nil, 60, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 60, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 60 ]
-
-racc_goto_pointer = [
- nil, 27, 62, nil, 4, 9, 34, -11, -5, 58,
- nil, nil, nil, nil, nil, -5, -57, -28, -27, -34,
- 187, nil, nil, 63, -30, nil, -19, -66, nil, nil,
- nil, -7, -64, -49, -24, -67, -4, -163, nil, -45,
- -39, -25, -59, -69, -13, nil, -196, -145, -66, -253,
- -143, -327, nil, -173, nil, nil, nil, nil, -127, -208,
- 339, nil, -90, -169, -166, -154, -167, -162, -156, -154,
- -152, -151, nil, -65, -28 ]
-
-racc_goto_default = [
- nil, nil, nil, 3, 4, 66, 73, nil, 93, 106,
- 92, 94, 95, 96, 97, 155, nil, 29, nil, nil,
- 107, 42, 6, 7, 8, 9, 44, 259, 27, 28,
- 30, nil, 79, 80, nil, nil, nil, 86, 87, 45,
- 46, nil, 146, 363, nil, 165, 166, 362, 321, 280,
- nil, 258, 260, 261, 121, 118, 119, 122, nil, nil,
- 133, 125, 134, 135, 136, 137, 138, 139, 140, 141,
- 142, 143, 144, 145, nil ]
-
-racc_reduce_table = [
- 0, 0, :racc_error,
- 1, 92, :_reduce_1,
- 2, 92, :_reduce_2,
- 1, 93, :_reduce_3,
- 1, 93, :_reduce_4,
- 4, 94, :_reduce_5,
- 3, 94, :_reduce_6,
- 1, 98, :_reduce_7,
- 2, 98, :_reduce_8,
- 1, 100, :_reduce_9,
- 1, 100, :_reduce_10,
- 1, 100, :_reduce_11,
- 1, 100, :_reduce_12,
- 1, 100, :_reduce_13,
- 1, 100, :_reduce_14,
- 3, 101, :_reduce_15,
- 4, 101, :_reduce_16,
- 3, 101, :_reduce_17,
- 3, 101, :_reduce_18,
- 3, 99, :_reduce_19,
- 2, 99, :_reduce_20,
- 1, 109, :_reduce_21,
- 2, 109, :_reduce_22,
- 1, 110, :_reduce_23,
- 1, 110, :_reduce_24,
- 2, 102, :_reduce_25,
- 1, 102, :_reduce_26,
- 5, 103, :_reduce_27,
- 7, 103, :_reduce_28,
- 5, 103, :_reduce_29,
- 5, 104, :_reduce_30,
- 7, 104, :_reduce_31,
- 9, 104, :_reduce_32,
- 8, 104, :_reduce_33,
- 8, 104, :_reduce_34,
- 7, 104, :_reduce_35,
- 8, 104, :_reduce_36,
- 7, 104, :_reduce_37,
- 7, 104, :_reduce_38,
- 6, 104, :_reduce_39,
- 8, 104, :_reduce_40,
- 7, 104, :_reduce_41,
- 7, 104, :_reduce_42,
- 6, 104, :_reduce_43,
- 3, 105, :_reduce_44,
- 2, 105, :_reduce_45,
- 2, 105, :_reduce_46,
- 3, 105, :_reduce_47,
- 2, 105, :_reduce_48,
- 3, 105, :_reduce_49,
- 3, 95, :_reduce_50,
- 2, 95, :_reduce_51,
- 2, 96, :_reduce_52,
- 1, 96, :_reduce_53,
- 2, 96, :_reduce_54,
- 1, 96, :_reduce_55,
- 2, 96, :_reduce_56,
- 1, 96, :_reduce_57,
- 2, 96, :_reduce_58,
- 1, 96, :_reduce_59,
- 1, 112, :_reduce_60,
- 3, 112, :_reduce_61,
- 1, 117, :_reduce_62,
- 3, 117, :_reduce_63,
- 1, 113, :_reduce_64,
- 1, 113, :_reduce_65,
- 1, 113, :_reduce_66,
- 1, 113, :_reduce_67,
- 1, 113, :_reduce_68,
- 1, 114, :_reduce_69,
- 1, 114, :_reduce_70,
- 1, 114, :_reduce_71,
- 1, 114, :_reduce_72,
- 1, 114, :_reduce_73,
- 1, 114, :_reduce_74,
- 1, 114, :_reduce_75,
- 1, 114, :_reduce_76,
- 1, 114, :_reduce_77,
- 1, 114, :_reduce_78,
- 1, 114, :_reduce_79,
- 1, 114, :_reduce_80,
- 1, 114, :_reduce_81,
- 1, 114, :_reduce_82,
- 1, 114, :_reduce_83,
- 5, 119, :_reduce_84,
- 4, 119, :_reduce_85,
- 2, 119, :_reduce_86,
- 5, 119, :_reduce_87,
- 2, 119, :_reduce_88,
- 1, 121, :_reduce_89,
- 1, 121, :_reduce_90,
- 1, 122, :_reduce_91,
- 2, 122, :_reduce_92,
- 3, 123, :_reduce_93,
- 2, 124, :_reduce_94,
- 1, 124, :_reduce_95,
- 2, 124, :_reduce_96,
- 1, 124, :_reduce_97,
- 1, 125, :_reduce_98,
- 3, 125, :_reduce_99,
- 1, 126, :_reduce_100,
- 3, 126, :_reduce_101,
- 2, 126, :_reduce_102,
- 5, 120, :_reduce_103,
- 4, 120, :_reduce_104,
- 6, 120, :_reduce_105,
- 5, 120, :_reduce_106,
- 2, 120, :_reduce_107,
- 5, 120, :_reduce_108,
- 6, 120, :_reduce_109,
- 2, 120, :_reduce_110,
- 1, 127, :_reduce_111,
- 3, 127, :_reduce_112,
- 1, 128, :_reduce_113,
- 3, 128, :_reduce_114,
- 1, 115, :_reduce_115,
- 1, 115, :_reduce_116,
- 1, 115, :_reduce_117,
- 1, 116, :_reduce_118,
- 2, 97, :_reduce_119,
- 1, 97, :_reduce_120,
- 1, 131, :_reduce_121,
- 3, 131, :_reduce_122,
- 5, 131, :_reduce_123,
- 4, 131, :_reduce_124,
- 4, 131, :_reduce_125,
- 3, 131, :_reduce_126,
- 6, 131, :_reduce_127,
- 5, 131, :_reduce_128,
- 6, 131, :_reduce_129,
- 5, 131, :_reduce_130,
- 4, 131, :_reduce_131,
- 4, 131, :_reduce_132,
- 4, 131, :_reduce_133,
- 3, 131, :_reduce_134,
- 2, 130, :_reduce_135,
- 1, 130, :_reduce_136,
- 3, 130, :_reduce_137,
- 2, 130, :_reduce_138,
- 1, 132, :_reduce_139,
- 2, 132, :_reduce_140,
- 1, 134, :_reduce_141,
- 3, 134, :_reduce_142,
- 1, 136, :_reduce_143,
- 3, 136, :_reduce_144,
- 2, 137, :_reduce_145,
- 2, 137, :_reduce_146,
- 1, 137, :_reduce_147,
- 1, 135, :_reduce_148,
- 3, 135, :_reduce_149,
- 2, 139, :_reduce_150,
- 1, 139, :_reduce_151,
- 1, 138, :_reduce_152,
- 2, 138, :_reduce_153,
- 1, 138, :_reduce_154,
- 3, 140, :_reduce_155,
- 4, 140, :_reduce_156,
- 3, 140, :_reduce_157,
- 3, 140, :_reduce_158,
- 2, 140, :_reduce_159,
- 4, 140, :_reduce_160,
- 3, 140, :_reduce_161,
- 4, 140, :_reduce_162,
- 3, 140, :_reduce_163,
- 3, 140, :_reduce_164,
- 2, 140, :_reduce_165,
- 1, 108, :_reduce_166,
- 1, 118, :_reduce_167,
- 3, 118, :_reduce_168,
- 4, 118, :_reduce_169,
- 2, 141, :_reduce_170,
- 1, 141, :_reduce_171,
- 4, 141, :_reduce_172,
- 3, 141, :_reduce_173,
- 2, 142, :_reduce_174,
- 1, 143, :_reduce_175,
- 2, 143, :_reduce_176,
- 3, 144, :_reduce_177,
- 2, 144, :_reduce_178,
- 1, 145, :_reduce_179,
- 1, 145, :_reduce_180,
- 1, 145, :_reduce_181,
- 3, 145, :_reduce_182,
- 3, 145, :_reduce_183,
- 1, 148, :_reduce_184,
- 4, 148, :_reduce_185,
- 4, 148, :_reduce_186,
- 3, 148, :_reduce_187,
- 3, 148, :_reduce_188,
- 3, 148, :_reduce_189,
- 2, 148, :_reduce_190,
- 2, 148, :_reduce_191,
- 6, 148, :_reduce_192,
- 7, 148, :_reduce_193,
- 1, 149, :_reduce_194,
- 3, 149, :_reduce_195,
- 1, 150, :_reduce_196,
- 1, 150, :_reduce_197,
- 1, 151, :_reduce_198,
- 2, 151, :_reduce_199,
- 2, 151, :_reduce_200,
- 2, 151, :_reduce_201,
- 2, 151, :_reduce_202,
- 4, 151, :_reduce_203,
- 1, 152, :_reduce_204,
- 1, 152, :_reduce_205,
- 1, 152, :_reduce_206,
- 1, 152, :_reduce_207,
- 1, 152, :_reduce_208,
- 1, 152, :_reduce_209,
- 1, 153, :_reduce_210,
- 4, 153, :_reduce_211,
- 1, 154, :_reduce_212,
- 3, 154, :_reduce_213,
- 3, 154, :_reduce_214,
- 3, 154, :_reduce_215,
- 1, 155, :_reduce_216,
- 3, 155, :_reduce_217,
- 3, 155, :_reduce_218,
- 1, 156, :_reduce_219,
- 3, 156, :_reduce_220,
- 3, 156, :_reduce_221,
- 1, 157, :_reduce_222,
- 3, 157, :_reduce_223,
- 3, 157, :_reduce_224,
- 3, 157, :_reduce_225,
- 3, 157, :_reduce_226,
- 1, 158, :_reduce_227,
- 3, 158, :_reduce_228,
- 3, 158, :_reduce_229,
- 1, 159, :_reduce_230,
- 3, 159, :_reduce_231,
- 1, 160, :_reduce_232,
- 3, 160, :_reduce_233,
- 1, 161, :_reduce_234,
- 3, 161, :_reduce_235,
- 1, 162, :_reduce_236,
- 3, 162, :_reduce_237,
- 1, 163, :_reduce_238,
- 3, 163, :_reduce_239,
- 1, 164, :_reduce_240,
- 5, 164, :_reduce_241,
- 1, 133, :_reduce_242,
- 3, 133, :_reduce_243,
- 1, 165, :_reduce_244,
- 1, 165, :_reduce_245,
- 1, 165, :_reduce_246,
- 1, 165, :_reduce_247,
- 1, 165, :_reduce_248,
- 1, 165, :_reduce_249,
- 1, 165, :_reduce_250,
- 1, 165, :_reduce_251,
- 1, 165, :_reduce_252,
- 1, 165, :_reduce_253,
- 1, 165, :_reduce_254,
- 1, 111, :_reduce_255,
- 3, 111, :_reduce_256,
- 1, 107, :_reduce_257,
- 1, 106, :_reduce_258,
- 1, 146, :_reduce_259,
- 1, 146, :_reduce_260,
- 1, 146, :_reduce_261,
- 1, 129, :_reduce_262,
- 2, 147, :_reduce_263,
- 1, 147, :_reduce_264 ]
-
-racc_reduce_n = 265
-
-racc_shift_n = 460
-
-racc_token_table = {
- false => 0,
- :error => 1,
- :COLON => 2,
- :CASE => 3,
- :DEFAULT => 4,
- :LBRACE => 5,
- :RBRACE => 6,
- :SEMICOLON => 7,
- :IF => 8,
- :LPAREN => 9,
- :RPAREN => 10,
- :ELSE => 11,
- :SWITCH => 12,
- :WHILE => 13,
- :DO => 14,
- :FOR => 15,
- :GOTO => 16,
- :CONTINUE => 17,
- :BREAK => 18,
- :RETURN => 19,
- :COMMA => 20,
- :EQ => 21,
- :TYPEDEF => 22,
- :EXTERN => 23,
- :STATIC => 24,
- :AUTO => 25,
- :REGISTER => 26,
- :VOID => 27,
- :CHAR => 28,
- :SHORT => 29,
- :INT => 30,
- :LONG => 31,
- :FLOAT => 32,
- :DOUBLE => 33,
- :SIGNED => 34,
- :UNSIGNED => 35,
- :BOOL => 36,
- :COMPLEX => 37,
- :IMAGINARY => 38,
- :STRUCT => 39,
- :UNION => 40,
- :ENUM => 41,
- :CONST => 42,
- :RESTRICT => 43,
- :VOLATILE => 44,
- :INLINE => 45,
- :LBRACKET => 46,
- :RBRACKET => 47,
- :MUL => 48,
- :ELLIPSIS => 49,
- :TYPENAME => 50,
- :DOT => 51,
- :ARROW => 52,
- :INC => 53,
- :DEC => 54,
- :SIZEOF => 55,
- :AND => 56,
- :ADD => 57,
- :SUB => 58,
- :NOT => 59,
- :BANG => 60,
- :DIV => 61,
- :MOD => 62,
- :LSHIFT => 63,
- :RSHIFT => 64,
- :LT => 65,
- :GT => 66,
- :LEQ => 67,
- :GEQ => 68,
- :EQEQ => 69,
- :NEQ => 70,
- :XOR => 71,
- :OR => 72,
- :ANDAND => 73,
- :OROR => 74,
- :QUESTION => 75,
- :MULEQ => 76,
- :DIVEQ => 77,
- :MODEQ => 78,
- :ADDEQ => 79,
- :SUBEQ => 80,
- :LSHIFTEQ => 81,
- :RSHIFTEQ => 82,
- :ANDEQ => 83,
- :XOREQ => 84,
- :OREQ => 85,
- :ID => 86,
- :ICON => 87,
- :FCON => 88,
- :CCON => 89,
- :SCON => 90 }
-
-racc_nt_base = 91
-
-racc_use_result_var = true
-
-Racc_arg = [
- racc_action_table,
- racc_action_check,
- racc_action_default,
- racc_action_pointer,
- racc_goto_table,
- racc_goto_check,
- racc_goto_default,
- racc_goto_pointer,
- racc_nt_base,
- racc_reduce_table,
- racc_token_table,
- racc_shift_n,
- racc_reduce_n,
- racc_use_result_var ]
-
-Racc_token_to_s_table = [
- "$end",
- "error",
- "COLON",
- "CASE",
- "DEFAULT",
- "LBRACE",
- "RBRACE",
- "SEMICOLON",
- "IF",
- "LPAREN",
- "RPAREN",
- "ELSE",
- "SWITCH",
- "WHILE",
- "DO",
- "FOR",
- "GOTO",
- "CONTINUE",
- "BREAK",
- "RETURN",
- "COMMA",
- "EQ",
- "TYPEDEF",
- "EXTERN",
- "STATIC",
- "AUTO",
- "REGISTER",
- "VOID",
- "CHAR",
- "SHORT",
- "INT",
- "LONG",
- "FLOAT",
- "DOUBLE",
- "SIGNED",
- "UNSIGNED",
- "BOOL",
- "COMPLEX",
- "IMAGINARY",
- "STRUCT",
- "UNION",
- "ENUM",
- "CONST",
- "RESTRICT",
- "VOLATILE",
- "INLINE",
- "LBRACKET",
- "RBRACKET",
- "MUL",
- "ELLIPSIS",
- "TYPENAME",
- "DOT",
- "ARROW",
- "INC",
- "DEC",
- "SIZEOF",
- "AND",
- "ADD",
- "SUB",
- "NOT",
- "BANG",
- "DIV",
- "MOD",
- "LSHIFT",
- "RSHIFT",
- "LT",
- "GT",
- "LEQ",
- "GEQ",
- "EQEQ",
- "NEQ",
- "XOR",
- "OR",
- "ANDAND",
- "OROR",
- "QUESTION",
- "MULEQ",
- "DIVEQ",
- "MODEQ",
- "ADDEQ",
- "SUBEQ",
- "LSHIFTEQ",
- "RSHIFTEQ",
- "ANDEQ",
- "XOREQ",
- "OREQ",
- "ID",
- "ICON",
- "FCON",
- "CCON",
- "SCON",
- "$start",
- "translation_unit",
- "external_declaration",
- "function_definition",
- "declaration",
- "declaration_specifiers",
- "declarator",
- "declaration_list",
- "compound_statement",
- "statement",
- "labeled_statement",
- "expression_statement",
- "selection_statement",
- "iteration_statement",
- "jump_statement",
- "identifier",
- "constant_expression",
- "typedef_name",
- "block_item_list",
- "block_item",
- "expression",
- "init_declarator_list",
- "storage_class_specifier",
- "type_specifier",
- "type_qualifier",
- "function_specifier",
- "init_declarator",
- "initializer",
- "struct_or_union_specifier",
- "enum_specifier",
- "struct_or_union",
- "struct_declaration_list",
- "struct_declaration",
- "specifier_qualifier_list",
- "struct_declarator_list",
- "struct_declarator",
- "enumerator_list",
- "enumerator",
- "enumeration_constant",
- "pointer",
- "direct_declarator",
- "type_qualifier_list",
- "assignment_expression",
- "parameter_type_list",
- "identifier_list",
- "parameter_list",
- "parameter_declaration",
- "abstract_declarator",
- "type_name",
- "direct_abstract_declarator",
- "initializer_list",
- "designation",
- "designator_list",
- "designator",
- "primary_expression",
- "constant",
- "string_literal",
- "postfix_expression",
- "argument_expression_list",
- "argument_expression",
- "unary_expression",
- "unary_operator",
- "cast_expression",
- "multiplicative_expression",
- "additive_expression",
- "shift_expression",
- "relational_expression",
- "equality_expression",
- "and_expression",
- "exclusive_or_expression",
- "inclusive_or_expression",
- "logical_and_expression",
- "logical_or_expression",
- "conditional_expression",
- "assignment_operator" ]
-
-Racc_debug_parser = false
-
-##### State transition tables end #####
-
-# reduce 0 omitted
-
-module_eval(<<'.,.,', 'cast.y', 32)
- def _reduce_1(val, _values, result)
- result = TranslationUnit.new_at(val[0].pos, NodeChain[val[0]])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 33)
- def _reduce_2(val, _values, result)
- result = val[0]; result.entities << val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 37)
- def _reduce_3(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 38)
- def _reduce_4(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 42)
- def _reduce_5(val, _values, result)
- result = make_function_def(val[0][0], val[0][1], val[1], val[2], val[3])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 43)
- def _reduce_6(val, _values, result)
- result = make_function_def(val[0][0], val[0][1], val[1], nil , val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 47)
- def _reduce_7(val, _values, result)
- result = [val[0]]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 48)
- def _reduce_8(val, _values, result)
- result = val[0] << val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 54)
- def _reduce_9(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 55)
- def _reduce_10(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 56)
- def _reduce_11(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 57)
- def _reduce_12(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 58)
- def _reduce_13(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 59)
- def _reduce_14(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 63)
- def _reduce_15(val, _values, result)
- val[2].labels.unshift(PlainLabel.new_at(val[0].pos, val[0].val)); result = val[2]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 64)
- def _reduce_16(val, _values, result)
- val[3].labels.unshift(Case .new_at(val[0].pos, val[1] )); result = val[3]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 65)
- def _reduce_17(val, _values, result)
- val[2].labels.unshift(Default .new_at(val[0].pos )); result = val[2]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 67)
- def _reduce_18(val, _values, result)
- val[2].labels.unshift(PlainLabel.new_at(val[0].pos, val[0].name)); result = val[2]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 71)
- def _reduce_19(val, _values, result)
- result = Block.new_at(val[0].pos, val[1])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 72)
- def _reduce_20(val, _values, result)
- result = Block.new_at(val[0].pos )
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 76)
- def _reduce_21(val, _values, result)
- result = NodeChain[val[0]]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 77)
- def _reduce_22(val, _values, result)
- result = val[0] << val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 81)
- def _reduce_23(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 82)
- def _reduce_24(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 86)
- def _reduce_25(val, _values, result)
- result = ExpressionStatement.new_at(val[0].pos, val[0])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 87)
- def _reduce_26(val, _values, result)
- result = ExpressionStatement.new_at(val[0].pos )
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 91)
- def _reduce_27(val, _values, result)
- result = If .new_at(val[0].pos, val[2], val[4] )
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 92)
- def _reduce_28(val, _values, result)
- result = If .new_at(val[0].pos, val[2], val[4], val[6])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 93)
- def _reduce_29(val, _values, result)
- result = Switch.new_at(val[0].pos, val[2], val[4] )
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 97)
- def _reduce_30(val, _values, result)
- result = While.new_at(val[0].pos, val[2], val[4] )
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 98)
- def _reduce_31(val, _values, result)
- result = While.new_at(val[0].pos, val[4], val[1], :do => true )
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 99)
- def _reduce_32(val, _values, result)
- result = For.new_at(val[0].pos, val[2], val[4], val[6], val[8])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 100)
- def _reduce_33(val, _values, result)
- result = For.new_at(val[0].pos, val[2], val[4], nil , val[7])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 101)
- def _reduce_34(val, _values, result)
- result = For.new_at(val[0].pos, val[2], nil , val[5], val[7])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 102)
- def _reduce_35(val, _values, result)
- result = For.new_at(val[0].pos, val[2], nil , nil , val[6])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 103)
- def _reduce_36(val, _values, result)
- result = For.new_at(val[0].pos, nil , val[3], val[5], val[7])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 104)
- def _reduce_37(val, _values, result)
- result = For.new_at(val[0].pos, nil , val[3], nil , val[6])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 105)
- def _reduce_38(val, _values, result)
- result = For.new_at(val[0].pos, nil , nil , val[4], val[6])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 106)
- def _reduce_39(val, _values, result)
- result = For.new_at(val[0].pos, nil , nil , nil , val[5])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 107)
- def _reduce_40(val, _values, result)
- result = For.new_at(val[0].pos, val[2], val[3], val[5], val[7])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 108)
- def _reduce_41(val, _values, result)
- result = For.new_at(val[0].pos, val[2], val[3], nil , val[6])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 109)
- def _reduce_42(val, _values, result)
- result = For.new_at(val[0].pos, val[2], nil , val[4], val[6])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 110)
- def _reduce_43(val, _values, result)
- result = For.new_at(val[0].pos, val[2], nil , nil , val[5])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 114)
- def _reduce_44(val, _values, result)
- result = Goto .new_at(val[0].pos, val[1].val)
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 115)
- def _reduce_45(val, _values, result)
- result = Continue.new_at(val[0].pos )
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 116)
- def _reduce_46(val, _values, result)
- result = Break .new_at(val[0].pos )
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 117)
- def _reduce_47(val, _values, result)
- result = Return .new_at(val[0].pos, val[1] )
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 118)
- def _reduce_48(val, _values, result)
- result = Return .new_at(val[0].pos )
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 120)
- def _reduce_49(val, _values, result)
- result = Goto .new_at(val[0].pos, val[1].name)
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 126)
- def _reduce_50(val, _values, result)
- result = make_declaration(val[0][0], val[0][1], val[1])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 127)
- def _reduce_51(val, _values, result)
- result = make_declaration(val[0][0], val[0][1], NodeArray[])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 131)
- def _reduce_52(val, _values, result)
- val[1][1] << val[0][1]; result = val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 132)
- def _reduce_53(val, _values, result)
- result = [val[0][0], [val[0][1]]]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 133)
- def _reduce_54(val, _values, result)
- val[1][1] << val[0][1]; result = val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 134)
- def _reduce_55(val, _values, result)
- result = [val[0][0], [val[0][1]]]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 135)
- def _reduce_56(val, _values, result)
- val[1][1] << val[0][1]; result = val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 136)
- def _reduce_57(val, _values, result)
- result = [val[0][0], [val[0][1]]]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 137)
- def _reduce_58(val, _values, result)
- val[1][1] << val[0][1]; result = val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 138)
- def _reduce_59(val, _values, result)
- result = [val[0][0], [val[0][1]]]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 142)
- def _reduce_60(val, _values, result)
- result = NodeArray[val[0]]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 143)
- def _reduce_61(val, _values, result)
- result = val[0] << val[2]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 147)
- def _reduce_62(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 148)
- def _reduce_63(val, _values, result)
- val[0].init = val[2]; result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 152)
- def _reduce_64(val, _values, result)
- result = [val[0].pos, :typedef ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 153)
- def _reduce_65(val, _values, result)
- result = [val[0].pos, :extern ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 154)
- def _reduce_66(val, _values, result)
- result = [val[0].pos, :static ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 155)
- def _reduce_67(val, _values, result)
- result = [val[0].pos, :auto ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 156)
- def _reduce_68(val, _values, result)
- result = [val[0].pos, :register]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 160)
- def _reduce_69(val, _values, result)
- result = [val[0].pos, :void ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 161)
- def _reduce_70(val, _values, result)
- result = [val[0].pos, :char ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 162)
- def _reduce_71(val, _values, result)
- result = [val[0].pos, :short ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 163)
- def _reduce_72(val, _values, result)
- result = [val[0].pos, :int ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 164)
- def _reduce_73(val, _values, result)
- result = [val[0].pos, :long ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 165)
- def _reduce_74(val, _values, result)
- result = [val[0].pos, :float ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 166)
- def _reduce_75(val, _values, result)
- result = [val[0].pos, :double ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 167)
- def _reduce_76(val, _values, result)
- result = [val[0].pos, :signed ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 168)
- def _reduce_77(val, _values, result)
- result = [val[0].pos, :unsigned ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 169)
- def _reduce_78(val, _values, result)
- result = [val[0].pos, :_Bool ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 170)
- def _reduce_79(val, _values, result)
- result = [val[0].pos, :_Complex ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 171)
- def _reduce_80(val, _values, result)
- result = [val[0].pos, :_Imaginary]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 172)
- def _reduce_81(val, _values, result)
- result = [val[0].pos, val[0] ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 173)
- def _reduce_82(val, _values, result)
- result = [val[0].pos, val[0] ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 174)
- def _reduce_83(val, _values, result)
- result = [val[0].pos, val[0] ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 178)
- def _reduce_84(val, _values, result)
- result = val[0][1].new_at(val[0][0], val[1].val, val[3])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 179)
- def _reduce_85(val, _values, result)
- result = val[0][1].new_at(val[0][0], nil , val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 180)
- def _reduce_86(val, _values, result)
- result = val[0][1].new_at(val[0][0], val[1].val, nil )
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 182)
- def _reduce_87(val, _values, result)
- result = val[0][1].new_at(val[0][0], val[1].name, val[3])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 183)
- def _reduce_88(val, _values, result)
- result = val[0][1].new_at(val[0][0], val[1].name, nil )
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 187)
- def _reduce_89(val, _values, result)
- result = [val[0].pos, Struct]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 188)
- def _reduce_90(val, _values, result)
- result = [val[0].pos, Union ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 192)
- def _reduce_91(val, _values, result)
- result = NodeArray[val[0]]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 193)
- def _reduce_92(val, _values, result)
- val[0] << val[1]; result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 197)
- def _reduce_93(val, _values, result)
- result = make_declaration(val[0][0], val[0][1], val[1])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 201)
- def _reduce_94(val, _values, result)
- val[1][1] << val[0][1]; result = val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 202)
- def _reduce_95(val, _values, result)
- result = [val[0][0], [val[0][1]]]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 203)
- def _reduce_96(val, _values, result)
- val[1][1] << val[0][1]; result = val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 204)
- def _reduce_97(val, _values, result)
- result = [val[0][0], [val[0][1]]]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 208)
- def _reduce_98(val, _values, result)
- result = NodeArray[val[0]]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 209)
- def _reduce_99(val, _values, result)
- result = val[0] << val[2]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 213)
- def _reduce_100(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 214)
- def _reduce_101(val, _values, result)
- result = val[0]; val[0].num_bits = val[2]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 215)
- def _reduce_102(val, _values, result)
- result = Declarator.new_at(val[0].pos, :num_bits => val[1])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 219)
- def _reduce_103(val, _values, result)
- result = Enum.new_at(val[0].pos, val[1].val, val[3])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 220)
- def _reduce_104(val, _values, result)
- result = Enum.new_at(val[0].pos, nil , val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 221)
- def _reduce_105(val, _values, result)
- result = Enum.new_at(val[0].pos, val[1].val, val[3])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 222)
- def _reduce_106(val, _values, result)
- result = Enum.new_at(val[0].pos, nil , val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 223)
- def _reduce_107(val, _values, result)
- result = Enum.new_at(val[0].pos, val[1].val, nil )
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 225)
- def _reduce_108(val, _values, result)
- result = Enum.new_at(val[0].pos, val[1].name, val[3])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 226)
- def _reduce_109(val, _values, result)
- result = Enum.new_at(val[0].pos, val[1].name, val[3])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 227)
- def _reduce_110(val, _values, result)
- result = Enum.new_at(val[0].pos, val[1].name, nil )
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 231)
- def _reduce_111(val, _values, result)
- result = NodeArray[val[0]]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 232)
- def _reduce_112(val, _values, result)
- result = val[0] << val[2]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 236)
- def _reduce_113(val, _values, result)
- result = Enumerator.new_at(val[0].pos, val[0].val, nil )
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 237)
- def _reduce_114(val, _values, result)
- result = Enumerator.new_at(val[0].pos, val[0].val, val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 241)
- def _reduce_115(val, _values, result)
- result = [val[0].pos, :const ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 242)
- def _reduce_116(val, _values, result)
- result = [val[0].pos, :restrict]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 243)
- def _reduce_117(val, _values, result)
- result = [val[0].pos, :volatile]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 247)
- def _reduce_118(val, _values, result)
- result = [val[0].pos, :inline]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 251)
- def _reduce_119(val, _values, result)
- result = add_decl_type(val[1], val[0])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 252)
- def _reduce_120(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 256)
- def _reduce_121(val, _values, result)
- result = Declarator.new_at(val[0].pos, nil, val[0].val)
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 257)
- def _reduce_122(val, _values, result)
- result = val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 258)
- def _reduce_123(val, _values, result)
- result = add_decl_type(val[0], Array.new_at(val[0].pos ))
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 259)
- def _reduce_124(val, _values, result)
- result = add_decl_type(val[0], Array.new_at(val[0].pos ))
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 260)
- def _reduce_125(val, _values, result)
- result = add_decl_type(val[0], Array.new_at(val[0].pos, nil, val[2]))
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 261)
- def _reduce_126(val, _values, result)
- result = add_decl_type(val[0], Array.new_at(val[0].pos ))
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 262)
- def _reduce_127(val, _values, result)
- result = add_decl_type(val[0], Array.new_at(val[0].pos ))
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 263)
- def _reduce_128(val, _values, result)
- result = add_decl_type(val[0], Array.new_at(val[0].pos ))
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 264)
- def _reduce_129(val, _values, result)
- result = add_decl_type(val[0], Array.new_at(val[0].pos ))
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 265)
- def _reduce_130(val, _values, result)
- result = add_decl_type(val[0], Array.new_at(val[0].pos ))
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 266)
- def _reduce_131(val, _values, result)
- result = add_decl_type(val[0], Array.new_at(val[0].pos ))
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 267)
- def _reduce_132(val, _values, result)
- result = add_decl_type(val[0], Function.new_at(val[0].pos, nil, param_list(*val[2]), :var_args => val[2][1]))
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 268)
- def _reduce_133(val, _values, result)
- result = add_decl_type(val[0], Function.new_at(val[0].pos, nil, val[2]))
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 269)
- def _reduce_134(val, _values, result)
- result = add_decl_type(val[0], Function.new_at(val[0].pos ))
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 273)
- def _reduce_135(val, _values, result)
- result = add_type_quals(Pointer.new_at(val[0].pos), val[1][1])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 274)
- def _reduce_136(val, _values, result)
- result = Pointer.new_at(val[0].pos)
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 275)
- def _reduce_137(val, _values, result)
- p = add_type_quals(Pointer.new_at(val[0].pos), val[1][1]); val[2].direct_type = p; result = val[2]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 276)
- def _reduce_138(val, _values, result)
- p = Pointer.new_at(val[0].pos) ; val[1].direct_type = p; result = val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 280)
- def _reduce_139(val, _values, result)
- result = [val[0][0], [val[0][1]]]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 281)
- def _reduce_140(val, _values, result)
- val[0][1] << val[1][1]; result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 285)
- def _reduce_141(val, _values, result)
- result = [val[0], false]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 286)
- def _reduce_142(val, _values, result)
- result = [val[0], true ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 290)
- def _reduce_143(val, _values, result)
- result = NodeArray[val[0]]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 291)
- def _reduce_144(val, _values, result)
- result = val[0] << val[2]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 295)
- def _reduce_145(val, _values, result)
- ind_type = val[1].indirect_type and ind_type.detach
- result = make_parameter(val[0][0], val[0][1], ind_type, val[1].name)
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 297)
- def _reduce_146(val, _values, result)
- result = make_parameter(val[0][0], val[0][1], val[1] , nil )
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 298)
- def _reduce_147(val, _values, result)
- result = make_parameter(val[0][0], val[0][1], nil , nil )
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 302)
- def _reduce_148(val, _values, result)
- result = NodeArray[Parameter.new_at(val[0].pos, nil, val[0].val)]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 303)
- def _reduce_149(val, _values, result)
- result = val[0] << Parameter.new_at(val[2].pos, nil, val[2].val)
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 307)
- def _reduce_150(val, _values, result)
- val[1].direct_type = make_direct_type(val[0][0], val[0][1]); result = val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 308)
- def _reduce_151(val, _values, result)
- result = make_direct_type(val[0][0], val[0][1])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 312)
- def _reduce_152(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 313)
- def _reduce_153(val, _values, result)
- val[1].direct_type = val[0]; result = val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 314)
- def _reduce_154(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 318)
- def _reduce_155(val, _values, result)
- result = val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 319)
- def _reduce_156(val, _values, result)
- val[0].direct_type = Array.new_at(val[0].pos, nil, val[2]); result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 320)
- def _reduce_157(val, _values, result)
- val[0].direct_type = Array.new_at(val[0].pos, nil, nil ); result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 321)
- def _reduce_158(val, _values, result)
- result = Array.new_at(val[0].pos, nil, val[1])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 322)
- def _reduce_159(val, _values, result)
- result = Array.new_at(val[0].pos )
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 323)
- def _reduce_160(val, _values, result)
- val[0].direct_type = Array.new_at(val[0].pos); result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 324)
- def _reduce_161(val, _values, result)
- result = Array.new_at(val[0].pos)
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 325)
- def _reduce_162(val, _values, result)
- val[0].direct_type = Function.new_at(val[0].pos, nil, param_list(*val[2]), val[2][1]); result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 326)
- def _reduce_163(val, _values, result)
- val[0].direct_type = Function.new_at(val[0].pos ); result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 327)
- def _reduce_164(val, _values, result)
- result = Function.new_at(val[0].pos, nil, param_list(*val[1]), val[1][1])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 328)
- def _reduce_165(val, _values, result)
- result = Function.new_at(val[0].pos )
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 334)
- def _reduce_166(val, _values, result)
- result = CustomType.new_at(val[0].pos, val[0].val)
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 338)
- def _reduce_167(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 339)
- def _reduce_168(val, _values, result)
- result = CompoundLiteral.new_at(val[0].pos, nil, val[1])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 340)
- def _reduce_169(val, _values, result)
- result = CompoundLiteral.new_at(val[0].pos, nil, val[1])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 344)
- def _reduce_170(val, _values, result)
- result = NodeArray[MemberInit.new_at(val[0][0] , val[0][1], val[1])]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 345)
- def _reduce_171(val, _values, result)
- result = NodeArray[MemberInit.new_at(val[0].pos, nil , val[0])]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 346)
- def _reduce_172(val, _values, result)
- result = val[0] << MemberInit.new_at(val[2][0] , val[2][1], val[3])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 347)
- def _reduce_173(val, _values, result)
- result = val[0] << MemberInit.new_at(val[2].pos, nil , val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 351)
- def _reduce_174(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 355)
- def _reduce_175(val, _values, result)
- result = val[0]; val[0][1] = NodeArray[val[0][1]]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 356)
- def _reduce_176(val, _values, result)
- result = val[0]; val[0][1] << val[1][1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 360)
- def _reduce_177(val, _values, result)
- result = [val[1].pos, val[1] ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 361)
- def _reduce_178(val, _values, result)
- result = [val[1].pos, Member.new_at(val[1].pos, val[1].val)]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 367)
- def _reduce_179(val, _values, result)
- result = Variable.new_at(val[0].pos, val[0].val)
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 368)
- def _reduce_180(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 369)
- def _reduce_181(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 371)
- def _reduce_182(val, _values, result)
- result = val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 372)
- def _reduce_183(val, _values, result)
- block_expressions_enabled? or parse_error val[0].pos, "compound statement found where expression expected"
- result = BlockExpression.new(val[1]); result.pos = val[0].pos
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 377)
- def _reduce_184(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 378)
- def _reduce_185(val, _values, result)
- result = Index .new_at(val[0].pos, val[0], val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 379)
- def _reduce_186(val, _values, result)
- result = Call .new_at(val[0].pos, val[0], val[2] )
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 380)
- def _reduce_187(val, _values, result)
- result = Call .new_at(val[0].pos, val[0], NodeArray[])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 381)
- def _reduce_188(val, _values, result)
- result = Dot .new_at(val[0].pos, val[0], Member.new(val[2].val))
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 382)
- def _reduce_189(val, _values, result)
- result = Arrow .new_at(val[0].pos, val[0], Member.new(val[2].val))
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 383)
- def _reduce_190(val, _values, result)
- result = PostInc .new_at(val[0].pos, val[0] )
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 384)
- def _reduce_191(val, _values, result)
- result = PostDec .new_at(val[0].pos, val[0] )
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 385)
- def _reduce_192(val, _values, result)
- result = CompoundLiteral.new_at(val[0].pos, val[1], val[4])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 386)
- def _reduce_193(val, _values, result)
- result = CompoundLiteral.new_at(val[0].pos, val[1], val[4])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 390)
- def _reduce_194(val, _values, result)
- result = NodeArray[val[0]]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 391)
- def _reduce_195(val, _values, result)
- result = val[0] << val[2]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 395)
- def _reduce_196(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 396)
- def _reduce_197(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 400)
- def _reduce_198(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 401)
- def _reduce_199(val, _values, result)
- result = PreInc.new_at(val[0].pos, val[1])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 402)
- def _reduce_200(val, _values, result)
- result = PreDec.new_at(val[0].pos, val[1])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 403)
- def _reduce_201(val, _values, result)
- result = val[0][0].new_at(val[0][1], val[1])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 404)
- def _reduce_202(val, _values, result)
- result = Sizeof.new_at(val[0].pos, val[1])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 405)
- def _reduce_203(val, _values, result)
- result = Sizeof.new_at(val[0].pos, val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 409)
- def _reduce_204(val, _values, result)
- result = [Address , val[0].pos]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 410)
- def _reduce_205(val, _values, result)
- result = [Dereference, val[0].pos]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 411)
- def _reduce_206(val, _values, result)
- result = [Positive , val[0].pos]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 412)
- def _reduce_207(val, _values, result)
- result = [Negative , val[0].pos]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 413)
- def _reduce_208(val, _values, result)
- result = [BitNot , val[0].pos]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 414)
- def _reduce_209(val, _values, result)
- result = [Not , val[0].pos]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 418)
- def _reduce_210(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 419)
- def _reduce_211(val, _values, result)
- result = Cast.new_at(val[0].pos, val[1], val[3])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 423)
- def _reduce_212(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 424)
- def _reduce_213(val, _values, result)
- result = Multiply.new_at(val[0].pos, val[0], val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 425)
- def _reduce_214(val, _values, result)
- result = Divide .new_at(val[0].pos, val[0], val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 426)
- def _reduce_215(val, _values, result)
- result = Mod .new_at(val[0].pos, val[0], val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 430)
- def _reduce_216(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 431)
- def _reduce_217(val, _values, result)
- result = Add .new_at(val[0].pos, val[0], val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 432)
- def _reduce_218(val, _values, result)
- result = Subtract.new_at(val[0].pos, val[0], val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 436)
- def _reduce_219(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 437)
- def _reduce_220(val, _values, result)
- result = ShiftLeft .new_at(val[0].pos, val[0], val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 438)
- def _reduce_221(val, _values, result)
- result = ShiftRight.new_at(val[0].pos, val[0], val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 442)
- def _reduce_222(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 443)
- def _reduce_223(val, _values, result)
- result = Less.new_at(val[0].pos, val[0], val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 444)
- def _reduce_224(val, _values, result)
- result = More.new_at(val[0].pos, val[0], val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 445)
- def _reduce_225(val, _values, result)
- result = LessOrEqual.new_at(val[0].pos, val[0], val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 446)
- def _reduce_226(val, _values, result)
- result = MoreOrEqual.new_at(val[0].pos, val[0], val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 450)
- def _reduce_227(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 451)
- def _reduce_228(val, _values, result)
- result = Equal .new_at(val[0].pos, val[0], val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 452)
- def _reduce_229(val, _values, result)
- result = NotEqual.new_at(val[0].pos, val[0], val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 456)
- def _reduce_230(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 457)
- def _reduce_231(val, _values, result)
- result = BitAnd.new_at(val[0].pos, val[0], val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 461)
- def _reduce_232(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 462)
- def _reduce_233(val, _values, result)
- result = BitXor.new_at(val[0].pos, val[0], val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 466)
- def _reduce_234(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 467)
- def _reduce_235(val, _values, result)
- result = BitOr.new_at(val[0].pos, val[0], val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 471)
- def _reduce_236(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 472)
- def _reduce_237(val, _values, result)
- result = And.new_at(val[0].pos, val[0], val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 476)
- def _reduce_238(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 477)
- def _reduce_239(val, _values, result)
- result = Or.new_at(val[0].pos, val[0], val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 481)
- def _reduce_240(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 482)
- def _reduce_241(val, _values, result)
- result = Conditional.new_at(val[0].pos, val[0], val[2], val[4])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 486)
- def _reduce_242(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 487)
- def _reduce_243(val, _values, result)
- result = val[1].new_at(val[0].pos, val[0], val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 491)
- def _reduce_244(val, _values, result)
- result = Assign
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 492)
- def _reduce_245(val, _values, result)
- result = MultiplyAssign
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 493)
- def _reduce_246(val, _values, result)
- result = DivideAssign
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 494)
- def _reduce_247(val, _values, result)
- result = ModAssign
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 495)
- def _reduce_248(val, _values, result)
- result = AddAssign
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 496)
- def _reduce_249(val, _values, result)
- result = SubtractAssign
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 497)
- def _reduce_250(val, _values, result)
- result = ShiftLeftAssign
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 498)
- def _reduce_251(val, _values, result)
- result = ShiftRightAssign
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 499)
- def _reduce_252(val, _values, result)
- result = BitAndAssign
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 500)
- def _reduce_253(val, _values, result)
- result = BitXorAssign
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 501)
- def _reduce_254(val, _values, result)
- result = BitOrAssign
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 505)
- def _reduce_255(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 507)
- def _reduce_256(val, _values, result)
- if val[0].is_a? Comma
- if val[2].is_a? Comma
- val[0].exprs.push(*val[2].exprs)
- else
- val[0].exprs << val[2]
- end
- result = val[0]
- else
- if val[2].is_a? Comma
- val[2].exprs.unshift(val[0])
- val[2].pos = val[0].pos
- result = val[2]
- else
- result = Comma.new_at(val[0].pos, NodeArray[val[0], val[2]])
- end
- end
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 527)
- def _reduce_257(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 542)
- def _reduce_258(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 546)
- def _reduce_259(val, _values, result)
- result = val[0].val; result.pos = val[0].pos
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 547)
- def _reduce_260(val, _values, result)
- result = val[0].val; result.pos = val[0].pos
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 550)
- def _reduce_261(val, _values, result)
- result = val[0].val; result.pos = val[0].pos
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 554)
- def _reduce_262(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 559)
- def _reduce_263(val, _values, result)
- val[0].val << val[1].val.val; result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'cast.y', 560)
- def _reduce_264(val, _values, result)
- result = val[0].val; result.pos = val[0].pos
- result
- end
-.,.,
-
-def _reduce_none(val, _values, result)
- val[0]
-end
-
- end # class Parser
-end # module C
diff --git a/test/racc/regress/csspool b/test/racc/regress/csspool
deleted file mode 100644
index a3d14a9b34..0000000000
--- a/test/racc/regress/csspool
+++ /dev/null
@@ -1,2314 +0,0 @@
-#
-# DO NOT MODIFY!!!!
-# This file is automatically generated by Racc 1.5.0
-# from Racc grammar file "".
-#
-
-require 'racc/parser.rb'
-module CSSPool
- module CSS
- class Parser < Racc::Parser
-
-module_eval(<<'...end csspool.y/module_eval...', 'csspool.y', 670)
-
-def numeric thing
- thing = thing.gsub(/[^\d.]/, '')
- Integer(thing) rescue Float(thing)
-end
-
-def interpret_identifier s
- interpret_escapes s
-end
-
-def interpret_uri s
- interpret_escapes s.match(/^url\((.*)\)$/mui)[1].strip.match(/^(['"]?)((?:\\.|.)*)\1$/mu)[2]
-end
-
-def interpret_string_no_quote s
- interpret_escapes s.match(/^(.*)\)$/mu)[1].strip.match(/^(['"]?)((?:\\.|.)*)\1$/mu)[2]
-end
-
-def interpret_string s
- interpret_escapes s.match(/^(['"])((?:\\.|.)*)\1$/mu)[2]
-end
-
-def interpret_escapes s
- token_exp = /\\(?:([0-9a-fA-F]{1,6}(?:\r\n|\s)?)|(.))/mu
- return s.gsub(token_exp) do |escape_sequence|
- if !$1.nil?
- code = $1.chomp.to_i 16
- code = 0xFFFD if code > 0x10FFFF
- next [code].pack('U')
- end
- next '' if $2 == "\n"
- next $2
- end
-end
-
-# override racc's on_error so we can have context in our error messages
-def on_error(t, val, vstack)
- errcontext = (@ss.pre_match[-10..-1] || @ss.pre_match) +
- @ss.matched + @ss.post_match[0..9]
- line_number = @ss.pre_match.lines.count
- raise ParseError, sprintf("parse error on value %s (%s) " +
- "on line %s around \"%s\"",
- val.inspect, token_to_str(t) || '?',
- line_number, errcontext)
-end
-
-def before_pos(val)
- # don't include leading whitespace
- return current_pos - val.last.length + val.last[/\A\s*/].size
-end
-
-def after_pos(val)
- # don't include trailing whitespace
- return current_pos - val.last[/\s*\z/].size
-end
-
-# charpos will work with multibyte strings but is not available until ruby 2
-def current_pos
- @ss.respond_to?('charpos') ? @ss.charpos : @ss.pos
-end
-...end csspool.y/module_eval...
-##### State transition tables begin ###
-
-racc_action_table = [
- 9, 10, 137, 129, 37, 31, 55, 139, 130, 39,
- 45, 47, 45, 47, 123, 9, 10, 103, 3, 37,
- 31, 98, 229, 103, 39, 45, 47, 230, 124, 125,
- 224, 20, 113, 56, 37, 31, 23, 114, 104, 39,
- 45, 47, 245, 27, 104, 11, 20, 126, 48, 25,
- 48, 23, 242, 29, 138, 244, 38, 46, 27, 46,
- 11, 108, 113, 48, 25, 9, 10, 114, 29, 37,
- 31, 38, 46, 223, 39, 45, 47, 49, 48, 115,
- 9, 10, 108, 113, 37, 31, 38, 46, 114, 39,
- 45, 47, 55, 339, 243, 155, 20, 108, 113, 37,
- 31, 23, 107, 114, 39, 45, 47, 231, 27, 115,
- 11, 20, 232, 48, 25, 55, 23, 59, 29, 56,
- 344, 38, 46, 27, 340, 11, 20, 53, 48, 25,
- 115, 23, 345, 29, 37, 31, 38, 46, 27, 39,
- 45, 47, 56, 48, 25, 115, -28, 105, 29, 37,
- 31, 38, 46, 116, 39, 45, 47, 250, 75, 120,
- 251, 20, 108, 113, 37, 31, 23, 118, 114, 39,
- 45, 47, 121, 27, 74, 73, 20, 313, 48, 25,
- 314, 23, 128, 29, 108, 113, 38, 46, 27, 215,
- 114, 20, 131, 48, 25, 75, 23, 136, 29, 37,
- 64, 38, 46, 27, 39, 45, 47, 92, 48, 25,
- 115, 74, 73, 29, 37, 31, 38, 46, 77, 39,
- 45, 47, 148, 94, 103, 156, 20, -89, 83, 37,
- 31, 23, 115, 87, 39, 45, 47, 160, 27, 85,
- 153, 20, 151, 48, 25, 104, 23, 84, 29, 157,
- 158, 38, 46, 27, 163, 252, 20, 151, 48, 25,
- 201, 23, 164, 29, 37, 31, 38, 46, 27, 39,
- 45, 47, 203, 48, 25, 188, 202, 59, 29, 37,
- 165, 38, 46, 187, 39, 45, 47, 201, 204, 166,
- 184, 83, 288, 198, 287, 190, 197, 192, 191, 193,
- 194, 195, 85, 202, 37, 45, 47, 37, 48, 39,
- 45, 47, 39, 45, 47, 167, 38, 46, 168, 83,
- 170, 113, 210, 48, 181, 186, 114, 185, 196, 37,
- 85, 38, 46, 92, 39, 45, 47, 203, 84, 150,
- 152, 151, 289, 48, 290, 292, 163, 291, 48, 94,
- -33, 48, 46, 204, 169, 199, 38, 46, 37, 38,
- 46, 200, -33, 39, 45, 47, 92, 188, 115, 59,
- 294, 258, 293, 48, 296, 187, 295, 298, 260, 297,
- 212, 38, 46, 83, 216, 198, 259, 190, 197, 192,
- 191, 193, 194, 195, 85, 45, 47, 45, 47, 45,
- 47, 217, 48, 218, 219, 188, 108, 59, 285, 108,
- 38, 46, 170, 187, 225, 226, 181, 186, 233, 185,
- 196, 83, 129, 198, 234, 190, 197, 192, 191, 193,
- 194, 195, 85, 48, 163, 48, 255, 48, 256, 155,
- 263, 169, 46, 188, 46, 59, 46, 264, 168, 265,
- 170, 187, 266, 92, 181, 186, 92, 185, 196, 83,
- 92, 198, 92, 190, 197, 192, 191, 193, 194, 195,
- 85, 198, 278, 190, 197, 192, 191, 193, 194, 195,
- 279, 188, 281, 59, 241, 235, 236, 237, 170, 187,
- 286, 229, 181, 186, 231, 185, 196, 83, 163, 198,
- 300, 190, 197, 192, 191, 193, 194, 195, 85, 301,
- 302, 238, 239, 240, 303, 306, 307, 255, 141, 188,
- 75, 59, 322, 163, 185, 168, 170, 187, 312, 317,
- 181, 186, 143, 185, 196, 83, 319, 198, 323, 190,
- 197, 192, 191, 193, 194, 195, 85, 324, 325, 145,
- 326, 327, 328, 329, 330, 331, 144, 188, 146, 59,
- 147, 332, 142, 333, 170, 187, 334, 306, 181, 186,
- 163, 185, 196, 83, 338, 198, 163, 190, 197, 192,
- 191, 193, 194, 195, 85, 346, 319, 319, 163, 351,
- 306, 163, 319, 357, 359, 188, nil, 59, nil, nil,
- nil, nil, 170, 187, nil, nil, 181, 186, nil, 185,
- 196, 83, nil, 198, nil, 190, 197, 192, 191, 193,
- 194, 195, 85, 272, nil, 83, nil, 198, nil, 190,
- 197, 192, 191, 193, 194, 195, nil, nil, nil, nil,
- 170, nil, nil, nil, 181, 186, nil, 185, 196, 272,
- nil, 83, nil, 198, nil, 190, 197, 192, 191, 193,
- 194, 195, 272, nil, 83, nil, 198, nil, 190, 197,
- 192, 191, 193, 194, 195, 272, nil, 83, nil, 198,
- nil, 190, 197, 192, 191, 193, 194, 195, 272, nil,
- 83, nil, 198, nil, 190, 197, 192, 191, 193, 194,
- 195, 272, nil, 83, nil, 198, nil, 190, 197, 192,
- 191, 193, 194, 195 ]
-
-racc_action_check = [
- 2, 2, 47, 38, 2, 2, 10, 47, 38, 2,
- 2, 2, 35, 35, 34, 5, 5, 26, 1, 5,
- 5, 26, 128, 217, 5, 5, 5, 128, 34, 34,
- 112, 2, 210, 10, 31, 31, 2, 210, 26, 31,
- 31, 31, 143, 2, 217, 2, 5, 34, 2, 2,
- 35, 5, 142, 2, 47, 143, 2, 2, 5, 35,
- 5, 110, 110, 5, 5, 6, 6, 110, 5, 6,
- 6, 5, 5, 112, 6, 6, 6, 3, 31, 210,
- 7, 7, 221, 221, 7, 7, 31, 31, 221, 7,
- 7, 7, 58, 309, 142, 58, 6, 28, 28, 12,
- 12, 6, 28, 28, 12, 12, 12, 131, 6, 110,
- 6, 7, 131, 6, 6, 11, 7, 11, 6, 58,
- 315, 6, 6, 7, 309, 7, 12, 9, 7, 7,
- 221, 12, 315, 7, 13, 13, 7, 7, 12, 13,
- 13, 13, 11, 12, 12, 28, 20, 27, 12, 14,
- 14, 12, 12, 29, 14, 14, 14, 149, 20, 32,
- 149, 13, 30, 30, 15, 15, 13, 30, 30, 15,
- 15, 15, 33, 13, 20, 20, 14, 269, 13, 13,
- 269, 14, 37, 13, 100, 100, 13, 13, 14, 100,
- 100, 15, 39, 14, 14, 157, 15, 46, 14, 19,
- 19, 14, 14, 15, 19, 19, 19, 25, 15, 15,
- 30, 157, 157, 15, 21, 21, 15, 15, 21, 21,
- 21, 21, 53, 25, 99, 67, 19, 99, 22, 24,
- 24, 19, 100, 24, 24, 24, 24, 71, 19, 22,
- 57, 21, 57, 19, 19, 99, 21, 22, 19, 70,
- 70, 19, 19, 21, 75, 154, 24, 154, 21, 21,
- 90, 24, 76, 21, 64, 64, 21, 21, 24, 64,
- 64, 64, 91, 24, 24, 83, 90, 83, 24, 121,
- 78, 24, 24, 83, 121, 121, 121, 206, 91, 79,
- 83, 83, 235, 83, 235, 83, 83, 83, 83, 83,
- 83, 83, 83, 206, 122, 41, 41, 144, 64, 122,
- 122, 122, 144, 144, 144, 80, 64, 64, 81, 166,
- 83, 92, 92, 121, 83, 83, 92, 83, 83, 146,
- 166, 121, 121, 92, 146, 146, 146, 207, 166, 54,
- 54, 54, 236, 41, 236, 237, 270, 237, 122, 92,
- 270, 144, 41, 207, 82, 86, 122, 122, 302, 144,
- 144, 88, 270, 302, 302, 302, 94, 171, 92, 171,
- 238, 171, 238, 146, 239, 171, 239, 240, 171, 240,
- 97, 146, 146, 171, 101, 171, 171, 171, 171, 171,
- 171, 171, 171, 171, 171, 42, 42, 43, 43, 44,
- 44, 102, 302, 105, 106, 223, 108, 223, 223, 109,
- 302, 302, 171, 223, 114, 117, 171, 171, 137, 171,
- 171, 223, 138, 223, 139, 223, 223, 223, 223, 223,
- 223, 223, 223, 42, 147, 43, 161, 44, 162, 172,
- 175, 176, 42, 261, 43, 261, 44, 177, 179, 183,
- 223, 261, 185, 201, 223, 223, 202, 223, 223, 261,
- 203, 261, 204, 261, 261, 261, 261, 261, 261, 261,
- 261, 189, 208, 189, 189, 189, 189, 189, 189, 189,
- 209, 285, 214, 285, 140, 140, 140, 140, 261, 285,
- 224, 233, 261, 261, 234, 261, 261, 285, 243, 285,
- 245, 285, 285, 285, 285, 285, 285, 285, 285, 246,
- 247, 140, 140, 140, 248, 249, 251, 254, 48, 286,
- 255, 286, 286, 256, 266, 267, 285, 286, 268, 280,
- 285, 285, 48, 285, 285, 286, 284, 286, 287, 286,
- 286, 286, 286, 286, 286, 286, 286, 288, 289, 48,
- 290, 291, 292, 293, 294, 295, 48, 322, 48, 322,
- 48, 296, 48, 297, 286, 322, 298, 299, 286, 286,
- 304, 286, 286, 322, 306, 322, 312, 322, 322, 322,
- 322, 322, 322, 322, 322, 316, 320, 321, 335, 337,
- 338, 340, 349, 350, 358, 353, nil, 353, nil, nil,
- nil, nil, 322, 353, nil, nil, 322, 322, nil, 322,
- 322, 353, nil, 353, nil, 353, 353, 353, 353, 353,
- 353, 353, 353, 186, nil, 186, nil, 186, nil, 186,
- 186, 186, 186, 186, 186, 186, nil, nil, nil, nil,
- 353, nil, nil, nil, 353, 353, nil, 353, 353, 272,
- nil, 272, nil, 272, nil, 272, 272, 272, 272, 272,
- 272, 272, 313, nil, 313, nil, 313, nil, 313, 313,
- 313, 313, 313, 313, 313, 314, nil, 314, nil, 314,
- nil, 314, 314, 314, 314, 314, 314, 314, 344, nil,
- 344, nil, 344, nil, 344, 344, 344, 344, 344, 344,
- 344, 345, nil, 345, nil, 345, nil, 345, 345, 345,
- 345, 345, 345, 345 ]
-
-racc_action_pointer = [
- nil, 18, -2, 77, nil, 13, 63, 78, nil, 123,
- 2, 111, 93, 128, 143, 158, nil, nil, nil, 193,
- 140, 208, 208, nil, 223, 189, 11, 141, 92, 144,
- 157, 28, 150, 164, 7, 0, nil, 124, -3, 134,
- nil, 293, 383, 385, 387, nil, 191, -4, 512, nil,
- nil, nil, nil, 217, 334, nil, nil, 235, 88, nil,
- nil, nil, nil, nil, 258, nil, nil, 215, nil, nil,
- 241, 231, nil, nil, nil, 247, 252, nil, 271, 281,
- 308, 311, 347, 271, nil, nil, 345, nil, 352, nil,
- 224, 236, 315, nil, 348, nil, nil, 370, nil, 218,
- 179, 375, 393, nil, nil, 394, 394, nil, 401, 404,
- 56, nil, 23, nil, 408, nil, nil, 405, nil, nil,
- nil, 273, 298, nil, nil, nil, nil, nil, 16, nil,
- nil, 101, nil, nil, nil, nil, nil, 360, 416, 366,
- 470, nil, 46, 36, 301, nil, 323, 427, nil, 152,
- nil, nil, nil, nil, 250, nil, nil, 177, nil, nil,
- nil, 400, 432, nil, nil, nil, 299, nil, nil, nil,
- nil, 363, 432, nil, nil, 433, 434, 440, nil, 441,
- nil, nil, nil, 430, nil, 444, 605, nil, nil, 449,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 435, 438, 442, 444, nil, 251, 301, 453, 461,
- 26, nil, nil, nil, 472, nil, nil, 17, nil, nil,
- nil, 77, nil, 401, 440, nil, nil, nil, nil, nil,
- nil, nil, nil, 485, 488, 288, 338, 341, 366, 370,
- 373, nil, nil, 491, nil, 481, 490, 502, 495, 509,
- nil, 510, nil, nil, 481, 502, 516, nil, nil, nil,
- nil, 439, nil, nil, nil, nil, 468, 518, 509, 155,
- 339, nil, 631, nil, nil, nil, nil, nil, nil, nil,
- 510, nil, nil, nil, 504, 477, 515, 524, 533, 534,
- 536, 537, 538, 539, 540, 541, 547, 549, 552, 561,
- nil, nil, 352, nil, 563, nil, 566, nil, nil, 74,
- nil, nil, 569, 644, 657, 109, 566, nil, nil, nil,
- 554, 555, 553, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 581, nil, 570, 584, nil,
- 584, nil, nil, nil, 670, 683, nil, nil, nil, 560,
- 574, nil, nil, 591, nil, nil, nil, nil, 575, nil ]
-
-racc_action_default = [
- -1, -229, -10, -229, -2, -6, -7, -8, -9, -229,
- -229, -229, -41, -42, -43, -44, -45, -46, -47, -33,
- -23, -229, -229, -55, -229, -229, -89, -229, -229, -229,
- -229, -229, -229, -103, -105, -111, -112, -115, -229, -120,
- -119, -124, -125, -126, -127, -132, -229, -229, -229, 360,
- -3, -4, -5, -229, -229, -15, -16, -229, -229, -228,
- -37, -38, -39, -40, -32, -48, -49, -229, -99, -21,
- -229, -229, -35, -26, -27, -33, -229, -53, -229, -57,
- -58, -59, -60, -229, -198, -214, -229, -62, -229, -64,
- -65, -66, -229, -71, -229, -73, -74, -229, -82, -85,
- -229, -229, -91, -92, -93, -229, -229, -95, -160, -165,
- -166, -167, -229, -174, -229, -176, -96, -229, -98, -100,
- -101, -229, -229, -106, -107, -108, -109, -110, -229, -117,
- -121, -229, -128, -129, -130, -131, -133, -115, -229, -229,
- -229, -147, -229, -229, -229, -152, -229, -33, -11, -229,
- -13, -14, -20, -18, -229, -227, -50, -28, -51, -35,
- -29, -25, -229, -32, -52, -54, -229, -197, -194, -213,
- -36, -182, -183, -184, -185, -186, -187, -188, -189, -190,
- -191, -192, -193, -229, -196, -200, -229, -212, -216, -229,
- -218, -219, -220, -221, -222, -223, -224, -225, -226, -61,
- -63, -229, -229, -229, -229, -67, -68, -69, -229, -229,
- -229, -72, -81, -84, -229, -87, -88, -89, -83, -94,
- -161, -164, -163, -229, -229, -175, -97, -102, -104, -116,
- -123, -118, -122, -229, -229, -229, -229, -229, -229, -229,
- -229, -146, -148, -33, -149, -229, -229, -114, -229, -156,
- -12, -229, -17, -22, -24, -229, -33, -56, -177, -178,
- -179, -229, -181, -215, -211, -195, -229, -209, -229, -202,
- -205, -208, -229, -217, -76, -78, -75, -77, -70, -79,
- -229, -86, -90, -162, -173, -229, -229, -229, -229, -229,
- -229, -229, -229, -229, -229, -229, -229, -229, -229, -156,
- -150, -151, -229, -153, -33, -157, -158, -19, -34, -229,
- -180, -199, -33, -229, -229, -229, -229, -80, -168, -172,
- -173, -173, -229, -134, -135, -136, -137, -138, -139, -140,
- -141, -142, -143, -144, -145, -33, -113, -229, -229, -30,
- -33, -201, -203, -204, -229, -229, -210, -169, -170, -173,
- -229, -154, -159, -229, -206, -207, -171, -155, -229, -31 ]
-
-racc_goto_table = [
- 81, 248, 183, 68, 106, 91, 117, 271, 78, 246,
- 273, 247, 82, 69, 209, 161, 97, 89, 268, 304,
- 90, 119, 54, 57, 220, 221, 318, 60, 61, 62,
- 63, 354, 355, 1, 65, 127, 76, 2, 149, 86,
- 58, 132, 133, 134, 135, 4, 70, 159, 50, 51,
- 52, 308, 67, 66, 119, 88, 208, 282, 227, 162,
- 228, 122, 347, 348, 140, 352, 261, 311, nil, 335,
- 154, nil, 207, nil, 211, nil, 214, nil, nil, nil,
- nil, nil, nil, nil, 205, nil, 222, 206, nil, 213,
- 262, 356, nil, 271, nil, nil, nil, nil, nil, nil,
- nil, nil, 254, nil, 316, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 249, 280, nil, 271, 271, nil, nil, nil, nil,
- nil, nil, 284, nil, 81, 342, 343, nil, nil, nil,
- 253, nil, 257, nil, nil, nil, 82, 336, nil, nil,
- nil, nil, nil, nil, 267, 271, 271, 247, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 310, 274, 275, 276, 277, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 283, nil, nil,
- nil, nil, nil, nil, 320, 321, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 299, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 309, 349, nil, nil, nil, nil, nil, nil, nil, nil,
- 267, nil, nil, nil, 315, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 358, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 337, nil,
- nil, 267, 267, nil, nil, nil, 341, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 350,
- nil, nil, 267, 267, 353 ]
-
-racc_goto_check = [
- 35, 62, 18, 17, 51, 41, 51, 77, 32, 58,
- 77, 58, 36, 12, 46, 15, 48, 39, 82, 68,
- 40, 55, 8, 8, 70, 70, 73, 7, 7, 7,
- 7, 84, 84, 1, 7, 61, 7, 3, 9, 7,
- 10, 61, 61, 61, 61, 2, 11, 14, 2, 2,
- 2, 16, 27, 28, 55, 38, 42, 52, 56, 17,
- 57, 59, 73, 73, 63, 69, 74, 81, nil, 68,
- 8, nil, 41, nil, 41, nil, 51, nil, nil, nil,
- nil, nil, nil, nil, 39, nil, 51, 40, nil, 48,
- 18, 73, nil, 77, nil, nil, nil, nil, nil, nil,
- nil, nil, 15, nil, 82, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 17, 46, nil, 77, 77, nil, nil, nil, nil,
- nil, nil, 18, nil, 35, 82, 82, nil, nil, nil,
- 12, nil, 32, nil, nil, nil, 36, 62, nil, nil,
- nil, nil, nil, nil, 35, 77, 77, 58, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 18, 41, 41, 41, 41, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 51, nil, nil,
- nil, nil, nil, nil, 18, 18, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 17, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 17, 18, nil, nil, nil, nil, nil, nil, nil, nil,
- 35, nil, nil, nil, 17, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 18, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 17, nil,
- nil, 35, 35, nil, nil, nil, 17, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 17,
- nil, nil, 35, 35, 17 ]
-
-racc_goto_pointer = [
- nil, 33, 43, 37, nil, nil, nil, 15, 12, -16,
- 29, 26, -7, nil, -24, -57, -204, -16, -81, nil,
- nil, nil, nil, nil, nil, nil, nil, 33, 34, nil,
- nil, nil, -14, nil, nil, -22, -10, nil, 30, -8,
- -5, -20, -36, nil, nil, nil, -78, nil, -10, nil,
- nil, -24, -160, nil, nil, -10, -63, -62, -135, 27,
- nil, 0, -145, 17, nil, nil, nil, nil, -230, -273,
- -84, nil, nil, -258, -105, nil, nil, -179, nil, nil,
- nil, -199, -168, nil, -313, nil ]
-
-racc_goto_default = [
- nil, nil, nil, nil, 5, 6, 7, 8, nil, nil,
- 172, nil, nil, 71, nil, nil, 72, nil, nil, 180,
- 12, 13, 14, 15, 16, 17, 18, nil, nil, 19,
- 21, 22, nil, 79, 80, 179, 176, 24, nil, nil,
- nil, nil, nil, 93, 95, 96, 111, 26, nil, 99,
- 100, nil, 101, 102, 28, 30, 32, 33, 34, nil,
- 35, 36, nil, 40, 41, 42, 43, 44, nil, 305,
- 110, 109, 112, nil, nil, 171, 173, 174, 175, 177,
- 178, 182, nil, 269, 270, 189 ]
-
-racc_reduce_table = [
- 0, 0, :racc_error,
- 0, 63, :_reduce_1,
- 2, 61, :_reduce_2,
- 2, 62, :_reduce_none,
- 2, 62, :_reduce_none,
- 2, 62, :_reduce_none,
- 1, 62, :_reduce_none,
- 1, 62, :_reduce_none,
- 1, 62, :_reduce_none,
- 1, 62, :_reduce_none,
- 0, 62, :_reduce_none,
- 3, 64, :_reduce_11,
- 4, 65, :_reduce_12,
- 3, 65, :_reduce_13,
- 2, 68, :_reduce_none,
- 1, 68, :_reduce_15,
- 1, 68, :_reduce_16,
- 4, 66, :_reduce_17,
- 3, 66, :_reduce_18,
- 3, 69, :_reduce_19,
- 1, 69, :_reduce_20,
- 1, 71, :_reduce_21,
- 3, 71, :_reduce_22,
- 0, 71, :_reduce_23,
- 3, 72, :_reduce_24,
- 2, 72, :_reduce_25,
- 1, 73, :_reduce_26,
- 1, 73, :_reduce_27,
- 0, 73, :_reduce_28,
- 1, 74, :_reduce_29,
- 5, 76, :_reduce_30,
- 8, 76, :_reduce_31,
- 1, 77, :_reduce_32,
- 0, 77, :_reduce_33,
- 3, 75, :_reduce_34,
- 0, 75, :_reduce_35,
- 1, 79, :_reduce_36,
- 2, 67, :_reduce_none,
- 2, 67, :_reduce_none,
- 2, 67, :_reduce_none,
- 2, 67, :_reduce_none,
- 1, 67, :_reduce_none,
- 1, 67, :_reduce_none,
- 1, 67, :_reduce_none,
- 1, 67, :_reduce_none,
- 1, 81, :_reduce_none,
- 1, 81, :_reduce_none,
- 1, 81, :_reduce_none,
- 1, 87, :_reduce_none,
- 1, 87, :_reduce_none,
- 3, 84, :_reduce_50,
- 3, 89, :_reduce_51,
- 3, 85, :_reduce_52,
- 2, 85, :_reduce_53,
- 3, 90, :_reduce_54,
- 1, 91, :_reduce_55,
- 3, 92, :_reduce_56,
- 1, 92, :_reduce_57,
- 1, 93, :_reduce_none,
- 1, 93, :_reduce_none,
- 1, 93, :_reduce_none,
- 3, 86, :_reduce_61,
- 2, 86, :_reduce_62,
- 3, 97, :_reduce_63,
- 1, 98, :_reduce_64,
- 1, 98, :_reduce_65,
- 1, 98, :_reduce_66,
- 1, 102, :_reduce_67,
- 1, 102, :_reduce_68,
- 1, 102, :_reduce_69,
- 3, 101, :_reduce_70,
- 1, 101, :_reduce_71,
- 2, 99, :_reduce_72,
- 1, 100, :_reduce_none,
- 1, 100, :_reduce_none,
- 3, 104, :_reduce_75,
- 3, 104, :_reduce_76,
- 3, 105, :_reduce_77,
- 3, 105, :_reduce_78,
- 3, 103, :_reduce_79,
- 4, 103, :_reduce_80,
- 3, 82, :_reduce_none,
- 2, 82, :_reduce_none,
- 3, 107, :_reduce_83,
- 2, 108, :_reduce_none,
- 1, 108, :_reduce_none,
- 3, 109, :_reduce_86,
- 2, 109, :_reduce_87,
- 2, 110, :_reduce_88,
- 0, 112, :_reduce_none,
- 3, 112, :_reduce_90,
- 1, 112, :_reduce_none,
- 1, 113, :_reduce_none,
- 1, 113, :_reduce_93,
- 3, 83, :_reduce_94,
- 2, 83, :_reduce_95,
- 2, 114, :_reduce_96,
- 3, 80, :_reduce_97,
- 2, 80, :_reduce_98,
- 1, 88, :_reduce_99,
- 2, 115, :_reduce_100,
- 2, 115, :_reduce_101,
- 3, 116, :_reduce_102,
- 1, 116, :_reduce_103,
- 3, 117, :_reduce_104,
- 1, 117, :_reduce_none,
- 1, 119, :_reduce_106,
- 1, 119, :_reduce_107,
- 1, 119, :_reduce_108,
- 1, 119, :_reduce_109,
- 2, 118, :_reduce_110,
- 1, 118, :_reduce_111,
- 1, 118, :_reduce_112,
- 3, 122, :_reduce_113,
- 1, 122, :_reduce_none,
- 1, 123, :_reduce_115,
- 3, 123, :_reduce_116,
- 2, 123, :_reduce_117,
- 3, 123, :_reduce_118,
- 1, 120, :_reduce_119,
- 1, 120, :_reduce_120,
- 2, 120, :_reduce_121,
- 3, 120, :_reduce_122,
- 3, 120, :_reduce_123,
- 1, 121, :_reduce_124,
- 1, 121, :_reduce_125,
- 1, 121, :_reduce_126,
- 1, 121, :_reduce_127,
- 2, 121, :_reduce_128,
- 2, 121, :_reduce_129,
- 2, 121, :_reduce_130,
- 2, 121, :_reduce_131,
- 1, 124, :_reduce_132,
- 2, 125, :_reduce_133,
- 5, 126, :_reduce_134,
- 5, 126, :_reduce_135,
- 5, 126, :_reduce_136,
- 5, 126, :_reduce_137,
- 5, 126, :_reduce_138,
- 5, 126, :_reduce_139,
- 5, 126, :_reduce_140,
- 5, 126, :_reduce_141,
- 5, 126, :_reduce_142,
- 5, 126, :_reduce_143,
- 5, 126, :_reduce_144,
- 5, 126, :_reduce_145,
- 3, 126, :_reduce_146,
- 2, 127, :_reduce_147,
- 3, 127, :_reduce_148,
- 3, 127, :_reduce_149,
- 4, 127, :_reduce_150,
- 4, 127, :_reduce_151,
- 2, 127, :_reduce_152,
- 4, 127, :_reduce_153,
- 6, 127, :_reduce_154,
- 7, 127, :_reduce_155,
- 0, 128, :_reduce_none,
- 1, 128, :_reduce_none,
- 1, 129, :_reduce_none,
- 3, 129, :_reduce_none,
- 1, 130, :_reduce_none,
- 2, 130, :_reduce_none,
- 3, 111, :_reduce_none,
- 2, 111, :_reduce_none,
- 2, 111, :_reduce_none,
- 1, 111, :_reduce_none,
- 1, 111, :_reduce_none,
- 1, 131, :_reduce_167,
- 4, 106, :_reduce_168,
- 5, 106, :_reduce_169,
- 5, 106, :_reduce_170,
- 6, 106, :_reduce_171,
- 1, 133, :_reduce_172,
- 0, 133, :_reduce_173,
- 1, 132, :_reduce_174,
- 2, 132, :_reduce_175,
- 1, 132, :_reduce_176,
- 1, 134, :_reduce_none,
- 1, 134, :_reduce_none,
- 1, 134, :_reduce_none,
- 3, 78, :_reduce_180,
- 2, 78, :_reduce_181,
- 1, 78, :_reduce_182,
- 1, 135, :_reduce_none,
- 1, 135, :_reduce_none,
- 1, 135, :_reduce_none,
- 1, 135, :_reduce_none,
- 1, 135, :_reduce_none,
- 1, 135, :_reduce_none,
- 1, 135, :_reduce_none,
- 1, 135, :_reduce_none,
- 1, 135, :_reduce_none,
- 1, 135, :_reduce_none,
- 1, 135, :_reduce_none,
- 2, 95, :_reduce_194,
- 3, 95, :_reduce_195,
- 2, 95, :_reduce_196,
- 2, 94, :_reduce_197,
- 1, 94, :_reduce_198,
- 3, 141, :_reduce_none,
- 1, 141, :_reduce_none,
- 4, 140, :_reduce_201,
- 1, 142, :_reduce_none,
- 3, 142, :_reduce_203,
- 3, 142, :_reduce_204,
- 1, 143, :_reduce_none,
- 4, 143, :_reduce_206,
- 4, 143, :_reduce_207,
- 1, 144, :_reduce_208,
- 1, 144, :_reduce_209,
- 3, 144, :_reduce_210,
- 2, 139, :_reduce_211,
- 1, 139, :_reduce_212,
- 2, 96, :_reduce_213,
- 1, 96, :_reduce_214,
- 2, 138, :_reduce_215,
- 1, 138, :_reduce_216,
- 2, 137, :_reduce_217,
- 1, 137, :_reduce_218,
- 1, 137, :_reduce_219,
- 1, 137, :_reduce_220,
- 1, 137, :_reduce_221,
- 1, 137, :_reduce_222,
- 1, 137, :_reduce_223,
- 1, 136, :_reduce_224,
- 1, 145, :_reduce_225,
- 1, 145, :_reduce_226,
- 2, 70, :_reduce_227,
- 1, 70, :_reduce_228 ]
-
-racc_reduce_n = 229
-
-racc_shift_n = 360
-
-racc_token_table = {
- false => 0,
- :error => 1,
- :CHARSET_SYM => 2,
- :IMPORT_SYM => 3,
- :STRING => 4,
- :SEMI => 5,
- :IDENT => 6,
- :S => 7,
- :COMMA => 8,
- :LBRACE => 9,
- :RBRACE => 10,
- :STAR => 11,
- :HASH => 12,
- :LSQUARE => 13,
- :RSQUARE => 14,
- :EQUAL => 15,
- :INCLUDES => 16,
- :DASHMATCH => 17,
- :LPAREN => 18,
- :RPAREN => 19,
- :FUNCTION => 20,
- :GREATER => 21,
- :PLUS => 22,
- :SLASH => 23,
- :NUMBER => 24,
- :MINUS => 25,
- :LENGTH => 26,
- :PERCENTAGE => 27,
- :ANGLE => 28,
- :TIME => 29,
- :FREQ => 30,
- :URI => 31,
- :IMPORTANT_SYM => 32,
- :MEDIA_SYM => 33,
- :NOT => 34,
- :ONLY => 35,
- :AND => 36,
- :NTH_PSEUDO_CLASS => 37,
- :DOCUMENT_QUERY_SYM => 38,
- :FUNCTION_NO_QUOTE => 39,
- :TILDE => 40,
- :PREFIXMATCH => 41,
- :SUFFIXMATCH => 42,
- :SUBSTRINGMATCH => 43,
- :NOT_PSEUDO_CLASS => 44,
- :KEYFRAMES_SYM => 45,
- :MATCHES_PSEUDO_CLASS => 46,
- :NAMESPACE_SYM => 47,
- :MOZ_PSEUDO_ELEMENT => 48,
- :RESOLUTION => 49,
- :COLON => 50,
- :SUPPORTS_SYM => 51,
- :OR => 52,
- :VARIABLE_NAME => 53,
- :CALC_SYM => 54,
- :FONTFACE_SYM => 55,
- :UNICODE_RANGE => 56,
- :RATIO => 57,
- "|" => 58,
- "." => 59 }
-
-racc_nt_base = 60
-
-racc_use_result_var = true
-
-Racc_arg = [
- racc_action_table,
- racc_action_check,
- racc_action_default,
- racc_action_pointer,
- racc_goto_table,
- racc_goto_check,
- racc_goto_default,
- racc_goto_pointer,
- racc_nt_base,
- racc_reduce_table,
- racc_token_table,
- racc_shift_n,
- racc_reduce_n,
- racc_use_result_var ]
-
-Racc_token_to_s_table = [
- "$end",
- "error",
- "CHARSET_SYM",
- "IMPORT_SYM",
- "STRING",
- "SEMI",
- "IDENT",
- "S",
- "COMMA",
- "LBRACE",
- "RBRACE",
- "STAR",
- "HASH",
- "LSQUARE",
- "RSQUARE",
- "EQUAL",
- "INCLUDES",
- "DASHMATCH",
- "LPAREN",
- "RPAREN",
- "FUNCTION",
- "GREATER",
- "PLUS",
- "SLASH",
- "NUMBER",
- "MINUS",
- "LENGTH",
- "PERCENTAGE",
- "ANGLE",
- "TIME",
- "FREQ",
- "URI",
- "IMPORTANT_SYM",
- "MEDIA_SYM",
- "NOT",
- "ONLY",
- "AND",
- "NTH_PSEUDO_CLASS",
- "DOCUMENT_QUERY_SYM",
- "FUNCTION_NO_QUOTE",
- "TILDE",
- "PREFIXMATCH",
- "SUFFIXMATCH",
- "SUBSTRINGMATCH",
- "NOT_PSEUDO_CLASS",
- "KEYFRAMES_SYM",
- "MATCHES_PSEUDO_CLASS",
- "NAMESPACE_SYM",
- "MOZ_PSEUDO_ELEMENT",
- "RESOLUTION",
- "COLON",
- "SUPPORTS_SYM",
- "OR",
- "VARIABLE_NAME",
- "CALC_SYM",
- "FONTFACE_SYM",
- "UNICODE_RANGE",
- "RATIO",
- "\"|\"",
- "\".\"",
- "$start",
- "document",
- "stylesheet",
- "@1",
- "charset",
- "import",
- "namespace",
- "body",
- "import_location",
- "medium",
- "ident",
- "media_query_list",
- "media_query",
- "optional_only_or_not",
- "media_type",
- "optional_and_exprs",
- "media_expr",
- "optional_space",
- "expr",
- "resolution",
- "ruleset",
- "conditional_rule",
- "keyframes_rule",
- "fontface_rule",
- "media",
- "document_query",
- "supports",
- "body_in_media",
- "empty_ruleset",
- "start_media",
- "start_document_query",
- "start_document_query_pos",
- "url_match_fns",
- "url_match_fn",
- "function_no_quote",
- "function",
- "uri",
- "start_supports",
- "supports_condition_root",
- "supports_negation",
- "supports_conjunction_or_disjunction",
- "supports_condition_in_parens",
- "supports_condition",
- "supports_declaration_condition",
- "supports_conjunction",
- "supports_disjunction",
- "declaration_internal",
- "start_keyframes_rule",
- "keyframes_blocks",
- "keyframes_block",
- "start_keyframes_block",
- "declarations",
- "keyframes_selectors",
- "keyframes_selector",
- "start_fontface_rule",
- "start_selector",
- "selectors",
- "selector",
- "simple_selector",
- "combinator",
- "element_name",
- "hcap",
- "simple_selectors",
- "ident_with_namespace",
- "hash",
- "class",
- "attrib",
- "pseudo",
- "any_number_of_idents",
- "multiple_idents",
- "one_or_more_semis",
- "declaration",
- "property",
- "prio",
- "operator",
- "term",
- "ratio",
- "numeric",
- "string",
- "hexcolor",
- "calc",
- "uranges",
- "calc_sum",
- "calc_product",
- "calc_value",
- "unary_operator" ]
-
-Racc_debug_parser = false
-
-##### State transition tables end #####
-
-# reduce 0 omitted
-
-module_eval(<<'.,.,', 'csspool.y', 26)
- def _reduce_1(val, _values, result)
- @handler.start_document
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 28)
- def _reduce_2(val, _values, result)
- @handler.end_document
- result
- end
-.,.,
-
-# reduce 3 omitted
-
-# reduce 4 omitted
-
-# reduce 5 omitted
-
-# reduce 6 omitted
-
-# reduce 7 omitted
-
-# reduce 8 omitted
-
-# reduce 9 omitted
-
-# reduce 10 omitted
-
-module_eval(<<'.,.,', 'csspool.y', 41)
- def _reduce_11(val, _values, result)
- @handler.charset interpret_string(val[1]), {}
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 45)
- def _reduce_12(val, _values, result)
- @handler.import_style val[2], val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 48)
- def _reduce_13(val, _values, result)
- @handler.import_style [], val[1]
-
- result
- end
-.,.,
-
-# reduce 14 omitted
-
-module_eval(<<'.,.,', 'csspool.y', 53)
- def _reduce_15(val, _values, result)
- result = Terms::String.new interpret_string val.first
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 54)
- def _reduce_16(val, _values, result)
- result = Terms::URI.new interpret_uri val.first
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 58)
- def _reduce_17(val, _values, result)
- @handler.namespace val[1], val[2]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 61)
- def _reduce_18(val, _values, result)
- @handler.namespace nil, val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 66)
- def _reduce_19(val, _values, result)
- result = val[0] << MediaType.new(val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 69)
- def _reduce_20(val, _values, result)
- result = [MediaType.new(val[0])]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 73)
- def _reduce_21(val, _values, result)
- result = MediaQueryList.new([ val[0] ])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 74)
- def _reduce_22(val, _values, result)
- result = val[0] << val[2]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 75)
- def _reduce_23(val, _values, result)
- result = MediaQueryList.new
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 78)
- def _reduce_24(val, _values, result)
- result = MediaQuery.new(val[0], val[1], val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 79)
- def _reduce_25(val, _values, result)
- result = MediaQuery.new(nil, val[0], val[1])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 82)
- def _reduce_26(val, _values, result)
- result = :only
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 83)
- def _reduce_27(val, _values, result)
- result = :not
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 84)
- def _reduce_28(val, _values, result)
- result = nil
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 87)
- def _reduce_29(val, _values, result)
- result = MediaType.new(val[0])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 90)
- def _reduce_30(val, _values, result)
- result = MediaType.new(val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 91)
- def _reduce_31(val, _values, result)
- result = MediaFeature.new(val[2], val[6][0])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 94)
- def _reduce_32(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 95)
- def _reduce_33(val, _values, result)
- result = nil
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 98)
- def _reduce_34(val, _values, result)
- result = val[0] << val[2]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 99)
- def _reduce_35(val, _values, result)
- result = []
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 103)
- def _reduce_36(val, _values, result)
- unit = val.first.gsub(/[\s\d.]/, '')
- number = numeric(val.first)
- result = Terms::Resolution.new(number, unit)
-
- result
- end
-.,.,
-
-# reduce 37 omitted
-
-# reduce 38 omitted
-
-# reduce 39 omitted
-
-# reduce 40 omitted
-
-# reduce 41 omitted
-
-# reduce 42 omitted
-
-# reduce 43 omitted
-
-# reduce 44 omitted
-
-# reduce 45 omitted
-
-# reduce 46 omitted
-
-# reduce 47 omitted
-
-# reduce 48 omitted
-
-# reduce 49 omitted
-
-module_eval(<<'.,.,', 'csspool.y', 128)
- def _reduce_50(val, _values, result)
- @handler.end_media val.first
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 132)
- def _reduce_51(val, _values, result)
- result = val[1]
- @handler.start_media result
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 137)
- def _reduce_52(val, _values, result)
- @handler.end_document_query(before_pos(val), after_pos(val))
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 138)
- def _reduce_53(val, _values, result)
- @handler.end_document_query(before_pos(val), after_pos(val))
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 142)
- def _reduce_54(val, _values, result)
- @handler.start_document_query(val[1], after_pos(val))
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 147)
- def _reduce_55(val, _values, result)
- @handler.node_start_pos = before_pos(val)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 152)
- def _reduce_56(val, _values, result)
- result = [val[0], val[2]].flatten
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 155)
- def _reduce_57(val, _values, result)
- result = val
-
- result
- end
-.,.,
-
-# reduce 58 omitted
-
-# reduce 59 omitted
-
-# reduce 60 omitted
-
-module_eval(<<'.,.,', 'csspool.y', 164)
- def _reduce_61(val, _values, result)
- @handler.end_supports
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 165)
- def _reduce_62(val, _values, result)
- @handler.end_supports
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 169)
- def _reduce_63(val, _values, result)
- @handler.start_supports val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 173)
- def _reduce_64(val, _values, result)
- result = val.join('')
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 174)
- def _reduce_65(val, _values, result)
- result = val.join('')
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 175)
- def _reduce_66(val, _values, result)
- result = val.join('')
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 178)
- def _reduce_67(val, _values, result)
- result = val.join('')
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 179)
- def _reduce_68(val, _values, result)
- result = val.join('')
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 180)
- def _reduce_69(val, _values, result)
- result = val.join('')
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 183)
- def _reduce_70(val, _values, result)
- result = val.join('')
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 184)
- def _reduce_71(val, _values, result)
- result = val.join('')
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 187)
- def _reduce_72(val, _values, result)
- result = val.join('')
- result
- end
-.,.,
-
-# reduce 73 omitted
-
-# reduce 74 omitted
-
-module_eval(<<'.,.,', 'csspool.y', 194)
- def _reduce_75(val, _values, result)
- result = val.join('')
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 195)
- def _reduce_76(val, _values, result)
- result = val.join('')
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 198)
- def _reduce_77(val, _values, result)
- result = val.join('')
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 199)
- def _reduce_78(val, _values, result)
- result = val.join('')
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 202)
- def _reduce_79(val, _values, result)
- result = val.join('')
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 203)
- def _reduce_80(val, _values, result)
- result = val.join('')
- result
- end
-.,.,
-
-# reduce 81 omitted
-
-# reduce 82 omitted
-
-module_eval(<<'.,.,', 'csspool.y', 211)
- def _reduce_83(val, _values, result)
- @handler.start_keyframes_rule val[1]
-
- result
- end
-.,.,
-
-# reduce 84 omitted
-
-# reduce 85 omitted
-
-module_eval(<<'.,.,', 'csspool.y', 219)
- def _reduce_86(val, _values, result)
- @handler.end_keyframes_block
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 220)
- def _reduce_87(val, _values, result)
- @handler.end_keyframes_block
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 224)
- def _reduce_88(val, _values, result)
- @handler.start_keyframes_block val[0]
-
- result
- end
-.,.,
-
-# reduce 89 omitted
-
-module_eval(<<'.,.,', 'csspool.y', 229)
- def _reduce_90(val, _values, result)
- result = val[0] + ', ' + val[2]
-
- result
- end
-.,.,
-
-# reduce 91 omitted
-
-# reduce 92 omitted
-
-module_eval(<<'.,.,', 'csspool.y', 235)
- def _reduce_93(val, _values, result)
- result = val[0].strip
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 238)
- def _reduce_94(val, _values, result)
- @handler.end_fontface_rule
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 239)
- def _reduce_95(val, _values, result)
- @handler.end_fontface_rule
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 243)
- def _reduce_96(val, _values, result)
- @handler.start_fontface_rule
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 248)
- def _reduce_97(val, _values, result)
- @handler.end_selector val.first
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 251)
- def _reduce_98(val, _values, result)
- @handler.end_selector val.first
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 256)
- def _reduce_99(val, _values, result)
- start = @handler.start_selector([])
- @handler.end_selector(start)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 261)
- def _reduce_100(val, _values, result)
- result = val.last
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 263)
- def _reduce_101(val, _values, result)
- @handler.start_selector val.first
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 269)
- def _reduce_102(val, _values, result)
- sel = Selector.new(val.first, {})
- result = [sel].concat(val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 274)
- def _reduce_103(val, _values, result)
- result = [Selector.new(val.first, {})]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 280)
- def _reduce_104(val, _values, result)
- val.flatten!
- val[2].combinator = val.delete_at 1
- result = val
-
- result
- end
-.,.,
-
-# reduce 105 omitted
-
-module_eval(<<'.,.,', 'csspool.y', 287)
- def _reduce_106(val, _values, result)
- result = :s
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 288)
- def _reduce_107(val, _values, result)
- result = :>
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 289)
- def _reduce_108(val, _values, result)
- result = :+
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 290)
- def _reduce_109(val, _values, result)
- result = :~
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 294)
- def _reduce_110(val, _values, result)
- selector = val.first
- selector.additional_selectors = val.last
- result = [selector]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 298)
- def _reduce_111(val, _values, result)
- result = val
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 301)
- def _reduce_112(val, _values, result)
- ss = Selectors::Simple.new nil, nil
- ss.additional_selectors = val.flatten
- result = [ss]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 307)
- def _reduce_113(val, _values, result)
- result = [val[0], val[2]].flatten
- result
- end
-.,.,
-
-# reduce 114 omitted
-
-module_eval(<<'.,.,', 'csspool.y', 311)
- def _reduce_115(val, _values, result)
- result = [interpret_identifier(val[0]), nil]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 312)
- def _reduce_116(val, _values, result)
- result = [interpret_identifier(val[2]), interpret_identifier(val[0])]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 313)
- def _reduce_117(val, _values, result)
- result = [interpret_identifier(val[1]), nil]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 314)
- def _reduce_118(val, _values, result)
- result = [interpret_identifier(val[2]), '*']
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 317)
- def _reduce_119(val, _values, result)
- result = Selectors::Type.new val.first[0], nil, val.first[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 318)
- def _reduce_120(val, _values, result)
- result = Selectors::Universal.new val.first
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 319)
- def _reduce_121(val, _values, result)
- result = Selectors::Universal.new val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 320)
- def _reduce_122(val, _values, result)
- result = Selectors::Universal.new val[2], nil, val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 321)
- def _reduce_123(val, _values, result)
- result = Selectors::Universal.new val[2], nil, interpret_identifier(val[0])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 324)
- def _reduce_124(val, _values, result)
- result = val
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 325)
- def _reduce_125(val, _values, result)
- result = val
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 326)
- def _reduce_126(val, _values, result)
- result = val
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 327)
- def _reduce_127(val, _values, result)
- result = val
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 328)
- def _reduce_128(val, _values, result)
- result = val.flatten
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 329)
- def _reduce_129(val, _values, result)
- result = val.flatten
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 330)
- def _reduce_130(val, _values, result)
- result = val.flatten
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 331)
- def _reduce_131(val, _values, result)
- result = val.flatten
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 335)
- def _reduce_132(val, _values, result)
- result = Selectors::Id.new interpret_identifier val.first.sub(/^#/, '')
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 339)
- def _reduce_133(val, _values, result)
- result = Selectors::Class.new interpret_identifier val.last
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 344)
- def _reduce_134(val, _values, result)
- result = Selectors::Attribute.new(
- val[1][0],
- interpret_identifier(val[3]),
- Selectors::Attribute::EQUALS,
- val[1][1]
- )
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 352)
- def _reduce_135(val, _values, result)
- result = Selectors::Attribute.new(
- val[1][0],
- interpret_string(val[3]),
- Selectors::Attribute::EQUALS,
- val[1][1]
- )
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 360)
- def _reduce_136(val, _values, result)
- result = Selectors::Attribute.new(
- val[1][0],
- interpret_string(val[3]),
- Selectors::Attribute::INCLUDES,
- val[1][1]
- )
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 368)
- def _reduce_137(val, _values, result)
- result = Selectors::Attribute.new(
- val[1][0],
- interpret_identifier(val[3]),
- Selectors::Attribute::INCLUDES,
- val[1][1]
- )
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 376)
- def _reduce_138(val, _values, result)
- result = Selectors::Attribute.new(
- val[1][0],
- interpret_identifier(val[3]),
- Selectors::Attribute::DASHMATCH,
- val[1][1]
- )
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 384)
- def _reduce_139(val, _values, result)
- result = Selectors::Attribute.new(
- val[1][0],
- interpret_string(val[3]),
- Selectors::Attribute::DASHMATCH,
- val[1][1]
- )
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 392)
- def _reduce_140(val, _values, result)
- result = Selectors::Attribute.new(
- val[1][0],
- interpret_identifier(val[3]),
- Selectors::Attribute::PREFIXMATCH,
- val[1][1]
- )
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 400)
- def _reduce_141(val, _values, result)
- result = Selectors::Attribute.new(
- val[1][0],
- interpret_string(val[3]),
- Selectors::Attribute::PREFIXMATCH,
- val[1][1]
- )
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 408)
- def _reduce_142(val, _values, result)
- result = Selectors::Attribute.new(
- val[1][0],
- interpret_identifier(val[3]),
- Selectors::Attribute::SUFFIXMATCH,
- val[1][1]
- )
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 416)
- def _reduce_143(val, _values, result)
- result = Selectors::Attribute.new(
- val[1][0],
- interpret_string(val[3]),
- Selectors::Attribute::SUFFIXMATCH,
- val[1][1]
- )
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 424)
- def _reduce_144(val, _values, result)
- result = Selectors::Attribute.new(
- val[1][0],
- interpret_identifier(val[3]),
- Selectors::Attribute::SUBSTRINGMATCH,
- val[1][1]
- )
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 432)
- def _reduce_145(val, _values, result)
- result = Selectors::Attribute.new(
- val[1][0],
- interpret_string(val[3]),
- Selectors::Attribute::SUBSTRINGMATCH,
- val[1][1]
- )
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 440)
- def _reduce_146(val, _values, result)
- result = Selectors::Attribute.new(
- val[1][0],
- nil,
- Selectors::Attribute::SET,
- val[1][1]
- )
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 450)
- def _reduce_147(val, _values, result)
- result = Selectors::pseudo interpret_identifier(val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 453)
- def _reduce_148(val, _values, result)
- result = Selectors::PseudoElement.new(
- interpret_identifier(val[2])
- )
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 458)
- def _reduce_149(val, _values, result)
- result = Selectors::PseudoClass.new(
- interpret_identifier(val[1].sub(/\($/, '')),
- ''
- )
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 464)
- def _reduce_150(val, _values, result)
- result = Selectors::PseudoClass.new(
- interpret_identifier(val[1].sub(/\($/, '')),
- interpret_identifier(val[2])
- )
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 470)
- def _reduce_151(val, _values, result)
- result = Selectors::PseudoClass.new(
- 'not',
- val[2].first.to_s
- )
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 476)
- def _reduce_152(val, _values, result)
- result = Selectors::PseudoClass.new(
- interpret_identifier(val[1].sub(/\(.*/, '')),
- interpret_identifier(val[1].sub(/.*\(/, '').sub(/\).*/, ''))
- )
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 482)
- def _reduce_153(val, _values, result)
- result = Selectors::PseudoClass.new(
- val[1].split('(').first.strip,
- val[2].join(', ')
- )
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 488)
- def _reduce_154(val, _values, result)
- result = Selectors::PseudoElement.new(
- interpret_identifier(val[1].sub(/\($/, ''))
- )
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 493)
- def _reduce_155(val, _values, result)
- result = Selectors::PseudoElement.new(
- interpret_identifier(val[2].sub(/\($/, ''))
- )
-
- result
- end
-.,.,
-
-# reduce 156 omitted
-
-# reduce 157 omitted
-
-# reduce 158 omitted
-
-# reduce 159 omitted
-
-# reduce 160 omitted
-
-# reduce 161 omitted
-
-# reduce 162 omitted
-
-# reduce 163 omitted
-
-# reduce 164 omitted
-
-# reduce 165 omitted
-
-# reduce 166 omitted
-
-module_eval(<<'.,.,', 'csspool.y', 519)
- def _reduce_167(val, _values, result)
- @handler.property val.first
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 523)
- def _reduce_168(val, _values, result)
- result = Declaration.new(val.first, val[2], val[3])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 525)
- def _reduce_169(val, _values, result)
- result = Declaration.new(val.first, val[3], val[4])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 527)
- def _reduce_170(val, _values, result)
- result = Declaration.new(val.first, val[3], val[4])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 529)
- def _reduce_171(val, _values, result)
- result = Declaration.new(val.first, val[4], val[5])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 532)
- def _reduce_172(val, _values, result)
- result = true
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 533)
- def _reduce_173(val, _values, result)
- result = false
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 536)
- def _reduce_174(val, _values, result)
- result = interpret_identifier val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 537)
- def _reduce_175(val, _values, result)
- result = interpret_identifier val.join
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 538)
- def _reduce_176(val, _values, result)
- result = interpret_identifier val[0]
- result
- end
-.,.,
-
-# reduce 177 omitted
-
-# reduce 178 omitted
-
-# reduce 179 omitted
-
-module_eval(<<'.,.,', 'csspool.y', 547)
- def _reduce_180(val, _values, result)
- result = [val.first, val.last].flatten
- val.last.first.operator = val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 550)
- def _reduce_181(val, _values, result)
- result = val.flatten
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 551)
- def _reduce_182(val, _values, result)
- result = val
- result
- end
-.,.,
-
-# reduce 183 omitted
-
-# reduce 184 omitted
-
-# reduce 185 omitted
-
-# reduce 186 omitted
-
-# reduce 187 omitted
-
-# reduce 188 omitted
-
-# reduce 189 omitted
-
-# reduce 190 omitted
-
-# reduce 191 omitted
-
-# reduce 192 omitted
-
-# reduce 193 omitted
-
-module_eval(<<'.,.,', 'csspool.y', 567)
- def _reduce_194(val, _values, result)
- result = val.first
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 569)
- def _reduce_195(val, _values, result)
- name = interpret_identifier val.first.sub(/\($/, '')
- if name == 'rgb'
- result = Terms::Rgb.new(*val[1])
- else
- result = Terms::Function.new name, val[1]
- end
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 577)
- def _reduce_196(val, _values, result)
- name = interpret_identifier val.first.sub(/\($/, '')
- result = Terms::Function.new name
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 582)
- def _reduce_197(val, _values, result)
- result = val.first
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 584)
- def _reduce_198(val, _values, result)
- parts = val.first.split('(')
- name = interpret_identifier parts.first
- result = Terms::Function.new(name, [Terms::String.new(interpret_string_no_quote(parts.last))])
-
- result
- end
-.,.,
-
-# reduce 199 omitted
-
-# reduce 200 omitted
-
-module_eval(<<'.,.,', 'csspool.y', 595)
- def _reduce_201(val, _values, result)
- result = Terms::Math.new(val.first.split('(').first, val[1])
-
- result
- end
-.,.,
-
-# reduce 202 omitted
-
-module_eval(<<'.,.,', 'csspool.y', 601)
- def _reduce_203(val, _values, result)
- val.insert(1, ' '); result = val.join('')
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 602)
- def _reduce_204(val, _values, result)
- val.insert(1, ' '); result = val.join('')
- result
- end
-.,.,
-
-# reduce 205 omitted
-
-module_eval(<<'.,.,', 'csspool.y', 606)
- def _reduce_206(val, _values, result)
- result = val.join('')
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 607)
- def _reduce_207(val, _values, result)
- result = val.join('')
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 610)
- def _reduce_208(val, _values, result)
- result = val.join('')
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 611)
- def _reduce_209(val, _values, result)
- result = val.join('')
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 612)
- def _reduce_210(val, _values, result)
- result = val.join('')
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 615)
- def _reduce_211(val, _values, result)
- result = val.first
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 616)
- def _reduce_212(val, _values, result)
- result = Terms::Hash.new val.first.sub(/^#/, '')
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 619)
- def _reduce_213(val, _values, result)
- result = val.first
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 620)
- def _reduce_214(val, _values, result)
- result = Terms::URI.new interpret_uri val.first
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 623)
- def _reduce_215(val, _values, result)
- result = val.first
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 624)
- def _reduce_216(val, _values, result)
- result = Terms::String.new interpret_string val.first
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 628)
- def _reduce_217(val, _values, result)
- result = val[1]
- val[1].unary_operator = val.first
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 632)
- def _reduce_218(val, _values, result)
- result = Terms::Number.new numeric val.first
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 635)
- def _reduce_219(val, _values, result)
- result = Terms::Number.new numeric(val.first), nil, '%'
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 638)
- def _reduce_220(val, _values, result)
- unit = val.first.gsub(/[\s\d.]/, '')
- result = Terms::Number.new numeric(val.first), nil, unit
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 642)
- def _reduce_221(val, _values, result)
- unit = val.first.gsub(/[\s\d.]/, '')
- result = Terms::Number.new numeric(val.first), nil, unit
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 646)
- def _reduce_222(val, _values, result)
- unit = val.first.gsub(/[\s\d.]/, '')
- result = Terms::Number.new numeric(val.first), nil, unit
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 650)
- def _reduce_223(val, _values, result)
- unit = val.first.gsub(/[\s\d.]/, '')
- result = Terms::Number.new numeric(val.first), nil, unit
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 656)
- def _reduce_224(val, _values, result)
- result = Terms::Ratio.new(val[0], val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 660)
- def _reduce_225(val, _values, result)
- result = :minus
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 661)
- def _reduce_226(val, _values, result)
- result = :plus
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 664)
- def _reduce_227(val, _values, result)
- result = val.first
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'csspool.y', 665)
- def _reduce_228(val, _values, result)
- result = Terms::Ident.new interpret_identifier val.first
- result
- end
-.,.,
-
-def _reduce_none(val, _values, result)
- val[0]
-end
-
- end # class Parser
- end # module CSS
-end # module CSSPool
diff --git a/test/racc/regress/edtf b/test/racc/regress/edtf
deleted file mode 100644
index 5947931260..0000000000
--- a/test/racc/regress/edtf
+++ /dev/null
@@ -1,1794 +0,0 @@
-#
-# DO NOT MODIFY!!!!
-# This file is automatically generated by Racc 1.5.0
-# from Racc grammar file "".
-#
-
-require 'racc/parser.rb'
-
-require 'strscan'
-
-module EDTF
- class Parser < Racc::Parser
-
-module_eval(<<'...end edtf.y/module_eval...', 'edtf.y', 468)
-
- @defaults = {
- :level => 2,
- :debug => false
- }.freeze
-
- class << self; attr_reader :defaults; end
-
- attr_reader :options
-
- def initialize(options = {})
- @options = Parser.defaults.merge(options)
- end
-
- def debug?
- !!(options[:debug] || ENV['DEBUG'])
- end
-
- def parse(input)
- parse!(input)
- rescue => e
- warn e.message if debug?
- nil
- end
-
- def parse!(input)
- @yydebug = debug?
- @src = StringScanner.new(input)
- do_parse
- end
-
- def on_error(tid, value, stack)
- raise ArgumentError,
- "failed to parse date: unexpected '#{value}' at #{stack.inspect}"
- end
-
- def apply_uncertainty(date, uncertainty, scope = nil)
- uncertainty.each do |u|
- scope.nil? ? date.send(u) : date.send(u, scope)
- end
- date
- end
-
- alias uoa apply_uncertainty
-
- def next_token
- case
- when @src.eos?
- nil
- # when @src.scan(/\s+/)
- # ignore whitespace
- when @src.scan(/\(/)
- ['(', @src.matched]
- # when @src.scan(/\)\?~-/)
- # [:PUA, [:uncertain!, :approximate!]]
- # when @src.scan(/\)\?-/)
- # [:PUA, [:uncertain!]]
- # when @src.scan(/\)~-/)
- # [:PUA, [:approximate!]]
- when @src.scan(/\)/)
- [')', @src.matched]
- when @src.scan(/\[/)
- ['[', @src.matched]
- when @src.scan(/\]/)
- [']', @src.matched]
- when @src.scan(/\{/)
- ['{', @src.matched]
- when @src.scan(/\}/)
- ['}', @src.matched]
- when @src.scan(/T/)
- [:T, @src.matched]
- when @src.scan(/Z/)
- [:Z, @src.matched]
- when @src.scan(/\?~/)
- [:UA, [:uncertain!, :approximate!]]
- when @src.scan(/\?/)
- [:UA, [:uncertain!]]
- when @src.scan(/~/)
- [:UA, [:approximate!]]
- when @src.scan(/open/i)
- [:OPEN, :open]
- when @src.scan(/unkn?own/i) # matches 'unkown' typo too
- [:UNKNOWN, :unknown]
- when @src.scan(/u/)
- [:U, @src.matched]
- when @src.scan(/x/i)
- [:X, @src.matched]
- when @src.scan(/y/)
- [:LONGYEAR, @src.matched]
- when @src.scan(/e/)
- [:E, @src.matched]
- when @src.scan(/\+/)
- ['+', @src.matched]
- when @src.scan(/-\(/)
- ['-(', @src.matched]
- when @src.scan(/-/)
- ['-', @src.matched]
- when @src.scan(/:/)
- [':', @src.matched]
- when @src.scan(/\//)
- ['/', @src.matched]
- when @src.scan(/\s*\.\.\s*/)
- [:DOTS, '..']
- when @src.scan(/\s*,\s*/)
- [',', ',']
- when @src.scan(/\^\w+/)
- ['^', @src.matched[1..-1]]
- when @src.scan(/\d/)
- [@src.matched, @src.matched.to_i]
- else @src.scan(/./)
- [:UNMATCHED, @src.rest]
- end
- end
-
-
-# -*- racc -*-
-...end edtf.y/module_eval...
-##### State transition tables begin ###
-
-racc_action_table = [
- 129, 128, 52, 111, 51, 112, 149, 208, 207, 57,
- -50, 43, 45, 40, 55, 42, 54, 44, 43, 45,
- 40, -48, 42, 53, 44, 64, 58, 46, 47, 48,
- 49, 50, 128, 56, 46, 47, 48, 49, 50, 207,
- 57, 65, 43, 45, 40, 55, 42, 157, 44, 43,
- 45, 40, 55, 42, 214, 44, 92, 58, 46, 47,
- 48, 49, 50, 66, 56, 46, 47, 48, 49, 50,
- 25, 56, 26, 93, 94, 67, 108, 12, -65, 43,
- 45, 40, -66, 42, 159, 44, 110, 33, 111, 34,
- 112, 95, 36, 25, 141, 46, 47, 48, 49, 50,
- 12, 58, 43, 45, 40, 101, 42, 103, 44, 104,
- 96, 148, 55, 133, 147, 36, 124, 125, 46, 47,
- 48, 49, 50, 87, 165, 111, 12, 112, 43, 45,
- 40, 56, 42, 146, 44, 166, 111, 150, 112, 218,
- 167, 36, 152, 153, 46, 47, 48, 49, 50, 87,
- 108, 111, 12, 112, 43, 45, 40, 188, 42, 186,
- 44, 187, 111, 190, 112, 154, 111, 36, 112, 156,
- 46, 47, 48, 49, 50, 69, 158, 43, 45, 189,
- 191, 42, 12, 44, 43, 45, 40, 200, 42, 201,
- 44, 168, 177, 46, 47, 48, 49, 50, 233, 178,
- 46, 47, 48, 49, 50, 12, 180, 43, 45, 40,
- 111, 42, 112, 44, 232, 234, 111, 240, 112, 239,
- 36, 192, 193, 46, 47, 48, 49, 50, 12, 202,
- 43, 45, 40, 118, 42, 117, 44, 104, 118, 121,
- 117, 209, 104, 36, 121, 210, 46, 47, 48, 49,
- 50, 12, 212, 43, 45, 40, 244, 42, 239, 44,
- 213, 43, 45, 40, 215, 42, 36, 44, 229, 46,
- 47, 48, 49, 50, 180, 180, 236, 46, 47, 48,
- 49, 50, 43, 45, 40, 253, 42, 254, 44, 43,
- 45, 40, 255, 42, 258, 44, 261, 264, 46, 47,
- 48, 49, 50, 124, 125, 46, 47, 48, 49, 50,
- 43, 45, 40, 265, 42, 192, 44, 43, 45, 266,
- 269, 42, 270, 44, 275, 280, 46, 47, 48, 49,
- 50, 284, 285, 46, 47, 48, 49, 50, 43, 45,
- 40, 286, 42, 290, 44, 43, 45, 292, 293, 42,
- 295, 44, 296, 297, 46, 47, 48, 49, 50, 300,
- 301, 46, 47, 48, 49, 50, 43, 45, 40, 180,
- 42, 303, 44, 43, 45, 40, 304, 42, 305, 44,
- 281, 306, 46, 47, 48, 49, 50, 307, 308, 46,
- 47, 48, 49, 50, 43, 45, 175, 311, 42, 312,
- 44, 43, 45, 40, 313, 42, 314, 44, 316, 317,
- 46, 47, 48, 49, 50, 318, 319, 46, 47, 48,
- 49, 50, 43, 45, nil, nil, 42, nil, 44, 43,
- 45, nil, nil, 42, nil, 44, nil, nil, 46, 47,
- 48, 49, 50, nil, nil, 46, 47, 48, 49, 50,
- 172, 194, 170, nil, 171, nil, 173, 43, 45, 40,
- nil, 42, nil, 44, nil, nil, 195, 196, 197, 198,
- 199, nil, nil, 46, 47, 48, 49, 50, 43, 45,
- 40, nil, 42, nil, 44, 43, 45, 40, nil, 42,
- nil, 44, nil, nil, 46, 47, 48, 49, 50, nil,
- nil, 46, 47, 48, 49, 50, 43, 45, 40, nil,
- 42, nil, 44, 43, 45, nil, nil, 42, nil, 44,
- nil, nil, 46, 47, 48, 49, 50, nil, nil, 46,
- 47, 48, 49, 50, 43, 45, 40, nil, 42, nil,
- 44, 43, 45, 40, nil, 42, nil, 44, nil, nil,
- 46, 47, 48, 49, 50, nil, nil, 46, 47, 48,
- 49, 50, 43, 45, 40, nil, 42, nil, 44, 43,
- 45, 40, nil, 42, nil, 44, nil, nil, 46, 47,
- 48, 49, 50, nil, nil, 46, 47, 48, 49, 50,
- 43, 45, nil, nil, 42, nil, 44, 43, 45, 40,
- nil, 42, nil, 44, nil, nil, 46, 47, 48, 49,
- 50, nil, nil, 46, 47, 48, 49, 50, 43, 45,
- 40, nil, 42, nil, 44, 43, 45, 273, nil, 42,
- nil, 44, nil, nil, 46, 47, 48, 49, 50, nil,
- nil, 46, 47, 48, 49, 50, 43, 45, 274, nil,
- 42, nil, 44, 43, 45, 276, nil, 42, nil, 44,
- nil, nil, 46, 47, 48, 49, 50, nil, nil, 46,
- 47, 48, 49, 50, 43, 45, 40, nil, 42, nil,
- 44, 43, 45, 40, nil, 42, nil, 44, nil, nil,
- 46, 47, 48, 49, 50, nil, nil, 46, 47, 48,
- 49, 50, 43, 45, 40, nil, 42, nil, 44, 43,
- 45, 40, nil, 42, nil, 44, nil, nil, 46, 47,
- 48, 49, 50, nil, nil, 46, 47, 48, 49, 50,
- 43, 45, 40, nil, 42, nil, 44, 43, 45, 315,
- nil, 42, nil, 44, nil, nil, 46, 47, 48, 49,
- 50, 116, nil, 46, 47, 48, 49, 50, 118, 250,
- 247, 118, 104, 117, 249, 104, 260, 121, nil, 281,
- nil, nil, nil, nil, 251, nil, 118, 288, 117, 118,
- 104, 117, 121, 104, 118, 121, 117, 118, 104, 117,
- 121, 104, nil, 121, 118, 250, 247, nil, 104, nil,
- 249, 118, 250, 247, nil, 104, nil, 249, nil, nil,
- 251, nil, 118, 250, 117, nil, 104, 251, 249, 118,
- 250, 310, nil, 104, nil, 249, nil, nil, 251, nil,
- 172, 169, 170, nil, 171, 251, 173, 182, 184, nil,
- 118, 181, 117, 183, 104, 118, 121, 117, 118, 104,
- 117, 121, 104, 118, 121, 117, 118, 104, 117, 121,
- 104, 118, 121, 117, nil, 104, nil, 121, 188, 271,
- 186, 118, 187, 117, 272, 104, nil, 121 ]
-
-racc_action_check = [
- 63, 63, 5, 56, 1, 56, 73, 127, 127, 73,
- 14, 63, 63, 63, 9, 63, 9, 63, 127, 127,
- 127, 5, 127, 5, 127, 16, 73, 63, 63, 63,
- 63, 63, 151, 9, 127, 127, 127, 127, 127, 224,
- 10, 17, 151, 151, 151, 89, 151, 89, 151, 224,
- 224, 224, 134, 224, 134, 224, 37, 10, 151, 151,
- 151, 151, 151, 18, 89, 224, 224, 224, 224, 224,
- 0, 134, 0, 37, 38, 22, 54, 0, 23, 0,
- 0, 0, 24, 0, 91, 0, 54, 0, 54, 0,
- 54, 38, 0, 67, 67, 0, 0, 0, 0, 0,
- 67, 91, 67, 67, 67, 52, 67, 52, 67, 52,
- 51, 72, 72, 66, 72, 67, 59, 60, 67, 67,
- 67, 67, 67, 33, 98, 66, 33, 66, 33, 33,
- 33, 72, 33, 71, 33, 98, 92, 74, 92, 147,
- 98, 33, 77, 78, 33, 33, 33, 33, 33, 34,
- 214, 147, 34, 147, 34, 34, 34, 112, 34, 112,
- 34, 112, 214, 113, 214, 79, 93, 34, 93, 88,
- 34, 34, 34, 34, 34, 26, 90, 26, 26, 113,
- 113, 26, 87, 26, 87, 87, 87, 121, 87, 121,
- 87, 99, 107, 26, 26, 26, 26, 26, 161, 108,
- 87, 87, 87, 87, 87, 153, 109, 153, 153, 153,
- 124, 153, 124, 153, 161, 161, 157, 166, 157, 166,
- 153, 115, 116, 153, 153, 153, 153, 153, 154, 123,
- 154, 154, 154, 58, 154, 58, 154, 58, 94, 58,
- 94, 128, 94, 154, 94, 129, 154, 154, 154, 154,
- 154, 265, 132, 265, 265, 265, 167, 265, 167, 265,
- 133, 12, 12, 12, 144, 12, 265, 12, 158, 265,
- 265, 265, 265, 265, 160, 162, 163, 12, 12, 12,
- 12, 12, 13, 13, 13, 169, 13, 178, 13, 36,
- 36, 36, 189, 36, 202, 36, 213, 218, 13, 13,
- 13, 13, 13, 220, 222, 36, 36, 36, 36, 36,
- 62, 62, 62, 225, 62, 230, 62, 64, 64, 232,
- 236, 64, 238, 64, 245, 253, 62, 62, 62, 62,
- 62, 256, 257, 64, 64, 64, 64, 64, 68, 68,
- 68, 260, 68, 264, 68, 69, 69, 267, 268, 69,
- 271, 69, 273, 274, 68, 68, 68, 68, 68, 280,
- 281, 69, 69, 69, 69, 69, 70, 70, 70, 283,
- 70, 284, 70, 75, 75, 75, 285, 75, 288, 75,
- 290, 292, 70, 70, 70, 70, 70, 293, 295, 75,
- 75, 75, 75, 75, 103, 103, 103, 300, 103, 304,
- 103, 104, 104, 104, 307, 104, 308, 104, 311, 312,
- 103, 103, 103, 103, 103, 313, 316, 104, 104, 104,
- 104, 104, 111, 111, nil, nil, 111, nil, 111, 117,
- 117, nil, nil, 117, nil, 117, nil, nil, 111, 111,
- 111, 111, 111, nil, nil, 117, 117, 117, 117, 117,
- 118, 118, 118, nil, 118, nil, 118, 126, 126, 126,
- nil, 126, nil, 126, nil, nil, 118, 118, 118, 118,
- 118, nil, nil, 126, 126, 126, 126, 126, 130, 130,
- 130, nil, 130, nil, 130, 143, 143, 143, nil, 143,
- nil, 143, nil, nil, 130, 130, 130, 130, 130, nil,
- nil, 143, 143, 143, 143, 143, 145, 145, 145, nil,
- 145, nil, 145, 146, 146, nil, nil, 146, nil, 146,
- nil, nil, 145, 145, 145, 145, 145, nil, nil, 146,
- 146, 146, 146, 146, 148, 148, 148, nil, 148, nil,
- 148, 149, 149, 149, nil, 149, nil, 149, nil, nil,
- 148, 148, 148, 148, 148, nil, nil, 149, 149, 149,
- 149, 149, 150, 150, 150, nil, 150, nil, 150, 205,
- 205, 205, nil, 205, nil, 205, nil, nil, 150, 150,
- 150, 150, 150, nil, nil, 205, 205, 205, 205, 205,
- 215, 215, nil, nil, 215, nil, 215, 216, 216, 216,
- nil, 216, nil, 216, nil, nil, 215, 215, 215, 215,
- 215, nil, nil, 216, 216, 216, 216, 216, 217, 217,
- 217, nil, 217, nil, 217, 240, 240, 240, nil, 240,
- nil, 240, nil, nil, 217, 217, 217, 217, 217, nil,
- nil, 240, 240, 240, 240, 240, 244, 244, 244, nil,
- 244, nil, 244, 247, 247, 247, nil, 247, nil, 247,
- nil, nil, 244, 244, 244, 244, 244, nil, nil, 247,
- 247, 247, 247, 247, 249, 249, 249, nil, 249, nil,
- 249, 250, 250, 250, nil, 250, nil, 250, nil, nil,
- 249, 249, 249, 249, 249, nil, nil, 250, 250, 250,
- 250, 250, 251, 251, 251, nil, 251, nil, 251, 262,
- 262, 262, nil, 262, nil, 262, nil, nil, 251, 251,
- 251, 251, 251, nil, nil, 262, 262, 262, 262, 262,
- 263, 263, 263, nil, 263, nil, 263, 310, 310, 310,
- nil, 310, nil, 310, nil, nil, 263, 263, 263, 263,
- 263, 57, nil, 310, 310, 310, 310, 310, 168, 168,
- 168, 57, 168, 57, 168, 57, 212, 57, nil, 254,
- nil, nil, nil, nil, 168, nil, 212, 261, 212, 254,
- 212, 254, 212, 254, 95, 254, 95, 261, 95, 261,
- 95, 261, nil, 261, 270, 270, 270, nil, 270, nil,
- 270, 275, 275, 275, nil, 275, nil, 275, nil, nil,
- 270, nil, 296, 296, 296, nil, 296, 275, 296, 297,
- 297, 297, nil, 297, nil, 297, nil, nil, 296, nil,
- 101, 101, 101, nil, 101, 297, 101, 110, 110, nil,
- 125, 110, 125, 110, 125, 159, 125, 159, 190, 159,
- 190, 159, 190, 191, 190, 191, 233, 191, 233, 191,
- 233, 234, 233, 234, nil, 234, nil, 234, 239, 239,
- 239, 255, 239, 255, 239, 255, nil, 255 ]
-
-racc_action_pointer = [
- 63, 4, nil, nil, nil, 0, nil, nil, nil, 2,
- 26, nil, 245, 266, -11, nil, 21, 18, 49, nil,
- nil, nil, 54, 78, 82, nil, 161, nil, nil, nil,
- nil, nil, nil, 112, 138, nil, 273, 42, 60, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 110, 89, nil, 70, nil, -15, 745, 217, 102,
- 103, nil, 294, -5, 301, nil, 107, 86, 322, 329,
- 350, 129, 100, -5, 126, 357, nil, 117, 115, 137,
- nil, nil, nil, nil, nil, nil, nil, 168, 142, 33,
- 146, 70, 118, 148, 222, 768, nil, nil, 121, 176,
- nil, 814, nil, 378, 385, nil, nil, 180, 193, 194,
- 821, 406, 141, 149, nil, 209, 216, 413, 434, nil,
- nil, 169, nil, 199, 192, 824, 441, 2, 235, 240,
- 462, nil, 238, 254, 40, nil, nil, nil, nil, nil,
- nil, nil, nil, 469, 260, 490, 497, 133, 518, 525,
- 546, 26, nil, 191, 214, nil, nil, 198, 256, 829,
- 262, 184, 263, 246, nil, nil, 199, 238, 742, 270,
- nil, nil, nil, nil, nil, nil, nil, nil, 273, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 280,
- 832, 837, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 282, nil, nil, 553, nil, nil, nil, nil,
- nil, nil, 760, 282, 144, 574, 581, 602, 291, nil,
- 289, nil, 290, nil, 33, 285, nil, nil, nil, nil,
- 303, nil, 307, 840, 845, nil, 308, nil, 307, 852,
- 609, nil, nil, nil, 630, 309, nil, 637, nil, 658,
- 665, 686, nil, 307, 763, 855, 301, 302, nil, nil,
- 335, 771, 693, 714, 329, 237, nil, 317, 318, nil,
- 778, 335, nil, 337, 338, 785, nil, nil, nil, nil,
- 341, 354, nil, 357, 359, 364, nil, nil, 372, nil,
- 374, nil, 369, 375, nil, 370, 796, 803, nil, nil,
- 382, nil, nil, nil, 369, nil, nil, 374, 388, nil,
- 721, 390, 397, 403, nil, nil, 398, nil, nil, nil ]
-
-racc_action_default = [
- -176, -176, -1, -2, -3, -4, -5, -6, -7, -8,
- -9, -10, -176, -176, -34, -35, -36, -37, -38, -39,
- -40, -41, -176, -49, -51, -52, -176, -64, -67, -68,
- -69, -70, -71, -176, -176, -107, -176, -109, -110, -111,
- -128, -129, -130, -131, -132, -133, -134, -135, -136, -137,
- -138, -176, -176, -76, -176, -112, -176, -176, -176, -8,
- -9, -11, -176, -176, -176, -72, -176, -176, -55, -176,
- -170, -176, -8, -9, -10, -176, -38, -176, -81, -86,
- -87, -88, -90, -91, -92, -93, -94, -176, -176, -176,
- -176, -176, -176, -176, -176, -176, 320, -12, -13, -176,
- -16, -176, -31, -176, -176, -152, -27, -29, -176, -126,
- -176, -176, -176, -176, -28, -30, -176, -176, -176, -153,
- -160, -176, -162, -176, -176, -176, -176, -176, -176, -176,
- -73, -174, -176, -176, -8, -47, -48, -49, -50, -51,
- -53, -54, -58, -56, -176, -171, -176, -176, -98, -97,
- -96, -176, -79, -176, -176, -95, -80, -176, -176, -176,
- -126, -176, -126, -176, -14, -18, -176, -176, -176, -176,
- -147, -148, -149, -150, -145, -151, -146, -114, -44, -59,
- -127, -60, -61, -62, -63, -139, -140, -141, -142, -176,
- -176, -176, -120, -45, -154, -155, -156, -157, -158, -159,
- -161, -163, -176, -29, -30, -176, -26, -42, -77, -43,
- -78, -175, -176, -176, -176, -176, -172, -74, -176, -101,
- -176, -100, -176, -99, -176, -83, -84, -85, -89, -108,
- -176, -113, -176, -176, -176, -117, -176, -19, -176, -176,
- -176, -143, -20, -21, -176, -176, -32, -176, -164, -176,
- -176, -176, -169, -176, -176, -115, -176, -176, -121, -102,
- -176, -176, -75, -173, -44, -176, -116, -176, -176, -118,
- -176, -176, -144, -176, -176, -176, -168, -165, -166, -167,
- -176, -176, -106, -126, -176, -176, -105, -103, -176, -57,
- -176, -82, -176, -176, -23, -176, -176, -176, -15, -33,
- -176, -46, -119, -122, -176, -104, -124, -176, -176, -25,
- -176, -176, -176, -176, -24, -22, -176, -123, -125, -17 ]
-
-racc_goto_table = [
- 70, 179, 130, 13, 228, 11, 248, 115, 123, 226,
- 227, 113, 245, 5, 14, 9, 63, 11, 68, 10,
- 18, 132, 22, 23, 71, 1, 24, 59, 237, 243,
- 2, 60, 309, 309, 241, 241, 75, 75, 131, 77,
- 88, 3, 4, 70, 162, 163, 6, 160, 161, 61,
- 97, 89, 231, 98, 235, 91, 164, 99, 298, 100,
- 242, 143, 102, 299, 15, 126, 127, 144, 16, 17,
- 75, 142, 11, 145, 135, 204, 109, 174, 151, 203,
- 136, 138, 134, 27, 217, 185, 10, 18, 28, 140,
- 137, 174, 11, 139, 29, 30, 31, 32, 225, 90,
- 155, 105, 59, nil, nil, nil, 60, 176, 248, 230,
- nil, nil, nil, 248, 294, 228, nil, nil, nil, nil,
- 131, 291, nil, nil, nil, nil, nil, nil, nil, 205,
- 206, nil, nil, 211, 248, 248, nil, nil, nil, nil,
- 256, 257, nil, nil, nil, nil, 142, nil, 216, nil,
- nil, nil, nil, 262, 224, 223, 75, 75, nil, nil,
- nil, nil, 259, 219, 220, 220, nil, nil, 221, 222,
- nil, nil, nil, nil, nil, 302, nil, nil, nil, nil,
- nil, nil, nil, 267, 268, nil, nil, nil, nil, 131,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 282, 283, nil, nil, 206, nil,
- nil, 287, nil, nil, 185, nil, nil, nil, 185, 263,
- 211, 174, nil, nil, nil, nil, nil, 206, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 277, 278, 279, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 211, 289, nil, 75, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 174 ]
-
-racc_goto_check = [
- 43, 45, 52, 23, 58, 11, 66, 26, 26, 57,
- 57, 24, 16, 5, 30, 9, 23, 11, 42, 10,
- 34, 24, 38, 40, 53, 1, 41, 9, 19, 19,
- 2, 10, 22, 22, 25, 25, 23, 23, 43, 54,
- 54, 3, 4, 43, 26, 26, 6, 24, 24, 7,
- 12, 9, 45, 13, 45, 10, 14, 15, 17, 18,
- 20, 42, 28, 29, 31, 23, 23, 53, 32, 33,
- 23, 23, 11, 23, 39, 26, 44, 43, 23, 24,
- 5, 30, 9, 46, 52, 43, 10, 34, 47, 38,
- 40, 43, 11, 41, 48, 49, 50, 51, 56, 61,
- 5, 65, 9, nil, nil, nil, 10, 23, 66, 26,
- nil, nil, nil, 66, 16, 58, nil, nil, nil, nil,
- 43, 57, nil, nil, nil, nil, nil, nil, nil, 23,
- 23, nil, nil, 23, 66, 66, nil, nil, nil, nil,
- 26, 26, nil, nil, nil, nil, 23, nil, 23, nil,
- nil, nil, nil, 52, 23, 11, 23, 23, nil, nil,
- nil, nil, 26, 9, 9, 9, nil, nil, 10, 10,
- nil, nil, nil, nil, nil, 45, nil, nil, nil, nil,
- nil, nil, nil, 26, 26, nil, nil, nil, nil, 43,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 26, 26, nil, nil, 23, nil,
- nil, 26, nil, nil, 43, nil, nil, nil, 43, 23,
- 23, 43, nil, nil, nil, nil, nil, 23, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 23, 23, 23, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 23, 23, nil, 23, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 43 ]
-
-racc_goto_pointer = [
- nil, 25, 30, 41, 42, 13, 46, 37, nil, 15,
- 19, 5, -2, 1, -42, 5, -156, -217, 7, -138,
- -107, nil, -264, 3, -45, -132, -50, nil, 10, -212,
- 14, 64, 68, 69, 20, nil, nil, nil, 22, 7,
- 23, 26, -8, -26, 22, -108, 83, 88, 94, 95,
- 96, 97, -62, -2, 6, nil, -55, -144, -150, nil,
- nil, 63, nil, nil, nil, 49, -162, nil ]
-
-racc_goto_default = [
- nil, nil, nil, nil, nil, 84, nil, 7, 8, 72,
- 73, 74, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 238, 252, 62, 107, 106, nil, 114, nil, 246,
- 86, nil, nil, nil, 76, 19, 20, 21, nil, nil,
- 85, nil, nil, 41, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 78, 79, 80, 81, 82,
- 83, 35, 37, 38, 39, 119, 120, 122 ]
-
-racc_reduce_table = [
- 0, 0, :racc_error,
- 1, 38, :_reduce_none,
- 1, 38, :_reduce_none,
- 1, 38, :_reduce_none,
- 1, 39, :_reduce_none,
- 1, 39, :_reduce_none,
- 1, 42, :_reduce_none,
- 1, 42, :_reduce_none,
- 1, 44, :_reduce_8,
- 1, 44, :_reduce_9,
- 1, 44, :_reduce_10,
- 2, 45, :_reduce_11,
- 3, 43, :_reduce_12,
- 1, 49, :_reduce_none,
- 2, 49, :_reduce_14,
- 5, 50, :_reduce_15,
- 1, 50, :_reduce_none,
- 8, 55, :_reduce_17,
- 1, 51, :_reduce_18,
- 2, 51, :_reduce_19,
- 2, 51, :_reduce_20,
- 1, 57, :_reduce_none,
- 5, 57, :_reduce_22,
- 3, 56, :_reduce_23,
- 5, 56, :_reduce_24,
- 4, 56, :_reduce_25,
- 4, 46, :_reduce_26,
- 1, 61, :_reduce_none,
- 1, 63, :_reduce_none,
- 3, 47, :_reduce_29,
- 3, 48, :_reduce_30,
- 1, 52, :_reduce_none,
- 1, 53, :_reduce_none,
- 1, 54, :_reduce_none,
- 1, 40, :_reduce_none,
- 1, 40, :_reduce_none,
- 1, 40, :_reduce_none,
- 1, 40, :_reduce_none,
- 1, 67, :_reduce_38,
- 1, 67, :_reduce_none,
- 1, 67, :_reduce_none,
- 1, 67, :_reduce_none,
- 4, 71, :_reduce_42,
- 4, 71, :_reduce_43,
- 4, 72, :_reduce_44,
- 4, 73, :_reduce_45,
- 7, 74, :_reduce_46,
- 3, 68, :_reduce_47,
- 1, 75, :_reduce_none,
- 1, 75, :_reduce_none,
- 1, 75, :_reduce_none,
- 1, 75, :_reduce_none,
- 1, 75, :_reduce_none,
- 1, 76, :_reduce_none,
- 1, 76, :_reduce_none,
- 2, 69, :_reduce_55,
- 3, 69, :_reduce_56,
- 5, 79, :_reduce_57,
- 2, 79, :_reduce_58,
- 4, 70, :_reduce_59,
- 2, 81, :_reduce_60,
- 2, 81, :_reduce_61,
- 2, 81, :_reduce_62,
- 2, 81, :_reduce_63,
- 1, 41, :_reduce_none,
- 1, 41, :_reduce_none,
- 1, 41, :_reduce_none,
- 1, 41, :_reduce_none,
- 1, 41, :_reduce_none,
- 1, 41, :_reduce_none,
- 1, 41, :_reduce_none,
- 1, 41, :_reduce_none,
- 2, 83, :_reduce_72,
- 3, 88, :_reduce_73,
- 4, 88, :_reduce_74,
- 5, 88, :_reduce_75,
- 2, 87, :_reduce_76,
- 4, 86, :_reduce_77,
- 4, 86, :_reduce_78,
- 3, 84, :_reduce_79,
- 3, 85, :_reduce_80,
- 1, 91, :_reduce_81,
- 5, 91, :_reduce_82,
- 3, 91, :_reduce_83,
- 3, 91, :_reduce_84,
- 3, 91, :_reduce_85,
- 1, 91, :_reduce_86,
- 1, 91, :_reduce_87,
- 1, 93, :_reduce_88,
- 3, 93, :_reduce_89,
- 1, 95, :_reduce_none,
- 1, 95, :_reduce_none,
- 1, 96, :_reduce_none,
- 1, 96, :_reduce_none,
- 1, 96, :_reduce_none,
- 2, 92, :_reduce_95,
- 2, 94, :_reduce_96,
- 2, 94, :_reduce_97,
- 2, 94, :_reduce_98,
- 3, 97, :_reduce_99,
- 3, 97, :_reduce_100,
- 3, 97, :_reduce_101,
- 5, 78, :_reduce_102,
- 6, 78, :_reduce_103,
- 7, 78, :_reduce_104,
- 6, 78, :_reduce_105,
- 6, 78, :_reduce_106,
- 1, 77, :_reduce_none,
- 4, 77, :_reduce_108,
- 1, 98, :_reduce_109,
- 1, 98, :_reduce_110,
- 1, 98, :_reduce_111,
- 2, 99, :_reduce_112,
- 4, 100, :_reduce_113,
- 4, 100, :_reduce_114,
- 5, 100, :_reduce_115,
- 5, 100, :_reduce_116,
- 4, 101, :_reduce_117,
- 5, 101, :_reduce_118,
- 7, 101, :_reduce_119,
- 4, 101, :_reduce_120,
- 5, 101, :_reduce_121,
- 7, 101, :_reduce_122,
- 9, 101, :_reduce_123,
- 7, 101, :_reduce_124,
- 9, 101, :_reduce_125,
- 0, 82, :_reduce_126,
- 1, 82, :_reduce_none,
- 1, 60, :_reduce_128,
- 1, 60, :_reduce_none,
- 1, 80, :_reduce_none,
- 1, 80, :_reduce_none,
- 1, 80, :_reduce_none,
- 1, 80, :_reduce_none,
- 1, 80, :_reduce_none,
- 1, 80, :_reduce_none,
- 1, 80, :_reduce_none,
- 1, 80, :_reduce_none,
- 1, 80, :_reduce_none,
- 2, 62, :_reduce_139,
- 2, 62, :_reduce_140,
- 2, 62, :_reduce_141,
- 2, 62, :_reduce_142,
- 1, 58, :_reduce_none,
- 2, 58, :_reduce_144,
- 2, 102, :_reduce_145,
- 2, 102, :_reduce_146,
- 2, 102, :_reduce_147,
- 2, 102, :_reduce_148,
- 2, 102, :_reduce_149,
- 2, 102, :_reduce_150,
- 2, 65, :_reduce_none,
- 1, 65, :_reduce_none,
- 1, 103, :_reduce_none,
- 2, 103, :_reduce_154,
- 2, 103, :_reduce_155,
- 2, 103, :_reduce_156,
- 2, 103, :_reduce_157,
- 2, 103, :_reduce_158,
- 2, 103, :_reduce_159,
- 1, 104, :_reduce_none,
- 2, 104, :_reduce_161,
- 1, 64, :_reduce_none,
- 2, 64, :_reduce_163,
- 1, 59, :_reduce_none,
- 2, 59, :_reduce_165,
- 2, 59, :_reduce_166,
- 2, 59, :_reduce_167,
- 2, 66, :_reduce_none,
- 1, 66, :_reduce_none,
- 1, 90, :_reduce_170,
- 2, 90, :_reduce_171,
- 3, 90, :_reduce_172,
- 4, 90, :_reduce_173,
- 1, 89, :_reduce_174,
- 2, 89, :_reduce_175 ]
-
-racc_reduce_n = 176
-
-racc_shift_n = 320
-
-racc_token_table = {
- false => 0,
- :error => 1,
- :T => 2,
- :Z => 3,
- :E => 4,
- :X => 5,
- :U => 6,
- :UNKNOWN => 7,
- :OPEN => 8,
- :LONGYEAR => 9,
- :UNMATCHED => 10,
- :DOTS => 11,
- :UA => 12,
- :PUA => 13,
- "-" => 14,
- ":" => 15,
- "2" => 16,
- "4" => 17,
- "0" => 18,
- "+" => 19,
- "1" => 20,
- "/" => 21,
- "3" => 22,
- "^" => 23,
- "[" => 24,
- "]" => 25,
- "{" => 26,
- "}" => 27,
- "," => 28,
- "(" => 29,
- ")" => 30,
- "-(" => 31,
- "5" => 32,
- "6" => 33,
- "7" => 34,
- "8" => 35,
- "9" => 36 }
-
-racc_nt_base = 37
-
-racc_use_result_var = true
-
-Racc_arg = [
- racc_action_table,
- racc_action_check,
- racc_action_default,
- racc_action_pointer,
- racc_goto_table,
- racc_goto_check,
- racc_goto_default,
- racc_goto_pointer,
- racc_nt_base,
- racc_reduce_table,
- racc_token_table,
- racc_shift_n,
- racc_reduce_n,
- racc_use_result_var ]
-
-Racc_token_to_s_table = [
- "$end",
- "error",
- "T",
- "Z",
- "E",
- "X",
- "U",
- "UNKNOWN",
- "OPEN",
- "LONGYEAR",
- "UNMATCHED",
- "DOTS",
- "UA",
- "PUA",
- "\"-\"",
- "\":\"",
- "\"2\"",
- "\"4\"",
- "\"0\"",
- "\"+\"",
- "\"1\"",
- "\"/\"",
- "\"3\"",
- "\"^\"",
- "\"[\"",
- "\"]\"",
- "\"{\"",
- "\"}\"",
- "\",\"",
- "\"(\"",
- "\")\"",
- "\"-(\"",
- "\"5\"",
- "\"6\"",
- "\"7\"",
- "\"8\"",
- "\"9\"",
- "$start",
- "edtf",
- "level_0_expression",
- "level_1_expression",
- "level_2_expression",
- "date",
- "date_time",
- "positive_date",
- "negative_date",
- "year",
- "year_month",
- "year_month_day",
- "time",
- "base_time",
- "zone_offset",
- "hour",
- "minute",
- "second",
- "midnight",
- "zone_offset_hour",
- "positive_zone_offset",
- "d01_13",
- "d01_59",
- "digit",
- "month",
- "d01_12",
- "day",
- "d01_31",
- "d00_23",
- "d00_59",
- "unspecified",
- "level_1_interval",
- "long_year_simple",
- "season",
- "unspecified_year",
- "unspecified_month",
- "unspecified_day",
- "unspecified_day_and_month",
- "level_1_start",
- "level_1_end",
- "partial_uncertain_or_approximate",
- "partial_unspecified",
- "long_year",
- "positive_digit",
- "season_number",
- "ua",
- "season_qualified",
- "choice_list",
- "inclusive_list",
- "masked_precision",
- "date_and_calendar",
- "long_year_scientific",
- "integer",
- "int1_4",
- "list",
- "earlier",
- "list_elements",
- "later",
- "list_element",
- "atomic",
- "consecutives",
- "pua_base",
- "pua_year",
- "pua_year_month",
- "pua_year_month_day",
- "d01_23",
- "d01_29",
- "d01_30" ]
-
-Racc_debug_parser = false
-
-##### State transition tables end #####
-
-# reduce 0 omitted
-
-# reduce 1 omitted
-
-# reduce 2 omitted
-
-# reduce 3 omitted
-
-# reduce 4 omitted
-
-# reduce 5 omitted
-
-# reduce 6 omitted
-
-# reduce 7 omitted
-
-module_eval(<<'.,.,', 'edtf.y', 54)
- def _reduce_8(val, _values, result)
- result = Date.new(val[0]).year_precision!
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 55)
- def _reduce_9(val, _values, result)
- result = Date.new(*val.flatten).month_precision!
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 56)
- def _reduce_10(val, _values, result)
- result = Date.new(*val.flatten).day_precision!
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 59)
- def _reduce_11(val, _values, result)
- result = -val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 63)
- def _reduce_12(val, _values, result)
- result = DateTime.new(val[0].year, val[0].month, val[0].day, *val[2])
- result.skip_timezone = (val[2].length == 3)
-
- result
- end
-.,.,
-
-# reduce 13 omitted
-
-module_eval(<<'.,.,', 'edtf.y', 68)
- def _reduce_14(val, _values, result)
- result = val.flatten
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 70)
- def _reduce_15(val, _values, result)
- result = val.values_at(0, 2, 4)
- result
- end
-.,.,
-
-# reduce 16 omitted
-
-module_eval(<<'.,.,', 'edtf.y', 73)
- def _reduce_17(val, _values, result)
- result = [24, 0, 0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 75)
- def _reduce_18(val, _values, result)
- result = 0
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 76)
- def _reduce_19(val, _values, result)
- result = -1 * val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 77)
- def _reduce_20(val, _values, result)
- result = val[1]
- result
- end
-.,.,
-
-# reduce 21 omitted
-
-module_eval(<<'.,.,', 'edtf.y', 81)
- def _reduce_22(val, _values, result)
- result = 0
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 85)
- def _reduce_23(val, _values, result)
- result = Rational(val[0] * 60 + val[2], 1440)
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 86)
- def _reduce_24(val, _values, result)
- result = Rational(840, 1440)
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 87)
- def _reduce_25(val, _values, result)
- result = Rational(val[3], 1440)
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 91)
- def _reduce_26(val, _values, result)
- result = val.zip([1000,100,10,1]).reduce(0) { |s,(a,b)| s += a * b }
-
- result
- end
-.,.,
-
-# reduce 27 omitted
-
-# reduce 28 omitted
-
-module_eval(<<'.,.,', 'edtf.y', 97)
- def _reduce_29(val, _values, result)
- result = [val[0], val[2]]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 104)
- def _reduce_30(val, _values, result)
- result = val[0] << val[2]
- if result[2] > 31 || (result[2] > 30 && [2,4,6,9,11].include?(result[1])) || (result[2] > 29 && result[1] == 2)
- raise ArgumentError, "invalid date (invalid days #{result[2]} for month #{result[1]})"
- end
-
- result
- end
-.,.,
-
-# reduce 31 omitted
-
-# reduce 32 omitted
-
-# reduce 33 omitted
-
-# reduce 34 omitted
-
-# reduce 35 omitted
-
-# reduce 36 omitted
-
-# reduce 37 omitted
-
-module_eval(<<'.,.,', 'edtf.y', 127)
- def _reduce_38(val, _values, result)
- result = Date.new(val[0][0]).year_precision!
- result.unspecified.year[2,2] = val[0][1]
-
- result
- end
-.,.,
-
-# reduce 39 omitted
-
-# reduce 40 omitted
-
-# reduce 41 omitted
-
-module_eval(<<'.,.,', 'edtf.y', 138)
- def _reduce_42(val, _values, result)
- result = [val[0,3].zip([1000,100,10]).reduce(0) { |s,(a,b)| s += a * b }, [false,true]]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 142)
- def _reduce_43(val, _values, result)
- result = [val[0,2].zip([1000,100]).reduce(0) { |s,(a,b)| s += a * b }, [true, true]]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 146)
- def _reduce_44(val, _values, result)
- result = Date.new(val[0]).unspecified!(:month)
- result.precision = :month
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 151)
- def _reduce_45(val, _values, result)
- result = Date.new(*val[0]).unspecified!(:day)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 155)
- def _reduce_46(val, _values, result)
- result = Date.new(val[0]).unspecified!([:day,:month])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 160)
- def _reduce_47(val, _values, result)
- result = Interval.new(val[0], val[2])
-
- result
- end
-.,.,
-
-# reduce 48 omitted
-
-# reduce 49 omitted
-
-# reduce 50 omitted
-
-# reduce 51 omitted
-
-# reduce 52 omitted
-
-# reduce 53 omitted
-
-# reduce 54 omitted
-
-module_eval(<<'.,.,', 'edtf.y', 171)
- def _reduce_55(val, _values, result)
- result = Date.new(val[1])
- result.precision = :year
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 176)
- def _reduce_56(val, _values, result)
- result = Date.new(-1 * val[2])
- result.precision = :year
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 183)
- def _reduce_57(val, _values, result)
- result = val.zip([10000,1000,100,10,1]).reduce(0) { |s,(a,b)| s += a * b }
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 185)
- def _reduce_58(val, _values, result)
- result = 10 * val[0] + val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 190)
- def _reduce_59(val, _values, result)
- result = Season.new(val[0], val[2])
- val[3].each { |ua| result.send(ua) }
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 194)
- def _reduce_60(val, _values, result)
- result = 21
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 195)
- def _reduce_61(val, _values, result)
- result = 22
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 196)
- def _reduce_62(val, _values, result)
- result = 23
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 197)
- def _reduce_63(val, _values, result)
- result = 24
- result
- end
-.,.,
-
-# reduce 64 omitted
-
-# reduce 65 omitted
-
-# reduce 66 omitted
-
-# reduce 67 omitted
-
-# reduce 68 omitted
-
-# reduce 69 omitted
-
-# reduce 70 omitted
-
-# reduce 71 omitted
-
-module_eval(<<'.,.,', 'edtf.y', 215)
- def _reduce_72(val, _values, result)
- result = val[0]; result.qualifier = val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 221)
- def _reduce_73(val, _values, result)
- result = Date.new(val[0].year * 10 ** val[2]).year_precision!
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 225)
- def _reduce_74(val, _values, result)
- result = Date.new(val[1] * 10 ** val[3]).year_precision!
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 229)
- def _reduce_75(val, _values, result)
- result = Date.new(-1 * val[2] * 10 ** val[4]).year_precision!
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 234)
- def _reduce_76(val, _values, result)
- result = val[0]; result.calendar = val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 240)
- def _reduce_77(val, _values, result)
- d = val[0,3].zip([1000,100,10]).reduce(0) { |s,(a,b)| s += a * b }
- result = EDTF::Decade.new(d)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 245)
- def _reduce_78(val, _values, result)
- d = val[0,2].zip([1000,100]).reduce(0) { |s,(a,b)| s += a * b }
- result = EDTF::Century.new(d)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 251)
- def _reduce_79(val, _values, result)
- result = val[1].choice!
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 253)
- def _reduce_80(val, _values, result)
- result = val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 255)
- def _reduce_81(val, _values, result)
- result = EDTF::Set.new(val[0]).earlier!
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 256)
- def _reduce_82(val, _values, result)
- result = EDTF::Set.new([val[0]] + val[2] + [val[4]]).earlier!.later!
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 257)
- def _reduce_83(val, _values, result)
- result = EDTF::Set.new([val[0]] + val[2]).earlier!
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 258)
- def _reduce_84(val, _values, result)
- result = EDTF::Set.new([val[0]] + [val[2]]).earlier!.later!
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 259)
- def _reduce_85(val, _values, result)
- result = EDTF::Set.new(val[0] + [val[2]]).later!
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 260)
- def _reduce_86(val, _values, result)
- result = EDTF::Set.new(*val[0])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 261)
- def _reduce_87(val, _values, result)
- result = EDTF::Set.new(val[0]).later!
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 264)
- def _reduce_88(val, _values, result)
- result = [val[0]].flatten
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 265)
- def _reduce_89(val, _values, result)
- result = val[0] + [val[2]].flatten
- result
- end
-.,.,
-
-# reduce 90 omitted
-
-# reduce 91 omitted
-
-# reduce 92 omitted
-
-# reduce 93 omitted
-
-# reduce 94 omitted
-
-module_eval(<<'.,.,', 'edtf.y', 277)
- def _reduce_95(val, _values, result)
- result = val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 279)
- def _reduce_96(val, _values, result)
- result = Date.new(*val[0]).year_precision!
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 280)
- def _reduce_97(val, _values, result)
- result = Date.new(*val[0]).month_precision!
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 281)
- def _reduce_98(val, _values, result)
- result = Date.new(val[0]).year_precision!
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 284)
- def _reduce_99(val, _values, result)
- result = (Date.new(val[0]).day_precision! .. Date.new(val[2]).day_precision!)
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 285)
- def _reduce_100(val, _values, result)
- result = (Date.new(val[0]).month_precision! .. Date.new(val[2]).month_precision!)
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 286)
- def _reduce_101(val, _values, result)
- result = (Date.new(val[0]).year_precision! .. Date.new(val[2]).year_precision!)
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 292)
- def _reduce_102(val, _values, result)
- result = Date.new(val[0][0], val[2], val[4])
- result.unspecified.year[2,2] = val[0][1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 297)
- def _reduce_103(val, _values, result)
- result = Date.new(val[0][0], 1, val[5])
- result.unspecified.year[2,2] = val[0][1]
- result.unspecified!(:month)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 303)
- def _reduce_104(val, _values, result)
- result = Date.new(val[0][0], 1, 1)
- result.unspecified.year[2,2] = val[0][1]
- result.unspecified!([:month, :day])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 309)
- def _reduce_105(val, _values, result)
- result = Date.new(val[0][0], val[2], 1)
- result.unspecified.year[2,2] = val[0][1]
- result.unspecified!(:day)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 315)
- def _reduce_106(val, _values, result)
- result = Date.new(val[0], 1, val[5])
- result.unspecified!(:month)
-
- result
- end
-.,.,
-
-# reduce 107 omitted
-
-module_eval(<<'.,.,', 'edtf.y', 322)
- def _reduce_108(val, _values, result)
- result = uoa(val[1], val[3])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 325)
- def _reduce_109(val, _values, result)
- result = val[0].year_precision!
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 326)
- def _reduce_110(val, _values, result)
- result = val[0][0].month_precision!
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 327)
- def _reduce_111(val, _values, result)
- result = val[0].day_precision!
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 329)
- def _reduce_112(val, _values, result)
- result = uoa(Date.new(val[0]), val[1], :year)
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 333)
- def _reduce_113(val, _values, result)
- result = [uoa(val[0].change(:month => val[2]), val[3], [:month, :year])]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 336)
- def _reduce_114(val, _values, result)
- result = [uoa(Date.new(val[0], val[2]), val[3], [:year, :month])]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 339)
- def _reduce_115(val, _values, result)
- result = [uoa(Date.new(val[0], val[2]), val[4], [:month]), true]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 342)
- def _reduce_116(val, _values, result)
- result = [uoa(val[0].change(:month => val[2]), val[4], [:month]), true]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 348)
- def _reduce_117(val, _values, result)
- result = uoa(val[0][0].change(:day => val[2]), val[3], val[0][1] ? [:day] : nil)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 351)
- def _reduce_118(val, _values, result)
- result = uoa(val[0][0].change(:day => val[2]), val[4], [:day])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 354)
- def _reduce_119(val, _values, result)
- result = uoa(uoa(Date.new(val[0], val[2], val[5]), val[4], :month), val[6], :day)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 357)
- def _reduce_120(val, _values, result)
- result = uoa(Date.new(val[0][0], val[0][1], val[2]), val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 360)
- def _reduce_121(val, _values, result)
- result = uoa(Date.new(val[0][0], val[0][1], val[2]), val[4], [:day])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 363)
- def _reduce_122(val, _values, result)
- result = uoa(Date.new(val[0], val[2], val[4]), val[6], [:month, :day])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 366)
- def _reduce_123(val, _values, result)
- result = Date.new(val[0], val[2], val[4])
- result = uoa(result, val[6], [:day])
- result = uoa(result, val[8], [:month, :day])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 371)
- def _reduce_124(val, _values, result)
- result = val[0].change(:month => val[2], :day => val[4])
- result = uoa(result, val[6], [:month, :day])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 375)
- def _reduce_125(val, _values, result)
- result = val[0].change(:month => val[2], :day => val[4])
- result = uoa(result, val[6], [:day])
- result = uoa(result, val[8], [:month, :day])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 386)
- def _reduce_126(val, _values, result)
- result = []
- result
- end
-.,.,
-
-# reduce 127 omitted
-
-module_eval(<<'.,.,', 'edtf.y', 390)
- def _reduce_128(val, _values, result)
- result = 0
- result
- end
-.,.,
-
-# reduce 129 omitted
-
-# reduce 130 omitted
-
-# reduce 131 omitted
-
-# reduce 132 omitted
-
-# reduce 133 omitted
-
-# reduce 134 omitted
-
-# reduce 135 omitted
-
-# reduce 136 omitted
-
-# reduce 137 omitted
-
-# reduce 138 omitted
-
-module_eval(<<'.,.,', 'edtf.y', 396)
- def _reduce_139(val, _values, result)
- result = val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 397)
- def _reduce_140(val, _values, result)
- result = 10
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 398)
- def _reduce_141(val, _values, result)
- result = 11
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 399)
- def _reduce_142(val, _values, result)
- result = 12
- result
- end
-.,.,
-
-# reduce 143 omitted
-
-module_eval(<<'.,.,', 'edtf.y', 403)
- def _reduce_144(val, _values, result)
- result = 13
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 406)
- def _reduce_145(val, _values, result)
- result = val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 407)
- def _reduce_146(val, _values, result)
- result = 10 + val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 408)
- def _reduce_147(val, _values, result)
- result = 20
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 409)
- def _reduce_148(val, _values, result)
- result = 21
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 410)
- def _reduce_149(val, _values, result)
- result = 22
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 411)
- def _reduce_150(val, _values, result)
- result = 23
- result
- end
-.,.,
-
-# reduce 151 omitted
-
-# reduce 152 omitted
-
-# reduce 153 omitted
-
-module_eval(<<'.,.,', 'edtf.y', 419)
- def _reduce_154(val, _values, result)
- result = 24
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 420)
- def _reduce_155(val, _values, result)
- result = 25
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 421)
- def _reduce_156(val, _values, result)
- result = 26
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 422)
- def _reduce_157(val, _values, result)
- result = 27
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 423)
- def _reduce_158(val, _values, result)
- result = 28
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 424)
- def _reduce_159(val, _values, result)
- result = 29
- result
- end
-.,.,
-
-# reduce 160 omitted
-
-module_eval(<<'.,.,', 'edtf.y', 428)
- def _reduce_161(val, _values, result)
- result = 30
- result
- end
-.,.,
-
-# reduce 162 omitted
-
-module_eval(<<'.,.,', 'edtf.y', 432)
- def _reduce_163(val, _values, result)
- result = 31
- result
- end
-.,.,
-
-# reduce 164 omitted
-
-module_eval(<<'.,.,', 'edtf.y', 436)
- def _reduce_165(val, _values, result)
- result = 30 + val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 437)
- def _reduce_166(val, _values, result)
- result = 40 + val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 438)
- def _reduce_167(val, _values, result)
- result = 50 + val[1]
- result
- end
-.,.,
-
-# reduce 168 omitted
-
-# reduce 169 omitted
-
-module_eval(<<'.,.,', 'edtf.y', 445)
- def _reduce_170(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 446)
- def _reduce_171(val, _values, result)
- result = 10 * val[0] + val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 449)
- def _reduce_172(val, _values, result)
- result = val.zip([100,10,1]).reduce(0) { |s,(a,b)| s += a * b }
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 453)
- def _reduce_173(val, _values, result)
- result = val.zip([1000,100,10,1]).reduce(0) { |s,(a,b)| s += a * b }
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 457)
- def _reduce_174(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'edtf.y', 458)
- def _reduce_175(val, _values, result)
- result = 10 * val[0] + val[1]
- result
- end
-.,.,
-
-def _reduce_none(val, _values, result)
- val[0]
-end
-
- end # class Parser
-end # module EDTF
diff --git a/test/racc/regress/huia b/test/racc/regress/huia
deleted file mode 100644
index cac22873df..0000000000
--- a/test/racc/regress/huia
+++ /dev/null
@@ -1,1681 +0,0 @@
-#
-# DO NOT MODIFY!!!!
-# This file is automatically generated by Racc 1.5.2
-# from Racc grammar file "".
-#
-
-require 'racc/parser.rb'
-module Huia
- class Parser < Racc::Parser
-
-module_eval(<<'...end huia.y/module_eval...', 'huia.y', 211)
-
-attr_accessor :lexer, :scopes, :state
-
-def initialize lexer
- @lexer = lexer
- @state = []
- @scopes = []
- push_scope
-end
-
-def ast
- @ast ||= do_parse
- @scopes.first
-end
-
-def on_error t, val, vstack
- line = lexer.line
- col = lexer.column
- message = "Unexpected #{token_to_str t} at #{lexer.filename} line #{line}:#{col}:\n\n"
-
- start = line - 5 > 0 ? line - 5 : 0
- i_size = line.to_s.size
- (start..(start + 5)).each do |i|
- message << sprintf("\t%#{i_size}d: %s\n", i, lexer.get_line(i))
- message << "\t#{' ' * i_size} #{'-' * (col - 1)}^\n" if i == line
- end
-
- raise SyntaxError, message
-end
-
-def next_token
- nt = lexer.next_computed_token
- # just use a state stack for now, we'll have to do something
- # more sophisticated soon.
- if nt && nt.first == :state
- if nt.last
- state.push << nt.last
- else
- state.pop
- end
- next_token
- else
- nt
- end
-end
-
-def push_scope
- new_scope = Huia::AST::Scope.new scope
- new_scope.file = lexer.filename
- new_scope.line = lexer.line
- new_scope.column = lexer.column
- scopes.push new_scope
- new_scope
-end
-
-def pop_scope
- scopes.pop
-end
-
-def scope
- scopes.last
-end
-
-def binary left, right, method
- node(:MethodCall, left, node(:CallSignature, method, [right]))
-end
-
-def unary left, method
- node(:MethodCall, left, node(:CallSignature, method))
-end
-
-def node type, *args
- Huia::AST.const_get(type).new(*args).tap do |n|
- n.file = lexer.filename
- n.line = lexer.line
- n.column = lexer.column
- end
-end
-alias n node
-
-def allocate_local name
- node(:Variable, name).tap do |n|
- scope.allocate_local n
- end
-end
-
-def allocate_local_assignment name, value
- node(:Assignment, name, value).tap do |n|
- scope.allocate_local n
- end
-end
-
-def this_closure
- allocate_local('@')
-end
-
-def scope_instance
- node(:ScopeInstance, scope)
-end
-
-def constant name
- return scope_instance if name == 'self'
- node(:Constant, name)
-end
-
-def to_string expr
- node(:MethodCall, expr, node(:CallSignature, 'toString'))
-end
-...end huia.y/module_eval...
-##### State transition tables begin ###
-
-racc_action_table = [
- 81, 106, 40, 37, 61, 62, 123, 153, 135, 71,
- 72, 77, 155, 178, 179, 39, 164, 37, 37, 5,
- 6, 137, 152, 73, 74, 75, 36, 36, 76, 28,
- 154, 80, 166, 172, 180, 22, 23, 37, 26, 27,
- 182, 60, 63, 19, 164, 40, 36, 61, 62, 186,
- nil, 33, 71, 72, 77, nil, nil, 134, 39, 133,
- 129, 37, 5, 6, nil, nil, 73, 74, 75, nil,
- 36, 76, 28, 134, 80, 169, 129, nil, 22, 23,
- nil, 26, 27, nil, 60, 63, 19, nil, 40, nil,
- 61, 62, nil, nil, 33, 71, 72, 77, nil, nil,
- nil, 39, nil, nil, 37, nil, nil, nil, nil, 73,
- 74, 75, nil, 36, 76, 28, nil, 80, nil, nil,
- nil, 22, 23, nil, 26, 27, nil, 60, 63, 19,
- nil, 40, nil, 61, 62, nil, nil, 33, 71, 72,
- 77, nil, nil, nil, 39, nil, nil, 37, nil, nil,
- nil, nil, 73, 74, 75, nil, 36, 76, 28, nil,
- 80, nil, nil, nil, 22, 23, nil, 26, 27, nil,
- 60, 63, 19, nil, 40, nil, 61, 62, nil, nil,
- 33, 71, 72, 77, nil, nil, nil, 39, nil, nil,
- 37, nil, nil, nil, nil, 73, 74, 75, nil, 36,
- 76, 28, nil, 80, nil, nil, nil, 22, 23, nil,
- 26, 27, nil, 60, 63, 19, nil, 40, nil, 61,
- 62, nil, nil, 33, 71, 72, 77, nil, 114, nil,
- 39, nil, nil, 37, nil, nil, 113, nil, 73, 74,
- 75, nil, 36, 76, 28, nil, 80, nil, nil, nil,
- 22, 23, nil, 26, 27, nil, 60, 63, 19, nil,
- 40, nil, 61, 62, nil, nil, 33, 71, 72, 77,
- nil, nil, nil, 39, nil, nil, 37, nil, nil, nil,
- nil, 73, 74, 75, nil, 36, 76, 28, nil, 80,
- nil, nil, nil, 22, 23, nil, 26, 27, nil, 60,
- 63, 19, nil, 40, nil, 61, 62, nil, nil, 33,
- 71, 72, 77, nil, nil, nil, 39, nil, nil, 37,
- nil, nil, nil, nil, 73, 74, 75, nil, 36, 76,
- 28, nil, 80, nil, nil, nil, 22, 23, nil, 26,
- 27, nil, 60, 63, 19, nil, 40, nil, 61, 62,
- nil, nil, 33, 71, 72, 77, nil, nil, nil, 39,
- nil, nil, 37, nil, nil, nil, nil, 73, 74, 75,
- nil, 36, 76, 28, nil, 80, nil, nil, nil, 22,
- 23, nil, 26, 27, nil, 60, 63, 19, nil, 40,
- nil, 61, 62, nil, nil, 33, 71, 72, 77, nil,
- nil, nil, 39, nil, nil, 37, nil, nil, nil, nil,
- 73, 74, 75, nil, 36, 76, 28, nil, 80, nil,
- nil, nil, 22, 23, nil, 26, 27, nil, 60, 63,
- 19, nil, 40, nil, 61, 62, nil, nil, 33, 71,
- 72, 77, nil, nil, nil, 39, nil, nil, 37, nil,
- nil, nil, nil, 73, 74, 75, nil, 36, 76, 28,
- nil, 80, nil, nil, nil, 22, 23, nil, 26, 27,
- nil, 60, 63, 19, nil, 40, nil, 61, 62, nil,
- nil, 33, 71, 72, 77, nil, nil, nil, 39, nil,
- nil, 37, nil, nil, nil, nil, 73, 74, 75, nil,
- 36, 76, 28, nil, 80, nil, nil, nil, 22, 23,
- nil, 26, 27, nil, 60, 63, 19, nil, 40, nil,
- 61, 62, nil, nil, 33, 71, 72, 77, nil, nil,
- nil, 39, nil, nil, 37, nil, nil, nil, nil, 73,
- 74, 75, nil, 36, 76, 28, nil, 80, nil, nil,
- nil, 22, 23, nil, 26, 27, nil, 60, 63, 19,
- nil, 40, nil, 61, 62, nil, nil, 33, 71, 72,
- 77, nil, nil, nil, 39, nil, nil, 37, nil, nil,
- nil, nil, 73, 74, 75, nil, 36, 76, 28, nil,
- 80, nil, nil, nil, 22, 23, nil, 26, 27, nil,
- 60, 63, 19, nil, 40, nil, 61, 62, nil, nil,
- 33, 71, 72, 77, nil, nil, nil, 39, nil, nil,
- 37, nil, nil, nil, nil, 73, 74, 75, nil, 36,
- 76, 28, nil, 80, nil, nil, nil, 22, 23, nil,
- 26, 27, nil, 60, 63, 19, nil, 40, nil, 61,
- 62, nil, nil, 33, 71, 72, 77, nil, nil, nil,
- 39, nil, nil, 37, nil, nil, nil, nil, 73, 74,
- 75, nil, 36, 76, 28, nil, 80, nil, nil, nil,
- 22, 23, nil, 26, 27, nil, 60, 63, 19, nil,
- 40, nil, 61, 62, nil, nil, 33, 71, 72, 77,
- nil, nil, nil, 39, nil, nil, 37, nil, nil, nil,
- nil, 73, 74, 75, nil, 36, 76, 28, nil, 80,
- nil, nil, nil, 22, 23, nil, 26, 27, nil, 60,
- 63, 19, nil, 40, nil, 61, 62, nil, nil, 33,
- 71, 72, 77, nil, nil, nil, 39, nil, nil, 37,
- nil, nil, nil, nil, 73, 74, 75, nil, 36, 76,
- 28, nil, 80, nil, nil, nil, 22, 23, nil, 26,
- 27, nil, 60, 63, 19, nil, 40, nil, 61, 62,
- nil, nil, 33, 71, 72, 77, nil, nil, nil, 39,
- nil, nil, 37, nil, nil, nil, nil, 73, 74, 75,
- nil, 36, 76, 28, nil, 80, nil, nil, nil, 22,
- 23, nil, 26, 27, nil, 60, 63, 19, nil, 40,
- nil, 61, 62, nil, nil, 33, 71, 72, 77, nil,
- nil, nil, 39, nil, nil, 37, nil, nil, nil, nil,
- 73, 74, 75, nil, 36, 76, 28, nil, 80, nil,
- nil, nil, 22, 23, nil, 26, 27, nil, 60, 63,
- 19, nil, 40, nil, 61, 62, nil, nil, 33, 71,
- 72, 77, nil, nil, nil, 39, nil, nil, 37, nil,
- nil, nil, nil, 73, 74, 75, nil, 36, 76, 28,
- nil, 80, nil, nil, nil, 22, 23, nil, 26, 27,
- nil, 60, 63, 19, nil, 40, nil, 61, 62, nil,
- nil, 33, 71, 72, 77, nil, nil, nil, 39, nil,
- nil, 37, nil, nil, nil, nil, 73, 74, 75, nil,
- 36, 76, 28, nil, 80, nil, nil, nil, 22, 23,
- nil, 26, 27, nil, 60, 63, 19, nil, 40, nil,
- 61, 62, nil, nil, 33, 71, 72, 77, nil, nil,
- nil, 39, nil, nil, 37, nil, nil, nil, nil, 73,
- 74, 75, nil, 36, 76, 28, nil, 80, nil, nil,
- nil, 22, 23, nil, 26, 27, nil, 60, 63, 19,
- nil, 40, nil, 61, 62, nil, nil, 33, 71, 72,
- 77, nil, nil, nil, 39, nil, nil, 37, nil, nil,
- nil, nil, 73, 74, 75, nil, 36, 76, 28, nil,
- 80, nil, nil, nil, 22, 23, nil, 26, 27, nil,
- 60, 63, 19, nil, 40, nil, 61, 62, nil, nil,
- 33, 71, 72, 77, nil, nil, nil, 39, nil, nil,
- 37, nil, nil, nil, nil, 73, 74, 75, nil, 36,
- 76, 28, nil, 80, nil, nil, nil, 22, 23, nil,
- 26, 27, nil, 60, 63, 19, nil, 40, nil, 61,
- 62, nil, nil, 33, 71, 72, 77, nil, nil, 160,
- 39, nil, nil, 37, 5, 6, nil, nil, 73, 74,
- 75, nil, 36, 76, 28, nil, 80, nil, nil, nil,
- 22, 23, nil, 26, 27, nil, 60, 63, 19, nil,
- 40, nil, 61, 62, nil, nil, 33, 71, 72, 77,
- nil, nil, nil, 39, nil, nil, 37, nil, nil, nil,
- nil, 73, 74, 75, nil, 36, 76, 28, nil, 80,
- nil, nil, nil, 22, 23, nil, 26, 27, nil, 60,
- 63, 19, nil, 40, nil, 61, 62, nil, nil, 33,
- 71, 72, 77, nil, nil, nil, 39, nil, nil, 37,
- nil, nil, nil, nil, 73, 74, 75, nil, 36, 76,
- 28, nil, 80, nil, nil, nil, 22, 23, nil, 26,
- 27, nil, 60, 63, 19, nil, 40, nil, 61, 62,
- nil, nil, 33, 71, 72, 77, nil, nil, nil, 39,
- nil, nil, 37, nil, nil, nil, nil, 73, 74, 75,
- nil, 36, 76, 28, nil, 80, nil, nil, nil, 22,
- 23, nil, 26, 27, nil, 60, 63, 19, nil, 40,
- nil, 61, 62, nil, nil, 33, 71, 72, 77, nil,
- nil, nil, 39, nil, nil, 37, nil, nil, nil, nil,
- 73, 74, 75, nil, 36, 76, 28, nil, 80, nil,
- nil, nil, 22, 23, nil, 26, 27, nil, 60, 63,
- 19, nil, 40, nil, 61, 62, nil, nil, 33, 71,
- 72, 77, nil, nil, nil, 39, nil, nil, 37, nil,
- nil, nil, nil, 73, 74, 75, nil, 36, 76, 28,
- nil, 80, nil, nil, nil, 22, 23, nil, 26, 27,
- nil, 60, 63, 19, nil, 40, nil, 61, 62, nil,
- nil, 33, 71, 72, 77, nil, nil, 160, 39, nil,
- nil, 37, 5, 6, nil, nil, 73, 74, 75, nil,
- 36, 76, 28, nil, 80, nil, nil, nil, 22, 23,
- nil, 26, 27, nil, 60, 63, 19, nil, 40, nil,
- 61, 62, nil, nil, 33, 71, 72, 77, nil, nil,
- nil, 39, nil, nil, 37, nil, nil, nil, nil, 73,
- 74, 75, nil, 36, 76, 28, nil, 80, nil, nil,
- nil, 22, 23, nil, 26, 27, nil, 60, 63, 19,
- 85, 86, 87, 88, nil, 84, nil, 33, 89, nil,
- nil, nil, nil, 84, 91, 5, 6, 85, 86, 87,
- 88, nil, 91, nil, nil, 89, nil, nil, nil, nil,
- 84, nil, 92, 93, 94, 95, 96, 97, 98, 91,
- 92, 93, 94, 95, 96, 97, 98, nil, 90, nil,
- nil, nil, nil, nil, nil, nil, nil, 92, 93, 94,
- 95, 96, 97, 98, nil, 90, 85, 86, 87, 88,
- nil, nil, nil, nil, 89, nil, nil, nil, nil, 84,
- nil, 85, 86, 87, 88, 156, nil, nil, 91, 89,
- nil, nil, nil, nil, 84, nil, nil, nil, nil, nil,
- nil, nil, nil, 91, nil, nil, 92, 93, 94, 95,
- 96, 97, 98, nil, 90, nil, nil, nil, nil, nil,
- nil, 92, 93, 94, 95, 96, 97, 98, nil, 90,
- 85, 86, 87, 88, nil, nil, nil, nil, 89, nil,
- nil, nil, nil, 84, nil, 165, 85, 86, 87, 88,
- nil, nil, 91, nil, 89, nil, nil, nil, 167, 84,
- nil, nil, nil, nil, nil, nil, nil, nil, 91, nil,
- 92, 93, 94, 95, 96, 97, 98, nil, 90, nil,
- nil, nil, nil, nil, nil, nil, 92, 93, 94, 95,
- 96, 97, 98, nil, 90, 85, 86, 87, 88, nil,
- nil, nil, nil, 89, nil, nil, nil, nil, 84, nil,
- 85, 86, 87, 88, nil, nil, nil, 91, 89, nil,
- nil, nil, nil, 84, nil, nil, nil, nil, nil, nil,
- nil, nil, 91, nil, nil, 92, 93, 94, 95, 96,
- 97, 98, nil, 90, nil, nil, nil, nil, nil, nil,
- 92, 93, 94, 95, 96, 97, 98, nil, 90, 85,
- 86, 87, 88, nil, nil, nil, nil, 89, nil, nil,
- nil, nil, 84, nil, 85, 86, 87, 88, nil, nil,
- nil, 91, 89, nil, nil, nil, nil, 84, nil, nil,
- nil, nil, nil, nil, nil, nil, 91, nil, nil, 92,
- 93, 94, 95, 96, 97, 98, nil, 90, nil, nil,
- nil, nil, nil, nil, 92, 93, 94, 95, 96, 97,
- 98, nil, 90, 85, 86, 87, 88, nil, nil, nil,
- nil, 89, nil, nil, nil, nil, 84, nil, 85, 86,
- 87, 88, nil, nil, nil, 91, 89, nil, nil, nil,
- nil, 84, nil, nil, nil, nil, nil, nil, nil, nil,
- 91, nil, nil, 92, 93, 94, 95, 96, 97, 98,
- nil, 90, nil, nil, nil, nil, nil, nil, 92, 93,
- 94, 95, 96, 97, 98, nil, 90, 85, 86, 87,
- 88, nil, nil, nil, nil, 89, nil, nil, nil, nil,
- 84, nil, 85, 86, 87, 88, nil, nil, nil, 91,
- 89, nil, nil, nil, nil, 84, nil, nil, nil, nil,
- nil, nil, nil, nil, 91, nil, nil, 92, 93, 94,
- 95, 96, 97, 98, nil, 90, nil, nil, nil, nil,
- nil, nil, 92, 93, 94, 95, 96, 97, 98, nil,
- 90, 85, 86, 87, 88, nil, nil, nil, nil, 89,
- nil, 160, nil, nil, 84, nil, 5, 6, 85, 86,
- 87, 88, nil, 91, nil, nil, 89, nil, nil, nil,
- nil, 84, nil, nil, nil, nil, nil, nil, nil, nil,
- 91, 92, 93, 94, 95, 96, 97, 98, nil, 90,
- nil, nil, nil, nil, nil, nil, nil, nil, 92, 93,
- 94, 95, 96, 97, 98, nil, 90, 85, 86, 87,
- 88, nil, nil, nil, nil, 89, nil, nil, nil, nil,
- 84, nil, 85, 86, 87, 88, nil, nil, nil, 91,
- 89, nil, nil, nil, nil, 84, nil, 181, nil, nil,
- nil, nil, nil, nil, 91, nil, nil, 92, 93, 94,
- 95, 96, 97, 98, nil, 90, nil, nil, nil, nil,
- nil, nil, 92, 93, 94, 95, 96, 97, 98, nil,
- 90, 85, 86, 87, 88, nil, nil, nil, nil, 89,
- nil, nil, nil, nil, 84, nil, 85, 86, 87, 88,
- nil, nil, nil, 91, 89, nil, nil, nil, nil, 84,
- nil, nil, nil, nil, nil, nil, nil, nil, 91, nil,
- nil, 92, 93, 94, 95, 96, 97, 98, nil, 90,
- nil, nil, nil, nil, nil, nil, 92, 93, 94, 95,
- 96, 97, 98, nil, 90, 87, 88, nil, nil, nil,
- nil, 89, nil, nil, nil, nil, 84, 87, 88, nil,
- nil, nil, nil, 89, nil, 91, nil, nil, 84, nil,
- 87, 88, nil, nil, nil, nil, 89, 91, nil, nil,
- nil, 84, nil, 92, 93, 94, 95, 96, 97, 98,
- 91, 90, nil, nil, nil, 92, 93, 94, 95, 96,
- 97, 98, nil, 90, nil, nil, nil, nil, 92, 93,
- 94, 95, 96, 97, 98, 89, 90, 87, 88, nil,
- 84, nil, nil, 89, nil, nil, nil, nil, 84, 91,
- nil, nil, nil, nil, nil, nil, nil, 91, nil, nil,
- 89, nil, nil, nil, nil, 84, nil, 92, 93, 94,
- 95, 96, 97, 98, 91, 92, 93, 94, 95, 96,
- 97, 98, nil, 90, nil, 89, nil, nil, nil, nil,
- 84, nil, 92, 93, 94, 95, 96, 97, 98, 91,
- 89, nil, nil, nil, nil, 84, nil, nil, nil, nil,
- 89, nil, nil, nil, 91, 84, nil, 92, 93, 94,
- 95, 96, 97, 98, 91, nil, nil, nil, nil, nil,
- nil, nil, 92, 93, 94, 95, 96, 97, 98, nil,
- nil, nil, 92, 93, 94, 95, 96, 97, 98 ]
-
-racc_action_check = [
- 1, 33, 1, 34, 1, 1, 40, 100, 81, 1,
- 1, 1, 102, 161, 161, 1, 112, 33, 1, 1,
- 1, 84, 100, 1, 1, 1, 33, 1, 1, 1,
- 102, 1, 121, 131, 163, 1, 1, 84, 1, 1,
- 178, 1, 1, 1, 179, 0, 84, 0, 0, 183,
- nil, 1, 0, 0, 0, nil, nil, 80, 0, 80,
- 80, 0, 0, 0, nil, nil, 0, 0, 0, nil,
- 0, 0, 0, 128, 0, 128, 128, nil, 0, 0,
- nil, 0, 0, nil, 0, 0, 0, nil, 19, nil,
- 19, 19, nil, nil, 0, 19, 19, 19, nil, nil,
- nil, 19, nil, nil, 19, nil, nil, nil, nil, 19,
- 19, 19, nil, 19, 19, 19, nil, 19, nil, nil,
- nil, 19, 19, nil, 19, 19, nil, 19, 19, 19,
- nil, 23, nil, 23, 23, nil, nil, 19, 23, 23,
- 23, nil, nil, nil, 23, nil, nil, 23, nil, nil,
- nil, nil, 23, 23, 23, nil, 23, 23, 23, nil,
- 23, nil, nil, nil, 23, 23, nil, 23, 23, nil,
- 23, 23, 23, nil, 27, nil, 27, 27, nil, nil,
- 23, 27, 27, 27, nil, nil, nil, 27, nil, nil,
- 27, nil, nil, nil, nil, 27, 27, 27, nil, 27,
- 27, 27, nil, 27, nil, nil, nil, 27, 27, nil,
- 27, 27, nil, 27, 27, 27, nil, 37, nil, 37,
- 37, nil, nil, 27, 37, 37, 37, nil, 37, nil,
- 37, nil, nil, 37, nil, nil, 37, nil, 37, 37,
- 37, nil, 37, 37, 37, nil, 37, nil, nil, nil,
- 37, 37, nil, 37, 37, nil, 37, 37, 37, nil,
- 39, nil, 39, 39, nil, nil, 37, 39, 39, 39,
- nil, nil, nil, 39, nil, nil, 39, nil, nil, nil,
- nil, 39, 39, 39, nil, 39, 39, 39, nil, 39,
- nil, nil, nil, 39, 39, nil, 39, 39, nil, 39,
- 39, 39, nil, 60, nil, 60, 60, nil, nil, 39,
- 60, 60, 60, nil, nil, nil, 60, nil, nil, 60,
- nil, nil, nil, nil, 60, 60, 60, nil, 60, 60,
- 60, nil, 60, nil, nil, nil, 60, 60, nil, 60,
- 60, nil, 60, 60, 60, nil, 61, nil, 61, 61,
- nil, nil, 60, 61, 61, 61, nil, nil, nil, 61,
- nil, nil, 61, nil, nil, nil, nil, 61, 61, 61,
- nil, 61, 61, 61, nil, 61, nil, nil, nil, 61,
- 61, nil, 61, 61, nil, 61, 61, 61, nil, 62,
- nil, 62, 62, nil, nil, 61, 62, 62, 62, nil,
- nil, nil, 62, nil, nil, 62, nil, nil, nil, nil,
- 62, 62, 62, nil, 62, 62, 62, nil, 62, nil,
- nil, nil, 62, 62, nil, 62, 62, nil, 62, 62,
- 62, nil, 63, nil, 63, 63, nil, nil, 62, 63,
- 63, 63, nil, nil, nil, 63, nil, nil, 63, nil,
- nil, nil, nil, 63, 63, 63, nil, 63, 63, 63,
- nil, 63, nil, nil, nil, 63, 63, nil, 63, 63,
- nil, 63, 63, 63, nil, 85, nil, 85, 85, nil,
- nil, 63, 85, 85, 85, nil, nil, nil, 85, nil,
- nil, 85, nil, nil, nil, nil, 85, 85, 85, nil,
- 85, 85, 85, nil, 85, nil, nil, nil, 85, 85,
- nil, 85, 85, nil, 85, 85, 85, nil, 86, nil,
- 86, 86, nil, nil, 85, 86, 86, 86, nil, nil,
- nil, 86, nil, nil, 86, nil, nil, nil, nil, 86,
- 86, 86, nil, 86, 86, 86, nil, 86, nil, nil,
- nil, 86, 86, nil, 86, 86, nil, 86, 86, 86,
- nil, 87, nil, 87, 87, nil, nil, 86, 87, 87,
- 87, nil, nil, nil, 87, nil, nil, 87, nil, nil,
- nil, nil, 87, 87, 87, nil, 87, 87, 87, nil,
- 87, nil, nil, nil, 87, 87, nil, 87, 87, nil,
- 87, 87, 87, nil, 88, nil, 88, 88, nil, nil,
- 87, 88, 88, 88, nil, nil, nil, 88, nil, nil,
- 88, nil, nil, nil, nil, 88, 88, 88, nil, 88,
- 88, 88, nil, 88, nil, nil, nil, 88, 88, nil,
- 88, 88, nil, 88, 88, 88, nil, 89, nil, 89,
- 89, nil, nil, 88, 89, 89, 89, nil, nil, nil,
- 89, nil, nil, 89, nil, nil, nil, nil, 89, 89,
- 89, nil, 89, 89, 89, nil, 89, nil, nil, nil,
- 89, 89, nil, 89, 89, nil, 89, 89, 89, nil,
- 90, nil, 90, 90, nil, nil, 89, 90, 90, 90,
- nil, nil, nil, 90, nil, nil, 90, nil, nil, nil,
- nil, 90, 90, 90, nil, 90, 90, 90, nil, 90,
- nil, nil, nil, 90, 90, nil, 90, 90, nil, 90,
- 90, 90, nil, 91, nil, 91, 91, nil, nil, 90,
- 91, 91, 91, nil, nil, nil, 91, nil, nil, 91,
- nil, nil, nil, nil, 91, 91, 91, nil, 91, 91,
- 91, nil, 91, nil, nil, nil, 91, 91, nil, 91,
- 91, nil, 91, 91, 91, nil, 92, nil, 92, 92,
- nil, nil, 91, 92, 92, 92, nil, nil, nil, 92,
- nil, nil, 92, nil, nil, nil, nil, 92, 92, 92,
- nil, 92, 92, 92, nil, 92, nil, nil, nil, 92,
- 92, nil, 92, 92, nil, 92, 92, 92, nil, 93,
- nil, 93, 93, nil, nil, 92, 93, 93, 93, nil,
- nil, nil, 93, nil, nil, 93, nil, nil, nil, nil,
- 93, 93, 93, nil, 93, 93, 93, nil, 93, nil,
- nil, nil, 93, 93, nil, 93, 93, nil, 93, 93,
- 93, nil, 94, nil, 94, 94, nil, nil, 93, 94,
- 94, 94, nil, nil, nil, 94, nil, nil, 94, nil,
- nil, nil, nil, 94, 94, 94, nil, 94, 94, 94,
- nil, 94, nil, nil, nil, 94, 94, nil, 94, 94,
- nil, 94, 94, 94, nil, 95, nil, 95, 95, nil,
- nil, 94, 95, 95, 95, nil, nil, nil, 95, nil,
- nil, 95, nil, nil, nil, nil, 95, 95, 95, nil,
- 95, 95, 95, nil, 95, nil, nil, nil, 95, 95,
- nil, 95, 95, nil, 95, 95, 95, nil, 96, nil,
- 96, 96, nil, nil, 95, 96, 96, 96, nil, nil,
- nil, 96, nil, nil, 96, nil, nil, nil, nil, 96,
- 96, 96, nil, 96, 96, 96, nil, 96, nil, nil,
- nil, 96, 96, nil, 96, 96, nil, 96, 96, 96,
- nil, 97, nil, 97, 97, nil, nil, 96, 97, 97,
- 97, nil, nil, nil, 97, nil, nil, 97, nil, nil,
- nil, nil, 97, 97, 97, nil, 97, 97, 97, nil,
- 97, nil, nil, nil, 97, 97, nil, 97, 97, nil,
- 97, 97, 97, nil, 98, nil, 98, 98, nil, nil,
- 97, 98, 98, 98, nil, nil, nil, 98, nil, nil,
- 98, nil, nil, nil, nil, 98, 98, 98, nil, 98,
- 98, 98, nil, 98, nil, nil, nil, 98, 98, nil,
- 98, 98, nil, 98, 98, 98, nil, 111, nil, 111,
- 111, nil, nil, 98, 111, 111, 111, nil, nil, 111,
- 111, nil, nil, 111, 111, 111, nil, nil, 111, 111,
- 111, nil, 111, 111, 111, nil, 111, nil, nil, nil,
- 111, 111, nil, 111, 111, nil, 111, 111, 111, nil,
- 123, nil, 123, 123, nil, nil, 111, 123, 123, 123,
- nil, nil, nil, 123, nil, nil, 123, nil, nil, nil,
- nil, 123, 123, 123, nil, 123, 123, 123, nil, 123,
- nil, nil, nil, 123, 123, nil, 123, 123, nil, 123,
- 123, 123, nil, 129, nil, 129, 129, nil, nil, 123,
- 129, 129, 129, nil, nil, nil, 129, nil, nil, 129,
- nil, nil, nil, nil, 129, 129, 129, nil, 129, 129,
- 129, nil, 129, nil, nil, nil, 129, 129, nil, 129,
- 129, nil, 129, 129, 129, nil, 153, nil, 153, 153,
- nil, nil, 129, 153, 153, 153, nil, nil, nil, 153,
- nil, nil, 153, nil, nil, nil, nil, 153, 153, 153,
- nil, 153, 153, 153, nil, 153, nil, nil, nil, 153,
- 153, nil, 153, 153, nil, 153, 153, 153, nil, 155,
- nil, 155, 155, nil, nil, 153, 155, 155, 155, nil,
- nil, nil, 155, nil, nil, 155, nil, nil, nil, nil,
- 155, 155, 155, nil, 155, 155, 155, nil, 155, nil,
- nil, nil, 155, 155, nil, 155, 155, nil, 155, 155,
- 155, nil, 156, nil, 156, 156, nil, nil, 155, 156,
- 156, 156, nil, nil, nil, 156, nil, nil, 156, nil,
- nil, nil, nil, 156, 156, 156, nil, 156, 156, 156,
- nil, 156, nil, nil, nil, 156, 156, nil, 156, 156,
- nil, 156, 156, 156, nil, 157, nil, 157, 157, nil,
- nil, 156, 157, 157, 157, nil, nil, 157, 157, nil,
- nil, 157, 157, 157, nil, nil, 157, 157, 157, nil,
- 157, 157, 157, nil, 157, nil, nil, nil, 157, 157,
- nil, 157, 157, nil, 157, 157, 157, nil, 180, nil,
- 180, 180, nil, nil, 157, 180, 180, 180, nil, nil,
- nil, 180, nil, nil, 180, nil, nil, nil, nil, 180,
- 180, 180, nil, 180, 180, 180, nil, 180, nil, nil,
- nil, 180, 180, nil, 180, 180, nil, 180, 180, 180,
- 3, 3, 3, 3, nil, 142, nil, 180, 3, nil,
- nil, nil, nil, 3, 142, 3, 3, 99, 99, 99,
- 99, nil, 3, nil, nil, 99, nil, nil, nil, nil,
- 99, nil, 142, 142, 142, 142, 142, 142, 142, 99,
- 3, 3, 3, 3, 3, 3, 3, nil, 3, nil,
- nil, nil, nil, nil, nil, nil, nil, 99, 99, 99,
- 99, 99, 99, 99, nil, 99, 101, 101, 101, 101,
- nil, nil, nil, nil, 101, nil, nil, nil, nil, 101,
- nil, 104, 104, 104, 104, 104, nil, nil, 101, 104,
- nil, nil, nil, nil, 104, nil, nil, nil, nil, nil,
- nil, nil, nil, 104, nil, nil, 101, 101, 101, 101,
- 101, 101, 101, nil, 101, nil, nil, nil, nil, nil,
- nil, 104, 104, 104, 104, 104, 104, 104, nil, 104,
- 117, 117, 117, 117, nil, nil, nil, nil, 117, nil,
- nil, nil, nil, 117, nil, 117, 122, 122, 122, 122,
- nil, nil, 117, nil, 122, nil, nil, nil, 122, 122,
- nil, nil, nil, nil, nil, nil, nil, nil, 122, nil,
- 117, 117, 117, 117, 117, 117, 117, nil, 117, nil,
- nil, nil, nil, nil, nil, nil, 122, 122, 122, 122,
- 122, 122, 122, nil, 122, 144, 144, 144, 144, nil,
- nil, nil, nil, 144, nil, nil, nil, nil, 144, nil,
- 145, 145, 145, 145, nil, nil, nil, 144, 145, nil,
- nil, nil, nil, 145, nil, nil, nil, nil, nil, nil,
- nil, nil, 145, nil, nil, 144, 144, 144, 144, 144,
- 144, 144, nil, 144, nil, nil, nil, nil, nil, nil,
- 145, 145, 145, 145, 145, 145, 145, nil, 145, 146,
- 146, 146, 146, nil, nil, nil, nil, 146, nil, nil,
- nil, nil, 146, nil, 147, 147, 147, 147, nil, nil,
- nil, 146, 147, nil, nil, nil, nil, 147, nil, nil,
- nil, nil, nil, nil, nil, nil, 147, nil, nil, 146,
- 146, 146, 146, 146, 146, 146, nil, 146, nil, nil,
- nil, nil, nil, nil, 147, 147, 147, 147, 147, 147,
- 147, nil, 147, 148, 148, 148, 148, nil, nil, nil,
- nil, 148, nil, nil, nil, nil, 148, nil, 149, 149,
- 149, 149, nil, nil, nil, 148, 149, nil, nil, nil,
- nil, 149, nil, nil, nil, nil, nil, nil, nil, nil,
- 149, nil, nil, 148, 148, 148, 148, 148, 148, 148,
- nil, 148, nil, nil, nil, nil, nil, nil, 149, 149,
- 149, 149, 149, 149, 149, nil, 149, 150, 150, 150,
- 150, nil, nil, nil, nil, 150, nil, nil, nil, nil,
- 150, nil, 151, 151, 151, 151, nil, nil, nil, 150,
- 151, nil, nil, nil, nil, 151, nil, nil, nil, nil,
- nil, nil, nil, nil, 151, nil, nil, 150, 150, 150,
- 150, 150, 150, 150, nil, 150, nil, nil, nil, nil,
- nil, nil, 151, 151, 151, 151, 151, 151, 151, nil,
- 151, 158, 158, 158, 158, nil, nil, nil, nil, 158,
- nil, 158, nil, nil, 158, nil, 158, 158, 168, 168,
- 168, 168, nil, 158, nil, nil, 168, nil, nil, nil,
- nil, 168, nil, nil, nil, nil, nil, nil, nil, nil,
- 168, 158, 158, 158, 158, 158, 158, 158, nil, 158,
- nil, nil, nil, nil, nil, nil, nil, nil, 168, 168,
- 168, 168, 168, 168, 168, nil, 168, 171, 171, 171,
- 171, nil, nil, nil, nil, 171, nil, nil, nil, nil,
- 171, nil, 173, 173, 173, 173, nil, nil, nil, 171,
- 173, nil, nil, nil, nil, 173, nil, 171, nil, nil,
- nil, nil, nil, nil, 173, nil, nil, 171, 171, 171,
- 171, 171, 171, 171, nil, 171, nil, nil, nil, nil,
- nil, nil, 173, 173, 173, 173, 173, 173, 173, nil,
- 173, 175, 175, 175, 175, nil, nil, nil, nil, 175,
- nil, nil, nil, nil, 175, nil, 185, 185, 185, 185,
- nil, nil, nil, 175, 185, nil, nil, nil, nil, 185,
- nil, nil, nil, nil, nil, nil, nil, nil, 185, nil,
- nil, 175, 175, 175, 175, 175, 175, 175, nil, 175,
- nil, nil, nil, nil, nil, nil, 185, 185, 185, 185,
- 185, 185, 185, nil, 185, 125, 125, nil, nil, nil,
- nil, 125, nil, nil, nil, nil, 125, 126, 126, nil,
- nil, nil, nil, 126, nil, 125, nil, nil, 126, nil,
- 138, 138, nil, nil, nil, nil, 138, 126, nil, nil,
- nil, 138, nil, 125, 125, 125, 125, 125, 125, 125,
- 138, 125, nil, nil, nil, 126, 126, 126, 126, 126,
- 126, 126, nil, 126, nil, nil, nil, nil, 138, 138,
- 138, 138, 138, 138, 138, 124, 138, 139, 139, nil,
- 124, nil, nil, 139, nil, nil, nil, nil, 139, 124,
- nil, nil, nil, nil, nil, nil, nil, 139, nil, nil,
- 127, nil, nil, nil, nil, 127, nil, 124, 124, 124,
- 124, 124, 124, 124, 127, 139, 139, 139, 139, 139,
- 139, 139, nil, 139, nil, 140, nil, nil, nil, nil,
- 140, nil, 127, 127, 127, 127, 127, 127, 127, 140,
- 141, nil, nil, nil, nil, 141, nil, nil, nil, nil,
- 143, nil, nil, nil, 141, 143, nil, 140, 140, 140,
- 140, 140, 140, 140, 143, nil, nil, nil, nil, nil,
- nil, nil, 141, 141, 141, 141, 141, 141, 141, nil,
- nil, nil, 143, 143, 143, 143, 143, 143, 143 ]
-
-racc_action_pointer = [
- 43, 0, nil, 1416, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 86,
- nil, nil, nil, 129, nil, nil, nil, 172, nil, nil,
- nil, nil, nil, -1, -15, nil, nil, 215, nil, 258,
- 3, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 301, 344, 387, 430, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 27, 8, nil, nil, 19, 473, 516, 559, 602, 645,
- 688, 731, 774, 817, 860, 903, 946, 989, 1032, 1433,
- -15, 1482, -10, nil, 1497, nil, nil, nil, nil, nil,
- nil, 1075, 14, nil, nil, nil, nil, 1546, nil, nil,
- nil, 13, 1562, 1118, 2123, 2059, 2071, 2148, 43, 1161,
- nil, 3, nil, nil, nil, nil, nil, nil, 2084, 2131,
- 2173, 2188, 1408, 2198, 1611, 1626, 1675, 1690, 1739, 1754,
- 1803, 1818, nil, 1204, nil, 1247, 1290, 1333, 1867, nil,
- nil, -8, nil, 31, nil, nil, nil, nil, 1884, nil,
- nil, 1933, nil, 1948, nil, 1997, nil, nil, 21, 42,
- 1376, nil, nil, 36, nil, 2012, nil ]
-
-racc_action_default = [
- -140, -140, -1, -4, -5, -6, -7, -10, -11, -12,
- -13, -14, -15, -16, -17, -18, -19, -20, -21, -23,
- -24, -25, -26, -140, -30, -31, -32, -140, -37, -55,
- -56, -57, -60, -140, -63, -64, -65, -140, -73, -140,
- -76, -77, -78, -79, -80, -81, -82, -83, -84, -85,
- -86, -87, -88, -89, -90, -91, -107, -108, -109, -110,
- -140, -140, -140, -140, -115, -116, -117, -118, -119, -120,
- -121, -122, -123, -124, -125, -126, -127, -128, -129, -130,
- -140, -140, -2, -3, -140, -140, -140, -140, -140, -140,
- -140, -140, -140, -140, -140, -140, -140, -140, -140, -22,
- -140, -28, -140, -34, -140, -61, -62, -74, -38, -39,
- -40, -140, -140, -46, -47, -48, -49, -69, -66, -67,
- -68, -71, -140, -140, -111, -112, -113, -114, -140, -140,
- -133, -135, -136, -137, -138, 187, -58, -59, -93, -94,
- -95, -96, -97, -98, -99, -100, -101, -102, -103, -104,
- -105, -106, -27, -140, -33, -140, -140, -140, -4, -43,
- -44, -140, -50, -52, -54, -70, -72, -75, -92, -131,
- -134, -140, -139, -29, -35, -36, -41, -42, -9, -140,
- -140, -132, -8, -140, -51, -53, -45 ]
-
-racc_goto_table = [
- 99, 82, 103, 83, 101, 1, 105, 130, 104, 183,
- 100, 102, 159, 162, 121, 108, 109, 110, 117, 111,
- 122, 115, 112, 161, 116, 107, 118, 119, 120, 128,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 124, 125, 126, 127, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 170, nil, 136, 176, 177,
- nil, nil, nil, nil, nil, nil, 138, 139, 140, 141,
- 142, 143, 144, 145, 146, 147, 148, 149, 150, 151,
- 184, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 158, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 168, nil, nil, nil, nil, nil,
- 171, nil, nil, nil, nil, nil, 157, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 174, nil, nil, nil, 173, nil, 104, 175, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 82, 83, nil,
- nil, 185 ]
-
-racc_goto_check = [
- 3, 2, 24, 4, 3, 1, 40, 77, 3, 5,
- 20, 23, 30, 35, 25, 26, 27, 28, 3, 29,
- 3, 31, 32, 33, 34, 43, 44, 45, 46, 75,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 3, 3, 3, 3, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 77, nil, 40, 30, 30,
- nil, nil, nil, nil, nil, nil, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 35, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 3, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 3, nil, nil, nil, nil, nil,
- 3, nil, nil, nil, nil, nil, 1, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 24, nil, nil, nil, 3, nil, 3, 3, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 2, 4, nil,
- nil, 3 ]
-
-racc_goto_pointer = [
- nil, 5, 0, -19, 0, -169, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- -13, nil, nil, -16, -25, -23, -22, -21, -20, -18,
- -99, -16, -15, -89, -13, -99, nil, nil, nil, nil,
- -27, nil, nil, -9, -11, -10, -9, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, -51, nil, -73, nil ]
-
-racc_goto_default = [
- nil, nil, 2, 3, 4, nil, 7, 8, 9, 10,
- 11, 12, 13, 14, 15, 16, 17, 18, 20, 21,
- nil, 24, 25, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 163, 29, 30, 31,
- 32, 34, 35, 38, nil, nil, nil, 41, 42, 43,
- 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
- 54, 55, 56, 57, 58, 59, 64, 65, 66, 67,
- 68, 69, 70, 78, 79, nil, 132, nil, 131 ]
-
-racc_reduce_table = [
- 0, 0, :racc_error,
- 1, 54, :_reduce_none,
- 2, 54, :_reduce_2,
- 2, 55, :_reduce_3,
- 1, 55, :_reduce_4,
- 1, 55, :_reduce_5,
- 1, 57, :_reduce_none,
- 1, 57, :_reduce_none,
- 1, 58, :_reduce_none,
- 0, 58, :_reduce_none,
- 1, 56, :_reduce_none,
- 1, 56, :_reduce_none,
- 1, 56, :_reduce_none,
- 1, 56, :_reduce_none,
- 1, 56, :_reduce_none,
- 1, 56, :_reduce_none,
- 1, 56, :_reduce_none,
- 1, 56, :_reduce_none,
- 1, 56, :_reduce_none,
- 1, 56, :_reduce_none,
- 1, 68, :_reduce_none,
- 1, 68, :_reduce_none,
- 2, 69, :_reduce_22,
- 1, 70, :_reduce_23,
- 1, 66, :_reduce_none,
- 1, 66, :_reduce_none,
- 1, 71, :_reduce_26,
- 3, 72, :_reduce_27,
- 1, 73, :_reduce_28,
- 3, 73, :_reduce_29,
- 1, 67, :_reduce_none,
- 1, 67, :_reduce_none,
- 1, 74, :_reduce_32,
- 3, 75, :_reduce_33,
- 1, 76, :_reduce_34,
- 3, 76, :_reduce_35,
- 3, 77, :_reduce_36,
- 1, 64, :_reduce_37,
- 1, 78, :_reduce_none,
- 1, 78, :_reduce_none,
- 1, 78, :_reduce_none,
- 3, 79, :_reduce_41,
- 3, 80, :_reduce_42,
- 2, 81, :_reduce_43,
- 1, 83, :_reduce_44,
- 5, 84, :_reduce_45,
- 1, 85, :_reduce_46,
- 1, 87, :_reduce_47,
- 1, 82, :_reduce_none,
- 1, 82, :_reduce_none,
- 1, 86, :_reduce_none,
- 3, 86, :_reduce_none,
- 1, 88, :_reduce_52,
- 3, 88, :_reduce_53,
- 1, 89, :_reduce_54,
- 1, 63, :_reduce_none,
- 1, 63, :_reduce_none,
- 1, 63, :_reduce_none,
- 3, 90, :_reduce_58,
- 3, 90, :_reduce_59,
- 1, 91, :_reduce_60,
- 2, 92, :_reduce_61,
- 2, 92, :_reduce_62,
- 1, 93, :_reduce_none,
- 1, 93, :_reduce_none,
- 1, 95, :_reduce_65,
- 2, 96, :_reduce_66,
- 1, 97, :_reduce_none,
- 1, 97, :_reduce_none,
- 1, 98, :_reduce_none,
- 2, 98, :_reduce_none,
- 1, 99, :_reduce_none,
- 2, 99, :_reduce_none,
- 1, 94, :_reduce_73,
- 2, 94, :_reduce_74,
- 3, 60, :_reduce_75,
- 1, 65, :_reduce_76,
- 1, 61, :_reduce_none,
- 1, 61, :_reduce_none,
- 1, 61, :_reduce_none,
- 1, 61, :_reduce_none,
- 1, 61, :_reduce_none,
- 1, 61, :_reduce_none,
- 1, 61, :_reduce_none,
- 1, 61, :_reduce_none,
- 1, 61, :_reduce_none,
- 1, 61, :_reduce_none,
- 1, 61, :_reduce_none,
- 1, 61, :_reduce_none,
- 1, 61, :_reduce_none,
- 1, 61, :_reduce_none,
- 1, 61, :_reduce_none,
- 3, 100, :_reduce_92,
- 3, 101, :_reduce_93,
- 3, 102, :_reduce_94,
- 3, 103, :_reduce_95,
- 3, 104, :_reduce_96,
- 3, 105, :_reduce_97,
- 3, 106, :_reduce_98,
- 3, 107, :_reduce_99,
- 3, 108, :_reduce_100,
- 3, 109, :_reduce_101,
- 3, 110, :_reduce_102,
- 3, 111, :_reduce_103,
- 3, 112, :_reduce_104,
- 3, 113, :_reduce_105,
- 3, 114, :_reduce_106,
- 1, 62, :_reduce_none,
- 1, 62, :_reduce_none,
- 1, 62, :_reduce_none,
- 1, 62, :_reduce_none,
- 2, 115, :_reduce_111,
- 2, 116, :_reduce_112,
- 2, 117, :_reduce_113,
- 2, 118, :_reduce_114,
- 1, 59, :_reduce_none,
- 1, 59, :_reduce_none,
- 1, 59, :_reduce_none,
- 1, 59, :_reduce_none,
- 1, 59, :_reduce_none,
- 1, 59, :_reduce_none,
- 1, 59, :_reduce_none,
- 1, 120, :_reduce_122,
- 1, 119, :_reduce_123,
- 1, 122, :_reduce_124,
- 1, 123, :_reduce_125,
- 1, 124, :_reduce_126,
- 1, 125, :_reduce_127,
- 1, 121, :_reduce_128,
- 1, 121, :_reduce_none,
- 1, 121, :_reduce_none,
- 3, 126, :_reduce_131,
- 3, 129, :_reduce_132,
- 1, 128, :_reduce_133,
- 2, 128, :_reduce_134,
- 1, 130, :_reduce_135,
- 1, 130, :_reduce_136,
- 2, 127, :_reduce_137,
- 1, 131, :_reduce_138,
- 2, 131, :_reduce_139 ]
-
-racc_reduce_n = 140
-
-racc_shift_n = 187
-
-racc_token_table = {
- false => 0,
- :error => 1,
- :IDENTIFIER => 2,
- :EQUAL => 3,
- :PLUS => 4,
- :MINUS => 5,
- :ASTERISK => 6,
- :FWD_SLASH => 7,
- :COLON => 8,
- :FLOAT => 9,
- :INTEGER => 10,
- :STRING => 11,
- :EXPO => 12,
- :INDENT => 13,
- :OUTDENT => 14,
- :OPAREN => 15,
- :CPAREN => 16,
- :DOT => 17,
- :SIGNATURE => 18,
- :NL => 19,
- :EOF => 20,
- :PIPE => 21,
- :COMMA => 22,
- :NIL => 23,
- :TRUE => 24,
- :FALSE => 25,
- :EQUALITY => 26,
- :CALL => 27,
- :SELF => 28,
- :CONSTANT => 29,
- :CHAR => 30,
- :DOUBLE_TICK_STRING => 31,
- :DOUBLE_TICK_STRING_END => 32,
- :INTERPOLATE_START => 33,
- :INTERPOLATE_END => 34,
- :BOX => 35,
- :LSQUARE => 36,
- :RSQUARE => 37,
- :FACES => 38,
- :LFACE => 39,
- :RFACE => 40,
- :BANG => 41,
- :TILDE => 42,
- :RETURN => 43,
- :NOT_EQUALITY => 44,
- :OR => 45,
- :AND => 46,
- :GT => 47,
- :LT => 48,
- :GTE => 49,
- :LTE => 50,
- :AT => 51,
- :PERCENT => 52 }
-
-racc_nt_base = 53
-
-racc_use_result_var = true
-
-Racc_arg = [
- racc_action_table,
- racc_action_check,
- racc_action_default,
- racc_action_pointer,
- racc_goto_table,
- racc_goto_check,
- racc_goto_default,
- racc_goto_pointer,
- racc_nt_base,
- racc_reduce_table,
- racc_token_table,
- racc_shift_n,
- racc_reduce_n,
- racc_use_result_var ]
-
-Racc_token_to_s_table = [
- "$end",
- "error",
- "IDENTIFIER",
- "EQUAL",
- "PLUS",
- "MINUS",
- "ASTERISK",
- "FWD_SLASH",
- "COLON",
- "FLOAT",
- "INTEGER",
- "STRING",
- "EXPO",
- "INDENT",
- "OUTDENT",
- "OPAREN",
- "CPAREN",
- "DOT",
- "SIGNATURE",
- "NL",
- "EOF",
- "PIPE",
- "COMMA",
- "NIL",
- "TRUE",
- "FALSE",
- "EQUALITY",
- "CALL",
- "SELF",
- "CONSTANT",
- "CHAR",
- "DOUBLE_TICK_STRING",
- "DOUBLE_TICK_STRING_END",
- "INTERPOLATE_START",
- "INTERPOLATE_END",
- "BOX",
- "LSQUARE",
- "RSQUARE",
- "FACES",
- "LFACE",
- "RFACE",
- "BANG",
- "TILDE",
- "RETURN",
- "NOT_EQUALITY",
- "OR",
- "AND",
- "GT",
- "LT",
- "GTE",
- "LTE",
- "AT",
- "PERCENT",
- "$start",
- "statements",
- "statement",
- "expr",
- "eol",
- "nlq",
- "literal",
- "grouped_expr",
- "binary_op",
- "unary_op",
- "method_call",
- "constant",
- "variable",
- "array",
- "hash",
- "return",
- "return_expr",
- "return_nil",
- "empty_array",
- "array_list",
- "array_items",
- "empty_hash",
- "hash_list",
- "hash_items",
- "hash_item",
- "indented",
- "indented_w_stmts",
- "indented_w_expr",
- "indented_wo_stmts",
- "indent",
- "outdent",
- "indent_w_args",
- "indent_pipe",
- "indent_args",
- "indent_wo_args",
- "indent_arg",
- "arg_var",
- "method_call_on_object",
- "method_call_on_self",
- "method_call_on_closure",
- "call_signature",
- "call_arguments",
- "call_simple_name",
- "call_argument",
- "call_passed_arg",
- "call_passed_simple",
- "call_passed_indented",
- "assignment",
- "addition",
- "subtraction",
- "multiplication",
- "division",
- "exponentiation",
- "modulo",
- "equality",
- "not_equality",
- "logical_or",
- "logical_and",
- "greater_than",
- "less_than",
- "greater_or_eq",
- "less_or_eq",
- "unary_not",
- "unary_plus",
- "unary_minus",
- "unary_complement",
- "integer",
- "float",
- "string",
- "nil",
- "true",
- "false",
- "self",
- "interpolated_string",
- "empty_string",
- "interpolated_string_contents",
- "interpolation",
- "interpolated_string_chunk",
- "chars" ]
-
-Racc_debug_parser = false
-
-##### State transition tables end #####
-
-# reduce 0 omitted
-
-# reduce 1 omitted
-
-module_eval(<<'.,.,', 'huia.y', 44)
- def _reduce_2(val, _values, result)
- return scope
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 46)
- def _reduce_3(val, _values, result)
- return scope.append val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 47)
- def _reduce_4(val, _values, result)
- return scope.append val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 48)
- def _reduce_5(val, _values, result)
- return scope
- result
- end
-.,.,
-
-# reduce 6 omitted
-
-# reduce 7 omitted
-
-# reduce 8 omitted
-
-# reduce 9 omitted
-
-# reduce 10 omitted
-
-# reduce 11 omitted
-
-# reduce 12 omitted
-
-# reduce 13 omitted
-
-# reduce 14 omitted
-
-# reduce 15 omitted
-
-# reduce 16 omitted
-
-# reduce 17 omitted
-
-# reduce 18 omitted
-
-# reduce 19 omitted
-
-# reduce 20 omitted
-
-# reduce 21 omitted
-
-module_eval(<<'.,.,', 'huia.y', 66)
- def _reduce_22(val, _values, result)
- return n(:Return, val[1])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 67)
- def _reduce_23(val, _values, result)
- return n(:Return, n(:Nil))
- result
- end
-.,.,
-
-# reduce 24 omitted
-
-# reduce 25 omitted
-
-module_eval(<<'.,.,', 'huia.y', 72)
- def _reduce_26(val, _values, result)
- return n :Array
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 74)
- def _reduce_27(val, _values, result)
- return val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 75)
- def _reduce_28(val, _values, result)
- return n :Array, [val[0]]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 76)
- def _reduce_29(val, _values, result)
- val[0].append(val[2]); return val[0]
- result
- end
-.,.,
-
-# reduce 30 omitted
-
-# reduce 31 omitted
-
-module_eval(<<'.,.,', 'huia.y', 80)
- def _reduce_32(val, _values, result)
- return n :Hash
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 81)
- def _reduce_33(val, _values, result)
- return val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 82)
- def _reduce_34(val, _values, result)
- return n :Hash, val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 83)
- def _reduce_35(val, _values, result)
- val[0].append(val[2]); return val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 84)
- def _reduce_36(val, _values, result)
- return n :HashItem, val[0], val[2]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 86)
- def _reduce_37(val, _values, result)
- return constant val[0]
- result
- end
-.,.,
-
-# reduce 38 omitted
-
-# reduce 39 omitted
-
-# reduce 40 omitted
-
-module_eval(<<'.,.,', 'huia.y', 91)
- def _reduce_41(val, _values, result)
- return val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 92)
- def _reduce_42(val, _values, result)
- return val[0].append(val[1])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 93)
- def _reduce_43(val, _values, result)
- return val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 94)
- def _reduce_44(val, _values, result)
- return pop_scope
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 97)
- def _reduce_45(val, _values, result)
- return val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 98)
- def _reduce_46(val, _values, result)
- return push_scope
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 99)
- def _reduce_47(val, _values, result)
- return push_scope
- result
- end
-.,.,
-
-# reduce 48 omitted
-
-# reduce 49 omitted
-
-# reduce 50 omitted
-
-# reduce 51 omitted
-
-module_eval(<<'.,.,', 'huia.y', 105)
- def _reduce_52(val, _values, result)
- return scope.add_argument val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 106)
- def _reduce_53(val, _values, result)
- return n :Assignment, val[0], val[2]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 107)
- def _reduce_54(val, _values, result)
- return n :Variable, val[0]
- result
- end
-.,.,
-
-# reduce 55 omitted
-
-# reduce 56 omitted
-
-# reduce 57 omitted
-
-module_eval(<<'.,.,', 'huia.y', 112)
- def _reduce_58(val, _values, result)
- return n :MethodCall, val[0], val[2]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 113)
- def _reduce_59(val, _values, result)
- return n :MethodCall, val[0], n(:CallSignature, val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 114)
- def _reduce_60(val, _values, result)
- return n :MethodCall, scope_instance, val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 116)
- def _reduce_61(val, _values, result)
- return n :MethodCall, this_closure, val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 117)
- def _reduce_62(val, _values, result)
- return n :MethodCall, this_closure, n(:CallSignature, val[1])
- result
- end
-.,.,
-
-# reduce 63 omitted
-
-# reduce 64 omitted
-
-module_eval(<<'.,.,', 'huia.y', 121)
- def _reduce_65(val, _values, result)
- return n :CallSignature, val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 122)
- def _reduce_66(val, _values, result)
- return n :CallSignature, val[0], [val[1]]
- result
- end
-.,.,
-
-# reduce 67 omitted
-
-# reduce 68 omitted
-
-# reduce 69 omitted
-
-# reduce 70 omitted
-
-# reduce 71 omitted
-
-# reduce 72 omitted
-
-module_eval(<<'.,.,', 'huia.y', 129)
- def _reduce_73(val, _values, result)
- return val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 130)
- def _reduce_74(val, _values, result)
- return val[0].concat_signature val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 132)
- def _reduce_75(val, _values, result)
- return n :Expression, val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 134)
- def _reduce_76(val, _values, result)
- return allocate_local val[0]
- result
- end
-.,.,
-
-# reduce 77 omitted
-
-# reduce 78 omitted
-
-# reduce 79 omitted
-
-# reduce 80 omitted
-
-# reduce 81 omitted
-
-# reduce 82 omitted
-
-# reduce 83 omitted
-
-# reduce 84 omitted
-
-# reduce 85 omitted
-
-# reduce 86 omitted
-
-# reduce 87 omitted
-
-# reduce 88 omitted
-
-# reduce 89 omitted
-
-# reduce 90 omitted
-
-# reduce 91 omitted
-
-module_eval(<<'.,.,', 'huia.y', 152)
- def _reduce_92(val, _values, result)
- return allocate_local_assignment val[0], val[2]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 153)
- def _reduce_93(val, _values, result)
- return binary val[0], val[2], 'plus:'
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 154)
- def _reduce_94(val, _values, result)
- return binary val[0], val[2], 'minus:'
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 155)
- def _reduce_95(val, _values, result)
- return binary val[0], val[2], 'multiplyBy:'
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 156)
- def _reduce_96(val, _values, result)
- return binary val[0], val[2], 'divideBy:'
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 157)
- def _reduce_97(val, _values, result)
- return binary val[0], val[2], 'toThePowerOf:'
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 158)
- def _reduce_98(val, _values, result)
- return binary val[0], val[2], 'moduloOf:'
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 159)
- def _reduce_99(val, _values, result)
- return binary val[0], val[2], 'isEqualTo:'
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 160)
- def _reduce_100(val, _values, result)
- return binary val[0], val[2], 'isNotEqualTo:'
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 161)
- def _reduce_101(val, _values, result)
- return binary val[0], val[2], 'logicalOr:'
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 162)
- def _reduce_102(val, _values, result)
- return binary val[0], val[2], 'logicalAnd:'
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 163)
- def _reduce_103(val, _values, result)
- return binary val[0], val[2], 'isGreaterThan:'
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 164)
- def _reduce_104(val, _values, result)
- return binary val[0], val[2], 'isLessThan:'
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 165)
- def _reduce_105(val, _values, result)
- return binary val[0], val[2], 'isGreaterOrEqualTo:'
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 166)
- def _reduce_106(val, _values, result)
- return binary val[0], val[2], 'isLessOrEqualTo:'
- result
- end
-.,.,
-
-# reduce 107 omitted
-
-# reduce 108 omitted
-
-# reduce 109 omitted
-
-# reduce 110 omitted
-
-module_eval(<<'.,.,', 'huia.y', 173)
- def _reduce_111(val, _values, result)
- return unary val[1], 'unaryNot'
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 174)
- def _reduce_112(val, _values, result)
- return unary val[1], 'unaryPlus'
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 175)
- def _reduce_113(val, _values, result)
- return unary val[1], 'unaryMinus'
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 176)
- def _reduce_114(val, _values, result)
- return unary val[1], 'unaryComplement'
- result
- end
-.,.,
-
-# reduce 115 omitted
-
-# reduce 116 omitted
-
-# reduce 117 omitted
-
-# reduce 118 omitted
-
-# reduce 119 omitted
-
-# reduce 120 omitted
-
-# reduce 121 omitted
-
-module_eval(<<'.,.,', 'huia.y', 186)
- def _reduce_122(val, _values, result)
- return n :Float, val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 187)
- def _reduce_123(val, _values, result)
- return n :Integer, val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 188)
- def _reduce_124(val, _values, result)
- return n :Nil
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 189)
- def _reduce_125(val, _values, result)
- return n :True
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 190)
- def _reduce_126(val, _values, result)
- return n :False
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 191)
- def _reduce_127(val, _values, result)
- return n :Self
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 193)
- def _reduce_128(val, _values, result)
- return n :String, val[0]
- result
- end
-.,.,
-
-# reduce 129 omitted
-
-# reduce 130 omitted
-
-module_eval(<<'.,.,', 'huia.y', 197)
- def _reduce_131(val, _values, result)
- return val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 198)
- def _reduce_132(val, _values, result)
- return val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 199)
- def _reduce_133(val, _values, result)
- return n :InterpolatedString, val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 200)
- def _reduce_134(val, _values, result)
- val[0].append(val[1]); return val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 201)
- def _reduce_135(val, _values, result)
- return val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 202)
- def _reduce_136(val, _values, result)
- return to_string(val[0])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 203)
- def _reduce_137(val, _values, result)
- return n :String, ''
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 205)
- def _reduce_138(val, _values, result)
- return n :String, val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'huia.y', 206)
- def _reduce_139(val, _values, result)
- val[0].append(val[1]); return val[0]
- result
- end
-.,.,
-
-def _reduce_none(val, _values, result)
- val[0]
-end
-
- end # class Parser
-end # module Huia
diff --git a/test/racc/regress/journey b/test/racc/regress/journey
deleted file mode 100644
index 3daf81dac0..0000000000
--- a/test/racc/regress/journey
+++ /dev/null
@@ -1,222 +0,0 @@
-#
-# DO NOT MODIFY!!!!
-# This file is automatically generated by Racc 1.5.0
-# from Racc grammar file "".
-#
-
-require 'racc/parser.rb'
-
-
-require 'journey/parser_extras'
-module Journey
- class Parser < Racc::Parser
-##### State transition tables begin ###
-
-racc_action_table = [
- 17, 21, 13, 15, 14, 7, nil, 16, 8, 19,
- 13, 15, 14, 7, 23, 16, 8, 19, 13, 15,
- 14, 7, nil, 16, 8, 13, 15, 14, 7, nil,
- 16, 8, 13, 15, 14, 7, nil, 16, 8 ]
-
-racc_action_check = [
- 1, 17, 1, 1, 1, 1, nil, 1, 1, 1,
- 20, 20, 20, 20, 20, 20, 20, 20, 0, 0,
- 0, 0, nil, 0, 0, 7, 7, 7, 7, nil,
- 7, 7, 19, 19, 19, 19, nil, 19, 19 ]
-
-racc_action_pointer = [
- 16, 0, nil, nil, nil, nil, nil, 23, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 1, nil, 30,
- 8, nil, nil, nil ]
-
-racc_action_default = [
- -18, -18, -2, -3, -4, -5, -6, -18, -9, -10,
- -11, -12, -13, -14, -15, -16, -17, -18, -1, -18,
- -18, 24, -8, -7 ]
-
-racc_goto_table = [
- 18, 1, nil, nil, nil, nil, nil, nil, 20, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 22, 18 ]
-
-racc_goto_check = [
- 2, 1, nil, nil, nil, nil, nil, nil, 1, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 2, 2 ]
-
-racc_goto_pointer = [
- nil, 1, -1, nil, nil, nil, nil, nil, nil, nil,
- nil ]
-
-racc_goto_default = [
- nil, nil, 2, 3, 4, 5, 6, 9, 10, 11,
- 12 ]
-
-racc_reduce_table = [
- 0, 0, :racc_error,
- 2, 11, :_reduce_1,
- 1, 11, :_reduce_2,
- 1, 11, :_reduce_none,
- 1, 12, :_reduce_none,
- 1, 12, :_reduce_none,
- 1, 12, :_reduce_none,
- 3, 15, :_reduce_7,
- 3, 13, :_reduce_8,
- 1, 16, :_reduce_9,
- 1, 14, :_reduce_none,
- 1, 14, :_reduce_none,
- 1, 14, :_reduce_none,
- 1, 14, :_reduce_none,
- 1, 19, :_reduce_14,
- 1, 17, :_reduce_15,
- 1, 18, :_reduce_16,
- 1, 20, :_reduce_17 ]
-
-racc_reduce_n = 18
-
-racc_shift_n = 24
-
-racc_token_table = {
- false => 0,
- :error => 1,
- :SLASH => 2,
- :LITERAL => 3,
- :SYMBOL => 4,
- :LPAREN => 5,
- :RPAREN => 6,
- :DOT => 7,
- :STAR => 8,
- :OR => 9 }
-
-racc_nt_base = 10
-
-racc_use_result_var = true
-
-Racc_arg = [
- racc_action_table,
- racc_action_check,
- racc_action_default,
- racc_action_pointer,
- racc_goto_table,
- racc_goto_check,
- racc_goto_default,
- racc_goto_pointer,
- racc_nt_base,
- racc_reduce_table,
- racc_token_table,
- racc_shift_n,
- racc_reduce_n,
- racc_use_result_var ]
-
-Racc_token_to_s_table = [
- "$end",
- "error",
- "SLASH",
- "LITERAL",
- "SYMBOL",
- "LPAREN",
- "RPAREN",
- "DOT",
- "STAR",
- "OR",
- "$start",
- "expressions",
- "expression",
- "or",
- "terminal",
- "group",
- "star",
- "symbol",
- "literal",
- "slash",
- "dot" ]
-
-Racc_debug_parser = false
-
-##### State transition tables end #####
-
-# reduce 0 omitted
-
-module_eval(<<'.,.,', 'journey.y', 6)
- def _reduce_1(val, _values, result)
- result = Cat.new(val.first, val.last)
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'journey.y', 7)
- def _reduce_2(val, _values, result)
- result = val.first
- result
- end
-.,.,
-
-# reduce 3 omitted
-
-# reduce 4 omitted
-
-# reduce 5 omitted
-
-# reduce 6 omitted
-
-module_eval(<<'.,.,', 'journey.y', 16)
- def _reduce_7(val, _values, result)
- result = Group.new(val[1])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'journey.y', 19)
- def _reduce_8(val, _values, result)
- result = Or.new([val.first, val.last])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'journey.y', 22)
- def _reduce_9(val, _values, result)
- result = Star.new(Symbol.new(val.last))
- result
- end
-.,.,
-
-# reduce 10 omitted
-
-# reduce 11 omitted
-
-# reduce 12 omitted
-
-# reduce 13 omitted
-
-module_eval(<<'.,.,', 'journey.y', 31)
- def _reduce_14(val, _values, result)
- result = Slash.new('/')
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'journey.y', 34)
- def _reduce_15(val, _values, result)
- result = Symbol.new(val.first)
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'journey.y', 37)
- def _reduce_16(val, _values, result)
- result = Literal.new(val.first)
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'journey.y', 39)
- def _reduce_17(val, _values, result)
- result = Dot.new(val.first)
- result
- end
-.,.,
-
-def _reduce_none(val, _values, result)
- val[0]
-end
-
- end # class Parser
-end # module Journey
diff --git a/test/racc/regress/liquor b/test/racc/regress/liquor
deleted file mode 100644
index 9fa2ca4da0..0000000000
--- a/test/racc/regress/liquor
+++ /dev/null
@@ -1,885 +0,0 @@
-#
-# DO NOT MODIFY!!!!
-# This file is automatically generated by Racc 1.5.0
-# from Racc grammar file "".
-#
-
-require 'racc/parser.rb'
-module Liquor
- class Parser < Racc::Parser
-
-module_eval(<<'...end liquor.y/module_eval...', 'liquor.y', 216)
- attr_reader :errors, :ast
-
- def initialize(tags={})
- super()
-
- @errors = []
- @ast = nil
- @tags = tags
- end
-
- def success?
- @errors.empty?
- end
-
- def parse(string, name='(code)')
- @errors.clear
- @name = name
- @ast = nil
-
- begin
- @stream = Lexer.lex(string, @name, @tags)
- @ast = do_parse
- rescue Liquor::SyntaxError => e
- @errors << e
- end
-
- success?
- end
-
- def next_token
- tok = @stream.shift
- [ tok[0], tok ] if tok
- end
-
- TOKEN_NAME_MAP = {
- :comma => ',',
- :dot => '.',
- :lblock => '{%',
- :rblock => '%}',
- :linterp => '{{',
- :rinterp => '}}',
- :lbracket => '[',
- :rbracket => ']',
- :lparen => '(',
- :rparen => ')',
- :pipe => '|',
- :op_not => '!',
- :op_mul => '*',
- :op_div => '/',
- :op_mod => '%',
- :op_plus => '+',
- :op_minus => '-',
- :op_eq => '==',
- :op_neq => '!=',
- :op_lt => '<',
- :op_leq => '<=',
- :op_gt => '>',
- :op_geq => '>=',
- :keyword => 'keyword argument name',
- :kwarg => 'keyword argument',
- :ident => 'identifier',
- }
-
- def on_error(error_token_id, error_token, value_stack)
- if token_to_str(error_token_id) == "$end"
- raise Liquor::SyntaxError.new("unexpected end of program", {
- file: @name
- })
- else
- type, (loc, value) = error_token
- type = TOKEN_NAME_MAP[type] || type
-
- raise Liquor::SyntaxError.new("unexpected token `#{type}'", loc)
- end
- end
-
- def retag(nodes)
- loc = nodes.map { |node| node[1] }.compact
- first, *, last = loc
- return first if last.nil?
-
- {
- file: first[:file],
- line: first[:line],
- start: first[:start],
- end: last[:end],
- }
- end
-
- def reduce_tag_args(list)
- list.each_slice(2).reduce([]) { |args, (k, v)|
- if v[0] == :block
- args << [ :blockarg, retag([ k, v ]), k, v[2] || [] ]
- else
- args << [ :kwarg, retag([ k, v ]), k, v ]
- end
- }
- end
-...end liquor.y/module_eval...
-##### State transition tables begin ###
-
-racc_action_table = [
- 76, 26, 26, 6, 7, 22, 5, 6, 25, 25,
- 5, 28, 32, 36, 37, 34, 35, 31, 29, 27,
- 33, 2, 30, 26, 26, 2, 6, 23, 41, 5,
- 25, 25, 38, 39, 28, 32, 36, 37, 34, 35,
- 31, 29, 27, 33, 2, 30, 40, 26, 96, 6,
- 24, 97, 5, 43, 25, 38, 39, 28, 32, 36,
- 37, 34, 35, 31, 29, 27, 33, 2, 30, 26,
- 54, 70, 77, 26, 75, 26, 25, 52, 38, 39,
- 25, 43, 25, 28, 32, 36, 37, 34, 35, 31,
- 29, 27, 33, 26, 30, 84, 26, 51, 6, 96,
- 25, 5, 97, 25, 38, 39, 28, 32, 36, 37,
- 34, 35, 31, 29, 27, 33, 2, 30, 74, 26,
- 87, 82, 96, 74, 70, 97, 25, 38, 39, 28,
- 32, 36, 37, 34, 35, 31, 29, 27, 33, 94,
- 30, 98, 26, 107, 6, 111, 52, 5, nil, 25,
- 38, 39, 28, 32, 36, 37, 34, 35, 31, 29,
- 27, 33, 2, 30, nil, 26, 51, 6, nil, 74,
- 5, nil, 25, 38, 39, 28, 32, 36, 37, 34,
- 35, 31, 29, 27, 33, 2, 30, nil, 26, nil,
- nil, nil, 102, nil, nil, 25, 38, 39, 28, 32,
- 36, 37, 34, 35, 31, 29, 27, 33, nil, 30,
- nil, 26, 96, nil, nil, 97, nil, nil, 25, 38,
- 39, 28, 32, 36, 37, 34, 35, 31, 29, 27,
- 33, nil, 30, nil, 26, nil, nil, nil, nil, nil,
- nil, 25, 38, 39, 28, 32, 36, 37, 34, 35,
- 31, 29, 27, 33, nil, 30, 13, 15, nil, 13,
- 15, 21, nil, 14, 21, 38, 14, nil, nil, nil,
- 18, nil, nil, 18, 19, nil, nil, 19, nil, 13,
- 15, nil, 16, nil, 21, 16, 14, nil, nil, 13,
- 15, nil, nil, 18, 21, nil, 14, 19, nil, 13,
- 15, nil, nil, 18, 21, 16, 14, 19, nil, 13,
- 15, 52, nil, 18, 21, 16, 14, 19, nil, 13,
- 15, nil, nil, 18, 21, 16, 14, 19, nil, 13,
- 15, 51, nil, 18, 21, 16, 14, 19, nil, 13,
- 15, nil, nil, 18, 21, 16, 14, 19, nil, 13,
- 15, nil, nil, 18, 21, 16, 14, 19, nil, 13,
- 15, nil, nil, 18, 21, 16, 14, 19, nil, 13,
- 15, nil, nil, 18, 21, 16, 14, 19, nil, 13,
- 15, nil, nil, 18, 21, 16, 14, 19, nil, 13,
- 15, nil, nil, 18, 21, 16, 14, 19, nil, 13,
- 15, nil, nil, 18, 21, 16, 14, 19, nil, 13,
- 15, nil, nil, 18, 21, 16, 14, 19, nil, 13,
- 15, nil, nil, 18, 21, 16, 14, 19, nil, 13,
- 15, nil, nil, 18, 21, 16, 14, 19, nil, 13,
- 15, nil, nil, 18, 21, 16, 14, 19, nil, 13,
- 15, nil, nil, 18, 21, 16, 14, 19, nil, 13,
- 15, 74, nil, 18, 21, 16, 14, 19, nil, 13,
- 15, nil, nil, 18, 21, 16, 14, 19, nil, 13,
- 15, nil, nil, 18, 21, 16, 14, 19, nil, 13,
- 15, 81, nil, 18, 21, 16, 14, 19, nil, 13,
- 15, nil, nil, 18, 21, 16, 14, 19, nil, 13,
- 15, nil, 26, 18, 21, 16, 14, 19, nil, 25,
- nil, 101, 28, 18, nil, 16, nil, 19, 31, 29,
- 27, 106, 26, 30, nil, 16, nil, nil, nil, 25,
- nil, nil, 28, nil, 26, nil, nil, nil, 31, 29,
- 27, 25, nil, 30, 28, nil, 26, nil, nil, nil,
- 31, 29, 27, 25, nil, 30, 28, nil, 26, nil,
- nil, nil, 31, 29, 27, 25, nil, 30, 28, nil,
- 26, nil, nil, nil, 31, 29, 27, 25, nil, 30,
- 28, nil, 26, nil, nil, nil, 31, 29, 27, 25,
- nil, 30, 28, 32, 36, 37, 34, 35, 31, 29,
- 27, 33, 26, 30, 26, nil, nil, nil, nil, 25,
- nil, 25, 28, nil, 28, nil, nil, nil, nil, 29,
- 27, 29, 27 ]
-
-racc_action_check = [
- 47, 47, 45, 0, 1, 6, 0, 2, 47, 45,
- 2, 47, 47, 47, 47, 47, 47, 47, 47, 47,
- 47, 0, 47, 46, 11, 2, 3, 7, 12, 3,
- 46, 11, 47, 47, 11, 11, 11, 11, 11, 11,
- 11, 11, 11, 11, 3, 11, 11, 44, 94, 4,
- 11, 94, 4, 13, 44, 11, 11, 44, 44, 44,
- 44, 44, 44, 44, 44, 44, 44, 4, 44, 55,
- 26, 40, 48, 49, 44, 56, 55, 49, 44, 44,
- 49, 54, 56, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 57, 49, 69, 53, 49, 81, 107,
- 57, 81, 107, 53, 49, 49, 53, 53, 53, 53,
- 53, 53, 53, 53, 53, 53, 81, 53, 70, 71,
- 72, 53, 111, 71, 84, 111, 71, 53, 53, 71,
- 71, 71, 71, 71, 71, 71, 71, 71, 71, 91,
- 71, 96, 79, 103, 101, 109, 79, 101, nil, 79,
- 71, 71, 79, 79, 79, 79, 79, 79, 79, 79,
- 79, 79, 101, 79, nil, 88, 79, 106, nil, 88,
- 106, nil, 88, 79, 79, 88, 88, 88, 88, 88,
- 88, 88, 88, 88, 88, 106, 88, nil, 99, nil,
- nil, nil, 99, nil, nil, 99, 88, 88, 99, 99,
- 99, 99, 99, 99, 99, 99, 99, 99, nil, 99,
- nil, 104, 104, nil, nil, 104, nil, nil, 104, 99,
- 99, 104, 104, 104, 104, 104, 104, 104, 104, 104,
- 104, nil, 104, nil, 67, nil, nil, nil, nil, nil,
- nil, 67, 104, 104, 67, 67, 67, 67, 67, 67,
- 67, 67, 67, 67, nil, 67, 5, 5, nil, 14,
- 14, 5, nil, 5, 14, 67, 14, nil, nil, nil,
- 5, nil, nil, 14, 5, nil, nil, 14, nil, 18,
- 18, nil, 5, nil, 18, 14, 18, nil, nil, 19,
- 19, nil, nil, 18, 19, nil, 19, 18, nil, 21,
- 21, nil, nil, 19, 21, 18, 21, 19, nil, 22,
- 22, 22, nil, 21, 22, 19, 22, 21, nil, 25,
- 25, nil, nil, 22, 25, 21, 25, 22, nil, 27,
- 27, 22, nil, 25, 27, 22, 27, 25, nil, 28,
- 28, nil, nil, 27, 28, 25, 28, 27, nil, 29,
- 29, nil, nil, 28, 29, 27, 29, 28, nil, 30,
- 30, nil, nil, 29, 30, 28, 30, 29, nil, 31,
- 31, nil, nil, 30, 31, 29, 31, 30, nil, 32,
- 32, nil, nil, 31, 32, 30, 32, 31, nil, 33,
- 33, nil, nil, 32, 33, 31, 33, 32, nil, 34,
- 34, nil, nil, 33, 34, 32, 34, 33, nil, 35,
- 35, nil, nil, 34, 35, 33, 35, 34, nil, 36,
- 36, nil, nil, 35, 36, 34, 36, 35, nil, 37,
- 37, nil, nil, 36, 37, 35, 37, 36, nil, 38,
- 38, nil, nil, 37, 38, 36, 38, 37, nil, 39,
- 39, nil, nil, 38, 39, 37, 39, 38, nil, 43,
- 43, 43, nil, 39, 43, 38, 43, 39, nil, 52,
- 52, nil, nil, 43, 52, 39, 52, 43, nil, 74,
- 74, nil, nil, 52, 74, 43, 74, 52, nil, 76,
- 76, 52, nil, 74, 76, 52, 76, 74, nil, 97,
- 97, nil, nil, 76, 97, 74, 97, 76, nil, 102,
- 102, nil, 60, 97, 102, 76, 102, 97, nil, 60,
- nil, 97, 60, 102, nil, 97, nil, 102, 60, 60,
- 60, 102, 61, 60, nil, 102, nil, nil, nil, 61,
- nil, nil, 61, nil, 62, nil, nil, nil, 61, 61,
- 61, 62, nil, 61, 62, nil, 63, nil, nil, nil,
- 62, 62, 62, 63, nil, 62, 63, nil, 64, nil,
- nil, nil, 63, 63, 63, 64, nil, 63, 64, nil,
- 65, nil, nil, nil, 64, 64, 64, 65, nil, 64,
- 65, nil, 66, nil, nil, nil, 65, 65, 65, 66,
- nil, 65, 66, 66, 66, 66, 66, 66, 66, 66,
- 66, 66, 58, 66, 59, nil, nil, nil, nil, 58,
- nil, 59, 58, nil, 59, nil, nil, nil, nil, 58,
- 58, 59, 59 ]
-
-racc_action_pointer = [
- -5, 4, -1, 18, 41, 251, 0, 27, nil, nil,
- nil, 21, -1, 41, 254, nil, nil, nil, 274, 284,
- nil, 294, 304, nil, nil, 314, 65, 324, 334, 344,
- 354, 364, 374, 384, 394, 404, 414, 424, 434, 444,
- 66, nil, nil, 454, 44, -1, 20, -2, 44, 70,
- nil, nil, 464, 93, 69, 66, 72, 90, 609, 611,
- 509, 529, 541, 553, 565, 577, 589, 231, nil, 70,
- 111, 116, 90, nil, 474, nil, 484, nil, nil, 139,
- nil, 90, nil, nil, 119, nil, nil, nil, 162, nil,
- nil, 130, nil, nil, 44, nil, 114, 494, nil, 185,
- nil, 136, 504, 134, 208, nil, 159, 95, nil, 136,
- nil, 118, nil ]
-
-racc_action_default = [
- -1, -57, -1, -1, -1, -57, -57, -57, -2, -3,
- -4, -57, -57, -7, -57, -9, -10, -11, -57, -57,
- -31, -35, -57, 113, -5, -57, -57, -57, -57, -57,
- -57, -57, -57, -57, -57, -57, -57, -57, -57, -57,
- -57, -6, -12, -40, -57, -16, -17, -34, -57, -57,
- -46, -47, -57, -57, -15, -18, -19, -20, -21, -22,
- -23, -24, -25, -26, -27, -28, -29, -30, -41, -43,
- -40, -40, -57, -38, -57, -8, -35, -32, -45, -57,
- -48, -1, -13, -14, -57, -44, -37, -36, -40, -33,
- -50, -57, -42, -39, -57, -49, -57, -57, -51, -57,
- -52, -1, -57, -57, -57, -54, -1, -57, -56, -57,
- -53, -57, -55 ]
-
-racc_goto_table = [
- 1, 11, 8, 9, 10, 48, 68, 12, 42, 50,
- 44, 72, 80, 73, 45, 46, 100, 105, 49, nil,
- nil, 53, nil, 55, 56, 57, 58, 59, 60, 61,
- 62, 63, 64, 65, 66, 67, 78, nil, nil, 71,
- 85, 86, 95, nil, nil, nil, nil, nil, 79, 83,
- 92, nil, 108, nil, nil, 110, nil, nil, 93, 112,
- 89, nil, nil, nil, nil, nil, 90, nil, nil, nil,
- 88, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 91, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 99, nil, nil, nil, nil, 104, nil,
- nil, 103, nil, nil, nil, nil, 109 ]
-
-racc_goto_check = [
- 1, 4, 1, 1, 1, 9, 12, 5, 8, 14,
- 4, 10, 15, 11, 4, 4, 17, 18, 4, nil,
- nil, 4, nil, 4, 4, 4, 4, 4, 4, 4,
- 4, 4, 4, 4, 4, 4, 14, nil, nil, 4,
- 11, 11, 16, nil, nil, nil, nil, nil, 4, 8,
- 12, nil, 16, nil, nil, 16, nil, nil, 11, 16,
- 9, nil, nil, nil, nil, nil, 14, nil, nil, nil,
- 4, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 1, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 4, nil, nil, nil, nil, 4, nil,
- nil, 1, nil, nil, nil, nil, 1 ]
-
-racc_goto_pointer = [
- nil, 0, nil, nil, -4, 2, nil, nil, -5, -16,
- -32, -30, -34, nil, -13, -40, -52, -81, -85 ]
-
-racc_goto_default = [
- nil, nil, 3, 4, 47, nil, 20, 17, nil, nil,
- nil, nil, nil, 69, nil, nil, nil, nil, nil ]
-
-racc_reduce_table = [
- 0, 0, :racc_error,
- 0, 37, :_reduce_1,
- 2, 37, :_reduce_2,
- 2, 37, :_reduce_3,
- 2, 37, :_reduce_4,
- 3, 38, :_reduce_5,
- 3, 38, :_reduce_6,
- 1, 42, :_reduce_none,
- 3, 42, :_reduce_8,
- 1, 40, :_reduce_none,
- 1, 40, :_reduce_none,
- 1, 40, :_reduce_none,
- 2, 40, :_reduce_12,
- 4, 40, :_reduce_13,
- 4, 40, :_reduce_14,
- 3, 40, :_reduce_15,
- 2, 40, :_reduce_16,
- 2, 40, :_reduce_17,
- 3, 40, :_reduce_18,
- 3, 40, :_reduce_19,
- 3, 40, :_reduce_20,
- 3, 40, :_reduce_21,
- 3, 40, :_reduce_22,
- 3, 40, :_reduce_23,
- 3, 40, :_reduce_24,
- 3, 40, :_reduce_25,
- 3, 40, :_reduce_26,
- 3, 40, :_reduce_27,
- 3, 40, :_reduce_28,
- 3, 40, :_reduce_29,
- 3, 40, :_reduce_30,
- 1, 40, :_reduce_none,
- 3, 43, :_reduce_32,
- 3, 45, :_reduce_33,
- 1, 45, :_reduce_34,
- 0, 45, :_reduce_35,
- 3, 44, :_reduce_36,
- 2, 46, :_reduce_37,
- 1, 46, :_reduce_38,
- 3, 47, :_reduce_39,
- 0, 47, :_reduce_40,
- 3, 41, :_reduce_41,
- 3, 48, :_reduce_42,
- 1, 48, :_reduce_43,
- 2, 49, :_reduce_44,
- 4, 39, :_reduce_45,
- 3, 39, :_reduce_46,
- 1, 50, :_reduce_47,
- 2, 50, :_reduce_48,
- 4, 51, :_reduce_49,
- 2, 51, :_reduce_50,
- 2, 52, :_reduce_51,
- 2, 52, :_reduce_52,
- 4, 53, :_reduce_53,
- 3, 53, :_reduce_54,
- 4, 54, :_reduce_55,
- 2, 54, :_reduce_56 ]
-
-racc_reduce_n = 57
-
-racc_shift_n = 113
-
-racc_token_table = {
- false => 0,
- :error => 1,
- :comma => 2,
- :dot => 3,
- :endtag => 4,
- :ident => 5,
- :integer => 6,
- :keyword => 7,
- :lblock => 8,
- :lblock2 => 9,
- :lbracket => 10,
- :linterp => 11,
- :lparen => 12,
- :op_div => 13,
- :op_eq => 14,
- :op_gt => 15,
- :op_geq => 16,
- :op_lt => 17,
- :op_leq => 18,
- :op_minus => 19,
- :op_mod => 20,
- :op_mul => 21,
- :op_neq => 22,
- :op_not => 23,
- :op_plus => 24,
- :pipe => 25,
- :plaintext => 26,
- :rblock => 27,
- :rbracket => 28,
- :rinterp => 29,
- :rparen => 30,
- :string => 31,
- :tag_ident => 32,
- :op_uminus => 33,
- :op_and => 34,
- :op_or => 35 }
-
-racc_nt_base = 36
-
-racc_use_result_var = true
-
-Racc_arg = [
- racc_action_table,
- racc_action_check,
- racc_action_default,
- racc_action_pointer,
- racc_goto_table,
- racc_goto_check,
- racc_goto_default,
- racc_goto_pointer,
- racc_nt_base,
- racc_reduce_table,
- racc_token_table,
- racc_shift_n,
- racc_reduce_n,
- racc_use_result_var ]
-
-Racc_token_to_s_table = [
- "$end",
- "error",
- "comma",
- "dot",
- "endtag",
- "ident",
- "integer",
- "keyword",
- "lblock",
- "lblock2",
- "lbracket",
- "linterp",
- "lparen",
- "op_div",
- "op_eq",
- "op_gt",
- "op_geq",
- "op_lt",
- "op_leq",
- "op_minus",
- "op_mod",
- "op_mul",
- "op_neq",
- "op_not",
- "op_plus",
- "pipe",
- "plaintext",
- "rblock",
- "rbracket",
- "rinterp",
- "rparen",
- "string",
- "tag_ident",
- "op_uminus",
- "op_and",
- "op_or",
- "$start",
- "block",
- "interp",
- "tag",
- "expr",
- "filter_chain",
- "primary_expr",
- "tuple",
- "function_args",
- "tuple_content",
- "function_args_inside",
- "function_keywords",
- "filter_chain_cont",
- "filter_call",
- "tag_first_cont",
- "tag_first_cont2",
- "tag_next_cont",
- "tag_next_cont2",
- "tag_next_cont3" ]
-
-Racc_debug_parser = false
-
-##### State transition tables end #####
-
-# reduce 0 omitted
-
-module_eval(<<'.,.,', 'liquor.y', 47)
- def _reduce_1(val, _values, result)
- result = []
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'liquor.y', 49)
- def _reduce_2(val, _values, result)
- result = [ val[0], *val[1] ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'liquor.y', 51)
- def _reduce_3(val, _values, result)
- result = [ val[0], *val[1] ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'liquor.y', 53)
- def _reduce_4(val, _values, result)
- result = [ val[0], *val[1] ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'liquor.y', 57)
- def _reduce_5(val, _values, result)
- result = [ :interp, retag(val), val[1] ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'liquor.y', 59)
- def _reduce_6(val, _values, result)
- result = [ :interp, retag(val), val[1] ]
- result
- end
-.,.,
-
-# reduce 7 omitted
-
-module_eval(<<'.,.,', 'liquor.y', 64)
- def _reduce_8(val, _values, result)
- result = [ val[1][0], retag(val), *val[1][2..-1] ]
- result
- end
-.,.,
-
-# reduce 9 omitted
-
-# reduce 10 omitted
-
-# reduce 11 omitted
-
-module_eval(<<'.,.,', 'liquor.y', 71)
- def _reduce_12(val, _values, result)
- result = [ :call, retag(val), val[0], val[1] ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'liquor.y', 73)
- def _reduce_13(val, _values, result)
- result = [ :index, retag(val), val[0], val[2] ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'liquor.y', 75)
- def _reduce_14(val, _values, result)
- result = [ :external, retag(val), val[0], val[2], val[3] ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'liquor.y', 77)
- def _reduce_15(val, _values, result)
- result = [ :external, retag(val), val[0], val[2], nil ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'liquor.y', 79)
- def _reduce_16(val, _values, result)
- result = [ :uminus, retag(val), val[1] ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'liquor.y', 81)
- def _reduce_17(val, _values, result)
- result = [ :not, retag(val), val[1] ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'liquor.y', 83)
- def _reduce_18(val, _values, result)
- result = [ :mul, retag(val), val[0], val[2] ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'liquor.y', 85)
- def _reduce_19(val, _values, result)
- result = [ :div, retag(val), val[0], val[2] ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'liquor.y', 87)
- def _reduce_20(val, _values, result)
- result = [ :mod, retag(val), val[0], val[2] ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'liquor.y', 89)
- def _reduce_21(val, _values, result)
- result = [ :plus, retag(val), val[0], val[2] ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'liquor.y', 91)
- def _reduce_22(val, _values, result)
- result = [ :minus, retag(val), val[0], val[2] ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'liquor.y', 93)
- def _reduce_23(val, _values, result)
- result = [ :eq, retag(val), val[0], val[2] ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'liquor.y', 95)
- def _reduce_24(val, _values, result)
- result = [ :neq, retag(val), val[0], val[2] ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'liquor.y', 97)
- def _reduce_25(val, _values, result)
- result = [ :lt, retag(val), val[0], val[2] ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'liquor.y', 99)
- def _reduce_26(val, _values, result)
- result = [ :leq, retag(val), val[0], val[2] ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'liquor.y', 101)
- def _reduce_27(val, _values, result)
- result = [ :gt, retag(val), val[0], val[2] ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'liquor.y', 103)
- def _reduce_28(val, _values, result)
- result = [ :geq, retag(val), val[0], val[2] ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'liquor.y', 105)
- def _reduce_29(val, _values, result)
- result = [ :and, retag(val), val[0], val[2] ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'liquor.y', 107)
- def _reduce_30(val, _values, result)
- result = [ :or, retag(val), val[0], val[2] ]
- result
- end
-.,.,
-
-# reduce 31 omitted
-
-module_eval(<<'.,.,', 'liquor.y', 112)
- def _reduce_32(val, _values, result)
- result = [ :tuple, retag(val), val[1].compact ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'liquor.y', 116)
- def _reduce_33(val, _values, result)
- result = [ val[0], *val[2] ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'liquor.y', 118)
- def _reduce_34(val, _values, result)
- result = [ val[0] ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'liquor.y', 120)
- def _reduce_35(val, _values, result)
- result = [ ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'liquor.y', 124)
- def _reduce_36(val, _values, result)
- result = [ :args, retag(val), *val[1] ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'liquor.y', 128)
- def _reduce_37(val, _values, result)
- result = [ val[0], val[1][2] ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'liquor.y', 130)
- def _reduce_38(val, _values, result)
- result = [ nil, val[0][2] ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'liquor.y', 134)
- def _reduce_39(val, _values, result)
- name = val[0][2].to_sym
- tail = val[2][2]
- loc = retag([ val[0], val[1] ])
-
- if tail.include? name
- @errors << SyntaxError.new("duplicate keyword argument `#{val[0][2]}'",
- tail[name][1])
- end
-
- hash = {
- name => [ val[1][0], loc, *val[1][2..-1] ]
- }.merge(tail)
-
- result = [ :keywords, retag([ loc, val[2] ]), hash ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'liquor.y', 150)
- def _reduce_40(val, _values, result)
- result = [ :keywords, nil, {} ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'liquor.y', 154)
- def _reduce_41(val, _values, result)
- result = [ val[0], *val[2] ].
- reduce { |tree, node| node[3][2] = tree; node }
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'liquor.y', 160)
- def _reduce_42(val, _values, result)
- result = [ val[0], *val[2] ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'liquor.y', 162)
- def _reduce_43(val, _values, result)
- result = [ val[0] ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'liquor.y', 166)
- def _reduce_44(val, _values, result)
- ident_loc = val[0][1]
- empty_args_loc = { line: ident_loc[:line],
- start: ident_loc[:end] + 1,
- end: ident_loc[:end] + 1, }
- result = [ :call, val[0][1], val[0],
- [ :args, val[1][1] || empty_args_loc, nil, val[1][2] ] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'liquor.y', 176)
- def _reduce_45(val, _values, result)
- result = [ :tag, retag(val), val[1], val[2], *reduce_tag_args(val[3][2]) ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'liquor.y', 178)
- def _reduce_46(val, _values, result)
- result = [ :tag, retag(val), val[1], nil, *reduce_tag_args(val[2][2]) ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'liquor.y', 186)
- def _reduce_47(val, _values, result)
- result = [ :cont, retag(val), [] ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'liquor.y', 188)
- def _reduce_48(val, _values, result)
- result = [ :cont, retag(val), [ val[0], *val[1][2] ] ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'liquor.y', 192)
- def _reduce_49(val, _values, result)
- result = [ :cont2, val[0][1], [ [:block, val[0][1], val[1] ], *val[3] ] ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'liquor.y', 194)
- def _reduce_50(val, _values, result)
- result = [ :cont2, retag(val), [ val[0], *val[1][2] ] ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'liquor.y', 198)
- def _reduce_51(val, _values, result)
- result = []
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'liquor.y', 200)
- def _reduce_52(val, _values, result)
- result = [ val[0], *val[1] ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'liquor.y', 204)
- def _reduce_53(val, _values, result)
- result = [ [:block, val[0][1], val[1] ], *val[3] ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'liquor.y', 206)
- def _reduce_54(val, _values, result)
- result = [ val[0], val[1], *val[2] ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'liquor.y', 210)
- def _reduce_55(val, _values, result)
- result = [ [:block, val[0][1], val[1] ], *val[3] ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'liquor.y', 212)
- def _reduce_56(val, _values, result)
- result = [ val[0], *val[1] ]
- result
- end
-.,.,
-
-def _reduce_none(val, _values, result)
- val[0]
-end
-
- end # class Parser
-end # module Liquor
diff --git a/test/racc/regress/machete b/test/racc/regress/machete
deleted file mode 100644
index 6297fe2ac9..0000000000
--- a/test/racc/regress/machete
+++ /dev/null
@@ -1,833 +0,0 @@
-#
-# DO NOT MODIFY!!!!
-# This file is automatically generated by Racc 1.5.0
-# from Racc grammar file "".
-#
-
-require 'racc/parser.rb'
-module Machete
- class Parser < Racc::Parser
-
-module_eval(<<'...end machete.y/module_eval...', 'machete.y', 175)
-
-include Matchers
-
-class SyntaxError < StandardError; end
-
-def parse(input)
- @input = input
- @pos = 0
-
- do_parse
-end
-
-private
-
-def integer_value(value)
- if value =~ /^0[bB]/
- value[2..-1].to_i(2)
- elsif value =~ /^0[oO]/
- value[2..-1].to_i(8)
- elsif value =~ /^0[dD]/
- value[2..-1].to_i(10)
- elsif value =~ /^0[xX]/
- value[2..-1].to_i(16)
- elsif value =~ /^0/
- value.to_i(8)
- else
- value.to_i
- end
-end
-
-def symbol_value(value)
- value[1..-1].to_sym
-end
-
-def string_value(value)
- quote = value[0..0]
- if quote == "'"
- value[1..-2].gsub("\\\\", "\\").gsub("\\'", "'")
- elsif quote == '"'
- value[1..-2].
- gsub("\\\\", "\\").
- gsub('\\"', '"').
- gsub("\\n", "\n").
- gsub("\\t", "\t").
- gsub("\\r", "\r").
- gsub("\\f", "\f").
- gsub("\\v", "\v").
- gsub("\\a", "\a").
- gsub("\\e", "\e").
- gsub("\\b", "\b").
- gsub("\\s", "\s").
- gsub(/\\([0-7]{1,3})/) { $1.to_i(8).chr }.
- gsub(/\\x([0-9a-fA-F]{1,2})/) { $1.to_i(16).chr }
- else
- raise "Unknown quote: #{quote.inspect}."
- end
-end
-
-REGEXP_OPTIONS = {
- 'i' => Regexp::IGNORECASE,
- 'm' => Regexp::MULTILINE,
- 'x' => Regexp::EXTENDED
-}
-
-def regexp_value(value)
- /\A\/(.*)\/([imx]*)\z/ =~ value
- pattern, options = $1, $2
-
- Regexp.new(pattern, options.chars.map { |ch| REGEXP_OPTIONS[ch] }.inject(:|))
-end
-
-# "^" needs to be here because if it were among operators recognized by
-# METHOD_NAME, "^=" would be recognized as two tokens.
-SIMPLE_TOKENS = [
- "|",
- "<",
- ">",
- ",",
- "=",
- "^=",
- "^",
- "$=",
- "[",
- "]",
- "*=",
- "*",
- "+",
- "?",
- "{",
- "}"
-]
-
-COMPLEX_TOKENS = [
- [:NIL, /^nil/],
- [:TRUE, /^true/],
- [:FALSE, /^false/],
- # INTEGER needs to be before METHOD_NAME, otherwise e.g. "+1" would be
- # recognized as two tokens.
- [
- :INTEGER,
- /^
- [+-]? # sign
- (
- 0[bB][01]+(_[01]+)* # binary (prefixed)
- |
- 0[oO][0-7]+(_[0-7]+)* # octal (prefixed)
- |
- 0[dD]\d+(_\d+)* # decimal (prefixed)
- |
- 0[xX][0-9a-fA-F]+(_[0-9a-fA-F]+)* # hexadecimal (prefixed)
- |
- 0[0-7]*(_[0-7]+)* # octal (unprefixed)
- |
- [1-9]\d*(_\d+)* # decimal (unprefixed)
- )
- /x
- ],
- [
- :SYMBOL,
- /^
- :
- (
- # class name
- [A-Z][a-zA-Z0-9_]*
- |
- # regular method name
- [a-z_][a-zA-Z0-9_]*[?!=]?
- |
- # instance variable name
- @[a-zA-Z_][a-zA-Z0-9_]*
- |
- # class variable name
- @@[a-zA-Z_][a-zA-Z0-9_]*
- |
- # operator (sorted by length, then alphabetically)
- (<=>|===|\[\]=|\*\*|\+@|-@|<<|<=|==|=~|>=|>>|\[\]|[%&*+\-\/<>^`|~])
- )
- /x
- ],
- [
- :STRING,
- /^
- (
- ' # sinqle-quoted string
- (
- \\[\\'] # escape
- |
- [^'] # regular character
- )*
- '
- |
- " # double-quoted string
- (
- \\ # escape
- (
- [\\"ntrfvaebs] # one-character escape
- |
- [0-7]{1,3} # octal number escape
- |
- x[0-9a-fA-F]{1,2} # hexadecimal number escape
- )
- |
- [^"] # regular character
- )*
- "
- )
- /x
- ],
- [
- :REGEXP,
- /^
- \/
- (
- \\ # escape
- (
- [\\\/ntrfvaebs\(\)\[\]\{\}\-\.\?\*\+\|\^\$] # one-character escape
- |
- [0-7]{2,3} # octal number escape
- |
- x[0-9a-fA-F]{1,2} # hexadecimal number escape
- )
- |
- [^\/] # regular character
- )*
- \/
- [imx]*
- /x
- ],
- # ANY, EVEN and ODD need to be before METHOD_NAME, otherwise they would be
- # recognized as method names.
- [:ANY, /^any/],
- [:EVEN, /^even/],
- [:ODD, /^odd/],
- # We exclude "*", "+", "<", ">", "^" and "|" from method names since they are
- # lexed as simple tokens. This is because they have also other meanings in
- # Machette patterns beside Ruby method names.
- [
- :METHOD_NAME,
- /^
- (
- # regular name
- [a-z_][a-zA-Z0-9_]*[?!=]?
- |
- # operator (sorted by length, then alphabetically)
- (<=>|===|\[\]=|\*\*|\+@|-@|<<|<=|==|=~|>=|>>|\[\]|[%&\-\/`~])
- )
- /x
- ],
- [:CLASS_NAME, /^[A-Z][a-zA-Z0-9_]*/]
-]
-
-def next_token
- skip_whitespace
-
- return false if remaining_input.empty?
-
- # Complex tokens need to be before simple tokens, otherwise e.g. "<<" would be
- # recognized as two tokens.
-
- COMPLEX_TOKENS.each do |type, regexp|
- if remaining_input =~ regexp
- @pos += $&.length
- return [type, $&]
- end
- end
-
- SIMPLE_TOKENS.each do |token|
- if remaining_input[0...token.length] == token
- @pos += token.length
- return [token, token]
- end
- end
-
- raise SyntaxError, "Unexpected character: #{remaining_input[0..0].inspect}."
-end
-
-def skip_whitespace
- if remaining_input =~ /\A^[ \t\r\n]+/
- @pos += $&.length
- end
-end
-
-def remaining_input
- @input[@pos..-1]
-end
-
-def on_error(error_token_id, error_value, value_stack)
- raise SyntaxError, "Unexpected token: #{error_value.inspect}."
-end
-...end machete.y/module_eval...
-##### State transition tables begin ###
-
-racc_action_table = [
- 75, 19, 9, 10, 11, 12, 13, 14, 15, 16,
- 66, 67, 68, 7, 24, 9, 10, 11, 12, 13,
- 14, 15, 16, 17, 74, 8, 7, 47, 9, 10,
- 11, 12, 13, 14, 15, 16, 48, 18, 8, 7,
- 71, 9, 10, 11, 12, 13, 14, 15, 16, 72,
- 70, 8, 7, 73, 9, 10, 11, 12, 13, 14,
- 15, 16, 69, 18, 8, 7, 30, 31, 32, 51,
- 52, 53, 54, 33, 34, 35, 29, 8, 41, 38,
- 39, 76, 30, 31, 32, 77, 36, 37, 40, 33,
- 34, 35, 29, nil, 41, 38, 39, 18, 49, 50,
- 62, 63, 36, 37, 40, 43, 44, 55, 64, 65,
- 45, 46, 57, 58, nil, nil, nil, nil, nil, 56 ]
-
-racc_action_check = [
- 70, 7, 0, 0, 0, 0, 0, 0, 0, 0,
- 54, 54, 54, 0, 17, 8, 8, 8, 8, 8,
- 8, 8, 8, 1, 70, 0, 8, 21, 18, 18,
- 18, 18, 18, 18, 18, 18, 22, 1, 8, 18,
- 56, 48, 48, 48, 48, 48, 48, 48, 48, 57,
- 55, 18, 48, 58, 51, 51, 51, 51, 51, 51,
- 51, 51, 55, 61, 48, 51, 19, 19, 19, 28,
- 28, 28, 28, 19, 19, 19, 19, 51, 19, 19,
- 19, 71, 50, 50, 50, 75, 19, 19, 19, 50,
- 50, 50, 50, nil, 50, 50, 50, 20, 26, 26,
- 52, 52, 50, 50, 50, 20, 20, 46, 53, 53,
- 20, 20, 46, 46, nil, nil, nil, nil, nil, 46 ]
-
-racc_action_pointer = [
- 0, 23, nil, nil, nil, nil, nil, -14, 13, nil,
- nil, nil, nil, nil, nil, nil, nil, 14, 26, 64,
- 83, 1, 19, nil, nil, nil, 82, nil, 51, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 102, nil, 39, nil,
- 80, 52, 94, 102, 4, 33, 35, 20, 24, nil,
- nil, 49, nil, nil, nil, nil, nil, nil, nil, nil,
- -5, 52, nil, nil, nil, 56, nil, nil ]
-
-racc_action_default = [
- -56, -56, -1, -3, -4, -5, -6, -7, -33, -48,
- -49, -50, -51, -52, -53, -54, -55, -56, -56, -56,
- -37, -56, -34, -35, 78, -2, -56, -9, -56, -19,
- -20, -21, -22, -23, -24, -25, -26, -27, -28, -29,
- -30, -31, -38, -39, -40, -41, -56, -32, -56, -8,
- -56, -56, -56, -56, -56, -56, -56, -56, -56, -36,
- -10, -11, -12, -15, -13, -16, -14, -17, -18, -42,
- -56, -56, -46, -47, -43, -56, -44, -45 ]
-
-racc_goto_table = [
- 1, 23, 27, 25, 26, 21, 22, 42, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 60, nil, nil, nil, nil, nil, nil,
- nil, 59, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 61 ]
-
-racc_goto_check = [
- 1, 12, 8, 2, 7, 10, 11, 13, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 8, nil, nil, nil, nil, nil, nil,
- nil, 12, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 1 ]
-
-racc_goto_pointer = [
- nil, 0, -15, nil, nil, nil, nil, -15, -17, nil,
- -3, -2, -7, -13 ]
-
-racc_goto_default = [
- nil, 20, 2, 3, 4, 5, 6, nil, nil, 28,
- nil, nil, nil, nil ]
-
-racc_reduce_table = [
- 0, 0, :racc_error,
- 1, 31, :_reduce_none,
- 3, 31, :_reduce_2,
- 1, 32, :_reduce_none,
- 1, 32, :_reduce_none,
- 1, 32, :_reduce_none,
- 1, 32, :_reduce_none,
- 1, 33, :_reduce_7,
- 4, 33, :_reduce_8,
- 1, 37, :_reduce_none,
- 3, 37, :_reduce_10,
- 3, 38, :_reduce_11,
- 3, 38, :_reduce_12,
- 3, 38, :_reduce_13,
- 3, 38, :_reduce_14,
- 3, 38, :_reduce_15,
- 3, 38, :_reduce_16,
- 3, 38, :_reduce_17,
- 3, 38, :_reduce_18,
- 1, 39, :_reduce_none,
- 1, 39, :_reduce_none,
- 1, 39, :_reduce_none,
- 1, 39, :_reduce_none,
- 1, 39, :_reduce_none,
- 1, 39, :_reduce_none,
- 1, 39, :_reduce_none,
- 1, 39, :_reduce_none,
- 1, 39, :_reduce_none,
- 1, 39, :_reduce_none,
- 1, 39, :_reduce_none,
- 1, 39, :_reduce_none,
- 1, 39, :_reduce_none,
- 3, 34, :_reduce_32,
- 0, 40, :_reduce_33,
- 1, 40, :_reduce_none,
- 1, 41, :_reduce_35,
- 3, 41, :_reduce_36,
- 1, 42, :_reduce_none,
- 2, 42, :_reduce_38,
- 1, 43, :_reduce_39,
- 1, 43, :_reduce_40,
- 1, 43, :_reduce_41,
- 3, 43, :_reduce_42,
- 4, 43, :_reduce_43,
- 4, 43, :_reduce_44,
- 5, 43, :_reduce_45,
- 3, 43, :_reduce_46,
- 3, 43, :_reduce_47,
- 1, 35, :_reduce_48,
- 1, 35, :_reduce_49,
- 1, 35, :_reduce_50,
- 1, 35, :_reduce_51,
- 1, 35, :_reduce_52,
- 1, 35, :_reduce_53,
- 1, 35, :_reduce_54,
- 1, 36, :_reduce_55 ]
-
-racc_reduce_n = 56
-
-racc_shift_n = 78
-
-racc_token_table = {
- false => 0,
- :error => 1,
- :NIL => 2,
- :TRUE => 3,
- :FALSE => 4,
- :INTEGER => 5,
- :SYMBOL => 6,
- :STRING => 7,
- :REGEXP => 8,
- :ANY => 9,
- :EVEN => 10,
- :ODD => 11,
- :METHOD_NAME => 12,
- :CLASS_NAME => 13,
- "|" => 14,
- "<" => 15,
- ">" => 16,
- "," => 17,
- "=" => 18,
- "^=" => 19,
- "$=" => 20,
- "*=" => 21,
- "*" => 22,
- "+" => 23,
- "^" => 24,
- "[" => 25,
- "]" => 26,
- "?" => 27,
- "{" => 28,
- "}" => 29 }
-
-racc_nt_base = 30
-
-racc_use_result_var = true
-
-Racc_arg = [
- racc_action_table,
- racc_action_check,
- racc_action_default,
- racc_action_pointer,
- racc_goto_table,
- racc_goto_check,
- racc_goto_default,
- racc_goto_pointer,
- racc_nt_base,
- racc_reduce_table,
- racc_token_table,
- racc_shift_n,
- racc_reduce_n,
- racc_use_result_var ]
-
-Racc_token_to_s_table = [
- "$end",
- "error",
- "NIL",
- "TRUE",
- "FALSE",
- "INTEGER",
- "SYMBOL",
- "STRING",
- "REGEXP",
- "ANY",
- "EVEN",
- "ODD",
- "METHOD_NAME",
- "CLASS_NAME",
- "\"|\"",
- "\"<\"",
- "\">\"",
- "\",\"",
- "\"=\"",
- "\"^=\"",
- "\"$=\"",
- "\"*=\"",
- "\"*\"",
- "\"+\"",
- "\"^\"",
- "\"[\"",
- "\"]\"",
- "\"?\"",
- "\"{\"",
- "\"}\"",
- "$start",
- "expression",
- "primary",
- "node",
- "array",
- "literal",
- "any",
- "attrs",
- "attr",
- "method_name",
- "items_opt",
- "items",
- "item",
- "quantifier" ]
-
-Racc_debug_parser = false
-
-##### State transition tables end #####
-
-# reduce 0 omitted
-
-# reduce 1 omitted
-
-module_eval(<<'.,.,', 'machete.y', 44)
- def _reduce_2(val, _values, result)
- result = if val[0].is_a?(ChoiceMatcher)
- ChoiceMatcher.new(val[0].alternatives << val[2])
- else
- ChoiceMatcher.new([val[0], val[2]])
- end
-
- result
- end
-.,.,
-
-# reduce 3 omitted
-
-# reduce 4 omitted
-
-# reduce 5 omitted
-
-# reduce 6 omitted
-
-module_eval(<<'.,.,', 'machete.y', 57)
- def _reduce_7(val, _values, result)
- result = NodeMatcher.new(val[0].to_sym)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'machete.y', 60)
- def _reduce_8(val, _values, result)
- result = NodeMatcher.new(val[0].to_sym, val[2])
-
- result
- end
-.,.,
-
-# reduce 9 omitted
-
-module_eval(<<'.,.,', 'machete.y', 64)
- def _reduce_10(val, _values, result)
- result = val[0].merge(val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'machete.y', 66)
- def _reduce_11(val, _values, result)
- result = { val[0].to_sym => val[2] }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'machete.y', 68)
- def _reduce_12(val, _values, result)
- result = {
- val[0].to_sym => SymbolRegexpMatcher.new(
- Regexp.new("^" + Regexp.escape(symbol_value(val[2]).to_s))
- )
- }
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'machete.y', 75)
- def _reduce_13(val, _values, result)
- result = {
- val[0].to_sym => SymbolRegexpMatcher.new(
- Regexp.new(Regexp.escape(symbol_value(val[2]).to_s) + "$")
- )
- }
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'machete.y', 82)
- def _reduce_14(val, _values, result)
- result = {
- val[0].to_sym => SymbolRegexpMatcher.new(
- Regexp.new(Regexp.escape(symbol_value(val[2]).to_s))
- )
- }
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'machete.y', 89)
- def _reduce_15(val, _values, result)
- result = {
- val[0].to_sym => StringRegexpMatcher.new(
- Regexp.new("^" + Regexp.escape(string_value(val[2])))
- )
- }
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'machete.y', 96)
- def _reduce_16(val, _values, result)
- result = {
- val[0].to_sym => StringRegexpMatcher.new(
- Regexp.new(Regexp.escape(string_value(val[2])) + "$")
- )
- }
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'machete.y', 103)
- def _reduce_17(val, _values, result)
- result = {
- val[0].to_sym => StringRegexpMatcher.new(
- Regexp.new(Regexp.escape(string_value(val[2])))
- )
- }
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'machete.y', 110)
- def _reduce_18(val, _values, result)
- result = {
- val[0].to_sym => IndifferentRegexpMatcher.new(
- Regexp.new(regexp_value(val[2]))
- )
- }
-
- result
- end
-.,.,
-
-# reduce 19 omitted
-
-# reduce 20 omitted
-
-# reduce 21 omitted
-
-# reduce 22 omitted
-
-# reduce 23 omitted
-
-# reduce 24 omitted
-
-# reduce 25 omitted
-
-# reduce 26 omitted
-
-# reduce 27 omitted
-
-# reduce 28 omitted
-
-# reduce 29 omitted
-
-# reduce 30 omitted
-
-# reduce 31 omitted
-
-module_eval(<<'.,.,', 'machete.y', 134)
- def _reduce_32(val, _values, result)
- result = ArrayMatcher.new(val[1])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'machete.y', 136)
- def _reduce_33(val, _values, result)
- result = []
- result
- end
-.,.,
-
-# reduce 34 omitted
-
-module_eval(<<'.,.,', 'machete.y', 139)
- def _reduce_35(val, _values, result)
- result = [val[0]]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'machete.y', 140)
- def _reduce_36(val, _values, result)
- result = val[0] << val[2]
- result
- end
-.,.,
-
-# reduce 37 omitted
-
-module_eval(<<'.,.,', 'machete.y', 143)
- def _reduce_38(val, _values, result)
- result = Quantifier.new(val[0], *val[1])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'machete.y', 145)
- def _reduce_39(val, _values, result)
- result = [0, nil, 1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'machete.y', 146)
- def _reduce_40(val, _values, result)
- result = [1, nil, 1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'machete.y', 147)
- def _reduce_41(val, _values, result)
- result = [0, 1, 1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'machete.y', 149)
- def _reduce_42(val, _values, result)
- result = [integer_value(val[1]), integer_value(val[1]), 1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'machete.y', 152)
- def _reduce_43(val, _values, result)
- result = [integer_value(val[1]), nil, 1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'machete.y', 155)
- def _reduce_44(val, _values, result)
- result = [0, integer_value(val[2]), 1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'machete.y', 158)
- def _reduce_45(val, _values, result)
- result = [integer_value(val[1]), integer_value(val[3]), 1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'machete.y', 160)
- def _reduce_46(val, _values, result)
- result = [0, nil, 2]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'machete.y', 161)
- def _reduce_47(val, _values, result)
- result = [1, nil, 2]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'machete.y', 163)
- def _reduce_48(val, _values, result)
- result = LiteralMatcher.new(nil)
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'machete.y', 164)
- def _reduce_49(val, _values, result)
- result = LiteralMatcher.new(true)
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'machete.y', 165)
- def _reduce_50(val, _values, result)
- result = LiteralMatcher.new(false)
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'machete.y', 166)
- def _reduce_51(val, _values, result)
- result = LiteralMatcher.new(integer_value(val[0]))
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'machete.y', 167)
- def _reduce_52(val, _values, result)
- result = LiteralMatcher.new(symbol_value(val[0]))
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'machete.y', 168)
- def _reduce_53(val, _values, result)
- result = LiteralMatcher.new(string_value(val[0]))
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'machete.y', 169)
- def _reduce_54(val, _values, result)
- result = LiteralMatcher.new(regexp_value(val[0]))
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'machete.y', 171)
- def _reduce_55(val, _values, result)
- result = AnyMatcher.new
- result
- end
-.,.,
-
-def _reduce_none(val, _values, result)
- val[0]
-end
-
- end # class Parser
-end # module Machete
diff --git a/test/racc/regress/mediacloth b/test/racc/regress/mediacloth
deleted file mode 100644
index cca7d3c7e4..0000000000
--- a/test/racc/regress/mediacloth
+++ /dev/null
@@ -1,1463 +0,0 @@
-#
-# DO NOT MODIFY!!!!
-# This file is automatically generated by Racc 1.5.0
-# from Racc grammar file "".
-#
-
-require 'racc/parser.rb'
-
-require 'mediacloth/mediawikiast'
-
-class MediaWikiParser < Racc::Parser
-
-module_eval(<<'...end mediacloth.y/module_eval...', 'mediacloth.y', 564)
-
-attr_accessor :lexer
-
-def initialize
- @nodes = []
- @context = []
- @wiki_ast_length = 0
- super
-end
-
-#Tokenizes input string and parses it.
-def parse(input)
- @yydebug=true
- lexer.tokenize(input)
- do_parse
- return @nodes.last
-end
-
-#Asks the lexer to return the next token.
-def next_token
- token = @lexer.lex
- if token[0].to_s.upcase.include? "_START"
- @context << token[2..3]
- elsif token[0].to_s.upcase.include? "_END"
- @ast_index = @context.last[0]
- @ast_length = token[2] + token[3] - @context.last[0]
- @context.pop
- else
- @ast_index = token[2]
- @ast_length = token[3]
- end
-
- @wiki_ast_length += token[3]
-
- return token[0..1]
-end
-...end mediacloth.y/module_eval...
-##### State transition tables begin ###
-
-racc_action_table = [
- 22, 28, 50, 29, 61, 13, 63, 132, 15, 86,
- 37, 87, 24, 33, 86, 34, 87, 35, 85, 23,
- 26, 25, 27, 12, 86, 30, 87, 31, 86, 42,
- 87, 32, 44, 86, 48, 87, 57, 17, 57, 22,
- 28, 21, 29, 46, 13, 51, 67, 15, 68, 11,
- 36, 24, 33, 14, 34, 69, 35, 36, 23, 26,
- 25, 27, 12, 86, 30, 87, 31, 75, 73, 70,
- 32, 48, 81, 71, 72, 76, 17, 77, 22, 28,
- 21, 29, 82, 13, 45, 51, 15, -65, 11, 36,
- 24, 33, 14, 34, -65, 35, 63, 23, 26, 25,
- 27, 12, 96, 30, 63, 31, 106, 109, 110, 32,
- 113, 114, 48, 117, 118, 17, 124, 22, 28, 21,
- 29, 57, 13, 127, 128, 15, 131, 11, 36, 24,
- 33, 14, 34, 136, 35, 137, 23, 26, 25, 27,
- 12, 138, 30, 75, 31, 51, 141, -63, 32, 106,
- 106, 150, 153, 51, 17, nil, nil, nil, 21, nil,
- 22, 28, 53, 29, nil, 13, 11, 36, 15, nil,
- 14, nil, 24, 33, nil, 34, nil, 35, nil, 23,
- 26, 25, 27, 12, nil, 30, nil, 31, nil, nil,
- nil, 32, nil, nil, nil, nil, nil, 17, nil, 22,
- 28, 21, 29, 55, 13, nil, nil, 15, nil, 11,
- 36, 24, 33, 14, 34, nil, 35, nil, 23, 26,
- 25, 27, 12, nil, 30, nil, 31, nil, nil, nil,
- 32, nil, nil, nil, nil, nil, 17, nil, 22, 28,
- 21, 29, nil, 13, nil, nil, 15, nil, 11, 36,
- 24, 33, 14, 34, nil, 35, nil, 23, 26, 25,
- 27, 12, nil, 30, nil, 31, nil, nil, nil, 32,
- nil, nil, nil, nil, nil, 17, nil, 22, 28, 21,
- 29, nil, 13, nil, nil, 15, nil, 11, 36, 24,
- 33, 14, 34, nil, 35, nil, 23, 26, 25, 27,
- 12, nil, 30, nil, 31, nil, nil, nil, 32, nil,
- nil, nil, nil, nil, 17, nil, 22, 28, 21, 29,
- nil, 13, nil, nil, 15, nil, 11, 36, 24, 33,
- 14, 34, nil, 35, nil, 23, 26, 25, 27, 12,
- nil, 30, nil, 31, nil, nil, nil, 32, nil, nil,
- nil, nil, nil, 17, nil, 22, 28, 21, 29, nil,
- 13, nil, nil, 15, nil, 11, 36, 24, 33, 14,
- 34, nil, 35, nil, 23, 26, 25, 27, 12, nil,
- 30, nil, 31, nil, nil, nil, 32, nil, nil, nil,
- nil, nil, 17, nil, 22, 28, 21, 29, nil, 13,
- nil, nil, 15, nil, 11, 36, 24, 33, 14, 34,
- nil, 35, nil, 23, 26, 25, 27, 12, nil, 30,
- nil, 31, nil, nil, nil, 32, nil, nil, nil, nil,
- nil, 17, 78, nil, nil, 21, nil, 22, 28, 88,
- 29, nil, 13, 11, 36, 15, nil, 14, nil, 24,
- 33, nil, 34, nil, 35, nil, 23, 26, 25, 27,
- 12, nil, 30, nil, 31, nil, nil, nil, 32, nil,
- nil, nil, nil, nil, 17, nil, 22, 28, 21, 29,
- 89, 13, nil, nil, 15, nil, 11, 36, 24, 33,
- 14, 34, nil, 35, nil, 23, 26, 25, 27, 12,
- nil, 30, nil, 31, nil, nil, nil, 32, nil, nil,
- nil, nil, nil, 17, nil, 22, 28, 21, 29, nil,
- 13, nil, nil, 15, nil, 11, 36, 24, 33, 14,
- 34, nil, 35, nil, 23, 26, 25, 27, 12, nil,
- 30, nil, 31, nil, nil, 93, 32, nil, nil, nil,
- nil, nil, 17, nil, 22, 28, 21, 29, nil, 13,
- nil, nil, 15, nil, 11, 36, 24, 33, 14, 34,
- nil, 35, nil, 23, 26, 25, 27, 12, nil, 30,
- nil, 31, nil, nil, nil, 32, nil, nil, 98, nil,
- nil, 17, nil, 22, 28, 21, 29, nil, 13, nil,
- nil, 15, nil, 11, 36, 24, 33, 14, 34, nil,
- 35, nil, 23, 26, 25, 27, 12, nil, 30, nil,
- 31, nil, nil, nil, 32, nil, nil, nil, nil, 101,
- 17, nil, nil, nil, 21, nil, 22, 28, nil, 29,
- nil, 13, 11, 36, 15, nil, 14, nil, 24, 33,
- 102, 34, nil, 35, nil, 23, 26, 25, 27, 12,
- nil, 30, nil, 31, nil, nil, nil, 32, nil, nil,
- nil, nil, nil, 17, nil, 22, 28, 21, 29, nil,
- 13, nil, nil, 15, nil, 11, 36, 24, 33, 14,
- 34, 103, 35, nil, 23, 26, 25, 27, 12, nil,
- 30, nil, 31, nil, nil, nil, 32, nil, nil, nil,
- nil, nil, 17, nil, 22, 28, 21, 29, nil, 13,
- nil, nil, 15, nil, 11, 36, 24, 33, 14, 34,
- nil, 35, 104, 23, 26, 25, 27, 12, nil, 30,
- nil, 31, nil, nil, nil, 32, nil, nil, nil, nil,
- nil, 17, nil, 22, 28, 21, 29, nil, 13, nil,
- nil, 15, nil, 11, 36, 24, 33, 14, 34, nil,
- 35, nil, 23, 26, 25, 27, 12, nil, 30, nil,
- 31, nil, nil, nil, 32, nil, nil, nil, nil, nil,
- 17, nil, 22, 28, 21, 29, nil, 13, nil, nil,
- 15, nil, 11, 36, 24, 33, 14, 34, nil, 35,
- nil, 23, 26, 25, 27, 12, nil, 30, nil, 31,
- nil, nil, nil, 32, nil, nil, nil, nil, nil, 17,
- nil, 22, 28, 21, 29, nil, 13, nil, nil, 15,
- nil, 11, 36, 24, 33, 14, 34, nil, 35, nil,
- 23, 26, 25, 27, 12, nil, 30, nil, 31, nil,
- nil, nil, 32, nil, nil, nil, nil, nil, 17, 115,
- 22, 28, 21, 29, nil, 13, nil, nil, 15, nil,
- 11, 36, 24, 33, 14, 34, nil, 35, nil, 23,
- 26, 25, 27, 12, nil, 30, nil, 31, nil, nil,
- nil, 32, nil, nil, nil, nil, nil, 17, nil, 22,
- 28, 21, 29, nil, 13, nil, 121, 15, nil, 11,
- 36, 24, 33, 14, 34, nil, 35, nil, 23, 26,
- 25, 27, 12, nil, 30, nil, 31, nil, nil, nil,
- 32, nil, nil, nil, nil, nil, 17, nil, 22, 28,
- 21, 29, nil, 13, nil, nil, 15, 123, 11, 36,
- 24, 33, 14, 34, nil, 35, nil, 23, 26, 25,
- 27, 12, nil, 30, nil, 31, nil, nil, 126, 32,
- nil, nil, nil, nil, nil, 17, nil, 22, 28, 21,
- 29, nil, 13, nil, nil, 15, nil, 11, 36, 24,
- 33, 14, 34, nil, 35, nil, 23, 26, 25, 27,
- 12, nil, 30, nil, 31, nil, nil, nil, 32, nil,
- nil, 129, nil, nil, 17, nil, 22, 28, 21, 29,
- nil, 13, nil, nil, 15, nil, 11, 36, 24, 33,
- 14, 34, nil, 35, nil, 23, 26, 25, 27, 12,
- nil, 30, nil, 31, nil, nil, nil, 32, nil, nil,
- nil, nil, 130, 17, nil, 22, 28, 21, 29, nil,
- 13, nil, 134, 15, nil, 11, 36, 24, 33, 14,
- 34, nil, 35, nil, 23, 26, 25, 27, 12, nil,
- 30, nil, 31, nil, nil, nil, 32, nil, nil, nil,
- nil, nil, 17, nil, 22, 28, 21, 29, nil, 13,
- nil, nil, 15, nil, 11, 36, 24, 33, 14, 34,
- nil, 35, nil, 23, 26, 25, 27, 12, nil, 30,
- nil, 31, nil, nil, nil, 32, nil, nil, nil, nil,
- nil, 17, nil, 22, 28, 21, 29, nil, 13, nil,
- nil, 15, nil, 11, 36, 24, 33, 14, 34, nil,
- 35, nil, 23, 26, 25, 27, 12, nil, 30, nil,
- 31, nil, nil, nil, 32, nil, nil, nil, nil, nil,
- 17, nil, 22, 28, 21, 29, nil, 13, nil, 142,
- 15, nil, 11, 36, 24, 33, 14, 34, nil, 35,
- nil, 23, 26, 25, 27, 12, nil, 30, nil, 31,
- nil, nil, nil, 32, nil, nil, nil, nil, nil, 17,
- nil, 22, 28, 21, 29, nil, 13, nil, nil, 15,
- 144, 11, 36, 24, 33, 14, 34, nil, 35, nil,
- 23, 26, 25, 27, 12, nil, 30, nil, 31, nil,
- nil, nil, 32, nil, nil, nil, nil, nil, 17, nil,
- nil, nil, 21, nil, nil, nil, nil, nil, nil, nil,
- 11, 36, 22, 28, 14, 29, nil, 13, nil, nil,
- 15, nil, 136, nil, 24, 33, nil, 34, nil, 35,
- nil, 23, 26, 25, 27, 12, nil, 30, nil, 31,
- nil, nil, nil, 32, nil, nil, nil, nil, nil, 17,
- nil, nil, nil, 21, nil, nil, nil, nil, nil, nil,
- nil, 11, 36, 22, 28, 14, 29, nil, 13, nil,
- nil, 15, nil, 136, nil, 24, 33, nil, 34, nil,
- 35, nil, 23, 26, 25, 27, 12, nil, 30, nil,
- 31, nil, nil, nil, 32, nil, nil, nil, nil, nil,
- 17, nil, nil, nil, 21, nil, nil, nil, nil, nil,
- nil, nil, 11, 36, nil, nil, 14 ]
-
-racc_action_check = [
- 0, 0, 21, 0, 32, 0, 32, 106, 0, 85,
- 1, 85, 0, 0, 121, 0, 121, 0, 51, 0,
- 0, 0, 0, 0, 123, 0, 123, 0, 142, 13,
- 142, 0, 15, 144, 17, 144, 30, 0, 31, 2,
- 2, 0, 2, 15, 2, 21, 36, 2, 37, 0,
- 0, 2, 2, 0, 2, 39, 2, 106, 2, 2,
- 2, 2, 2, 51, 2, 51, 2, 44, 44, 41,
- 2, 48, 48, 42, 43, 45, 2, 46, 12, 12,
- 2, 12, 49, 12, 15, 50, 12, 56, 2, 2,
- 12, 12, 2, 12, 58, 12, 59, 12, 12, 12,
- 12, 12, 60, 12, 62, 12, 67, 73, 74, 12,
- 76, 77, 81, 83, 84, 12, 90, 14, 14, 12,
- 14, 91, 14, 94, 95, 14, 105, 12, 12, 14,
- 14, 12, 14, 109, 14, 112, 14, 14, 14, 14,
- 14, 113, 14, 114, 14, 118, 119, 125, 14, 132,
- 133, 135, 139, 141, 14, nil, nil, nil, 14, nil,
- 28, 28, 28, 28, nil, 28, 14, 14, 28, nil,
- 14, nil, 28, 28, nil, 28, nil, 28, nil, 28,
- 28, 28, 28, 28, nil, 28, nil, 28, nil, nil,
- nil, 28, nil, nil, nil, nil, nil, 28, nil, 29,
- 29, 28, 29, 29, 29, nil, nil, 29, nil, 28,
- 28, 29, 29, 28, 29, nil, 29, nil, 29, 29,
- 29, 29, 29, nil, 29, nil, 29, nil, nil, nil,
- 29, nil, nil, nil, nil, nil, 29, nil, 33, 33,
- 29, 33, nil, 33, nil, nil, 33, nil, 29, 29,
- 33, 33, 29, 33, nil, 33, nil, 33, 33, 33,
- 33, 33, nil, 33, nil, 33, nil, nil, nil, 33,
- nil, nil, nil, nil, nil, 33, nil, 34, 34, 33,
- 34, nil, 34, nil, nil, 34, nil, 33, 33, 34,
- 34, 33, 34, nil, 34, nil, 34, 34, 34, 34,
- 34, nil, 34, nil, 34, nil, nil, nil, 34, nil,
- nil, nil, nil, nil, 34, nil, 35, 35, 34, 35,
- nil, 35, nil, nil, 35, nil, 34, 34, 35, 35,
- 34, 35, nil, 35, nil, 35, 35, 35, 35, 35,
- nil, 35, nil, 35, nil, nil, nil, 35, nil, nil,
- nil, nil, nil, 35, nil, 40, 40, 35, 40, nil,
- 40, nil, nil, 40, nil, 35, 35, 40, 40, 35,
- 40, nil, 40, nil, 40, 40, 40, 40, 40, nil,
- 40, nil, 40, nil, nil, nil, 40, nil, nil, nil,
- nil, nil, 40, nil, 47, 47, 40, 47, nil, 47,
- nil, nil, 47, nil, 40, 40, 47, 47, 40, 47,
- nil, 47, nil, 47, 47, 47, 47, 47, nil, 47,
- nil, 47, nil, nil, nil, 47, nil, nil, nil, nil,
- nil, 47, 47, nil, nil, 47, nil, 52, 52, 52,
- 52, nil, 52, 47, 47, 52, nil, 47, nil, 52,
- 52, nil, 52, nil, 52, nil, 52, 52, 52, 52,
- 52, nil, 52, nil, 52, nil, nil, nil, 52, nil,
- nil, nil, nil, nil, 52, nil, 54, 54, 52, 54,
- 54, 54, nil, nil, 54, nil, 52, 52, 54, 54,
- 52, 54, nil, 54, nil, 54, 54, 54, 54, 54,
- nil, 54, nil, 54, nil, nil, nil, 54, nil, nil,
- nil, nil, nil, 54, nil, 57, 57, 54, 57, nil,
- 57, nil, nil, 57, nil, 54, 54, 57, 57, 54,
- 57, nil, 57, nil, 57, 57, 57, 57, 57, nil,
- 57, nil, 57, nil, nil, 57, 57, nil, nil, nil,
- nil, nil, 57, nil, 61, 61, 57, 61, nil, 61,
- nil, nil, 61, nil, 57, 57, 61, 61, 57, 61,
- nil, 61, nil, 61, 61, 61, 61, 61, nil, 61,
- nil, 61, nil, nil, nil, 61, nil, nil, 61, nil,
- nil, 61, nil, 63, 63, 61, 63, nil, 63, nil,
- nil, 63, nil, 61, 61, 63, 63, 61, 63, nil,
- 63, nil, 63, 63, 63, 63, 63, nil, 63, nil,
- 63, nil, nil, nil, 63, nil, nil, nil, nil, 63,
- 63, nil, nil, nil, 63, nil, 64, 64, nil, 64,
- nil, 64, 63, 63, 64, nil, 63, nil, 64, 64,
- 64, 64, nil, 64, nil, 64, 64, 64, 64, 64,
- nil, 64, nil, 64, nil, nil, nil, 64, nil, nil,
- nil, nil, nil, 64, nil, 65, 65, 64, 65, nil,
- 65, nil, nil, 65, nil, 64, 64, 65, 65, 64,
- 65, 65, 65, nil, 65, 65, 65, 65, 65, nil,
- 65, nil, 65, nil, nil, nil, 65, nil, nil, nil,
- nil, nil, 65, nil, 66, 66, 65, 66, nil, 66,
- nil, nil, 66, nil, 65, 65, 66, 66, 65, 66,
- nil, 66, 66, 66, 66, 66, 66, 66, nil, 66,
- nil, 66, nil, nil, nil, 66, nil, nil, nil, nil,
- nil, 66, nil, 71, 71, 66, 71, nil, 71, nil,
- nil, 71, nil, 66, 66, 71, 71, 66, 71, nil,
- 71, nil, 71, 71, 71, 71, 71, nil, 71, nil,
- 71, nil, nil, nil, 71, nil, nil, nil, nil, nil,
- 71, nil, 75, 75, 71, 75, nil, 75, nil, nil,
- 75, nil, 71, 71, 75, 75, 71, 75, nil, 75,
- nil, 75, 75, 75, 75, 75, nil, 75, nil, 75,
- nil, nil, nil, 75, nil, nil, nil, nil, nil, 75,
- nil, 79, 79, 75, 79, nil, 79, nil, nil, 79,
- nil, 75, 75, 79, 79, 75, 79, nil, 79, nil,
- 79, 79, 79, 79, 79, nil, 79, nil, 79, nil,
- nil, nil, 79, nil, nil, nil, nil, nil, 79, 79,
- 86, 86, 79, 86, nil, 86, nil, nil, 86, nil,
- 79, 79, 86, 86, 79, 86, nil, 86, nil, 86,
- 86, 86, 86, 86, nil, 86, nil, 86, nil, nil,
- nil, 86, nil, nil, nil, nil, nil, 86, nil, 87,
- 87, 86, 87, nil, 87, nil, 86, 87, nil, 86,
- 86, 87, 87, 86, 87, nil, 87, nil, 87, 87,
- 87, 87, 87, nil, 87, nil, 87, nil, nil, nil,
- 87, nil, nil, nil, nil, nil, 87, nil, 92, 92,
- 87, 92, nil, 92, nil, nil, 92, 87, 87, 87,
- 92, 92, 87, 92, nil, 92, nil, 92, 92, 92,
- 92, 92, nil, 92, nil, 92, nil, nil, 92, 92,
- nil, nil, nil, nil, nil, 92, nil, 97, 97, 92,
- 97, nil, 97, nil, nil, 97, nil, 92, 92, 97,
- 97, 92, 97, nil, 97, nil, 97, 97, 97, 97,
- 97, nil, 97, nil, 97, nil, nil, nil, 97, nil,
- nil, 97, nil, nil, 97, nil, 100, 100, 97, 100,
- nil, 100, nil, nil, 100, nil, 97, 97, 100, 100,
- 97, 100, nil, 100, nil, 100, 100, 100, 100, 100,
- nil, 100, nil, 100, nil, nil, nil, 100, nil, nil,
- nil, nil, 100, 100, nil, 108, 108, 100, 108, nil,
- 108, nil, 108, 108, nil, 100, 100, 108, 108, 100,
- 108, nil, 108, nil, 108, 108, 108, 108, 108, nil,
- 108, nil, 108, nil, nil, nil, 108, nil, nil, nil,
- nil, nil, 108, nil, 111, 111, 108, 111, nil, 111,
- nil, nil, 111, nil, 108, 108, 111, 111, 108, 111,
- nil, 111, nil, 111, 111, 111, 111, 111, nil, 111,
- nil, 111, nil, nil, nil, 111, nil, nil, nil, nil,
- nil, 111, nil, 120, 120, 111, 120, nil, 120, nil,
- nil, 120, nil, 111, 111, 120, 120, 111, 120, nil,
- 120, nil, 120, 120, 120, 120, 120, nil, 120, nil,
- 120, nil, nil, nil, 120, nil, nil, nil, nil, nil,
- 120, nil, 122, 122, 120, 122, nil, 122, nil, 120,
- 122, nil, 120, 120, 122, 122, 120, 122, nil, 122,
- nil, 122, 122, 122, 122, 122, nil, 122, nil, 122,
- nil, nil, nil, 122, nil, nil, nil, nil, nil, 122,
- nil, 134, 134, 122, 134, nil, 134, nil, nil, 134,
- 122, 122, 122, 134, 134, 122, 134, nil, 134, nil,
- 134, 134, 134, 134, 134, nil, 134, nil, 134, nil,
- nil, nil, 134, nil, nil, nil, nil, nil, 134, nil,
- nil, nil, 134, nil, nil, nil, nil, nil, nil, nil,
- 134, 134, 136, 136, 134, 136, nil, 136, nil, nil,
- 136, nil, 136, nil, 136, 136, nil, 136, nil, 136,
- nil, 136, 136, 136, 136, 136, nil, 136, nil, 136,
- nil, nil, nil, 136, nil, nil, nil, nil, nil, 136,
- nil, nil, nil, 136, nil, nil, nil, nil, nil, nil,
- nil, 136, 136, 152, 152, 136, 152, nil, 152, nil,
- nil, 152, nil, 152, nil, 152, 152, nil, 152, nil,
- 152, nil, 152, 152, 152, 152, 152, nil, 152, nil,
- 152, nil, nil, nil, 152, nil, nil, nil, nil, nil,
- 152, nil, nil, nil, 152, nil, nil, nil, nil, nil,
- nil, nil, 152, 152, nil, nil, 152 ]
-
-racc_action_pointer = [
- -2, 10, 37, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 76, 27, 115, 30, nil, -7, nil, nil,
- nil, 0, nil, nil, nil, nil, nil, nil, 158, 197,
- 5, 7, -31, 236, 275, 314, 44, 48, nil, 29,
- 353, 61, 64, 18, 55, 73, 23, 392, 30, 38,
- 40, 16, 435, nil, 474, nil, 59, 513, 64, 59,
- 68, 552, 67, 591, 634, 673, 712, 94, nil, nil,
- nil, 751, nil, 105, 97, 790, 98, 109, nil, 829,
- nil, 71, nil, 69, 68, -38, 868, 907, nil, nil,
- 88, 90, 946, nil, 93, 90, nil, 985, nil, nil,
- 1024, nil, nil, nil, nil, 73, 5, nil, 1063, 121,
- nil, 1102, 124, 139, 131, nil, nil, nil, 100, 100,
- 1141, -33, 1180, -23, nil, 116, nil, nil, nil, nil,
- nil, nil, 137, 138, 1219, 140, 1270, nil, nil, 141,
- nil, 108, -19, nil, -14, nil, nil, nil, nil, nil,
- nil, nil, 1321, nil, nil, nil, nil, nil ]
-
-racc_action_default = [
- -83, -83, -1, -2, -3, -4, -5, -6, -7, -8,
- -9, -10, -19, -83, -19, -83, -18, -23, -37, -39,
- -40, -43, -51, -52, -53, -54, -55, -56, -83, -83,
- -83, -83, -73, -83, -83, -83, -83, -83, -38, -83,
- -20, -83, -26, -83, -30, -83, -83, -83, -23, -83,
- -43, -46, -83, -57, -83, -58, -63, -83, -63, -73,
- -83, -83, -73, -83, -83, -83, -83, -80, 158, -11,
- -12, -83, -13, -83, -83, -83, -32, -83, -21, -83,
- -24, -23, -41, -83, -83, -46, -83, -83, -59, -60,
- -83, -83, -83, -66, -83, -83, -69, -83, -70, -72,
- -83, -74, -76, -77, -78, -83, -83, -27, -28, -34,
- -15, -31, -83, -83, -30, -22, -25, -42, -43, -83,
- -83, -46, -83, -46, -61, -65, -67, -62, -68, -71,
- -75, -79, -80, -80, -83, -83, -34, -16, -33, -83,
- -44, -43, -46, -47, -46, -49, -64, -81, -82, -29,
- -14, -35, -34, -17, -45, -48, -50, -36 ]
-
-racc_goto_table = [
- 38, 84, 74, 105, 49, 39, 90, 43, 94, 60,
- 135, 1, 133, 2, 47, 41, 107, 112, 59, 56,
- 58, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 83, nil, 119, 95, 151, 38, 99,
- nil, 52, 54, nil, nil, 80, 64, 65, 66, nil,
- 38, nil, 38, 157, nil, nil, nil, nil, nil, nil,
- 79, nil, 38, 38, 38, nil, nil, nil, 147, 148,
- 92, 143, 139, 145, 97, 146, 100, 38, 116, 149,
- 125, nil, nil, nil, 108, nil, nil, nil, 111, nil,
- 38, nil, 155, nil, 156, 38, nil, nil, 38, 120,
- 122, 140, nil, nil, nil, nil, 38, nil, nil, 38,
- nil, nil, nil, nil, nil, nil, nil, nil, 38, nil,
- 38, nil, nil, nil, 154, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 108, nil, 152,
- 38 ]
-
-racc_goto_check = [
- 3, 23, 15, 30, 22, 12, 25, 12, 25, 28,
- 14, 1, 11, 2, 18, 13, 19, 16, 27, 24,
- 24, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 22, nil, 23, 28, 14, 3, 28,
- nil, 2, 2, nil, nil, 18, 2, 2, 2, nil,
- 3, nil, 3, 14, nil, nil, nil, nil, nil, nil,
- 2, nil, 3, 3, 3, nil, nil, nil, 30, 30,
- 2, 23, 15, 23, 2, 25, 2, 3, 18, 19,
- 24, nil, nil, nil, 2, nil, nil, nil, 2, nil,
- 3, nil, 23, nil, 23, 3, nil, nil, 3, 2,
- 2, 22, nil, nil, nil, nil, 3, nil, nil, 3,
- nil, nil, nil, nil, nil, nil, nil, nil, 3, nil,
- 3, nil, nil, nil, 22, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 2, nil, 2,
- 3 ]
-
-racc_goto_pointer = [
- nil, 11, 13, -2, nil, nil, nil, nil, nil, nil,
- nil, -94, -7, 2, -99, -42, -59, nil, -3, -55,
- nil, nil, -17, -50, -11, -50, nil, -14, -23, nil,
- -64 ]
-
-racc_goto_default = [
- nil, nil, 40, 18, 3, 4, 5, 6, 7, 8,
- 9, 10, nil, nil, nil, nil, nil, 16, nil, nil,
- 19, 20, nil, nil, nil, nil, 91, nil, nil, 62,
- nil ]
-
-racc_reduce_table = [
- 0, 0, :racc_error,
- 1, 58, :_reduce_1,
- 1, 60, :_reduce_2,
- 1, 60, :_reduce_3,
- 1, 60, :_reduce_4,
- 1, 60, :_reduce_5,
- 1, 60, :_reduce_6,
- 1, 60, :_reduce_7,
- 1, 60, :_reduce_8,
- 1, 60, :_reduce_9,
- 1, 60, :_reduce_10,
- 3, 60, :_reduce_11,
- 3, 60, :_reduce_12,
- 3, 60, :_reduce_13,
- 6, 60, :_reduce_14,
- 4, 60, :_reduce_15,
- 5, 60, :_reduce_16,
- 6, 60, :_reduce_17,
- 1, 60, :_reduce_none,
- 0, 69, :_reduce_19,
- 1, 69, :_reduce_20,
- 3, 67, :_reduce_21,
- 4, 67, :_reduce_22,
- 0, 75, :_reduce_23,
- 2, 75, :_reduce_24,
- 3, 75, :_reduce_25,
- 1, 70, :_reduce_26,
- 3, 70, :_reduce_27,
- 1, 76, :_reduce_28,
- 3, 76, :_reduce_29,
- 0, 72, :_reduce_30,
- 2, 72, :_reduce_31,
- 0, 73, :_reduce_32,
- 2, 73, :_reduce_33,
- 0, 71, :_reduce_34,
- 2, 71, :_reduce_35,
- 3, 71, :_reduce_36,
- 1, 59, :_reduce_37,
- 2, 59, :_reduce_38,
- 1, 61, :_reduce_39,
- 1, 61, :_reduce_40,
- 3, 74, :_reduce_41,
- 4, 74, :_reduce_42,
- 0, 79, :_reduce_43,
- 4, 79, :_reduce_44,
- 5, 79, :_reduce_45,
- 0, 80, :_reduce_46,
- 3, 80, :_reduce_47,
- 4, 80, :_reduce_48,
- 3, 80, :_reduce_49,
- 4, 80, :_reduce_50,
- 1, 77, :_reduce_51,
- 1, 77, :_reduce_52,
- 1, 77, :_reduce_53,
- 1, 77, :_reduce_54,
- 1, 77, :_reduce_55,
- 1, 77, :_reduce_56,
- 2, 78, :_reduce_57,
- 2, 78, :_reduce_58,
- 3, 78, :_reduce_59,
- 3, 78, :_reduce_60,
- 4, 62, :_reduce_61,
- 4, 63, :_reduce_62,
- 0, 83, :_reduce_63,
- 3, 82, :_reduce_64,
- 0, 82, :_reduce_65,
- 2, 81, :_reduce_66,
- 3, 81, :_reduce_67,
- 4, 64, :_reduce_68,
- 3, 64, :_reduce_69,
- 2, 84, :_reduce_70,
- 3, 84, :_reduce_71,
- 2, 85, :_reduce_72,
- 0, 85, :_reduce_73,
- 2, 86, :_reduce_74,
- 3, 86, :_reduce_75,
- 3, 65, :_reduce_76,
- 3, 65, :_reduce_77,
- 3, 66, :_reduce_78,
- 4, 68, :_reduce_79,
- 0, 87, :_reduce_80,
- 3, 87, :_reduce_81,
- 3, 87, :_reduce_82 ]
-
-racc_reduce_n = 83
-
-racc_shift_n = 158
-
-racc_token_table = {
- false => 0,
- :error => 1,
- :TEXT => 2,
- :BOLD_START => 3,
- :BOLD_END => 4,
- :ITALIC_START => 5,
- :ITALIC_END => 6,
- :LINK_START => 7,
- :LINK_END => 8,
- :LINKSEP => 9,
- :INTLINK_START => 10,
- :INTLINK_END => 11,
- :INTLINKSEP => 12,
- :RESOURCESEP => 13,
- :CHAR_ENT => 14,
- :PRE_START => 15,
- :PRE_END => 16,
- :PREINDENT_START => 17,
- :PREINDENT_END => 18,
- :SECTION_START => 19,
- :SECTION_END => 20,
- :HLINE => 21,
- :SIGNATURE_NAME => 22,
- :SIGNATURE_DATE => 23,
- :SIGNATURE_FULL => 24,
- :PARA_START => 25,
- :PARA_END => 26,
- :UL_START => 27,
- :UL_END => 28,
- :OL_START => 29,
- :OL_END => 30,
- :LI_START => 31,
- :LI_END => 32,
- :DL_START => 33,
- :DL_END => 34,
- :DT_START => 35,
- :DT_END => 36,
- :DD_START => 37,
- :DD_END => 38,
- :TAG_START => 39,
- :TAG_END => 40,
- :ATTR_NAME => 41,
- :ATTR_VALUE => 42,
- :TABLE_START => 43,
- :TABLE_END => 44,
- :ROW_START => 45,
- :ROW_END => 46,
- :HEAD_START => 47,
- :HEAD_END => 48,
- :CELL_START => 49,
- :CELL_END => 50,
- :KEYWORD => 51,
- :TEMPLATE_START => 52,
- :TEMPLATE_END => 53,
- :CATEGORY => 54,
- :PASTE_START => 55,
- :PASTE_END => 56 }
-
-racc_nt_base = 57
-
-racc_use_result_var = true
-
-Racc_arg = [
- racc_action_table,
- racc_action_check,
- racc_action_default,
- racc_action_pointer,
- racc_goto_table,
- racc_goto_check,
- racc_goto_default,
- racc_goto_pointer,
- racc_nt_base,
- racc_reduce_table,
- racc_token_table,
- racc_shift_n,
- racc_reduce_n,
- racc_use_result_var ]
-
-Racc_token_to_s_table = [
- "$end",
- "error",
- "TEXT",
- "BOLD_START",
- "BOLD_END",
- "ITALIC_START",
- "ITALIC_END",
- "LINK_START",
- "LINK_END",
- "LINKSEP",
- "INTLINK_START",
- "INTLINK_END",
- "INTLINKSEP",
- "RESOURCESEP",
- "CHAR_ENT",
- "PRE_START",
- "PRE_END",
- "PREINDENT_START",
- "PREINDENT_END",
- "SECTION_START",
- "SECTION_END",
- "HLINE",
- "SIGNATURE_NAME",
- "SIGNATURE_DATE",
- "SIGNATURE_FULL",
- "PARA_START",
- "PARA_END",
- "UL_START",
- "UL_END",
- "OL_START",
- "OL_END",
- "LI_START",
- "LI_END",
- "DL_START",
- "DL_END",
- "DT_START",
- "DT_END",
- "DD_START",
- "DD_END",
- "TAG_START",
- "TAG_END",
- "ATTR_NAME",
- "ATTR_VALUE",
- "TABLE_START",
- "TABLE_END",
- "ROW_START",
- "ROW_END",
- "HEAD_START",
- "HEAD_END",
- "CELL_START",
- "CELL_END",
- "KEYWORD",
- "TEMPLATE_START",
- "TEMPLATE_END",
- "CATEGORY",
- "PASTE_START",
- "PASTE_END",
- "$start",
- "wiki",
- "repeated_contents",
- "contents",
- "text",
- "bulleted_list",
- "numbered_list",
- "dictionary_list",
- "preformatted",
- "section",
- "tag",
- "template",
- "para_contents",
- "link_contents",
- "reslink_repeated_contents",
- "intlink_repeated_contents",
- "cat_sort_contents",
- "table",
- "tag_attributes",
- "link_repeated_contents",
- "element",
- "formatted_element",
- "table_contents",
- "row_contents",
- "list_item",
- "list_contents",
- "@1",
- "dictionary_term",
- "dictionary_contents",
- "dictionary_definition",
- "template_parameters" ]
-
-Racc_debug_parser = false
-
-##### State transition tables end #####
-
-# reduce 0 omitted
-
-module_eval(<<'.,.,', 'mediacloth.y', 47)
- def _reduce_1(val, _values, result)
- @nodes.push WikiAST.new(0, @wiki_ast_length)
- #@nodes.last.children.insert(0, val[0])
- #puts val[0]
- @nodes.last.children += val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 57)
- def _reduce_2(val, _values, result)
- result = val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 61)
- def _reduce_3(val, _values, result)
- result = val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 65)
- def _reduce_4(val, _values, result)
- result = val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 69)
- def _reduce_5(val, _values, result)
- list = ListAST.new(@ast_index, @ast_length)
- list.list_type = :Dictionary
- list.children = val[0]
- result = list
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 76)
- def _reduce_6(val, _values, result)
- result = val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 80)
- def _reduce_7(val, _values, result)
- result = val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 84)
- def _reduce_8(val, _values, result)
- result = val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 88)
- def _reduce_9(val, _values, result)
- result = val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 92)
- def _reduce_10(val, _values, result)
- k = KeywordAST.new(@ast_index, @ast_length)
- k.text = val[0]
- result = k
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 98)
- def _reduce_11(val, _values, result)
- p = ParagraphAST.new(@ast_index, @ast_length)
- p.children = val[1]
- result = p
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 104)
- def _reduce_12(val, _values, result)
- l = LinkAST.new(@ast_index, @ast_length)
- l.link_type = val[0]
- l.url = val[1][0]
- l.children += val[1][1..-1] if val[1].length > 1
- result = l
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 112)
- def _reduce_13(val, _values, result)
- p = PasteAST.new(@ast_index, @ast_length)
- p.children = val[1]
- result = p
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 118)
- def _reduce_14(val, _values, result)
- l = ResourceLinkAST.new(@ast_index, @ast_length)
- l.prefix = val[1]
- l.locator = val[3]
- l.children = val[4] unless val[4].nil? or val[4].empty?
- result = l
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 126)
- def _reduce_15(val, _values, result)
- l = InternalLinkAST.new(@ast_index, @ast_length)
- l.locator = val[1]
- l.children = val[2] unless val[2].nil? or val[2].empty?
- result = l
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 133)
- def _reduce_16(val, _values, result)
- l = CategoryAST.new(@ast_index, @ast_length)
- l.locator = val[2]
- l.sort_as = val[3]
- result = l
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 140)
- def _reduce_17(val, _values, result)
- l = CategoryLinkAST.new(@ast_index, @ast_length)
- l.locator = val[3]
- l.children = val[4] unless val[4].nil? or val[4].empty?
- result = l
-
- result
- end
-.,.,
-
-# reduce 18 omitted
-
-module_eval(<<'.,.,', 'mediacloth.y', 150)
- def _reduce_19(val, _values, result)
- result = nil
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 154)
- def _reduce_20(val, _values, result)
- result = val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 161)
- def _reduce_21(val, _values, result)
- if val[0] != val[2]
- raise Racc::ParseError.new("XHTML end tag #{val[2]} does not match start tag #{val[0]}")
- end
- elem = ElementAST.new(@ast_index, @ast_length)
- elem.name = val[0]
- elem.attributes = val[1]
- result = elem
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 171)
- def _reduce_22(val, _values, result)
- if val[0] != val[3]
- raise Racc::ParseError.new("XHTML end tag #{val[3]} does not match start tag #{val[0]}")
- end
- elem = ElementAST.new(@ast_index, @ast_length)
- elem.name = val[0]
- elem.attributes = val[1]
- elem.children += val[2]
- result = elem
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 184)
- def _reduce_23(val, _values, result)
- result = nil
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 188)
- def _reduce_24(val, _values, result)
- attr_map = val[2] ? val[2] : {}
- attr_map[val[0]] = true
- result = attr_map
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 194)
- def _reduce_25(val, _values, result)
- attr_map = val[2] ? val[2] : {}
- attr_map[val[0]] = val[1]
- result = attr_map
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 204)
- def _reduce_26(val, _values, result)
- result = val
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 208)
- def _reduce_27(val, _values, result)
- result = [val[0]]
- result += val[2]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 217)
- def _reduce_28(val, _values, result)
- result = val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 221)
- def _reduce_29(val, _values, result)
- result = val[0]
- result += val[2] if val[2]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 229)
- def _reduce_30(val, _values, result)
- result = nil
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 233)
- def _reduce_31(val, _values, result)
- result = val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 239)
- def _reduce_32(val, _values, result)
- result = nil
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 243)
- def _reduce_33(val, _values, result)
- result = val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 249)
- def _reduce_34(val, _values, result)
- result = nil
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 253)
- def _reduce_35(val, _values, result)
- result = val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 257)
- def _reduce_36(val, _values, result)
- i = InternalLinkItemAST.new(@ast_index, @ast_length)
- i.children = val[1]
- result = [i]
- result += val[2] if val[2]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 266)
- def _reduce_37(val, _values, result)
- result = []
- result << val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 271)
- def _reduce_38(val, _values, result)
- result = []
- result += val[0]
- result << val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 279)
- def _reduce_39(val, _values, result)
- p = TextAST.new(@ast_index, @ast_length)
- p.formatting = val[0][0]
- p.contents = val[0][1]
- result = p
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 286)
- def _reduce_40(val, _values, result)
- result = val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 293)
- def _reduce_41(val, _values, result)
- table = TableAST.new(@ast_index, @ast_length)
- table.children = val[1] unless val[1].nil? or val[1].empty?
- result = table
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 299)
- def _reduce_42(val, _values, result)
- table = TableAST.new(@ast_index, @ast_length)
- table.options = val[1]
- table.children = val[2] unless val[2].nil? or val[2].empty?
- result = table
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 307)
- def _reduce_43(val, _values, result)
- result = nil
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 311)
- def _reduce_44(val, _values, result)
- row = TableRowAST.new(@ast_index, @ast_length)
- row.children = val[1] unless val[1].nil? or val[1].empty?
- result = [row]
- result += val[3] unless val[3].nil? or val[3].empty?
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 318)
- def _reduce_45(val, _values, result)
- row = TableRowAST.new(@ast_index, @ast_length)
- row.children = val[2] unless val[2].nil? or val[2].empty?
- row.options = val[1]
- result = [row]
- result += val[4] unless val[4].nil? or val[4].empty?
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 327)
- def _reduce_46(val, _values, result)
- result = nil
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 331)
- def _reduce_47(val, _values, result)
- cell = TableCellAST.new(@ast_index, @ast_length)
- cell.type = :head
- result = [cell]
- result += val[2] unless val[2].nil? or val[2].empty?
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 338)
- def _reduce_48(val, _values, result)
- cell = TableCellAST.new(@ast_index, @ast_length)
- cell.children = val[1] unless val[1].nil? or val[1].empty?
- cell.type = :head
- result = [cell]
- result += val[3] unless val[3].nil? or val[3].empty?
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 346)
- def _reduce_49(val, _values, result)
- cell = TableCellAST.new(@ast_index, @ast_length)
- cell.type = :body
- result = [cell]
- result += val[2] unless val[2].nil? or val[2].empty?
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 353)
- def _reduce_50(val, _values, result)
- if val[2] == 'attributes'
- result = []
- else
- cell = TableCellAST.new(@ast_index, @ast_length)
- cell.children = val[1] unless val[1].nil? or val[1].empty?
- cell.type = :body
- result = [cell]
- end
- result += val[3] unless val[3].nil? or val[3].empty?
- if val[2] == 'attributes' and val[3] and val[3].first.class == TableCellAST
- val[3].first.attributes = val[1]
- end
- result
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 371)
- def _reduce_51(val, _values, result)
- return [:None, val[0]]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 373)
- def _reduce_52(val, _values, result)
- return [:HLine, val[0]]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 375)
- def _reduce_53(val, _values, result)
- return [:CharacterEntity, val[0]]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 377)
- def _reduce_54(val, _values, result)
- return [:SignatureDate, val[0]]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 379)
- def _reduce_55(val, _values, result)
- return [:SignatureName, val[0]]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 381)
- def _reduce_56(val, _values, result)
- return [:SignatureFull, val[0]]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 387)
- def _reduce_57(val, _values, result)
- result = FormattedAST.new(@ast_index, @ast_length)
- result.formatting = :Bold
- result
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 393)
- def _reduce_58(val, _values, result)
- result = FormattedAST.new(@ast_index, @ast_length)
- result.formatting = :Italic
- result
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 399)
- def _reduce_59(val, _values, result)
- p = FormattedAST.new(@ast_index, @ast_length)
- p.formatting = :Bold
- p.children += val[1]
- result = p
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 406)
- def _reduce_60(val, _values, result)
- p = FormattedAST.new(@ast_index, @ast_length)
- p.formatting = :Italic
- p.children += val[1]
- result = p
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 415)
- def _reduce_61(val, _values, result)
- list = ListAST.new(@ast_index, @ast_length)
- list.list_type = :Bulleted
- list.children << val[1]
- list.children += val[2]
- result = list
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 425)
- def _reduce_62(val, _values, result)
- list = ListAST.new(@ast_index, @ast_length)
- list.list_type = :Numbered
- list.children << val[1]
- list.children += val[2]
- result = list
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 434)
- def _reduce_63(val, _values, result)
- result = []
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 437)
- def _reduce_64(val, _values, result)
- result << val[1]
- result += val[2]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 441)
- def _reduce_65(val, _values, result)
- result = []
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 447)
- def _reduce_66(val, _values, result)
- result = ListItemAST.new(@ast_index, @ast_length)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 451)
- def _reduce_67(val, _values, result)
- li = ListItemAST.new(@ast_index, @ast_length)
- li.children += val[1]
- result = li
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 460)
- def _reduce_68(val, _values, result)
- result = [val[1]]
- result += val[2]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 465)
- def _reduce_69(val, _values, result)
- result = val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 472)
- def _reduce_70(val, _values, result)
- result = ListTermAST.new(@ast_index, @ast_length)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 476)
- def _reduce_71(val, _values, result)
- term = ListTermAST.new(@ast_index, @ast_length)
- term.children += val[1]
- result = term
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 484)
- def _reduce_72(val, _values, result)
- result = [val[0]]
- result += val[1] if val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 489)
- def _reduce_73(val, _values, result)
- result = []
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 495)
- def _reduce_74(val, _values, result)
- result = ListDefinitionAST.new(@ast_index, @ast_length)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 499)
- def _reduce_75(val, _values, result)
- term = ListDefinitionAST.new(@ast_index, @ast_length)
- term.children += val[1]
- result = term
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 506)
- def _reduce_76(val, _values, result)
- p = PreformattedAST.new(@ast_index, @ast_length)
- p.children += val[1]
- result = p
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 512)
- def _reduce_77(val, _values, result)
- p = PreformattedAST.new(@ast_index, @ast_length)
- p.indented = true
- p.children += val[1]
- result = p
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 520)
- def _reduce_78(val, _values, result)
- result = [val[1], val[0].length]
- s = SectionAST.new(@ast_index, @ast_length)
- s.children = val[1]
- s.level = val[0].length
- result = s
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 530)
- def _reduce_79(val, _values, result)
- t = TemplateAST.new(@ast_index, @ast_length)
- t.template_name = val[1]
- t.children = val[2] unless val[2].nil? or val[2].empty?
- result = t
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 539)
- def _reduce_80(val, _values, result)
- result = nil
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 543)
- def _reduce_81(val, _values, result)
- p = TemplateParameterAST.new(@ast_index, @ast_length)
- p.parameter_value = val[1]
- result = [p]
- result += val[2] if val[2]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mediacloth.y', 550)
- def _reduce_82(val, _values, result)
- p = TemplateParameterAST.new(@ast_index, @ast_length)
- p.children << val[1]
- result = [p]
- result += val[2] if val[2]
-
- result
- end
-.,.,
-
-def _reduce_none(val, _values, result)
- val[0]
-end
-
-end # class MediaWikiParser
diff --git a/test/racc/regress/mof b/test/racc/regress/mof
deleted file mode 100644
index d702292e51..0000000000
--- a/test/racc/regress/mof
+++ /dev/null
@@ -1,1368 +0,0 @@
-#
-# DO NOT MODIFY!!!!
-# This file is automatically generated by Racc 1.5.0
-# from Racc grammar file "".
-#
-
-require 'racc/parser.rb'
-
-
-# parser.rb - generated by racc
-
-require 'strscan'
-require 'rubygems'
-require 'cim'
-require File.join(__dir__, 'result')
-require File.join(__dir__, 'scanner')
-require File.join(__dir__, 'case')
-
-module MOF
- class Parser < Racc::Parser
-
-module_eval(<<'...end mof.y/module_eval...', 'mof.y', 571)
-
-#
-# Initialize MOF::Parser
-# MOF::Parser.new options = {}
-#
-# options -> Hash of options
-# :debug -> boolean
-# :includes -> array of include dirs
-# :style -> :cim or :wmi
-#
-def initialize options = {}
- @yydebug = options[:debug]
- @includes = options[:includes] || []
- @quiet = options[:quiet]
- @style = options[:style] || :cim # default to style CIM v2.2 syntax
-
- @lineno = 1
- @file = nil
- @iconv = nil
- @eol = "\n"
- @fname = nil
- @fstack = []
- @in_comment = false
- @seen_files = []
- @qualifiers = {}
-end
-
-#
-# Make options hash from argv
-#
-# returns [ files, options ]
-#
-
- def self.argv_handler name, argv
- files = []
- options = { :namespace => "" }
- while argv.size > 0
- case opt = argv.shift
- when "-h"
- $stderr.puts "Ruby MOF compiler"
- $stderr.puts "#{name} [-h] [-d] [-I <dir>] [<moffiles>]"
- $stderr.puts "Compiles <moffile>"
- $stderr.puts "\t-d debug"
- $stderr.puts "\t-h this help"
- $stderr.puts "\t-I <dir> include dir"
- $stderr.puts "\t-f force"
- $stderr.puts "\t-n <namespace>"
- $stderr.puts "\t-o <output>"
- $stderr.puts "\t-s <style> syntax style (wmi,cim)"
- $stderr.puts "\t-q quiet"
- $stderr.puts "\t<moffiles> file(s) to read (else use $stdin)"
- exit 0
- when "-f" then options[:force] = true
- when "-s" then options[:style] = argv.shift.to_sym
- when "-d" then options[:debug] = true
- when "-q" then options[:quiet] = true
- when "-I"
- options[:includes] ||= []
- dirname = argv.shift
- unless File.directory?(dirname)
- files << dirname
- dirname = File.dirname(dirname)
- end
- options[:includes] << Pathname.new(dirname)
- when "-n" then options[:namespace] = argv.shift
- when "-o" then options[:output] = argv.shift
- when /^-.+/
- $stderr.puts "Undefined option #{opt}"
- else
- files << opt
- end
- end
- [ files, options ]
- end
-
-include Helper
-include Scanner
-
-...end mof.y/module_eval...
-##### State transition tables begin ###
-
-racc_action_table = [
- 13, 172, 163, 197, 174, 27, 63, 17, 145, 146,
- 147, 62, 28, 172, 11, 173, 174, 173, 148, 11,
- 144, 149, 150, 151, 152, 18, 163, 173, 33, 153,
- 106, 107, 108, 109, 110, 112, 111, 40, 15, 16,
- 42, 55, 57, 68, 69, 71, 72, 52, 53, 54,
- 56, 163, 7, 199, 35, 42, 174, 7, 10, 10,
- 115, 102, 114, 36, 10, 55, 57, 68, 69, 71,
- 72, 52, 53, 54, 56, 51, 190, 44, -77, 42,
- 33, 189, 10, 10, 33, 102, 51, 164, 60, 10,
- 55, 57, 68, 69, 71, 72, 52, 53, 54, 56,
- 170, 35, 10, 21, 42, 22, 23, 10, 29, 31,
- 102, 35, 95, 96, 55, 57, 25, 65, 24, 78,
- 52, 53, 54, 56, 97, 55, 57, 35, 180, 181,
- 100, 52, 53, 54, 56, 93, 79, 80, 81, 82,
- 83, 84, 85, 86, 87, 88, 89, 90, 91, 92,
- -25, 93, 79, 80, 81, 82, 83, 84, 85, 86,
- 87, 88, 89, 90, 91, 92, 191, 192, 102, 60,
- 55, 57, 68, 69, 71, 72, 52, 53, 54, 56,
- 145, 146, 147, 172, 113, 97, 174, 10, 18, 118,
- 148, 119, 144, 149, 150, 151, 152, 173, 121, 124,
- 35, 153, 55, 57, 68, 69, 71, 72, 52, 53,
- 54, 56, 106, 107, 108, 109, 110, 112, 111, 10,
- 55, 57, 68, 69, 71, 72, 52, 53, 54, 56,
- 21, 126, 22, 23, 127, 129, 21, 10, 22, 23,
- 130, 131, 133, 25, 135, 24, 10, 141, 154, 25,
- 35, 24, 93, 79, 80, 81, 82, 83, 84, 85,
- 86, 87, 88, 89, 90, 91, 92, 106, 107, 108,
- 109, 110, 112, 111, 184, 185, 194, 200, 121, 207,
- -59, 121, 209, 211, 135, 135, 218, 220, 221, 226,
- 228, 229, 231, 10, 121, 135 ]
-
-racc_action_check = [
- 1, 140, 135, 186, 140, 12, 37, 8, 131, 131,
- 131, 37, 13, 194, 0, 140, 194, 186, 131, 1,
- 131, 131, 131, 131, 131, 8, 189, 194, 16, 131,
- 65, 65, 65, 65, 65, 65, 65, 20, 7, 7,
- 20, 135, 135, 135, 135, 135, 135, 135, 135, 135,
- 135, 211, 0, 187, 17, 135, 187, 1, 135, 0,
- 75, 135, 75, 18, 1, 189, 189, 189, 189, 189,
- 189, 189, 189, 189, 189, 33, 177, 26, 207, 189,
- 29, 177, 189, 207, 30, 189, 96, 137, 34, 137,
- 211, 211, 211, 211, 211, 211, 211, 211, 211, 211,
- 138, 36, 138, 10, 211, 10, 10, 211, 15, 15,
- 211, 169, 47, 47, 33, 33, 10, 38, 10, 43,
- 33, 33, 33, 33, 49, 96, 96, 216, 142, 142,
- 58, 96, 96, 96, 96, 169, 169, 169, 169, 169,
- 169, 169, 169, 169, 169, 169, 169, 169, 169, 169,
- 42, 216, 216, 216, 216, 216, 216, 216, 216, 216,
- 216, 216, 216, 216, 216, 216, 178, 178, 60, 61,
- 42, 42, 42, 42, 42, 42, 42, 42, 42, 42,
- 181, 181, 181, 218, 66, 70, 218, 42, 74, 77,
- 181, 78, 181, 181, 181, 181, 181, 218, 94, 98,
- 100, 181, 40, 40, 40, 40, 40, 40, 40, 40,
- 40, 40, 141, 141, 141, 141, 141, 141, 141, 40,
- 115, 115, 115, 115, 115, 115, 115, 115, 115, 115,
- 11, 102, 11, 11, 103, 116, 63, 115, 63, 63,
- 118, 119, 121, 11, 122, 11, 127, 130, 132, 63,
- 161, 63, 44, 44, 44, 44, 44, 44, 44, 44,
- 44, 44, 44, 44, 44, 44, 44, 192, 192, 192,
- 192, 192, 192, 192, 162, 164, 183, 188, 195, 196,
- 197, 198, 201, 205, 206, 208, 210, 212, 213, 217,
- 221, 222, 223, 229, 230, 233 ]
-
-racc_action_pointer = [
- -5, 0, nil, nil, nil, nil, nil, 32, -2, nil,
- 95, 222, -58, 12, nil, 101, -30, 46, 32, nil,
- -21, nil, nil, nil, nil, nil, 11, nil, nil, 22,
- 26, nil, nil, 67, 60, nil, 93, -54, 51, nil,
- 155, nil, 123, 59, 220, nil, nil, 53, nil, 76,
- nil, nil, nil, nil, nil, nil, nil, nil, 64, nil,
- 101, 141, nil, 228, nil, 18, 125, nil, nil, nil,
- 137, nil, nil, nil, 161, 0, nil, 129, 171, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 134, nil, 78, nil, 138, nil,
- 192, nil, 223, 173, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 173, 172, nil, 214, 183,
- nil, 195, 176, nil, nil, nil, nil, 182, nil, nil,
- 189, -1, 183, nil, nil, -6, nil, 25, 38, nil,
- -7, 200, 69, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 242, 208, nil, 212, nil, nil, nil, nil, 103,
- nil, nil, nil, nil, nil, nil, nil, 13, 107, nil,
- nil, 171, nil, 207, nil, nil, -5, 45, 248, 18,
- nil, nil, 255, nil, 5, 214, 221, 222, 217, nil,
- nil, 219, nil, nil, nil, 215, 216, 19, 217, nil,
- 226, 43, 224, 229, nil, nil, 119, 226, 175, nil,
- nil, 227, 231, 284, nil, nil, nil, nil, nil, 229,
- 230, nil, nil, 227, nil, nil ]
-
-racc_action_default = [
- -1, -25, -2, -4, -5, -6, -7, -161, -161, -26,
- -161, -161, -161, -161, -3, -161, -12, -161, -161, -28,
- -33, -133, -134, -135, -136, -137, -161, -155, 236, -12,
- -12, -11, -10, -161, -44, -48, -161, -161, -31, -34,
- -25, -36, -100, -161, -161, -8, -9, -161, -14, -16,
- -17, -18, -110, -111, -112, -113, -114, -115, -46, -45,
- -161, -44, -27, -161, -30, -161, -161, -103, -104, -105,
- -106, -107, -108, -109, -161, -161, -101, -131, -161, -60,
- -61, -62, -63, -64, -65, -66, -67, -68, -69, -70,
- -71, -72, -73, -74, -86, -13, -161, -116, -161, -47,
- -161, -49, -161, -161, -29, -32, -37, -38, -39, -40,
- -41, -42, -43, -35, -99, -25, -161, -132, -161, -161,
- -87, -91, -93, -15, -20, -51, -50, -25, -102, -130,
- -161, -161, -161, -92, -94, -25, -138, -25, -25, -157,
- -161, -161, -161, -140, -142, -143, -144, -145, -146, -147,
- -148, -149, -150, -151, -90, -95, -96, -97, -98, -117,
- -118, -161, -161, -122, -161, -21, -22, -23, -24, -161,
- -156, -158, -55, -56, -58, -128, -129, -161, -161, -153,
- -139, -161, -119, -161, -121, -19, -161, -161, -75, -25,
- -160, -152, -161, -141, -161, -86, -161, -55, -86, -57,
- -76, -161, -154, -123, -125, -161, -93, -25, -93, -159,
- -124, -25, -161, -161, -78, -80, -161, -161, -161, -127,
- -52, -161, -79, -161, -83, -84, -53, -126, -54, -25,
- -86, -85, -81, -88, -82, -89 ]
-
-racc_goto_table = [
- 8, 8, 34, 94, 122, 105, 136, 155, 48, 66,
- 49, 76, 50, 19, 143, 187, 58, 204, 215, 32,
- 139, 61, 2, 14, 12, 12, 1, 30, 47, 98,
- 137, 171, 45, 46, 165, 166, 167, 168, 37, 26,
- 232, 227, 38, 103, 64, 39, 41, 99, 101, 195,
- 198, 196, 213, 214, 222, 223, 230, 234, 235, 132,
- 75, 201, 225, 182, 193, 203, 104, 210, 177, 43,
- 77, 123, 116, 49, 117, 50, 142, 178, 138, nil,
- nil, 179, nil, 219, 128, 125, nil, nil, nil, nil,
- 212, nil, 217, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 206, nil, nil, 208, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 140, 186, nil,
- nil, nil, 202, nil, nil, nil, nil, 169, 140, nil,
- 233, nil, nil, nil, nil, nil, 183, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 224, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 216, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 216 ]
-
-racc_goto_check = [
- 13, 13, 14, 35, 37, 28, 38, 52, 10, 30,
- 11, 30, 12, 23, 69, 39, 15, 61, 44, 7,
- 72, 14, 2, 2, 55, 55, 1, 8, 9, 16,
- 17, 72, 7, 7, 18, 19, 20, 21, 24, 25,
- 44, 61, 26, 15, 27, 29, 31, 33, 34, 36,
- 40, 41, 42, 43, 45, 46, 47, 48, 50, 51,
- 54, 52, 39, 58, 69, 60, 23, 62, 63, 64,
- 65, 10, 66, 11, 67, 12, 68, 70, 71, nil,
- nil, 28, nil, 52, 30, 14, nil, nil, nil, nil,
- 38, nil, 38, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 37, nil, nil, 37, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 13, 35, nil,
- nil, nil, 28, nil, nil, nil, nil, 13, 13, nil,
- 37, nil, nil, nil, nil, nil, 14, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 35, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 13, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 13 ]
-
-racc_goto_pointer = [
- nil, 26, 22, nil, nil, nil, nil, 3, 12, -5,
- -25, -23, -21, 0, -15, -18, -29, -94, -103, -102,
- -101, -100, nil, 3, 19, 28, 22, 6, -60, 25,
- -31, 26, nil, -11, -12, -41, -137, -90, -116, -154,
- -137, -135, -155, -154, -189, -161, -161, -167, -176, nil,
- -175, -62, -128, nil, 18, 24, nil, nil, -98, nil,
- -129, -177, -137, -72, 43, 27, -5, -3, -55, -117,
- -64, -49, -107 ]
-
-racc_goto_default = [
- nil, nil, nil, 3, 4, 5, 6, nil, nil, nil,
- nil, 70, 67, 74, 188, nil, nil, nil, nil, nil,
- nil, nil, 9, nil, nil, 20, nil, nil, nil, nil,
- 156, 157, 59, nil, 160, nil, 175, nil, nil, nil,
- 176, nil, nil, nil, nil, nil, nil, nil, nil, 120,
- 134, nil, nil, 158, nil, 73, 159, 161, nil, 162,
- nil, nil, nil, 205, nil, nil, nil, nil, nil, nil,
- nil, nil, nil ]
-
-racc_reduce_table = [
- 0, 0, :racc_error,
- 0, 71, :_reduce_1,
- 1, 71, :_reduce_2,
- 2, 71, :_reduce_3,
- 1, 72, :_reduce_none,
- 1, 72, :_reduce_5,
- 1, 72, :_reduce_6,
- 1, 72, :_reduce_7,
- 4, 73, :_reduce_8,
- 4, 73, :_reduce_none,
- 3, 73, :_reduce_10,
- 1, 78, :_reduce_none,
- 0, 77, :_reduce_12,
- 3, 77, :_reduce_13,
- 1, 79, :_reduce_none,
- 3, 79, :_reduce_none,
- 1, 80, :_reduce_none,
- 1, 80, :_reduce_17,
- 1, 80, :_reduce_none,
- 9, 74, :_reduce_19,
- 0, 87, :_reduce_20,
- 2, 87, :_reduce_21,
- 1, 88, :_reduce_none,
- 1, 88, :_reduce_none,
- 1, 88, :_reduce_none,
- 0, 83, :_reduce_none,
- 1, 83, :_reduce_26,
- 4, 92, :_reduce_27,
- 0, 94, :_reduce_28,
- 3, 94, :_reduce_29,
- 3, 93, :_reduce_30,
- 0, 97, :_reduce_none,
- 2, 97, :_reduce_32,
- 0, 96, :_reduce_none,
- 1, 96, :_reduce_none,
- 3, 99, :_reduce_35,
- 1, 99, :_reduce_none,
- 1, 98, :_reduce_none,
- 1, 98, :_reduce_none,
- 1, 98, :_reduce_none,
- 1, 98, :_reduce_none,
- 1, 98, :_reduce_none,
- 1, 98, :_reduce_none,
- 1, 98, :_reduce_43,
- 0, 85, :_reduce_none,
- 1, 85, :_reduce_none,
- 0, 86, :_reduce_none,
- 1, 86, :_reduce_none,
- 1, 84, :_reduce_48,
- 2, 102, :_reduce_49,
- 2, 104, :_reduce_50,
- 2, 103, :_reduce_51,
- 6, 89, :_reduce_52,
- 6, 91, :_reduce_53,
- 7, 90, :_reduce_54,
- 1, 106, :_reduce_none,
- 1, 106, :_reduce_56,
- 1, 110, :_reduce_none,
- 1, 110, :_reduce_58,
- 1, 111, :_reduce_none,
- 1, 105, :_reduce_none,
- 1, 105, :_reduce_none,
- 1, 105, :_reduce_none,
- 1, 105, :_reduce_none,
- 1, 105, :_reduce_none,
- 1, 105, :_reduce_none,
- 1, 105, :_reduce_none,
- 1, 105, :_reduce_none,
- 1, 105, :_reduce_none,
- 1, 105, :_reduce_none,
- 1, 105, :_reduce_none,
- 1, 105, :_reduce_none,
- 1, 105, :_reduce_none,
- 1, 105, :_reduce_none,
- 1, 105, :_reduce_74,
- 1, 109, :_reduce_75,
- 2, 109, :_reduce_76,
- 0, 112, :_reduce_none,
- 1, 112, :_reduce_none,
- 2, 113, :_reduce_79,
- 0, 115, :_reduce_80,
- 3, 115, :_reduce_81,
- 5, 114, :_reduce_82,
- 1, 116, :_reduce_none,
- 1, 116, :_reduce_none,
- 1, 117, :_reduce_none,
- 0, 107, :_reduce_none,
- 1, 107, :_reduce_none,
- 0, 118, :_reduce_none,
- 1, 118, :_reduce_89,
- 3, 119, :_reduce_90,
- 0, 121, :_reduce_91,
- 1, 121, :_reduce_none,
- 0, 108, :_reduce_none,
- 1, 108, :_reduce_none,
- 2, 120, :_reduce_95,
- 1, 122, :_reduce_none,
- 1, 122, :_reduce_none,
- 1, 122, :_reduce_none,
- 3, 101, :_reduce_99,
- 0, 124, :_reduce_none,
- 1, 124, :_reduce_101,
- 3, 124, :_reduce_102,
- 1, 100, :_reduce_none,
- 1, 100, :_reduce_none,
- 1, 100, :_reduce_none,
- 1, 100, :_reduce_none,
- 1, 100, :_reduce_none,
- 1, 100, :_reduce_none,
- 1, 100, :_reduce_109,
- 1, 82, :_reduce_none,
- 1, 82, :_reduce_none,
- 1, 82, :_reduce_none,
- 1, 82, :_reduce_none,
- 1, 82, :_reduce_none,
- 1, 81, :_reduce_none,
- 2, 81, :_reduce_116,
- 1, 123, :_reduce_none,
- 1, 123, :_reduce_none,
- 2, 126, :_reduce_none,
- 0, 127, :_reduce_none,
- 2, 127, :_reduce_none,
- 1, 129, :_reduce_none,
- 3, 128, :_reduce_none,
- 2, 130, :_reduce_none,
- 0, 132, :_reduce_none,
- 3, 132, :_reduce_none,
- 3, 131, :_reduce_none,
- 1, 133, :_reduce_none,
- 1, 133, :_reduce_none,
- 6, 75, :_reduce_130,
- 0, 136, :_reduce_none,
- 1, 136, :_reduce_none,
- 1, 95, :_reduce_none,
- 1, 95, :_reduce_none,
- 1, 95, :_reduce_none,
- 1, 95, :_reduce_none,
- 1, 95, :_reduce_none,
- 4, 134, :_reduce_138,
- 5, 135, :_reduce_139,
- 1, 138, :_reduce_140,
- 3, 138, :_reduce_141,
- 1, 139, :_reduce_none,
- 1, 139, :_reduce_none,
- 1, 139, :_reduce_none,
- 1, 139, :_reduce_none,
- 1, 139, :_reduce_none,
- 1, 139, :_reduce_none,
- 1, 139, :_reduce_none,
- 1, 139, :_reduce_none,
- 1, 139, :_reduce_none,
- 1, 139, :_reduce_none,
- 5, 137, :_reduce_152,
- 1, 140, :_reduce_153,
- 3, 140, :_reduce_154,
- 2, 76, :_reduce_none,
- 8, 125, :_reduce_none,
- 1, 141, :_reduce_none,
- 2, 141, :_reduce_none,
- 5, 142, :_reduce_none,
- 3, 142, :_reduce_160 ]
-
-racc_reduce_n = 161
-
-racc_shift_n = 236
-
-racc_token_table = {
- false => 0,
- :error => 1,
- "*" => 2,
- "/" => 3,
- "+" => 4,
- "-" => 5,
- :PRAGMA => 6,
- :INCLUDE => 7,
- :IDENTIFIER => 8,
- :CLASS => 9,
- :ASSOCIATION => 10,
- :INDICATION => 11,
- :AMENDED => 12,
- :ENABLEOVERRIDE => 13,
- :DISABLEOVERRIDE => 14,
- :RESTRICTED => 15,
- :TOSUBCLASS => 16,
- :TOINSTANCE => 17,
- :TRANSLATABLE => 18,
- :QUALIFIER => 19,
- :SCOPE => 20,
- :SCHEMA => 21,
- :PROPERTY => 22,
- :REFERENCE => 23,
- :METHOD => 24,
- :PARAMETER => 25,
- :FLAVOR => 26,
- :INSTANCE => 27,
- :AS => 28,
- :REF => 29,
- :ANY => 30,
- :OF => 31,
- :DT_VOID => 32,
- :DT_UINT8 => 33,
- :DT_SINT8 => 34,
- :DT_UINT16 => 35,
- :DT_SINT16 => 36,
- :DT_UINT32 => 37,
- :DT_SINT32 => 38,
- :DT_UINT64 => 39,
- :DT_SINT64 => 40,
- :DT_REAL32 => 41,
- :DT_REAL64 => 42,
- :DT_CHAR16 => 43,
- :DT_STR => 44,
- :DT_BOOLEAN => 45,
- :DT_DATETIME => 46,
- :positiveDecimalValue => 47,
- :stringValue => 48,
- :realValue => 49,
- :charValue => 50,
- :booleanValue => 51,
- :nullValue => 52,
- :binaryValue => 53,
- :octalValue => 54,
- :decimalValue => 55,
- :hexValue => 56,
- "#" => 57,
- "(" => 58,
- ")" => 59,
- "," => 60,
- "{" => 61,
- "}" => 62,
- ";" => 63,
- "[" => 64,
- "]" => 65,
- ":" => 66,
- "$" => 67,
- "=" => 68,
- "." => 69 }
-
-racc_nt_base = 70
-
-racc_use_result_var = true
-
-Racc_arg = [
- racc_action_table,
- racc_action_check,
- racc_action_default,
- racc_action_pointer,
- racc_goto_table,
- racc_goto_check,
- racc_goto_default,
- racc_goto_pointer,
- racc_nt_base,
- racc_reduce_table,
- racc_token_table,
- racc_shift_n,
- racc_reduce_n,
- racc_use_result_var ]
-
-Racc_token_to_s_table = [
- "$end",
- "error",
- "\"*\"",
- "\"/\"",
- "\"+\"",
- "\"-\"",
- "PRAGMA",
- "INCLUDE",
- "IDENTIFIER",
- "CLASS",
- "ASSOCIATION",
- "INDICATION",
- "AMENDED",
- "ENABLEOVERRIDE",
- "DISABLEOVERRIDE",
- "RESTRICTED",
- "TOSUBCLASS",
- "TOINSTANCE",
- "TRANSLATABLE",
- "QUALIFIER",
- "SCOPE",
- "SCHEMA",
- "PROPERTY",
- "REFERENCE",
- "METHOD",
- "PARAMETER",
- "FLAVOR",
- "INSTANCE",
- "AS",
- "REF",
- "ANY",
- "OF",
- "DT_VOID",
- "DT_UINT8",
- "DT_SINT8",
- "DT_UINT16",
- "DT_SINT16",
- "DT_UINT32",
- "DT_SINT32",
- "DT_UINT64",
- "DT_SINT64",
- "DT_REAL32",
- "DT_REAL64",
- "DT_CHAR16",
- "DT_STR",
- "DT_BOOLEAN",
- "DT_DATETIME",
- "positiveDecimalValue",
- "stringValue",
- "realValue",
- "charValue",
- "booleanValue",
- "nullValue",
- "binaryValue",
- "octalValue",
- "decimalValue",
- "hexValue",
- "\"#\"",
- "\"(\"",
- "\")\"",
- "\",\"",
- "\"{\"",
- "\"}\"",
- "\";\"",
- "\"[\"",
- "\"]\"",
- "\":\"",
- "\"$\"",
- "\"=\"",
- "\".\"",
- "$start",
- "mofSpecification",
- "mofProduction",
- "compilerDirective",
- "classDeclaration",
- "qualifierDeclaration",
- "instanceDeclaration",
- "pragmaParameters_opt",
- "pragmaName",
- "pragmaParameterValues",
- "pragmaParameterValue",
- "string",
- "integerValue",
- "qualifierList_opt",
- "className",
- "alias_opt",
- "superClass_opt",
- "classFeatures",
- "classFeature",
- "propertyDeclaration",
- "methodDeclaration",
- "referenceDeclaration",
- "qualifierList",
- "qualifier",
- "qualifiers",
- "qualifierName",
- "qualifierParameter_opt",
- "flavor_opt",
- "flavor",
- "qualifierParameter",
- "constantValue",
- "arrayInitializer",
- "alias",
- "superClass",
- "aliasIdentifier",
- "dataType",
- "propertyName",
- "array_opt",
- "defaultValue_opt",
- "objectRef",
- "referenceName",
- "methodName",
- "parameterList_opt",
- "parameterList",
- "parameter",
- "parameters",
- "typespec",
- "parameterName",
- "parameterValue_opt",
- "array",
- "defaultValue",
- "positiveDecimalValue_opt",
- "initializer",
- "referenceInitializer",
- "constantValues",
- "instance",
- "objectHandle",
- "namespace_opt",
- "modelPath",
- "namespaceHandle",
- "keyValuePairList",
- "keyValuePair",
- "keyValuePairs",
- "keyname",
- "qualifierType",
- "scope",
- "defaultFlavor_opt",
- "defaultFlavor",
- "metaElements",
- "metaElement",
- "flavors",
- "valueInitializers",
- "valueInitializer" ]
-
-Racc_debug_parser = false
-
-##### State transition tables end #####
-
-# reduce 0 omitted
-
-module_eval(<<'.,.,', 'mof.y', 41)
- def _reduce_1(val, _values, result)
- result = Hash.new
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mof.y', 43)
- def _reduce_2(val, _values, result)
- result = { @name => @result }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mof.y', 45)
- def _reduce_3(val, _values, result)
- result = val[0]
- result[@name] = @result
-
- result
- end
-.,.,
-
-# reduce 4 omitted
-
-module_eval(<<'.,.,', 'mof.y', 53)
- def _reduce_5(val, _values, result)
- #puts "Class '#{val[0].name}'"
- @result.classes << val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mof.y', 57)
- def _reduce_6(val, _values, result)
- @result.qualifiers << val[0]
- @qualifiers[val[0].name.downcase] = val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mof.y', 61)
- def _reduce_7(val, _values, result)
- @result.instances << val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mof.y', 71)
- def _reduce_8(val, _values, result)
- raise MOF::Helper::Error.new(@name,@lineno,@line,"Missing filename after '#pragma include'") unless val[3]
- open val[3], :pragma
-
- result
- end
-.,.,
-
-# reduce 9 omitted
-
-module_eval(<<'.,.,', 'mof.y', 76)
- def _reduce_10(val, _values, result)
- raise StyleError.new(@name,@lineno,@line,"Use '#pragma include' instead of '#include'") unless @style == :wmi
- raise MOF::Helper::Error.new(@name,@lineno,@line,"Missing filename after '#include'") unless val[2]
- open val[2], :pragma
-
- result
- end
-.,.,
-
-# reduce 11 omitted
-
-module_eval(<<'.,.,', 'mof.y', 88)
- def _reduce_12(val, _values, result)
- raise StyleError.new(@name,@lineno,@line,"#pragma parameter missing") unless @style == :wmi
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mof.y', 90)
- def _reduce_13(val, _values, result)
- result = val[1]
- result
- end
-.,.,
-
-# reduce 14 omitted
-
-# reduce 15 omitted
-
-# reduce 16 omitted
-
-module_eval(<<'.,.,', 'mof.y', 101)
- def _reduce_17(val, _values, result)
- raise StyleError.new(@name,@lineno,@line,"#pragma parameter missing") unless @style == :wmi
- result
- end
-.,.,
-
-# reduce 18 omitted
-
-module_eval(<<'.,.,', 'mof.y', 112)
- def _reduce_19(val, _values, result)
- qualifiers = val[0]
- features = val[6]
- # FIXME: features must not include references
- result = CIM::Class.new(val[2],qualifiers,val[3],val[4],features)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mof.y', 121)
- def _reduce_20(val, _values, result)
- result = []
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mof.y', 123)
- def _reduce_21(val, _values, result)
- result = val[0] << val[1]
- result
- end
-.,.,
-
-# reduce 22 omitted
-
-# reduce 23 omitted
-
-# reduce 24 omitted
-
-# reduce 25 omitted
-
-module_eval(<<'.,.,', 'mof.y', 136)
- def _reduce_26(val, _values, result)
- result = CIM::QualifierSet.new val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mof.y', 141)
- def _reduce_27(val, _values, result)
- result = val[2]
- result.unshift val[1] if val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mof.y', 147)
- def _reduce_28(val, _values, result)
- result = []
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mof.y', 149)
- def _reduce_29(val, _values, result)
- result = val[0]
- result << val[2] if val[2]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mof.y', 156)
- def _reduce_30(val, _values, result)
- # Get qualifier decl
- qualifier = case val[0]
- when CIM::Qualifier then val[0].definition
- when CIM::QualifierDeclaration then val[0]
- when String then @qualifiers[val[0].downcase]
- else
- nil
- end
- raise MOF::Helper::Error.new(@name,@lineno,@line,"'#{val[0]}' is not a valid qualifier") unless qualifier
- value = val[1]
- raise MOF::Helper::Error.new(@name,@lineno,@line,"#{value.inspect} does not match qualifier type '#{qualifier.type}'") unless qualifier.type.matches?(value)||@style == :wmi
- # Don't propagate a boolean 'false'
- if qualifier.type == :boolean && value == false
- result = nil
- else
- result = CIM::Qualifier.new(qualifier,value,val[2])
- end
-
- result
- end
-.,.,
-
-# reduce 31 omitted
-
-module_eval(<<'.,.,', 'mof.y', 179)
- def _reduce_32(val, _values, result)
- result = CIM::QualifierFlavors.new val[1]
- result
- end
-.,.,
-
-# reduce 33 omitted
-
-# reduce 34 omitted
-
-module_eval(<<'.,.,', 'mof.y', 189)
- def _reduce_35(val, _values, result)
- result = val[1]
- result
- end
-.,.,
-
-# reduce 36 omitted
-
-# reduce 37 omitted
-
-# reduce 38 omitted
-
-# reduce 39 omitted
-
-# reduce 40 omitted
-
-# reduce 41 omitted
-
-# reduce 42 omitted
-
-module_eval(<<'.,.,', 'mof.y', 196)
- def _reduce_43(val, _values, result)
- case val[0].to_sym
- when :amended, :toinstance
- raise StyleError.new(@name,@lineno,@line,"'#{val[0]}' is not a valid flavor") unless @style == :wmi
- end
-
- result
- end
-.,.,
-
-# reduce 44 omitted
-
-# reduce 45 omitted
-
-# reduce 46 omitted
-
-# reduce 47 omitted
-
-module_eval(<<'.,.,', 'mof.y', 215)
- def _reduce_48(val, _values, result)
- raise ParseError.new("Class name must be prefixed by '<schema>_'") unless val[0].include?("_") || @style == :wmi
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mof.y', 220)
- def _reduce_49(val, _values, result)
- result = val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mof.y', 225)
- def _reduce_50(val, _values, result)
- result = val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mof.y', 230)
- def _reduce_51(val, _values, result)
- result = val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mof.y', 236)
- def _reduce_52(val, _values, result)
- if val[3]
- type = CIM::Array.new val[3],val[1]
- else
- type = val[1]
- end
- result = CIM::Property.new(type,val[2],val[0],val[4])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mof.y', 247)
- def _reduce_53(val, _values, result)
- if val[4]
- raise StyleError.new(@name,@lineno,@line,"Array not allowed in reference declaration") unless @style == :wmi
- end
- result = CIM::Reference.new(val[1],val[2],val[0],val[4])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mof.y', 255)
- def _reduce_54(val, _values, result)
- result = CIM::Method.new(val[1],val[2],val[0],val[4])
- result
- end
-.,.,
-
-# reduce 55 omitted
-
-module_eval(<<'.,.,', 'mof.y', 261)
- def _reduce_56(val, _values, result)
- # tmplprov.mof has 'string Property;'
- raise StyleError.new(@name,@lineno,@line,"Invalid keyword '#{val[0]}' used for property name") unless @style == :wmi
-
- result
- end
-.,.,
-
-# reduce 57 omitted
-
-module_eval(<<'.,.,', 'mof.y', 269)
- def _reduce_58(val, _values, result)
- result = "Indication"
- result
- end
-.,.,
-
-# reduce 59 omitted
-
-# reduce 60 omitted
-
-# reduce 61 omitted
-
-# reduce 62 omitted
-
-# reduce 63 omitted
-
-# reduce 64 omitted
-
-# reduce 65 omitted
-
-# reduce 66 omitted
-
-# reduce 67 omitted
-
-# reduce 68 omitted
-
-# reduce 69 omitted
-
-# reduce 70 omitted
-
-# reduce 71 omitted
-
-# reduce 72 omitted
-
-# reduce 73 omitted
-
-module_eval(<<'.,.,', 'mof.y', 292)
- def _reduce_74(val, _values, result)
- raise StyleError.new(@name,@lineno,@line,"'void' is not a valid datatype") unless @style == :wmi
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mof.y', 297)
- def _reduce_75(val, _values, result)
- # WMI uses class names as data types (without REF ?!)
- raise StyleError.new(@name,@lineno,@line,"Expected 'ref' keyword after classname '#{val[0]}'") unless @style == :wmi
- result = CIM::ReferenceType.new val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mof.y', 303)
- def _reduce_76(val, _values, result)
- result = CIM::ReferenceType.new val[0]
- result
- end
-.,.,
-
-# reduce 77 omitted
-
-# reduce 78 omitted
-
-module_eval(<<'.,.,', 'mof.y', 313)
- def _reduce_79(val, _values, result)
- result = val[1].unshift val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mof.y', 318)
- def _reduce_80(val, _values, result)
- result = []
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mof.y', 320)
- def _reduce_81(val, _values, result)
- result = val[0] << val[2]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mof.y', 325)
- def _reduce_82(val, _values, result)
- if val[3]
- type = CIM::Array.new val[3], val[1]
- else
- type = val[1]
- end
- result = CIM::Property.new(type,val[2],val[0])
-
- result
- end
-.,.,
-
-# reduce 83 omitted
-
-# reduce 84 omitted
-
-# reduce 85 omitted
-
-# reduce 86 omitted
-
-# reduce 87 omitted
-
-# reduce 88 omitted
-
-module_eval(<<'.,.,', 'mof.y', 351)
- def _reduce_89(val, _values, result)
- raise "Default parameter value not allowed in syntax style '{@style}'" unless @style == :wmi
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mof.y', 356)
- def _reduce_90(val, _values, result)
- result = val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mof.y', 361)
- def _reduce_91(val, _values, result)
- result = -1
- result
- end
-.,.,
-
-# reduce 92 omitted
-
-# reduce 93 omitted
-
-# reduce 94 omitted
-
-module_eval(<<'.,.,', 'mof.y', 372)
- def _reduce_95(val, _values, result)
- result = val[1]
- result
- end
-.,.,
-
-# reduce 96 omitted
-
-# reduce 97 omitted
-
-# reduce 98 omitted
-
-module_eval(<<'.,.,', 'mof.y', 383)
- def _reduce_99(val, _values, result)
- result = val[1]
- result
- end
-.,.,
-
-# reduce 100 omitted
-
-module_eval(<<'.,.,', 'mof.y', 389)
- def _reduce_101(val, _values, result)
- result = [ val[0] ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mof.y', 391)
- def _reduce_102(val, _values, result)
- result = val[0] << val[2]
- result
- end
-.,.,
-
-# reduce 103 omitted
-
-# reduce 104 omitted
-
-# reduce 105 omitted
-
-# reduce 106 omitted
-
-# reduce 107 omitted
-
-# reduce 108 omitted
-
-module_eval(<<'.,.,', 'mof.y', 402)
- def _reduce_109(val, _values, result)
- raise "Instance as property value not allowed in syntax style '{@style}'" unless @style == :wmi
- result
- end
-.,.,
-
-# reduce 110 omitted
-
-# reduce 111 omitted
-
-# reduce 112 omitted
-
-# reduce 113 omitted
-
-# reduce 114 omitted
-
-# reduce 115 omitted
-
-module_eval(<<'.,.,', 'mof.y', 416)
- def _reduce_116(val, _values, result)
- result = val[0] + val[1]
- result
- end
-.,.,
-
-# reduce 117 omitted
-
-# reduce 118 omitted
-
-# reduce 119 omitted
-
-# reduce 120 omitted
-
-# reduce 121 omitted
-
-# reduce 122 omitted
-
-# reduce 123 omitted
-
-# reduce 124 omitted
-
-# reduce 125 omitted
-
-# reduce 126 omitted
-
-# reduce 127 omitted
-
-# reduce 128 omitted
-
-# reduce 129 omitted
-
-module_eval(<<'.,.,', 'mof.y', 471)
- def _reduce_130(val, _values, result)
- result = CIM::QualifierDeclaration.new( val[1], val[2][0], val[2][1], val[3], val[4])
- result
- end
-.,.,
-
-# reduce 131 omitted
-
-# reduce 132 omitted
-
-# reduce 133 omitted
-
-# reduce 134 omitted
-
-# reduce 135 omitted
-
-# reduce 136 omitted
-
-# reduce 137 omitted
-
-module_eval(<<'.,.,', 'mof.y', 490)
- def _reduce_138(val, _values, result)
- type = val[2].nil? ? val[1] : CIM::Array.new(val[2],val[1])
- result = [ type, val[3] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mof.y', 497)
- def _reduce_139(val, _values, result)
- result = CIM::QualifierScopes.new(val[3])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mof.y', 502)
- def _reduce_140(val, _values, result)
- result = [ val[0] ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mof.y', 504)
- def _reduce_141(val, _values, result)
- result = val[0] << val[2]
- result
- end
-.,.,
-
-# reduce 142 omitted
-
-# reduce 143 omitted
-
-# reduce 144 omitted
-
-# reduce 145 omitted
-
-# reduce 146 omitted
-
-# reduce 147 omitted
-
-# reduce 148 omitted
-
-# reduce 149 omitted
-
-# reduce 150 omitted
-
-# reduce 151 omitted
-
-module_eval(<<'.,.,', 'mof.y', 522)
- def _reduce_152(val, _values, result)
- result = CIM::QualifierFlavors.new val[3]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mof.y', 527)
- def _reduce_153(val, _values, result)
- result = [ val[0] ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'mof.y', 529)
- def _reduce_154(val, _values, result)
- result = val[0] << val[2]
- result
- end
-.,.,
-
-# reduce 155 omitted
-
-# reduce 156 omitted
-
-# reduce 157 omitted
-
-# reduce 158 omitted
-
-# reduce 159 omitted
-
-module_eval(<<'.,.,', 'mof.y', 553)
- def _reduce_160(val, _values, result)
- raise "Instance property '#{val[1]} must have a value" unless @style == :wmi
- result
- end
-.,.,
-
-def _reduce_none(val, _values, result)
- val[0]
-end
-
- end # class Parser
-end # module MOF
-
-
diff --git a/test/racc/regress/namae b/test/racc/regress/namae
deleted file mode 100644
index 5a795e4579..0000000000
--- a/test/racc/regress/namae
+++ /dev/null
@@ -1,634 +0,0 @@
-#
-# DO NOT MODIFY!!!!
-# This file is automatically generated by Racc 1.5.0
-# from Racc grammar file "".
-#
-
-require 'racc/parser.rb'
-
-require 'singleton'
-require 'strscan'
-
-module Namae
- class Parser < Racc::Parser
-
-module_eval(<<'...end namae.y/module_eval...', 'namae.y', 135)
-
- include Singleton
-
- attr_reader :options, :input
-
- def initialize
- @input, @options = StringScanner.new(''), {
- :debug => false,
- :prefer_comma_as_separator => false,
- :comma => ',',
- :stops => ',;',
- :separator => /\s*(\band\b|\&|;)\s*/i,
- :title => /\s*\b(sir|lord|count(ess)?|(gen|adm|col|maj|capt|cmdr|lt|sgt|cpl|pvt|prof|dr|md|ph\.?d)\.?)(\s+|$)/i,
- :suffix => /\s*\b(JR|Jr|jr|SR|Sr|sr|[IVX]{2,})(\.|\b)/,
- :appellation => /\s*\b((mrs?|ms|fr|hr)\.?|miss|herr|frau)(\s+|$)/i
- }
- end
-
- def debug?
- options[:debug] || ENV['DEBUG']
- end
-
- def separator
- options[:separator]
- end
-
- def comma
- options[:comma]
- end
-
- def stops
- options[:stops]
- end
-
- def title
- options[:title]
- end
-
- def suffix
- options[:suffix]
- end
-
- def appellation
- options[:appellation]
- end
-
- def prefer_comma_as_separator?
- options[:prefer_comma_as_separator]
- end
-
- def parse(input)
- parse!(input)
- rescue => e
- warn e.message if debug?
- []
- end
-
- def parse!(string)
- input.string = normalize(string)
- reset
- do_parse
- end
-
- def normalize(string)
- string = string.strip
- string
- end
-
- def reset
- @commas, @words, @initials, @suffices, @yydebug = 0, 0, 0, 0, debug?
- self
- end
-
- private
-
- def stack
- @vstack || @racc_vstack || []
- end
-
- def last_token
- stack[-1]
- end
-
- def consume_separator
- return next_token if seen_separator?
- @commas, @words, @initials, @suffices = 0, 0, 0, 0
- [:AND, :AND]
- end
-
- def consume_comma
- @commas += 1
- [:COMMA, :COMMA]
- end
-
- def consume_word(type, word)
- @words += 1
-
- case type
- when :UWORD
- @initials += 1 if word =~ /^[[:upper:]]+\b/
- when :SUFFIX
- @suffices += 1
- end
-
- [type, word]
- end
-
- def seen_separator?
- !stack.empty? && last_token == :AND
- end
-
- def suffix?
- !@suffices.zero? || will_see_suffix?
- end
-
- def will_see_suffix?
- input.peek(8).to_s.strip.split(/\s+/)[0] =~ suffix
- end
-
- def will_see_initial?
- input.peek(6).to_s.strip.split(/\s+/)[0] =~ /^[[:upper:]]+\b/
- end
-
- def seen_full_name?
- prefer_comma_as_separator? && @words > 1 &&
- (@initials > 0 || !will_see_initial?) && !will_see_suffix?
- end
-
- def next_token
- case
- when input.nil?, input.eos?
- nil
- when input.scan(separator)
- consume_separator
- when input.scan(/\s*#{comma}\s*/)
- if @commas.zero? && !seen_full_name? || @commas == 1 && suffix?
- consume_comma
- else
- consume_separator
- end
- when input.scan(/\s+/)
- next_token
- when input.scan(title)
- consume_word(:TITLE, input.matched.strip)
- when input.scan(suffix)
- consume_word(:SUFFIX, input.matched.strip)
- when input.scan(appellation)
- [:APPELLATION, input.matched.strip]
- when input.scan(/((\\\w+)?\{[^\}]*\})*[[:upper:]][^\s#{stops}]*/)
- consume_word(:UWORD, input.matched)
- when input.scan(/((\\\w+)?\{[^\}]*\})*[[:lower:]][^\s#{stops}]*/)
- consume_word(:LWORD, input.matched)
- when input.scan(/(\\\w+)?\{[^\}]*\}[^\s#{stops}]*/)
- consume_word(:PWORD, input.matched)
- when input.scan(/('[^'\n]+')|("[^"\n]+")/)
- consume_word(:NICK, input.matched[1...-1])
- else
- raise ArgumentError,
- "Failed to parse name #{input.string.inspect}: unmatched data at offset #{input.pos}"
- end
- end
-
- def on_error(tid, value, stack)
- raise ArgumentError,
- "Failed to parse name: unexpected '#{value}' at #{stack.inspect}"
- end
-
-# -*- racc -*-
-...end namae.y/module_eval...
-##### State transition tables begin ###
-
-racc_action_table = [
- -39, 16, 32, 30, -40, 31, 33, -39, 17, -39,
- -39, -40, 67, -40, -40, 66, 53, 52, 54, -38,
- 59, -22, 39, -34, 45, 58, -38, 53, 52, 54,
- 53, 52, 54, 59, 39, 39, 62, 39, 53, 52,
- 54, 14, 12, 15, 68, 39, 7, 8, 14, 12,
- 15, 58, 39, 7, 8, 14, 22, 15, 24, 14,
- 22, 15, 24, 14, 22, 15, 30, 28, 31, 30,
- 28, 31, -19, -19, -19, 30, 42, 31, 30, 28,
- 31, -20, -20, -20, 30, 46, 31, 30, 28, 31,
- 30, 28, 31, -19, -19, -19, 53, 52, 54, 53,
- 52, 54, 39, 58, 59 ]
-
-racc_action_check = [
- 14, 1, 11, 43, 15, 43, 16, 14, 1, 14,
- 14, 15, 50, 15, 15, 49, 49, 49, 49, 12,
- 50, 12, 23, 49, 27, 37, 12, 32, 32, 32,
- 45, 45, 45, 38, 32, 40, 44, 45, 62, 62,
- 62, 0, 0, 0, 57, 62, 0, 0, 17, 17,
- 17, 60, 61, 17, 17, 9, 9, 9, 9, 20,
- 20, 20, 20, 5, 5, 5, 10, 10, 10, 21,
- 21, 21, 22, 22, 22, 24, 24, 24, 25, 25,
- 25, 28, 28, 28, 29, 29, 29, 35, 35, 35,
- 41, 41, 41, 42, 42, 42, 67, 67, 67, 73,
- 73, 73, 64, 70, 72 ]
-
-racc_action_pointer = [
- 38, 1, nil, nil, nil, 60, nil, nil, nil, 52,
- 63, 0, 19, nil, 0, 4, 6, 45, nil, nil,
- 56, 66, 69, 12, 72, 75, nil, 22, 78, 81,
- nil, nil, 24, nil, nil, 84, nil, 16, 23, nil,
- 25, 87, 90, 0, 34, 27, nil, nil, nil, 13,
- 10, nil, nil, nil, nil, nil, nil, 35, nil, nil,
- 42, 42, 35, nil, 92, nil, nil, 93, nil, nil,
- 94, nil, 94, 96, nil ]
-
-racc_action_default = [
- -1, -49, -2, -4, -5, -49, -8, -9, -10, -23,
- -49, -49, -19, -28, -30, -31, -49, -49, -6, -7,
- -49, -49, -38, -41, -49, -49, -29, -15, -22, -23,
- -30, -31, -36, 75, -3, -49, -15, -45, -42, -43,
- -41, -49, -22, -23, -14, -36, -21, -16, -24, -37,
- -26, -32, -38, -39, -40, -14, -11, -46, -47, -44,
- -45, -41, -36, -17, -49, -33, -35, -49, -48, -12,
- -45, -18, -25, -27, -13 ]
-
-racc_goto_table = [
- 3, 37, 26, 50, 56, 18, 2, 9, 47, 23,
- 1, 19, 20, 26, 73, 27, 50, 3, 60, 64,
- 23, 63, 26, 34, 9, nil, 36, 69, 21, 40,
- 44, 43, 25, 50, nil, 72, 26, 74, 71, 70,
- 55, nil, nil, 35, nil, nil, 61, 41, nil, 65,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 65 ]
-
-racc_goto_check = [
- 3, 8, 17, 16, 9, 3, 2, 7, 12, 3,
- 1, 4, 7, 17, 14, 10, 16, 3, 8, 15,
- 3, 12, 17, 2, 7, nil, 10, 9, 11, 10,
- 10, 7, 11, 16, nil, 16, 17, 9, 12, 8,
- 10, nil, nil, 11, nil, nil, 10, 11, nil, 3,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 3 ]
-
-racc_goto_pointer = [
- nil, 10, 6, 0, 6, nil, nil, 7, -22, -33,
- 5, 23, -24, nil, -53, -30, -29, -7, nil ]
-
-racc_goto_default = [
- nil, nil, nil, 51, 4, 5, 6, 29, nil, nil,
- 11, 10, nil, 48, 49, nil, 38, 13, 57 ]
-
-racc_reduce_table = [
- 0, 0, :racc_error,
- 0, 12, :_reduce_1,
- 1, 12, :_reduce_2,
- 3, 12, :_reduce_3,
- 1, 13, :_reduce_4,
- 1, 13, :_reduce_none,
- 2, 13, :_reduce_6,
- 2, 13, :_reduce_7,
- 1, 13, :_reduce_none,
- 1, 16, :_reduce_9,
- 1, 16, :_reduce_10,
- 4, 15, :_reduce_11,
- 5, 15, :_reduce_12,
- 6, 15, :_reduce_13,
- 3, 15, :_reduce_14,
- 2, 15, :_reduce_15,
- 3, 17, :_reduce_16,
- 4, 17, :_reduce_17,
- 5, 17, :_reduce_18,
- 1, 22, :_reduce_none,
- 2, 22, :_reduce_20,
- 3, 22, :_reduce_21,
- 1, 21, :_reduce_none,
- 1, 21, :_reduce_none,
- 1, 23, :_reduce_24,
- 3, 23, :_reduce_25,
- 1, 23, :_reduce_26,
- 3, 23, :_reduce_27,
- 1, 18, :_reduce_none,
- 2, 18, :_reduce_29,
- 1, 28, :_reduce_none,
- 1, 28, :_reduce_none,
- 1, 25, :_reduce_none,
- 2, 25, :_reduce_33,
- 0, 26, :_reduce_none,
- 1, 26, :_reduce_none,
- 0, 24, :_reduce_none,
- 1, 24, :_reduce_none,
- 1, 14, :_reduce_none,
- 1, 14, :_reduce_none,
- 1, 14, :_reduce_none,
- 0, 19, :_reduce_none,
- 1, 19, :_reduce_none,
- 1, 27, :_reduce_none,
- 2, 27, :_reduce_44,
- 0, 20, :_reduce_none,
- 1, 20, :_reduce_none,
- 1, 29, :_reduce_none,
- 2, 29, :_reduce_48 ]
-
-racc_reduce_n = 49
-
-racc_shift_n = 75
-
-racc_token_table = {
- false => 0,
- :error => 1,
- :COMMA => 2,
- :UWORD => 3,
- :LWORD => 4,
- :PWORD => 5,
- :NICK => 6,
- :AND => 7,
- :APPELLATION => 8,
- :TITLE => 9,
- :SUFFIX => 10 }
-
-racc_nt_base = 11
-
-racc_use_result_var = true
-
-Racc_arg = [
- racc_action_table,
- racc_action_check,
- racc_action_default,
- racc_action_pointer,
- racc_goto_table,
- racc_goto_check,
- racc_goto_default,
- racc_goto_pointer,
- racc_nt_base,
- racc_reduce_table,
- racc_token_table,
- racc_shift_n,
- racc_reduce_n,
- racc_use_result_var ]
-
-Racc_token_to_s_table = [
- "$end",
- "error",
- "COMMA",
- "UWORD",
- "LWORD",
- "PWORD",
- "NICK",
- "AND",
- "APPELLATION",
- "TITLE",
- "SUFFIX",
- "$start",
- "names",
- "name",
- "word",
- "display_order",
- "honorific",
- "sort_order",
- "u_words",
- "opt_suffices",
- "opt_titles",
- "last",
- "von",
- "first",
- "opt_words",
- "words",
- "opt_comma",
- "suffices",
- "u_word",
- "titles" ]
-
-Racc_debug_parser = false
-
-##### State transition tables end #####
-
-# reduce 0 omitted
-
-module_eval(<<'.,.,', 'namae.y', 39)
- def _reduce_1(val, _values, result)
- result = []
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'namae.y', 40)
- def _reduce_2(val, _values, result)
- result = [val[0]]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'namae.y', 41)
- def _reduce_3(val, _values, result)
- result = val[0] << val[2]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'namae.y', 43)
- def _reduce_4(val, _values, result)
- result = Name.new(:given => val[0])
- result
- end
-.,.,
-
-# reduce 5 omitted
-
-module_eval(<<'.,.,', 'namae.y', 45)
- def _reduce_6(val, _values, result)
- result = val[0].merge(:family => val[1])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'namae.y', 46)
- def _reduce_7(val, _values, result)
- result = val[1].merge(val[0])
- result
- end
-.,.,
-
-# reduce 8 omitted
-
-module_eval(<<'.,.,', 'namae.y', 49)
- def _reduce_9(val, _values, result)
- result = Name.new(:appellation => val[0])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'namae.y', 50)
- def _reduce_10(val, _values, result)
- result = Name.new(:title => val[0])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'namae.y', 54)
- def _reduce_11(val, _values, result)
- result = Name.new(:given => val[0], :family => val[1],
- :suffix => val[2], :title => val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'namae.y', 59)
- def _reduce_12(val, _values, result)
- result = Name.new(:given => val[0], :nick => val[1],
- :family => val[2], :suffix => val[3], :title => val[4])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'namae.y', 64)
- def _reduce_13(val, _values, result)
- result = Name.new(:given => val[0], :nick => val[1],
- :particle => val[2], :family => val[3],
- :suffix => val[4], :title => val[5])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'namae.y', 70)
- def _reduce_14(val, _values, result)
- result = Name.new(:given => val[0], :particle => val[1],
- :family => val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'namae.y', 75)
- def _reduce_15(val, _values, result)
- result = Name.new(:particle => val[0], :family => val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'namae.y', 80)
- def _reduce_16(val, _values, result)
- result = Name.new({ :family => val[0], :suffix => val[2][0],
- :given => val[2][1] }, !!val[2][0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'namae.y', 85)
- def _reduce_17(val, _values, result)
- result = Name.new({ :particle => val[0], :family => val[1],
- :suffix => val[3][0], :given => val[3][1] }, !!val[3][0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'namae.y', 90)
- def _reduce_18(val, _values, result)
- result = Name.new({ :particle => val[0,2].join(' '), :family => val[2],
- :suffix => val[4][0], :given => val[4][1] }, !!val[4][0])
-
- result
- end
-.,.,
-
-# reduce 19 omitted
-
-module_eval(<<'.,.,', 'namae.y', 96)
- def _reduce_20(val, _values, result)
- result = val.join(' ')
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'namae.y', 97)
- def _reduce_21(val, _values, result)
- result = val.join(' ')
- result
- end
-.,.,
-
-# reduce 22 omitted
-
-# reduce 23 omitted
-
-module_eval(<<'.,.,', 'namae.y', 101)
- def _reduce_24(val, _values, result)
- result = [nil,val[0]]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'namae.y', 102)
- def _reduce_25(val, _values, result)
- result = [val[2],val[0]]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'namae.y', 103)
- def _reduce_26(val, _values, result)
- result = [val[0],nil]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'namae.y', 104)
- def _reduce_27(val, _values, result)
- result = [val[0],val[2]]
- result
- end
-.,.,
-
-# reduce 28 omitted
-
-module_eval(<<'.,.,', 'namae.y', 107)
- def _reduce_29(val, _values, result)
- result = val.join(' ')
- result
- end
-.,.,
-
-# reduce 30 omitted
-
-# reduce 31 omitted
-
-# reduce 32 omitted
-
-module_eval(<<'.,.,', 'namae.y', 112)
- def _reduce_33(val, _values, result)
- result = val.join(' ')
- result
- end
-.,.,
-
-# reduce 34 omitted
-
-# reduce 35 omitted
-
-# reduce 36 omitted
-
-# reduce 37 omitted
-
-# reduce 38 omitted
-
-# reduce 39 omitted
-
-# reduce 40 omitted
-
-# reduce 41 omitted
-
-# reduce 42 omitted
-
-# reduce 43 omitted
-
-module_eval(<<'.,.,', 'namae.y', 122)
- def _reduce_44(val, _values, result)
- result = val.join(' ')
- result
- end
-.,.,
-
-# reduce 45 omitted
-
-# reduce 46 omitted
-
-# reduce 47 omitted
-
-module_eval(<<'.,.,', 'namae.y', 127)
- def _reduce_48(val, _values, result)
- result = val.join(' ')
- result
- end
-.,.,
-
-def _reduce_none(val, _values, result)
- val[0]
-end
-
- end # class Parser
-end # module Namae
diff --git a/test/racc/regress/nasl b/test/racc/regress/nasl
deleted file mode 100644
index 52a329d20a..0000000000
--- a/test/racc/regress/nasl
+++ /dev/null
@@ -1,2548 +0,0 @@
-#
-# DO NOT MODIFY!!!!
-# This file is automatically generated by Racc 1.5.2
-# from Racc grammar file "".
-#
-
-require 'racc/parser.rb'
-
-
-require 'nasl/parser/tree'
-
-require 'nasl/parser/argument'
-require 'nasl/parser/array'
-require 'nasl/parser/assigment'
-require 'nasl/parser/block'
-require 'nasl/parser/break'
-require 'nasl/parser/call'
-require 'nasl/parser/comment'
-require 'nasl/parser/continue'
-require 'nasl/parser/decrement'
-require 'nasl/parser/empty'
-require 'nasl/parser/export'
-require 'nasl/parser/expression'
-require 'nasl/parser/for'
-require 'nasl/parser/foreach'
-require 'nasl/parser/function'
-require 'nasl/parser/global'
-require 'nasl/parser/identifier'
-require 'nasl/parser/if'
-require 'nasl/parser/import'
-require 'nasl/parser/include'
-require 'nasl/parser/increment'
-require 'nasl/parser/integer'
-require 'nasl/parser/ip'
-require 'nasl/parser/key_value_pair'
-require 'nasl/parser/list'
-require 'nasl/parser/local'
-require 'nasl/parser/lvalue'
-require 'nasl/parser/parameter'
-require 'nasl/parser/reference'
-require 'nasl/parser/repeat'
-require 'nasl/parser/repetition'
-require 'nasl/parser/return'
-require 'nasl/parser/string'
-require 'nasl/parser/undefined'
-require 'nasl/parser/while'
-
-module Nasl
- class Grammar < Racc::Parser
-
-module_eval(<<'...end nasl.y/module_eval...', 'nasl.y', 582)
-
-def n(cls, *args)
- begin
- Nasl.const_get(cls).new(@tree, *args)
- rescue
- puts "An exception occurred during the creation of a #{cls} instance."
- puts
- puts "The arguments passed to the constructor were:"
- puts args
- puts
- puts @tok.last.context
- puts
- raise
- end
-end
-
-def c(*args)
- n(:Comment, *args)
- args[1]
-end
-
-def on_error(type, value, stack)
- raise ParseException, "The language's grammar does not permit #{value.name} to appear here", value.context
-end
-
-def next_token
- @tok = @tkz.get_token
-
- if @first && @tok.first == :COMMENT
- n(:Comment, @tok.last)
- @tok = @tkz.get_token
- end
- @first = false
-
- return @tok
-end
-
-def parse(env, code, path)
- @first = true
- @tree = Tree.new(env)
- @tkz = Tokenizer.new(code, path)
- @tree.concat(do_parse)
-end
-
-...end nasl.y/module_eval...
-##### State transition tables begin ###
-
-racc_action_table = [
- 144, 143, 161, 162, 163, 164, 165, 166, 157, 158,
- 159, 160, 153, 152, 151, 154, 155, 156, 145, 146,
- 147, 149, 150, 82, 54, 111, 148, 81, 218, 83,
- 55, 51, 50, 56, 54, 54, 80, 11, 78, 65,
- 55, 55, 53, 63, 54, 54, 66, 95, 102, 103,
- 55, 55, 53, 53, 64, 54, 218, 269, 67, 94,
- 96, 55, 53, 53, 97, 98, 99, 100, 101, 102,
- 103, 104, 82, 53, 267, 217, 81, 130, 83, 131,
- 51, 50, 130, 54, 131, 80, 130, 54, 131, 55,
- 51, 50, 68, 55, 54, 72, 95, 147, 149, 150,
- 55, 53, 73, 148, 54, 53, 102, 103, 74, 96,
- 55, 109, 53, 97, 98, 99, 100, 101, 102, 103,
- 104, 82, 53, 112, 114, 81, 54, 83, 133, 51,
- 50, 134, 55, 136, 80, 137, 54, 138, 141, 51,
- 50, 167, 55, 54, 53, 95, 147, 149, 150, 55,
- 10, 11, 148, 54, 53, 172, 37, 37, 96, 55,
- 185, 53, 97, 98, 99, 100, 101, 102, 103, 104,
- 82, 53, 192, 195, 81, 225, 83, 226, 51, 50,
- 148, 54, 148, 80, 179, 148, 253, 55, 254, 255,
- 54, 54, 54, 256, 95, 257, 55, 55, 55, 53,
- 97, 98, 99, 100, 101, 102, 103, 96, 53, 53,
- 53, 97, 98, 99, 100, 101, 102, 103, 104, 82,
- 54, 258, 259, 81, 260, 83, 55, 51, 50, 262,
- 54, 266, 80, 268, 270, 43, 55, 273, 53, 54,
- 274, 54, 275, 95, 148, 55, 148, 55, 53, 97,
- 98, 99, 100, 101, 102, 103, 96, 53, 148, 53,
- 97, 98, 99, 100, 101, 102, 103, 104, 82, 148,
- 276, 43, 81, 300, 83, 301, 51, 50, 306, nil,
- nil, 80, 154, 155, 156, 145, 146, 147, 149, 150,
- 54, nil, 95, 148, nil, nil, 55, nil, 145, 146,
- 147, 149, 150, nil, nil, 96, 148, nil, 53, 97,
- 98, 99, 100, 101, 102, 103, 104, 82, nil, nil,
- nil, 81, nil, 83, nil, 51, 50, nil, nil, nil,
- 80, nil, 145, 146, 147, 149, 150, nil, nil, 54,
- 148, 95, nil, nil, nil, 55, nil, nil, 145, 146,
- 147, 149, 150, 94, 96, 184, 148, 53, 97, 98,
- 99, 100, 101, 102, 103, 104, 82, nil, nil, nil,
- 81, nil, 83, nil, 51, 50, nil, nil, nil, 80,
- 97, 98, 99, 100, 101, nil, nil, nil, 54, nil,
- 95, nil, nil, nil, 55, 97, 98, 99, 100, 101,
- nil, nil, nil, 96, nil, nil, 53, 97, 98, 99,
- 100, 101, 102, 103, 104, 82, nil, nil, nil, 81,
- nil, 83, nil, 51, 50, nil, nil, nil, 80, 97,
- 98, 99, 100, 101, nil, nil, nil, 54, nil, 95,
- nil, nil, nil, 55, nil, nil, nil, nil, nil, nil,
- nil, nil, 96, nil, nil, 53, 97, 98, 99, 100,
- 101, 102, 103, 104, 82, nil, nil, nil, 81, nil,
- 83, nil, 51, 50, nil, nil, nil, 80, nil, nil,
- nil, nil, nil, nil, nil, nil, 54, nil, 95, nil,
- nil, nil, 55, nil, nil, nil, nil, nil, nil, nil,
- 94, 96, nil, nil, 53, 97, 98, 99, 100, 101,
- 102, 103, 104, 82, nil, nil, nil, 81, nil, 83,
- nil, 51, 50, nil, nil, nil, 80, nil, nil, nil,
- nil, nil, nil, nil, nil, 54, nil, 95, nil, nil,
- nil, 55, nil, nil, nil, nil, nil, nil, nil, nil,
- 96, nil, nil, 53, 97, 98, 99, 100, 101, 102,
- 103, 104, 82, nil, nil, nil, 81, nil, 83, nil,
- 51, 50, nil, nil, nil, 80, nil, nil, nil, nil,
- nil, nil, nil, nil, 54, nil, 95, nil, nil, nil,
- 55, nil, nil, nil, nil, nil, nil, nil, nil, 96,
- nil, nil, 53, 97, 98, 99, 100, 101, 102, 103,
- 104, 82, nil, nil, nil, 81, nil, 83, nil, 51,
- 50, nil, nil, nil, 80, nil, nil, nil, nil, nil,
- nil, nil, nil, 54, nil, 95, nil, nil, nil, 55,
- nil, nil, nil, nil, nil, nil, nil, nil, 96, nil,
- nil, 53, 97, 98, 99, 100, 101, 102, 103, 104,
- 82, nil, nil, nil, 81, nil, 83, nil, 51, 50,
- nil, nil, nil, 80, nil, nil, nil, nil, nil, nil,
- nil, nil, 54, nil, 95, nil, nil, nil, 55, nil,
- nil, nil, nil, nil, nil, nil, nil, 96, nil, nil,
- 53, 97, 98, 99, 100, 101, 102, 103, 104, 82,
- nil, nil, nil, 81, nil, 83, nil, 51, 50, nil,
- nil, nil, 80, nil, nil, nil, nil, nil, nil, nil,
- nil, 54, nil, 95, nil, nil, nil, 55, nil, nil,
- nil, nil, nil, nil, nil, nil, 96, nil, nil, 53,
- 97, 98, 99, 100, 101, 102, 103, 104, 82, nil,
- nil, nil, 81, nil, 83, nil, 51, 50, nil, nil,
- nil, 80, nil, nil, nil, nil, nil, nil, nil, nil,
- 54, nil, 95, nil, nil, nil, 55, nil, nil, nil,
- nil, nil, nil, nil, nil, 96, nil, nil, 53, 97,
- 98, 99, 100, 101, 102, 103, 104, 82, nil, nil,
- nil, 81, nil, 83, nil, 51, 50, nil, nil, nil,
- 80, nil, nil, nil, nil, nil, nil, nil, nil, 54,
- nil, 95, nil, nil, nil, 55, nil, nil, nil, nil,
- nil, nil, nil, nil, 96, nil, nil, 53, 97, 98,
- 99, 100, 101, 102, 103, 104, 82, nil, nil, nil,
- 81, nil, 83, nil, 51, 50, nil, nil, nil, 80,
- nil, nil, nil, nil, nil, nil, nil, nil, 54, nil,
- 95, nil, nil, nil, 55, nil, nil, nil, nil, nil,
- nil, nil, nil, 96, nil, nil, 53, 97, 98, 99,
- 100, 101, 102, 103, 104, 82, nil, nil, nil, 81,
- nil, 83, nil, 51, 50, nil, nil, nil, 80, 208,
- nil, nil, nil, nil, nil, nil, nil, 54, nil, 95,
- nil, nil, nil, 55, nil, nil, nil, nil, nil, nil,
- nil, 94, 96, nil, nil, 53, 97, 98, 99, 100,
- 101, 102, 103, 104, 82, nil, nil, nil, 81, nil,
- 83, nil, 51, 50, nil, nil, nil, 80, nil, nil,
- nil, nil, nil, nil, nil, nil, 54, nil, 95, nil,
- nil, nil, 55, nil, nil, nil, nil, nil, nil, nil,
- nil, 96, nil, nil, 53, 97, 98, 99, 100, 101,
- 102, 103, 104, 82, nil, nil, nil, 81, nil, 83,
- nil, 51, 50, nil, nil, nil, 80, nil, nil, nil,
- nil, nil, nil, nil, nil, 54, nil, 95, nil, nil,
- nil, 55, nil, nil, nil, nil, nil, nil, nil, 94,
- 96, nil, nil, 53, 97, 98, 99, 100, 101, 102,
- 103, 104, 82, nil, nil, nil, 81, nil, 83, nil,
- 51, 50, nil, nil, nil, 80, nil, nil, nil, nil,
- nil, nil, nil, nil, 54, nil, 95, nil, nil, nil,
- 55, nil, nil, nil, nil, nil, nil, nil, nil, 96,
- nil, nil, 53, 97, 98, 99, 100, 101, 102, 103,
- 104, 82, nil, nil, nil, 81, nil, 83, nil, 51,
- 50, nil, nil, nil, 80, nil, nil, nil, nil, nil,
- nil, nil, nil, 54, nil, 95, nil, nil, nil, 55,
- nil, nil, nil, nil, nil, nil, nil, nil, 96, nil,
- nil, 53, 97, 98, 99, 100, 101, 102, 103, 104,
- 82, nil, nil, nil, 81, nil, 83, nil, 51, 50,
- nil, nil, nil, 80, nil, nil, nil, nil, nil, nil,
- nil, nil, 54, nil, 95, nil, nil, nil, 55, nil,
- nil, nil, nil, nil, nil, nil, nil, 96, nil, nil,
- 53, 97, 98, 99, 100, 101, 102, 103, 104, 82,
- nil, nil, nil, 81, nil, 83, nil, 51, 50, nil,
- nil, nil, 80, nil, nil, nil, nil, nil, nil, nil,
- nil, 54, nil, 95, nil, nil, nil, 55, nil, nil,
- nil, nil, nil, nil, nil, nil, 96, nil, nil, 53,
- 97, 98, 99, 100, 101, 102, 103, 104, 82, nil,
- nil, nil, 81, nil, 83, nil, 51, 50, nil, nil,
- nil, 80, nil, nil, nil, nil, nil, nil, nil, nil,
- 54, nil, 95, nil, nil, nil, 55, nil, nil, nil,
- nil, nil, nil, nil, nil, 96, nil, nil, 53, 97,
- 98, 99, 100, 101, 102, 103, 104, 82, nil, nil,
- nil, 81, nil, 83, nil, 51, 50, nil, nil, nil,
- 80, nil, nil, nil, nil, nil, nil, nil, nil, 54,
- nil, 95, nil, nil, nil, 55, nil, nil, nil, nil,
- nil, nil, nil, nil, 96, nil, nil, 53, 97, 98,
- 99, 100, 101, 102, 103, 104, 82, nil, nil, nil,
- 81, nil, 83, nil, 51, 50, nil, nil, nil, 80,
- nil, nil, nil, nil, nil, nil, nil, nil, 54, nil,
- 95, nil, nil, nil, 55, nil, nil, nil, nil, nil,
- nil, nil, nil, 96, nil, nil, 53, 97, 98, 99,
- 100, 101, 102, 103, 104, 82, nil, nil, nil, 81,
- nil, 83, nil, 51, 50, nil, nil, nil, 80, nil,
- nil, nil, nil, nil, nil, nil, nil, 54, nil, 95,
- nil, nil, nil, 55, nil, nil, nil, nil, nil, nil,
- nil, nil, 96, nil, nil, 53, 97, 98, 99, 100,
- 101, 102, 103, 104, 82, nil, nil, nil, 81, nil,
- 83, nil, 51, 50, nil, nil, nil, 80, nil, nil,
- nil, nil, nil, nil, nil, nil, 54, nil, 95, nil,
- nil, nil, 55, nil, nil, nil, nil, nil, nil, nil,
- nil, 96, nil, nil, 53, 97, 98, 99, 100, 101,
- 102, 103, 104, 82, nil, nil, nil, 81, nil, 83,
- nil, 51, 50, nil, nil, nil, 80, nil, nil, nil,
- nil, nil, nil, nil, nil, 54, nil, 95, nil, nil,
- nil, 55, nil, nil, nil, nil, nil, nil, nil, nil,
- 96, nil, nil, 53, 97, 98, 99, 100, 101, 102,
- 103, 104, 82, nil, nil, nil, 81, nil, 83, nil,
- 51, 50, nil, nil, nil, 80, nil, nil, nil, nil,
- nil, nil, nil, nil, 54, nil, 95, nil, nil, nil,
- 55, nil, nil, nil, nil, nil, nil, nil, nil, 96,
- nil, nil, 53, 97, 98, 99, 100, 101, 102, 103,
- 104, 82, nil, nil, nil, 81, nil, 83, nil, 51,
- 50, nil, nil, nil, 80, nil, nil, nil, nil, nil,
- nil, nil, nil, 54, nil, 95, nil, nil, nil, 55,
- nil, nil, nil, nil, nil, nil, nil, nil, 96, nil,
- nil, 53, 97, 98, 99, 100, 101, 102, 103, 104,
- 82, nil, nil, nil, 81, nil, 83, nil, 51, 50,
- nil, nil, nil, 80, nil, nil, nil, nil, nil, nil,
- nil, nil, 54, nil, 95, nil, nil, nil, 55, nil,
- nil, nil, nil, nil, nil, nil, nil, 96, nil, nil,
- 53, 97, 98, 99, 100, 101, 102, 103, 104, 82,
- nil, nil, nil, 81, nil, 83, nil, 51, 50, nil,
- nil, nil, 80, nil, nil, nil, nil, nil, nil, nil,
- nil, 54, nil, 95, nil, nil, nil, 55, nil, nil,
- nil, nil, nil, nil, nil, nil, 96, nil, nil, 53,
- 97, 98, 99, 100, 101, 102, 103, 104, 82, nil,
- nil, nil, 81, nil, 83, nil, 51, 50, nil, nil,
- nil, 80, nil, nil, nil, nil, nil, nil, nil, nil,
- 54, nil, 95, nil, nil, nil, 55, nil, nil, nil,
- nil, nil, nil, nil, nil, 96, nil, nil, 53, 97,
- 98, 99, 100, 101, 102, 103, 104, 82, nil, nil,
- nil, 81, nil, 83, nil, 51, 50, nil, nil, nil,
- 80, nil, nil, nil, nil, nil, nil, nil, nil, 54,
- nil, 95, nil, nil, nil, 55, nil, nil, nil, nil,
- nil, nil, nil, nil, 96, nil, nil, 53, 97, 98,
- 99, 100, 101, 102, 103, 104, 82, nil, nil, nil,
- 81, nil, 83, nil, 51, 50, nil, nil, nil, 80,
- nil, nil, nil, nil, nil, nil, nil, nil, 54, nil,
- 95, nil, nil, nil, 55, nil, nil, nil, nil, nil,
- nil, nil, nil, 96, nil, nil, 53, 97, 98, 99,
- 100, 101, 102, 103, 104, 82, nil, nil, nil, 81,
- nil, 83, nil, 51, 50, nil, nil, nil, 80, nil,
- nil, nil, nil, nil, nil, nil, nil, 54, nil, 95,
- nil, nil, nil, 55, nil, nil, nil, nil, nil, nil,
- nil, nil, 96, nil, nil, 53, 97, 98, 99, 100,
- 101, 102, 103, 104, 82, nil, nil, nil, 81, nil,
- 83, nil, 51, 50, nil, nil, nil, 80, nil, nil,
- nil, nil, nil, nil, nil, nil, 54, nil, 95, nil,
- nil, nil, 55, nil, nil, nil, nil, nil, nil, nil,
- nil, 96, nil, nil, 53, 97, 98, 99, 100, 101,
- 102, 103, 104, 82, nil, nil, nil, 81, nil, 83,
- nil, 51, 50, nil, nil, nil, 80, nil, nil, nil,
- nil, nil, nil, nil, nil, 54, nil, 95, nil, nil,
- nil, 55, nil, nil, nil, nil, nil, nil, nil, nil,
- 96, nil, nil, 53, 97, 98, 99, 100, 101, 102,
- 103, 104, 82, nil, nil, nil, 81, nil, 83, nil,
- 51, 50, nil, nil, nil, 80, nil, nil, nil, nil,
- nil, nil, nil, nil, 54, nil, 95, nil, nil, nil,
- 55, nil, nil, nil, nil, nil, nil, nil, nil, 96,
- nil, nil, 53, 97, 98, 99, 100, 101, 102, 103,
- 104, 82, nil, nil, nil, 81, nil, 83, nil, 51,
- 50, nil, nil, nil, 80, nil, nil, nil, nil, nil,
- nil, nil, nil, 54, nil, 95, nil, nil, nil, 55,
- nil, nil, nil, nil, nil, nil, nil, nil, 96, nil,
- nil, 53, 97, 98, 99, 100, 101, 102, 103, 104,
- 82, nil, nil, nil, 81, nil, 83, nil, 51, 50,
- nil, nil, nil, 80, nil, nil, nil, nil, nil, nil,
- nil, nil, 54, nil, 95, nil, nil, nil, 55, nil,
- nil, nil, nil, nil, nil, nil, nil, 96, nil, nil,
- 53, 97, 98, 99, 100, 101, 102, 103, 104, 82,
- nil, nil, nil, 81, nil, 83, nil, 51, 50, nil,
- nil, nil, 80, nil, nil, nil, nil, nil, nil, nil,
- nil, 54, nil, 95, nil, nil, nil, 55, nil, nil,
- nil, nil, nil, nil, nil, nil, 96, nil, nil, 53,
- 97, 98, 99, 100, 101, 102, 103, 104, 82, nil,
- nil, nil, 81, nil, 83, nil, 51, 50, nil, nil,
- nil, 80, nil, nil, nil, nil, nil, nil, nil, nil,
- 54, nil, 95, nil, nil, nil, 55, nil, nil, nil,
- nil, nil, nil, nil, nil, 96, nil, nil, 53, 97,
- 98, 99, 100, 101, 102, 103, 104, 82, nil, nil,
- nil, 81, nil, 83, nil, 51, 50, nil, nil, nil,
- 80, nil, nil, nil, nil, nil, nil, nil, nil, 54,
- nil, 95, nil, nil, nil, 55, nil, nil, nil, nil,
- nil, nil, nil, nil, 96, nil, nil, 53, 97, 98,
- 99, 100, 101, 102, 103, 104, 82, nil, nil, nil,
- 81, nil, 83, nil, 51, 50, nil, nil, nil, 80,
- nil, nil, nil, nil, nil, nil, nil, nil, 54, nil,
- 95, nil, nil, nil, 55, nil, nil, nil, nil, nil,
- nil, nil, 94, 96, nil, nil, 53, 97, 98, 99,
- 100, 101, 102, 103, 104, 82, nil, nil, nil, 81,
- nil, 83, nil, 51, 50, nil, nil, nil, 80, nil,
- nil, nil, nil, nil, nil, nil, nil, 54, nil, 95,
- nil, nil, nil, 55, nil, nil, nil, nil, nil, nil,
- nil, 94, 96, nil, nil, 53, 97, 98, 99, 100,
- 101, 102, 103, 104, 82, nil, nil, nil, 81, nil,
- 83, nil, 51, 50, nil, nil, nil, 80, nil, nil,
- nil, nil, nil, nil, nil, nil, 54, nil, 95, nil,
- nil, nil, 55, nil, nil, nil, nil, nil, nil, nil,
- 94, 96, nil, nil, 53, 97, 98, 99, 100, 101,
- 102, 103, 104, 82, nil, nil, nil, 81, nil, 83,
- nil, 51, 50, nil, nil, nil, 80, nil, nil, nil,
- nil, nil, nil, nil, nil, 54, nil, 95, nil, nil,
- nil, 55, nil, nil, nil, nil, nil, nil, nil, 94,
- 96, nil, nil, 53, 97, 98, 99, 100, 101, 102,
- 103, 104, 82, nil, nil, nil, 81, nil, 83, nil,
- 51, 50, nil, nil, nil, 80, nil, nil, nil, nil,
- nil, nil, nil, nil, 54, nil, 95, nil, nil, nil,
- 55, nil, nil, nil, nil, nil, nil, nil, nil, 96,
- nil, nil, 53, 97, 98, 99, 100, 101, 102, 103,
- 104, 82, nil, nil, nil, 81, nil, 83, nil, 51,
- 50, nil, nil, nil, 80, nil, nil, nil, nil, nil,
- nil, nil, nil, 54, nil, 95, nil, nil, nil, 55,
- nil, nil, nil, nil, nil, nil, nil, nil, 96, nil,
- nil, 53, 97, 98, 99, 100, 101, 102, 103, 104,
- 82, nil, nil, nil, 81, nil, 83, nil, 51, 50,
- nil, nil, nil, 80, nil, nil, nil, nil, nil, nil,
- nil, nil, 54, nil, 95, nil, nil, nil, 55, nil,
- nil, nil, nil, nil, nil, nil, 94, 96, nil, nil,
- 53, 97, 98, 99, 100, 101, 102, 103, 104, 82,
- nil, nil, nil, 81, nil, 83, nil, 51, 50, nil,
- nil, nil, 80, nil, nil, nil, nil, nil, nil, nil,
- nil, 54, nil, 95, nil, nil, nil, 55, nil, nil,
- nil, nil, nil, nil, nil, 94, 96, nil, nil, 53,
- 97, 98, 99, 100, 101, 102, 103, 104, 115, 116,
- 117, 118, 119, 120, 123, 122, 121, 115, 116, 117,
- 118, 119, 120, 123, 122, 121, 153, 152, 151, 154,
- 155, 156, 145, 146, 147, 149, 150, nil, nil, nil,
- 148, nil, nil, nil, 126, 125, nil, nil, nil, 124,
- nil, nil, nil, 126, 125, nil, nil, nil, 124, 144,
- 143, 161, 162, 163, 164, 165, 166, 157, 158, 159,
- 160, 153, 152, 151, 154, 155, 156, 145, 146, 147,
- 149, 150, nil, nil, nil, 148, nil, nil, nil, nil,
- nil, nil, nil, 142, 144, 143, 161, 162, 163, 164,
- 165, 166, 157, 158, 159, 160, 153, 152, 151, 154,
- 155, 156, 145, 146, 147, 149, 150, nil, nil, nil,
- 148, nil, nil, nil, nil, nil, nil, nil, 221, 144,
- 143, 161, 162, 163, 164, 165, 166, 157, 158, 159,
- 160, 153, 152, 151, 154, 155, 156, 145, 146, 147,
- 149, 150, nil, nil, nil, 148, nil, nil, nil, nil,
- nil, nil, nil, 289, 144, 143, 161, 162, 163, 164,
- 165, 166, 157, 158, 159, 160, 153, 152, 151, 154,
- 155, 156, 145, 146, 147, 149, 150, nil, nil, nil,
- 148, nil, nil, nil, nil, nil, nil, nil, 297, 144,
- 143, 161, 162, 163, 164, 165, 166, 157, 158, 159,
- 160, 153, 152, 151, 154, 155, 156, 145, 146, 147,
- 149, 150, nil, nil, nil, 148, nil, nil, nil, nil,
- nil, nil, 251, 144, 143, 161, 162, 163, 164, 165,
- 166, 157, 158, 159, 160, 153, 152, 151, 154, 155,
- 156, 145, 146, 147, 149, 150, nil, nil, nil, 148,
- nil, nil, nil, nil, nil, nil, 263, 144, 143, 161,
- 162, 163, 164, 165, 166, 157, 158, 159, 160, 153,
- 152, 151, 154, 155, 156, 145, 146, 147, 149, 150,
- nil, nil, nil, 148, nil, nil, nil, nil, nil, nil,
- 265, 144, 143, 161, 162, 163, 164, 165, 166, 157,
- 158, 159, 160, 153, 152, 151, 154, 155, 156, 145,
- 146, 147, 149, 150, nil, nil, nil, 148, nil, nil,
- nil, nil, nil, nil, 286, 144, 143, 161, 162, 163,
- 164, 165, 166, 157, 158, 159, 160, 153, 152, 151,
- 154, 155, 156, 145, 146, 147, 149, 150, nil, nil,
- nil, 148, 51, 50, 4, 10, 11, nil, 299, 36,
- 32, 34, 37, 39, 40, 41, 54, 42, 43, nil,
- 44, 45, 55, 46, nil, 47, nil, 48, 51, 50,
- 4, 10, 11, nil, 53, 36, 32, 34, 37, 39,
- 40, 41, 54, 42, 43, nil, 44, 45, 55, 46,
- nil, 47, nil, 48, 51, 50, 105, nil, nil, nil,
- 53, 36, 32, 34, 37, 39, 40, 41, 54, 42,
- 43, 107, 44, 45, 55, 46, nil, 47, nil, 48,
- 51, 50, 105, nil, nil, nil, 53, 36, 32, 34,
- 37, 39, 40, 41, 54, 42, 43, nil, 44, 45,
- 55, 46, nil, 47, nil, 48, 51, 50, 105, nil,
- nil, nil, 53, 36, 32, 34, 37, 39, 40, 41,
- 54, 42, 43, nil, 44, 45, 55, 46, nil, 47,
- nil, 48, 51, 50, 105, nil, nil, nil, 53, 36,
- 32, 34, 37, 39, 40, 41, 54, 42, 43, nil,
- 44, 45, 55, 46, nil, 47, nil, 48, 51, 50,
- 105, nil, nil, nil, 53, 36, 32, 34, 37, 39,
- 40, 41, 54, 42, 43, nil, 44, 45, 55, 46,
- nil, 47, nil, 48, 51, 50, 105, nil, nil, nil,
- 53, 36, 32, 34, 37, 39, 40, 41, 54, 42,
- 43, nil, 44, 45, 55, 46, nil, 47, nil, 48,
- 51, 50, 105, nil, nil, nil, 53, 36, 32, 34,
- 37, 39, 40, 41, 54, 42, 43, nil, 44, 45,
- 55, 46, nil, 47, nil, 48, 51, 50, 105, nil,
- nil, nil, 53, 36, 32, 34, 37, 39, 40, 41,
- 54, 42, 43, nil, 44, 45, 55, 46, nil, 47,
- nil, 48, 51, 50, 105, nil, nil, nil, 53, 36,
- 32, 34, 37, 39, 40, 41, 54, 42, 43, nil,
- 44, 45, 55, 46, nil, 47, nil, 48, nil, nil,
- nil, nil, nil, nil, 53, 144, 143, 161, 162, 163,
- 164, 165, 166, 157, 158, 159, 160, 153, 152, 151,
- 154, 155, 156, 145, 146, 147, 149, 150, nil, nil,
- nil, 148, 144, 143, 161, 162, 163, 164, 165, 166,
- 157, 158, 159, 160, 153, 152, 151, 154, 155, 156,
- 145, 146, 147, 149, 150, nil, nil, nil, 148, 144,
- 143, 161, 162, 163, 164, 165, 166, 157, 158, 159,
- 160, 153, 152, 151, 154, 155, 156, 145, 146, 147,
- 149, 150, nil, nil, nil, 148, 144, 143, 161, 162,
- 163, 164, 165, 166, 157, 158, 159, 160, 153, 152,
- 151, 154, 155, 156, 145, 146, 147, 149, 150, nil,
- nil, nil, 148, 144, 143, 161, 162, 163, 164, 165,
- 166, 157, 158, 159, 160, 153, 152, 151, 154, 155,
- 156, 145, 146, 147, 149, 150, nil, nil, nil, 148,
- 144, 143, 161, 162, 163, 164, 165, 166, 157, 158,
- 159, 160, 153, 152, 151, 154, 155, 156, 145, 146,
- 147, 149, 150, nil, nil, nil, 148, 144, 143, 161,
- 162, 163, 164, 165, 166, 157, 158, 159, 160, 153,
- 152, 151, 154, 155, 156, 145, 146, 147, 149, 150,
- nil, nil, nil, 148, 144, 143, 161, 162, 163, 164,
- 165, 166, 157, 158, 159, 160, 153, 152, 151, 154,
- 155, 156, 145, 146, 147, 149, 150, nil, nil, nil,
- 148, 144, 143, 161, 162, 163, 164, 165, 166, 157,
- 158, 159, 160, 153, 152, 151, 154, 155, 156, 145,
- 146, 147, 149, 150, nil, nil, nil, 148, 144, 143,
- 161, 162, 163, 164, 165, 166, 157, 158, 159, 160,
- 153, 152, 151, 154, 155, 156, 145, 146, 147, 149,
- 150, nil, nil, nil, 148, 144, 143, 161, 162, 163,
- 164, 165, 166, 157, 158, 159, 160, 153, 152, 151,
- 154, 155, 156, 145, 146, 147, 149, 150, nil, nil,
- nil, 148, 144, 143, 161, 162, 163, 164, 165, 166,
- 157, 158, 159, 160, 153, 152, 151, 154, 155, 156,
- 145, 146, 147, 149, 150, nil, nil, nil, 148, 144,
- 143, 161, 162, 163, 164, 165, 166, 157, 158, 159,
- 160, 153, 152, 151, 154, 155, 156, 145, 146, 147,
- 149, 150, nil, nil, nil, 148, 144, 143, 161, 162,
- 163, 164, 165, 166, 157, 158, 159, 160, 153, 152,
- 151, 154, 155, 156, 145, 146, 147, 149, 150, nil,
- nil, nil, 148, 144, 143, 161, 162, 163, 164, 165,
- 166, 157, 158, 159, 160, 153, 152, 151, 154, 155,
- 156, 145, 146, 147, 149, 150, nil, nil, nil, 148,
- 144, 143, 161, 162, 163, 164, 165, 166, 157, 158,
- 159, 160, 153, 152, 151, 154, 155, 156, 145, 146,
- 147, 149, 150, nil, nil, nil, 148, 143, 161, 162,
- 163, 164, 165, 166, 157, 158, 159, 160, 153, 152,
- 151, 154, 155, 156, 145, 146, 147, 149, 150, nil,
- nil, nil, 148, 161, 162, 163, 164, 165, 166, 157,
- 158, 159, 160, 153, 152, 151, 154, 155, 156, 145,
- 146, 147, 149, 150, nil, nil, nil, 148, 153, 152,
- 151, 154, 155, 156, 145, 146, 147, 149, 150, nil,
- nil, nil, 148, 153, 152, 151, 154, 155, 156, 145,
- 146, 147, 149, 150, nil, nil, nil, 148, 153, 152,
- 151, 154, 155, 156, 145, 146, 147, 149, 150, nil,
- nil, nil, 148, 153, 152, 151, 154, 155, 156, 145,
- 146, 147, 149, 150, nil, nil, nil, 148, 153, 152,
- 151, 154, 155, 156, 145, 146, 147, 149, 150, nil,
- nil, nil, 148, 153, 152, 151, 154, 155, 156, 145,
- 146, 147, 149, 150, nil, nil, nil, 148, 153, 152,
- 151, 154, 155, 156, 145, 146, 147, 149, 150, nil,
- nil, nil, 148, 153, 152, 151, 154, 155, 156, 145,
- 146, 147, 149, 150, nil, nil, nil, 148, 153, 152,
- 151, 154, 155, 156, 145, 146, 147, 149, 150, nil,
- nil, nil, 148, 152, 151, 154, 155, 156, 145, 146,
- 147, 149, 150, nil, nil, nil, 148, 151, 154, 155,
- 156, 145, 146, 147, 149, 150, nil, nil, nil, 148 ]
-
-racc_action_check = [
- 213, 213, 213, 213, 213, 213, 213, 213, 213, 213,
- 213, 213, 213, 213, 213, 213, 213, 213, 213, 213,
- 213, 213, 213, 42, 11, 45, 213, 42, 273, 42,
- 11, 42, 42, 1, 45, 37, 42, 10, 42, 33,
- 45, 37, 11, 31, 41, 42, 33, 42, 73, 73,
- 41, 42, 45, 37, 32, 273, 134, 213, 34, 42,
- 42, 273, 41, 42, 42, 42, 42, 42, 42, 42,
- 42, 42, 66, 273, 210, 134, 66, 210, 66, 210,
- 66, 66, 52, 134, 52, 66, 132, 50, 132, 134,
- 109, 109, 35, 50, 66, 38, 66, 229, 229, 229,
- 66, 134, 39, 229, 109, 50, 74, 74, 40, 66,
- 109, 44, 66, 66, 66, 66, 66, 66, 66, 66,
- 66, 80, 109, 46, 48, 80, 51, 80, 56, 80,
- 80, 62, 51, 69, 80, 70, 94, 71, 75, 297,
- 297, 77, 94, 80, 51, 80, 230, 230, 230, 80,
- 4, 4, 230, 297, 94, 90, 105, 4, 80, 297,
- 106, 80, 80, 80, 80, 80, 80, 80, 80, 80,
- 81, 297, 110, 113, 81, 139, 81, 140, 81, 81,
- 169, 95, 170, 81, 95, 171, 174, 95, 175, 176,
- 111, 131, 81, 177, 81, 178, 111, 131, 81, 95,
- 95, 95, 95, 95, 95, 95, 95, 81, 111, 131,
- 81, 81, 81, 81, 81, 81, 81, 81, 81, 82,
- 138, 182, 183, 82, 187, 82, 138, 82, 82, 193,
- 256, 207, 82, 212, 216, 217, 256, 220, 138, 218,
- 225, 82, 226, 82, 231, 218, 232, 82, 256, 256,
- 256, 256, 256, 256, 256, 256, 82, 218, 233, 82,
- 82, 82, 82, 82, 82, 82, 82, 82, 83, 234,
- 252, 270, 83, 288, 83, 296, 83, 83, 302, nil,
- nil, 83, 235, 235, 235, 235, 235, 235, 235, 235,
- 83, nil, 83, 235, nil, nil, 83, nil, 238, 238,
- 238, 238, 238, nil, nil, 83, 238, nil, 83, 83,
- 83, 83, 83, 83, 83, 83, 83, 96, nil, nil,
- nil, 96, nil, 96, nil, 96, 96, nil, nil, nil,
- 96, nil, 239, 239, 239, 239, 239, nil, nil, 96,
- 239, 96, nil, nil, nil, 96, nil, nil, 240, 240,
- 240, 240, 240, 96, 96, 96, 240, 96, 96, 96,
- 96, 96, 96, 96, 96, 96, 112, nil, nil, nil,
- 112, nil, 112, nil, 112, 112, nil, nil, nil, 112,
- 172, 172, 172, 172, 172, nil, nil, nil, 112, nil,
- 112, nil, nil, nil, 112, 276, 276, 276, 276, 276,
- nil, nil, nil, 112, nil, nil, 112, 112, 112, 112,
- 112, 112, 112, 112, 112, 114, nil, nil, nil, 114,
- nil, 114, nil, 114, 114, nil, nil, nil, 114, 301,
- 301, 301, 301, 301, nil, nil, nil, 114, nil, 114,
- nil, nil, nil, 114, nil, nil, nil, nil, nil, nil,
- nil, nil, 114, nil, nil, 114, 114, 114, 114, 114,
- 114, 114, 114, 114, 115, nil, nil, nil, 115, nil,
- 115, nil, 115, 115, nil, nil, nil, 115, nil, nil,
- nil, nil, nil, nil, nil, nil, 115, nil, 115, nil,
- nil, nil, 115, nil, nil, nil, nil, nil, nil, nil,
- 115, 115, nil, nil, 115, 115, 115, 115, 115, 115,
- 115, 115, 115, 116, nil, nil, nil, 116, nil, 116,
- nil, 116, 116, nil, nil, nil, 116, nil, nil, nil,
- nil, nil, nil, nil, nil, 116, nil, 116, nil, nil,
- nil, 116, nil, nil, nil, nil, nil, nil, nil, nil,
- 116, nil, nil, 116, 116, 116, 116, 116, 116, 116,
- 116, 116, 117, nil, nil, nil, 117, nil, 117, nil,
- 117, 117, nil, nil, nil, 117, nil, nil, nil, nil,
- nil, nil, nil, nil, 117, nil, 117, nil, nil, nil,
- 117, nil, nil, nil, nil, nil, nil, nil, nil, 117,
- nil, nil, 117, 117, 117, 117, 117, 117, 117, 117,
- 117, 118, nil, nil, nil, 118, nil, 118, nil, 118,
- 118, nil, nil, nil, 118, nil, nil, nil, nil, nil,
- nil, nil, nil, 118, nil, 118, nil, nil, nil, 118,
- nil, nil, nil, nil, nil, nil, nil, nil, 118, nil,
- nil, 118, 118, 118, 118, 118, 118, 118, 118, 118,
- 119, nil, nil, nil, 119, nil, 119, nil, 119, 119,
- nil, nil, nil, 119, nil, nil, nil, nil, nil, nil,
- nil, nil, 119, nil, 119, nil, nil, nil, 119, nil,
- nil, nil, nil, nil, nil, nil, nil, 119, nil, nil,
- 119, 119, 119, 119, 119, 119, 119, 119, 119, 120,
- nil, nil, nil, 120, nil, 120, nil, 120, 120, nil,
- nil, nil, 120, nil, nil, nil, nil, nil, nil, nil,
- nil, 120, nil, 120, nil, nil, nil, 120, nil, nil,
- nil, nil, nil, nil, nil, nil, 120, nil, nil, 120,
- 120, 120, 120, 120, 120, 120, 120, 120, 121, nil,
- nil, nil, 121, nil, 121, nil, 121, 121, nil, nil,
- nil, 121, nil, nil, nil, nil, nil, nil, nil, nil,
- 121, nil, 121, nil, nil, nil, 121, nil, nil, nil,
- nil, nil, nil, nil, nil, 121, nil, nil, 121, 121,
- 121, 121, 121, 121, 121, 121, 121, 122, nil, nil,
- nil, 122, nil, 122, nil, 122, 122, nil, nil, nil,
- 122, nil, nil, nil, nil, nil, nil, nil, nil, 122,
- nil, 122, nil, nil, nil, 122, nil, nil, nil, nil,
- nil, nil, nil, nil, 122, nil, nil, 122, 122, 122,
- 122, 122, 122, 122, 122, 122, 123, nil, nil, nil,
- 123, nil, 123, nil, 123, 123, nil, nil, nil, 123,
- nil, nil, nil, nil, nil, nil, nil, nil, 123, nil,
- 123, nil, nil, nil, 123, nil, nil, nil, nil, nil,
- nil, nil, nil, 123, nil, nil, 123, 123, 123, 123,
- 123, 123, 123, 123, 123, 124, nil, nil, nil, 124,
- nil, 124, nil, 124, 124, nil, nil, nil, 124, 124,
- nil, nil, nil, nil, nil, nil, nil, 124, nil, 124,
- nil, nil, nil, 124, nil, nil, nil, nil, nil, nil,
- nil, 124, 124, nil, nil, 124, 124, 124, 124, 124,
- 124, 124, 124, 124, 130, nil, nil, nil, 130, nil,
- 130, nil, 130, 130, nil, nil, nil, 130, nil, nil,
- nil, nil, nil, nil, nil, nil, 130, nil, 130, nil,
- nil, nil, 130, nil, nil, nil, nil, nil, nil, nil,
- nil, 130, nil, nil, 130, 130, 130, 130, 130, 130,
- 130, 130, 130, 137, nil, nil, nil, 137, nil, 137,
- nil, 137, 137, nil, nil, nil, 137, nil, nil, nil,
- nil, nil, nil, nil, nil, 137, nil, 137, nil, nil,
- nil, 137, nil, nil, nil, nil, nil, nil, nil, 137,
- 137, nil, nil, 137, 137, 137, 137, 137, 137, 137,
- 137, 137, 143, nil, nil, nil, 143, nil, 143, nil,
- 143, 143, nil, nil, nil, 143, nil, nil, nil, nil,
- nil, nil, nil, nil, 143, nil, 143, nil, nil, nil,
- 143, nil, nil, nil, nil, nil, nil, nil, nil, 143,
- nil, nil, 143, 143, 143, 143, 143, 143, 143, 143,
- 143, 144, nil, nil, nil, 144, nil, 144, nil, 144,
- 144, nil, nil, nil, 144, nil, nil, nil, nil, nil,
- nil, nil, nil, 144, nil, 144, nil, nil, nil, 144,
- nil, nil, nil, nil, nil, nil, nil, nil, 144, nil,
- nil, 144, 144, 144, 144, 144, 144, 144, 144, 144,
- 145, nil, nil, nil, 145, nil, 145, nil, 145, 145,
- nil, nil, nil, 145, nil, nil, nil, nil, nil, nil,
- nil, nil, 145, nil, 145, nil, nil, nil, 145, nil,
- nil, nil, nil, nil, nil, nil, nil, 145, nil, nil,
- 145, 145, 145, 145, 145, 145, 145, 145, 145, 146,
- nil, nil, nil, 146, nil, 146, nil, 146, 146, nil,
- nil, nil, 146, nil, nil, nil, nil, nil, nil, nil,
- nil, 146, nil, 146, nil, nil, nil, 146, nil, nil,
- nil, nil, nil, nil, nil, nil, 146, nil, nil, 146,
- 146, 146, 146, 146, 146, 146, 146, 146, 147, nil,
- nil, nil, 147, nil, 147, nil, 147, 147, nil, nil,
- nil, 147, nil, nil, nil, nil, nil, nil, nil, nil,
- 147, nil, 147, nil, nil, nil, 147, nil, nil, nil,
- nil, nil, nil, nil, nil, 147, nil, nil, 147, 147,
- 147, 147, 147, 147, 147, 147, 147, 148, nil, nil,
- nil, 148, nil, 148, nil, 148, 148, nil, nil, nil,
- 148, nil, nil, nil, nil, nil, nil, nil, nil, 148,
- nil, 148, nil, nil, nil, 148, nil, nil, nil, nil,
- nil, nil, nil, nil, 148, nil, nil, 148, 148, 148,
- 148, 148, 148, 148, 148, 148, 149, nil, nil, nil,
- 149, nil, 149, nil, 149, 149, nil, nil, nil, 149,
- nil, nil, nil, nil, nil, nil, nil, nil, 149, nil,
- 149, nil, nil, nil, 149, nil, nil, nil, nil, nil,
- nil, nil, nil, 149, nil, nil, 149, 149, 149, 149,
- 149, 149, 149, 149, 149, 150, nil, nil, nil, 150,
- nil, 150, nil, 150, 150, nil, nil, nil, 150, nil,
- nil, nil, nil, nil, nil, nil, nil, 150, nil, 150,
- nil, nil, nil, 150, nil, nil, nil, nil, nil, nil,
- nil, nil, 150, nil, nil, 150, 150, 150, 150, 150,
- 150, 150, 150, 150, 151, nil, nil, nil, 151, nil,
- 151, nil, 151, 151, nil, nil, nil, 151, nil, nil,
- nil, nil, nil, nil, nil, nil, 151, nil, 151, nil,
- nil, nil, 151, nil, nil, nil, nil, nil, nil, nil,
- nil, 151, nil, nil, 151, 151, 151, 151, 151, 151,
- 151, 151, 151, 152, nil, nil, nil, 152, nil, 152,
- nil, 152, 152, nil, nil, nil, 152, nil, nil, nil,
- nil, nil, nil, nil, nil, 152, nil, 152, nil, nil,
- nil, 152, nil, nil, nil, nil, nil, nil, nil, nil,
- 152, nil, nil, 152, 152, 152, 152, 152, 152, 152,
- 152, 152, 153, nil, nil, nil, 153, nil, 153, nil,
- 153, 153, nil, nil, nil, 153, nil, nil, nil, nil,
- nil, nil, nil, nil, 153, nil, 153, nil, nil, nil,
- 153, nil, nil, nil, nil, nil, nil, nil, nil, 153,
- nil, nil, 153, 153, 153, 153, 153, 153, 153, 153,
- 153, 154, nil, nil, nil, 154, nil, 154, nil, 154,
- 154, nil, nil, nil, 154, nil, nil, nil, nil, nil,
- nil, nil, nil, 154, nil, 154, nil, nil, nil, 154,
- nil, nil, nil, nil, nil, nil, nil, nil, 154, nil,
- nil, 154, 154, 154, 154, 154, 154, 154, 154, 154,
- 155, nil, nil, nil, 155, nil, 155, nil, 155, 155,
- nil, nil, nil, 155, nil, nil, nil, nil, nil, nil,
- nil, nil, 155, nil, 155, nil, nil, nil, 155, nil,
- nil, nil, nil, nil, nil, nil, nil, 155, nil, nil,
- 155, 155, 155, 155, 155, 155, 155, 155, 155, 156,
- nil, nil, nil, 156, nil, 156, nil, 156, 156, nil,
- nil, nil, 156, nil, nil, nil, nil, nil, nil, nil,
- nil, 156, nil, 156, nil, nil, nil, 156, nil, nil,
- nil, nil, nil, nil, nil, nil, 156, nil, nil, 156,
- 156, 156, 156, 156, 156, 156, 156, 156, 157, nil,
- nil, nil, 157, nil, 157, nil, 157, 157, nil, nil,
- nil, 157, nil, nil, nil, nil, nil, nil, nil, nil,
- 157, nil, 157, nil, nil, nil, 157, nil, nil, nil,
- nil, nil, nil, nil, nil, 157, nil, nil, 157, 157,
- 157, 157, 157, 157, 157, 157, 157, 158, nil, nil,
- nil, 158, nil, 158, nil, 158, 158, nil, nil, nil,
- 158, nil, nil, nil, nil, nil, nil, nil, nil, 158,
- nil, 158, nil, nil, nil, 158, nil, nil, nil, nil,
- nil, nil, nil, nil, 158, nil, nil, 158, 158, 158,
- 158, 158, 158, 158, 158, 158, 159, nil, nil, nil,
- 159, nil, 159, nil, 159, 159, nil, nil, nil, 159,
- nil, nil, nil, nil, nil, nil, nil, nil, 159, nil,
- 159, nil, nil, nil, 159, nil, nil, nil, nil, nil,
- nil, nil, nil, 159, nil, nil, 159, 159, 159, 159,
- 159, 159, 159, 159, 159, 160, nil, nil, nil, 160,
- nil, 160, nil, 160, 160, nil, nil, nil, 160, nil,
- nil, nil, nil, nil, nil, nil, nil, 160, nil, 160,
- nil, nil, nil, 160, nil, nil, nil, nil, nil, nil,
- nil, nil, 160, nil, nil, 160, 160, 160, 160, 160,
- 160, 160, 160, 160, 161, nil, nil, nil, 161, nil,
- 161, nil, 161, 161, nil, nil, nil, 161, nil, nil,
- nil, nil, nil, nil, nil, nil, 161, nil, 161, nil,
- nil, nil, 161, nil, nil, nil, nil, nil, nil, nil,
- nil, 161, nil, nil, 161, 161, 161, 161, 161, 161,
- 161, 161, 161, 162, nil, nil, nil, 162, nil, 162,
- nil, 162, 162, nil, nil, nil, 162, nil, nil, nil,
- nil, nil, nil, nil, nil, 162, nil, 162, nil, nil,
- nil, 162, nil, nil, nil, nil, nil, nil, nil, nil,
- 162, nil, nil, 162, 162, 162, 162, 162, 162, 162,
- 162, 162, 163, nil, nil, nil, 163, nil, 163, nil,
- 163, 163, nil, nil, nil, 163, nil, nil, nil, nil,
- nil, nil, nil, nil, 163, nil, 163, nil, nil, nil,
- 163, nil, nil, nil, nil, nil, nil, nil, nil, 163,
- nil, nil, 163, 163, 163, 163, 163, 163, 163, 163,
- 163, 164, nil, nil, nil, 164, nil, 164, nil, 164,
- 164, nil, nil, nil, 164, nil, nil, nil, nil, nil,
- nil, nil, nil, 164, nil, 164, nil, nil, nil, 164,
- nil, nil, nil, nil, nil, nil, nil, nil, 164, nil,
- nil, 164, 164, 164, 164, 164, 164, 164, 164, 164,
- 165, nil, nil, nil, 165, nil, 165, nil, 165, 165,
- nil, nil, nil, 165, nil, nil, nil, nil, nil, nil,
- nil, nil, 165, nil, 165, nil, nil, nil, 165, nil,
- nil, nil, nil, nil, nil, nil, nil, 165, nil, nil,
- 165, 165, 165, 165, 165, 165, 165, 165, 165, 166,
- nil, nil, nil, 166, nil, 166, nil, 166, 166, nil,
- nil, nil, 166, nil, nil, nil, nil, nil, nil, nil,
- nil, 166, nil, 166, nil, nil, nil, 166, nil, nil,
- nil, nil, nil, nil, nil, nil, 166, nil, nil, 166,
- 166, 166, 166, 166, 166, 166, 166, 166, 192, nil,
- nil, nil, 192, nil, 192, nil, 192, 192, nil, nil,
- nil, 192, nil, nil, nil, nil, nil, nil, nil, nil,
- 192, nil, 192, nil, nil, nil, 192, nil, nil, nil,
- nil, nil, nil, nil, nil, 192, nil, nil, 192, 192,
- 192, 192, 192, 192, 192, 192, 192, 195, nil, nil,
- nil, 195, nil, 195, nil, 195, 195, nil, nil, nil,
- 195, nil, nil, nil, nil, nil, nil, nil, nil, 195,
- nil, 195, nil, nil, nil, 195, nil, nil, nil, nil,
- nil, nil, nil, nil, 195, nil, nil, 195, 195, 195,
- 195, 195, 195, 195, 195, 195, 253, nil, nil, nil,
- 253, nil, 253, nil, 253, 253, nil, nil, nil, 253,
- nil, nil, nil, nil, nil, nil, nil, nil, 253, nil,
- 253, nil, nil, nil, 253, nil, nil, nil, nil, nil,
- nil, nil, 253, 253, nil, nil, 253, 253, 253, 253,
- 253, 253, 253, 253, 253, 254, nil, nil, nil, 254,
- nil, 254, nil, 254, 254, nil, nil, nil, 254, nil,
- nil, nil, nil, nil, nil, nil, nil, 254, nil, 254,
- nil, nil, nil, 254, nil, nil, nil, nil, nil, nil,
- nil, 254, 254, nil, nil, 254, 254, 254, 254, 254,
- 254, 254, 254, 254, 255, nil, nil, nil, 255, nil,
- 255, nil, 255, 255, nil, nil, nil, 255, nil, nil,
- nil, nil, nil, nil, nil, nil, 255, nil, 255, nil,
- nil, nil, 255, nil, nil, nil, nil, nil, nil, nil,
- 255, 255, nil, nil, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 258, nil, nil, nil, 258, nil, 258,
- nil, 258, 258, nil, nil, nil, 258, nil, nil, nil,
- nil, nil, nil, nil, nil, 258, nil, 258, nil, nil,
- nil, 258, nil, nil, nil, nil, nil, nil, nil, 258,
- 258, nil, nil, 258, 258, 258, 258, 258, 258, 258,
- 258, 258, 260, nil, nil, nil, 260, nil, 260, nil,
- 260, 260, nil, nil, nil, 260, nil, nil, nil, nil,
- nil, nil, nil, nil, 260, nil, 260, nil, nil, nil,
- 260, nil, nil, nil, nil, nil, nil, nil, nil, 260,
- nil, nil, 260, 260, 260, 260, 260, 260, 260, 260,
- 260, 262, nil, nil, nil, 262, nil, 262, nil, 262,
- 262, nil, nil, nil, 262, nil, nil, nil, nil, nil,
- nil, nil, nil, 262, nil, 262, nil, nil, nil, 262,
- nil, nil, nil, nil, nil, nil, nil, nil, 262, nil,
- nil, 262, 262, 262, 262, 262, 262, 262, 262, 262,
- 267, nil, nil, nil, 267, nil, 267, nil, 267, 267,
- nil, nil, nil, 267, nil, nil, nil, nil, nil, nil,
- nil, nil, 267, nil, 267, nil, nil, nil, 267, nil,
- nil, nil, nil, nil, nil, nil, 267, 267, nil, nil,
- 267, 267, 267, 267, 267, 267, 267, 267, 267, 268,
- nil, nil, nil, 268, nil, 268, nil, 268, 268, nil,
- nil, nil, 268, nil, nil, nil, nil, nil, nil, nil,
- nil, 268, nil, 268, nil, nil, nil, 268, nil, nil,
- nil, nil, nil, nil, nil, 268, 268, nil, nil, 268,
- 268, 268, 268, 268, 268, 268, 268, 268, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 79, 79, 79,
- 79, 79, 79, 79, 79, 79, 241, 241, 241, 241,
- 241, 241, 241, 241, 241, 241, 241, nil, nil, nil,
- 241, nil, nil, nil, 49, 49, nil, nil, nil, 49,
- nil, nil, nil, 79, 79, nil, nil, nil, 79, 76,
- 76, 76, 76, 76, 76, 76, 76, 76, 76, 76,
- 76, 76, 76, 76, 76, 76, 76, 76, 76, 76,
- 76, 76, nil, nil, nil, 76, nil, nil, nil, nil,
- nil, nil, nil, 76, 135, 135, 135, 135, 135, 135,
- 135, 135, 135, 135, 135, 135, 135, 135, 135, 135,
- 135, 135, 135, 135, 135, 135, 135, nil, nil, nil,
- 135, nil, nil, nil, nil, nil, nil, nil, 135, 264,
- 264, 264, 264, 264, 264, 264, 264, 264, 264, 264,
- 264, 264, 264, 264, 264, 264, 264, 264, 264, 264,
- 264, 264, nil, nil, nil, 264, nil, nil, nil, nil,
- nil, nil, nil, 264, 285, 285, 285, 285, 285, 285,
- 285, 285, 285, 285, 285, 285, 285, 285, 285, 285,
- 285, 285, 285, 285, 285, 285, 285, nil, nil, nil,
- 285, nil, nil, nil, nil, nil, nil, nil, 285, 168,
- 168, 168, 168, 168, 168, 168, 168, 168, 168, 168,
- 168, 168, 168, 168, 168, 168, 168, 168, 168, 168,
- 168, 168, nil, nil, nil, 168, nil, nil, nil, nil,
- nil, nil, 168, 194, 194, 194, 194, 194, 194, 194,
- 194, 194, 194, 194, 194, 194, 194, 194, 194, 194,
- 194, 194, 194, 194, 194, 194, nil, nil, nil, 194,
- nil, nil, nil, nil, nil, nil, 194, 196, 196, 196,
- 196, 196, 196, 196, 196, 196, 196, 196, 196, 196,
- 196, 196, 196, 196, 196, 196, 196, 196, 196, 196,
- nil, nil, nil, 196, nil, nil, nil, nil, nil, nil,
- 196, 261, 261, 261, 261, 261, 261, 261, 261, 261,
- 261, 261, 261, 261, 261, 261, 261, 261, 261, 261,
- 261, 261, 261, 261, nil, nil, nil, 261, nil, nil,
- nil, nil, nil, nil, 261, 287, 287, 287, 287, 287,
- 287, 287, 287, 287, 287, 287, 287, 287, 287, 287,
- 287, 287, 287, 287, 287, 287, 287, 287, nil, nil,
- nil, 287, 0, 0, 0, 0, 0, nil, 287, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, nil,
- 0, 0, 0, 0, nil, 0, nil, 0, 3, 3,
- 3, 3, 3, nil, 0, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, nil, 3, 3, 3, 3,
- nil, 3, nil, 3, 43, 43, 43, nil, nil, nil,
- 3, 43, 43, 43, 43, 43, 43, 43, 43, 43,
- 43, 43, 43, 43, 43, 43, nil, 43, nil, 43,
- 47, 47, 47, nil, nil, nil, 43, 47, 47, 47,
- 47, 47, 47, 47, 47, 47, 47, nil, 47, 47,
- 47, 47, nil, 47, nil, 47, 108, 108, 108, nil,
- nil, nil, 47, 108, 108, 108, 108, 108, 108, 108,
- 108, 108, 108, nil, 108, 108, 108, 108, nil, 108,
- nil, 108, 263, 263, 263, nil, nil, nil, 108, 263,
- 263, 263, 263, 263, 263, 263, 263, 263, 263, nil,
- 263, 263, 263, 263, nil, 263, nil, 263, 265, 265,
- 265, nil, nil, nil, 263, 265, 265, 265, 265, 265,
- 265, 265, 265, 265, 265, nil, 265, 265, 265, 265,
- nil, 265, nil, 265, 286, 286, 286, nil, nil, nil,
- 265, 286, 286, 286, 286, 286, 286, 286, 286, 286,
- 286, nil, 286, 286, 286, 286, nil, 286, nil, 286,
- 299, 299, 299, nil, nil, nil, 286, 299, 299, 299,
- 299, 299, 299, 299, 299, 299, 299, nil, 299, 299,
- 299, 299, nil, 299, nil, 299, 300, 300, 300, nil,
- nil, nil, 299, 300, 300, 300, 300, 300, 300, 300,
- 300, 300, 300, nil, 300, 300, 300, 300, nil, 300,
- nil, 300, 306, 306, 306, nil, nil, nil, 300, 306,
- 306, 306, 306, 306, 306, 306, 306, 306, 306, nil,
- 306, 306, 306, 306, nil, 306, nil, 306, nil, nil,
- nil, nil, nil, nil, 306, 180, 180, 180, 180, 180,
- 180, 180, 180, 180, 180, 180, 180, 180, 180, 180,
- 180, 180, 180, 180, 180, 180, 180, 180, nil, nil,
- nil, 180, 197, 197, 197, 197, 197, 197, 197, 197,
- 197, 197, 197, 197, 197, 197, 197, 197, 197, 197,
- 197, 197, 197, 197, 197, nil, nil, nil, 197, 199,
- 199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
- 199, 199, 199, 199, 199, 199, 199, 199, 199, 199,
- 199, 199, nil, nil, nil, 199, 200, 200, 200, 200,
- 200, 200, 200, 200, 200, 200, 200, 200, 200, 200,
- 200, 200, 200, 200, 200, 200, 200, 200, 200, nil,
- nil, nil, 200, 201, 201, 201, 201, 201, 201, 201,
- 201, 201, 201, 201, 201, 201, 201, 201, 201, 201,
- 201, 201, 201, 201, 201, 201, nil, nil, nil, 201,
- 202, 202, 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, nil, nil, nil, 202, 203, 203, 203,
- 203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
- 203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
- nil, nil, nil, 203, 204, 204, 204, 204, 204, 204,
- 204, 204, 204, 204, 204, 204, 204, 204, 204, 204,
- 204, 204, 204, 204, 204, 204, 204, nil, nil, nil,
- 204, 205, 205, 205, 205, 205, 205, 205, 205, 205,
- 205, 205, 205, 205, 205, 205, 205, 205, 205, 205,
- 205, 205, 205, 205, nil, nil, nil, 205, 206, 206,
- 206, 206, 206, 206, 206, 206, 206, 206, 206, 206,
- 206, 206, 206, 206, 206, 206, 206, 206, 206, 206,
- 206, nil, nil, nil, 206, 209, 209, 209, 209, 209,
- 209, 209, 209, 209, 209, 209, 209, 209, 209, 209,
- 209, 209, 209, 209, 209, 209, 209, 209, nil, nil,
- nil, 209, 222, 222, 222, 222, 222, 222, 222, 222,
- 222, 222, 222, 222, 222, 222, 222, 222, 222, 222,
- 222, 222, 222, 222, 222, nil, nil, nil, 222, 277,
- 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
- 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
- 277, 277, nil, nil, nil, 277, 279, 279, 279, 279,
- 279, 279, 279, 279, 279, 279, 279, 279, 279, 279,
- 279, 279, 279, 279, 279, 279, 279, 279, 279, nil,
- nil, nil, 279, 281, 281, 281, 281, 281, 281, 281,
- 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
- 281, 281, 281, 281, 281, 281, nil, nil, nil, 281,
- 291, 291, 291, 291, 291, 291, 291, 291, 291, 291,
- 291, 291, 291, 291, 291, 291, 291, 291, 291, 291,
- 291, 291, 291, nil, nil, nil, 291, 228, 228, 228,
- 228, 228, 228, 228, 228, 228, 228, 228, 228, 228,
- 228, 228, 228, 228, 228, 228, 228, 228, 228, nil,
- nil, nil, 228, 227, 227, 227, 227, 227, 227, 227,
- 227, 227, 227, 227, 227, 227, 227, 227, 227, 227,
- 227, 227, 227, 227, nil, nil, nil, 227, 242, 242,
- 242, 242, 242, 242, 242, 242, 242, 242, 242, nil,
- nil, nil, 242, 243, 243, 243, 243, 243, 243, 243,
- 243, 243, 243, 243, nil, nil, nil, 243, 244, 244,
- 244, 244, 244, 244, 244, 244, 244, 244, 244, nil,
- nil, nil, 244, 245, 245, 245, 245, 245, 245, 245,
- 245, 245, 245, 245, nil, nil, nil, 245, 246, 246,
- 246, 246, 246, 246, 246, 246, 246, 246, 246, nil,
- nil, nil, 246, 247, 247, 247, 247, 247, 247, 247,
- 247, 247, 247, 247, nil, nil, nil, 247, 248, 248,
- 248, 248, 248, 248, 248, 248, 248, 248, 248, nil,
- nil, nil, 248, 249, 249, 249, 249, 249, 249, 249,
- 249, 249, 249, 249, nil, nil, nil, 249, 250, 250,
- 250, 250, 250, 250, 250, 250, 250, 250, 250, nil,
- nil, nil, 250, 237, 237, 237, 237, 237, 237, 237,
- 237, 237, 237, nil, nil, nil, 237, 236, 236, 236,
- 236, 236, 236, 236, 236, 236, nil, nil, nil, 236 ]
-
-racc_action_pointer = [
- 3034, 33, nil, 3060, 109, nil, nil, nil, nil, nil,
- -5, -28, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, -2, 9, -6, 13, 47, nil, -17, 50, 59,
- 65, -8, -7, 3086, 68, -18, 80, 3112, 81, 2716,
- 35, 74, 15, nil, nil, nil, 128, nil, nil, nil,
- nil, nil, 88, nil, nil, nil, 42, nil, nil, 88,
- 133, 72, nil, -28, 30, 93, 2758, 96, nil, 2725,
- 91, 140, 189, 238, nil, nil, nil, nil, nil, nil,
- 86, nil, nil, nil, 84, 129, 287, nil, nil, nil,
- nil, nil, nil, nil, nil, 108, 105, nil, 3138, 52,
- 129, 138, 336, 111, 385, 434, 483, 532, 581, 630,
- 679, 728, 777, 826, 875, nil, nil, nil, nil, nil,
- 924, 139, 19, nil, 31, 2793, nil, 973, 168, 131,
- 133, nil, nil, 1022, 1071, 1120, 1169, 1218, 1267, 1316,
- 1365, 1414, 1463, 1512, 1561, 1610, 1659, 1708, 1757, 1806,
- 1855, 1904, 1953, 2002, 2051, 2100, 2149, nil, 2898, 143,
- 145, 148, 309, nil, 122, 124, 125, 128, 140, nil,
- 3354, nil, 156, 154, nil, nil, nil, 179, nil, nil,
- nil, nil, 2198, 171, 2932, 2247, 2966, 3381, nil, 3408,
- 3435, 3462, 3489, 3516, 3543, 3570, 3597, 187, nil, 3624,
- 10, nil, 168, -11, nil, nil, 190, 181, 187, nil,
- 172, nil, 3651, nil, nil, 195, 197, 3810, 3785, 66,
- 115, 207, 209, 221, 232, 256, 3972, 3959, 269, 303,
- 319, 2713, 3825, 3840, 3855, 3870, 3885, 3900, 3915, 3930,
- 3945, nil, 201, 2296, 2345, 2394, 178, nil, 2443, nil,
- 2492, 3000, 2541, 3164, 2828, 3190, nil, 2590, 2639, nil,
- 217, nil, nil, 3, nil, nil, 324, 3678, nil, 3705,
- nil, 3732, nil, nil, nil, 2863, 3216, 3034, 213, nil,
- nil, 3759, nil, nil, nil, nil, 206, 101, nil, 3242,
- 3268, 358, 234, nil, nil, nil, 3294, nil ]
-
-racc_action_default = [
- -2, -172, -1, -4, -172, -6, -8, -9, -10, -11,
- -172, -172, -15, -16, -17, -18, -19, -20, -22, -23,
- -24, -25, -26, -27, -28, -29, -30, -31, -32, -33,
- -34, -172, -172, -172, -172, -172, -40, -172, -172, -172,
- -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
- -172, -172, -128, -160, -161, -162, -172, -3, -5, -7,
- -21, -12, -172, -35, -36, -37, -172, -38, -39, -172,
- -157, -159, -42, -172, -172, -172, -172, -172, -49, -108,
- -172, -172, -172, -172, -93, -94, -105, -106, -107, -109,
- -110, -111, -112, -113, -172, -172, -172, -163, -164, -165,
- -166, -167, -169, -170, -171, -172, -172, -51, -154, -138,
- -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
- -172, -172, -172, -172, -172, -72, -74, -71, -73, -127,
- -172, -172, -142, 308, -172, -172, -41, -172, -172, -172,
- -172, -45, -47, -172, -172, -172, -172, -172, -172, -172,
- -172, -172, -172, -172, -172, -172, -172, -172, -172, -172,
- -172, -172, -172, -172, -172, -172, -172, -48, -172, -77,
- -81, -82, -172, -129, -172, -172, -172, -126, -172, -133,
- -143, -144, -146, -172, -148, -50, -153, -172, -134, -135,
- -136, -137, -172, -172, -172, -172, -172, -59, -60, -61,
- -62, -63, -64, -65, -66, -67, -68, -172, -70, -116,
- -128, -117, -131, -172, -140, -141, -172, -172, -172, -150,
- -152, -46, -155, -156, -158, -172, -172, -76, -78, -79,
- -80, -83, -84, -85, -86, -87, -88, -89, -90, -91,
- -92, -95, -96, -97, -98, -99, -100, -101, -102, -103,
- -104, -75, -172, -172, -172, -172, -125, -132, -172, -147,
- -172, -172, -172, -172, -172, -172, -69, -172, -172, -139,
- -172, -14, -149, -172, -43, -44, -172, -118, -121, -119,
- -122, -120, -123, -124, -145, -172, -172, -172, -55, -57,
- -58, -114, -115, -130, -13, -151, -172, -138, -53, -172,
- -172, -172, -172, -54, -56, -168, -172, -52 ]
-
-racc_goto_table = [
- 31, 187, 62, 31, 175, 33, 77, 183, 33, 178,
- 35, 139, 140, 35, 207, 38, 216, 106, 38, 60,
- 69, 1, 271, 59, 75, 58, 215, 49, 70, 61,
- 49, 108, 70, 174, 2, 113, 110, 57, nil, nil,
- nil, nil, nil, 31, nil, nil, nil, 31, 33, nil,
- nil, nil, 33, 35, nil, nil, nil, 35, 38, nil,
- nil, nil, 38, nil, nil, nil, nil, nil, nil, nil,
- 49, nil, nil, nil, 49, 294, nil, 127, 128, 198,
- nil, 252, 186, nil, nil, 173, 176, nil, 211, nil,
- nil, nil, nil, nil, nil, nil, 108, nil, nil, nil,
- nil, 223, 193, nil, nil, nil, nil, nil, 31, 188,
- nil, nil, nil, 33, 189, 210, nil, nil, 35, 190,
- 60, 224, 214, 38, 191, 219, nil, nil, nil, 70,
- nil, nil, nil, nil, nil, 49, 49, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 295, nil, nil, 293, nil,
- nil, nil, nil, nil, nil, 175, nil, nil, nil, 284,
- 283, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 296, nil, nil, nil, 302,
- nil, nil, nil, nil, 174, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 272,
- 305, nil, nil, nil, nil, nil, nil, 278, 280, 282,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 292, 211, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 176, nil, nil,
- nil, 288, nil, 290, nil, nil, nil, nil, nil, 210,
- nil, nil, nil, 31, 219, 31, nil, nil, 33, nil,
- 33, nil, nil, 35, 298, 35, nil, nil, 38, 76,
- 38, nil, nil, nil, nil, nil, 31, 303, 304, nil,
- 49, 33, 49, nil, 307, nil, 35, 188, nil, 31,
- 31, 38, 189, 135, 33, 33, 31, 190, nil, 35,
- 35, 33, 191, 49, 38, 38, 35, 168, 169, 170,
- 171, 38, nil, nil, 49, nil, 49, 49, nil, nil,
- nil, nil, nil, 49, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 194,
- nil, 196, 197, 199, 200, 201, 202, 203, 204, 205,
- 206, 209, nil, nil, nil, nil, nil, 213, nil, nil,
- nil, nil, nil, nil, 222, nil, nil, nil, nil, nil,
- 227, 228, 229, 230, 231, 232, 233, 234, 235, 236,
- 237, 238, 239, 240, 241, 242, 243, 244, 245, 246,
- 247, 248, 249, 250, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 261,
- nil, nil, 264, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 277, 279, 281, nil, nil, nil, nil, 285, nil, 287,
- nil, nil, nil, nil, 291, 209 ]
-
-racc_goto_check = [
- 30, 39, 9, 30, 43, 31, 37, 53, 31, 49,
- 32, 35, 35, 32, 41, 34, 10, 38, 34, 18,
- 33, 1, 11, 5, 33, 4, 50, 40, 9, 5,
- 40, 6, 9, 35, 2, 6, 9, 2, nil, nil,
- nil, nil, nil, 30, nil, nil, nil, 30, 31, nil,
- nil, nil, 31, 32, nil, nil, nil, 32, 34, nil,
- nil, nil, 34, nil, nil, nil, nil, nil, nil, nil,
- 40, nil, nil, nil, 40, 11, nil, 40, 40, 37,
- nil, 43, 38, nil, nil, 9, 9, nil, 37, nil,
- nil, nil, nil, nil, nil, nil, 6, nil, nil, nil,
- nil, 37, 9, nil, nil, nil, nil, nil, 30, 30,
- nil, nil, nil, 31, 31, 9, nil, nil, 32, 32,
- 18, 33, 9, 34, 34, 9, nil, nil, nil, 9,
- nil, nil, nil, nil, nil, 40, 40, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 10, nil, nil, 41, nil,
- nil, nil, nil, nil, nil, 43, nil, nil, nil, 53,
- 49, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 43, nil, nil, nil, 39,
- nil, nil, nil, nil, 35, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 9,
- 43, nil, nil, nil, nil, nil, nil, 37, 37, 37,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 37, 37, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 9, nil, nil,
- nil, 6, nil, 6, nil, nil, nil, nil, nil, 9,
- nil, nil, nil, 30, 9, 30, nil, nil, 31, nil,
- 31, nil, nil, 32, 6, 32, nil, nil, 34, 36,
- 34, nil, nil, nil, nil, nil, 30, 6, 6, nil,
- 40, 31, 40, nil, 6, nil, 32, 30, nil, 30,
- 30, 34, 31, 36, 31, 31, 30, 32, nil, 32,
- 32, 31, 34, 40, 34, 34, 32, 36, 36, 36,
- 36, 34, nil, nil, 40, nil, 40, 40, nil, nil,
- nil, nil, nil, 40, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 36,
- nil, 36, 36, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, nil, nil, nil, nil, nil, 36, nil, nil,
- nil, nil, nil, nil, 36, nil, nil, nil, nil, nil,
- 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, 36, 36, 36, 36, 36, 36,
- 36, 36, 36, 36, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 36,
- nil, nil, 36, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 36, 36, 36, nil, nil, nil, nil, 36, nil, 36,
- nil, nil, nil, nil, 36, 36 ]
-
-racc_goto_pointer = [
- nil, 21, 34, nil, 21, 19, -12, nil, nil, -9,
- -118, -195, nil, nil, nil, nil, nil, nil, 15, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 0, 5, 10, -17, 15, -62, 237, -36, -26, -108,
- 27, -110, nil, -91, nil, nil, nil, nil, nil, -86,
- -106, nil, nil, -89, nil, nil ]
-
-racc_goto_default = [
- nil, nil, nil, 3, 5, 6, 7, 8, 9, 52,
- nil, 25, 12, 13, 14, 15, 16, 17, 18, 19,
- 20, 21, 22, 23, 24, 26, 27, 28, 29, 30,
- 86, 88, 85, nil, 84, 87, 180, 181, nil, nil,
- 79, nil, 89, 90, 91, 92, 93, 212, 177, nil,
- 129, 132, 182, nil, 220, 71 ]
-
-racc_reduce_table = [
- 0, 0, :racc_error,
- 1, 80, :_reduce_1,
- 0, 80, :_reduce_2,
- 2, 81, :_reduce_3,
- 1, 81, :_reduce_4,
- 2, 82, :_reduce_5,
- 1, 82, :_reduce_6,
- 2, 82, :_reduce_7,
- 1, 82, :_reduce_8,
- 1, 82, :_reduce_9,
- 1, 85, :_reduce_10,
- 1, 85, :_reduce_11,
- 2, 83, :_reduce_12,
- 6, 84, :_reduce_13,
- 5, 84, :_reduce_14,
- 1, 86, :_reduce_15,
- 1, 86, :_reduce_16,
- 1, 86, :_reduce_17,
- 1, 86, :_reduce_18,
- 1, 86, :_reduce_19,
- 1, 86, :_reduce_20,
- 2, 86, :_reduce_21,
- 1, 86, :_reduce_22,
- 1, 86, :_reduce_23,
- 1, 86, :_reduce_24,
- 1, 86, :_reduce_25,
- 1, 86, :_reduce_26,
- 1, 86, :_reduce_27,
- 1, 86, :_reduce_28,
- 1, 87, :_reduce_29,
- 1, 87, :_reduce_30,
- 1, 87, :_reduce_31,
- 1, 87, :_reduce_32,
- 1, 87, :_reduce_33,
- 1, 87, :_reduce_34,
- 2, 91, :_reduce_35,
- 2, 92, :_reduce_36,
- 2, 93, :_reduce_37,
- 2, 94, :_reduce_38,
- 2, 95, :_reduce_39,
- 1, 96, :_reduce_40,
- 3, 97, :_reduce_41,
- 2, 100, :_reduce_42,
- 5, 98, :_reduce_43,
- 5, 99, :_reduce_44,
- 3, 101, :_reduce_45,
- 4, 102, :_reduce_46,
- 3, 103, :_reduce_47,
- 3, 103, :_reduce_48,
- 2, 103, :_reduce_49,
- 3, 90, :_reduce_50,
- 2, 90, :_reduce_51,
- 9, 104, :_reduce_52,
- 6, 105, :_reduce_53,
- 7, 105, :_reduce_54,
- 5, 106, :_reduce_55,
- 7, 106, :_reduce_56,
- 5, 107, :_reduce_57,
- 5, 108, :_reduce_58,
- 3, 109, :_reduce_59,
- 3, 109, :_reduce_60,
- 3, 109, :_reduce_61,
- 3, 109, :_reduce_62,
- 3, 109, :_reduce_63,
- 3, 109, :_reduce_64,
- 3, 109, :_reduce_65,
- 3, 109, :_reduce_66,
- 3, 109, :_reduce_67,
- 3, 109, :_reduce_68,
- 4, 110, :_reduce_69,
- 3, 110, :_reduce_70,
- 2, 111, :_reduce_71,
- 2, 111, :_reduce_72,
- 2, 113, :_reduce_73,
- 2, 113, :_reduce_74,
- 3, 115, :_reduce_75,
- 3, 115, :_reduce_76,
- 2, 115, :_reduce_77,
- 3, 115, :_reduce_78,
- 3, 115, :_reduce_79,
- 3, 115, :_reduce_80,
- 2, 115, :_reduce_81,
- 2, 115, :_reduce_82,
- 3, 115, :_reduce_83,
- 3, 115, :_reduce_84,
- 3, 115, :_reduce_85,
- 3, 115, :_reduce_86,
- 3, 115, :_reduce_87,
- 3, 115, :_reduce_88,
- 3, 115, :_reduce_89,
- 3, 115, :_reduce_90,
- 3, 115, :_reduce_91,
- 3, 115, :_reduce_92,
- 1, 115, :_reduce_93,
- 1, 115, :_reduce_94,
- 3, 115, :_reduce_95,
- 3, 115, :_reduce_96,
- 3, 115, :_reduce_97,
- 3, 115, :_reduce_98,
- 3, 115, :_reduce_99,
- 3, 115, :_reduce_100,
- 3, 115, :_reduce_101,
- 3, 115, :_reduce_102,
- 3, 115, :_reduce_103,
- 3, 115, :_reduce_104,
- 1, 115, :_reduce_105,
- 1, 115, :_reduce_106,
- 1, 115, :_reduce_107,
- 1, 115, :_reduce_108,
- 1, 115, :_reduce_109,
- 1, 115, :_reduce_110,
- 1, 115, :_reduce_111,
- 1, 115, :_reduce_112,
- 1, 115, :_reduce_113,
- 3, 126, :_reduce_114,
- 3, 126, :_reduce_115,
- 1, 126, :_reduce_116,
- 1, 126, :_reduce_117,
- 3, 127, :_reduce_118,
- 3, 127, :_reduce_119,
- 3, 127, :_reduce_120,
- 3, 127, :_reduce_121,
- 3, 127, :_reduce_122,
- 3, 127, :_reduce_123,
- 3, 128, :_reduce_124,
- 2, 128, :_reduce_125,
- 1, 128, :_reduce_126,
- 2, 119, :_reduce_127,
- 1, 119, :_reduce_128,
- 2, 116, :_reduce_129,
- 3, 120, :_reduce_130,
- 1, 120, :_reduce_131,
- 3, 125, :_reduce_132,
- 2, 125, :_reduce_133,
- 1, 118, :_reduce_134,
- 1, 118, :_reduce_135,
- 1, 118, :_reduce_136,
- 1, 118, :_reduce_137,
- 0, 118, :_reduce_138,
- 3, 130, :_reduce_139,
- 2, 130, :_reduce_140,
- 2, 129, :_reduce_141,
- 1, 129, :_reduce_142,
- 1, 131, :_reduce_143,
- 1, 131, :_reduce_144,
- 3, 132, :_reduce_145,
- 1, 132, :_reduce_146,
- 3, 124, :_reduce_147,
- 2, 124, :_reduce_148,
- 2, 133, :_reduce_149,
- 1, 133, :_reduce_150,
- 3, 89, :_reduce_151,
- 1, 89, :_reduce_152,
- 2, 117, :_reduce_153,
- 1, 117, :_reduce_154,
- 3, 134, :_reduce_155,
- 3, 134, :_reduce_156,
- 1, 134, :_reduce_157,
- 3, 112, :_reduce_158,
- 1, 112, :_reduce_159,
- 1, 88, :_reduce_160,
- 1, 88, :_reduce_161,
- 1, 88, :_reduce_162,
- 1, 122, :_reduce_163,
- 1, 122, :_reduce_164,
- 1, 122, :_reduce_165,
- 1, 122, :_reduce_166,
- 1, 122, :_reduce_167,
- 7, 121, :_reduce_168,
- 1, 114, :_reduce_169,
- 1, 114, :_reduce_170,
- 1, 123, :_reduce_171 ]
-
-racc_reduce_n = 172
-
-racc_shift_n = 308
-
-racc_token_table = {
- false => 0,
- :error => 1,
- :ASS_EQ => 2,
- :ADD_EQ => 3,
- :SUB_EQ => 4,
- :MUL_EQ => 5,
- :DIV_EQ => 6,
- :MOD_EQ => 7,
- :SLL_EQ => 8,
- :SRA_EQ => 9,
- :SRL_EQ => 10,
- :OR => 11,
- :AND => 12,
- :CMP_LT => 13,
- :CMP_GT => 14,
- :CMP_EQ => 15,
- :CMP_NE => 16,
- :CMP_GE => 17,
- :CMP_LE => 18,
- :SUBSTR_EQ => 19,
- :SUBSTR_NE => 20,
- :REGEX_EQ => 21,
- :REGEX_NE => 22,
- :BIT_OR => 23,
- :BIT_XOR => 24,
- :AMPERSAND => 25,
- :BIT_SRA => 26,
- :BIT_SRL => 27,
- :BIT_SLL => 28,
- :ADD => 29,
- :SUB => 30,
- :MUL => 31,
- :DIV => 32,
- :MOD => 33,
- :NOT => 34,
- :UMINUS => 35,
- :BIT_NOT => 36,
- :EXP => 37,
- :INCR => 38,
- :DECR => 39,
- :COMMENT => 40,
- :EXPORT => 41,
- :FUNCTION => 42,
- :LPAREN => 43,
- :RPAREN => 44,
- :SEMICOLON => 45,
- :BREAK => 46,
- :CONTINUE => 47,
- :GLOBAL => 48,
- :IMPORT => 49,
- :INCLUDE => 50,
- :LOCAL => 51,
- :REP => 52,
- :RETURN => 53,
- :LBRACE => 54,
- :RBRACE => 55,
- :FOR => 56,
- :FOREACH => 57,
- :IN => 58,
- :IF => 59,
- :ELSE => 60,
- :REPEAT => 61,
- :UNTIL => 62,
- :WHILE => 63,
- :COLON => 64,
- :COMMA => 65,
- :AT_SIGN => 66,
- :LBRACK => 67,
- :RBRACK => 68,
- :PERIOD => 69,
- :IDENT => 70,
- :INT_DEC => 71,
- :INT_HEX => 72,
- :INT_OCT => 73,
- :FALSE => 74,
- :TRUE => 75,
- :DATA => 76,
- :STRING => 77,
- :UNDEF => 78 }
-
-racc_nt_base = 79
-
-racc_use_result_var = false
-
-Racc_arg = [
- racc_action_table,
- racc_action_check,
- racc_action_default,
- racc_action_pointer,
- racc_goto_table,
- racc_goto_check,
- racc_goto_default,
- racc_goto_pointer,
- racc_nt_base,
- racc_reduce_table,
- racc_token_table,
- racc_shift_n,
- racc_reduce_n,
- racc_use_result_var ]
-
-Racc_token_to_s_table = [
- "$end",
- "error",
- "ASS_EQ",
- "ADD_EQ",
- "SUB_EQ",
- "MUL_EQ",
- "DIV_EQ",
- "MOD_EQ",
- "SLL_EQ",
- "SRA_EQ",
- "SRL_EQ",
- "OR",
- "AND",
- "CMP_LT",
- "CMP_GT",
- "CMP_EQ",
- "CMP_NE",
- "CMP_GE",
- "CMP_LE",
- "SUBSTR_EQ",
- "SUBSTR_NE",
- "REGEX_EQ",
- "REGEX_NE",
- "BIT_OR",
- "BIT_XOR",
- "AMPERSAND",
- "BIT_SRA",
- "BIT_SRL",
- "BIT_SLL",
- "ADD",
- "SUB",
- "MUL",
- "DIV",
- "MOD",
- "NOT",
- "UMINUS",
- "BIT_NOT",
- "EXP",
- "INCR",
- "DECR",
- "COMMENT",
- "EXPORT",
- "FUNCTION",
- "LPAREN",
- "RPAREN",
- "SEMICOLON",
- "BREAK",
- "CONTINUE",
- "GLOBAL",
- "IMPORT",
- "INCLUDE",
- "LOCAL",
- "REP",
- "RETURN",
- "LBRACE",
- "RBRACE",
- "FOR",
- "FOREACH",
- "IN",
- "IF",
- "ELSE",
- "REPEAT",
- "UNTIL",
- "WHILE",
- "COLON",
- "COMMA",
- "AT_SIGN",
- "LBRACK",
- "RBRACK",
- "PERIOD",
- "IDENT",
- "INT_DEC",
- "INT_HEX",
- "INT_OCT",
- "FALSE",
- "TRUE",
- "DATA",
- "STRING",
- "UNDEF",
- "$start",
- "start",
- "roots",
- "root",
- "export",
- "function",
- "statement",
- "simple",
- "compound",
- "ident",
- "params",
- "block",
- "assign",
- "break",
- "call",
- "continue",
- "decr",
- "empty",
- "global",
- "import",
- "include",
- "incr",
- "local",
- "rep",
- "return",
- "for",
- "foreach",
- "if",
- "repeat",
- "while",
- "assign_exp",
- "call_exp",
- "decr_exp",
- "var_decls",
- "incr_exp",
- "string",
- "expr",
- "ref",
- "statements",
- "field",
- "lval",
- "args",
- "ip",
- "int",
- "undef",
- "list_expr",
- "array_expr",
- "arg",
- "kv_pair",
- "kv_pairs",
- "indexes",
- "index",
- "list_elem",
- "list_elems",
- "param",
- "var_decl" ]
-
-Racc_debug_parser = false
-
-##### State transition tables end #####
-
-# reduce 0 omitted
-
-module_eval(<<'.,.,', 'nasl.y', 61)
- def _reduce_1(val, _values)
- val[0]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 63)
- def _reduce_2(val, _values)
- []
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 67)
- def _reduce_3(val, _values)
- [val[0]] + val[1]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 69)
- def _reduce_4(val, _values)
- [val[0]]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 73)
- def _reduce_5(val, _values)
- c(*val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 75)
- def _reduce_6(val, _values)
- val[0]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 77)
- def _reduce_7(val, _values)
- c(*val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 79)
- def _reduce_8(val, _values)
- val[0]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 81)
- def _reduce_9(val, _values)
- val[0]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 85)
- def _reduce_10(val, _values)
- val[0]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 87)
- def _reduce_11(val, _values)
- val[0]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 95)
- def _reduce_12(val, _values)
- n(:Export, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 99)
- def _reduce_13(val, _values)
- n(:Function, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 101)
- def _reduce_14(val, _values)
- n(:Function, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 105)
- def _reduce_15(val, _values)
- val[0]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 107)
- def _reduce_16(val, _values)
- val[0]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 109)
- def _reduce_17(val, _values)
- val[0]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 111)
- def _reduce_18(val, _values)
- val[0]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 113)
- def _reduce_19(val, _values)
- val[0]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 115)
- def _reduce_20(val, _values)
- val[0]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 117)
- def _reduce_21(val, _values)
- c(*val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 119)
- def _reduce_22(val, _values)
- val[0]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 121)
- def _reduce_23(val, _values)
- val[0]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 123)
- def _reduce_24(val, _values)
- val[0]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 125)
- def _reduce_25(val, _values)
- val[0]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 127)
- def _reduce_26(val, _values)
- val[0]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 129)
- def _reduce_27(val, _values)
- val[0]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 131)
- def _reduce_28(val, _values)
- val[0]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 135)
- def _reduce_29(val, _values)
- val[0]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 137)
- def _reduce_30(val, _values)
- val[0]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 139)
- def _reduce_31(val, _values)
- val[0]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 141)
- def _reduce_32(val, _values)
- val[0]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 143)
- def _reduce_33(val, _values)
- val[0]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 145)
- def _reduce_34(val, _values)
- val[0]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 153)
- def _reduce_35(val, _values)
- val[0]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 157)
- def _reduce_36(val, _values)
- n(:Break, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 161)
- def _reduce_37(val, _values)
- val[0]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 165)
- def _reduce_38(val, _values)
- n(:Continue, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 169)
- def _reduce_39(val, _values)
- val[0]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 173)
- def _reduce_40(val, _values)
- n(:Empty, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 177)
- def _reduce_41(val, _values)
- n(:Global, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 181)
- def _reduce_42(val, _values)
- val[0]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 185)
- def _reduce_43(val, _values)
- n(:Import, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 189)
- def _reduce_44(val, _values)
- n(:Include, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 193)
- def _reduce_45(val, _values)
- n(:Local, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 197)
- def _reduce_46(val, _values)
- n(:Repetition, *val[0..-1])
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 201)
- def _reduce_47(val, _values)
- n(:Return, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 203)
- def _reduce_48(val, _values)
- n(:Return, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 205)
- def _reduce_49(val, _values)
- n(:Return, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 213)
- def _reduce_50(val, _values)
- n(:Block, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 215)
- def _reduce_51(val, _values)
- n(:Block, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 219)
- def _reduce_52(val, _values)
- n(:For, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 223)
- def _reduce_53(val, _values)
- n(:Foreach, val[0], val[1], val[3], val[5])
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 225)
- def _reduce_54(val, _values)
- n(:Foreach, val[0], val[2], val[4], val[6])
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 229)
- def _reduce_55(val, _values)
- n(:If, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 231)
- def _reduce_56(val, _values)
- n(:If, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 235)
- def _reduce_57(val, _values)
- n(:Repeat, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 239)
- def _reduce_58(val, _values)
- n(:While, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 247)
- def _reduce_59(val, _values)
- n(:Assignment, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 249)
- def _reduce_60(val, _values)
- n(:Assignment, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 251)
- def _reduce_61(val, _values)
- n(:Assignment, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 253)
- def _reduce_62(val, _values)
- n(:Assignment, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 255)
- def _reduce_63(val, _values)
- n(:Assignment, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 257)
- def _reduce_64(val, _values)
- n(:Assignment, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 259)
- def _reduce_65(val, _values)
- n(:Assignment, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 261)
- def _reduce_66(val, _values)
- n(:Assignment, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 263)
- def _reduce_67(val, _values)
- n(:Assignment, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 265)
- def _reduce_68(val, _values)
- n(:Assignment, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 269)
- def _reduce_69(val, _values)
- n(:Call, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 271)
- def _reduce_70(val, _values)
- n(:Call, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 275)
- def _reduce_71(val, _values)
- n(:Decrement, val[0])
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 277)
- def _reduce_72(val, _values)
- n(:Decrement, val[0])
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 281)
- def _reduce_73(val, _values)
- n(:Increment, val[0])
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 283)
- def _reduce_74(val, _values)
- n(:Increment, val[0])
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 287)
- def _reduce_75(val, _values)
- n(:Expression, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 289)
- def _reduce_76(val, _values)
- n(:Expression, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 291)
- def _reduce_77(val, _values)
- n(:Expression, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 293)
- def _reduce_78(val, _values)
- n(:Expression, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 295)
- def _reduce_79(val, _values)
- n(:Expression, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 297)
- def _reduce_80(val, _values)
- n(:Expression, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 299)
- def _reduce_81(val, _values)
- n(:Expression, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 301)
- def _reduce_82(val, _values)
- n(:Expression, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 303)
- def _reduce_83(val, _values)
- n(:Expression, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 305)
- def _reduce_84(val, _values)
- n(:Expression, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 307)
- def _reduce_85(val, _values)
- n(:Expression, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 309)
- def _reduce_86(val, _values)
- n(:Expression, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 311)
- def _reduce_87(val, _values)
- n(:Expression, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 313)
- def _reduce_88(val, _values)
- n(:Expression, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 315)
- def _reduce_89(val, _values)
- n(:Expression, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 317)
- def _reduce_90(val, _values)
- n(:Expression, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 319)
- def _reduce_91(val, _values)
- n(:Expression, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 321)
- def _reduce_92(val, _values)
- n(:Expression, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 323)
- def _reduce_93(val, _values)
- val[0]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 325)
- def _reduce_94(val, _values)
- val[0]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 327)
- def _reduce_95(val, _values)
- n(:Expression, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 329)
- def _reduce_96(val, _values)
- n(:Expression, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 331)
- def _reduce_97(val, _values)
- n(:Expression, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 333)
- def _reduce_98(val, _values)
- n(:Expression, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 335)
- def _reduce_99(val, _values)
- n(:Expression, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 337)
- def _reduce_100(val, _values)
- n(:Expression, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 339)
- def _reduce_101(val, _values)
- n(:Expression, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 341)
- def _reduce_102(val, _values)
- n(:Expression, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 343)
- def _reduce_103(val, _values)
- n(:Expression, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 345)
- def _reduce_104(val, _values)
- n(:Expression, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 347)
- def _reduce_105(val, _values)
- val[0]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 349)
- def _reduce_106(val, _values)
- val[0]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 351)
- def _reduce_107(val, _values)
- val[0]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 353)
- def _reduce_108(val, _values)
- val[0]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 355)
- def _reduce_109(val, _values)
- val[0]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 357)
- def _reduce_110(val, _values)
- val[0]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 359)
- def _reduce_111(val, _values)
- val[0]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 361)
- def _reduce_112(val, _values)
- val[0]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 363)
- def _reduce_113(val, _values)
- val[0]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 371)
- def _reduce_114(val, _values)
- n(:Argument, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 373)
- def _reduce_115(val, _values)
- n(:Argument, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 375)
- def _reduce_116(val, _values)
- n(:Argument, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 377)
- def _reduce_117(val, _values)
- n(:Argument, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 381)
- def _reduce_118(val, _values)
- n(:KeyValuePair, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 383)
- def _reduce_119(val, _values)
- n(:KeyValuePair, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 385)
- def _reduce_120(val, _values)
- n(:KeyValuePair, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 387)
- def _reduce_121(val, _values)
- n(:KeyValuePair, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 389)
- def _reduce_122(val, _values)
- n(:KeyValuePair, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 391)
- def _reduce_123(val, _values)
- n(:KeyValuePair, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 395)
- def _reduce_124(val, _values)
- [val[0]] + val[2]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 397)
- def _reduce_125(val, _values)
- [val[0]]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 399)
- def _reduce_126(val, _values)
- [val[0]]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 403)
- def _reduce_127(val, _values)
- n(:Lvalue, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 405)
- def _reduce_128(val, _values)
- n(:Lvalue, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 409)
- def _reduce_129(val, _values)
- n(:Reference, val[1])
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 417)
- def _reduce_130(val, _values)
- [val[0]] + val[2]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 419)
- def _reduce_131(val, _values)
- [val[0]]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 423)
- def _reduce_132(val, _values)
- n(:Array, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 425)
- def _reduce_133(val, _values)
- n(:Array, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 429)
- def _reduce_134(val, _values)
- val[0]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 431)
- def _reduce_135(val, _values)
- val[0]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 433)
- def _reduce_136(val, _values)
- val[0]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 435)
- def _reduce_137(val, _values)
- val[0]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 437)
- def _reduce_138(val, _values)
- nil
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 441)
- def _reduce_139(val, _values)
- val[1]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 443)
- def _reduce_140(val, _values)
- val[1]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 447)
- def _reduce_141(val, _values)
- [val[0]] + val[1]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 449)
- def _reduce_142(val, _values)
- [val[0]]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 453)
- def _reduce_143(val, _values)
- val[0]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 455)
- def _reduce_144(val, _values)
- val[0]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 459)
- def _reduce_145(val, _values)
- [val[0]] + val[2]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 461)
- def _reduce_146(val, _values)
- [val[0]]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 465)
- def _reduce_147(val, _values)
- n(:List, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 467)
- def _reduce_148(val, _values)
- n(:List, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 471)
- def _reduce_149(val, _values)
- n(:Parameter, val[1], 'reference')
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 473)
- def _reduce_150(val, _values)
- n(:Parameter, val[0], 'value')
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 477)
- def _reduce_151(val, _values)
- [val[0]] + val[2]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 479)
- def _reduce_152(val, _values)
- [val[0]]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 483)
- def _reduce_153(val, _values)
- [val[0]] + val[1]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 485)
- def _reduce_154(val, _values)
- [val[0]]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 489)
- def _reduce_155(val, _values)
- n(:Assignment, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 491)
- def _reduce_156(val, _values)
- n(:Assignment, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 493)
- def _reduce_157(val, _values)
- val[0]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 497)
- def _reduce_158(val, _values)
- [val[0]] + val[2]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 499)
- def _reduce_159(val, _values)
- [val[0]]
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 507)
- def _reduce_160(val, _values)
- n(:Identifier, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 509)
- def _reduce_161(val, _values)
- n(:Identifier, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 511)
- def _reduce_162(val, _values)
- n(:Identifier, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 515)
- def _reduce_163(val, _values)
- n(:Integer, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 517)
- def _reduce_164(val, _values)
- n(:Integer, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 519)
- def _reduce_165(val, _values)
- n(:Integer, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 521)
- def _reduce_166(val, _values)
- n(:Integer, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 523)
- def _reduce_167(val, _values)
- n(:Integer, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 527)
- def _reduce_168(val, _values)
- n(:Ip, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 530)
- def _reduce_169(val, _values)
- n(:String, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 532)
- def _reduce_170(val, _values)
- n(:String, *val)
- end
-.,.,
-
-module_eval(<<'.,.,', 'nasl.y', 536)
- def _reduce_171(val, _values)
- n(:Undefined, *val)
- end
-.,.,
-
-def _reduce_none(val, _values)
- val[0]
-end
-
- end # class Grammar
-end # module Nasl
-
-
diff --git a/test/racc/regress/nokogiri-css b/test/racc/regress/nokogiri-css
deleted file mode 100644
index bc2faf8702..0000000000
--- a/test/racc/regress/nokogiri-css
+++ /dev/null
@@ -1,836 +0,0 @@
-#
-# DO NOT MODIFY!!!!
-# This file is automatically generated by Racc 1.5.0
-# from Racc grammar file "".
-#
-
-require 'racc/parser.rb'
-
-
-require 'nokogiri/css/parser_extras'
-module Nokogiri
- module CSS
- class Parser < Racc::Parser
-##### State transition tables begin ###
-
-racc_action_table = [
- 24, 93, 56, 57, 33, 55, 94, 23, 24, 22,
- 12, 93, 33, 27, 35, 52, 44, 22, -23, 25,
- 45, 98, 23, 33, 26, 18, 20, 25, 27, -23,
- 23, 24, 26, 18, 20, 33, 27, 11, 39, 24,
- 22, 23, 74, 33, 18, 91, 90, 27, 22, 12,
- 25, 24, -23, 23, 85, 26, 18, 20, 25, 27,
- 66, 23, 24, 26, 18, 20, 33, 27, 101, 100,
- 51, 22, 86, 88, 24, 26, 56, 87, 89, 60,
- 92, 25, 95, 46, 23, 49, 26, 18, 20, 90,
- 27, 33, 33, 51, 96, 99, 56, 58, 26, 60,
- 102, 103, 33, 33, 33, 93, 39, 39, 105, 23,
- 23, 108, 18, 18, 20, 27, 27, 39, 39, 39,
- 23, 23, 23, 18, 18, 18, 27, 27, 27, 33,
- 33, 56, 87, 109, 60, 22, 56, 87, nil, 60,
- 33, nil, nil, nil, 39, 39, nil, 23, 23, nil,
- 18, 18, 20, 27, 27, 39, 82, 83, 23, 56,
- 87, 18, 60, nil, 27, 82, 83, 78, 79, 80,
- nil, 81, nil, nil, nil, 77, 78, 79, 80, nil,
- 81, 4, 5, 10, 77, 4, 5, 43, nil, nil,
- nil, 6, nil, 8, 7, 6, nil, 8, 7, 4,
- 5, 10, nil, nil, nil, nil, nil, nil, nil, 6,
- nil, 8, 7 ]
-
-racc_action_check = [
- 3, 58, 24, 24, 3, 24, 57, 15, 9, 3,
- 64, 57, 9, 15, 11, 24, 18, 9, 58, 3,
- 21, 64, 3, 14, 3, 3, 3, 9, 3, 22,
- 9, 12, 9, 9, 9, 12, 9, 1, 14, 42,
- 12, 14, 45, 42, 14, 55, 55, 14, 42, 1,
- 12, 27, 46, 12, 49, 12, 12, 12, 42, 12,
- 27, 42, 43, 42, 42, 42, 43, 42, 76, 76,
- 27, 43, 50, 53, 23, 27, 51, 51, 54, 51,
- 56, 43, 59, 23, 43, 23, 43, 43, 43, 60,
- 43, 28, 25, 23, 61, 75, 25, 25, 23, 25,
- 84, 86, 29, 30, 31, 87, 28, 25, 91, 28,
- 25, 94, 28, 25, 25, 28, 25, 29, 30, 31,
- 29, 30, 31, 29, 30, 31, 29, 30, 31, 32,
- 39, 90, 90, 105, 90, 39, 92, 92, nil, 92,
- 62, nil, nil, nil, 32, 39, nil, 32, 39, nil,
- 32, 39, 39, 32, 39, 62, 47, 47, 62, 93,
- 93, 62, 93, nil, 62, 48, 48, 47, 47, 47,
- nil, 47, nil, nil, nil, 47, 48, 48, 48, nil,
- 48, 0, 0, 0, 48, 17, 17, 17, nil, nil,
- nil, 0, nil, 0, 0, 17, nil, 17, 17, 26,
- 26, 26, nil, nil, nil, nil, nil, nil, nil, 26,
- nil, 26, 26 ]
-
-racc_action_pointer = [
- 174, 37, nil, -2, nil, nil, nil, nil, nil, 6,
- nil, 14, 29, nil, 17, -17, nil, 178, 5, nil,
- nil, -9, 0, 72, -8, 86, 192, 49, 85, 96,
- 97, 98, 123, nil, nil, nil, nil, nil, nil, 124,
- nil, nil, 37, 60, nil, 31, 23, 153, 162, 29,
- 43, 66, nil, 50, 55, 34, 68, -1, -11, 59,
- 77, 71, 134, nil, -2, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 70, 58, nil, nil, nil,
- nil, nil, nil, nil, 75, nil, 90, 93, nil, nil,
- 121, 101, 126, 149, 98, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 120, nil, nil, nil, nil ]
-
-racc_action_default = [
- -74, -75, -2, -24, -4, -5, -6, -7, -8, -24,
- -73, -75, -24, -3, -47, -10, -13, -17, -75, -19,
- -20, -75, -22, -24, -75, -24, -74, -75, -53, -54,
- -55, -56, -57, -58, -14, 110, -1, -9, -46, -24,
- -11, -12, -24, -24, -18, -75, -29, -61, -61, -75,
- -75, -75, -30, -75, -75, -38, -39, -40, -22, -75,
- -38, -75, -70, -72, -75, -44, -45, -48, -49, -50,
- -51, -52, -15, -16, -21, -75, -75, -62, -63, -64,
- -65, -66, -67, -68, -75, -27, -75, -40, -31, -32,
- -75, -43, -75, -75, -75, -33, -69, -71, -34, -25,
- -59, -60, -26, -28, -35, -75, -36, -37, -42, -41 ]
-
-racc_goto_table = [
- 53, 38, 13, 1, 42, 48, 62, 37, 34, 65,
- 40, 36, 63, 75, 84, 67, 68, 69, 70, 71,
- 62, 41, 50, 47, 54, nil, 63, nil, nil, 64,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 72, 73, nil, nil, nil, nil, nil, nil, 97,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 104, nil, 106, 107 ]
-
-racc_goto_check = [
- 18, 12, 2, 1, 5, 9, 7, 8, 2, 9,
- 10, 2, 12, 17, 17, 12, 12, 12, 12, 12,
- 7, 11, 15, 16, 19, nil, 12, nil, nil, 1,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 2, 2, nil, nil, nil, nil, nil, nil, 12,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 18, nil, 18, 18 ]
-
-racc_goto_pointer = [
- nil, 3, -1, nil, nil, -13, nil, -19, -7, -18,
- -5, 6, -13, nil, nil, -1, 0, -34, -24, 0,
- nil, nil, nil, nil ]
-
-racc_goto_default = [
- nil, nil, nil, 2, 3, 9, 17, 14, nil, 15,
- 31, 30, 16, 29, 19, 21, nil, nil, 59, nil,
- 28, 32, 76, 61 ]
-
-racc_reduce_table = [
- 0, 0, :racc_error,
- 3, 32, :_reduce_1,
- 1, 32, :_reduce_2,
- 2, 32, :_reduce_3,
- 1, 36, :_reduce_4,
- 1, 36, :_reduce_5,
- 1, 36, :_reduce_6,
- 1, 36, :_reduce_7,
- 1, 36, :_reduce_8,
- 2, 37, :_reduce_9,
- 1, 37, :_reduce_none,
- 2, 37, :_reduce_11,
- 2, 37, :_reduce_12,
- 1, 37, :_reduce_13,
- 2, 34, :_reduce_14,
- 3, 33, :_reduce_15,
- 3, 33, :_reduce_16,
- 1, 33, :_reduce_none,
- 2, 44, :_reduce_18,
- 1, 38, :_reduce_none,
- 1, 38, :_reduce_20,
- 3, 45, :_reduce_21,
- 1, 45, :_reduce_22,
- 1, 46, :_reduce_23,
- 0, 46, :_reduce_none,
- 4, 42, :_reduce_25,
- 4, 42, :_reduce_26,
- 3, 42, :_reduce_27,
- 3, 47, :_reduce_28,
- 1, 47, :_reduce_29,
- 2, 40, :_reduce_30,
- 3, 40, :_reduce_31,
- 3, 40, :_reduce_32,
- 3, 40, :_reduce_33,
- 3, 40, :_reduce_34,
- 3, 49, :_reduce_35,
- 3, 49, :_reduce_36,
- 3, 49, :_reduce_37,
- 1, 49, :_reduce_none,
- 1, 49, :_reduce_none,
- 1, 49, :_reduce_40,
- 4, 50, :_reduce_41,
- 3, 50, :_reduce_42,
- 2, 50, :_reduce_43,
- 2, 41, :_reduce_44,
- 2, 41, :_reduce_45,
- 1, 39, :_reduce_none,
- 0, 39, :_reduce_none,
- 2, 43, :_reduce_48,
- 2, 43, :_reduce_49,
- 2, 43, :_reduce_50,
- 2, 43, :_reduce_51,
- 2, 43, :_reduce_52,
- 1, 43, :_reduce_none,
- 1, 43, :_reduce_none,
- 1, 43, :_reduce_none,
- 1, 43, :_reduce_none,
- 1, 43, :_reduce_none,
- 1, 51, :_reduce_58,
- 2, 48, :_reduce_59,
- 2, 48, :_reduce_60,
- 0, 48, :_reduce_none,
- 1, 53, :_reduce_62,
- 1, 53, :_reduce_63,
- 1, 53, :_reduce_64,
- 1, 53, :_reduce_65,
- 1, 53, :_reduce_66,
- 1, 53, :_reduce_67,
- 1, 53, :_reduce_68,
- 3, 52, :_reduce_69,
- 1, 54, :_reduce_none,
- 2, 54, :_reduce_none,
- 1, 54, :_reduce_none,
- 1, 35, :_reduce_none,
- 0, 35, :_reduce_none ]
-
-racc_reduce_n = 75
-
-racc_shift_n = 110
-
-racc_token_table = {
- false => 0,
- :error => 1,
- :FUNCTION => 2,
- :INCLUDES => 3,
- :DASHMATCH => 4,
- :LBRACE => 5,
- :HASH => 6,
- :PLUS => 7,
- :GREATER => 8,
- :S => 9,
- :STRING => 10,
- :IDENT => 11,
- :COMMA => 12,
- :NUMBER => 13,
- :PREFIXMATCH => 14,
- :SUFFIXMATCH => 15,
- :SUBSTRINGMATCH => 16,
- :TILDE => 17,
- :NOT_EQUAL => 18,
- :SLASH => 19,
- :DOUBLESLASH => 20,
- :NOT => 21,
- :EQUAL => 22,
- :RPAREN => 23,
- :LSQUARE => 24,
- :RSQUARE => 25,
- :HAS => 26,
- "." => 27,
- "*" => 28,
- "|" => 29,
- ":" => 30 }
-
-racc_nt_base = 31
-
-racc_use_result_var = true
-
-Racc_arg = [
- racc_action_table,
- racc_action_check,
- racc_action_default,
- racc_action_pointer,
- racc_goto_table,
- racc_goto_check,
- racc_goto_default,
- racc_goto_pointer,
- racc_nt_base,
- racc_reduce_table,
- racc_token_table,
- racc_shift_n,
- racc_reduce_n,
- racc_use_result_var ]
-
-Racc_token_to_s_table = [
- "$end",
- "error",
- "FUNCTION",
- "INCLUDES",
- "DASHMATCH",
- "LBRACE",
- "HASH",
- "PLUS",
- "GREATER",
- "S",
- "STRING",
- "IDENT",
- "COMMA",
- "NUMBER",
- "PREFIXMATCH",
- "SUFFIXMATCH",
- "SUBSTRINGMATCH",
- "TILDE",
- "NOT_EQUAL",
- "SLASH",
- "DOUBLESLASH",
- "NOT",
- "EQUAL",
- "RPAREN",
- "LSQUARE",
- "RSQUARE",
- "HAS",
- "\".\"",
- "\"*\"",
- "\"|\"",
- "\":\"",
- "$start",
- "selector",
- "simple_selector_1toN",
- "prefixless_combinator_selector",
- "optional_S",
- "combinator",
- "simple_selector",
- "element_name",
- "hcap_0toN",
- "function",
- "pseudo",
- "attrib",
- "hcap_1toN",
- "class",
- "namespaced_ident",
- "namespace",
- "attrib_name",
- "attrib_val_0or1",
- "expr",
- "nth",
- "attribute_id",
- "negation",
- "eql_incl_dash",
- "negation_arg" ]
-
-Racc_debug_parser = false
-
-##### State transition tables end #####
-
-# reduce 0 omitted
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 9)
- def _reduce_1(val, _values, result)
- result = [val.first, val.last].flatten
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 11)
- def _reduce_2(val, _values, result)
- result = val.flatten
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 12)
- def _reduce_3(val, _values, result)
- result = [val.last].flatten
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 15)
- def _reduce_4(val, _values, result)
- result = :DIRECT_ADJACENT_SELECTOR
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 16)
- def _reduce_5(val, _values, result)
- result = :CHILD_SELECTOR
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 17)
- def _reduce_6(val, _values, result)
- result = :FOLLOWING_SELECTOR
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 18)
- def _reduce_7(val, _values, result)
- result = :DESCENDANT_SELECTOR
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 19)
- def _reduce_8(val, _values, result)
- result = :CHILD_SELECTOR
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 23)
- def _reduce_9(val, _values, result)
- result = if val[1].nil?
- val.first
- else
- Node.new(:CONDITIONAL_SELECTOR, [val.first, val[1]])
- end
-
- result
- end
-.,.,
-
-# reduce 10 omitted
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 31)
- def _reduce_11(val, _values, result)
- result = Node.new(:CONDITIONAL_SELECTOR, val)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 34)
- def _reduce_12(val, _values, result)
- result = Node.new(:CONDITIONAL_SELECTOR, val)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 37)
- def _reduce_13(val, _values, result)
- result = Node.new(:CONDITIONAL_SELECTOR,
- [Node.new(:ELEMENT_NAME, ['*']), val.first]
- )
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 44)
- def _reduce_14(val, _values, result)
- result = Node.new(val.first, [nil, val.last])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 49)
- def _reduce_15(val, _values, result)
- result = Node.new(val[1], [val.first, val.last])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 52)
- def _reduce_16(val, _values, result)
- result = Node.new(:DESCENDANT_SELECTOR, [val.first, val.last])
-
- result
- end
-.,.,
-
-# reduce 17 omitted
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 57)
- def _reduce_18(val, _values, result)
- result = Node.new(:CLASS_CONDITION, [val[1]])
- result
- end
-.,.,
-
-# reduce 19 omitted
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 61)
- def _reduce_20(val, _values, result)
- result = Node.new(:ELEMENT_NAME, val)
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 65)
- def _reduce_21(val, _values, result)
- result = Node.new(:ELEMENT_NAME,
- [[val.first, val.last].compact.join(':')]
- )
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 70)
- def _reduce_22(val, _values, result)
- name = @namespaces.key?('xmlns') ? "xmlns:#{val.first}" : val.first
- result = Node.new(:ELEMENT_NAME, [name])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 75)
- def _reduce_23(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-# reduce 24 omitted
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 80)
- def _reduce_25(val, _values, result)
- result = Node.new(:ATTRIBUTE_CONDITION,
- [val[1]] + (val[2] || [])
- )
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 85)
- def _reduce_26(val, _values, result)
- result = Node.new(:ATTRIBUTE_CONDITION,
- [val[1]] + (val[2] || [])
- )
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 90)
- def _reduce_27(val, _values, result)
- # Non standard, but hpricot supports it.
- result = Node.new(:PSEUDO_CLASS,
- [Node.new(:FUNCTION, ['nth-child(', val[1]])]
- )
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 98)
- def _reduce_28(val, _values, result)
- result = Node.new(:ELEMENT_NAME,
- [[val.first, val.last].compact.join(':')]
- )
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 103)
- def _reduce_29(val, _values, result)
- # Default namespace is not applied to attributes.
- # So we don't add prefix "xmlns:" as in namespaced_ident.
- result = Node.new(:ELEMENT_NAME, [val.first])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 110)
- def _reduce_30(val, _values, result)
- result = Node.new(:FUNCTION, [val.first.strip])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 113)
- def _reduce_31(val, _values, result)
- result = Node.new(:FUNCTION, [val.first.strip, val[1]].flatten)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 116)
- def _reduce_32(val, _values, result)
- result = Node.new(:FUNCTION, [val.first.strip, val[1]].flatten)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 119)
- def _reduce_33(val, _values, result)
- result = Node.new(:FUNCTION, [val.first.strip, val[1]].flatten)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 122)
- def _reduce_34(val, _values, result)
- result = Node.new(:FUNCTION, [val.first.strip, val[1]].flatten)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 126)
- def _reduce_35(val, _values, result)
- result = [val.first, val.last]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 127)
- def _reduce_36(val, _values, result)
- result = [val.first, val.last]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 128)
- def _reduce_37(val, _values, result)
- result = [val.first, val.last]
- result
- end
-.,.,
-
-# reduce 38 omitted
-
-# reduce 39 omitted
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 133)
- def _reduce_40(val, _values, result)
- case val[0]
- when 'even'
- result = Node.new(:NTH, ['2','n','+','0'])
- when 'odd'
- result = Node.new(:NTH, ['2','n','+','1'])
- when 'n'
- result = Node.new(:NTH, ['1','n','+','0'])
- else
- # This is not CSS standard. It allows us to support this:
- # assert_xpath("//a[foo(., @href)]", @parser.parse('a:foo(@href)'))
- # assert_xpath("//a[foo(., @a, b)]", @parser.parse('a:foo(@a, b)'))
- # assert_xpath("//a[foo(., a, 10)]", @parser.parse('a:foo(a, 10)'))
- result = val
- end
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 152)
- def _reduce_41(val, _values, result)
- if val[1] == 'n'
- result = Node.new(:NTH, val)
- else
- raise Racc::ParseError, "parse error on IDENT '#{val[1]}'"
- end
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 158)
- def _reduce_42(val, _values, result)
- # n+3, -n+3
- if val[0] == 'n'
- val.unshift("1")
- result = Node.new(:NTH, val)
- elsif val[0] == '-n'
- val[0] = 'n'
- val.unshift("-1")
- result = Node.new(:NTH, val)
- else
- raise Racc::ParseError, "parse error on IDENT '#{val[1]}'"
- end
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 170)
- def _reduce_43(val, _values, result)
- # 5n, -5n, 10n-1
- n = val[1]
- if n[0, 2] == 'n-'
- val[1] = 'n'
- val << "-"
- # b is contained in n as n is the string "n-b"
- val << n[2, n.size]
- result = Node.new(:NTH, val)
- elsif n == 'n'
- val << "+"
- val << "0"
- result = Node.new(:NTH, val)
- else
- raise Racc::ParseError, "parse error on IDENT '#{val[1]}'"
- end
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 189)
- def _reduce_44(val, _values, result)
- result = Node.new(:PSEUDO_CLASS, [val[1]])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 191)
- def _reduce_45(val, _values, result)
- result = Node.new(:PSEUDO_CLASS, [val[1]])
- result
- end
-.,.,
-
-# reduce 46 omitted
-
-# reduce 47 omitted
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 199)
- def _reduce_48(val, _values, result)
- result = Node.new(:COMBINATOR, val)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 202)
- def _reduce_49(val, _values, result)
- result = Node.new(:COMBINATOR, val)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 205)
- def _reduce_50(val, _values, result)
- result = Node.new(:COMBINATOR, val)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 208)
- def _reduce_51(val, _values, result)
- result = Node.new(:COMBINATOR, val)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 211)
- def _reduce_52(val, _values, result)
- result = Node.new(:COMBINATOR, val)
-
- result
- end
-.,.,
-
-# reduce 53 omitted
-
-# reduce 54 omitted
-
-# reduce 55 omitted
-
-# reduce 56 omitted
-
-# reduce 57 omitted
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 220)
- def _reduce_58(val, _values, result)
- result = Node.new(:ID, val)
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 223)
- def _reduce_59(val, _values, result)
- result = [val.first, val[1]]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 224)
- def _reduce_60(val, _values, result)
- result = [val.first, val[1]]
- result
- end
-.,.,
-
-# reduce 61 omitted
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 228)
- def _reduce_62(val, _values, result)
- result = :equal
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 229)
- def _reduce_63(val, _values, result)
- result = :prefix_match
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 230)
- def _reduce_64(val, _values, result)
- result = :suffix_match
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 231)
- def _reduce_65(val, _values, result)
- result = :substring_match
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 232)
- def _reduce_66(val, _values, result)
- result = :not_equal
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 233)
- def _reduce_67(val, _values, result)
- result = :includes
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 234)
- def _reduce_68(val, _values, result)
- result = :dash_match
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'nokogiri-css.y', 238)
- def _reduce_69(val, _values, result)
- result = Node.new(:NOT, [val[1]])
-
- result
- end
-.,.,
-
-# reduce 70 omitted
-
-# reduce 71 omitted
-
-# reduce 72 omitted
-
-# reduce 73 omitted
-
-# reduce 74 omitted
-
-def _reduce_none(val, _values, result)
- val[0]
-end
-
- end # class Parser
- end # module CSS
-end # module Nokogiri
diff --git a/test/racc/regress/opal b/test/racc/regress/opal
deleted file mode 100644
index 53420a8f0e..0000000000
--- a/test/racc/regress/opal
+++ /dev/null
@@ -1,10107 +0,0 @@
-#
-# DO NOT MODIFY!!!!
-# This file is automatically generated by Racc 1.5.2
-# from Racc grammar file "".
-#
-
-require 'racc/parser.rb'
-module Opal
- class Parser < Racc::Parser
-
-module_eval(<<'...end opal.y/module_eval...', 'opal.y', 1808)
-
-...end opal.y/module_eval...
-##### State transition tables begin ###
-
-racc_action_table = [
- 63, 64, 65, 8, 51, 575, 552, -92, 57, 58,
- 619, 205, 206, 61, 73, 59, 60, 62, 23, 24,
- 66, 67, 74, 544, 754, 607, 543, 22, 28, 27,
- 90, 89, 91, 92, 97, 751, 17, 607, 273, -458,
- 612, 653, 7, 41, 6, 9, 94, 93, 575, 84,
- 50, 86, 85, 87, 273, 88, 95, 96, 653, 81,
- 82, -100, 38, 39, -99, -68, 597, -446, 344, 343,
- -95, 205, 206, 618, -446, 652, -97, 581, 575, 582,
- -94, 205, 206, -96, 575, 36, 609, 608, 30, -92,
- 575, 52, 652, 108, 54, 770, 32, -84, 609, 608,
- 40, 101, -79, -92, 268, 752, 100, 195, 18, -100,
- -99, 551, -84, 79, 73, 75, 76, 77, 78, 101,
- -95, 574, 74, 80, 100, 272, -98, 63, 64, 65,
- 56, 51, -97, 53, 653, 57, 58, 196, 37, 83,
- 61, 272, 59, 60, 62, 23, 24, 66, 67, 454,
- -534, 205, 206, 197, 22, 28, 27, 90, 89, 91,
- 92, 308, 101, 17, 574, -84, -91, 100, 652, -90,
- 41, 308, 596, 94, 93, -86, 84, 50, 86, 85,
- 87, -88, 88, 95, 96, -85, 81, 82, -87, 38,
- 39, 101, 101, -535, 574, 900, 100, 100, 101, -100,
- 574, -449, -84, 100, 101, 198, 574, 649, -449, 100,
- -96, -84, 210, 246, -98, 214, 215, -92, 52, -92,
- -91, 54, -92, -100, -99, -100, -99, 40, -100, -99,
- -94, -89, 273, 607, -95, 18, -95, 299, 726, -95,
- 79, 73, 75, 76, 77, 78, -97, -90, -97, 74,
- 80, -97, -86, 726, 63, 64, 65, 56, 51, -88,
- 53, 544, 57, 58, 546, 37, 83, 61, 531, 59,
- 60, 62, 23, 24, 66, 67, 205, 206, 653, 205,
- 206, 22, 28, 27, 90, 89, 91, 92, -91, -534,
- 219, 777, 300, -535, 609, 608, 605, 41, 268, 227,
- 94, 93, 308, 84, 50, 86, 85, 87, 388, 88,
- 95, 96, 652, 81, 82, -90, 38, 39, -99, 272,
- -86, 726, 301, 302, -96, -91, -96, -88, -98, -96,
- -98, 224, 810, -98, -91, 226, 225, -87, 101, 210,
- 725, -93, 214, 100, -94, 52, -94, -85, 54, -94,
- 391, -89, -90, 101, 40, 725, 788, -86, 100, 402,
- 101, -90, 218, 415, -88, 100, -86, 79, 73, 75,
- 76, 77, 78, -88, 453, 101, 74, 80, 455, 204,
- 100, 63, 64, 65, 56, 51, 607, 53, 544, 57,
- 58, 546, 37, 83, 61, 789, 59, 60, 62, 258,
- 259, 66, 67, 876, -534, -87, -95, 877, 257, 28,
- 27, 90, 89, 91, 92, -85, 456, 219, -535, -89,
- -91, 101, 607, 725, 41, 607, 100, 94, 93, -100,
- 84, 50, 86, 85, 87, 261, 88, 95, 96, -456,
- 81, 82, -87, 38, 39, -97, -456, 609, 608, 610,
- 101, -87, -85, -93, 215, 100, -89, -94, 487, 264,
- 265, -85, 754, -455, -454, -89, 210, 266, 489, 214,
- -455, -454, 52, 751, 813, 54, 582, 256, 491, 254,
- 497, 40, -67, 609, 608, 614, 609, 608, 620, 218,
- 400, 401, 203, 201, 79, 73, 75, 76, 77, 78,
- 202, 514, 544, 74, 80, 546, 344, 343, 63, 64,
- 65, 56, 51, 101, 53, -451, 57, 58, 100, 37,
- 83, 61, -451, 59, 60, 62, 258, 259, 66, 67,
- 515, -532, 527, 528, 516, 257, 28, 27, 90, 89,
- 91, 92, 101, 752, 219, -331, -331, 100, 199, 625,
- 200, 41, 525, -331, 94, 93, 277, 84, 50, 86,
- 85, 87, 261, 88, 95, 96, 308, 81, 82, 268,
- 38, 39, 532, 227, 231, 236, 237, 238, 233, 235,
- 243, 244, 239, 240, -449, -449, 220, 221, -452, 101,
- 241, 242, -449, 210, 100, -452, 214, -532, 533, 52,
- 227, -331, 54, -331, 256, 224, 254, 230, 40, 226,
- 225, 222, 223, 234, 232, 228, 218, 229, -532, 203,
- 449, 79, 73, 75, 76, 77, 78, 450, 308, -458,
- 74, 80, 547, 245, 548, 63, 64, 65, 56, 51,
- -449, 53, -449, 57, 58, 491, 37, 83, 61, 555,
- 59, 60, 62, 258, 259, 66, 67, 103, 104, 105,
- 106, 107, 257, 28, 27, 90, 89, 91, 92, -453,
- -84, 219, 524, 521, 531, 452, -453, 451, 41, -92,
- 522, 94, 93, 558, 84, 50, 86, 85, 87, 261,
- 88, 95, 96, 559, 81, 82, 561, 38, 39, 570,
- 227, 231, 236, 237, 238, 233, 235, 243, 244, 239,
- 240, 524, 534, 220, 221, -90, 412, 241, 242, 535,
- 210, 414, 413, 214, -99, 571, 52, 404, 520, 54,
- 523, 256, 224, 254, 230, 40, 226, 225, 222, 223,
- 234, 232, 228, 218, 229, 587, 524, 584, 79, 73,
- 75, 76, 77, 78, 585, 588, 630, 74, 80, 589,
- 245, 650, -255, -255, -255, 56, -255, 452, 53, 451,
- -255, -255, 613, 37, 83, -255, 617, -255, -255, -255,
- -255, -255, -255, -255, 103, 104, 105, 106, 107, -255,
- -255, -255, -255, -255, -255, -255, 621, -86, -255, 524,
- 593, 624, 583, 625, 586, -255, -95, 591, -255, -255,
- 627, -255, -255, -255, -255, -255, -255, -255, -255, -255,
- -263, -255, -255, 628, -255, -255, 629, 227, 231, 236,
- 237, 238, 233, 235, 243, 244, 239, 240, -284, -284,
- 220, 221, 205, 206, 241, 242, -284, -255, 268, 631,
- -255, 268, 227, -255, 227, 592, -255, 523, -255, 224,
- -255, 230, -255, 226, 225, 222, 223, 234, 232, 228,
- -255, 229, 344, 343, 602, -255, -255, -255, -255, -255,
- -255, 603, 832, 813, -255, -255, 776, 245, 227, -233,
- -88, 227, -255, 915, -284, -255, -284, 308, 754, -97,
- -255, -255, 63, 64, 65, 8, 51, 344, 343, 751,
- 57, 58, 832, 813, 670, 61, 671, 59, 60, 62,
- 23, 24, 66, 67, 679, 681, -79, -85, 682, 22,
- 28, 27, 90, 89, 91, 92, -94, 684, 17, 537,
- 341, 340, 344, 343, 7, 41, 227, 9, 94, 93,
- 694, 84, 50, 86, 85, 87, 700, 88, 95, 96,
- 701, 81, 82, 702, 38, 39, 706, 227, 231, 236,
- 237, 238, 233, 235, 243, 244, 239, 240, 224, 752,
- 220, 221, 226, 225, 241, 242, 716, 36, 718, 721,
- 281, 582, 729, 52, 772, -264, 54, 497, 32, 224,
- 497, 230, 40, 226, 225, 222, 223, 234, 232, 228,
- 18, 229, 497, 524, 593, 79, 73, 75, 76, 77,
- 78, 822, 791, 792, 74, 80, 489, 245, 491, 63,
- 64, 65, 56, 51, 800, 53, 802, 57, 58, 803,
- 37, 83, 61, 694, 59, 60, 62, 258, 259, 66,
- 67, 708, 807, 268, 268, 808, 257, 291, 295, 90,
- 89, 91, 92, 268, 227, 219, -286, -286, 227, 592,
- 813, 523, 292, 819, -286, 94, 93, 820, 84, 50,
- 86, 85, 87, 558, 88, 95, 96, 561, 81, 82,
- 823, 327, 824, 336, 334, 333, 561, 335, 341, 340,
- 344, 343, 827, 866, 867, -283, -283, 868, 95, 96,
- 813, 836, 837, -283, 289, 839, 840, 286, -535, -534,
- 52, 842, -286, 54, -286, 285, 850, 852, 855, 856,
- 338, 858, 915, 860, 862, 864, -265, 754, 341, 340,
- 344, 343, 79, 73, 75, 76, 77, 78, 751, 794,
- 878, 74, 80, 879, 880, 881, 63, 64, 65, 56,
- 51, -283, 53, -283, 57, 58, 883, 296, 83, 61,
- 884, 59, 60, 62, 258, 259, 66, 67, 708, 341,
- 340, 344, 343, 257, 291, 295, 90, 89, 91, 92,
- 524, 946, 219, 103, 104, 105, 106, 107, 947, 292,
- 227, 694, 94, 93, 886, 84, 50, 86, 85, 87,
- -263, 88, 95, 96, 890, 81, 82, 764, 752, 336,
- 334, 333, 754, 335, 895, 341, 340, 344, 343, 897,
- 903, 905, 224, 751, 906, 308, 226, 225, 222, 223,
- 919, 289, -266, 921, 214, -535, 945, 52, 586, 563,
- 54, 336, 334, 333, 561, 335, 338, 749, 931, 932,
- 937, 855, 939, 860, 341, 340, 344, 343, 860, 79,
- 73, 75, 76, 77, 78, 862, 948, 954, 74, 80,
- 700, 964, 860, 298, 966, 967, 56, nil, nil, 53,
- nil, nil, nil, nil, 296, 83, 63, 64, 65, 227,
- 51, nil, nil, 752, 57, 58, nil, nil, nil, 61,
- nil, 59, 60, 62, 258, 259, 66, 67, nil, nil,
- nil, nil, nil, 257, 291, 295, 90, 89, 91, 92,
- nil, 224, 219, nil, nil, 226, 225, 222, 223, 41,
- nil, nil, 94, 93, nil, 84, 50, 86, 85, 87,
- nil, 88, 95, 96, nil, 81, 82, nil, 38, 39,
- nil, 227, 231, 236, 237, 238, 233, 235, 243, 244,
- 239, 240, nil, nil, 220, 221, nil, nil, 241, 242,
- nil, 210, nil, nil, 214, nil, nil, 52, nil, nil,
- 54, nil, nil, 224, nil, 230, 40, 226, 225, 222,
- 223, 234, 232, 228, 218, 229, nil, nil, nil, 79,
- 73, 75, 76, 77, 78, nil, nil, nil, 74, 80,
- nil, 245, nil, 63, 64, 65, 56, 51, nil, 53,
- nil, 57, 58, nil, 37, 83, 61, nil, 59, 60,
- 62, 258, 259, 66, 67, nil, nil, nil, nil, nil,
- 257, 291, 295, 90, 89, 91, 92, nil, 563, 219,
- 336, 334, 333, nil, 335, nil, 41, nil, nil, 94,
- 93, nil, 84, 50, 86, 85, 87, nil, 88, 95,
- 96, nil, 81, 82, nil, 38, 39, nil, 227, 231,
- 236, 237, 238, 233, 235, 243, 244, 239, 240, nil,
- nil, 220, 221, nil, nil, 241, 242, nil, 210, nil,
- nil, 214, nil, nil, 52, nil, nil, 54, nil, nil,
- 224, nil, 230, 40, 226, 225, 222, 223, 234, 232,
- 228, 218, 229, nil, nil, nil, 79, 73, 75, 76,
- 77, 78, nil, nil, nil, 74, 80, nil, 245, nil,
- 63, 64, 65, 56, 51, nil, 53, nil, 57, 58,
- nil, 37, 83, 61, nil, 59, 60, 62, 258, 259,
- 66, 67, nil, nil, nil, nil, nil, 257, 291, 295,
- 90, 89, 91, 92, nil, nil, 219, nil, nil, nil,
- nil, nil, nil, 41, nil, nil, 94, 93, nil, 84,
- 50, 86, 85, 87, nil, 88, 95, 96, nil, 81,
- 82, nil, 38, 39, nil, 227, 231, 236, 237, 238,
- 233, 235, 243, 244, 239, 240, nil, nil, 220, 221,
- nil, nil, 241, 242, nil, 210, nil, nil, 214, nil,
- nil, 52, nil, nil, 54, nil, nil, 224, nil, 230,
- 40, 226, 225, 222, 223, 234, 232, 228, 218, 229,
- nil, nil, nil, 79, 73, 75, 76, 77, 78, nil,
- nil, nil, 74, 80, nil, 245, nil, 63, 64, 65,
- 56, 51, nil, 53, nil, 57, 58, nil, 37, 83,
- 61, nil, 59, 60, 62, 23, 24, 66, 67, nil,
- nil, nil, nil, nil, 22, 28, 27, 90, 89, 91,
- 92, nil, nil, 17, nil, nil, nil, nil, nil, nil,
- 41, nil, nil, 94, 93, nil, 84, 50, 86, 85,
- 87, nil, 88, 95, 96, nil, 81, 82, nil, 38,
- 39, nil, 227, 231, 236, 237, 238, 233, 235, 243,
- 244, 239, 240, nil, nil, 220, 221, nil, nil, 241,
- 242, nil, 210, nil, nil, 214, nil, nil, 52, nil,
- nil, 54, nil, nil, 224, nil, 230, 40, 226, 225,
- 222, 223, 234, 232, 228, 18, 229, nil, nil, nil,
- 79, 73, 75, 76, 77, 78, nil, nil, nil, 74,
- 80, nil, 245, nil, 63, 64, 65, 56, 51, nil,
- 53, nil, 57, 58, nil, 37, 83, 61, nil, 59,
- 60, 62, 258, 259, 66, 67, nil, nil, nil, nil,
- nil, 257, 28, 27, 90, 89, 91, 92, nil, nil,
- 219, nil, nil, nil, nil, nil, nil, 41, nil, nil,
- 94, 93, nil, 84, 50, 86, 85, 87, 261, 88,
- 95, 96, nil, 81, 82, nil, 38, 39, nil, 227,
- 231, 236, 237, 238, 233, 235, 243, 244, 239, 240,
- nil, nil, 220, 221, nil, nil, 241, 242, nil, 210,
- nil, nil, 214, nil, nil, 52, nil, nil, 54, nil,
- 256, 224, nil, 230, 40, 226, 225, 222, 223, 234,
- 232, 228, 218, 229, nil, nil, nil, 79, 73, 75,
- 76, 77, 78, nil, nil, nil, 74, 80, nil, 245,
- nil, 63, 64, 65, 56, 51, nil, 53, nil, 57,
- 58, nil, 37, 83, 61, nil, 59, 60, 62, 258,
- 259, 66, 67, nil, nil, nil, nil, nil, 257, 291,
- 295, 90, 89, 91, 92, nil, nil, 219, nil, nil,
- nil, nil, nil, nil, 41, nil, nil, 94, 93, nil,
- 84, 50, 86, 85, 87, 261, 88, 95, 96, nil,
- 81, 82, nil, 38, 39, nil, 227, 231, 236, 237,
- 238, 233, 235, 243, 244, 239, 240, nil, nil, 220,
- 221, nil, nil, 241, 242, nil, 210, nil, nil, 214,
- nil, nil, 52, nil, nil, 54, nil, nil, 224, nil,
- 230, 40, 226, 225, 222, 223, 234, 232, 228, 218,
- 229, nil, nil, nil, 79, 73, 75, 76, 77, 78,
- nil, nil, nil, 74, 80, nil, 245, nil, 63, 64,
- 65, 56, 51, nil, 53, nil, 57, 58, nil, 37,
- 83, 61, nil, 59, 60, 62, 23, 24, 66, 67,
- nil, nil, nil, nil, nil, 22, 28, 27, 90, 89,
- 91, 92, nil, nil, 17, nil, nil, nil, nil, nil,
- nil, 41, nil, nil, 94, 93, nil, 84, 50, 86,
- 85, 87, nil, 88, 95, 96, nil, 81, 82, nil,
- 38, 39, nil, 227, 231, 236, 237, 238, 233, 235,
- 243, 244, 239, 240, nil, nil, 220, 221, nil, nil,
- 241, 242, nil, 210, nil, nil, 214, nil, nil, 52,
- nil, nil, 54, nil, nil, 224, nil, 230, 40, 226,
- 225, 222, 223, 234, 232, 228, 18, 229, nil, nil,
- nil, 79, 73, 75, 76, 77, 78, nil, nil, nil,
- 74, 80, nil, 245, nil, 63, 64, 65, 56, 51,
- nil, 53, nil, 57, 58, nil, 37, 83, 61, nil,
- 59, 60, 62, 23, 24, 66, 67, nil, nil, nil,
- nil, nil, 22, 28, 27, 90, 89, 91, 92, nil,
- nil, 17, nil, nil, nil, nil, nil, nil, 41, nil,
- nil, 94, 93, nil, 84, 50, 86, 85, 87, nil,
- 88, 95, 96, nil, 81, 82, nil, 38, 39, nil,
- 227, 231, 236, 237, 238, 233, 235, 243, 244, 239,
- 240, nil, nil, 220, 221, nil, nil, 241, 242, nil,
- 210, nil, nil, 214, nil, nil, 52, nil, nil, 54,
- nil, nil, 224, nil, 230, 40, 226, 225, 222, 223,
- 234, 232, 228, 18, 229, nil, nil, nil, 79, 73,
- 75, 76, 77, 78, nil, nil, nil, 74, 80, nil,
- 245, nil, 63, 64, 65, 56, 51, nil, 53, nil,
- 57, 58, nil, 37, 83, 61, nil, 59, 60, 62,
- 23, 24, 66, 67, nil, nil, nil, nil, nil, 22,
- 28, 27, 90, 89, 91, 92, nil, nil, 17, nil,
- nil, nil, nil, nil, nil, 41, nil, nil, 94, 93,
- nil, 84, 50, 86, 85, 87, nil, 88, 95, 96,
- nil, 81, 82, nil, 38, 39, nil, 227, 231, 236,
- 237, 238, 233, 235, 243, 244, 239, 240, nil, nil,
- 220, 221, nil, nil, 241, 242, nil, 210, nil, nil,
- 214, nil, nil, 52, nil, nil, 54, nil, nil, 224,
- nil, 230, 40, 226, 225, 222, 223, 234, 232, 228,
- 18, 229, nil, nil, nil, 79, 73, 75, 76, 77,
- 78, nil, nil, nil, 74, 80, 101, 245, nil, -233,
- nil, 100, 56, nil, nil, 53, nil, nil, nil, nil,
- 37, 83, 63, 64, 65, nil, 51, nil, nil, nil,
- 57, 58, nil, nil, nil, 61, nil, 59, 60, 62,
- 258, 259, 66, 67, nil, nil, nil, nil, nil, 257,
- 291, 295, 90, 89, 91, 92, nil, nil, 219, nil,
- nil, nil, nil, nil, nil, 292, nil, nil, 94, 93,
- nil, 84, 50, 86, 85, 87, nil, 88, 95, 96,
- nil, 81, 82, 227, 231, 236, 237, 238, 233, 235,
- 243, 244, 239, 240, 227, nil, 220, 221, nil, nil,
- 241, 242, nil, nil, nil, nil, nil, 356, nil, nil,
- 30, 241, 242, 52, nil, 224, 54, 230, 32, 226,
- 225, 222, 223, 234, 232, 228, 224, 229, 230, nil,
- 226, 225, 222, 223, nil, 79, 73, 75, 76, 77,
- 78, nil, nil, 245, 74, 80, nil, nil, nil, 63,
- 64, 65, 56, 51, nil, 53, nil, 57, 58, nil,
- 296, 83, 61, nil, 59, 60, 62, 258, 259, 66,
- 67, nil, nil, nil, nil, nil, 257, 291, 295, 90,
- 89, 91, 92, nil, nil, 219, nil, nil, nil, nil,
- nil, nil, 292, nil, nil, 94, 93, nil, 84, 50,
- 86, 85, 361, nil, 88, 95, 96, nil, 81, 82,
- 227, 231, 236, 237, 238, 233, 235, 243, 244, 239,
- 240, 227, nil, 220, 221, nil, nil, 241, 242, nil,
- nil, 367, nil, nil, 362, nil, nil, 214, 241, 242,
- 52, nil, 224, 54, 230, nil, 226, 225, 222, 223,
- 234, 232, 228, 224, 229, 230, nil, 226, 225, 222,
- 223, nil, 79, 73, 75, 76, 77, 78, nil, nil,
- 245, 74, 80, nil, nil, nil, -531, -531, -531, 56,
- -531, nil, 53, nil, -531, -531, nil, 296, 83, -531,
- nil, -531, -531, -531, -531, -531, -531, -531, nil, -531,
- nil, nil, nil, -531, -531, -531, -531, -531, -531, -531,
- nil, nil, -531, nil, nil, nil, nil, nil, nil, -531,
- nil, nil, -531, -531, nil, -531, -531, -531, -531, -531,
- -531, -531, -531, -531, nil, -531, -531, nil, -531, -531,
- nil, 227, 231, 236, 237, 238, 233, 235, 243, 244,
- 239, 240, nil, nil, 220, 221, nil, nil, 241, 242,
- nil, -531, nil, nil, -531, -531, nil, -531, nil, nil,
- -531, nil, -531, 224, -531, 230, -531, 226, 225, 222,
- 223, 234, 232, 228, -531, 229, -531, nil, nil, -531,
- -531, -531, -531, -531, -531, nil, nil, nil, -531, -531,
- nil, 245, nil, -532, -532, -532, -531, -532, nil, -531,
- nil, -532, -532, nil, -531, -531, -532, nil, -532, -532,
- -532, -532, -532, -532, -532, nil, -532, nil, nil, nil,
- -532, -532, -532, -532, -532, -532, -532, nil, nil, -532,
- nil, nil, nil, nil, nil, nil, -532, nil, nil, -532,
- -532, nil, -532, -532, -532, -532, -532, -532, -532, -532,
- -532, nil, -532, -532, nil, -532, -532, nil, 227, 231,
- 236, 237, 238, 233, 235, 243, 244, 239, 240, nil,
- nil, 220, 221, nil, nil, 241, 242, nil, -532, nil,
- nil, -532, -532, nil, -532, nil, nil, -532, nil, -532,
- 224, -532, 230, -532, 226, 225, 222, 223, 234, 232,
- 228, -532, 229, -532, nil, nil, -532, -532, -532, -532,
- -532, -532, nil, nil, nil, -532, -532, nil, 245, nil,
- nil, nil, nil, -532, nil, nil, -532, nil, nil, nil,
- nil, -532, -532, 63, 64, 65, 8, 51, nil, nil,
- nil, 57, 58, nil, nil, nil, 61, nil, 59, 60,
- 62, 23, 24, 66, 67, nil, nil, nil, nil, nil,
- 22, 28, 27, 90, 89, 91, 92, nil, nil, 17,
- nil, nil, nil, nil, nil, 7, 41, 6, 9, 94,
- 93, nil, 84, 50, 86, 85, 87, nil, 88, 95,
- 96, nil, 81, 82, nil, 38, 39, nil, 227, 231,
- 236, 237, 238, 233, 235, 243, 244, 239, 240, nil,
- nil, 220, 221, nil, nil, 241, 242, nil, 36, nil,
- nil, 30, nil, nil, 52, nil, nil, 54, nil, 32,
- 224, nil, 230, 40, 226, 225, 222, 223, 234, 232,
- 228, 18, 229, nil, nil, nil, 79, 73, 75, 76,
- 77, 78, nil, nil, nil, 74, 80, nil, 245, nil,
- nil, nil, 404, 56, nil, nil, 53, nil, nil, nil,
- nil, 37, 83, 63, 64, 65, nil, 51, nil, nil,
- nil, 57, 58, nil, nil, nil, 61, nil, 59, 60,
- 62, 23, 24, 66, 67, nil, nil, nil, nil, nil,
- 22, 28, 27, 90, 89, 91, 92, nil, 563, 17,
- 336, 334, 333, nil, 335, nil, 41, nil, nil, 94,
- 93, nil, 84, 50, 86, 85, 87, nil, 88, 95,
- 96, nil, 81, 82, nil, 38, 39, 563, nil, 336,
- 334, 333, nil, 335, nil, nil, 563, 566, 336, 334,
- 333, nil, 335, nil, nil, 569, nil, nil, 210, nil,
- nil, 214, nil, nil, 52, nil, nil, 54, nil, nil,
- nil, nil, nil, 40, nil, nil, 566, nil, nil, nil,
- nil, 18, nil, nil, 569, 566, 79, 73, 75, 76,
- 77, 78, nil, 829, nil, 74, 80, nil, nil, nil,
- 63, 64, 65, 56, 51, nil, 53, nil, 57, 58,
- nil, 37, 83, 61, nil, 59, 60, 62, 23, 24,
- 66, 67, nil, nil, nil, nil, nil, 22, 28, 27,
- 90, 89, 91, 92, nil, nil, 17, nil, nil, nil,
- nil, nil, nil, 41, nil, nil, 94, 93, nil, 84,
- 50, 86, 85, 87, nil, 88, 95, 96, nil, 81,
- 82, nil, 38, 39, nil, 227, 231, 236, 237, 238,
- 233, 235, 243, 244, 239, 240, nil, nil, -555, -555,
- nil, nil, 241, 242, nil, 210, nil, nil, 214, nil,
- nil, 52, nil, nil, 54, nil, nil, 224, nil, 230,
- 40, 226, 225, 222, 223, 234, 232, 228, 18, 229,
- nil, nil, nil, 79, 73, 75, 76, 77, 78, nil,
- nil, nil, 74, 80, nil, nil, nil, 63, 64, 65,
- 56, 51, nil, 53, nil, 57, 58, nil, 37, 83,
- 61, nil, 59, 60, 62, 23, 24, 66, 67, nil,
- nil, nil, nil, nil, 22, 28, 27, 90, 89, 91,
- 92, nil, nil, 17, nil, nil, nil, nil, nil, nil,
- 41, nil, nil, 94, 93, nil, 84, 50, 86, 85,
- 87, nil, 88, 95, 96, nil, 81, 82, nil, 38,
- 39, nil, 227, 231, 236, 237, 238, 233, 235, 243,
- 244, 239, 240, nil, nil, -555, -555, nil, nil, 241,
- 242, nil, 210, nil, nil, 214, nil, nil, 52, nil,
- nil, 54, nil, nil, 224, nil, 230, 40, 226, 225,
- 222, 223, 234, 232, 228, 18, 229, nil, nil, nil,
- 79, 73, 75, 76, 77, 78, nil, nil, nil, 74,
- 80, nil, nil, nil, 63, 64, 65, 56, 51, nil,
- 53, nil, 57, 58, nil, 37, 83, 61, nil, 59,
- 60, 62, 23, 24, 66, 67, nil, nil, nil, nil,
- nil, 22, 28, 27, 90, 89, 91, 92, nil, nil,
- 17, nil, nil, nil, nil, nil, nil, 41, nil, nil,
- 94, 93, nil, 84, 50, 86, 85, 87, nil, 88,
- 95, 96, nil, 81, 82, nil, 38, 39, nil, 227,
- -555, -555, -555, -555, 233, 235, nil, nil, -555, -555,
- nil, nil, nil, nil, nil, nil, 241, 242, nil, 210,
- nil, nil, 214, nil, nil, 52, nil, nil, 54, nil,
- nil, 224, nil, 230, 40, 226, 225, 222, 223, 234,
- 232, 228, 18, 229, nil, nil, nil, 79, 73, 75,
- 76, 77, 78, nil, nil, nil, 74, 80, nil, nil,
- nil, nil, nil, nil, 56, nil, nil, 53, nil, nil,
- nil, nil, 37, 83, 63, 64, 65, 8, 51, nil,
- nil, nil, 57, 58, nil, nil, nil, 61, nil, 59,
- 60, 62, 23, 24, 66, 67, nil, nil, nil, nil,
- nil, 22, 28, 27, 90, 89, 91, 92, nil, nil,
- 17, nil, nil, nil, nil, nil, 7, 41, nil, 9,
- 94, 93, nil, 84, 50, 86, 85, 87, nil, 88,
- 95, 96, nil, 81, 82, nil, 38, 39, nil, 227,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 241, 242, nil, 36,
- nil, nil, 30, nil, nil, 52, nil, nil, 54, nil,
- 32, 224, nil, 230, 40, 226, 225, 222, 223, nil,
- nil, 228, 18, 229, nil, nil, nil, 79, 73, 75,
- 76, 77, 78, nil, nil, nil, 74, 80, nil, nil,
- nil, nil, nil, nil, 56, nil, nil, 53, nil, nil,
- nil, nil, 37, 83, 63, 64, 65, 8, 51, nil,
- nil, nil, 57, 58, nil, nil, nil, 61, nil, 59,
- 60, 62, 23, 24, 66, 67, nil, nil, nil, nil,
- nil, 22, 28, 27, 90, 89, 91, 92, nil, nil,
- 17, nil, nil, nil, nil, nil, 7, 41, 6, 9,
- 94, 93, nil, 84, 50, 86, 85, 87, nil, 88,
- 95, 96, nil, 81, 82, nil, 38, 39, nil, 227,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 241, 242, nil, 36,
- nil, nil, 30, nil, nil, 52, nil, nil, 54, nil,
- 32, 224, nil, 230, 40, 226, 225, 222, 223, nil,
- nil, 228, 18, 229, nil, nil, nil, 79, 73, 75,
- 76, 77, 78, nil, nil, nil, 74, 80, nil, nil,
- nil, nil, nil, nil, 56, nil, nil, 53, nil, nil,
- nil, nil, 37, 83, 63, 64, 65, 8, 51, nil,
- nil, nil, 57, 58, nil, nil, nil, 61, nil, 59,
- 60, 62, 23, 24, 66, 67, nil, nil, nil, nil,
- nil, 22, 28, 27, 90, 89, 91, 92, nil, nil,
- 17, nil, nil, nil, nil, nil, 7, 41, nil, 9,
- 94, 93, nil, 84, 50, 86, 85, 87, nil, 88,
- 95, 96, nil, 81, 82, nil, 38, 39, nil, 227,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 241, 242, nil, 36,
- nil, nil, 30, nil, nil, 52, nil, nil, 54, nil,
- 32, 224, nil, 230, 40, 226, 225, 222, 223, nil,
- nil, 228, 18, 229, nil, nil, nil, 79, 73, 75,
- 76, 77, 78, nil, nil, nil, 74, 80, nil, nil,
- nil, 63, 64, 65, 56, 51, nil, 53, nil, 57,
- 58, nil, 37, 83, 61, nil, 59, 60, 62, 23,
- 24, 66, 67, nil, nil, nil, nil, nil, 22, 28,
- 27, 90, 89, 91, 92, nil, nil, 219, nil, nil,
- nil, nil, nil, nil, 41, nil, nil, 94, 93, nil,
- 84, 50, 86, 85, 87, nil, 88, 95, 96, nil,
- 81, 82, nil, 38, 39, nil, 227, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 241, 242, nil, 210, nil, nil, 214,
- nil, nil, 52, nil, nil, 54, nil, 421, 224, nil,
- 230, 40, 226, 225, 222, 223, nil, nil, 228, 218,
- 229, nil, nil, nil, 79, 73, 75, 76, 77, 78,
- nil, nil, nil, 74, 80, nil, nil, nil, 63, 64,
- 65, 56, 51, nil, 53, nil, 57, 58, nil, 37,
- 83, 61, nil, 59, 60, 62, 23, 24, 66, 67,
- nil, nil, nil, nil, nil, 22, 28, 27, 90, 89,
- 91, 92, nil, nil, 219, nil, nil, nil, nil, nil,
- nil, 41, nil, nil, 94, 93, nil, 84, 50, 86,
- 85, 87, nil, 88, 95, 96, nil, 81, 82, nil,
- 38, 39, nil, 227, -555, -555, -555, -555, 233, 235,
- nil, nil, -555, -555, nil, nil, nil, nil, nil, nil,
- 241, 242, nil, 210, nil, nil, 214, nil, nil, 52,
- nil, nil, 54, nil, 421, 224, nil, 230, 40, 226,
- 225, 222, 223, 234, 232, 228, 218, 229, nil, nil,
- nil, 79, 73, 75, 76, 77, 78, nil, nil, nil,
- 74, 80, nil, nil, nil, 63, 64, 65, 56, 51,
- nil, 53, nil, 57, 58, nil, 37, 83, 61, nil,
- 59, 60, 62, 23, 24, 66, 67, nil, nil, nil,
- nil, nil, 22, 28, 27, 90, 89, 91, 92, nil,
- nil, 219, nil, nil, nil, nil, nil, nil, 41, nil,
- nil, 94, 93, nil, 84, 50, 86, 85, 87, nil,
- 88, 95, 96, nil, 81, 82, nil, 38, 39, nil,
- 227, -555, -555, -555, -555, 233, 235, nil, nil, -555,
- -555, nil, nil, nil, nil, nil, nil, 241, 242, nil,
- 210, nil, nil, 214, nil, nil, 52, nil, nil, 54,
- nil, nil, 224, nil, 230, 40, 226, 225, 222, 223,
- 234, 232, 228, 218, 229, nil, nil, nil, 79, 73,
- 75, 76, 77, 78, nil, nil, nil, 74, 80, nil,
- nil, nil, 63, 64, 65, 56, 51, nil, 53, nil,
- 57, 58, nil, 37, 83, 61, nil, 59, 60, 62,
- 258, 259, 66, 67, nil, nil, nil, nil, nil, 257,
- 28, 27, 90, 89, 91, 92, nil, nil, 219, nil,
- nil, nil, nil, nil, nil, 41, nil, nil, 94, 93,
- nil, 84, 50, 86, 85, 87, 261, 88, 95, 96,
- nil, 81, 82, nil, 38, 39, nil, 227, -555, -555,
- -555, -555, 233, 235, nil, nil, -555, -555, nil, nil,
- nil, nil, nil, nil, 241, 242, nil, 210, nil, nil,
- 214, nil, nil, 52, nil, nil, 54, nil, 256, 224,
- nil, 230, 40, 226, 225, 222, 223, 234, 232, 228,
- 218, 229, nil, nil, nil, 79, 73, 75, 76, 77,
- 78, nil, nil, nil, 74, 80, nil, nil, nil, 63,
- 64, 65, 56, 51, nil, 53, nil, 57, 58, nil,
- 37, 83, 61, nil, 59, 60, 62, 258, 259, 66,
- 67, nil, nil, nil, nil, nil, 257, 28, 27, 90,
- 89, 91, 92, nil, nil, 219, nil, nil, nil, nil,
- nil, nil, 41, nil, nil, 94, 93, nil, 84, 50,
- 86, 85, 87, 261, 88, 95, 96, nil, 81, 82,
- nil, 38, 39, nil, 227, -555, -555, -555, -555, 233,
- 235, nil, nil, -555, -555, nil, nil, nil, nil, nil,
- nil, 241, 242, nil, 210, nil, nil, 214, nil, nil,
- 52, nil, nil, 54, nil, 256, 224, nil, 230, 40,
- 226, 225, 222, 223, 234, 232, 228, 218, 229, nil,
- nil, nil, 79, 73, 75, 76, 77, 78, nil, nil,
- nil, 74, 80, nil, nil, nil, 63, 64, 65, 56,
- 51, nil, 53, nil, 57, 58, nil, 37, 83, 61,
- nil, 59, 60, 62, 23, 24, 66, 67, nil, nil,
- nil, nil, nil, 22, 28, 27, 90, 89, 91, 92,
- nil, nil, 219, nil, nil, nil, nil, nil, nil, 41,
- nil, nil, 94, 93, nil, 84, 50, 86, 85, 87,
- nil, 88, 95, 96, nil, 81, 82, nil, 38, 39,
- nil, 227, -555, -555, -555, -555, 233, 235, nil, nil,
- -555, -555, nil, nil, nil, nil, nil, nil, 241, 242,
- nil, 210, nil, nil, 214, nil, nil, 52, nil, nil,
- 54, nil, nil, 224, nil, 230, 40, 226, 225, 222,
- 223, 234, 232, 228, 218, 229, nil, nil, nil, 79,
- 73, 75, 76, 77, 78, nil, nil, nil, 74, 80,
- nil, nil, nil, 63, 64, 65, 56, 51, nil, 53,
- nil, 57, 58, nil, 37, 83, 61, nil, 59, 60,
- 62, 23, 24, 66, 67, nil, nil, nil, nil, nil,
- 22, 28, 27, 90, 89, 91, 92, nil, nil, 17,
- nil, nil, nil, nil, nil, nil, 41, nil, nil, 94,
- 93, nil, 84, 50, 86, 85, 87, nil, 88, 95,
- 96, nil, 81, 82, nil, 38, 39, nil, 227, 231,
- 236, 237, 238, 233, 235, nil, nil, 239, 240, nil,
- nil, nil, nil, nil, nil, 241, 242, nil, 210, nil,
- nil, 214, nil, nil, 52, nil, nil, 54, nil, nil,
- 224, nil, 230, 40, 226, 225, 222, 223, 234, 232,
- 228, 18, 229, nil, nil, nil, 79, 73, 75, 76,
- 77, 78, nil, nil, nil, 74, 80, nil, nil, nil,
- 63, 64, 65, 56, 51, nil, 53, nil, 57, 58,
- nil, 37, 83, 61, nil, 59, 60, 62, 23, 24,
- 66, 67, nil, nil, nil, nil, nil, 22, 28, 27,
- 90, 89, 91, 92, nil, nil, 17, nil, nil, nil,
- nil, nil, nil, 41, nil, nil, 94, 93, nil, 84,
- 50, 86, 85, 87, nil, 88, 95, 96, nil, 81,
- 82, nil, 38, 39, nil, 227, 231, 236, 237, 238,
- 233, 235, 243, nil, 239, 240, nil, nil, nil, nil,
- nil, nil, 241, 242, nil, 210, nil, nil, 214, nil,
- nil, 52, nil, nil, 54, nil, nil, 224, nil, 230,
- 40, 226, 225, 222, 223, 234, 232, 228, 18, 229,
- nil, nil, nil, 79, 73, 75, 76, 77, 78, nil,
- nil, nil, 74, 80, nil, nil, nil, nil, nil, nil,
- 56, nil, nil, 53, nil, nil, nil, nil, 37, 83,
- 63, 64, 65, 8, 51, nil, nil, nil, 57, 58,
- nil, nil, nil, 61, nil, 59, 60, 62, 23, 24,
- 66, 67, nil, nil, nil, nil, nil, 22, 28, 27,
- 90, 89, 91, 92, nil, nil, 17, nil, nil, nil,
- nil, nil, 7, 41, nil, 9, 94, 93, nil, 84,
- 50, 86, 85, 87, nil, 88, 95, 96, nil, 81,
- 82, nil, 38, 39, nil, 227, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 241, 242, nil, 36, nil, nil, 30, nil,
- nil, 52, nil, nil, 54, nil, 32, 224, nil, nil,
- 40, 226, 225, 222, 223, nil, nil, nil, 18, nil,
- nil, nil, nil, 79, 73, 75, 76, 77, 78, nil,
- nil, nil, 74, 80, nil, nil, nil, 63, 64, 65,
- 56, 51, nil, 53, nil, 57, 58, nil, 37, 83,
- 61, nil, 59, 60, 62, 23, 24, 66, 67, nil,
- nil, nil, nil, nil, 22, 28, 27, 90, 89, 91,
- 92, nil, nil, 17, nil, nil, nil, nil, nil, nil,
- 41, nil, nil, 94, 93, nil, 84, 50, 86, 85,
- 87, nil, 88, 95, 96, nil, 81, 82, nil, 38,
- 39, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 210, nil, nil, 214, nil, 458, 52, nil,
- nil, 54, nil, nil, nil, nil, nil, 40, nil, nil,
- nil, nil, nil, nil, nil, 18, nil, nil, nil, nil,
- 79, 73, 75, 76, 77, 78, nil, nil, nil, 74,
- 80, nil, nil, nil, 63, 64, 65, 56, 51, nil,
- 53, nil, 57, 58, nil, 37, 83, 61, nil, 59,
- 60, 62, 258, 259, 66, 67, nil, nil, nil, nil,
- nil, 257, 291, 295, 90, 89, 91, 92, nil, nil,
- 219, nil, nil, nil, nil, nil, nil, 41, nil, nil,
- 94, 93, nil, 84, 50, 86, 85, 87, nil, 88,
- 95, 96, nil, 81, 82, nil, 38, 39, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 210,
- nil, nil, 214, nil, nil, 52, nil, nil, 54, nil,
- nil, nil, nil, nil, 40, nil, nil, nil, nil, nil,
- nil, nil, 218, nil, nil, nil, nil, 79, 73, 75,
- 76, 77, 78, nil, nil, nil, 74, 80, nil, nil,
- nil, 63, 64, 65, 56, 51, nil, 53, nil, 57,
- 58, nil, 37, 83, 61, nil, 59, 60, 62, 258,
- 259, 66, 67, nil, nil, nil, nil, nil, 257, 291,
- 295, 90, 89, 91, 92, nil, nil, 219, nil, nil,
- nil, nil, nil, nil, 41, nil, nil, 94, 93, nil,
- 84, 50, 86, 85, 87, nil, 88, 95, 96, nil,
- 81, 82, nil, 38, 39, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 210, nil, nil, 214,
- nil, nil, 52, nil, nil, 54, nil, nil, nil, nil,
- nil, 40, nil, nil, nil, nil, nil, nil, nil, 218,
- nil, nil, nil, nil, 79, 73, 75, 76, 77, 78,
- nil, nil, nil, 74, 80, nil, nil, nil, 63, 64,
- 65, 56, 51, nil, 53, nil, 57, 58, nil, 37,
- 83, 61, nil, 59, 60, 62, 258, 259, 66, 67,
- nil, nil, nil, nil, nil, 257, 291, 295, 90, 89,
- 91, 92, nil, nil, 219, nil, nil, nil, nil, nil,
- nil, 41, nil, nil, 94, 93, nil, 84, 50, 86,
- 85, 87, nil, 88, 95, 96, nil, 81, 82, nil,
- 38, 39, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 210, nil, nil, 214, nil, nil, 52,
- nil, nil, 54, nil, nil, nil, nil, nil, 40, nil,
- nil, nil, nil, nil, nil, nil, 218, nil, nil, nil,
- nil, 79, 73, 75, 76, 77, 78, nil, nil, nil,
- 74, 80, nil, nil, nil, 63, 64, 65, 56, 51,
- nil, 53, nil, 57, 58, nil, 37, 83, 61, nil,
- 59, 60, 62, 258, 259, 66, 67, nil, nil, nil,
- nil, nil, 257, 291, 295, 90, 89, 91, 92, nil,
- nil, 219, nil, nil, nil, nil, nil, nil, 41, nil,
- nil, 94, 93, nil, 84, 50, 86, 85, 87, nil,
- 88, 95, 96, nil, 81, 82, nil, 38, 39, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 210, nil, nil, 214, nil, nil, 52, nil, nil, 54,
- nil, nil, nil, nil, nil, 40, nil, nil, nil, nil,
- nil, nil, nil, 218, nil, nil, nil, nil, 79, 73,
- 75, 76, 77, 78, nil, nil, nil, 74, 80, nil,
- nil, nil, 63, 64, 65, 56, 51, nil, 53, nil,
- 57, 58, nil, 37, 83, 61, nil, 59, 60, 62,
- 258, 259, 66, 67, nil, nil, nil, nil, nil, 257,
- 291, 295, 90, 89, 91, 92, nil, nil, 219, nil,
- nil, nil, nil, nil, nil, 41, nil, nil, 94, 93,
- nil, 84, 50, 86, 85, 87, nil, 88, 95, 96,
- nil, 81, 82, nil, 38, 39, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 210, nil, nil,
- 214, nil, nil, 52, nil, nil, 54, nil, nil, nil,
- nil, nil, 40, nil, nil, nil, nil, nil, nil, nil,
- 218, nil, nil, nil, nil, 79, 73, 75, 76, 77,
- 78, nil, nil, nil, 74, 80, nil, nil, nil, 63,
- 64, 65, 56, 51, nil, 53, nil, 57, 58, nil,
- 37, 83, 61, nil, 59, 60, 62, 258, 259, 66,
- 67, nil, nil, nil, nil, nil, 257, 291, 295, 90,
- 89, 91, 92, nil, nil, 219, nil, nil, nil, nil,
- nil, nil, 41, nil, nil, 94, 93, nil, 84, 50,
- 86, 85, 87, nil, 88, 95, 96, nil, 81, 82,
- nil, 38, 39, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 210, nil, nil, 214, nil, nil,
- 52, nil, nil, 54, nil, nil, nil, nil, nil, 40,
- nil, nil, nil, nil, nil, nil, nil, 218, nil, nil,
- nil, nil, 79, 73, 75, 76, 77, 78, nil, nil,
- nil, 74, 80, nil, nil, nil, 63, 64, 65, 56,
- 51, nil, 53, nil, 57, 58, nil, 37, 83, 61,
- nil, 59, 60, 62, 258, 259, 66, 67, nil, nil,
- nil, nil, nil, 257, 291, 295, 90, 89, 91, 92,
- nil, nil, 219, nil, nil, nil, nil, nil, nil, 41,
- nil, nil, 94, 93, nil, 84, 50, 86, 85, 87,
- nil, 88, 95, 96, nil, 81, 82, nil, 38, 39,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 210, nil, nil, 214, nil, nil, 52, nil, nil,
- 54, nil, nil, nil, nil, nil, 40, nil, nil, nil,
- nil, nil, nil, nil, 218, nil, nil, nil, nil, 79,
- 73, 75, 76, 77, 78, nil, nil, nil, 74, 80,
- nil, nil, nil, 63, 64, 65, 56, 51, nil, 53,
- nil, 57, 58, nil, 37, 83, 61, nil, 59, 60,
- 62, 258, 259, 66, 67, nil, nil, nil, nil, nil,
- 257, 291, 295, 90, 89, 91, 92, nil, nil, 219,
- nil, nil, nil, nil, nil, nil, 41, nil, nil, 94,
- 93, nil, 84, 50, 86, 85, 87, nil, 88, 95,
- 96, nil, 81, 82, nil, 38, 39, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 210, nil,
- nil, 214, nil, nil, 52, nil, nil, 54, nil, nil,
- nil, nil, nil, 40, nil, nil, nil, nil, nil, nil,
- nil, 218, nil, nil, nil, nil, 79, 73, 75, 76,
- 77, 78, nil, nil, nil, 74, 80, nil, nil, nil,
- 63, 64, 65, 56, 51, nil, 53, nil, 57, 58,
- nil, 37, 83, 61, nil, 59, 60, 62, 258, 259,
- 66, 67, nil, nil, nil, nil, nil, 257, 291, 295,
- 90, 89, 91, 92, nil, nil, 219, nil, nil, nil,
- nil, nil, nil, 41, nil, nil, 94, 93, nil, 84,
- 50, 86, 85, 87, nil, 88, 95, 96, nil, 81,
- 82, nil, 38, 39, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 210, nil, nil, 214, nil,
- nil, 52, nil, nil, 54, nil, nil, nil, nil, nil,
- 40, nil, nil, nil, nil, nil, nil, nil, 218, nil,
- nil, nil, nil, 79, 73, 75, 76, 77, 78, nil,
- nil, nil, 74, 80, nil, nil, nil, 63, 64, 65,
- 56, 51, nil, 53, nil, 57, 58, nil, 37, 83,
- 61, nil, 59, 60, 62, 258, 259, 66, 67, nil,
- nil, nil, nil, nil, 257, 291, 295, 90, 89, 91,
- 92, nil, nil, 219, nil, nil, nil, nil, nil, nil,
- 41, nil, nil, 94, 93, nil, 84, 50, 86, 85,
- 87, nil, 88, 95, 96, nil, 81, 82, nil, 38,
- 39, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 210, nil, nil, 214, nil, nil, 52, nil,
- nil, 54, nil, nil, nil, nil, nil, 40, nil, nil,
- nil, nil, nil, nil, nil, 218, nil, nil, nil, nil,
- 79, 73, 75, 76, 77, 78, nil, nil, nil, 74,
- 80, nil, nil, nil, 63, 64, 65, 56, 51, nil,
- 53, nil, 57, 58, nil, 37, 83, 61, nil, 59,
- 60, 62, 258, 259, 66, 67, nil, nil, nil, nil,
- nil, 257, 291, 295, 90, 89, 91, 92, nil, nil,
- 219, nil, nil, nil, nil, nil, nil, 41, nil, nil,
- 94, 93, nil, 84, 50, 86, 85, 87, nil, 88,
- 95, 96, nil, 81, 82, nil, 38, 39, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 210,
- nil, nil, 214, nil, nil, 52, nil, nil, 54, nil,
- nil, nil, nil, nil, 40, nil, nil, nil, nil, nil,
- nil, nil, 218, nil, nil, nil, nil, 79, 73, 75,
- 76, 77, 78, nil, nil, nil, 74, 80, nil, nil,
- nil, 63, 64, 65, 56, 51, nil, 53, nil, 57,
- 58, nil, 37, 83, 61, nil, 59, 60, 62, 258,
- 259, 66, 67, nil, nil, nil, nil, nil, 257, 291,
- 295, 90, 89, 91, 92, nil, nil, 219, nil, nil,
- nil, nil, nil, nil, 41, nil, nil, 94, 93, nil,
- 84, 50, 86, 85, 87, nil, 88, 95, 96, nil,
- 81, 82, nil, 38, 39, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 210, nil, nil, 214,
- nil, nil, 52, nil, nil, 54, nil, nil, nil, nil,
- nil, 40, nil, nil, nil, nil, nil, nil, nil, 218,
- nil, nil, nil, nil, 79, 73, 75, 76, 77, 78,
- nil, nil, nil, 74, 80, nil, nil, nil, 63, 64,
- 65, 56, 51, nil, 53, nil, 57, 58, nil, 37,
- 83, 61, nil, 59, 60, 62, 258, 259, 66, 67,
- nil, nil, nil, nil, nil, 257, 291, 295, 90, 89,
- 91, 92, nil, nil, 219, nil, nil, nil, nil, nil,
- nil, 41, nil, nil, 94, 93, nil, 84, 50, 86,
- 85, 87, nil, 88, 95, 96, nil, 81, 82, nil,
- 38, 39, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 210, nil, nil, 214, nil, nil, 52,
- nil, nil, 54, nil, nil, nil, nil, nil, 40, nil,
- nil, nil, nil, nil, nil, nil, 218, nil, nil, nil,
- nil, 79, 73, 75, 76, 77, 78, nil, nil, nil,
- 74, 80, nil, nil, nil, 63, 64, 65, 56, 51,
- nil, 53, nil, 57, 58, nil, 37, 83, 61, nil,
- 59, 60, 62, 258, 259, 66, 67, nil, nil, nil,
- nil, nil, 257, 291, 295, 90, 89, 91, 92, nil,
- nil, 219, nil, nil, nil, nil, nil, nil, 41, nil,
- nil, 94, 93, nil, 84, 50, 86, 85, 87, nil,
- 88, 95, 96, nil, 81, 82, nil, 38, 39, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 210, nil, nil, 214, nil, nil, 52, nil, nil, 54,
- nil, nil, nil, nil, nil, 40, nil, nil, nil, nil,
- nil, nil, nil, 218, nil, nil, nil, nil, 79, 73,
- 75, 76, 77, 78, nil, nil, nil, 74, 80, nil,
- nil, nil, 63, 64, 65, 56, 51, nil, 53, nil,
- 57, 58, nil, 37, 83, 61, nil, 59, 60, 62,
- 258, 259, 66, 67, nil, nil, nil, nil, nil, 257,
- 291, 295, 90, 89, 91, 92, nil, nil, 219, nil,
- nil, nil, nil, nil, nil, 41, nil, nil, 94, 93,
- nil, 84, 50, 86, 85, 87, nil, 88, 95, 96,
- nil, 81, 82, nil, 38, 39, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 210, nil, nil,
- 214, nil, nil, 52, nil, nil, 54, nil, nil, nil,
- nil, nil, 40, nil, nil, nil, nil, nil, nil, nil,
- 218, nil, nil, nil, nil, 79, 73, 75, 76, 77,
- 78, nil, nil, nil, 74, 80, nil, nil, nil, 63,
- 64, 65, 56, 51, nil, 53, nil, 57, 58, nil,
- 37, 83, 61, nil, 59, 60, 62, 258, 259, 66,
- 67, nil, nil, nil, nil, nil, 257, 291, 295, 90,
- 89, 91, 92, nil, nil, 219, nil, nil, nil, nil,
- nil, nil, 41, nil, nil, 94, 93, nil, 84, 50,
- 86, 85, 87, nil, 88, 95, 96, nil, 81, 82,
- nil, 38, 39, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 210, nil, nil, 214, nil, nil,
- 52, nil, nil, 54, nil, nil, nil, nil, nil, 40,
- nil, nil, nil, nil, nil, nil, nil, 218, nil, nil,
- nil, nil, 79, 73, 75, 76, 77, 78, nil, nil,
- nil, 74, 80, nil, nil, nil, 63, 64, 65, 56,
- 51, nil, 53, nil, 57, 58, nil, 37, 83, 61,
- nil, 59, 60, 62, 258, 259, 66, 67, nil, nil,
- nil, nil, nil, 257, 291, 295, 90, 89, 91, 92,
- nil, nil, 219, nil, nil, nil, nil, nil, nil, 41,
- nil, nil, 94, 93, nil, 84, 50, 86, 85, 87,
- nil, 88, 95, 96, nil, 81, 82, nil, 38, 39,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 210, nil, nil, 214, nil, nil, 52, nil, nil,
- 54, nil, nil, nil, nil, nil, 40, nil, nil, nil,
- nil, nil, nil, nil, 218, nil, nil, nil, nil, 79,
- 73, 75, 76, 77, 78, nil, nil, nil, 74, 80,
- nil, nil, nil, 63, 64, 65, 56, 51, nil, 53,
- nil, 57, 58, nil, 37, 83, 61, nil, 59, 60,
- 62, 258, 259, 66, 67, nil, nil, nil, nil, nil,
- 257, 291, 295, 90, 89, 91, 92, nil, nil, 219,
- nil, nil, nil, nil, nil, nil, 41, nil, nil, 94,
- 93, nil, 84, 50, 86, 85, 87, nil, 88, 95,
- 96, nil, 81, 82, nil, 38, 39, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 210, nil,
- nil, 214, nil, nil, 52, nil, nil, 54, nil, nil,
- nil, nil, nil, 40, nil, nil, nil, nil, nil, nil,
- nil, 218, nil, nil, nil, nil, 79, 73, 75, 76,
- 77, 78, nil, nil, nil, 74, 80, nil, nil, nil,
- 63, 64, 65, 56, 51, nil, 53, nil, 57, 58,
- nil, 37, 83, 61, nil, 59, 60, 62, 258, 259,
- 66, 67, nil, nil, nil, nil, nil, 257, 291, 295,
- 90, 89, 91, 92, nil, nil, 219, nil, nil, nil,
- nil, nil, nil, 41, nil, nil, 94, 93, nil, 84,
- 50, 86, 85, 87, nil, 88, 95, 96, nil, 81,
- 82, nil, 38, 39, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 210, nil, nil, 214, nil,
- nil, 52, nil, nil, 54, nil, nil, nil, nil, nil,
- 40, nil, nil, nil, nil, nil, nil, nil, 218, nil,
- nil, nil, nil, 79, 73, 75, 76, 77, 78, nil,
- nil, nil, 74, 80, nil, nil, nil, 63, 64, 65,
- 56, 51, nil, 53, nil, 57, 58, nil, 37, 83,
- 61, nil, 59, 60, 62, 258, 259, 66, 67, nil,
- nil, nil, nil, nil, 257, 291, 295, 90, 89, 91,
- 92, nil, nil, 219, nil, nil, nil, nil, nil, nil,
- 41, nil, nil, 94, 93, nil, 84, 50, 86, 85,
- 87, nil, 88, 95, 96, nil, 81, 82, nil, 38,
- 39, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 210, nil, nil, 214, nil, nil, 52, nil,
- nil, 54, nil, nil, nil, nil, nil, 40, nil, nil,
- nil, nil, nil, nil, nil, 218, nil, nil, nil, nil,
- 79, 73, 75, 76, 77, 78, nil, nil, nil, 74,
- 80, nil, nil, nil, 63, 64, 65, 56, 51, nil,
- 53, nil, 57, 58, nil, 37, 83, 61, nil, 59,
- 60, 62, 258, 259, 66, 67, nil, nil, nil, nil,
- nil, 257, 291, 295, 90, 89, 91, 92, nil, nil,
- 219, nil, nil, nil, nil, nil, nil, 41, nil, nil,
- 94, 93, nil, 84, 50, 86, 85, 87, nil, 88,
- 95, 96, nil, 81, 82, nil, 38, 39, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 210,
- nil, nil, 214, nil, nil, 52, nil, nil, 54, nil,
- nil, nil, nil, nil, 40, nil, nil, nil, nil, nil,
- nil, nil, 218, nil, nil, nil, nil, 79, 73, 75,
- 76, 77, 78, nil, nil, nil, 74, 80, nil, nil,
- nil, 63, 64, 65, 56, 51, nil, 53, nil, 57,
- 58, nil, 37, 83, 61, nil, 59, 60, 62, 258,
- 259, 66, 67, nil, nil, nil, nil, nil, 257, 291,
- 295, 90, 89, 91, 92, nil, nil, 219, nil, nil,
- nil, nil, nil, nil, 41, nil, nil, 94, 93, nil,
- 84, 50, 86, 85, 87, nil, 88, 95, 96, nil,
- 81, 82, nil, 38, 39, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 210, nil, nil, 214,
- nil, nil, 52, nil, nil, 54, nil, nil, nil, nil,
- nil, 40, nil, nil, nil, nil, nil, nil, nil, 218,
- nil, nil, nil, nil, 79, 73, 75, 76, 77, 78,
- nil, nil, nil, 74, 80, nil, nil, nil, 63, 64,
- 65, 56, 51, nil, 53, nil, 57, 58, nil, 37,
- 83, 61, nil, 59, 60, 62, 258, 259, 66, 67,
- nil, nil, nil, nil, nil, 257, 291, 295, 90, 89,
- 91, 92, nil, nil, 219, nil, nil, nil, nil, nil,
- nil, 41, nil, nil, 94, 93, nil, 84, 50, 86,
- 85, 87, nil, 88, 95, 96, nil, 81, 82, nil,
- 38, 39, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 210, nil, nil, 214, nil, nil, 52,
- nil, nil, 54, nil, nil, nil, nil, nil, 40, nil,
- nil, nil, nil, nil, nil, nil, 218, nil, nil, nil,
- nil, 79, 73, 75, 76, 77, 78, nil, nil, nil,
- 74, 80, nil, nil, nil, 63, 64, 65, 56, 51,
- nil, 53, nil, 57, 58, nil, 37, 83, 61, nil,
- 59, 60, 62, 258, 259, 66, 67, nil, nil, nil,
- nil, nil, 257, 291, 295, 90, 89, 91, 92, nil,
- nil, 219, nil, nil, nil, nil, nil, nil, 41, nil,
- nil, 94, 93, nil, 84, 50, 86, 85, 87, nil,
- 88, 95, 96, nil, 81, 82, nil, 38, 39, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 210, nil, nil, 214, nil, nil, 52, nil, nil, 54,
- nil, nil, nil, nil, nil, 40, nil, nil, nil, nil,
- nil, nil, nil, 218, nil, nil, nil, nil, 79, 73,
- 75, 76, 77, 78, nil, nil, nil, 74, 80, nil,
- nil, nil, 63, 64, 65, 56, 51, nil, 53, nil,
- 57, 58, nil, 37, 83, 61, nil, 59, 60, 62,
- 258, 259, 66, 67, nil, nil, nil, nil, nil, 257,
- 291, 295, 90, 89, 91, 92, nil, nil, 219, nil,
- nil, nil, nil, nil, nil, 41, nil, nil, 94, 93,
- nil, 84, 50, 86, 85, 87, nil, 88, 95, 96,
- nil, 81, 82, nil, 38, 39, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 210, nil, nil,
- 214, nil, nil, 52, nil, nil, 54, nil, nil, nil,
- nil, nil, 40, nil, nil, nil, nil, nil, nil, nil,
- 218, nil, nil, nil, nil, 79, 73, 75, 76, 77,
- 78, nil, nil, nil, 74, 80, nil, nil, nil, 63,
- 64, 65, 56, 51, nil, 53, nil, 57, 58, nil,
- 37, 83, 61, nil, 59, 60, 62, 258, 259, 66,
- 67, nil, nil, nil, nil, nil, 257, 291, 295, 90,
- 89, 91, 92, nil, nil, 219, nil, nil, nil, nil,
- nil, nil, 41, nil, nil, 94, 93, nil, 84, 50,
- 86, 85, 87, nil, 88, 95, 96, nil, 81, 82,
- nil, 38, 39, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 210, nil, nil, 214, nil, nil,
- 52, nil, nil, 54, nil, nil, nil, nil, nil, 40,
- nil, nil, nil, nil, nil, nil, nil, 218, nil, nil,
- nil, nil, 79, 73, 75, 76, 77, 78, nil, nil,
- nil, 74, 80, nil, nil, nil, 63, 64, 65, 56,
- 51, nil, 53, nil, 57, 58, nil, 37, 83, 61,
- nil, 59, 60, 62, 258, 259, 66, 67, nil, nil,
- nil, nil, nil, 257, 291, 295, 90, 89, 91, 92,
- nil, nil, 219, nil, nil, nil, nil, nil, nil, 41,
- nil, nil, 94, 93, nil, 84, 50, 86, 85, 87,
- nil, 88, 95, 96, nil, 81, 82, nil, 38, 39,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 210, nil, nil, 214, nil, nil, 52, nil, nil,
- 54, nil, nil, nil, nil, nil, 40, nil, nil, nil,
- nil, nil, nil, nil, 218, nil, nil, nil, nil, 79,
- 73, 75, 76, 77, 78, nil, nil, nil, 74, 80,
- nil, nil, nil, 63, 64, 65, 56, 51, nil, 53,
- nil, 57, 58, nil, 37, 83, 61, nil, 59, 60,
- 62, 258, 259, 66, 67, nil, nil, nil, nil, nil,
- 257, 291, 295, 90, 89, 91, 92, nil, nil, 219,
- nil, nil, nil, nil, nil, nil, 41, nil, nil, 94,
- 93, nil, 84, 50, 86, 85, 87, nil, 88, 95,
- 96, nil, 81, 82, nil, 38, 39, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 210, nil,
- nil, 214, nil, nil, 52, nil, nil, 54, nil, nil,
- nil, nil, nil, 40, nil, nil, nil, nil, nil, nil,
- nil, 218, nil, nil, nil, nil, 79, 73, 75, 76,
- 77, 78, nil, nil, nil, 74, 80, nil, nil, nil,
- 63, 64, 65, 56, 51, nil, 53, nil, 57, 58,
- nil, 37, 83, 61, nil, 59, 60, 62, 258, 259,
- 66, 67, nil, nil, nil, nil, nil, 257, 291, 295,
- 90, 89, 91, 92, nil, nil, 219, nil, nil, nil,
- nil, nil, nil, 41, nil, nil, 94, 93, nil, 84,
- 50, 86, 85, 87, nil, 88, 95, 96, nil, 81,
- 82, nil, 38, 39, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 210, nil, nil, 214, nil,
- nil, 52, nil, nil, 54, nil, nil, nil, nil, nil,
- 40, nil, nil, nil, nil, nil, nil, nil, 218, nil,
- nil, nil, nil, 79, 73, 75, 76, 77, 78, nil,
- nil, nil, 74, 80, nil, nil, nil, 63, 64, 65,
- 56, 51, nil, 53, nil, 57, 58, nil, 37, 83,
- 61, nil, 59, 60, 62, 258, 259, 66, 67, nil,
- nil, nil, nil, nil, 257, 291, 295, 90, 89, 91,
- 92, nil, nil, 219, nil, nil, nil, nil, nil, nil,
- 41, nil, nil, 94, 93, nil, 84, 50, 86, 85,
- 87, nil, 88, 95, 96, nil, 81, 82, nil, 38,
- 39, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 210, nil, nil, 214, nil, nil, 52, nil,
- nil, 54, nil, nil, nil, nil, nil, 40, nil, nil,
- nil, nil, nil, nil, nil, 218, nil, nil, nil, nil,
- 79, 73, 75, 76, 77, 78, nil, nil, nil, 74,
- 80, nil, nil, nil, 63, 64, 65, 56, 51, nil,
- 53, nil, 57, 58, nil, 37, 83, 61, nil, 59,
- 60, 62, 258, 259, 66, 67, nil, nil, nil, nil,
- nil, 257, 28, 27, 90, 89, 91, 92, nil, nil,
- 219, nil, nil, nil, nil, nil, nil, 41, nil, nil,
- 94, 93, nil, 84, 50, 86, 85, 87, 261, 88,
- 95, 96, nil, 81, 82, nil, 38, 39, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 210,
- nil, nil, 214, nil, nil, 52, nil, nil, 54, nil,
- 256, nil, 254, nil, 40, nil, nil, nil, nil, nil,
- nil, nil, 218, nil, nil, nil, nil, 79, 73, 75,
- 76, 77, 78, nil, nil, nil, 74, 80, nil, nil,
- nil, 63, 64, 65, 56, 51, nil, 53, nil, 57,
- 58, nil, 37, 83, 61, nil, 59, 60, 62, 258,
- 259, 66, 67, nil, nil, nil, nil, nil, 257, 28,
- 27, 90, 89, 91, 92, nil, nil, 219, nil, nil,
- nil, nil, nil, nil, 41, nil, nil, 94, 93, nil,
- 84, 50, 86, 85, 87, 261, 88, 95, 96, nil,
- 81, 82, nil, 38, 39, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 210, nil, nil, 214,
- nil, nil, 506, nil, nil, 54, nil, 256, nil, 254,
- nil, 40, nil, nil, nil, nil, nil, nil, nil, 218,
- nil, nil, nil, nil, 79, 73, 75, 76, 77, 78,
- nil, nil, nil, 74, 80, nil, nil, nil, 63, 64,
- 65, 56, 51, nil, 53, nil, 57, 58, nil, 37,
- 83, 61, nil, 59, 60, 62, 258, 259, 66, 67,
- nil, nil, nil, nil, nil, 257, 28, 27, 90, 89,
- 91, 92, nil, nil, 219, nil, nil, nil, nil, nil,
- nil, 41, nil, nil, 94, 93, nil, 84, 50, 86,
- 85, 87, 261, 88, 95, 96, nil, 81, 82, nil,
- 38, 39, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 210, nil, nil, 214, nil, 510, 52,
- nil, nil, 54, nil, 256, nil, 254, nil, 40, nil,
- nil, nil, nil, nil, nil, nil, 218, nil, nil, nil,
- nil, 79, 73, 75, 76, 77, 78, nil, nil, nil,
- 74, 80, nil, nil, nil, nil, nil, nil, 56, nil,
- nil, 53, nil, nil, nil, nil, 37, 83, 63, 64,
- 65, 8, 51, nil, nil, nil, 57, 58, nil, nil,
- nil, 61, nil, 59, 60, 62, 23, 24, 66, 67,
- nil, nil, nil, nil, nil, 22, 28, 27, 90, 89,
- 91, 92, nil, nil, 17, nil, nil, nil, nil, nil,
- 7, 41, nil, 9, 94, 93, nil, 84, 50, 86,
- 85, 87, nil, 88, 95, 96, nil, 81, 82, nil,
- 38, 39, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 36, nil, nil, 281, nil, nil, 52,
- nil, nil, 54, nil, 32, nil, nil, nil, 40, nil,
- nil, nil, nil, nil, nil, nil, 18, nil, nil, nil,
- nil, 79, 73, 75, 76, 77, 78, nil, nil, nil,
- 74, 80, nil, nil, nil, 63, 64, 65, 56, 51,
- nil, 53, nil, 57, 58, nil, 37, 83, 61, nil,
- 59, 60, 62, 258, 259, 66, 67, nil, nil, nil,
- nil, nil, 257, 291, 295, 90, 89, 91, 92, nil,
- nil, 219, nil, nil, nil, nil, nil, nil, 292, nil,
- nil, 94, 93, nil, 84, 50, 86, 85, 87, nil,
- 88, 95, 96, nil, 81, 82, 764, nil, 336, 334,
- 333, 754, 335, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 751, nil, nil, nil, nil, nil, nil, nil,
- 289, nil, nil, 214, nil, nil, 52, nil, nil, 54,
- nil, nil, nil, nil, nil, 338, nil, nil, nil, nil,
- nil, nil, nil, 341, 340, 344, 343, nil, 79, 73,
- 75, 76, 77, 78, nil, nil, nil, 74, 80, nil,
- nil, nil, 518, nil, nil, 56, nil, nil, 53, nil,
- nil, nil, nil, 296, 83, 63, 64, 65, 8, 51,
- nil, nil, 752, 57, 58, nil, nil, nil, 61, nil,
- 59, 60, 62, 23, 24, 66, 67, nil, nil, nil,
- nil, nil, 22, 28, 27, 90, 89, 91, 92, nil,
- nil, 17, nil, nil, nil, nil, nil, 7, 41, nil,
- 9, 94, 93, nil, 84, 50, 86, 85, 87, nil,
- 88, 95, 96, nil, 81, 82, nil, 38, 39, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 36, nil, nil, 281, nil, nil, 52, nil, nil, 54,
- nil, 32, nil, nil, nil, 40, nil, nil, nil, nil,
- nil, nil, nil, 18, nil, nil, nil, nil, 79, 73,
- 75, 76, 77, 78, nil, nil, nil, 74, 80, nil,
- nil, nil, 63, 64, 65, 56, 51, nil, 53, nil,
- 57, 58, nil, 37, 83, 61, nil, 59, 60, 62,
- 258, 259, 66, 67, nil, nil, nil, nil, nil, 257,
- 291, 295, 90, 89, 91, 92, nil, nil, 219, nil,
- nil, nil, nil, nil, nil, 292, nil, nil, 94, 93,
- nil, 84, 50, 86, 85, 87, nil, 88, 95, 96,
- nil, 81, 82, 327, nil, 336, 334, 333, nil, 335,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 289, nil, nil,
- 286, nil, nil, 52, nil, nil, 54, nil, nil, nil,
- nil, nil, 338, 322, nil, nil, nil, nil, nil, nil,
- 341, 340, 344, 343, nil, 79, 73, 75, 76, 77,
- 78, nil, nil, nil, 74, 80, nil, nil, nil, 63,
- 64, 65, 56, 51, nil, 53, nil, 57, 58, nil,
- 296, 83, 61, nil, 59, 60, 62, 258, 259, 66,
- 67, nil, nil, nil, nil, nil, 257, 291, 295, 90,
- 89, 91, 92, nil, nil, 219, nil, nil, nil, nil,
- nil, nil, 41, nil, nil, 94, 93, nil, 84, 50,
- 86, 85, 87, nil, 88, 95, 96, nil, 81, 82,
- nil, 38, 39, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 210, nil, nil, 214, 537, nil,
- 52, nil, nil, 54, nil, nil, nil, nil, nil, 40,
- nil, nil, nil, nil, nil, nil, nil, 218, nil, nil,
- nil, nil, 79, 73, 75, 76, 77, 78, nil, nil,
- nil, 74, 80, nil, nil, nil, nil, nil, nil, 56,
- nil, nil, 53, nil, nil, nil, nil, 37, 83, 63,
- 64, 65, 8, 51, nil, nil, nil, 57, 58, nil,
- nil, nil, 61, nil, 59, 60, 62, 23, 24, 66,
- 67, nil, nil, nil, nil, nil, 22, 28, 27, 90,
- 89, 91, 92, nil, nil, 17, nil, nil, nil, nil,
- nil, 7, 41, nil, 9, 94, 93, nil, 84, 50,
- 86, 85, 87, nil, 88, 95, 96, nil, 81, 82,
- nil, 38, 39, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 36, nil, nil, 30, nil, nil,
- 52, nil, nil, 54, nil, 32, nil, nil, nil, 40,
- nil, nil, nil, nil, nil, nil, nil, 18, nil, nil,
- nil, nil, 79, 73, 75, 76, 77, 78, nil, nil,
- nil, 74, 80, nil, nil, nil, 63, 64, 65, 56,
- 51, nil, 53, nil, 57, 58, nil, 37, 83, 61,
- nil, 59, 60, 62, 23, 24, 66, 67, nil, nil,
- nil, nil, nil, 22, 28, 27, 90, 89, 91, 92,
- nil, nil, 17, nil, nil, nil, nil, nil, nil, 41,
- nil, nil, 94, 93, nil, 84, 50, 86, 85, 87,
- nil, 88, 95, 96, nil, 81, 82, nil, 38, 39,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 210, nil, nil, 214, nil, nil, 52, nil, nil,
- 54, nil, nil, nil, nil, nil, 40, nil, nil, nil,
- nil, nil, nil, nil, 18, nil, nil, nil, nil, 79,
- 73, 75, 76, 77, 78, nil, nil, nil, 74, 80,
- nil, nil, nil, 63, 64, 65, 56, 51, nil, 53,
- nil, 57, 58, nil, 37, 83, 61, nil, 59, 60,
- 62, 23, 24, 66, 67, nil, nil, nil, nil, nil,
- 22, 28, 27, 90, 89, 91, 92, nil, nil, 17,
- nil, nil, nil, nil, nil, nil, 41, nil, nil, 94,
- 93, nil, 84, 50, 86, 85, 87, nil, 88, 95,
- 96, nil, 81, 82, nil, 38, 39, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 210, nil,
- nil, 214, nil, nil, 52, nil, nil, 54, nil, nil,
- nil, nil, nil, 40, nil, nil, nil, nil, nil, nil,
- nil, 18, nil, nil, nil, nil, 79, 73, 75, 76,
- 77, 78, nil, nil, nil, 74, 80, nil, nil, nil,
- 63, 64, 65, 56, 51, nil, 53, nil, 57, 58,
- nil, 37, 83, 61, nil, 59, 60, 62, 258, 259,
- 66, 67, nil, nil, nil, nil, nil, 257, 291, 295,
- 90, 89, 91, 92, nil, nil, 219, nil, nil, nil,
- nil, nil, nil, 292, nil, nil, 94, 93, nil, 84,
- 50, 86, 85, 361, nil, 88, 95, 96, nil, 81,
- 82, 327, nil, 336, 334, 333, nil, 335, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 362, nil, nil, 214, nil,
- nil, 52, nil, nil, 54, nil, nil, nil, nil, nil,
- 338, nil, 554, nil, nil, nil, nil, nil, 341, 340,
- 344, 343, nil, 79, 73, 75, 76, 77, 78, nil,
- nil, nil, 74, 80, nil, nil, nil, 63, 64, 65,
- 56, 51, nil, 53, nil, 57, 58, nil, 296, 83,
- 61, nil, 59, 60, 62, 23, 24, 66, 67, nil,
- nil, nil, nil, nil, 22, 28, 27, 90, 89, 91,
- 92, nil, nil, 17, nil, nil, nil, nil, nil, nil,
- 41, nil, nil, 94, 93, nil, 84, 50, 86, 85,
- 87, nil, 88, 95, 96, nil, 81, 82, nil, 38,
- 39, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 210, nil, nil, 214, nil, nil, 52, nil,
- nil, 54, nil, nil, nil, nil, nil, 40, nil, nil,
- nil, nil, nil, nil, nil, 18, nil, nil, nil, nil,
- 79, 73, 75, 76, 77, 78, nil, nil, nil, 74,
- 80, nil, nil, nil, 63, 64, 65, 56, 51, nil,
- 53, nil, 57, 58, nil, 37, 83, 61, nil, 59,
- 60, 62, 258, 259, 66, 67, nil, nil, nil, nil,
- nil, 257, 291, 295, 90, 89, 91, 92, nil, nil,
- 219, nil, nil, nil, nil, nil, nil, 41, nil, nil,
- 94, 93, nil, 84, 50, 86, 85, 87, nil, 88,
- 95, 96, nil, 81, 82, nil, 38, 39, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 210,
- nil, nil, 214, nil, nil, 52, nil, nil, 54, nil,
- nil, nil, nil, nil, 40, nil, nil, nil, nil, nil,
- nil, nil, 218, nil, nil, nil, nil, 79, 73, 75,
- 76, 77, 78, nil, nil, nil, 74, 80, nil, nil,
- nil, -255, -255, -255, 56, -255, nil, 53, nil, -255,
- -255, nil, 37, 83, -255, nil, -255, -255, -255, -255,
- -255, -255, -255, nil, nil, nil, nil, nil, -255, -255,
- -255, -255, -255, -255, -255, nil, nil, -255, nil, nil,
- nil, nil, nil, nil, -255, nil, nil, -255, -255, nil,
- -255, -255, -255, -255, -255, -255, -255, -255, -255, nil,
- -255, -255, nil, -255, -255, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, -255, nil, nil, -255,
- 268, nil, -255, nil, nil, -255, nil, -255, nil, -255,
- nil, -255, nil, nil, nil, nil, nil, nil, nil, -255,
- nil, nil, nil, nil, -255, -255, -255, -255, -255, -255,
- nil, nil, nil, -255, -255, nil, nil, nil, -536, -536,
- -536, -255, -536, nil, -255, nil, -536, -536, nil, -255,
- -255, -536, nil, -536, -536, -536, -536, -536, -536, -536,
- nil, nil, nil, nil, nil, -536, -536, -536, -536, -536,
- -536, -536, nil, nil, -536, nil, nil, nil, nil, nil,
- nil, -536, nil, nil, -536, -536, nil, -536, -536, -536,
- -536, -536, -536, -536, -536, -536, nil, -536, -536, nil,
- -536, -536, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, -536, nil, nil, -536, -536, nil, -536,
- nil, nil, -536, nil, -536, nil, -536, nil, -536, nil,
- nil, nil, nil, nil, nil, nil, -536, nil, nil, nil,
- nil, -536, -536, -536, -536, -536, -536, nil, nil, nil,
- -536, -536, nil, nil, nil, -537, -537, -537, -536, -537,
- nil, -536, nil, -537, -537, nil, -536, -536, -537, nil,
- -537, -537, -537, -537, -537, -537, -537, nil, nil, nil,
- nil, nil, -537, -537, -537, -537, -537, -537, -537, nil,
- nil, -537, nil, nil, nil, nil, nil, nil, -537, nil,
- nil, -537, -537, nil, -537, -537, -537, -537, -537, -537,
- -537, -537, -537, nil, -537, -537, nil, -537, -537, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- -537, nil, nil, -537, -537, nil, -537, nil, nil, -537,
- nil, -537, nil, -537, nil, -537, nil, nil, nil, nil,
- nil, nil, nil, -537, nil, nil, nil, nil, -537, -537,
- -537, -537, -537, -537, nil, nil, nil, -537, -537, nil,
- nil, nil, -255, -255, -255, -537, -255, nil, -537, nil,
- -255, -255, nil, -537, -537, -255, nil, -255, -255, -255,
- -255, -255, -255, -255, nil, nil, nil, nil, nil, -255,
- -255, -255, -255, -255, -255, -255, nil, nil, -255, nil,
- nil, nil, nil, nil, nil, -255, nil, nil, -255, -255,
- nil, -255, -255, -255, -255, -255, -255, -255, -255, -255,
- nil, -255, -255, nil, -255, -255, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, -255, nil, nil,
- -255, 268, nil, -255, nil, nil, -255, nil, -255, nil,
- -255, nil, -255, nil, nil, nil, nil, nil, nil, nil,
- -255, nil, nil, nil, nil, -255, -255, -255, -255, -255,
- -255, nil, nil, nil, -255, -255, nil, nil, nil, 63,
- 64, 65, -255, 51, nil, -255, nil, 57, 58, nil,
- -255, -255, 61, nil, 59, 60, 62, 258, 259, 66,
- 67, nil, nil, nil, nil, nil, 257, 28, 27, 90,
- 89, 91, 92, nil, nil, 219, nil, nil, nil, nil,
- nil, nil, 41, nil, nil, 94, 93, nil, 84, 50,
- 86, 85, 87, 261, 88, 95, 96, nil, 81, 82,
- nil, 38, 39, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 210, nil, nil, 214, nil, nil,
- 52, nil, nil, 54, nil, 256, nil, nil, nil, 40,
- nil, nil, nil, nil, nil, nil, nil, 218, nil, nil,
- nil, nil, 79, 73, 75, 76, 77, 78, nil, nil,
- nil, 74, 80, nil, nil, nil, 63, 64, 65, 56,
- 51, nil, 53, nil, 57, 58, nil, 37, 83, 61,
- nil, 59, 60, 62, 258, 259, 66, 67, nil, nil,
- nil, nil, nil, 257, 28, 27, 90, 89, 91, 92,
- nil, nil, 219, nil, nil, nil, nil, nil, nil, 41,
- nil, nil, 94, 93, nil, 84, 50, 86, 85, 87,
- 261, 88, 95, 96, nil, 81, 82, nil, 38, 39,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 210, nil, nil, 214, nil, nil, 52, nil, nil,
- 54, nil, 256, nil, nil, nil, 40, nil, nil, nil,
- nil, nil, nil, nil, 218, nil, nil, nil, nil, 79,
- 73, 75, 76, 77, 78, nil, nil, nil, 74, 80,
- nil, nil, nil, 63, 64, 65, 56, 51, nil, 53,
- nil, 57, 58, nil, 37, 83, 61, nil, 59, 60,
- 62, 258, 259, 66, 67, nil, nil, nil, nil, nil,
- 257, 291, 295, 90, 89, 91, 92, nil, nil, 219,
- nil, nil, nil, nil, nil, nil, 41, nil, nil, 94,
- 93, nil, 84, 50, 86, 85, 87, nil, 88, 95,
- 96, nil, 81, 82, nil, 38, 39, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 210, nil,
- nil, 214, nil, nil, 52, nil, nil, 54, nil, nil,
- nil, nil, nil, 40, nil, nil, nil, nil, nil, nil,
- nil, 218, nil, nil, nil, nil, 79, 73, 75, 76,
- 77, 78, nil, nil, nil, 74, 80, nil, nil, nil,
- 63, 64, 65, 56, 51, nil, 53, nil, 57, 58,
- nil, 37, 83, 61, nil, 59, 60, 62, 258, 259,
- 66, 67, nil, nil, nil, nil, nil, 257, 291, 295,
- 90, 89, 91, 92, nil, nil, 219, nil, nil, nil,
- nil, nil, nil, 41, nil, nil, 94, 93, nil, 84,
- 50, 86, 85, 87, nil, 88, 95, 96, nil, 81,
- 82, nil, 38, 39, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 210, nil, nil, 214, nil,
- nil, 52, nil, nil, 54, nil, nil, nil, nil, nil,
- 40, nil, nil, nil, nil, nil, nil, nil, 218, nil,
- nil, nil, nil, 79, 73, 75, 76, 77, 78, nil,
- nil, nil, 74, 80, nil, nil, nil, 63, 64, 65,
- 56, 51, nil, 53, nil, 57, 58, nil, 37, 83,
- 61, nil, 59, 60, 62, 258, 259, 66, 67, nil,
- nil, nil, nil, nil, 257, 291, 295, 90, 89, 91,
- 92, nil, nil, 219, nil, nil, nil, nil, nil, nil,
- 41, nil, nil, 94, 93, nil, 84, 50, 86, 85,
- 87, nil, 88, 95, 96, nil, 81, 82, nil, 38,
- 39, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 210, nil, nil, 214, nil, nil, 52, nil,
- nil, 54, nil, nil, nil, nil, nil, 40, nil, nil,
- nil, nil, nil, nil, nil, 218, nil, nil, nil, nil,
- 79, 73, 75, 76, 77, 78, nil, nil, nil, 74,
- 80, nil, nil, nil, 63, 64, 65, 56, 51, nil,
- 53, nil, 57, 58, nil, 37, 83, 61, nil, 59,
- 60, 62, 258, 259, 66, 67, nil, nil, nil, nil,
- nil, 257, 291, 295, 90, 89, 91, 92, nil, nil,
- 219, nil, nil, nil, nil, nil, nil, 41, nil, nil,
- 94, 93, nil, 84, 50, 86, 85, 87, 261, 88,
- 95, 96, nil, 81, 82, nil, 38, 39, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 210,
- nil, nil, 214, nil, nil, 52, nil, nil, 54, nil,
- 658, nil, 254, nil, 40, nil, nil, nil, nil, nil,
- nil, nil, 218, nil, nil, nil, nil, 79, 73, 75,
- 76, 77, 78, nil, nil, nil, 74, 80, nil, nil,
- nil, 63, 64, 65, 56, 51, nil, 53, nil, 57,
- 58, nil, 37, 83, 61, nil, 59, 60, 62, 258,
- 259, 66, 67, nil, nil, nil, nil, nil, 257, 291,
- 295, 90, 89, 91, 92, nil, nil, 219, nil, nil,
- nil, nil, nil, nil, 41, nil, nil, 94, 93, nil,
- 84, 50, 86, 85, 87, 261, 88, 95, 96, nil,
- 81, 82, nil, 38, 39, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 210, nil, nil, 214,
- nil, nil, 52, nil, nil, 54, nil, nil, nil, 254,
- nil, 40, nil, nil, nil, nil, nil, nil, nil, 218,
- nil, nil, nil, nil, 79, 73, 75, 76, 77, 78,
- nil, nil, nil, 74, 80, nil, nil, nil, 63, 64,
- 65, 56, 51, nil, 53, nil, 57, 58, nil, 37,
- 83, 61, nil, 59, 60, 62, 258, 259, 66, 67,
- nil, nil, nil, nil, nil, 257, 291, 295, 90, 89,
- 91, 92, nil, nil, 219, nil, nil, nil, nil, nil,
- nil, 41, nil, nil, 94, 93, nil, 84, 50, 86,
- 85, 87, nil, 88, 95, 96, nil, 81, 82, nil,
- 38, 39, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 210, nil, nil, 214, nil, nil, 52,
- nil, nil, 54, nil, nil, nil, nil, nil, 40, nil,
- nil, nil, nil, nil, nil, nil, 218, nil, nil, nil,
- nil, 79, 73, 75, 76, 77, 78, nil, nil, nil,
- 74, 80, nil, nil, nil, 63, 64, 65, 56, 51,
- nil, 53, nil, 57, 58, nil, 37, 83, 61, nil,
- 59, 60, 62, 23, 24, 66, 67, nil, nil, nil,
- nil, nil, 22, 28, 27, 90, 89, 91, 92, nil,
- nil, 17, nil, nil, nil, nil, nil, nil, 41, nil,
- nil, 94, 93, nil, 84, 50, 86, 85, 87, nil,
- 88, 95, 96, nil, 81, 82, nil, 38, 39, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 210, nil, nil, 214, nil, 675, 52, nil, nil, 54,
- nil, nil, nil, 254, nil, 40, nil, nil, nil, nil,
- nil, nil, nil, 18, nil, nil, nil, nil, 79, 73,
- 75, 76, 77, 78, nil, nil, nil, 74, 80, nil,
- nil, nil, nil, nil, nil, 56, nil, nil, 53, nil,
- nil, nil, nil, 37, 83, 63, 64, 65, 8, 51,
- nil, nil, nil, 57, 58, nil, nil, nil, 61, nil,
- 59, 60, 62, 23, 24, 66, 67, nil, nil, nil,
- nil, nil, 22, 28, 27, 90, 89, 91, 92, nil,
- nil, 17, nil, nil, nil, nil, nil, 7, 41, nil,
- 9, 94, 93, nil, 84, 50, 86, 85, 87, nil,
- 88, 95, 96, nil, 81, 82, nil, 38, 39, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 36, nil, nil, 30, nil, nil, 52, nil, nil, 54,
- nil, 32, nil, nil, nil, 40, nil, nil, nil, nil,
- nil, nil, nil, 18, nil, nil, nil, nil, 79, 73,
- 75, 76, 77, 78, nil, nil, nil, 74, 80, nil,
- nil, nil, nil, nil, 404, 56, nil, nil, 53, nil,
- nil, nil, nil, 37, 83, 63, 64, 65, nil, 51,
- nil, nil, nil, 57, 58, nil, nil, nil, 61, nil,
- 59, 60, 62, 258, 259, 66, 67, nil, nil, nil,
- nil, nil, 257, 291, 295, 90, 89, 91, 92, nil,
- nil, 219, nil, nil, nil, nil, nil, nil, 292, nil,
- nil, 94, 93, nil, 84, 50, 86, 85, 87, nil,
- 88, 95, 96, nil, 81, 82, 327, nil, 336, 334,
- 333, nil, 335, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 289, nil, nil, 286, nil, nil, 52, nil, nil, 54,
- nil, nil, nil, nil, nil, 338, nil, nil, nil, nil,
- nil, nil, nil, 341, 340, 344, 343, nil, 79, 73,
- 75, 76, 77, 78, nil, nil, nil, 74, 80, nil,
- nil, nil, 63, 64, 65, 56, 51, nil, 53, nil,
- 57, 58, nil, 296, 83, 61, nil, 59, 60, 62,
- 258, 259, 66, 67, nil, nil, nil, nil, nil, 257,
- 28, 27, 90, 89, 91, 92, nil, nil, 219, nil,
- nil, nil, nil, nil, nil, 41, nil, nil, 94, 93,
- nil, 84, 50, 86, 85, 87, 261, 88, 95, 96,
- nil, 81, 82, nil, 38, 39, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 210, nil, nil,
- 214, nil, nil, 52, nil, nil, 54, nil, 256, nil,
- nil, nil, 40, nil, nil, nil, nil, nil, nil, nil,
- 218, nil, nil, nil, nil, 79, 73, 75, 76, 77,
- 78, nil, nil, nil, 74, 80, nil, nil, nil, 63,
- 64, 65, 56, 51, nil, 53, nil, 57, 58, nil,
- 37, 83, 61, nil, 59, 60, 62, 258, 259, 66,
- 67, nil, nil, nil, nil, nil, 257, 28, 27, 90,
- 89, 91, 92, nil, nil, 219, nil, nil, nil, nil,
- nil, nil, 41, nil, nil, 94, 93, nil, 84, 50,
- 86, 85, 87, 261, 88, 95, 96, nil, 81, 82,
- nil, 38, 39, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 210, nil, nil, 214, nil, nil,
- 52, nil, nil, 54, nil, 256, nil, nil, nil, 40,
- nil, nil, nil, nil, nil, nil, nil, 218, nil, nil,
- nil, nil, 79, 73, 75, 76, 77, 78, nil, nil,
- nil, 74, 80, nil, nil, nil, 63, 64, 65, 56,
- 51, nil, 53, nil, 57, 58, nil, 37, 83, 61,
- nil, 59, 60, 62, 258, 259, 66, 67, nil, nil,
- nil, nil, nil, 257, 291, 295, 90, 89, 91, 92,
- nil, nil, 219, nil, nil, nil, nil, nil, nil, 41,
- nil, nil, 94, 93, nil, 84, 50, 86, 85, 87,
- nil, 88, 95, 96, nil, 81, 82, nil, 38, 39,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 210, nil, nil, 214, nil, nil, 52, nil, nil,
- 54, nil, nil, nil, nil, nil, 40, nil, nil, nil,
- nil, nil, nil, nil, 218, nil, nil, nil, nil, 79,
- 73, 75, 76, 77, 78, nil, nil, nil, 74, 80,
- nil, nil, nil, 63, 64, 65, 56, 51, nil, 53,
- nil, 57, 58, nil, 37, 83, 61, nil, 59, 60,
- 62, 258, 259, 66, 67, nil, nil, nil, nil, nil,
- 257, 291, 295, 90, 89, 91, 92, nil, nil, 219,
- nil, nil, nil, nil, nil, nil, 41, nil, nil, 94,
- 93, nil, 84, 50, 86, 85, 87, nil, 88, 95,
- 96, nil, 81, 82, nil, 38, 39, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 210, nil,
- nil, 214, nil, nil, 52, nil, nil, 54, nil, nil,
- nil, nil, nil, 40, nil, nil, nil, nil, nil, nil,
- nil, 218, nil, nil, nil, nil, 79, 73, 75, 76,
- 77, 78, nil, nil, nil, 74, 80, nil, nil, nil,
- 63, 64, 65, 56, 51, nil, 53, nil, 57, 58,
- nil, 37, 83, 61, nil, 59, 60, 62, 258, 259,
- 66, 67, nil, nil, nil, nil, nil, 257, 291, 295,
- 90, 89, 91, 92, nil, nil, 219, nil, nil, nil,
- nil, nil, nil, 41, nil, nil, 94, 93, nil, 84,
- 50, 86, 85, 87, nil, 88, 95, 96, nil, 81,
- 82, nil, 38, 39, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 210, nil, nil, 214, nil,
- nil, 52, nil, nil, 54, nil, nil, nil, nil, nil,
- 40, nil, nil, nil, nil, nil, nil, nil, 218, nil,
- nil, nil, nil, 79, 73, 75, 76, 77, 78, nil,
- nil, nil, 74, 80, nil, nil, nil, 63, 64, 65,
- 56, 51, nil, 53, nil, 57, 58, nil, 37, 83,
- 61, nil, 59, 60, 62, 23, 24, 66, 67, nil,
- nil, nil, nil, nil, 22, 28, 27, 90, 89, 91,
- 92, nil, nil, 17, nil, nil, nil, nil, nil, nil,
- 41, nil, nil, 94, 93, nil, 84, 50, 86, 85,
- 87, nil, 88, 95, 96, nil, 81, 82, nil, 38,
- 39, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 210, nil, nil, 214, nil, nil, 52, nil,
- nil, 54, nil, nil, nil, nil, nil, 40, nil, nil,
- nil, nil, nil, nil, nil, 18, nil, nil, nil, nil,
- 79, 73, 75, 76, 77, 78, nil, nil, nil, 74,
- 80, nil, nil, nil, 63, 64, 65, 56, 51, nil,
- 53, nil, 57, 58, nil, 37, 83, 61, nil, 59,
- 60, 62, 258, 259, 66, 67, nil, nil, nil, nil,
- nil, 257, 291, 295, 90, 89, 91, 92, nil, nil,
- 219, nil, nil, nil, nil, nil, nil, 41, nil, nil,
- 94, 93, nil, 84, 50, 86, 85, 87, 261, 88,
- 95, 96, nil, 81, 82, nil, 38, 39, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 210,
- nil, nil, 214, nil, nil, 52, nil, nil, 54, nil,
- 658, nil, nil, nil, 40, nil, nil, nil, nil, nil,
- nil, nil, 218, nil, nil, nil, nil, 79, 73, 75,
- 76, 77, 78, nil, nil, nil, 74, 80, nil, nil,
- nil, 63, 64, 65, 56, 51, nil, 53, nil, 57,
- 58, nil, 37, 83, 61, nil, 59, 60, 62, 258,
- 259, 66, 67, nil, nil, nil, nil, nil, 257, 291,
- 295, 90, 89, 91, 92, nil, nil, 219, nil, nil,
- nil, nil, nil, nil, 41, nil, nil, 94, 93, nil,
- 84, 50, 86, 85, 87, 261, 88, 95, 96, nil,
- 81, 82, nil, 38, 39, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 210, nil, nil, 214,
- nil, nil, 52, nil, nil, 54, nil, nil, nil, nil,
- nil, 40, nil, nil, nil, nil, nil, nil, nil, 218,
- nil, nil, nil, nil, 79, 73, 75, 76, 77, 78,
- nil, nil, nil, 74, 80, nil, nil, nil, nil, nil,
- nil, 56, nil, nil, 53, nil, nil, nil, nil, 37,
- 83, 63, 64, 65, 8, 51, nil, nil, nil, 57,
- 58, nil, nil, nil, 61, nil, 59, 60, 62, 23,
- 24, 66, 67, nil, nil, nil, nil, nil, 22, 28,
- 27, 90, 89, 91, 92, nil, nil, 17, nil, nil,
- nil, nil, nil, 7, 41, nil, 9, 94, 93, nil,
- 84, 50, 86, 85, 87, nil, 88, 95, 96, nil,
- 81, 82, nil, 38, 39, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 36, nil, nil, 30,
- nil, nil, 52, nil, nil, 54, nil, 32, nil, nil,
- nil, 40, nil, nil, nil, nil, nil, nil, nil, 18,
- nil, nil, nil, nil, 79, 73, 75, 76, 77, 78,
- nil, nil, nil, 74, 80, nil, nil, nil, nil, nil,
- nil, 56, nil, nil, 53, nil, nil, nil, nil, 37,
- 83, 63, 64, 65, 8, 51, nil, nil, nil, 57,
- 58, nil, nil, nil, 61, nil, 59, 60, 62, 23,
- 24, 66, 67, nil, nil, nil, nil, nil, 22, 28,
- 27, 90, 89, 91, 92, nil, nil, 17, nil, nil,
- nil, nil, nil, 7, 41, nil, 9, 94, 93, nil,
- 84, 50, 86, 85, 87, nil, 88, 95, 96, nil,
- 81, 82, nil, 38, 39, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 36, nil, nil, 30,
- nil, nil, 52, nil, nil, 54, nil, 32, nil, nil,
- nil, 40, nil, nil, nil, nil, nil, nil, nil, 18,
- nil, nil, nil, nil, 79, 73, 75, 76, 77, 78,
- nil, nil, nil, 74, 80, nil, nil, nil, 63, 64,
- 65, 56, 51, nil, 53, nil, 57, 58, nil, 37,
- 83, 61, nil, 59, 60, 62, 258, 259, 66, 67,
- nil, nil, nil, nil, nil, 257, 291, 295, 90, 89,
- 91, 92, nil, nil, 219, nil, nil, nil, nil, nil,
- nil, 292, nil, nil, 94, 93, nil, 84, 50, 86,
- 85, 87, nil, 88, 95, 96, nil, 81, 82, 764,
- nil, 336, 334, 333, 754, 335, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 751, nil, nil, nil, nil,
- nil, nil, nil, 712, nil, nil, 214, nil, nil, 52,
- nil, nil, 54, nil, nil, nil, nil, nil, 338, nil,
- nil, nil, nil, nil, nil, nil, 341, 340, 344, 343,
- nil, 79, 73, 75, 76, 77, 78, nil, nil, nil,
- 74, 80, nil, nil, nil, nil, nil, nil, 56, nil,
- nil, 53, nil, nil, nil, nil, 296, 83, 63, 64,
- 65, 8, 51, nil, nil, 752, 57, 58, nil, nil,
- nil, 61, nil, 59, 60, 62, 23, 24, 66, 67,
- nil, nil, nil, nil, nil, 22, 28, 27, 90, 89,
- 91, 92, nil, nil, 17, nil, nil, nil, nil, nil,
- 7, 41, nil, 9, 94, 93, nil, 84, 50, 86,
- 85, 87, nil, 88, 95, 96, nil, 81, 82, nil,
- 38, 39, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 36, nil, nil, 30, nil, nil, 52,
- nil, nil, 54, nil, 32, nil, nil, nil, 40, nil,
- nil, nil, nil, nil, nil, nil, 18, nil, nil, nil,
- nil, 79, 73, 75, 76, 77, 78, nil, nil, nil,
- 74, 80, nil, nil, nil, nil, nil, nil, 56, nil,
- nil, 53, nil, nil, nil, nil, 37, 83, 63, 64,
- 65, 8, 51, nil, nil, nil, 57, 58, nil, nil,
- nil, 61, nil, 59, 60, 62, 23, 24, 66, 67,
- nil, nil, nil, nil, nil, 22, 28, 27, 90, 89,
- 91, 92, nil, nil, 17, nil, nil, nil, nil, nil,
- 7, 41, nil, 9, 94, 93, nil, 84, 50, 86,
- 85, 87, nil, 88, 95, 96, nil, 81, 82, nil,
- 38, 39, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 36, nil, nil, 30, nil, nil, 52,
- nil, nil, 54, nil, 32, nil, nil, nil, 40, nil,
- nil, nil, nil, nil, nil, nil, 18, nil, nil, nil,
- nil, 79, 73, 75, 76, 77, 78, nil, nil, nil,
- 74, 80, nil, nil, nil, nil, nil, nil, 56, nil,
- nil, 53, nil, nil, nil, nil, 37, 83, 63, 64,
- 65, 8, 51, nil, nil, nil, 57, 58, nil, nil,
- nil, 61, nil, 59, 60, 62, 23, 24, 66, 67,
- nil, nil, nil, nil, nil, 22, 28, 27, 90, 89,
- 91, 92, nil, nil, 17, nil, nil, nil, nil, nil,
- 7, 41, nil, 9, 94, 93, nil, 84, 50, 86,
- 85, 87, nil, 88, 95, 96, nil, 81, 82, nil,
- 38, 39, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 36, nil, nil, 30, nil, nil, 52,
- nil, nil, 54, nil, 32, nil, nil, nil, 40, nil,
- nil, nil, nil, nil, nil, nil, 18, nil, nil, nil,
- nil, 79, 73, 75, 76, 77, 78, nil, nil, nil,
- 74, 80, nil, nil, nil, 63, 64, 65, 56, 51,
- nil, 53, nil, 57, 58, nil, 37, 83, 61, nil,
- 59, 60, 62, 258, 259, 66, 67, nil, nil, nil,
- nil, nil, 257, 28, 27, 90, 89, 91, 92, nil,
- nil, 219, nil, nil, nil, nil, nil, nil, 41, nil,
- nil, 94, 93, nil, 84, 50, 86, 85, 87, 261,
- 88, 95, 96, nil, 81, 82, nil, 38, 39, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 210, nil, nil, 214, nil, nil, 52, nil, nil, 54,
- nil, 256, nil, nil, nil, 40, nil, nil, nil, nil,
- nil, nil, nil, 218, nil, nil, nil, nil, 79, 73,
- 75, 76, 77, 78, nil, nil, nil, 74, 80, nil,
- nil, nil, 63, 64, 65, 56, 51, nil, 53, nil,
- 57, 58, nil, 37, 83, 61, nil, 59, 60, 62,
- 258, 259, 66, 67, nil, nil, nil, nil, nil, 257,
- 28, 27, 90, 89, 91, 92, nil, nil, 219, nil,
- nil, nil, nil, nil, nil, 41, nil, nil, 94, 93,
- nil, 84, 50, 86, 85, 87, 261, 88, 95, 96,
- nil, 81, 82, nil, 38, 39, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 210, nil, nil,
- 214, nil, nil, 52, nil, nil, 54, nil, 256, nil,
- nil, nil, 40, nil, nil, nil, nil, nil, nil, nil,
- 218, nil, nil, nil, nil, 79, 73, 75, 76, 77,
- 78, nil, nil, nil, 74, 80, nil, nil, nil, 63,
- 64, 65, 56, 51, nil, 53, nil, 57, 58, nil,
- 37, 83, 61, nil, 59, 60, 62, 258, 259, 66,
- 67, nil, nil, nil, nil, nil, 257, 28, 27, 90,
- 89, 91, 92, nil, nil, 219, nil, nil, nil, nil,
- nil, nil, 41, nil, nil, 94, 93, nil, 84, 50,
- 86, 85, 87, 261, 88, 95, 96, nil, 81, 82,
- nil, 38, 39, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 210, nil, nil, 214, nil, nil,
- 52, nil, nil, 54, nil, 256, nil, nil, nil, 40,
- nil, nil, nil, nil, nil, nil, nil, 218, nil, nil,
- nil, nil, 79, 73, 75, 76, 77, 78, nil, nil,
- nil, 74, 80, nil, nil, nil, 63, 64, 65, 56,
- 51, nil, 53, nil, 57, 58, nil, 37, 83, 61,
- nil, 59, 60, 62, 23, 24, 66, 67, nil, nil,
- nil, nil, nil, 22, 28, 27, 90, 89, 91, 92,
- nil, nil, 17, nil, nil, nil, nil, nil, nil, 41,
- nil, nil, 94, 93, nil, 84, 50, 86, 85, 87,
- nil, 88, 95, 96, nil, 81, 82, nil, 38, 39,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 210, nil, nil, 214, nil, nil, 52, nil, nil,
- 54, nil, nil, nil, nil, nil, 40, nil, nil, nil,
- nil, nil, nil, nil, 18, nil, nil, nil, nil, 79,
- 73, 75, 76, 77, 78, nil, nil, nil, 74, 80,
- nil, nil, nil, 63, 64, 65, 56, 51, nil, 53,
- nil, 57, 58, nil, 37, 83, 61, nil, 59, 60,
- 62, 23, 24, 66, 67, nil, nil, nil, nil, nil,
- 22, 28, 27, 90, 89, 91, 92, nil, nil, 17,
- nil, nil, nil, nil, nil, nil, 41, nil, nil, 94,
- 93, nil, 84, 50, 86, 85, 87, nil, 88, 95,
- 96, nil, 81, 82, nil, 38, 39, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 210, nil,
- nil, 214, nil, nil, 52, nil, nil, 54, nil, nil,
- nil, nil, nil, 40, nil, nil, nil, nil, nil, nil,
- nil, 18, nil, nil, nil, nil, 79, 73, 75, 76,
- 77, 78, nil, nil, nil, 74, 80, nil, nil, nil,
- 63, 64, 65, 56, 51, nil, 53, nil, 57, 58,
- nil, 37, 83, 61, nil, 59, 60, 62, 258, 259,
- 66, 67, nil, nil, nil, nil, nil, 257, 291, 295,
- 90, 89, 91, 92, nil, nil, 219, nil, nil, nil,
- nil, nil, nil, 41, nil, nil, 94, 93, nil, 84,
- 50, 86, 85, 87, nil, 88, 95, 96, nil, 81,
- 82, nil, 38, 39, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 210, nil, nil, 214, nil,
- nil, 52, nil, nil, 54, nil, nil, nil, nil, nil,
- 40, nil, nil, nil, nil, nil, nil, nil, 218, nil,
- nil, nil, nil, 79, 73, 75, 76, 77, 78, nil,
- nil, nil, 74, 80, nil, nil, nil, 63, 64, 65,
- 56, 51, nil, 53, nil, 57, 58, nil, 37, 83,
- 61, nil, 59, 60, 62, 258, 259, 66, 67, nil,
- nil, nil, nil, nil, 257, 291, 295, 90, 89, 91,
- 92, nil, nil, 219, nil, nil, nil, nil, nil, nil,
- 41, nil, nil, 94, 93, nil, 84, 50, 86, 85,
- 87, nil, 88, 95, 96, nil, 81, 82, nil, 38,
- 39, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 210, nil, nil, 214, nil, nil, 52, nil,
- nil, 54, nil, 775, nil, nil, nil, 40, nil, nil,
- nil, nil, nil, nil, nil, 218, nil, nil, nil, nil,
- 79, 73, 75, 76, 77, 78, nil, nil, nil, 74,
- 80, nil, nil, nil, 63, 64, 65, 56, 51, nil,
- 53, nil, 57, 58, nil, 37, 83, 61, nil, 59,
- 60, 62, 23, 24, 66, 67, nil, nil, nil, nil,
- nil, 22, 28, 27, 90, 89, 91, 92, nil, nil,
- 219, nil, nil, nil, nil, nil, nil, 41, nil, nil,
- 94, 93, nil, 84, 50, 86, 85, 87, nil, 88,
- 95, 96, nil, 81, 82, nil, 38, 39, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 210,
- nil, nil, 214, nil, nil, 52, nil, nil, 54, nil,
- nil, nil, nil, nil, 40, nil, nil, nil, nil, nil,
- nil, nil, 218, nil, nil, nil, nil, 79, 73, 75,
- 76, 77, 78, nil, nil, nil, 74, 80, nil, nil,
- nil, 63, 64, 65, 56, 51, nil, 53, nil, 57,
- 58, nil, 37, 83, 61, nil, 59, 60, 62, 23,
- 24, 66, 67, nil, nil, nil, nil, nil, 22, 28,
- 27, 90, 89, 91, 92, nil, nil, 219, nil, nil,
- nil, nil, nil, nil, 41, nil, nil, 94, 93, nil,
- 84, 50, 86, 85, 87, nil, 88, 95, 96, nil,
- 81, 82, nil, 38, 39, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 210, nil, nil, 214,
- nil, nil, 52, nil, nil, 54, nil, nil, nil, nil,
- nil, 40, nil, nil, nil, nil, nil, nil, nil, 218,
- nil, nil, nil, nil, 79, 73, 75, 76, 77, 78,
- nil, nil, nil, 74, 80, nil, nil, nil, 63, 64,
- 65, 56, 51, nil, 53, nil, 57, 58, nil, 37,
- 83, 61, nil, 59, 60, 62, 23, 24, 66, 67,
- nil, nil, nil, nil, nil, 22, 28, 27, 90, 89,
- 91, 92, nil, nil, 219, nil, nil, nil, nil, nil,
- nil, 41, nil, nil, 94, 93, nil, 84, 50, 86,
- 85, 87, nil, 88, 95, 96, nil, 81, 82, nil,
- 38, 39, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 210, nil, nil, 214, nil, nil, 52,
- nil, nil, 54, nil, nil, nil, nil, nil, 40, nil,
- nil, nil, nil, nil, nil, nil, 218, nil, nil, nil,
- nil, 79, 73, 75, 76, 77, 78, nil, nil, nil,
- 74, 80, nil, nil, nil, 63, 64, 65, 56, 51,
- nil, 53, nil, 57, 58, nil, 37, 83, 61, nil,
- 59, 60, 62, 258, 259, 66, 67, nil, nil, nil,
- nil, nil, 257, 291, 295, 90, 89, 91, 92, nil,
- nil, 219, nil, nil, nil, nil, nil, nil, 41, nil,
- nil, 94, 93, nil, 84, 50, 86, 85, 87, nil,
- 88, 95, 96, nil, 81, 82, nil, 38, 39, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 210, nil, nil, 214, nil, nil, 52, nil, nil, 54,
- nil, nil, nil, nil, nil, 40, nil, nil, nil, nil,
- nil, nil, nil, 218, nil, nil, nil, nil, 79, 73,
- 75, 76, 77, 78, nil, nil, nil, 74, 80, nil,
- nil, nil, 63, 64, 65, 56, 51, nil, 53, nil,
- 57, 58, nil, 37, 83, 61, nil, 59, 60, 62,
- 258, 259, 66, 67, nil, nil, nil, nil, nil, 257,
- 291, 295, 90, 89, 91, 92, nil, nil, 219, nil,
- nil, nil, nil, nil, nil, 41, nil, nil, 94, 93,
- nil, 84, 50, 86, 85, 87, nil, 88, 95, 96,
- nil, 81, 82, nil, 38, 39, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 210, nil, nil,
- 214, nil, nil, 52, nil, nil, 54, nil, nil, nil,
- nil, nil, 40, nil, nil, nil, nil, nil, nil, nil,
- 218, nil, nil, nil, nil, 79, 73, 75, 76, 77,
- 78, nil, nil, nil, 74, 80, nil, nil, nil, nil,
- nil, nil, 56, nil, nil, 53, nil, nil, nil, nil,
- 37, 83, 63, 64, 65, 8, 51, nil, nil, nil,
- 57, 58, nil, nil, nil, 61, nil, 59, 60, 62,
- 23, 24, 66, 67, nil, nil, nil, nil, nil, 22,
- 28, 27, 90, 89, 91, 92, nil, nil, 17, nil,
- nil, nil, nil, nil, 7, 41, nil, 9, 94, 93,
- nil, 84, 50, 86, 85, 87, nil, 88, 95, 96,
- nil, 81, 82, nil, 38, 39, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 36, nil, nil,
- 30, nil, nil, 52, nil, nil, 54, nil, 32, nil,
- nil, nil, 40, nil, nil, nil, nil, nil, nil, nil,
- 18, nil, nil, nil, nil, 79, 73, 75, 76, 77,
- 78, nil, nil, nil, 74, 80, nil, nil, nil, 63,
- 64, 65, 56, 51, nil, 53, nil, 57, 58, nil,
- 37, 83, 61, nil, 59, 60, 62, 258, 259, 66,
- 67, nil, nil, nil, nil, nil, 257, 291, 295, 90,
- 89, 91, 92, nil, nil, 219, nil, nil, nil, nil,
- nil, nil, 41, nil, nil, 94, 93, nil, 84, 50,
- 86, 85, 87, nil, 88, 95, 96, nil, 81, 82,
- nil, 38, 39, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 210, nil, nil, 214, nil, nil,
- 52, nil, nil, 54, nil, nil, nil, nil, nil, 40,
- nil, nil, nil, nil, nil, nil, nil, 218, nil, nil,
- nil, nil, 79, 73, 75, 76, 77, 78, nil, nil,
- nil, 74, 80, nil, nil, nil, nil, nil, nil, 56,
- nil, nil, 53, nil, nil, nil, nil, 37, 83, 63,
- 64, 65, 8, 51, nil, nil, nil, 57, 58, nil,
- nil, nil, 61, nil, 59, 60, 62, 23, 24, 66,
- 67, nil, nil, nil, nil, nil, 22, 28, 27, 90,
- 89, 91, 92, nil, nil, 17, nil, nil, nil, nil,
- nil, 7, 41, nil, 9, 94, 93, nil, 84, 50,
- 86, 85, 87, nil, 88, 95, 96, nil, 81, 82,
- nil, 38, 39, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 36, nil, nil, 30, nil, nil,
- 52, nil, nil, 54, nil, 32, nil, nil, nil, 40,
- nil, nil, nil, nil, nil, nil, nil, 18, nil, nil,
- nil, nil, 79, 73, 75, 76, 77, 78, nil, nil,
- nil, 74, 80, nil, nil, nil, 63, 64, 65, 56,
- 51, nil, 53, nil, 57, 58, nil, 37, 83, 61,
- nil, 59, 60, 62, 258, 259, 66, 67, nil, nil,
- nil, nil, nil, 257, 291, 295, 90, 89, 91, 92,
- nil, nil, 219, nil, nil, nil, nil, nil, nil, 41,
- nil, nil, 94, 93, nil, 84, 50, 86, 85, 87,
- 261, 88, 95, 96, nil, 81, 82, nil, 38, 39,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 210, nil, nil, 214, nil, nil, 52, nil, nil,
- 54, nil, 658, nil, 254, nil, 40, nil, nil, nil,
- nil, nil, nil, nil, 218, nil, nil, nil, nil, 79,
- 73, 75, 76, 77, 78, nil, nil, nil, 74, 80,
- nil, nil, nil, 63, 64, 65, 56, 51, nil, 53,
- nil, 57, 58, nil, 37, 83, 61, nil, 59, 60,
- 62, 258, 259, 66, 67, nil, nil, nil, nil, nil,
- 257, 291, 295, 90, 89, 91, 92, nil, nil, 219,
- nil, nil, nil, nil, nil, nil, 41, nil, nil, 94,
- 93, nil, 84, 50, 86, 85, 87, 261, 88, 95,
- 96, nil, 81, 82, nil, 38, 39, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 210, nil,
- nil, 214, nil, nil, 52, nil, nil, 54, nil, nil,
- nil, 254, nil, 40, nil, nil, nil, nil, nil, nil,
- nil, 218, nil, nil, nil, nil, 79, 73, 75, 76,
- 77, 78, nil, nil, nil, 74, 80, nil, nil, nil,
- nil, nil, nil, 56, nil, nil, 53, nil, nil, nil,
- nil, 37, 83, 63, 64, 65, 8, 51, nil, nil,
- nil, 57, 58, nil, nil, nil, 61, nil, 59, 60,
- 62, 23, 24, 66, 67, nil, nil, nil, nil, nil,
- 22, 28, 27, 90, 89, 91, 92, nil, nil, 17,
- nil, nil, nil, nil, nil, 7, 41, nil, 9, 94,
- 93, nil, 84, 50, 86, 85, 87, nil, 88, 95,
- 96, nil, 81, 82, nil, 38, 39, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 36, nil,
- nil, 30, nil, nil, 52, nil, nil, 54, nil, 32,
- nil, nil, nil, 40, nil, nil, nil, nil, nil, nil,
- nil, 18, nil, nil, nil, nil, 79, 73, 75, 76,
- 77, 78, nil, nil, nil, 74, 80, nil, nil, nil,
- nil, nil, nil, 56, nil, nil, 53, nil, nil, nil,
- nil, 37, 83, 63, 64, 65, 8, 51, nil, nil,
- nil, 57, 58, nil, nil, nil, 61, nil, 59, 60,
- 62, 23, 24, 66, 67, nil, nil, nil, nil, nil,
- 22, 28, 27, 90, 89, 91, 92, nil, nil, 17,
- nil, nil, nil, nil, nil, 7, 41, nil, 9, 94,
- 93, nil, 84, 50, 86, 85, 87, nil, 88, 95,
- 96, nil, 81, 82, nil, 38, 39, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 36, nil,
- nil, 30, nil, nil, 52, nil, nil, 54, nil, 32,
- nil, nil, nil, 40, nil, nil, nil, nil, nil, nil,
- nil, 18, nil, nil, nil, nil, 79, 73, 75, 76,
- 77, 78, nil, nil, nil, 74, 80, nil, nil, nil,
- 63, 64, 65, 56, 51, nil, 53, nil, 57, 58,
- nil, 37, 83, 61, nil, 59, 60, 62, 258, 259,
- 66, 67, nil, nil, nil, nil, nil, 257, 291, 295,
- 90, 89, 91, 92, nil, nil, 219, nil, nil, nil,
- nil, nil, nil, 292, nil, nil, 94, 93, nil, 84,
- 50, 86, 85, 87, nil, 88, 95, 96, nil, 81,
- 82, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 289, nil, nil, 286, nil,
- nil, 52, nil, nil, 54, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 79, 73, 75, 76, 77, 78, nil,
- nil, nil, 74, 80, nil, nil, nil, 63, 64, 65,
- 56, 51, nil, 53, nil, 57, 58, nil, 296, 83,
- 61, nil, 59, 60, 62, 258, 259, 66, 67, nil,
- nil, nil, nil, nil, 257, 291, 295, 90, 89, 91,
- 92, nil, nil, 219, nil, nil, nil, nil, nil, nil,
- 292, nil, nil, 94, 93, nil, 84, 50, 86, 85,
- 87, nil, 88, 95, 96, nil, 81, 82, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 289, nil, nil, 286, nil, nil, 52, nil,
- nil, 54, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 79, 73, 75, 76, 77, 78, nil, nil, nil, 74,
- 80, nil, nil, nil, 63, 64, 65, 56, 51, nil,
- 53, nil, 57, 58, nil, 296, 83, 61, nil, 59,
- 60, 62, 258, 259, 66, 67, nil, nil, nil, nil,
- nil, 257, 291, 295, 90, 89, 91, 92, nil, nil,
- 219, nil, nil, nil, nil, nil, nil, 41, nil, nil,
- 94, 93, nil, 84, 50, 86, 85, 87, nil, 88,
- 95, 96, nil, 81, 82, nil, 38, 39, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 210,
- nil, nil, 214, nil, nil, 52, nil, nil, 54, nil,
- 421, nil, nil, nil, 40, nil, nil, nil, nil, nil,
- nil, nil, 218, nil, nil, nil, nil, 79, 73, 75,
- 76, 77, 78, nil, nil, nil, 74, 80, nil, nil,
- nil, 63, 64, 65, 56, 51, nil, 53, nil, 57,
- 58, nil, 37, 83, 61, nil, 59, 60, 62, 258,
- 259, 66, 67, nil, nil, nil, nil, nil, 257, 291,
- 295, 90, 89, 91, 92, nil, nil, 219, nil, nil,
- nil, nil, nil, nil, 41, nil, nil, 94, 93, nil,
- 84, 50, 86, 85, 87, nil, 88, 95, 96, nil,
- 81, 82, nil, 38, 39, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 210, nil, nil, 214,
- nil, nil, 52, nil, nil, 54, nil, 256, nil, nil,
- nil, 40, nil, nil, nil, nil, nil, nil, nil, 218,
- nil, nil, nil, nil, 79, 73, 75, 76, 77, 78,
- nil, nil, nil, 74, 80, nil, nil, nil, 63, 64,
- 65, 56, 51, nil, 53, nil, 57, 58, nil, 37,
- 83, 61, nil, 59, 60, 62, 23, 24, 66, 67,
- nil, nil, nil, nil, nil, 22, 28, 27, 90, 89,
- 91, 92, nil, nil, 17, nil, nil, nil, nil, nil,
- nil, 41, nil, nil, 94, 93, nil, 84, 50, 86,
- 85, 87, nil, 88, 95, 96, nil, 81, 82, nil,
- 38, 39, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 210, nil, nil, 214, nil, nil, 52,
- nil, nil, 54, nil, nil, nil, nil, nil, 40, nil,
- nil, nil, nil, nil, nil, nil, 18, nil, nil, nil,
- nil, 79, 73, 75, 76, 77, 78, nil, nil, nil,
- 74, 80, nil, nil, nil, nil, nil, nil, 56, nil,
- nil, 53, nil, nil, nil, nil, 37, 83, 63, 64,
- 65, 8, 51, nil, nil, nil, 57, 58, nil, nil,
- nil, 61, nil, 59, 60, 62, 23, 24, 66, 67,
- nil, nil, nil, nil, nil, 22, 28, 27, 90, 89,
- 91, 92, nil, nil, 17, nil, nil, nil, nil, nil,
- 7, 41, nil, 9, 94, 93, nil, 84, 50, 86,
- 85, 87, nil, 88, 95, 96, nil, 81, 82, nil,
- 38, 39, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 36, nil, nil, 30, nil, nil, 52,
- nil, nil, 54, nil, 32, nil, nil, nil, 40, nil,
- nil, nil, nil, nil, nil, nil, 18, nil, nil, nil,
- nil, 79, 73, 75, 76, 77, 78, nil, nil, nil,
- 74, 80, nil, nil, nil, nil, nil, nil, 56, nil,
- nil, 53, nil, nil, nil, nil, 37, 83, 63, 64,
- 65, 8, 51, nil, nil, nil, 57, 58, nil, nil,
- nil, 61, nil, 59, 60, 62, 23, 24, 66, 67,
- nil, nil, nil, nil, nil, 22, 28, 27, 90, 89,
- 91, 92, nil, nil, 17, nil, nil, nil, nil, nil,
- 7, 41, nil, 9, 94, 93, nil, 84, 50, 86,
- 85, 87, nil, 88, 95, 96, nil, 81, 82, nil,
- 38, 39, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 36, nil, nil, 30, nil, nil, 52,
- nil, nil, 54, nil, 32, nil, nil, nil, 40, nil,
- nil, nil, nil, nil, nil, nil, 18, nil, nil, nil,
- nil, 79, 73, 75, 76, 77, 78, nil, nil, nil,
- 74, 80, nil, nil, nil, nil, nil, nil, 56, nil,
- nil, 53, nil, nil, nil, nil, 37, 83, 63, 64,
- 65, 8, 51, nil, nil, nil, 57, 58, nil, nil,
- nil, 61, nil, 59, 60, 62, 23, 24, 66, 67,
- nil, nil, nil, nil, nil, 22, 28, 27, 90, 89,
- 91, 92, nil, nil, 17, nil, nil, nil, nil, nil,
- 7, 41, nil, 9, 94, 93, nil, 84, 50, 86,
- 85, 87, nil, 88, 95, 96, nil, 81, 82, nil,
- 38, 39, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 36, nil, nil, 30, nil, nil, 52,
- nil, nil, 54, nil, 32, nil, nil, nil, 40, nil,
- nil, nil, nil, nil, nil, nil, 18, nil, nil, nil,
- nil, 79, 73, 75, 76, 77, 78, nil, nil, nil,
- 74, 80, nil, nil, nil, 63, 64, 65, 56, 51,
- nil, 53, nil, 57, 58, nil, 37, 83, 61, nil,
- 59, 60, 62, 258, 259, 66, 67, nil, nil, nil,
- nil, nil, 257, 291, 295, 90, 89, 91, 92, nil,
- nil, 219, nil, nil, nil, nil, nil, nil, 41, nil,
- nil, 94, 93, nil, 84, 50, 86, 85, 87, nil,
- 88, 95, 96, nil, 81, 82, nil, 38, 39, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 210, nil, nil, 214, nil, nil, 52, nil, nil, 54,
- nil, nil, nil, nil, nil, 40, nil, nil, nil, nil,
- nil, nil, nil, 218, nil, nil, nil, nil, 79, 73,
- 75, 76, 77, 78, nil, nil, nil, 74, 80, nil,
- nil, nil, nil, nil, nil, 56, nil, nil, 53, nil,
- nil, nil, nil, 37, 83, 63, 64, 65, 8, 51,
- nil, nil, nil, 57, 58, nil, nil, nil, 61, nil,
- 59, 60, 62, 23, 24, 66, 67, nil, nil, nil,
- nil, nil, 22, 28, 27, 90, 89, 91, 92, nil,
- nil, 17, nil, nil, nil, nil, nil, 7, 41, nil,
- 9, 94, 93, nil, 84, 50, 86, 85, 87, nil,
- 88, 95, 96, nil, 81, 82, nil, 38, 39, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 36, nil, nil, 30, nil, nil, 52, nil, nil, 54,
- nil, 32, nil, nil, nil, 40, nil, nil, nil, nil,
- nil, nil, nil, 18, nil, nil, nil, nil, 79, 73,
- 75, 76, 77, 78, nil, nil, nil, 74, 80, nil,
- nil, nil, 63, 64, 65, 56, 51, nil, 53, nil,
- 57, 58, nil, 37, 83, 61, nil, 59, 60, 62,
- 258, 259, 66, 67, nil, nil, nil, nil, nil, 257,
- 291, 295, 90, 89, 91, 92, nil, nil, 219, nil,
- nil, nil, nil, nil, nil, 41, nil, nil, 94, 93,
- nil, 84, 50, 86, 85, 87, nil, 88, 95, 96,
- nil, 81, 82, nil, 38, 39, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 210, nil, nil,
- 214, nil, nil, 52, nil, nil, 54, nil, nil, nil,
- nil, nil, 40, nil, nil, nil, nil, nil, nil, nil,
- 218, nil, nil, nil, nil, 79, 73, 75, 76, 77,
- 78, nil, nil, nil, 74, 80, nil, nil, nil, 63,
- 64, 65, 56, 51, nil, 53, nil, 57, 58, nil,
- 37, 83, 61, nil, 59, 60, 62, 23, 24, 66,
- 67, nil, nil, nil, nil, nil, 22, 28, 27, 90,
- 89, 91, 92, nil, nil, 219, nil, nil, nil, nil,
- nil, nil, 41, nil, nil, 94, 93, nil, 84, 50,
- 86, 85, 87, nil, 88, 95, 96, nil, 81, 82,
- nil, 38, 39, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 210, nil, nil, 214, nil, nil,
- 52, nil, nil, 54, nil, nil, nil, nil, nil, 40,
- nil, nil, nil, nil, nil, nil, nil, 218, nil, nil,
- nil, nil, 79, 73, 75, 76, 77, 78, nil, nil,
- nil, 74, 80, nil, nil, nil, 63, 64, 65, 56,
- 51, nil, 53, nil, 57, 58, nil, 37, 83, 61,
- nil, 59, 60, 62, 23, 24, 66, 67, nil, nil,
- nil, nil, nil, 22, 28, 27, 90, 89, 91, 92,
- nil, nil, 219, nil, nil, nil, nil, nil, nil, 41,
- nil, nil, 94, 93, nil, 84, 50, 86, 85, 87,
- nil, 88, 95, 96, nil, 81, 82, nil, 38, 39,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 210, nil, nil, 214, nil, nil, 52, nil, nil,
- 54, nil, nil, nil, nil, nil, 40, nil, nil, nil,
- nil, nil, nil, nil, 218, nil, nil, nil, nil, 79,
- 73, 75, 76, 77, 78, nil, nil, nil, 74, 80,
- nil, nil, nil, 63, 64, 65, 56, 51, nil, 53,
- nil, 57, 58, nil, 37, 83, 61, nil, 59, 60,
- 62, 258, 259, 66, 67, nil, nil, nil, nil, nil,
- 257, 291, 295, 90, 89, 91, 92, nil, nil, 219,
- nil, nil, nil, nil, nil, nil, 41, nil, nil, 94,
- 93, nil, 84, 50, 86, 85, 87, nil, 88, 95,
- 96, nil, 81, 82, nil, 38, 39, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 210, nil,
- nil, 214, nil, nil, 52, nil, nil, 54, nil, nil,
- nil, nil, nil, 40, nil, nil, nil, nil, nil, nil,
- nil, 218, nil, nil, nil, nil, 79, 73, 75, 76,
- 77, 78, nil, nil, nil, 74, 80, nil, nil, nil,
- 63, 64, 65, 56, 51, nil, 53, nil, 57, 58,
- nil, 37, 83, 61, nil, 59, 60, 62, 258, 259,
- 66, 67, nil, nil, nil, nil, nil, 257, 291, 295,
- 90, 89, 91, 92, nil, nil, 219, nil, nil, nil,
- nil, nil, nil, 41, nil, nil, 94, 93, nil, 84,
- 50, 86, 85, 87, nil, 88, 95, 96, nil, 81,
- 82, nil, 38, 39, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 210, nil, nil, 214, nil,
- nil, 52, nil, nil, 54, nil, nil, nil, nil, nil,
- 40, nil, nil, nil, nil, nil, nil, nil, 218, nil,
- nil, nil, nil, 79, 73, 75, 76, 77, 78, nil,
- nil, nil, 74, 80, nil, nil, nil, 63, 64, 65,
- 56, 51, nil, 53, nil, 57, 58, nil, 37, 83,
- 61, nil, 59, 60, 62, 258, 259, 66, 67, nil,
- nil, nil, nil, nil, 257, 291, 295, 90, 89, 91,
- 92, nil, nil, 219, nil, nil, nil, nil, nil, nil,
- 41, nil, nil, 94, 93, nil, 84, 50, 86, 85,
- 87, nil, 88, 95, 96, nil, 81, 82, nil, 38,
- 39, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 210, nil, nil, 214, nil, nil, 52, nil,
- nil, 54, nil, nil, nil, nil, nil, 40, nil, nil,
- nil, nil, nil, nil, nil, 218, nil, nil, nil, nil,
- 79, 73, 75, 76, 77, 78, nil, nil, nil, 74,
- 80, nil, nil, nil, 63, 64, 65, 56, 51, nil,
- 53, nil, 57, 58, nil, 37, 83, 61, nil, 59,
- 60, 62, 258, 259, 66, 67, nil, nil, nil, nil,
- nil, 257, 291, 295, 90, 89, 91, 92, nil, nil,
- 219, nil, nil, nil, nil, nil, nil, 41, nil, nil,
- 94, 93, nil, 84, 50, 86, 85, 87, nil, 88,
- 95, 96, nil, 81, 82, nil, 38, 39, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 210,
- nil, nil, 214, nil, nil, 52, nil, nil, 54, nil,
- 256, nil, nil, nil, 40, nil, nil, nil, nil, nil,
- nil, nil, 218, nil, nil, nil, nil, 79, 73, 75,
- 76, 77, 78, nil, nil, nil, 74, 80, nil, nil,
- nil, nil, nil, nil, 56, nil, nil, 53, nil, nil,
- nil, nil, 37, 83, 63, 64, 65, 8, 51, nil,
- nil, nil, 57, 58, nil, nil, nil, 61, nil, 59,
- 60, 62, 23, 24, 66, 67, nil, nil, nil, nil,
- nil, 22, 28, 27, 90, 89, 91, 92, nil, nil,
- 17, nil, nil, nil, nil, nil, 7, 41, nil, 9,
- 94, 93, nil, 84, 50, 86, 85, 87, nil, 88,
- 95, 96, nil, 81, 82, nil, 38, 39, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 36,
- nil, nil, 30, nil, nil, 52, nil, nil, 54, nil,
- 32, nil, nil, nil, 40, nil, nil, nil, nil, nil,
- nil, nil, 18, nil, nil, nil, nil, 79, 73, 75,
- 76, 77, 78, nil, nil, nil, 74, 80, nil, nil,
- nil, 63, 64, 65, 56, 51, nil, 53, nil, 57,
- 58, nil, 37, 83, 61, nil, 59, 60, 62, 23,
- 24, 66, 67, nil, nil, nil, nil, nil, 22, 28,
- 27, 90, 89, 91, 92, nil, nil, 17, nil, nil,
- nil, nil, nil, nil, 41, nil, nil, 94, 93, nil,
- 84, 50, 86, 85, 87, nil, 88, 95, 96, nil,
- 81, 82, nil, 38, 39, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 210, nil, nil, 214,
- nil, nil, 52, nil, nil, 54, nil, nil, nil, nil,
- nil, 40, nil, nil, nil, nil, nil, nil, nil, 18,
- nil, nil, nil, nil, 79, 73, 75, 76, 77, 78,
- nil, nil, nil, 74, 80, nil, nil, nil, nil, nil,
- nil, 56, nil, nil, 53, nil, nil, nil, nil, 37,
- 83, 63, 64, 65, 8, 51, nil, nil, nil, 57,
- 58, nil, nil, nil, 61, nil, 59, 60, 62, 23,
- 24, 66, 67, nil, nil, nil, nil, nil, 22, 28,
- 27, 90, 89, 91, 92, nil, nil, 17, nil, nil,
- nil, nil, nil, 7, 41, nil, 9, 94, 93, nil,
- 84, 50, 86, 85, 87, nil, 88, 95, 96, nil,
- 81, 82, nil, 38, 39, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 36, nil, nil, 30,
- nil, nil, 52, nil, nil, 54, nil, 32, nil, nil,
- nil, 40, nil, nil, nil, nil, nil, nil, nil, 18,
- nil, nil, nil, nil, 79, 73, 75, 76, 77, 78,
- nil, nil, nil, 74, 80, nil, nil, nil, nil, nil,
- nil, 56, nil, nil, 53, nil, nil, nil, nil, 37,
- 83, 63, 64, 65, 8, 51, nil, nil, nil, 57,
- 58, nil, nil, nil, 61, nil, 59, 60, 62, 23,
- 24, 66, 67, nil, nil, nil, nil, nil, 22, 28,
- 27, 90, 89, 91, 92, nil, nil, 17, nil, nil,
- nil, nil, nil, 7, 41, nil, 9, 94, 93, nil,
- 84, 50, 86, 85, 87, nil, 88, 95, 96, nil,
- 81, 82, nil, 38, 39, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 36, nil, nil, 30,
- nil, nil, 52, nil, nil, 54, nil, 32, nil, nil,
- nil, 40, nil, nil, nil, nil, nil, nil, nil, 18,
- nil, nil, nil, nil, 79, 73, 75, 76, 77, 78,
- nil, nil, nil, 74, 80, nil, nil, nil, 63, 64,
- 65, 56, 51, nil, 53, nil, 57, 58, nil, 37,
- 83, 61, nil, 59, 60, 62, 258, 259, 66, 67,
- nil, nil, nil, nil, nil, 257, 291, 295, 90, 89,
- 91, 92, nil, nil, 219, nil, nil, nil, nil, nil,
- nil, 41, nil, nil, 94, 93, nil, 84, 50, 86,
- 85, 87, nil, 88, 95, 96, nil, 81, 82, nil,
- 38, 39, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 210, nil, nil, 214, nil, nil, 52,
- nil, nil, 54, nil, nil, nil, nil, nil, 40, nil,
- nil, nil, nil, nil, nil, nil, 218, nil, nil, nil,
- nil, 79, 73, 75, 76, 77, 78, nil, nil, nil,
- 74, 80, nil, nil, nil, 63, 64, 65, 56, 51,
- nil, 53, nil, 57, 58, nil, 37, 83, 61, nil,
- 59, 60, 62, 258, 259, 66, 67, nil, nil, nil,
- nil, nil, 257, 291, 295, 90, 89, 91, 92, nil,
- nil, 219, nil, nil, nil, nil, nil, nil, 41, nil,
- nil, 94, 93, nil, 84, 50, 86, 85, 87, nil,
- 88, 95, 96, nil, 81, 82, nil, 38, 39, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 210, nil, nil, 214, nil, nil, 52, nil, nil, 54,
- nil, nil, nil, nil, nil, 40, nil, nil, nil, nil,
- nil, nil, nil, 218, nil, nil, nil, nil, 79, 73,
- 75, 76, 77, 78, nil, nil, nil, 74, 80, nil,
- nil, nil, 63, 64, 65, 56, 51, nil, 53, nil,
- 57, 58, nil, 37, 83, 61, nil, 59, 60, 62,
- 258, 259, 66, 67, nil, nil, nil, nil, nil, 257,
- 291, 295, 90, 89, 91, 92, nil, nil, 219, nil,
- nil, nil, nil, nil, nil, 41, nil, nil, 94, 93,
- nil, 84, 50, 86, 85, 87, nil, 88, 95, 96,
- nil, 81, 82, nil, 38, 39, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 210, nil, nil,
- 214, nil, nil, 52, nil, nil, 54, nil, nil, nil,
- nil, nil, 40, nil, nil, nil, nil, nil, nil, nil,
- 218, nil, nil, nil, nil, 79, 73, 75, 76, 77,
- 78, nil, nil, nil, 74, 80, nil, nil, nil, 63,
- 64, 65, 56, 51, nil, 53, nil, 57, 58, nil,
- 37, 83, 61, nil, 59, 60, 62, 258, 259, 66,
- 67, nil, nil, nil, nil, nil, 257, 291, 295, 90,
- 89, 91, 92, nil, nil, 219, nil, nil, nil, nil,
- nil, nil, 41, nil, nil, 94, 93, nil, 84, 50,
- 86, 85, 87, 261, 88, 95, 96, nil, 81, 82,
- nil, 38, 39, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 210, nil, nil, 214, nil, nil,
- 52, nil, nil, 54, nil, nil, nil, 254, nil, 40,
- nil, nil, nil, nil, nil, nil, nil, 218, nil, nil,
- nil, nil, 79, 73, 75, 76, 77, 78, nil, nil,
- nil, 74, 80, nil, nil, nil, nil, nil, nil, 56,
- nil, nil, 53, nil, nil, nil, nil, 37, 83, 63,
- 64, 65, 8, 51, nil, nil, nil, 57, 58, nil,
- nil, nil, 61, nil, 59, 60, 62, 23, 24, 66,
- 67, nil, nil, nil, nil, nil, 22, 28, 27, 90,
- 89, 91, 92, nil, nil, 17, nil, nil, nil, nil,
- nil, 7, 41, nil, 9, 94, 93, nil, 84, 50,
- 86, 85, 87, nil, 88, 95, 96, nil, 81, 82,
- nil, 38, 39, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 36, nil, nil, 30, nil, nil,
- 52, nil, nil, 54, nil, 32, nil, nil, nil, 40,
- nil, nil, nil, nil, nil, nil, nil, 18, nil, nil,
- nil, nil, 79, 73, 75, 76, 77, 78, nil, nil,
- nil, 74, 80, nil, nil, nil, 63, 64, 65, 56,
- 51, nil, 53, nil, 57, 58, nil, 37, 83, 61,
- nil, 59, 60, 62, 258, 259, 66, 67, nil, nil,
- nil, nil, nil, 257, 291, 295, 90, 89, 91, 92,
- nil, nil, 219, nil, nil, nil, nil, nil, nil, 292,
- nil, nil, 94, 93, nil, 84, 50, 86, 85, 87,
- nil, 88, 95, 96, nil, 81, 82, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 926, nil, nil, 214, nil, nil, 52, nil, nil,
- 54, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 79,
- 73, 75, 76, 77, 78, nil, nil, nil, 74, 80,
- nil, nil, nil, 63, 64, 65, 56, 51, nil, 53,
- nil, 57, 58, nil, 296, 83, 61, nil, 59, 60,
- 62, 258, 259, 66, 67, nil, nil, nil, nil, nil,
- 257, 291, 295, 90, 89, 91, 92, nil, nil, 219,
- nil, nil, nil, nil, nil, nil, 41, nil, nil, 94,
- 93, nil, 84, 50, 86, 85, 87, nil, 88, 95,
- 96, nil, 81, 82, nil, 38, 39, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 210, nil,
- nil, 214, nil, nil, 52, nil, nil, 54, nil, 658,
- nil, nil, nil, 40, nil, nil, nil, nil, nil, nil,
- nil, 218, nil, nil, nil, nil, 79, 73, 75, 76,
- 77, 78, nil, nil, nil, 74, 80, nil, nil, nil,
- nil, nil, nil, 56, nil, nil, 53, nil, nil, nil,
- nil, 37, 83, 63, 64, 65, 8, 51, nil, nil,
- nil, 57, 58, nil, nil, nil, 61, nil, 59, 60,
- 62, 23, 24, 66, 67, nil, nil, nil, nil, nil,
- 22, 28, 27, 90, 89, 91, 92, nil, nil, 17,
- nil, nil, nil, nil, nil, 7, 41, nil, 9, 94,
- 93, nil, 84, 50, 86, 85, 87, nil, 88, 95,
- 96, nil, 81, 82, nil, 38, 39, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 36, nil,
- nil, 30, nil, nil, 52, nil, nil, 54, nil, 32,
- nil, nil, nil, 40, nil, nil, nil, nil, nil, nil,
- nil, 18, nil, nil, nil, nil, 79, 73, 75, 76,
- 77, 78, nil, nil, nil, 74, 80, nil, nil, nil,
- nil, nil, nil, 56, nil, nil, 53, nil, nil, nil,
- nil, 37, 83, 63, 64, 65, 8, 51, nil, nil,
- nil, 57, 58, nil, nil, nil, 61, nil, 59, 60,
- 62, 23, 24, 66, 67, nil, nil, nil, nil, nil,
- 22, 28, 27, 90, 89, 91, 92, nil, nil, 17,
- nil, nil, nil, nil, nil, 7, 41, nil, 9, 94,
- 93, nil, 84, 50, 86, 85, 87, nil, 88, 95,
- 96, nil, 81, 82, nil, 38, 39, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 36, nil,
- nil, 30, nil, nil, 52, nil, nil, 54, nil, 32,
- nil, nil, nil, 40, nil, nil, nil, nil, nil, nil,
- nil, 18, nil, nil, nil, nil, 79, 73, 75, 76,
- 77, 78, nil, nil, nil, 74, 80, nil, nil, nil,
- 63, 64, 65, 56, 51, nil, 53, nil, 57, 58,
- nil, 37, 83, 61, nil, 59, 60, 62, 258, 259,
- 66, 67, nil, nil, nil, nil, nil, 257, 291, 295,
- 90, 89, 91, 92, nil, nil, 219, nil, nil, nil,
- nil, nil, nil, 41, nil, nil, 94, 93, nil, 84,
- 50, 86, 85, 87, nil, 88, 95, 96, nil, 81,
- 82, nil, 38, 39, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 210, nil, nil, 214, nil,
- nil, 52, nil, nil, 54, nil, 658, nil, 254, nil,
- 40, nil, nil, nil, nil, nil, nil, nil, 218, nil,
- nil, nil, nil, 79, 73, 75, 76, 77, 78, nil,
- nil, nil, 74, 80, nil, nil, nil, nil, nil, nil,
- 56, nil, nil, 53, nil, nil, nil, nil, 37, 83,
- 63, 64, 65, 8, 51, nil, nil, nil, 57, 58,
- nil, nil, nil, 61, nil, 59, 60, 62, 23, 24,
- 66, 67, nil, nil, nil, nil, nil, 22, 28, 27,
- 90, 89, 91, 92, nil, nil, 17, nil, nil, nil,
- nil, nil, 7, 41, nil, 9, 94, 93, nil, 84,
- 50, 86, 85, 87, nil, 88, 95, 96, nil, 81,
- 82, nil, 38, 39, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 36, nil, nil, 30, nil,
- nil, 52, nil, nil, 54, nil, 32, nil, nil, nil,
- 40, nil, nil, nil, nil, nil, nil, nil, 18, nil,
- nil, nil, nil, 79, 73, 75, 76, 77, 78, nil,
- nil, nil, 74, 80, nil, nil, nil, nil, nil, nil,
- 56, nil, nil, 53, nil, nil, nil, nil, 37, 83,
- 63, 64, 65, 8, 51, nil, nil, nil, 57, 58,
- nil, nil, nil, 61, nil, 59, 60, 62, 23, 24,
- 66, 67, nil, nil, nil, nil, nil, 22, 28, 27,
- 90, 89, 91, 92, nil, nil, 17, nil, nil, nil,
- nil, nil, 7, 41, nil, 9, 94, 93, nil, 84,
- 50, 86, 85, 87, nil, 88, 95, 96, nil, 81,
- 82, nil, 38, 39, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 36, nil, nil, 30, nil,
- nil, 52, nil, nil, 54, nil, 32, nil, nil, nil,
- 40, nil, nil, nil, nil, nil, nil, nil, 18, nil,
- nil, nil, nil, 79, 73, 75, 76, 77, 78, nil,
- nil, nil, 74, 80, nil, nil, nil, nil, nil, nil,
- 56, nil, nil, 53, nil, nil, nil, nil, 37, 83,
- 63, 64, 65, 8, 51, nil, nil, nil, 57, 58,
- nil, nil, nil, 61, nil, 59, 60, 62, 23, 24,
- 66, 67, nil, nil, nil, nil, nil, 22, 28, 27,
- 90, 89, 91, 92, nil, nil, 17, nil, nil, nil,
- nil, nil, 7, 41, nil, 9, 94, 93, nil, 84,
- 50, 86, 85, 87, nil, 88, 95, 96, nil, 81,
- 82, nil, 38, 39, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 36, nil, nil, 30, nil,
- nil, 52, nil, nil, 54, nil, 32, nil, nil, nil,
- 40, nil, nil, nil, nil, nil, nil, nil, 18, nil,
- nil, nil, nil, 79, 73, 75, 76, 77, 78, nil,
- nil, nil, 74, 80, nil, nil, nil, nil, nil, nil,
- 56, nil, nil, 53, nil, nil, nil, nil, 37, 83,
- 63, 64, 65, 8, 51, nil, nil, nil, 57, 58,
- nil, nil, nil, 61, nil, 59, 60, 62, 23, 24,
- 66, 67, nil, nil, nil, nil, nil, 22, 28, 27,
- 90, 89, 91, 92, nil, nil, 17, nil, nil, nil,
- nil, nil, 7, 41, nil, 9, 94, 93, nil, 84,
- 50, 86, 85, 87, nil, 88, 95, 96, nil, 81,
- 82, nil, 38, 39, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 36, nil, nil, 30, nil,
- nil, 52, nil, nil, 54, nil, 32, nil, nil, nil,
- 40, nil, nil, nil, nil, nil, nil, nil, 18, nil,
- nil, nil, nil, 79, 73, 75, 76, 77, 78, nil,
- nil, nil, 74, 80, nil, nil, nil, 63, 64, 65,
- 56, 51, nil, 53, nil, 57, 58, nil, 37, 83,
- 61, nil, 59, 60, 62, 258, 259, 66, 67, nil,
- nil, nil, nil, nil, 257, 28, 27, 90, 89, 91,
- 92, nil, nil, 219, nil, nil, nil, nil, nil, nil,
- 41, nil, nil, 94, 93, nil, 84, 50, 86, 85,
- 87, 261, 88, 95, 96, nil, 81, 82, nil, 38,
- 39, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 210, nil, nil, 214, nil, nil, 52, nil,
- nil, 54, nil, 256, nil, nil, nil, 40, nil, nil,
- nil, nil, nil, nil, nil, 218, nil, nil, nil, -538,
- 79, 73, 75, 76, 77, 78, -538, -538, -538, 74,
- 80, nil, -538, -538, nil, -538, nil, 56, nil, nil,
- 53, nil, nil, nil, -538, 37, 83, nil, nil, nil,
- nil, nil, nil, nil, nil, -538, -538, nil, -538, -538,
- -538, -538, -538, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, -538, -538, -538, -538,
- -538, -538, -538, -538, -538, -538, -538, -538, -538, -538,
- -538, -283, nil, -538, -538, -538, nil, 636, -283, -283,
- -283, -538, nil, nil, -283, -283, nil, -283, -538, nil,
- -538, nil, -538, -538, -538, -538, -538, -538, -538, nil,
- -538, -538, -538, nil, nil, nil, nil, -283, -283, nil,
- -283, -283, -283, -283, -283, -538, -538, nil, -87, nil,
- -538, nil, nil, -538, nil, -538, nil, -96, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, -283, -283,
- -283, -283, -283, -283, -283, -283, -283, -283, -283, -283,
- -283, -283, -283, nil, nil, -283, -283, -283, nil, 639,
- nil, nil, nil, -283, nil, nil, nil, nil, nil, nil,
- -283, nil, -283, nil, -283, -283, -283, -283, -283, -283,
- -283, nil, -283, nil, -283, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, -283, -283, nil,
- -89, nil, -283, -538, nil, -283, nil, -283, nil, -98,
- -538, -538, -538, nil, nil, -538, -538, -538, nil, -538,
- nil, nil, nil, nil, nil, nil, nil, nil, -538, -538,
- -538, nil, nil, nil, nil, nil, nil, nil, nil, -538,
- -538, nil, -538, -538, -538, -538, -538, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- -538, -538, -538, -538, -538, -538, -538, -538, -538, -538,
- -538, -538, -538, -538, -538, nil, nil, -538, -538, -538,
- nil, 790, -538, nil, nil, -538, nil, nil, -538, nil,
- -538, nil, -538, nil, -538, nil, -538, -538, -538, -538,
- -538, -538, -538, nil, -538, -538, -538, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, -538,
- -538, -538, -538, nil, -538, -283, nil, -538, nil, -538,
- nil, -96, -283, -283, -283, nil, nil, -283, -283, -283,
- nil, -283, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, -283, -283, nil, nil, nil, nil, nil, nil, nil,
- nil, -283, -283, nil, -283, -283, -283, -283, -283, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, -283, -283, -283, -283, -283, -283, -283, -283,
- -283, -283, -283, -283, -283, -283, -283, nil, nil, -283,
- -283, -283, nil, 639, -283, nil, nil, -283, nil, nil,
- -283, nil, -283, nil, -283, nil, -283, nil, -283, -283,
- -283, -283, -283, -283, -283, nil, -283, nil, -283, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, -283, -283, -283, -283, nil, -283, -292, nil, -283,
- nil, -283, nil, -98, -292, -292, -292, nil, nil, -292,
- -292, -292, nil, -292, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, -292, -292, nil, nil, nil, nil, nil,
- nil, nil, nil, -292, -292, nil, -292, -292, -292, -292,
- -292, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, -292, -292, -292, -292, -292, -292,
- -292, -292, -292, -292, -292, -292, -292, -292, -292, nil,
- nil, -292, -292, -292, nil, nil, -292, nil, 277, -292,
- nil, nil, -292, nil, -292, nil, -292, nil, -292, nil,
- -292, -292, -292, -292, -292, -292, -292, nil, -292, nil,
- -292, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, -292, -292, -292, -292, -278, -292, nil,
- nil, -292, nil, -292, -278, -278, -278, nil, nil, -278,
- -278, -278, nil, -278, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, -278, -278, -278, nil, nil, nil, nil,
- nil, nil, nil, -278, -278, nil, -278, -278, -278, -278,
- -278, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, -278, -278, -278, -278, -278, -278,
- -278, -278, -278, -278, -278, -278, -278, -278, -278, nil,
- nil, -278, -278, -278, nil, nil, -278, nil, nil, -278,
- nil, nil, -278, nil, -278, nil, -278, nil, -278, nil,
- -278, -278, -278, -278, -278, -278, -278, nil, -278, nil,
- -278, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, -278, -278, -278, -278, -554, -278, nil,
- -278, -278, nil, -278, -554, -554, -554, nil, nil, -554,
- -554, -554, nil, -554, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, -554, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, -554, -554, nil, -554, -554, -554, -554,
- -554, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, -554, nil, nil, nil, nil, nil,
- nil, -554, -554, -554, nil, nil, -554, -554, -554, nil,
- -554, nil, nil, nil, nil, -554, -554, nil, nil, nil,
- -554, nil, nil, -554, nil, nil, nil, nil, 268, -554,
- -554, -554, nil, -554, -554, -554, -554, -554, nil, nil,
- nil, nil, 764, nil, 336, 334, 333, 754, 335, nil,
- -554, nil, nil, nil, nil, nil, nil, nil, 751, nil,
- nil, nil, -554, -554, nil, -554, nil, nil, -554, -554,
- -554, -554, -554, -554, -554, -554, -554, nil, -554, nil,
- -554, 338, 749, nil, nil, 268, -554, nil, -554, 341,
- 340, 344, 343, nil, nil, nil, nil, nil, -554, -554,
- nil, -554, -554, -554, -554, -554, nil, -554, nil, nil,
- nil, nil, nil, 436, 440, nil, nil, 438, nil, nil,
- -554, nil, -554, nil, nil, -554, 142, 143, 752, 139,
- 121, 122, 123, 130, 127, 129, nil, nil, 124, 125,
- -554, -554, nil, nil, 144, 145, 131, 132, -554, nil,
- nil, nil, nil, 268, -554, nil, nil, nil, nil, nil,
- 136, 135, nil, 120, 141, 138, 137, 133, 134, 128,
- 126, 118, 140, 119, nil, -554, 146, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, -554, nil,
- -554, nil, nil, -554, 156, 167, 157, 180, 153, 173,
- 163, 162, 188, 191, 178, 161, 160, 155, 181, 189,
- 190, 165, 154, 168, 172, 174, 166, 159, nil, nil,
- nil, 175, 182, 177, 176, 169, 179, 164, 152, 171,
- 170, 183, 184, 185, 186, 187, 151, 158, 149, 150,
- 147, 148, nil, 111, 113, 110, nil, 112, nil, nil,
- nil, nil, nil, nil, nil, nil, 142, 143, nil, 139,
- 121, 122, 123, 130, 127, 129, nil, nil, 124, 125,
- nil, nil, nil, nil, 144, 145, 131, 132, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 136, 135, nil, 120, 141, 138, 137, 133, 134, 128,
- 126, 118, 140, 119, nil, nil, 146, 192, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 80, 156, 167,
- 157, 180, 153, 173, 163, 162, 188, 191, 178, 161,
- 160, 155, 181, 189, 190, 165, 154, 168, 172, 174,
- 166, 159, nil, nil, nil, 175, 182, 177, 176, 169,
- 179, 164, 152, 171, 170, 183, 184, 185, 186, 187,
- 151, 158, 149, 150, 147, 148, nil, 111, 113, nil,
- nil, 112, nil, nil, nil, nil, nil, nil, nil, nil,
- 142, 143, nil, 139, 121, 122, 123, 130, 127, 129,
- nil, nil, 124, 125, nil, nil, nil, nil, 144, 145,
- 131, 132, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 136, 135, nil, 120, 141, 138,
- 137, 133, 134, 128, 126, 118, 140, 119, nil, nil,
- 146, 192, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 80, 156, 167, 157, 180, 153, 173, 163, 162,
- 188, 191, 178, 161, 160, 155, 181, 189, 190, 165,
- 154, 168, 172, 174, 166, 159, nil, nil, nil, 175,
- 182, 177, 176, 169, 179, 164, 152, 171, 170, 183,
- 184, 185, 186, 187, 151, 158, 149, 150, 147, 148,
- nil, 111, 113, nil, nil, 112, nil, nil, nil, nil,
- nil, nil, nil, nil, 142, 143, nil, 139, 121, 122,
- 123, 130, 127, 129, nil, nil, 124, 125, nil, nil,
- nil, nil, 144, 145, 131, 132, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 136, 135,
- nil, 120, 141, 138, 137, 133, 134, 128, 126, 118,
- 140, 119, nil, nil, 146, 192, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 80, 156, 167, 157, 180,
- 153, 173, 163, 162, 188, 191, 178, 161, 160, 155,
- 181, 189, 190, 165, 154, 168, 172, 174, 166, 159,
- nil, nil, nil, 175, 182, 177, 176, 169, 179, 164,
- 152, 171, 170, 183, 184, 185, 186, 187, 151, 158,
- 149, 150, 147, 148, nil, 111, 113, nil, nil, 112,
- nil, nil, nil, nil, nil, nil, nil, nil, 142, 143,
- nil, 139, 121, 122, 123, 130, 127, 129, nil, nil,
- 124, 125, nil, nil, nil, nil, 144, 145, 131, 132,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 136, 135, nil, 120, 141, 138, 137, 133,
- 134, 128, 126, 118, 140, 119, nil, nil, 146, 192,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 80,
- 156, 167, 157, 180, 153, 173, 163, 162, 188, 191,
- 178, 161, 160, 155, 181, 189, 190, 165, 154, 168,
- 172, 174, 166, 159, nil, nil, nil, 175, 182, 177,
- 376, 375, 377, 374, 152, 171, 170, 183, 184, 185,
- 186, 187, 151, 158, 149, 150, 372, 373, nil, 370,
- 113, 86, 85, 371, nil, 88, nil, nil, nil, nil,
- nil, nil, 142, 143, nil, 139, 121, 122, 123, 130,
- 127, 129, nil, nil, 124, 125, nil, nil, nil, nil,
- 144, 145, 131, 132, nil, nil, nil, nil, nil, 381,
- nil, nil, nil, nil, nil, nil, 136, 135, nil, 120,
- 141, 138, 137, 133, 134, 128, 126, 118, 140, 119,
- nil, nil, 146, 156, 167, 157, 180, 153, 173, 163,
- 162, 188, 191, 178, 161, 160, 155, 181, 189, 190,
- 165, 154, 168, 172, 174, 166, 159, nil, nil, nil,
- 175, 182, 177, 176, 169, 179, 164, 152, 171, 170,
- 183, 184, 185, 186, 187, 151, 158, 149, 150, 147,
- 148, nil, 111, 113, 398, 397, 112, nil, 399, nil,
- nil, nil, nil, nil, nil, 142, 143, nil, 139, 121,
- 122, 123, 130, 127, 129, nil, nil, 124, 125, nil,
- nil, nil, nil, 144, 145, 131, 132, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 136,
- 135, nil, 120, 141, 138, 137, 133, 134, 128, 126,
- 118, 140, 119, nil, nil, 146, 156, 167, 157, 180,
- 153, 173, 163, 162, 188, 191, 178, 161, 160, 155,
- 181, 189, 190, 165, 154, 168, 172, 174, 166, 159,
- nil, nil, nil, 175, 182, 177, 176, 169, 179, 164,
- 152, 171, 170, 183, 184, 185, 186, 187, 151, 158,
- 149, 150, 147, 148, nil, 111, 113, 398, 397, 112,
- nil, 399, nil, nil, nil, nil, nil, nil, 142, 143,
- nil, 139, 121, 122, 123, 130, 127, 129, nil, nil,
- 124, 125, nil, nil, nil, nil, 144, 145, 131, 132,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 136, 135, nil, 120, 141, 138, 137, 133,
- 134, 128, 126, 118, 140, 119, nil, nil, 146, 156,
- 167, 157, 180, 153, 173, 163, 162, 188, 191, 178,
- 161, 160, 155, 181, 189, 190, 165, 154, 168, 172,
- 174, 166, 159, nil, nil, nil, 175, 182, 177, 176,
- 169, 179, 164, 152, 171, 170, 183, 184, 185, 186,
- 187, 151, 158, 149, 150, 147, 148, nil, 111, 113,
- nil, nil, 112, nil, nil, nil, nil, nil, nil, nil,
- nil, 142, 143, nil, 139, 121, 122, 123, 130, 127,
- 129, nil, nil, 124, 125, nil, nil, nil, nil, 144,
- 145, 131, 132, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 136, 135, nil, 120, 141,
- 138, 137, 133, 134, 128, 126, 118, 140, 119, 430,
- 434, 146, nil, 431, nil, nil, nil, nil, nil, nil,
- nil, nil, 142, 143, nil, 139, 121, 122, 123, 130,
- 127, 129, nil, nil, 124, 125, nil, nil, nil, nil,
- 144, 145, 131, 132, nil, nil, nil, nil, nil, 268,
- nil, nil, nil, nil, nil, nil, 136, 135, nil, 120,
- 141, 138, 137, 133, 134, 128, 126, 118, 140, 119,
- 443, 434, 146, nil, 444, nil, nil, nil, nil, nil,
- nil, nil, nil, 142, 143, nil, 139, 121, 122, 123,
- 130, 127, 129, nil, nil, 124, 125, nil, nil, nil,
- nil, 144, 145, 131, 132, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 136, 135, nil,
- 120, 141, 138, 137, 133, 134, 128, 126, 118, 140,
- 119, 443, 434, 146, nil, 444, nil, nil, nil, nil,
- nil, nil, nil, nil, 142, 143, nil, 139, 121, 122,
- 123, 130, 127, 129, nil, nil, 124, 125, nil, nil,
- nil, nil, 144, 145, 131, 132, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 136, 135,
- nil, 120, 141, 138, 137, 133, 134, 128, 126, 118,
- 140, 119, 443, 434, 146, nil, 444, nil, nil, nil,
- nil, nil, nil, nil, nil, 142, 143, nil, 139, 121,
- 122, 123, 130, 127, 129, nil, nil, 124, 125, nil,
- nil, nil, nil, 144, 145, 131, 132, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 136,
- 135, nil, 120, 141, 138, 137, 133, 134, 128, 126,
- 118, 140, 119, 443, 434, 146, nil, 444, nil, nil,
- nil, nil, nil, nil, nil, nil, 142, 143, nil, 139,
- 121, 122, 123, 130, 127, 129, nil, nil, 124, 125,
- nil, nil, nil, nil, 144, 145, 131, 132, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 136, 135, nil, 120, 141, 138, 137, 133, 134, 128,
- 126, 118, 140, 119, 642, 434, 146, nil, 643, nil,
- nil, nil, nil, nil, nil, nil, nil, 142, 143, nil,
- 139, 121, 122, 123, 130, 127, 129, nil, nil, 124,
- 125, nil, nil, nil, nil, 144, 145, 131, 132, nil,
- nil, nil, nil, nil, 268, nil, nil, nil, nil, nil,
- nil, 136, 135, nil, 120, 141, 138, 137, 133, 134,
- 128, 126, 118, 140, 119, 644, 440, 146, nil, 645,
- nil, nil, nil, nil, nil, nil, nil, nil, 142, 143,
- nil, 139, 121, 122, 123, 130, 127, 129, nil, nil,
- 124, 125, nil, nil, nil, nil, 144, 145, 131, 132,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 136, 135, nil, 120, 141, 138, 137, 133,
- 134, 128, 126, 118, 140, 119, 686, 434, 146, nil,
- 687, nil, nil, nil, nil, nil, nil, nil, nil, 142,
- 143, nil, 139, 121, 122, 123, 130, 127, 129, nil,
- nil, 124, 125, nil, nil, nil, nil, 144, 145, 131,
- 132, nil, nil, nil, nil, nil, 268, nil, nil, nil,
- nil, nil, nil, 136, 135, nil, 120, 141, 138, 137,
- 133, 134, 128, 126, 118, 140, 119, 689, 440, 146,
- nil, 690, nil, nil, nil, nil, nil, nil, nil, nil,
- 142, 143, nil, 139, 121, 122, 123, 130, 127, 129,
- nil, nil, 124, 125, nil, nil, nil, nil, 144, 145,
- 131, 132, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 136, 135, nil, 120, 141, 138,
- 137, 133, 134, 128, 126, 118, 140, 119, 443, 434,
- 146, nil, 444, nil, nil, nil, nil, nil, nil, nil,
- nil, 142, 143, nil, 139, 121, 122, 123, 130, 127,
- 129, nil, nil, 124, 125, nil, nil, nil, nil, 144,
- 145, 131, 132, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 136, 135, nil, 120, 141,
- 138, 137, 133, 134, 128, 126, 118, 140, 119, 642,
- 434, 146, nil, 643, nil, nil, nil, nil, nil, nil,
- nil, nil, 142, 143, nil, 139, 121, 122, 123, 130,
- 127, 129, nil, nil, 124, 125, nil, nil, nil, nil,
- 144, 145, 131, 132, nil, nil, nil, nil, nil, 268,
- nil, nil, nil, nil, nil, nil, 136, 135, nil, 120,
- 141, 138, 137, 133, 134, 128, 126, 118, 140, 119,
- 644, 440, 146, nil, 645, nil, nil, nil, nil, nil,
- nil, nil, nil, 142, 143, nil, 139, 121, 122, 123,
- 130, 127, 129, nil, nil, 124, 125, nil, nil, nil,
- nil, 144, 145, 131, 132, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 136, 135, nil,
- 120, 141, 138, 137, 133, 134, 128, 126, 118, 140,
- 119, 733, 434, 146, nil, 734, nil, nil, nil, nil,
- nil, nil, nil, nil, 142, 143, nil, 139, 121, 122,
- 123, 130, 127, 129, nil, nil, 124, 125, nil, nil,
- nil, nil, 144, 145, 131, 132, nil, nil, nil, nil,
- nil, 268, nil, nil, nil, nil, nil, nil, 136, 135,
- nil, 120, 141, 138, 137, 133, 134, 128, 126, 118,
- 140, 119, 735, 440, 146, nil, 736, nil, nil, nil,
- nil, nil, nil, nil, nil, 142, 143, nil, 139, 121,
- 122, 123, 130, 127, 129, nil, nil, 124, 125, nil,
- nil, nil, nil, 144, 145, 131, 132, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 136,
- 135, nil, 120, 141, 138, 137, 133, 134, 128, 126,
- 118, 140, 119, 741, 440, 146, nil, 739, nil, nil,
- nil, nil, nil, nil, nil, nil, 142, 143, nil, 139,
- 121, 122, 123, 130, 127, 129, nil, nil, 124, 125,
- nil, nil, nil, nil, 144, 145, 131, 132, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 136, 135, nil, 120, 141, 138, 137, 133, 134, 128,
- 126, 118, 140, 119, 443, 434, 146, nil, 444, nil,
- nil, nil, nil, nil, nil, nil, nil, 142, 143, nil,
- 139, 121, 122, 123, 130, 127, 129, nil, nil, 124,
- 125, nil, nil, nil, nil, 144, 145, 131, 132, nil,
- nil, nil, nil, nil, 268, nil, nil, nil, nil, nil,
- nil, 136, 135, nil, 120, 141, 138, 137, 133, 134,
- 128, 126, 118, 140, 119, 741, 440, 146, nil, 892,
- nil, nil, nil, nil, nil, nil, nil, nil, 142, 143,
- nil, 139, 121, 122, 123, 130, 127, 129, nil, nil,
- 124, 125, nil, nil, nil, nil, 144, 145, 131, 132,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 136, 135, nil, 120, 141, 138, 137, 133,
- 134, 128, 126, 118, 140, 119, 959, 434, 146, nil,
- 960, nil, nil, nil, nil, nil, nil, nil, nil, 142,
- 143, nil, 139, 121, 122, 123, 130, 127, 129, nil,
- nil, 124, 125, nil, nil, nil, nil, 144, 145, 131,
- 132, nil, nil, nil, nil, nil, 268, nil, nil, nil,
- nil, nil, nil, 136, 135, nil, 120, 141, 138, 137,
- 133, 134, 128, 126, 118, 140, 119, 961, 440, 146,
- nil, 962, nil, nil, nil, nil, nil, nil, nil, nil,
- 142, 143, nil, 139, 121, 122, 123, 130, 127, 129,
- nil, nil, 124, 125, nil, nil, nil, nil, 144, 145,
- 131, 132, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 136, 135, nil, 120, 141, 138,
- 137, 133, 134, 128, 126, 118, 140, 119, nil, nil,
- 146 ]
-
-racc_action_check = [
- 0, 0, 0, 0, 0, 347, 321, 354, 0, 0,
- 392, 746, 746, 0, 71, 0, 0, 0, 0, 0,
- 0, 0, 71, 313, 852, 615, 313, 0, 0, 0,
- 0, 0, 0, 0, 1, 852, 0, 387, 26, 209,
- 387, 485, 0, 0, 0, 0, 0, 0, 348, 0,
- 0, 0, 0, 0, 55, 0, 0, 0, 497, 0,
- 0, 357, 0, 0, 587, 681, 366, 370, 852, 852,
- 733, 310, 310, 392, 370, 485, 734, 352, 838, 352,
- 839, 604, 604, 735, 889, 0, 615, 615, 0, 209,
- 896, 0, 497, 6, 0, 615, 0, 287, 387, 387,
- 0, 746, 681, 924, 26, 852, 746, 9, 0, 927,
- 948, 321, 354, 0, 0, 0, 0, 0, 0, 347,
- 959, 347, 0, 0, 347, 26, 736, 17, 17, 17,
- 0, 17, 960, 0, 507, 17, 17, 10, 0, 0,
- 17, 55, 17, 17, 17, 17, 17, 17, 17, 211,
- 735, 457, 457, 11, 17, 17, 17, 17, 17, 17,
- 17, 310, 348, 17, 348, 287, 357, 348, 507, 587,
- 17, 604, 366, 17, 17, 733, 17, 17, 17, 17,
- 17, 734, 17, 17, 17, 839, 17, 17, 735, 17,
- 17, 366, 838, 736, 838, 838, 366, 838, 889, 211,
- 889, 371, 287, 889, 896, 12, 896, 457, 371, 896,
- 961, 287, 17, 20, 962, 17, 17, 924, 17, 924,
- 290, 17, 924, 927, 948, 927, 948, 17, 927, 948,
- 967, 736, 293, 383, 959, 17, 959, 34, 577, 959,
- 17, 17, 17, 17, 17, 17, 960, 525, 960, 17,
- 17, 960, 686, 578, 18, 18, 18, 17, 18, 687,
- 17, 314, 18, 18, 314, 17, 17, 18, 453, 18,
- 18, 18, 18, 18, 18, 18, 698, 698, 508, 15,
- 15, 18, 18, 18, 18, 18, 18, 18, 290, 961,
- 18, 629, 36, 962, 383, 383, 383, 18, 293, 461,
- 18, 18, 41, 18, 18, 18, 18, 18, 77, 18,
- 18, 18, 508, 18, 18, 525, 18, 18, 453, 293,
- 686, 841, 37, 37, 961, 290, 961, 687, 962, 961,
- 962, 461, 698, 962, 290, 461, 461, 689, 577, 18,
- 577, 629, 18, 577, 967, 18, 967, 807, 18, 967,
- 78, 690, 525, 578, 18, 578, 642, 686, 578, 97,
- 3, 525, 18, 193, 687, 3, 686, 18, 18, 18,
- 18, 18, 18, 687, 210, 278, 18, 18, 212, 14,
- 278, 22, 22, 22, 18, 22, 385, 18, 317, 22,
- 22, 317, 18, 18, 22, 643, 22, 22, 22, 22,
- 22, 22, 22, 791, 689, 689, 642, 792, 22, 22,
- 22, 22, 22, 22, 22, 807, 213, 22, 690, 690,
- 14, 841, 389, 841, 22, 394, 841, 22, 22, 14,
- 22, 22, 22, 22, 22, 22, 22, 22, 22, 372,
- 22, 22, 689, 22, 22, 643, 372, 385, 385, 385,
- 351, 689, 807, 791, 219, 351, 690, 792, 251, 25,
- 25, 807, 860, 373, 374, 690, 22, 25, 252, 22,
- 373, 374, 22, 860, 934, 22, 934, 22, 255, 22,
- 267, 22, 280, 389, 389, 389, 394, 394, 394, 22,
- 83, 83, 13, 13, 22, 22, 22, 22, 22, 22,
- 13, 282, 703, 22, 22, 703, 860, 860, 23, 23,
- 23, 22, 23, 597, 22, 375, 23, 23, 597, 22,
- 22, 23, 375, 23, 23, 23, 23, 23, 23, 23,
- 283, 361, 296, 296, 284, 23, 23, 23, 23, 23,
- 23, 23, 744, 860, 23, 42, 42, 744, 13, 648,
- 13, 23, 289, 42, 23, 23, 291, 23, 23, 23,
- 23, 23, 23, 23, 23, 23, 292, 23, 23, 295,
- 23, 23, 301, 648, 648, 648, 648, 648, 648, 648,
- 648, 648, 648, 648, 361, 361, 648, 648, 376, 750,
- 648, 648, 361, 23, 750, 376, 23, 361, 302, 23,
- 305, 42, 23, 42, 23, 648, 23, 648, 23, 648,
- 648, 648, 648, 648, 648, 648, 23, 648, 361, 208,
- 208, 23, 23, 23, 23, 23, 23, 208, 312, 35,
- 23, 23, 315, 648, 316, 24, 24, 24, 23, 24,
- 361, 23, 361, 24, 24, 318, 23, 23, 24, 326,
- 24, 24, 24, 24, 24, 24, 24, 5, 5, 5,
- 5, 5, 24, 24, 24, 24, 24, 24, 24, 377,
- 35, 24, 288, 288, 300, 208, 377, 208, 24, 35,
- 288, 24, 24, 327, 24, 24, 24, 24, 24, 24,
- 24, 24, 24, 329, 24, 24, 330, 24, 24, 342,
- 484, 484, 484, 484, 484, 484, 484, 484, 484, 484,
- 484, 303, 303, 484, 484, 300, 110, 484, 484, 303,
- 24, 110, 110, 24, 300, 345, 24, 353, 288, 24,
- 288, 24, 484, 24, 484, 24, 484, 484, 484, 484,
- 484, 484, 484, 24, 484, 356, 355, 355, 24, 24,
- 24, 24, 24, 24, 355, 358, 430, 24, 24, 362,
- 484, 484, 27, 27, 27, 24, 27, 303, 24, 303,
- 27, 27, 388, 24, 24, 27, 391, 27, 27, 27,
- 27, 27, 27, 27, 279, 279, 279, 279, 279, 27,
- 27, 27, 27, 27, 27, 27, 410, 430, 27, 364,
- 364, 416, 355, 419, 355, 27, 430, 364, 27, 27,
- 422, 27, 27, 27, 27, 27, 27, 27, 27, 27,
- 424, 27, 27, 428, 27, 27, 429, 419, 419, 419,
- 419, 419, 419, 419, 419, 419, 419, 419, 589, 589,
- 419, 419, 346, 346, 419, 419, 589, 27, 437, 431,
- 27, 27, 463, 27, 464, 364, 27, 364, 27, 419,
- 27, 419, 27, 419, 419, 419, 419, 419, 419, 419,
- 27, 419, 561, 561, 379, 27, 27, 27, 27, 27,
- 27, 379, 720, 720, 27, 27, 628, 419, 465, 419,
- 431, 466, 27, 858, 589, 27, 589, 499, 858, 431,
- 27, 27, 30, 30, 30, 30, 30, 855, 855, 858,
- 30, 30, 949, 949, 502, 30, 503, 30, 30, 30,
- 30, 30, 30, 30, 509, 513, 514, 628, 517, 30,
- 30, 30, 30, 30, 30, 30, 628, 519, 30, 526,
- 858, 858, 858, 858, 30, 30, 462, 30, 30, 30,
- 529, 30, 30, 30, 30, 30, 538, 30, 30, 30,
- 539, 30, 30, 540, 30, 30, 553, 19, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 462, 858,
- 19, 19, 462, 462, 19, 19, 564, 30, 568, 573,
- 30, 579, 580, 30, 619, 626, 30, 632, 30, 19,
- 637, 19, 30, 19, 19, 19, 19, 19, 19, 19,
- 30, 19, 640, 711, 711, 30, 30, 30, 30, 30,
- 30, 711, 646, 647, 30, 30, 655, 19, 657, 31,
- 31, 31, 30, 31, 669, 30, 673, 31, 31, 676,
- 30, 30, 31, 683, 31, 31, 31, 31, 31, 31,
- 31, 555, 685, 688, 691, 692, 31, 31, 31, 31,
- 31, 31, 31, 693, 696, 31, 840, 840, 697, 711,
- 699, 711, 31, 704, 840, 31, 31, 705, 31, 31,
- 31, 31, 31, 708, 31, 31, 31, 710, 31, 31,
- 712, 652, 713, 652, 652, 652, 714, 652, 555, 555,
- 555, 555, 717, 768, 768, 739, 739, 768, 768, 768,
- 722, 728, 730, 739, 31, 732, 737, 31, 739, 741,
- 31, 742, 840, 31, 840, 31, 753, 757, 758, 760,
- 652, 761, 939, 762, 764, 767, 774, 939, 652, 652,
- 652, 652, 31, 31, 31, 31, 31, 31, 939, 652,
- 795, 31, 31, 796, 799, 801, 32, 32, 32, 31,
- 32, 739, 31, 739, 32, 32, 804, 31, 31, 32,
- 805, 32, 32, 32, 32, 32, 32, 32, 824, 939,
- 939, 939, 939, 32, 32, 32, 32, 32, 32, 32,
- 925, 925, 32, 680, 680, 680, 680, 680, 925, 32,
- 480, 806, 32, 32, 811, 32, 32, 32, 32, 32,
- 814, 32, 32, 32, 815, 32, 32, 600, 939, 600,
- 600, 600, 600, 600, 830, 824, 824, 824, 824, 833,
- 843, 846, 480, 600, 847, 848, 480, 480, 480, 480,
- 870, 32, 871, 882, 32, 892, 925, 32, 925, 569,
- 32, 569, 569, 569, 893, 569, 600, 600, 898, 899,
- 907, 909, 912, 913, 600, 600, 600, 600, 914, 32,
- 32, 32, 32, 32, 32, 915, 926, 936, 32, 32,
- 944, 953, 955, 32, 956, 958, 32, nil, nil, 32,
- nil, nil, nil, nil, 32, 32, 38, 38, 38, 481,
- 38, nil, nil, 600, 38, 38, nil, nil, nil, 38,
- nil, 38, 38, 38, 38, 38, 38, 38, nil, nil,
- nil, nil, nil, 38, 38, 38, 38, 38, 38, 38,
- nil, 481, 38, nil, nil, 481, 481, 481, 481, 38,
- nil, nil, 38, 38, nil, 38, 38, 38, 38, 38,
- nil, 38, 38, 38, nil, 38, 38, nil, 38, 38,
- nil, 249, 249, 249, 249, 249, 249, 249, 249, 249,
- 249, 249, nil, nil, 249, 249, nil, nil, 249, 249,
- nil, 38, nil, nil, 38, nil, nil, 38, nil, nil,
- 38, nil, nil, 249, nil, 249, 38, 249, 249, 249,
- 249, 249, 249, 249, 38, 249, nil, nil, nil, 38,
- 38, 38, 38, 38, 38, nil, nil, nil, 38, 38,
- nil, 249, nil, 39, 39, 39, 38, 39, nil, 38,
- nil, 39, 39, nil, 38, 38, 39, nil, 39, 39,
- 39, 39, 39, 39, 39, nil, nil, nil, nil, nil,
- 39, 39, 39, 39, 39, 39, 39, nil, 829, 39,
- 829, 829, 829, nil, 829, nil, 39, nil, nil, 39,
- 39, nil, 39, 39, 39, 39, 39, nil, 39, 39,
- 39, nil, 39, 39, nil, 39, 39, nil, 427, 427,
- 427, 427, 427, 427, 427, 427, 427, 427, 427, nil,
- nil, 427, 427, nil, nil, 427, 427, nil, 39, nil,
- nil, 39, nil, nil, 39, nil, nil, 39, nil, nil,
- 427, nil, 427, 39, 427, 427, 427, 427, 427, 427,
- 427, 39, 427, nil, nil, nil, 39, 39, 39, 39,
- 39, 39, nil, nil, nil, 39, 39, nil, 427, nil,
- 40, 40, 40, 39, 40, nil, 39, nil, 40, 40,
- nil, 39, 39, 40, nil, 40, 40, 40, 40, 40,
- 40, 40, nil, nil, nil, nil, nil, 40, 40, 40,
- 40, 40, 40, 40, nil, nil, 40, nil, nil, nil,
- nil, nil, nil, 40, nil, nil, 40, 40, nil, 40,
- 40, 40, 40, 40, nil, 40, 40, 40, nil, 40,
- 40, nil, 40, 40, nil, 446, 446, 446, 446, 446,
- 446, 446, 446, 446, 446, 446, nil, nil, 446, 446,
- nil, nil, 446, 446, nil, 40, nil, nil, 40, nil,
- nil, 40, nil, nil, 40, nil, nil, 446, nil, 446,
- 40, 446, 446, 446, 446, 446, 446, 446, 40, 446,
- nil, nil, nil, 40, 40, 40, 40, 40, 40, nil,
- nil, nil, 40, 40, nil, 446, nil, 52, 52, 52,
- 40, 52, nil, 40, nil, 52, 52, nil, 40, 40,
- 52, nil, 52, 52, 52, 52, 52, 52, 52, nil,
- nil, nil, nil, nil, 52, 52, 52, 52, 52, 52,
- 52, nil, nil, 52, nil, nil, nil, nil, nil, nil,
- 52, nil, nil, 52, 52, nil, 52, 52, 52, 52,
- 52, nil, 52, 52, 52, nil, 52, 52, nil, 52,
- 52, nil, 536, 536, 536, 536, 536, 536, 536, 536,
- 536, 536, 536, nil, nil, 536, 536, nil, nil, 536,
- 536, nil, 52, nil, nil, 52, nil, nil, 52, nil,
- nil, 52, nil, nil, 536, nil, 536, 52, 536, 536,
- 536, 536, 536, 536, 536, 52, 536, nil, nil, nil,
- 52, 52, 52, 52, 52, 52, nil, nil, nil, 52,
- 52, nil, 536, nil, 53, 53, 53, 52, 53, nil,
- 52, nil, 53, 53, nil, 52, 52, 53, nil, 53,
- 53, 53, 53, 53, 53, 53, nil, nil, nil, nil,
- nil, 53, 53, 53, 53, 53, 53, 53, nil, nil,
- 53, nil, nil, nil, nil, nil, nil, 53, nil, nil,
- 53, 53, nil, 53, 53, 53, 53, 53, 53, 53,
- 53, 53, nil, 53, 53, nil, 53, 53, nil, 695,
- 695, 695, 695, 695, 695, 695, 695, 695, 695, 695,
- nil, nil, 695, 695, nil, nil, 695, 695, nil, 53,
- nil, nil, 53, nil, nil, 53, nil, nil, 53, nil,
- 53, 695, nil, 695, 53, 695, 695, 695, 695, 695,
- 695, 695, 53, 695, nil, nil, nil, 53, 53, 53,
- 53, 53, 53, nil, nil, nil, 53, 53, nil, 695,
- nil, 54, 54, 54, 53, 54, nil, 53, nil, 54,
- 54, nil, 53, 53, 54, nil, 54, 54, 54, 54,
- 54, 54, 54, nil, nil, nil, nil, nil, 54, 54,
- 54, 54, 54, 54, 54, nil, nil, 54, nil, nil,
- nil, nil, nil, nil, 54, nil, nil, 54, 54, nil,
- 54, 54, 54, 54, 54, 54, 54, 54, 54, nil,
- 54, 54, nil, 54, 54, nil, 773, 773, 773, 773,
- 773, 773, 773, 773, 773, 773, 773, nil, nil, 773,
- 773, nil, nil, 773, 773, nil, 54, nil, nil, 54,
- nil, nil, 54, nil, nil, 54, nil, nil, 773, nil,
- 773, 54, 773, 773, 773, 773, 773, 773, 773, 54,
- 773, nil, nil, nil, 54, 54, 54, 54, 54, 54,
- nil, nil, nil, 54, 54, nil, 773, nil, 57, 57,
- 57, 54, 57, nil, 54, nil, 57, 57, nil, 54,
- 54, 57, nil, 57, 57, 57, 57, 57, 57, 57,
- nil, nil, nil, nil, nil, 57, 57, 57, 57, 57,
- 57, 57, nil, nil, 57, nil, nil, nil, nil, nil,
- nil, 57, nil, nil, 57, 57, nil, 57, 57, 57,
- 57, 57, nil, 57, 57, 57, nil, 57, 57, nil,
- 57, 57, nil, 779, 779, 779, 779, 779, 779, 779,
- 779, 779, 779, 779, nil, nil, 779, 779, nil, nil,
- 779, 779, nil, 57, nil, nil, 57, nil, nil, 57,
- nil, nil, 57, nil, nil, 779, nil, 779, 57, 779,
- 779, 779, 779, 779, 779, 779, 57, 779, nil, nil,
- nil, 57, 57, 57, 57, 57, 57, nil, nil, nil,
- 57, 57, nil, 779, nil, 58, 58, 58, 57, 58,
- nil, 57, nil, 58, 58, nil, 57, 57, 58, nil,
- 58, 58, 58, 58, 58, 58, 58, nil, nil, nil,
- nil, nil, 58, 58, 58, 58, 58, 58, 58, nil,
- nil, 58, nil, nil, nil, nil, nil, nil, 58, nil,
- nil, 58, 58, nil, 58, 58, 58, 58, 58, nil,
- 58, 58, 58, nil, 58, 58, nil, 58, 58, nil,
- 781, 781, 781, 781, 781, 781, 781, 781, 781, 781,
- 781, nil, nil, 781, 781, nil, nil, 781, 781, nil,
- 58, nil, nil, 58, nil, nil, 58, nil, nil, 58,
- nil, nil, 781, nil, 781, 58, 781, 781, 781, 781,
- 781, 781, 781, 58, 781, nil, nil, nil, 58, 58,
- 58, 58, 58, 58, nil, nil, nil, 58, 58, nil,
- 781, nil, 61, 61, 61, 58, 61, nil, 58, nil,
- 61, 61, nil, 58, 58, 61, nil, 61, 61, 61,
- 61, 61, 61, 61, nil, nil, nil, nil, nil, 61,
- 61, 61, 61, 61, 61, 61, nil, nil, 61, nil,
- nil, nil, nil, nil, nil, 61, nil, nil, 61, 61,
- nil, 61, 61, 61, 61, 61, nil, 61, 61, 61,
- nil, 61, 61, nil, 61, 61, nil, 672, 672, 672,
- 672, 672, 672, 672, 672, 672, 672, 672, nil, nil,
- 672, 672, nil, nil, 672, 672, nil, 61, nil, nil,
- 61, nil, nil, 61, nil, nil, 61, nil, nil, 672,
- nil, 672, 61, 672, 672, 672, 672, 672, 672, 672,
- 61, 672, nil, nil, nil, 61, 61, 61, 61, 61,
- 61, nil, nil, nil, 61, 61, 61, 672, nil, 672,
- nil, 61, 61, nil, nil, 61, nil, nil, nil, nil,
- 61, 61, 62, 62, 62, nil, 62, nil, nil, nil,
- 62, 62, nil, nil, nil, 62, nil, 62, 62, 62,
- 62, 62, 62, 62, nil, nil, nil, nil, nil, 62,
- 62, 62, 62, 62, 62, 62, nil, nil, 62, nil,
- nil, nil, nil, nil, nil, 62, nil, nil, 62, 62,
- nil, 62, 62, 62, 62, 62, nil, 62, 62, 62,
- nil, 62, 62, 784, 784, 784, 784, 784, 784, 784,
- 784, 784, 784, 784, 467, nil, 784, 784, nil, nil,
- 784, 784, nil, nil, nil, nil, nil, 62, nil, nil,
- 62, 467, 467, 62, nil, 784, 62, 784, 62, 784,
- 784, 784, 784, 784, 784, 784, 467, 784, 467, nil,
- 467, 467, 467, 467, nil, 62, 62, 62, 62, 62,
- 62, nil, nil, 784, 62, 62, nil, nil, nil, 63,
- 63, 63, 62, 63, nil, 62, nil, 63, 63, nil,
- 62, 62, 63, nil, 63, 63, 63, 63, 63, 63,
- 63, nil, nil, nil, nil, nil, 63, 63, 63, 63,
- 63, 63, 63, nil, nil, 63, nil, nil, nil, nil,
- nil, nil, 63, nil, nil, 63, 63, nil, 63, 63,
- 63, 63, 63, nil, 63, 63, 63, nil, 63, 63,
- 786, 786, 786, 786, 786, 786, 786, 786, 786, 786,
- 786, 468, nil, 786, 786, nil, nil, 786, 786, nil,
- nil, 63, nil, nil, 63, nil, nil, 63, 468, 468,
- 63, nil, 786, 63, 786, nil, 786, 786, 786, 786,
- 786, 786, 786, 468, 786, 468, nil, 468, 468, 468,
- 468, nil, 63, 63, 63, 63, 63, 63, nil, nil,
- 786, 63, 63, nil, nil, nil, 84, 84, 84, 63,
- 84, nil, 63, nil, 84, 84, nil, 63, 63, 84,
- nil, 84, 84, 84, 84, 84, 84, 84, nil, 84,
- nil, nil, nil, 84, 84, 84, 84, 84, 84, 84,
- nil, nil, 84, nil, nil, nil, nil, nil, nil, 84,
- nil, nil, 84, 84, nil, 84, 84, 84, 84, 84,
- 84, 84, 84, 84, nil, 84, 84, nil, 84, 84,
- nil, 793, 793, 793, 793, 793, 793, 793, 793, 793,
- 793, 793, nil, nil, 793, 793, nil, nil, 793, 793,
- nil, 84, nil, nil, 84, 84, nil, 84, nil, nil,
- 84, nil, 84, 793, 84, 793, 84, 793, 793, 793,
- 793, 793, 793, 793, 84, 793, 84, nil, nil, 84,
- 84, 84, 84, 84, 84, nil, nil, nil, 84, 84,
- nil, 793, nil, 87, 87, 87, 84, 87, nil, 84,
- nil, 87, 87, nil, 84, 84, 87, nil, 87, 87,
- 87, 87, 87, 87, 87, nil, 87, nil, nil, nil,
- 87, 87, 87, 87, 87, 87, 87, nil, nil, 87,
- nil, nil, nil, nil, nil, nil, 87, nil, nil, 87,
- 87, nil, 87, 87, 87, 87, 87, 87, 87, 87,
- 87, nil, 87, 87, nil, 87, 87, nil, 873, 873,
- 873, 873, 873, 873, 873, 873, 873, 873, 873, nil,
- nil, 873, 873, nil, nil, 873, 873, nil, 87, nil,
- nil, 87, 87, nil, 87, nil, nil, 87, nil, 87,
- 873, 87, 873, 87, 873, 873, 873, 873, 873, 873,
- 873, 87, 873, 87, nil, nil, 87, 87, 87, 87,
- 87, 87, nil, nil, nil, 87, 87, nil, 873, nil,
- nil, nil, nil, 87, nil, nil, 87, nil, nil, nil,
- nil, 87, 87, 99, 99, 99, 99, 99, nil, nil,
- nil, 99, 99, nil, nil, nil, 99, nil, 99, 99,
- 99, 99, 99, 99, 99, nil, nil, nil, nil, nil,
- 99, 99, 99, 99, 99, 99, 99, nil, nil, 99,
- nil, nil, nil, nil, nil, 99, 99, 99, 99, 99,
- 99, nil, 99, 99, 99, 99, 99, nil, 99, 99,
- 99, nil, 99, 99, nil, 99, 99, nil, 875, 875,
- 875, 875, 875, 875, 875, 875, 875, 875, 875, nil,
- nil, 875, 875, nil, nil, 875, 875, nil, 99, nil,
- nil, 99, nil, nil, 99, nil, nil, 99, nil, 99,
- 875, nil, 875, 99, 875, 875, 875, 875, 875, 875,
- 875, 99, 875, nil, nil, nil, 99, 99, 99, 99,
- 99, 99, nil, nil, nil, 99, 99, nil, 875, nil,
- nil, nil, 99, 99, nil, nil, 99, nil, nil, nil,
- nil, 99, 99, 103, 103, 103, nil, 103, nil, nil,
- nil, 103, 103, nil, nil, nil, 103, nil, 103, 103,
- 103, 103, 103, 103, 103, nil, nil, nil, nil, nil,
- 103, 103, 103, 103, 103, 103, 103, nil, 338, 103,
- 338, 338, 338, nil, 338, nil, 103, nil, nil, 103,
- 103, nil, 103, 103, 103, 103, 103, nil, 103, 103,
- 103, nil, 103, 103, nil, 103, 103, 566, nil, 566,
- 566, 566, nil, 566, nil, nil, 718, 338, 718, 718,
- 718, nil, 718, nil, nil, 338, nil, nil, 103, nil,
- nil, 103, nil, nil, 103, nil, nil, 103, nil, nil,
- nil, nil, nil, 103, nil, nil, 566, nil, nil, nil,
- nil, 103, nil, nil, 566, 718, 103, 103, 103, 103,
- 103, 103, nil, 718, nil, 103, 103, nil, nil, nil,
- 104, 104, 104, 103, 104, nil, 103, nil, 104, 104,
- nil, 103, 103, 104, nil, 104, 104, 104, 104, 104,
- 104, 104, nil, nil, nil, nil, nil, 104, 104, 104,
- 104, 104, 104, 104, nil, nil, 104, nil, nil, nil,
- nil, nil, nil, 104, nil, nil, 104, 104, nil, 104,
- 104, 104, 104, 104, nil, 104, 104, 104, nil, 104,
- 104, nil, 104, 104, nil, 459, 459, 459, 459, 459,
- 459, 459, 459, 459, 459, 459, nil, nil, 459, 459,
- nil, nil, 459, 459, nil, 104, nil, nil, 104, nil,
- nil, 104, nil, nil, 104, nil, nil, 459, nil, 459,
- 104, 459, 459, 459, 459, 459, 459, 459, 104, 459,
- nil, nil, nil, 104, 104, 104, 104, 104, 104, nil,
- nil, nil, 104, 104, nil, nil, nil, 105, 105, 105,
- 104, 105, nil, 104, nil, 105, 105, nil, 104, 104,
- 105, nil, 105, 105, 105, 105, 105, 105, 105, nil,
- nil, nil, nil, nil, 105, 105, 105, 105, 105, 105,
- 105, nil, nil, 105, nil, nil, nil, nil, nil, nil,
- 105, nil, nil, 105, 105, nil, 105, 105, 105, 105,
- 105, nil, 105, 105, 105, nil, 105, 105, nil, 105,
- 105, nil, 460, 460, 460, 460, 460, 460, 460, 460,
- 460, 460, 460, nil, nil, 460, 460, nil, nil, 460,
- 460, nil, 105, nil, nil, 105, nil, nil, 105, nil,
- nil, 105, nil, nil, 460, nil, 460, 105, 460, 460,
- 460, 460, 460, 460, 460, 105, 460, nil, nil, nil,
- 105, 105, 105, 105, 105, 105, nil, nil, nil, 105,
- 105, nil, nil, nil, 106, 106, 106, 105, 106, nil,
- 105, nil, 106, 106, nil, 105, 105, 106, nil, 106,
- 106, 106, 106, 106, 106, 106, nil, nil, nil, nil,
- nil, 106, 106, 106, 106, 106, 106, 106, nil, nil,
- 106, nil, nil, nil, nil, nil, nil, 106, nil, nil,
- 106, 106, nil, 106, 106, 106, 106, 106, nil, 106,
- 106, 106, nil, 106, 106, nil, 106, 106, nil, 470,
- 470, 470, 470, 470, 470, 470, nil, nil, 470, 470,
- nil, nil, nil, nil, nil, nil, 470, 470, nil, 106,
- nil, nil, 106, nil, nil, 106, nil, nil, 106, nil,
- nil, 470, nil, 470, 106, 470, 470, 470, 470, 470,
- 470, 470, 106, 470, nil, nil, nil, 106, 106, 106,
- 106, 106, 106, nil, nil, nil, 106, 106, nil, nil,
- nil, nil, nil, nil, 106, nil, nil, 106, nil, nil,
- nil, nil, 106, 106, 107, 107, 107, 107, 107, nil,
- nil, nil, 107, 107, nil, nil, nil, 107, nil, 107,
- 107, 107, 107, 107, 107, 107, nil, nil, nil, nil,
- nil, 107, 107, 107, 107, 107, 107, 107, nil, nil,
- 107, nil, nil, nil, nil, nil, 107, 107, nil, 107,
- 107, 107, nil, 107, 107, 107, 107, 107, nil, 107,
- 107, 107, nil, 107, 107, nil, 107, 107, nil, 471,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 471, 471, nil, 107,
- nil, nil, 107, nil, nil, 107, nil, nil, 107, nil,
- 107, 471, nil, 471, 107, 471, 471, 471, 471, nil,
- nil, 471, 107, 471, nil, nil, nil, 107, 107, 107,
- 107, 107, 107, nil, nil, nil, 107, 107, nil, nil,
- nil, nil, nil, nil, 107, nil, nil, 107, nil, nil,
- nil, nil, 107, 107, 108, 108, 108, 108, 108, nil,
- nil, nil, 108, 108, nil, nil, nil, 108, nil, 108,
- 108, 108, 108, 108, 108, 108, nil, nil, nil, nil,
- nil, 108, 108, 108, 108, 108, 108, 108, nil, nil,
- 108, nil, nil, nil, nil, nil, 108, 108, 108, 108,
- 108, 108, nil, 108, 108, 108, 108, 108, nil, 108,
- 108, 108, nil, 108, 108, nil, 108, 108, nil, 472,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 472, 472, nil, 108,
- nil, nil, 108, nil, nil, 108, nil, nil, 108, nil,
- 108, 472, nil, 472, 108, 472, 472, 472, 472, nil,
- nil, 472, 108, 472, nil, nil, nil, 108, 108, 108,
- 108, 108, 108, nil, nil, nil, 108, 108, nil, nil,
- nil, nil, nil, nil, 108, nil, nil, 108, nil, nil,
- nil, nil, 108, 108, 195, 195, 195, 195, 195, nil,
- nil, nil, 195, 195, nil, nil, nil, 195, nil, 195,
- 195, 195, 195, 195, 195, 195, nil, nil, nil, nil,
- nil, 195, 195, 195, 195, 195, 195, 195, nil, nil,
- 195, nil, nil, nil, nil, nil, 195, 195, nil, 195,
- 195, 195, nil, 195, 195, 195, 195, 195, nil, 195,
- 195, 195, nil, 195, 195, nil, 195, 195, nil, 473,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 473, 473, nil, 195,
- nil, nil, 195, nil, nil, 195, nil, nil, 195, nil,
- 195, 473, nil, 473, 195, 473, 473, 473, 473, nil,
- nil, 473, 195, 473, nil, nil, nil, 195, 195, 195,
- 195, 195, 195, nil, nil, nil, 195, 195, nil, nil,
- nil, 196, 196, 196, 195, 196, nil, 195, nil, 196,
- 196, nil, 195, 195, 196, nil, 196, 196, 196, 196,
- 196, 196, 196, nil, nil, nil, nil, nil, 196, 196,
- 196, 196, 196, 196, 196, nil, nil, 196, nil, nil,
- nil, nil, nil, nil, 196, nil, nil, 196, 196, nil,
- 196, 196, 196, 196, 196, nil, 196, 196, 196, nil,
- 196, 196, nil, 196, 196, nil, 474, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 474, 474, nil, 196, nil, nil, 196,
- nil, nil, 196, nil, nil, 196, nil, 196, 474, nil,
- 474, 196, 474, 474, 474, 474, nil, nil, 474, 196,
- 474, nil, nil, nil, 196, 196, 196, 196, 196, 196,
- nil, nil, nil, 196, 196, nil, nil, nil, 197, 197,
- 197, 196, 197, nil, 196, nil, 197, 197, nil, 196,
- 196, 197, nil, 197, 197, 197, 197, 197, 197, 197,
- nil, nil, nil, nil, nil, 197, 197, 197, 197, 197,
- 197, 197, nil, nil, 197, nil, nil, nil, nil, nil,
- nil, 197, nil, nil, 197, 197, nil, 197, 197, 197,
- 197, 197, nil, 197, 197, 197, nil, 197, 197, nil,
- 197, 197, nil, 475, 475, 475, 475, 475, 475, 475,
- nil, nil, 475, 475, nil, nil, nil, nil, nil, nil,
- 475, 475, nil, 197, nil, nil, 197, nil, nil, 197,
- nil, nil, 197, nil, 197, 475, nil, 475, 197, 475,
- 475, 475, 475, 475, 475, 475, 197, 475, nil, nil,
- nil, 197, 197, 197, 197, 197, 197, nil, nil, nil,
- 197, 197, nil, nil, nil, 198, 198, 198, 197, 198,
- nil, 197, nil, 198, 198, nil, 197, 197, 198, nil,
- 198, 198, 198, 198, 198, 198, 198, nil, nil, nil,
- nil, nil, 198, 198, 198, 198, 198, 198, 198, nil,
- nil, 198, nil, nil, nil, nil, nil, nil, 198, nil,
- nil, 198, 198, nil, 198, 198, 198, 198, 198, nil,
- 198, 198, 198, nil, 198, 198, nil, 198, 198, nil,
- 476, 476, 476, 476, 476, 476, 476, nil, nil, 476,
- 476, nil, nil, nil, nil, nil, nil, 476, 476, nil,
- 198, nil, nil, 198, nil, nil, 198, nil, nil, 198,
- nil, nil, 476, nil, 476, 198, 476, 476, 476, 476,
- 476, 476, 476, 198, 476, nil, nil, nil, 198, 198,
- 198, 198, 198, 198, nil, nil, nil, 198, 198, nil,
- nil, nil, 199, 199, 199, 198, 199, nil, 198, nil,
- 199, 199, nil, 198, 198, 199, nil, 199, 199, 199,
- 199, 199, 199, 199, nil, nil, nil, nil, nil, 199,
- 199, 199, 199, 199, 199, 199, nil, nil, 199, nil,
- nil, nil, nil, nil, nil, 199, nil, nil, 199, 199,
- nil, 199, 199, 199, 199, 199, 199, 199, 199, 199,
- nil, 199, 199, nil, 199, 199, nil, 477, 477, 477,
- 477, 477, 477, 477, nil, nil, 477, 477, nil, nil,
- nil, nil, nil, nil, 477, 477, nil, 199, nil, nil,
- 199, nil, nil, 199, nil, nil, 199, nil, 199, 477,
- nil, 477, 199, 477, 477, 477, 477, 477, 477, 477,
- 199, 477, nil, nil, nil, 199, 199, 199, 199, 199,
- 199, nil, nil, nil, 199, 199, nil, nil, nil, 200,
- 200, 200, 199, 200, nil, 199, nil, 200, 200, nil,
- 199, 199, 200, nil, 200, 200, 200, 200, 200, 200,
- 200, nil, nil, nil, nil, nil, 200, 200, 200, 200,
- 200, 200, 200, nil, nil, 200, nil, nil, nil, nil,
- nil, nil, 200, nil, nil, 200, 200, nil, 200, 200,
- 200, 200, 200, 200, 200, 200, 200, nil, 200, 200,
- nil, 200, 200, nil, 478, 478, 478, 478, 478, 478,
- 478, nil, nil, 478, 478, nil, nil, nil, nil, nil,
- nil, 478, 478, nil, 200, nil, nil, 200, nil, nil,
- 200, nil, nil, 200, nil, 200, 478, nil, 478, 200,
- 478, 478, 478, 478, 478, 478, 478, 200, 478, nil,
- nil, nil, 200, 200, 200, 200, 200, 200, nil, nil,
- nil, 200, 200, nil, nil, nil, 204, 204, 204, 200,
- 204, nil, 200, nil, 204, 204, nil, 200, 200, 204,
- nil, 204, 204, 204, 204, 204, 204, 204, nil, nil,
- nil, nil, nil, 204, 204, 204, 204, 204, 204, 204,
- nil, nil, 204, nil, nil, nil, nil, nil, nil, 204,
- nil, nil, 204, 204, nil, 204, 204, 204, 204, 204,
- nil, 204, 204, 204, nil, 204, 204, nil, 204, 204,
- nil, 479, 479, 479, 479, 479, 479, 479, nil, nil,
- 479, 479, nil, nil, nil, nil, nil, nil, 479, 479,
- nil, 204, nil, nil, 204, nil, nil, 204, nil, nil,
- 204, nil, nil, 479, nil, 479, 204, 479, 479, 479,
- 479, 479, 479, 479, 204, 479, nil, nil, nil, 204,
- 204, 204, 204, 204, 204, nil, nil, nil, 204, 204,
- nil, nil, nil, 205, 205, 205, 204, 205, nil, 204,
- nil, 205, 205, nil, 204, 204, 205, nil, 205, 205,
- 205, 205, 205, 205, 205, nil, nil, nil, nil, nil,
- 205, 205, 205, 205, 205, 205, 205, nil, nil, 205,
- nil, nil, nil, nil, nil, nil, 205, nil, nil, 205,
- 205, nil, 205, 205, 205, 205, 205, nil, 205, 205,
- 205, nil, 205, 205, nil, 205, 205, nil, 482, 482,
- 482, 482, 482, 482, 482, nil, nil, 482, 482, nil,
- nil, nil, nil, nil, nil, 482, 482, nil, 205, nil,
- nil, 205, nil, nil, 205, nil, nil, 205, nil, nil,
- 482, nil, 482, 205, 482, 482, 482, 482, 482, 482,
- 482, 205, 482, nil, nil, nil, 205, 205, 205, 205,
- 205, 205, nil, nil, nil, 205, 205, nil, nil, nil,
- 206, 206, 206, 205, 206, nil, 205, nil, 206, 206,
- nil, 205, 205, 206, nil, 206, 206, 206, 206, 206,
- 206, 206, nil, nil, nil, nil, nil, 206, 206, 206,
- 206, 206, 206, 206, nil, nil, 206, nil, nil, nil,
- nil, nil, nil, 206, nil, nil, 206, 206, nil, 206,
- 206, 206, 206, 206, nil, 206, 206, 206, nil, 206,
- 206, nil, 206, 206, nil, 483, 483, 483, 483, 483,
- 483, 483, 483, nil, 483, 483, nil, nil, nil, nil,
- nil, nil, 483, 483, nil, 206, nil, nil, 206, nil,
- nil, 206, nil, nil, 206, nil, nil, 483, nil, 483,
- 206, 483, 483, 483, 483, 483, 483, 483, 206, 483,
- nil, nil, nil, 206, 206, 206, 206, 206, 206, nil,
- nil, nil, 206, 206, nil, nil, nil, nil, nil, nil,
- 206, nil, nil, 206, nil, nil, nil, nil, 206, 206,
- 214, 214, 214, 214, 214, nil, nil, nil, 214, 214,
- nil, nil, nil, 214, nil, 214, 214, 214, 214, 214,
- 214, 214, nil, nil, nil, nil, nil, 214, 214, 214,
- 214, 214, 214, 214, nil, nil, 214, nil, nil, nil,
- nil, nil, 214, 214, nil, 214, 214, 214, nil, 214,
- 214, 214, 214, 214, nil, 214, 214, 214, nil, 214,
- 214, nil, 214, 214, nil, 469, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 469, 469, nil, 214, nil, nil, 214, nil,
- nil, 214, nil, nil, 214, nil, 214, 469, nil, nil,
- 214, 469, 469, 469, 469, nil, nil, nil, 214, nil,
- nil, nil, nil, 214, 214, 214, 214, 214, 214, nil,
- nil, nil, 214, 214, nil, nil, nil, 215, 215, 215,
- 214, 215, nil, 214, nil, 215, 215, nil, 214, 214,
- 215, nil, 215, 215, 215, 215, 215, 215, 215, nil,
- nil, nil, nil, nil, 215, 215, 215, 215, 215, 215,
- 215, nil, nil, 215, nil, nil, nil, nil, nil, nil,
- 215, nil, nil, 215, 215, nil, 215, 215, 215, 215,
- 215, nil, 215, 215, 215, nil, 215, 215, nil, 215,
- 215, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 215, nil, nil, 215, nil, 215, 215, nil,
- nil, 215, nil, nil, nil, nil, nil, 215, nil, nil,
- nil, nil, nil, nil, nil, 215, nil, nil, nil, nil,
- 215, 215, 215, 215, 215, 215, nil, nil, nil, 215,
- 215, nil, nil, nil, 218, 218, 218, 215, 218, nil,
- 215, nil, 218, 218, nil, 215, 215, 218, nil, 218,
- 218, 218, 218, 218, 218, 218, nil, nil, nil, nil,
- nil, 218, 218, 218, 218, 218, 218, 218, nil, nil,
- 218, nil, nil, nil, nil, nil, nil, 218, nil, nil,
- 218, 218, nil, 218, 218, 218, 218, 218, nil, 218,
- 218, 218, nil, 218, 218, nil, 218, 218, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 218,
- nil, nil, 218, nil, nil, 218, nil, nil, 218, nil,
- nil, nil, nil, nil, 218, nil, nil, nil, nil, nil,
- nil, nil, 218, nil, nil, nil, nil, 218, 218, 218,
- 218, 218, 218, nil, nil, nil, 218, 218, nil, nil,
- nil, 220, 220, 220, 218, 220, nil, 218, nil, 220,
- 220, nil, 218, 218, 220, nil, 220, 220, 220, 220,
- 220, 220, 220, nil, nil, nil, nil, nil, 220, 220,
- 220, 220, 220, 220, 220, nil, nil, 220, nil, nil,
- nil, nil, nil, nil, 220, nil, nil, 220, 220, nil,
- 220, 220, 220, 220, 220, nil, 220, 220, 220, nil,
- 220, 220, nil, 220, 220, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 220, nil, nil, 220,
- nil, nil, 220, nil, nil, 220, nil, nil, nil, nil,
- nil, 220, nil, nil, nil, nil, nil, nil, nil, 220,
- nil, nil, nil, nil, 220, 220, 220, 220, 220, 220,
- nil, nil, nil, 220, 220, nil, nil, nil, 221, 221,
- 221, 220, 221, nil, 220, nil, 221, 221, nil, 220,
- 220, 221, nil, 221, 221, 221, 221, 221, 221, 221,
- nil, nil, nil, nil, nil, 221, 221, 221, 221, 221,
- 221, 221, nil, nil, 221, nil, nil, nil, nil, nil,
- nil, 221, nil, nil, 221, 221, nil, 221, 221, 221,
- 221, 221, nil, 221, 221, 221, nil, 221, 221, nil,
- 221, 221, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 221, nil, nil, 221, nil, nil, 221,
- nil, nil, 221, nil, nil, nil, nil, nil, 221, nil,
- nil, nil, nil, nil, nil, nil, 221, nil, nil, nil,
- nil, 221, 221, 221, 221, 221, 221, nil, nil, nil,
- 221, 221, nil, nil, nil, 222, 222, 222, 221, 222,
- nil, 221, nil, 222, 222, nil, 221, 221, 222, nil,
- 222, 222, 222, 222, 222, 222, 222, nil, nil, nil,
- nil, nil, 222, 222, 222, 222, 222, 222, 222, nil,
- nil, 222, nil, nil, nil, nil, nil, nil, 222, nil,
- nil, 222, 222, nil, 222, 222, 222, 222, 222, nil,
- 222, 222, 222, nil, 222, 222, nil, 222, 222, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 222, nil, nil, 222, nil, nil, 222, nil, nil, 222,
- nil, nil, nil, nil, nil, 222, nil, nil, nil, nil,
- nil, nil, nil, 222, nil, nil, nil, nil, 222, 222,
- 222, 222, 222, 222, nil, nil, nil, 222, 222, nil,
- nil, nil, 223, 223, 223, 222, 223, nil, 222, nil,
- 223, 223, nil, 222, 222, 223, nil, 223, 223, 223,
- 223, 223, 223, 223, nil, nil, nil, nil, nil, 223,
- 223, 223, 223, 223, 223, 223, nil, nil, 223, nil,
- nil, nil, nil, nil, nil, 223, nil, nil, 223, 223,
- nil, 223, 223, 223, 223, 223, nil, 223, 223, 223,
- nil, 223, 223, nil, 223, 223, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 223, nil, nil,
- 223, nil, nil, 223, nil, nil, 223, nil, nil, nil,
- nil, nil, 223, nil, nil, nil, nil, nil, nil, nil,
- 223, nil, nil, nil, nil, 223, 223, 223, 223, 223,
- 223, nil, nil, nil, 223, 223, nil, nil, nil, 224,
- 224, 224, 223, 224, nil, 223, nil, 224, 224, nil,
- 223, 223, 224, nil, 224, 224, 224, 224, 224, 224,
- 224, nil, nil, nil, nil, nil, 224, 224, 224, 224,
- 224, 224, 224, nil, nil, 224, nil, nil, nil, nil,
- nil, nil, 224, nil, nil, 224, 224, nil, 224, 224,
- 224, 224, 224, nil, 224, 224, 224, nil, 224, 224,
- nil, 224, 224, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 224, nil, nil, 224, nil, nil,
- 224, nil, nil, 224, nil, nil, nil, nil, nil, 224,
- nil, nil, nil, nil, nil, nil, nil, 224, nil, nil,
- nil, nil, 224, 224, 224, 224, 224, 224, nil, nil,
- nil, 224, 224, nil, nil, nil, 225, 225, 225, 224,
- 225, nil, 224, nil, 225, 225, nil, 224, 224, 225,
- nil, 225, 225, 225, 225, 225, 225, 225, nil, nil,
- nil, nil, nil, 225, 225, 225, 225, 225, 225, 225,
- nil, nil, 225, nil, nil, nil, nil, nil, nil, 225,
- nil, nil, 225, 225, nil, 225, 225, 225, 225, 225,
- nil, 225, 225, 225, nil, 225, 225, nil, 225, 225,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 225, nil, nil, 225, nil, nil, 225, nil, nil,
- 225, nil, nil, nil, nil, nil, 225, nil, nil, nil,
- nil, nil, nil, nil, 225, nil, nil, nil, nil, 225,
- 225, 225, 225, 225, 225, nil, nil, nil, 225, 225,
- nil, nil, nil, 226, 226, 226, 225, 226, nil, 225,
- nil, 226, 226, nil, 225, 225, 226, nil, 226, 226,
- 226, 226, 226, 226, 226, nil, nil, nil, nil, nil,
- 226, 226, 226, 226, 226, 226, 226, nil, nil, 226,
- nil, nil, nil, nil, nil, nil, 226, nil, nil, 226,
- 226, nil, 226, 226, 226, 226, 226, nil, 226, 226,
- 226, nil, 226, 226, nil, 226, 226, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 226, nil,
- nil, 226, nil, nil, 226, nil, nil, 226, nil, nil,
- nil, nil, nil, 226, nil, nil, nil, nil, nil, nil,
- nil, 226, nil, nil, nil, nil, 226, 226, 226, 226,
- 226, 226, nil, nil, nil, 226, 226, nil, nil, nil,
- 227, 227, 227, 226, 227, nil, 226, nil, 227, 227,
- nil, 226, 226, 227, nil, 227, 227, 227, 227, 227,
- 227, 227, nil, nil, nil, nil, nil, 227, 227, 227,
- 227, 227, 227, 227, nil, nil, 227, nil, nil, nil,
- nil, nil, nil, 227, nil, nil, 227, 227, nil, 227,
- 227, 227, 227, 227, nil, 227, 227, 227, nil, 227,
- 227, nil, 227, 227, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 227, nil, nil, 227, nil,
- nil, 227, nil, nil, 227, nil, nil, nil, nil, nil,
- 227, nil, nil, nil, nil, nil, nil, nil, 227, nil,
- nil, nil, nil, 227, 227, 227, 227, 227, 227, nil,
- nil, nil, 227, 227, nil, nil, nil, 228, 228, 228,
- 227, 228, nil, 227, nil, 228, 228, nil, 227, 227,
- 228, nil, 228, 228, 228, 228, 228, 228, 228, nil,
- nil, nil, nil, nil, 228, 228, 228, 228, 228, 228,
- 228, nil, nil, 228, nil, nil, nil, nil, nil, nil,
- 228, nil, nil, 228, 228, nil, 228, 228, 228, 228,
- 228, nil, 228, 228, 228, nil, 228, 228, nil, 228,
- 228, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 228, nil, nil, 228, nil, nil, 228, nil,
- nil, 228, nil, nil, nil, nil, nil, 228, nil, nil,
- nil, nil, nil, nil, nil, 228, nil, nil, nil, nil,
- 228, 228, 228, 228, 228, 228, nil, nil, nil, 228,
- 228, nil, nil, nil, 229, 229, 229, 228, 229, nil,
- 228, nil, 229, 229, nil, 228, 228, 229, nil, 229,
- 229, 229, 229, 229, 229, 229, nil, nil, nil, nil,
- nil, 229, 229, 229, 229, 229, 229, 229, nil, nil,
- 229, nil, nil, nil, nil, nil, nil, 229, nil, nil,
- 229, 229, nil, 229, 229, 229, 229, 229, nil, 229,
- 229, 229, nil, 229, 229, nil, 229, 229, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 229,
- nil, nil, 229, nil, nil, 229, nil, nil, 229, nil,
- nil, nil, nil, nil, 229, nil, nil, nil, nil, nil,
- nil, nil, 229, nil, nil, nil, nil, 229, 229, 229,
- 229, 229, 229, nil, nil, nil, 229, 229, nil, nil,
- nil, 230, 230, 230, 229, 230, nil, 229, nil, 230,
- 230, nil, 229, 229, 230, nil, 230, 230, 230, 230,
- 230, 230, 230, nil, nil, nil, nil, nil, 230, 230,
- 230, 230, 230, 230, 230, nil, nil, 230, nil, nil,
- nil, nil, nil, nil, 230, nil, nil, 230, 230, nil,
- 230, 230, 230, 230, 230, nil, 230, 230, 230, nil,
- 230, 230, nil, 230, 230, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 230, nil, nil, 230,
- nil, nil, 230, nil, nil, 230, nil, nil, nil, nil,
- nil, 230, nil, nil, nil, nil, nil, nil, nil, 230,
- nil, nil, nil, nil, 230, 230, 230, 230, 230, 230,
- nil, nil, nil, 230, 230, nil, nil, nil, 231, 231,
- 231, 230, 231, nil, 230, nil, 231, 231, nil, 230,
- 230, 231, nil, 231, 231, 231, 231, 231, 231, 231,
- nil, nil, nil, nil, nil, 231, 231, 231, 231, 231,
- 231, 231, nil, nil, 231, nil, nil, nil, nil, nil,
- nil, 231, nil, nil, 231, 231, nil, 231, 231, 231,
- 231, 231, nil, 231, 231, 231, nil, 231, 231, nil,
- 231, 231, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 231, nil, nil, 231, nil, nil, 231,
- nil, nil, 231, nil, nil, nil, nil, nil, 231, nil,
- nil, nil, nil, nil, nil, nil, 231, nil, nil, nil,
- nil, 231, 231, 231, 231, 231, 231, nil, nil, nil,
- 231, 231, nil, nil, nil, 232, 232, 232, 231, 232,
- nil, 231, nil, 232, 232, nil, 231, 231, 232, nil,
- 232, 232, 232, 232, 232, 232, 232, nil, nil, nil,
- nil, nil, 232, 232, 232, 232, 232, 232, 232, nil,
- nil, 232, nil, nil, nil, nil, nil, nil, 232, nil,
- nil, 232, 232, nil, 232, 232, 232, 232, 232, nil,
- 232, 232, 232, nil, 232, 232, nil, 232, 232, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 232, nil, nil, 232, nil, nil, 232, nil, nil, 232,
- nil, nil, nil, nil, nil, 232, nil, nil, nil, nil,
- nil, nil, nil, 232, nil, nil, nil, nil, 232, 232,
- 232, 232, 232, 232, nil, nil, nil, 232, 232, nil,
- nil, nil, 233, 233, 233, 232, 233, nil, 232, nil,
- 233, 233, nil, 232, 232, 233, nil, 233, 233, 233,
- 233, 233, 233, 233, nil, nil, nil, nil, nil, 233,
- 233, 233, 233, 233, 233, 233, nil, nil, 233, nil,
- nil, nil, nil, nil, nil, 233, nil, nil, 233, 233,
- nil, 233, 233, 233, 233, 233, nil, 233, 233, 233,
- nil, 233, 233, nil, 233, 233, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 233, nil, nil,
- 233, nil, nil, 233, nil, nil, 233, nil, nil, nil,
- nil, nil, 233, nil, nil, nil, nil, nil, nil, nil,
- 233, nil, nil, nil, nil, 233, 233, 233, 233, 233,
- 233, nil, nil, nil, 233, 233, nil, nil, nil, 234,
- 234, 234, 233, 234, nil, 233, nil, 234, 234, nil,
- 233, 233, 234, nil, 234, 234, 234, 234, 234, 234,
- 234, nil, nil, nil, nil, nil, 234, 234, 234, 234,
- 234, 234, 234, nil, nil, 234, nil, nil, nil, nil,
- nil, nil, 234, nil, nil, 234, 234, nil, 234, 234,
- 234, 234, 234, nil, 234, 234, 234, nil, 234, 234,
- nil, 234, 234, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 234, nil, nil, 234, nil, nil,
- 234, nil, nil, 234, nil, nil, nil, nil, nil, 234,
- nil, nil, nil, nil, nil, nil, nil, 234, nil, nil,
- nil, nil, 234, 234, 234, 234, 234, 234, nil, nil,
- nil, 234, 234, nil, nil, nil, 235, 235, 235, 234,
- 235, nil, 234, nil, 235, 235, nil, 234, 234, 235,
- nil, 235, 235, 235, 235, 235, 235, 235, nil, nil,
- nil, nil, nil, 235, 235, 235, 235, 235, 235, 235,
- nil, nil, 235, nil, nil, nil, nil, nil, nil, 235,
- nil, nil, 235, 235, nil, 235, 235, 235, 235, 235,
- nil, 235, 235, 235, nil, 235, 235, nil, 235, 235,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 235, nil, nil, 235, nil, nil, 235, nil, nil,
- 235, nil, nil, nil, nil, nil, 235, nil, nil, nil,
- nil, nil, nil, nil, 235, nil, nil, nil, nil, 235,
- 235, 235, 235, 235, 235, nil, nil, nil, 235, 235,
- nil, nil, nil, 236, 236, 236, 235, 236, nil, 235,
- nil, 236, 236, nil, 235, 235, 236, nil, 236, 236,
- 236, 236, 236, 236, 236, nil, nil, nil, nil, nil,
- 236, 236, 236, 236, 236, 236, 236, nil, nil, 236,
- nil, nil, nil, nil, nil, nil, 236, nil, nil, 236,
- 236, nil, 236, 236, 236, 236, 236, nil, 236, 236,
- 236, nil, 236, 236, nil, 236, 236, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 236, nil,
- nil, 236, nil, nil, 236, nil, nil, 236, nil, nil,
- nil, nil, nil, 236, nil, nil, nil, nil, nil, nil,
- nil, 236, nil, nil, nil, nil, 236, 236, 236, 236,
- 236, 236, nil, nil, nil, 236, 236, nil, nil, nil,
- 237, 237, 237, 236, 237, nil, 236, nil, 237, 237,
- nil, 236, 236, 237, nil, 237, 237, 237, 237, 237,
- 237, 237, nil, nil, nil, nil, nil, 237, 237, 237,
- 237, 237, 237, 237, nil, nil, 237, nil, nil, nil,
- nil, nil, nil, 237, nil, nil, 237, 237, nil, 237,
- 237, 237, 237, 237, nil, 237, 237, 237, nil, 237,
- 237, nil, 237, 237, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 237, nil, nil, 237, nil,
- nil, 237, nil, nil, 237, nil, nil, nil, nil, nil,
- 237, nil, nil, nil, nil, nil, nil, nil, 237, nil,
- nil, nil, nil, 237, 237, 237, 237, 237, 237, nil,
- nil, nil, 237, 237, nil, nil, nil, 238, 238, 238,
- 237, 238, nil, 237, nil, 238, 238, nil, 237, 237,
- 238, nil, 238, 238, 238, 238, 238, 238, 238, nil,
- nil, nil, nil, nil, 238, 238, 238, 238, 238, 238,
- 238, nil, nil, 238, nil, nil, nil, nil, nil, nil,
- 238, nil, nil, 238, 238, nil, 238, 238, 238, 238,
- 238, nil, 238, 238, 238, nil, 238, 238, nil, 238,
- 238, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 238, nil, nil, 238, nil, nil, 238, nil,
- nil, 238, nil, nil, nil, nil, nil, 238, nil, nil,
- nil, nil, nil, nil, nil, 238, nil, nil, nil, nil,
- 238, 238, 238, 238, 238, 238, nil, nil, nil, 238,
- 238, nil, nil, nil, 239, 239, 239, 238, 239, nil,
- 238, nil, 239, 239, nil, 238, 238, 239, nil, 239,
- 239, 239, 239, 239, 239, 239, nil, nil, nil, nil,
- nil, 239, 239, 239, 239, 239, 239, 239, nil, nil,
- 239, nil, nil, nil, nil, nil, nil, 239, nil, nil,
- 239, 239, nil, 239, 239, 239, 239, 239, nil, 239,
- 239, 239, nil, 239, 239, nil, 239, 239, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 239,
- nil, nil, 239, nil, nil, 239, nil, nil, 239, nil,
- nil, nil, nil, nil, 239, nil, nil, nil, nil, nil,
- nil, nil, 239, nil, nil, nil, nil, 239, 239, 239,
- 239, 239, 239, nil, nil, nil, 239, 239, nil, nil,
- nil, 240, 240, 240, 239, 240, nil, 239, nil, 240,
- 240, nil, 239, 239, 240, nil, 240, 240, 240, 240,
- 240, 240, 240, nil, nil, nil, nil, nil, 240, 240,
- 240, 240, 240, 240, 240, nil, nil, 240, nil, nil,
- nil, nil, nil, nil, 240, nil, nil, 240, 240, nil,
- 240, 240, 240, 240, 240, nil, 240, 240, 240, nil,
- 240, 240, nil, 240, 240, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 240, nil, nil, 240,
- nil, nil, 240, nil, nil, 240, nil, nil, nil, nil,
- nil, 240, nil, nil, nil, nil, nil, nil, nil, 240,
- nil, nil, nil, nil, 240, 240, 240, 240, 240, 240,
- nil, nil, nil, 240, 240, nil, nil, nil, 241, 241,
- 241, 240, 241, nil, 240, nil, 241, 241, nil, 240,
- 240, 241, nil, 241, 241, 241, 241, 241, 241, 241,
- nil, nil, nil, nil, nil, 241, 241, 241, 241, 241,
- 241, 241, nil, nil, 241, nil, nil, nil, nil, nil,
- nil, 241, nil, nil, 241, 241, nil, 241, 241, 241,
- 241, 241, nil, 241, 241, 241, nil, 241, 241, nil,
- 241, 241, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 241, nil, nil, 241, nil, nil, 241,
- nil, nil, 241, nil, nil, nil, nil, nil, 241, nil,
- nil, nil, nil, nil, nil, nil, 241, nil, nil, nil,
- nil, 241, 241, 241, 241, 241, 241, nil, nil, nil,
- 241, 241, nil, nil, nil, 242, 242, 242, 241, 242,
- nil, 241, nil, 242, 242, nil, 241, 241, 242, nil,
- 242, 242, 242, 242, 242, 242, 242, nil, nil, nil,
- nil, nil, 242, 242, 242, 242, 242, 242, 242, nil,
- nil, 242, nil, nil, nil, nil, nil, nil, 242, nil,
- nil, 242, 242, nil, 242, 242, 242, 242, 242, nil,
- 242, 242, 242, nil, 242, 242, nil, 242, 242, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 242, nil, nil, 242, nil, nil, 242, nil, nil, 242,
- nil, nil, nil, nil, nil, 242, nil, nil, nil, nil,
- nil, nil, nil, 242, nil, nil, nil, nil, 242, 242,
- 242, 242, 242, 242, nil, nil, nil, 242, 242, nil,
- nil, nil, 243, 243, 243, 242, 243, nil, 242, nil,
- 243, 243, nil, 242, 242, 243, nil, 243, 243, 243,
- 243, 243, 243, 243, nil, nil, nil, nil, nil, 243,
- 243, 243, 243, 243, 243, 243, nil, nil, 243, nil,
- nil, nil, nil, nil, nil, 243, nil, nil, 243, 243,
- nil, 243, 243, 243, 243, 243, nil, 243, 243, 243,
- nil, 243, 243, nil, 243, 243, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 243, nil, nil,
- 243, nil, nil, 243, nil, nil, 243, nil, nil, nil,
- nil, nil, 243, nil, nil, nil, nil, nil, nil, nil,
- 243, nil, nil, nil, nil, 243, 243, 243, 243, 243,
- 243, nil, nil, nil, 243, 243, nil, nil, nil, 244,
- 244, 244, 243, 244, nil, 243, nil, 244, 244, nil,
- 243, 243, 244, nil, 244, 244, 244, 244, 244, 244,
- 244, nil, nil, nil, nil, nil, 244, 244, 244, 244,
- 244, 244, 244, nil, nil, 244, nil, nil, nil, nil,
- nil, nil, 244, nil, nil, 244, 244, nil, 244, 244,
- 244, 244, 244, nil, 244, 244, 244, nil, 244, 244,
- nil, 244, 244, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 244, nil, nil, 244, nil, nil,
- 244, nil, nil, 244, nil, nil, nil, nil, nil, 244,
- nil, nil, nil, nil, nil, nil, nil, 244, nil, nil,
- nil, nil, 244, 244, 244, 244, 244, 244, nil, nil,
- nil, 244, 244, nil, nil, nil, 245, 245, 245, 244,
- 245, nil, 244, nil, 245, 245, nil, 244, 244, 245,
- nil, 245, 245, 245, 245, 245, 245, 245, nil, nil,
- nil, nil, nil, 245, 245, 245, 245, 245, 245, 245,
- nil, nil, 245, nil, nil, nil, nil, nil, nil, 245,
- nil, nil, 245, 245, nil, 245, 245, 245, 245, 245,
- nil, 245, 245, 245, nil, 245, 245, nil, 245, 245,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 245, nil, nil, 245, nil, nil, 245, nil, nil,
- 245, nil, nil, nil, nil, nil, 245, nil, nil, nil,
- nil, nil, nil, nil, 245, nil, nil, nil, nil, 245,
- 245, 245, 245, 245, 245, nil, nil, nil, 245, 245,
- nil, nil, nil, 254, 254, 254, 245, 254, nil, 245,
- nil, 254, 254, nil, 245, 245, 254, nil, 254, 254,
- 254, 254, 254, 254, 254, nil, nil, nil, nil, nil,
- 254, 254, 254, 254, 254, 254, 254, nil, nil, 254,
- nil, nil, nil, nil, nil, nil, 254, nil, nil, 254,
- 254, nil, 254, 254, 254, 254, 254, nil, 254, 254,
- 254, nil, 254, 254, nil, 254, 254, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 254, nil,
- nil, 254, nil, nil, 254, nil, nil, 254, nil, nil,
- nil, nil, nil, 254, nil, nil, nil, nil, nil, nil,
- nil, 254, nil, nil, nil, nil, 254, 254, 254, 254,
- 254, 254, nil, nil, nil, 254, 254, nil, nil, nil,
- 256, 256, 256, 254, 256, nil, 254, nil, 256, 256,
- nil, 254, 254, 256, nil, 256, 256, 256, 256, 256,
- 256, 256, nil, nil, nil, nil, nil, 256, 256, 256,
- 256, 256, 256, 256, nil, nil, 256, nil, nil, nil,
- nil, nil, nil, 256, nil, nil, 256, 256, nil, 256,
- 256, 256, 256, 256, nil, 256, 256, 256, nil, 256,
- 256, nil, 256, 256, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 256, nil, nil, 256, nil,
- nil, 256, nil, nil, 256, nil, nil, nil, nil, nil,
- 256, nil, nil, nil, nil, nil, nil, nil, 256, nil,
- nil, nil, nil, 256, 256, 256, 256, 256, 256, nil,
- nil, nil, 256, 256, nil, nil, nil, 261, 261, 261,
- 256, 261, nil, 256, nil, 261, 261, nil, 256, 256,
- 261, nil, 261, 261, 261, 261, 261, 261, 261, nil,
- nil, nil, nil, nil, 261, 261, 261, 261, 261, 261,
- 261, nil, nil, 261, nil, nil, nil, nil, nil, nil,
- 261, nil, nil, 261, 261, nil, 261, 261, 261, 261,
- 261, nil, 261, 261, 261, nil, 261, 261, nil, 261,
- 261, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 261, nil, nil, 261, nil, nil, 261, nil,
- nil, 261, nil, nil, nil, nil, nil, 261, nil, nil,
- nil, nil, nil, nil, nil, 261, nil, nil, nil, nil,
- 261, 261, 261, 261, 261, 261, nil, nil, nil, 261,
- 261, nil, nil, nil, 268, 268, 268, 261, 268, nil,
- 261, nil, 268, 268, nil, 261, 261, 268, nil, 268,
- 268, 268, 268, 268, 268, 268, nil, nil, nil, nil,
- nil, 268, 268, 268, 268, 268, 268, 268, nil, nil,
- 268, nil, nil, nil, nil, nil, nil, 268, nil, nil,
- 268, 268, nil, 268, 268, 268, 268, 268, 268, 268,
- 268, 268, nil, 268, 268, nil, 268, 268, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 268,
- nil, nil, 268, nil, nil, 268, nil, nil, 268, nil,
- 268, nil, 268, nil, 268, nil, nil, nil, nil, nil,
- nil, nil, 268, nil, nil, nil, nil, 268, 268, 268,
- 268, 268, 268, nil, nil, nil, 268, 268, nil, nil,
- nil, 269, 269, 269, 268, 269, nil, 268, nil, 269,
- 269, nil, 268, 268, 269, nil, 269, 269, 269, 269,
- 269, 269, 269, nil, nil, nil, nil, nil, 269, 269,
- 269, 269, 269, 269, 269, nil, nil, 269, nil, nil,
- nil, nil, nil, nil, 269, nil, nil, 269, 269, nil,
- 269, 269, 269, 269, 269, 269, 269, 269, 269, nil,
- 269, 269, nil, 269, 269, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 269, nil, nil, 269,
- nil, nil, 269, nil, nil, 269, nil, 269, nil, 269,
- nil, 269, nil, nil, nil, nil, nil, nil, nil, 269,
- nil, nil, nil, nil, 269, 269, 269, 269, 269, 269,
- nil, nil, nil, 269, 269, nil, nil, nil, 277, 277,
- 277, 269, 277, nil, 269, nil, 277, 277, nil, 269,
- 269, 277, nil, 277, 277, 277, 277, 277, 277, 277,
- nil, nil, nil, nil, nil, 277, 277, 277, 277, 277,
- 277, 277, nil, nil, 277, nil, nil, nil, nil, nil,
- nil, 277, nil, nil, 277, 277, nil, 277, 277, 277,
- 277, 277, 277, 277, 277, 277, nil, 277, 277, nil,
- 277, 277, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 277, nil, nil, 277, nil, 277, 277,
- nil, nil, 277, nil, 277, nil, 277, nil, 277, nil,
- nil, nil, nil, nil, nil, nil, 277, nil, nil, nil,
- nil, 277, 277, 277, 277, 277, 277, nil, nil, nil,
- 277, 277, nil, nil, nil, nil, nil, nil, 277, nil,
- nil, 277, nil, nil, nil, nil, 277, 277, 281, 281,
- 281, 281, 281, nil, nil, nil, 281, 281, nil, nil,
- nil, 281, nil, 281, 281, 281, 281, 281, 281, 281,
- nil, nil, nil, nil, nil, 281, 281, 281, 281, 281,
- 281, 281, nil, nil, 281, nil, nil, nil, nil, nil,
- 281, 281, nil, 281, 281, 281, nil, 281, 281, 281,
- 281, 281, nil, 281, 281, 281, nil, 281, 281, nil,
- 281, 281, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 281, nil, nil, 281, nil, nil, 281,
- nil, nil, 281, nil, 281, nil, nil, nil, 281, nil,
- nil, nil, nil, nil, nil, nil, 281, nil, nil, nil,
- nil, 281, 281, 281, 281, 281, 281, nil, nil, nil,
- 281, 281, nil, nil, nil, 285, 285, 285, 281, 285,
- nil, 281, nil, 285, 285, nil, 281, 281, 285, nil,
- 285, 285, 285, 285, 285, 285, 285, nil, nil, nil,
- nil, nil, 285, 285, 285, 285, 285, 285, 285, nil,
- nil, 285, nil, nil, nil, nil, nil, nil, 285, nil,
- nil, 285, 285, nil, 285, 285, 285, 285, 285, nil,
- 285, 285, 285, nil, 285, 285, 749, nil, 749, 749,
- 749, 749, 749, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 749, nil, nil, nil, nil, nil, nil, nil,
- 285, nil, nil, 285, nil, nil, 285, nil, nil, 285,
- nil, nil, nil, nil, nil, 749, nil, nil, nil, nil,
- nil, nil, nil, 749, 749, 749, 749, nil, 285, 285,
- 285, 285, 285, 285, nil, nil, nil, 285, 285, nil,
- nil, nil, 285, nil, nil, 285, nil, nil, 285, nil,
- nil, nil, nil, 285, 285, 286, 286, 286, 286, 286,
- nil, nil, 749, 286, 286, nil, nil, nil, 286, nil,
- 286, 286, 286, 286, 286, 286, 286, nil, nil, nil,
- nil, nil, 286, 286, 286, 286, 286, 286, 286, nil,
- nil, 286, nil, nil, nil, nil, nil, 286, 286, nil,
- 286, 286, 286, nil, 286, 286, 286, 286, 286, nil,
- 286, 286, 286, nil, 286, 286, nil, 286, 286, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 286, nil, nil, 286, nil, nil, 286, nil, nil, 286,
- nil, 286, nil, nil, nil, 286, nil, nil, nil, nil,
- nil, nil, nil, 286, nil, nil, nil, nil, 286, 286,
- 286, 286, 286, 286, nil, nil, nil, 286, 286, nil,
- nil, nil, 298, 298, 298, 286, 298, nil, 286, nil,
- 298, 298, nil, 286, 286, 298, nil, 298, 298, 298,
- 298, 298, 298, 298, nil, nil, nil, nil, nil, 298,
- 298, 298, 298, 298, 298, 298, nil, nil, 298, nil,
- nil, nil, nil, nil, nil, 298, nil, nil, 298, 298,
- nil, 298, 298, 298, 298, 298, nil, 298, 298, 298,
- nil, 298, 298, 56, nil, 56, 56, 56, nil, 56,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 298, nil, nil,
- 298, nil, nil, 298, nil, nil, 298, nil, nil, nil,
- nil, nil, 56, 56, nil, nil, nil, nil, nil, nil,
- 56, 56, 56, 56, nil, 298, 298, 298, 298, 298,
- 298, nil, nil, nil, 298, 298, nil, nil, nil, 307,
- 307, 307, 298, 307, nil, 298, nil, 307, 307, nil,
- 298, 298, 307, nil, 307, 307, 307, 307, 307, 307,
- 307, nil, nil, nil, nil, nil, 307, 307, 307, 307,
- 307, 307, 307, nil, nil, 307, nil, nil, nil, nil,
- nil, nil, 307, nil, nil, 307, 307, nil, 307, 307,
- 307, 307, 307, nil, 307, 307, 307, nil, 307, 307,
- nil, 307, 307, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 307, nil, nil, 307, 307, nil,
- 307, nil, nil, 307, nil, nil, nil, nil, nil, 307,
- nil, nil, nil, nil, nil, nil, nil, 307, nil, nil,
- nil, nil, 307, 307, 307, 307, 307, 307, nil, nil,
- nil, 307, 307, nil, nil, nil, nil, nil, nil, 307,
- nil, nil, 307, nil, nil, nil, nil, 307, 307, 309,
- 309, 309, 309, 309, nil, nil, nil, 309, 309, nil,
- nil, nil, 309, nil, 309, 309, 309, 309, 309, 309,
- 309, nil, nil, nil, nil, nil, 309, 309, 309, 309,
- 309, 309, 309, nil, nil, 309, nil, nil, nil, nil,
- nil, 309, 309, nil, 309, 309, 309, nil, 309, 309,
- 309, 309, 309, nil, 309, 309, 309, nil, 309, 309,
- nil, 309, 309, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 309, nil, nil, 309, nil, nil,
- 309, nil, nil, 309, nil, 309, nil, nil, nil, 309,
- nil, nil, nil, nil, nil, nil, nil, 309, nil, nil,
- nil, nil, 309, 309, 309, 309, 309, 309, nil, nil,
- nil, 309, 309, nil, nil, nil, 349, 349, 349, 309,
- 349, nil, 309, nil, 349, 349, nil, 309, 309, 349,
- nil, 349, 349, 349, 349, 349, 349, 349, nil, nil,
- nil, nil, nil, 349, 349, 349, 349, 349, 349, 349,
- nil, nil, 349, nil, nil, nil, nil, nil, nil, 349,
- nil, nil, 349, 349, nil, 349, 349, 349, 349, 349,
- nil, 349, 349, 349, nil, 349, 349, nil, 349, 349,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 349, nil, nil, 349, nil, nil, 349, nil, nil,
- 349, nil, nil, nil, nil, nil, 349, nil, nil, nil,
- nil, nil, nil, nil, 349, nil, nil, nil, nil, 349,
- 349, 349, 349, 349, 349, nil, nil, nil, 349, 349,
- nil, nil, nil, 350, 350, 350, 349, 350, nil, 349,
- nil, 350, 350, nil, 349, 349, 350, nil, 350, 350,
- 350, 350, 350, 350, 350, nil, nil, nil, nil, nil,
- 350, 350, 350, 350, 350, 350, 350, nil, nil, 350,
- nil, nil, nil, nil, nil, nil, 350, nil, nil, 350,
- 350, nil, 350, 350, 350, 350, 350, nil, 350, 350,
- 350, nil, 350, 350, nil, 350, 350, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 350, nil,
- nil, 350, nil, nil, 350, nil, nil, 350, nil, nil,
- nil, nil, nil, 350, nil, nil, nil, nil, nil, nil,
- nil, 350, nil, nil, nil, nil, 350, 350, 350, 350,
- 350, 350, nil, nil, nil, 350, 350, nil, nil, nil,
- 369, 369, 369, 350, 369, nil, 350, nil, 369, 369,
- nil, 350, 350, 369, nil, 369, 369, 369, 369, 369,
- 369, 369, nil, nil, nil, nil, nil, 369, 369, 369,
- 369, 369, 369, 369, nil, nil, 369, nil, nil, nil,
- nil, nil, nil, 369, nil, nil, 369, 369, nil, 369,
- 369, 369, 369, 369, nil, 369, 369, 369, nil, 369,
- 369, 322, nil, 322, 322, 322, nil, 322, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 369, nil, nil, 369, nil,
- nil, 369, nil, nil, 369, nil, nil, nil, nil, nil,
- 322, nil, 322, nil, nil, nil, nil, nil, 322, 322,
- 322, 322, nil, 369, 369, 369, 369, 369, 369, nil,
- nil, nil, 369, 369, nil, nil, nil, 381, 381, 381,
- 369, 381, nil, 369, nil, 381, 381, nil, 369, 369,
- 381, nil, 381, 381, 381, 381, 381, 381, 381, nil,
- nil, nil, nil, nil, 381, 381, 381, 381, 381, 381,
- 381, nil, nil, 381, nil, nil, nil, nil, nil, nil,
- 381, nil, nil, 381, 381, nil, 381, 381, 381, 381,
- 381, nil, 381, 381, 381, nil, 381, 381, nil, 381,
- 381, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 381, nil, nil, 381, nil, nil, 381, nil,
- nil, 381, nil, nil, nil, nil, nil, 381, nil, nil,
- nil, nil, nil, nil, nil, 381, nil, nil, nil, nil,
- 381, 381, 381, 381, 381, 381, nil, nil, nil, 381,
- 381, nil, nil, nil, 421, 421, 421, 381, 421, nil,
- 381, nil, 421, 421, nil, 381, 381, 421, nil, 421,
- 421, 421, 421, 421, 421, 421, nil, nil, nil, nil,
- nil, 421, 421, 421, 421, 421, 421, 421, nil, nil,
- 421, nil, nil, nil, nil, nil, nil, 421, nil, nil,
- 421, 421, nil, 421, 421, 421, 421, 421, nil, 421,
- 421, 421, nil, 421, 421, nil, 421, 421, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 421,
- nil, nil, 421, nil, nil, 421, nil, nil, 421, nil,
- nil, nil, nil, nil, 421, nil, nil, nil, nil, nil,
- nil, nil, 421, nil, nil, nil, nil, 421, 421, 421,
- 421, 421, 421, nil, nil, nil, 421, 421, nil, nil,
- nil, 432, 432, 432, 421, 432, nil, 421, nil, 432,
- 432, nil, 421, 421, 432, nil, 432, 432, 432, 432,
- 432, 432, 432, nil, nil, nil, nil, nil, 432, 432,
- 432, 432, 432, 432, 432, nil, nil, 432, nil, nil,
- nil, nil, nil, nil, 432, nil, nil, 432, 432, nil,
- 432, 432, 432, 432, 432, 432, 432, 432, 432, nil,
- 432, 432, nil, 432, 432, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 432, nil, nil, 432,
- 432, nil, 432, nil, nil, 432, nil, 432, nil, 432,
- nil, 432, nil, nil, nil, nil, nil, nil, nil, 432,
- nil, nil, nil, nil, 432, 432, 432, 432, 432, 432,
- nil, nil, nil, 432, 432, nil, nil, nil, 440, 440,
- 440, 432, 440, nil, 432, nil, 440, 440, nil, 432,
- 432, 440, nil, 440, 440, 440, 440, 440, 440, 440,
- nil, nil, nil, nil, nil, 440, 440, 440, 440, 440,
- 440, 440, nil, nil, 440, nil, nil, nil, nil, nil,
- nil, 440, nil, nil, 440, 440, nil, 440, 440, 440,
- 440, 440, 440, 440, 440, 440, nil, 440, 440, nil,
- 440, 440, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 440, nil, nil, 440, 440, nil, 440,
- nil, nil, 440, nil, 440, nil, 440, nil, 440, nil,
- nil, nil, nil, nil, nil, nil, 440, nil, nil, nil,
- nil, 440, 440, 440, 440, 440, 440, nil, nil, nil,
- 440, 440, nil, nil, nil, 441, 441, 441, 440, 441,
- nil, 440, nil, 441, 441, nil, 440, 440, 441, nil,
- 441, 441, 441, 441, 441, 441, 441, nil, nil, nil,
- nil, nil, 441, 441, 441, 441, 441, 441, 441, nil,
- nil, 441, nil, nil, nil, nil, nil, nil, 441, nil,
- nil, 441, 441, nil, 441, 441, 441, 441, 441, 441,
- 441, 441, 441, nil, 441, 441, nil, 441, 441, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 441, nil, nil, 441, 441, nil, 441, nil, nil, 441,
- nil, 441, nil, 441, nil, 441, nil, nil, nil, nil,
- nil, nil, nil, 441, nil, nil, nil, nil, 441, 441,
- 441, 441, 441, 441, nil, nil, nil, 441, 441, nil,
- nil, nil, 442, 442, 442, 441, 442, nil, 441, nil,
- 442, 442, nil, 441, 441, 442, nil, 442, 442, 442,
- 442, 442, 442, 442, nil, nil, nil, nil, nil, 442,
- 442, 442, 442, 442, 442, 442, nil, nil, 442, nil,
- nil, nil, nil, nil, nil, 442, nil, nil, 442, 442,
- nil, 442, 442, 442, 442, 442, 442, 442, 442, 442,
- nil, 442, 442, nil, 442, 442, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 442, nil, nil,
- 442, 442, nil, 442, nil, nil, 442, nil, 442, nil,
- 442, nil, 442, nil, nil, nil, nil, nil, nil, nil,
- 442, nil, nil, nil, nil, 442, 442, 442, 442, 442,
- 442, nil, nil, nil, 442, 442, nil, nil, nil, 451,
- 451, 451, 442, 451, nil, 442, nil, 451, 451, nil,
- 442, 442, 451, nil, 451, 451, 451, 451, 451, 451,
- 451, nil, nil, nil, nil, nil, 451, 451, 451, 451,
- 451, 451, 451, nil, nil, 451, nil, nil, nil, nil,
- nil, nil, 451, nil, nil, 451, 451, nil, 451, 451,
- 451, 451, 451, 451, 451, 451, 451, nil, 451, 451,
- nil, 451, 451, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 451, nil, nil, 451, nil, nil,
- 451, nil, nil, 451, nil, 451, nil, nil, nil, 451,
- nil, nil, nil, nil, nil, nil, nil, 451, nil, nil,
- nil, nil, 451, 451, 451, 451, 451, 451, nil, nil,
- nil, 451, 451, nil, nil, nil, 452, 452, 452, 451,
- 452, nil, 451, nil, 452, 452, nil, 451, 451, 452,
- nil, 452, 452, 452, 452, 452, 452, 452, nil, nil,
- nil, nil, nil, 452, 452, 452, 452, 452, 452, 452,
- nil, nil, 452, nil, nil, nil, nil, nil, nil, 452,
- nil, nil, 452, 452, nil, 452, 452, 452, 452, 452,
- 452, 452, 452, 452, nil, 452, 452, nil, 452, 452,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 452, nil, nil, 452, nil, nil, 452, nil, nil,
- 452, nil, 452, nil, nil, nil, 452, nil, nil, nil,
- nil, nil, nil, nil, 452, nil, nil, nil, nil, 452,
- 452, 452, 452, 452, 452, nil, nil, nil, 452, 452,
- nil, nil, nil, 454, 454, 454, 452, 454, nil, 452,
- nil, 454, 454, nil, 452, 452, 454, nil, 454, 454,
- 454, 454, 454, 454, 454, nil, nil, nil, nil, nil,
- 454, 454, 454, 454, 454, 454, 454, nil, nil, 454,
- nil, nil, nil, nil, nil, nil, 454, nil, nil, 454,
- 454, nil, 454, 454, 454, 454, 454, nil, 454, 454,
- 454, nil, 454, 454, nil, 454, 454, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 454, nil,
- nil, 454, nil, nil, 454, nil, nil, 454, nil, nil,
- nil, nil, nil, 454, nil, nil, nil, nil, nil, nil,
- nil, 454, nil, nil, nil, nil, 454, 454, 454, 454,
- 454, 454, nil, nil, nil, 454, 454, nil, nil, nil,
- 455, 455, 455, 454, 455, nil, 454, nil, 455, 455,
- nil, 454, 454, 455, nil, 455, 455, 455, 455, 455,
- 455, 455, nil, nil, nil, nil, nil, 455, 455, 455,
- 455, 455, 455, 455, nil, nil, 455, nil, nil, nil,
- nil, nil, nil, 455, nil, nil, 455, 455, nil, 455,
- 455, 455, 455, 455, nil, 455, 455, 455, nil, 455,
- 455, nil, 455, 455, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 455, nil, nil, 455, nil,
- nil, 455, nil, nil, 455, nil, nil, nil, nil, nil,
- 455, nil, nil, nil, nil, nil, nil, nil, 455, nil,
- nil, nil, nil, 455, 455, 455, 455, 455, 455, nil,
- nil, nil, 455, 455, nil, nil, nil, 456, 456, 456,
- 455, 456, nil, 455, nil, 456, 456, nil, 455, 455,
- 456, nil, 456, 456, 456, 456, 456, 456, 456, nil,
- nil, nil, nil, nil, 456, 456, 456, 456, 456, 456,
- 456, nil, nil, 456, nil, nil, nil, nil, nil, nil,
- 456, nil, nil, 456, 456, nil, 456, 456, 456, 456,
- 456, nil, 456, 456, 456, nil, 456, 456, nil, 456,
- 456, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 456, nil, nil, 456, nil, nil, 456, nil,
- nil, 456, nil, nil, nil, nil, nil, 456, nil, nil,
- nil, nil, nil, nil, nil, 456, nil, nil, nil, nil,
- 456, 456, 456, 456, 456, 456, nil, nil, nil, 456,
- 456, nil, nil, nil, 487, 487, 487, 456, 487, nil,
- 456, nil, 487, 487, nil, 456, 456, 487, nil, 487,
- 487, 487, 487, 487, 487, 487, nil, nil, nil, nil,
- nil, 487, 487, 487, 487, 487, 487, 487, nil, nil,
- 487, nil, nil, nil, nil, nil, nil, 487, nil, nil,
- 487, 487, nil, 487, 487, 487, 487, 487, 487, 487,
- 487, 487, nil, 487, 487, nil, 487, 487, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 487,
- nil, nil, 487, nil, nil, 487, nil, nil, 487, nil,
- 487, nil, 487, nil, 487, nil, nil, nil, nil, nil,
- nil, nil, 487, nil, nil, nil, nil, 487, 487, 487,
- 487, 487, 487, nil, nil, nil, 487, 487, nil, nil,
- nil, 489, 489, 489, 487, 489, nil, 487, nil, 489,
- 489, nil, 487, 487, 489, nil, 489, 489, 489, 489,
- 489, 489, 489, nil, nil, nil, nil, nil, 489, 489,
- 489, 489, 489, 489, 489, nil, nil, 489, nil, nil,
- nil, nil, nil, nil, 489, nil, nil, 489, 489, nil,
- 489, 489, 489, 489, 489, 489, 489, 489, 489, nil,
- 489, 489, nil, 489, 489, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 489, nil, nil, 489,
- nil, nil, 489, nil, nil, 489, nil, nil, nil, 489,
- nil, 489, nil, nil, nil, nil, nil, nil, nil, 489,
- nil, nil, nil, nil, 489, 489, 489, 489, 489, 489,
- nil, nil, nil, 489, 489, nil, nil, nil, 491, 491,
- 491, 489, 491, nil, 489, nil, 491, 491, nil, 489,
- 489, 491, nil, 491, 491, 491, 491, 491, 491, 491,
- nil, nil, nil, nil, nil, 491, 491, 491, 491, 491,
- 491, 491, nil, nil, 491, nil, nil, nil, nil, nil,
- nil, 491, nil, nil, 491, 491, nil, 491, 491, 491,
- 491, 491, nil, 491, 491, 491, nil, 491, 491, nil,
- 491, 491, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 491, nil, nil, 491, nil, nil, 491,
- nil, nil, 491, nil, nil, nil, nil, nil, 491, nil,
- nil, nil, nil, nil, nil, nil, 491, nil, nil, nil,
- nil, 491, 491, 491, 491, 491, 491, nil, nil, nil,
- 491, 491, nil, nil, nil, 506, 506, 506, 491, 506,
- nil, 491, nil, 506, 506, nil, 491, 491, 506, nil,
- 506, 506, 506, 506, 506, 506, 506, nil, nil, nil,
- nil, nil, 506, 506, 506, 506, 506, 506, 506, nil,
- nil, 506, nil, nil, nil, nil, nil, nil, 506, nil,
- nil, 506, 506, nil, 506, 506, 506, 506, 506, nil,
- 506, 506, 506, nil, 506, 506, nil, 506, 506, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 506, nil, nil, 506, nil, 506, 506, nil, nil, 506,
- nil, nil, nil, 506, nil, 506, nil, nil, nil, nil,
- nil, nil, nil, 506, nil, nil, nil, nil, 506, 506,
- 506, 506, 506, 506, nil, nil, nil, 506, 506, nil,
- nil, nil, nil, nil, nil, 506, nil, nil, 506, nil,
- nil, nil, nil, 506, 506, 512, 512, 512, 512, 512,
- nil, nil, nil, 512, 512, nil, nil, nil, 512, nil,
- 512, 512, 512, 512, 512, 512, 512, nil, nil, nil,
- nil, nil, 512, 512, 512, 512, 512, 512, 512, nil,
- nil, 512, nil, nil, nil, nil, nil, 512, 512, nil,
- 512, 512, 512, nil, 512, 512, 512, 512, 512, nil,
- 512, 512, 512, nil, 512, 512, nil, 512, 512, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 512, nil, nil, 512, nil, nil, 512, nil, nil, 512,
- nil, 512, nil, nil, nil, 512, nil, nil, nil, nil,
- nil, nil, nil, 512, nil, nil, nil, nil, 512, 512,
- 512, 512, 512, 512, nil, nil, nil, 512, 512, nil,
- nil, nil, nil, nil, 512, 512, nil, nil, 512, nil,
- nil, nil, nil, 512, 512, 518, 518, 518, nil, 518,
- nil, nil, nil, 518, 518, nil, nil, nil, 518, nil,
- 518, 518, 518, 518, 518, 518, 518, nil, nil, nil,
- nil, nil, 518, 518, 518, 518, 518, 518, 518, nil,
- nil, 518, nil, nil, nil, nil, nil, nil, 518, nil,
- nil, 518, 518, nil, 518, 518, 518, 518, 518, nil,
- 518, 518, 518, nil, 518, 518, 559, nil, 559, 559,
- 559, nil, 559, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 518, nil, nil, 518, nil, nil, 518, nil, nil, 518,
- nil, nil, nil, nil, nil, 559, nil, nil, nil, nil,
- nil, nil, nil, 559, 559, 559, 559, nil, 518, 518,
- 518, 518, 518, 518, nil, nil, nil, 518, 518, nil,
- nil, nil, 520, 520, 520, 518, 520, nil, 518, nil,
- 520, 520, nil, 518, 518, 520, nil, 520, 520, 520,
- 520, 520, 520, 520, nil, nil, nil, nil, nil, 520,
- 520, 520, 520, 520, 520, 520, nil, nil, 520, nil,
- nil, nil, nil, nil, nil, 520, nil, nil, 520, 520,
- nil, 520, 520, 520, 520, 520, 520, 520, 520, 520,
- nil, 520, 520, nil, 520, 520, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 520, nil, nil,
- 520, nil, nil, 520, nil, nil, 520, nil, 520, nil,
- nil, nil, 520, nil, nil, nil, nil, nil, nil, nil,
- 520, nil, nil, nil, nil, 520, 520, 520, 520, 520,
- 520, nil, nil, nil, 520, 520, nil, nil, nil, 523,
- 523, 523, 520, 523, nil, 520, nil, 523, 523, nil,
- 520, 520, 523, nil, 523, 523, 523, 523, 523, 523,
- 523, nil, nil, nil, nil, nil, 523, 523, 523, 523,
- 523, 523, 523, nil, nil, 523, nil, nil, nil, nil,
- nil, nil, 523, nil, nil, 523, 523, nil, 523, 523,
- 523, 523, 523, 523, 523, 523, 523, nil, 523, 523,
- nil, 523, 523, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 523, nil, nil, 523, nil, nil,
- 523, nil, nil, 523, nil, 523, nil, nil, nil, 523,
- nil, nil, nil, nil, nil, nil, nil, 523, nil, nil,
- nil, nil, 523, 523, 523, 523, 523, 523, nil, nil,
- nil, 523, 523, nil, nil, nil, 531, 531, 531, 523,
- 531, nil, 523, nil, 531, 531, nil, 523, 523, 531,
- nil, 531, 531, 531, 531, 531, 531, 531, nil, nil,
- nil, nil, nil, 531, 531, 531, 531, 531, 531, 531,
- nil, nil, 531, nil, nil, nil, nil, nil, nil, 531,
- nil, nil, 531, 531, nil, 531, 531, 531, 531, 531,
- nil, 531, 531, 531, nil, 531, 531, nil, 531, 531,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 531, nil, nil, 531, nil, nil, 531, nil, nil,
- 531, nil, nil, nil, nil, nil, 531, nil, nil, nil,
- nil, nil, nil, nil, 531, nil, nil, nil, nil, 531,
- 531, 531, 531, 531, 531, nil, nil, nil, 531, 531,
- nil, nil, nil, 532, 532, 532, 531, 532, nil, 531,
- nil, 532, 532, nil, 531, 531, 532, nil, 532, 532,
- 532, 532, 532, 532, 532, nil, nil, nil, nil, nil,
- 532, 532, 532, 532, 532, 532, 532, nil, nil, 532,
- nil, nil, nil, nil, nil, nil, 532, nil, nil, 532,
- 532, nil, 532, 532, 532, 532, 532, nil, 532, 532,
- 532, nil, 532, 532, nil, 532, 532, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 532, nil,
- nil, 532, nil, nil, 532, nil, nil, 532, nil, nil,
- nil, nil, nil, 532, nil, nil, nil, nil, nil, nil,
- nil, 532, nil, nil, nil, nil, 532, 532, 532, 532,
- 532, 532, nil, nil, nil, 532, 532, nil, nil, nil,
- 533, 533, 533, 532, 533, nil, 532, nil, 533, 533,
- nil, 532, 532, 533, nil, 533, 533, 533, 533, 533,
- 533, 533, nil, nil, nil, nil, nil, 533, 533, 533,
- 533, 533, 533, 533, nil, nil, 533, nil, nil, nil,
- nil, nil, nil, 533, nil, nil, 533, 533, nil, 533,
- 533, 533, 533, 533, nil, 533, 533, 533, nil, 533,
- 533, nil, 533, 533, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 533, nil, nil, 533, nil,
- nil, 533, nil, nil, 533, nil, nil, nil, nil, nil,
- 533, nil, nil, nil, nil, nil, nil, nil, 533, nil,
- nil, nil, nil, 533, 533, 533, 533, 533, 533, nil,
- nil, nil, 533, 533, nil, nil, nil, 537, 537, 537,
- 533, 537, nil, 533, nil, 537, 537, nil, 533, 533,
- 537, nil, 537, 537, 537, 537, 537, 537, 537, nil,
- nil, nil, nil, nil, 537, 537, 537, 537, 537, 537,
- 537, nil, nil, 537, nil, nil, nil, nil, nil, nil,
- 537, nil, nil, 537, 537, nil, 537, 537, 537, 537,
- 537, nil, 537, 537, 537, nil, 537, 537, nil, 537,
- 537, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 537, nil, nil, 537, nil, nil, 537, nil,
- nil, 537, nil, nil, nil, nil, nil, 537, nil, nil,
- nil, nil, nil, nil, nil, 537, nil, nil, nil, nil,
- 537, 537, 537, 537, 537, 537, nil, nil, nil, 537,
- 537, nil, nil, nil, 543, 543, 543, 537, 543, nil,
- 537, nil, 543, 543, nil, 537, 537, 543, nil, 543,
- 543, 543, 543, 543, 543, 543, nil, nil, nil, nil,
- nil, 543, 543, 543, 543, 543, 543, 543, nil, nil,
- 543, nil, nil, nil, nil, nil, nil, 543, nil, nil,
- 543, 543, nil, 543, 543, 543, 543, 543, 543, 543,
- 543, 543, nil, 543, 543, nil, 543, 543, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 543,
- nil, nil, 543, nil, nil, 543, nil, nil, 543, nil,
- 543, nil, nil, nil, 543, nil, nil, nil, nil, nil,
- nil, nil, 543, nil, nil, nil, nil, 543, 543, 543,
- 543, 543, 543, nil, nil, nil, 543, 543, nil, nil,
- nil, 546, 546, 546, 543, 546, nil, 543, nil, 546,
- 546, nil, 543, 543, 546, nil, 546, 546, 546, 546,
- 546, 546, 546, nil, nil, nil, nil, nil, 546, 546,
- 546, 546, 546, 546, 546, nil, nil, 546, nil, nil,
- nil, nil, nil, nil, 546, nil, nil, 546, 546, nil,
- 546, 546, 546, 546, 546, 546, 546, 546, 546, nil,
- 546, 546, nil, 546, 546, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 546, nil, nil, 546,
- nil, nil, 546, nil, nil, 546, nil, nil, nil, nil,
- nil, 546, nil, nil, nil, nil, nil, nil, nil, 546,
- nil, nil, nil, nil, 546, 546, 546, 546, 546, 546,
- nil, nil, nil, 546, 546, nil, nil, nil, nil, nil,
- nil, 546, nil, nil, 546, nil, nil, nil, nil, 546,
- 546, 551, 551, 551, 551, 551, nil, nil, nil, 551,
- 551, nil, nil, nil, 551, nil, 551, 551, 551, 551,
- 551, 551, 551, nil, nil, nil, nil, nil, 551, 551,
- 551, 551, 551, 551, 551, nil, nil, 551, nil, nil,
- nil, nil, nil, 551, 551, nil, 551, 551, 551, nil,
- 551, 551, 551, 551, 551, nil, 551, 551, 551, nil,
- 551, 551, nil, 551, 551, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 551, nil, nil, 551,
- nil, nil, 551, nil, nil, 551, nil, 551, nil, nil,
- nil, 551, nil, nil, nil, nil, nil, nil, nil, 551,
- nil, nil, nil, nil, 551, 551, 551, 551, 551, 551,
- nil, nil, nil, 551, 551, nil, nil, nil, nil, nil,
- nil, 551, nil, nil, 551, nil, nil, nil, nil, 551,
- 551, 552, 552, 552, 552, 552, nil, nil, nil, 552,
- 552, nil, nil, nil, 552, nil, 552, 552, 552, 552,
- 552, 552, 552, nil, nil, nil, nil, nil, 552, 552,
- 552, 552, 552, 552, 552, nil, nil, 552, nil, nil,
- nil, nil, nil, 552, 552, nil, 552, 552, 552, nil,
- 552, 552, 552, 552, 552, nil, 552, 552, 552, nil,
- 552, 552, nil, 552, 552, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 552, nil, nil, 552,
- nil, nil, 552, nil, nil, 552, nil, 552, nil, nil,
- nil, 552, nil, nil, nil, nil, nil, nil, nil, 552,
- nil, nil, nil, nil, 552, 552, 552, 552, 552, 552,
- nil, nil, nil, 552, 552, nil, nil, nil, 558, 558,
- 558, 552, 558, nil, 552, nil, 558, 558, nil, 552,
- 552, 558, nil, 558, 558, 558, 558, 558, 558, 558,
- nil, nil, nil, nil, nil, 558, 558, 558, 558, 558,
- 558, 558, nil, nil, 558, nil, nil, nil, nil, nil,
- nil, 558, nil, nil, 558, 558, nil, 558, 558, 558,
- 558, 558, nil, 558, 558, 558, nil, 558, 558, 856,
- nil, 856, 856, 856, 856, 856, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 856, nil, nil, nil, nil,
- nil, nil, nil, 558, nil, nil, 558, nil, nil, 558,
- nil, nil, 558, nil, nil, nil, nil, nil, 856, nil,
- nil, nil, nil, nil, nil, nil, 856, 856, 856, 856,
- nil, 558, 558, 558, 558, 558, 558, nil, nil, nil,
- 558, 558, nil, nil, nil, nil, nil, nil, 558, nil,
- nil, 558, nil, nil, nil, nil, 558, 558, 572, 572,
- 572, 572, 572, nil, nil, 856, 572, 572, nil, nil,
- nil, 572, nil, 572, 572, 572, 572, 572, 572, 572,
- nil, nil, nil, nil, nil, 572, 572, 572, 572, 572,
- 572, 572, nil, nil, 572, nil, nil, nil, nil, nil,
- 572, 572, nil, 572, 572, 572, nil, 572, 572, 572,
- 572, 572, nil, 572, 572, 572, nil, 572, 572, nil,
- 572, 572, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 572, nil, nil, 572, nil, nil, 572,
- nil, nil, 572, nil, 572, nil, nil, nil, 572, nil,
- nil, nil, nil, nil, nil, nil, 572, nil, nil, nil,
- nil, 572, 572, 572, 572, 572, 572, nil, nil, nil,
- 572, 572, nil, nil, nil, nil, nil, nil, 572, nil,
- nil, 572, nil, nil, nil, nil, 572, 572, 576, 576,
- 576, 576, 576, nil, nil, nil, 576, 576, nil, nil,
- nil, 576, nil, 576, 576, 576, 576, 576, 576, 576,
- nil, nil, nil, nil, nil, 576, 576, 576, 576, 576,
- 576, 576, nil, nil, 576, nil, nil, nil, nil, nil,
- 576, 576, nil, 576, 576, 576, nil, 576, 576, 576,
- 576, 576, nil, 576, 576, 576, nil, 576, 576, nil,
- 576, 576, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 576, nil, nil, 576, nil, nil, 576,
- nil, nil, 576, nil, 576, nil, nil, nil, 576, nil,
- nil, nil, nil, nil, nil, nil, 576, nil, nil, nil,
- nil, 576, 576, 576, 576, 576, 576, nil, nil, nil,
- 576, 576, nil, nil, nil, nil, nil, nil, 576, nil,
- nil, 576, nil, nil, nil, nil, 576, 576, 581, 581,
- 581, 581, 581, nil, nil, nil, 581, 581, nil, nil,
- nil, 581, nil, 581, 581, 581, 581, 581, 581, 581,
- nil, nil, nil, nil, nil, 581, 581, 581, 581, 581,
- 581, 581, nil, nil, 581, nil, nil, nil, nil, nil,
- 581, 581, nil, 581, 581, 581, nil, 581, 581, 581,
- 581, 581, nil, 581, 581, 581, nil, 581, 581, nil,
- 581, 581, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 581, nil, nil, 581, nil, nil, 581,
- nil, nil, 581, nil, 581, nil, nil, nil, 581, nil,
- nil, nil, nil, nil, nil, nil, 581, nil, nil, nil,
- nil, 581, 581, 581, 581, 581, 581, nil, nil, nil,
- 581, 581, nil, nil, nil, 583, 583, 583, 581, 583,
- nil, 581, nil, 583, 583, nil, 581, 581, 583, nil,
- 583, 583, 583, 583, 583, 583, 583, nil, nil, nil,
- nil, nil, 583, 583, 583, 583, 583, 583, 583, nil,
- nil, 583, nil, nil, nil, nil, nil, nil, 583, nil,
- nil, 583, 583, nil, 583, 583, 583, 583, 583, 583,
- 583, 583, 583, nil, 583, 583, nil, 583, 583, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 583, nil, nil, 583, nil, nil, 583, nil, nil, 583,
- nil, 583, nil, nil, nil, 583, nil, nil, nil, nil,
- nil, nil, nil, 583, nil, nil, nil, nil, 583, 583,
- 583, 583, 583, 583, nil, nil, nil, 583, 583, nil,
- nil, nil, 586, 586, 586, 583, 586, nil, 583, nil,
- 586, 586, nil, 583, 583, 586, nil, 586, 586, 586,
- 586, 586, 586, 586, nil, nil, nil, nil, nil, 586,
- 586, 586, 586, 586, 586, 586, nil, nil, 586, nil,
- nil, nil, nil, nil, nil, 586, nil, nil, 586, 586,
- nil, 586, 586, 586, 586, 586, 586, 586, 586, 586,
- nil, 586, 586, nil, 586, 586, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 586, nil, nil,
- 586, nil, nil, 586, nil, nil, 586, nil, 586, nil,
- nil, nil, 586, nil, nil, nil, nil, nil, nil, nil,
- 586, nil, nil, nil, nil, 586, 586, 586, 586, 586,
- 586, nil, nil, nil, 586, 586, nil, nil, nil, 592,
- 592, 592, 586, 592, nil, 586, nil, 592, 592, nil,
- 586, 586, 592, nil, 592, 592, 592, 592, 592, 592,
- 592, nil, nil, nil, nil, nil, 592, 592, 592, 592,
- 592, 592, 592, nil, nil, 592, nil, nil, nil, nil,
- nil, nil, 592, nil, nil, 592, 592, nil, 592, 592,
- 592, 592, 592, 592, 592, 592, 592, nil, 592, 592,
- nil, 592, 592, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 592, nil, nil, 592, nil, nil,
- 592, nil, nil, 592, nil, 592, nil, nil, nil, 592,
- nil, nil, nil, nil, nil, nil, nil, 592, nil, nil,
- nil, nil, 592, 592, 592, 592, 592, 592, nil, nil,
- nil, 592, 592, nil, nil, nil, 596, 596, 596, 592,
- 596, nil, 592, nil, 596, 596, nil, 592, 592, 596,
- nil, 596, 596, 596, 596, 596, 596, 596, nil, nil,
- nil, nil, nil, 596, 596, 596, 596, 596, 596, 596,
- nil, nil, 596, nil, nil, nil, nil, nil, nil, 596,
- nil, nil, 596, 596, nil, 596, 596, 596, 596, 596,
- nil, 596, 596, 596, nil, 596, 596, nil, 596, 596,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 596, nil, nil, 596, nil, nil, 596, nil, nil,
- 596, nil, nil, nil, nil, nil, 596, nil, nil, nil,
- nil, nil, nil, nil, 596, nil, nil, nil, nil, 596,
- 596, 596, 596, 596, 596, nil, nil, nil, 596, 596,
- nil, nil, nil, 598, 598, 598, 596, 598, nil, 596,
- nil, 598, 598, nil, 596, 596, 598, nil, 598, 598,
- 598, 598, 598, 598, 598, nil, nil, nil, nil, nil,
- 598, 598, 598, 598, 598, 598, 598, nil, nil, 598,
- nil, nil, nil, nil, nil, nil, 598, nil, nil, 598,
- 598, nil, 598, 598, 598, 598, 598, nil, 598, 598,
- 598, nil, 598, 598, nil, 598, 598, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 598, nil,
- nil, 598, nil, nil, 598, nil, nil, 598, nil, nil,
- nil, nil, nil, 598, nil, nil, nil, nil, nil, nil,
- nil, 598, nil, nil, nil, nil, 598, 598, 598, 598,
- 598, 598, nil, nil, nil, 598, 598, nil, nil, nil,
- 625, 625, 625, 598, 625, nil, 598, nil, 625, 625,
- nil, 598, 598, 625, nil, 625, 625, 625, 625, 625,
- 625, 625, nil, nil, nil, nil, nil, 625, 625, 625,
- 625, 625, 625, 625, nil, nil, 625, nil, nil, nil,
- nil, nil, nil, 625, nil, nil, 625, 625, nil, 625,
- 625, 625, 625, 625, nil, 625, 625, 625, nil, 625,
- 625, nil, 625, 625, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 625, nil, nil, 625, nil,
- nil, 625, nil, nil, 625, nil, nil, nil, nil, nil,
- 625, nil, nil, nil, nil, nil, nil, nil, 625, nil,
- nil, nil, nil, 625, 625, 625, 625, 625, 625, nil,
- nil, nil, 625, 625, nil, nil, nil, 627, 627, 627,
- 625, 627, nil, 625, nil, 627, 627, nil, 625, 625,
- 627, nil, 627, 627, 627, 627, 627, 627, 627, nil,
- nil, nil, nil, nil, 627, 627, 627, 627, 627, 627,
- 627, nil, nil, 627, nil, nil, nil, nil, nil, nil,
- 627, nil, nil, 627, 627, nil, 627, 627, 627, 627,
- 627, nil, 627, 627, 627, nil, 627, 627, nil, 627,
- 627, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 627, nil, nil, 627, nil, nil, 627, nil,
- nil, 627, nil, 627, nil, nil, nil, 627, nil, nil,
- nil, nil, nil, nil, nil, 627, nil, nil, nil, nil,
- 627, 627, 627, 627, 627, 627, nil, nil, nil, 627,
- 627, nil, nil, nil, 630, 630, 630, 627, 630, nil,
- 627, nil, 630, 630, nil, 627, 627, 630, nil, 630,
- 630, 630, 630, 630, 630, 630, nil, nil, nil, nil,
- nil, 630, 630, 630, 630, 630, 630, 630, nil, nil,
- 630, nil, nil, nil, nil, nil, nil, 630, nil, nil,
- 630, 630, nil, 630, 630, 630, 630, 630, nil, 630,
- 630, 630, nil, 630, 630, nil, 630, 630, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 630,
- nil, nil, 630, nil, nil, 630, nil, nil, 630, nil,
- nil, nil, nil, nil, 630, nil, nil, nil, nil, nil,
- nil, nil, 630, nil, nil, nil, nil, 630, 630, 630,
- 630, 630, 630, nil, nil, nil, 630, 630, nil, nil,
- nil, 631, 631, 631, 630, 631, nil, 630, nil, 631,
- 631, nil, 630, 630, 631, nil, 631, 631, 631, 631,
- 631, 631, 631, nil, nil, nil, nil, nil, 631, 631,
- 631, 631, 631, 631, 631, nil, nil, 631, nil, nil,
- nil, nil, nil, nil, 631, nil, nil, 631, 631, nil,
- 631, 631, 631, 631, 631, nil, 631, 631, 631, nil,
- 631, 631, nil, 631, 631, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 631, nil, nil, 631,
- nil, nil, 631, nil, nil, 631, nil, nil, nil, nil,
- nil, 631, nil, nil, nil, nil, nil, nil, nil, 631,
- nil, nil, nil, nil, 631, 631, 631, 631, 631, 631,
- nil, nil, nil, 631, 631, nil, nil, nil, 636, 636,
- 636, 631, 636, nil, 631, nil, 636, 636, nil, 631,
- 631, 636, nil, 636, 636, 636, 636, 636, 636, 636,
- nil, nil, nil, nil, nil, 636, 636, 636, 636, 636,
- 636, 636, nil, nil, 636, nil, nil, nil, nil, nil,
- nil, 636, nil, nil, 636, 636, nil, 636, 636, 636,
- 636, 636, nil, 636, 636, 636, nil, 636, 636, nil,
- 636, 636, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 636, nil, nil, 636, nil, nil, 636,
- nil, nil, 636, nil, nil, nil, nil, nil, 636, nil,
- nil, nil, nil, nil, nil, nil, 636, nil, nil, nil,
- nil, 636, 636, 636, 636, 636, 636, nil, nil, nil,
- 636, 636, nil, nil, nil, 639, 639, 639, 636, 639,
- nil, 636, nil, 639, 639, nil, 636, 636, 639, nil,
- 639, 639, 639, 639, 639, 639, 639, nil, nil, nil,
- nil, nil, 639, 639, 639, 639, 639, 639, 639, nil,
- nil, 639, nil, nil, nil, nil, nil, nil, 639, nil,
- nil, 639, 639, nil, 639, 639, 639, 639, 639, nil,
- 639, 639, 639, nil, 639, 639, nil, 639, 639, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 639, nil, nil, 639, nil, nil, 639, nil, nil, 639,
- nil, nil, nil, nil, nil, 639, nil, nil, nil, nil,
- nil, nil, nil, 639, nil, nil, nil, nil, 639, 639,
- 639, 639, 639, 639, nil, nil, nil, 639, 639, nil,
- nil, nil, 650, 650, 650, 639, 650, nil, 639, nil,
- 650, 650, nil, 639, 639, 650, nil, 650, 650, 650,
- 650, 650, 650, 650, nil, nil, nil, nil, nil, 650,
- 650, 650, 650, 650, 650, 650, nil, nil, 650, nil,
- nil, nil, nil, nil, nil, 650, nil, nil, 650, 650,
- nil, 650, 650, 650, 650, 650, nil, 650, 650, 650,
- nil, 650, 650, nil, 650, 650, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 650, nil, nil,
- 650, nil, nil, 650, nil, nil, 650, nil, nil, nil,
- nil, nil, 650, nil, nil, nil, nil, nil, nil, nil,
- 650, nil, nil, nil, nil, 650, 650, 650, 650, 650,
- 650, nil, nil, nil, 650, 650, nil, nil, nil, nil,
- nil, nil, 650, nil, nil, 650, nil, nil, nil, nil,
- 650, 650, 654, 654, 654, 654, 654, nil, nil, nil,
- 654, 654, nil, nil, nil, 654, nil, 654, 654, 654,
- 654, 654, 654, 654, nil, nil, nil, nil, nil, 654,
- 654, 654, 654, 654, 654, 654, nil, nil, 654, nil,
- nil, nil, nil, nil, 654, 654, nil, 654, 654, 654,
- nil, 654, 654, 654, 654, 654, nil, 654, 654, 654,
- nil, 654, 654, nil, 654, 654, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 654, nil, nil,
- 654, nil, nil, 654, nil, nil, 654, nil, 654, nil,
- nil, nil, 654, nil, nil, nil, nil, nil, nil, nil,
- 654, nil, nil, nil, nil, 654, 654, 654, 654, 654,
- 654, nil, nil, nil, 654, 654, nil, nil, nil, 658,
- 658, 658, 654, 658, nil, 654, nil, 658, 658, nil,
- 654, 654, 658, nil, 658, 658, 658, 658, 658, 658,
- 658, nil, nil, nil, nil, nil, 658, 658, 658, 658,
- 658, 658, 658, nil, nil, 658, nil, nil, nil, nil,
- nil, nil, 658, nil, nil, 658, 658, nil, 658, 658,
- 658, 658, 658, nil, 658, 658, 658, nil, 658, 658,
- nil, 658, 658, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 658, nil, nil, 658, nil, nil,
- 658, nil, nil, 658, nil, nil, nil, nil, nil, 658,
- nil, nil, nil, nil, nil, nil, nil, 658, nil, nil,
- nil, nil, 658, 658, 658, 658, 658, 658, nil, nil,
- nil, 658, 658, nil, nil, nil, nil, nil, nil, 658,
- nil, nil, 658, nil, nil, nil, nil, 658, 658, 667,
- 667, 667, 667, 667, nil, nil, nil, 667, 667, nil,
- nil, nil, 667, nil, 667, 667, 667, 667, 667, 667,
- 667, nil, nil, nil, nil, nil, 667, 667, 667, 667,
- 667, 667, 667, nil, nil, 667, nil, nil, nil, nil,
- nil, 667, 667, nil, 667, 667, 667, nil, 667, 667,
- 667, 667, 667, nil, 667, 667, 667, nil, 667, 667,
- nil, 667, 667, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 667, nil, nil, 667, nil, nil,
- 667, nil, nil, 667, nil, 667, nil, nil, nil, 667,
- nil, nil, nil, nil, nil, nil, nil, 667, nil, nil,
- nil, nil, 667, 667, 667, 667, 667, 667, nil, nil,
- nil, 667, 667, nil, nil, nil, 670, 670, 670, 667,
- 670, nil, 667, nil, 670, 670, nil, 667, 667, 670,
- nil, 670, 670, 670, 670, 670, 670, 670, nil, nil,
- nil, nil, nil, 670, 670, 670, 670, 670, 670, 670,
- nil, nil, 670, nil, nil, nil, nil, nil, nil, 670,
- nil, nil, 670, 670, nil, 670, 670, 670, 670, 670,
- 670, 670, 670, 670, nil, 670, 670, nil, 670, 670,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 670, nil, nil, 670, nil, nil, 670, nil, nil,
- 670, nil, 670, nil, 670, nil, 670, nil, nil, nil,
- nil, nil, nil, nil, 670, nil, nil, nil, nil, 670,
- 670, 670, 670, 670, 670, nil, nil, nil, 670, 670,
- nil, nil, nil, 671, 671, 671, 670, 671, nil, 670,
- nil, 671, 671, nil, 670, 670, 671, nil, 671, 671,
- 671, 671, 671, 671, 671, nil, nil, nil, nil, nil,
- 671, 671, 671, 671, 671, 671, 671, nil, nil, 671,
- nil, nil, nil, nil, nil, nil, 671, nil, nil, 671,
- 671, nil, 671, 671, 671, 671, 671, 671, 671, 671,
- 671, nil, 671, 671, nil, 671, 671, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 671, nil,
- nil, 671, nil, nil, 671, nil, nil, 671, nil, nil,
- nil, 671, nil, 671, nil, nil, nil, nil, nil, nil,
- nil, 671, nil, nil, nil, nil, 671, 671, 671, 671,
- 671, 671, nil, nil, nil, 671, 671, nil, nil, nil,
- nil, nil, nil, 671, nil, nil, 671, nil, nil, nil,
- nil, 671, 671, 677, 677, 677, 677, 677, nil, nil,
- nil, 677, 677, nil, nil, nil, 677, nil, 677, 677,
- 677, 677, 677, 677, 677, nil, nil, nil, nil, nil,
- 677, 677, 677, 677, 677, 677, 677, nil, nil, 677,
- nil, nil, nil, nil, nil, 677, 677, nil, 677, 677,
- 677, nil, 677, 677, 677, 677, 677, nil, 677, 677,
- 677, nil, 677, 677, nil, 677, 677, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 677, nil,
- nil, 677, nil, nil, 677, nil, nil, 677, nil, 677,
- nil, nil, nil, 677, nil, nil, nil, nil, nil, nil,
- nil, 677, nil, nil, nil, nil, 677, 677, 677, 677,
- 677, 677, nil, nil, nil, 677, 677, nil, nil, nil,
- nil, nil, nil, 677, nil, nil, 677, nil, nil, nil,
- nil, 677, 677, 678, 678, 678, 678, 678, nil, nil,
- nil, 678, 678, nil, nil, nil, 678, nil, 678, 678,
- 678, 678, 678, 678, 678, nil, nil, nil, nil, nil,
- 678, 678, 678, 678, 678, 678, 678, nil, nil, 678,
- nil, nil, nil, nil, nil, 678, 678, nil, 678, 678,
- 678, nil, 678, 678, 678, 678, 678, nil, 678, 678,
- 678, nil, 678, 678, nil, 678, 678, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 678, nil,
- nil, 678, nil, nil, 678, nil, nil, 678, nil, 678,
- nil, nil, nil, 678, nil, nil, nil, nil, nil, nil,
- nil, 678, nil, nil, nil, nil, 678, 678, 678, 678,
- 678, 678, nil, nil, nil, 678, 678, nil, nil, nil,
- 682, 682, 682, 678, 682, nil, 678, nil, 682, 682,
- nil, 678, 678, 682, nil, 682, 682, 682, 682, 682,
- 682, 682, nil, nil, nil, nil, nil, 682, 682, 682,
- 682, 682, 682, 682, nil, nil, 682, nil, nil, nil,
- nil, nil, nil, 682, nil, nil, 682, 682, nil, 682,
- 682, 682, 682, 682, nil, 682, 682, 682, nil, 682,
- 682, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 682, nil, nil, 682, nil,
- nil, 682, nil, nil, 682, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 682, 682, 682, 682, 682, 682, nil,
- nil, nil, 682, 682, nil, nil, nil, 694, 694, 694,
- 682, 694, nil, 682, nil, 694, 694, nil, 682, 682,
- 694, nil, 694, 694, 694, 694, 694, 694, 694, nil,
- nil, nil, nil, nil, 694, 694, 694, 694, 694, 694,
- 694, nil, nil, 694, nil, nil, nil, nil, nil, nil,
- 694, nil, nil, 694, 694, nil, 694, 694, 694, 694,
- 694, nil, 694, 694, 694, nil, 694, 694, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 694, nil, nil, 694, nil, nil, 694, nil,
- nil, 694, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 694, 694, 694, 694, 694, 694, nil, nil, nil, 694,
- 694, nil, nil, nil, 700, 700, 700, 694, 700, nil,
- 694, nil, 700, 700, nil, 694, 694, 700, nil, 700,
- 700, 700, 700, 700, 700, 700, nil, nil, nil, nil,
- nil, 700, 700, 700, 700, 700, 700, 700, nil, nil,
- 700, nil, nil, nil, nil, nil, nil, 700, nil, nil,
- 700, 700, nil, 700, 700, 700, 700, 700, nil, 700,
- 700, 700, nil, 700, 700, nil, 700, 700, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 700,
- nil, nil, 700, nil, nil, 700, nil, nil, 700, nil,
- 700, nil, nil, nil, 700, nil, nil, nil, nil, nil,
- nil, nil, 700, nil, nil, nil, nil, 700, 700, 700,
- 700, 700, 700, nil, nil, nil, 700, 700, nil, nil,
- nil, 731, 731, 731, 700, 731, nil, 700, nil, 731,
- 731, nil, 700, 700, 731, nil, 731, 731, 731, 731,
- 731, 731, 731, nil, nil, nil, nil, nil, 731, 731,
- 731, 731, 731, 731, 731, nil, nil, 731, nil, nil,
- nil, nil, nil, nil, 731, nil, nil, 731, 731, nil,
- 731, 731, 731, 731, 731, nil, 731, 731, 731, nil,
- 731, 731, nil, 731, 731, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 731, nil, nil, 731,
- nil, nil, 731, nil, nil, 731, nil, 731, nil, nil,
- nil, 731, nil, nil, nil, nil, nil, nil, nil, 731,
- nil, nil, nil, nil, 731, 731, 731, 731, 731, 731,
- nil, nil, nil, 731, 731, nil, nil, nil, 738, 738,
- 738, 731, 738, nil, 731, nil, 738, 738, nil, 731,
- 731, 738, nil, 738, 738, 738, 738, 738, 738, 738,
- nil, nil, nil, nil, nil, 738, 738, 738, 738, 738,
- 738, 738, nil, nil, 738, nil, nil, nil, nil, nil,
- nil, 738, nil, nil, 738, 738, nil, 738, 738, 738,
- 738, 738, nil, 738, 738, 738, nil, 738, 738, nil,
- 738, 738, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 738, nil, nil, 738, nil, nil, 738,
- nil, nil, 738, nil, nil, nil, nil, nil, 738, nil,
- nil, nil, nil, nil, nil, nil, 738, nil, nil, nil,
- nil, 738, 738, 738, 738, 738, 738, nil, nil, nil,
- 738, 738, nil, nil, nil, nil, nil, nil, 738, nil,
- nil, 738, nil, nil, nil, nil, 738, 738, 743, 743,
- 743, 743, 743, nil, nil, nil, 743, 743, nil, nil,
- nil, 743, nil, 743, 743, 743, 743, 743, 743, 743,
- nil, nil, nil, nil, nil, 743, 743, 743, 743, 743,
- 743, 743, nil, nil, 743, nil, nil, nil, nil, nil,
- 743, 743, nil, 743, 743, 743, nil, 743, 743, 743,
- 743, 743, nil, 743, 743, 743, nil, 743, 743, nil,
- 743, 743, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 743, nil, nil, 743, nil, nil, 743,
- nil, nil, 743, nil, 743, nil, nil, nil, 743, nil,
- nil, nil, nil, nil, nil, nil, 743, nil, nil, nil,
- nil, 743, 743, 743, 743, 743, 743, nil, nil, nil,
- 743, 743, nil, nil, nil, nil, nil, nil, 743, nil,
- nil, 743, nil, nil, nil, nil, 743, 743, 747, 747,
- 747, 747, 747, nil, nil, nil, 747, 747, nil, nil,
- nil, 747, nil, 747, 747, 747, 747, 747, 747, 747,
- nil, nil, nil, nil, nil, 747, 747, 747, 747, 747,
- 747, 747, nil, nil, 747, nil, nil, nil, nil, nil,
- 747, 747, nil, 747, 747, 747, nil, 747, 747, 747,
- 747, 747, nil, 747, 747, 747, nil, 747, 747, nil,
- 747, 747, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 747, nil, nil, 747, nil, nil, 747,
- nil, nil, 747, nil, 747, nil, nil, nil, 747, nil,
- nil, nil, nil, nil, nil, nil, 747, nil, nil, nil,
- nil, 747, 747, 747, 747, 747, 747, nil, nil, nil,
- 747, 747, nil, nil, nil, nil, nil, nil, 747, nil,
- nil, 747, nil, nil, nil, nil, 747, 747, 748, 748,
- 748, 748, 748, nil, nil, nil, 748, 748, nil, nil,
- nil, 748, nil, 748, 748, 748, 748, 748, 748, 748,
- nil, nil, nil, nil, nil, 748, 748, 748, 748, 748,
- 748, 748, nil, nil, 748, nil, nil, nil, nil, nil,
- 748, 748, nil, 748, 748, 748, nil, 748, 748, 748,
- 748, 748, nil, 748, 748, 748, nil, 748, 748, nil,
- 748, 748, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 748, nil, nil, 748, nil, nil, 748,
- nil, nil, 748, nil, 748, nil, nil, nil, 748, nil,
- nil, nil, nil, nil, nil, nil, 748, nil, nil, nil,
- nil, 748, 748, 748, 748, 748, 748, nil, nil, nil,
- 748, 748, nil, nil, nil, 755, 755, 755, 748, 755,
- nil, 748, nil, 755, 755, nil, 748, 748, 755, nil,
- 755, 755, 755, 755, 755, 755, 755, nil, nil, nil,
- nil, nil, 755, 755, 755, 755, 755, 755, 755, nil,
- nil, 755, nil, nil, nil, nil, nil, nil, 755, nil,
- nil, 755, 755, nil, 755, 755, 755, 755, 755, nil,
- 755, 755, 755, nil, 755, 755, nil, 755, 755, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 755, nil, nil, 755, nil, nil, 755, nil, nil, 755,
- nil, nil, nil, nil, nil, 755, nil, nil, nil, nil,
- nil, nil, nil, 755, nil, nil, nil, nil, 755, 755,
- 755, 755, 755, 755, nil, nil, nil, 755, 755, nil,
- nil, nil, nil, nil, nil, 755, nil, nil, 755, nil,
- nil, nil, nil, 755, 755, 769, 769, 769, 769, 769,
- nil, nil, nil, 769, 769, nil, nil, nil, 769, nil,
- 769, 769, 769, 769, 769, 769, 769, nil, nil, nil,
- nil, nil, 769, 769, 769, 769, 769, 769, 769, nil,
- nil, 769, nil, nil, nil, nil, nil, 769, 769, nil,
- 769, 769, 769, nil, 769, 769, 769, 769, 769, nil,
- 769, 769, 769, nil, 769, 769, nil, 769, 769, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 769, nil, nil, 769, nil, nil, 769, nil, nil, 769,
- nil, 769, nil, nil, nil, 769, nil, nil, nil, nil,
- nil, nil, nil, 769, nil, nil, nil, nil, 769, 769,
- 769, 769, 769, 769, nil, nil, nil, 769, 769, nil,
- nil, nil, 775, 775, 775, 769, 775, nil, 769, nil,
- 775, 775, nil, 769, 769, 775, nil, 775, 775, 775,
- 775, 775, 775, 775, nil, nil, nil, nil, nil, 775,
- 775, 775, 775, 775, 775, 775, nil, nil, 775, nil,
- nil, nil, nil, nil, nil, 775, nil, nil, 775, 775,
- nil, 775, 775, 775, 775, 775, nil, 775, 775, 775,
- nil, 775, 775, nil, 775, 775, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 775, nil, nil,
- 775, nil, nil, 775, nil, nil, 775, nil, nil, nil,
- nil, nil, 775, nil, nil, nil, nil, nil, nil, nil,
- 775, nil, nil, nil, nil, 775, 775, 775, 775, 775,
- 775, nil, nil, nil, 775, 775, nil, nil, nil, 776,
- 776, 776, 775, 776, nil, 775, nil, 776, 776, nil,
- 775, 775, 776, nil, 776, 776, 776, 776, 776, 776,
- 776, nil, nil, nil, nil, nil, 776, 776, 776, 776,
- 776, 776, 776, nil, nil, 776, nil, nil, nil, nil,
- nil, nil, 776, nil, nil, 776, 776, nil, 776, 776,
- 776, 776, 776, nil, 776, 776, 776, nil, 776, 776,
- nil, 776, 776, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 776, nil, nil, 776, nil, nil,
- 776, nil, nil, 776, nil, nil, nil, nil, nil, 776,
- nil, nil, nil, nil, nil, nil, nil, 776, nil, nil,
- nil, nil, 776, 776, 776, 776, 776, 776, nil, nil,
- nil, 776, 776, nil, nil, nil, 777, 777, 777, 776,
- 777, nil, 776, nil, 777, 777, nil, 776, 776, 777,
- nil, 777, 777, 777, 777, 777, 777, 777, nil, nil,
- nil, nil, nil, 777, 777, 777, 777, 777, 777, 777,
- nil, nil, 777, nil, nil, nil, nil, nil, nil, 777,
- nil, nil, 777, 777, nil, 777, 777, 777, 777, 777,
- nil, 777, 777, 777, nil, 777, 777, nil, 777, 777,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 777, nil, nil, 777, nil, nil, 777, nil, nil,
- 777, nil, nil, nil, nil, nil, 777, nil, nil, nil,
- nil, nil, nil, nil, 777, nil, nil, nil, nil, 777,
- 777, 777, 777, 777, 777, nil, nil, nil, 777, 777,
- nil, nil, nil, 788, 788, 788, 777, 788, nil, 777,
- nil, 788, 788, nil, 777, 777, 788, nil, 788, 788,
- 788, 788, 788, 788, 788, nil, nil, nil, nil, nil,
- 788, 788, 788, 788, 788, 788, 788, nil, nil, 788,
- nil, nil, nil, nil, nil, nil, 788, nil, nil, 788,
- 788, nil, 788, 788, 788, 788, 788, nil, 788, 788,
- 788, nil, 788, 788, nil, 788, 788, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 788, nil,
- nil, 788, nil, nil, 788, nil, nil, 788, nil, nil,
- nil, nil, nil, 788, nil, nil, nil, nil, nil, nil,
- nil, 788, nil, nil, nil, nil, 788, 788, 788, 788,
- 788, 788, nil, nil, nil, 788, 788, nil, nil, nil,
- 789, 789, 789, 788, 789, nil, 788, nil, 789, 789,
- nil, 788, 788, 789, nil, 789, 789, 789, 789, 789,
- 789, 789, nil, nil, nil, nil, nil, 789, 789, 789,
- 789, 789, 789, 789, nil, nil, 789, nil, nil, nil,
- nil, nil, nil, 789, nil, nil, 789, 789, nil, 789,
- 789, 789, 789, 789, nil, 789, 789, 789, nil, 789,
- 789, nil, 789, 789, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 789, nil, nil, 789, nil,
- nil, 789, nil, nil, 789, nil, nil, nil, nil, nil,
- 789, nil, nil, nil, nil, nil, nil, nil, 789, nil,
- nil, nil, nil, 789, 789, 789, 789, 789, 789, nil,
- nil, nil, 789, 789, nil, nil, nil, 790, 790, 790,
- 789, 790, nil, 789, nil, 790, 790, nil, 789, 789,
- 790, nil, 790, 790, 790, 790, 790, 790, 790, nil,
- nil, nil, nil, nil, 790, 790, 790, 790, 790, 790,
- 790, nil, nil, 790, nil, nil, nil, nil, nil, nil,
- 790, nil, nil, 790, 790, nil, 790, 790, 790, 790,
- 790, nil, 790, 790, 790, nil, 790, 790, nil, 790,
- 790, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 790, nil, nil, 790, nil, nil, 790, nil,
- nil, 790, nil, nil, nil, nil, nil, 790, nil, nil,
- nil, nil, nil, nil, nil, 790, nil, nil, nil, nil,
- 790, 790, 790, 790, 790, 790, nil, nil, nil, 790,
- 790, nil, nil, nil, 802, 802, 802, 790, 802, nil,
- 790, nil, 802, 802, nil, 790, 790, 802, nil, 802,
- 802, 802, 802, 802, 802, 802, nil, nil, nil, nil,
- nil, 802, 802, 802, 802, 802, 802, 802, nil, nil,
- 802, nil, nil, nil, nil, nil, nil, 802, nil, nil,
- 802, 802, nil, 802, 802, 802, 802, 802, nil, 802,
- 802, 802, nil, 802, 802, nil, 802, 802, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 802,
- nil, nil, 802, nil, nil, 802, nil, nil, 802, nil,
- 802, nil, nil, nil, 802, nil, nil, nil, nil, nil,
- nil, nil, 802, nil, nil, nil, nil, 802, 802, 802,
- 802, 802, 802, nil, nil, nil, 802, 802, nil, nil,
- nil, nil, nil, nil, 802, nil, nil, 802, nil, nil,
- nil, nil, 802, 802, 813, 813, 813, 813, 813, nil,
- nil, nil, 813, 813, nil, nil, nil, 813, nil, 813,
- 813, 813, 813, 813, 813, 813, nil, nil, nil, nil,
- nil, 813, 813, 813, 813, 813, 813, 813, nil, nil,
- 813, nil, nil, nil, nil, nil, 813, 813, nil, 813,
- 813, 813, nil, 813, 813, 813, 813, 813, nil, 813,
- 813, 813, nil, 813, 813, nil, 813, 813, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 813,
- nil, nil, 813, nil, nil, 813, nil, nil, 813, nil,
- 813, nil, nil, nil, 813, nil, nil, nil, nil, nil,
- nil, nil, 813, nil, nil, nil, nil, 813, 813, 813,
- 813, 813, 813, nil, nil, nil, 813, 813, nil, nil,
- nil, 832, 832, 832, 813, 832, nil, 813, nil, 832,
- 832, nil, 813, 813, 832, nil, 832, 832, 832, 832,
- 832, 832, 832, nil, nil, nil, nil, nil, 832, 832,
- 832, 832, 832, 832, 832, nil, nil, 832, nil, nil,
- nil, nil, nil, nil, 832, nil, nil, 832, 832, nil,
- 832, 832, 832, 832, 832, nil, 832, 832, 832, nil,
- 832, 832, nil, 832, 832, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 832, nil, nil, 832,
- nil, nil, 832, nil, nil, 832, nil, nil, nil, nil,
- nil, 832, nil, nil, nil, nil, nil, nil, nil, 832,
- nil, nil, nil, nil, 832, 832, 832, 832, 832, 832,
- nil, nil, nil, 832, 832, nil, nil, nil, nil, nil,
- nil, 832, nil, nil, 832, nil, nil, nil, nil, 832,
- 832, 834, 834, 834, 834, 834, nil, nil, nil, 834,
- 834, nil, nil, nil, 834, nil, 834, 834, 834, 834,
- 834, 834, 834, nil, nil, nil, nil, nil, 834, 834,
- 834, 834, 834, 834, 834, nil, nil, 834, nil, nil,
- nil, nil, nil, 834, 834, nil, 834, 834, 834, nil,
- 834, 834, 834, 834, 834, nil, 834, 834, 834, nil,
- 834, 834, nil, 834, 834, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 834, nil, nil, 834,
- nil, nil, 834, nil, nil, 834, nil, 834, nil, nil,
- nil, 834, nil, nil, nil, nil, nil, nil, nil, 834,
- nil, nil, nil, nil, 834, 834, 834, 834, 834, 834,
- nil, nil, nil, 834, 834, nil, nil, nil, nil, nil,
- nil, 834, nil, nil, 834, nil, nil, nil, nil, 834,
- 834, 835, 835, 835, 835, 835, nil, nil, nil, 835,
- 835, nil, nil, nil, 835, nil, 835, 835, 835, 835,
- 835, 835, 835, nil, nil, nil, nil, nil, 835, 835,
- 835, 835, 835, 835, 835, nil, nil, 835, nil, nil,
- nil, nil, nil, 835, 835, nil, 835, 835, 835, nil,
- 835, 835, 835, 835, 835, nil, 835, 835, 835, nil,
- 835, 835, nil, 835, 835, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 835, nil, nil, 835,
- nil, nil, 835, nil, nil, 835, nil, 835, nil, nil,
- nil, 835, nil, nil, nil, nil, nil, nil, nil, 835,
- nil, nil, nil, nil, 835, 835, 835, 835, 835, 835,
- nil, nil, nil, 835, 835, nil, nil, nil, 862, 862,
- 862, 835, 862, nil, 835, nil, 862, 862, nil, 835,
- 835, 862, nil, 862, 862, 862, 862, 862, 862, 862,
- nil, nil, nil, nil, nil, 862, 862, 862, 862, 862,
- 862, 862, nil, nil, 862, nil, nil, nil, nil, nil,
- nil, 862, nil, nil, 862, 862, nil, 862, 862, 862,
- 862, 862, nil, 862, 862, 862, nil, 862, 862, nil,
- 862, 862, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 862, nil, nil, 862, nil, nil, 862,
- nil, nil, 862, nil, nil, nil, nil, nil, 862, nil,
- nil, nil, nil, nil, nil, nil, 862, nil, nil, nil,
- nil, 862, 862, 862, 862, 862, 862, nil, nil, nil,
- 862, 862, nil, nil, nil, 876, 876, 876, 862, 876,
- nil, 862, nil, 876, 876, nil, 862, 862, 876, nil,
- 876, 876, 876, 876, 876, 876, 876, nil, nil, nil,
- nil, nil, 876, 876, 876, 876, 876, 876, 876, nil,
- nil, 876, nil, nil, nil, nil, nil, nil, 876, nil,
- nil, 876, 876, nil, 876, 876, 876, 876, 876, nil,
- 876, 876, 876, nil, 876, 876, nil, 876, 876, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 876, nil, nil, 876, nil, nil, 876, nil, nil, 876,
- nil, nil, nil, nil, nil, 876, nil, nil, nil, nil,
- nil, nil, nil, 876, nil, nil, nil, nil, 876, 876,
- 876, 876, 876, 876, nil, nil, nil, 876, 876, nil,
- nil, nil, 877, 877, 877, 876, 877, nil, 876, nil,
- 877, 877, nil, 876, 876, 877, nil, 877, 877, 877,
- 877, 877, 877, 877, nil, nil, nil, nil, nil, 877,
- 877, 877, 877, 877, 877, 877, nil, nil, 877, nil,
- nil, nil, nil, nil, nil, 877, nil, nil, 877, 877,
- nil, 877, 877, 877, 877, 877, nil, 877, 877, 877,
- nil, 877, 877, nil, 877, 877, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 877, nil, nil,
- 877, nil, nil, 877, nil, nil, 877, nil, nil, nil,
- nil, nil, 877, nil, nil, nil, nil, nil, nil, nil,
- 877, nil, nil, nil, nil, 877, 877, 877, 877, 877,
- 877, nil, nil, nil, 877, 877, nil, nil, nil, 881,
- 881, 881, 877, 881, nil, 877, nil, 881, 881, nil,
- 877, 877, 881, nil, 881, 881, 881, 881, 881, 881,
- 881, nil, nil, nil, nil, nil, 881, 881, 881, 881,
- 881, 881, 881, nil, nil, 881, nil, nil, nil, nil,
- nil, nil, 881, nil, nil, 881, 881, nil, 881, 881,
- 881, 881, 881, 881, 881, 881, 881, nil, 881, 881,
- nil, 881, 881, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 881, nil, nil, 881, nil, nil,
- 881, nil, nil, 881, nil, nil, nil, 881, nil, 881,
- nil, nil, nil, nil, nil, nil, nil, 881, nil, nil,
- nil, nil, 881, 881, 881, 881, 881, 881, nil, nil,
- nil, 881, 881, nil, nil, nil, nil, nil, nil, 881,
- nil, nil, 881, nil, nil, nil, nil, 881, 881, 886,
- 886, 886, 886, 886, nil, nil, nil, 886, 886, nil,
- nil, nil, 886, nil, 886, 886, 886, 886, 886, 886,
- 886, nil, nil, nil, nil, nil, 886, 886, 886, 886,
- 886, 886, 886, nil, nil, 886, nil, nil, nil, nil,
- nil, 886, 886, nil, 886, 886, 886, nil, 886, 886,
- 886, 886, 886, nil, 886, 886, 886, nil, 886, 886,
- nil, 886, 886, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 886, nil, nil, 886, nil, nil,
- 886, nil, nil, 886, nil, 886, nil, nil, nil, 886,
- nil, nil, nil, nil, nil, nil, nil, 886, nil, nil,
- nil, nil, 886, 886, 886, 886, 886, 886, nil, nil,
- nil, 886, 886, nil, nil, nil, 890, 890, 890, 886,
- 890, nil, 886, nil, 890, 890, nil, 886, 886, 890,
- nil, 890, 890, 890, 890, 890, 890, 890, nil, nil,
- nil, nil, nil, 890, 890, 890, 890, 890, 890, 890,
- nil, nil, 890, nil, nil, nil, nil, nil, nil, 890,
- nil, nil, 890, 890, nil, 890, 890, 890, 890, 890,
- nil, 890, 890, 890, nil, 890, 890, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 890, nil, nil, 890, nil, nil, 890, nil, nil,
- 890, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 890,
- 890, 890, 890, 890, 890, nil, nil, nil, 890, 890,
- nil, nil, nil, 900, 900, 900, 890, 900, nil, 890,
- nil, 900, 900, nil, 890, 890, 900, nil, 900, 900,
- 900, 900, 900, 900, 900, nil, nil, nil, nil, nil,
- 900, 900, 900, 900, 900, 900, 900, nil, nil, 900,
- nil, nil, nil, nil, nil, nil, 900, nil, nil, 900,
- 900, nil, 900, 900, 900, 900, 900, nil, 900, 900,
- 900, nil, 900, 900, nil, 900, 900, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 900, nil,
- nil, 900, nil, nil, 900, nil, nil, 900, nil, 900,
- nil, nil, nil, 900, nil, nil, nil, nil, nil, nil,
- nil, 900, nil, nil, nil, nil, 900, 900, 900, 900,
- 900, 900, nil, nil, nil, 900, 900, nil, nil, nil,
- nil, nil, nil, 900, nil, nil, 900, nil, nil, nil,
- nil, 900, 900, 901, 901, 901, 901, 901, nil, nil,
- nil, 901, 901, nil, nil, nil, 901, nil, 901, 901,
- 901, 901, 901, 901, 901, nil, nil, nil, nil, nil,
- 901, 901, 901, 901, 901, 901, 901, nil, nil, 901,
- nil, nil, nil, nil, nil, 901, 901, nil, 901, 901,
- 901, nil, 901, 901, 901, 901, 901, nil, 901, 901,
- 901, nil, 901, 901, nil, 901, 901, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 901, nil,
- nil, 901, nil, nil, 901, nil, nil, 901, nil, 901,
- nil, nil, nil, 901, nil, nil, nil, nil, nil, nil,
- nil, 901, nil, nil, nil, nil, 901, 901, 901, 901,
- 901, 901, nil, nil, nil, 901, 901, nil, nil, nil,
- nil, nil, nil, 901, nil, nil, 901, nil, nil, nil,
- nil, 901, 901, 904, 904, 904, 904, 904, nil, nil,
- nil, 904, 904, nil, nil, nil, 904, nil, 904, 904,
- 904, 904, 904, 904, 904, nil, nil, nil, nil, nil,
- 904, 904, 904, 904, 904, 904, 904, nil, nil, 904,
- nil, nil, nil, nil, nil, 904, 904, nil, 904, 904,
- 904, nil, 904, 904, 904, 904, 904, nil, 904, 904,
- 904, nil, 904, 904, nil, 904, 904, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 904, nil,
- nil, 904, nil, nil, 904, nil, nil, 904, nil, 904,
- nil, nil, nil, 904, nil, nil, nil, nil, nil, nil,
- nil, 904, nil, nil, nil, nil, 904, 904, 904, 904,
- 904, 904, nil, nil, nil, 904, 904, nil, nil, nil,
- 921, 921, 921, 904, 921, nil, 904, nil, 921, 921,
- nil, 904, 904, 921, nil, 921, 921, 921, 921, 921,
- 921, 921, nil, nil, nil, nil, nil, 921, 921, 921,
- 921, 921, 921, 921, nil, nil, 921, nil, nil, nil,
- nil, nil, nil, 921, nil, nil, 921, 921, nil, 921,
- 921, 921, 921, 921, nil, 921, 921, 921, nil, 921,
- 921, nil, 921, 921, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 921, nil, nil, 921, nil,
- nil, 921, nil, nil, 921, nil, 921, nil, 921, nil,
- 921, nil, nil, nil, nil, nil, nil, nil, 921, nil,
- nil, nil, nil, 921, 921, 921, 921, 921, 921, nil,
- nil, nil, 921, 921, nil, nil, nil, nil, nil, nil,
- 921, nil, nil, 921, nil, nil, nil, nil, 921, 921,
- 923, 923, 923, 923, 923, nil, nil, nil, 923, 923,
- nil, nil, nil, 923, nil, 923, 923, 923, 923, 923,
- 923, 923, nil, nil, nil, nil, nil, 923, 923, 923,
- 923, 923, 923, 923, nil, nil, 923, nil, nil, nil,
- nil, nil, 923, 923, nil, 923, 923, 923, nil, 923,
- 923, 923, 923, 923, nil, 923, 923, 923, nil, 923,
- 923, nil, 923, 923, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 923, nil, nil, 923, nil,
- nil, 923, nil, nil, 923, nil, 923, nil, nil, nil,
- 923, nil, nil, nil, nil, nil, nil, nil, 923, nil,
- nil, nil, nil, 923, 923, 923, 923, 923, 923, nil,
- nil, nil, 923, 923, nil, nil, nil, nil, nil, nil,
- 923, nil, nil, 923, nil, nil, nil, nil, 923, 923,
- 930, 930, 930, 930, 930, nil, nil, nil, 930, 930,
- nil, nil, nil, 930, nil, 930, 930, 930, 930, 930,
- 930, 930, nil, nil, nil, nil, nil, 930, 930, 930,
- 930, 930, 930, 930, nil, nil, 930, nil, nil, nil,
- nil, nil, 930, 930, nil, 930, 930, 930, nil, 930,
- 930, 930, 930, 930, nil, 930, 930, 930, nil, 930,
- 930, nil, 930, 930, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 930, nil, nil, 930, nil,
- nil, 930, nil, nil, 930, nil, 930, nil, nil, nil,
- 930, nil, nil, nil, nil, nil, nil, nil, 930, nil,
- nil, nil, nil, 930, 930, 930, 930, 930, 930, nil,
- nil, nil, 930, 930, nil, nil, nil, nil, nil, nil,
- 930, nil, nil, 930, nil, nil, nil, nil, 930, 930,
- 935, 935, 935, 935, 935, nil, nil, nil, 935, 935,
- nil, nil, nil, 935, nil, 935, 935, 935, 935, 935,
- 935, 935, nil, nil, nil, nil, nil, 935, 935, 935,
- 935, 935, 935, 935, nil, nil, 935, nil, nil, nil,
- nil, nil, 935, 935, nil, 935, 935, 935, nil, 935,
- 935, 935, 935, 935, nil, 935, 935, 935, nil, 935,
- 935, nil, 935, 935, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 935, nil, nil, 935, nil,
- nil, 935, nil, nil, 935, nil, 935, nil, nil, nil,
- 935, nil, nil, nil, nil, nil, nil, nil, 935, nil,
- nil, nil, nil, 935, 935, 935, 935, 935, 935, nil,
- nil, nil, 935, 935, nil, nil, nil, nil, nil, nil,
- 935, nil, nil, 935, nil, nil, nil, nil, 935, 935,
- 943, 943, 943, 943, 943, nil, nil, nil, 943, 943,
- nil, nil, nil, 943, nil, 943, 943, 943, 943, 943,
- 943, 943, nil, nil, nil, nil, nil, 943, 943, 943,
- 943, 943, 943, 943, nil, nil, 943, nil, nil, nil,
- nil, nil, 943, 943, nil, 943, 943, 943, nil, 943,
- 943, 943, 943, 943, nil, 943, 943, 943, nil, 943,
- 943, nil, 943, 943, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 943, nil, nil, 943, nil,
- nil, 943, nil, nil, 943, nil, 943, nil, nil, nil,
- 943, nil, nil, nil, nil, nil, nil, nil, 943, nil,
- nil, nil, nil, 943, 943, 943, 943, 943, 943, nil,
- nil, nil, 943, 943, nil, nil, nil, 945, 945, 945,
- 943, 945, nil, 943, nil, 945, 945, nil, 943, 943,
- 945, nil, 945, 945, 945, 945, 945, 945, 945, nil,
- nil, nil, nil, nil, 945, 945, 945, 945, 945, 945,
- 945, nil, nil, 945, nil, nil, nil, nil, nil, nil,
- 945, nil, nil, 945, 945, nil, 945, 945, 945, 945,
- 945, 945, 945, 945, 945, nil, 945, 945, nil, 945,
- 945, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 945, nil, nil, 945, nil, nil, 945, nil,
- nil, 945, nil, 945, nil, nil, nil, 945, nil, nil,
- nil, nil, nil, nil, nil, 945, nil, nil, nil, 436,
- 945, 945, 945, 945, 945, 945, 436, 436, 436, 945,
- 945, nil, 436, 436, nil, 436, nil, 945, nil, nil,
- 945, nil, nil, nil, 436, 945, 945, nil, nil, nil,
- nil, nil, nil, nil, nil, 436, 436, nil, 436, 436,
- 436, 436, 436, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 436, 436, 436, 436,
- 436, 436, 436, 436, 436, 436, 436, 436, 436, 436,
- 436, 438, nil, 436, 436, 436, nil, 436, 438, 438,
- 438, 436, nil, nil, 438, 438, nil, 438, 436, nil,
- 436, nil, 436, 436, 436, 436, 436, 436, 436, nil,
- 436, 436, 436, nil, nil, nil, nil, 438, 438, nil,
- 438, 438, 438, 438, 438, 436, 436, nil, 436, nil,
- 436, nil, nil, 436, nil, 436, nil, 436, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 438, 438,
- 438, 438, 438, 438, 438, 438, 438, 438, 438, 438,
- 438, 438, 438, nil, nil, 438, 438, 438, nil, 438,
- nil, nil, nil, 438, nil, nil, nil, nil, nil, nil,
- 438, nil, 438, nil, 438, 438, 438, 438, 438, 438,
- 438, nil, 438, nil, 438, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 438, 438, nil,
- 438, nil, 438, 644, nil, 438, nil, 438, nil, 438,
- 644, 644, 644, nil, nil, 644, 644, 644, nil, 644,
- nil, nil, nil, nil, nil, nil, nil, nil, 644, 644,
- 644, nil, nil, nil, nil, nil, nil, nil, nil, 644,
- 644, nil, 644, 644, 644, 644, 644, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 644, 644, 644, 644, 644, 644, 644, 644, 644, 644,
- 644, 644, 644, 644, 644, nil, nil, 644, 644, 644,
- nil, 644, 644, nil, nil, 644, nil, nil, 644, nil,
- 644, nil, 644, nil, 644, nil, 644, 644, 644, 644,
- 644, 644, 644, nil, 644, 644, 644, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 644,
- 644, 644, 644, nil, 644, 645, nil, 644, nil, 644,
- nil, 644, 645, 645, 645, nil, nil, 645, 645, 645,
- nil, 645, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 645, 645, nil, nil, nil, nil, nil, nil, nil,
- nil, 645, 645, nil, 645, 645, 645, 645, 645, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 645, 645, 645, 645, 645, 645, 645, 645,
- 645, 645, 645, 645, 645, 645, 645, nil, nil, 645,
- 645, 645, nil, 645, 645, nil, nil, 645, nil, nil,
- 645, nil, 645, nil, 645, nil, 645, nil, 645, 645,
- 645, 645, 645, 645, 645, nil, 645, nil, 645, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 645, 645, 645, 645, nil, 645, 28, nil, 645,
- nil, 645, nil, 645, 28, 28, 28, nil, nil, 28,
- 28, 28, nil, 28, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 28, 28, nil, nil, nil, nil, nil,
- nil, nil, nil, 28, 28, nil, 28, 28, 28, 28,
- 28, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 28, 28, 28, 28, 28, 28,
- 28, 28, 28, 28, 28, 28, 28, 28, 28, nil,
- nil, 28, 28, 28, nil, nil, 28, nil, 28, 28,
- nil, nil, 28, nil, 28, nil, 28, nil, 28, nil,
- 28, 28, 28, 28, 28, 28, 28, nil, 28, nil,
- 28, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 28, 28, 28, 28, 50, 28, nil,
- nil, 28, nil, 28, 50, 50, 50, nil, nil, 50,
- 50, 50, nil, 50, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 50, 50, 50, nil, nil, nil, nil,
- nil, nil, nil, 50, 50, nil, 50, 50, 50, 50,
- 50, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 50, 50, 50, 50, 50, 50,
- 50, 50, 50, 50, 50, 50, 50, 50, 50, nil,
- nil, 50, 50, 50, nil, nil, 50, nil, nil, 50,
- nil, nil, 50, nil, 50, nil, 50, nil, 50, nil,
- 50, 50, 50, 50, 50, 50, 50, nil, 50, nil,
- 50, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 50, 50, 50, 50, 494, 50, nil,
- 50, 50, nil, 50, 494, 494, 494, nil, nil, 494,
- 494, 494, nil, 494, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 494, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 494, 494, nil, 494, 494, 494, 494,
- 494, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 495, nil, nil, nil, nil, nil,
- nil, 495, 495, 495, nil, nil, 495, 495, 495, nil,
- 495, nil, nil, nil, nil, 494, 494, nil, nil, nil,
- 495, nil, nil, 494, nil, nil, nil, nil, 494, 494,
- 495, 495, nil, 495, 495, 495, 495, 495, nil, nil,
- nil, nil, 918, nil, 918, 918, 918, 918, 918, nil,
- 494, nil, nil, nil, nil, nil, nil, nil, 918, nil,
- nil, nil, 496, 494, nil, 494, nil, nil, 494, 496,
- 496, 496, 495, 495, 496, 496, 496, nil, 496, nil,
- 495, 918, 918, nil, nil, 495, 495, nil, 496, 918,
- 918, 918, 918, nil, nil, nil, nil, nil, 496, 496,
- nil, 496, 496, 496, 496, 496, nil, 495, nil, nil,
- nil, nil, nil, 202, 202, nil, nil, 202, nil, nil,
- 495, nil, 495, nil, nil, 495, 202, 202, 918, 202,
- 202, 202, 202, 202, 202, 202, nil, nil, 202, 202,
- 496, 496, nil, nil, 202, 202, 202, 202, 496, nil,
- nil, nil, nil, 496, 496, nil, nil, nil, nil, nil,
- 202, 202, nil, 202, 202, 202, 202, 202, 202, 202,
- 202, 202, 202, 202, nil, 496, 202, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 496, nil,
- 496, nil, nil, 496, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, nil, nil,
- nil, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, nil, 7, 7, 7, nil, 7, nil, nil,
- nil, nil, nil, nil, nil, nil, 7, 7, nil, 7,
- 7, 7, 7, 7, 7, 7, nil, nil, 7, 7,
- nil, nil, nil, nil, 7, 7, 7, 7, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 7, 7, nil, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, nil, nil, 7, 7, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 7, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, nil, nil, nil, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, nil, 8, 8, nil,
- nil, 8, nil, nil, nil, nil, nil, nil, nil, nil,
- 8, 8, nil, 8, 8, 8, 8, 8, 8, 8,
- nil, nil, 8, 8, nil, nil, nil, nil, 8, 8,
- 8, 8, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 8, 8, nil, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, nil, nil,
- 8, 8, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 8, 411, 411, 411, 411, 411, 411, 411, 411,
- 411, 411, 411, 411, 411, 411, 411, 411, 411, 411,
- 411, 411, 411, 411, 411, 411, nil, nil, nil, 411,
- 411, 411, 411, 411, 411, 411, 411, 411, 411, 411,
- 411, 411, 411, 411, 411, 411, 411, 411, 411, 411,
- nil, 411, 411, nil, nil, 411, nil, nil, nil, nil,
- nil, nil, nil, nil, 411, 411, nil, 411, 411, 411,
- 411, 411, 411, 411, nil, nil, 411, 411, nil, nil,
- nil, nil, 411, 411, 411, 411, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 411, 411,
- nil, 411, 411, 411, 411, 411, 411, 411, 411, 411,
- 411, 411, nil, nil, 411, 411, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 411, 415, 415, 415, 415,
- 415, 415, 415, 415, 415, 415, 415, 415, 415, 415,
- 415, 415, 415, 415, 415, 415, 415, 415, 415, 415,
- nil, nil, nil, 415, 415, 415, 415, 415, 415, 415,
- 415, 415, 415, 415, 415, 415, 415, 415, 415, 415,
- 415, 415, 415, 415, nil, 415, 415, nil, nil, 415,
- nil, nil, nil, nil, nil, nil, nil, nil, 415, 415,
- nil, 415, 415, 415, 415, 415, 415, 415, nil, nil,
- 415, 415, nil, nil, nil, nil, 415, 415, 415, 415,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 415, 415, nil, 415, 415, 415, 415, 415,
- 415, 415, 415, 415, 415, 415, nil, nil, 415, 415,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 415,
- 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
- 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
- 65, 65, 65, 65, nil, nil, nil, 65, 65, 65,
- 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
- 65, 65, 65, 65, 65, 65, 65, 65, nil, 65,
- 65, 65, 65, 65, nil, 65, nil, nil, nil, nil,
- nil, nil, 65, 65, nil, 65, 65, 65, 65, 65,
- 65, 65, nil, nil, 65, 65, nil, nil, nil, nil,
- 65, 65, 65, 65, nil, nil, nil, nil, nil, 65,
- nil, nil, nil, nil, nil, nil, 65, 65, nil, 65,
- 65, 65, 65, 65, 65, 65, 65, 65, 65, 65,
- nil, nil, 65, 79, 79, 79, 79, 79, 79, 79,
- 79, 79, 79, 79, 79, 79, 79, 79, 79, 79,
- 79, 79, 79, 79, 79, 79, 79, nil, nil, nil,
- 79, 79, 79, 79, 79, 79, 79, 79, 79, 79,
- 79, 79, 79, 79, 79, 79, 79, 79, 79, 79,
- 79, nil, 79, 79, 79, 79, 79, nil, 79, nil,
- nil, nil, nil, nil, nil, 79, 79, nil, 79, 79,
- 79, 79, 79, 79, 79, nil, nil, 79, 79, nil,
- nil, nil, nil, 79, 79, 79, 79, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 79,
- 79, nil, 79, 79, 79, 79, 79, 79, 79, 79,
- 79, 79, 79, nil, nil, 79, 192, 192, 192, 192,
- 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
- 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
- nil, nil, nil, 192, 192, 192, 192, 192, 192, 192,
- 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
- 192, 192, 192, 192, nil, 192, 192, 192, 192, 192,
- nil, 192, nil, nil, nil, nil, nil, nil, 192, 192,
- nil, 192, 192, 192, 192, 192, 192, 192, nil, nil,
- 192, 192, nil, nil, nil, nil, 192, 192, 192, 192,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 192, 192, nil, 192, 192, 192, 192, 192,
- 192, 192, 192, 192, 192, 192, nil, nil, 192, 766,
- 766, 766, 766, 766, 766, 766, 766, 766, 766, 766,
- 766, 766, 766, 766, 766, 766, 766, 766, 766, 766,
- 766, 766, 766, nil, nil, nil, 766, 766, 766, 766,
- 766, 766, 766, 766, 766, 766, 766, 766, 766, 766,
- 766, 766, 766, 766, 766, 766, 766, nil, 766, 766,
- nil, nil, 766, nil, nil, nil, nil, nil, nil, nil,
- nil, 766, 766, nil, 766, 766, 766, 766, 766, 766,
- 766, nil, nil, 766, 766, nil, nil, nil, nil, 766,
- 766, 766, 766, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 766, 766, nil, 766, 766,
- 766, 766, 766, 766, 766, 766, 766, 766, 766, 201,
- 201, 766, nil, 201, nil, nil, nil, nil, nil, nil,
- nil, nil, 201, 201, nil, 201, 201, 201, 201, 201,
- 201, 201, nil, nil, 201, 201, nil, nil, nil, nil,
- 201, 201, 201, 201, nil, nil, nil, nil, nil, 201,
- nil, nil, nil, nil, nil, nil, 201, 201, nil, 201,
- 201, 201, 201, 201, 201, 201, 201, 201, 201, 201,
- 203, 203, 201, nil, 203, nil, nil, nil, nil, nil,
- nil, nil, nil, 203, 203, nil, 203, 203, 203, 203,
- 203, 203, 203, nil, nil, 203, 203, nil, nil, nil,
- nil, 203, 203, 203, 203, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 203, 203, nil,
- 203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
- 203, 264, 264, 203, nil, 264, nil, nil, nil, nil,
- nil, nil, nil, nil, 264, 264, nil, 264, 264, 264,
- 264, 264, 264, 264, nil, nil, 264, 264, nil, nil,
- nil, nil, 264, 264, 264, 264, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 264, 264,
- nil, 264, 264, 264, 264, 264, 264, 264, 264, 264,
- 264, 264, 265, 265, 264, nil, 265, nil, nil, nil,
- nil, nil, nil, nil, nil, 265, 265, nil, 265, 265,
- 265, 265, 265, 265, 265, nil, nil, 265, 265, nil,
- nil, nil, nil, 265, 265, 265, 265, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 265,
- 265, nil, 265, 265, 265, 265, 265, 265, 265, 265,
- 265, 265, 265, 266, 266, 265, nil, 266, nil, nil,
- nil, nil, nil, nil, nil, nil, 266, 266, nil, 266,
- 266, 266, 266, 266, 266, 266, nil, nil, 266, 266,
- nil, nil, nil, nil, 266, 266, 266, 266, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 266, 266, nil, 266, 266, 266, 266, 266, 266, 266,
- 266, 266, 266, 266, 449, 449, 266, nil, 449, nil,
- nil, nil, nil, nil, nil, nil, nil, 449, 449, nil,
- 449, 449, 449, 449, 449, 449, 449, nil, nil, 449,
- 449, nil, nil, nil, nil, 449, 449, 449, 449, nil,
- nil, nil, nil, nil, 449, nil, nil, nil, nil, nil,
- nil, 449, 449, nil, 449, 449, 449, 449, 449, 449,
- 449, 449, 449, 449, 449, 450, 450, 449, nil, 450,
- nil, nil, nil, nil, nil, nil, nil, nil, 450, 450,
- nil, 450, 450, 450, 450, 450, 450, 450, nil, nil,
- 450, 450, nil, nil, nil, nil, 450, 450, 450, 450,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 450, 450, nil, 450, 450, 450, 450, 450,
- 450, 450, 450, 450, 450, 450, 521, 521, 450, nil,
- 521, nil, nil, nil, nil, nil, nil, nil, nil, 521,
- 521, nil, 521, 521, 521, 521, 521, 521, 521, nil,
- nil, 521, 521, nil, nil, nil, nil, 521, 521, 521,
- 521, nil, nil, nil, nil, nil, 521, nil, nil, nil,
- nil, nil, nil, 521, 521, nil, 521, 521, 521, 521,
- 521, 521, 521, 521, 521, 521, 521, 522, 522, 521,
- nil, 522, nil, nil, nil, nil, nil, nil, nil, nil,
- 522, 522, nil, 522, 522, 522, 522, 522, 522, 522,
- nil, nil, 522, 522, nil, nil, nil, nil, 522, 522,
- 522, 522, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 522, 522, nil, 522, 522, 522,
- 522, 522, 522, 522, 522, 522, 522, 522, 524, 524,
- 522, nil, 524, nil, nil, nil, nil, nil, nil, nil,
- nil, 524, 524, nil, 524, 524, 524, 524, 524, 524,
- 524, nil, nil, 524, 524, nil, nil, nil, nil, 524,
- 524, 524, 524, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 524, 524, nil, 524, 524,
- 524, 524, 524, 524, 524, 524, 524, 524, 524, 534,
- 534, 524, nil, 534, nil, nil, nil, nil, nil, nil,
- nil, nil, 534, 534, nil, 534, 534, 534, 534, 534,
- 534, 534, nil, nil, 534, 534, nil, nil, nil, nil,
- 534, 534, 534, 534, nil, nil, nil, nil, nil, 534,
- nil, nil, nil, nil, nil, nil, 534, 534, nil, 534,
- 534, 534, 534, 534, 534, 534, 534, 534, 534, 534,
- 535, 535, 534, nil, 535, nil, nil, nil, nil, nil,
- nil, nil, nil, 535, 535, nil, 535, 535, 535, 535,
- 535, 535, 535, nil, nil, 535, 535, nil, nil, nil,
- nil, 535, 535, 535, 535, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 535, 535, nil,
- 535, 535, 535, 535, 535, 535, 535, 535, 535, 535,
- 535, 584, 584, 535, nil, 584, nil, nil, nil, nil,
- nil, nil, nil, nil, 584, 584, nil, 584, 584, 584,
- 584, 584, 584, 584, nil, nil, 584, 584, nil, nil,
- nil, nil, 584, 584, 584, 584, nil, nil, nil, nil,
- nil, 584, nil, nil, nil, nil, nil, nil, 584, 584,
- nil, 584, 584, 584, 584, 584, 584, 584, 584, 584,
- 584, 584, 585, 585, 584, nil, 585, nil, nil, nil,
- nil, nil, nil, nil, nil, 585, 585, nil, 585, 585,
- 585, 585, 585, 585, 585, nil, nil, 585, 585, nil,
- nil, nil, nil, 585, 585, 585, 585, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 585,
- 585, nil, 585, 585, 585, 585, 585, 585, 585, 585,
- 585, 585, 585, 591, 591, 585, nil, 591, nil, nil,
- nil, nil, nil, nil, nil, nil, 591, 591, nil, 591,
- 591, 591, 591, 591, 591, 591, nil, nil, 591, 591,
- nil, nil, nil, nil, 591, 591, 591, 591, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 591, 591, nil, 591, 591, 591, 591, 591, 591, 591,
- 591, 591, 591, 591, 593, 593, 591, nil, 593, nil,
- nil, nil, nil, nil, nil, nil, nil, 593, 593, nil,
- 593, 593, 593, 593, 593, 593, 593, nil, nil, 593,
- 593, nil, nil, nil, nil, 593, 593, 593, 593, nil,
- nil, nil, nil, nil, 593, nil, nil, nil, nil, nil,
- nil, 593, 593, nil, 593, 593, 593, 593, 593, 593,
- 593, 593, 593, 593, 593, 822, 822, 593, nil, 822,
- nil, nil, nil, nil, nil, nil, nil, nil, 822, 822,
- nil, 822, 822, 822, 822, 822, 822, 822, nil, nil,
- 822, 822, nil, nil, nil, nil, 822, 822, 822, 822,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 822, 822, nil, 822, 822, 822, 822, 822,
- 822, 822, 822, 822, 822, 822, 946, 946, 822, nil,
- 946, nil, nil, nil, nil, nil, nil, nil, nil, 946,
- 946, nil, 946, 946, 946, 946, 946, 946, 946, nil,
- nil, 946, 946, nil, nil, nil, nil, 946, 946, 946,
- 946, nil, nil, nil, nil, nil, 946, nil, nil, nil,
- nil, nil, nil, 946, 946, nil, 946, 946, 946, 946,
- 946, 946, 946, 946, 946, 946, 946, 947, 947, 946,
- nil, 947, nil, nil, nil, nil, nil, nil, nil, nil,
- 947, 947, nil, 947, 947, 947, 947, 947, 947, 947,
- nil, nil, 947, 947, nil, nil, nil, nil, 947, 947,
- 947, 947, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 947, 947, nil, 947, 947, 947,
- 947, 947, 947, 947, 947, 947, 947, 947, nil, nil,
- 947 ]
-
-racc_action_pointer = [
- -2, 34, nil, 234, nil, 618, -19, 22922, 23046, -5,
- -1, 15, 117, 414, 291, 243, nil, 125, 252, 900,
- 186, nil, 379, 506, 633, 381, 13, 760, 22407, nil,
- 900, 1027, 1154, nil, 108, 541, 237, 261, 1294, 1421,
- 1548, 176, 467, nil, nil, nil, nil, nil, nil, nil,
- 22537, nil, 1675, 1802, 1929, 29, 9932, 2056, 2183, nil,
- nil, 2310, 2450, 2577, nil, 23418, nil, nil, nil, nil,
- nil, -102, nil, nil, nil, nil, nil, 178, 220, 23531,
- nil, nil, nil, 429, 2704, nil, nil, 2831, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 359, nil, 2971,
- nil, nil, nil, 3111, 3238, 3365, 3492, 3632, 3772, nil,
- 663, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 23644, 234, nil, 3912, 4039, 4166, 4293, 4420,
- 4547, 23818, 22792, 23879, 4674, 4801, 4928, nil, 541, -49,
- 319, 61, 240, 328, 5068, 5195, nil, nil, 5322, 363,
- 5449, 5576, 5703, 5830, 5957, 6084, 6211, 6338, 6465, 6592,
- 6719, 6846, 6973, 7100, 7227, 7354, 7481, 7608, 7735, 7862,
- 7989, 8116, 8243, 8370, 8497, 8624, nil, nil, nil, 1294,
- nil, 329, 339, nil, 8751, 389, 8878, nil, nil, nil,
- nil, 9005, nil, nil, 23940, 24001, 24062, 383, 9132, 9259,
- nil, nil, nil, nil, nil, nil, nil, 9386, 249, 745,
- 390, 9526, 409, 438, 405, 9653, 9793, 73, 594, 497,
- 196, 465, 440, 207, nil, 478, 471, nil, 9920, nil,
- 586, 505, 531, 633, nil, 533, nil, 10047, nil, 10187,
- 35, nil, 502, -103, 135, 537, 521, 262, 556, nil,
- nil, -22, 10580, nil, nil, nil, 520, 545, nil, 564,
- 567, nil, nil, nil, nil, nil, nil, nil, 3097, nil,
- nil, nil, 648, nil, nil, 674, 806, -7, 36, 10314,
- 10441, 324, 63, 596, -17, 668, 690, 37, 731, nil,
- nil, 506, 704, nil, 721, nil, 65, nil, nil, 10568,
- -12, 122, 360, 384, 385, 436, 509, 590, nil, 795,
- nil, 10695, nil, 173, nil, 326, nil, -23, 649, 362,
- nil, 653, -50, nil, 365, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 683, 23170, nil, nil, nil, 23294, 688, nil, nil, 760,
- nil, 10822, 681, nil, 691, nil, nil, 1421, 728, 731,
- 668, 761, 10949, nil, nil, nil, 21929, 757, 22011, nil,
- 11076, 11203, 11330, nil, nil, nil, 1548, nil, nil, 24123,
- 24184, 11457, 11584, 180, 11711, 11838, 11965, 115, nil, 3238,
- 3365, 232, 879, 785, 787, 821, 824, 2457, 2584, 5068,
- 3492, 3632, 3772, 3912, 4039, 4166, 4293, 4420, 4547, 4674,
- 1133, 1232, 4801, 4928, 633, -34, nil, 12092, nil, 12219,
- nil, 12346, nil, nil, 22667, 22724, 22792, -17, nil, 771,
- nil, nil, 785, 787, nil, nil, 12473, 59, 203, 832,
- nil, nil, 12613, 833, 797, nil, nil, 799, 12753, 845,
- 12880, 24245, 24306, 13007, 24367, 223, 848, nil, nil, 821,
- nil, 13134, 13261, 13388, 24428, 24489, 1675, 13515, 949, 951,
- 871, nil, nil, 13642, nil, nil, 13769, nil, nil, nil,
- nil, 13909, 14049, 874, nil, 1000, nil, nil, 14176, 12765,
- nil, 772, nil, nil, 894, nil, 3126, nil, 859, 1198,
- nil, nil, 14316, 977, nil, nil, 14456, 212, 227, 975,
- 983, 14596, nil, 14723, 24550, 24611, 14850, 40, nil, 760,
- nil, 24672, 14977, 24733, nil, nil, 15104, 387, 15231, nil,
- 1166, nil, nil, nil, 45, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, -35, nil, nil, nil, 864,
- nil, nil, nil, nil, nil, 15358, 866, 15485, 798, 203,
- 15612, 15739, 900, nil, nil, nil, 15866, 903, nil, 15993,
- 915, nil, 268, 307, 22143, 22275, 927, 928, 506, nil,
- 16120, nil, 1040, nil, 16260, 897, nil, 939, 16387, nil,
- nil, nil, nil, nil, nil, nil, nil, 16527, nil, 942,
- 16654, 16781, 2310, 907, nil, nil, 947, 16921, 17061, nil,
- 1154, -27, 17188, 914, nil, 957, 228, 235, 962, 313,
- 327, 963, 960, 972, 17315, 1802, 997, 1001, 240, 1056,
- 17442, nil, nil, 376, 960, 1068, nil, nil, 945, nil,
- 958, 935, 1035, 963, 967, nil, nil, 1010, 3135, nil,
- 869, nil, 1096, nil, nil, nil, nil, nil, 1102, nil,
- 1103, 17569, 1020, 46, 52, 59, 102, 1021, 17696, 1027,
- nil, 1028, 1026, 17836, 416, nil, -25, 17976, 18116, 9665,
- 463, nil, nil, 1075, nil, 18243, nil, 998, 999, nil,
- 1000, 1002, 1004, nil, 996, nil, 23757, 1043, 1050, 18383,
- nil, nil, nil, 1929, 1007, 18510, 18637, 18764, nil, 2056,
- nil, 2183, nil, nil, 2446, nil, 2573, nil, 18891, 19018,
- 19145, 315, 319, 2704, nil, 1041, 1144, nil, nil, 1041,
- nil, 1026, 19272, nil, 1053, 1161, 1072, 323, nil, nil,
- nil, 1196, nil, 19412, 1081, 1125, nil, nil, nil, nil,
- nil, nil, 24794, nil, 1127, nil, nil, nil, nil, 1407,
- 1215, nil, 19539, 1220, 19679, 19819, nil, nil, 66, 56,
- 988, 295, nil, 1221, nil, nil, 1222, 1225, 1109, nil,
- nil, nil, -32, nil, nil, 807, 14188, nil, 842, nil,
- 406, nil, 19946, nil, nil, nil, nil, nil, nil, nil,
- 1127, 1113, nil, 2831, nil, 2971, 20073, 20200, nil, nil,
- nil, 20327, 1114, nil, nil, nil, 20467, nil, nil, 72,
- 20594, nil, 1154, 1125, nil, nil, 78, nil, 1249, 1250,
- 20721, 20861, nil, nil, 21001, nil, nil, 1168, nil, 1132,
- nil, nil, 1133, 1134, 1139, 1137, nil, nil, 22721, nil,
- nil, 21128, nil, 21268, 91, 1112, 1221, 97, nil, nil,
- 21408, nil, nil, nil, 460, 21548, 1268, nil, nil, 1081,
- nil, nil, nil, 21688, 1273, 21815, 24855, 24916, 98, 899,
- nil, nil, nil, 1272, nil, 1153, 1275, nil, 1190, 108,
- 120, 198, 202, nil, nil, nil, nil, 218 ]
-
-racc_action_default = [
- -3, -555, -1, -543, -4, -6, -555, -555, -555, -555,
- -555, -555, -555, -555, -277, -37, -38, -555, -555, -43,
- -45, -46, -289, -327, -328, -50, -255, -382, -255, -65,
- -10, -69, -76, -78, -555, -457, -555, -555, -555, -555,
- -555, -545, -232, -270, -271, -272, -273, -274, -275, -276,
- -533, -279, -555, -554, -525, -297, -554, -555, -555, -302,
- -305, -543, -555, -555, -319, -555, -329, -330, -400, -401,
- -402, -403, -404, -554, -407, -554, -554, -554, -554, -554,
- -434, -440, -441, -555, -446, -447, -448, -449, -450, -451,
- -452, -453, -454, -455, -456, -459, -460, -555, -2, -544,
- -550, -551, -552, -555, -555, -555, -555, -555, -3, -13,
- -555, -105, -106, -107, -108, -109, -110, -111, -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, -555, -18, -112, -10, -555, -555, -555, -554,
- -554, -555, -555, -555, -555, -555, -555, -41, -555, -457,
- -555, -277, -555, -555, -10, -555, -42, -224, -555, -555,
- -555, -555, -555, -555, -555, -555, -555, -555, -555, -555,
- -555, -555, -555, -555, -555, -555, -555, -555, -555, -555,
- -555, -555, -555, -555, -555, -555, -369, -371, -47, -233,
- -248, -262, -262, -252, -555, -263, -555, -289, -327, -328,
- -527, -555, -48, -49, -555, -555, -555, -55, -554, -555,
- -296, -375, -383, -385, -63, -381, -64, -555, -543, -11,
- -65, -10, -555, -555, -70, -73, -10, -457, -555, -555,
- -277, -292, -545, -555, -331, -382, -555, -75, -555, -80,
- -284, -442, -443, -555, -209, -210, -225, -555, -546, -10,
- -545, -234, -545, -547, -547, -555, -555, -547, -555, -298,
- -299, -555, -555, -342, -343, -350, -554, -491, -357, -554,
- -554, -368, -490, -492, -493, -494, -495, -496, -555, -509,
- -514, -515, -517, -518, -519, -555, -44, -555, -555, -555,
- -555, -543, -555, -544, -457, -555, -555, -277, -555, -498,
- -499, -101, -555, -103, -555, -277, -555, -316, -457, -555,
- -105, -106, -143, -144, -160, -165, -172, -175, -322, -555,
- -523, -555, -405, -555, -420, -555, -422, -555, -555, -555,
- -412, -555, -555, -418, -555, -433, -435, -436, -437, -438,
- -444, -445, 968, -5, -553, -19, -20, -21, -22, -23,
- -555, -555, -15, -16, -17, -555, -555, -25, -34, -188,
- -263, -555, -555, -26, -35, -36, -27, -190, -555, -555,
- -534, -535, -554, -378, -536, -537, -534, -255, -535, -380,
- -539, -540, -554, -534, -535, -33, -198, -39, -40, -555,
- -555, -554, -554, -284, -555, -555, -555, -555, -295, -199,
- -200, -201, -202, -203, -204, -205, -206, -211, -212, -213,
- -214, -215, -216, -217, -218, -219, -220, -221, -222, -223,
- -226, -227, -228, -229, -555, -554, -249, -555, -250, -555,
- -260, -555, -264, -530, -255, -255, -255, -554, -56, -545,
- -243, -244, -262, -262, -256, -257, -555, -554, -554, -555,
- -291, -9, -544, -555, -66, -282, -81, -71, -555, -555,
- -554, -555, -555, -554, -555, -284, -555, -442, -443, -77,
- -82, -555, -555, -555, -555, -555, -230, -555, -392, -555,
- -555, -235, -236, -549, -548, -238, -549, -287, -288, -526,
- -339, -10, -10, -555, -341, -555, -359, -366, -555, -363,
- -364, -555, -367, -491, -555, -500, -555, -502, -504, -508,
- -516, -520, -10, -332, -333, -334, -10, -555, -555, -555,
- -555, -10, -387, -554, -555, -555, -554, -284, -311, -101,
- -102, -555, -554, -555, -314, -461, -555, -555, -555, -320,
- -489, -324, -541, -542, -545, -406, -421, -424, -425, -427,
- -408, -423, -409, -410, -411, -555, -414, -416, -417, -555,
- -439, -7, -14, -113, -24, -555, -269, -555, -285, -286,
- -555, -555, -59, -241, -242, -376, -555, -61, -379, -555,
- -57, -377, -534, -535, -534, -535, -555, -555, -188, -294,
- -555, -353, -555, -355, -10, -262, -261, -265, -555, -528,
- -529, -51, -372, -52, -373, -53, -374, -10, -239, -555,
- -245, -247, -43, -555, -254, -258, -555, -10, -10, -290,
- -12, -66, -555, -74, -79, -555, -534, -535, -554, -538,
- -283, -555, -555, -554, -555, -197, -207, -208, -555, -554,
- -554, -280, -281, -547, -555, -555, -340, -351, -555, -358,
- -554, -352, -555, -554, -554, -510, -497, -555, -555, -507,
- -554, -335, -554, -303, -336, -337, -338, -306, -555, -309,
- -555, -555, -555, -534, -535, -538, -283, -555, -555, -101,
- -104, -538, -555, -10, -555, -463, -555, -10, -10, -489,
- -555, -466, -467, -469, -470, -472, -473, -522, -522, -478,
- -480, -480, -480, -488, -491, -512, -555, -555, -555, -10,
- -413, -415, -419, -189, -267, -555, -555, -555, -30, -193,
- -31, -194, -60, -32, -195, -62, -196, -58, -555, -555,
- -555, -286, -285, -231, -354, -555, -555, -251, -266, -555,
- -240, -262, -555, -259, -555, -555, -72, -285, -286, -83,
- -293, -554, -348, -10, -393, -554, -394, -395, -237, -344,
- -345, -365, -555, -284, -555, -361, -362, -501, -503, -506,
- -555, -346, -555, -555, -10, -10, -308, -310, -555, -285,
- -93, -555, -285, -555, -462, -317, -555, -555, -545, -465,
- -468, -471, -555, -476, -477, -555, -555, -484, -555, -486,
- -555, -487, -555, -325, -524, -426, -429, -430, -431, -432,
- -555, -268, -28, -191, -29, -192, -555, -555, -356, -370,
- -54, -246, -262, -384, -386, -8, -10, -399, -349, -555,
- -555, -397, -283, -554, -505, -300, -555, -301, -555, -555,
- -555, -10, -312, -315, -10, -321, -323, -555, -474, -522,
- -521, -479, -480, -480, -480, -555, -513, -511, -489, -428,
- -253, -555, -398, -10, -457, -555, -555, -277, -396, -360,
- -10, -304, -307, -265, -554, -10, -555, -464, -475, -555,
- -482, -483, -485, -10, -392, -554, -555, -555, -284, -554,
- -388, -389, -390, -555, -318, -480, -555, -391, -555, -534,
- -535, -538, -283, -347, -313, -481, -326, -285 ]
-
-racc_goto_table = [
- 13, 315, 307, 699, 323, 378, 498, 114, 114, 539,
- 250, 250, 250, 432, 437, 442, 5, 208, 208, 396,
- 284, 488, 208, 208, 208, 659, 331, 102, 294, 294,
- 13, 288, 288, 572, 576, 529, 10, 98, 12, 557,
- 748, 312, 560, 562, 251, 251, 251, 366, 565, 109,
- 194, 580, 208, 208, 117, 117, 216, 208, 208, 294,
- 294, 208, 355, 364, 99, 114, 10, 715, 12, 418,
- 425, 760, 707, 267, 274, 276, 494, 495, 496, 114,
- 542, 545, 659, 2, 549, 102, 280, 297, 252, 252,
- 252, 606, 763, 723, 727, 352, 759, 616, 359, 13,
- 1, 916, 590, 208, 208, 208, 208, 13, 13, 347,
- 348, 403, 282, 351, 641, 5, 564, 710, 385, 387,
- 317, 714, 394, 409, 5, 885, 830, 248, 262, 263,
- 193, 360, 396, 411, 499, 10, 668, 12, 676, 504,
- 207, 654, 811, 10, 10, 12, 12, 428, 429, 853,
- 854, 380, 316, 667, 319, 405, 406, 407, 408, 320,
- 358, 594, 762, 677, 678, 833, 662, 664, 666, 379,
- 601, 309, 349, 834, 350, 310, 835, 738, 935, 743,
- 346, 346, 916, 598, 346, 904, 369, 312, 312, 747,
- 600, 410, 114, 766, 918, 13, 208, 208, 208, 208,
- 208, 321, 441, 550, 208, 208, 208, 659, 713, 247,
- 485, 656, 507, 656, 13, 208, 508, 950, 422, 422,
- 760, 731, 815, 889, 382, 383, 346, 346, 346, 346,
- 674, 10, 389, 12, 417, 423, 426, 615, 392, 865,
- 768, 763, 445, 769, 848, 759, 909, 908, 912, 828,
- 10, nil, 12, 526, nil, 683, 250, 250, nil, nil,
- nil, 432, 437, nil, nil, 250, nil, nil, 208, 208,
- 553, 540, 488, 541, nil, nil, 565, 208, 728, 719,
- nil, 13, 294, nil, nil, 288, 13, 530, nil, nil,
- 502, 251, 331, nil, nil, 294, nil, nil, 288, 251,
- nil, 938, 102, nil, nil, nil, nil, nil, nil, 13,
- nil, 762, 511, nil, nil, nil, nil, 10, nil, 12,
- nil, nil, 10, 771, 12, nil, 271, 275, 447, 448,
- 14, 740, nil, 688, 503, 252, 693, 280, 457, 512,
- 517, 707, 280, 252, 717, 10, 688, 12, 910, 208,
- 208, 910, 759, 599, 759, 963, 759, 902, 943, nil,
- 14, 290, 290, 513, 715, 641, 294, nil, 519, 364,
- nil, 782, nil, 501, 505, 102, 785, 951, nil, 787,
- nil, 208, 509, nil, nil, 579, 893, nil, nil, 760,
- 595, nil, 357, 365, 656, 656, 688, nil, nil, 646,
- 647, 577, 578, nil, nil, 688, nil, nil, nil, 957,
- 763, 114, nil, nil, 759, 114, nil, 659, 913, 806,
- 914, nil, nil, 821, 797, nil, 825, 826, 565, 14,
- nil, nil, nil, nil, nil, 759, nil, 14, 14, 312,
- 312, nil, nil, 843, nil, nil, nil, 846, 847, nil,
- 441, 208, 208, 622, nil, nil, nil, 623, 117, nil,
- 669, nil, 117, nil, nil, nil, nil, nil, 685, nil,
- 818, 692, 346, 346, nil, nil, nil, nil, nil, 632,
- 762, nil, nil, nil, 637, nil, nil, nil, nil, 640,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 955, nil, nil, 604, nil, 208, 530, 312, nil,
- nil, 312, 13, nil, nil, 294, nil, nil, 288, nil,
- 208, nil, 441, 208, 901, 14, nil, nil, 680, nil,
- nil, 732, nil, nil, 737, 441, nil, 208, nil, 894,
- 742, 661, 663, 665, 14, nil, nil, nil, 10, nil,
- 12, 13, 13, 655, nil, 294, nil, nil, 711, nil,
- nil, nil, nil, nil, nil, 767, nil, nil, nil, nil,
- 797, 312, 13, 816, 312, 923, 13, 857, 859, 861,
- 312, 13, 930, 208, nil, 441, 208, 10, 10, 12,
- 12, 441, 208, 271, 35, 275, 208, nil, 208, nil,
- 795, 724, 724, nil, 936, 656, 929, nil, 10, 703,
- 12, 14, 10, nil, 12, 290, 14, 10, nil, 12,
- nil, 745, 331, nil, 35, 287, 287, nil, 290, 310,
- 208, 208, nil, 952, nil, nil, 208, nil, nil, 14,
- nil, nil, nil, 956, nil, 656, nil, nil, 744, nil,
- nil, 920, nil, nil, 13, nil, 354, 368, nil, 368,
- 698, nil, 283, nil, nil, nil, nil, 13, 778, 780,
- nil, 530, nil, nil, 783, nil, nil, 13, 13, 294,
- nil, nil, 288, 809, nil, nil, nil, nil, nil, nil,
- 10, 294, 12, 35, 288, nil, nil, nil, nil, 365,
- nil, 35, 35, 10, nil, 12, 863, nil, nil, nil,
- nil, nil, nil, 10, 10, 12, 12, nil, nil, 346,
- nil, 746, 422, nil, nil, nil, nil, nil, nil, 940,
- 941, 942, 634, nil, nil, nil, 801, 638, 208, nil,
- nil, nil, 634, 13, nil, nil, nil, 13, 13, nil,
- nil, nil, nil, 838, nil, nil, nil, nil, 688, nil,
- nil, nil, nil, nil, nil, nil, 114, nil, 844, 13,
- 845, nil, 965, nil, 849, nil, 208, 208, nil, 10,
- nil, 12, nil, 10, 10, 12, 12, nil, nil, 35,
- 841, nil, nil, nil, 634, 634, 634, nil, nil, nil,
- nil, nil, nil, nil, nil, 10, nil, 12, 35, 907,
- nil, nil, nil, 13, 872, 874, nil, nil, nil, nil,
- nil, nil, 441, nil, 882, nil, nil, 416, nil, nil,
- nil, nil, 208, 318, 13, 13, nil, nil, nil, nil,
- nil, nil, 14, nil, nil, nil, 283, nil, 290, 10,
- nil, 12, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 346, nil, nil, nil, 724, nil, nil, nil, nil,
- 10, 10, 12, 12, nil, 35, nil, nil, nil, 287,
- 35, 14, 14, nil, 896, nil, 13, 294, 365, nil,
- 925, nil, 287, 958, nil, nil, nil, nil, nil, nil,
- nil, 13, 14, 35, 13, nil, 14, nil, nil, nil,
- nil, 14, nil, 283, nil, nil, nil, nil, 283, nil,
- nil, nil, 10, 13, 12, nil, 928, nil, nil, nil,
- 13, nil, nil, 312, nil, 13, nil, 10, nil, 12,
- 10, nil, 12, 13, nil, 208, nil, 441, nil, nil,
- nil, nil, nil, nil, nil, 346, nil, nil, nil, 10,
- nil, 12, nil, 368, nil, nil, 10, nil, 12, nil,
- nil, 10, nil, 12, nil, 420, 424, nil, nil, 10,
- nil, 12, nil, nil, 14, nil, nil, nil, 634, nil,
- nil, 638, nil, 634, nil, nil, nil, 14, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 14, 14, nil,
- nil, nil, 290, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 290, nil, nil, nil, nil, nil,
- nil, nil, nil, 490, nil, 492, nil, nil, nil, nil,
- 493, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 324, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 14, nil, nil, nil, 14, 14, 384,
- nil, 386, 386, 390, 393, 386, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 869, 14,
- nil, nil, nil, nil, nil, nil, 35, nil, nil, nil,
- nil, nil, 287, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 14, nil, 35, 35, nil, nil, nil,
- nil, nil, 368, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 14, 14, 35, 217, nil, nil,
- 35, 249, 249, 249, nil, 35, nil, nil, nil, nil,
- nil, nil, nil, 704, 705, nil, nil, 304, 305, 306,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 626, nil, 249, 249, 720, nil, nil, nil, 722, nil,
- nil, nil, nil, 730, nil, nil, 14, nil, nil, nil,
- 927, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 14, nil, nil, 14, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 35, nil,
- nil, nil, nil, 14, nil, nil, nil, nil, nil, nil,
- 14, 35, nil, nil, nil, 14, 657, nil, 318, nil,
- 660, 35, 35, 14, 500, nil, 287, nil, nil, nil,
- nil, nil, nil, nil, nil, 673, 796, nil, 287, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 799,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 804,
- 805, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 657, nil, nil, 318, nil, nil, nil, nil,
- nil, nil, 556, nil, nil, 556, 556, 35, nil, nil,
- nil, 35, 35, nil, nil, 419, 249, 427, 249, 249,
- nil, nil, nil, 446, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 35, nil, nil, nil, 217, nil, 459,
- 460, 461, 462, 463, 464, 465, 466, 467, 468, 469,
- 470, 471, 472, 473, 474, 475, 476, 477, 478, 479,
- 480, 481, 482, 483, 484, nil, nil, nil, nil, nil,
- nil, 870, nil, 249, nil, 249, 774, 35, nil, nil,
- 249, nil, nil, nil, nil, nil, nil, 249, 249, nil,
- nil, nil, nil, nil, nil, nil, 249, nil, 35, 35,
- nil, nil, nil, nil, nil, nil, nil, 798, 633, nil,
- nil, nil, nil, nil, nil, 888, nil, nil, 633, 657,
- 318, nil, nil, nil, nil, nil, 536, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 898, 899, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 814,
- 35, nil, nil, nil, 924, nil, nil, nil, nil, nil,
- nil, 651, nil, nil, nil, 35, nil, nil, 35, nil,
- 633, 633, 633, 651, nil, nil, nil, nil, nil, nil,
- 420, nil, nil, 651, 651, nil, nil, 35, 922, nil,
- nil, nil, nil, nil, 35, nil, nil, nil, nil, 35,
- nil, nil, nil, 934, 851, nil, nil, 35, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 871, 944, nil, nil, nil, nil,
- nil, nil, 949, nil, nil, nil, nil, 953, nil, nil,
- 249, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 420, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 249, 249, nil, 446, 648, 427, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 249, nil, 249, nil,
- 249, 917, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 672, nil, nil, nil, nil,
- 318, nil, nil, nil, nil, nil, nil, nil, nil, 249,
- nil, nil, 249, nil, nil, nil, nil, nil, nil, 933,
- 695, 696, 697, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 249, nil, 633, 249, nil, nil, nil, 633,
- 933, nil, nil, nil, nil, 812, 817, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 556, nil, nil, 556,
- 556, nil, nil, nil, nil, nil, 812, nil, 812, nil,
- nil, nil, 249, nil, nil, 249, nil, nil, nil, nil,
- nil, 249, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 773, nil, 249, nil, nil, 779,
- 781, nil, nil, 293, 293, 784, nil, nil, 786, nil,
- 293, 293, 293, nil, nil, nil, nil, nil, nil, 793,
- nil, nil, nil, nil, nil, nil, 293, 249, nil, nil,
- nil, nil, nil, nil, 293, 293, nil, 887, nil, 249,
- 249, 891, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 249,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 249, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 556,
- nil, nil, nil, nil, 249, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 249, 873, 875, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 779, 781, 784,
- 812, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 249, nil, nil, nil, 812, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 293, nil, 293, 293, 293, 293, 293, 293, 293, 293,
- 293, 293, 293, 293, 293, 293, 293, 293, 293, 293,
- 293, 293, 293, 293, 293, 293, 293, 293, nil, nil,
- nil, nil, nil, nil, nil, nil, 293, nil, 293, nil,
- nil, 249, nil, 293, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 875, 873, nil, nil, nil,
- 249, nil, nil, nil, nil, nil, nil, 293, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 249,
- 293, nil, nil, nil, nil, nil, nil, nil, nil, 293,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 249, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 249, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 293, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 293, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 293, 293, 293, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 293,
- nil, 293, nil, 293, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 293, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 293, 293, 293, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 293, nil, nil, 293, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 293, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 293, nil, 293,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 293, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 293, nil, nil, nil, nil, nil, nil, nil,
- 293, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 293, 293, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 293, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 293, nil, nil, nil,
- nil, nil, 293, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 293, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 293, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 293, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 293, 293, 293, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 293, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 293, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 293, 293,
- nil, nil, nil, 293, nil, nil, nil, nil, nil, nil,
- nil, nil, 293, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 293, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 293 ]
-
-racc_goto_check = [
- 21, 22, 51, 10, 104, 47, 35, 48, 48, 8,
- 29, 29, 29, 33, 33, 33, 7, 21, 21, 47,
- 41, 61, 21, 21, 21, 154, 107, 83, 52, 52,
- 21, 21, 21, 77, 77, 43, 17, 4, 20, 109,
- 84, 29, 109, 109, 54, 54, 54, 46, 145, 14,
- 14, 80, 21, 21, 50, 50, 18, 21, 21, 52,
- 52, 21, 21, 21, 6, 48, 17, 147, 20, 24,
- 24, 110, 106, 34, 34, 34, 33, 33, 33, 48,
- 55, 55, 154, 2, 55, 83, 38, 42, 56, 56,
- 56, 129, 141, 79, 79, 4, 108, 129, 17, 21,
- 1, 151, 45, 21, 21, 21, 21, 21, 21, 16,
- 16, 5, 39, 16, 60, 7, 148, 111, 126, 126,
- 56, 111, 126, 7, 7, 12, 78, 31, 31, 31,
- 15, 19, 47, 27, 58, 17, 59, 20, 63, 64,
- 26, 36, 11, 17, 17, 20, 20, 22, 22, 142,
- 142, 72, 73, 36, 74, 16, 16, 16, 16, 76,
- 81, 82, 111, 36, 36, 11, 60, 60, 60, 85,
- 86, 87, 88, 89, 90, 26, 91, 92, 93, 94,
- 26, 26, 151, 95, 26, 96, 97, 29, 29, 98,
- 99, 2, 48, 100, 101, 21, 21, 21, 21, 21,
- 21, 102, 48, 103, 21, 21, 21, 154, 105, 112,
- 113, 62, 115, 62, 21, 21, 116, 117, 54, 54,
- 110, 118, 119, 120, 124, 125, 26, 26, 26, 26,
- 62, 17, 127, 20, 18, 18, 18, 128, 130, 131,
- 132, 141, 18, 133, 135, 108, 137, 139, 144, 149,
- 17, nil, 20, 51, nil, 43, 29, 29, nil, nil,
- nil, 33, 33, nil, nil, 29, nil, nil, 21, 21,
- 104, 51, 61, 51, nil, nil, 145, 21, 80, 145,
- nil, 21, 52, nil, nil, 21, 21, 41, nil, nil,
- 54, 54, 107, nil, nil, 52, nil, nil, 21, 54,
- nil, 142, 83, nil, nil, nil, nil, nil, nil, 21,
- nil, 111, 4, nil, nil, nil, nil, 17, nil, 20,
- nil, nil, 17, 129, 20, nil, 57, 57, 26, 26,
- 23, 45, nil, 33, 56, 56, 33, 38, 26, 6,
- 42, 106, 38, 56, 148, 17, 33, 20, 108, 21,
- 21, 108, 108, 46, 108, 78, 108, 79, 84, nil,
- 23, 23, 23, 39, 147, 60, 52, nil, 39, 21,
- nil, 35, nil, 31, 31, 83, 35, 11, nil, 35,
- nil, 21, 31, nil, nil, 4, 111, nil, nil, 110,
- 83, nil, 23, 23, 62, 62, 33, nil, nil, 22,
- 22, 16, 16, nil, nil, 33, nil, nil, nil, 10,
- 141, 48, nil, nil, 108, 48, nil, 154, 111, 43,
- 111, nil, nil, 109, 61, nil, 109, 109, 145, 23,
- nil, nil, nil, nil, nil, 108, nil, 23, 23, 29,
- 29, nil, nil, 8, nil, nil, nil, 8, 8, nil,
- 48, 21, 21, 14, nil, nil, nil, 14, 50, nil,
- 51, nil, 50, nil, nil, nil, nil, nil, 22, nil,
- 55, 22, 26, 26, nil, nil, nil, nil, nil, 34,
- 111, nil, nil, nil, 34, nil, nil, nil, nil, 34,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 111, nil, nil, 26, nil, 21, 41, 29, nil,
- nil, 29, 21, nil, nil, 52, nil, nil, 21, nil,
- 21, nil, 48, 21, 77, 23, nil, nil, 7, nil,
- nil, 22, nil, nil, 22, 48, nil, 21, nil, 145,
- 22, 34, 34, 34, 23, nil, nil, nil, 17, nil,
- 20, 21, 21, 56, nil, 52, nil, nil, 21, nil,
- nil, nil, nil, nil, nil, 51, nil, nil, nil, nil,
- 61, 29, 21, 24, 29, 77, 21, 143, 143, 143,
- 29, 21, 77, 21, nil, 48, 21, 17, 17, 20,
- 20, 48, 21, 57, 44, 57, 21, nil, 21, nil,
- 104, 83, 83, nil, 8, 62, 109, nil, 17, 56,
- 20, 23, 17, nil, 20, 23, 23, 17, nil, 20,
- nil, 83, 107, nil, 44, 44, 44, nil, 23, 26,
- 21, 21, nil, 80, nil, nil, 21, nil, nil, 23,
- nil, nil, nil, 8, nil, 62, nil, nil, 16, nil,
- nil, 61, nil, nil, 21, nil, 44, 44, nil, 44,
- 26, nil, 9, nil, nil, nil, nil, 21, 18, 18,
- nil, 41, nil, nil, 18, nil, nil, 21, 21, 52,
- nil, nil, 21, 41, nil, nil, nil, nil, nil, nil,
- 17, 52, 20, 44, 21, nil, nil, nil, nil, 23,
- nil, 44, 44, 17, nil, 20, 47, nil, nil, nil,
- nil, nil, nil, 17, 17, 20, 20, nil, nil, 26,
- nil, 26, 54, nil, nil, nil, nil, nil, nil, 143,
- 143, 143, 57, nil, nil, nil, 56, 57, 21, nil,
- nil, nil, 57, 21, nil, nil, nil, 21, 21, nil,
- nil, nil, nil, 54, nil, nil, nil, nil, 33, nil,
- nil, nil, nil, nil, nil, nil, 48, nil, 83, 21,
- 83, nil, 143, nil, 83, nil, 21, 21, nil, 17,
- nil, 20, nil, 17, 17, 20, 20, nil, nil, 44,
- 16, nil, nil, nil, 57, 57, 57, nil, nil, nil,
- nil, nil, nil, nil, nil, 17, nil, 20, 44, 51,
- nil, nil, nil, 21, 18, 18, nil, nil, nil, nil,
- nil, nil, 48, nil, 54, nil, nil, 9, nil, nil,
- nil, nil, 21, 25, 21, 21, nil, nil, nil, nil,
- nil, nil, 23, nil, nil, nil, 9, nil, 23, 17,
- nil, 20, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 26, nil, nil, nil, 83, nil, nil, nil, nil,
- 17, 17, 20, 20, nil, 44, nil, nil, nil, 44,
- 44, 23, 23, nil, 16, nil, 21, 52, 23, nil,
- 21, nil, 44, 22, nil, nil, nil, nil, nil, nil,
- nil, 21, 23, 44, 21, nil, 23, nil, nil, nil,
- nil, 23, nil, 9, nil, nil, nil, nil, 9, nil,
- nil, nil, 17, 21, 20, nil, 17, nil, nil, nil,
- 21, nil, nil, 29, nil, 21, nil, 17, nil, 20,
- 17, nil, 20, 21, nil, 21, nil, 48, nil, nil,
- nil, nil, nil, nil, nil, 26, nil, nil, nil, 17,
- nil, 20, nil, 44, nil, nil, 17, nil, 20, nil,
- nil, 17, nil, 20, nil, 25, 25, nil, nil, 17,
- nil, 20, nil, nil, 23, nil, nil, nil, 57, nil,
- nil, 57, nil, 57, nil, nil, nil, 23, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 23, 23, nil,
- nil, nil, 23, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 23, nil, nil, nil, nil, nil,
- nil, nil, nil, 25, nil, 25, nil, nil, nil, nil,
- 25, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 53, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 23, nil, nil, nil, 23, 23, 53,
- nil, 53, 53, 53, 53, 53, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 23, 23,
- nil, nil, nil, nil, nil, nil, 44, nil, nil, nil,
- nil, nil, 44, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 23, nil, 44, 44, nil, nil, nil,
- nil, nil, 44, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 23, 23, 44, 28, nil, nil,
- 44, 28, 28, 28, nil, 44, nil, nil, nil, nil,
- nil, nil, nil, 9, 9, nil, nil, 28, 28, 28,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 25, nil, 28, 28, 9, nil, nil, nil, 9, nil,
- nil, nil, nil, 9, nil, nil, 23, nil, nil, nil,
- 23, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 23, nil, nil, 23, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 44, nil,
- nil, nil, nil, 23, nil, nil, nil, nil, nil, nil,
- 23, 44, nil, nil, nil, 23, 25, nil, 25, nil,
- 25, 44, 44, 23, 53, nil, 44, nil, nil, nil,
- nil, nil, nil, nil, nil, 25, 9, nil, 44, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 9,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 9,
- 9, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 25, nil, nil, 25, nil, nil, nil, nil,
- nil, nil, 53, nil, nil, 53, 53, 44, nil, nil,
- nil, 44, 44, nil, nil, 28, 28, 28, 28, 28,
- nil, nil, nil, 28, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 44, nil, nil, nil, 28, nil, 28,
- 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
- 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
- 28, 28, 28, 28, 28, nil, nil, nil, nil, nil,
- nil, 9, nil, 28, nil, 28, 25, 44, nil, nil,
- 28, nil, nil, nil, nil, nil, nil, 28, 28, nil,
- nil, nil, nil, nil, nil, nil, 28, nil, 44, 44,
- nil, nil, nil, nil, nil, nil, nil, 25, 53, nil,
- nil, nil, nil, nil, nil, 9, nil, nil, 53, 25,
- 25, nil, nil, nil, nil, nil, 28, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 9, 9, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 25,
- 44, nil, nil, nil, 44, nil, nil, nil, nil, nil,
- nil, 53, nil, nil, nil, 44, nil, nil, 44, nil,
- 53, 53, 53, 53, nil, nil, nil, nil, nil, nil,
- 25, nil, nil, 53, 53, nil, nil, 44, 9, nil,
- nil, nil, nil, nil, 44, nil, nil, nil, nil, 44,
- nil, nil, nil, 9, 25, nil, nil, 44, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 25, 9, nil, nil, nil, nil,
- nil, nil, 9, nil, nil, nil, nil, 9, nil, nil,
- 28, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 25, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 28, 28, nil, 28, 28, 28, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 28, nil, 28, nil,
- 28, 25, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 28, nil, nil, nil, nil,
- 25, nil, nil, nil, nil, nil, nil, nil, nil, 28,
- nil, nil, 28, nil, nil, nil, nil, nil, nil, 25,
- 28, 28, 28, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 28, nil, 53, 28, nil, nil, nil, 53,
- 25, nil, nil, nil, nil, 53, 53, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 53, nil, nil, 53,
- 53, nil, nil, nil, nil, nil, 53, nil, 53, nil,
- nil, nil, 28, nil, nil, 28, nil, nil, nil, nil,
- nil, 28, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 28, nil, 28, nil, nil, 28,
- 28, nil, nil, 37, 37, 28, nil, nil, 28, nil,
- 37, 37, 37, nil, nil, nil, nil, nil, nil, 28,
- nil, nil, nil, nil, nil, nil, 37, 28, nil, nil,
- nil, nil, nil, nil, 37, 37, nil, 53, nil, 28,
- 28, 53, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 28,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 28, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 53,
- nil, nil, nil, nil, 28, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 28, 28, 28, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 28, 28, 28,
- 53, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 28, nil, nil, nil, 53, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 37, nil, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, 37, 37,
- 37, 37, 37, 37, 37, 37, 37, 37, nil, nil,
- nil, nil, nil, nil, nil, nil, 37, nil, 37, nil,
- nil, 28, nil, 37, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 28, 28, nil, nil, nil,
- 28, nil, nil, nil, nil, nil, nil, 37, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 28,
- 37, nil, nil, nil, nil, nil, nil, nil, nil, 37,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 28, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 28, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 37, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 37, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 37, 37, 37, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 37,
- nil, 37, nil, 37, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 37, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 37, 37, 37, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 37, nil, nil, 37, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 37, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 37, nil, 37,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 37, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 37, nil, nil, nil, nil, nil, nil, nil,
- 37, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 37, 37, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 37, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 37, nil, nil, nil,
- nil, nil, 37, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 37, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 37, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 37, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 37, 37, 37, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 37, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 37, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 37, 37,
- nil, nil, nil, 37, nil, nil, nil, nil, nil, nil,
- nil, nil, 37, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 37, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 37 ]
-
-racc_goto_pointer = [
- nil, 100, 83, nil, 34, 12, 61, 16, -300, 632,
- -535, -557, -686, nil, 42, 122, 52, 36, 38, 69,
- 38, 0, -52, 330, -127, 779, 123, 24, 1149, -12,
- nil, 105, nil, -188, 47, -261, -344, 1752, 56, 82,
- nil, -11, 55, -263, 594, -260, -16, -60, 0, nil,
- 47, -39, -3, 1006, 22, -233, 66, 300, -134, -363,
- -328, -231, -276, -368, -130, nil, nil, nil, nil, nil,
- nil, nil, 86, 98, 99, nil, 103, -314, -594, -484,
- -301, 98, -205, 24, -560, 104, -209, 120, 113, -550,
- 114, -551, -411, -724, -415, -184, -660, 122, -410, -188,
- -408, -669, 145, -118, -52, -351, -483, -30, -504, -287,
- -529, -438, 189, -36, nil, -60, -57, -717, -361, -478,
- -592, nil, nil, nil, 153, 152, 43, 155, -152, -292,
- 160, -529, -368, -366, nil, -505, nil, -606, nil, -605,
- nil, -508, -608, -183, -608, -290, nil, -492, -222, -469,
- nil, -757, nil, nil, -464 ]
-
-racc_goto_default = [
- nil, nil, nil, 3, nil, 4, 353, 279, nil, 538,
- nil, 831, nil, 278, nil, nil, nil, 212, 16, 11,
- 213, 303, nil, 211, nil, 255, 15, nil, 19, 20,
- 21, nil, 25, 691, nil, nil, nil, 26, 29, nil,
- 31, 34, 33, nil, 209, 363, nil, 116, 435, 115,
- 69, nil, 42, 311, 313, nil, 314, 433, nil, nil,
- 635, 486, 253, nil, nil, 269, 43, 44, 45, 46,
- 47, 48, 49, nil, 270, 55, nil, nil, nil, nil,
- nil, nil, nil, 573, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 326, 325, 709, 328, nil,
- 329, 330, nil, nil, 439, nil, nil, nil, nil, nil,
- nil, 68, 70, 71, 72, nil, nil, nil, nil, 611,
- nil, nil, nil, nil, 395, 750, 753, 758, 755, 756,
- 757, 911, nil, nil, 761, 337, 332, 339, nil, 567,
- 568, 765, 342, 345, 260 ]
-
-racc_reduce_table = [
- 0, 0, :racc_error,
- 1, 143, :_reduce_none,
- 2, 144, :_reduce_2,
- 0, 145, :_reduce_3,
- 1, 145, :_reduce_4,
- 3, 145, :_reduce_5,
- 1, 147, :_reduce_none,
- 4, 147, :_reduce_7,
- 4, 150, :_reduce_8,
- 2, 151, :_reduce_9,
- 0, 155, :_reduce_10,
- 1, 155, :_reduce_11,
- 3, 155, :_reduce_12,
- 0, 169, :_reduce_13,
- 4, 149, :_reduce_14,
- 3, 149, :_reduce_15,
- 3, 149, :_reduce_none,
- 3, 149, :_reduce_17,
- 2, 149, :_reduce_18,
- 3, 149, :_reduce_19,
- 3, 149, :_reduce_20,
- 3, 149, :_reduce_21,
- 3, 149, :_reduce_22,
- 3, 149, :_reduce_23,
- 4, 149, :_reduce_none,
- 3, 149, :_reduce_25,
- 3, 149, :_reduce_26,
- 3, 149, :_reduce_27,
- 6, 149, :_reduce_none,
- 6, 149, :_reduce_none,
- 5, 149, :_reduce_30,
- 5, 149, :_reduce_none,
- 5, 149, :_reduce_none,
- 3, 149, :_reduce_none,
- 3, 149, :_reduce_34,
- 3, 149, :_reduce_35,
- 3, 149, :_reduce_36,
- 1, 149, :_reduce_none,
- 1, 168, :_reduce_none,
- 3, 168, :_reduce_39,
- 3, 168, :_reduce_40,
- 2, 168, :_reduce_41,
- 2, 168, :_reduce_42,
- 1, 168, :_reduce_none,
- 1, 158, :_reduce_none,
- 1, 160, :_reduce_none,
- 1, 160, :_reduce_none,
- 2, 160, :_reduce_47,
- 2, 160, :_reduce_48,
- 2, 160, :_reduce_49,
- 1, 172, :_reduce_none,
- 4, 172, :_reduce_none,
- 4, 172, :_reduce_none,
- 4, 172, :_reduce_none,
- 4, 177, :_reduce_none,
- 2, 171, :_reduce_55,
- 3, 171, :_reduce_none,
- 4, 171, :_reduce_57,
- 5, 171, :_reduce_none,
- 4, 171, :_reduce_59,
- 5, 171, :_reduce_none,
- 4, 171, :_reduce_61,
- 5, 171, :_reduce_none,
- 2, 171, :_reduce_63,
- 2, 171, :_reduce_64,
- 1, 161, :_reduce_65,
- 3, 161, :_reduce_66,
- 1, 181, :_reduce_67,
- 3, 181, :_reduce_68,
- 1, 180, :_reduce_69,
- 2, 180, :_reduce_70,
- 3, 180, :_reduce_71,
- 5, 180, :_reduce_none,
- 2, 180, :_reduce_73,
- 4, 180, :_reduce_none,
- 2, 180, :_reduce_75,
- 1, 180, :_reduce_76,
- 3, 180, :_reduce_none,
- 1, 183, :_reduce_78,
- 3, 183, :_reduce_79,
- 2, 182, :_reduce_80,
- 3, 182, :_reduce_81,
- 1, 185, :_reduce_none,
- 3, 185, :_reduce_none,
- 1, 184, :_reduce_84,
- 4, 184, :_reduce_85,
- 3, 184, :_reduce_86,
- 3, 184, :_reduce_none,
- 3, 184, :_reduce_none,
- 3, 184, :_reduce_none,
- 2, 184, :_reduce_none,
- 1, 184, :_reduce_none,
- 1, 159, :_reduce_92,
- 4, 159, :_reduce_93,
- 4, 159, :_reduce_94,
- 3, 159, :_reduce_95,
- 3, 159, :_reduce_96,
- 3, 159, :_reduce_97,
- 3, 159, :_reduce_98,
- 2, 159, :_reduce_99,
- 1, 159, :_reduce_none,
- 1, 187, :_reduce_none,
- 2, 188, :_reduce_102,
- 1, 188, :_reduce_103,
- 3, 188, :_reduce_104,
- 1, 189, :_reduce_none,
- 1, 189, :_reduce_none,
- 1, 189, :_reduce_none,
- 1, 189, :_reduce_108,
- 1, 189, :_reduce_109,
- 1, 156, :_reduce_110,
- 1, 156, :_reduce_none,
- 1, 157, :_reduce_112,
- 3, 157, :_reduce_113,
- 1, 190, :_reduce_none,
- 1, 190, :_reduce_none,
- 1, 190, :_reduce_none,
- 1, 190, :_reduce_none,
- 1, 190, :_reduce_none,
- 1, 190, :_reduce_none,
- 1, 190, :_reduce_none,
- 1, 190, :_reduce_none,
- 1, 190, :_reduce_none,
- 1, 190, :_reduce_none,
- 1, 190, :_reduce_none,
- 1, 190, :_reduce_none,
- 1, 190, :_reduce_none,
- 1, 190, :_reduce_none,
- 1, 190, :_reduce_none,
- 1, 190, :_reduce_none,
- 1, 190, :_reduce_none,
- 1, 190, :_reduce_none,
- 1, 190, :_reduce_none,
- 1, 190, :_reduce_none,
- 1, 190, :_reduce_none,
- 1, 190, :_reduce_none,
- 1, 190, :_reduce_none,
- 1, 190, :_reduce_none,
- 1, 190, :_reduce_none,
- 1, 190, :_reduce_none,
- 1, 190, :_reduce_none,
- 1, 190, :_reduce_none,
- 1, 190, :_reduce_none,
- 1, 191, :_reduce_none,
- 1, 191, :_reduce_none,
- 1, 191, :_reduce_none,
- 1, 191, :_reduce_none,
- 1, 191, :_reduce_none,
- 1, 191, :_reduce_none,
- 1, 191, :_reduce_none,
- 1, 191, :_reduce_none,
- 1, 191, :_reduce_none,
- 1, 191, :_reduce_none,
- 1, 191, :_reduce_none,
- 1, 191, :_reduce_none,
- 1, 191, :_reduce_none,
- 1, 191, :_reduce_none,
- 1, 191, :_reduce_none,
- 1, 191, :_reduce_none,
- 1, 191, :_reduce_none,
- 1, 191, :_reduce_none,
- 1, 191, :_reduce_none,
- 1, 191, :_reduce_none,
- 1, 191, :_reduce_none,
- 1, 191, :_reduce_none,
- 1, 191, :_reduce_none,
- 1, 191, :_reduce_none,
- 1, 191, :_reduce_none,
- 1, 191, :_reduce_none,
- 1, 191, :_reduce_none,
- 1, 191, :_reduce_none,
- 1, 191, :_reduce_none,
- 1, 191, :_reduce_none,
- 1, 191, :_reduce_none,
- 1, 191, :_reduce_none,
- 1, 191, :_reduce_none,
- 1, 191, :_reduce_none,
- 1, 191, :_reduce_none,
- 1, 191, :_reduce_none,
- 1, 191, :_reduce_none,
- 1, 191, :_reduce_none,
- 1, 191, :_reduce_none,
- 1, 191, :_reduce_none,
- 1, 191, :_reduce_none,
- 1, 191, :_reduce_none,
- 1, 191, :_reduce_none,
- 1, 191, :_reduce_none,
- 1, 191, :_reduce_none,
- 3, 170, :_reduce_188,
- 5, 170, :_reduce_189,
- 3, 170, :_reduce_190,
- 6, 170, :_reduce_191,
- 6, 170, :_reduce_192,
- 5, 170, :_reduce_193,
- 5, 170, :_reduce_none,
- 5, 170, :_reduce_none,
- 5, 170, :_reduce_none,
- 4, 170, :_reduce_none,
- 3, 170, :_reduce_none,
- 3, 170, :_reduce_199,
- 3, 170, :_reduce_200,
- 3, 170, :_reduce_201,
- 3, 170, :_reduce_202,
- 3, 170, :_reduce_203,
- 3, 170, :_reduce_204,
- 3, 170, :_reduce_205,
- 3, 170, :_reduce_206,
- 4, 170, :_reduce_207,
- 4, 170, :_reduce_208,
- 2, 170, :_reduce_209,
- 2, 170, :_reduce_210,
- 3, 170, :_reduce_211,
- 3, 170, :_reduce_212,
- 3, 170, :_reduce_213,
- 3, 170, :_reduce_214,
- 3, 170, :_reduce_215,
- 3, 170, :_reduce_216,
- 3, 170, :_reduce_217,
- 3, 170, :_reduce_218,
- 3, 170, :_reduce_219,
- 3, 170, :_reduce_220,
- 3, 170, :_reduce_221,
- 3, 170, :_reduce_222,
- 3, 170, :_reduce_223,
- 2, 170, :_reduce_224,
- 2, 170, :_reduce_225,
- 3, 170, :_reduce_226,
- 3, 170, :_reduce_227,
- 3, 170, :_reduce_228,
- 3, 170, :_reduce_229,
- 3, 170, :_reduce_230,
- 5, 170, :_reduce_231,
- 1, 170, :_reduce_none,
- 1, 167, :_reduce_none,
- 1, 164, :_reduce_234,
- 2, 164, :_reduce_235,
- 2, 164, :_reduce_236,
- 4, 164, :_reduce_237,
- 2, 164, :_reduce_238,
- 3, 199, :_reduce_239,
- 2, 201, :_reduce_none,
- 1, 202, :_reduce_241,
- 1, 202, :_reduce_none,
- 1, 200, :_reduce_243,
- 1, 200, :_reduce_none,
- 2, 200, :_reduce_245,
- 4, 200, :_reduce_246,
- 2, 200, :_reduce_247,
- 1, 173, :_reduce_248,
- 2, 173, :_reduce_249,
- 2, 173, :_reduce_250,
- 4, 173, :_reduce_251,
- 1, 173, :_reduce_252,
- 4, 205, :_reduce_none,
- 1, 205, :_reduce_none,
- 0, 207, :_reduce_255,
- 2, 176, :_reduce_256,
- 1, 206, :_reduce_none,
- 2, 206, :_reduce_258,
- 3, 206, :_reduce_259,
- 2, 204, :_reduce_260,
- 2, 203, :_reduce_261,
- 0, 203, :_reduce_262,
- 1, 196, :_reduce_263,
- 2, 196, :_reduce_264,
- 3, 196, :_reduce_265,
- 4, 196, :_reduce_266,
- 3, 166, :_reduce_267,
- 4, 166, :_reduce_268,
- 2, 166, :_reduce_269,
- 1, 194, :_reduce_none,
- 1, 194, :_reduce_none,
- 1, 194, :_reduce_none,
- 1, 194, :_reduce_none,
- 1, 194, :_reduce_none,
- 1, 194, :_reduce_none,
- 1, 194, :_reduce_none,
- 1, 194, :_reduce_none,
- 1, 194, :_reduce_none,
- 0, 229, :_reduce_279,
- 4, 194, :_reduce_280,
- 4, 194, :_reduce_281,
- 3, 194, :_reduce_282,
- 3, 194, :_reduce_283,
- 2, 194, :_reduce_284,
- 4, 194, :_reduce_285,
- 4, 194, :_reduce_286,
- 3, 194, :_reduce_287,
- 3, 194, :_reduce_288,
- 1, 194, :_reduce_289,
- 4, 194, :_reduce_290,
- 3, 194, :_reduce_291,
- 1, 194, :_reduce_292,
- 5, 194, :_reduce_293,
- 4, 194, :_reduce_294,
- 3, 194, :_reduce_295,
- 2, 194, :_reduce_296,
- 1, 194, :_reduce_none,
- 2, 194, :_reduce_298,
- 2, 194, :_reduce_299,
- 6, 194, :_reduce_300,
- 6, 194, :_reduce_301,
- 0, 230, :_reduce_302,
- 0, 231, :_reduce_303,
- 7, 194, :_reduce_304,
- 0, 232, :_reduce_305,
- 0, 233, :_reduce_306,
- 7, 194, :_reduce_307,
- 5, 194, :_reduce_308,
- 4, 194, :_reduce_309,
- 5, 194, :_reduce_310,
- 0, 234, :_reduce_311,
- 0, 235, :_reduce_312,
- 9, 194, :_reduce_313,
- 0, 236, :_reduce_314,
- 6, 194, :_reduce_315,
- 0, 237, :_reduce_316,
- 0, 238, :_reduce_317,
- 8, 194, :_reduce_318,
- 0, 239, :_reduce_319,
- 0, 240, :_reduce_320,
- 6, 194, :_reduce_321,
- 0, 241, :_reduce_322,
- 6, 194, :_reduce_323,
- 0, 242, :_reduce_324,
- 0, 243, :_reduce_325,
- 9, 194, :_reduce_326,
- 1, 194, :_reduce_327,
- 1, 194, :_reduce_328,
- 1, 194, :_reduce_329,
- 1, 194, :_reduce_none,
- 1, 163, :_reduce_none,
- 1, 219, :_reduce_none,
- 1, 219, :_reduce_none,
- 1, 219, :_reduce_none,
- 2, 219, :_reduce_none,
- 1, 221, :_reduce_none,
- 1, 221, :_reduce_none,
- 1, 221, :_reduce_none,
- 2, 218, :_reduce_339,
- 3, 244, :_reduce_340,
- 2, 244, :_reduce_341,
- 1, 244, :_reduce_none,
- 1, 244, :_reduce_none,
- 3, 245, :_reduce_344,
- 3, 245, :_reduce_345,
- 1, 220, :_reduce_346,
- 5, 220, :_reduce_347,
- 1, 153, :_reduce_none,
- 2, 153, :_reduce_349,
- 1, 247, :_reduce_350,
- 3, 247, :_reduce_351,
- 3, 248, :_reduce_352,
- 1, 178, :_reduce_none,
- 2, 178, :_reduce_354,
- 1, 178, :_reduce_355,
- 3, 178, :_reduce_356,
- 1, 249, :_reduce_357,
- 2, 251, :_reduce_358,
- 1, 251, :_reduce_359,
- 6, 246, :_reduce_360,
- 4, 246, :_reduce_361,
- 4, 246, :_reduce_362,
- 2, 246, :_reduce_363,
- 2, 246, :_reduce_364,
- 4, 246, :_reduce_365,
- 2, 246, :_reduce_366,
- 2, 246, :_reduce_367,
- 1, 246, :_reduce_368,
- 0, 255, :_reduce_369,
- 5, 254, :_reduce_370,
- 2, 174, :_reduce_371,
- 4, 174, :_reduce_none,
- 4, 174, :_reduce_none,
- 4, 174, :_reduce_none,
- 2, 217, :_reduce_375,
- 4, 217, :_reduce_376,
- 4, 217, :_reduce_377,
- 3, 217, :_reduce_378,
- 4, 217, :_reduce_379,
- 3, 217, :_reduce_380,
- 2, 217, :_reduce_381,
- 1, 217, :_reduce_382,
- 0, 257, :_reduce_383,
- 5, 216, :_reduce_384,
- 0, 258, :_reduce_385,
- 5, 216, :_reduce_386,
- 0, 260, :_reduce_387,
- 6, 222, :_reduce_388,
- 1, 259, :_reduce_389,
- 1, 259, :_reduce_none,
- 6, 152, :_reduce_391,
- 0, 152, :_reduce_392,
- 1, 261, :_reduce_393,
- 1, 261, :_reduce_none,
- 1, 261, :_reduce_none,
- 2, 262, :_reduce_396,
- 1, 262, :_reduce_397,
- 2, 154, :_reduce_398,
- 1, 154, :_reduce_none,
- 1, 208, :_reduce_none,
- 1, 208, :_reduce_none,
- 1, 208, :_reduce_none,
- 1, 209, :_reduce_403,
- 1, 265, :_reduce_none,
- 2, 265, :_reduce_405,
- 3, 266, :_reduce_406,
- 1, 266, :_reduce_407,
- 3, 210, :_reduce_408,
- 3, 211, :_reduce_409,
- 3, 212, :_reduce_410,
- 3, 212, :_reduce_411,
- 1, 269, :_reduce_412,
- 3, 269, :_reduce_413,
- 1, 270, :_reduce_414,
- 2, 270, :_reduce_415,
- 3, 213, :_reduce_416,
- 3, 213, :_reduce_417,
- 1, 272, :_reduce_418,
- 3, 272, :_reduce_419,
- 1, 267, :_reduce_420,
- 2, 267, :_reduce_421,
- 1, 268, :_reduce_422,
- 2, 268, :_reduce_423,
- 1, 271, :_reduce_424,
- 0, 274, :_reduce_425,
- 3, 271, :_reduce_426,
- 0, 275, :_reduce_427,
- 4, 271, :_reduce_428,
- 1, 273, :_reduce_429,
- 1, 273, :_reduce_430,
- 1, 273, :_reduce_431,
- 1, 273, :_reduce_none,
- 2, 192, :_reduce_433,
- 1, 192, :_reduce_434,
- 1, 276, :_reduce_none,
- 1, 276, :_reduce_none,
- 1, 276, :_reduce_none,
- 1, 276, :_reduce_none,
- 3, 264, :_reduce_439,
- 1, 263, :_reduce_440,
- 1, 263, :_reduce_441,
- 2, 263, :_reduce_442,
- 2, 263, :_reduce_443,
- 2, 263, :_reduce_444,
- 2, 263, :_reduce_445,
- 1, 186, :_reduce_446,
- 1, 186, :_reduce_447,
- 1, 186, :_reduce_448,
- 1, 186, :_reduce_449,
- 1, 186, :_reduce_450,
- 1, 186, :_reduce_451,
- 1, 186, :_reduce_452,
- 1, 186, :_reduce_453,
- 1, 186, :_reduce_454,
- 1, 186, :_reduce_455,
- 1, 186, :_reduce_456,
- 1, 214, :_reduce_457,
- 1, 162, :_reduce_458,
- 1, 165, :_reduce_459,
- 1, 165, :_reduce_none,
- 1, 224, :_reduce_461,
- 3, 224, :_reduce_462,
- 2, 224, :_reduce_463,
- 4, 226, :_reduce_464,
- 2, 226, :_reduce_465,
- 1, 278, :_reduce_none,
- 1, 278, :_reduce_none,
- 2, 279, :_reduce_468,
- 1, 279, :_reduce_469,
- 1, 280, :_reduce_470,
- 2, 281, :_reduce_471,
- 1, 281, :_reduce_472,
- 1, 282, :_reduce_473,
- 3, 282, :_reduce_474,
- 4, 283, :_reduce_475,
- 2, 283, :_reduce_476,
- 2, 283, :_reduce_477,
- 1, 283, :_reduce_478,
- 2, 285, :_reduce_479,
- 0, 285, :_reduce_480,
- 6, 277, :_reduce_481,
- 4, 277, :_reduce_482,
- 4, 277, :_reduce_483,
- 2, 277, :_reduce_484,
- 4, 277, :_reduce_485,
- 2, 277, :_reduce_486,
- 2, 277, :_reduce_487,
- 1, 277, :_reduce_488,
- 0, 277, :_reduce_489,
- 1, 287, :_reduce_none,
- 1, 287, :_reduce_491,
- 1, 288, :_reduce_492,
- 1, 288, :_reduce_493,
- 1, 288, :_reduce_494,
- 1, 288, :_reduce_495,
- 1, 289, :_reduce_496,
- 3, 289, :_reduce_497,
- 1, 223, :_reduce_none,
- 1, 223, :_reduce_none,
- 1, 291, :_reduce_500,
- 3, 291, :_reduce_none,
- 1, 292, :_reduce_502,
- 3, 292, :_reduce_503,
- 1, 290, :_reduce_none,
- 4, 290, :_reduce_none,
- 3, 290, :_reduce_none,
- 2, 290, :_reduce_none,
- 1, 290, :_reduce_none,
- 1, 252, :_reduce_509,
- 3, 252, :_reduce_510,
- 3, 293, :_reduce_511,
- 1, 286, :_reduce_512,
- 3, 286, :_reduce_513,
- 1, 294, :_reduce_none,
- 1, 294, :_reduce_none,
- 2, 253, :_reduce_516,
- 1, 253, :_reduce_517,
- 1, 295, :_reduce_none,
- 1, 295, :_reduce_none,
- 2, 250, :_reduce_520,
- 2, 284, :_reduce_521,
- 0, 284, :_reduce_522,
- 1, 227, :_reduce_523,
- 4, 227, :_reduce_524,
- 0, 215, :_reduce_525,
- 2, 215, :_reduce_526,
- 1, 198, :_reduce_527,
- 3, 198, :_reduce_528,
- 3, 296, :_reduce_529,
- 2, 296, :_reduce_530,
- 1, 179, :_reduce_none,
- 1, 179, :_reduce_none,
- 1, 179, :_reduce_none,
- 1, 175, :_reduce_none,
- 1, 175, :_reduce_none,
- 1, 175, :_reduce_none,
- 1, 175, :_reduce_none,
- 1, 256, :_reduce_none,
- 1, 256, :_reduce_none,
- 1, 256, :_reduce_none,
- 1, 228, :_reduce_none,
- 1, 228, :_reduce_none,
- 0, 146, :_reduce_none,
- 1, 146, :_reduce_none,
- 0, 193, :_reduce_none,
- 1, 193, :_reduce_none,
- 0, 197, :_reduce_none,
- 1, 197, :_reduce_none,
- 1, 197, :_reduce_none,
- 1, 225, :_reduce_none,
- 1, 225, :_reduce_none,
- 1, 148, :_reduce_none,
- 2, 148, :_reduce_none,
- 0, 195, :_reduce_554 ]
-
-racc_reduce_n = 555
-
-racc_shift_n = 968
-
-racc_token_table = {
- false => 0,
- :error => 1,
- :kCLASS => 2,
- :kMODULE => 3,
- :kDEF => 4,
- :kUNDEF => 5,
- :kBEGIN => 6,
- :kRESCUE => 7,
- :kENSURE => 8,
- :kEND => 9,
- :kIF => 10,
- :kUNLESS => 11,
- :kTHEN => 12,
- :kELSIF => 13,
- :kELSE => 14,
- :kCASE => 15,
- :kWHEN => 16,
- :kWHILE => 17,
- :kUNTIL => 18,
- :kFOR => 19,
- :kBREAK => 20,
- :kNEXT => 21,
- :kREDO => 22,
- :kRETRY => 23,
- :kIN => 24,
- :kDO => 25,
- :kDO_COND => 26,
- :kDO_BLOCK => 27,
- :kDO_LAMBDA => 28,
- :kRETURN => 29,
- :kYIELD => 30,
- :kSUPER => 31,
- :kSELF => 32,
- :kNIL => 33,
- :kTRUE => 34,
- :kFALSE => 35,
- :kAND => 36,
- :kOR => 37,
- :kNOT => 38,
- :kIF_MOD => 39,
- :kUNLESS_MOD => 40,
- :kWHILE_MOD => 41,
- :kUNTIL_MOD => 42,
- :kRESCUE_MOD => 43,
- :kALIAS => 44,
- :kDEFINED => 45,
- :klBEGIN => 46,
- :klEND => 47,
- :k__LINE__ => 48,
- :k__FILE__ => 49,
- :k__ENCODING__ => 50,
- :tIDENTIFIER => 51,
- :tFID => 52,
- :tGVAR => 53,
- :tIVAR => 54,
- :tCONSTANT => 55,
- :tLABEL => 56,
- :tCVAR => 57,
- :tNTH_REF => 58,
- :tBACK_REF => 59,
- :tSTRING_CONTENT => 60,
- :tINTEGER => 61,
- :tFLOAT => 62,
- :tREGEXP_END => 63,
- :tUPLUS => 64,
- :tUMINUS => 65,
- :tUMINUS_NUM => 66,
- :tPOW => 67,
- :tCMP => 68,
- :tEQ => 69,
- :tEQQ => 70,
- :tNEQ => 71,
- :tGEQ => 72,
- :tLEQ => 73,
- :tANDOP => 74,
- :tOROP => 75,
- :tMATCH => 76,
- :tNMATCH => 77,
- :tJSDOT => 78,
- :tDOT => 79,
- :tDOT2 => 80,
- :tDOT3 => 81,
- :tAREF => 82,
- :tASET => 83,
- :tLSHFT => 84,
- :tRSHFT => 85,
- :tCOLON2 => 86,
- :tCOLON3 => 87,
- :tOP_ASGN => 88,
- :tASSOC => 89,
- :tLPAREN => 90,
- :tLPAREN2 => 91,
- :tRPAREN => 92,
- :tLPAREN_ARG => 93,
- :ARRAY_BEG => 94,
- :tRBRACK => 95,
- :tLBRACE => 96,
- :tLBRACE_ARG => 97,
- :tSTAR => 98,
- :tSTAR2 => 99,
- :tAMPER => 100,
- :tAMPER2 => 101,
- :tTILDE => 102,
- :tPERCENT => 103,
- :tDIVIDE => 104,
- :tPLUS => 105,
- :tMINUS => 106,
- :tLT => 107,
- :tGT => 108,
- :tPIPE => 109,
- :tBANG => 110,
- :tCARET => 111,
- :tLCURLY => 112,
- :tRCURLY => 113,
- :tBACK_REF2 => 114,
- :tSYMBEG => 115,
- :tSTRING_BEG => 116,
- :tXSTRING_BEG => 117,
- :tREGEXP_BEG => 118,
- :tWORDS_BEG => 119,
- :tAWORDS_BEG => 120,
- :tSTRING_DBEG => 121,
- :tSTRING_DVAR => 122,
- :tSTRING_END => 123,
- :tSTRING => 124,
- :tSYMBOL => 125,
- :tNL => 126,
- :tEH => 127,
- :tCOLON => 128,
- :tCOMMA => 129,
- :tSPACE => 130,
- :tSEMI => 131,
- :tLAMBDA => 132,
- :tLAMBEG => 133,
- :tLBRACK2 => 134,
- :tLBRACK => 135,
- :tJSLBRACK => 136,
- :tDSTAR => 137,
- :tEQL => 138,
- :tLOWEST => 139,
- "-@NUM" => 140,
- "+@NUM" => 141 }
-
-racc_nt_base = 142
-
-racc_use_result_var = true
-
-Racc_arg = [
- racc_action_table,
- racc_action_check,
- racc_action_default,
- racc_action_pointer,
- racc_goto_table,
- racc_goto_check,
- racc_goto_default,
- racc_goto_pointer,
- racc_nt_base,
- racc_reduce_table,
- racc_token_table,
- racc_shift_n,
- racc_reduce_n,
- racc_use_result_var ]
-
-Racc_token_to_s_table = [
- "$end",
- "error",
- "kCLASS",
- "kMODULE",
- "kDEF",
- "kUNDEF",
- "kBEGIN",
- "kRESCUE",
- "kENSURE",
- "kEND",
- "kIF",
- "kUNLESS",
- "kTHEN",
- "kELSIF",
- "kELSE",
- "kCASE",
- "kWHEN",
- "kWHILE",
- "kUNTIL",
- "kFOR",
- "kBREAK",
- "kNEXT",
- "kREDO",
- "kRETRY",
- "kIN",
- "kDO",
- "kDO_COND",
- "kDO_BLOCK",
- "kDO_LAMBDA",
- "kRETURN",
- "kYIELD",
- "kSUPER",
- "kSELF",
- "kNIL",
- "kTRUE",
- "kFALSE",
- "kAND",
- "kOR",
- "kNOT",
- "kIF_MOD",
- "kUNLESS_MOD",
- "kWHILE_MOD",
- "kUNTIL_MOD",
- "kRESCUE_MOD",
- "kALIAS",
- "kDEFINED",
- "klBEGIN",
- "klEND",
- "k__LINE__",
- "k__FILE__",
- "k__ENCODING__",
- "tIDENTIFIER",
- "tFID",
- "tGVAR",
- "tIVAR",
- "tCONSTANT",
- "tLABEL",
- "tCVAR",
- "tNTH_REF",
- "tBACK_REF",
- "tSTRING_CONTENT",
- "tINTEGER",
- "tFLOAT",
- "tREGEXP_END",
- "tUPLUS",
- "tUMINUS",
- "tUMINUS_NUM",
- "tPOW",
- "tCMP",
- "tEQ",
- "tEQQ",
- "tNEQ",
- "tGEQ",
- "tLEQ",
- "tANDOP",
- "tOROP",
- "tMATCH",
- "tNMATCH",
- "tJSDOT",
- "tDOT",
- "tDOT2",
- "tDOT3",
- "tAREF",
- "tASET",
- "tLSHFT",
- "tRSHFT",
- "tCOLON2",
- "tCOLON3",
- "tOP_ASGN",
- "tASSOC",
- "tLPAREN",
- "tLPAREN2",
- "tRPAREN",
- "tLPAREN_ARG",
- "ARRAY_BEG",
- "tRBRACK",
- "tLBRACE",
- "tLBRACE_ARG",
- "tSTAR",
- "tSTAR2",
- "tAMPER",
- "tAMPER2",
- "tTILDE",
- "tPERCENT",
- "tDIVIDE",
- "tPLUS",
- "tMINUS",
- "tLT",
- "tGT",
- "tPIPE",
- "tBANG",
- "tCARET",
- "tLCURLY",
- "tRCURLY",
- "tBACK_REF2",
- "tSYMBEG",
- "tSTRING_BEG",
- "tXSTRING_BEG",
- "tREGEXP_BEG",
- "tWORDS_BEG",
- "tAWORDS_BEG",
- "tSTRING_DBEG",
- "tSTRING_DVAR",
- "tSTRING_END",
- "tSTRING",
- "tSYMBOL",
- "tNL",
- "tEH",
- "tCOLON",
- "tCOMMA",
- "tSPACE",
- "tSEMI",
- "tLAMBDA",
- "tLAMBEG",
- "tLBRACK2",
- "tLBRACK",
- "tJSLBRACK",
- "tDSTAR",
- "tEQL",
- "tLOWEST",
- "\"-@NUM\"",
- "\"+@NUM\"",
- "$start",
- "program",
- "top_compstmt",
- "top_stmts",
- "opt_terms",
- "top_stmt",
- "terms",
- "stmt",
- "bodystmt",
- "compstmt",
- "opt_rescue",
- "opt_else",
- "opt_ensure",
- "stmts",
- "fitem",
- "undef_list",
- "expr_value",
- "lhs",
- "command_call",
- "mlhs",
- "var_lhs",
- "primary_value",
- "aref_args",
- "backref",
- "mrhs",
- "arg_value",
- "expr",
- "@1",
- "arg",
- "command",
- "block_command",
- "call_args",
- "block_call",
- "operation2",
- "command_args",
- "cmd_brace_block",
- "opt_block_var",
- "operation",
- "mlhs_basic",
- "mlhs_entry",
- "mlhs_head",
- "mlhs_item",
- "mlhs_node",
- "mlhs_post",
- "variable",
- "cname",
- "cpath",
- "fname",
- "op",
- "reswords",
- "symbol",
- "opt_nl",
- "primary",
- "none",
- "args",
- "trailer",
- "assocs",
- "paren_args",
- "opt_call_args",
- "rparen",
- "opt_paren_args",
- "opt_block_arg",
- "block_arg",
- "call_args2",
- "open_args",
- "@2",
- "literal",
- "strings",
- "xstring",
- "regexp",
- "words",
- "awords",
- "var_ref",
- "assoc_list",
- "brace_block",
- "method_call",
- "lambda",
- "then",
- "if_tail",
- "do",
- "case_body",
- "for_var",
- "superclass",
- "term",
- "f_arglist",
- "singleton",
- "dot_or_colon",
- "@3",
- "@4",
- "@5",
- "@6",
- "@7",
- "@8",
- "@9",
- "@10",
- "@11",
- "@12",
- "@13",
- "@14",
- "@15",
- "@16",
- "@17",
- "f_larglist",
- "lambda_body",
- "block_param",
- "f_block_optarg",
- "f_block_opt",
- "block_args_tail",
- "f_block_arg",
- "opt_block_args_tail",
- "f_arg",
- "f_rest_arg",
- "do_block",
- "@18",
- "operation3",
- "@19",
- "@20",
- "cases",
- "@21",
- "exc_list",
- "exc_var",
- "numeric",
- "dsym",
- "string",
- "string1",
- "string_contents",
- "xstring_contents",
- "word_list",
- "word",
- "string_content",
- "qword_list",
- "string_dvar",
- "@22",
- "@23",
- "sym",
- "f_args",
- "kwrest_mark",
- "f_kwrest",
- "f_label",
- "f_kw",
- "f_kwarg",
- "args_tail",
- "opt_f_block_arg",
- "opt_args_tail",
- "f_optarg",
- "f_norm_arg",
- "f_bad_arg",
- "f_arg_item",
- "f_margs",
- "f_marg",
- "f_marg_list",
- "f_opt",
- "restarg_mark",
- "blkarg_mark",
- "assoc" ]
-
-Racc_debug_parser = false
-
-##### State transition tables end #####
-
-# reduce 0 omitted
-
-# reduce 1 omitted
-
-module_eval(<<'.,.,', 'opal.y', 70)
- def _reduce_2(val, _values, result)
- result = new_compstmt val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 75)
- def _reduce_3(val, _values, result)
- result = new_block
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 79)
- def _reduce_4(val, _values, result)
- result = new_block val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 83)
- def _reduce_5(val, _values, result)
- val[0] << val[2]
- result = val[0]
-
- result
- end
-.,.,
-
-# reduce 6 omitted
-
-module_eval(<<'.,.,', 'opal.y', 90)
- def _reduce_7(val, _values, result)
- result = val[2]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 95)
- def _reduce_8(val, _values, result)
- result = new_body(val[0], val[1], val[2], val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 100)
- def _reduce_9(val, _values, result)
- result = new_compstmt val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 105)
- def _reduce_10(val, _values, result)
- result = new_block
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 109)
- def _reduce_11(val, _values, result)
- result = new_block val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 113)
- def _reduce_12(val, _values, result)
- val[0] << val[2]
- result = val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 119)
- def _reduce_13(val, _values, result)
- lexer.lex_state = :expr_fname
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 123)
- def _reduce_14(val, _values, result)
- result = new_alias(val[0], val[1], val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 127)
- def _reduce_15(val, _values, result)
- result = s(:valias, value(val[1]).to_sym, value(val[2]).to_sym)
-
- result
- end
-.,.,
-
-# reduce 16 omitted
-
-module_eval(<<'.,.,', 'opal.y', 132)
- def _reduce_17(val, _values, result)
- result = s(:valias, value(val[1]).to_sym, value(val[2]).to_sym)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 136)
- def _reduce_18(val, _values, result)
- result = val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 140)
- def _reduce_19(val, _values, result)
- result = new_if(val[1], val[2], val[0], nil)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 144)
- def _reduce_20(val, _values, result)
- result = new_if(val[1], val[2], nil, val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 148)
- def _reduce_21(val, _values, result)
- result = new_while(val[1], val[2], val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 152)
- def _reduce_22(val, _values, result)
- result = new_until(val[1], val[2], val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 156)
- def _reduce_23(val, _values, result)
- result = new_rescue_mod(val[1], val[0], val[2])
-
- result
- end
-.,.,
-
-# reduce 24 omitted
-
-module_eval(<<'.,.,', 'opal.y', 161)
- def _reduce_25(val, _values, result)
- result = new_assign(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 165)
- def _reduce_26(val, _values, result)
- result = s(:masgn, val[0], s(:to_ary, val[2]))
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 169)
- def _reduce_27(val, _values, result)
- result = new_op_asgn val[1], val[0], val[2]
-
- result
- end
-.,.,
-
-# reduce 28 omitted
-
-# reduce 29 omitted
-
-module_eval(<<'.,.,', 'opal.y', 175)
- def _reduce_30(val, _values, result)
- result = s(:op_asgn2, val[0], op_to_setter(val[2]), value(val[3]).to_sym, val[4])
-
- result
- end
-.,.,
-
-# reduce 31 omitted
-
-# reduce 32 omitted
-
-# reduce 33 omitted
-
-module_eval(<<'.,.,', 'opal.y', 182)
- def _reduce_34(val, _values, result)
- result = new_assign val[0], val[1], s(:svalue, val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 186)
- def _reduce_35(val, _values, result)
- result = s(:masgn, val[0], s(:to_ary, val[2]))
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 190)
- def _reduce_36(val, _values, result)
- result = s(:masgn, val[0], val[2])
-
- result
- end
-.,.,
-
-# reduce 37 omitted
-
-# reduce 38 omitted
-
-module_eval(<<'.,.,', 'opal.y', 197)
- def _reduce_39(val, _values, result)
- result = s(:and, val[0], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 201)
- def _reduce_40(val, _values, result)
- result = s(:or, val[0], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 205)
- def _reduce_41(val, _values, result)
- result = new_unary_call(['!', []], val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 209)
- def _reduce_42(val, _values, result)
- result = new_unary_call(val[0], val[1])
-
- result
- end
-.,.,
-
-# reduce 43 omitted
-
-# reduce 44 omitted
-
-# reduce 45 omitted
-
-# reduce 46 omitted
-
-module_eval(<<'.,.,', 'opal.y', 219)
- def _reduce_47(val, _values, result)
- result = new_return(val[0], val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 223)
- def _reduce_48(val, _values, result)
- result = new_break(val[0], val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 227)
- def _reduce_49(val, _values, result)
- result = new_next(val[0], val[1])
-
- result
- end
-.,.,
-
-# reduce 50 omitted
-
-# reduce 51 omitted
-
-# reduce 52 omitted
-
-# reduce 53 omitted
-
-# reduce 54 omitted
-
-module_eval(<<'.,.,', 'opal.y', 239)
- def _reduce_55(val, _values, result)
- result = new_call(nil, val[0], val[1])
-
- result
- end
-.,.,
-
-# reduce 56 omitted
-
-module_eval(<<'.,.,', 'opal.y', 244)
- def _reduce_57(val, _values, result)
- result = new_js_call(val[0], val[2], val[3])
-
- result
- end
-.,.,
-
-# reduce 58 omitted
-
-module_eval(<<'.,.,', 'opal.y', 249)
- def _reduce_59(val, _values, result)
- result = new_call(val[0], val[2], val[3])
-
- result
- end
-.,.,
-
-# reduce 60 omitted
-
-module_eval(<<'.,.,', 'opal.y', 254)
- def _reduce_61(val, _values, result)
- result = new_call(val[0], val[2], val[3])
-
- result
- end
-.,.,
-
-# reduce 62 omitted
-
-module_eval(<<'.,.,', 'opal.y', 259)
- def _reduce_63(val, _values, result)
- result = new_super(val[0], val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 263)
- def _reduce_64(val, _values, result)
- result = new_yield val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 268)
- def _reduce_65(val, _values, result)
- result = val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 272)
- def _reduce_66(val, _values, result)
- result = val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 277)
- def _reduce_67(val, _values, result)
- result = val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 281)
- def _reduce_68(val, _values, result)
- result = val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 286)
- def _reduce_69(val, _values, result)
- result = val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 290)
- def _reduce_70(val, _values, result)
- result = val[0] << val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 294)
- def _reduce_71(val, _values, result)
- result = val[0] << s(:splat, val[2])
-
- result
- end
-.,.,
-
-# reduce 72 omitted
-
-module_eval(<<'.,.,', 'opal.y', 299)
- def _reduce_73(val, _values, result)
- result = val[0] << s(:splat)
-
- result
- end
-.,.,
-
-# reduce 74 omitted
-
-module_eval(<<'.,.,', 'opal.y', 304)
- def _reduce_75(val, _values, result)
- result = s(:array, s(:splat, val[1]))
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 308)
- def _reduce_76(val, _values, result)
- result = s(:array, s(:splat))
-
- result
- end
-.,.,
-
-# reduce 77 omitted
-
-module_eval(<<'.,.,', 'opal.y', 314)
- def _reduce_78(val, _values, result)
- result = val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 318)
- def _reduce_79(val, _values, result)
- result = val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 323)
- def _reduce_80(val, _values, result)
- result = s(:array, val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 327)
- def _reduce_81(val, _values, result)
- result = val[0] << val[1]
-
- result
- end
-.,.,
-
-# reduce 82 omitted
-
-# reduce 83 omitted
-
-module_eval(<<'.,.,', 'opal.y', 335)
- def _reduce_84(val, _values, result)
- result = new_assignable val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 339)
- def _reduce_85(val, _values, result)
- args = val[2] ? val[2] : []
- result = s(:attrasgn, val[0], :[]=, s(:arglist, *args))
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 344)
- def _reduce_86(val, _values, result)
- result = new_call val[0], val[2], []
-
- result
- end
-.,.,
-
-# reduce 87 omitted
-
-# reduce 88 omitted
-
-# reduce 89 omitted
-
-# reduce 90 omitted
-
-# reduce 91 omitted
-
-module_eval(<<'.,.,', 'opal.y', 354)
- def _reduce_92(val, _values, result)
- result = new_assignable val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 358)
- def _reduce_93(val, _values, result)
- result = new_js_attrasgn(val[0], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 362)
- def _reduce_94(val, _values, result)
- result = new_attrasgn(val[0], :[]=, val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 366)
- def _reduce_95(val, _values, result)
- result = new_attrasgn(val[0], op_to_setter(val[2]))
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 370)
- def _reduce_96(val, _values, result)
- result = new_attrasgn(val[0], op_to_setter(val[2]))
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 374)
- def _reduce_97(val, _values, result)
- result = new_attrasgn(val[0], op_to_setter(val[2]))
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 378)
- def _reduce_98(val, _values, result)
- result = new_colon2(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 382)
- def _reduce_99(val, _values, result)
- result = new_colon3(val[0], val[1])
-
- result
- end
-.,.,
-
-# reduce 100 omitted
-
-# reduce 101 omitted
-
-module_eval(<<'.,.,', 'opal.y', 390)
- def _reduce_102(val, _values, result)
- result = new_colon3(val[0], val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 394)
- def _reduce_103(val, _values, result)
- result = new_const(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 398)
- def _reduce_104(val, _values, result)
- result = new_colon2(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-# reduce 105 omitted
-
-# reduce 106 omitted
-
-# reduce 107 omitted
-
-module_eval(<<'.,.,', 'opal.y', 406)
- def _reduce_108(val, _values, result)
- lexer.lex_state = :expr_end
- result = val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 411)
- def _reduce_109(val, _values, result)
- lexer.lex_state = :expr_end
- result = val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 417)
- def _reduce_110(val, _values, result)
- result = new_sym(val[0])
-
- result
- end
-.,.,
-
-# reduce 111 omitted
-
-module_eval(<<'.,.,', 'opal.y', 423)
- def _reduce_112(val, _values, result)
- result = s(:undef, val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 427)
- def _reduce_113(val, _values, result)
- result = val[0] << val[2]
-
- result
- end
-.,.,
-
-# reduce 114 omitted
-
-# reduce 115 omitted
-
-# reduce 116 omitted
-
-# reduce 117 omitted
-
-# reduce 118 omitted
-
-# reduce 119 omitted
-
-# reduce 120 omitted
-
-# reduce 121 omitted
-
-# reduce 122 omitted
-
-# reduce 123 omitted
-
-# reduce 124 omitted
-
-# reduce 125 omitted
-
-# reduce 126 omitted
-
-# reduce 127 omitted
-
-# reduce 128 omitted
-
-# reduce 129 omitted
-
-# reduce 130 omitted
-
-# reduce 131 omitted
-
-# reduce 132 omitted
-
-# reduce 133 omitted
-
-# reduce 134 omitted
-
-# reduce 135 omitted
-
-# reduce 136 omitted
-
-# reduce 137 omitted
-
-# reduce 138 omitted
-
-# reduce 139 omitted
-
-# reduce 140 omitted
-
-# reduce 141 omitted
-
-# reduce 142 omitted
-
-# reduce 143 omitted
-
-# reduce 144 omitted
-
-# reduce 145 omitted
-
-# reduce 146 omitted
-
-# reduce 147 omitted
-
-# reduce 148 omitted
-
-# reduce 149 omitted
-
-# reduce 150 omitted
-
-# reduce 151 omitted
-
-# reduce 152 omitted
-
-# reduce 153 omitted
-
-# reduce 154 omitted
-
-# reduce 155 omitted
-
-# reduce 156 omitted
-
-# reduce 157 omitted
-
-# reduce 158 omitted
-
-# reduce 159 omitted
-
-# reduce 160 omitted
-
-# reduce 161 omitted
-
-# reduce 162 omitted
-
-# reduce 163 omitted
-
-# reduce 164 omitted
-
-# reduce 165 omitted
-
-# reduce 166 omitted
-
-# reduce 167 omitted
-
-# reduce 168 omitted
-
-# reduce 169 omitted
-
-# reduce 170 omitted
-
-# reduce 171 omitted
-
-# reduce 172 omitted
-
-# reduce 173 omitted
-
-# reduce 174 omitted
-
-# reduce 175 omitted
-
-# reduce 176 omitted
-
-# reduce 177 omitted
-
-# reduce 178 omitted
-
-# reduce 179 omitted
-
-# reduce 180 omitted
-
-# reduce 181 omitted
-
-# reduce 182 omitted
-
-# reduce 183 omitted
-
-# reduce 184 omitted
-
-# reduce 185 omitted
-
-# reduce 186 omitted
-
-# reduce 187 omitted
-
-module_eval(<<'.,.,', 'opal.y', 447)
- def _reduce_188(val, _values, result)
- result = new_assign(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 451)
- def _reduce_189(val, _values, result)
- result = new_assign val[0], val[1], s(:rescue_mod, val[2], val[4])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 455)
- def _reduce_190(val, _values, result)
- result = new_op_asgn val[1], val[0], val[2]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 459)
- def _reduce_191(val, _values, result)
- result = new_op_asgn1(val[0], val[2], val[4], val[5])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 463)
- def _reduce_192(val, _values, result)
- raise ".JS[...] #{val[4]} is not supported"
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 467)
- def _reduce_193(val, _values, result)
- result = s(:op_asgn2, val[0], op_to_setter(val[2]), value(val[3]).to_sym, val[4])
-
- result
- end
-.,.,
-
-# reduce 194 omitted
-
-# reduce 195 omitted
-
-# reduce 196 omitted
-
-# reduce 197 omitted
-
-# reduce 198 omitted
-
-module_eval(<<'.,.,', 'opal.y', 476)
- def _reduce_199(val, _values, result)
- result = new_irange(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 480)
- def _reduce_200(val, _values, result)
- result = new_erange(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 484)
- def _reduce_201(val, _values, result)
- result = new_binary_call(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 488)
- def _reduce_202(val, _values, result)
- result = new_binary_call(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 492)
- def _reduce_203(val, _values, result)
- result = new_binary_call(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 496)
- def _reduce_204(val, _values, result)
- result = new_binary_call(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 500)
- def _reduce_205(val, _values, result)
- result = new_binary_call(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 504)
- def _reduce_206(val, _values, result)
- result = new_binary_call(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 508)
- def _reduce_207(val, _values, result)
- result = new_call new_binary_call(new_int(val[1]), val[2], val[3]), [:"-@", []], []
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 512)
- def _reduce_208(val, _values, result)
- result = new_call new_binary_call(new_float(val[1]), val[2], val[3]), [:"-@", []], []
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 516)
- def _reduce_209(val, _values, result)
- result = new_call val[1], [:"+@", []], []
- if [:int, :float].include? val[1].type
- result = val[1]
- end
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 523)
- def _reduce_210(val, _values, result)
- result = new_call val[1], [:"-@", []], []
- if val[1].type == :int
- val[1][1] = -val[1][1]
- result = val[1]
- elsif val[1].type == :float
- val[1][1] = -val[1][1].to_f
- result = val[1]
- end
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 534)
- def _reduce_211(val, _values, result)
- result = new_binary_call(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 538)
- def _reduce_212(val, _values, result)
- result = new_binary_call(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 542)
- def _reduce_213(val, _values, result)
- result = new_binary_call(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 546)
- def _reduce_214(val, _values, result)
- result = new_binary_call(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 550)
- def _reduce_215(val, _values, result)
- result = new_binary_call(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 554)
- def _reduce_216(val, _values, result)
- result = new_binary_call(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 558)
- def _reduce_217(val, _values, result)
- result = new_binary_call(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 562)
- def _reduce_218(val, _values, result)
- result = new_binary_call(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 566)
- def _reduce_219(val, _values, result)
- result = new_binary_call(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 570)
- def _reduce_220(val, _values, result)
- result = new_binary_call(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 574)
- def _reduce_221(val, _values, result)
- result = new_binary_call(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 578)
- def _reduce_222(val, _values, result)
- result = new_binary_call(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 582)
- def _reduce_223(val, _values, result)
- result = new_binary_call(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 586)
- def _reduce_224(val, _values, result)
- result = new_unary_call(val[0], val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 590)
- def _reduce_225(val, _values, result)
- result = new_unary_call(val[0], val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 594)
- def _reduce_226(val, _values, result)
- result = new_binary_call(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 598)
- def _reduce_227(val, _values, result)
- result = new_binary_call(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 602)
- def _reduce_228(val, _values, result)
- result = new_and(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 606)
- def _reduce_229(val, _values, result)
- result = new_or(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 610)
- def _reduce_230(val, _values, result)
- result = s(:defined, val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 614)
- def _reduce_231(val, _values, result)
- result = new_if(val[1], val[0], val[2], val[4])
-
- result
- end
-.,.,
-
-# reduce 232 omitted
-
-# reduce 233 omitted
-
-module_eval(<<'.,.,', 'opal.y', 622)
- def _reduce_234(val, _values, result)
- result = nil
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 626)
- def _reduce_235(val, _values, result)
- result = [val[0]]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 630)
- def _reduce_236(val, _values, result)
- result = val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 634)
- def _reduce_237(val, _values, result)
- val[0] << s(:hash, *val[2])
- result = val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 639)
- def _reduce_238(val, _values, result)
- result = [s(:hash, *val[0])]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 644)
- def _reduce_239(val, _values, result)
- result = val[1]
-
- result
- end
-.,.,
-
-# reduce 240 omitted
-
-module_eval(<<'.,.,', 'opal.y', 651)
- def _reduce_241(val, _values, result)
- result = []
-
- result
- end
-.,.,
-
-# reduce 242 omitted
-
-module_eval(<<'.,.,', 'opal.y', 657)
- def _reduce_243(val, _values, result)
- result = []
-
- result
- end
-.,.,
-
-# reduce 244 omitted
-
-module_eval(<<'.,.,', 'opal.y', 662)
- def _reduce_245(val, _values, result)
- result = val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 666)
- def _reduce_246(val, _values, result)
- result = val[0]
- result << new_hash(nil, val[2], nil)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 671)
- def _reduce_247(val, _values, result)
- result = [new_hash(nil, val[0], nil)]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 676)
- def _reduce_248(val, _values, result)
- result = [val[0]]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 680)
- def _reduce_249(val, _values, result)
- result = val[0]
- add_block_pass val[0], val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 685)
- def _reduce_250(val, _values, result)
- result = [new_hash(nil, val[0], nil)]
- add_block_pass result, val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 690)
- def _reduce_251(val, _values, result)
- result = val[0]
- result << new_hash(nil, val[2], nil)
- result << val[3] if val[3]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 696)
- def _reduce_252(val, _values, result)
- result = []
- add_block_pass result, val[0]
-
- result
- end
-.,.,
-
-# reduce 253 omitted
-
-# reduce 254 omitted
-
-module_eval(<<'.,.,', 'opal.y', 704)
- def _reduce_255(val, _values, result)
- lexer.cmdarg_push 1
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 708)
- def _reduce_256(val, _values, result)
- lexer.cmdarg_pop
- result = val[1]
-
- result
- end
-.,.,
-
-# reduce 257 omitted
-
-module_eval(<<'.,.,', 'opal.y', 715)
- def _reduce_258(val, _values, result)
- result = nil
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 719)
- def _reduce_259(val, _values, result)
- result = val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 724)
- def _reduce_260(val, _values, result)
- result = new_block_pass(val[0], val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 729)
- def _reduce_261(val, _values, result)
- result = val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 733)
- def _reduce_262(val, _values, result)
- result = nil
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 738)
- def _reduce_263(val, _values, result)
- result = [val[0]]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 742)
- def _reduce_264(val, _values, result)
- result = [new_splat(val[0], val[1])]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 746)
- def _reduce_265(val, _values, result)
- result = val[0] << val[2]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 750)
- def _reduce_266(val, _values, result)
- result = val[0] << new_splat(val[2], val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 755)
- def _reduce_267(val, _values, result)
- val[0] << val[2]
- result = s(:array, *val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 760)
- def _reduce_268(val, _values, result)
- val[0] << s(:splat, val[3])
- result = s(:array, *val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 765)
- def _reduce_269(val, _values, result)
- result = s(:splat, val[1])
-
- result
- end
-.,.,
-
-# reduce 270 omitted
-
-# reduce 271 omitted
-
-# reduce 272 omitted
-
-# reduce 273 omitted
-
-# reduce 274 omitted
-
-# reduce 275 omitted
-
-# reduce 276 omitted
-
-# reduce 277 omitted
-
-# reduce 278 omitted
-
-module_eval(<<'.,.,', 'opal.y', 779)
- def _reduce_279(val, _values, result)
- result = lexer.line
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 783)
- def _reduce_280(val, _values, result)
- result = s(:begin, val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 787)
- def _reduce_281(val, _values, result)
- result = val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 791)
- def _reduce_282(val, _values, result)
- result = new_paren(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 795)
- def _reduce_283(val, _values, result)
- result = new_colon2(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 799)
- def _reduce_284(val, _values, result)
- result = new_colon3(val[0], val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 803)
- def _reduce_285(val, _values, result)
- result = new_call val[0], [:[], []], val[2]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 807)
- def _reduce_286(val, _values, result)
- result = new_js_call val[0], [:[], []], val[2]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 811)
- def _reduce_287(val, _values, result)
- result = new_array(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 815)
- def _reduce_288(val, _values, result)
- result = new_hash(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 819)
- def _reduce_289(val, _values, result)
- result = new_return(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 823)
- def _reduce_290(val, _values, result)
- result = new_yield val[2]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 827)
- def _reduce_291(val, _values, result)
- result = s(:yield)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 831)
- def _reduce_292(val, _values, result)
- result = s(:yield)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 835)
- def _reduce_293(val, _values, result)
- result = s(:defined, val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 839)
- def _reduce_294(val, _values, result)
- result = new_unary_call(['!', []], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 843)
- def _reduce_295(val, _values, result)
- result = new_unary_call(['!', []], new_nil(val[0]))
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 847)
- def _reduce_296(val, _values, result)
- result = new_call(nil, val[0], [])
- result << val[1]
-
- result
- end
-.,.,
-
-# reduce 297 omitted
-
-module_eval(<<'.,.,', 'opal.y', 853)
- def _reduce_298(val, _values, result)
- val[0] << val[1]
- result = val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 858)
- def _reduce_299(val, _values, result)
- result = val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 862)
- def _reduce_300(val, _values, result)
- result = new_if(val[0], val[1], val[3], val[4])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 866)
- def _reduce_301(val, _values, result)
- result = new_if(val[0], val[1], val[4], val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 870)
- def _reduce_302(val, _values, result)
- lexer.cond_push 1
- result = lexer.line
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 875)
- def _reduce_303(val, _values, result)
- lexer.cond_pop
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 879)
- def _reduce_304(val, _values, result)
- result = s(:while, val[2], val[5])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 883)
- def _reduce_305(val, _values, result)
- lexer.cond_push 1
- result = lexer.line
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 888)
- def _reduce_306(val, _values, result)
- lexer.cond_pop
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 892)
- def _reduce_307(val, _values, result)
- result = s(:until, val[2], val[5])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 896)
- def _reduce_308(val, _values, result)
- result = s(:case, val[1], *val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 900)
- def _reduce_309(val, _values, result)
- result = s(:case, nil, *val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 904)
- def _reduce_310(val, _values, result)
- result = s(:case, nil, val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 908)
- def _reduce_311(val, _values, result)
- lexer.cond_push 1
- result = lexer.line
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 913)
- def _reduce_312(val, _values, result)
- lexer.cond_pop
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 917)
- def _reduce_313(val, _values, result)
- result = s(:for, val[4], val[1], val[7])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 921)
- def _reduce_314(val, _values, result)
- # ...
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 925)
- def _reduce_315(val, _values, result)
- result = new_class val[0], val[1], val[2], val[4], val[5]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 929)
- def _reduce_316(val, _values, result)
- result = lexer.line
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 933)
- def _reduce_317(val, _values, result)
- # ...
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 937)
- def _reduce_318(val, _values, result)
- result = new_sclass(val[0], val[3], val[6], val[7])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 941)
- def _reduce_319(val, _values, result)
- result = lexer.line
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 945)
- def _reduce_320(val, _values, result)
- # ...
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 949)
- def _reduce_321(val, _values, result)
- result = new_module(val[0], val[2], val[4], val[5])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 953)
- def _reduce_322(val, _values, result)
- push_scope
- lexer.lex_state = :expr_endfn
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 958)
- def _reduce_323(val, _values, result)
- result = new_def(val[0], nil, val[1], val[3], val[4], val[5])
- pop_scope
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 963)
- def _reduce_324(val, _values, result)
- lexer.lex_state = :expr_fname
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 967)
- def _reduce_325(val, _values, result)
- push_scope
- lexer.lex_state = :expr_endfn
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 972)
- def _reduce_326(val, _values, result)
- result = new_def(val[0], val[1], val[4], val[6], val[7], val[8])
- pop_scope
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 977)
- def _reduce_327(val, _values, result)
- result = new_break(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 981)
- def _reduce_328(val, _values, result)
- result = s(:next)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 985)
- def _reduce_329(val, _values, result)
- result = s(:redo)
-
- result
- end
-.,.,
-
-# reduce 330 omitted
-
-# reduce 331 omitted
-
-# reduce 332 omitted
-
-# reduce 333 omitted
-
-# reduce 334 omitted
-
-# reduce 335 omitted
-
-# reduce 336 omitted
-
-# reduce 337 omitted
-
-# reduce 338 omitted
-
-module_eval(<<'.,.,', 'opal.y', 1002)
- def _reduce_339(val, _values, result)
- result = new_call nil, [:lambda, []], []
- result << new_iter(val[0], val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1008)
- def _reduce_340(val, _values, result)
- result = val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1012)
- def _reduce_341(val, _values, result)
- result = nil
-
- result
- end
-.,.,
-
-# reduce 342 omitted
-
-# reduce 343 omitted
-
-module_eval(<<'.,.,', 'opal.y', 1019)
- def _reduce_344(val, _values, result)
- result = val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1023)
- def _reduce_345(val, _values, result)
- result = val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1028)
- def _reduce_346(val, _values, result)
- result = val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1032)
- def _reduce_347(val, _values, result)
- result = new_if(val[0], val[1], val[3], val[4])
-
- result
- end
-.,.,
-
-# reduce 348 omitted
-
-module_eval(<<'.,.,', 'opal.y', 1038)
- def _reduce_349(val, _values, result)
- result = val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1043)
- def _reduce_350(val, _values, result)
- result = s(:block, val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1047)
- def _reduce_351(val, _values, result)
- val[0] << val[2]
- result = val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1053)
- def _reduce_352(val, _values, result)
- result = new_assign(new_assignable(new_ident(
- val[0])), val[1], val[2])
-
- result
- end
-.,.,
-
-# reduce 353 omitted
-
-module_eval(<<'.,.,', 'opal.y', 1060)
- def _reduce_354(val, _values, result)
- result = nil
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1064)
- def _reduce_355(val, _values, result)
- result = nil
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1068)
- def _reduce_356(val, _values, result)
- result = val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1073)
- def _reduce_357(val, _values, result)
- result = val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1078)
- def _reduce_358(val, _values, result)
- result = val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1082)
- def _reduce_359(val, _values, result)
- nil
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1087)
- def _reduce_360(val, _values, result)
- result = new_block_args(val[0], val[2], val[4], val[5])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1091)
- def _reduce_361(val, _values, result)
- result = new_block_args(val[0], val[2], nil, val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1095)
- def _reduce_362(val, _values, result)
- result = new_block_args(val[0], nil, val[2], val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1099)
- def _reduce_363(val, _values, result)
- result = new_block_args(val[0], nil, nil, nil)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1103)
- def _reduce_364(val, _values, result)
- result = new_block_args(val[0], nil, nil, val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1107)
- def _reduce_365(val, _values, result)
- result = new_block_args(nil, val[0], val[2], val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1111)
- def _reduce_366(val, _values, result)
- result = new_block_args(nil, val[0], nil, val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1115)
- def _reduce_367(val, _values, result)
- result = new_block_args(nil, nil, val[0], val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1119)
- def _reduce_368(val, _values, result)
- result = new_block_args(nil, nil, nil, val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1124)
- def _reduce_369(val, _values, result)
- push_scope :block
- result = lexer.line
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1129)
- def _reduce_370(val, _values, result)
- result = new_iter val[2], val[3]
- pop_scope
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1135)
- def _reduce_371(val, _values, result)
- val[0] << val[1]
- result = val[0]
-
- result
- end
-.,.,
-
-# reduce 372 omitted
-
-# reduce 373 omitted
-
-# reduce 374 omitted
-
-module_eval(<<'.,.,', 'opal.y', 1144)
- def _reduce_375(val, _values, result)
- result = new_call(nil, val[0], val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1148)
- def _reduce_376(val, _values, result)
- result = new_call(val[0], val[2], val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1152)
- def _reduce_377(val, _values, result)
- result = new_js_call(val[0], val[2], val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1156)
- def _reduce_378(val, _values, result)
- result = new_call(val[0], [:call, []], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1160)
- def _reduce_379(val, _values, result)
- result = new_call(val[0], val[2], val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1164)
- def _reduce_380(val, _values, result)
- result = new_call(val[0], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1168)
- def _reduce_381(val, _values, result)
- result = new_super(val[0], val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1172)
- def _reduce_382(val, _values, result)
- result = new_super(val[0], nil)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1177)
- def _reduce_383(val, _values, result)
- push_scope :block
- result = lexer.line
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1182)
- def _reduce_384(val, _values, result)
- result = new_iter val[2], val[3]
- pop_scope
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1187)
- def _reduce_385(val, _values, result)
- push_scope :block
- result = lexer.line
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1192)
- def _reduce_386(val, _values, result)
- result = new_iter val[2], val[3]
- pop_scope
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1198)
- def _reduce_387(val, _values, result)
- result = lexer.line
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1202)
- def _reduce_388(val, _values, result)
- part = s(:when, s(:array, *val[2]), val[4])
- result = [part]
- result.push(*val[5]) if val[5]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1209)
- def _reduce_389(val, _values, result)
- result = [val[0]]
-
- result
- end
-.,.,
-
-# reduce 390 omitted
-
-module_eval(<<'.,.,', 'opal.y', 1215)
- def _reduce_391(val, _values, result)
- exc = val[1] || s(:array)
- exc << new_assign(val[2], val[2], s(:gvar, '$!'.intern)) if val[2]
- result = [s(:resbody, exc, val[4])]
- result.push val[5].first if val[5]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1222)
- def _reduce_392(val, _values, result)
- result = nil
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1227)
- def _reduce_393(val, _values, result)
- result = s(:array, val[0])
-
- result
- end
-.,.,
-
-# reduce 394 omitted
-
-# reduce 395 omitted
-
-module_eval(<<'.,.,', 'opal.y', 1234)
- def _reduce_396(val, _values, result)
- result = val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1238)
- def _reduce_397(val, _values, result)
- result = nil
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1243)
- def _reduce_398(val, _values, result)
- result = val[1].nil? ? s(:nil) : val[1]
-
- result
- end
-.,.,
-
-# reduce 399 omitted
-
-# reduce 400 omitted
-
-# reduce 401 omitted
-
-# reduce 402 omitted
-
-module_eval(<<'.,.,', 'opal.y', 1253)
- def _reduce_403(val, _values, result)
- result = new_str val[0]
-
- result
- end
-.,.,
-
-# reduce 404 omitted
-
-module_eval(<<'.,.,', 'opal.y', 1259)
- def _reduce_405(val, _values, result)
- result = str_append val[0], val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1264)
- def _reduce_406(val, _values, result)
- result = val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1268)
- def _reduce_407(val, _values, result)
- result = s(:str, value(val[0]))
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1273)
- def _reduce_408(val, _values, result)
- result = new_xstr(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1278)
- def _reduce_409(val, _values, result)
- result = new_regexp val[1], val[2]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1283)
- def _reduce_410(val, _values, result)
- result = s(:array)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1287)
- def _reduce_411(val, _values, result)
- result = val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1292)
- def _reduce_412(val, _values, result)
- result = s(:array)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1296)
- def _reduce_413(val, _values, result)
- part = val[1]
- part = s(:dstr, "", val[1]) if part.type == :evstr
- result = val[0] << part
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1303)
- def _reduce_414(val, _values, result)
- result = val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1307)
- def _reduce_415(val, _values, result)
- result = val[0].concat([val[1]])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1312)
- def _reduce_416(val, _values, result)
- result = s(:array)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1316)
- def _reduce_417(val, _values, result)
- result = val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1321)
- def _reduce_418(val, _values, result)
- result = s(:array)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1325)
- def _reduce_419(val, _values, result)
- result = val[0] << s(:str, value(val[1]))
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1330)
- def _reduce_420(val, _values, result)
- result = nil
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1334)
- def _reduce_421(val, _values, result)
- result = str_append val[0], val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1339)
- def _reduce_422(val, _values, result)
- result = nil
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1343)
- def _reduce_423(val, _values, result)
- result = str_append val[0], val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1348)
- def _reduce_424(val, _values, result)
- result = new_str_content(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1352)
- def _reduce_425(val, _values, result)
- result = lexer.strterm
- lexer.strterm = nil
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1357)
- def _reduce_426(val, _values, result)
- lexer.strterm = val[1]
- result = new_evstr(val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1362)
- def _reduce_427(val, _values, result)
- lexer.cond_push 0
- lexer.cmdarg_push 0
- result = lexer.strterm
- lexer.strterm = nil
- lexer.lex_state = :expr_beg
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1370)
- def _reduce_428(val, _values, result)
- lexer.strterm = val[1]
- lexer.cond_lexpop
- lexer.cmdarg_lexpop
- result = new_evstr(val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1378)
- def _reduce_429(val, _values, result)
- result = new_gvar(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1382)
- def _reduce_430(val, _values, result)
- result = new_ivar(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1386)
- def _reduce_431(val, _values, result)
- result = new_cvar(val[0])
-
- result
- end
-.,.,
-
-# reduce 432 omitted
-
-module_eval(<<'.,.,', 'opal.y', 1393)
- def _reduce_433(val, _values, result)
- result = new_sym(val[1])
- lexer.lex_state = :expr_end
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1398)
- def _reduce_434(val, _values, result)
- result = new_sym(val[0])
-
- result
- end
-.,.,
-
-# reduce 435 omitted
-
-# reduce 436 omitted
-
-# reduce 437 omitted
-
-# reduce 438 omitted
-
-module_eval(<<'.,.,', 'opal.y', 1408)
- def _reduce_439(val, _values, result)
- result = new_dsym val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1413)
- def _reduce_440(val, _values, result)
- result = new_int(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1417)
- def _reduce_441(val, _values, result)
- result = new_float(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1421)
- def _reduce_442(val, _values, result)
- result = negate_num(new_int(val[1]))
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1425)
- def _reduce_443(val, _values, result)
- result = negate_num(new_float(val[1]))
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1429)
- def _reduce_444(val, _values, result)
- result = new_int(val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1433)
- def _reduce_445(val, _values, result)
- result = new_float(val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1438)
- def _reduce_446(val, _values, result)
- result = new_ident(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1442)
- def _reduce_447(val, _values, result)
- result = new_ivar(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1446)
- def _reduce_448(val, _values, result)
- result = new_gvar(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1450)
- def _reduce_449(val, _values, result)
- result = new_const(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1454)
- def _reduce_450(val, _values, result)
- result = new_cvar(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1458)
- def _reduce_451(val, _values, result)
- result = new_nil(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1462)
- def _reduce_452(val, _values, result)
- result = new_self(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1466)
- def _reduce_453(val, _values, result)
- result = new_true(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1470)
- def _reduce_454(val, _values, result)
- result = new_false(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1474)
- def _reduce_455(val, _values, result)
- result = new___FILE__(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1478)
- def _reduce_456(val, _values, result)
- result = new___LINE__(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1483)
- def _reduce_457(val, _values, result)
- result = new_var_ref(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1488)
- def _reduce_458(val, _values, result)
- result = new_assignable val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1493)
- def _reduce_459(val, _values, result)
- result = s(:nth_ref, value(val[0]))
-
- result
- end
-.,.,
-
-# reduce 460 omitted
-
-module_eval(<<'.,.,', 'opal.y', 1499)
- def _reduce_461(val, _values, result)
- result = nil
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1503)
- def _reduce_462(val, _values, result)
- result = val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1507)
- def _reduce_463(val, _values, result)
- result = nil
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1512)
- def _reduce_464(val, _values, result)
- result = val[1]
- lexer.lex_state = :expr_beg
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1517)
- def _reduce_465(val, _values, result)
- result = val[0]
- lexer.lex_state = :expr_beg
-
- result
- end
-.,.,
-
-# reduce 466 omitted
-
-# reduce 467 omitted
-
-module_eval(<<'.,.,', 'opal.y', 1526)
- def _reduce_468(val, _values, result)
- result = new_kwrestarg(val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1530)
- def _reduce_469(val, _values, result)
- result = new_kwrestarg()
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1535)
- def _reduce_470(val, _values, result)
- result = new_sym(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1540)
- def _reduce_471(val, _values, result)
- result = new_kwoptarg(val[0], val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1544)
- def _reduce_472(val, _values, result)
- result = new_kwarg(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1549)
- def _reduce_473(val, _values, result)
- result = [val[0]]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1553)
- def _reduce_474(val, _values, result)
- result = val[0]
- result << val[2]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1559)
- def _reduce_475(val, _values, result)
- result = new_args_tail(val[0], val[2], val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1563)
- def _reduce_476(val, _values, result)
- result = new_args_tail(val[0], nil, val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1567)
- def _reduce_477(val, _values, result)
- result = new_args_tail(nil, val[0], val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1571)
- def _reduce_478(val, _values, result)
- result = new_args_tail(nil, nil, val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1576)
- def _reduce_479(val, _values, result)
- result = val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1580)
- def _reduce_480(val, _values, result)
- result = new_args_tail(nil, nil, nil)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1585)
- def _reduce_481(val, _values, result)
- result = new_args(val[0], val[2], val[4], val[5])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1589)
- def _reduce_482(val, _values, result)
- result = new_args(val[0], val[2], nil, val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1593)
- def _reduce_483(val, _values, result)
- result = new_args(val[0], nil, val[2], val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1597)
- def _reduce_484(val, _values, result)
- result = new_args(val[0], nil, nil, val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1601)
- def _reduce_485(val, _values, result)
- result = new_args(nil, val[0], val[2], val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1605)
- def _reduce_486(val, _values, result)
- result = new_args(nil, val[0], nil, val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1609)
- def _reduce_487(val, _values, result)
- result = new_args(nil, nil, val[0], val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1613)
- def _reduce_488(val, _values, result)
- result = new_args(nil, nil, nil, val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1617)
- def _reduce_489(val, _values, result)
- result = new_args(nil, nil, nil, nil)
-
- result
- end
-.,.,
-
-# reduce 490 omitted
-
-module_eval(<<'.,.,', 'opal.y', 1623)
- def _reduce_491(val, _values, result)
- result = value(val[0]).to_sym
- scope.add_local result
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1629)
- def _reduce_492(val, _values, result)
- raise 'formal argument cannot be a constant'
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1633)
- def _reduce_493(val, _values, result)
- raise 'formal argument cannot be an instance variable'
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1637)
- def _reduce_494(val, _values, result)
- raise 'formal argument cannot be a class variable'
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1641)
- def _reduce_495(val, _values, result)
- raise 'formal argument cannot be a global variable'
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1646)
- def _reduce_496(val, _values, result)
- result = val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1650)
- def _reduce_497(val, _values, result)
- result = val[1]
-
- result
- end
-.,.,
-
-# reduce 498 omitted
-
-# reduce 499 omitted
-
-module_eval(<<'.,.,', 'opal.y', 1658)
- def _reduce_500(val, _values, result)
- result = s(:lasgn, val[0])
-
- result
- end
-.,.,
-
-# reduce 501 omitted
-
-module_eval(<<'.,.,', 'opal.y', 1664)
- def _reduce_502(val, _values, result)
- result = s(:array, val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1668)
- def _reduce_503(val, _values, result)
- val[0] << val[2]
- result = val[0]
-
- result
- end
-.,.,
-
-# reduce 504 omitted
-
-# reduce 505 omitted
-
-# reduce 506 omitted
-
-# reduce 507 omitted
-
-# reduce 508 omitted
-
-module_eval(<<'.,.,', 'opal.y', 1680)
- def _reduce_509(val, _values, result)
- result = [val[0]]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1684)
- def _reduce_510(val, _values, result)
- val[0] << val[2]
- result = val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1690)
- def _reduce_511(val, _values, result)
- result = new_assign(new_assignable(new_ident(val[0])), val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1695)
- def _reduce_512(val, _values, result)
- result = s(:block, val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1699)
- def _reduce_513(val, _values, result)
- result = val[0]
- val[0] << val[2]
-
- result
- end
-.,.,
-
-# reduce 514 omitted
-
-# reduce 515 omitted
-
-module_eval(<<'.,.,', 'opal.y', 1708)
- def _reduce_516(val, _values, result)
- result = "*#{value(val[1])}".to_sym
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1712)
- def _reduce_517(val, _values, result)
- result = :"*"
-
- result
- end
-.,.,
-
-# reduce 518 omitted
-
-# reduce 519 omitted
-
-module_eval(<<'.,.,', 'opal.y', 1720)
- def _reduce_520(val, _values, result)
- result = "&#{value(val[1])}".to_sym
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1725)
- def _reduce_521(val, _values, result)
- result = val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1729)
- def _reduce_522(val, _values, result)
- result = nil
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1734)
- def _reduce_523(val, _values, result)
- result = val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1738)
- def _reduce_524(val, _values, result)
- result = val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1743)
- def _reduce_525(val, _values, result)
- result = []
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1747)
- def _reduce_526(val, _values, result)
- result = val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1752)
- def _reduce_527(val, _values, result)
- result = val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1756)
- def _reduce_528(val, _values, result)
- result = val[0].push(*val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1761)
- def _reduce_529(val, _values, result)
- result = [val[0], val[2]]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'opal.y', 1765)
- def _reduce_530(val, _values, result)
- result = [new_sym(val[0]), val[1]]
-
- result
- end
-.,.,
-
-# reduce 531 omitted
-
-# reduce 532 omitted
-
-# reduce 533 omitted
-
-# reduce 534 omitted
-
-# reduce 535 omitted
-
-# reduce 536 omitted
-
-# reduce 537 omitted
-
-# reduce 538 omitted
-
-# reduce 539 omitted
-
-# reduce 540 omitted
-
-# reduce 541 omitted
-
-# reduce 542 omitted
-
-# reduce 543 omitted
-
-# reduce 544 omitted
-
-# reduce 545 omitted
-
-# reduce 546 omitted
-
-# reduce 547 omitted
-
-# reduce 548 omitted
-
-# reduce 549 omitted
-
-# reduce 550 omitted
-
-# reduce 551 omitted
-
-# reduce 552 omitted
-
-# reduce 553 omitted
-
-module_eval(<<'.,.,', 'opal.y', 1802)
- def _reduce_554(val, _values, result)
- result = nil
-
- result
- end
-.,.,
-
-def _reduce_none(val, _values, result)
- val[0]
-end
-
- end # class Parser
-end # module Opal
diff --git a/test/racc/regress/php_serialization b/test/racc/regress/php_serialization
deleted file mode 100644
index e412db1cc8..0000000000
--- a/test/racc/regress/php_serialization
+++ /dev/null
@@ -1,336 +0,0 @@
-#
-# DO NOT MODIFY!!!!
-# This file is automatically generated by Racc 1.5.0
-# from Racc grammar file "".
-#
-
-require 'racc/parser.rb'
-
-require 'php_serialization/tokenizer'
-
-module PhpSerialization
- class Unserializer < Racc::Parser
-
-module_eval(<<'...end php_serialization.y/module_eval...', 'php_serialization.y', 84)
- def initialize(tokenizer_klass = Tokenizer)
- @tokenizer_klass = tokenizer_klass
- end
-
- def run(string)
- @tokenizer = @tokenizer_klass.new(string)
- yyparse(@tokenizer, :each)
- return @object
- ensure
- @tokenizer = nil
- end
-
- def next_token
- @tokenizer.next_token
- end
-...end php_serialization.y/module_eval...
-##### State transition tables begin ###
-
-racc_action_table = [
- 9, 10, 16, 17, 11, 12, 13, 18, 14, 9,
- 10, 15, 19, 11, 12, 13, 20, 14, 21, 46,
- 15, 9, 10, 22, 23, 11, 12, 13, 24, 14,
- 9, 10, 15, 25, 11, 12, 13, 26, 14, 27,
- 51, 15, 28, 29, 30, 31, 32, 33, 34, 35,
- 36, 37, 38, 39, 40, 41, 43, 47, 49 ]
-
-racc_action_check = [
- 0, 0, 1, 2, 0, 0, 0, 3, 0, 42,
- 42, 0, 4, 42, 42, 42, 5, 42, 6, 42,
- 42, 45, 45, 10, 11, 45, 45, 45, 12, 45,
- 50, 50, 45, 13, 50, 50, 50, 14, 50, 15,
- 50, 50, 16, 22, 23, 24, 25, 26, 27, 32,
- 33, 34, 35, 36, 37, 39, 41, 43, 47 ]
-
-racc_action_pointer = [
- -3, 2, 1, 5, 10, 14, 16, nil, nil, nil,
- 18, 19, 23, 28, 32, 34, 42, nil, nil, nil,
- nil, nil, 37, 38, 39, 40, 41, 42, nil, nil,
- nil, nil, 44, 45, 46, 42, 43, 42, nil, 50,
- nil, 50, 6, 52, nil, 18, nil, 46, nil, nil,
- 27, nil ]
-
-racc_action_default = [
- -18, -18, -18, -18, -18, -18, -18, -6, -7, -8,
- -18, -18, -18, -18, -18, -18, -18, -1, -2, -3,
- -4, -5, -18, -18, -18, -18, -18, -18, 52, -9,
- -10, -11, -18, -18, -18, -18, -18, -18, -12, -18,
- -15, -18, -18, -18, -14, -18, -17, -18, -16, -15,
- -18, -13 ]
-
-racc_goto_table = [
- 1, 42, nil, nil, nil, nil, nil, nil, nil, nil,
- 50, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 48 ]
-
-racc_goto_check = [
- 1, 9, nil, nil, nil, nil, nil, nil, nil, nil,
- 9, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 1 ]
-
-racc_goto_pointer = [
- nil, 0, nil, nil, nil, nil, nil, nil, nil, -39,
- nil ]
-
-racc_goto_default = [
- nil, 45, 2, 3, 4, 5, 6, 7, 8, nil,
- 44 ]
-
-racc_reduce_table = [
- 0, 0, :racc_error,
- 2, 16, :_reduce_1,
- 2, 16, :_reduce_2,
- 2, 16, :_reduce_3,
- 2, 16, :_reduce_4,
- 2, 16, :_reduce_5,
- 1, 16, :_reduce_6,
- 1, 16, :_reduce_7,
- 1, 17, :_reduce_8,
- 3, 18, :_reduce_9,
- 3, 19, :_reduce_10,
- 3, 20, :_reduce_11,
- 5, 21, :_reduce_12,
- 11, 23, :_reduce_13,
- 2, 24, :_reduce_14,
- 0, 24, :_reduce_15,
- 2, 25, :_reduce_16,
- 7, 22, :_reduce_17 ]
-
-racc_reduce_n = 18
-
-racc_shift_n = 52
-
-racc_token_table = {
- false => 0,
- :error => 1,
- ";" => 2,
- "N" => 3,
- "b" => 4,
- ":" => 5,
- :NUMBER => 6,
- "i" => 7,
- "d" => 8,
- "s" => 9,
- :STRING => 10,
- "O" => 11,
- "{" => 12,
- "}" => 13,
- "a" => 14 }
-
-racc_nt_base = 15
-
-racc_use_result_var = true
-
-Racc_arg = [
- racc_action_table,
- racc_action_check,
- racc_action_default,
- racc_action_pointer,
- racc_goto_table,
- racc_goto_check,
- racc_goto_default,
- racc_goto_pointer,
- racc_nt_base,
- racc_reduce_table,
- racc_token_table,
- racc_shift_n,
- racc_reduce_n,
- racc_use_result_var ]
-
-Racc_token_to_s_table = [
- "$end",
- "error",
- "\";\"",
- "\"N\"",
- "\"b\"",
- "\":\"",
- "NUMBER",
- "\"i\"",
- "\"d\"",
- "\"s\"",
- "STRING",
- "\"O\"",
- "\"{\"",
- "\"}\"",
- "\"a\"",
- "$start",
- "data",
- "null",
- "bool",
- "integer",
- "double",
- "string",
- "assoc_array",
- "object",
- "attribute_list",
- "attribute" ]
-
-Racc_debug_parser = false
-
-##### State transition tables end #####
-
-# reduce 0 omitted
-
-module_eval(<<'.,.,', 'php_serialization.y', 6)
- def _reduce_1(val, _values, result)
- @object = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'php_serialization.y', 7)
- def _reduce_2(val, _values, result)
- @object = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'php_serialization.y', 8)
- def _reduce_3(val, _values, result)
- @object = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'php_serialization.y', 9)
- def _reduce_4(val, _values, result)
- @object = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'php_serialization.y', 10)
- def _reduce_5(val, _values, result)
- @object = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'php_serialization.y', 11)
- def _reduce_6(val, _values, result)
- @object = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'php_serialization.y', 12)
- def _reduce_7(val, _values, result)
- @object = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'php_serialization.y', 15)
- def _reduce_8(val, _values, result)
- result = nil
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'php_serialization.y', 18)
- def _reduce_9(val, _values, result)
- result = Integer(val[2]) > 0
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'php_serialization.y', 21)
- def _reduce_10(val, _values, result)
- result = Integer(val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'php_serialization.y', 24)
- def _reduce_11(val, _values, result)
- result = Float(val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'php_serialization.y', 27)
- def _reduce_12(val, _values, result)
- result = val[4]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'php_serialization.y', 32)
- def _reduce_13(val, _values, result)
- if eval("defined?(#{val[4]})")
- result = Object.const_get(val[4]).new
-
- val[9].each do |(attr_name, value)|
- # Protected and private attributes will have a \0..\0 prefix
- attr_name = attr_name.gsub(/\A\\0[^\\]+\\0/, '')
- result.instance_variable_set("@#{attr_name}", value)
- end
- else
- klass_name = val[4].gsub(/^Struct::/, '')
- attr_names, values = [], []
-
- val[9].each do |(attr_name, value)|
- # Protected and private attributes will have a \0..\0 prefix
- attr_names << attr_name.gsub(/\A\\0[^\\]+\\0/, '')
- values << value
- end
-
- result = Struct.new(klass_name, *attr_names).new(*values)
- result.instance_variable_set("@_php_class", klass_name)
- end
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'php_serialization.y', 56)
- def _reduce_14(val, _values, result)
- result = val[0] << val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'php_serialization.y', 57)
- def _reduce_15(val, _values, result)
- result = []
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'php_serialization.y', 60)
- def _reduce_16(val, _values, result)
- result = val
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'php_serialization.y', 65)
- def _reduce_17(val, _values, result)
- # Checks if the keys are a sequence of integers
- idx = -1
- arr = val[5].all? { |(k,v)| k == (idx += 1) }
-
- if arr
- result = val[5].map { |(k,v)| v }
- else
- result = Hash[val[5]]
- end
-
- result
- end
-.,.,
-
-def _reduce_none(val, _values, result)
- val[0]
-end
-
- end # class Unserializer
-end # module PhpSerialization
diff --git a/test/racc/regress/riml b/test/racc/regress/riml
deleted file mode 100644
index 5882a431cf..0000000000
--- a/test/racc/regress/riml
+++ /dev/null
@@ -1,4037 +0,0 @@
-#
-# DO NOT MODIFY!!!!
-# This file is automatically generated by Racc 1.5.2
-# from Racc grammar file "".
-#
-
-require 'racc/parser.rb'
-
- require File.expand_path("../lexer", __FILE__)
- require File.expand_path("../nodes", __FILE__)
- require File.expand_path("../errors", __FILE__)
- require File.expand_path("../ast_rewriter", __FILE__)
-module Riml
- class Parser < Racc::Parser
-
-module_eval(<<'...end riml.y/module_eval...', 'riml.y', 592)
- # This code will be put as-is in the parser class
-
- attr_accessor :ast_rewriter
- attr_writer :options
-
- # The Parser and AST_Rewriter share this same hash of options
- def options
- @options ||= {}
- end
-
- def self.ast_cache
- @ast_cache
- end
- @ast_cache = {}
-
- # parses tokens or code into output nodes
- def parse(object, ast_rewriter = Riml::AST_Rewriter.new, filename = nil, included = false)
- if (ast = self.class.ast_cache[filename])
- else
- if tokens?(object)
- @tokens = object
- elsif code?(object)
- @lexer = Riml::Lexer.new(object, filename, true)
- end
-
- begin
- ast = do_parse
- rescue Racc::ParseError => e
- raise unless @lexer
- if (invalid_token = @lexer.prev_token_is_keyword?)
- warning = "#{invalid_token.inspect} is a keyword, and cannot " \
- "be used as a variable name"
- end
- error_msg = e.message
- error_msg << "\nWARNING: #{warning}" if warning
- error = Riml::ParseError.new(error_msg, @lexer.filename, @lexer.lineno)
- raise error
- end
- self.class.ast_cache[filename] = ast if filename
- end
- @ast_rewriter ||= ast_rewriter
- return ast unless @ast_rewriter
- @ast_rewriter.ast = ast.dup
- @ast_rewriter.options ||= options
- @ast_rewriter.rewrite(filename, included)
- @ast_rewriter.ast
- end
-
- # get the next token from either the list of tokens provided, or
- # the lexer getting the next token
- def next_token
- return @tokens.shift unless @lexer
- token = @lexer.next_token
- if token && @lexer.parser_info
- @current_parser_info = token.pop
- end
- token
- end
-
- private
-
- def tokens?(object)
- Array === object
- end
-
- def code?(object)
- String === object
- end
-
- def make_node(racc_val)
- node = yield racc_val
- node.parser_info = @current_parser_info
- node
- end
-...end riml.y/module_eval...
-##### State transition tables begin ###
-
-racc_action_table = [
- 135, 265, 60, 139, 136, 211, 417, 418, 48, 47,
- 411, 211, 448, 274, 146, 56, 199, 89, 272, 60,
- 273, 270, 409, 271, 37, 46, 48, 47, 37, 49,
- 44, 45, 392, 412, 37, 449, 384, 60, 50, 70,
- 316, 61, 386, 385, 317, 62, 63, 129, 130, 132,
- 127, 128, 131, 115, 116, 117, 121, 122, 123, 118,
- 119, 120, 124, 125, 126, 102, 104, 103, 109, 111,
- 110, 112, 114, 113, 106, 108, 107, 133, 134, 101,
- 100, 137, 171, 80, 38, 173, 37, 81, 38, 82,
- 85, 83, 84, 87, 38, 105, 86, 37, 75, 76,
- 153, 152, 57, 56, 88, 89, 77, 37, 90, 58,
- 59, 78, 37, 46, 48, 47, 91, 49, 44, 45,
- 64, 72, 73, -116, 161, 60, 50, 70, 79, 61,
- 272, 37, 92, 62, 63, 271, 48, 47, -178, -178,
- -178, -178, 211, 147, 211, 211, 38, 60, -43, -43,
- 153, 152, 329, 409, 99, 409, 409, 38, 331, 153,
- 152, -42, -42, 161, 60, 50, 70, 38, 139, 313,
- 29, 313, 38, 52, 80, 54, 164, 277, 81, 277,
- 82, 85, 83, 84, 87, 279, 279, 86, 149, 75,
- 76, 38, 182, 57, 56, 88, 89, 77, 149, 90,
- 58, 59, 78, 37, 46, 48, 47, 91, 49, 44,
- 45, 64, 72, 73, -116, 164, 60, 50, 70, 79,
- 61, 164, 60, 164, 62, 63, -204, 277, 149, 164,
- 279, 164, -203, 305, 149, 366, 141, 164, 164, -44,
- -44, 129, 130, 132, -85, -85, -85, -85, 142, -48,
- -48, -116, 258, 60, 50, 70, -99, -98, 60, 50,
- 70, 29, 149, 38, 52, 80, 54, 371, 149, 81,
- 52, 82, 85, 83, 84, 87, 149, 139, 86, 164,
- 75, 76, 164, 139, 57, 56, 88, 89, 77, 105,
- 90, 58, 59, 78, 37, 46, 48, 47, 91, 49,
- 44, 45, 64, 72, 73, -99, -98, 60, 50, 70,
- 79, 61, -46, -46, 370, 62, 63, -175, -175, -175,
- -175, 139, 129, 130, 132, -47, -47, -45, -45, 433,
- 195, 432, 129, 130, 132, 127, 128, 131, 115, 116,
- 117, 121, 122, 123, 118, 119, 120, 124, 125, 126,
- 164, 354, 29, 211, 38, 52, 80, 54, 153, 152,
- 81, 60, 82, 85, 83, 84, 87, 149, 60, 86,
- 105, 75, 76, 417, 437, 57, 56, 88, 89, 77,
- 105, 90, 58, 59, 78, 215, 46, 48, 47, 91,
- 49, 44, 45, 64, 72, 73, -116, 216, 60, 50,
- 70, 79, 61, 139, 218, 319, 62, 63, -175, -175,
- -175, -175, -178, -178, -178, -178, 211, 147, 48, 47,
- 211, 49, 48, 47, 262, 49, -176, -176, -176, -176,
- 263, 320, 191, 192, 193, 194, 267, 129, 130, 132,
- 127, 128, 131, 29, 269, 269, 52, 269, 54, 129,
- 130, 132, 127, 128, 131, 115, 116, 117, 121, 122,
- 123, 118, 119, 120, 124, 125, 126, 102, 104, 103,
- 109, 111, 110, 112, 114, 113, 106, 108, 107, 133,
- 134, 101, 100, 137, 323, 105, 258, 276, 294, 295,
- 149, 139, 302, 305, 306, 105, 139, 105, 312, 326,
- 327, 328, 333, 105, 105, 105, 342, 346, 357, 361,
- 320, 258, 362, 363, 60, 129, 130, 132, 127, 128,
- 131, 129, 130, 132, 127, 128, 131, 368, 129, 130,
- 132, 127, 128, 131, 115, 116, 117, 121, 122, 123,
- 118, 119, 120, 124, 125, 126, 102, 104, 103, 109,
- 111, 110, 112, 114, 113, 106, 108, 107, 133, 134,
- 101, 100, 137, 105, 80, 129, 130, 132, 81, 105,
- 82, 85, 83, 84, 87, 374, 105, 86, 377, 75,
- 76, 379, 380, 57, 56, 88, 89, 77, 393, 90,
- 58, 59, 78, 37, 46, 48, 47, 91, 49, 44,
- 45, 64, 72, 73, -116, 302, 60, 50, 70, 79,
- 61, 394, 397, 105, 62, 63, 269, 258, 129, 130,
- 132, 127, 128, 131, 115, 116, 117, 121, 122, 123,
- 118, 119, 120, 124, 125, 126, 102, 104, 103, 109,
- 111, 110, 112, 114, 113, 106, 108, 107, 133, 134,
- 101, 29, 400, 38, 52, 80, 54, 401, 402, 81,
- -245, 82, 85, 83, 84, 87, 105, 403, 86, 406,
- 75, 76, 60, 211, 57, 56, 88, 89, 77, 211,
- 90, 58, 59, 78, 37, 46, 48, 47, 91, 49,
- 44, 45, 64, 72, 73, 427, 60, 60, 50, 70,
- 79, 61, 430, 431, 434, 62, 63, 435, 438, 129,
- 130, 132, 127, 128, 131, 115, 116, 117, 121, 122,
- 123, 118, 119, 120, 124, 125, 126, 102, 104, 103,
- 109, 111, 110, 112, 114, 113, 106, 108, 107, 133,
- 134, 440, 29, 441, 38, 52, 80, 54, 442, 443,
- 81, 211, 82, 85, 83, 84, 87, 105, 445, 86,
- 446, 75, 76, 371, 371, 57, 56, 88, 89, 77,
- 211, 90, 58, 59, 78, 37, 46, 48, 47, 91,
- 49, 44, 45, 64, 72, 73, 458, 435, 60, 50,
- 70, 79, 61, 462, 463, 371, 62, 63, 465, 468,
- 129, 130, 132, 127, 128, 131, 115, 116, 117, 121,
- 122, 123, 118, 119, 120, 124, 125, 126, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 129,
- 130, 132, nil, 29, nil, 38, 52, 80, 54, nil,
- nil, 81, nil, 82, 85, 83, 84, 87, 105, nil,
- 86, nil, 75, 76, nil, nil, 57, 56, 88, 89,
- 77, nil, 90, 58, 59, 78, 37, 46, 48, 47,
- 91, 49, 44, 45, 64, 72, 73, 105, nil, 60,
- 50, 70, 79, 61, nil, nil, nil, 62, 63, nil,
- nil, 129, 130, 132, 127, 128, 131, 115, 116, 117,
- 121, 122, 123, 118, 119, 120, 124, 125, 126, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 129, 130, 132, nil, 29, nil, 38, 52, 80, 54,
- nil, nil, 81, nil, 82, 85, 83, 84, 87, 105,
- nil, 86, nil, 75, 76, nil, nil, 57, 56, 88,
- 89, 77, nil, 90, 58, 59, 78, 37, 46, 48,
- 47, 91, 49, 44, 45, 64, 72, 73, 105, nil,
- 60, 50, 70, 79, 61, nil, nil, nil, 62, 63,
- 414, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 29, nil, 38, 52, nil,
- 54, nil, 129, 130, 132, 127, 128, 131, 115, 116,
- 117, 121, 122, 123, 118, 119, 120, 124, 125, 126,
- 102, 104, 103, 109, 111, 110, 112, 114, 113, 106,
- 108, 107, 133, 134, 101, 100, 137, 419, nil, nil,
- nil, nil, nil, nil, nil, nil, 146, 56, nil, 89,
- 105, nil, 90, nil, nil, nil, nil, 46, 48, 47,
- nil, 49, 44, 45, 64, nil, nil, nil, nil, 60,
- 50, 70, nil, 61, nil, nil, nil, 62, 63, 129,
- 130, 132, 127, 128, 131, 115, 116, 117, 121, 122,
- 123, 118, 119, 120, 124, 125, 126, 102, 104, 103,
- 109, 111, 110, 112, 114, 113, 106, 108, 107, 133,
- 134, 101, 100, 137, 29, nil, nil, 52, nil, 54,
- nil, 261, 146, 56, nil, 89, nil, 105, 90, nil,
- nil, nil, nil, 46, 48, 47, nil, 49, 44, 45,
- 64, nil, nil, nil, nil, 60, 50, 70, nil, 61,
- nil, nil, nil, 62, 63, 180, 146, 56, nil, 89,
- nil, nil, 90, nil, nil, nil, nil, 46, 48, 47,
- nil, 49, 44, 45, 64, nil, nil, -116, nil, 60,
- 50, 70, nil, 61, nil, nil, nil, 62, 63, nil,
- 29, nil, nil, 52, nil, 54, nil, 261, nil, 129,
- 130, 132, 127, 128, 131, 115, 116, 117, 121, 122,
- 123, 118, 119, 120, 124, 125, 126, nil, 180, 146,
- 56, nil, 89, nil, 176, 90, nil, 52, nil, 54,
- 46, 48, 47, nil, 49, 44, 45, 64, nil, nil,
- nil, nil, 60, 50, 70, nil, 61, 105, nil, nil,
- 62, 63, 180, 146, 56, nil, 89, nil, nil, 90,
- nil, nil, nil, nil, 46, 48, 47, nil, 49, 44,
- 45, 64, nil, nil, nil, nil, 60, 50, 70, nil,
- 61, nil, nil, nil, 62, 63, nil, 29, -119, nil,
- 52, nil, 54, nil, nil, 129, 130, 132, 127, 128,
- 131, 115, 116, 117, 121, 122, 123, 118, 119, 120,
- 124, 125, 126, nil, nil, nil, 180, 146, 56, nil,
- 89, 29, -119, 90, 52, nil, 54, nil, 46, 48,
- 47, nil, 49, 44, 45, 64, nil, nil, nil, nil,
- 60, 50, 70, 105, 61, nil, nil, nil, 62, 63,
- 180, 146, 56, nil, 89, nil, nil, 90, nil, nil,
- nil, nil, 46, 48, 47, nil, 49, 44, 45, 64,
- nil, nil, nil, nil, 60, 50, 70, nil, 61, nil,
- nil, nil, 62, 63, nil, 29, -119, nil, 52, nil,
- 54, nil, nil, 129, 130, 132, 127, 128, 131, 115,
- 116, 117, 121, 122, 123, 118, 119, 120, 124, 125,
- 126, nil, nil, nil, 180, 146, 56, nil, 89, 29,
- -119, 90, 52, nil, 54, nil, 46, 48, 47, nil,
- 49, 44, 45, 64, nil, nil, nil, nil, 60, 50,
- 70, 105, 61, nil, nil, nil, 62, 63, 180, 146,
- 56, nil, 89, nil, nil, 90, nil, nil, nil, nil,
- 46, 48, 47, nil, 49, 44, 45, 64, nil, nil,
- nil, nil, 60, 50, 70, nil, 61, nil, nil, nil,
- 62, 63, nil, 29, -121, nil, 52, nil, 54, nil,
- nil, 129, 130, 132, 127, 128, 131, 115, 116, 117,
- 121, 122, 123, 118, 119, 120, 124, 125, 126, nil,
- nil, nil, nil, 146, 56, nil, 89, 29, -119, 90,
- 52, nil, 54, nil, 46, 48, 47, nil, 49, 44,
- 45, 64, nil, nil, nil, nil, 60, 50, 70, 105,
- 61, nil, nil, nil, 62, 63, 180, 146, 56, nil,
- 89, nil, nil, 90, nil, nil, nil, nil, 46, 48,
- 47, nil, 49, 44, 45, 64, nil, nil, nil, nil,
- 60, 50, 70, nil, 61, nil, nil, nil, 62, 63,
- nil, 29, nil, nil, 52, nil, 54, 350, nil, 129,
- 130, 132, 127, 128, 131, 115, 116, 117, 121, 122,
- 123, 118, 119, 120, 124, 125, 126, nil, nil, nil,
- 180, 146, 56, nil, 89, 29, -119, 90, 52, nil,
- 54, nil, 46, 48, 47, nil, 49, 44, 45, 64,
- nil, nil, nil, nil, 60, 50, 70, 105, 61, nil,
- nil, nil, 62, 63, 365, 146, 56, nil, 89, nil,
- nil, 90, nil, nil, nil, nil, 46, 48, 47, nil,
- 49, 44, 45, 64, nil, nil, nil, nil, 60, 50,
- 70, nil, 61, nil, nil, nil, 62, 63, nil, 29,
- -119, nil, 52, nil, 54, nil, 129, 130, 132, 127,
- 128, 131, 115, 116, 117, 121, 122, 123, 118, 119,
- 120, 124, 125, 126, nil, nil, nil, 180, 146, 56,
- nil, 89, nil, 29, 90, nil, 52, nil, 54, 46,
- 48, 47, nil, 49, 44, 45, 64, nil, nil, nil,
- nil, 60, 50, 70, 105, 61, nil, nil, nil, 62,
- 63, 180, 146, 56, nil, 89, nil, nil, 90, nil,
- nil, nil, nil, 46, 48, 47, nil, 49, 44, 45,
- 64, nil, nil, nil, nil, 60, 50, 70, nil, 61,
- nil, nil, nil, 62, 63, nil, 29, -119, nil, 52,
- nil, 54, nil, nil, 129, 130, 132, 127, 128, 131,
- 115, 116, 117, 121, 122, 123, 118, 119, 120, 124,
- 125, 126, nil, nil, nil, nil, 146, 56, nil, 89,
- 29, -119, 90, 52, nil, 54, nil, 46, 48, 47,
- nil, 49, 44, 45, 64, nil, nil, nil, nil, 60,
- 50, 70, 105, 61, nil, nil, nil, 62, 63, 146,
- 56, nil, 89, nil, nil, 90, nil, nil, nil, nil,
- 46, 48, 47, nil, 49, 44, 45, 64, nil, nil,
- -116, nil, 60, 50, 70, nil, 61, nil, nil, nil,
- 62, 63, 146, 56, 29, 89, nil, 52, 90, 54,
- nil, nil, nil, 46, 48, 47, nil, 49, 44, 45,
- 64, nil, nil, -116, nil, 60, 50, 70, nil, 61,
- nil, nil, nil, 62, 63, 146, 56, 29, 89, nil,
- 52, 90, 54, nil, nil, 167, 46, 48, 47, nil,
- 49, 44, 45, 64, nil, nil, nil, nil, 60, 50,
- 70, nil, 61, nil, nil, nil, 62, 63, 146, 56,
- 29, 89, nil, 52, 90, 54, nil, nil, nil, 46,
- 48, 47, nil, 49, 44, 45, 64, nil, nil, nil,
- nil, 60, 50, 70, nil, 61, nil, nil, nil, 62,
- 63, 146, 56, 165, 89, nil, 52, 90, 54, nil,
- nil, nil, 46, 48, 47, nil, 49, 44, 45, 64,
- nil, nil, nil, nil, 60, 50, 70, nil, 61, nil,
- nil, nil, 62, 63, 146, 56, 29, 89, nil, 52,
- 90, 54, nil, nil, nil, 46, 48, 47, nil, 49,
- 44, 45, 64, nil, nil, nil, nil, 60, 50, 70,
- nil, 61, nil, nil, nil, 62, 63, 146, 56, 29,
- 89, nil, 52, 90, 54, nil, nil, nil, 46, 48,
- 47, nil, 49, 44, 45, 64, nil, nil, -116, nil,
- 60, 50, 70, nil, 61, nil, nil, nil, 62, 63,
- 146, 56, 29, 89, nil, 52, 90, 54, nil, nil,
- nil, 46, 48, 47, nil, 49, 44, 45, 64, nil,
- nil, nil, nil, 60, 50, 70, nil, 61, nil, nil,
- nil, 62, 63, 146, 56, 29, 89, nil, 52, 90,
- 54, nil, nil, nil, 46, 48, 47, nil, 49, 44,
- 45, 64, nil, nil, nil, nil, 60, 50, 70, nil,
- 61, nil, nil, nil, 62, 63, 146, 56, 29, 89,
- nil, 52, 90, 54, nil, nil, nil, 46, 48, 47,
- nil, 49, 44, 45, 64, nil, nil, nil, nil, 60,
- 50, 70, nil, 61, nil, nil, nil, 62, 63, 146,
- 56, 29, 89, nil, 52, 90, 54, nil, nil, nil,
- 46, 48, 47, nil, 49, 44, 45, 64, nil, nil,
- nil, nil, 60, 50, 70, nil, 61, nil, nil, nil,
- 62, 63, 146, 56, 29, 89, nil, 52, 90, 54,
- nil, nil, nil, 46, 48, 47, nil, 49, 44, 45,
- 64, nil, nil, nil, nil, 60, 50, 70, nil, 61,
- nil, nil, nil, 62, 63, 146, 56, 29, 89, nil,
- 52, 90, 54, nil, nil, nil, 46, 48, 47, nil,
- 49, 44, 45, 64, nil, nil, nil, nil, 60, 50,
- 70, nil, 61, nil, nil, nil, 62, 63, 146, 56,
- 29, 89, nil, 52, 90, 54, nil, nil, nil, 46,
- 48, 47, nil, 49, 44, 45, 64, nil, nil, nil,
- nil, 60, 50, 70, nil, 61, nil, nil, nil, 62,
- 63, 146, 56, 29, 89, nil, 52, 90, 54, nil,
- nil, nil, 46, 48, 47, nil, 49, 44, 45, 64,
- nil, nil, nil, nil, 60, 50, 70, nil, 61, nil,
- nil, nil, 62, 63, 146, 56, 29, 89, nil, 52,
- 90, 54, nil, nil, nil, 46, 48, 47, nil, 49,
- 44, 45, 64, nil, nil, nil, nil, 60, 50, 70,
- nil, 61, nil, nil, nil, 62, 63, 146, 56, 29,
- 89, nil, 52, 90, 54, nil, nil, nil, 46, 48,
- 47, nil, 49, 44, 45, 64, nil, nil, nil, nil,
- 60, 50, 70, nil, 61, nil, nil, nil, 62, 63,
- 146, 56, 29, 89, nil, 52, 90, 54, nil, nil,
- nil, 46, 48, 47, nil, 49, 44, 45, 64, nil,
- nil, nil, nil, 60, 50, 70, nil, 61, nil, nil,
- nil, 62, 63, 146, 56, 29, 89, nil, 52, 90,
- 54, nil, nil, nil, 46, 48, 47, nil, 49, 44,
- 45, 64, nil, nil, nil, nil, 60, 50, 70, nil,
- 61, nil, nil, nil, 62, 63, 146, 56, 29, 89,
- nil, 52, 90, 54, nil, nil, nil, 46, 48, 47,
- nil, 49, 44, 45, 64, nil, nil, nil, nil, 60,
- 50, 70, nil, 61, nil, nil, nil, 62, 63, 146,
- 56, 29, 89, nil, 52, 90, 54, nil, nil, nil,
- 46, 48, 47, nil, 49, 44, 45, 64, nil, nil,
- nil, nil, 60, 50, 70, nil, 61, nil, nil, nil,
- 62, 63, 146, 56, 29, 89, nil, 52, 90, 54,
- nil, nil, nil, 46, 48, 47, nil, 49, 44, 45,
- 64, nil, nil, nil, nil, 60, 50, 70, nil, 61,
- nil, nil, nil, 62, 63, 146, 56, 29, 89, nil,
- 52, 90, 54, nil, nil, nil, 46, 48, 47, nil,
- 49, 44, 45, 64, nil, nil, nil, nil, 60, 50,
- 70, nil, 61, nil, nil, nil, 62, 63, 146, 56,
- 29, 89, nil, 52, 90, 54, nil, nil, nil, 46,
- 48, 47, nil, 49, 44, 45, 64, nil, nil, nil,
- nil, 60, 50, 70, nil, 61, nil, nil, nil, 62,
- 63, 146, 56, 29, 89, nil, 52, 90, 54, nil,
- nil, nil, 46, 48, 47, nil, 49, 44, 45, 64,
- nil, nil, nil, nil, 60, 50, 70, nil, 61, nil,
- nil, nil, 62, 63, 146, 56, 29, 89, nil, 52,
- 90, 54, nil, nil, nil, 46, 48, 47, nil, 49,
- 44, 45, 64, nil, nil, nil, nil, 60, 50, 70,
- nil, 61, nil, nil, nil, 62, 63, 146, 56, 29,
- 89, nil, 52, 90, 54, nil, nil, nil, 46, 48,
- 47, nil, 49, 44, 45, 64, nil, nil, nil, nil,
- 60, 50, 70, nil, 61, nil, nil, nil, 62, 63,
- 146, 56, 29, 89, nil, 52, 90, 54, nil, nil,
- nil, 46, 48, 47, nil, 49, 44, 45, 64, nil,
- nil, nil, nil, 60, 50, 70, nil, 61, nil, nil,
- nil, 62, 63, 146, 56, 29, 89, nil, 52, 90,
- 54, nil, nil, nil, 46, 48, 47, nil, 49, 44,
- 45, 64, nil, nil, nil, nil, 60, 50, 70, nil,
- 61, nil, nil, nil, 62, 63, 146, 56, 29, 89,
- nil, 52, 90, 54, nil, nil, nil, 46, 48, 47,
- nil, 49, 44, 45, 64, nil, nil, nil, nil, 60,
- 50, 70, nil, 61, nil, nil, nil, 62, 63, 146,
- 56, 29, 89, nil, 52, 90, 54, nil, nil, nil,
- 46, 48, 47, nil, 49, 44, 45, 64, nil, nil,
- nil, nil, 60, 50, 70, nil, 61, nil, nil, nil,
- 62, 63, 146, 56, 29, 89, nil, 52, 90, 54,
- nil, nil, nil, 46, 48, 47, nil, 49, 44, 45,
- 64, nil, nil, nil, nil, 60, 50, 70, nil, 61,
- nil, nil, nil, 62, 63, 146, 56, 29, 89, nil,
- 52, 90, 54, nil, nil, nil, 46, 48, 47, nil,
- 49, 44, 45, 64, nil, nil, nil, nil, 60, 50,
- 70, nil, 61, nil, nil, nil, 62, 63, 146, 56,
- 29, 89, nil, 52, 90, 54, nil, nil, nil, 46,
- 48, 47, nil, 49, 44, 45, 64, nil, nil, nil,
- nil, 60, 50, 70, nil, 61, nil, nil, nil, 62,
- 63, 146, 56, 29, 89, nil, 52, 90, 54, nil,
- nil, nil, 46, 48, 47, nil, 49, 44, 45, 64,
- nil, nil, nil, nil, 60, 50, 70, nil, 61, nil,
- nil, nil, 62, 63, 146, 56, 29, 89, nil, 52,
- 90, 54, nil, nil, nil, 46, 48, 47, nil, 49,
- 44, 45, 64, nil, nil, nil, nil, 60, 50, 70,
- nil, 61, nil, nil, nil, 62, 63, 146, 56, 29,
- 89, nil, 52, 90, 54, nil, nil, nil, 46, 48,
- 47, nil, 49, 44, 45, 64, nil, nil, nil, nil,
- 60, 50, 70, nil, 61, nil, nil, nil, 62, 63,
- 146, 56, 29, 89, nil, 52, 90, 54, nil, nil,
- nil, 46, 48, 47, nil, 49, 44, 45, 64, nil,
- nil, nil, nil, 60, 50, 70, nil, 61, nil, nil,
- nil, 62, 63, 146, 56, 29, 89, nil, 52, 90,
- 54, nil, nil, nil, 46, 48, 47, nil, 49, 44,
- 45, 64, nil, nil, nil, nil, 60, 50, 70, nil,
- 61, nil, nil, nil, 62, 63, 146, 56, 29, 89,
- nil, 52, 90, 54, nil, nil, nil, 46, 48, 47,
- nil, 49, 44, 45, 64, nil, nil, nil, nil, 60,
- 50, 70, nil, 61, nil, nil, nil, 62, 63, 146,
- 56, 29, 89, nil, 52, 90, 54, nil, nil, nil,
- 46, 48, 47, nil, 49, 44, 45, 64, nil, nil,
- nil, nil, 60, 50, 70, nil, 61, nil, nil, nil,
- 62, 63, 146, 56, 29, 89, nil, 52, 90, 54,
- nil, nil, nil, 46, 48, 47, nil, 49, 44, 45,
- 64, nil, nil, nil, nil, 60, 50, 70, nil, 61,
- nil, nil, nil, 62, 63, 146, 56, 29, 89, nil,
- 52, 90, 54, nil, nil, nil, 46, 48, 47, nil,
- 49, 44, 45, 64, nil, nil, nil, nil, 60, 50,
- 70, nil, 61, nil, nil, nil, 62, 63, 146, 56,
- 29, 89, nil, 52, 90, 54, nil, nil, nil, 46,
- 48, 47, nil, 49, 44, 45, 64, nil, nil, nil,
- nil, 60, 50, 70, nil, 61, nil, nil, nil, 62,
- 63, 146, 56, 29, 89, nil, 52, 90, 54, nil,
- nil, nil, 46, 48, 47, nil, 49, 44, 45, 64,
- nil, nil, nil, nil, 60, 50, 70, nil, 61, nil,
- nil, nil, 62, 63, 146, 56, 29, 89, nil, 52,
- 90, 54, nil, nil, nil, 46, 48, 47, nil, 49,
- 44, 45, 64, nil, nil, nil, nil, 60, 50, 70,
- nil, 61, nil, nil, nil, 62, 63, 146, 56, 29,
- 89, nil, 52, 90, 54, nil, nil, nil, 46, 48,
- 47, nil, 49, 44, 45, 64, nil, nil, nil, nil,
- 60, 50, 70, nil, 61, nil, nil, nil, 62, 63,
- 146, 56, 29, 89, nil, 52, 90, 54, nil, nil,
- nil, 46, 48, 47, nil, 49, 44, 45, 64, nil,
- nil, nil, nil, 60, 50, 70, nil, 61, nil, nil,
- nil, 62, 63, 146, 56, 29, 89, nil, 52, 90,
- 54, nil, nil, nil, 46, 48, 47, nil, 49, 44,
- 45, 64, nil, nil, nil, nil, 60, 50, 70, nil,
- 61, nil, nil, nil, 62, 63, 146, 56, 29, 89,
- nil, 52, 90, 54, nil, nil, nil, 46, 48, 47,
- nil, 49, 44, 45, 64, nil, nil, nil, nil, 60,
- 50, 70, nil, 61, nil, nil, nil, 62, 63, 146,
- 56, 29, 89, nil, 52, 90, 54, nil, nil, nil,
- 46, 48, 47, nil, 49, 44, 45, 64, nil, nil,
- -116, nil, 60, 50, 70, nil, 61, nil, nil, nil,
- 62, 63, 146, 56, 29, 89, nil, 52, 90, 288,
- nil, nil, nil, 46, 48, 47, nil, 49, 44, 45,
- 64, nil, nil, nil, nil, 60, 50, 70, nil, 61,
- nil, nil, nil, 62, 63, 146, 56, 29, 89, nil,
- 52, 90, 54, nil, nil, nil, 46, 48, 47, nil,
- 49, 44, 45, 64, nil, nil, nil, nil, 60, 50,
- 70, nil, 61, nil, nil, nil, 62, 63, 146, 56,
- 29, 89, nil, 52, 90, 54, nil, nil, nil, 46,
- 48, 47, nil, 49, 44, 45, 64, nil, nil, nil,
- nil, 60, 50, 70, nil, 61, nil, nil, nil, 62,
- 63, 146, 56, 29, 89, nil, 52, 90, 54, nil,
- nil, nil, 46, 48, 47, nil, 49, 44, 45, 64,
- nil, nil, nil, nil, 60, 50, 70, nil, 61, nil,
- nil, nil, 62, 63, 146, 56, 29, 89, nil, 52,
- 90, 54, nil, nil, nil, 46, 48, 47, nil, 49,
- 44, 45, 64, nil, nil, nil, nil, 60, 50, 70,
- nil, 61, nil, nil, nil, 62, 63, 146, 56, 29,
- 89, nil, 52, 90, 54, nil, nil, nil, 46, 48,
- 47, nil, 49, 44, 45, 64, nil, nil, nil, nil,
- 60, 50, 70, nil, 61, nil, nil, nil, 62, 63,
- 146, 56, 29, 89, nil, 52, 90, 54, nil, nil,
- nil, 46, 48, 47, nil, 49, 44, 45, 64, nil,
- nil, -116, nil, 60, 50, 70, nil, 61, nil, nil,
- nil, 62, 63, 146, 56, 29, 89, nil, 52, 90,
- 54, nil, nil, nil, 46, 48, 47, nil, 49, 44,
- 45, 64, nil, nil, nil, nil, 60, 50, 70, nil,
- 61, nil, nil, nil, 62, 63, 146, 56, 29, 89,
- nil, 52, 90, 54, nil, nil, nil, 46, 48, 47,
- nil, 49, 44, 45, 64, nil, nil, nil, nil, 60,
- 50, 70, nil, 61, nil, nil, nil, 62, 63, 146,
- 56, 29, 89, nil, 52, 90, 54, nil, nil, nil,
- 46, 48, 47, nil, 49, 44, 45, 64, nil, nil,
- nil, nil, 60, 50, 70, nil, 61, nil, nil, nil,
- 62, 63, nil, nil, 29, nil, nil, 52, 348, 54,
- 129, 130, 132, 127, 128, 131, 115, 116, 117, 121,
- 122, 123, 118, 119, 120, 124, 125, 126, nil, nil,
- nil, nil, 146, 56, nil, 89, nil, 29, 90, nil,
- 52, nil, 54, 46, 48, 47, nil, 49, 44, 45,
- 64, nil, nil, -116, nil, 60, 50, 70, 105, 61,
- nil, nil, nil, 62, 63, 146, 56, nil, 89, nil,
- nil, 90, nil, nil, nil, nil, 46, 48, 47, nil,
- 49, 44, 45, 64, nil, nil, nil, nil, 60, 50,
- 70, nil, 61, nil, nil, nil, 62, 63, 146, 56,
- 29, 89, nil, 52, 90, 288, nil, nil, nil, 46,
- 48, 47, nil, 49, 44, 45, 64, nil, nil, nil,
- nil, 60, 50, 70, nil, 61, nil, nil, nil, 62,
- 63, 146, 56, 29, 89, nil, 52, 90, 54, nil,
- nil, nil, 46, 48, 47, nil, 49, 44, 45, 64,
- nil, nil, nil, nil, 60, 50, 70, nil, 61, nil,
- nil, nil, 62, 63, 146, 56, 29, 89, nil, 52,
- 90, 54, nil, nil, nil, 46, 48, 47, nil, 49,
- 44, 45, 64, nil, nil, nil, nil, 60, 50, 70,
- nil, 61, nil, nil, nil, 62, 63, 146, 56, 29,
- 89, nil, 52, 90, 54, nil, nil, nil, 46, 48,
- 47, nil, 49, 44, 45, 64, nil, nil, nil, nil,
- 60, 50, 70, nil, 61, nil, nil, nil, 62, 63,
- 146, 56, 29, 89, nil, 52, 90, 54, nil, nil,
- nil, 46, 48, 47, nil, 49, 44, 45, 64, nil,
- nil, nil, nil, 60, 50, 70, nil, 61, nil, nil,
- nil, 62, 63, 146, 56, 29, 89, nil, 52, 90,
- 54, nil, nil, nil, 46, 48, 47, nil, 49, 44,
- 45, 64, nil, nil, nil, nil, 60, 50, 70, nil,
- 61, nil, nil, nil, 62, 63, 146, 56, 29, 89,
- nil, 52, 90, 54, nil, nil, nil, 46, 48, 47,
- nil, 49, 44, 45, 64, nil, nil, nil, nil, 60,
- 50, 70, nil, 61, nil, nil, nil, 62, 63, 146,
- 56, 29, 89, nil, 52, 90, 54, nil, nil, nil,
- 46, 48, 47, nil, 49, 44, 45, 64, nil, nil,
- nil, nil, 60, 50, 70, nil, 61, nil, nil, nil,
- 62, 63, 146, 56, 29, 89, nil, 52, 90, 54,
- nil, nil, nil, 46, 48, 47, nil, 49, 44, 45,
- 64, nil, nil, nil, nil, 60, 50, 70, nil, 61,
- nil, nil, nil, 62, 63, 146, 56, 29, 89, nil,
- 52, 90, 54, nil, nil, nil, 46, 48, 47, nil,
- 49, 44, 45, 64, nil, nil, -116, nil, 60, 50,
- 70, nil, 61, nil, nil, nil, 62, 63, 146, 56,
- 29, 89, nil, 52, 90, 54, nil, nil, nil, 46,
- 48, 47, nil, 49, 44, 45, 64, nil, nil, nil,
- nil, 60, 50, 70, nil, 61, nil, nil, nil, 62,
- 63, 146, 56, 29, 89, nil, 52, 90, 54, nil,
- nil, nil, 46, 48, 47, nil, 49, 44, 45, 64,
- nil, nil, nil, nil, 60, 50, 70, nil, 61, nil,
- nil, nil, 62, 63, 146, 56, 29, 89, nil, 52,
- 90, 54, nil, nil, nil, 46, 48, 47, nil, 49,
- 44, 45, 64, nil, nil, nil, nil, 60, 50, 70,
- nil, 61, nil, nil, nil, 62, 63, 146, 56, 29,
- 89, nil, 52, 90, 54, nil, nil, nil, 46, 48,
- 47, nil, 49, 44, 45, 64, nil, nil, nil, nil,
- 60, 50, 70, nil, 61, nil, nil, nil, 62, 63,
- 146, 56, 29, 89, nil, 52, nil, 54, nil, nil,
- nil, 46, 48, 47, nil, 49, 44, 45, nil, nil,
- nil, nil, nil, 60, 50, 70, nil, 61, nil, nil,
- nil, 62, 63, 146, 56, 29, 89, nil, 52, nil,
- 54, nil, nil, nil, 46, 48, 47, nil, 49, 44,
- 45, 64, nil, nil, nil, nil, 60, 50, 70, nil,
- 61, nil, nil, nil, 62, 63, 146, 56, 188, 89,
- nil, 52, nil, nil, nil, nil, nil, 46, 48, 47,
- nil, 49, 44, 45, 64, nil, nil, nil, nil, 60,
- 50, 70, nil, 61, nil, nil, nil, 62, 63, nil,
- nil, 188, nil, nil, 52, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 211, nil, nil, nil, nil, nil, 129, 130, 132, 127,
- 128, 131, nil, nil, 188, nil, nil, 52, 129, 130,
- 132, 127, 128, 131, 115, 116, 117, 121, 122, 123,
- 118, 119, 120, 124, 125, 126, 102, 104, 103, 109,
- 111, 110, 112, 114, 113, 106, 108, 107, 133, 134,
- 101, 100, 137, 211, 105, nil, nil, nil, nil, 129,
- 130, 132, 127, 128, 131, nil, 105, nil, nil, nil,
- nil, 129, 130, 132, 127, 128, 131, 115, 116, 117,
- 121, 122, 123, 118, 119, 120, 124, 125, 126, 102,
- 104, 103, 109, 111, 110, 112, 114, 113, 106, 108,
- 107, 133, 134, 101, 100, 137, 211, 105, nil, nil,
- nil, nil, 129, 130, 132, 127, 128, 131, nil, 105,
- nil, nil, nil, nil, 129, 130, 132, 127, 128, 131,
- 115, 116, 117, 121, 122, 123, 118, 119, 120, 124,
- 125, 126, 102, 104, 103, 109, 111, 110, 112, 114,
- 113, 106, 108, 107, 133, 134, 101, 100, 137, 211,
- 105, nil, nil, nil, nil, 129, 130, 132, 127, 128,
- 131, nil, 105, nil, nil, nil, nil, 129, 130, 132,
- 127, 128, 131, 115, 116, 117, 121, 122, 123, 118,
- 119, 120, 124, 125, 126, 102, 104, 103, 109, 111,
- 110, 112, 114, 113, 106, 108, 107, 133, 134, 101,
- 100, 137, 211, 105, nil, nil, nil, nil, 129, 130,
- 132, 127, 128, 131, nil, 105, nil, nil, nil, nil,
- 129, 130, 132, 127, 128, 131, 115, 116, 117, 121,
- 122, 123, 118, 119, 120, 124, 125, 126, 102, 104,
- 103, 109, 111, 110, 112, 114, 113, 106, 108, 107,
- 133, 134, 101, 100, 137, 455, 105, nil, nil, nil,
- nil, 129, 130, 132, 127, 128, 131, nil, 105, nil,
- nil, nil, nil, 129, 130, 132, 127, 128, 131, 115,
- 116, 117, 121, 122, 123, 118, 119, 120, 124, 125,
- 126, 102, 104, 103, 109, 111, 110, 112, 114, 113,
- 106, 108, 107, 133, 134, 101, 100, 137, 460, 105,
- nil, nil, nil, 129, 130, 132, 127, 128, 131, nil,
- nil, 105, nil, nil, nil, nil, 129, 130, 132, 127,
- 128, 131, 115, 116, 117, 121, 122, 123, 118, 119,
- 120, 124, 125, 126, 102, 104, 103, 109, 111, 110,
- 112, 114, 113, 106, 108, 107, 133, 134, 101, 100,
- 137, 105, 129, 130, 132, 127, 128, 131, nil, nil,
- nil, nil, nil, nil, 105, 129, 130, 132, 127, 128,
- 131, 115, 116, 117, 121, 122, 123, 118, 119, 120,
- 124, 125, 126, 102, 104, 103, 109, 111, 110, 112,
- 114, 113, 106, 108, 107, 133, 134, 101, 100, 137,
- 105, nil, nil, nil, nil, nil, 266, 129, 130, 132,
- 127, 128, 131, 105, 129, 130, 132, 127, 128, 131,
- 115, 116, 117, 121, 122, 123, 118, 119, 120, 124,
- 125, 126, 102, 104, 103, 109, 111, 110, 112, 114,
- 113, 106, 108, 107, 133, 134, 101, 100, 137, nil,
- nil, nil, nil, nil, nil, 105, nil, nil, nil, nil,
- nil, nil, 105, 129, 130, 132, 127, 128, 131, 115,
- 116, 117, 121, 122, 123, 118, 119, 120, 124, 125,
- 126, 102, 104, 103, 109, 111, 110, 112, 114, 113,
- 106, 108, 107, 133, 134, 101, 100, 137, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 275, 105, 129, 130, 132, 127, 128, 131, 115, 116,
- 117, 121, 122, 123, 118, 119, 120, 124, 125, 126,
- 102, 104, 103, 109, 111, 110, 112, 114, 113, 106,
- 108, 107, 133, 134, 101, 100, 137, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 105, 129, 130, 132, 127, 128, 131, 115, 116, 117,
- 121, 122, 123, 118, 119, 120, 124, 125, 126, 102,
- 104, 103, 109, 111, 110, 112, 114, 113, 106, 108,
- 107, 133, 134, 101, 100, 137, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 105,
- 129, 130, 132, 127, 128, 131, 115, 116, 117, 121,
- 122, 123, 118, 119, 120, 124, 125, 126, 102, 104,
- 103, 109, 111, 110, 112, 114, 113, 106, 108, 107,
- 133, 134, 101, 100, 137, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 105, 129,
- 130, 132, 127, 128, 131, 115, 116, 117, 121, 122,
- 123, 118, 119, 120, 124, 125, 126, 102, 104, 103,
- 109, 111, 110, 112, 114, 113, 106, 108, 107, 133,
- 134, 101, 100, 137, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 105, 129, 130,
- 132, 127, 128, 131, 115, 116, 117, 121, 122, 123,
- 118, 119, 120, 124, 125, 126, 129, 130, 132, 127,
- 128, 131, 115, 116, 117, 121, 122, 123, 118, 119,
- 120, 124, 125, 126, 102, 104, 103, 109, 111, 110,
- 112, 114, 113, 106, 108, 107, 105, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 105, 129, 130, 132, 127, 128,
- 131, 115, 116, 117, 121, 122, 123, 118, 119, 120,
- 124, 125, 126, 102, 104, 103, 109, 111, 110, 112,
- 114, 113, 106, 108, 107, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 105, 129, 130, 132, 127, 128, 131,
- 115, 116, 117, 121, 122, 123, 118, 119, 120, 124,
- 125, 126, 102, 104, 103, 109, 111, 110, 112, 114,
- 113, 106, 108, 107, 133, 134, 101, 100, 137, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 105, 129, 130, 132, 127, 128, 131, 115,
- 116, 117, 121, 122, 123, 118, 119, 120, 124, 125,
- 126, 102, 104, 103, 109, 111, 110, 112, 114, 113,
- 106, 108, 107, 133, 134, 101, 100, 137, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 105, 129, 130, 132, 127, 128, 131, 115, 116,
- 117, 121, 122, 123, 118, 119, 120, 124, 125, 126,
- 102, 104, 103, 109, 111, 110, 112, 114, 113, 106,
- 108, 107, 133, 134, 101, 100, 137, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 337,
- 105, 129, 130, 132, 127, 128, 131, 115, 116, 117,
- 121, 122, 123, 118, 119, 120, 124, 125, 126, 102,
- 104, 103, 109, 111, 110, 112, 114, 113, 106, 108,
- 107, 133, 134, 101, 100, 137, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 340, nil, nil, 341, 105,
- 129, 130, 132, 127, 128, 131, 115, 116, 117, 121,
- 122, 123, 118, 119, 120, 124, 125, 126, 102, 104,
- 103, 109, 111, 110, 112, 114, 113, 106, 108, 107,
- 133, 134, 101, 100, 137, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 105, 129,
- 130, 132, 127, 128, 131, 115, 116, 117, 121, 122,
- 123, 118, 119, 120, 124, 125, 126, 102, 104, 103,
- 109, 111, 110, 112, 114, 113, 106, 108, 107, 133,
- 134, 101, 100, 137, nil, nil, nil, nil, nil, nil,
- 266, nil, nil, nil, nil, nil, nil, 105, 129, 130,
- 132, 127, 128, 131, 115, 116, 117, 121, 122, 123,
- 118, 119, 120, 124, 125, 126, 102, 104, 103, 109,
- 111, 110, 112, 114, 113, 106, 108, 107, 133, 134,
- 101, 100, 137, nil, nil, nil, nil, nil, nil, 360,
- nil, nil, nil, nil, nil, nil, 105, 129, 130, 132,
- 127, 128, 131, 115, 116, 117, 121, 122, 123, 118,
- 119, 120, 124, 125, 126, 102, 104, 103, 109, 111,
- 110, 112, 114, 113, 106, 108, 107, 133, 134, 101,
- 100, 137, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 105, 129, 130, 132, 127,
- 128, 131, 115, 116, 117, 121, 122, 123, 118, 119,
- 120, 124, 125, 126, 102, 104, 103, 109, 111, 110,
- 112, 114, 113, 106, 108, 107, 133, 134, 101, 100,
- 137, nil, nil, nil, nil, nil, nil, 360, nil, nil,
- nil, nil, nil, nil, 105, 129, 130, 132, 127, 128,
- 131, 115, 116, 117, 121, 122, 123, 118, 119, 120,
- 124, 125, 126, 102, 104, 103, 109, 111, 110, 112,
- 114, 113, 106, 108, 107, 133, 134, 101, 100, 137,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 105, 129, 130, 132, 127, 128, 131,
- 115, 116, 117, 121, 122, 123, 118, 119, 120, 124,
- 125, 126, 102, 104, 103, 109, 111, 110, 112, 114,
- 113, 106, 108, 107, 133, 134, 101, 100, 137, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 105, 129, 130, 132, 127, 128, 131, 115,
- 116, 117, 121, 122, 123, 118, 119, 120, 124, 125,
- 126, 102, 104, 103, 109, 111, 110, 112, 114, 113,
- 106, 108, 107, 133, 134, 101, 100, 137, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 105, 129, 130, 132, 127, 128, 131, 115, 116,
- 117, 121, 122, 123, 118, 119, 120, 124, 125, 126,
- 102, 104, 103, 109, 111, 110, 112, 114, 113, 106,
- 108, 107, 133, 134, 101, 100, 137, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 105, 129, 130, 132, 127, 128, 131, 115, 116, 117,
- 121, 122, 123, 118, 119, 120, 124, 125, 126, 102,
- 104, 103, 109, 111, 110, 112, 114, 113, 106, 108,
- 107, 133, 134, 101, 100, 137, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 396, nil, nil, 341, 105,
- 129, 130, 132, 127, 128, 131, 115, 116, 117, 121,
- 122, 123, 118, 119, 120, 124, 125, 126, 102, 104,
- 103, 109, 111, 110, 112, 114, 113, 106, 108, 107,
- 133, 134, 101, 100, 137, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 105, 129,
- 130, 132, 127, 128, 131, 115, 116, 117, 121, 122,
- 123, 118, 119, 120, 124, 125, 126, 102, 104, 103,
- 109, 111, 110, 112, 114, 113, 106, 108, 107, 133,
- 134, 101, 100, 137, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 399, nil, nil, nil, 105, 129, 130,
- 132, 127, 128, 131, 115, 116, 117, 121, 122, 123,
- 118, 119, 120, 124, 125, 126, 102, 104, 103, 109,
- 111, 110, 112, 114, 113, 106, 108, 107, 133, 134,
- 101, 100, 137, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 105, 129, 130, 132,
- 127, 128, 131, 115, 116, 117, 121, 122, 123, 118,
- 119, 120, 124, 125, 126, 102, 104, 103, 109, 111,
- 110, 112, 114, 113, 106, 108, 107, 133, 134, 101,
- 100, 137, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 105, 129, 130, 132, 127,
- 128, 131, 115, 116, 117, 121, 122, 123, 118, 119,
- 120, 124, 125, 126, 102, 104, 103, 109, 111, 110,
- 112, 114, 113, 106, 108, 107, 133, 134, 101, 100,
- 137, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 105, 129, 130, 132, 127, 128,
- 131, 115, 116, 117, 121, 122, 123, 118, 119, 120,
- 124, 125, 126, 102, 104, 103, 109, 111, 110, 112,
- 114, 113, 106, 108, 107, 133, 134, 101, 100, 137,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 105, 129, 130, 132, 127, 128, 131,
- 115, 116, 117, 121, 122, 123, 118, 119, 120, 124,
- 125, 126, 102, 104, 103, 109, 111, 110, 112, 114,
- 113, 106, 108, 107, 133, 134, 101, 100, 137, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 105, 129, 130, 132, 127, 128, 131, 115,
- 116, 117, 121, 122, 123, 118, 119, 120, 124, 125,
- 126, 102, 104, 103, 109, 111, 110, 112, 114, 113,
- 106, 108, 107, 133, 134, 101, 100, 137, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 105, 129, 130, 132, 127, 128, 131, 115, 116,
- 117, 121, 122, 123, 118, 119, 120, 124, 125, 126,
- 102, 104, 103, 109, 111, 110, 112, 114, 113, 106,
- 108, 107, 133, 134, 101, 100, 137, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 105, 129, 130, 132, 127, 128, 131, 115, 116, 117,
- 121, 122, 123, 118, 119, 120, 124, 125, 126, 102,
- 104, 103, 109, 111, 110, 112, 114, 113, 106, 108,
- 107, 133, 134, 101, 100, 137, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 105,
- 129, 130, 132, 127, 128, 131, 115, 116, 117, 121,
- 122, 123, 118, 119, 120, 124, 125, 126, 102, 104,
- 103, 109, 111, 110, 112, 114, 113, 106, 108, 107,
- 133, 134, 101, 100, 137, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 105, 129,
- 130, 132, 127, 128, 131, 115, 116, 117, 121, 122,
- 123, 118, 119, 120, 124, 125, 126, 102, 104, 103,
- 109, 111, 110, 112, 114, 113, 106, 108, 107, 133,
- 134, 101, 100, 137, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 105 ]
-
-racc_action_check = [
- 22, 143, 74, 143, 22, 333, 376, 376, 182, 182,
- 370, 369, 433, 157, 57, 57, 74, 57, 155, 182,
- 157, 155, 369, 155, 3, 57, 57, 57, 93, 57,
- 57, 57, 333, 370, 376, 433, 330, 57, 57, 57,
- 202, 57, 330, 330, 202, 57, 57, 22, 22, 22,
- 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 57, 0, 3, 57, 332, 0, 93, 0,
- 0, 0, 0, 0, 376, 22, 0, 454, 0, 0,
- 287, 287, 0, 0, 0, 0, 0, 461, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 55, 0, 0, 0, 0, 0,
- 298, 466, 1, 0, 0, 298, 59, 59, 283, 283,
- 283, 283, 447, 283, 451, 464, 332, 59, 283, 283,
- 40, 40, 210, 447, 19, 451, 464, 454, 210, 181,
- 181, 287, 287, 175, 72, 72, 72, 461, 23, 200,
- 0, 213, 0, 0, 2, 0, 55, 277, 2, 161,
- 2, 2, 2, 2, 2, 162, 278, 2, 284, 2,
- 2, 466, 59, 2, 2, 2, 2, 2, 286, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 175, 2, 2, 2, 2,
- 2, 200, 86, 213, 2, 2, 161, 313, 266, 277,
- 314, 161, 162, 304, 360, 304, 24, 162, 278, 284,
- 284, 186, 186, 186, 138, 138, 138, 138, 27, 286,
- 286, 8, 138, 8, 8, 8, 403, 430, 73, 73,
- 73, 2, 32, 2, 2, 94, 2, 315, 35, 94,
- 86, 94, 94, 94, 94, 94, 285, 266, 94, 313,
- 94, 94, 314, 360, 94, 94, 94, 94, 94, 186,
- 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
- 94, 94, 94, 94, 94, 403, 430, 94, 94, 94,
- 94, 94, 281, 281, 315, 94, 94, 285, 285, 285,
- 285, 43, 187, 187, 187, 282, 282, 285, 285, 410,
- 70, 410, 222, 222, 222, 222, 222, 222, 222, 222,
- 222, 222, 222, 222, 222, 222, 222, 222, 222, 222,
- 290, 290, 94, 87, 94, 94, 95, 94, 387, 387,
- 95, 88, 95, 95, 95, 95, 95, 33, 89, 95,
- 187, 95, 95, 416, 416, 95, 95, 95, 95, 95,
- 222, 95, 95, 95, 95, 90, 95, 95, 95, 95,
- 95, 95, 95, 95, 95, 95, 95, 92, 95, 95,
- 95, 95, 95, 96, 97, 203, 95, 95, 33, 33,
- 33, 33, 31, 31, 31, 31, 331, 31, 331, 331,
- 386, 331, 386, 386, 140, 386, 42, 42, 42, 42,
- 141, 203, 66, 66, 66, 66, 146, 235, 235, 235,
- 235, 235, 235, 95, 148, 150, 95, 151, 95, 203,
- 203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
- 203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
- 203, 203, 203, 203, 203, 203, 203, 203, 203, 203,
- 203, 203, 203, 203, 204, 235, 154, 160, 166, 169,
- 170, 174, 178, 183, 184, 185, 189, 203, 199, 207,
- 208, 209, 212, 249, 250, 252, 260, 268, 293, 297,
- 204, 299, 300, 301, 305, 236, 236, 236, 236, 236,
- 236, 237, 237, 237, 237, 237, 237, 312, 204, 204,
- 204, 204, 204, 204, 204, 204, 204, 204, 204, 204,
- 204, 204, 204, 204, 204, 204, 204, 204, 204, 204,
- 204, 204, 204, 204, 204, 204, 204, 204, 204, 204,
- 204, 204, 204, 236, 211, 247, 247, 247, 211, 237,
- 211, 211, 211, 211, 211, 318, 204, 211, 322, 211,
- 211, 324, 325, 211, 211, 211, 211, 211, 334, 211,
- 211, 211, 211, 211, 211, 211, 211, 211, 211, 211,
- 211, 211, 211, 211, 211, 335, 211, 211, 211, 211,
- 211, 336, 339, 247, 211, 211, 344, 345, 220, 220,
- 220, 220, 220, 220, 220, 220, 220, 220, 220, 220,
- 220, 220, 220, 220, 220, 220, 220, 220, 220, 220,
- 220, 220, 220, 220, 220, 220, 220, 220, 220, 220,
- 220, 211, 353, 211, 211, 320, 211, 355, 356, 320,
- 320, 320, 320, 320, 320, 320, 220, 359, 320, 367,
- 320, 320, 368, 385, 320, 320, 320, 320, 320, 389,
- 320, 320, 320, 320, 320, 320, 320, 320, 320, 320,
- 320, 320, 320, 320, 320, 391, 392, 320, 320, 320,
- 320, 320, 404, 408, 411, 320, 320, 412, 417, 221,
- 221, 221, 221, 221, 221, 221, 221, 221, 221, 221,
- 221, 221, 221, 221, 221, 221, 221, 221, 221, 221,
- 221, 221, 221, 221, 221, 221, 221, 221, 221, 221,
- 221, 420, 320, 421, 320, 320, 438, 320, 422, 423,
- 438, 425, 438, 438, 438, 438, 438, 221, 428, 438,
- 429, 438, 438, 432, 434, 438, 438, 438, 438, 438,
- 445, 438, 438, 438, 438, 438, 438, 438, 438, 438,
- 438, 438, 438, 438, 438, 438, 448, 449, 438, 438,
- 438, 438, 438, 456, 457, 458, 438, 438, 459, 467,
- 223, 223, 223, 223, 223, 223, 223, 223, 223, 223,
- 223, 223, 223, 223, 223, 223, 223, 223, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 248,
- 248, 248, nil, 438, nil, 438, 438, 455, 438, nil,
- nil, 455, nil, 455, 455, 455, 455, 455, 223, nil,
- 455, nil, 455, 455, nil, nil, 455, 455, 455, 455,
- 455, nil, 455, 455, 455, 455, 455, 455, 455, 455,
- 455, 455, 455, 455, 455, 455, 455, 248, nil, 455,
- 455, 455, 455, 455, nil, nil, nil, 455, 455, nil,
- nil, 224, 224, 224, 224, 224, 224, 224, 224, 224,
- 224, 224, 224, 224, 224, 224, 224, 224, 224, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 251, 251, 251, nil, 455, nil, 455, 455, 460, 455,
- nil, nil, 460, nil, 460, 460, 460, 460, 460, 224,
- nil, 460, nil, 460, 460, nil, nil, 460, 460, 460,
- 460, 460, nil, 460, 460, 460, 460, 460, 460, 460,
- 460, 460, 460, 460, 460, 460, 460, 460, 251, nil,
- 460, 460, 460, 460, 460, nil, nil, nil, 460, 460,
- 375, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 460, nil, 460, 460, nil,
- 460, nil, 375, 375, 375, 375, 375, 375, 375, 375,
- 375, 375, 375, 375, 375, 375, 375, 375, 375, 375,
- 375, 375, 375, 375, 375, 375, 375, 375, 375, 375,
- 375, 375, 375, 375, 375, 375, 375, 378, nil, nil,
- nil, nil, nil, nil, nil, nil, 139, 139, nil, 139,
- 375, nil, 139, nil, nil, nil, nil, 139, 139, 139,
- nil, 139, 139, 139, 139, nil, nil, nil, nil, 139,
- 139, 139, nil, 139, nil, nil, nil, 139, 139, 378,
- 378, 378, 378, 378, 378, 378, 378, 378, 378, 378,
- 378, 378, 378, 378, 378, 378, 378, 378, 378, 378,
- 378, 378, 378, 378, 378, 378, 378, 378, 378, 378,
- 378, 378, 378, 378, 139, nil, nil, 139, nil, 139,
- nil, 139, 258, 258, nil, 258, nil, 378, 258, nil,
- nil, nil, nil, 258, 258, 258, nil, 258, 258, 258,
- 258, nil, nil, nil, nil, 258, 258, 258, nil, 258,
- nil, nil, nil, 258, 258, 58, 58, 58, nil, 58,
- nil, nil, 58, nil, nil, nil, nil, 58, 58, 58,
- nil, 58, 58, 58, 58, nil, nil, 58, nil, 58,
- 58, 58, nil, 58, nil, nil, nil, 58, 58, nil,
- 258, nil, nil, 258, nil, 258, nil, 258, nil, 226,
- 226, 226, 226, 226, 226, 226, 226, 226, 226, 226,
- 226, 226, 226, 226, 226, 226, 226, nil, 147, 147,
- 147, nil, 147, nil, 58, 147, nil, 58, nil, 58,
- 147, 147, 147, nil, 147, 147, 147, 147, nil, nil,
- nil, nil, 147, 147, 147, nil, 147, 226, nil, nil,
- 147, 147, 165, 165, 165, nil, 165, nil, nil, 165,
- nil, nil, nil, nil, 165, 165, 165, nil, 165, 165,
- 165, 165, nil, nil, nil, nil, 165, 165, 165, nil,
- 165, nil, nil, nil, 165, 165, nil, 147, 147, nil,
- 147, nil, 147, nil, nil, 227, 227, 227, 227, 227,
- 227, 227, 227, 227, 227, 227, 227, 227, 227, 227,
- 227, 227, 227, nil, nil, nil, 171, 171, 171, nil,
- 171, 165, 165, 171, 165, nil, 165, nil, 171, 171,
- 171, nil, 171, 171, 171, 171, nil, nil, nil, nil,
- 171, 171, 171, 227, 171, nil, nil, nil, 171, 171,
- 176, 176, 176, nil, 176, nil, nil, 176, nil, nil,
- nil, nil, 176, 176, 176, nil, 176, 176, 176, 176,
- nil, nil, nil, nil, 176, 176, 176, nil, 176, nil,
- nil, nil, 176, 176, nil, 171, 171, nil, 171, nil,
- 171, nil, nil, 228, 228, 228, 228, 228, 228, 228,
- 228, 228, 228, 228, 228, 228, 228, 228, 228, 228,
- 228, nil, nil, nil, 215, 215, 215, nil, 215, 176,
- 176, 215, 176, nil, 176, nil, 215, 215, 215, nil,
- 215, 215, 215, 215, nil, nil, nil, nil, 215, 215,
- 215, 228, 215, nil, nil, nil, 215, 215, 267, 267,
- 267, nil, 267, nil, nil, 267, nil, nil, nil, nil,
- 267, 267, 267, nil, 267, 267, 267, 267, nil, nil,
- nil, nil, 267, 267, 267, nil, 267, nil, nil, nil,
- 267, 267, nil, 215, 215, nil, 215, nil, 215, nil,
- nil, 229, 229, 229, 229, 229, 229, 229, 229, 229,
- 229, 229, 229, 229, 229, 229, 229, 229, 229, nil,
- nil, nil, nil, 274, 274, nil, 274, 267, 267, 274,
- 267, nil, 267, nil, 274, 274, 274, nil, 274, 274,
- 274, 274, nil, nil, nil, nil, 274, 274, 274, 229,
- 274, nil, nil, nil, 274, 274, 276, 276, 276, nil,
- 276, nil, nil, 276, nil, nil, nil, nil, 276, 276,
- 276, nil, 276, 276, 276, 276, nil, nil, nil, nil,
- 276, 276, 276, nil, 276, nil, nil, nil, 276, 276,
- nil, 274, nil, nil, 274, nil, 274, 274, nil, 230,
- 230, 230, 230, 230, 230, 230, 230, 230, 230, 230,
- 230, 230, 230, 230, 230, 230, 230, nil, nil, nil,
- 295, 295, 295, nil, 295, 276, 276, 295, 276, nil,
- 276, nil, 295, 295, 295, nil, 295, 295, 295, 295,
- nil, nil, nil, nil, 295, 295, 295, 230, 295, nil,
- nil, nil, 295, 295, 302, 302, 302, nil, 302, nil,
- nil, 302, nil, nil, nil, nil, 302, 302, 302, nil,
- 302, 302, 302, 302, nil, nil, nil, nil, 302, 302,
- 302, nil, 302, nil, nil, nil, 302, 302, nil, 295,
- 295, nil, 295, nil, 295, nil, 231, 231, 231, 231,
- 231, 231, 231, 231, 231, 231, 231, 231, 231, 231,
- 231, 231, 231, 231, nil, nil, nil, 362, 362, 362,
- nil, 362, nil, 302, 362, nil, 302, nil, 302, 362,
- 362, 362, nil, 362, 362, 362, 362, nil, nil, nil,
- nil, 362, 362, 362, 231, 362, nil, nil, nil, 362,
- 362, 393, 393, 393, nil, 393, nil, nil, 393, nil,
- nil, nil, nil, 393, 393, 393, nil, 393, 393, 393,
- 393, nil, nil, nil, nil, 393, 393, 393, nil, 393,
- nil, nil, nil, 393, 393, nil, 362, 362, nil, 362,
- nil, 362, nil, nil, 232, 232, 232, 232, 232, 232,
- 232, 232, 232, 232, 232, 232, 232, 232, 232, 232,
- 232, 232, nil, nil, nil, nil, 29, 29, nil, 29,
- 393, 393, 29, 393, nil, 393, nil, 29, 29, 29,
- nil, 29, 29, 29, 29, nil, nil, nil, nil, 29,
- 29, 29, 232, 29, nil, nil, nil, 29, 29, 52,
- 52, nil, 52, nil, nil, 52, nil, nil, nil, nil,
- 52, 52, 52, nil, 52, 52, 52, 52, nil, nil,
- 52, nil, 52, 52, 52, nil, 52, nil, nil, nil,
- 52, 52, 54, 54, 29, 54, nil, 29, 54, 29,
- nil, nil, nil, 54, 54, 54, nil, 54, 54, 54,
- 54, nil, nil, 54, nil, 54, 54, 54, nil, 54,
- nil, nil, nil, 54, 54, 56, 56, 52, 56, nil,
- 52, 56, 52, nil, nil, 56, 56, 56, 56, nil,
- 56, 56, 56, 56, nil, nil, nil, nil, 56, 56,
- 56, nil, 56, nil, nil, nil, 56, 56, 61, 61,
- 54, 61, nil, 54, 61, 54, nil, nil, nil, 61,
- 61, 61, nil, 61, 61, 61, 61, nil, nil, nil,
- nil, 61, 61, 61, nil, 61, nil, nil, nil, 61,
- 61, 62, 62, 56, 62, nil, 56, 62, 56, nil,
- nil, nil, 62, 62, 62, nil, 62, 62, 62, 62,
- nil, nil, nil, nil, 62, 62, 62, nil, 62, nil,
- nil, nil, 62, 62, 63, 63, 61, 63, nil, 61,
- 63, 61, nil, nil, nil, 63, 63, 63, nil, 63,
- 63, 63, 63, nil, nil, nil, nil, 63, 63, 63,
- nil, 63, nil, nil, nil, 63, 63, 78, 78, 62,
- 78, nil, 62, 78, 62, nil, nil, nil, 78, 78,
- 78, nil, 78, 78, 78, 78, nil, nil, 78, nil,
- 78, 78, 78, nil, 78, nil, nil, nil, 78, 78,
- 80, 80, 63, 80, nil, 63, 80, 63, nil, nil,
- nil, 80, 80, 80, nil, 80, 80, 80, 80, nil,
- nil, nil, nil, 80, 80, 80, nil, 80, nil, nil,
- nil, 80, 80, 81, 81, 78, 81, nil, 78, 81,
- 78, nil, nil, nil, 81, 81, 81, nil, 81, 81,
- 81, 81, nil, nil, nil, nil, 81, 81, 81, nil,
- 81, nil, nil, nil, 81, 81, 82, 82, 80, 82,
- nil, 80, 82, 80, nil, nil, nil, 82, 82, 82,
- nil, 82, 82, 82, 82, nil, nil, nil, nil, 82,
- 82, 82, nil, 82, nil, nil, nil, 82, 82, 85,
- 85, 81, 85, nil, 81, 85, 81, nil, nil, nil,
- 85, 85, 85, nil, 85, 85, 85, 85, nil, nil,
- nil, nil, 85, 85, 85, nil, 85, nil, nil, nil,
- 85, 85, 100, 100, 82, 100, nil, 82, 100, 82,
- nil, nil, nil, 100, 100, 100, nil, 100, 100, 100,
- 100, nil, nil, nil, nil, 100, 100, 100, nil, 100,
- nil, nil, nil, 100, 100, 101, 101, 85, 101, nil,
- 85, 101, 85, nil, nil, nil, 101, 101, 101, nil,
- 101, 101, 101, 101, nil, nil, nil, nil, 101, 101,
- 101, nil, 101, nil, nil, nil, 101, 101, 102, 102,
- 100, 102, nil, 100, 102, 100, nil, nil, nil, 102,
- 102, 102, nil, 102, 102, 102, 102, nil, nil, nil,
- nil, 102, 102, 102, nil, 102, nil, nil, nil, 102,
- 102, 103, 103, 101, 103, nil, 101, 103, 101, nil,
- nil, nil, 103, 103, 103, nil, 103, 103, 103, 103,
- nil, nil, nil, nil, 103, 103, 103, nil, 103, nil,
- nil, nil, 103, 103, 104, 104, 102, 104, nil, 102,
- 104, 102, nil, nil, nil, 104, 104, 104, nil, 104,
- 104, 104, 104, nil, nil, nil, nil, 104, 104, 104,
- nil, 104, nil, nil, nil, 104, 104, 105, 105, 103,
- 105, nil, 103, 105, 103, nil, nil, nil, 105, 105,
- 105, nil, 105, 105, 105, 105, nil, nil, nil, nil,
- 105, 105, 105, nil, 105, nil, nil, nil, 105, 105,
- 106, 106, 104, 106, nil, 104, 106, 104, nil, nil,
- nil, 106, 106, 106, nil, 106, 106, 106, 106, nil,
- nil, nil, nil, 106, 106, 106, nil, 106, nil, nil,
- nil, 106, 106, 107, 107, 105, 107, nil, 105, 107,
- 105, nil, nil, nil, 107, 107, 107, nil, 107, 107,
- 107, 107, nil, nil, nil, nil, 107, 107, 107, nil,
- 107, nil, nil, nil, 107, 107, 108, 108, 106, 108,
- nil, 106, 108, 106, nil, nil, nil, 108, 108, 108,
- nil, 108, 108, 108, 108, nil, nil, nil, nil, 108,
- 108, 108, nil, 108, nil, nil, nil, 108, 108, 109,
- 109, 107, 109, nil, 107, 109, 107, nil, nil, nil,
- 109, 109, 109, nil, 109, 109, 109, 109, nil, nil,
- nil, nil, 109, 109, 109, nil, 109, nil, nil, nil,
- 109, 109, 110, 110, 108, 110, nil, 108, 110, 108,
- nil, nil, nil, 110, 110, 110, nil, 110, 110, 110,
- 110, nil, nil, nil, nil, 110, 110, 110, nil, 110,
- nil, nil, nil, 110, 110, 111, 111, 109, 111, nil,
- 109, 111, 109, nil, nil, nil, 111, 111, 111, nil,
- 111, 111, 111, 111, nil, nil, nil, nil, 111, 111,
- 111, nil, 111, nil, nil, nil, 111, 111, 112, 112,
- 110, 112, nil, 110, 112, 110, nil, nil, nil, 112,
- 112, 112, nil, 112, 112, 112, 112, nil, nil, nil,
- nil, 112, 112, 112, nil, 112, nil, nil, nil, 112,
- 112, 113, 113, 111, 113, nil, 111, 113, 111, nil,
- nil, nil, 113, 113, 113, nil, 113, 113, 113, 113,
- nil, nil, nil, nil, 113, 113, 113, nil, 113, nil,
- nil, nil, 113, 113, 114, 114, 112, 114, nil, 112,
- 114, 112, nil, nil, nil, 114, 114, 114, nil, 114,
- 114, 114, 114, nil, nil, nil, nil, 114, 114, 114,
- nil, 114, nil, nil, nil, 114, 114, 115, 115, 113,
- 115, nil, 113, 115, 113, nil, nil, nil, 115, 115,
- 115, nil, 115, 115, 115, 115, nil, nil, nil, nil,
- 115, 115, 115, nil, 115, nil, nil, nil, 115, 115,
- 116, 116, 114, 116, nil, 114, 116, 114, nil, nil,
- nil, 116, 116, 116, nil, 116, 116, 116, 116, nil,
- nil, nil, nil, 116, 116, 116, nil, 116, nil, nil,
- nil, 116, 116, 117, 117, 115, 117, nil, 115, 117,
- 115, nil, nil, nil, 117, 117, 117, nil, 117, 117,
- 117, 117, nil, nil, nil, nil, 117, 117, 117, nil,
- 117, nil, nil, nil, 117, 117, 118, 118, 116, 118,
- nil, 116, 118, 116, nil, nil, nil, 118, 118, 118,
- nil, 118, 118, 118, 118, nil, nil, nil, nil, 118,
- 118, 118, nil, 118, nil, nil, nil, 118, 118, 119,
- 119, 117, 119, nil, 117, 119, 117, nil, nil, nil,
- 119, 119, 119, nil, 119, 119, 119, 119, nil, nil,
- nil, nil, 119, 119, 119, nil, 119, nil, nil, nil,
- 119, 119, 120, 120, 118, 120, nil, 118, 120, 118,
- nil, nil, nil, 120, 120, 120, nil, 120, 120, 120,
- 120, nil, nil, nil, nil, 120, 120, 120, nil, 120,
- nil, nil, nil, 120, 120, 121, 121, 119, 121, nil,
- 119, 121, 119, nil, nil, nil, 121, 121, 121, nil,
- 121, 121, 121, 121, nil, nil, nil, nil, 121, 121,
- 121, nil, 121, nil, nil, nil, 121, 121, 122, 122,
- 120, 122, nil, 120, 122, 120, nil, nil, nil, 122,
- 122, 122, nil, 122, 122, 122, 122, nil, nil, nil,
- nil, 122, 122, 122, nil, 122, nil, nil, nil, 122,
- 122, 123, 123, 121, 123, nil, 121, 123, 121, nil,
- nil, nil, 123, 123, 123, nil, 123, 123, 123, 123,
- nil, nil, nil, nil, 123, 123, 123, nil, 123, nil,
- nil, nil, 123, 123, 124, 124, 122, 124, nil, 122,
- 124, 122, nil, nil, nil, 124, 124, 124, nil, 124,
- 124, 124, 124, nil, nil, nil, nil, 124, 124, 124,
- nil, 124, nil, nil, nil, 124, 124, 125, 125, 123,
- 125, nil, 123, 125, 123, nil, nil, nil, 125, 125,
- 125, nil, 125, 125, 125, 125, nil, nil, nil, nil,
- 125, 125, 125, nil, 125, nil, nil, nil, 125, 125,
- 126, 126, 124, 126, nil, 124, 126, 124, nil, nil,
- nil, 126, 126, 126, nil, 126, 126, 126, 126, nil,
- nil, nil, nil, 126, 126, 126, nil, 126, nil, nil,
- nil, 126, 126, 127, 127, 125, 127, nil, 125, 127,
- 125, nil, nil, nil, 127, 127, 127, nil, 127, 127,
- 127, 127, nil, nil, nil, nil, 127, 127, 127, nil,
- 127, nil, nil, nil, 127, 127, 128, 128, 126, 128,
- nil, 126, 128, 126, nil, nil, nil, 128, 128, 128,
- nil, 128, 128, 128, 128, nil, nil, nil, nil, 128,
- 128, 128, nil, 128, nil, nil, nil, 128, 128, 129,
- 129, 127, 129, nil, 127, 129, 127, nil, nil, nil,
- 129, 129, 129, nil, 129, 129, 129, 129, nil, nil,
- nil, nil, 129, 129, 129, nil, 129, nil, nil, nil,
- 129, 129, 130, 130, 128, 130, nil, 128, 130, 128,
- nil, nil, nil, 130, 130, 130, nil, 130, 130, 130,
- 130, nil, nil, nil, nil, 130, 130, 130, nil, 130,
- nil, nil, nil, 130, 130, 131, 131, 129, 131, nil,
- 129, 131, 129, nil, nil, nil, 131, 131, 131, nil,
- 131, 131, 131, 131, nil, nil, nil, nil, 131, 131,
- 131, nil, 131, nil, nil, nil, 131, 131, 132, 132,
- 130, 132, nil, 130, 132, 130, nil, nil, nil, 132,
- 132, 132, nil, 132, 132, 132, 132, nil, nil, nil,
- nil, 132, 132, 132, nil, 132, nil, nil, nil, 132,
- 132, 133, 133, 131, 133, nil, 131, 133, 131, nil,
- nil, nil, 133, 133, 133, nil, 133, 133, 133, 133,
- nil, nil, nil, nil, 133, 133, 133, nil, 133, nil,
- nil, nil, 133, 133, 134, 134, 132, 134, nil, 132,
- 134, 132, nil, nil, nil, 134, 134, 134, nil, 134,
- 134, 134, 134, nil, nil, nil, nil, 134, 134, 134,
- nil, 134, nil, nil, nil, 134, 134, 135, 135, 133,
- 135, nil, 133, 135, 133, nil, nil, nil, 135, 135,
- 135, nil, 135, 135, 135, 135, nil, nil, nil, nil,
- 135, 135, 135, nil, 135, nil, nil, nil, 135, 135,
- 136, 136, 134, 136, nil, 134, 136, 134, nil, nil,
- nil, 136, 136, 136, nil, 136, 136, 136, 136, nil,
- nil, nil, nil, 136, 136, 136, nil, 136, nil, nil,
- nil, 136, 136, 137, 137, 135, 137, nil, 135, 137,
- 135, nil, nil, nil, 137, 137, 137, nil, 137, 137,
- 137, 137, nil, nil, nil, nil, 137, 137, 137, nil,
- 137, nil, nil, nil, 137, 137, 164, 164, 136, 164,
- nil, 136, 164, 136, nil, nil, nil, 164, 164, 164,
- nil, 164, 164, 164, 164, nil, nil, nil, nil, 164,
- 164, 164, nil, 164, nil, nil, nil, 164, 164, 173,
- 173, 137, 173, nil, 137, 173, 137, nil, nil, nil,
- 173, 173, 173, nil, 173, 173, 173, 173, nil, nil,
- 173, nil, 173, 173, 173, nil, 173, nil, nil, nil,
- 173, 173, 180, 180, 164, 180, nil, 164, 180, 164,
- nil, nil, nil, 180, 180, 180, nil, 180, 180, 180,
- 180, nil, nil, nil, nil, 180, 180, 180, nil, 180,
- nil, nil, nil, 180, 180, 188, 188, 173, 188, nil,
- 173, 188, 173, nil, nil, nil, 188, 188, 188, nil,
- 188, 188, 188, 188, nil, nil, nil, nil, 188, 188,
- 188, nil, 188, nil, nil, nil, 188, 188, 191, 191,
- 180, 191, nil, 180, 191, 180, nil, nil, nil, 191,
- 191, 191, nil, 191, 191, 191, 191, nil, nil, nil,
- nil, 191, 191, 191, nil, 191, nil, nil, nil, 191,
- 191, 192, 192, 188, 192, nil, 188, 192, 188, nil,
- nil, nil, 192, 192, 192, nil, 192, 192, 192, 192,
- nil, nil, nil, nil, 192, 192, 192, nil, 192, nil,
- nil, nil, 192, 192, 193, 193, 191, 193, nil, 191,
- 193, 191, nil, nil, nil, 193, 193, 193, nil, 193,
- 193, 193, 193, nil, nil, nil, nil, 193, 193, 193,
- nil, 193, nil, nil, nil, 193, 193, 194, 194, 192,
- 194, nil, 192, 194, 192, nil, nil, nil, 194, 194,
- 194, nil, 194, 194, 194, 194, nil, nil, nil, nil,
- 194, 194, 194, nil, 194, nil, nil, nil, 194, 194,
- 261, 261, 193, 261, nil, 193, 261, 193, nil, nil,
- nil, 261, 261, 261, nil, 261, 261, 261, 261, nil,
- nil, 261, nil, 261, 261, 261, nil, 261, nil, nil,
- nil, 261, 261, 270, 270, 194, 270, nil, 194, 270,
- 194, nil, nil, nil, 270, 270, 270, nil, 270, 270,
- 270, 270, nil, nil, nil, nil, 270, 270, 270, nil,
- 270, nil, nil, nil, 270, 270, 272, 272, 261, 272,
- nil, 261, 272, 261, nil, nil, nil, 272, 272, 272,
- nil, 272, 272, 272, 272, nil, nil, nil, nil, 272,
- 272, 272, nil, 272, nil, nil, nil, 272, 272, 275,
- 275, 270, 275, nil, 270, 275, 270, nil, nil, nil,
- 275, 275, 275, nil, 275, 275, 275, 275, nil, nil,
- nil, nil, 275, 275, 275, nil, 275, nil, nil, nil,
- 275, 275, nil, nil, 272, nil, nil, 272, 272, 272,
- 233, 233, 233, 233, 233, 233, 233, 233, 233, 233,
- 233, 233, 233, 233, 233, 233, 233, 233, nil, nil,
- nil, nil, 288, 288, nil, 288, nil, 275, 288, nil,
- 275, nil, 275, 288, 288, 288, nil, 288, 288, 288,
- 288, nil, nil, 288, nil, 288, 288, 288, 233, 288,
- nil, nil, nil, 288, 288, 291, 291, nil, 291, nil,
- nil, 291, nil, nil, nil, nil, 291, 291, 291, nil,
- 291, 291, 291, 291, nil, nil, nil, nil, 291, 291,
- 291, nil, 291, nil, nil, nil, 291, 291, 294, 294,
- 288, 294, nil, 288, 294, 288, nil, nil, nil, 294,
- 294, 294, nil, 294, 294, 294, 294, nil, nil, nil,
- nil, 294, 294, 294, nil, 294, nil, nil, nil, 294,
- 294, 316, 316, 291, 316, nil, 291, 316, 291, nil,
- nil, nil, 316, 316, 316, nil, 316, 316, 316, 316,
- nil, nil, nil, nil, 316, 316, 316, nil, 316, nil,
- nil, nil, 316, 316, 317, 317, 294, 317, nil, 294,
- 317, 294, nil, nil, nil, 317, 317, 317, nil, 317,
- 317, 317, 317, nil, nil, nil, nil, 317, 317, 317,
- nil, 317, nil, nil, nil, 317, 317, 319, 319, 316,
- 319, nil, 316, 319, 316, nil, nil, nil, 319, 319,
- 319, nil, 319, 319, 319, 319, nil, nil, nil, nil,
- 319, 319, 319, nil, 319, nil, nil, nil, 319, 319,
- 323, 323, 317, 323, nil, 317, 323, 317, nil, nil,
- nil, 323, 323, 323, nil, 323, 323, 323, 323, nil,
- nil, nil, nil, 323, 323, 323, nil, 323, nil, nil,
- nil, 323, 323, 326, 326, 319, 326, nil, 319, 326,
- 319, nil, nil, nil, 326, 326, 326, nil, 326, 326,
- 326, 326, nil, nil, nil, nil, 326, 326, 326, nil,
- 326, nil, nil, nil, 326, 326, 327, 327, 323, 327,
- nil, 323, 327, 323, nil, nil, nil, 327, 327, 327,
- nil, 327, 327, 327, 327, nil, nil, nil, nil, 327,
- 327, 327, nil, 327, nil, nil, nil, 327, 327, 328,
- 328, 326, 328, nil, 326, 328, 326, nil, nil, nil,
- 328, 328, 328, nil, 328, 328, 328, 328, nil, nil,
- nil, nil, 328, 328, 328, nil, 328, nil, nil, nil,
- 328, 328, 337, 337, 327, 337, nil, 327, 337, 327,
- nil, nil, nil, 337, 337, 337, nil, 337, 337, 337,
- 337, nil, nil, nil, nil, 337, 337, 337, nil, 337,
- nil, nil, nil, 337, 337, 341, 341, 328, 341, nil,
- 328, 341, 328, nil, nil, nil, 341, 341, 341, nil,
- 341, 341, 341, 341, nil, nil, 341, nil, 341, 341,
- 341, nil, 341, nil, nil, nil, 341, 341, 365, 365,
- 337, 365, nil, 337, 365, 337, nil, nil, nil, 365,
- 365, 365, nil, 365, 365, 365, 365, nil, nil, nil,
- nil, 365, 365, 365, nil, 365, nil, nil, nil, 365,
- 365, 418, 418, 341, 418, nil, 341, 418, 341, nil,
- nil, nil, 418, 418, 418, nil, 418, 418, 418, 418,
- nil, nil, nil, nil, 418, 418, 418, nil, 418, nil,
- nil, nil, 418, 418, 435, 435, 365, 435, nil, 365,
- 435, 365, nil, nil, nil, 435, 435, 435, nil, 435,
- 435, 435, 435, nil, nil, nil, nil, 435, 435, 435,
- nil, 435, nil, nil, nil, 435, 435, 437, 437, 418,
- 437, nil, 418, 437, 418, nil, nil, nil, 437, 437,
- 437, nil, 437, 437, 437, 437, nil, nil, nil, nil,
- 437, 437, 437, nil, 437, nil, nil, nil, 437, 437,
- 64, 64, 435, 64, nil, 435, nil, 435, nil, nil,
- nil, 64, 64, 64, nil, 64, 64, 64, nil, nil,
- nil, nil, nil, 64, 64, 64, nil, 64, nil, nil,
- nil, 64, 64, 99, 99, 437, 99, nil, 437, nil,
- 437, nil, nil, nil, 99, 99, 99, nil, 99, 99,
- 99, 99, nil, nil, nil, nil, 99, 99, 99, nil,
- 99, nil, nil, nil, 99, 99, 142, 142, 64, 142,
- nil, 64, nil, nil, nil, nil, nil, 142, 142, 142,
- nil, 142, 142, 142, 142, nil, nil, nil, nil, 142,
- 142, 142, nil, 142, nil, nil, nil, 142, 142, nil,
- nil, 99, nil, nil, 99, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 205, nil, nil, nil, nil, nil, 238, 238, 238, 238,
- 238, 238, nil, nil, 142, nil, nil, 142, 205, 205,
- 205, 205, 205, 205, 205, 205, 205, 205, 205, 205,
- 205, 205, 205, 205, 205, 205, 205, 205, 205, 205,
- 205, 205, 205, 205, 205, 205, 205, 205, 205, 205,
- 205, 205, 205, 206, 238, nil, nil, nil, nil, 239,
- 239, 239, 239, 239, 239, nil, 205, nil, nil, nil,
- nil, 206, 206, 206, 206, 206, 206, 206, 206, 206,
- 206, 206, 206, 206, 206, 206, 206, 206, 206, 206,
- 206, 206, 206, 206, 206, 206, 206, 206, 206, 206,
- 206, 206, 206, 206, 206, 206, 381, 239, nil, nil,
- nil, nil, 240, 240, 240, 240, 240, 240, nil, 206,
- nil, nil, nil, nil, 381, 381, 381, 381, 381, 381,
- 381, 381, 381, 381, 381, 381, 381, 381, 381, 381,
- 381, 381, 381, 381, 381, 381, 381, 381, 381, 381,
- 381, 381, 381, 381, 381, 381, 381, 381, 381, 382,
- 240, nil, nil, nil, nil, 241, 241, 241, 241, 241,
- 241, nil, 381, nil, nil, nil, nil, 382, 382, 382,
- 382, 382, 382, 382, 382, 382, 382, 382, 382, 382,
- 382, 382, 382, 382, 382, 382, 382, 382, 382, 382,
- 382, 382, 382, 382, 382, 382, 382, 382, 382, 382,
- 382, 382, 383, 241, nil, nil, nil, nil, 242, 242,
- 242, 242, 242, 242, nil, 382, nil, nil, nil, nil,
- 383, 383, 383, 383, 383, 383, 383, 383, 383, 383,
- 383, 383, 383, 383, 383, 383, 383, 383, 383, 383,
- 383, 383, 383, 383, 383, 383, 383, 383, 383, 383,
- 383, 383, 383, 383, 383, 439, 242, nil, nil, nil,
- nil, 243, 243, 243, 243, 243, 243, nil, 383, nil,
- nil, nil, nil, 439, 439, 439, 439, 439, 439, 439,
- 439, 439, 439, 439, 439, 439, 439, 439, 439, 439,
- 439, 439, 439, 439, 439, 439, 439, 439, 439, 439,
- 439, 439, 439, 439, 439, 439, 439, 439, 453, 243,
- nil, nil, nil, 244, 244, 244, 244, 244, 244, nil,
- nil, 439, nil, nil, nil, nil, 453, 453, 453, 453,
- 453, 453, 453, 453, 453, 453, 453, 453, 453, 453,
- 453, 453, 453, 453, 453, 453, 453, 453, 453, 453,
- 453, 453, 453, 453, 453, 453, 453, 453, 453, 453,
- 453, 244, 245, 245, 245, 245, 245, 245, nil, nil,
- nil, nil, nil, nil, 453, 145, 145, 145, 145, 145,
- 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
- 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
- 145, 145, 145, 145, 145, 145, 145, 145, 145, 145,
- 245, nil, nil, nil, nil, nil, 145, 246, 246, 246,
- 246, 246, 246, 145, 156, 156, 156, 156, 156, 156,
- 156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
- 156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
- 156, 156, 156, 156, 156, 156, 156, 156, 156, nil,
- nil, nil, nil, nil, nil, 246, nil, nil, nil, nil,
- nil, nil, 156, 159, 159, 159, 159, 159, 159, 159,
- 159, 159, 159, 159, 159, 159, 159, 159, 159, 159,
- 159, 159, 159, 159, 159, 159, 159, 159, 159, 159,
- 159, 159, 159, 159, 159, 159, 159, 159, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 159, 159, 168, 168, 168, 168, 168, 168, 168, 168,
- 168, 168, 168, 168, 168, 168, 168, 168, 168, 168,
- 168, 168, 168, 168, 168, 168, 168, 168, 168, 168,
- 168, 168, 168, 168, 168, 168, 168, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 168, 179, 179, 179, 179, 179, 179, 179, 179, 179,
- 179, 179, 179, 179, 179, 179, 179, 179, 179, 179,
- 179, 179, 179, 179, 179, 179, 179, 179, 179, 179,
- 179, 179, 179, 179, 179, 179, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 179,
- 201, 201, 201, 201, 201, 201, 201, 201, 201, 201,
- 201, 201, 201, 201, 201, 201, 201, 201, 201, 201,
- 201, 201, 201, 201, 201, 201, 201, 201, 201, 201,
- 201, 201, 201, 201, 201, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 201, 225,
- 225, 225, 225, 225, 225, 225, 225, 225, 225, 225,
- 225, 225, 225, 225, 225, 225, 225, 225, 225, 225,
- 225, 225, 225, 225, 225, 225, 225, 225, 225, 225,
- 225, 225, 225, 225, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 225, 234, 234,
- 234, 234, 234, 234, 234, 234, 234, 234, 234, 234,
- 234, 234, 234, 234, 234, 234, 253, 253, 253, 253,
- 253, 253, 253, 253, 253, 253, 253, 253, 253, 253,
- 253, 253, 253, 253, 253, 253, 253, 253, 253, 253,
- 253, 253, 253, 253, 253, 253, 234, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 253, 254, 254, 254, 254, 254,
- 254, 254, 254, 254, 254, 254, 254, 254, 254, 254,
- 254, 254, 254, 254, 254, 254, 254, 254, 254, 254,
- 254, 254, 254, 254, 254, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 254, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, 255, 255, 255, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 255, 256, 256, 256, 256, 256, 256, 256,
- 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
- 256, 256, 256, 256, 256, 256, 256, 256, 256, 256,
- 256, 256, 256, 256, 256, 256, 256, 256, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 256, 257, 257, 257, 257, 257, 257, 257, 257,
- 257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
- 257, 257, 257, 257, 257, 257, 257, 257, 257, 257,
- 257, 257, 257, 257, 257, 257, 257, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 257,
- 257, 259, 259, 259, 259, 259, 259, 259, 259, 259,
- 259, 259, 259, 259, 259, 259, 259, 259, 259, 259,
- 259, 259, 259, 259, 259, 259, 259, 259, 259, 259,
- 259, 259, 259, 259, 259, 259, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 259, nil, nil, 259, 259,
- 289, 289, 289, 289, 289, 289, 289, 289, 289, 289,
- 289, 289, 289, 289, 289, 289, 289, 289, 289, 289,
- 289, 289, 289, 289, 289, 289, 289, 289, 289, 289,
- 289, 289, 289, 289, 289, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 289, 292,
- 292, 292, 292, 292, 292, 292, 292, 292, 292, 292,
- 292, 292, 292, 292, 292, 292, 292, 292, 292, 292,
- 292, 292, 292, 292, 292, 292, 292, 292, 292, 292,
- 292, 292, 292, 292, nil, nil, nil, nil, nil, nil,
- 292, nil, nil, nil, nil, nil, nil, 292, 296, 296,
- 296, 296, 296, 296, 296, 296, 296, 296, 296, 296,
- 296, 296, 296, 296, 296, 296, 296, 296, 296, 296,
- 296, 296, 296, 296, 296, 296, 296, 296, 296, 296,
- 296, 296, 296, nil, nil, nil, nil, nil, nil, 296,
- nil, nil, nil, nil, nil, nil, 296, 303, 303, 303,
- 303, 303, 303, 303, 303, 303, 303, 303, 303, 303,
- 303, 303, 303, 303, 303, 303, 303, 303, 303, 303,
- 303, 303, 303, 303, 303, 303, 303, 303, 303, 303,
- 303, 303, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 303, 307, 307, 307, 307,
- 307, 307, 307, 307, 307, 307, 307, 307, 307, 307,
- 307, 307, 307, 307, 307, 307, 307, 307, 307, 307,
- 307, 307, 307, 307, 307, 307, 307, 307, 307, 307,
- 307, nil, nil, nil, nil, nil, nil, 307, nil, nil,
- nil, nil, nil, nil, 307, 308, 308, 308, 308, 308,
- 308, 308, 308, 308, 308, 308, 308, 308, 308, 308,
- 308, 308, 308, 308, 308, 308, 308, 308, 308, 308,
- 308, 308, 308, 308, 308, 308, 308, 308, 308, 308,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 308, 309, 309, 309, 309, 309, 309,
- 309, 309, 309, 309, 309, 309, 309, 309, 309, 309,
- 309, 309, 309, 309, 309, 309, 309, 309, 309, 309,
- 309, 309, 309, 309, 309, 309, 309, 309, 309, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 309, 310, 310, 310, 310, 310, 310, 310,
- 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
- 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
- 310, 310, 310, 310, 310, 310, 310, 310, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 310, 311, 311, 311, 311, 311, 311, 311, 311,
- 311, 311, 311, 311, 311, 311, 311, 311, 311, 311,
- 311, 311, 311, 311, 311, 311, 311, 311, 311, 311,
- 311, 311, 311, 311, 311, 311, 311, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 311, 338, 338, 338, 338, 338, 338, 338, 338, 338,
- 338, 338, 338, 338, 338, 338, 338, 338, 338, 338,
- 338, 338, 338, 338, 338, 338, 338, 338, 338, 338,
- 338, 338, 338, 338, 338, 338, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 338, nil, nil, 338, 338,
- 343, 343, 343, 343, 343, 343, 343, 343, 343, 343,
- 343, 343, 343, 343, 343, 343, 343, 343, 343, 343,
- 343, 343, 343, 343, 343, 343, 343, 343, 343, 343,
- 343, 343, 343, 343, 343, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 343, 347,
- 347, 347, 347, 347, 347, 347, 347, 347, 347, 347,
- 347, 347, 347, 347, 347, 347, 347, 347, 347, 347,
- 347, 347, 347, 347, 347, 347, 347, 347, 347, 347,
- 347, 347, 347, 347, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 347, nil, nil, nil, 347, 349, 349,
- 349, 349, 349, 349, 349, 349, 349, 349, 349, 349,
- 349, 349, 349, 349, 349, 349, 349, 349, 349, 349,
- 349, 349, 349, 349, 349, 349, 349, 349, 349, 349,
- 349, 349, 349, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 349, 352, 352, 352,
- 352, 352, 352, 352, 352, 352, 352, 352, 352, 352,
- 352, 352, 352, 352, 352, 352, 352, 352, 352, 352,
- 352, 352, 352, 352, 352, 352, 352, 352, 352, 352,
- 352, 352, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 352, 358, 358, 358, 358,
- 358, 358, 358, 358, 358, 358, 358, 358, 358, 358,
- 358, 358, 358, 358, 358, 358, 358, 358, 358, 358,
- 358, 358, 358, 358, 358, 358, 358, 358, 358, 358,
- 358, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 358, 364, 364, 364, 364, 364,
- 364, 364, 364, 364, 364, 364, 364, 364, 364, 364,
- 364, 364, 364, 364, 364, 364, 364, 364, 364, 364,
- 364, 364, 364, 364, 364, 364, 364, 364, 364, 364,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 364, 372, 372, 372, 372, 372, 372,
- 372, 372, 372, 372, 372, 372, 372, 372, 372, 372,
- 372, 372, 372, 372, 372, 372, 372, 372, 372, 372,
- 372, 372, 372, 372, 372, 372, 372, 372, 372, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 372, 373, 373, 373, 373, 373, 373, 373,
- 373, 373, 373, 373, 373, 373, 373, 373, 373, 373,
- 373, 373, 373, 373, 373, 373, 373, 373, 373, 373,
- 373, 373, 373, 373, 373, 373, 373, 373, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 373, 395, 395, 395, 395, 395, 395, 395, 395,
- 395, 395, 395, 395, 395, 395, 395, 395, 395, 395,
- 395, 395, 395, 395, 395, 395, 395, 395, 395, 395,
- 395, 395, 395, 395, 395, 395, 395, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 395, 398, 398, 398, 398, 398, 398, 398, 398, 398,
- 398, 398, 398, 398, 398, 398, 398, 398, 398, 398,
- 398, 398, 398, 398, 398, 398, 398, 398, 398, 398,
- 398, 398, 398, 398, 398, 398, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 398,
- 405, 405, 405, 405, 405, 405, 405, 405, 405, 405,
- 405, 405, 405, 405, 405, 405, 405, 405, 405, 405,
- 405, 405, 405, 405, 405, 405, 405, 405, 405, 405,
- 405, 405, 405, 405, 405, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 405, 452,
- 452, 452, 452, 452, 452, 452, 452, 452, 452, 452,
- 452, 452, 452, 452, 452, 452, 452, 452, 452, 452,
- 452, 452, 452, 452, 452, 452, 452, 452, 452, 452,
- 452, 452, 452, 452, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 452 ]
-
-racc_action_pointer = [
- 81, 132, 172, -7, nil, nil, nil, nil, 209, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 66,
- nil, nil, -2, 76, 182, nil, nil, 160, nil, 1805,
- nil, 328, 219, 324, nil, 225, nil, nil, nil, nil,
- 117, nil, 342, 229, nil, nil, nil, nil, nil, nil,
- nil, nil, 1838, nil, 1871, 82, 1904, -7, 1155, 103,
- nil, 1937, 1970, 2003, 4409, nil, 348, nil, nil, nil,
- 288, nil, 120, 214, -42, nil, nil, nil, 2036, nil,
- 2069, 2102, 2135, nil, nil, 2168, 178, 322, 317, 324,
- 296, nil, 397, -3, 263, 354, 311, 362, nil, 4442,
- 2201, 2234, 2267, 2300, 2333, 2366, 2399, 2432, 2465, 2498,
- 2531, 2564, 2597, 2630, 2663, 2696, 2729, 2762, 2795, 2828,
- 2861, 2894, 2927, 2960, 2993, 3026, 3059, 3092, 3125, 3158,
- 3191, 3224, 3257, 3290, 3323, 3356, 3389, 3422, 160, 1045,
- 381, 388, 4475, -89, nil, 4886, 347, 1218, 401, nil,
- 402, 404, nil, nil, 394, -70, 4935, -75, nil, 4984,
- 398, 137, 143, nil, 3455, 1252, 400, nil, 5033, 400,
- 447, 1316, nil, 3488, 399, 121, 1350, nil, 404, 5082,
- 3521, 126, -25, 405, 452, 398, 192, 273, 3554, 404,
- nil, 3587, 3620, 3653, 3686, nil, nil, nil, nil, 456,
- 127, 5131, 38, 400, 479, 4519, 4572, 483, 484, 485,
- 145, 562, 460, 129, nil, 1414, nil, nil, nil, nil,
- 569, 660, 283, 751, 842, 5180, 1170, 1266, 1364, 1462,
- 1560, 1657, 1755, 3831, 5229, 388, 466, 472, 4507, 4560,
- 4613, 4666, 4719, 4772, 4824, 4873, 4928, 516, 780, 406,
- 407, 871, 408, 5247, 5296, 5345, 5394, 5443, 1121, 5492,
- 413, 3719, nil, nil, nil, nil, 185, 1448, 417, nil,
- 3752, nil, 3785, nil, 1512, 3818, 1546, 135, 144, nil,
- nil, 218, 231, 54, 145, 233, 155, 67, 3881, 5541,
- 256, 3914, 5590, 418, 3947, 1610, 5639, 419, 42, 419,
- 423, 423, 1644, 5688, 145, 470, nil, 5737, 5786, 5835,
- 5884, 5933, 472, 185, 188, 225, 3980, 4013, 568, 4046,
- 653, nil, 571, 4079, 574, 575, 4112, 4145, 4178, nil,
- 29, 385, 55, -26, 499, 517, 521, 4211, 5982, 519,
- nil, 4244, nil, 6031, 573, 525, nil, 6080, nil, 6129,
- nil, nil, 6178, 562, nil, 562, 563, nil, 6227, 577,
- 191, nil, 1707, nil, 6276, 4277, nil, 627, 628, -20,
- -9, nil, 6325, 6374, nil, 973, 3, nil, 1050, nil,
- nil, 4625, 4678, 4731, nil, 642, 389, 325, nil, 648,
- nil, 688, 652, 1741, nil, 6423, nil, nil, 6472, nil,
- nil, nil, nil, 213, 612, 6521, nil, nil, 696, nil,
- 241, 614, 623, nil, nil, nil, 370, 677, 4310, nil,
- 734, 736, 741, 742, nil, 720, nil, nil, 716, 670,
- 214, nil, 721, -7, 722, 4343, nil, 4376, 744, 4784,
- nil, nil, nil, nil, nil, 739, nil, 111, 696, 703,
- nil, 113, 6570, 4837, 66, 835, 786, 787, 753, 791,
- 926, 76, nil, nil, 114, nil, 100, 792, nil ]
-
-racc_action_default = [
- -1, -259, -2, -3, -4, -8, -9, -10, -11, -12,
- -13, -14, -15, -16, -17, -18, -19, -20, -21, -22,
- -23, -24, -25, -26, -27, -29, -30, -31, -32, -116,
- -34, -35, -36, -37, -38, -39, -40, -49, -50, -51,
- -52, -53, -54, -55, -56, -57, -58, -59, -60, -63,
- -64, -65, -69, -72, -75, -259, -116, -116, -119, -116,
- -115, -116, -116, -116, -116, -168, -259, -177, -179, -180,
- -259, -184, -116, -116, -116, -200, -201, -202, -217, -219,
- -116, -116, -116, -228, -229, -116, -116, -259, -116, -116,
- -257, -258, -259, -7, -116, -6, -259, -259, -188, -116,
- -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
- -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
- -116, -116, -116, -116, -116, -116, -116, -116, -116, -116,
- -116, -116, -116, -116, -116, -116, -116, -116, -83, -116,
- -28, -259, -116, -26, -31, -259, -259, -116, -80, -94,
- -79, -81, -61, -62, -182, -259, -70, -259, -76, -259,
- -259, -183, -185, -189, -116, -116, -101, -102, -127, -35,
- -37, -116, -54, -69, -259, -259, -116, -107, -120, -123,
- -116, -111, -116, -109, -259, -164, -165, -166, -116, -259,
- -167, -116, -116, -116, -116, -181, -186, -187, -117, -259,
- -259, -218, -214, -259, -259, -259, -259, -259, -259, -259,
- -237, -245, -259, -259, -255, -116, 469, -5, -183, -170,
- -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, -222, -225, -259, -116, -259,
- -259, -93, -97, -96, -169, -41, -33, -116, -259, -95,
- -116, -67, -116, -73, -116, -116, -116, -259, -190, -191,
- -192, -29, -30, -35, -36, -37, -39, -52, -75, -259,
- -259, -116, -123, -259, -116, -116, -123, -259, -259, -83,
- -259, -259, -116, -124, -259, -116, -110, -259, -171, -172,
- -173, -174, -259, -204, -203, -207, -116, -116, -259, -116,
- -116, -246, -259, -116, -259, -259, -116, -116, -116, -234,
- -259, -259, -244, -259, -105, -122, -259, -116, -259, -259,
- -86, -91, -87, -92, -82, -84, -99, -259, -68, -71,
- -74, -77, -78, -259, -193, -259, -259, -100, -128, -259,
- -259, -103, -116, -106, -125, -116, -108, -259, -116, -259,
- -208, -205, -215, -216, -220, -259, -244, -223, -259, -227,
- -230, -259, -259, -259, -235, -259, -259, -243, -238, -259,
- -242, -259, -116, -116, -256, -226, -88, -89, -90, -66,
- -98, -194, -195, -114, -259, -126, -112, -118, -259, -206,
- -259, -259, -209, -210, -221, -247, -248, -259, -116, -224,
- -259, -259, -259, -259, -240, -259, -239, -253, -259, -259,
- -113, -196, -207, -259, -207, -116, -249, -116, -116, -259,
- -231, -232, -233, -236, -241, -259, -104, -259, -259, -211,
- -212, -259, -213, -259, -250, -116, -259, -259, -207, -259,
- -116, -251, -254, -197, -259, -198, -252, -259, -199 ]
-
-racc_goto_table = [
- 2, 154, 3, 95, 27, 169, 27, 96, 210, 98,
- 390, 170, 148, 281, 155, 151, 183, 369, 413, 260,
- 389, 415, 172, 318, 322, 1, 282, 217, 140, 356,
- 284, 286, 209, 351, 166, 214, 97, 200, 335, 336,
- 190, 207, 410, 202, 177, 330, 416, nil, nil, nil,
- nil, 208, nil, nil, 154, nil, nil, nil, nil, nil,
- nil, 436, nil, nil, nil, 390, nil, nil, nil, nil,
- nil, 96, 96, 196, 197, 425, nil, nil, nil, nil,
- nil, 450, nil, nil, nil, 175, nil, 184, nil, nil,
- nil, nil, 160, 95, nil, nil, 145, nil, 27, 27,
- 97, 97, 198, 219, nil, nil, 181, nil, nil, nil,
- nil, nil, 283, nil, 97, nil, 212, 213, 285, 156,
- nil, 159, nil, 168, nil, 179, 324, 325, 185, 186,
- 187, 162, 299, 268, 447, 298, 451, 281, 339, 304,
- 281, 280, nil, 291, nil, 201, 264, 203, 204, 205,
- 282, 293, 206, 282, 284, 286, nil, 284, 286, nil,
- 464, nil, 301, nil, nil, nil, nil, 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, 256, 257, nil, 259, nil, nil, nil,
- 184, 287, 300, 332, 179, 27, nil, nil, nil, nil,
- nil, nil, nil, nil, 345, nil, nil, nil, nil, 181,
- nil, 289, 292, nil, nil, nil, 283, 315, 296, 283,
- 156, nil, 285, 292, nil, 285, 344, 303, nil, nil,
- 334, 162, 388, nil, 391, 307, nil, 280, 308, 309,
- 310, 311, 353, nil, 148, nil, 151, 291, nil, 355,
- nil, nil, nil, nil, nil, nil, 314, nil, nil, nil,
- nil, 359, 179, nil, nil, nil, nil, nil, nil, 314,
- 408, nil, nil, 280, nil, nil, nil, nil, nil, nil,
- nil, nil, 420, 421, 422, nil, 423, 424, nil, nil,
- 426, nil, nil, nil, nil, nil, nil, nil, 345, nil,
- nil, nil, 376, nil, 27, 338, nil, nil, 343, nil,
- nil, nil, 95, 367, 179, 287, 143, 347, 287, 349,
- 344, 159, 352, 179, nil, nil, 444, nil, 404, nil,
- nil, nil, nil, nil, nil, 159, nil, nil, 289, nil,
- nil, 358, 179, nil, 174, nil, 456, nil, 457, 364,
- nil, 189, 459, nil, nil, nil, 95, nil, 387, 429,
- nil, nil, nil, 372, 373, 467, 375, nil, nil, nil,
- 378, nil, nil, 381, 382, 383, 407, nil, nil, nil,
- nil, nil, nil, nil, 395, nil, 189, nil, 398, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 428, nil, nil, nil, nil, nil, nil, nil, nil, 179,
- nil, nil, 405, 387, nil, nil, nil, nil, nil, nil,
- 454, nil, 27, nil, nil, nil, nil, nil, nil, 189,
- nil, nil, nil, nil, 95, nil, nil, 461, nil, 27,
- 179, 95, 466, nil, 27, nil, 95, nil, nil, nil,
- nil, nil, 143, nil, nil, nil, nil, nil, 143, nil,
- nil, nil, nil, 143, nil, 439, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 143, nil, nil, nil, nil,
- nil, nil, 452, nil, 453 ]
-
-racc_goto_check = [
- 2, 50, 3, 2, 28, 31, 28, 42, 70, 64,
- 40, 33, 49, 26, 45, 49, 58, 69, 72, 52,
- 76, 77, 41, 74, 74, 1, 27, 4, 25, 37,
- 32, 35, 44, 48, 56, 57, 53, 59, 60, 61,
- 62, 65, 71, 73, 55, 75, 78, nil, nil, nil,
- nil, 41, nil, nil, 50, nil, nil, nil, nil, nil,
- nil, 77, nil, nil, nil, 40, nil, nil, nil, nil,
- nil, 42, 42, 64, 64, 76, nil, nil, nil, nil,
- nil, 72, nil, nil, nil, 53, nil, 53, nil, nil,
- nil, nil, 54, 2, nil, nil, 22, nil, 28, 28,
- 53, 53, 53, 28, nil, nil, 38, nil, nil, nil,
- nil, nil, 31, nil, 53, nil, 53, 53, 33, 22,
- nil, 22, nil, 22, nil, 22, 70, 70, 22, 22,
- 22, 66, 50, 55, 69, 45, 69, 26, 52, 58,
- 26, 67, nil, 67, nil, 22, 28, 22, 22, 22,
- 27, 55, 22, 27, 32, 35, nil, 32, 35, nil,
- 69, nil, 55, nil, nil, nil, nil, 22, 22, 22,
- 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, nil, 22, nil, nil, nil,
- 53, 38, 54, 3, 22, 28, nil, nil, nil, nil,
- nil, nil, nil, nil, 50, nil, nil, nil, nil, 38,
- nil, 22, 22, nil, nil, nil, 31, 54, 22, 31,
- 22, nil, 33, 22, nil, 33, 49, 22, nil, nil,
- 54, 66, 70, nil, 70, 22, nil, 67, 22, 22,
- 22, 22, 55, nil, 49, nil, 49, 67, nil, 67,
- nil, nil, nil, nil, nil, nil, 66, nil, nil, nil,
- nil, 55, 22, nil, nil, nil, nil, nil, nil, 66,
- 70, nil, nil, 67, nil, nil, nil, nil, nil, nil,
- nil, nil, 70, 70, 70, nil, 70, 70, nil, nil,
- 70, nil, nil, nil, nil, nil, nil, nil, 50, nil,
- nil, nil, 3, nil, 28, 22, nil, nil, 22, nil,
- nil, nil, 2, 53, 22, 38, 23, 22, 38, 22,
- 49, 22, 22, 22, nil, nil, 70, nil, 55, nil,
- nil, nil, nil, nil, nil, 22, nil, nil, 22, nil,
- nil, 22, 22, nil, 23, nil, 70, nil, 70, 22,
- nil, 23, 70, nil, nil, nil, 2, nil, 38, 55,
- nil, nil, nil, 22, 22, 70, 22, nil, nil, nil,
- 22, nil, nil, 22, 22, 22, 53, nil, nil, nil,
- nil, nil, nil, nil, 22, nil, 23, nil, 22, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 53, nil, nil, nil, nil, nil, nil, nil, nil, 22,
- nil, nil, 22, 38, nil, nil, nil, nil, nil, nil,
- 3, nil, 28, nil, nil, nil, nil, nil, nil, 23,
- nil, nil, nil, nil, 2, nil, nil, 3, nil, 28,
- 22, 2, 3, nil, 28, nil, 2, nil, nil, nil,
- nil, nil, 23, nil, nil, nil, nil, nil, 23, nil,
- nil, nil, nil, 23, nil, 22, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 23, nil, nil, nil, nil,
- nil, nil, 22, nil, 22 ]
-
-racc_goto_pointer = [
- nil, 25, 0, 2, -68, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 67, 307, nil, 4, -151, -138, 4, nil,
- nil, -52, -134, -46, nil, -133, nil, -262, 47, nil,
- -321, -35, -1, nil, -54, -38, nil, nil, -241, -20,
- -42, nil, -120, 28, 37, -14, -22, -54, -43, -37,
- -177, -176, -24, nil, 1, -45, 76, -21, nil, -298,
- -79, -328, -352, -35, -180, -165, -311, -355, -330 ]
-
-racc_goto_default = [
- nil, nil, 94, 93, 4, 5, 6, 7, 8, 9,
- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
- 20, 21, 22, 23, 24, nil, 25, 26, 144, 28,
- 30, 31, 32, 33, 34, 35, 36, 290, 40, 39,
- 41, 42, 43, 51, 67, nil, 53, 157, 158, 150,
- 138, 68, nil, 55, nil, 297, nil, nil, nil, nil,
- 178, nil, 65, 66, 71, 69, 278, 163, 74, nil,
- 321, nil, nil, nil, nil, nil, nil, nil, nil ]
-
-racc_reduce_table = [
- 0, 0, :racc_error,
- 0, 99, :_reduce_1,
- 1, 99, :_reduce_2,
- 1, 99, :_reduce_3,
- 1, 101, :_reduce_4,
- 3, 101, :_reduce_5,
- 2, 101, :_reduce_6,
- 2, 101, :_reduce_7,
- 1, 102, :_reduce_8,
- 1, 102, :_reduce_9,
- 1, 102, :_reduce_10,
- 1, 102, :_reduce_11,
- 1, 102, :_reduce_12,
- 1, 102, :_reduce_13,
- 1, 102, :_reduce_14,
- 1, 102, :_reduce_15,
- 1, 102, :_reduce_16,
- 1, 102, :_reduce_17,
- 1, 102, :_reduce_18,
- 1, 102, :_reduce_19,
- 1, 102, :_reduce_20,
- 1, 102, :_reduce_21,
- 1, 102, :_reduce_22,
- 1, 102, :_reduce_23,
- 1, 102, :_reduce_24,
- 1, 102, :_reduce_25,
- 1, 120, :_reduce_26,
- 1, 120, :_reduce_27,
- 2, 120, :_reduce_28,
- 1, 120, :_reduce_29,
- 1, 120, :_reduce_30,
- 1, 120, :_reduce_31,
- 1, 120, :_reduce_32,
- 3, 120, :_reduce_33,
- 1, 121, :_reduce_34,
- 1, 121, :_reduce_35,
- 1, 121, :_reduce_36,
- 1, 121, :_reduce_37,
- 1, 121, :_reduce_38,
- 1, 121, :_reduce_39,
- 1, 121, :_reduce_40,
- 3, 121, :_reduce_41,
- 1, 135, :_reduce_42,
- 1, 135, :_reduce_43,
- 1, 135, :_reduce_44,
- 1, 135, :_reduce_45,
- 1, 135, :_reduce_46,
- 1, 135, :_reduce_47,
- 1, 135, :_reduce_48,
- 1, 100, :_reduce_49,
- 1, 100, :_reduce_50,
- 1, 132, :_reduce_51,
- 1, 132, :_reduce_52,
- 1, 132, :_reduce_53,
- 1, 132, :_reduce_54,
- 1, 132, :_reduce_55,
- 1, 132, :_reduce_56,
- 1, 132, :_reduce_57,
- 1, 137, :_reduce_58,
- 1, 136, :_reduce_59,
- 1, 136, :_reduce_60,
- 2, 136, :_reduce_61,
- 2, 136, :_reduce_62,
- 1, 138, :_reduce_63,
- 1, 140, :_reduce_64,
- 1, 139, :_reduce_65,
- 5, 142, :_reduce_66,
- 3, 141, :_reduce_67,
- 4, 141, :_reduce_68,
- 0, 143, :_reduce_69,
- 1, 143, :_reduce_70,
- 3, 143, :_reduce_71,
- 1, 122, :_reduce_72,
- 3, 144, :_reduce_73,
- 4, 144, :_reduce_74,
- 0, 145, :_reduce_75,
- 1, 145, :_reduce_76,
- 3, 145, :_reduce_77,
- 3, 146, :_reduce_78,
- 2, 129, :_reduce_79,
- 2, 129, :_reduce_80,
- 2, 129, :_reduce_81,
- 4, 129, :_reduce_82,
- 2, 130, :_reduce_83,
- 4, 130, :_reduce_84,
- 2, 149, :_reduce_85,
- 3, 148, :_reduce_86,
- 3, 148, :_reduce_87,
- 4, 148, :_reduce_88,
- 4, 148, :_reduce_89,
- 3, 150, :_reduce_90,
- 2, 150, :_reduce_91,
- 2, 150, :_reduce_92,
- 1, 150, :_reduce_93,
- 1, 147, :_reduce_94,
- 2, 147, :_reduce_95,
- 2, 123, :_reduce_96,
- 2, 123, :_reduce_97,
- 5, 133, :_reduce_98,
- 4, 133, :_reduce_99,
- 4, 133, :_reduce_100,
- 2, 133, :_reduce_101,
- 2, 133, :_reduce_102,
- 4, 133, :_reduce_103,
- 5, 155, :_reduce_104,
- 2, 155, :_reduce_105,
- 4, 115, :_reduce_106,
- 2, 115, :_reduce_107,
- 4, 116, :_reduce_108,
- 2, 116, :_reduce_109,
- 2, 156, :_reduce_110,
- 1, 156, :_reduce_111,
- 4, 156, :_reduce_112,
- 6, 103, :_reduce_113,
- 5, 103, :_reduce_114,
- 1, 151, :_reduce_115,
- 0, 151, :_reduce_116,
- 1, 157, :_reduce_117,
- 4, 157, :_reduce_118,
- 0, 153, :_reduce_119,
- 1, 153, :_reduce_120,
- 0, 159, :_reduce_121,
- 1, 159, :_reduce_122,
- 1, 158, :_reduce_123,
- 2, 158, :_reduce_124,
- 3, 158, :_reduce_125,
- 4, 158, :_reduce_126,
- 1, 154, :_reduce_127,
- 3, 154, :_reduce_128,
- 3, 124, :_reduce_129,
- 3, 124, :_reduce_130,
- 3, 124, :_reduce_131,
- 3, 124, :_reduce_132,
- 3, 124, :_reduce_133,
- 3, 124, :_reduce_134,
- 3, 124, :_reduce_135,
- 3, 124, :_reduce_136,
- 3, 124, :_reduce_137,
- 3, 124, :_reduce_138,
- 3, 124, :_reduce_139,
- 3, 124, :_reduce_140,
- 3, 124, :_reduce_141,
- 3, 124, :_reduce_142,
- 3, 124, :_reduce_143,
- 3, 124, :_reduce_144,
- 3, 124, :_reduce_145,
- 3, 124, :_reduce_146,
- 3, 124, :_reduce_147,
- 3, 124, :_reduce_148,
- 3, 124, :_reduce_149,
- 3, 124, :_reduce_150,
- 3, 124, :_reduce_151,
- 3, 124, :_reduce_152,
- 3, 124, :_reduce_153,
- 3, 124, :_reduce_154,
- 3, 124, :_reduce_155,
- 3, 124, :_reduce_156,
- 3, 124, :_reduce_157,
- 3, 124, :_reduce_158,
- 3, 124, :_reduce_159,
- 3, 124, :_reduce_160,
- 3, 124, :_reduce_161,
- 3, 124, :_reduce_162,
- 3, 124, :_reduce_163,
- 2, 128, :_reduce_164,
- 2, 128, :_reduce_165,
- 2, 128, :_reduce_166,
- 2, 126, :_reduce_167,
- 1, 126, :_reduce_168,
- 3, 117, :_reduce_169,
- 3, 117, :_reduce_170,
- 3, 160, :_reduce_171,
- 3, 160, :_reduce_172,
- 3, 160, :_reduce_173,
- 3, 160, :_reduce_174,
- 1, 161, :_reduce_175,
- 1, 161, :_reduce_176,
- 1, 161, :_reduce_177,
- 1, 161, :_reduce_178,
- 1, 161, :_reduce_179,
- 1, 162, :_reduce_180,
- 2, 162, :_reduce_181,
- 2, 162, :_reduce_182,
- 2, 163, :_reduce_183,
- 1, 131, :_reduce_184,
- 2, 131, :_reduce_185,
- 2, 106, :_reduce_186,
- 2, 106, :_reduce_187,
- 2, 106, :_reduce_188,
- 1, 164, :_reduce_189,
- 2, 164, :_reduce_190,
- 2, 164, :_reduce_191,
- 2, 164, :_reduce_192,
- 3, 165, :_reduce_193,
- 4, 165, :_reduce_194,
- 4, 165, :_reduce_195,
- 6, 104, :_reduce_196,
- 9, 104, :_reduce_197,
- 9, 104, :_reduce_198,
- 11, 104, :_reduce_199,
- 1, 166, :_reduce_200,
- 1, 166, :_reduce_201,
- 1, 166, :_reduce_202,
- 1, 152, :_reduce_203,
- 1, 152, :_reduce_204,
- 1, 167, :_reduce_205,
- 2, 167, :_reduce_206,
- 0, 167, :_reduce_207,
- 0, 169, :_reduce_208,
- 1, 169, :_reduce_209,
- 1, 169, :_reduce_210,
- 3, 169, :_reduce_211,
- 3, 169, :_reduce_212,
- 3, 170, :_reduce_213,
- 2, 105, :_reduce_214,
- 4, 105, :_reduce_215,
- 4, 105, :_reduce_216,
- 0, 171, :_reduce_217,
- 1, 171, :_reduce_218,
- 1, 114, :_reduce_219,
- 4, 118, :_reduce_220,
- 5, 118, :_reduce_221,
- 3, 118, :_reduce_222,
- 4, 119, :_reduce_223,
- 5, 119, :_reduce_224,
- 3, 119, :_reduce_225,
- 5, 125, :_reduce_226,
- 4, 109, :_reduce_227,
- 1, 113, :_reduce_228,
- 1, 113, :_reduce_229,
- 4, 110, :_reduce_230,
- 6, 108, :_reduce_231,
- 6, 108, :_reduce_232,
- 6, 108, :_reduce_233,
- 3, 111, :_reduce_234,
- 4, 111, :_reduce_235,
- 6, 111, :_reduce_236,
- 0, 173, :_reduce_237,
- 2, 173, :_reduce_238,
- 3, 173, :_reduce_239,
- 3, 173, :_reduce_240,
- 4, 173, :_reduce_241,
- 1, 174, :_reduce_242,
- 1, 174, :_reduce_243,
- 2, 168, :_reduce_244,
- 1, 168, :_reduce_245,
- 1, 172, :_reduce_246,
- 3, 172, :_reduce_247,
- 3, 172, :_reduce_248,
- 4, 172, :_reduce_249,
- 3, 175, :_reduce_250,
- 4, 176, :_reduce_251,
- 5, 176, :_reduce_252,
- 5, 112, :_reduce_253,
- 8, 112, :_reduce_254,
- 2, 134, :_reduce_255,
- 4, 127, :_reduce_256,
- 1, 127, :_reduce_257,
- 1, 107, :_reduce_258 ]
-
-racc_reduce_n = 259
-
-racc_shift_n = 469
-
-racc_token_table = {
- false => 0,
- :error => 1,
- :IF => 2,
- :ELSE => 3,
- :ELSEIF => 4,
- :THEN => 5,
- :UNLESS => 6,
- :END => 7,
- :WHILE => 8,
- :UNTIL => 9,
- :BREAK => 10,
- :CONTINUE => 11,
- :TRY => 12,
- :CATCH => 13,
- :FINALLY => 14,
- :FOR => 15,
- :IN => 16,
- :DEF => 17,
- :DEF_BANG => 18,
- :SPLAT_PARAM => 19,
- :SPLAT_ARG => 20,
- :CALL => 21,
- :BUILTIN_COMMAND => 22,
- :CLASS => 23,
- :NEW => 24,
- :DEFM => 25,
- :DEFM_BANG => 26,
- :SUPER => 27,
- :RIML_FILE_COMMAND => 28,
- :RIML_CLASS_COMMAND => 29,
- :RETURN => 30,
- :NEWLINE => 31,
- :NUMBER => 32,
- :STRING_D => 33,
- :STRING_S => 34,
- :EX_LITERAL => 35,
- :REGEXP => 36,
- :TRUE => 37,
- :FALSE => 38,
- :LET => 39,
- :UNLET => 40,
- :UNLET_BANG => 41,
- :IDENTIFIER => 42,
- :DICT_VAL => 43,
- :SCOPE_MODIFIER => 44,
- :SCOPE_MODIFIER_LITERAL => 45,
- :SPECIAL_VAR_PREFIX => 46,
- :FINISH => 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,
- :IS => 79,
- :ISNOT => 80,
- "&&" => 81,
- "||" => 82,
- "?" => 83,
- "=" => 84,
- "+=" => 85,
- "-=" => 86,
- ".=" => 87,
- "," => 88,
- "(" => 89,
- ")" => 90,
- ";" => 91,
- "[" => 92,
- "]" => 93,
- "{" => 94,
- "}" => 95,
- ":" => 96,
- "===" => 97 }
-
-racc_nt_base = 98
-
-racc_use_result_var = true
-
-Racc_arg = [
- racc_action_table,
- racc_action_check,
- racc_action_default,
- racc_action_pointer,
- racc_goto_table,
- racc_goto_check,
- racc_goto_default,
- racc_goto_pointer,
- racc_nt_base,
- racc_reduce_table,
- racc_token_table,
- racc_shift_n,
- racc_reduce_n,
- racc_use_result_var ]
-
-Racc_token_to_s_table = [
- "$end",
- "error",
- "IF",
- "ELSE",
- "ELSEIF",
- "THEN",
- "UNLESS",
- "END",
- "WHILE",
- "UNTIL",
- "BREAK",
- "CONTINUE",
- "TRY",
- "CATCH",
- "FINALLY",
- "FOR",
- "IN",
- "DEF",
- "DEF_BANG",
- "SPLAT_PARAM",
- "SPLAT_ARG",
- "CALL",
- "BUILTIN_COMMAND",
- "CLASS",
- "NEW",
- "DEFM",
- "DEFM_BANG",
- "SUPER",
- "RIML_FILE_COMMAND",
- "RIML_CLASS_COMMAND",
- "RETURN",
- "NEWLINE",
- "NUMBER",
- "STRING_D",
- "STRING_S",
- "EX_LITERAL",
- "REGEXP",
- "TRUE",
- "FALSE",
- "LET",
- "UNLET",
- "UNLET_BANG",
- "IDENTIFIER",
- "DICT_VAL",
- "SCOPE_MODIFIER",
- "SCOPE_MODIFIER_LITERAL",
- "SPECIAL_VAR_PREFIX",
- "FINISH",
- "\"!\"",
- "\"*\"",
- "\"/\"",
- "\"%\"",
- "\"+\"",
- "\"-\"",
- "\".\"",
- "\">\"",
- "\">#\"",
- "\">?\"",
- "\"<\"",
- "\"<#\"",
- "\"<?\"",
- "\">=\"",
- "\">=#\"",
- "\">=?\"",
- "\"<=\"",
- "\"<=#\"",
- "\"<=?\"",
- "\"==\"",
- "\"==?\"",
- "\"==#\"",
- "\"=~\"",
- "\"=~?\"",
- "\"=~#\"",
- "\"!~\"",
- "\"!~?\"",
- "\"!~#\"",
- "\"!=\"",
- "\"!=?\"",
- "\"!=#\"",
- "IS",
- "ISNOT",
- "\"&&\"",
- "\"||\"",
- "\"?\"",
- "\"=\"",
- "\"+=\"",
- "\"-=\"",
- "\".=\"",
- "\",\"",
- "\"(\"",
- "\")\"",
- "\";\"",
- "\"[\"",
- "\"]\"",
- "\"{\"",
- "\"}\"",
- "\":\"",
- "\"===\"",
- "$start",
- "Root",
- "Terminator",
- "Statements",
- "Statement",
- "ExplicitCall",
- "Def",
- "Return",
- "UnletVariable",
- "ExLiteral",
- "For",
- "While",
- "Until",
- "Try",
- "ClassDefinition",
- "LoopKeyword",
- "EndScript",
- "RimlFileCommand",
- "RimlClassCommand",
- "MultiAssign",
- "If",
- "Unless",
- "Expression",
- "ExpressionWithoutDictLiteral",
- "Dictionary",
- "DictGetWithDotLiteral",
- "BinaryOperator",
- "Ternary",
- "Assign",
- "Super",
- "UnaryOperator",
- "DictGet",
- "ListOrDictGet",
- "AllVariableRetrieval",
- "LiteralWithoutDictLiteral",
- "Call",
- "ObjectInstantiation",
- "PossibleStringValue",
- "String",
- "Number",
- "Regexp",
- "List",
- "ScopeModifierLiteral",
- "ListLiteral",
- "ListUnpack",
- "ListItems",
- "DictionaryLiteral",
- "DictItems",
- "DictItem",
- "DictGetWithDot",
- "ListOrDictGetWithBrackets",
- "ListOrDictGetAssign",
- "SubList",
- "Scope",
- "DefCallIdentifier",
- "ArgList",
- "ArgListWithoutNothing",
- "ObjectInstantiationCall",
- "ClassArgList",
- "SIDAndScope",
- "ArgListWithoutNothingWithSplat",
- "ArgListWithSplat",
- "AssignExpression",
- "AssignLHS",
- "VariableRetrieval",
- "SimpleVariableRetrieval",
- "CurlyBraceName",
- "CurlyBraceVarPart",
- "FunctionType",
- "DefKeywords",
- "Block",
- "ParamList",
- "DefaultParam",
- "Returnable",
- "IfBlock",
- "Catch",
- "Catchable",
- "ElseBlock",
- "ElseifBlock" ]
-
-Racc_debug_parser = false
-
-##### State transition tables end #####
-
-# reduce 0 omitted
-
-module_eval(<<'.,.,', 'riml.y', 61)
- def _reduce_1(val, _values, result)
- result = make_node(val) { |_| Riml::Nodes.new([]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 62)
- def _reduce_2(val, _values, result)
- result = make_node(val) { |_| Riml::Nodes.new([]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 63)
- def _reduce_3(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 68)
- def _reduce_4(val, _values, result)
- result = make_node(val) { |v| Riml::Nodes.new([ v[0] ]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 69)
- def _reduce_5(val, _values, result)
- result = val[0] << val[2]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 70)
- def _reduce_6(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 71)
- def _reduce_7(val, _values, result)
- result = make_node(val) { |v| Riml::Nodes.new(v[1]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 76)
- def _reduce_8(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 77)
- def _reduce_9(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 78)
- def _reduce_10(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 79)
- def _reduce_11(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 80)
- def _reduce_12(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 81)
- def _reduce_13(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 82)
- def _reduce_14(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 83)
- def _reduce_15(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 84)
- def _reduce_16(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 85)
- def _reduce_17(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 86)
- def _reduce_18(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 87)
- def _reduce_19(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 88)
- def _reduce_20(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 89)
- def _reduce_21(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 90)
- def _reduce_22(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 91)
- def _reduce_23(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 92)
- def _reduce_24(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 93)
- def _reduce_25(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 97)
- def _reduce_26(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 98)
- def _reduce_27(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 99)
- def _reduce_28(val, _values, result)
- result = make_node(val) { |v| Riml::DictGetDotNode.new(v[0], v[1]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 100)
- def _reduce_29(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 101)
- def _reduce_30(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 102)
- def _reduce_31(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 103)
- def _reduce_32(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 104)
- def _reduce_33(val, _values, result)
- result = make_node(val) { |v| Riml::WrapInParensNode.new(v[1]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 108)
- def _reduce_34(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 109)
- def _reduce_35(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 110)
- def _reduce_36(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 111)
- def _reduce_37(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 112)
- def _reduce_38(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 113)
- def _reduce_39(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 114)
- def _reduce_40(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 115)
- def _reduce_41(val, _values, result)
- result = make_node(val) { |v| Riml::WrapInParensNode.new(v[1]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 120)
- def _reduce_42(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 121)
- def _reduce_43(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 122)
- def _reduce_44(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 123)
- def _reduce_45(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 124)
- def _reduce_46(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 125)
- def _reduce_47(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 126)
- def _reduce_48(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 130)
- def _reduce_49(val, _values, result)
- result = nil
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 131)
- def _reduce_50(val, _values, result)
- result = nil
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 135)
- def _reduce_51(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 136)
- def _reduce_52(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 137)
- def _reduce_53(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 138)
- def _reduce_54(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 139)
- def _reduce_55(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 140)
- def _reduce_56(val, _values, result)
- result = make_node(val) { |_| Riml::TrueNode.new }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 141)
- def _reduce_57(val, _values, result)
- result = make_node(val) { |_| Riml::FalseNode.new }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 145)
- def _reduce_58(val, _values, result)
- result = make_node(val) { |v| Riml::NumberNode.new(v[0]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 149)
- def _reduce_59(val, _values, result)
- result = make_node(val) { |v| Riml::StringNode.new(v[0], :s) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 150)
- def _reduce_60(val, _values, result)
- result = make_node(val) { |v| Riml::StringNode.new(v[0], :d) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 151)
- def _reduce_61(val, _values, result)
- result = make_node(val) { |v| Riml::StringLiteralConcatNode.new(v[0], Riml::StringNode.new(v[1], :s)) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 152)
- def _reduce_62(val, _values, result)
- result = make_node(val) { |v| Riml::StringLiteralConcatNode.new(v[0], Riml::StringNode.new(v[1], :d)) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 156)
- def _reduce_63(val, _values, result)
- result = make_node(val) { |v| Riml::RegexpNode.new(v[0]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 160)
- def _reduce_64(val, _values, result)
- result = make_node(val) { |v| Riml::ScopeModifierLiteralNode.new(v[0]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 164)
- def _reduce_65(val, _values, result)
- result = make_node(val) { |v| Riml::ListNode.new(v[0]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 168)
- def _reduce_66(val, _values, result)
- result = make_node(val) { |v| Riml::ListUnpackNode.new(v[1] << v[3]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 172)
- def _reduce_67(val, _values, result)
- result = val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 173)
- def _reduce_68(val, _values, result)
- result = val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 177)
- def _reduce_69(val, _values, result)
- result = []
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 178)
- def _reduce_70(val, _values, result)
- result = [val[0]]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 179)
- def _reduce_71(val, _values, result)
- result = val[0] << val[2]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 183)
- def _reduce_72(val, _values, result)
- result = make_node(val) { |v| Riml::DictionaryNode.new(v[0]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 190)
- def _reduce_73(val, _values, result)
- result = val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 191)
- def _reduce_74(val, _values, result)
- result = val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 196)
- def _reduce_75(val, _values, result)
- result = []
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 197)
- def _reduce_76(val, _values, result)
- result = val
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 198)
- def _reduce_77(val, _values, result)
- result = val[0] << val[2]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 203)
- def _reduce_78(val, _values, result)
- result = [val[0], val[2]]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 207)
- def _reduce_79(val, _values, result)
- result = make_node(val) { |v| Riml::DictGetDotNode.new(v[0], v[1]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 208)
- def _reduce_80(val, _values, result)
- result = make_node(val) { |v| Riml::DictGetDotNode.new(v[0], v[1]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 209)
- def _reduce_81(val, _values, result)
- result = make_node(val) { |v| Riml::DictGetDotNode.new(v[0], v[1]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 210)
- def _reduce_82(val, _values, result)
- result = make_node(val) { |v| Riml::DictGetDotNode.new(Riml::WrapInParensNode.new(v[1]), v[3]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 214)
- def _reduce_83(val, _values, result)
- result = make_node(val) { |v| Riml::ListOrDictGetNode.new(v[0], v[1]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 215)
- def _reduce_84(val, _values, result)
- result = make_node(val) { |v| Riml::ListOrDictGetNode.new(Riml::WrapInParensNode.new(v[1]), v[3]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 219)
- def _reduce_85(val, _values, result)
- result = make_node(val) { |v| Riml::ListOrDictGetNode.new(v[0], v[1]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 223)
- def _reduce_86(val, _values, result)
- result = [val[1]]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 224)
- def _reduce_87(val, _values, result)
- result = [val[1]]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 225)
- def _reduce_88(val, _values, result)
- result = val[0] << val[2]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 226)
- def _reduce_89(val, _values, result)
- result = val[0] << val[2]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 230)
- def _reduce_90(val, _values, result)
- result = make_node(val) { |v| Riml::SublistNode.new([v[0], Riml::LiteralNode.new(' : '), v[2]]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 231)
- def _reduce_91(val, _values, result)
- result = make_node(val) { |v| Riml::SublistNode.new([v[0], Riml::LiteralNode.new(' :')]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 232)
- def _reduce_92(val, _values, result)
- result = make_node(val) { |v| Riml::SublistNode.new([Riml::LiteralNode.new(': '), v[1]]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 233)
- def _reduce_93(val, _values, result)
- result = make_node(val) { |_| Riml::SublistNode.new([Riml::LiteralNode.new(':')]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 237)
- def _reduce_94(val, _values, result)
- result = [val[0]]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 238)
- def _reduce_95(val, _values, result)
- result = val[0] << val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 242)
- def _reduce_96(val, _values, result)
- result = [val[1]]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 243)
- def _reduce_97(val, _values, result)
- result = val[0] << val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 247)
- def _reduce_98(val, _values, result)
- result = make_node(val) { |v| Riml::CallNode.new(v[0], v[1], v[3]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 248)
- def _reduce_99(val, _values, result)
- result = make_node(val) { |v| Riml::CallNode.new(nil, v[0], v[2]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 249)
- def _reduce_100(val, _values, result)
- result = make_node(val) { |v| Riml::CallNode.new(nil, v[0], v[2]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 250)
- def _reduce_101(val, _values, result)
- result = make_node(val) { |v| Riml::CallNode.new(nil, v[0], v[1]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 251)
- def _reduce_102(val, _values, result)
- result = make_node(val) { |v| Riml::CallNode.new(nil, v[0], []) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 252)
- def _reduce_103(val, _values, result)
- result = make_node(val) { |v| Riml::ExplicitCallNode.new(nil, nil, v[2]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 256)
- def _reduce_104(val, _values, result)
- result = make_node(val) { |v| Riml::CallNode.new(v[0], v[1], v[3]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 257)
- def _reduce_105(val, _values, result)
- result = make_node(val) { |v| Riml::CallNode.new(v[0], v[1], []) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 261)
- def _reduce_106(val, _values, result)
- result = make_node(val) { |v| Riml::RimlFileCommandNode.new(nil, v[0], v[2]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 262)
- def _reduce_107(val, _values, result)
- result = make_node(val) { |v| Riml::RimlFileCommandNode.new(nil, v[0], v[1]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 266)
- def _reduce_108(val, _values, result)
- result = make_node(val) { |v| Riml::RimlClassCommandNode.new(nil, v[0], v[2]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 267)
- def _reduce_109(val, _values, result)
- result = make_node(val) { |v| Riml::RimlClassCommandNode.new(nil, v[0], v[1]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 271)
- def _reduce_110(val, _values, result)
- result = ["#{val[0]}#{val[1]}"]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 272)
- def _reduce_111(val, _values, result)
- result = val
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 273)
- def _reduce_112(val, _values, result)
- result = val[0].concat ["#{val[2]}#{val[3]}"]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 277)
- def _reduce_113(val, _values, result)
- result = make_node(val) { |v| Riml::ExplicitCallNode.new(v[1], v[2], v[4]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 278)
- def _reduce_114(val, _values, result)
- result = make_node(val) { |v| Riml::ExplicitCallNode.new(nil, v[1], v[3]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 282)
- def _reduce_115(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 283)
- def _reduce_116(val, _values, result)
- result = nil
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 288)
- def _reduce_117(val, _values, result)
- result = [ nil, val[0] ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 289)
- def _reduce_118(val, _values, result)
- result = [ make_node(val) { |v| Riml::SIDNode.new(v[1]) }, val[3] ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 293)
- def _reduce_119(val, _values, result)
- result = []
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 294)
- def _reduce_120(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 298)
- def _reduce_121(val, _values, result)
- result = []
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 299)
- def _reduce_122(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 303)
- def _reduce_123(val, _values, result)
- result = val
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 304)
- def _reduce_124(val, _values, result)
- result = [ make_node(val) { |v| Riml::SplatNode.new(v[1]) } ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 305)
- def _reduce_125(val, _values, result)
- result = val[0] << val[2]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 306)
- def _reduce_126(val, _values, result)
- result = val[0] << make_node(val) { |v| Riml::SplatNode.new(v[3]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 310)
- def _reduce_127(val, _values, result)
- result = val
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 311)
- def _reduce_128(val, _values, result)
- result = val[0] << val[2]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 315)
- def _reduce_129(val, _values, result)
- result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 316)
- def _reduce_130(val, _values, result)
- result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 318)
- def _reduce_131(val, _values, result)
- result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 319)
- def _reduce_132(val, _values, result)
- result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 320)
- def _reduce_133(val, _values, result)
- result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 323)
- def _reduce_134(val, _values, result)
- result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 325)
- def _reduce_135(val, _values, result)
- result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 326)
- def _reduce_136(val, _values, result)
- result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 327)
- def _reduce_137(val, _values, result)
- result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 329)
- def _reduce_138(val, _values, result)
- result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 330)
- def _reduce_139(val, _values, result)
- result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 331)
- def _reduce_140(val, _values, result)
- result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 333)
- def _reduce_141(val, _values, result)
- result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 334)
- def _reduce_142(val, _values, result)
- result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 335)
- def _reduce_143(val, _values, result)
- result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 337)
- def _reduce_144(val, _values, result)
- result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 338)
- def _reduce_145(val, _values, result)
- result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 339)
- def _reduce_146(val, _values, result)
- result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 341)
- def _reduce_147(val, _values, result)
- result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 342)
- def _reduce_148(val, _values, result)
- result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 343)
- def _reduce_149(val, _values, result)
- result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 345)
- def _reduce_150(val, _values, result)
- result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 346)
- def _reduce_151(val, _values, result)
- result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 347)
- def _reduce_152(val, _values, result)
- result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 349)
- def _reduce_153(val, _values, result)
- result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 350)
- def _reduce_154(val, _values, result)
- result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 351)
- def _reduce_155(val, _values, result)
- result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 353)
- def _reduce_156(val, _values, result)
- result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 354)
- def _reduce_157(val, _values, result)
- result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 355)
- def _reduce_158(val, _values, result)
- result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 356)
- def _reduce_159(val, _values, result)
- result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 357)
- def _reduce_160(val, _values, result)
- result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 358)
- def _reduce_161(val, _values, result)
- result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 360)
- def _reduce_162(val, _values, result)
- result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 361)
- def _reduce_163(val, _values, result)
- result = make_node(val) { |v| Riml::BinaryOperatorNode.new(v[1], [v[0], v[2]]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 365)
- def _reduce_164(val, _values, result)
- result = make_node(val) { |v| Riml::UnaryOperatorNode.new(val[0], [val[1]]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 366)
- def _reduce_165(val, _values, result)
- result = make_node(val) { |v| Riml::UnaryOperatorNode.new(val[0], [val[1]]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 367)
- def _reduce_166(val, _values, result)
- result = make_node(val) { |v| Riml::UnaryOperatorNode.new(val[0], [val[1]]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 372)
- def _reduce_167(val, _values, result)
- result = make_node(val) { |v| Riml::AssignNode.new(v[1][0], v[1][1], v[1][2]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 373)
- def _reduce_168(val, _values, result)
- result = make_node(val) { |v| Riml::AssignNode.new(v[0][0], v[0][1], v[0][2]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 377)
- def _reduce_169(val, _values, result)
- result = make_node(val) { |v| Riml::MultiAssignNode.new([v[0], v[2]]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 378)
- def _reduce_170(val, _values, result)
- val[0].assigns << val[2]; result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 383)
- def _reduce_171(val, _values, result)
- result = [val[1], val[0], val[2]]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 384)
- def _reduce_172(val, _values, result)
- result = [val[1], val[0], val[2]]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 385)
- def _reduce_173(val, _values, result)
- result = [val[1], val[0], val[2]]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 386)
- def _reduce_174(val, _values, result)
- result = [val[1], val[0], val[2]]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 390)
- def _reduce_175(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 391)
- def _reduce_176(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 392)
- def _reduce_177(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 393)
- def _reduce_178(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 394)
- def _reduce_179(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 399)
- def _reduce_180(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 400)
- def _reduce_181(val, _values, result)
- result = make_node(val) { |v| Riml::GetSpecialVariableNode.new(v[0], v[1]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 401)
- def _reduce_182(val, _values, result)
- result = make_node(val) { |v| Riml::GetVariableByScopeAndDictNameNode.new(v[0], v[1]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 405)
- def _reduce_183(val, _values, result)
- result = make_node(val) { |v| Riml::GetVariableNode.new(v[0], v[1]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 409)
- def _reduce_184(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 410)
- def _reduce_185(val, _values, result)
- result = make_node(val) { |v| Riml::GetCurlyBraceNameNode.new(v[0], v[1]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 414)
- def _reduce_186(val, _values, result)
- result = make_node(val) { |v| Riml::UnletVariableNode.new('!', [ v[1] ]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 415)
- def _reduce_187(val, _values, result)
- result = make_node(val) { |v| Riml::UnletVariableNode.new('!', [ v[1] ]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 416)
- def _reduce_188(val, _values, result)
- result = val[0] << val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 420)
- def _reduce_189(val, _values, result)
- result = make_node(val) { |v| Riml::CurlyBraceVariable.new([ v[0] ]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 421)
- def _reduce_190(val, _values, result)
- result = make_node(val) { |v| Riml::CurlyBraceVariable.new([ Riml::CurlyBracePart.new(v[0]), v[1] ]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 422)
- def _reduce_191(val, _values, result)
- result = val[0] << make_node(val) { |v| Riml::CurlyBracePart.new(v[1]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 423)
- def _reduce_192(val, _values, result)
- result = val[0] << val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 427)
- def _reduce_193(val, _values, result)
- result = make_node(val) { |v| Riml::CurlyBracePart.new(v[1]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 428)
- def _reduce_194(val, _values, result)
- result = make_node(val) { |v| Riml::CurlyBracePart.new([v[1], v[2]]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 429)
- def _reduce_195(val, _values, result)
- result = make_node(val) { |v| Riml::CurlyBracePart.new([v[1], v[2]]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 435)
- def _reduce_196(val, _values, result)
- result = make_node(val) { |v| Riml.const_get(val[0]).new('!', v[1][0], v[1][1], v[2], [], v[3], v[4]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 436)
- def _reduce_197(val, _values, result)
- result = make_node(val) { |v| Riml.const_get(val[0]).new('!', v[1][0], v[1][1], v[2], v[4], v[6], v[7]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 437)
- def _reduce_198(val, _values, result)
- result = make_node(val) { |v| Riml.const_get(val[0]).new('!', v[1][0], v[1][1], v[2], [v[4]], v[6], v[7]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 438)
- def _reduce_199(val, _values, result)
- result = make_node(val) { |v| Riml.const_get(val[0]).new('!', v[1][0], v[1][1], v[2], v[4] << v[6], v[8], v[9]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 442)
- def _reduce_200(val, _values, result)
- result = "DefNode"
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 443)
- def _reduce_201(val, _values, result)
- result = "DefNode"
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 444)
- def _reduce_202(val, _values, result)
- result = "DefMethodNode"
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 449)
- def _reduce_203(val, _values, result)
- result = make_node(val) { |v| Riml::GetCurlyBraceNameNode.new('', v[0]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 450)
- def _reduce_204(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 455)
- def _reduce_205(val, _values, result)
- result = [val[0]]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 456)
- def _reduce_206(val, _values, result)
- result = val[0] << val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 457)
- def _reduce_207(val, _values, result)
- result = nil
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 461)
- def _reduce_208(val, _values, result)
- result = []
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 462)
- def _reduce_209(val, _values, result)
- result = val
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 463)
- def _reduce_210(val, _values, result)
- result = val
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 464)
- def _reduce_211(val, _values, result)
- result = val[0] << val[2]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 465)
- def _reduce_212(val, _values, result)
- result = val[0] << val[2]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 469)
- def _reduce_213(val, _values, result)
- result = make_node(val) { |v| Riml::DefaultParamNode.new(v[0], v[2]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 473)
- def _reduce_214(val, _values, result)
- result = make_node(val) { |v| Riml::ReturnNode.new(v[1]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 474)
- def _reduce_215(val, _values, result)
- result = make_node(val) { |v| Riml::IfNode.new(v[3], Nodes.new([ReturnNode.new(v[1])])) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 475)
- def _reduce_216(val, _values, result)
- result = make_node(val) { |v| Riml::UnlessNode.new(v[3], Nodes.new([ReturnNode.new(v[1])])) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 479)
- def _reduce_217(val, _values, result)
- result = nil
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 480)
- def _reduce_218(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 484)
- def _reduce_219(val, _values, result)
- result = make_node(val) { |_| Riml::FinishNode.new }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 489)
- def _reduce_220(val, _values, result)
- result = make_node(val) { |v| Riml::IfNode.new(v[1], v[2]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 490)
- def _reduce_221(val, _values, result)
- result = make_node(val) { |v| Riml::IfNode.new(v[1], Riml::Nodes.new([v[3]])) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 491)
- def _reduce_222(val, _values, result)
- result = make_node(val) { |v| Riml::IfNode.new(v[2], Riml::Nodes.new([v[0]])) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 495)
- def _reduce_223(val, _values, result)
- result = make_node(val) { |v| Riml::UnlessNode.new(v[1], v[2]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 496)
- def _reduce_224(val, _values, result)
- result = make_node(val) { |v| Riml::UnlessNode.new(v[1], Riml::Nodes.new([v[3]])) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 497)
- def _reduce_225(val, _values, result)
- result = make_node(val) { |v| Riml::UnlessNode.new(v[2], Riml::Nodes.new([v[0]])) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 501)
- def _reduce_226(val, _values, result)
- result = make_node(val) { |v| Riml::TernaryOperatorNode.new([v[0], v[2], v[4]]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 505)
- def _reduce_227(val, _values, result)
- result = make_node(val) { |v| Riml::WhileNode.new(v[1], v[2]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 509)
- def _reduce_228(val, _values, result)
- result = make_node(val) { |_| Riml::BreakNode.new }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 510)
- def _reduce_229(val, _values, result)
- result = make_node(val) { |_| Riml::ContinueNode.new }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 514)
- def _reduce_230(val, _values, result)
- result = make_node(val) { |v| Riml::UntilNode.new(v[1], v[2]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 518)
- def _reduce_231(val, _values, result)
- result = make_node(val) { |v| Riml::ForNode.new(v[1], v[3], v[4]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 519)
- def _reduce_232(val, _values, result)
- result = make_node(val) { |v| Riml::ForNode.new(v[1], v[3], v[4]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 520)
- def _reduce_233(val, _values, result)
- result = make_node(val) { |v| Riml::ForNode.new(v[1], v[3], v[4]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 524)
- def _reduce_234(val, _values, result)
- result = make_node(val) { |v| Riml::TryNode.new(v[1], nil, nil) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 525)
- def _reduce_235(val, _values, result)
- result = make_node(val) { |v| Riml::TryNode.new(v[1], v[2], nil) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 526)
- def _reduce_236(val, _values, result)
- result = make_node(val) { |v| Riml::TryNode.new(v[1], v[2], v[4]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 530)
- def _reduce_237(val, _values, result)
- result = nil
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 531)
- def _reduce_238(val, _values, result)
- result = [ make_node(val) { |v| Riml::CatchNode.new(nil, v[1]) } ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 532)
- def _reduce_239(val, _values, result)
- result = [ make_node(val) { |v| Riml::CatchNode.new(v[1], v[2]) } ]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 533)
- def _reduce_240(val, _values, result)
- result = val[0] << make_node(val) { |v| Riml::CatchNode.new(nil, v[2]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 534)
- def _reduce_241(val, _values, result)
- result = val[0] << make_node(val) { |v| Riml::CatchNode.new(v[2], v[3]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 538)
- def _reduce_242(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 539)
- def _reduce_243(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 546)
- def _reduce_244(val, _values, result)
- result = val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 547)
- def _reduce_245(val, _values, result)
- result = make_node(val) { |_| Riml::Nodes.new([]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 551)
- def _reduce_246(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 552)
- def _reduce_247(val, _values, result)
- result = val[1] << val[2]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 553)
- def _reduce_248(val, _values, result)
- result = val[1] << val[2]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 554)
- def _reduce_249(val, _values, result)
- result = val[1] << val[2] << val[3]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 558)
- def _reduce_250(val, _values, result)
- result = make_node(val) { |v| Riml::ElseNode.new(v[2]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 562)
- def _reduce_251(val, _values, result)
- result = make_node(val) { |v| Riml::Nodes.new([Riml::ElseifNode.new(v[1], v[3])]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 563)
- def _reduce_252(val, _values, result)
- result = val[0] << make_node(val) { |v| Riml::ElseifNode.new(v[2], v[4]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 567)
- def _reduce_253(val, _values, result)
- result = make_node(val) { |v| Riml::ClassDefinitionNode.new(v[1], v[2], nil, v[3]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 568)
- def _reduce_254(val, _values, result)
- result = make_node(val) { |v| Riml::ClassDefinitionNode.new(v[1], v[2], (v[4] || ClassDefinitionNode::DEFAULT_SCOPE_MODIFIER) + v[5], v[6]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 572)
- def _reduce_255(val, _values, result)
- result = make_node(val) { |v| Riml::ObjectInstantiationNode.new(v[1]) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 576)
- def _reduce_256(val, _values, result)
- result = make_node(val) { |v| Riml::SuperNode.new(v[2], true) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 577)
- def _reduce_257(val, _values, result)
- result = make_node(val) { |_| Riml::SuperNode.new([], false) }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'riml.y', 581)
- def _reduce_258(val, _values, result)
- result = make_node(val) { |v| Riml::ExLiteralNode.new(v[0]) }
- result
- end
-.,.,
-
-def _reduce_none(val, _values, result)
- val[0]
-end
-
- end # class Parser
-end # module Riml
diff --git a/test/racc/regress/ruby18 b/test/racc/regress/ruby18
deleted file mode 100644
index 9e9c55d564..0000000000
--- a/test/racc/regress/ruby18
+++ /dev/null
@@ -1,9945 +0,0 @@
-#
-# DO NOT MODIFY!!!!
-# This file is automatically generated by Racc 1.5.2
-# from Racc grammar file "".
-#
-
-require 'racc/parser.rb'
-
-
-require 'parser'
-
-module Parser
- class Ruby18 < Racc::Parser
-
-module_eval(<<'...end ruby18.y/module_eval...', 'ruby18.y', 1936)
-
- def version
- 18
- end
-
- def default_encoding
- Encoding::BINARY if defined? Encoding
- end
-...end ruby18.y/module_eval...
-##### State transition tables begin ###
-
-racc_action_table = [
- -480, 195, 196, 195, 196, 489, 814, -480, -480, -480,
- 511, 578, 578, -480, -480, -80, -480, -429, 579, 579,
- 489, 72, 531, -87, 558, -480, 99, 489, -86, 73,
- 95, 98, 395, 195, 196, -480, -480, -82, -480, -480,
- -480, -480, -480, 489, 489, 558, 495, -84, 496, -83,
- -81, 463, 659, 658, 662, 661, 186, 99, 557, 558,
- 291, 291, 98, -80, -480, -480, -480, -480, -480, -480,
- -480, -480, -480, -480, -480, -480, -480, -480, -87, 557,
- -480, -480, -480, 259, 546, 530, 722, -74, -480, -61,
- 99, -480, 291, 557, 621, 98, -480, -86, -480, -85,
- -480, -480, -480, -480, -480, -480, -480, -277, -480, -480,
- -480, 187, -476, 510, -277, -277, -277, 99, -72, 488,
- -277, -277, 98, -277, -480, -480, -79, -75, -69, -480,
- -83, -78, 99, 99, 488, 621, -76, 98, 98, 99,
- -74, 488, -277, -277, 98, -277, -277, -277, -277, -277,
- -76, -74, -75, -73, 431, 99, 99, 488, 488, 621,
- 98, 98, -477, 259, 502, 195, 196, 258, 503, -74,
- 690, -277, -277, -277, -277, -277, -277, -277, -277, -277,
- -277, -277, -277, -277, -277, 558, 259, -277, -277, -277,
- -74, 549, 99, -74, 620, -277, 713, 98, -277, 691,
- -76, 188, -77, -277, 521, -277, 521, -277, -277, -277,
- -277, -277, -277, -277, -272, -277, -82, -277, -76, 557,
- 189, -272, -272, -272, 99, 254, -272, -272, -272, 98,
- -272, -277, -277, 99, -77, 620, -277, -85, 98, -76,
- -272, -272, -76, 477, 190, -84, 476, 258, 254, -272,
- -272, 768, -272, -272, -272, -272, -272, 99, 194, 620,
- 477, 234, 98, 479, 521, 523, 522, 523, 522, 519,
- 258, 477, 358, 282, 482, 673, 360, 359, -272, -272,
- -272, -272, -272, -272, -272, -272, -272, -272, -272, -272,
- -272, -272, 521, 192, -272, -272, -272, -81, 283, -272,
- 193, -79, -272, 521, -87, -272, -272, 291, -272, 191,
- -272, 349, -272, 215, -272, -272, -272, -272, -272, -272,
- -272, -226, -272, 361, -272, 523, 522, 524, -226, -226,
- -226, 814, 394, -226, -226, -226, 521, -226, -272, -272,
- -272, -272, 396, -272, -473, 212, 606, -226, 496, 214,
- 213, 210, 211, 523, 522, 526, -226, -226, 397, -226,
- -226, -226, -226, -226, 523, 522, 527, 251, 477, 426,
- -474, 479, -480, -480, 252, -319, -226, 659, 658, 662,
- 661, 428, -319, -226, -226, -226, -417, -476, -226, -226,
- -226, -319, -226, -417, -417, 431, -226, 523, 522, 532,
- -429, -417, -226, -226, 284, 285, -473, 436, 254, -226,
- -417, -226, -226, -60, -226, -226, -226, -226, -226, 463,
- -421, 451, -480, -480, 541, -477, 542, -421, -473, -480,
- -480, -226, -474, 680, -476, -476, -421, -476, -480, -480,
- 452, 215, 453, -72, -476, -226, -80, -226, 215, -476,
- -226, -226, 391, -476, -474, 99, -480, -480, -226, 392,
- 98, 99, -78, 254, -226, -86, 98, -74, 393, -76,
- -82, -476, -84, 212, -428, -477, -73, 214, 213, -81,
- 212, -428, -477, 459, 214, 213, -226, -477, 461, 462,
- -428, -477, 195, 196, -421, -476, -476, -476, 263, -476,
- -226, -421, -226, -476, -476, -226, 291, -480, -476, -477,
- -476, -476, -476, -476, -476, -476, -476, 195, 196, 734,
- 606, -476, -476, -476, -476, -476, -476, -476, -427, 215,
- 254, -426, -425, 662, 661, -427, 464, -476, -426, -425,
- -476, -476, -476, -476, -476, -476, -476, -476, -476, -476,
- 465, -476, -476, -422, -476, -476, -476, -480, 734, 606,
- -422, 212, 215, -423, -480, 214, 213, 210, 211, -476,
- -423, 457, 471, -480, -424, 472, -476, 692, 458, -476,
- -476, -424, -476, -476, 291, 481, -476, 456, -476, 484,
- -476, -480, -476, 351, 516, -271, 466, 498, 500, 501,
- -476, 517, -271, 467, 499, -476, -476, -476, -476, -476,
- -476, -271, 393, 497, -476, -476, -477, -477, -477, 535,
- -477, 536, 538, -83, -477, -477, -259, 540, 254, -477,
- 215, -477, -477, -477, -477, -477, -477, -477, 215, 215,
- 215, 568, -477, -477, -477, -477, -477, -477, -477, 667,
- 668, 575, 669, 93, 94, 291, 580, 234, -477, 590,
- 591, -477, -477, -477, -477, -477, -477, -477, -477, -477,
- -477, -69, -477, -477, 592, -477, -477, -477, 215, 219,
- 224, 225, 226, 221, 223, 231, 232, 227, 228, 507,
- -497, -497, -278, 469, 229, 230, 505, -477, 549, -278,
- -477, -477, 606, -477, -477, 506, 291, -477, -278, -477,
- 212, -477, 218, -477, 214, 213, 210, 211, 222, 220,
- 216, -477, 217, 616, 496, 624, -477, -477, -477, -477,
- -477, -477, 672, -278, 675, -477, -477, 62, 63, 64,
- -278, 51, 436, 436, -85, 56, 57, 693, 704, -278,
- 60, 431, 58, 59, 61, 23, 24, 65, 66, 431,
- 243, 707, 708, 22, 28, 27, 88, 87, 89, 90,
- 715, 717, 17, 721, 254, 254, 215, 537, 215, 41,
- 724, -259, 92, 91, 82, 50, 84, 83, 86, 85,
- 93, 94, 728, 80, 81, 730, 38, 39, 37, 215,
- 219, 224, 225, 226, 221, 223, 231, 232, 227, 228,
- -277, 208, 209, -279, 606, 229, 230, -277, 200, 738,
- -279, 204, -477, 739, 52, 53, -277, 740, 54, -279,
- 743, 212, 745, 218, 40, 214, 213, 210, 211, 222,
- 220, 216, 18, 217, 749, 753, 755, 79, 72, 74,
- 75, 76, 77, 758, 759, 760, 73, 78, 761, 99,
- 233, 763, -215, -277, 98, 62, 63, 64, 7, 51,
- -277, -260, 769, 56, 57, -477, 777, 778, 60, -277,
- 58, 59, 61, 23, 24, 65, 66, 568, 568, 254,
- 254, 22, 28, 27, 88, 87, 89, 90, 234, 568,
- 17, 101, 102, 103, 104, 105, 6, 41, 8, 9,
- 92, 91, 82, 50, 84, 83, 86, 85, 93, 94,
- 790, 80, 81, 791, 38, 39, 37, 215, 219, 224,
- 225, 226, 221, 223, 231, 232, 227, 228, -428, -497,
- -497, 823, 792, 229, 230, -428, 36, 797, 824, 30,
- 799, 805, 52, 53, -428, 807, 54, 822, 32, 212,
- 291, 218, 40, 214, 213, 210, 211, 222, 220, 216,
- 18, 217, 818, 825, 826, 79, 72, 74, 75, 76,
- 77, 827, -271, 829, 73, 78, 62, 63, 64, -271,
- 51, 830, 351, -278, 56, 57, 832, 835, -271, 60,
- -278, 58, 59, 61, 246, 247, 65, 66, 839, -278,
- 840, 846, 245, 275, 279, 88, 87, 89, 90, 101,
- 102, 103, 104, 105, 847, 848, 758, 758, 276, 759,
- 861, 92, 91, 82, 50, 84, 83, 86, 85, 93,
- 94, 568, 80, 81, 215, 568, 655, 280, 653, 652,
- 651, 654, -277, 471, 874, -279, 875, 876, 880, -277,
- 229, 230, -279, 883, -477, 758, 885, 772, -277, 886,
- 204, -279, 568, 52, 53, 568, 212, 54, 218, 568,
- 214, 213, 210, 211, 645, nil, 216, nil, 217, nil,
- nil, nil, 659, 658, 662, 661, 79, 72, 74, 75,
- 76, 77, nil, nil, nil, 73, 78, nil, 62, 63,
- 64, 775, 51, nil, nil, nil, 56, 57, nil, nil,
- nil, 60, nil, 58, 59, 61, 246, 247, 65, 66,
- nil, nil, nil, nil, 245, 275, 279, 88, 87, 89,
- 90, 101, 102, 103, 104, 105, nil, nil, 537, nil,
- 276, nil, nil, 92, 91, 82, 50, 84, 83, 86,
- 85, 93, 94, nil, 80, 81, nil, nil, nil, 280,
- 215, 219, 224, 225, 226, 221, 223, 231, 232, 227,
- 228, nil, 208, 209, nil, nil, 229, 230, nil, 772,
- nil, nil, 204, nil, nil, 52, 53, nil, nil, 54,
- nil, nil, 212, nil, 218, nil, 214, 213, 210, 211,
- 222, 220, 216, nil, 217, nil, nil, nil, 79, 72,
- 74, 75, 76, 77, nil, nil, nil, 73, 78, nil,
- nil, 233, nil, 855, 5, 62, 63, 64, 7, 51,
- nil, nil, nil, 56, 57, nil, nil, nil, 60, nil,
- 58, 59, 61, 23, 24, 65, 66, nil, nil, nil,
- nil, 22, 28, 27, 88, 87, 89, 90, nil, nil,
- 17, nil, nil, nil, nil, nil, 6, 41, 8, 9,
- 92, 91, 82, 50, 84, 83, 86, 85, 93, 94,
- nil, 80, 81, nil, 38, 39, 37, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 36, nil, nil, 30,
- nil, nil, 52, 53, nil, nil, 54, nil, 32, nil,
- nil, nil, 40, 655, nil, 653, 652, 651, 654, nil,
- 18, nil, nil, nil, nil, 79, 72, 74, 75, 76,
- 77, nil, nil, nil, 73, 78, 5, 62, 63, 64,
- 7, 51, nil, nil, nil, 56, 57, nil, nil, nil,
- 60, nil, 58, 59, 61, 23, 24, 65, 66, 659,
- 658, 662, 661, 22, 28, 27, 88, 87, 89, 90,
- nil, nil, 17, nil, nil, nil, nil, nil, 6, 41,
- 8, 9, 92, 91, 82, 50, 84, 83, 86, 85,
- 93, 94, nil, 80, 81, nil, 38, 39, 37, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 36, nil,
- nil, 265, nil, nil, 52, 53, nil, nil, 54, nil,
- 32, nil, nil, nil, 40, 655, nil, 653, 652, 651,
- 654, nil, 18, nil, nil, nil, nil, 79, 72, 74,
- 75, 76, 77, nil, nil, nil, 73, 78, 5, 62,
- 63, 64, 7, 51, nil, nil, nil, 56, 57, nil,
- nil, nil, 60, nil, 58, 59, 61, 23, 24, 65,
- 66, 659, 658, 662, 661, 22, 28, 27, 88, 87,
- 89, 90, nil, nil, 17, nil, nil, nil, nil, nil,
- 6, 41, 8, 9, 92, 91, 82, 50, 84, 83,
- 86, 85, 93, 94, nil, 80, 81, nil, 38, 39,
- 37, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 36, nil, nil, 30, nil, nil, 52, 53, nil, nil,
- 54, nil, 32, nil, nil, nil, 40, 655, nil, 653,
- 652, 651, 654, nil, 18, nil, nil, nil, nil, 79,
- 72, 74, 75, 76, 77, nil, nil, nil, 73, 78,
- 5, 62, 63, 64, 7, 51, nil, nil, nil, 56,
- 57, nil, nil, nil, 60, 645, 58, 59, 61, 23,
- 24, 65, 66, 659, 658, 662, 661, 22, 28, 27,
- 88, 87, 89, 90, nil, nil, 17, nil, nil, nil,
- nil, nil, 6, 41, 8, 9, 92, 91, 82, 50,
- 84, 83, 86, 85, 93, 94, nil, 80, 81, nil,
- 38, 39, 37, 215, -497, -497, -497, -497, 221, 223,
- nil, nil, -497, -497, nil, nil, nil, nil, nil, 229,
- 230, nil, 36, nil, nil, 30, nil, nil, 52, 53,
- nil, nil, 54, nil, 32, 212, nil, 218, 40, 214,
- 213, 210, 211, 222, 220, 216, 18, 217, nil, nil,
- nil, 79, 72, 74, 75, 76, 77, nil, nil, nil,
- 73, 78, 5, 62, 63, 64, 7, 51, nil, nil,
- nil, 56, 57, nil, nil, nil, 60, nil, 58, 59,
- 61, 23, 24, 65, 66, nil, nil, nil, nil, 22,
- 28, 27, 88, 87, 89, 90, nil, nil, 17, nil,
- nil, nil, nil, nil, 6, 41, 8, 9, 92, 91,
- 82, 50, 84, 83, 86, 85, 93, 94, nil, 80,
- 81, nil, 38, 39, 37, 215, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 229, 230, nil, 36, nil, nil, 30, nil, nil,
- 52, 53, nil, nil, 54, nil, 32, 212, nil, 218,
- 40, 214, 213, 210, 211, nil, nil, 216, 18, 217,
- nil, nil, nil, 79, 72, 74, 75, 76, 77, nil,
- nil, nil, 73, 78, 5, 62, 63, 64, 7, 51,
- nil, nil, nil, 56, 57, nil, nil, nil, 60, nil,
- 58, 59, 61, 23, 24, 65, 66, nil, nil, nil,
- nil, 22, 28, 27, 88, 87, 89, 90, nil, nil,
- 17, nil, nil, nil, nil, nil, 6, 41, 8, 9,
- 92, 91, 82, 50, 84, 83, 86, 85, 93, 94,
- nil, 80, 81, nil, 38, 39, 37, 215, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 229, 230, nil, 36, nil, nil, 30,
- nil, nil, 52, 53, nil, nil, 54, nil, 32, 212,
- nil, 218, 40, 214, 213, 210, 211, nil, nil, 216,
- 18, 217, nil, nil, nil, 79, 72, 74, 75, 76,
- 77, nil, nil, nil, 73, 78, 5, 62, 63, 64,
- 7, 51, nil, nil, nil, 56, 57, nil, nil, nil,
- 60, nil, 58, 59, 61, 23, 24, 65, 66, nil,
- nil, nil, nil, 22, 28, 27, 88, 87, 89, 90,
- nil, nil, 17, nil, nil, nil, nil, nil, 6, 41,
- 8, 9, 92, 91, 82, 50, 84, 83, 86, 85,
- 93, 94, nil, 80, 81, nil, 38, 39, 37, 215,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 229, 230, nil, 36, nil,
- nil, 265, nil, nil, 52, 53, nil, nil, 54, nil,
- 32, 212, nil, 218, 40, 214, 213, 210, 211, nil,
- nil, 216, 18, 217, nil, nil, nil, 79, 72, 74,
- 75, 76, 77, nil, nil, nil, 73, 78, 5, 62,
- 63, 64, 7, 51, nil, nil, nil, 56, 57, nil,
- nil, nil, 60, nil, 58, 59, 61, 23, 24, 65,
- 66, nil, nil, nil, nil, 22, 28, 27, 88, 87,
- 89, 90, nil, nil, 17, nil, nil, nil, nil, nil,
- 6, 41, 8, 9, 92, 91, 82, 50, 84, 83,
- 86, 85, 93, 94, nil, 80, 81, nil, 38, 39,
- 37, 215, -497, -497, -497, -497, 221, 223, nil, nil,
- -497, -497, nil, nil, nil, nil, nil, 229, 230, nil,
- 36, nil, nil, 265, nil, nil, 52, 53, nil, nil,
- 54, nil, 32, 212, nil, 218, 40, 214, 213, 210,
- 211, 222, 220, 216, 18, 217, nil, nil, nil, 79,
- 72, 74, 75, 76, 77, nil, nil, nil, 73, 78,
- 5, 62, 63, 64, 7, 51, nil, nil, nil, 56,
- 57, nil, nil, nil, 60, nil, 58, 59, 61, 23,
- 24, 65, 66, nil, nil, nil, nil, 22, 28, 27,
- 88, 87, 89, 90, nil, nil, 17, nil, nil, nil,
- nil, nil, 6, 41, 8, 9, 92, 91, 82, 50,
- 84, 83, 86, 85, 93, 94, nil, 80, 81, nil,
- 38, 39, 37, 215, -497, -497, -497, -497, 221, 223,
- nil, nil, -497, -497, nil, nil, nil, nil, nil, 229,
- 230, nil, 36, nil, nil, 30, nil, nil, 52, 53,
- nil, nil, 54, nil, 32, 212, nil, 218, 40, 214,
- 213, 210, 211, 222, 220, 216, 18, 217, nil, nil,
- nil, 79, 72, 74, 75, 76, 77, nil, nil, nil,
- 73, 78, 5, 62, 63, 64, 7, 51, nil, nil,
- nil, 56, 57, nil, nil, nil, 60, nil, 58, 59,
- 61, 23, 24, 65, 66, nil, nil, nil, nil, 22,
- 28, 27, 88, 87, 89, 90, nil, nil, 17, nil,
- nil, nil, nil, nil, 6, 41, 8, 9, 92, 91,
- 82, 50, 84, 83, 86, 85, 93, 94, nil, 80,
- 81, nil, 38, 39, 37, 215, -497, -497, -497, -497,
- 221, 223, nil, nil, -497, -497, nil, nil, nil, nil,
- nil, 229, 230, nil, 36, nil, nil, 30, nil, nil,
- 52, 53, nil, nil, 54, nil, 32, 212, nil, 218,
- 40, 214, 213, 210, 211, 222, 220, 216, 18, 217,
- nil, nil, nil, 79, 72, 74, 75, 76, 77, nil,
- nil, nil, 73, 78, 5, 62, 63, 64, 7, 51,
- nil, nil, nil, 56, 57, nil, nil, nil, 60, nil,
- 58, 59, 61, 23, 24, 65, 66, nil, nil, nil,
- nil, 22, 28, 27, 88, 87, 89, 90, nil, nil,
- 17, nil, nil, nil, nil, nil, 6, 41, 8, 9,
- 92, 91, 82, 50, 84, 83, 86, 85, 93, 94,
- nil, 80, 81, nil, 38, 39, 37, 215, -497, -497,
- -497, -497, 221, 223, nil, nil, -497, -497, nil, nil,
- nil, nil, nil, 229, 230, nil, 36, nil, nil, 30,
- nil, nil, 52, 53, nil, nil, 54, nil, 32, 212,
- nil, 218, 40, 214, 213, 210, 211, 222, 220, 216,
- 18, 217, nil, nil, nil, 79, 72, 74, 75, 76,
- 77, nil, nil, nil, 73, 78, 5, 62, 63, 64,
- 7, 51, nil, nil, nil, 56, 57, nil, nil, nil,
- 60, nil, 58, 59, 61, 23, 24, 65, 66, nil,
- nil, nil, nil, 22, 28, 27, 88, 87, 89, 90,
- nil, nil, 17, nil, nil, nil, nil, nil, 6, 41,
- 8, 9, 92, 91, 82, 50, 84, 83, 86, 85,
- 93, 94, nil, 80, 81, nil, 38, 39, 37, 215,
- -497, -497, -497, -497, 221, 223, nil, nil, -497, -497,
- nil, nil, nil, nil, nil, 229, 230, nil, 36, nil,
- nil, 30, nil, nil, 52, 53, nil, nil, 54, nil,
- 32, 212, nil, 218, 40, 214, 213, 210, 211, 222,
- 220, 216, 18, 217, nil, nil, nil, 79, 72, 74,
- 75, 76, 77, nil, nil, nil, 73, 78, 5, 62,
- 63, 64, 7, 51, nil, nil, nil, 56, 57, nil,
- nil, nil, 60, nil, 58, 59, 61, 23, 24, 65,
- 66, nil, nil, nil, nil, 22, 28, 27, 88, 87,
- 89, 90, nil, nil, 17, nil, nil, nil, nil, nil,
- 6, 41, 8, 9, 92, 91, 82, 50, 84, 83,
- 86, 85, 93, 94, nil, 80, 81, nil, 38, 39,
- 37, 215, 219, 224, 225, 226, 221, 223, nil, nil,
- 227, 228, nil, nil, nil, nil, nil, 229, 230, nil,
- 36, nil, nil, 30, nil, nil, 52, 53, nil, nil,
- 54, nil, 32, 212, nil, 218, 40, 214, 213, 210,
- 211, 222, 220, 216, 18, 217, nil, nil, nil, 79,
- 72, 74, 75, 76, 77, nil, nil, nil, 73, 78,
- 5, 62, 63, 64, 7, 51, nil, nil, nil, 56,
- 57, nil, nil, nil, 60, nil, 58, 59, 61, 23,
- 24, 65, 66, nil, nil, nil, nil, 22, 28, 27,
- 88, 87, 89, 90, nil, nil, 17, nil, nil, nil,
- nil, nil, 6, 41, 8, 9, 92, 91, 82, 50,
- 84, 83, 86, 85, 93, 94, nil, 80, 81, nil,
- 38, 39, 37, 215, 219, 224, 225, 226, 221, 223,
- 231, nil, 227, 228, nil, nil, nil, nil, nil, 229,
- 230, nil, 36, nil, nil, 30, nil, nil, 52, 53,
- nil, nil, 54, nil, 32, 212, nil, 218, 40, 214,
- 213, 210, 211, 222, 220, 216, 18, 217, nil, nil,
- nil, 79, 72, 74, 75, 76, 77, nil, nil, nil,
- 73, 78, 5, 62, 63, 64, 7, 51, nil, nil,
- nil, 56, 57, nil, nil, nil, 60, nil, 58, 59,
- 61, 23, 24, 65, 66, nil, nil, nil, nil, 22,
- 28, 27, 88, 87, 89, 90, nil, nil, 17, nil,
- nil, nil, nil, nil, 6, 41, 8, 9, 92, 91,
- 82, 50, 84, 83, 86, 85, 93, 94, nil, 80,
- 81, nil, 38, 39, 37, 215, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 229, 230, nil, 36, nil, nil, 30, nil, nil,
- 52, 53, nil, nil, 54, nil, 32, 212, nil, 218,
- 40, 214, 213, 210, 211, nil, nil, nil, 18, nil,
- nil, nil, nil, 79, 72, 74, 75, 76, 77, nil,
- nil, nil, 73, 78, 5, 62, 63, 64, 7, 51,
- nil, nil, nil, 56, 57, nil, nil, nil, 60, nil,
- 58, 59, 61, 23, 24, 65, 66, nil, nil, nil,
- nil, 22, 28, 27, 88, 87, 89, 90, nil, nil,
- 17, nil, nil, nil, nil, nil, 6, 41, 8, 9,
- 92, 91, 82, 50, 84, 83, 86, 85, 93, 94,
- nil, 80, 81, nil, 38, 39, 37, 215, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 229, 230, nil, 36, nil, nil, 30,
- nil, nil, 52, 53, nil, nil, 54, nil, 32, 212,
- nil, 218, 40, 214, 213, 210, 211, nil, nil, nil,
- 18, nil, nil, nil, nil, 79, 72, 74, 75, 76,
- 77, nil, nil, nil, 73, 78, 5, 62, 63, 64,
- 7, 51, nil, nil, nil, 56, 57, nil, nil, nil,
- 60, nil, 58, 59, 61, 23, 24, 65, 66, nil,
- nil, nil, nil, 22, 28, 27, 88, 87, 89, 90,
- nil, nil, 17, nil, nil, nil, nil, nil, 6, 41,
- 8, 9, 92, 91, 82, 50, 84, 83, 86, 85,
- 93, 94, nil, 80, 81, nil, 38, 39, 37, 215,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 229, 230, nil, 36, nil,
- nil, 30, nil, nil, 52, 53, nil, nil, 54, nil,
- 32, 212, nil, nil, 40, 214, 213, 210, 211, nil,
- nil, nil, 18, nil, nil, nil, nil, 79, 72, 74,
- 75, 76, 77, nil, nil, nil, 73, 78, 5, 62,
- 63, 64, 7, 51, nil, nil, nil, 56, 57, nil,
- nil, nil, 60, nil, 58, 59, 61, 23, 24, 65,
- 66, nil, nil, nil, nil, 22, 28, 27, 88, 87,
- 89, 90, nil, nil, 17, nil, nil, nil, nil, nil,
- 6, 41, 8, 9, 92, 91, 82, 50, 84, 83,
- 86, 85, 93, 94, nil, 80, 81, nil, 38, 39,
- 37, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 36, nil, nil, 30, nil, nil, 52, 53, nil, nil,
- 54, nil, 32, nil, nil, nil, 40, nil, nil, nil,
- nil, nil, nil, nil, 18, nil, nil, nil, nil, 79,
- 72, 74, 75, 76, 77, nil, nil, nil, 73, 78,
- 5, 62, 63, 64, 7, 51, nil, nil, nil, 56,
- 57, nil, nil, nil, 60, nil, 58, 59, 61, 23,
- 24, 65, 66, nil, nil, nil, nil, 22, 28, 27,
- 88, 87, 89, 90, nil, nil, 17, nil, nil, nil,
- nil, nil, 6, 41, 8, 9, 92, 91, 82, 50,
- 84, 83, 86, 85, 93, 94, nil, 80, 81, nil,
- 38, 39, 37, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 36, nil, nil, 30, nil, nil, 52, 53,
- nil, nil, 54, nil, 32, nil, nil, nil, 40, nil,
- nil, nil, nil, nil, nil, nil, 18, nil, nil, nil,
- nil, 79, 72, 74, 75, 76, 77, nil, nil, nil,
- 73, 78, 5, 62, 63, 64, 7, 51, nil, nil,
- nil, 56, 57, nil, nil, nil, 60, nil, 58, 59,
- 61, 23, 24, 65, 66, nil, nil, nil, nil, 22,
- 28, 27, 88, 87, 89, 90, nil, nil, 17, nil,
- nil, nil, nil, nil, 6, 41, 8, 9, 92, 91,
- 82, 50, 84, 83, 86, 85, 93, 94, nil, 80,
- 81, nil, 38, 39, 37, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 36, nil, nil, 30, nil, nil,
- 52, 53, nil, nil, 54, nil, 32, nil, nil, nil,
- 40, nil, nil, nil, nil, nil, nil, nil, 18, nil,
- nil, nil, nil, 79, 72, 74, 75, 76, 77, nil,
- nil, nil, 73, 78, 5, 62, 63, 64, 7, 51,
- nil, nil, nil, 56, 57, nil, nil, nil, 60, nil,
- 58, 59, 61, 23, 24, 65, 66, nil, nil, nil,
- nil, 22, 28, 27, 88, 87, 89, 90, nil, nil,
- 17, nil, nil, nil, nil, nil, 6, 41, 8, 9,
- 92, 91, 82, 50, 84, 83, 86, 85, 93, 94,
- nil, 80, 81, nil, 38, 39, 37, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 36, nil, nil, 30,
- nil, nil, 52, 53, nil, nil, 54, nil, 32, nil,
- nil, nil, 40, nil, nil, nil, nil, nil, nil, nil,
- 18, nil, nil, nil, nil, 79, 72, 74, 75, 76,
- 77, nil, nil, nil, 73, 78, 5, 62, 63, 64,
- 7, 51, nil, nil, nil, 56, 57, nil, nil, nil,
- 60, nil, 58, 59, 61, 23, 24, 65, 66, nil,
- nil, nil, nil, 22, 28, 27, 88, 87, 89, 90,
- nil, nil, 17, nil, nil, nil, nil, nil, 6, 41,
- 8, 9, 92, 91, 82, 50, 84, 83, 86, 85,
- 93, 94, nil, 80, 81, nil, 38, 39, 37, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 36, nil,
- nil, 30, nil, nil, 52, 53, nil, nil, 54, nil,
- 32, nil, nil, nil, 40, nil, nil, nil, nil, nil,
- nil, nil, 18, nil, nil, nil, nil, 79, 72, 74,
- 75, 76, 77, nil, nil, nil, 73, 78, 5, 62,
- 63, 64, 7, 51, nil, nil, nil, 56, 57, nil,
- nil, nil, 60, nil, 58, 59, 61, 23, 24, 65,
- 66, nil, nil, nil, nil, 22, 28, 27, 88, 87,
- 89, 90, nil, nil, 17, nil, nil, nil, nil, nil,
- 6, 41, 8, 9, 92, 91, 82, 50, 84, 83,
- 86, 85, 93, 94, nil, 80, 81, nil, 38, 39,
- 37, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 36, nil, nil, 30, nil, nil, 52, 53, nil, nil,
- 54, nil, 32, nil, nil, nil, 40, nil, nil, nil,
- nil, nil, nil, nil, 18, nil, nil, nil, nil, 79,
- 72, 74, 75, 76, 77, nil, nil, nil, 73, 78,
- 5, 62, 63, 64, 7, 51, nil, nil, nil, 56,
- 57, nil, nil, nil, 60, nil, 58, 59, 61, 23,
- 24, 65, 66, nil, nil, nil, nil, 22, 28, 27,
- 88, 87, 89, 90, nil, nil, 17, nil, nil, nil,
- nil, nil, 6, 41, 8, 9, 92, 91, 82, 50,
- 84, 83, 86, 85, 93, 94, nil, 80, 81, nil,
- 38, 39, 37, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 36, nil, nil, 30, nil, nil, 52, 53,
- nil, nil, 54, nil, 32, nil, nil, nil, 40, nil,
- nil, nil, nil, nil, nil, nil, 18, nil, nil, nil,
- nil, 79, 72, 74, 75, 76, 77, nil, nil, nil,
- 73, 78, 5, 62, 63, 64, 7, 51, nil, nil,
- nil, 56, 57, nil, nil, nil, 60, nil, 58, 59,
- 61, 23, 24, 65, 66, nil, nil, nil, nil, 22,
- 28, 27, 88, 87, 89, 90, nil, nil, 17, nil,
- nil, nil, nil, nil, 6, 41, 8, 9, 92, 91,
- 82, 50, 84, 83, 86, 85, 93, 94, nil, 80,
- 81, nil, 38, 39, 37, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 36, nil, nil, 30, nil, nil,
- 52, 53, nil, nil, 54, nil, 32, nil, nil, nil,
- 40, nil, nil, nil, nil, nil, nil, nil, 18, nil,
- nil, nil, nil, 79, 72, 74, 75, 76, 77, nil,
- nil, nil, 73, 78, 5, 62, 63, 64, 7, 51,
- nil, nil, nil, 56, 57, nil, nil, nil, 60, nil,
- 58, 59, 61, 23, 24, 65, 66, nil, nil, nil,
- nil, 22, 28, 27, 88, 87, 89, 90, nil, nil,
- 17, nil, nil, nil, nil, nil, 6, 41, 8, 9,
- 92, 91, 82, 50, 84, 83, 86, 85, 93, 94,
- nil, 80, 81, nil, 38, 39, 37, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 36, nil, nil, 30,
- nil, nil, 52, 53, nil, nil, 54, nil, 32, nil,
- nil, nil, 40, nil, nil, nil, nil, nil, nil, nil,
- 18, nil, nil, nil, nil, 79, 72, 74, 75, 76,
- 77, nil, nil, nil, 73, 78, 5, 62, 63, 64,
- 7, 51, nil, nil, nil, 56, 57, nil, nil, nil,
- 60, nil, 58, 59, 61, 23, 24, 65, 66, nil,
- nil, nil, nil, 22, 28, 27, 88, 87, 89, 90,
- nil, nil, 17, nil, nil, nil, nil, nil, 6, 41,
- 8, 9, 92, 91, 82, 50, 84, 83, 86, 85,
- 93, 94, nil, 80, 81, nil, 38, 39, 37, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 36, nil,
- nil, 30, nil, nil, 52, 53, nil, nil, 54, nil,
- 32, nil, nil, nil, 40, nil, nil, nil, nil, nil,
- nil, nil, 18, nil, nil, nil, nil, 79, 72, 74,
- 75, 76, 77, nil, nil, nil, 73, 78, 5, 62,
- 63, 64, 7, 51, nil, nil, nil, 56, 57, nil,
- nil, nil, 60, nil, 58, 59, 61, 23, 24, 65,
- 66, nil, nil, nil, nil, 22, 28, 27, 88, 87,
- 89, 90, nil, nil, 17, nil, nil, nil, nil, nil,
- 6, 41, 8, 9, 92, 91, 82, 50, 84, 83,
- 86, 85, 93, 94, nil, 80, 81, nil, 38, 39,
- 37, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 36, nil, nil, 30, nil, nil, 52, 53, nil, nil,
- 54, nil, 32, nil, nil, nil, 40, nil, nil, nil,
- nil, nil, nil, nil, 18, nil, nil, nil, nil, 79,
- 72, 74, 75, 76, 77, nil, nil, nil, 73, 78,
- 5, 62, 63, 64, 7, 51, nil, nil, nil, 56,
- 57, nil, nil, nil, 60, nil, 58, 59, 61, 23,
- 24, 65, 66, nil, nil, nil, nil, 22, 28, 27,
- 88, 87, 89, 90, nil, nil, 17, nil, nil, nil,
- nil, nil, 6, 41, 8, 9, 92, 91, 82, 50,
- 84, 83, 86, 85, 93, 94, nil, 80, 81, nil,
- 38, 39, 37, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 36, nil, nil, 30, nil, nil, 52, 53,
- nil, nil, 54, nil, 32, nil, nil, nil, 40, nil,
- nil, nil, nil, nil, nil, nil, 18, nil, nil, nil,
- nil, 79, 72, 74, 75, 76, 77, nil, nil, nil,
- 73, 78, 62, 63, 64, 7, 51, nil, nil, nil,
- 56, 57, nil, nil, nil, 60, nil, 58, 59, 61,
- 23, 24, 65, 66, nil, nil, nil, nil, 22, 28,
- 27, 88, 87, 89, 90, nil, nil, 17, nil, nil,
- nil, nil, nil, 6, 41, 8, 9, 92, 91, 82,
- 50, 84, 83, 86, 85, 93, 94, nil, 80, 81,
- nil, 38, 39, 37, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 36, nil, nil, 30, nil, nil, 52,
- 53, nil, nil, 54, nil, 32, nil, nil, nil, 40,
- nil, nil, nil, nil, nil, nil, nil, 18, nil, nil,
- nil, nil, 79, 72, 74, 75, 76, 77, nil, nil,
- nil, 73, 78, 153, 164, 154, 177, 150, 170, 160,
- 159, 180, 181, 175, 158, 157, 152, 178, 182, 183,
- 162, 151, 165, 169, 171, 163, 156, nil, nil, 172,
- 179, 174, 173, 166, 176, 161, 149, 168, 167, nil,
- nil, nil, nil, nil, 148, 155, 146, 147, 144, 145,
- 109, 111, 108, nil, 110, nil, nil, nil, nil, nil,
- nil, nil, 139, 140, nil, 137, 121, 122, 123, nil,
- 126, 128, nil, nil, 124, nil, nil, nil, nil, 141,
- 142, 129, 130, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 134, 133, nil, 120,
- 138, 136, 135, 131, 132, 127, 125, 118, nil, 119,
- nil, nil, 143, 79, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 78, 153, 164, 154, 177, 150, 170,
- 160, 159, 180, 181, 175, 158, 157, 152, 178, 182,
- 183, 162, 151, 165, 169, 171, 163, 156, nil, nil,
- 172, 179, 174, 173, 166, 176, 161, 149, 168, 167,
- nil, nil, nil, nil, nil, 148, 155, 146, 147, 144,
- 145, 109, 111, nil, nil, 110, nil, nil, nil, nil,
- nil, nil, nil, 139, 140, nil, 137, 121, 122, 123,
- nil, 126, 128, nil, nil, 124, nil, nil, nil, nil,
- 141, 142, 129, 130, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 134, 133, nil,
- 120, 138, 136, 135, 131, 132, 127, 125, 118, nil,
- 119, nil, nil, 143, 79, nil, nil, 62, 63, 64,
- nil, 51, nil, nil, 78, 56, 57, nil, nil, nil,
- 60, nil, 58, 59, 61, 23, 24, 65, 66, nil,
- nil, nil, nil, 22, 28, 27, 88, 87, 89, 90,
- nil, nil, 17, nil, nil, nil, nil, nil, nil, 41,
- nil, nil, 92, 91, 82, 50, 84, 83, 86, 85,
- 93, 94, nil, 80, 81, nil, 38, 39, 37, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 200, nil,
- nil, 204, nil, nil, 52, 53, nil, nil, 54, nil,
- nil, nil, nil, nil, 40, nil, nil, nil, nil, nil,
- nil, nil, 18, nil, nil, nil, nil, 79, 72, 74,
- 75, 76, 77, nil, nil, nil, 73, 78, 62, 63,
- 64, nil, 51, nil, nil, nil, 56, 57, nil, nil,
- nil, 60, nil, 58, 59, 61, 23, 24, 65, 66,
- nil, nil, nil, nil, 22, 28, 27, 88, 87, 89,
- 90, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 41, nil, nil, 92, 91, 82, 50, 84, 83, 86,
- 85, 93, 94, nil, 80, 81, nil, 38, 39, 37,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 200,
- nil, nil, 204, nil, nil, 52, 53, nil, nil, 54,
- nil, nil, nil, nil, nil, 40, nil, nil, nil, nil,
- nil, nil, nil, 207, nil, nil, nil, nil, 79, 72,
- 74, 75, 76, 77, nil, nil, nil, 73, 78, 62,
- 63, 64, nil, 51, nil, nil, nil, 56, 57, nil,
- nil, nil, 60, nil, 58, 59, 61, 246, 247, 65,
- 66, nil, nil, nil, nil, 245, 28, 27, 88, 87,
- 89, 90, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 41, nil, nil, 92, 91, 82, 50, 84, 83,
- 86, 85, 93, 94, nil, 80, 81, nil, 38, 39,
- 37, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 200, nil, nil, 204, nil, nil, 52, 53, nil, nil,
- 54, nil, 241, nil, 243, nil, 40, nil, nil, nil,
- nil, nil, nil, nil, 207, nil, nil, nil, nil, 79,
- 72, 74, 75, 76, 77, nil, nil, nil, 73, 78,
- 62, 63, 64, nil, 51, nil, nil, nil, 56, 57,
- nil, nil, nil, 60, nil, 58, 59, 61, 246, 247,
- 65, 66, nil, nil, nil, nil, 245, 28, 27, 88,
- 87, 89, 90, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 41, nil, nil, 92, 91, 82, 50, 84,
- 83, 86, 85, 93, 94, nil, 80, 81, nil, 38,
- 39, 37, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 200, nil, nil, 204, nil, nil, 52, 53, nil,
- nil, 54, nil, 241, nil, 243, nil, 40, nil, nil,
- nil, nil, nil, nil, nil, 207, nil, nil, nil, nil,
- 79, 72, 74, 75, 76, 77, nil, nil, nil, 73,
- 78, 62, 63, 64, nil, 51, nil, nil, nil, 56,
- 57, nil, nil, nil, 60, nil, 58, 59, 61, 246,
- 247, 65, 66, nil, nil, nil, nil, 245, 28, 27,
- 88, 87, 89, 90, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 41, nil, nil, 92, 91, 82, 50,
- 84, 83, 86, 85, 93, 94, nil, 80, 81, nil,
- 38, 39, 37, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 200, nil, nil, 204, nil, nil, 52, 53,
- nil, nil, 54, nil, 241, nil, 243, nil, 40, nil,
- nil, nil, nil, nil, nil, nil, 207, nil, nil, nil,
- nil, 79, 72, 74, 75, 76, 77, nil, nil, nil,
- 73, 78, -249, -249, -249, nil, -249, nil, nil, nil,
- -249, -249, nil, nil, nil, -249, nil, -249, -249, -249,
- -249, -249, -249, -249, nil, nil, nil, nil, -249, -249,
- -249, -249, -249, -249, -249, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, -249, nil, nil, -249, -249, -249,
- -249, -249, -249, -249, -249, -249, -249, nil, -249, -249,
- nil, -249, -249, -249, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, -249, nil, nil, -249, 254, nil, -249,
- -249, nil, nil, -249, nil, -249, nil, -249, nil, -249,
- nil, nil, nil, nil, nil, nil, nil, -249, nil, nil,
- nil, nil, -249, -249, -249, -249, -249, -249, nil, nil,
- nil, -249, -249, -249, -249, -249, nil, -249, nil, nil,
- nil, -249, -249, nil, nil, nil, -249, nil, -249, -249,
- -249, -249, -249, -249, -249, nil, nil, nil, nil, -249,
- -249, -249, -249, -249, -249, -249, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, -249, nil, nil, -249, -249,
- -249, -249, -249, -249, -249, -249, -249, -249, nil, -249,
- -249, nil, -249, -249, -249, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, -249, nil, nil, -249, 263, nil,
- -249, -249, nil, nil, -249, nil, -249, nil, -249, nil,
- -249, nil, nil, nil, nil, nil, nil, nil, -249, nil,
- nil, nil, nil, -249, -249, -249, -249, -249, -249, nil,
- nil, nil, -249, -249, 62, 63, 64, nil, 51, nil,
- nil, nil, 56, 57, nil, nil, nil, 60, nil, 58,
- 59, 61, 246, 247, 65, 66, nil, nil, nil, nil,
- 245, 275, 279, 88, 87, 89, 90, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 276, nil, nil, 92,
- 91, 82, 50, 84, 83, 86, 85, 93, 94, nil,
- 80, 81, nil, nil, nil, 280, nil, 215, 219, 224,
- 225, 226, 221, 223, 231, 232, 227, 228, nil, 208,
- 209, nil, nil, 229, 230, 273, nil, nil, 270, nil,
- nil, 52, 53, nil, nil, 54, nil, 269, nil, 212,
- nil, 218, nil, 214, 213, 210, 211, 222, 220, 216,
- nil, 217, nil, nil, 79, 72, 74, 75, 76, 77,
- nil, nil, nil, 73, 78, 62, 63, 64, 233, 51,
- 568, nil, nil, 56, 57, nil, nil, nil, 60, nil,
- 58, 59, 61, 246, 247, 65, 66, nil, nil, nil,
- nil, 245, 275, 279, 88, 87, 89, 90, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 276, nil, nil,
- 92, 91, 82, 50, 84, 83, 86, 85, 93, 94,
- nil, 80, 81, nil, nil, nil, 280, nil, 215, 219,
- 224, 225, 226, 221, 223, 231, 232, 227, 228, nil,
- 208, 209, nil, nil, 229, 230, 273, nil, nil, 204,
- nil, nil, 52, 53, nil, nil, 54, nil, nil, nil,
- 212, nil, 218, nil, 214, 213, 210, 211, 222, 220,
- 216, nil, 217, nil, nil, 79, 72, 74, 75, 76,
- 77, nil, nil, nil, 73, 78, 62, 63, 64, 233,
- 51, nil, nil, nil, 56, 57, nil, nil, nil, 60,
- nil, 58, 59, 61, 246, 247, 65, 66, nil, nil,
- nil, nil, 245, 275, 279, 88, 87, 89, 90, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 41, nil,
- nil, 92, 91, 82, 50, 84, 83, 86, 85, 93,
- 94, nil, 80, 81, nil, 38, 39, 37, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 200, nil, nil,
- 204, nil, nil, 52, 53, nil, nil, 54, nil, nil,
- nil, nil, nil, 40, nil, nil, nil, nil, nil, nil,
- nil, 207, nil, nil, nil, nil, 79, 72, 74, 75,
- 76, 77, nil, nil, nil, 73, 78, 62, 63, 64,
- nil, 51, nil, nil, nil, 56, 57, nil, nil, nil,
- 60, nil, 58, 59, 61, 246, 247, 65, 66, nil,
- nil, nil, nil, 245, 275, 279, 88, 87, 89, 90,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 41,
- nil, nil, 92, 91, 82, 50, 84, 83, 86, 85,
- 93, 94, nil, 80, 81, nil, 38, 39, 37, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 200, nil,
- nil, 204, nil, nil, 52, 53, nil, nil, 54, nil,
- nil, nil, nil, nil, 40, nil, nil, nil, nil, nil,
- nil, nil, 207, nil, nil, nil, nil, 79, 72, 74,
- 75, 76, 77, nil, nil, nil, 73, 78, 62, 63,
- 64, nil, 51, nil, nil, nil, 56, 57, nil, nil,
- nil, 60, nil, 58, 59, 61, 246, 247, 65, 66,
- nil, nil, nil, nil, 245, 275, 279, 88, 87, 89,
- 90, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 41, nil, nil, 92, 91, 82, 50, 84, 83, 86,
- 85, 93, 94, nil, 80, 81, nil, 38, 39, 37,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 200,
- nil, nil, 204, nil, nil, 52, 53, nil, nil, 54,
- nil, nil, nil, nil, nil, 40, nil, nil, nil, nil,
- nil, nil, nil, 207, nil, nil, nil, nil, 79, 72,
- 74, 75, 76, 77, nil, nil, nil, 73, 78, 62,
- 63, 64, nil, 51, nil, nil, nil, 56, 57, nil,
- nil, nil, 60, nil, 58, 59, 61, 23, 24, 65,
- 66, nil, nil, nil, nil, 22, 28, 27, 88, 87,
- 89, 90, nil, nil, 17, nil, nil, nil, nil, nil,
- nil, 41, nil, nil, 92, 91, 82, 50, 84, 83,
- 86, 85, 93, 94, nil, 80, 81, nil, 38, 39,
- 37, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 200, nil, nil, 204, nil, nil, 52, 53, nil, nil,
- 54, nil, nil, nil, nil, nil, 40, nil, nil, nil,
- nil, nil, nil, nil, 18, nil, nil, nil, nil, 79,
- 72, 74, 75, 76, 77, nil, nil, nil, 73, 78,
- 62, 63, 64, nil, 51, nil, nil, nil, 56, 57,
- nil, nil, nil, 60, nil, 58, 59, 61, 246, 247,
- 65, 66, nil, nil, nil, nil, 245, 28, 27, 88,
- 87, 89, 90, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 41, nil, nil, 92, 91, 82, 50, 84,
- 83, 86, 85, 93, 94, nil, 80, 81, nil, 38,
- 39, 37, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 200, nil, nil, 204, nil, nil, 52, 53, nil,
- nil, 54, nil, 299, nil, nil, nil, 40, nil, nil,
- nil, nil, nil, nil, nil, 207, nil, nil, nil, nil,
- 79, 72, 74, 75, 76, 77, nil, nil, nil, 73,
- 78, 62, 63, 64, nil, 51, nil, nil, nil, 56,
- 57, nil, nil, nil, 60, nil, 58, 59, 61, 246,
- 247, 65, 66, nil, nil, nil, nil, 245, 275, 279,
- 88, 87, 89, 90, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 41, nil, nil, 92, 91, 82, 50,
- 84, 83, 86, 85, 93, 94, nil, 80, 81, nil,
- 38, 39, 37, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 200, nil, nil, 204, nil, nil, 52, 53,
- nil, nil, 54, nil, nil, nil, nil, nil, 40, nil,
- nil, nil, nil, nil, nil, nil, 207, nil, nil, nil,
- nil, 79, 72, 74, 75, 76, 77, nil, nil, nil,
- 73, 78, 62, 63, 64, nil, 51, nil, nil, nil,
- 56, 57, nil, nil, nil, 60, nil, 58, 59, 61,
- 23, 24, 65, 66, nil, nil, nil, nil, 22, 28,
- 27, 88, 87, 89, 90, nil, nil, 17, nil, nil,
- nil, nil, nil, nil, 41, nil, nil, 92, 91, 82,
- 50, 84, 83, 86, 85, 93, 94, nil, 80, 81,
- nil, 38, 39, 37, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 200, nil, nil, 204, nil, nil, 52,
- 53, nil, nil, 54, nil, nil, nil, nil, nil, 40,
- nil, nil, nil, nil, nil, nil, nil, 18, nil, nil,
- nil, nil, 79, 72, 74, 75, 76, 77, nil, nil,
- nil, 73, 78, 62, 63, 64, nil, 51, nil, nil,
- nil, 56, 57, nil, nil, nil, 60, nil, 58, 59,
- 61, 23, 24, 65, 66, nil, nil, nil, nil, 22,
- 28, 27, 88, 87, 89, 90, nil, nil, 17, nil,
- nil, nil, nil, nil, nil, 41, nil, nil, 92, 91,
- 82, 50, 84, 83, 86, 85, 93, 94, nil, 80,
- 81, nil, 38, 39, 37, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 200, nil, nil, 204, nil, nil,
- 52, 53, nil, nil, 54, nil, nil, nil, nil, nil,
- 40, nil, nil, nil, nil, nil, nil, nil, 18, nil,
- nil, nil, nil, 79, 72, 74, 75, 76, 77, nil,
- nil, nil, 73, 78, 62, 63, 64, nil, 51, nil,
- nil, nil, 56, 57, nil, nil, nil, 60, nil, 58,
- 59, 61, 246, 247, 65, 66, nil, nil, nil, nil,
- 245, 275, 279, 88, 87, 89, 90, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 276, nil, nil, 92,
- 91, 82, 50, 84, 83, 86, 85, 93, 94, nil,
- 80, 81, nil, nil, nil, 280, nil, 215, 219, 224,
- 225, 226, 221, 223, 231, 232, 227, 228, nil, 208,
- 209, nil, nil, 229, 230, 315, nil, nil, 30, nil,
- nil, 52, 53, nil, nil, 54, nil, 32, nil, 212,
- nil, 218, nil, 214, 213, 210, 211, 222, 220, 216,
- nil, 217, nil, nil, 79, 72, 74, 75, 76, 77,
- nil, nil, nil, 73, 78, 62, 63, 64, 233, 51,
- nil, nil, nil, 56, 57, nil, nil, nil, 60, nil,
- 58, 59, 61, 246, 247, 65, 66, nil, nil, nil,
- nil, 245, 275, 279, 88, 87, 89, 90, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 276, nil, nil,
- 92, 91, 320, 50, 84, 83, 321, 85, 93, 94,
- nil, 80, 81, nil, nil, nil, 280, nil, 215, 219,
- 224, 225, 226, 221, 223, 231, 232, 227, 228, nil,
- 208, 209, nil, 327, 229, 230, 322, nil, nil, 204,
- nil, nil, 52, 53, nil, nil, 54, nil, nil, nil,
- 212, nil, 218, nil, 214, 213, 210, 211, 222, 220,
- 216, nil, 217, nil, nil, 79, 72, 74, 75, 76,
- 77, nil, nil, nil, 73, 78, 62, 63, 64, 233,
- 51, nil, nil, nil, 56, 57, nil, nil, nil, 60,
- nil, 58, 59, 61, 246, 247, 65, 66, nil, nil,
- nil, nil, 245, 275, 279, 88, 87, 89, 90, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 276, nil,
- nil, 92, 91, 320, 50, 84, 83, 321, 85, 93,
- 94, nil, 80, 81, nil, nil, nil, 280, nil, 215,
- 219, 224, 225, 226, 221, 223, 231, 232, 227, 228,
- nil, 208, 209, nil, nil, 229, 230, 322, nil, nil,
- 204, nil, nil, 52, 53, nil, nil, 54, nil, nil,
- nil, 212, nil, 218, nil, 214, 213, 210, 211, 222,
- 220, 216, nil, 217, nil, nil, 79, 72, 74, 75,
- 76, 77, nil, nil, nil, 73, 78, -473, -473, -473,
- 233, -473, nil, nil, nil, -473, -473, nil, nil, nil,
- -473, nil, -473, -473, -473, -473, -473, -473, -473, nil,
- -473, nil, nil, -473, -473, -473, -473, -473, -473, -473,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, -473,
- nil, nil, -473, -473, -473, -473, -473, -473, -473, -473,
- -473, -473, nil, -473, -473, nil, -473, -473, -473, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, -473, nil,
- nil, -473, -473, nil, -473, -473, nil, nil, -473, nil,
- -473, nil, -473, nil, -473, nil, nil, nil, nil, nil,
- nil, nil, -473, nil, -473, nil, nil, -473, -473, -473,
- -473, -473, -473, nil, nil, nil, -473, -473, -474, -474,
- -474, nil, -474, nil, nil, nil, -474, -474, nil, nil,
- nil, -474, nil, -474, -474, -474, -474, -474, -474, -474,
- nil, -474, nil, nil, -474, -474, -474, -474, -474, -474,
- -474, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- -474, nil, nil, -474, -474, -474, -474, -474, -474, -474,
- -474, -474, -474, nil, -474, -474, nil, -474, -474, -474,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, -474,
- nil, nil, -474, -474, nil, -474, -474, nil, nil, -474,
- nil, -474, nil, -474, nil, -474, nil, nil, nil, nil,
- nil, nil, nil, -474, nil, -474, nil, nil, -474, -474,
- -474, -474, -474, -474, nil, nil, nil, -474, -474, 62,
- 63, 64, nil, 51, nil, nil, nil, 56, 57, nil,
- nil, nil, 60, nil, 58, 59, 61, 23, 24, 65,
- 66, nil, nil, nil, nil, 22, 28, 27, 88, 87,
- 89, 90, nil, nil, 17, nil, nil, nil, nil, nil,
- nil, 41, nil, nil, 92, 91, 82, 50, 84, 83,
- 86, 85, 93, 94, nil, 80, 81, nil, 38, 39,
- 37, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 200, nil, nil, 204, nil, nil, 52, 53, nil, nil,
- 54, nil, nil, nil, nil, nil, 40, nil, nil, nil,
- nil, nil, nil, nil, 18, nil, nil, nil, nil, 79,
- 72, 74, 75, 76, 77, nil, nil, nil, 73, 78,
- 62, 63, 64, nil, 51, nil, nil, nil, 56, 57,
- nil, nil, nil, 60, nil, 58, 59, 61, 23, 24,
- 65, 66, nil, nil, nil, nil, 22, 28, 27, 88,
- 87, 89, 90, nil, nil, 17, nil, nil, nil, nil,
- nil, nil, 41, nil, nil, 92, 91, 82, 50, 84,
- 83, 86, 85, 93, 94, nil, 80, 81, nil, 38,
- 39, 37, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 200, nil, nil, 204, nil, nil, 52, 53, nil,
- nil, 54, nil, nil, nil, nil, nil, 40, nil, nil,
- nil, nil, nil, nil, nil, 18, nil, nil, nil, nil,
- 79, 72, 74, 75, 76, 77, nil, nil, nil, 73,
- 78, 62, 63, 64, nil, 51, nil, nil, nil, 56,
- 57, nil, nil, nil, 60, nil, 58, 59, 61, 23,
- 24, 65, 66, nil, nil, nil, nil, 22, 28, 27,
- 88, 87, 89, 90, nil, nil, 17, nil, nil, nil,
- nil, nil, nil, 41, nil, nil, 92, 91, 82, 50,
- 84, 83, 86, 85, 93, 94, nil, 80, 81, nil,
- 38, 39, 37, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 200, nil, nil, 204, nil, nil, 52, 53,
- nil, nil, 54, nil, nil, nil, nil, nil, 40, nil,
- nil, nil, nil, nil, nil, nil, 18, nil, nil, nil,
- nil, 79, 72, 74, 75, 76, 77, nil, nil, nil,
- 73, 78, 62, 63, 64, nil, 51, nil, nil, nil,
- 56, 57, nil, nil, nil, 60, nil, 58, 59, 61,
- 23, 24, 65, 66, nil, nil, nil, nil, 22, 28,
- 27, 88, 87, 89, 90, nil, nil, 17, nil, nil,
- nil, nil, nil, nil, 41, nil, nil, 92, 91, 82,
- 50, 84, 83, 86, 85, 93, 94, nil, 80, 81,
- nil, 38, 39, 37, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 200, nil, nil, 204, nil, nil, 52,
- 53, nil, nil, 54, nil, nil, nil, nil, nil, 40,
- nil, nil, nil, nil, nil, nil, nil, 18, nil, nil,
- nil, nil, 79, 72, 74, 75, 76, 77, nil, nil,
- nil, 73, 78, 62, 63, 64, 7, 51, nil, nil,
- nil, 56, 57, nil, nil, nil, 60, nil, 58, 59,
- 61, 23, 24, 65, 66, nil, nil, nil, nil, 22,
- 28, 27, 88, 87, 89, 90, nil, nil, 17, nil,
- nil, nil, nil, nil, 6, 41, 8, 9, 92, 91,
- 82, 50, 84, 83, 86, 85, 93, 94, nil, 80,
- 81, nil, 38, 39, 37, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 36, nil, nil, 30, nil, nil,
- 52, 53, nil, nil, 54, nil, 32, nil, nil, nil,
- 40, nil, nil, nil, nil, nil, nil, nil, 18, nil,
- nil, nil, nil, 79, 72, 74, 75, 76, 77, nil,
- nil, nil, 73, 78, 62, 63, 64, nil, 51, nil,
- nil, nil, 56, 57, nil, nil, nil, 60, nil, 58,
- 59, 61, 23, 24, 65, 66, nil, nil, nil, nil,
- 22, 28, 27, 88, 87, 89, 90, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 41, nil, nil, 92,
- 91, 82, 50, 84, 83, 86, 85, 93, 94, nil,
- 80, 81, nil, 38, 39, 37, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 200, nil, nil, 204, nil,
- nil, 52, 53, nil, nil, 54, nil, 369, nil, nil,
- nil, 40, nil, nil, nil, nil, nil, nil, nil, 207,
- nil, nil, nil, nil, 79, 72, 74, 75, 76, 77,
- nil, nil, nil, 73, 78, 62, 63, 64, nil, 51,
- nil, nil, nil, 56, 57, nil, nil, nil, 60, nil,
- 58, 59, 61, 23, 24, 65, 66, nil, nil, nil,
- nil, 22, 28, 27, 88, 87, 89, 90, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 41, nil, nil,
- 92, 91, 82, 50, 84, 83, 86, 85, 93, 94,
- nil, 80, 81, nil, 38, 39, 37, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 200, nil, nil, 204,
- nil, nil, 52, 53, nil, nil, 54, nil, 369, nil,
- nil, nil, 40, nil, nil, nil, nil, nil, nil, nil,
- 207, nil, nil, nil, nil, 79, 72, 74, 75, 76,
- 77, nil, nil, nil, 73, 78, 62, 63, 64, nil,
- 51, nil, nil, nil, 56, 57, nil, nil, nil, 60,
- nil, 58, 59, 61, 23, 24, 65, 66, nil, nil,
- nil, nil, 22, 28, 27, 88, 87, 89, 90, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 41, nil,
- nil, 92, 91, 82, 50, 84, 83, 86, 85, 93,
- 94, nil, 80, 81, nil, 38, 39, 37, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 200, nil, nil,
- 204, nil, nil, 52, 53, nil, nil, 54, nil, nil,
- nil, nil, nil, 40, nil, nil, nil, nil, nil, nil,
- nil, 207, nil, nil, nil, nil, 79, 72, 74, 75,
- 76, 77, nil, nil, nil, 73, 78, 62, 63, 64,
- nil, 51, nil, nil, nil, 56, 57, nil, nil, nil,
- 60, nil, 58, 59, 61, 246, 247, 65, 66, nil,
- nil, nil, nil, 245, 28, 27, 88, 87, 89, 90,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 41,
- nil, nil, 92, 91, 82, 50, 84, 83, 86, 85,
- 93, 94, nil, 80, 81, nil, 38, 39, 37, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 200, nil,
- nil, 204, nil, nil, 52, 53, nil, nil, 54, nil,
- 299, nil, nil, nil, 40, nil, nil, nil, nil, nil,
- nil, nil, 207, nil, nil, nil, nil, 79, 72, 74,
- 75, 76, 77, nil, nil, nil, 73, 78, 62, 63,
- 64, nil, 51, nil, nil, nil, 56, 57, nil, nil,
- nil, 60, nil, 58, 59, 61, 23, 24, 65, 66,
- nil, nil, nil, nil, 22, 28, 27, 88, 87, 89,
- 90, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 41, nil, nil, 92, 91, 82, 50, 84, 83, 86,
- 85, 93, 94, nil, 80, 81, nil, 38, 39, 37,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 200,
- nil, nil, 204, nil, nil, 52, 53, nil, nil, 54,
- nil, nil, nil, nil, nil, 40, nil, nil, nil, nil,
- nil, nil, nil, 207, nil, nil, nil, nil, 79, 72,
- 74, 75, 76, 77, nil, nil, nil, 73, 78, 62,
- 63, 64, nil, 51, nil, nil, nil, 56, 57, nil,
- nil, nil, 60, nil, 58, 59, 61, 23, 24, 65,
- 66, nil, nil, nil, nil, 22, 28, 27, 88, 87,
- 89, 90, nil, nil, 17, nil, nil, nil, nil, nil,
- nil, 41, nil, nil, 92, 91, 82, 50, 84, 83,
- 86, 85, 93, 94, nil, 80, 81, nil, 38, 39,
- 37, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 200, nil, nil, 204, nil, nil, 52, 53, nil, nil,
- 54, nil, nil, nil, nil, nil, 40, nil, nil, nil,
- nil, nil, nil, nil, 18, nil, nil, nil, nil, 79,
- 72, 74, 75, 76, 77, nil, nil, nil, 73, 78,
- 62, 63, 64, nil, 51, nil, nil, nil, 56, 57,
- nil, nil, nil, 60, nil, 58, 59, 61, 23, 24,
- 65, 66, nil, nil, nil, nil, 22, 28, 27, 88,
- 87, 89, 90, nil, nil, 17, nil, nil, nil, nil,
- nil, nil, 41, nil, nil, 92, 91, 82, 50, 84,
- 83, 86, 85, 93, 94, nil, 80, 81, nil, 38,
- 39, 37, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 200, nil, nil, 204, nil, nil, 52, 53, nil,
- nil, 54, nil, nil, nil, nil, nil, 40, nil, nil,
- nil, nil, nil, nil, nil, 18, nil, nil, nil, nil,
- 79, 72, 74, 75, 76, 77, nil, nil, nil, 73,
- 78, 62, 63, 64, nil, 51, nil, nil, nil, 56,
- 57, nil, nil, nil, 60, nil, 58, 59, 61, 246,
- 247, 65, 66, nil, nil, nil, nil, 245, 275, 279,
- 88, 87, 89, 90, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 41, nil, nil, 92, 91, 82, 50,
- 84, 83, 86, 85, 93, 94, nil, 80, 81, nil,
- 38, 39, 37, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 200, nil, nil, 204, nil, nil, 52, 53,
- nil, nil, 54, nil, nil, nil, nil, nil, 40, nil,
- nil, nil, nil, nil, nil, nil, 207, nil, nil, nil,
- nil, 79, 72, 74, 75, 76, 77, nil, nil, nil,
- 73, 78, 62, 63, 64, nil, 51, nil, nil, nil,
- 56, 57, nil, nil, nil, 60, nil, 58, 59, 61,
- 246, 247, 65, 66, nil, nil, nil, nil, 245, 275,
- 279, 88, 87, 89, 90, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 41, nil, nil, 92, 91, 82,
- 50, 84, 83, 86, 85, 93, 94, nil, 80, 81,
- nil, 38, 39, 37, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 200, nil, nil, 204, nil, nil, 52,
- 53, nil, nil, 54, nil, nil, nil, nil, nil, 40,
- nil, nil, nil, nil, nil, nil, nil, 207, nil, nil,
- nil, nil, 79, 72, 74, 75, 76, 77, nil, nil,
- nil, 73, 78, 62, 63, 64, nil, 51, nil, nil,
- nil, 56, 57, nil, nil, nil, 60, nil, 58, 59,
- 61, 246, 247, 65, 66, nil, nil, nil, nil, 245,
- 275, 279, 88, 87, 89, 90, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 41, nil, nil, 92, 91,
- 82, 50, 84, 83, 86, 85, 93, 94, nil, 80,
- 81, nil, 38, 39, 37, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 200, nil, nil, 204, nil, nil,
- 52, 53, nil, nil, 54, nil, nil, nil, nil, nil,
- 40, nil, nil, nil, nil, nil, nil, nil, 207, nil,
- nil, nil, nil, 79, 72, 74, 75, 76, 77, nil,
- nil, nil, 73, 78, 62, 63, 64, nil, 51, nil,
- nil, nil, 56, 57, nil, nil, nil, 60, nil, 58,
- 59, 61, 246, 247, 65, 66, nil, nil, nil, nil,
- 245, 275, 279, 88, 87, 89, 90, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 41, nil, nil, 92,
- 91, 82, 50, 84, 83, 86, 85, 93, 94, nil,
- 80, 81, nil, 38, 39, 37, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 200, nil, nil, 204, nil,
- nil, 52, 53, nil, nil, 54, nil, nil, nil, nil,
- nil, 40, nil, nil, nil, nil, nil, nil, nil, 207,
- nil, nil, nil, nil, 79, 72, 74, 75, 76, 77,
- nil, nil, nil, 73, 78, 62, 63, 64, nil, 51,
- nil, nil, nil, 56, 57, nil, nil, nil, 60, nil,
- 58, 59, 61, 246, 247, 65, 66, nil, nil, nil,
- nil, 245, 275, 279, 88, 87, 89, 90, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 41, nil, nil,
- 92, 91, 82, 50, 84, 83, 86, 85, 93, 94,
- nil, 80, 81, nil, 38, 39, 37, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 200, nil, nil, 204,
- nil, nil, 52, 53, nil, nil, 54, nil, nil, nil,
- nil, nil, 40, nil, nil, nil, nil, nil, nil, nil,
- 207, nil, nil, nil, nil, 79, 72, 74, 75, 76,
- 77, nil, nil, nil, 73, 78, 62, 63, 64, nil,
- 51, nil, nil, nil, 56, 57, nil, nil, nil, 60,
- nil, 58, 59, 61, 246, 247, 65, 66, nil, nil,
- nil, nil, 245, 275, 279, 88, 87, 89, 90, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 41, nil,
- nil, 92, 91, 82, 50, 84, 83, 86, 85, 93,
- 94, nil, 80, 81, nil, 38, 39, 37, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 200, nil, nil,
- 204, nil, nil, 52, 53, nil, nil, 54, nil, nil,
- nil, nil, nil, 40, nil, nil, nil, nil, nil, nil,
- nil, 207, nil, nil, nil, nil, 79, 72, 74, 75,
- 76, 77, nil, nil, nil, 73, 78, 62, 63, 64,
- nil, 51, nil, nil, nil, 56, 57, nil, nil, nil,
- 60, nil, 58, 59, 61, 246, 247, 65, 66, nil,
- nil, nil, nil, 245, 275, 279, 88, 87, 89, 90,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 41,
- nil, nil, 92, 91, 82, 50, 84, 83, 86, 85,
- 93, 94, nil, 80, 81, nil, 38, 39, 37, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 200, nil,
- nil, 204, nil, nil, 52, 53, nil, nil, 54, nil,
- nil, nil, nil, nil, 40, nil, nil, nil, nil, nil,
- nil, nil, 207, nil, nil, nil, nil, 79, 72, 74,
- 75, 76, 77, nil, nil, nil, 73, 78, 62, 63,
- 64, nil, 51, nil, nil, nil, 56, 57, nil, nil,
- nil, 60, nil, 58, 59, 61, 246, 247, 65, 66,
- nil, nil, nil, nil, 245, 275, 279, 88, 87, 89,
- 90, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 41, nil, nil, 92, 91, 82, 50, 84, 83, 86,
- 85, 93, 94, nil, 80, 81, nil, 38, 39, 37,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 200,
- nil, nil, 204, nil, nil, 52, 53, nil, nil, 54,
- nil, nil, nil, nil, nil, 40, nil, nil, nil, nil,
- nil, nil, nil, 207, nil, nil, nil, nil, 79, 72,
- 74, 75, 76, 77, nil, nil, nil, 73, 78, 62,
- 63, 64, nil, 51, nil, nil, nil, 56, 57, nil,
- nil, nil, 60, nil, 58, 59, 61, 246, 247, 65,
- 66, nil, nil, nil, nil, 245, 275, 279, 88, 87,
- 89, 90, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 41, nil, nil, 92, 91, 82, 50, 84, 83,
- 86, 85, 93, 94, nil, 80, 81, nil, 38, 39,
- 37, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 200, nil, nil, 204, nil, nil, 52, 53, nil, nil,
- 54, nil, nil, nil, nil, nil, 40, nil, nil, nil,
- nil, nil, nil, nil, 207, nil, nil, nil, nil, 79,
- 72, 74, 75, 76, 77, nil, nil, nil, 73, 78,
- 62, 63, 64, nil, 51, nil, nil, nil, 56, 57,
- nil, nil, nil, 60, nil, 58, 59, 61, 246, 247,
- 65, 66, nil, nil, nil, nil, 245, 275, 279, 88,
- 87, 89, 90, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 41, nil, nil, 92, 91, 82, 50, 84,
- 83, 86, 85, 93, 94, nil, 80, 81, nil, 38,
- 39, 37, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 200, nil, nil, 204, nil, nil, 52, 53, nil,
- nil, 54, nil, nil, nil, nil, nil, 40, nil, nil,
- nil, nil, nil, nil, nil, 207, nil, nil, nil, nil,
- 79, 72, 74, 75, 76, 77, nil, nil, nil, 73,
- 78, 62, 63, 64, nil, 51, nil, nil, nil, 56,
- 57, nil, nil, nil, 60, nil, 58, 59, 61, 246,
- 247, 65, 66, nil, nil, nil, nil, 245, 275, 279,
- 88, 87, 89, 90, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 41, nil, nil, 92, 91, 82, 50,
- 84, 83, 86, 85, 93, 94, nil, 80, 81, nil,
- 38, 39, 37, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 200, nil, nil, 204, nil, nil, 52, 53,
- nil, nil, 54, nil, nil, nil, nil, nil, 40, nil,
- nil, nil, nil, nil, nil, nil, 207, nil, nil, nil,
- nil, 79, 72, 74, 75, 76, 77, nil, nil, nil,
- 73, 78, 62, 63, 64, nil, 51, nil, nil, nil,
- 56, 57, nil, nil, nil, 60, nil, 58, 59, 61,
- 246, 247, 65, 66, nil, nil, nil, nil, 245, 275,
- 279, 88, 87, 89, 90, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 41, nil, nil, 92, 91, 82,
- 50, 84, 83, 86, 85, 93, 94, nil, 80, 81,
- nil, 38, 39, 37, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 200, nil, nil, 204, nil, nil, 52,
- 53, nil, nil, 54, nil, nil, nil, nil, nil, 40,
- nil, nil, nil, nil, nil, nil, nil, 207, nil, nil,
- nil, nil, 79, 72, 74, 75, 76, 77, nil, nil,
- nil, 73, 78, 62, 63, 64, nil, 51, nil, nil,
- nil, 56, 57, nil, nil, nil, 60, nil, 58, 59,
- 61, 246, 247, 65, 66, nil, nil, nil, nil, 245,
- 275, 279, 88, 87, 89, 90, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 41, nil, nil, 92, 91,
- 82, 50, 84, 83, 86, 85, 93, 94, nil, 80,
- 81, nil, 38, 39, 37, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 200, nil, nil, 204, nil, nil,
- 52, 53, nil, nil, 54, nil, nil, nil, nil, nil,
- 40, nil, nil, nil, nil, nil, nil, nil, 207, nil,
- nil, nil, nil, 79, 72, 74, 75, 76, 77, nil,
- nil, nil, 73, 78, 62, 63, 64, nil, 51, nil,
- nil, nil, 56, 57, nil, nil, nil, 60, nil, 58,
- 59, 61, 246, 247, 65, 66, nil, nil, nil, nil,
- 245, 275, 279, 88, 87, 89, 90, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 41, nil, nil, 92,
- 91, 82, 50, 84, 83, 86, 85, 93, 94, nil,
- 80, 81, nil, 38, 39, 37, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 200, nil, nil, 204, nil,
- nil, 52, 53, nil, nil, 54, nil, nil, nil, nil,
- nil, 40, nil, nil, nil, nil, nil, nil, nil, 207,
- nil, nil, nil, nil, 79, 72, 74, 75, 76, 77,
- nil, nil, nil, 73, 78, 62, 63, 64, nil, 51,
- nil, nil, nil, 56, 57, nil, nil, nil, 60, nil,
- 58, 59, 61, 246, 247, 65, 66, nil, nil, nil,
- nil, 245, 275, 279, 88, 87, 89, 90, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 41, nil, nil,
- 92, 91, 82, 50, 84, 83, 86, 85, 93, 94,
- nil, 80, 81, nil, 38, 39, 37, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 200, nil, nil, 204,
- nil, nil, 52, 53, nil, nil, 54, nil, nil, nil,
- nil, nil, 40, nil, nil, nil, nil, nil, nil, nil,
- 207, nil, nil, nil, nil, 79, 72, 74, 75, 76,
- 77, nil, nil, nil, 73, 78, 62, 63, 64, nil,
- 51, nil, nil, nil, 56, 57, nil, nil, nil, 60,
- nil, 58, 59, 61, 246, 247, 65, 66, nil, nil,
- nil, nil, 245, 275, 279, 88, 87, 89, 90, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 41, nil,
- nil, 92, 91, 82, 50, 84, 83, 86, 85, 93,
- 94, nil, 80, 81, nil, 38, 39, 37, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 200, nil, nil,
- 204, nil, nil, 52, 53, nil, nil, 54, nil, nil,
- nil, nil, nil, 40, nil, nil, nil, nil, nil, nil,
- nil, 207, nil, nil, nil, nil, 79, 72, 74, 75,
- 76, 77, nil, nil, nil, 73, 78, 62, 63, 64,
- nil, 51, nil, nil, nil, 56, 57, nil, nil, nil,
- 60, nil, 58, 59, 61, 246, 247, 65, 66, nil,
- nil, nil, nil, 245, 275, 279, 88, 87, 89, 90,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 41,
- nil, nil, 92, 91, 82, 50, 84, 83, 86, 85,
- 93, 94, nil, 80, 81, nil, 38, 39, 37, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 200, nil,
- nil, 204, nil, nil, 52, 53, nil, nil, 54, nil,
- nil, nil, nil, nil, 40, nil, nil, nil, nil, nil,
- nil, nil, 207, nil, nil, nil, nil, 79, 72, 74,
- 75, 76, 77, nil, nil, nil, 73, 78, 62, 63,
- 64, nil, 51, nil, nil, nil, 56, 57, nil, nil,
- nil, 60, nil, 58, 59, 61, 246, 247, 65, 66,
- nil, nil, nil, nil, 245, 275, 279, 88, 87, 89,
- 90, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 41, nil, nil, 92, 91, 82, 50, 84, 83, 86,
- 85, 93, 94, nil, 80, 81, nil, 38, 39, 37,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 200,
- nil, nil, 204, nil, nil, 52, 53, nil, nil, 54,
- nil, nil, nil, nil, nil, 40, nil, nil, nil, nil,
- nil, nil, nil, 207, nil, nil, nil, nil, 79, 72,
- 74, 75, 76, 77, nil, nil, nil, 73, 78, 62,
- 63, 64, nil, 51, nil, nil, nil, 56, 57, nil,
- nil, nil, 60, nil, 58, 59, 61, 246, 247, 65,
- 66, nil, nil, nil, nil, 245, 275, 279, 88, 87,
- 89, 90, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 41, nil, nil, 92, 91, 82, 50, 84, 83,
- 86, 85, 93, 94, nil, 80, 81, nil, 38, 39,
- 37, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 200, nil, nil, 204, nil, nil, 52, 53, nil, nil,
- 54, nil, nil, nil, nil, nil, 40, nil, nil, nil,
- nil, nil, nil, nil, 207, nil, nil, nil, nil, 79,
- 72, 74, 75, 76, 77, nil, nil, nil, 73, 78,
- 62, 63, 64, nil, 51, nil, nil, nil, 56, 57,
- nil, nil, nil, 60, nil, 58, 59, 61, 246, 247,
- 65, 66, nil, nil, nil, nil, 245, 275, 279, 88,
- 87, 89, 90, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 41, nil, nil, 92, 91, 82, 50, 84,
- 83, 86, 85, 93, 94, nil, 80, 81, nil, 38,
- 39, 37, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 200, nil, nil, 204, nil, nil, 52, 53, nil,
- nil, 54, nil, nil, nil, nil, nil, 40, nil, nil,
- nil, nil, nil, nil, nil, 207, nil, nil, nil, nil,
- 79, 72, 74, 75, 76, 77, nil, nil, nil, 73,
- 78, 62, 63, 64, nil, 51, nil, nil, nil, 56,
- 57, nil, nil, nil, 60, nil, 58, 59, 61, 246,
- 247, 65, 66, nil, nil, nil, nil, 245, 275, 279,
- 88, 87, 89, 90, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 41, nil, nil, 92, 91, 82, 50,
- 84, 83, 86, 85, 93, 94, nil, 80, 81, nil,
- 38, 39, 37, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 200, nil, nil, 204, nil, nil, 52, 53,
- nil, nil, 54, nil, nil, nil, nil, nil, 40, nil,
- nil, nil, nil, nil, nil, nil, 207, nil, nil, nil,
- nil, 79, 72, 74, 75, 76, 77, nil, nil, nil,
- 73, 78, 62, 63, 64, nil, 51, nil, nil, nil,
- 56, 57, nil, nil, nil, 60, nil, 58, 59, 61,
- 246, 247, 65, 66, nil, nil, nil, nil, 245, 275,
- 279, 88, 87, 89, 90, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 41, nil, nil, 92, 91, 82,
- 50, 84, 83, 86, 85, 93, 94, nil, 80, 81,
- nil, 38, 39, 37, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 200, nil, nil, 204, nil, nil, 52,
- 53, nil, nil, 54, nil, nil, nil, nil, nil, 40,
- nil, nil, nil, nil, nil, nil, nil, 207, nil, nil,
- nil, nil, 79, 72, 74, 75, 76, 77, nil, nil,
- nil, 73, 78, 62, 63, 64, nil, 51, nil, nil,
- nil, 56, 57, nil, nil, nil, 60, nil, 58, 59,
- 61, 246, 247, 65, 66, nil, nil, nil, nil, 245,
- 275, 279, 88, 87, 89, 90, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 41, nil, nil, 92, 91,
- 82, 50, 84, 83, 86, 85, 93, 94, nil, 80,
- 81, nil, 38, 39, 37, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 200, nil, nil, 204, nil, nil,
- 52, 53, nil, nil, 54, nil, nil, nil, nil, nil,
- 40, nil, nil, nil, nil, nil, nil, nil, 207, nil,
- nil, nil, nil, 79, 72, 74, 75, 76, 77, nil,
- nil, nil, 73, 78, 62, 63, 64, nil, 51, nil,
- nil, nil, 56, 57, nil, nil, nil, 60, nil, 58,
- 59, 61, 246, 247, 65, 66, nil, nil, nil, nil,
- 245, 275, 279, 88, 87, 89, 90, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 41, nil, nil, 92,
- 91, 82, 50, 84, 83, 86, 85, 93, 94, nil,
- 80, 81, nil, 38, 39, 37, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 200, nil, nil, 204, nil,
- nil, 52, 53, nil, nil, 54, nil, nil, nil, nil,
- nil, 40, nil, nil, nil, nil, nil, nil, nil, 207,
- nil, nil, nil, nil, 79, 72, 74, 75, 76, 77,
- nil, nil, nil, 73, 78, 62, 63, 64, nil, 51,
- nil, nil, nil, 56, 57, nil, nil, nil, 60, nil,
- 58, 59, 61, 246, 247, 65, 66, nil, nil, nil,
- nil, 245, 275, 279, 88, 87, 89, 90, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 41, nil, nil,
- 92, 91, 82, 50, 84, 83, 86, 85, 93, 94,
- nil, 80, 81, nil, 38, 39, 37, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 200, nil, nil, 204,
- nil, nil, 52, 53, nil, nil, 54, nil, nil, nil,
- nil, nil, 40, nil, nil, nil, nil, nil, nil, nil,
- 207, nil, nil, nil, nil, 79, 72, 74, 75, 76,
- 77, nil, nil, nil, 73, 78, 62, 63, 64, nil,
- 51, nil, nil, nil, 56, 57, nil, nil, nil, 60,
- nil, 58, 59, 61, 246, 247, 65, 66, nil, nil,
- nil, nil, 245, 275, 279, 88, 87, 89, 90, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 41, nil,
- nil, 92, 91, 82, 50, 84, 83, 86, 85, 93,
- 94, nil, 80, 81, nil, 38, 39, 37, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 200, nil, nil,
- 204, nil, nil, 52, 53, nil, nil, 54, nil, nil,
- nil, nil, nil, 40, nil, nil, nil, nil, nil, nil,
- nil, 207, nil, nil, nil, nil, 79, 72, 74, 75,
- 76, 77, nil, nil, nil, 73, 78, 62, 63, 64,
- nil, 51, nil, nil, nil, 56, 57, nil, nil, nil,
- 60, nil, 58, 59, 61, 246, 247, 65, 66, nil,
- nil, nil, nil, 245, 275, 279, 88, 87, 89, 90,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 41,
- nil, nil, 92, 91, 82, 50, 84, 83, 86, 85,
- 93, 94, nil, 80, 81, nil, 38, 39, 37, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 200, nil,
- nil, 204, nil, nil, 52, 53, nil, nil, 54, nil,
- nil, nil, nil, nil, 40, nil, nil, nil, nil, nil,
- nil, nil, 207, nil, nil, nil, nil, 79, 72, 74,
- 75, 76, 77, nil, nil, nil, 73, 78, 62, 63,
- 64, nil, 51, nil, nil, nil, 56, 57, nil, nil,
- nil, 60, nil, 58, 59, 61, 246, 247, 65, 66,
- nil, nil, nil, nil, 245, 275, 279, 88, 87, 89,
- 90, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 41, nil, nil, 92, 91, 82, 50, 84, 83, 86,
- 85, 93, 94, nil, 80, 81, nil, 38, 39, 37,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 200,
- nil, nil, 204, nil, nil, 52, 53, nil, nil, 54,
- nil, nil, nil, nil, nil, 40, nil, nil, nil, nil,
- nil, nil, nil, 207, nil, nil, nil, nil, 79, 72,
- 74, 75, 76, 77, nil, nil, nil, 73, 78, 62,
- 63, 64, nil, 51, nil, nil, nil, 56, 57, nil,
- nil, nil, 60, nil, 58, 59, 61, 246, 247, 65,
- 66, nil, nil, nil, nil, 245, 275, 279, 88, 87,
- 89, 90, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 41, nil, nil, 92, 91, 82, 50, 84, 83,
- 86, 85, 93, 94, nil, 80, 81, nil, 38, 39,
- 37, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 200, nil, nil, 204, nil, nil, 52, 53, nil, nil,
- 54, nil, nil, nil, nil, nil, 40, nil, nil, nil,
- nil, nil, nil, nil, 207, nil, nil, nil, nil, 79,
- 72, 74, 75, 76, 77, nil, nil, nil, 73, 78,
- 62, 63, 64, nil, 51, nil, nil, nil, 56, 57,
- nil, nil, nil, 60, nil, 58, 59, 61, 246, 247,
- 65, 66, nil, nil, nil, nil, 245, 28, 27, 88,
- 87, 89, 90, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 41, nil, nil, 92, 91, 82, 50, 84,
- 83, 86, 85, 93, 94, nil, 80, 81, nil, 38,
- 39, 37, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 200, nil, nil, 204, nil, nil, 52, 53, nil,
- nil, 54, nil, 241, nil, 243, nil, 40, nil, nil,
- nil, nil, nil, nil, nil, 207, nil, nil, nil, nil,
- 79, 72, 74, 75, 76, 77, nil, nil, nil, 73,
- 78, 62, 63, 64, nil, 51, nil, nil, nil, 56,
- 57, nil, nil, nil, 60, nil, 58, 59, 61, 246,
- 247, 65, 66, nil, nil, nil, nil, 245, 28, 27,
- 88, 87, 89, 90, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 41, nil, nil, 92, 91, 82, 50,
- 84, 83, 86, 85, 93, 94, nil, 80, 81, nil,
- 38, 39, 37, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 200, nil, nil, 204, nil, nil, 445, 53,
- nil, nil, 54, nil, 241, nil, 243, nil, 40, nil,
- nil, nil, nil, nil, nil, nil, 207, nil, nil, nil,
- nil, 79, 72, 74, 75, 76, 77, nil, nil, nil,
- 73, 78, 62, 63, 64, nil, 51, nil, nil, nil,
- 56, 57, nil, nil, nil, 60, nil, 58, 59, 61,
- 246, 247, 65, 66, nil, nil, nil, nil, 245, 28,
- 27, 88, 87, 89, 90, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 41, nil, nil, 92, 91, 82,
- 50, 84, 83, 86, 85, 93, 94, nil, 80, 81,
- nil, 38, 39, 37, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 200, nil, nil, 204, nil, 449, 52,
- 53, nil, nil, 54, nil, 241, nil, 243, nil, 40,
- nil, nil, nil, nil, nil, nil, nil, 207, nil, nil,
- nil, nil, 79, 72, 74, 75, 76, 77, nil, nil,
- nil, 73, 78, 62, 63, 64, nil, 51, nil, nil,
- nil, 56, 57, nil, nil, nil, 60, nil, 58, 59,
- 61, 246, 247, 65, 66, nil, nil, nil, nil, 245,
- 275, 279, 88, 87, 89, 90, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 276, nil, nil, 92, 91,
- 82, 50, 84, 83, 86, 85, 93, 94, nil, 80,
- 81, nil, nil, nil, 280, nil, 215, 219, 224, 225,
- 226, 221, 223, 231, 232, 227, 228, nil, 208, 209,
- nil, nil, 229, 230, 273, nil, nil, 204, nil, nil,
- 52, 53, nil, nil, 54, nil, nil, nil, 212, nil,
- 218, nil, 214, 213, 210, 211, 222, 220, 216, nil,
- 217, nil, nil, 79, 72, 74, 75, 76, 77, nil,
- nil, nil, 73, 78, 62, 63, 64, 233, 51, nil,
- nil, nil, 56, 57, nil, nil, nil, 60, nil, 58,
- 59, 61, 246, 247, 65, 66, nil, nil, nil, nil,
- 245, 275, 279, 88, 87, 89, 90, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 41, nil, nil, 92,
- 91, 82, 50, 84, 83, 86, 85, 93, 94, nil,
- 80, 81, nil, 38, 39, 37, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 200, nil, nil, 204, 469,
- nil, 52, 53, nil, nil, 54, nil, nil, nil, nil,
- nil, 40, nil, nil, nil, nil, nil, nil, nil, 207,
- nil, nil, nil, nil, 79, 72, 74, 75, 76, 77,
- nil, nil, nil, 73, 78, 62, 63, 64, nil, 51,
- nil, nil, nil, 56, 57, nil, nil, nil, 60, nil,
- 58, 59, 61, 246, 247, 65, 66, nil, nil, nil,
- nil, 245, 275, 279, 88, 87, 89, 90, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 41, nil, nil,
- 92, 91, 82, 50, 84, 83, 86, 85, 93, 94,
- nil, 80, 81, nil, 38, 39, 37, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 200, nil, nil, 204,
- nil, nil, 52, 53, nil, nil, 54, nil, nil, nil,
- nil, nil, 40, nil, nil, nil, nil, nil, nil, nil,
- 207, nil, nil, nil, nil, 79, 72, 74, 75, 76,
- 77, nil, nil, nil, 73, 78, 62, 63, 64, nil,
- 51, nil, nil, nil, 56, 57, nil, nil, nil, 60,
- nil, 58, 59, 61, 23, 24, 65, 66, nil, nil,
- nil, nil, 22, 28, 27, 88, 87, 89, 90, nil,
- nil, 17, nil, nil, nil, nil, nil, nil, 41, nil,
- nil, 92, 91, 82, 50, 84, 83, 86, 85, 93,
- 94, nil, 80, 81, nil, 38, 39, 37, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 200, nil, nil,
- 204, nil, nil, 52, 53, nil, nil, 54, nil, nil,
- nil, nil, nil, 40, nil, nil, nil, nil, nil, nil,
- nil, 18, nil, nil, nil, nil, 79, 72, 74, 75,
- 76, 77, nil, nil, nil, 73, 78, 62, 63, 64,
- nil, 51, nil, nil, nil, 56, 57, nil, nil, nil,
- 60, nil, 58, 59, 61, 23, 24, 65, 66, nil,
- nil, nil, nil, 22, 28, 27, 88, 87, 89, 90,
- nil, nil, 17, nil, nil, nil, nil, nil, nil, 41,
- nil, nil, 92, 91, 82, 50, 84, 83, 86, 85,
- 93, 94, nil, 80, 81, nil, 38, 39, 37, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 200, nil,
- nil, 204, nil, nil, 52, 53, nil, nil, 54, nil,
- nil, nil, nil, nil, 40, nil, nil, nil, nil, nil,
- nil, nil, 18, nil, nil, nil, nil, 79, 72, 74,
- 75, 76, 77, nil, nil, nil, 73, 78, 62, 63,
- 64, nil, 51, nil, nil, nil, 56, 57, nil, nil,
- nil, 60, nil, 58, 59, 61, 23, 24, 65, 66,
- nil, nil, nil, nil, 22, 28, 27, 88, 87, 89,
- 90, nil, nil, 17, nil, nil, nil, nil, nil, nil,
- 41, nil, nil, 92, 91, 82, 50, 84, 83, 86,
- 85, 93, 94, nil, 80, 81, nil, 38, 39, 37,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 200,
- nil, nil, 204, nil, nil, 52, 53, nil, nil, 54,
- nil, nil, nil, nil, nil, 40, nil, nil, nil, nil,
- nil, nil, nil, 18, nil, nil, nil, nil, 79, 72,
- 74, 75, 76, 77, nil, nil, nil, 73, 78, 62,
- 63, 64, nil, 51, nil, nil, nil, 56, 57, nil,
- nil, nil, 60, nil, 58, 59, 61, 23, 24, 65,
- 66, nil, nil, nil, nil, 22, 28, 27, 88, 87,
- 89, 90, nil, nil, 17, nil, nil, nil, nil, nil,
- nil, 41, nil, nil, 92, 91, 82, 50, 84, 83,
- 86, 85, 93, 94, nil, 80, 81, nil, 38, 39,
- 37, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 200, nil, nil, 204, nil, nil, 52, 53, nil, nil,
- 54, nil, nil, nil, nil, nil, 40, nil, nil, nil,
- nil, nil, nil, nil, 18, nil, nil, nil, nil, 79,
- 72, 74, 75, 76, 77, nil, nil, nil, 73, 78,
- 153, 164, 154, 177, 150, 170, 160, 159, 180, 181,
- 175, 158, 157, 152, 178, 182, 183, 162, 151, 165,
- 169, 171, 163, 156, nil, nil, 172, 179, 174, 173,
- 166, 176, 161, 149, 168, 167, nil, nil, nil, nil,
- nil, 148, 155, 146, 147, 144, 145, 109, 111, nil,
- nil, 110, nil, nil, nil, nil, nil, nil, nil, 139,
- 140, nil, 137, 121, 122, 123, nil, 126, 128, nil,
- nil, 124, nil, nil, nil, nil, 141, 142, 129, 130,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 134, 133, nil, 120, 138, 136, 135,
- 131, 132, 127, 125, 118, nil, 119, nil, nil, 143,
- 79, nil, nil, 62, 63, 64, nil, 51, nil, nil,
- 78, 56, 57, nil, nil, nil, 60, nil, 58, 59,
- 61, 246, 247, 65, 66, nil, nil, nil, nil, 245,
- 275, 279, 88, 87, 89, 90, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 41, nil, nil, 92, 91,
- 82, 50, 84, 83, 86, 85, 93, 94, nil, 80,
- 81, nil, 38, 39, 37, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 200, nil, nil, 204, nil, nil,
- 52, 53, nil, nil, 54, nil, nil, nil, nil, nil,
- 40, nil, nil, nil, nil, nil, nil, nil, 207, nil,
- nil, nil, nil, 79, 72, 74, 75, 76, 77, nil,
- nil, nil, 73, 78, -249, -249, -249, nil, -249, nil,
- nil, nil, -249, -249, nil, nil, nil, -249, nil, -249,
- -249, -249, -249, -249, -249, -249, nil, nil, nil, nil,
- -249, -249, -249, -249, -249, -249, -249, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, -249, nil, nil, -249,
- -249, -249, -249, -249, -249, -249, -249, -249, -249, nil,
- -249, -249, nil, -249, -249, -249, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, -249, nil, nil, -249, 254,
- nil, -249, -249, nil, nil, -249, nil, -249, nil, -249,
- nil, -249, nil, nil, nil, nil, nil, nil, nil, -249,
- nil, nil, nil, nil, -249, -249, -249, -249, -249, -249,
- nil, nil, nil, -249, -249, -478, -478, -478, nil, -478,
- nil, nil, nil, -478, -478, nil, nil, nil, -478, nil,
- -478, -478, -478, -478, -478, -478, -478, nil, nil, nil,
- nil, -478, -478, -478, -478, -478, -478, -478, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, -478, nil, nil,
- -478, -478, -478, -478, -478, -478, -478, -478, -478, -478,
- nil, -478, -478, nil, -478, -478, -478, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, -478, nil, nil, -478,
- -478, nil, -478, -478, nil, nil, -478, nil, -478, nil,
- -478, nil, -478, nil, nil, nil, nil, nil, nil, nil,
- -478, nil, nil, nil, nil, -478, -478, -478, -478, -478,
- -478, nil, nil, nil, -478, -478, -479, -479, -479, nil,
- -479, nil, nil, nil, -479, -479, nil, nil, nil, -479,
- nil, -479, -479, -479, -479, -479, -479, -479, nil, nil,
- nil, nil, -479, -479, -479, -479, -479, -479, -479, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, -479, nil,
- nil, -479, -479, -479, -479, -479, -479, -479, -479, -479,
- -479, nil, -479, -479, nil, -479, -479, -479, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, -479, nil, nil,
- -479, -479, nil, -479, -479, nil, nil, -479, nil, -479,
- nil, -479, nil, -479, nil, nil, nil, nil, nil, nil,
- nil, -479, nil, nil, nil, nil, -479, -479, -479, -479,
- -479, -479, nil, nil, nil, -479, -479, 62, 63, 64,
- nil, 51, nil, nil, nil, 56, 57, nil, nil, nil,
- 60, nil, 58, 59, 61, 246, 247, 65, 66, nil,
- nil, nil, nil, 245, 28, 27, 88, 87, 89, 90,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 41,
- nil, nil, 92, 91, 82, 50, 84, 83, 86, 85,
- 93, 94, nil, 80, 81, nil, 38, 39, 37, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 200, nil,
- nil, 204, nil, nil, 52, 53, nil, nil, 54, nil,
- 299, nil, nil, nil, 40, nil, nil, nil, nil, nil,
- nil, nil, 207, nil, nil, nil, nil, 79, 72, 74,
- 75, 76, 77, nil, nil, nil, 73, 78, 62, 63,
- 64, nil, 51, nil, nil, nil, 56, 57, nil, nil,
- nil, 60, nil, 58, 59, 61, 246, 247, 65, 66,
- nil, nil, nil, nil, 245, 275, 279, 88, 87, 89,
- 90, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 41, nil, nil, 92, 91, 82, 50, 84, 83, 86,
- 85, 93, 94, nil, 80, 81, nil, 38, 39, 37,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 200,
- nil, nil, 204, nil, nil, 52, 53, nil, nil, 54,
- nil, nil, nil, nil, nil, 40, nil, nil, nil, nil,
- nil, nil, nil, 207, nil, nil, nil, nil, 79, 72,
- 74, 75, 76, 77, nil, nil, nil, 73, 78, 62,
- 63, 64, nil, 51, nil, nil, nil, 56, 57, nil,
- nil, nil, 60, nil, 58, 59, 61, 246, 247, 65,
- 66, nil, nil, nil, nil, 245, 275, 279, 88, 87,
- 89, 90, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 41, nil, nil, 92, 91, 82, 50, 84, 83,
- 86, 85, 93, 94, nil, 80, 81, nil, 38, 39,
- 37, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 200, nil, nil, 204, nil, nil, 52, 53, nil, nil,
- 54, nil, nil, nil, nil, nil, 40, nil, nil, nil,
- nil, nil, nil, nil, 207, nil, nil, nil, nil, 79,
- 72, 74, 75, 76, 77, nil, nil, nil, 73, 78,
- 62, 63, 64, nil, 51, nil, nil, nil, 56, 57,
- nil, nil, nil, 60, nil, 58, 59, 61, 246, 247,
- 65, 66, nil, nil, nil, nil, 245, 275, 279, 88,
- 87, 89, 90, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 41, nil, nil, 92, 91, 82, 50, 84,
- 83, 86, 85, 93, 94, nil, 80, 81, nil, 38,
- 39, 37, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 200, nil, nil, 204, nil, nil, 52, 53, nil,
- nil, 54, nil, nil, nil, nil, nil, 40, nil, nil,
- nil, nil, nil, nil, nil, 207, nil, nil, nil, nil,
- 79, 72, 74, 75, 76, 77, nil, nil, nil, 73,
- 78, 62, 63, 64, nil, 51, nil, nil, nil, 56,
- 57, nil, nil, nil, 60, nil, 58, 59, 61, 246,
- 247, 65, 66, nil, nil, nil, nil, 245, 275, 279,
- 88, 87, 89, 90, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 41, nil, nil, 92, 91, 82, 50,
- 84, 83, 86, 85, 93, 94, nil, 80, 81, nil,
- 38, 39, 37, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 200, nil, nil, 204, nil, nil, 52, 53,
- nil, nil, 54, nil, 560, nil, 243, nil, 40, nil,
- nil, nil, nil, nil, nil, nil, 207, nil, nil, nil,
- nil, 79, 72, 74, 75, 76, 77, nil, nil, nil,
- 73, 78, 62, 63, 64, nil, 51, nil, nil, nil,
- 56, 57, nil, nil, nil, 60, nil, 58, 59, 61,
- 246, 247, 65, 66, nil, nil, nil, nil, 245, 275,
- 279, 88, 87, 89, 90, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 41, nil, nil, 92, 91, 82,
- 50, 84, 83, 86, 85, 93, 94, nil, 80, 81,
- nil, 38, 39, 37, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 200, nil, nil, 204, nil, nil, 52,
- 53, nil, nil, 54, nil, 564, nil, 243, nil, 40,
- nil, nil, nil, nil, nil, nil, nil, 207, nil, nil,
- nil, nil, 79, 72, 74, 75, 76, 77, nil, nil,
- nil, 73, 78, 62, 63, 64, nil, 51, nil, nil,
- nil, 56, 57, nil, nil, nil, 60, nil, 58, 59,
- 61, 246, 247, 65, 66, nil, nil, nil, nil, 245,
- 275, 279, 88, 87, 89, 90, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 41, nil, nil, 92, 91,
- 82, 50, 84, 83, 86, 85, 93, 94, nil, 80,
- 81, nil, 38, 39, 37, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 200, nil, nil, 204, nil, nil,
- 52, 53, nil, nil, 54, nil, nil, nil, nil, nil,
- 40, nil, nil, nil, nil, nil, nil, nil, 207, nil,
- nil, nil, nil, 79, 72, 74, 75, 76, 77, nil,
- nil, nil, 73, 78, 62, 63, 64, nil, 51, nil,
- nil, nil, 56, 57, nil, nil, nil, 60, nil, 58,
- 59, 61, 23, 24, 65, 66, nil, nil, nil, nil,
- 22, 28, 27, 88, 87, 89, 90, nil, nil, 17,
- nil, nil, nil, nil, nil, nil, 41, nil, nil, 92,
- 91, 82, 50, 84, 83, 86, 85, 93, 94, nil,
- 80, 81, nil, 38, 39, 37, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 200, nil, nil, 204, nil,
- nil, 52, 53, nil, nil, 54, nil, 584, nil, 243,
- nil, 40, nil, nil, nil, nil, nil, nil, nil, 18,
- nil, nil, nil, nil, 79, 72, 74, 75, 76, 77,
- nil, nil, nil, 73, 78, 62, 63, 64, nil, 51,
- nil, nil, nil, 56, 57, nil, nil, nil, 60, nil,
- 58, 59, 61, 246, 247, 65, 66, nil, nil, nil,
- nil, 245, 28, 27, 88, 87, 89, 90, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 41, nil, nil,
- 92, 91, 82, 50, 84, 83, 86, 85, 93, 94,
- nil, 80, 81, nil, 38, 39, 37, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 200, nil, nil, 204,
- nil, nil, 52, 53, nil, nil, 54, nil, 299, nil,
- nil, nil, 40, nil, nil, nil, nil, nil, nil, nil,
- 207, nil, nil, nil, nil, 79, 72, 74, 75, 76,
- 77, nil, nil, nil, 73, 78, 62, 63, 64, nil,
- 51, nil, nil, nil, 56, 57, nil, nil, nil, 60,
- nil, 58, 59, 61, 246, 247, 65, 66, nil, nil,
- nil, nil, 245, 275, 279, 88, 87, 89, 90, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 41, nil,
- nil, 92, 91, 82, 50, 84, 83, 86, 85, 93,
- 94, nil, 80, 81, nil, 38, 39, 37, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 200, nil, nil,
- 204, nil, nil, 52, 53, nil, nil, 54, nil, nil,
- nil, nil, nil, 40, nil, nil, nil, nil, nil, nil,
- nil, 207, nil, nil, nil, nil, 79, 72, 74, 75,
- 76, 77, nil, nil, nil, 73, 78, 62, 63, 64,
- nil, 51, nil, nil, nil, 56, 57, nil, nil, nil,
- 60, nil, 58, 59, 61, 246, 247, 65, 66, nil,
- nil, nil, nil, 245, 275, 279, 88, 87, 89, 90,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 41,
- nil, nil, 92, 91, 82, 50, 84, 83, 86, 85,
- 93, 94, nil, 80, 81, nil, 38, 39, 37, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 200, nil,
- nil, 204, nil, nil, 52, 53, nil, nil, 54, nil,
- nil, nil, nil, nil, 40, nil, nil, nil, nil, nil,
- nil, nil, 207, nil, nil, nil, nil, 79, 72, 74,
- 75, 76, 77, nil, nil, nil, 73, 78, 62, 63,
- 64, nil, 51, nil, nil, nil, 56, 57, nil, nil,
- nil, 60, nil, 58, 59, 61, 246, 247, 65, 66,
- nil, nil, nil, nil, 245, 275, 279, 88, 87, 89,
- 90, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 41, nil, nil, 92, 91, 82, 50, 84, 83, 86,
- 85, 93, 94, nil, 80, 81, nil, 38, 39, 37,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 200,
- nil, nil, 204, nil, nil, 52, 53, nil, nil, 54,
- nil, nil, nil, nil, nil, 40, nil, nil, nil, nil,
- nil, nil, nil, 207, nil, nil, nil, nil, 79, 72,
- 74, 75, 76, 77, nil, nil, nil, 73, 78, 62,
- 63, 64, nil, 51, nil, nil, nil, 56, 57, nil,
- nil, nil, 60, nil, 58, 59, 61, 23, 24, 65,
- 66, nil, nil, nil, nil, 22, 28, 27, 88, 87,
- 89, 90, nil, nil, 17, nil, nil, nil, nil, nil,
- nil, 41, nil, nil, 92, 91, 82, 50, 84, 83,
- 86, 85, 93, 94, nil, 80, 81, nil, 38, 39,
- 37, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 200, nil, nil, 204, nil, nil, 52, 53, nil, nil,
- 54, nil, nil, nil, nil, nil, 40, nil, nil, nil,
- nil, nil, nil, nil, 18, nil, nil, nil, nil, 79,
- 72, 74, 75, 76, 77, nil, nil, nil, 73, 78,
- 62, 63, 64, nil, 51, nil, nil, nil, 56, 57,
- nil, nil, nil, 60, nil, 58, 59, 61, 246, 247,
- 65, 66, nil, nil, nil, nil, 245, 275, 279, 88,
- 87, 89, 90, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 41, nil, nil, 92, 91, 82, 50, 84,
- 83, 86, 85, 93, 94, nil, 80, 81, nil, 38,
- 39, 37, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 200, nil, nil, 204, nil, nil, 52, 53, nil,
- nil, 54, nil, 369, nil, nil, nil, 40, nil, nil,
- nil, nil, nil, nil, nil, 207, nil, nil, nil, nil,
- 79, 72, 74, 75, 76, 77, nil, nil, nil, 73,
- 78, 62, 63, 64, nil, 51, nil, nil, nil, 56,
- 57, nil, nil, nil, 60, nil, 58, 59, 61, 246,
- 247, 65, 66, nil, nil, nil, nil, 245, 275, 279,
- 88, 87, 89, 90, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 41, nil, nil, 92, 91, 82, 50,
- 84, 83, 86, 85, 93, 94, nil, 80, 81, nil,
- 38, 39, 37, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 200, nil, nil, 204, nil, nil, 52, 53,
- nil, nil, 54, nil, 612, nil, nil, nil, 40, nil,
- nil, nil, nil, nil, nil, nil, 207, nil, nil, nil,
- nil, 79, 72, 74, 75, 76, 77, nil, nil, nil,
- 73, 78, 62, 63, 64, nil, 51, nil, nil, nil,
- 56, 57, nil, nil, nil, 60, nil, 58, 59, 61,
- 246, 247, 65, 66, nil, nil, nil, nil, 245, 275,
- 279, 88, 87, 89, 90, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 41, nil, nil, 92, 91, 82,
- 50, 84, 83, 86, 85, 93, 94, nil, 80, 81,
- nil, 38, 39, 37, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 200, nil, nil, 204, nil, nil, 52,
- 53, nil, nil, 54, nil, nil, nil, nil, nil, 40,
- nil, nil, nil, nil, nil, nil, nil, 207, nil, nil,
- nil, nil, 79, 72, 74, 75, 76, 77, nil, nil,
- nil, 73, 78, 62, 63, 64, nil, 51, nil, nil,
- nil, 56, 57, nil, nil, nil, 60, nil, 58, 59,
- 61, 246, 247, 65, 66, nil, nil, nil, nil, 245,
- 275, 279, 88, 87, 89, 90, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 41, nil, nil, 92, 91,
- 82, 50, 84, 83, 86, 85, 93, 94, nil, 80,
- 81, nil, 38, 39, 37, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 200, nil, nil, 204, nil, nil,
- 52, 53, nil, nil, 54, nil, nil, nil, nil, nil,
- 40, nil, nil, nil, nil, nil, nil, nil, 207, nil,
- nil, nil, nil, 79, 72, 74, 75, 76, 77, nil,
- nil, nil, 73, 78, 62, 63, 64, nil, 51, nil,
- nil, nil, 56, 57, nil, nil, nil, 60, nil, 58,
- 59, 61, 246, 247, 65, 66, nil, nil, nil, nil,
- 245, 275, 279, 88, 87, 89, 90, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 41, nil, nil, 92,
- 91, 82, 50, 84, 83, 86, 85, 93, 94, nil,
- 80, 81, nil, 38, 39, 37, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 200, nil, nil, 204, nil,
- nil, 52, 53, nil, nil, 54, nil, 628, nil, nil,
- nil, 40, nil, nil, nil, nil, nil, nil, nil, 207,
- nil, nil, nil, nil, 79, 72, 74, 75, 76, 77,
- nil, nil, nil, 73, 78, 62, 63, 64, nil, 51,
- nil, nil, nil, 56, 57, nil, nil, nil, 60, nil,
- 58, 59, 61, 246, 247, 65, 66, nil, nil, nil,
- nil, 245, 28, 27, 88, 87, 89, 90, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 41, nil, nil,
- 92, 91, 82, 50, 84, 83, 86, 85, 93, 94,
- nil, 80, 81, nil, 38, 39, 37, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 200, nil, nil, 204,
- nil, nil, 52, 53, nil, nil, 54, nil, 299, nil,
- nil, nil, 40, nil, nil, nil, nil, nil, nil, nil,
- 207, nil, nil, nil, nil, 79, 72, 74, 75, 76,
- 77, nil, nil, nil, 73, 78, 62, 63, 64, nil,
- 51, nil, nil, nil, 56, 57, nil, nil, nil, 60,
- nil, 58, 59, 61, 246, 247, 65, 66, nil, nil,
- nil, nil, 245, 28, 27, 88, 87, 89, 90, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 41, nil,
- nil, 92, 91, 82, 50, 84, 83, 86, 85, 93,
- 94, nil, 80, 81, nil, 38, 39, 37, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 200, nil, nil,
- 204, nil, nil, 52, 53, nil, nil, 54, nil, 299,
- nil, nil, nil, 40, nil, nil, nil, nil, nil, nil,
- nil, 207, nil, nil, nil, nil, 79, 72, 74, 75,
- 76, 77, nil, nil, nil, 73, 78, 62, 63, 64,
- nil, 51, nil, nil, nil, 56, 57, nil, nil, nil,
- 60, nil, 58, 59, 61, 23, 24, 65, 66, nil,
- nil, nil, nil, 22, 28, 27, 88, 87, 89, 90,
- nil, nil, 17, nil, nil, nil, nil, nil, nil, 41,
- nil, nil, 92, 91, 82, 50, 84, 83, 86, 85,
- 93, 94, nil, 80, 81, nil, 38, 39, 37, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 200, nil,
- nil, 204, nil, nil, 52, 53, nil, nil, 54, nil,
- nil, nil, nil, nil, 40, nil, nil, nil, nil, nil,
- nil, nil, 18, nil, nil, nil, nil, 79, 72, 74,
- 75, 76, 77, nil, nil, nil, 73, 78, 153, 164,
- 154, 177, 150, 170, 160, 159, 180, 181, 175, 158,
- 157, 152, 178, 182, 183, 162, 151, 165, 169, 171,
- 163, 156, nil, nil, 172, 179, 174, 173, 166, 176,
- 161, 149, 168, 167, nil, nil, nil, nil, nil, 148,
- 155, 146, 147, 144, 145, 109, 111, nil, nil, 110,
- nil, nil, nil, nil, nil, nil, nil, 139, 140, nil,
- 137, 121, 122, 123, nil, 126, 128, nil, nil, 124,
- nil, nil, nil, nil, 141, 142, 129, 130, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 134, 133, nil, 120, 138, 136, 135, 131, 132,
- 127, 125, 118, nil, 119, nil, nil, 143, 79, nil,
- nil, 62, 63, 64, nil, 51, nil, nil, 78, 56,
- 57, nil, nil, nil, 60, nil, 58, 59, 61, 246,
- 247, 65, 66, nil, nil, nil, nil, 245, 275, 279,
- 88, 87, 89, 90, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 41, nil, nil, 92, 91, 82, 50,
- 84, 83, 86, 85, 93, 94, nil, 80, 81, nil,
- 38, 39, 37, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 200, nil, nil, 204, nil, nil, 52, 53,
- nil, nil, 54, nil, nil, nil, nil, nil, 40, nil,
- nil, nil, nil, nil, nil, nil, 207, nil, nil, nil,
- nil, 79, 72, 74, 75, 76, 77, nil, nil, nil,
- 73, 78, 62, 63, 64, nil, 51, nil, nil, nil,
- 56, 57, nil, nil, nil, 60, nil, 58, 59, 61,
- 246, 247, 65, 66, nil, nil, nil, nil, 245, 275,
- 279, 88, 87, 89, 90, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 41, nil, nil, 92, 91, 82,
- 50, 84, 83, 86, 85, 93, 94, nil, 80, 81,
- nil, 38, 39, 37, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 200, nil, nil, 204, nil, nil, 52,
- 53, nil, nil, 54, nil, 679, nil, nil, nil, 40,
- nil, nil, nil, nil, nil, nil, nil, 207, nil, nil,
- nil, nil, 79, 72, 74, 75, 76, 77, nil, nil,
- nil, 73, 78, 62, 63, 64, nil, 51, nil, nil,
- nil, 56, 57, nil, nil, nil, 60, nil, 58, 59,
- 61, 23, 24, 65, 66, nil, nil, nil, nil, 22,
- 28, 27, 88, 87, 89, 90, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 41, nil, nil, 92, 91,
- 82, 50, 84, 83, 86, 85, 93, 94, nil, 80,
- 81, nil, 38, 39, 37, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 200, nil, nil, 204, nil, nil,
- 52, 53, nil, nil, 54, nil, nil, nil, nil, nil,
- 40, nil, nil, nil, nil, nil, nil, nil, 207, nil,
- nil, nil, nil, 79, 72, 74, 75, 76, 77, nil,
- nil, nil, 73, 78, 62, 63, 64, nil, 51, nil,
- nil, nil, 56, 57, nil, nil, nil, 60, nil, 58,
- 59, 61, 23, 24, 65, 66, nil, nil, nil, nil,
- 22, 28, 27, 88, 87, 89, 90, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 41, nil, nil, 92,
- 91, 82, 50, 84, 83, 86, 85, 93, 94, nil,
- 80, 81, nil, 38, 39, 37, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 200, nil, nil, 204, nil,
- nil, 52, 53, nil, nil, 54, nil, nil, nil, nil,
- nil, 40, nil, nil, nil, nil, nil, nil, nil, 207,
- nil, nil, nil, nil, 79, 72, 74, 75, 76, 77,
- nil, nil, nil, 73, 78, 62, 63, 64, nil, 51,
- nil, nil, nil, 56, 57, nil, nil, nil, 60, nil,
- 58, 59, 61, 23, 24, 65, 66, nil, nil, nil,
- nil, 22, 28, 27, 88, 87, 89, 90, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 41, nil, nil,
- 92, 91, 82, 50, 84, 83, 86, 85, 93, 94,
- nil, 80, 81, nil, 38, 39, 37, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 200, nil, nil, 204,
- nil, nil, 52, 53, nil, nil, 54, nil, nil, nil,
- nil, nil, 40, nil, nil, nil, nil, nil, nil, nil,
- 207, nil, nil, nil, nil, 79, 72, 74, 75, 76,
- 77, nil, nil, nil, 73, 78, 62, 63, 64, nil,
- 51, nil, nil, nil, 56, 57, nil, nil, nil, 60,
- nil, 58, 59, 61, 246, 247, 65, 66, nil, nil,
- nil, nil, 245, 275, 279, 88, 87, 89, 90, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 41, nil,
- nil, 92, 91, 82, 50, 84, 83, 86, 85, 93,
- 94, nil, 80, 81, nil, 38, 39, 37, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 200, nil, nil,
- 204, nil, nil, 52, 53, nil, nil, 54, nil, nil,
- nil, nil, nil, 40, nil, nil, nil, nil, nil, nil,
- nil, 207, nil, nil, nil, nil, 79, 72, 74, 75,
- 76, 77, nil, nil, nil, 73, 78, 62, 63, 64,
- nil, 51, nil, nil, nil, 56, 57, nil, nil, nil,
- 60, nil, 58, 59, 61, 246, 247, 65, 66, nil,
- nil, nil, nil, 245, 275, 279, 88, 87, 89, 90,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 41,
- nil, nil, 92, 91, 82, 50, 84, 83, 86, 85,
- 93, 94, nil, 80, 81, nil, 38, 39, 37, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 200, nil,
- nil, 204, nil, nil, 52, 53, nil, nil, 54, nil,
- nil, nil, nil, nil, 40, nil, nil, nil, nil, nil,
- nil, nil, 207, nil, nil, nil, nil, 79, 72, 74,
- 75, 76, 77, nil, nil, nil, 73, 78, 62, 63,
- 64, nil, 51, nil, nil, nil, 56, 57, nil, nil,
- nil, 60, nil, 58, 59, 61, 246, 247, 65, 66,
- nil, nil, nil, nil, 245, 275, 279, 88, 87, 89,
- 90, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 276, nil, nil, 92, 91, 82, 50, 84, 83, 86,
- 85, 93, 94, nil, 80, 81, nil, nil, nil, 280,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 273,
- nil, nil, 270, nil, nil, 52, 53, nil, nil, 54,
- nil, 697, nil, 698, nil, nil, nil, nil, nil, nil,
- nil, nil, 699, nil, nil, nil, nil, nil, 79, 72,
- 74, 75, 76, 77, nil, nil, nil, 73, 78, 62,
- 63, 64, nil, 51, nil, nil, nil, 56, 57, nil,
- nil, nil, 60, nil, 58, 59, 61, 246, 247, 65,
- 66, nil, nil, nil, nil, 245, 275, 279, 88, 87,
- 89, 90, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 41, nil, nil, 92, 91, 82, 50, 84, 83,
- 86, 85, 93, 94, nil, 80, 81, nil, 38, 39,
- 37, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 200, nil, nil, 204, nil, nil, 52, 53, nil, nil,
- 54, nil, nil, nil, nil, nil, 40, nil, nil, nil,
- nil, nil, nil, nil, 207, nil, nil, nil, nil, 79,
- 72, 74, 75, 76, 77, nil, nil, nil, 73, 78,
- 62, 63, 64, nil, 51, nil, nil, nil, 56, 57,
- nil, nil, nil, 60, nil, 58, 59, 61, 246, 247,
- 65, 66, nil, nil, nil, nil, 245, 275, 279, 88,
- 87, 89, 90, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 41, nil, nil, 92, 91, 82, 50, 84,
- 83, 86, 85, 93, 94, nil, 80, 81, nil, 38,
- 39, 37, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 200, nil, nil, 204, nil, nil, 52, 53, nil,
- nil, 54, nil, nil, nil, nil, nil, 40, nil, nil,
- nil, nil, nil, nil, nil, 207, nil, nil, nil, nil,
- 79, 72, 74, 75, 76, 77, nil, nil, nil, 73,
- 78, 62, 63, 64, nil, 51, nil, nil, nil, 56,
- 57, nil, nil, nil, 60, nil, 58, 59, 61, 246,
- 247, 65, 66, nil, nil, nil, nil, 245, 28, 27,
- 88, 87, 89, 90, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 41, nil, nil, 92, 91, 82, 50,
- 84, 83, 86, 85, 93, 94, nil, 80, 81, nil,
- 38, 39, 37, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 200, nil, nil, 204, nil, nil, 52, 53,
- nil, nil, 54, nil, 560, nil, 243, nil, 40, nil,
- nil, nil, nil, nil, nil, nil, 207, nil, nil, nil,
- nil, 79, 72, 74, 75, 76, 77, nil, nil, nil,
- 73, 78, 62, 63, 64, nil, 51, nil, nil, nil,
- 56, 57, nil, nil, nil, 60, nil, 58, 59, 61,
- 246, 247, 65, 66, nil, nil, nil, nil, 245, 275,
- 279, 88, 87, 89, 90, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 41, nil, nil, 92, 91, 82,
- 50, 84, 83, 86, 85, 93, 94, nil, 80, 81,
- nil, 38, 39, 37, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 200, nil, nil, 204, nil, nil, 52,
- 53, nil, nil, 54, nil, nil, nil, nil, nil, 40,
- nil, nil, nil, nil, nil, nil, nil, 207, nil, nil,
- nil, nil, 79, 72, 74, 75, 76, 77, nil, nil,
- nil, 73, 78, 62, 63, 64, nil, 51, nil, nil,
- nil, 56, 57, nil, nil, nil, 60, nil, 58, 59,
- 61, 246, 247, 65, 66, nil, nil, nil, nil, 245,
- 275, 279, 88, 87, 89, 90, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 41, nil, nil, 92, 91,
- 82, 50, 84, 83, 86, 85, 93, 94, nil, 80,
- 81, nil, 38, 39, 37, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 200, nil, nil, 204, nil, nil,
- 52, 53, nil, nil, 54, nil, nil, nil, nil, nil,
- 40, nil, nil, nil, nil, nil, nil, nil, 207, nil,
- nil, nil, nil, 79, 72, 74, 75, 76, 77, nil,
- nil, nil, 73, 78, 62, 63, 64, nil, 51, nil,
- nil, nil, 56, 57, nil, nil, nil, 60, nil, 58,
- 59, 61, 246, 247, 65, 66, nil, nil, nil, nil,
- 245, 275, 279, 88, 87, 89, 90, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 41, nil, nil, 92,
- 91, 82, 50, 84, 83, 86, 85, 93, 94, nil,
- 80, 81, nil, 38, 39, 37, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 200, nil, nil, 204, nil,
- nil, 52, 53, nil, nil, 54, nil, nil, nil, nil,
- nil, 40, nil, nil, nil, nil, nil, nil, nil, 207,
- nil, nil, nil, nil, 79, 72, 74, 75, 76, 77,
- nil, nil, nil, 73, 78, 62, 63, 64, nil, 51,
- nil, nil, nil, 56, 57, nil, nil, nil, 60, nil,
- 58, 59, 61, 23, 24, 65, 66, nil, nil, nil,
- nil, 22, 28, 27, 88, 87, 89, 90, nil, nil,
- 17, nil, nil, nil, nil, nil, nil, 41, nil, nil,
- 92, 91, 82, 50, 84, 83, 86, 85, 93, 94,
- nil, 80, 81, nil, 38, 39, 37, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 200, nil, nil, 204,
- nil, nil, 52, 53, nil, nil, 54, nil, nil, nil,
- nil, nil, 40, nil, nil, nil, nil, nil, nil, nil,
- 18, nil, nil, nil, nil, 79, 72, 74, 75, 76,
- 77, nil, nil, nil, 73, 78, 62, 63, 64, nil,
- 51, nil, nil, nil, 56, 57, nil, nil, nil, 60,
- nil, 58, 59, 61, 246, 247, 65, 66, nil, nil,
- nil, nil, 245, 275, 279, 88, 87, 89, 90, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 41, nil,
- nil, 92, 91, 82, 50, 84, 83, 86, 85, 93,
- 94, nil, 80, 81, nil, 38, 39, 37, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 200, nil, nil,
- 204, nil, nil, 52, 53, nil, nil, 54, nil, nil,
- nil, nil, nil, 40, nil, nil, nil, nil, nil, nil,
- nil, 207, nil, nil, nil, nil, 79, 72, 74, 75,
- 76, 77, nil, nil, nil, 73, 78, 62, 63, 64,
- nil, 51, nil, nil, nil, 56, 57, nil, nil, nil,
- 60, nil, 58, 59, 61, 23, 24, 65, 66, nil,
- nil, nil, nil, 22, 28, 27, 88, 87, 89, 90,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 41,
- nil, nil, 92, 91, 82, 50, 84, 83, 86, 85,
- 93, 94, nil, 80, 81, nil, 38, 39, 37, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 200, nil,
- nil, 204, nil, nil, 52, 53, nil, nil, 54, nil,
- nil, nil, nil, nil, 40, nil, nil, nil, nil, nil,
- nil, nil, 207, nil, nil, nil, nil, 79, 72, 74,
- 75, 76, 77, nil, nil, nil, 73, 78, 62, 63,
- 64, nil, 51, nil, nil, nil, 56, 57, nil, nil,
- nil, 60, nil, 58, 59, 61, 246, 247, 65, 66,
- nil, nil, nil, nil, 245, 275, 279, 88, 87, 89,
- 90, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 41, nil, nil, 92, 91, 82, 50, 84, 83, 86,
- 85, 93, 94, nil, 80, 81, nil, 38, 39, 37,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 200,
- nil, nil, 204, nil, nil, 52, 53, nil, nil, 54,
- nil, nil, nil, nil, nil, 40, nil, nil, nil, nil,
- nil, nil, nil, 207, nil, nil, nil, nil, 79, 72,
- 74, 75, 76, 77, nil, nil, nil, 73, 78, 62,
- 63, 64, nil, 51, nil, nil, nil, 56, 57, nil,
- nil, nil, 60, nil, 58, 59, 61, 246, 247, 65,
- 66, nil, nil, nil, nil, 245, 275, 279, 88, 87,
- 89, 90, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 41, nil, nil, 92, 91, 82, 50, 84, 83,
- 86, 85, 93, 94, nil, 80, 81, nil, 38, 39,
- 37, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 200, nil, nil, 204, nil, nil, 52, 53, nil, nil,
- 54, nil, nil, nil, nil, nil, 40, nil, nil, nil,
- nil, nil, nil, nil, 207, nil, nil, nil, nil, 79,
- 72, 74, 75, 76, 77, nil, nil, nil, 73, 78,
- 62, 63, 64, nil, 51, nil, nil, nil, 56, 57,
- nil, nil, nil, 60, nil, 58, 59, 61, 246, 247,
- 65, 66, nil, nil, nil, nil, 245, 275, 279, 88,
- 87, 89, 90, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 41, nil, nil, 92, 91, 82, 50, 84,
- 83, 86, 85, 93, 94, nil, 80, 81, nil, 38,
- 39, 37, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 200, nil, nil, 204, nil, nil, 52, 53, nil,
- nil, 54, nil, nil, nil, nil, nil, 40, nil, nil,
- nil, nil, nil, nil, nil, 207, nil, nil, nil, nil,
- 79, 72, 74, 75, 76, 77, nil, nil, nil, 73,
- 78, 62, 63, 64, nil, 51, nil, nil, nil, 56,
- 57, nil, nil, nil, 60, nil, 58, 59, 61, 246,
- 247, 65, 66, nil, nil, nil, nil, 245, 275, 279,
- 88, 87, 89, 90, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 276, nil, nil, 92, 91, 82, 50,
- 84, 83, 86, 85, 93, 94, nil, 80, 81, nil,
- nil, nil, 280, nil, 215, 219, 224, 225, 226, 221,
- 223, 231, 232, 227, 228, nil, 208, 209, nil, nil,
- 229, 230, 772, nil, nil, 204, nil, nil, 52, 53,
- nil, nil, 54, nil, nil, nil, 212, nil, 218, nil,
- 214, 213, 210, 211, 222, 220, 216, nil, 217, nil,
- nil, 79, 72, 74, 75, 76, 77, nil, nil, nil,
- 73, 78, 62, 63, 64, 233, 51, nil, nil, nil,
- 56, 57, nil, nil, nil, 60, nil, 58, 59, 61,
- 246, 247, 65, 66, nil, nil, nil, nil, 245, 275,
- 279, 88, 87, 89, 90, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 41, nil, nil, 92, 91, 82,
- 50, 84, 83, 86, 85, 93, 94, nil, 80, 81,
- nil, 38, 39, 37, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 200, nil, nil, 204, nil, nil, 52,
- 53, nil, nil, 54, nil, 780, nil, 243, nil, 40,
- nil, nil, nil, nil, nil, nil, nil, 207, nil, nil,
- nil, nil, 79, 72, 74, 75, 76, 77, nil, nil,
- nil, 73, 78, 62, 63, 64, nil, 51, nil, nil,
- nil, 56, 57, nil, nil, nil, 60, nil, 58, 59,
- 61, 246, 247, 65, 66, nil, nil, nil, nil, 245,
- 275, 279, 88, 87, 89, 90, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 41, nil, nil, 92, 91,
- 82, 50, 84, 83, 86, 85, 93, 94, nil, 80,
- 81, nil, 38, 39, 37, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 200, nil, nil, 204, nil, nil,
- 52, 53, nil, nil, 54, nil, 786, nil, 243, nil,
- 40, nil, nil, nil, nil, nil, nil, nil, 207, nil,
- nil, nil, nil, 79, 72, 74, 75, 76, 77, nil,
- nil, nil, 73, 78, 62, 63, 64, nil, 51, nil,
- nil, nil, 56, 57, nil, nil, nil, 60, nil, 58,
- 59, 61, 246, 247, 65, 66, nil, nil, nil, nil,
- 245, 275, 279, 88, 87, 89, 90, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 41, nil, nil, 92,
- 91, 82, 50, 84, 83, 86, 85, 93, 94, nil,
- 80, 81, nil, 38, 39, 37, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 200, nil, nil, 204, nil,
- nil, 52, 53, nil, nil, 54, nil, 788, nil, 243,
- nil, 40, nil, nil, nil, nil, nil, nil, nil, 207,
- nil, nil, nil, nil, 79, 72, 74, 75, 76, 77,
- nil, nil, nil, 73, 78, 62, 63, 64, nil, 51,
- nil, nil, nil, 56, 57, nil, nil, nil, 60, nil,
- 58, 59, 61, 246, 247, 65, 66, nil, nil, nil,
- nil, 245, 275, 279, 88, 87, 89, 90, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 276, nil, nil,
- 92, 91, 82, 50, 84, 83, 86, 85, 93, 94,
- nil, 80, 81, nil, nil, nil, 280, nil, 215, 219,
- 224, 225, 226, 221, 223, 231, 232, 227, 228, nil,
- 208, 209, nil, nil, 229, 230, 772, nil, nil, 204,
- nil, nil, 52, 53, nil, nil, 54, nil, nil, nil,
- 212, nil, 218, nil, 214, 213, 210, 211, 222, 220,
- 216, nil, 217, nil, nil, 79, 72, 74, 75, 76,
- 77, nil, nil, nil, 73, 78, 62, 63, 64, 233,
- 51, nil, nil, nil, 56, 57, nil, nil, nil, 60,
- nil, 58, 59, 61, 23, 24, 65, 66, nil, nil,
- nil, nil, 22, 28, 27, 88, 87, 89, 90, nil,
- nil, 17, nil, nil, nil, nil, nil, nil, 41, nil,
- nil, 92, 91, 82, 50, 84, 83, 86, 85, 93,
- 94, nil, 80, 81, nil, 38, 39, 37, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 200, nil, nil,
- 204, nil, nil, 52, 53, nil, nil, 54, nil, nil,
- nil, nil, nil, 40, nil, nil, nil, nil, nil, nil,
- nil, 18, nil, nil, nil, nil, 79, 72, 74, 75,
- 76, 77, nil, nil, nil, 73, 78, 62, 63, 64,
- nil, 51, nil, nil, nil, 56, 57, nil, nil, nil,
- 60, nil, 58, 59, 61, 246, 247, 65, 66, nil,
- nil, nil, nil, 245, 275, 279, 88, 87, 89, 90,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 41,
- nil, nil, 92, 91, 82, 50, 84, 83, 86, 85,
- 93, 94, nil, 80, 81, nil, 38, 39, 37, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 200, nil,
- nil, 204, nil, nil, 52, 53, nil, nil, 54, nil,
- 802, nil, nil, nil, 40, nil, nil, nil, nil, nil,
- nil, nil, 207, nil, nil, nil, nil, 79, 72, 74,
- 75, 76, 77, nil, nil, nil, 73, 78, 62, 63,
- 64, nil, 51, nil, nil, nil, 56, 57, nil, nil,
- nil, 60, nil, 58, 59, 61, 246, 247, 65, 66,
- nil, nil, nil, nil, 245, 275, 279, 88, 87, 89,
- 90, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 41, nil, nil, 92, 91, 82, 50, 84, 83, 86,
- 85, 93, 94, nil, 80, 81, nil, 38, 39, 37,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 200,
- nil, nil, 204, nil, nil, 52, 53, nil, nil, 54,
- nil, nil, nil, nil, nil, 40, nil, nil, nil, nil,
- nil, nil, nil, 207, nil, nil, nil, nil, 79, 72,
- 74, 75, 76, 77, nil, nil, nil, 73, 78, 62,
- 63, 64, nil, 51, nil, nil, nil, 56, 57, nil,
- nil, nil, 60, nil, 58, 59, 61, 246, 247, 65,
- 66, nil, nil, nil, nil, 245, 275, 279, 88, 87,
- 89, 90, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 41, nil, nil, 92, 91, 82, 50, 84, 83,
- 86, 85, 93, 94, nil, 80, 81, nil, 38, 39,
- 37, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 200, nil, nil, 204, nil, nil, 52, 53, nil, nil,
- 54, nil, nil, nil, nil, nil, 40, nil, nil, nil,
- nil, nil, nil, nil, 207, nil, nil, nil, nil, 79,
- 72, 74, 75, 76, 77, nil, nil, nil, 73, 78,
- 62, 63, 64, nil, 51, nil, nil, nil, 56, 57,
- nil, nil, nil, 60, nil, 58, 59, 61, 246, 247,
- 65, 66, nil, nil, nil, nil, 245, 275, 279, 88,
- 87, 89, 90, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 276, nil, nil, 92, 91, 82, 50, 84,
- 83, 86, 85, 93, 94, nil, 80, 81, nil, nil,
- nil, 280, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 273, nil, nil, 270, nil, nil, 52, 53, nil,
- nil, 54, nil, 821, nil, 820, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 79, 72, 74, 75, 76, 77, nil, nil, nil, 73,
- 78, 62, 63, 64, nil, 51, nil, nil, nil, 56,
- 57, nil, nil, nil, 60, nil, 58, 59, 61, 246,
- 247, 65, 66, nil, nil, nil, nil, 245, 275, 279,
- 88, 87, 89, 90, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 41, nil, nil, 92, 91, 82, 50,
- 84, 83, 86, 85, 93, 94, nil, 80, 81, nil,
- 38, 39, 37, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 200, nil, nil, 204, nil, nil, 52, 53,
- nil, nil, 54, nil, nil, nil, nil, nil, 40, nil,
- nil, nil, nil, nil, nil, nil, 207, nil, nil, nil,
- nil, 79, 72, 74, 75, 76, 77, nil, nil, nil,
- 73, 78, 62, 63, 64, nil, 51, nil, nil, nil,
- 56, 57, nil, nil, nil, 60, nil, 58, 59, 61,
- 246, 247, 65, 66, nil, nil, nil, nil, 245, 275,
- 279, 88, 87, 89, 90, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 41, nil, nil, 92, 91, 82,
- 50, 84, 83, 86, 85, 93, 94, nil, 80, 81,
- nil, 38, 39, 37, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 200, nil, nil, 204, nil, nil, 52,
- 53, nil, nil, 54, nil, nil, nil, nil, nil, 40,
- nil, nil, nil, nil, nil, nil, nil, 207, nil, nil,
- nil, nil, 79, 72, 74, 75, 76, 77, nil, nil,
- nil, 73, 78, 62, 63, 64, nil, 51, nil, nil,
- nil, 56, 57, nil, nil, nil, 60, nil, 58, 59,
- 61, 246, 247, 65, 66, nil, nil, nil, nil, 245,
- 275, 279, 88, 87, 89, 90, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 41, nil, nil, 92, 91,
- 82, 50, 84, 83, 86, 85, 93, 94, nil, 80,
- 81, nil, 38, 39, 37, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 200, nil, nil, 204, nil, nil,
- 52, 53, nil, nil, 54, nil, nil, nil, nil, nil,
- 40, nil, nil, nil, nil, nil, nil, nil, 207, nil,
- nil, nil, nil, 79, 72, 74, 75, 76, 77, nil,
- nil, nil, 73, 78, 62, 63, 64, nil, 51, nil,
- nil, nil, 56, 57, nil, nil, nil, 60, nil, 58,
- 59, 61, 246, 247, 65, 66, nil, nil, nil, nil,
- 245, 275, 279, 88, 87, 89, 90, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 41, nil, nil, 92,
- 91, 82, 50, 84, 83, 86, 85, 93, 94, nil,
- 80, 81, nil, 38, 39, 37, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 200, nil, nil, 204, nil,
- nil, 52, 53, nil, nil, 54, nil, nil, nil, nil,
- nil, 40, nil, nil, nil, nil, nil, nil, nil, 207,
- nil, nil, nil, nil, 79, 72, 74, 75, 76, 77,
- nil, nil, nil, 73, 78, 62, 63, 64, nil, 51,
- nil, nil, nil, 56, 57, nil, nil, nil, 60, nil,
- 58, 59, 61, 246, 247, 65, 66, nil, nil, nil,
- nil, 245, 275, 279, 88, 87, 89, 90, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 276, nil, nil,
- 92, 91, 82, 50, 84, 83, 86, 85, 93, 94,
- nil, 80, 81, nil, nil, nil, 280, nil, 215, 219,
- 224, 225, 226, 221, 223, 231, 232, 227, 228, nil,
- 208, 209, nil, nil, 229, 230, 772, nil, nil, 204,
- nil, nil, 52, 53, nil, nil, 54, nil, nil, nil,
- 212, nil, 218, nil, 214, 213, 210, 211, 222, 220,
- 216, nil, 217, nil, nil, 79, 72, 74, 75, 76,
- 77, nil, nil, nil, 73, 78, 62, 63, 64, 233,
- 51, nil, nil, nil, 56, 57, nil, nil, nil, 60,
- nil, 58, 59, 61, 246, 247, 65, 66, nil, nil,
- nil, nil, 245, 28, 27, 88, 87, 89, 90, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 41, nil,
- nil, 92, 91, 82, 50, 84, 83, 86, 85, 93,
- 94, nil, 80, 81, nil, 38, 39, 37, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 200, nil, nil,
- 204, nil, nil, 52, 53, nil, nil, 54, nil, 299,
- nil, nil, nil, 40, nil, nil, nil, nil, nil, nil,
- nil, 207, nil, nil, nil, nil, 79, 72, 74, 75,
- 76, 77, nil, nil, nil, 73, 78, 62, 63, 64,
- nil, 51, nil, nil, nil, 56, 57, nil, nil, nil,
- 60, nil, 58, 59, 61, 246, 247, 65, 66, nil,
- nil, nil, nil, 245, 275, 279, 88, 87, 89, 90,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 276,
- nil, nil, 92, 91, 82, 50, 84, 83, 86, 85,
- 93, 94, nil, 80, 81, nil, nil, nil, 280, nil,
- 215, 219, 224, 225, 226, 221, 223, 231, 232, 227,
- 228, nil, 208, 209, nil, nil, 229, 230, 772, nil,
- nil, 204, nil, nil, 52, 53, nil, nil, 54, nil,
- nil, nil, 212, nil, 218, nil, 214, 213, 210, 211,
- 222, 220, 216, nil, 217, nil, nil, 79, 72, 74,
- 75, 76, 77, nil, nil, nil, 73, 78, 62, 63,
- 64, 233, 51, nil, nil, nil, 56, 57, nil, nil,
- nil, 60, nil, 58, 59, 61, 246, 247, 65, 66,
- nil, nil, nil, nil, 245, 275, 279, 88, 87, 89,
- 90, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 41, nil, nil, 92, 91, 82, 50, 84, 83, 86,
- 85, 93, 94, nil, 80, 81, nil, 38, 39, 37,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 200,
- nil, nil, 204, nil, nil, 52, 53, nil, nil, 54,
- nil, 864, nil, 243, nil, 40, nil, nil, nil, nil,
- nil, nil, nil, 207, nil, nil, nil, nil, 79, 72,
- 74, 75, 76, 77, nil, nil, nil, 73, 78, 62,
- 63, 64, nil, 51, nil, nil, nil, 56, 57, nil,
- nil, nil, 60, nil, 58, 59, 61, 246, 247, 65,
- 66, nil, nil, nil, nil, 245, 275, 279, 88, 87,
- 89, 90, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 41, nil, nil, 92, 91, 82, 50, 84, 83,
- 86, 85, 93, 94, nil, 80, 81, nil, 38, 39,
- 37, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 200, nil, nil, 204, nil, nil, 52, 53, nil, nil,
- 54, nil, 867, nil, 243, nil, 40, nil, nil, nil,
- nil, nil, nil, nil, 207, nil, nil, nil, nil, 79,
- 72, 74, 75, 76, 77, nil, nil, nil, 73, 78,
- 62, 63, 64, nil, 51, nil, nil, nil, 56, 57,
- nil, nil, nil, 60, nil, 58, 59, 61, 246, 247,
- 65, 66, nil, nil, nil, nil, 245, 275, 279, 88,
- 87, 89, 90, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 276, nil, nil, 92, 91, 82, 50, 84,
- 83, 86, 85, 93, 94, nil, 80, 81, nil, nil,
- nil, 280, nil, 215, 219, 224, 225, 226, 221, 223,
- 231, 232, 227, 228, nil, 208, 209, nil, nil, 229,
- 230, 772, nil, nil, 204, nil, nil, 52, 53, nil,
- nil, 54, nil, nil, nil, 212, nil, 218, nil, 214,
- 213, 210, 211, 222, 220, 216, nil, 217, nil, nil,
- 79, 72, 74, 75, 76, 77, nil, nil, nil, 73,
- 78, 62, 63, 64, 233, 51, nil, nil, nil, 56,
- 57, nil, nil, nil, 60, nil, 58, 59, 61, 246,
- 247, 65, 66, nil, nil, nil, nil, 245, 275, 279,
- 88, 87, 89, 90, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 41, nil, nil, 92, 91, 82, 50,
- 84, 83, 86, 85, 93, 94, nil, 80, 81, nil,
- 38, 39, 37, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 200, nil, nil, 204, nil, nil, 52, 53,
- nil, nil, 54, nil, nil, nil, nil, nil, 40, nil,
- nil, nil, nil, nil, nil, nil, 207, nil, nil, nil,
- nil, 79, 72, 74, 75, 76, 77, nil, nil, nil,
- 73, 78, 62, 63, 64, nil, 51, nil, nil, nil,
- 56, 57, nil, nil, nil, 60, nil, 58, 59, 61,
- 246, 247, 65, 66, nil, nil, nil, nil, 245, 275,
- 279, 88, 87, 89, 90, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 41, nil, nil, 92, 91, 82,
- 50, 84, 83, 86, 85, 93, 94, nil, 80, 81,
- nil, 38, 39, 37, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 200, nil, nil, 204, nil, nil, 52,
- 53, nil, nil, 54, nil, nil, nil, nil, nil, 40,
- nil, nil, nil, nil, nil, nil, nil, 207, nil, nil,
- nil, nil, 79, 72, 74, 75, 76, 77, nil, nil,
- nil, 73, 78, 62, 63, 64, nil, 51, nil, nil,
- nil, 56, 57, nil, nil, nil, 60, nil, 58, 59,
- 61, 246, 247, 65, 66, nil, nil, nil, nil, 245,
- 275, 279, 88, 87, 89, 90, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 276, nil, nil, 92, 91,
- 82, 50, 84, 83, 86, 85, 93, 94, nil, 80,
- 81, nil, nil, nil, 280, nil, 215, 219, 224, 225,
- 226, 221, 223, 231, 232, 227, 228, nil, 208, 209,
- nil, nil, 229, 230, 772, nil, nil, 204, nil, nil,
- 52, 53, nil, nil, 54, nil, nil, nil, 212, nil,
- 218, nil, 214, 213, 210, 211, 222, 220, 216, nil,
- 217, nil, nil, 79, 72, 74, 75, 76, 77, nil,
- nil, nil, 73, 78, 62, 63, 64, 233, 51, nil,
- nil, nil, 56, 57, nil, nil, nil, 60, nil, 58,
- 59, 61, 246, 247, 65, 66, nil, nil, nil, nil,
- 245, 275, 279, 88, 87, 89, 90, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 41, nil, nil, 92,
- 91, 82, 50, 84, 83, 86, 85, 93, 94, nil,
- 80, 81, nil, 38, 39, 37, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 200, nil, nil, 204, nil,
- nil, 52, 53, nil, nil, 54, nil, 889, nil, 243,
- nil, 40, nil, nil, nil, nil, nil, nil, nil, 207,
- nil, nil, nil, nil, 79, 72, 74, 75, 76, 77,
- nil, nil, nil, 73, 78, 62, 63, 64, nil, 51,
- nil, nil, nil, 56, 57, nil, nil, nil, 60, nil,
- 58, 59, 61, 246, 247, 65, 66, nil, nil, nil,
- nil, 245, 275, 279, 88, 87, 89, 90, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 276, nil, nil,
- 92, 91, 82, 50, 84, 83, 86, 85, 93, 94,
- nil, 80, 81, nil, nil, nil, 280, nil, 215, 219,
- 224, 225, 226, 221, 223, 231, 232, 227, 228, nil,
- 208, 209, nil, nil, 229, 230, 772, nil, nil, 204,
- nil, nil, 52, 53, nil, nil, 54, nil, nil, nil,
- 212, nil, 218, nil, 214, 213, 210, 211, 222, 220,
- 216, nil, 217, nil, nil, 79, 72, 74, 75, 76,
- 77, nil, nil, nil, 73, 78, 62, 63, 64, 233,
- 51, nil, nil, nil, 56, 57, nil, nil, nil, 60,
- nil, 58, 59, 61, 246, 247, 65, 66, nil, nil,
- nil, nil, 245, 275, 279, 88, 87, 89, 90, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 41, nil,
- nil, 92, 91, 82, 50, 84, 83, 86, 85, 93,
- 94, nil, 80, 81, nil, 38, 39, 37, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 200, nil, nil,
- 204, nil, nil, 52, 53, nil, nil, 54, nil, nil,
- nil, nil, nil, 40, nil, nil, nil, nil, nil, nil,
- nil, 207, nil, nil, nil, nil, 79, 72, 74, 75,
- 76, 77, nil, nil, nil, 73, 78, 153, 164, 154,
- 177, 150, 170, 160, 159, 180, 181, 175, 158, 157,
- 152, 178, 182, 183, 162, 151, 165, 169, 171, 163,
- 156, nil, nil, 172, 179, 174, 336, 335, 337, 334,
- 149, 168, 167, nil, nil, nil, nil, nil, 148, 155,
- 146, 147, 332, 333, 330, 111, 84, 83, 331, 85,
- nil, nil, nil, nil, nil, nil, 139, 140, nil, 137,
- 121, 122, 123, nil, 126, 128, nil, nil, 124, nil,
- nil, nil, nil, 141, 142, 129, 130, nil, nil, nil,
- nil, nil, 341, nil, nil, nil, nil, nil, nil, nil,
- 134, 133, nil, 120, 138, 136, 135, 131, 132, 127,
- 125, 118, nil, 119, nil, nil, 143, 153, 164, 154,
- 177, 150, 170, 160, 159, 180, 181, 175, 158, 157,
- 152, 178, 182, 183, 162, 151, 165, 169, 171, 163,
- 156, nil, nil, 172, 179, 174, 173, 166, 176, 161,
- 149, 168, 167, nil, nil, nil, nil, nil, 148, 155,
- 146, 147, 144, 145, 109, 111, nil, nil, 110, nil,
- nil, nil, nil, nil, nil, nil, 139, 140, nil, 137,
- 121, 122, 123, nil, 126, 128, nil, nil, 124, nil,
- nil, nil, nil, 141, 142, 129, 130, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 134, 133, nil, 120, 138, 136, 135, 131, 132, 127,
- 125, 118, nil, 119, nil, nil, 143, 215, 219, 224,
- 225, 226, 221, 223, 231, 232, 227, 228, nil, 208,
- 209, nil, nil, 229, 230, nil, nil, nil, -215, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 212,
- nil, 218, nil, 214, 213, 210, 211, 222, 220, 216,
- nil, 217, nil, nil, nil, nil, nil, nil, nil, 376,
- 379, nil, nil, 377, nil, nil, nil, nil, 233, nil,
- -215, 139, 140, nil, 137, 121, 122, 123, nil, 126,
- 128, nil, nil, 124, nil, nil, nil, nil, 141, 142,
- 129, 130, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 134, 133, nil, 120, 138,
- 136, 135, 131, 132, 127, 125, 118, nil, 119, 381,
- 385, 143, nil, 383, nil, nil, nil, nil, nil, nil,
- nil, 139, 140, nil, 137, 121, 122, 123, nil, 126,
- 128, nil, nil, 124, nil, nil, nil, nil, 141, 142,
- 129, 130, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 134, 133, nil, 120, 138,
- 136, 135, 131, 132, 127, 125, 118, nil, 119, 433,
- 379, 143, nil, 434, nil, nil, nil, nil, nil, nil,
- nil, 139, 140, nil, 137, 121, 122, 123, nil, 126,
- 128, nil, nil, 124, nil, nil, nil, nil, 141, 142,
- 129, 130, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 134, 133, nil, 120, 138,
- 136, 135, 131, 132, 127, 125, 118, nil, 119, 433,
- 379, 143, nil, 434, nil, nil, nil, nil, nil, nil,
- nil, 139, 140, nil, 137, 121, 122, 123, nil, 126,
- 128, nil, nil, 124, nil, nil, nil, nil, 141, 142,
- 129, 130, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 134, 133, nil, 120, 138,
- 136, 135, 131, 132, 127, 125, 118, nil, 119, 550,
- 379, 143, nil, 551, nil, nil, nil, nil, nil, nil,
- nil, 139, 140, nil, 137, 121, 122, 123, nil, 126,
- 128, nil, nil, 124, nil, nil, nil, nil, 141, 142,
- 129, 130, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 134, 133, nil, 120, 138,
- 136, 135, 131, 132, 127, 125, 118, nil, 119, 552,
- 385, 143, nil, 553, nil, nil, nil, nil, nil, nil,
- nil, 139, 140, nil, 137, 121, 122, 123, nil, 126,
- 128, nil, nil, 124, nil, nil, nil, nil, 141, 142,
- 129, 130, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 134, 133, nil, 120, 138,
- 136, 135, 131, 132, 127, 125, 118, nil, 119, nil,
- nil, 143, 215, 219, 224, 225, 226, 221, 223, 231,
- 232, 227, 228, nil, 208, 209, nil, nil, 229, 230,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 212, nil, 218, nil, 214, 213,
- 210, 211, 222, 220, 216, nil, 217, nil, nil, nil,
- nil, nil, nil, 594, 379, nil, nil, 595, nil, nil,
- nil, nil, nil, 233, 556, 139, 140, nil, 137, 121,
- 122, 123, nil, 126, 128, nil, nil, 124, nil, nil,
- nil, nil, 141, 142, 129, 130, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 134,
- 133, nil, 120, 138, 136, 135, 131, 132, 127, 125,
- 118, nil, 119, 597, 385, 143, nil, 598, nil, nil,
- nil, nil, nil, nil, nil, 139, 140, nil, 137, 121,
- 122, 123, nil, 126, 128, nil, nil, 124, nil, nil,
- nil, nil, 141, 142, 129, 130, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 134,
- 133, nil, 120, 138, 136, 135, 131, 132, 127, 125,
- 118, nil, 119, 550, 379, 143, nil, 551, nil, nil,
- nil, nil, nil, nil, nil, 139, 140, nil, 137, 121,
- 122, 123, nil, 126, 128, nil, nil, 124, nil, nil,
- nil, nil, 141, 142, 129, 130, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 134,
- 133, nil, 120, 138, 136, 135, 131, 132, 127, 125,
- 118, nil, 119, 552, 385, 143, nil, 553, nil, nil,
- nil, nil, nil, nil, nil, 139, 140, nil, 137, 121,
- 122, 123, nil, 126, 128, nil, nil, 124, nil, nil,
- nil, nil, 141, 142, 129, 130, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 134,
- 133, nil, 120, 138, 136, 135, 131, 132, 127, 125,
- 118, nil, 119, 630, 379, 143, nil, 631, nil, nil,
- nil, nil, nil, nil, nil, 139, 140, nil, 137, 121,
- 122, 123, nil, 126, 128, nil, nil, 124, nil, nil,
- nil, nil, 141, 142, 129, 130, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 134,
- 133, nil, 120, 138, 136, 135, 131, 132, 127, 125,
- 118, nil, 119, 632, 385, 143, nil, 633, nil, nil,
- nil, nil, nil, nil, nil, 139, 140, nil, 137, 121,
- 122, 123, nil, 126, 128, nil, nil, 124, nil, nil,
- nil, nil, 141, 142, 129, 130, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 134,
- 133, nil, 120, 138, 136, 135, 131, 132, 127, 125,
- 118, nil, 119, 635, 385, 143, nil, 636, nil, nil,
- nil, nil, nil, nil, nil, 139, 140, nil, 137, 121,
- 122, 123, nil, 126, 128, nil, nil, 124, nil, nil,
- nil, nil, 141, 142, 129, 130, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 134,
- 133, nil, 120, 138, 136, 135, 131, 132, 127, 125,
- 118, nil, 119, 433, 379, 143, nil, 434, nil, nil,
- nil, nil, nil, nil, nil, 139, 140, nil, 137, 121,
- 122, 123, nil, 126, 128, nil, nil, 124, nil, nil,
- nil, nil, 141, 142, 129, 130, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 134,
- 133, nil, 120, 138, 136, 135, 131, 132, 127, 125,
- 118, nil, 119, 433, 379, 143, nil, 434, nil, nil,
- nil, nil, nil, nil, nil, 139, 140, nil, 137, 121,
- 122, 123, nil, 126, 128, nil, nil, 124, nil, nil,
- nil, nil, 141, 142, 129, 130, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 134,
- 133, nil, 120, 138, 136, 135, 131, 132, 127, 125,
- 118, nil, 119, 433, 379, 143, nil, 434, nil, nil,
- nil, nil, nil, nil, nil, 139, 140, nil, 137, 121,
- 122, 123, nil, 126, 128, nil, nil, 124, nil, nil,
- nil, nil, 141, 142, 129, 130, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 134,
- 133, nil, 120, 138, 136, 135, 131, 132, 127, 125,
- 118, nil, 119, 857, 379, 143, nil, 858, nil, nil,
- nil, nil, nil, nil, nil, 139, 140, nil, 137, 121,
- 122, 123, nil, 126, 128, nil, nil, 124, nil, nil,
- nil, nil, 141, 142, 129, 130, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 134,
- 133, nil, 120, 138, 136, 135, 131, 132, 127, 125,
- 118, nil, 119, 859, 385, 143, nil, 860, nil, nil,
- nil, nil, nil, nil, nil, 139, 140, nil, 137, 121,
- 122, 123, nil, 126, 128, nil, nil, 124, nil, nil,
- nil, nil, 141, 142, 129, 130, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 134,
- 133, nil, 120, 138, 136, 135, 131, 132, 127, 125,
- 118, nil, 119, nil, nil, 143, 215, 219, 224, 225,
- 226, 221, 223, 231, 232, 227, 228, nil, 208, 209,
- nil, nil, 229, 230, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 212, nil,
- 218, nil, 214, 213, 210, 211, 222, 220, 216, nil,
- 217, nil, 215, 219, 224, 225, 226, 221, 223, 231,
- 232, 227, 228, nil, 208, 209, 291, 233, 229, 230,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 212, nil, 218, nil, 214, 213,
- 210, 211, 222, 220, 216, nil, 217, nil, 215, 219,
- 224, 225, 226, 221, 223, 231, 232, 227, 228, nil,
- 208, 209, 291, 233, 229, 230, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 212, nil, 218, nil, 214, 213, 210, 211, 222, 220,
- 216, nil, 217, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 233 ]
-
-racc_action_check = [
- 381, 512, 512, 518, 518, 306, 755, 381, 381, 381,
- 326, 440, 711, 381, 381, 313, 381, 199, 440, 711,
- 307, 70, 347, 316, 424, 381, 3, 627, 500, 70,
- 1, 3, 201, 603, 603, 381, 381, 630, 381, 381,
- 381, 381, 381, 727, 798, 446, 311, 631, 311, 632,
- 743, 394, 755, 755, 755, 755, 8, 310, 424, 447,
- 440, 711, 310, 199, 381, 381, 381, 381, 381, 381,
- 381, 381, 381, 381, 381, 381, 381, 381, 201, 446,
- 381, 381, 381, 55, 381, 347, 603, 594, 381, 591,
- 512, 381, 518, 447, 491, 512, 381, 394, 381, 633,
- 381, 381, 381, 381, 381, 381, 381, 383, 381, 381,
- 381, 9, 632, 326, 383, 383, 383, 306, 313, 306,
- 383, 383, 306, 383, 381, 381, 316, 381, 591, 381,
- 381, 500, 307, 326, 307, 492, 595, 307, 326, 627,
- 630, 627, 383, 383, 627, 383, 383, 383, 383, 383,
- 631, 594, 632, 743, 582, 727, 798, 727, 798, 744,
- 727, 798, 633, 26, 322, 15, 15, 55, 322, 594,
- 550, 383, 383, 383, 383, 383, 383, 383, 383, 383,
- 383, 383, 383, 383, 383, 574, 277, 383, 383, 383,
- 594, 383, 491, 594, 491, 383, 582, 491, 383, 551,
- 595, 10, 633, 383, 528, 383, 343, 383, 383, 383,
- 383, 383, 383, 383, 50, 383, 550, 383, 595, 574,
- 11, 50, 50, 50, 511, 26, 50, 50, 50, 511,
- 50, 383, 383, 492, 383, 492, 383, 383, 492, 595,
- 50, 50, 595, 297, 12, 551, 297, 26, 277, 50,
- 50, 693, 50, 50, 50, 50, 50, 744, 14, 744,
- 298, 20, 744, 298, 344, 528, 528, 343, 343, 343,
- 277, 301, 108, 34, 301, 528, 108, 108, 50, 50,
- 50, 50, 50, 50, 50, 50, 50, 50, 50, 50,
- 50, 50, 345, 13, 50, 50, 50, 693, 36, 50,
- 13, 14, 50, 346, 14, 50, 50, 41, 50, 13,
- 50, 95, 50, 419, 50, 50, 50, 50, 50, 50,
- 50, 432, 50, 184, 50, 344, 344, 344, 432, 432,
- 432, 848, 200, 432, 432, 432, 348, 432, 50, 50,
- 50, 50, 202, 50, 320, 419, 803, 432, 803, 419,
- 419, 419, 419, 345, 345, 345, 432, 432, 203, 432,
- 432, 432, 432, 432, 346, 346, 346, 25, 303, 239,
- 321, 303, 597, 635, 25, 42, 435, 848, 848, 848,
- 848, 240, 42, 435, 435, 435, 330, 857, 435, 435,
- 435, 42, 435, 330, 320, 244, 432, 348, 348, 348,
- 35, 320, 435, 432, 37, 37, 320, 253, 432, 432,
- 320, 435, 435, 264, 435, 435, 435, 435, 435, 283,
- 321, 266, 597, 635, 376, 858, 377, 321, 320, 597,
- 635, 432, 321, 540, 597, 635, 321, 857, 597, 635,
- 267, 400, 268, 35, 857, 432, 35, 432, 401, 857,
- 432, 435, 198, 857, 321, 640, 597, 635, 435, 198,
- 640, 646, 283, 435, 435, 283, 646, 376, 198, 377,
- 376, 857, 377, 400, 271, 858, 540, 400, 400, 540,
- 401, 271, 858, 273, 401, 401, 435, 858, 280, 280,
- 271, 858, 294, 294, 331, 552, 552, 552, 275, 552,
- 435, 331, 435, 552, 552, 435, 276, 859, 552, 858,
- 552, 552, 552, 552, 552, 552, 552, 305, 305, 615,
- 615, 552, 552, 552, 552, 552, 552, 552, 332, 420,
- 279, 333, 334, 758, 758, 332, 284, 552, 333, 334,
- 552, 552, 552, 552, 552, 552, 552, 552, 552, 552,
- 285, 552, 552, 335, 552, 552, 552, 859, 870, 870,
- 335, 420, 288, 336, 859, 420, 420, 420, 420, 859,
- 336, 272, 292, 859, 337, 293, 552, 552, 272, 552,
- 552, 337, 552, 552, 296, 300, 552, 272, 552, 302,
- 552, 859, 552, 312, 339, 274, 286, 314, 315, 317,
- 552, 339, 274, 286, 314, 552, 552, 552, 552, 552,
- 552, 274, 286, 314, 552, 552, 553, 553, 553, 362,
- 553, 363, 368, 552, 553, 553, 371, 375, 382, 553,
- 402, 553, 553, 553, 553, 553, 553, 553, 403, 404,
- 405, 429, 553, 553, 553, 553, 553, 553, 553, 522,
- 522, 438, 522, 522, 522, 439, 441, 442, 553, 448,
- 450, 553, 553, 553, 553, 553, 553, 553, 553, 553,
- 553, 451, 553, 553, 455, 553, 553, 553, 398, 398,
- 398, 398, 398, 398, 398, 398, 398, 398, 398, 324,
- 398, 398, 459, 460, 398, 398, 324, 553, 553, 459,
- 553, 553, 470, 553, 553, 324, 473, 553, 459, 553,
- 398, 553, 398, 553, 398, 398, 398, 398, 398, 398,
- 398, 553, 398, 487, 493, 494, 553, 553, 553, 553,
- 553, 553, 526, 503, 531, 553, 553, 60, 60, 60,
- 503, 60, 543, 547, 553, 60, 60, 554, 561, 503,
- 60, 563, 60, 60, 60, 60, 60, 60, 60, 566,
- 568, 576, 577, 60, 60, 60, 60, 60, 60, 60,
- 583, 586, 60, 593, 596, 599, 601, 366, 602, 60,
- 604, 607, 60, 60, 60, 60, 60, 60, 60, 60,
- 60, 60, 608, 60, 60, 611, 60, 60, 60, 366,
- 366, 366, 366, 366, 366, 366, 366, 366, 366, 366,
- 598, 366, 366, 721, 617, 366, 366, 598, 60, 623,
- 721, 60, 598, 625, 60, 60, 598, 626, 60, 721,
- 629, 366, 638, 366, 60, 366, 366, 366, 366, 366,
- 366, 366, 60, 366, 643, 647, 648, 60, 60, 60,
- 60, 60, 60, 649, 655, 660, 60, 60, 663, 60,
- 366, 665, 366, 636, 60, 97, 97, 97, 97, 97,
- 636, 678, 696, 97, 97, 636, 700, 701, 97, 636,
- 97, 97, 97, 97, 97, 97, 97, 702, 705, 709,
- 710, 97, 97, 97, 97, 97, 97, 97, 712, 716,
- 97, 4, 4, 4, 4, 4, 97, 97, 97, 97,
- 97, 97, 97, 97, 97, 97, 97, 97, 97, 97,
- 718, 97, 97, 719, 97, 97, 97, 399, 399, 399,
- 399, 399, 399, 399, 399, 399, 399, 399, 770, 399,
- 399, 771, 720, 399, 399, 770, 97, 732, 771, 97,
- 735, 746, 97, 97, 770, 750, 97, 771, 97, 399,
- 751, 399, 97, 399, 399, 399, 399, 399, 399, 399,
- 97, 399, 764, 772, 774, 97, 97, 97, 97, 97,
- 97, 775, 773, 782, 97, 97, 697, 697, 697, 773,
- 697, 783, 97, 825, 697, 697, 784, 787, 773, 697,
- 825, 697, 697, 697, 697, 697, 697, 697, 800, 825,
- 801, 806, 697, 697, 697, 697, 697, 697, 697, 106,
- 106, 106, 106, 106, 808, 809, 810, 813, 697, 814,
- 826, 697, 697, 697, 697, 697, 697, 697, 697, 697,
- 697, 833, 697, 697, 410, 836, 514, 697, 514, 514,
- 514, 514, 860, 837, 854, 876, 855, 856, 865, 860,
- 410, 410, 876, 871, 860, 872, 873, 697, 860, 874,
- 697, 876, 878, 697, 697, 881, 410, 697, 410, 892,
- 410, 410, 410, 410, 514, nil, 410, nil, 410, nil,
- nil, nil, 514, 514, 514, 514, 697, 697, 697, 697,
- 697, 697, nil, nil, nil, 697, 697, nil, 821, 821,
- 821, 697, 821, nil, nil, nil, 821, 821, nil, nil,
- nil, 821, nil, 821, 821, 821, 821, 821, 821, 821,
- nil, nil, nil, nil, 821, 821, 821, 821, 821, 821,
- 821, 350, 350, 350, 350, 350, nil, nil, 555, nil,
- 821, nil, nil, 821, 821, 821, 821, 821, 821, 821,
- 821, 821, 821, nil, 821, 821, nil, nil, nil, 821,
- 555, 555, 555, 555, 555, 555, 555, 555, 555, 555,
- 555, nil, 555, 555, nil, nil, 555, 555, nil, 821,
- nil, nil, 821, nil, nil, 821, 821, nil, nil, 821,
- nil, nil, 555, nil, 555, nil, 555, 555, 555, 555,
- 555, 555, 555, nil, 555, nil, nil, nil, 821, 821,
- 821, 821, 821, 821, nil, nil, nil, 821, 821, nil,
- nil, 555, nil, 821, 0, 0, 0, 0, 0, 0,
- nil, nil, nil, 0, 0, nil, nil, nil, 0, nil,
- 0, 0, 0, 0, 0, 0, 0, nil, nil, nil,
- nil, 0, 0, 0, 0, 0, 0, 0, nil, nil,
- 0, nil, nil, nil, nil, nil, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- nil, 0, 0, nil, 0, 0, 0, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 0, nil, nil, 0,
- nil, nil, 0, 0, nil, nil, 0, nil, 0, nil,
- nil, nil, 0, 645, nil, 645, 645, 645, 645, nil,
- 0, nil, nil, nil, nil, 0, 0, 0, 0, 0,
- 0, nil, nil, nil, 0, 0, 30, 30, 30, 30,
- 30, 30, nil, nil, nil, 30, 30, nil, nil, nil,
- 30, nil, 30, 30, 30, 30, 30, 30, 30, 645,
- 645, 645, 645, 30, 30, 30, 30, 30, 30, 30,
- nil, nil, 30, nil, nil, nil, nil, nil, 30, 30,
- 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,
- 30, 30, nil, 30, 30, nil, 30, 30, 30, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 30, nil,
- nil, 30, nil, nil, 30, 30, nil, nil, 30, nil,
- 30, nil, nil, nil, 30, 753, nil, 753, 753, 753,
- 753, nil, 30, nil, nil, nil, nil, 30, 30, 30,
- 30, 30, 30, nil, nil, nil, 30, 30, 51, 51,
- 51, 51, 51, 51, nil, nil, nil, 51, 51, nil,
- nil, nil, 51, nil, 51, 51, 51, 51, 51, 51,
- 51, 753, 753, 753, 753, 51, 51, 51, 51, 51,
- 51, 51, nil, nil, 51, nil, nil, nil, nil, nil,
- 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, nil, 51, 51, nil, 51, 51,
- 51, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 51, nil, nil, 51, nil, nil, 51, 51, nil, nil,
- 51, nil, 51, nil, nil, nil, 51, 817, nil, 817,
- 817, 817, 817, nil, 51, nil, nil, nil, nil, 51,
- 51, 51, 51, 51, 51, nil, nil, nil, 51, 51,
- 186, 186, 186, 186, 186, 186, nil, nil, nil, 186,
- 186, nil, nil, nil, 186, 817, 186, 186, 186, 186,
- 186, 186, 186, 817, 817, 817, 817, 186, 186, 186,
- 186, 186, 186, 186, nil, nil, 186, nil, nil, nil,
- nil, nil, 186, 186, 186, 186, 186, 186, 186, 186,
- 186, 186, 186, 186, 186, 186, nil, 186, 186, nil,
- 186, 186, 186, 409, 409, 409, 409, 409, 409, 409,
- nil, nil, 409, 409, nil, nil, nil, nil, nil, 409,
- 409, nil, 186, nil, nil, 186, nil, nil, 186, 186,
- nil, nil, 186, nil, 186, 409, nil, 409, 186, 409,
- 409, 409, 409, 409, 409, 409, 186, 409, nil, nil,
- nil, 186, 186, 186, 186, 186, 186, nil, nil, nil,
- 186, 186, 187, 187, 187, 187, 187, 187, nil, nil,
- nil, 187, 187, nil, nil, nil, 187, nil, 187, 187,
- 187, 187, 187, 187, 187, nil, nil, nil, nil, 187,
- 187, 187, 187, 187, 187, 187, nil, nil, 187, nil,
- nil, nil, nil, nil, 187, 187, 187, 187, 187, 187,
- 187, 187, 187, 187, 187, 187, 187, 187, nil, 187,
- 187, nil, 187, 187, 187, 411, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 411, 411, nil, 187, nil, nil, 187, nil, nil,
- 187, 187, nil, nil, 187, nil, 187, 411, nil, 411,
- 187, 411, 411, 411, 411, nil, nil, 411, 187, 411,
- nil, nil, nil, 187, 187, 187, 187, 187, 187, nil,
- nil, nil, 187, 187, 204, 204, 204, 204, 204, 204,
- nil, nil, nil, 204, 204, nil, nil, nil, 204, nil,
- 204, 204, 204, 204, 204, 204, 204, nil, nil, nil,
- nil, 204, 204, 204, 204, 204, 204, 204, nil, nil,
- 204, nil, nil, nil, nil, nil, 204, 204, 204, 204,
- 204, 204, 204, 204, 204, 204, 204, 204, 204, 204,
- nil, 204, 204, nil, 204, 204, 204, 412, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 412, 412, nil, 204, nil, nil, 204,
- nil, nil, 204, 204, nil, nil, 204, nil, 204, 412,
- nil, 412, 204, 412, 412, 412, 412, nil, nil, 412,
- 204, 412, nil, nil, nil, 204, 204, 204, 204, 204,
- 204, nil, nil, nil, 204, 204, 265, 265, 265, 265,
- 265, 265, nil, nil, nil, 265, 265, nil, nil, nil,
- 265, nil, 265, 265, 265, 265, 265, 265, 265, nil,
- nil, nil, nil, 265, 265, 265, 265, 265, 265, 265,
- nil, nil, 265, nil, nil, nil, nil, nil, 265, 265,
- 265, 265, 265, 265, 265, 265, 265, 265, 265, 265,
- 265, 265, nil, 265, 265, nil, 265, 265, 265, 413,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 413, 413, nil, 265, nil,
- nil, 265, nil, nil, 265, 265, nil, nil, 265, nil,
- 265, 413, nil, 413, 265, 413, 413, 413, 413, nil,
- nil, 413, 265, 413, nil, nil, nil, 265, 265, 265,
- 265, 265, 265, nil, nil, nil, 265, 265, 270, 270,
- 270, 270, 270, 270, nil, nil, nil, 270, 270, nil,
- nil, nil, 270, nil, 270, 270, 270, 270, 270, 270,
- 270, nil, nil, nil, nil, 270, 270, 270, 270, 270,
- 270, 270, nil, nil, 270, nil, nil, nil, nil, nil,
- 270, 270, 270, 270, 270, 270, 270, 270, 270, 270,
- 270, 270, 270, 270, nil, 270, 270, nil, 270, 270,
- 270, 414, 414, 414, 414, 414, 414, 414, nil, nil,
- 414, 414, nil, nil, nil, nil, nil, 414, 414, nil,
- 270, nil, nil, 270, nil, nil, 270, 270, nil, nil,
- 270, nil, 270, 414, nil, 414, 270, 414, 414, 414,
- 414, 414, 414, 414, 270, 414, nil, nil, nil, 270,
- 270, 270, 270, 270, 270, nil, nil, nil, 270, 270,
- 486, 486, 486, 486, 486, 486, nil, nil, nil, 486,
- 486, nil, nil, nil, 486, nil, 486, 486, 486, 486,
- 486, 486, 486, nil, nil, nil, nil, 486, 486, 486,
- 486, 486, 486, 486, nil, nil, 486, nil, nil, nil,
- nil, nil, 486, 486, 486, 486, 486, 486, 486, 486,
- 486, 486, 486, 486, 486, 486, nil, 486, 486, nil,
- 486, 486, 486, 415, 415, 415, 415, 415, 415, 415,
- nil, nil, 415, 415, nil, nil, nil, nil, nil, 415,
- 415, nil, 486, nil, nil, 486, nil, nil, 486, 486,
- nil, nil, 486, nil, 486, 415, nil, 415, 486, 415,
- 415, 415, 415, 415, 415, 415, 486, 415, nil, nil,
- nil, 486, 486, 486, 486, 486, 486, nil, nil, nil,
- 486, 486, 490, 490, 490, 490, 490, 490, nil, nil,
- nil, 490, 490, nil, nil, nil, 490, nil, 490, 490,
- 490, 490, 490, 490, 490, nil, nil, nil, nil, 490,
- 490, 490, 490, 490, 490, 490, nil, nil, 490, nil,
- nil, nil, nil, nil, 490, 490, 490, 490, 490, 490,
- 490, 490, 490, 490, 490, 490, 490, 490, nil, 490,
- 490, nil, 490, 490, 490, 416, 416, 416, 416, 416,
- 416, 416, nil, nil, 416, 416, nil, nil, nil, nil,
- nil, 416, 416, nil, 490, nil, nil, 490, nil, nil,
- 490, 490, nil, nil, 490, nil, 490, 416, nil, 416,
- 490, 416, 416, 416, 416, 416, 416, 416, 490, 416,
- nil, nil, nil, 490, 490, 490, 490, 490, 490, nil,
- nil, nil, 490, 490, 495, 495, 495, 495, 495, 495,
- nil, nil, nil, 495, 495, nil, nil, nil, 495, nil,
- 495, 495, 495, 495, 495, 495, 495, nil, nil, nil,
- nil, 495, 495, 495, 495, 495, 495, 495, nil, nil,
- 495, nil, nil, nil, nil, nil, 495, 495, 495, 495,
- 495, 495, 495, 495, 495, 495, 495, 495, 495, 495,
- nil, 495, 495, nil, 495, 495, 495, 417, 417, 417,
- 417, 417, 417, 417, nil, nil, 417, 417, nil, nil,
- nil, nil, nil, 417, 417, nil, 495, nil, nil, 495,
- nil, nil, 495, 495, nil, nil, 495, nil, 495, 417,
- nil, 417, 495, 417, 417, 417, 417, 417, 417, 417,
- 495, 417, nil, nil, nil, 495, 495, 495, 495, 495,
- 495, nil, nil, nil, 495, 495, 513, 513, 513, 513,
- 513, 513, nil, nil, nil, 513, 513, nil, nil, nil,
- 513, nil, 513, 513, 513, 513, 513, 513, 513, nil,
- nil, nil, nil, 513, 513, 513, 513, 513, 513, 513,
- nil, nil, 513, nil, nil, nil, nil, nil, 513, 513,
- 513, 513, 513, 513, 513, 513, 513, 513, 513, 513,
- 513, 513, nil, 513, 513, nil, 513, 513, 513, 418,
- 418, 418, 418, 418, 418, 418, nil, nil, 418, 418,
- nil, nil, nil, nil, nil, 418, 418, nil, 513, nil,
- nil, 513, nil, nil, 513, 513, nil, nil, 513, nil,
- 513, 418, nil, 418, 513, 418, 418, 418, 418, 418,
- 418, 418, 513, 418, nil, nil, nil, 513, 513, 513,
- 513, 513, 513, nil, nil, nil, 513, 513, 559, 559,
- 559, 559, 559, 559, nil, nil, nil, 559, 559, nil,
- nil, nil, 559, nil, 559, 559, 559, 559, 559, 559,
- 559, nil, nil, nil, nil, 559, 559, 559, 559, 559,
- 559, 559, nil, nil, 559, nil, nil, nil, nil, nil,
- 559, 559, 559, 559, 559, 559, 559, 559, 559, 559,
- 559, 559, 559, 559, nil, 559, 559, nil, 559, 559,
- 559, 421, 421, 421, 421, 421, 421, 421, nil, nil,
- 421, 421, nil, nil, nil, nil, nil, 421, 421, nil,
- 559, nil, nil, 559, nil, nil, 559, 559, nil, nil,
- 559, nil, 559, 421, nil, 421, 559, 421, 421, 421,
- 421, 421, 421, 421, 559, 421, nil, nil, nil, 559,
- 559, 559, 559, 559, 559, nil, nil, nil, 559, 559,
- 588, 588, 588, 588, 588, 588, nil, nil, nil, 588,
- 588, nil, nil, nil, 588, nil, 588, 588, 588, 588,
- 588, 588, 588, nil, nil, nil, nil, 588, 588, 588,
- 588, 588, 588, 588, nil, nil, 588, nil, nil, nil,
- nil, nil, 588, 588, 588, 588, 588, 588, 588, 588,
- 588, 588, 588, 588, 588, 588, nil, 588, 588, nil,
- 588, 588, 588, 422, 422, 422, 422, 422, 422, 422,
- 422, nil, 422, 422, nil, nil, nil, nil, nil, 422,
- 422, nil, 588, nil, nil, 588, nil, nil, 588, 588,
- nil, nil, 588, nil, 588, 422, nil, 422, 588, 422,
- 422, 422, 422, 422, 422, 422, 588, 422, nil, nil,
- nil, 588, 588, 588, 588, 588, 588, nil, nil, nil,
- 588, 588, 589, 589, 589, 589, 589, 589, nil, nil,
- nil, 589, 589, nil, nil, nil, 589, nil, 589, 589,
- 589, 589, 589, 589, 589, nil, nil, nil, nil, 589,
- 589, 589, 589, 589, 589, 589, nil, nil, 589, nil,
- nil, nil, nil, nil, 589, 589, 589, 589, 589, 589,
- 589, 589, 589, 589, 589, 589, 589, 589, nil, 589,
- 589, nil, 589, 589, 589, 406, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 406, 406, nil, 589, nil, nil, 589, nil, nil,
- 589, 589, nil, nil, 589, nil, 589, 406, nil, 406,
- 589, 406, 406, 406, 406, nil, nil, nil, 589, nil,
- nil, nil, nil, 589, 589, 589, 589, 589, 589, nil,
- nil, nil, 589, 589, 606, 606, 606, 606, 606, 606,
- nil, nil, nil, 606, 606, nil, nil, nil, 606, nil,
- 606, 606, 606, 606, 606, 606, 606, nil, nil, nil,
- nil, 606, 606, 606, 606, 606, 606, 606, nil, nil,
- 606, nil, nil, nil, nil, nil, 606, 606, 606, 606,
- 606, 606, 606, 606, 606, 606, 606, 606, 606, 606,
- nil, 606, 606, nil, 606, 606, 606, 407, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 407, 407, nil, 606, nil, nil, 606,
- nil, nil, 606, 606, nil, nil, 606, nil, 606, 407,
- nil, 407, 606, 407, 407, 407, 407, nil, nil, nil,
- 606, nil, nil, nil, nil, 606, 606, 606, 606, 606,
- 606, nil, nil, nil, 606, 606, 639, 639, 639, 639,
- 639, 639, nil, nil, nil, 639, 639, nil, nil, nil,
- 639, nil, 639, 639, 639, 639, 639, 639, 639, nil,
- nil, nil, nil, 639, 639, 639, 639, 639, 639, 639,
- nil, nil, 639, nil, nil, nil, nil, nil, 639, 639,
- 639, 639, 639, 639, 639, 639, 639, 639, 639, 639,
- 639, 639, nil, 639, 639, nil, 639, 639, 639, 408,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 408, 408, nil, 639, nil,
- nil, 639, nil, nil, 639, 639, nil, nil, 639, nil,
- 639, 408, nil, nil, 639, 408, 408, 408, 408, nil,
- nil, nil, 639, nil, nil, nil, nil, 639, 639, 639,
- 639, 639, 639, nil, nil, nil, 639, 639, 644, 644,
- 644, 644, 644, 644, nil, nil, nil, 644, 644, nil,
- nil, nil, 644, nil, 644, 644, 644, 644, 644, 644,
- 644, nil, nil, nil, nil, 644, 644, 644, 644, 644,
- 644, 644, nil, nil, 644, nil, nil, nil, nil, nil,
- 644, 644, 644, 644, 644, 644, 644, 644, 644, 644,
- 644, 644, 644, 644, nil, 644, 644, nil, 644, 644,
- 644, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 644, nil, nil, 644, nil, nil, 644, 644, nil, nil,
- 644, nil, 644, nil, nil, nil, 644, nil, nil, nil,
- nil, nil, nil, nil, 644, nil, nil, nil, nil, 644,
- 644, 644, 644, 644, 644, nil, nil, nil, 644, 644,
- 671, 671, 671, 671, 671, 671, nil, nil, nil, 671,
- 671, nil, nil, nil, 671, nil, 671, 671, 671, 671,
- 671, 671, 671, nil, nil, nil, nil, 671, 671, 671,
- 671, 671, 671, 671, nil, nil, 671, nil, nil, nil,
- nil, nil, 671, 671, 671, 671, 671, 671, 671, 671,
- 671, 671, 671, 671, 671, 671, nil, 671, 671, nil,
- 671, 671, 671, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 671, nil, nil, 671, nil, nil, 671, 671,
- nil, nil, 671, nil, 671, nil, nil, nil, 671, nil,
- nil, nil, nil, nil, nil, nil, 671, nil, nil, nil,
- nil, 671, 671, 671, 671, 671, 671, nil, nil, nil,
- 671, 671, 706, 706, 706, 706, 706, 706, nil, nil,
- nil, 706, 706, nil, nil, nil, 706, nil, 706, 706,
- 706, 706, 706, 706, 706, nil, nil, nil, nil, 706,
- 706, 706, 706, 706, 706, 706, nil, nil, 706, nil,
- nil, nil, nil, nil, 706, 706, 706, 706, 706, 706,
- 706, 706, 706, 706, 706, 706, 706, 706, nil, 706,
- 706, nil, 706, 706, 706, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 706, nil, nil, 706, nil, nil,
- 706, 706, nil, nil, 706, nil, 706, nil, nil, nil,
- 706, nil, nil, nil, nil, nil, nil, nil, 706, nil,
- nil, nil, nil, 706, 706, 706, 706, 706, 706, nil,
- nil, nil, 706, 706, 724, 724, 724, 724, 724, 724,
- nil, nil, nil, 724, 724, nil, nil, nil, 724, nil,
- 724, 724, 724, 724, 724, 724, 724, nil, nil, nil,
- nil, 724, 724, 724, 724, 724, 724, 724, nil, nil,
- 724, nil, nil, nil, nil, nil, 724, 724, 724, 724,
- 724, 724, 724, 724, 724, 724, 724, 724, 724, 724,
- nil, 724, 724, nil, 724, 724, 724, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 724, nil, nil, 724,
- nil, nil, 724, 724, nil, nil, 724, nil, 724, nil,
- nil, nil, 724, nil, nil, nil, nil, nil, nil, nil,
- 724, nil, nil, nil, nil, 724, 724, 724, 724, 724,
- 724, nil, nil, nil, 724, 724, 736, 736, 736, 736,
- 736, 736, nil, nil, nil, 736, 736, nil, nil, nil,
- 736, nil, 736, 736, 736, 736, 736, 736, 736, nil,
- nil, nil, nil, 736, 736, 736, 736, 736, 736, 736,
- nil, nil, 736, nil, nil, nil, nil, nil, 736, 736,
- 736, 736, 736, 736, 736, 736, 736, 736, 736, 736,
- 736, 736, nil, 736, 736, nil, 736, 736, 736, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 736, nil,
- nil, 736, nil, nil, 736, 736, nil, nil, 736, nil,
- 736, nil, nil, nil, 736, nil, nil, nil, nil, nil,
- nil, nil, 736, nil, nil, nil, nil, 736, 736, 736,
- 736, 736, 736, nil, nil, nil, 736, 736, 737, 737,
- 737, 737, 737, 737, nil, nil, nil, 737, 737, nil,
- nil, nil, 737, nil, 737, 737, 737, 737, 737, 737,
- 737, nil, nil, nil, nil, 737, 737, 737, 737, 737,
- 737, 737, nil, nil, 737, nil, nil, nil, nil, nil,
- 737, 737, 737, 737, 737, 737, 737, 737, 737, 737,
- 737, 737, 737, 737, nil, 737, 737, nil, 737, 737,
- 737, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 737, nil, nil, 737, nil, nil, 737, 737, nil, nil,
- 737, nil, 737, nil, nil, nil, 737, nil, nil, nil,
- nil, nil, nil, nil, 737, nil, nil, nil, nil, 737,
- 737, 737, 737, 737, 737, nil, nil, nil, 737, 737,
- 741, 741, 741, 741, 741, 741, nil, nil, nil, 741,
- 741, nil, nil, nil, 741, nil, 741, 741, 741, 741,
- 741, 741, 741, nil, nil, nil, nil, 741, 741, 741,
- 741, 741, 741, 741, nil, nil, 741, nil, nil, nil,
- nil, nil, 741, 741, 741, 741, 741, 741, 741, 741,
- 741, 741, 741, 741, 741, 741, nil, 741, 741, nil,
- 741, 741, 741, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 741, nil, nil, 741, nil, nil, 741, 741,
- nil, nil, 741, nil, 741, nil, nil, nil, 741, nil,
- nil, nil, nil, nil, nil, nil, 741, nil, nil, nil,
- nil, 741, 741, 741, 741, 741, 741, nil, nil, nil,
- 741, 741, 748, 748, 748, 748, 748, 748, nil, nil,
- nil, 748, 748, nil, nil, nil, 748, nil, 748, 748,
- 748, 748, 748, 748, 748, nil, nil, nil, nil, 748,
- 748, 748, 748, 748, 748, 748, nil, nil, 748, nil,
- nil, nil, nil, nil, 748, 748, 748, 748, 748, 748,
- 748, 748, 748, 748, 748, 748, 748, 748, nil, 748,
- 748, nil, 748, 748, 748, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 748, nil, nil, 748, nil, nil,
- 748, 748, nil, nil, 748, nil, 748, nil, nil, nil,
- 748, nil, nil, nil, nil, nil, nil, nil, 748, nil,
- nil, nil, nil, 748, 748, 748, 748, 748, 748, nil,
- nil, nil, 748, 748, 794, 794, 794, 794, 794, 794,
- nil, nil, nil, 794, 794, nil, nil, nil, 794, nil,
- 794, 794, 794, 794, 794, 794, 794, nil, nil, nil,
- nil, 794, 794, 794, 794, 794, 794, 794, nil, nil,
- 794, nil, nil, nil, nil, nil, 794, 794, 794, 794,
- 794, 794, 794, 794, 794, 794, 794, 794, 794, 794,
- nil, 794, 794, nil, 794, 794, 794, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 794, nil, nil, 794,
- nil, nil, 794, 794, nil, nil, 794, nil, 794, nil,
- nil, nil, 794, nil, nil, nil, nil, nil, nil, nil,
- 794, nil, nil, nil, nil, 794, 794, 794, 794, 794,
- 794, nil, nil, nil, 794, 794, 838, 838, 838, 838,
- 838, 838, nil, nil, nil, 838, 838, nil, nil, nil,
- 838, nil, 838, 838, 838, 838, 838, 838, 838, nil,
- nil, nil, nil, 838, 838, 838, 838, 838, 838, 838,
- nil, nil, 838, nil, nil, nil, nil, nil, 838, 838,
- 838, 838, 838, 838, 838, 838, 838, 838, 838, 838,
- 838, 838, nil, 838, 838, nil, 838, 838, 838, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 838, nil,
- nil, 838, nil, nil, 838, 838, nil, nil, 838, nil,
- 838, nil, nil, nil, 838, nil, nil, nil, nil, nil,
- nil, nil, 838, nil, nil, nil, nil, 838, 838, 838,
- 838, 838, 838, nil, nil, nil, 838, 838, 845, 845,
- 845, 845, 845, 845, nil, nil, nil, 845, 845, nil,
- nil, nil, 845, nil, 845, 845, 845, 845, 845, 845,
- 845, nil, nil, nil, nil, 845, 845, 845, 845, 845,
- 845, 845, nil, nil, 845, nil, nil, nil, nil, nil,
- 845, 845, 845, 845, 845, 845, 845, 845, 845, 845,
- 845, 845, 845, 845, nil, 845, 845, nil, 845, 845,
- 845, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 845, nil, nil, 845, nil, nil, 845, 845, nil, nil,
- 845, nil, 845, nil, nil, nil, 845, nil, nil, nil,
- nil, nil, nil, nil, 845, nil, nil, nil, nil, 845,
- 845, 845, 845, 845, 845, nil, nil, nil, 845, 845,
- 852, 852, 852, 852, 852, 852, nil, nil, nil, 852,
- 852, nil, nil, nil, 852, nil, 852, 852, 852, 852,
- 852, 852, 852, nil, nil, nil, nil, 852, 852, 852,
- 852, 852, 852, 852, nil, nil, 852, nil, nil, nil,
- nil, nil, 852, 852, 852, 852, 852, 852, 852, 852,
- 852, 852, 852, 852, 852, 852, nil, 852, 852, nil,
- 852, 852, 852, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 852, nil, nil, 852, nil, nil, 852, 852,
- nil, nil, 852, nil, 852, nil, nil, nil, 852, nil,
- nil, nil, nil, nil, nil, nil, 852, nil, nil, nil,
- nil, 852, 852, 852, 852, 852, 852, nil, nil, nil,
- 852, 852, 5, 5, 5, 5, 5, nil, nil, nil,
- 5, 5, nil, nil, nil, 5, nil, 5, 5, 5,
- 5, 5, 5, 5, nil, nil, nil, nil, 5, 5,
- 5, 5, 5, 5, 5, nil, nil, 5, nil, nil,
- nil, nil, nil, 5, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, 5, nil, 5, 5,
- nil, 5, 5, 5, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 5, nil, nil, 5, nil, nil, 5,
- 5, nil, nil, 5, nil, 5, nil, nil, nil, 5,
- nil, nil, nil, nil, nil, nil, nil, 5, nil, nil,
- nil, nil, 5, 5, 5, 5, 5, 5, nil, nil,
- nil, 5, 5, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, 6, 6, 6, 6, nil, nil, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, 6, nil,
- nil, nil, nil, nil, 6, 6, 6, 6, 6, 6,
- 6, 6, 6, nil, 6, nil, nil, nil, nil, nil,
- nil, nil, 6, 6, nil, 6, 6, 6, 6, nil,
- 6, 6, nil, nil, 6, nil, nil, nil, nil, 6,
- 6, 6, 6, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 6, 6, nil, 6,
- 6, 6, 6, 6, 6, 6, 6, 6, nil, 6,
- nil, nil, 6, 6, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 6, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, nil, nil,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- nil, nil, nil, nil, nil, 7, 7, 7, 7, 7,
- 7, 7, 7, nil, nil, 7, nil, nil, nil, nil,
- nil, nil, nil, 7, 7, nil, 7, 7, 7, 7,
- nil, 7, 7, nil, nil, 7, nil, nil, nil, nil,
- 7, 7, 7, 7, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 7, 7, nil,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, nil,
- 7, nil, nil, 7, 7, nil, nil, 17, 17, 17,
- nil, 17, nil, nil, 7, 17, 17, nil, nil, nil,
- 17, nil, 17, 17, 17, 17, 17, 17, 17, nil,
- nil, nil, nil, 17, 17, 17, 17, 17, 17, 17,
- nil, nil, 17, nil, nil, nil, nil, nil, nil, 17,
- nil, nil, 17, 17, 17, 17, 17, 17, 17, 17,
- 17, 17, nil, 17, 17, nil, 17, 17, 17, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 17, nil,
- nil, 17, nil, nil, 17, 17, nil, nil, 17, nil,
- nil, nil, nil, nil, 17, nil, nil, nil, nil, nil,
- nil, nil, 17, nil, nil, nil, nil, 17, 17, 17,
- 17, 17, 17, nil, nil, nil, 17, 17, 18, 18,
- 18, nil, 18, nil, nil, nil, 18, 18, nil, nil,
- nil, 18, nil, 18, 18, 18, 18, 18, 18, 18,
- nil, nil, nil, nil, 18, 18, 18, 18, 18, 18,
- 18, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 18, nil, nil, 18, 18, 18, 18, 18, 18, 18,
- 18, 18, 18, nil, 18, 18, nil, 18, 18, 18,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 18,
- nil, nil, 18, nil, nil, 18, 18, nil, nil, 18,
- nil, nil, nil, nil, nil, 18, nil, nil, nil, nil,
- nil, nil, nil, 18, nil, nil, nil, nil, 18, 18,
- 18, 18, 18, 18, nil, nil, nil, 18, 18, 22,
- 22, 22, nil, 22, nil, nil, nil, 22, 22, nil,
- nil, nil, 22, nil, 22, 22, 22, 22, 22, 22,
- 22, nil, nil, nil, nil, 22, 22, 22, 22, 22,
- 22, 22, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 22, nil, nil, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 22, nil, 22, 22, nil, 22, 22,
- 22, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 22, nil, nil, 22, nil, nil, 22, 22, nil, nil,
- 22, nil, 22, nil, 22, nil, 22, nil, nil, nil,
- nil, nil, nil, nil, 22, nil, nil, nil, nil, 22,
- 22, 22, 22, 22, 22, nil, nil, nil, 22, 22,
- 23, 23, 23, nil, 23, nil, nil, nil, 23, 23,
- nil, nil, nil, 23, nil, 23, 23, 23, 23, 23,
- 23, 23, nil, nil, nil, nil, 23, 23, 23, 23,
- 23, 23, 23, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 23, nil, nil, 23, 23, 23, 23, 23,
- 23, 23, 23, 23, 23, nil, 23, 23, nil, 23,
- 23, 23, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 23, nil, nil, 23, nil, nil, 23, 23, nil,
- nil, 23, nil, 23, nil, 23, nil, 23, nil, nil,
- nil, nil, nil, nil, nil, 23, nil, nil, nil, nil,
- 23, 23, 23, 23, 23, 23, nil, nil, nil, 23,
- 23, 24, 24, 24, nil, 24, nil, nil, nil, 24,
- 24, nil, nil, nil, 24, nil, 24, 24, 24, 24,
- 24, 24, 24, nil, nil, nil, nil, 24, 24, 24,
- 24, 24, 24, 24, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 24, nil, nil, 24, 24, 24, 24,
- 24, 24, 24, 24, 24, 24, nil, 24, 24, nil,
- 24, 24, 24, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 24, nil, nil, 24, nil, nil, 24, 24,
- nil, nil, 24, nil, 24, nil, 24, nil, 24, nil,
- nil, nil, nil, nil, nil, nil, 24, nil, nil, nil,
- nil, 24, 24, 24, 24, 24, 24, nil, nil, nil,
- 24, 24, 27, 27, 27, nil, 27, nil, nil, nil,
- 27, 27, nil, nil, nil, 27, nil, 27, 27, 27,
- 27, 27, 27, 27, nil, nil, nil, nil, 27, 27,
- 27, 27, 27, 27, 27, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 27, nil, nil, 27, 27, 27,
- 27, 27, 27, 27, 27, 27, 27, nil, 27, 27,
- nil, 27, 27, 27, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 27, nil, nil, 27, 27, nil, 27,
- 27, nil, nil, 27, nil, 27, nil, 27, nil, 27,
- nil, nil, nil, nil, nil, nil, nil, 27, nil, nil,
- nil, nil, 27, 27, 27, 27, 27, 27, nil, nil,
- nil, 27, 27, 28, 28, 28, nil, 28, nil, nil,
- nil, 28, 28, nil, nil, nil, 28, nil, 28, 28,
- 28, 28, 28, 28, 28, nil, nil, nil, nil, 28,
- 28, 28, 28, 28, 28, 28, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 28, nil, nil, 28, 28,
- 28, 28, 28, 28, 28, 28, 28, 28, nil, 28,
- 28, nil, 28, 28, 28, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 28, nil, nil, 28, 28, nil,
- 28, 28, nil, nil, 28, nil, 28, nil, 28, nil,
- 28, nil, nil, nil, nil, nil, nil, nil, 28, nil,
- nil, nil, nil, 28, 28, 28, 28, 28, 28, nil,
- nil, nil, 28, 28, 31, 31, 31, nil, 31, nil,
- nil, nil, 31, 31, nil, nil, nil, 31, nil, 31,
- 31, 31, 31, 31, 31, 31, nil, nil, nil, nil,
- 31, 31, 31, 31, 31, 31, 31, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 31, nil, nil, 31,
- 31, 31, 31, 31, 31, 31, 31, 31, 31, nil,
- 31, 31, nil, nil, nil, 31, nil, 828, 828, 828,
- 828, 828, 828, 828, 828, 828, 828, 828, nil, 828,
- 828, nil, nil, 828, 828, 31, nil, nil, 31, nil,
- nil, 31, 31, nil, nil, 31, nil, 31, nil, 828,
- nil, 828, nil, 828, 828, 828, 828, 828, 828, 828,
- nil, 828, nil, nil, 31, 31, 31, 31, 31, 31,
- nil, nil, nil, 31, 31, 32, 32, 32, 828, 32,
- 828, nil, nil, 32, 32, nil, nil, nil, 32, nil,
- 32, 32, 32, 32, 32, 32, 32, nil, nil, nil,
- nil, 32, 32, 32, 32, 32, 32, 32, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 32, nil, nil,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- nil, 32, 32, nil, nil, nil, 32, nil, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, nil,
- 19, 19, nil, nil, 19, 19, 32, nil, nil, 32,
- nil, nil, 32, 32, nil, nil, 32, nil, nil, nil,
- 19, nil, 19, nil, 19, 19, 19, 19, 19, 19,
- 19, nil, 19, nil, nil, 32, 32, 32, 32, 32,
- 32, nil, nil, nil, 32, 32, 38, 38, 38, 19,
- 38, nil, nil, nil, 38, 38, nil, nil, nil, 38,
- nil, 38, 38, 38, 38, 38, 38, 38, nil, nil,
- nil, nil, 38, 38, 38, 38, 38, 38, 38, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 38, nil,
- nil, 38, 38, 38, 38, 38, 38, 38, 38, 38,
- 38, nil, 38, 38, nil, 38, 38, 38, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 38, nil, nil,
- 38, nil, nil, 38, 38, nil, nil, 38, nil, nil,
- nil, nil, nil, 38, nil, nil, nil, nil, nil, nil,
- nil, 38, nil, nil, nil, nil, 38, 38, 38, 38,
- 38, 38, nil, nil, nil, 38, 38, 39, 39, 39,
- nil, 39, nil, nil, nil, 39, 39, nil, nil, nil,
- 39, nil, 39, 39, 39, 39, 39, 39, 39, nil,
- nil, nil, nil, 39, 39, 39, 39, 39, 39, 39,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 39,
- nil, nil, 39, 39, 39, 39, 39, 39, 39, 39,
- 39, 39, nil, 39, 39, nil, 39, 39, 39, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 39, nil,
- nil, 39, nil, nil, 39, 39, nil, nil, 39, nil,
- nil, nil, nil, nil, 39, nil, nil, nil, nil, nil,
- nil, nil, 39, nil, nil, nil, nil, 39, 39, 39,
- 39, 39, 39, nil, nil, nil, 39, 39, 40, 40,
- 40, nil, 40, nil, nil, nil, 40, 40, nil, nil,
- nil, 40, nil, 40, 40, 40, 40, 40, 40, 40,
- nil, nil, nil, nil, 40, 40, 40, 40, 40, 40,
- 40, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 40, nil, nil, 40, 40, 40, 40, 40, 40, 40,
- 40, 40, 40, nil, 40, 40, nil, 40, 40, 40,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 40,
- nil, nil, 40, nil, nil, 40, 40, nil, nil, 40,
- nil, nil, nil, nil, nil, 40, nil, nil, nil, nil,
- nil, nil, nil, 40, nil, nil, nil, nil, 40, 40,
- 40, 40, 40, 40, nil, nil, nil, 40, 40, 52,
- 52, 52, nil, 52, nil, nil, nil, 52, 52, nil,
- nil, nil, 52, nil, 52, 52, 52, 52, 52, 52,
- 52, nil, nil, nil, nil, 52, 52, 52, 52, 52,
- 52, 52, nil, nil, 52, nil, nil, nil, nil, nil,
- nil, 52, nil, nil, 52, 52, 52, 52, 52, 52,
- 52, 52, 52, 52, nil, 52, 52, nil, 52, 52,
- 52, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 52, nil, nil, 52, nil, nil, 52, 52, nil, nil,
- 52, nil, nil, nil, nil, nil, 52, nil, nil, nil,
- nil, nil, nil, nil, 52, nil, nil, nil, nil, 52,
- 52, 52, 52, 52, 52, nil, nil, nil, 52, 52,
- 53, 53, 53, nil, 53, nil, nil, nil, 53, 53,
- nil, nil, nil, 53, nil, 53, 53, 53, 53, 53,
- 53, 53, nil, nil, nil, nil, 53, 53, 53, 53,
- 53, 53, 53, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 53, nil, nil, 53, 53, 53, 53, 53,
- 53, 53, 53, 53, 53, nil, 53, 53, nil, 53,
- 53, 53, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 53, nil, nil, 53, nil, nil, 53, 53, nil,
- nil, 53, nil, 53, nil, nil, nil, 53, nil, nil,
- nil, nil, nil, nil, nil, 53, nil, nil, nil, nil,
- 53, 53, 53, 53, 53, 53, nil, nil, nil, 53,
- 53, 54, 54, 54, nil, 54, nil, nil, nil, 54,
- 54, nil, nil, nil, 54, nil, 54, 54, 54, 54,
- 54, 54, 54, nil, nil, nil, nil, 54, 54, 54,
- 54, 54, 54, 54, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 54, nil, nil, 54, 54, 54, 54,
- 54, 54, 54, 54, 54, 54, nil, 54, 54, nil,
- 54, 54, 54, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 54, nil, nil, 54, nil, nil, 54, 54,
- nil, nil, 54, nil, nil, nil, nil, nil, 54, nil,
- nil, nil, nil, nil, nil, nil, 54, nil, nil, nil,
- nil, 54, 54, 54, 54, 54, 54, nil, nil, nil,
- 54, 54, 56, 56, 56, nil, 56, nil, nil, nil,
- 56, 56, nil, nil, nil, 56, nil, 56, 56, 56,
- 56, 56, 56, 56, nil, nil, nil, nil, 56, 56,
- 56, 56, 56, 56, 56, nil, nil, 56, nil, nil,
- nil, nil, nil, nil, 56, nil, nil, 56, 56, 56,
- 56, 56, 56, 56, 56, 56, 56, nil, 56, 56,
- nil, 56, 56, 56, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 56, nil, nil, 56, nil, nil, 56,
- 56, nil, nil, 56, nil, nil, nil, nil, nil, 56,
- nil, nil, nil, nil, nil, nil, nil, 56, nil, nil,
- nil, nil, 56, 56, 56, 56, 56, 56, nil, nil,
- nil, 56, 56, 57, 57, 57, nil, 57, nil, nil,
- nil, 57, 57, nil, nil, nil, 57, nil, 57, 57,
- 57, 57, 57, 57, 57, nil, nil, nil, nil, 57,
- 57, 57, 57, 57, 57, 57, nil, nil, 57, nil,
- nil, nil, nil, nil, nil, 57, nil, nil, 57, 57,
- 57, 57, 57, 57, 57, 57, 57, 57, nil, 57,
- 57, nil, 57, 57, 57, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 57, nil, nil, 57, nil, nil,
- 57, 57, nil, nil, 57, nil, nil, nil, nil, nil,
- 57, nil, nil, nil, nil, nil, nil, nil, 57, nil,
- nil, nil, nil, 57, 57, 57, 57, 57, 57, nil,
- nil, nil, 57, 57, 61, 61, 61, nil, 61, nil,
- nil, nil, 61, 61, nil, nil, nil, 61, nil, 61,
- 61, 61, 61, 61, 61, 61, nil, nil, nil, nil,
- 61, 61, 61, 61, 61, 61, 61, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 61, nil, nil, 61,
- 61, 61, 61, 61, 61, 61, 61, 61, 61, nil,
- 61, 61, nil, nil, nil, 61, nil, 237, 237, 237,
- 237, 237, 237, 237, 237, 237, 237, 237, nil, 237,
- 237, nil, nil, 237, 237, 61, nil, nil, 61, nil,
- nil, 61, 61, nil, nil, 61, nil, 61, nil, 237,
- nil, 237, nil, 237, 237, 237, 237, 237, 237, 237,
- nil, 237, nil, nil, 61, 61, 61, 61, 61, 61,
- nil, nil, nil, 61, 61, 62, 62, 62, 237, 62,
- nil, nil, nil, 62, 62, nil, nil, nil, 62, nil,
- 62, 62, 62, 62, 62, 62, 62, nil, nil, nil,
- nil, 62, 62, 62, 62, 62, 62, 62, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 62, nil, nil,
- 62, 62, 62, 62, 62, 62, 62, 62, 62, 62,
- nil, 62, 62, nil, nil, nil, 62, nil, 374, 374,
- 374, 374, 374, 374, 374, 374, 374, 374, 374, nil,
- 374, 374, nil, 62, 374, 374, 62, nil, nil, 62,
- nil, nil, 62, 62, nil, nil, 62, nil, nil, nil,
- 374, nil, 374, nil, 374, 374, 374, 374, 374, 374,
- 374, nil, 374, nil, nil, 62, 62, 62, 62, 62,
- 62, nil, nil, nil, 62, 62, 63, 63, 63, 374,
- 63, nil, nil, nil, 63, 63, nil, nil, nil, 63,
- nil, 63, 63, 63, 63, 63, 63, 63, nil, nil,
- nil, nil, 63, 63, 63, 63, 63, 63, 63, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 63, nil,
- nil, 63, 63, 63, 63, 63, 63, 63, 63, 63,
- 63, nil, 63, 63, nil, nil, nil, 63, nil, 388,
- 388, 388, 388, 388, 388, 388, 388, 388, 388, 388,
- nil, 388, 388, nil, nil, 388, 388, 63, nil, nil,
- 63, nil, nil, 63, 63, nil, nil, 63, nil, nil,
- nil, 388, nil, 388, nil, 388, 388, 388, 388, 388,
- 388, 388, nil, 388, nil, nil, 63, 63, 63, 63,
- 63, 63, nil, nil, nil, 63, 63, 82, 82, 82,
- 388, 82, nil, nil, nil, 82, 82, nil, nil, nil,
- 82, nil, 82, 82, 82, 82, 82, 82, 82, nil,
- 82, nil, nil, 82, 82, 82, 82, 82, 82, 82,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 82,
- nil, nil, 82, 82, 82, 82, 82, 82, 82, 82,
- 82, 82, nil, 82, 82, nil, 82, 82, 82, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 82, nil,
- nil, 82, 82, nil, 82, 82, nil, nil, 82, nil,
- 82, nil, 82, nil, 82, nil, nil, nil, nil, nil,
- nil, nil, 82, nil, 82, nil, nil, 82, 82, 82,
- 82, 82, 82, nil, nil, nil, 82, 82, 86, 86,
- 86, nil, 86, nil, nil, nil, 86, 86, nil, nil,
- nil, 86, nil, 86, 86, 86, 86, 86, 86, 86,
- nil, 86, nil, nil, 86, 86, 86, 86, 86, 86,
- 86, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 86, nil, nil, 86, 86, 86, 86, 86, 86, 86,
- 86, 86, 86, nil, 86, 86, nil, 86, 86, 86,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 86,
- nil, nil, 86, 86, nil, 86, 86, nil, nil, 86,
- nil, 86, nil, 86, nil, 86, nil, nil, nil, nil,
- nil, nil, nil, 86, nil, 86, nil, nil, 86, 86,
- 86, 86, 86, 86, nil, nil, nil, 86, 86, 101,
- 101, 101, nil, 101, nil, nil, nil, 101, 101, nil,
- nil, nil, 101, nil, 101, 101, 101, 101, 101, 101,
- 101, nil, nil, nil, nil, 101, 101, 101, 101, 101,
- 101, 101, nil, nil, 101, nil, nil, nil, nil, nil,
- nil, 101, nil, nil, 101, 101, 101, 101, 101, 101,
- 101, 101, 101, 101, nil, 101, 101, nil, 101, 101,
- 101, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 101, nil, nil, 101, nil, nil, 101, 101, nil, nil,
- 101, nil, nil, nil, nil, nil, 101, nil, nil, nil,
- nil, nil, nil, nil, 101, nil, nil, nil, nil, 101,
- 101, 101, 101, 101, 101, nil, nil, nil, 101, 101,
- 102, 102, 102, nil, 102, nil, nil, nil, 102, 102,
- nil, nil, nil, 102, nil, 102, 102, 102, 102, 102,
- 102, 102, nil, nil, nil, nil, 102, 102, 102, 102,
- 102, 102, 102, nil, nil, 102, nil, nil, nil, nil,
- nil, nil, 102, nil, nil, 102, 102, 102, 102, 102,
- 102, 102, 102, 102, 102, nil, 102, 102, nil, 102,
- 102, 102, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 102, nil, nil, 102, nil, nil, 102, 102, nil,
- nil, 102, nil, nil, nil, nil, nil, 102, nil, nil,
- nil, nil, nil, nil, nil, 102, nil, nil, nil, nil,
- 102, 102, 102, 102, 102, 102, nil, nil, nil, 102,
- 102, 103, 103, 103, nil, 103, nil, nil, nil, 103,
- 103, nil, nil, nil, 103, nil, 103, 103, 103, 103,
- 103, 103, 103, nil, nil, nil, nil, 103, 103, 103,
- 103, 103, 103, 103, nil, nil, 103, nil, nil, nil,
- nil, nil, nil, 103, nil, nil, 103, 103, 103, 103,
- 103, 103, 103, 103, 103, 103, nil, 103, 103, nil,
- 103, 103, 103, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 103, nil, nil, 103, nil, nil, 103, 103,
- nil, nil, 103, nil, nil, nil, nil, nil, 103, nil,
- nil, nil, nil, nil, nil, nil, 103, nil, nil, nil,
- nil, 103, 103, 103, 103, 103, 103, nil, nil, nil,
- 103, 103, 104, 104, 104, nil, 104, nil, nil, nil,
- 104, 104, nil, nil, nil, 104, nil, 104, 104, 104,
- 104, 104, 104, 104, nil, nil, nil, nil, 104, 104,
- 104, 104, 104, 104, 104, nil, nil, 104, nil, nil,
- nil, nil, nil, nil, 104, nil, nil, 104, 104, 104,
- 104, 104, 104, 104, 104, 104, 104, nil, 104, 104,
- nil, 104, 104, 104, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 104, nil, nil, 104, nil, nil, 104,
- 104, nil, nil, 104, nil, nil, nil, nil, nil, 104,
- nil, nil, nil, nil, nil, nil, nil, 104, nil, nil,
- nil, nil, 104, 104, 104, 104, 104, 104, nil, nil,
- nil, 104, 104, 105, 105, 105, 105, 105, nil, nil,
- nil, 105, 105, nil, nil, nil, 105, nil, 105, 105,
- 105, 105, 105, 105, 105, nil, nil, nil, nil, 105,
- 105, 105, 105, 105, 105, 105, nil, nil, 105, nil,
- nil, nil, nil, nil, 105, 105, 105, 105, 105, 105,
- 105, 105, 105, 105, 105, 105, 105, 105, nil, 105,
- 105, nil, 105, 105, 105, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 105, nil, nil, 105, nil, nil,
- 105, 105, nil, nil, 105, nil, 105, nil, nil, nil,
- 105, nil, nil, nil, nil, nil, nil, nil, 105, nil,
- nil, nil, nil, 105, 105, 105, 105, 105, 105, nil,
- nil, nil, 105, 105, 188, 188, 188, nil, 188, nil,
- nil, nil, 188, 188, nil, nil, nil, 188, nil, 188,
- 188, 188, 188, 188, 188, 188, nil, nil, nil, nil,
- 188, 188, 188, 188, 188, 188, 188, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 188, nil, nil, 188,
- 188, 188, 188, 188, 188, 188, 188, 188, 188, nil,
- 188, 188, nil, 188, 188, 188, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 188, nil, nil, 188, nil,
- nil, 188, 188, nil, nil, 188, nil, 188, nil, nil,
- nil, 188, nil, nil, nil, nil, nil, nil, nil, 188,
- nil, nil, nil, nil, 188, 188, 188, 188, 188, 188,
- nil, nil, nil, 188, 188, 189, 189, 189, nil, 189,
- nil, nil, nil, 189, 189, nil, nil, nil, 189, nil,
- 189, 189, 189, 189, 189, 189, 189, nil, nil, nil,
- nil, 189, 189, 189, 189, 189, 189, 189, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 189, nil, nil,
- 189, 189, 189, 189, 189, 189, 189, 189, 189, 189,
- nil, 189, 189, nil, 189, 189, 189, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 189, nil, nil, 189,
- nil, nil, 189, 189, nil, nil, 189, nil, 189, nil,
- nil, nil, 189, nil, nil, nil, nil, nil, nil, nil,
- 189, nil, nil, nil, nil, 189, 189, 189, 189, 189,
- 189, nil, nil, nil, 189, 189, 190, 190, 190, nil,
- 190, nil, nil, nil, 190, 190, nil, nil, nil, 190,
- nil, 190, 190, 190, 190, 190, 190, 190, nil, nil,
- nil, nil, 190, 190, 190, 190, 190, 190, 190, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 190, nil,
- nil, 190, 190, 190, 190, 190, 190, 190, 190, 190,
- 190, nil, 190, 190, nil, 190, 190, 190, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 190, nil, nil,
- 190, nil, nil, 190, 190, nil, nil, 190, nil, nil,
- nil, nil, nil, 190, nil, nil, nil, nil, nil, nil,
- nil, 190, nil, nil, nil, nil, 190, 190, 190, 190,
- 190, 190, nil, nil, nil, 190, 190, 191, 191, 191,
- nil, 191, nil, nil, nil, 191, 191, nil, nil, nil,
- 191, nil, 191, 191, 191, 191, 191, 191, 191, nil,
- nil, nil, nil, 191, 191, 191, 191, 191, 191, 191,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 191,
- nil, nil, 191, 191, 191, 191, 191, 191, 191, 191,
- 191, 191, nil, 191, 191, nil, 191, 191, 191, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 191, nil,
- nil, 191, nil, nil, 191, 191, nil, nil, 191, nil,
- 191, nil, nil, nil, 191, nil, nil, nil, nil, nil,
- nil, nil, 191, nil, nil, nil, nil, 191, 191, 191,
- 191, 191, 191, nil, nil, nil, 191, 191, 194, 194,
- 194, nil, 194, nil, nil, nil, 194, 194, nil, nil,
- nil, 194, nil, 194, 194, 194, 194, 194, 194, 194,
- nil, nil, nil, nil, 194, 194, 194, 194, 194, 194,
- 194, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 194, nil, nil, 194, 194, 194, 194, 194, 194, 194,
- 194, 194, 194, nil, 194, 194, nil, 194, 194, 194,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 194,
- nil, nil, 194, nil, nil, 194, 194, nil, nil, 194,
- nil, nil, nil, nil, nil, 194, nil, nil, nil, nil,
- nil, nil, nil, 194, nil, nil, nil, nil, 194, 194,
- 194, 194, 194, 194, nil, nil, nil, 194, 194, 195,
- 195, 195, nil, 195, nil, nil, nil, 195, 195, nil,
- nil, nil, 195, nil, 195, 195, 195, 195, 195, 195,
- 195, nil, nil, nil, nil, 195, 195, 195, 195, 195,
- 195, 195, nil, nil, 195, nil, nil, nil, nil, nil,
- nil, 195, nil, nil, 195, 195, 195, 195, 195, 195,
- 195, 195, 195, 195, nil, 195, 195, nil, 195, 195,
- 195, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 195, nil, nil, 195, nil, nil, 195, 195, nil, nil,
- 195, nil, nil, nil, nil, nil, 195, nil, nil, nil,
- nil, nil, nil, nil, 195, nil, nil, nil, nil, 195,
- 195, 195, 195, 195, 195, nil, nil, nil, 195, 195,
- 196, 196, 196, nil, 196, nil, nil, nil, 196, 196,
- nil, nil, nil, 196, nil, 196, 196, 196, 196, 196,
- 196, 196, nil, nil, nil, nil, 196, 196, 196, 196,
- 196, 196, 196, nil, nil, 196, nil, nil, nil, nil,
- nil, nil, 196, nil, nil, 196, 196, 196, 196, 196,
- 196, 196, 196, 196, 196, nil, 196, 196, nil, 196,
- 196, 196, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 196, nil, nil, 196, nil, nil, 196, 196, nil,
- nil, 196, nil, nil, nil, nil, nil, 196, nil, nil,
- nil, nil, nil, nil, nil, 196, nil, nil, nil, nil,
- 196, 196, 196, 196, 196, 196, nil, nil, nil, 196,
- 196, 207, 207, 207, nil, 207, nil, nil, nil, 207,
- 207, nil, nil, nil, 207, nil, 207, 207, 207, 207,
- 207, 207, 207, nil, nil, nil, nil, 207, 207, 207,
- 207, 207, 207, 207, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 207, nil, nil, 207, 207, 207, 207,
- 207, 207, 207, 207, 207, 207, nil, 207, 207, nil,
- 207, 207, 207, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 207, nil, nil, 207, nil, nil, 207, 207,
- nil, nil, 207, nil, nil, nil, nil, nil, 207, nil,
- nil, nil, nil, nil, nil, nil, 207, nil, nil, nil,
- nil, 207, 207, 207, 207, 207, 207, nil, nil, nil,
- 207, 207, 208, 208, 208, nil, 208, nil, nil, nil,
- 208, 208, nil, nil, nil, 208, nil, 208, 208, 208,
- 208, 208, 208, 208, nil, nil, nil, nil, 208, 208,
- 208, 208, 208, 208, 208, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 208, nil, nil, 208, 208, 208,
- 208, 208, 208, 208, 208, 208, 208, nil, 208, 208,
- nil, 208, 208, 208, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 208, nil, nil, 208, nil, nil, 208,
- 208, nil, nil, 208, nil, nil, nil, nil, nil, 208,
- nil, nil, nil, nil, nil, nil, nil, 208, nil, nil,
- nil, nil, 208, 208, 208, 208, 208, 208, nil, nil,
- nil, 208, 208, 209, 209, 209, nil, 209, nil, nil,
- nil, 209, 209, nil, nil, nil, 209, nil, 209, 209,
- 209, 209, 209, 209, 209, nil, nil, nil, nil, 209,
- 209, 209, 209, 209, 209, 209, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 209, nil, nil, 209, 209,
- 209, 209, 209, 209, 209, 209, 209, 209, nil, 209,
- 209, nil, 209, 209, 209, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 209, nil, nil, 209, nil, nil,
- 209, 209, nil, nil, 209, nil, nil, nil, nil, nil,
- 209, nil, nil, nil, nil, nil, nil, nil, 209, nil,
- nil, nil, nil, 209, 209, 209, 209, 209, 209, nil,
- nil, nil, 209, 209, 210, 210, 210, nil, 210, nil,
- nil, nil, 210, 210, nil, nil, nil, 210, nil, 210,
- 210, 210, 210, 210, 210, 210, nil, nil, nil, nil,
- 210, 210, 210, 210, 210, 210, 210, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 210, nil, nil, 210,
- 210, 210, 210, 210, 210, 210, 210, 210, 210, nil,
- 210, 210, nil, 210, 210, 210, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 210, nil, nil, 210, nil,
- nil, 210, 210, nil, nil, 210, nil, nil, nil, nil,
- nil, 210, nil, nil, nil, nil, nil, nil, nil, 210,
- nil, nil, nil, nil, 210, 210, 210, 210, 210, 210,
- nil, nil, nil, 210, 210, 211, 211, 211, nil, 211,
- nil, nil, nil, 211, 211, nil, nil, nil, 211, nil,
- 211, 211, 211, 211, 211, 211, 211, nil, nil, nil,
- nil, 211, 211, 211, 211, 211, 211, 211, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 211, nil, nil,
- 211, 211, 211, 211, 211, 211, 211, 211, 211, 211,
- nil, 211, 211, nil, 211, 211, 211, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 211, nil, nil, 211,
- nil, nil, 211, 211, nil, nil, 211, nil, nil, nil,
- nil, nil, 211, nil, nil, nil, nil, nil, nil, nil,
- 211, nil, nil, nil, nil, 211, 211, 211, 211, 211,
- 211, nil, nil, nil, 211, 211, 212, 212, 212, nil,
- 212, nil, nil, nil, 212, 212, nil, nil, nil, 212,
- nil, 212, 212, 212, 212, 212, 212, 212, nil, nil,
- nil, nil, 212, 212, 212, 212, 212, 212, 212, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 212, nil,
- nil, 212, 212, 212, 212, 212, 212, 212, 212, 212,
- 212, nil, 212, 212, nil, 212, 212, 212, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 212, nil, nil,
- 212, nil, nil, 212, 212, nil, nil, 212, nil, nil,
- nil, nil, nil, 212, nil, nil, nil, nil, nil, nil,
- nil, 212, nil, nil, nil, nil, 212, 212, 212, 212,
- 212, 212, nil, nil, nil, 212, 212, 213, 213, 213,
- nil, 213, nil, nil, nil, 213, 213, nil, nil, nil,
- 213, nil, 213, 213, 213, 213, 213, 213, 213, nil,
- nil, nil, nil, 213, 213, 213, 213, 213, 213, 213,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 213,
- nil, nil, 213, 213, 213, 213, 213, 213, 213, 213,
- 213, 213, nil, 213, 213, nil, 213, 213, 213, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 213, nil,
- nil, 213, nil, nil, 213, 213, nil, nil, 213, nil,
- nil, nil, nil, nil, 213, nil, nil, nil, nil, nil,
- nil, nil, 213, nil, nil, nil, nil, 213, 213, 213,
- 213, 213, 213, nil, nil, nil, 213, 213, 214, 214,
- 214, nil, 214, nil, nil, nil, 214, 214, nil, nil,
- nil, 214, nil, 214, 214, 214, 214, 214, 214, 214,
- nil, nil, nil, nil, 214, 214, 214, 214, 214, 214,
- 214, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 214, nil, nil, 214, 214, 214, 214, 214, 214, 214,
- 214, 214, 214, nil, 214, 214, nil, 214, 214, 214,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 214,
- nil, nil, 214, nil, nil, 214, 214, nil, nil, 214,
- nil, nil, nil, nil, nil, 214, nil, nil, nil, nil,
- nil, nil, nil, 214, nil, nil, nil, nil, 214, 214,
- 214, 214, 214, 214, nil, nil, nil, 214, 214, 215,
- 215, 215, nil, 215, nil, nil, nil, 215, 215, nil,
- nil, nil, 215, nil, 215, 215, 215, 215, 215, 215,
- 215, nil, nil, nil, nil, 215, 215, 215, 215, 215,
- 215, 215, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 215, nil, nil, 215, 215, 215, 215, 215, 215,
- 215, 215, 215, 215, nil, 215, 215, nil, 215, 215,
- 215, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 215, nil, nil, 215, nil, nil, 215, 215, nil, nil,
- 215, nil, nil, nil, nil, nil, 215, nil, nil, nil,
- nil, nil, nil, nil, 215, nil, nil, nil, nil, 215,
- 215, 215, 215, 215, 215, nil, nil, nil, 215, 215,
- 216, 216, 216, nil, 216, nil, nil, nil, 216, 216,
- nil, nil, nil, 216, nil, 216, 216, 216, 216, 216,
- 216, 216, nil, nil, nil, nil, 216, 216, 216, 216,
- 216, 216, 216, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 216, nil, nil, 216, 216, 216, 216, 216,
- 216, 216, 216, 216, 216, nil, 216, 216, nil, 216,
- 216, 216, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 216, nil, nil, 216, nil, nil, 216, 216, nil,
- nil, 216, nil, nil, nil, nil, nil, 216, nil, nil,
- nil, nil, nil, nil, nil, 216, nil, nil, nil, nil,
- 216, 216, 216, 216, 216, 216, nil, nil, nil, 216,
- 216, 217, 217, 217, nil, 217, nil, nil, nil, 217,
- 217, nil, nil, nil, 217, nil, 217, 217, 217, 217,
- 217, 217, 217, nil, nil, nil, nil, 217, 217, 217,
- 217, 217, 217, 217, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 217, nil, nil, 217, 217, 217, 217,
- 217, 217, 217, 217, 217, 217, nil, 217, 217, nil,
- 217, 217, 217, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 217, nil, nil, 217, nil, nil, 217, 217,
- nil, nil, 217, nil, nil, nil, nil, nil, 217, nil,
- nil, nil, nil, nil, nil, nil, 217, nil, nil, nil,
- nil, 217, 217, 217, 217, 217, 217, nil, nil, nil,
- 217, 217, 218, 218, 218, nil, 218, nil, nil, nil,
- 218, 218, nil, nil, nil, 218, nil, 218, 218, 218,
- 218, 218, 218, 218, nil, nil, nil, nil, 218, 218,
- 218, 218, 218, 218, 218, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 218, nil, nil, 218, 218, 218,
- 218, 218, 218, 218, 218, 218, 218, nil, 218, 218,
- nil, 218, 218, 218, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 218, nil, nil, 218, nil, nil, 218,
- 218, nil, nil, 218, nil, nil, nil, nil, nil, 218,
- nil, nil, nil, nil, nil, nil, nil, 218, nil, nil,
- nil, nil, 218, 218, 218, 218, 218, 218, nil, nil,
- nil, 218, 218, 219, 219, 219, nil, 219, nil, nil,
- nil, 219, 219, nil, nil, nil, 219, nil, 219, 219,
- 219, 219, 219, 219, 219, nil, nil, nil, nil, 219,
- 219, 219, 219, 219, 219, 219, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 219, nil, nil, 219, 219,
- 219, 219, 219, 219, 219, 219, 219, 219, nil, 219,
- 219, nil, 219, 219, 219, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 219, nil, nil, 219, nil, nil,
- 219, 219, nil, nil, 219, nil, nil, nil, nil, nil,
- 219, nil, nil, nil, nil, nil, nil, nil, 219, nil,
- nil, nil, nil, 219, 219, 219, 219, 219, 219, nil,
- nil, nil, 219, 219, 220, 220, 220, nil, 220, nil,
- nil, nil, 220, 220, nil, nil, nil, 220, nil, 220,
- 220, 220, 220, 220, 220, 220, nil, nil, nil, nil,
- 220, 220, 220, 220, 220, 220, 220, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 220, nil, nil, 220,
- 220, 220, 220, 220, 220, 220, 220, 220, 220, nil,
- 220, 220, nil, 220, 220, 220, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 220, nil, nil, 220, nil,
- nil, 220, 220, nil, nil, 220, nil, nil, nil, nil,
- nil, 220, nil, nil, nil, nil, nil, nil, nil, 220,
- nil, nil, nil, nil, 220, 220, 220, 220, 220, 220,
- nil, nil, nil, 220, 220, 221, 221, 221, nil, 221,
- nil, nil, nil, 221, 221, nil, nil, nil, 221, nil,
- 221, 221, 221, 221, 221, 221, 221, nil, nil, nil,
- nil, 221, 221, 221, 221, 221, 221, 221, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 221, nil, nil,
- 221, 221, 221, 221, 221, 221, 221, 221, 221, 221,
- nil, 221, 221, nil, 221, 221, 221, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 221, nil, nil, 221,
- nil, nil, 221, 221, nil, nil, 221, nil, nil, nil,
- nil, nil, 221, nil, nil, nil, nil, nil, nil, nil,
- 221, nil, nil, nil, nil, 221, 221, 221, 221, 221,
- 221, nil, nil, nil, 221, 221, 222, 222, 222, nil,
- 222, nil, nil, nil, 222, 222, nil, nil, nil, 222,
- nil, 222, 222, 222, 222, 222, 222, 222, nil, nil,
- nil, nil, 222, 222, 222, 222, 222, 222, 222, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 222, nil,
- nil, 222, 222, 222, 222, 222, 222, 222, 222, 222,
- 222, nil, 222, 222, nil, 222, 222, 222, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 222, nil, nil,
- 222, nil, nil, 222, 222, nil, nil, 222, nil, nil,
- nil, nil, nil, 222, nil, nil, nil, nil, nil, nil,
- nil, 222, nil, nil, nil, nil, 222, 222, 222, 222,
- 222, 222, nil, nil, nil, 222, 222, 223, 223, 223,
- nil, 223, nil, nil, nil, 223, 223, nil, nil, nil,
- 223, nil, 223, 223, 223, 223, 223, 223, 223, nil,
- nil, nil, nil, 223, 223, 223, 223, 223, 223, 223,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 223,
- nil, nil, 223, 223, 223, 223, 223, 223, 223, 223,
- 223, 223, nil, 223, 223, nil, 223, 223, 223, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 223, nil,
- nil, 223, nil, nil, 223, 223, nil, nil, 223, nil,
- nil, nil, nil, nil, 223, nil, nil, nil, nil, nil,
- nil, nil, 223, nil, nil, nil, nil, 223, 223, 223,
- 223, 223, 223, nil, nil, nil, 223, 223, 224, 224,
- 224, nil, 224, nil, nil, nil, 224, 224, nil, nil,
- nil, 224, nil, 224, 224, 224, 224, 224, 224, 224,
- nil, nil, nil, nil, 224, 224, 224, 224, 224, 224,
- 224, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 224, nil, nil, 224, 224, 224, 224, 224, 224, 224,
- 224, 224, 224, nil, 224, 224, nil, 224, 224, 224,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 224,
- nil, nil, 224, nil, nil, 224, 224, nil, nil, 224,
- nil, nil, nil, nil, nil, 224, nil, nil, nil, nil,
- nil, nil, nil, 224, nil, nil, nil, nil, 224, 224,
- 224, 224, 224, 224, nil, nil, nil, 224, 224, 225,
- 225, 225, nil, 225, nil, nil, nil, 225, 225, nil,
- nil, nil, 225, nil, 225, 225, 225, 225, 225, 225,
- 225, nil, nil, nil, nil, 225, 225, 225, 225, 225,
- 225, 225, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 225, nil, nil, 225, 225, 225, 225, 225, 225,
- 225, 225, 225, 225, nil, 225, 225, nil, 225, 225,
- 225, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 225, nil, nil, 225, nil, nil, 225, 225, nil, nil,
- 225, nil, nil, nil, nil, nil, 225, nil, nil, nil,
- nil, nil, nil, nil, 225, nil, nil, nil, nil, 225,
- 225, 225, 225, 225, 225, nil, nil, nil, 225, 225,
- 226, 226, 226, nil, 226, nil, nil, nil, 226, 226,
- nil, nil, nil, 226, nil, 226, 226, 226, 226, 226,
- 226, 226, nil, nil, nil, nil, 226, 226, 226, 226,
- 226, 226, 226, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 226, nil, nil, 226, 226, 226, 226, 226,
- 226, 226, 226, 226, 226, nil, 226, 226, nil, 226,
- 226, 226, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 226, nil, nil, 226, nil, nil, 226, 226, nil,
- nil, 226, nil, nil, nil, nil, nil, 226, nil, nil,
- nil, nil, nil, nil, nil, 226, nil, nil, nil, nil,
- 226, 226, 226, 226, 226, 226, nil, nil, nil, 226,
- 226, 227, 227, 227, nil, 227, nil, nil, nil, 227,
- 227, nil, nil, nil, 227, nil, 227, 227, 227, 227,
- 227, 227, 227, nil, nil, nil, nil, 227, 227, 227,
- 227, 227, 227, 227, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 227, nil, nil, 227, 227, 227, 227,
- 227, 227, 227, 227, 227, 227, nil, 227, 227, nil,
- 227, 227, 227, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 227, nil, nil, 227, nil, nil, 227, 227,
- nil, nil, 227, nil, nil, nil, nil, nil, 227, nil,
- nil, nil, nil, nil, nil, nil, 227, nil, nil, nil,
- nil, 227, 227, 227, 227, 227, 227, nil, nil, nil,
- 227, 227, 228, 228, 228, nil, 228, nil, nil, nil,
- 228, 228, nil, nil, nil, 228, nil, 228, 228, 228,
- 228, 228, 228, 228, nil, nil, nil, nil, 228, 228,
- 228, 228, 228, 228, 228, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 228, nil, nil, 228, 228, 228,
- 228, 228, 228, 228, 228, 228, 228, nil, 228, 228,
- nil, 228, 228, 228, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 228, nil, nil, 228, nil, nil, 228,
- 228, nil, nil, 228, nil, nil, nil, nil, nil, 228,
- nil, nil, nil, nil, nil, nil, nil, 228, nil, nil,
- nil, nil, 228, 228, 228, 228, 228, 228, nil, nil,
- nil, 228, 228, 229, 229, 229, nil, 229, nil, nil,
- nil, 229, 229, nil, nil, nil, 229, nil, 229, 229,
- 229, 229, 229, 229, 229, nil, nil, nil, nil, 229,
- 229, 229, 229, 229, 229, 229, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 229, nil, nil, 229, 229,
- 229, 229, 229, 229, 229, 229, 229, 229, nil, 229,
- 229, nil, 229, 229, 229, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 229, nil, nil, 229, nil, nil,
- 229, 229, nil, nil, 229, nil, nil, nil, nil, nil,
- 229, nil, nil, nil, nil, nil, nil, nil, 229, nil,
- nil, nil, nil, 229, 229, 229, 229, 229, 229, nil,
- nil, nil, 229, 229, 230, 230, 230, nil, 230, nil,
- nil, nil, 230, 230, nil, nil, nil, 230, nil, 230,
- 230, 230, 230, 230, 230, 230, nil, nil, nil, nil,
- 230, 230, 230, 230, 230, 230, 230, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 230, nil, nil, 230,
- 230, 230, 230, 230, 230, 230, 230, 230, 230, nil,
- 230, 230, nil, 230, 230, 230, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 230, nil, nil, 230, nil,
- nil, 230, 230, nil, nil, 230, nil, nil, nil, nil,
- nil, 230, nil, nil, nil, nil, nil, nil, nil, 230,
- nil, nil, nil, nil, 230, 230, 230, 230, 230, 230,
- nil, nil, nil, 230, 230, 231, 231, 231, nil, 231,
- nil, nil, nil, 231, 231, nil, nil, nil, 231, nil,
- 231, 231, 231, 231, 231, 231, 231, nil, nil, nil,
- nil, 231, 231, 231, 231, 231, 231, 231, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 231, nil, nil,
- 231, 231, 231, 231, 231, 231, 231, 231, 231, 231,
- nil, 231, 231, nil, 231, 231, 231, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 231, nil, nil, 231,
- nil, nil, 231, 231, nil, nil, 231, nil, nil, nil,
- nil, nil, 231, nil, nil, nil, nil, nil, nil, nil,
- 231, nil, nil, nil, nil, 231, 231, 231, 231, 231,
- 231, nil, nil, nil, 231, 231, 232, 232, 232, nil,
- 232, nil, nil, nil, 232, 232, nil, nil, nil, 232,
- nil, 232, 232, 232, 232, 232, 232, 232, nil, nil,
- nil, nil, 232, 232, 232, 232, 232, 232, 232, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 232, nil,
- nil, 232, 232, 232, 232, 232, 232, 232, 232, 232,
- 232, nil, 232, 232, nil, 232, 232, 232, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 232, nil, nil,
- 232, nil, nil, 232, 232, nil, nil, 232, nil, nil,
- nil, nil, nil, 232, nil, nil, nil, nil, nil, nil,
- nil, 232, nil, nil, nil, nil, 232, 232, 232, 232,
- 232, 232, nil, nil, nil, 232, 232, 233, 233, 233,
- nil, 233, nil, nil, nil, 233, 233, nil, nil, nil,
- 233, nil, 233, 233, 233, 233, 233, 233, 233, nil,
- nil, nil, nil, 233, 233, 233, 233, 233, 233, 233,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 233,
- nil, nil, 233, 233, 233, 233, 233, 233, 233, 233,
- 233, 233, nil, 233, 233, nil, 233, 233, 233, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 233, nil,
- nil, 233, nil, nil, 233, 233, nil, nil, 233, nil,
- nil, nil, nil, nil, 233, nil, nil, nil, nil, nil,
- nil, nil, 233, nil, nil, nil, nil, 233, 233, 233,
- 233, 233, 233, nil, nil, nil, 233, 233, 241, 241,
- 241, nil, 241, nil, nil, nil, 241, 241, nil, nil,
- nil, 241, nil, 241, 241, 241, 241, 241, 241, 241,
- nil, nil, nil, nil, 241, 241, 241, 241, 241, 241,
- 241, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 241, nil, nil, 241, 241, 241, 241, 241, 241, 241,
- 241, 241, 241, nil, 241, 241, nil, 241, 241, 241,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 241,
- nil, nil, 241, nil, nil, 241, 241, nil, nil, 241,
- nil, nil, nil, nil, nil, 241, nil, nil, nil, nil,
- nil, nil, nil, 241, nil, nil, nil, nil, 241, 241,
- 241, 241, 241, 241, nil, nil, nil, 241, 241, 243,
- 243, 243, nil, 243, nil, nil, nil, 243, 243, nil,
- nil, nil, 243, nil, 243, 243, 243, 243, 243, 243,
- 243, nil, nil, nil, nil, 243, 243, 243, 243, 243,
- 243, 243, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 243, nil, nil, 243, 243, 243, 243, 243, 243,
- 243, 243, 243, 243, nil, 243, 243, nil, 243, 243,
- 243, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 243, nil, nil, 243, nil, nil, 243, 243, nil, nil,
- 243, nil, nil, nil, nil, nil, 243, nil, nil, nil,
- nil, nil, nil, nil, 243, nil, nil, nil, nil, 243,
- 243, 243, 243, 243, 243, nil, nil, nil, 243, 243,
- 254, 254, 254, nil, 254, nil, nil, nil, 254, 254,
- nil, nil, nil, 254, nil, 254, 254, 254, 254, 254,
- 254, 254, nil, nil, nil, nil, 254, 254, 254, 254,
- 254, 254, 254, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 254, nil, nil, 254, 254, 254, 254, 254,
- 254, 254, 254, 254, 254, nil, 254, 254, nil, 254,
- 254, 254, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 254, nil, nil, 254, nil, nil, 254, 254, nil,
- nil, 254, nil, 254, nil, 254, nil, 254, nil, nil,
- nil, nil, nil, nil, nil, 254, nil, nil, nil, nil,
- 254, 254, 254, 254, 254, 254, nil, nil, nil, 254,
- 254, 255, 255, 255, nil, 255, nil, nil, nil, 255,
- 255, nil, nil, nil, 255, nil, 255, 255, 255, 255,
- 255, 255, 255, nil, nil, nil, nil, 255, 255, 255,
- 255, 255, 255, 255, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 255, nil, nil, 255, 255, 255, 255,
- 255, 255, 255, 255, 255, 255, nil, 255, 255, nil,
- 255, 255, 255, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 255, nil, nil, 255, nil, nil, 255, 255,
- nil, nil, 255, nil, 255, nil, 255, nil, 255, nil,
- nil, nil, nil, nil, nil, nil, 255, nil, nil, nil,
- nil, 255, 255, 255, 255, 255, 255, nil, nil, nil,
- 255, 255, 263, 263, 263, nil, 263, nil, nil, nil,
- 263, 263, nil, nil, nil, 263, nil, 263, 263, 263,
- 263, 263, 263, 263, nil, nil, nil, nil, 263, 263,
- 263, 263, 263, 263, 263, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 263, nil, nil, 263, 263, 263,
- 263, 263, 263, 263, 263, 263, 263, nil, 263, 263,
- nil, 263, 263, 263, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 263, nil, nil, 263, nil, 263, 263,
- 263, nil, nil, 263, nil, 263, nil, 263, nil, 263,
- nil, nil, nil, nil, nil, nil, nil, 263, nil, nil,
- nil, nil, 263, 263, 263, 263, 263, 263, nil, nil,
- nil, 263, 263, 269, 269, 269, nil, 269, nil, nil,
- nil, 269, 269, nil, nil, nil, 269, nil, 269, 269,
- 269, 269, 269, 269, 269, nil, nil, nil, nil, 269,
- 269, 269, 269, 269, 269, 269, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 269, nil, nil, 269, 269,
- 269, 269, 269, 269, 269, 269, 269, 269, nil, 269,
- 269, nil, nil, nil, 269, nil, 468, 468, 468, 468,
- 468, 468, 468, 468, 468, 468, 468, nil, 468, 468,
- nil, nil, 468, 468, 269, nil, nil, 269, nil, nil,
- 269, 269, nil, nil, 269, nil, nil, nil, 468, nil,
- 468, nil, 468, 468, 468, 468, 468, 468, 468, nil,
- 468, nil, nil, 269, 269, 269, 269, 269, 269, nil,
- nil, nil, 269, 269, 290, 290, 290, 468, 290, nil,
- nil, nil, 290, 290, nil, nil, nil, 290, nil, 290,
- 290, 290, 290, 290, 290, 290, nil, nil, nil, nil,
- 290, 290, 290, 290, 290, 290, 290, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 290, nil, nil, 290,
- 290, 290, 290, 290, 290, 290, 290, 290, 290, nil,
- 290, 290, nil, 290, 290, 290, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 290, nil, nil, 290, 290,
- nil, 290, 290, nil, nil, 290, nil, nil, nil, nil,
- nil, 290, nil, nil, nil, nil, nil, nil, nil, 290,
- nil, nil, nil, nil, 290, 290, 290, 290, 290, 290,
- nil, nil, nil, 290, 290, 299, 299, 299, nil, 299,
- nil, nil, nil, 299, 299, nil, nil, nil, 299, nil,
- 299, 299, 299, 299, 299, 299, 299, nil, nil, nil,
- nil, 299, 299, 299, 299, 299, 299, 299, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 299, nil, nil,
- 299, 299, 299, 299, 299, 299, 299, 299, 299, 299,
- nil, 299, 299, nil, 299, 299, 299, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 299, nil, nil, 299,
- nil, nil, 299, 299, nil, nil, 299, nil, nil, nil,
- nil, nil, 299, nil, nil, nil, nil, nil, nil, nil,
- 299, nil, nil, nil, nil, 299, 299, 299, 299, 299,
- 299, nil, nil, nil, 299, 299, 308, 308, 308, nil,
- 308, nil, nil, nil, 308, 308, nil, nil, nil, 308,
- nil, 308, 308, 308, 308, 308, 308, 308, nil, nil,
- nil, nil, 308, 308, 308, 308, 308, 308, 308, nil,
- nil, 308, nil, nil, nil, nil, nil, nil, 308, nil,
- nil, 308, 308, 308, 308, 308, 308, 308, 308, 308,
- 308, nil, 308, 308, nil, 308, 308, 308, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 308, nil, nil,
- 308, nil, nil, 308, 308, nil, nil, 308, nil, nil,
- nil, nil, nil, 308, nil, nil, nil, nil, nil, nil,
- nil, 308, nil, nil, nil, nil, 308, 308, 308, 308,
- 308, 308, nil, nil, nil, 308, 308, 309, 309, 309,
- nil, 309, nil, nil, nil, 309, 309, nil, nil, nil,
- 309, nil, 309, 309, 309, 309, 309, 309, 309, nil,
- nil, nil, nil, 309, 309, 309, 309, 309, 309, 309,
- nil, nil, 309, nil, nil, nil, nil, nil, nil, 309,
- nil, nil, 309, 309, 309, 309, 309, 309, 309, 309,
- 309, 309, nil, 309, 309, nil, 309, 309, 309, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 309, nil,
- nil, 309, nil, nil, 309, 309, nil, nil, 309, nil,
- nil, nil, nil, nil, 309, nil, nil, nil, nil, nil,
- nil, nil, 309, nil, nil, nil, nil, 309, 309, 309,
- 309, 309, 309, nil, nil, nil, 309, 309, 327, 327,
- 327, nil, 327, nil, nil, nil, 327, 327, nil, nil,
- nil, 327, nil, 327, 327, 327, 327, 327, 327, 327,
- nil, nil, nil, nil, 327, 327, 327, 327, 327, 327,
- 327, nil, nil, 327, nil, nil, nil, nil, nil, nil,
- 327, nil, nil, 327, 327, 327, 327, 327, 327, 327,
- 327, 327, 327, nil, 327, 327, nil, 327, 327, 327,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 327,
- nil, nil, 327, nil, nil, 327, 327, nil, nil, 327,
- nil, nil, nil, nil, nil, 327, nil, nil, nil, nil,
- nil, nil, nil, 327, nil, nil, nil, nil, 327, 327,
- 327, 327, 327, 327, nil, nil, nil, 327, 327, 341,
- 341, 341, nil, 341, nil, nil, nil, 341, 341, nil,
- nil, nil, 341, nil, 341, 341, 341, 341, 341, 341,
- 341, nil, nil, nil, nil, 341, 341, 341, 341, 341,
- 341, 341, nil, nil, 341, nil, nil, nil, nil, nil,
- nil, 341, nil, nil, 341, 341, 341, 341, 341, 341,
- 341, 341, 341, 341, nil, 341, 341, nil, 341, 341,
- 341, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 341, nil, nil, 341, nil, nil, 341, 341, nil, nil,
- 341, nil, nil, nil, nil, nil, 341, nil, nil, nil,
- nil, nil, nil, nil, 341, nil, nil, nil, nil, 341,
- 341, 341, 341, 341, 341, nil, nil, nil, 341, 341,
- 357, 357, 357, 357, 357, 357, 357, 357, 357, 357,
- 357, 357, 357, 357, 357, 357, 357, 357, 357, 357,
- 357, 357, 357, 357, nil, nil, 357, 357, 357, 357,
- 357, 357, 357, 357, 357, 357, nil, nil, nil, nil,
- nil, 357, 357, 357, 357, 357, 357, 357, 357, nil,
- nil, 357, nil, nil, nil, nil, nil, nil, nil, 357,
- 357, nil, 357, 357, 357, 357, nil, 357, 357, nil,
- nil, 357, nil, nil, nil, nil, 357, 357, 357, 357,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 357, 357, nil, 357, 357, 357, 357,
- 357, 357, 357, 357, 357, nil, 357, nil, nil, 357,
- 357, nil, nil, 369, 369, 369, nil, 369, nil, nil,
- 357, 369, 369, nil, nil, nil, 369, nil, 369, 369,
- 369, 369, 369, 369, 369, nil, nil, nil, nil, 369,
- 369, 369, 369, 369, 369, 369, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 369, nil, nil, 369, 369,
- 369, 369, 369, 369, 369, 369, 369, 369, nil, 369,
- 369, nil, 369, 369, 369, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 369, nil, nil, 369, nil, nil,
- 369, 369, nil, nil, 369, nil, nil, nil, nil, nil,
- 369, nil, nil, nil, nil, nil, nil, nil, 369, nil,
- nil, nil, nil, 369, 369, 369, 369, 369, 369, nil,
- nil, nil, 369, 369, 378, 378, 378, nil, 378, nil,
- nil, nil, 378, 378, nil, nil, nil, 378, nil, 378,
- 378, 378, 378, 378, 378, 378, nil, nil, nil, nil,
- 378, 378, 378, 378, 378, 378, 378, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 378, nil, nil, 378,
- 378, 378, 378, 378, 378, 378, 378, 378, 378, nil,
- 378, 378, nil, 378, 378, 378, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 378, nil, nil, 378, 378,
- nil, 378, 378, nil, nil, 378, nil, 378, nil, 378,
- nil, 378, nil, nil, nil, nil, nil, nil, nil, 378,
- nil, nil, nil, nil, 378, 378, 378, 378, 378, 378,
- nil, nil, nil, 378, 378, 385, 385, 385, nil, 385,
- nil, nil, nil, 385, 385, nil, nil, nil, 385, nil,
- 385, 385, 385, 385, 385, 385, 385, nil, nil, nil,
- nil, 385, 385, 385, 385, 385, 385, 385, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 385, nil, nil,
- 385, 385, 385, 385, 385, 385, 385, 385, 385, 385,
- nil, 385, 385, nil, 385, 385, 385, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 385, nil, nil, 385,
- 385, nil, 385, 385, nil, nil, 385, nil, 385, nil,
- 385, nil, 385, nil, nil, nil, nil, nil, nil, nil,
- 385, nil, nil, nil, nil, 385, 385, 385, 385, 385,
- 385, nil, nil, nil, 385, 385, 386, 386, 386, nil,
- 386, nil, nil, nil, 386, 386, nil, nil, nil, 386,
- nil, 386, 386, 386, 386, 386, 386, 386, nil, nil,
- nil, nil, 386, 386, 386, 386, 386, 386, 386, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 386, nil,
- nil, 386, 386, 386, 386, 386, 386, 386, 386, 386,
- 386, nil, 386, 386, nil, 386, 386, 386, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 386, nil, nil,
- 386, 386, nil, 386, 386, nil, nil, 386, nil, 386,
- nil, 386, nil, 386, nil, nil, nil, nil, nil, nil,
- nil, 386, nil, nil, nil, nil, 386, 386, 386, 386,
- 386, 386, nil, nil, nil, 386, 386, 393, 393, 393,
- nil, 393, nil, nil, nil, 393, 393, nil, nil, nil,
- 393, nil, 393, 393, 393, 393, 393, 393, 393, nil,
- nil, nil, nil, 393, 393, 393, 393, 393, 393, 393,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 393,
- nil, nil, 393, 393, 393, 393, 393, 393, 393, 393,
- 393, 393, nil, 393, 393, nil, 393, 393, 393, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 393, nil,
- nil, 393, nil, nil, 393, 393, nil, nil, 393, nil,
- 393, nil, nil, nil, 393, nil, nil, nil, nil, nil,
- nil, nil, 393, nil, nil, nil, nil, 393, 393, 393,
- 393, 393, 393, nil, nil, nil, 393, 393, 395, 395,
- 395, nil, 395, nil, nil, nil, 395, 395, nil, nil,
- nil, 395, nil, 395, 395, 395, 395, 395, 395, 395,
- nil, nil, nil, nil, 395, 395, 395, 395, 395, 395,
- 395, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 395, nil, nil, 395, 395, 395, 395, 395, 395, 395,
- 395, 395, 395, nil, 395, 395, nil, 395, 395, 395,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 395,
- nil, nil, 395, nil, nil, 395, 395, nil, nil, 395,
- nil, nil, nil, nil, nil, 395, nil, nil, nil, nil,
- nil, nil, nil, 395, nil, nil, nil, nil, 395, 395,
- 395, 395, 395, 395, nil, nil, nil, 395, 395, 396,
- 396, 396, nil, 396, nil, nil, nil, 396, 396, nil,
- nil, nil, 396, nil, 396, 396, 396, 396, 396, 396,
- 396, nil, nil, nil, nil, 396, 396, 396, 396, 396,
- 396, 396, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 396, nil, nil, 396, 396, 396, 396, 396, 396,
- 396, 396, 396, 396, nil, 396, 396, nil, 396, 396,
- 396, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 396, nil, nil, 396, nil, nil, 396, 396, nil, nil,
- 396, nil, nil, nil, nil, nil, 396, nil, nil, nil,
- nil, nil, nil, nil, 396, nil, nil, nil, nil, 396,
- 396, 396, 396, 396, 396, nil, nil, nil, 396, 396,
- 397, 397, 397, nil, 397, nil, nil, nil, 397, 397,
- nil, nil, nil, 397, nil, 397, 397, 397, 397, 397,
- 397, 397, nil, nil, nil, nil, 397, 397, 397, 397,
- 397, 397, 397, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 397, nil, nil, 397, 397, 397, 397, 397,
- 397, 397, 397, 397, 397, nil, 397, 397, nil, 397,
- 397, 397, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 397, nil, nil, 397, nil, nil, 397, 397, nil,
- nil, 397, nil, nil, nil, nil, nil, 397, nil, nil,
- nil, nil, nil, nil, nil, 397, nil, nil, nil, nil,
- 397, 397, 397, 397, 397, 397, nil, nil, nil, 397,
- 397, 426, 426, 426, nil, 426, nil, nil, nil, 426,
- 426, nil, nil, nil, 426, nil, 426, 426, 426, 426,
- 426, 426, 426, nil, nil, nil, nil, 426, 426, 426,
- 426, 426, 426, 426, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 426, nil, nil, 426, 426, 426, 426,
- 426, 426, 426, 426, 426, 426, nil, 426, 426, nil,
- 426, 426, 426, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 426, nil, nil, 426, nil, nil, 426, 426,
- nil, nil, 426, nil, 426, nil, 426, nil, 426, nil,
- nil, nil, nil, nil, nil, nil, 426, nil, nil, nil,
- nil, 426, 426, 426, 426, 426, 426, nil, nil, nil,
- 426, 426, 428, 428, 428, nil, 428, nil, nil, nil,
- 428, 428, nil, nil, nil, 428, nil, 428, 428, 428,
- 428, 428, 428, 428, nil, nil, nil, nil, 428, 428,
- 428, 428, 428, 428, 428, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 428, nil, nil, 428, 428, 428,
- 428, 428, 428, 428, 428, 428, 428, nil, 428, 428,
- nil, 428, 428, 428, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 428, nil, nil, 428, nil, nil, 428,
- 428, nil, nil, 428, nil, 428, nil, 428, nil, 428,
- nil, nil, nil, nil, nil, nil, nil, 428, nil, nil,
- nil, nil, 428, 428, 428, 428, 428, 428, nil, nil,
- nil, 428, 428, 431, 431, 431, nil, 431, nil, nil,
- nil, 431, 431, nil, nil, nil, 431, nil, 431, 431,
- 431, 431, 431, 431, 431, nil, nil, nil, nil, 431,
- 431, 431, 431, 431, 431, 431, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 431, nil, nil, 431, 431,
- 431, 431, 431, 431, 431, 431, 431, 431, nil, 431,
- 431, nil, 431, 431, 431, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 431, nil, nil, 431, nil, nil,
- 431, 431, nil, nil, 431, nil, nil, nil, nil, nil,
- 431, nil, nil, nil, nil, nil, nil, nil, 431, nil,
- nil, nil, nil, 431, 431, 431, 431, 431, 431, nil,
- nil, nil, 431, 431, 445, 445, 445, nil, 445, nil,
- nil, nil, 445, 445, nil, nil, nil, 445, nil, 445,
- 445, 445, 445, 445, 445, 445, nil, nil, nil, nil,
- 445, 445, 445, 445, 445, 445, 445, nil, nil, 445,
- nil, nil, nil, nil, nil, nil, 445, nil, nil, 445,
- 445, 445, 445, 445, 445, 445, 445, 445, 445, nil,
- 445, 445, nil, 445, 445, 445, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 445, nil, nil, 445, nil,
- nil, 445, 445, nil, nil, 445, nil, 445, nil, 445,
- nil, 445, nil, nil, nil, nil, nil, nil, nil, 445,
- nil, nil, nil, nil, 445, 445, 445, 445, 445, 445,
- nil, nil, nil, 445, 445, 456, 456, 456, nil, 456,
- nil, nil, nil, 456, 456, nil, nil, nil, 456, nil,
- 456, 456, 456, 456, 456, 456, 456, nil, nil, nil,
- nil, 456, 456, 456, 456, 456, 456, 456, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 456, nil, nil,
- 456, 456, 456, 456, 456, 456, 456, 456, 456, 456,
- nil, 456, 456, nil, 456, 456, 456, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 456, nil, nil, 456,
- nil, nil, 456, 456, nil, nil, 456, nil, 456, nil,
- nil, nil, 456, nil, nil, nil, nil, nil, nil, nil,
- 456, nil, nil, nil, nil, 456, 456, 456, 456, 456,
- 456, nil, nil, nil, 456, 456, 463, 463, 463, nil,
- 463, nil, nil, nil, 463, 463, nil, nil, nil, 463,
- nil, 463, 463, 463, 463, 463, 463, 463, nil, nil,
- nil, nil, 463, 463, 463, 463, 463, 463, 463, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 463, nil,
- nil, 463, 463, 463, 463, 463, 463, 463, 463, 463,
- 463, nil, 463, 463, nil, 463, 463, 463, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 463, nil, nil,
- 463, nil, nil, 463, 463, nil, nil, 463, nil, nil,
- nil, nil, nil, 463, nil, nil, nil, nil, nil, nil,
- nil, 463, nil, nil, nil, nil, 463, 463, 463, 463,
- 463, 463, nil, nil, nil, 463, 463, 464, 464, 464,
- nil, 464, nil, nil, nil, 464, 464, nil, nil, nil,
- 464, nil, 464, 464, 464, 464, 464, 464, 464, nil,
- nil, nil, nil, 464, 464, 464, 464, 464, 464, 464,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 464,
- nil, nil, 464, 464, 464, 464, 464, 464, 464, 464,
- 464, 464, nil, 464, 464, nil, 464, 464, 464, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 464, nil,
- nil, 464, nil, nil, 464, 464, nil, nil, 464, nil,
- nil, nil, nil, nil, 464, nil, nil, nil, nil, nil,
- nil, nil, 464, nil, nil, nil, nil, 464, 464, 464,
- 464, 464, 464, nil, nil, nil, 464, 464, 465, 465,
- 465, nil, 465, nil, nil, nil, 465, 465, nil, nil,
- nil, 465, nil, 465, 465, 465, 465, 465, 465, 465,
- nil, nil, nil, nil, 465, 465, 465, 465, 465, 465,
- 465, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 465, nil, nil, 465, 465, 465, 465, 465, 465, 465,
- 465, 465, 465, nil, 465, 465, nil, 465, 465, 465,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 465,
- nil, nil, 465, nil, nil, 465, 465, nil, nil, 465,
- nil, nil, nil, nil, nil, 465, nil, nil, nil, nil,
- nil, nil, nil, 465, nil, nil, nil, nil, 465, 465,
- 465, 465, 465, 465, nil, nil, nil, 465, 465, 469,
- 469, 469, nil, 469, nil, nil, nil, 469, 469, nil,
- nil, nil, 469, nil, 469, 469, 469, 469, 469, 469,
- 469, nil, nil, nil, nil, 469, 469, 469, 469, 469,
- 469, 469, nil, nil, 469, nil, nil, nil, nil, nil,
- nil, 469, nil, nil, 469, 469, 469, 469, 469, 469,
- 469, 469, 469, 469, nil, 469, 469, nil, 469, 469,
- 469, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 469, nil, nil, 469, nil, nil, 469, 469, nil, nil,
- 469, nil, nil, nil, nil, nil, 469, nil, nil, nil,
- nil, nil, nil, nil, 469, nil, nil, nil, nil, 469,
- 469, 469, 469, 469, 469, nil, nil, nil, 469, 469,
- 471, 471, 471, nil, 471, nil, nil, nil, 471, 471,
- nil, nil, nil, 471, nil, 471, 471, 471, 471, 471,
- 471, 471, nil, nil, nil, nil, 471, 471, 471, 471,
- 471, 471, 471, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 471, nil, nil, 471, 471, 471, 471, 471,
- 471, 471, 471, 471, 471, nil, 471, 471, nil, 471,
- 471, 471, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 471, nil, nil, 471, nil, nil, 471, 471, nil,
- nil, 471, nil, 471, nil, nil, nil, 471, nil, nil,
- nil, nil, nil, nil, nil, 471, nil, nil, nil, nil,
- 471, 471, 471, 471, 471, 471, nil, nil, nil, 471,
- 471, 476, 476, 476, nil, 476, nil, nil, nil, 476,
- 476, nil, nil, nil, 476, nil, 476, 476, 476, 476,
- 476, 476, 476, nil, nil, nil, nil, 476, 476, 476,
- 476, 476, 476, 476, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 476, nil, nil, 476, 476, 476, 476,
- 476, 476, 476, 476, 476, 476, nil, 476, 476, nil,
- 476, 476, 476, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 476, nil, nil, 476, nil, nil, 476, 476,
- nil, nil, 476, nil, 476, nil, nil, nil, 476, nil,
- nil, nil, nil, nil, nil, nil, 476, nil, nil, nil,
- nil, 476, 476, 476, 476, 476, 476, nil, nil, nil,
- 476, 476, 479, 479, 479, nil, 479, nil, nil, nil,
- 479, 479, nil, nil, nil, 479, nil, 479, 479, 479,
- 479, 479, 479, 479, nil, nil, nil, nil, 479, 479,
- 479, 479, 479, 479, 479, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 479, nil, nil, 479, 479, 479,
- 479, 479, 479, 479, 479, 479, 479, nil, 479, 479,
- nil, 479, 479, 479, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 479, nil, nil, 479, nil, nil, 479,
- 479, nil, nil, 479, nil, nil, nil, nil, nil, 479,
- nil, nil, nil, nil, nil, nil, nil, 479, nil, nil,
- nil, nil, 479, 479, 479, 479, 479, 479, nil, nil,
- nil, 479, 479, 482, 482, 482, nil, 482, nil, nil,
- nil, 482, 482, nil, nil, nil, 482, nil, 482, 482,
- 482, 482, 482, 482, 482, nil, nil, nil, nil, 482,
- 482, 482, 482, 482, 482, 482, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 482, nil, nil, 482, 482,
- 482, 482, 482, 482, 482, 482, 482, 482, nil, 482,
- 482, nil, 482, 482, 482, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 482, nil, nil, 482, nil, nil,
- 482, 482, nil, nil, 482, nil, nil, nil, nil, nil,
- 482, nil, nil, nil, nil, nil, nil, nil, 482, nil,
- nil, nil, nil, 482, 482, 482, 482, 482, 482, nil,
- nil, nil, 482, 482, 496, 496, 496, nil, 496, nil,
- nil, nil, 496, 496, nil, nil, nil, 496, nil, 496,
- 496, 496, 496, 496, 496, 496, nil, nil, nil, nil,
- 496, 496, 496, 496, 496, 496, 496, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 496, nil, nil, 496,
- 496, 496, 496, 496, 496, 496, 496, 496, 496, nil,
- 496, 496, nil, 496, 496, 496, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 496, nil, nil, 496, nil,
- nil, 496, 496, nil, nil, 496, nil, 496, nil, nil,
- nil, 496, nil, nil, nil, nil, nil, nil, nil, 496,
- nil, nil, nil, nil, 496, 496, 496, 496, 496, 496,
- nil, nil, nil, 496, 496, 497, 497, 497, nil, 497,
- nil, nil, nil, 497, 497, nil, nil, nil, 497, nil,
- 497, 497, 497, 497, 497, 497, 497, nil, nil, nil,
- nil, 497, 497, 497, 497, 497, 497, 497, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 497, nil, nil,
- 497, 497, 497, 497, 497, 497, 497, 497, 497, 497,
- nil, 497, 497, nil, 497, 497, 497, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 497, nil, nil, 497,
- nil, nil, 497, 497, nil, nil, 497, nil, 497, nil,
- nil, nil, 497, nil, nil, nil, nil, nil, nil, nil,
- 497, nil, nil, nil, nil, 497, 497, 497, 497, 497,
- 497, nil, nil, nil, 497, 497, 506, 506, 506, nil,
- 506, nil, nil, nil, 506, 506, nil, nil, nil, 506,
- nil, 506, 506, 506, 506, 506, 506, 506, nil, nil,
- nil, nil, 506, 506, 506, 506, 506, 506, 506, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 506, nil,
- nil, 506, 506, 506, 506, 506, 506, 506, 506, 506,
- 506, nil, 506, 506, nil, 506, 506, 506, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 506, nil, nil,
- 506, nil, nil, 506, 506, nil, nil, 506, nil, 506,
- nil, nil, nil, 506, nil, nil, nil, nil, nil, nil,
- nil, 506, nil, nil, nil, nil, 506, 506, 506, 506,
- 506, 506, nil, nil, nil, 506, 506, 510, 510, 510,
- nil, 510, nil, nil, nil, 510, 510, nil, nil, nil,
- 510, nil, 510, 510, 510, 510, 510, 510, 510, nil,
- nil, nil, nil, 510, 510, 510, 510, 510, 510, 510,
- nil, nil, 510, nil, nil, nil, nil, nil, nil, 510,
- nil, nil, 510, 510, 510, 510, 510, 510, 510, 510,
- 510, 510, nil, 510, 510, nil, 510, 510, 510, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 510, nil,
- nil, 510, nil, nil, 510, 510, nil, nil, 510, nil,
- nil, nil, nil, nil, 510, nil, nil, nil, nil, nil,
- nil, nil, 510, nil, nil, nil, nil, 510, 510, 510,
- 510, 510, 510, nil, nil, nil, 510, 510, 534, 534,
- 534, 534, 534, 534, 534, 534, 534, 534, 534, 534,
- 534, 534, 534, 534, 534, 534, 534, 534, 534, 534,
- 534, 534, nil, nil, 534, 534, 534, 534, 534, 534,
- 534, 534, 534, 534, nil, nil, nil, nil, nil, 534,
- 534, 534, 534, 534, 534, 534, 534, nil, nil, 534,
- nil, nil, nil, nil, nil, nil, nil, 534, 534, nil,
- 534, 534, 534, 534, nil, 534, 534, nil, nil, 534,
- nil, nil, nil, nil, 534, 534, 534, 534, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 534, 534, nil, 534, 534, 534, 534, 534, 534,
- 534, 534, 534, nil, 534, nil, nil, 534, 534, nil,
- nil, 537, 537, 537, nil, 537, nil, nil, 534, 537,
- 537, nil, nil, nil, 537, nil, 537, 537, 537, 537,
- 537, 537, 537, nil, nil, nil, nil, 537, 537, 537,
- 537, 537, 537, 537, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 537, nil, nil, 537, 537, 537, 537,
- 537, 537, 537, 537, 537, 537, nil, 537, 537, nil,
- 537, 537, 537, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 537, nil, nil, 537, nil, nil, 537, 537,
- nil, nil, 537, nil, nil, nil, nil, nil, 537, nil,
- nil, nil, nil, nil, nil, nil, 537, nil, nil, nil,
- nil, 537, 537, 537, 537, 537, 537, nil, nil, nil,
- 537, 537, 538, 538, 538, nil, 538, nil, nil, nil,
- 538, 538, nil, nil, nil, 538, nil, 538, 538, 538,
- 538, 538, 538, 538, nil, nil, nil, nil, 538, 538,
- 538, 538, 538, 538, 538, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 538, nil, nil, 538, 538, 538,
- 538, 538, 538, 538, 538, 538, 538, nil, 538, 538,
- nil, 538, 538, 538, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 538, nil, nil, 538, nil, nil, 538,
- 538, nil, nil, 538, nil, 538, nil, nil, nil, 538,
- nil, nil, nil, nil, nil, nil, nil, 538, nil, nil,
- nil, nil, 538, 538, 538, 538, 538, 538, nil, nil,
- nil, 538, 538, 541, 541, 541, nil, 541, nil, nil,
- nil, 541, 541, nil, nil, nil, 541, nil, 541, 541,
- 541, 541, 541, 541, 541, nil, nil, nil, nil, 541,
- 541, 541, 541, 541, 541, 541, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 541, nil, nil, 541, 541,
- 541, 541, 541, 541, 541, 541, 541, 541, nil, 541,
- 541, nil, 541, 541, 541, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 541, nil, nil, 541, nil, nil,
- 541, 541, nil, nil, 541, nil, nil, nil, nil, nil,
- 541, nil, nil, nil, nil, nil, nil, nil, 541, nil,
- nil, nil, nil, 541, 541, 541, 541, 541, 541, nil,
- nil, nil, 541, 541, 542, 542, 542, nil, 542, nil,
- nil, nil, 542, 542, nil, nil, nil, 542, nil, 542,
- 542, 542, 542, 542, 542, 542, nil, nil, nil, nil,
- 542, 542, 542, 542, 542, 542, 542, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 542, nil, nil, 542,
- 542, 542, 542, 542, 542, 542, 542, 542, 542, nil,
- 542, 542, nil, 542, 542, 542, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 542, nil, nil, 542, nil,
- nil, 542, 542, nil, nil, 542, nil, nil, nil, nil,
- nil, 542, nil, nil, nil, nil, nil, nil, nil, 542,
- nil, nil, nil, nil, 542, 542, 542, 542, 542, 542,
- nil, nil, nil, 542, 542, 546, 546, 546, nil, 546,
- nil, nil, nil, 546, 546, nil, nil, nil, 546, nil,
- 546, 546, 546, 546, 546, 546, 546, nil, nil, nil,
- nil, 546, 546, 546, 546, 546, 546, 546, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 546, nil, nil,
- 546, 546, 546, 546, 546, 546, 546, 546, 546, 546,
- nil, 546, 546, nil, 546, 546, 546, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 546, nil, nil, 546,
- nil, nil, 546, 546, nil, nil, 546, nil, nil, nil,
- nil, nil, 546, nil, nil, nil, nil, nil, nil, nil,
- 546, nil, nil, nil, nil, 546, 546, 546, 546, 546,
- 546, nil, nil, nil, 546, 546, 549, 549, 549, nil,
- 549, nil, nil, nil, 549, 549, nil, nil, nil, 549,
- nil, 549, 549, 549, 549, 549, 549, 549, nil, nil,
- nil, nil, 549, 549, 549, 549, 549, 549, 549, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 549, nil,
- nil, 549, 549, 549, 549, 549, 549, 549, 549, 549,
- 549, nil, 549, 549, nil, 549, 549, 549, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 549, nil, nil,
- 549, nil, nil, 549, 549, nil, nil, 549, nil, nil,
- nil, nil, nil, 549, nil, nil, nil, nil, nil, nil,
- nil, 549, nil, nil, nil, nil, 549, 549, 549, 549,
- 549, 549, nil, nil, nil, 549, 549, 556, 556, 556,
- nil, 556, nil, nil, nil, 556, 556, nil, nil, nil,
- 556, nil, 556, 556, 556, 556, 556, 556, 556, nil,
- nil, nil, nil, 556, 556, 556, 556, 556, 556, 556,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 556,
- nil, nil, 556, 556, 556, 556, 556, 556, 556, 556,
- 556, 556, nil, 556, 556, nil, 556, 556, 556, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 556, nil,
- nil, 556, nil, nil, 556, 556, nil, nil, 556, nil,
- nil, nil, nil, nil, 556, nil, nil, nil, nil, nil,
- nil, nil, 556, nil, nil, nil, nil, 556, 556, 556,
- 556, 556, 556, nil, nil, nil, 556, 556, 557, 557,
- 557, nil, 557, nil, nil, nil, 557, 557, nil, nil,
- nil, 557, nil, 557, 557, 557, 557, 557, 557, 557,
- nil, nil, nil, nil, 557, 557, 557, 557, 557, 557,
- 557, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 557, nil, nil, 557, 557, 557, 557, 557, 557, 557,
- 557, 557, 557, nil, 557, 557, nil, nil, nil, 557,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 557,
- nil, nil, 557, nil, nil, 557, 557, nil, nil, 557,
- nil, 557, nil, 557, nil, nil, nil, nil, nil, nil,
- nil, nil, 557, nil, nil, nil, nil, nil, 557, 557,
- 557, 557, 557, 557, nil, nil, nil, 557, 557, 560,
- 560, 560, nil, 560, nil, nil, nil, 560, 560, nil,
- nil, nil, 560, nil, 560, 560, 560, 560, 560, 560,
- 560, nil, nil, nil, nil, 560, 560, 560, 560, 560,
- 560, 560, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 560, nil, nil, 560, 560, 560, 560, 560, 560,
- 560, 560, 560, 560, nil, 560, 560, nil, 560, 560,
- 560, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 560, nil, nil, 560, nil, nil, 560, 560, nil, nil,
- 560, nil, nil, nil, nil, nil, 560, nil, nil, nil,
- nil, nil, nil, nil, 560, nil, nil, nil, nil, 560,
- 560, 560, 560, 560, 560, nil, nil, nil, 560, 560,
- 564, 564, 564, nil, 564, nil, nil, nil, 564, 564,
- nil, nil, nil, 564, nil, 564, 564, 564, 564, 564,
- 564, 564, nil, nil, nil, nil, 564, 564, 564, 564,
- 564, 564, 564, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 564, nil, nil, 564, 564, 564, 564, 564,
- 564, 564, 564, 564, 564, nil, 564, 564, nil, 564,
- 564, 564, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 564, nil, nil, 564, nil, nil, 564, 564, nil,
- nil, 564, nil, nil, nil, nil, nil, 564, nil, nil,
- nil, nil, nil, nil, nil, 564, nil, nil, nil, nil,
- 564, 564, 564, 564, 564, 564, nil, nil, nil, 564,
- 564, 580, 580, 580, nil, 580, nil, nil, nil, 580,
- 580, nil, nil, nil, 580, nil, 580, 580, 580, 580,
- 580, 580, 580, nil, nil, nil, nil, 580, 580, 580,
- 580, 580, 580, 580, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 580, nil, nil, 580, 580, 580, 580,
- 580, 580, 580, 580, 580, 580, nil, 580, 580, nil,
- 580, 580, 580, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 580, nil, nil, 580, nil, nil, 580, 580,
- nil, nil, 580, nil, 580, nil, 580, nil, 580, nil,
- nil, nil, nil, nil, nil, nil, 580, nil, nil, nil,
- nil, 580, 580, 580, 580, 580, 580, nil, nil, nil,
- 580, 580, 584, 584, 584, nil, 584, nil, nil, nil,
- 584, 584, nil, nil, nil, 584, nil, 584, 584, 584,
- 584, 584, 584, 584, nil, nil, nil, nil, 584, 584,
- 584, 584, 584, 584, 584, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 584, nil, nil, 584, 584, 584,
- 584, 584, 584, 584, 584, 584, 584, nil, 584, 584,
- nil, 584, 584, 584, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 584, nil, nil, 584, nil, nil, 584,
- 584, nil, nil, 584, nil, nil, nil, nil, nil, 584,
- nil, nil, nil, nil, nil, nil, nil, 584, nil, nil,
- nil, nil, 584, 584, 584, 584, 584, 584, nil, nil,
- nil, 584, 584, 612, 612, 612, nil, 612, nil, nil,
- nil, 612, 612, nil, nil, nil, 612, nil, 612, 612,
- 612, 612, 612, 612, 612, nil, nil, nil, nil, 612,
- 612, 612, 612, 612, 612, 612, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 612, nil, nil, 612, 612,
- 612, 612, 612, 612, 612, 612, 612, 612, nil, 612,
- 612, nil, 612, 612, 612, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 612, nil, nil, 612, nil, nil,
- 612, 612, nil, nil, 612, nil, nil, nil, nil, nil,
- 612, nil, nil, nil, nil, nil, nil, nil, 612, nil,
- nil, nil, nil, 612, 612, 612, 612, 612, 612, nil,
- nil, nil, 612, 612, 628, 628, 628, nil, 628, nil,
- nil, nil, 628, 628, nil, nil, nil, 628, nil, 628,
- 628, 628, 628, 628, 628, 628, nil, nil, nil, nil,
- 628, 628, 628, 628, 628, 628, 628, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 628, nil, nil, 628,
- 628, 628, 628, 628, 628, 628, 628, 628, 628, nil,
- 628, 628, nil, 628, 628, 628, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 628, nil, nil, 628, nil,
- nil, 628, 628, nil, nil, 628, nil, nil, nil, nil,
- nil, 628, nil, nil, nil, nil, nil, nil, nil, 628,
- nil, nil, nil, nil, 628, 628, 628, 628, 628, 628,
- nil, nil, nil, 628, 628, 634, 634, 634, nil, 634,
- nil, nil, nil, 634, 634, nil, nil, nil, 634, nil,
- 634, 634, 634, 634, 634, 634, 634, nil, nil, nil,
- nil, 634, 634, 634, 634, 634, 634, 634, nil, nil,
- 634, nil, nil, nil, nil, nil, nil, 634, nil, nil,
- 634, 634, 634, 634, 634, 634, 634, 634, 634, 634,
- nil, 634, 634, nil, 634, 634, 634, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 634, nil, nil, 634,
- nil, nil, 634, 634, nil, nil, 634, nil, nil, nil,
- nil, nil, 634, nil, nil, nil, nil, nil, nil, nil,
- 634, nil, nil, nil, nil, 634, 634, 634, 634, 634,
- 634, nil, nil, nil, 634, 634, 679, 679, 679, nil,
- 679, nil, nil, nil, 679, 679, nil, nil, nil, 679,
- nil, 679, 679, 679, 679, 679, 679, 679, nil, nil,
- nil, nil, 679, 679, 679, 679, 679, 679, 679, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 679, nil,
- nil, 679, 679, 679, 679, 679, 679, 679, 679, 679,
- 679, nil, 679, 679, nil, 679, 679, 679, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 679, nil, nil,
- 679, nil, nil, 679, 679, nil, nil, 679, nil, nil,
- nil, nil, nil, 679, nil, nil, nil, nil, nil, nil,
- nil, 679, nil, nil, nil, nil, 679, 679, 679, 679,
- 679, 679, nil, nil, nil, 679, 679, 680, 680, 680,
- nil, 680, nil, nil, nil, 680, 680, nil, nil, nil,
- 680, nil, 680, 680, 680, 680, 680, 680, 680, nil,
- nil, nil, nil, 680, 680, 680, 680, 680, 680, 680,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 680,
- nil, nil, 680, 680, 680, 680, 680, 680, 680, 680,
- 680, 680, nil, 680, 680, nil, 680, 680, 680, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 680, nil,
- nil, 680, nil, nil, 680, 680, nil, nil, 680, nil,
- nil, nil, nil, nil, 680, nil, nil, nil, nil, nil,
- nil, nil, 680, nil, nil, nil, nil, 680, 680, 680,
- 680, 680, 680, nil, nil, nil, 680, 680, 690, 690,
- 690, nil, 690, nil, nil, nil, 690, 690, nil, nil,
- nil, 690, nil, 690, 690, 690, 690, 690, 690, 690,
- nil, nil, nil, nil, 690, 690, 690, 690, 690, 690,
- 690, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 690, nil, nil, 690, 690, 690, 690, 690, 690, 690,
- 690, 690, 690, nil, 690, 690, nil, 690, 690, 690,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 690,
- nil, nil, 690, nil, nil, 690, 690, nil, nil, 690,
- nil, nil, nil, nil, nil, 690, nil, nil, nil, nil,
- nil, nil, nil, 690, nil, nil, nil, nil, 690, 690,
- 690, 690, 690, 690, nil, nil, nil, 690, 690, 691,
- 691, 691, nil, 691, nil, nil, nil, 691, 691, nil,
- nil, nil, 691, nil, 691, 691, 691, 691, 691, 691,
- 691, nil, nil, nil, nil, 691, 691, 691, 691, 691,
- 691, 691, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 691, nil, nil, 691, 691, 691, 691, 691, 691,
- 691, 691, 691, 691, nil, 691, 691, nil, 691, 691,
- 691, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 691, nil, nil, 691, nil, nil, 691, 691, nil, nil,
- 691, nil, nil, nil, nil, nil, 691, nil, nil, nil,
- nil, nil, nil, nil, 691, nil, nil, nil, nil, 691,
- 691, 691, 691, 691, 691, nil, nil, nil, 691, 691,
- 692, 692, 692, nil, 692, nil, nil, nil, 692, 692,
- nil, nil, nil, 692, nil, 692, 692, 692, 692, 692,
- 692, 692, nil, nil, nil, nil, 692, 692, 692, 692,
- 692, 692, 692, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 692, nil, nil, 692, 692, 692, 692, 692,
- 692, 692, 692, 692, 692, nil, 692, 692, nil, 692,
- 692, 692, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 692, nil, nil, 692, nil, nil, 692, 692, nil,
- nil, 692, nil, nil, nil, nil, nil, 692, nil, nil,
- nil, nil, nil, nil, nil, 692, nil, nil, nil, nil,
- 692, 692, 692, 692, 692, 692, nil, nil, nil, 692,
- 692, 698, 698, 698, nil, 698, nil, nil, nil, 698,
- 698, nil, nil, nil, 698, nil, 698, 698, 698, 698,
- 698, 698, 698, nil, nil, nil, nil, 698, 698, 698,
- 698, 698, 698, 698, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 698, nil, nil, 698, 698, 698, 698,
- 698, 698, 698, 698, 698, 698, nil, 698, 698, nil,
- nil, nil, 698, nil, 600, 600, 600, 600, 600, 600,
- 600, 600, 600, 600, 600, nil, 600, 600, nil, nil,
- 600, 600, 698, nil, nil, 698, nil, nil, 698, 698,
- nil, nil, 698, nil, nil, nil, 600, nil, 600, nil,
- 600, 600, 600, 600, 600, 600, 600, nil, 600, nil,
- nil, 698, 698, 698, 698, 698, 698, nil, nil, nil,
- 698, 698, 704, 704, 704, 600, 704, nil, nil, nil,
- 704, 704, nil, nil, nil, 704, nil, 704, 704, 704,
- 704, 704, 704, 704, nil, nil, nil, nil, 704, 704,
- 704, 704, 704, 704, 704, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 704, nil, nil, 704, 704, 704,
- 704, 704, 704, 704, 704, 704, 704, nil, 704, 704,
- nil, 704, 704, 704, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 704, nil, nil, 704, nil, nil, 704,
- 704, nil, nil, 704, nil, 704, nil, 704, nil, 704,
- nil, nil, nil, nil, nil, nil, nil, 704, nil, nil,
- nil, nil, 704, 704, 704, 704, 704, 704, nil, nil,
- nil, 704, 704, 713, 713, 713, nil, 713, nil, nil,
- nil, 713, 713, nil, nil, nil, 713, nil, 713, 713,
- 713, 713, 713, 713, 713, nil, nil, nil, nil, 713,
- 713, 713, 713, 713, 713, 713, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 713, nil, nil, 713, 713,
- 713, 713, 713, 713, 713, 713, 713, 713, nil, 713,
- 713, nil, 713, 713, 713, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 713, nil, nil, 713, nil, nil,
- 713, 713, nil, nil, 713, nil, 713, nil, 713, nil,
- 713, nil, nil, nil, nil, nil, nil, nil, 713, nil,
- nil, nil, nil, 713, 713, 713, 713, 713, 713, nil,
- nil, nil, 713, 713, 715, 715, 715, nil, 715, nil,
- nil, nil, 715, 715, nil, nil, nil, 715, nil, 715,
- 715, 715, 715, 715, 715, 715, nil, nil, nil, nil,
- 715, 715, 715, 715, 715, 715, 715, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 715, nil, nil, 715,
- 715, 715, 715, 715, 715, 715, 715, 715, 715, nil,
- 715, 715, nil, 715, 715, 715, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 715, nil, nil, 715, nil,
- nil, 715, 715, nil, nil, 715, nil, 715, nil, 715,
- nil, 715, nil, nil, nil, nil, nil, nil, nil, 715,
- nil, nil, nil, nil, 715, 715, 715, 715, 715, 715,
- nil, nil, nil, 715, 715, 728, 728, 728, nil, 728,
- nil, nil, nil, 728, 728, nil, nil, nil, 728, nil,
- 728, 728, 728, 728, 728, 728, 728, nil, nil, nil,
- nil, 728, 728, 728, 728, 728, 728, 728, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 728, nil, nil,
- 728, 728, 728, 728, 728, 728, 728, 728, 728, 728,
- nil, 728, 728, nil, nil, nil, 728, nil, 677, 677,
- 677, 677, 677, 677, 677, 677, 677, 677, 677, nil,
- 677, 677, nil, nil, 677, 677, 728, nil, nil, 728,
- nil, nil, 728, 728, nil, nil, 728, nil, nil, nil,
- 677, nil, 677, nil, 677, 677, 677, 677, 677, 677,
- 677, nil, 677, nil, nil, 728, 728, 728, 728, 728,
- 728, nil, nil, nil, 728, 728, 734, 734, 734, 677,
- 734, nil, nil, nil, 734, 734, nil, nil, nil, 734,
- nil, 734, 734, 734, 734, 734, 734, 734, nil, nil,
- nil, nil, 734, 734, 734, 734, 734, 734, 734, nil,
- nil, 734, nil, nil, nil, nil, nil, nil, 734, nil,
- nil, 734, 734, 734, 734, 734, 734, 734, 734, 734,
- 734, nil, 734, 734, nil, 734, 734, 734, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 734, nil, nil,
- 734, nil, nil, 734, 734, nil, nil, 734, nil, nil,
- nil, nil, nil, 734, nil, nil, nil, nil, nil, nil,
- nil, 734, nil, nil, nil, nil, 734, 734, 734, 734,
- 734, 734, nil, nil, nil, 734, 734, 740, 740, 740,
- nil, 740, nil, nil, nil, 740, 740, nil, nil, nil,
- 740, nil, 740, 740, 740, 740, 740, 740, 740, nil,
- nil, nil, nil, 740, 740, 740, 740, 740, 740, 740,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 740,
- nil, nil, 740, 740, 740, 740, 740, 740, 740, 740,
- 740, 740, nil, 740, 740, nil, 740, 740, 740, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 740, nil,
- nil, 740, nil, nil, 740, 740, nil, nil, 740, nil,
- 740, nil, nil, nil, 740, nil, nil, nil, nil, nil,
- nil, nil, 740, nil, nil, nil, nil, 740, 740, 740,
- 740, 740, 740, nil, nil, nil, 740, 740, 759, 759,
- 759, nil, 759, nil, nil, nil, 759, 759, nil, nil,
- nil, 759, nil, 759, 759, 759, 759, 759, 759, 759,
- nil, nil, nil, nil, 759, 759, 759, 759, 759, 759,
- 759, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 759, nil, nil, 759, 759, 759, 759, 759, 759, 759,
- 759, 759, 759, nil, 759, 759, nil, 759, 759, 759,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 759,
- nil, nil, 759, nil, nil, 759, 759, nil, nil, 759,
- nil, nil, nil, nil, nil, 759, nil, nil, nil, nil,
- nil, nil, nil, 759, nil, nil, nil, nil, 759, 759,
- 759, 759, 759, 759, nil, nil, nil, 759, 759, 768,
- 768, 768, nil, 768, nil, nil, nil, 768, 768, nil,
- nil, nil, 768, nil, 768, 768, 768, 768, 768, 768,
- 768, nil, nil, nil, nil, 768, 768, 768, 768, 768,
- 768, 768, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 768, nil, nil, 768, 768, 768, 768, 768, 768,
- 768, 768, 768, 768, nil, 768, 768, nil, 768, 768,
- 768, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 768, nil, nil, 768, nil, nil, 768, 768, nil, nil,
- 768, nil, nil, nil, nil, nil, 768, nil, nil, nil,
- nil, nil, nil, nil, 768, nil, nil, nil, nil, 768,
- 768, 768, 768, 768, 768, nil, nil, nil, 768, 768,
- 769, 769, 769, nil, 769, nil, nil, nil, 769, 769,
- nil, nil, nil, 769, nil, 769, 769, 769, 769, 769,
- 769, 769, nil, nil, nil, nil, 769, 769, 769, 769,
- 769, 769, 769, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 769, nil, nil, 769, 769, 769, 769, 769,
- 769, 769, 769, 769, 769, nil, 769, 769, nil, nil,
- nil, 769, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 769, nil, nil, 769, nil, nil, 769, 769, nil,
- nil, 769, nil, 769, nil, 769, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 769, 769, 769, 769, 769, 769, nil, nil, nil, 769,
- 769, 780, 780, 780, nil, 780, nil, nil, nil, 780,
- 780, nil, nil, nil, 780, nil, 780, 780, 780, 780,
- 780, 780, 780, nil, nil, nil, nil, 780, 780, 780,
- 780, 780, 780, 780, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 780, nil, nil, 780, 780, 780, 780,
- 780, 780, 780, 780, 780, 780, nil, 780, 780, nil,
- 780, 780, 780, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 780, nil, nil, 780, nil, nil, 780, 780,
- nil, nil, 780, nil, nil, nil, nil, nil, 780, nil,
- nil, nil, nil, nil, nil, nil, 780, nil, nil, nil,
- nil, 780, 780, 780, 780, 780, 780, nil, nil, nil,
- 780, 780, 786, 786, 786, nil, 786, nil, nil, nil,
- 786, 786, nil, nil, nil, 786, nil, 786, 786, 786,
- 786, 786, 786, 786, nil, nil, nil, nil, 786, 786,
- 786, 786, 786, 786, 786, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 786, nil, nil, 786, 786, 786,
- 786, 786, 786, 786, 786, 786, 786, nil, 786, 786,
- nil, 786, 786, 786, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 786, nil, nil, 786, nil, nil, 786,
- 786, nil, nil, 786, nil, nil, nil, nil, nil, 786,
- nil, nil, nil, nil, nil, nil, nil, 786, nil, nil,
- nil, nil, 786, 786, 786, 786, 786, 786, nil, nil,
- nil, 786, 786, 788, 788, 788, nil, 788, nil, nil,
- nil, 788, 788, nil, nil, nil, 788, nil, 788, 788,
- 788, 788, 788, 788, 788, nil, nil, nil, nil, 788,
- 788, 788, 788, 788, 788, 788, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 788, nil, nil, 788, 788,
- 788, 788, 788, 788, 788, 788, 788, 788, nil, 788,
- 788, nil, 788, 788, 788, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 788, nil, nil, 788, nil, nil,
- 788, 788, nil, nil, 788, nil, nil, nil, nil, nil,
- 788, nil, nil, nil, nil, nil, nil, nil, 788, nil,
- nil, nil, nil, 788, 788, 788, 788, 788, 788, nil,
- nil, nil, 788, 788, 802, 802, 802, nil, 802, nil,
- nil, nil, 802, 802, nil, nil, nil, 802, nil, 802,
- 802, 802, 802, 802, 802, 802, nil, nil, nil, nil,
- 802, 802, 802, 802, 802, 802, 802, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 802, nil, nil, 802,
- 802, 802, 802, 802, 802, 802, 802, 802, 802, nil,
- 802, 802, nil, 802, 802, 802, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 802, nil, nil, 802, nil,
- nil, 802, 802, nil, nil, 802, nil, nil, nil, nil,
- nil, 802, nil, nil, nil, nil, nil, nil, nil, 802,
- nil, nil, nil, nil, 802, 802, 802, 802, 802, 802,
- nil, nil, nil, 802, 802, 820, 820, 820, nil, 820,
- nil, nil, nil, 820, 820, nil, nil, nil, 820, nil,
- 820, 820, 820, 820, 820, 820, 820, nil, nil, nil,
- nil, 820, 820, 820, 820, 820, 820, 820, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 820, nil, nil,
- 820, 820, 820, 820, 820, 820, 820, 820, 820, 820,
- nil, 820, 820, nil, nil, nil, 820, nil, 682, 682,
- 682, 682, 682, 682, 682, 682, 682, 682, 682, nil,
- 682, 682, nil, nil, 682, 682, 820, nil, nil, 820,
- nil, nil, 820, 820, nil, nil, 820, nil, nil, nil,
- 682, nil, 682, nil, 682, 682, 682, 682, 682, 682,
- 682, nil, 682, nil, nil, 820, 820, 820, 820, 820,
- 820, nil, nil, nil, 820, 820, 822, 822, 822, 682,
- 822, nil, nil, nil, 822, 822, nil, nil, nil, 822,
- nil, 822, 822, 822, 822, 822, 822, 822, nil, nil,
- nil, nil, 822, 822, 822, 822, 822, 822, 822, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 822, nil,
- nil, 822, 822, 822, 822, 822, 822, 822, 822, 822,
- 822, nil, 822, 822, nil, 822, 822, 822, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 822, nil, nil,
- 822, nil, nil, 822, 822, nil, nil, 822, nil, 822,
- nil, nil, nil, 822, nil, nil, nil, nil, nil, nil,
- nil, 822, nil, nil, nil, nil, 822, 822, 822, 822,
- 822, 822, nil, nil, nil, 822, 822, 827, 827, 827,
- nil, 827, nil, nil, nil, 827, 827, nil, nil, nil,
- 827, nil, 827, 827, 827, 827, 827, 827, 827, nil,
- nil, nil, nil, 827, 827, 827, 827, 827, 827, 827,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 827,
- nil, nil, 827, 827, 827, 827, 827, 827, 827, 827,
- 827, 827, nil, 827, 827, nil, nil, nil, 827, nil,
- 684, 684, 684, 684, 684, 684, 684, 684, 684, 684,
- 684, nil, 684, 684, nil, nil, 684, 684, 827, nil,
- nil, 827, nil, nil, 827, 827, nil, nil, 827, nil,
- nil, nil, 684, nil, 684, nil, 684, 684, 684, 684,
- 684, 684, 684, nil, 684, nil, nil, 827, 827, 827,
- 827, 827, 827, nil, nil, nil, 827, 827, 832, 832,
- 832, 684, 832, nil, nil, nil, 832, 832, nil, nil,
- nil, 832, nil, 832, 832, 832, 832, 832, 832, 832,
- nil, nil, nil, nil, 832, 832, 832, 832, 832, 832,
- 832, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 832, nil, nil, 832, 832, 832, 832, 832, 832, 832,
- 832, 832, 832, nil, 832, 832, nil, 832, 832, 832,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 832,
- nil, nil, 832, nil, nil, 832, 832, nil, nil, 832,
- nil, 832, nil, 832, nil, 832, nil, nil, nil, nil,
- nil, nil, nil, 832, nil, nil, nil, nil, 832, 832,
- 832, 832, 832, 832, nil, nil, nil, 832, 832, 835,
- 835, 835, nil, 835, nil, nil, nil, 835, 835, nil,
- nil, nil, 835, nil, 835, 835, 835, 835, 835, 835,
- 835, nil, nil, nil, nil, 835, 835, 835, 835, 835,
- 835, 835, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 835, nil, nil, 835, 835, 835, 835, 835, 835,
- 835, 835, 835, 835, nil, 835, 835, nil, 835, 835,
- 835, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 835, nil, nil, 835, nil, nil, 835, 835, nil, nil,
- 835, nil, 835, nil, 835, nil, 835, nil, nil, nil,
- nil, nil, nil, nil, 835, nil, nil, nil, nil, 835,
- 835, 835, 835, 835, 835, nil, nil, nil, 835, 835,
- 861, 861, 861, nil, 861, nil, nil, nil, 861, 861,
- nil, nil, nil, 861, nil, 861, 861, 861, 861, 861,
- 861, 861, nil, nil, nil, nil, 861, 861, 861, 861,
- 861, 861, 861, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 861, nil, nil, 861, 861, 861, 861, 861,
- 861, 861, 861, 861, 861, nil, 861, 861, nil, nil,
- nil, 861, nil, 687, 687, 687, 687, 687, 687, 687,
- 687, 687, 687, 687, nil, 687, 687, nil, nil, 687,
- 687, 861, nil, nil, 861, nil, nil, 861, 861, nil,
- nil, 861, nil, nil, nil, 687, nil, 687, nil, 687,
- 687, 687, 687, 687, 687, 687, nil, 687, nil, nil,
- 861, 861, 861, 861, 861, 861, nil, nil, nil, 861,
- 861, 864, 864, 864, 687, 864, nil, nil, nil, 864,
- 864, nil, nil, nil, 864, nil, 864, 864, 864, 864,
- 864, 864, 864, nil, nil, nil, nil, 864, 864, 864,
- 864, 864, 864, 864, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 864, nil, nil, 864, 864, 864, 864,
- 864, 864, 864, 864, 864, 864, nil, 864, 864, nil,
- 864, 864, 864, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 864, nil, nil, 864, nil, nil, 864, 864,
- nil, nil, 864, nil, nil, nil, nil, nil, 864, nil,
- nil, nil, nil, nil, nil, nil, 864, nil, nil, nil,
- nil, 864, 864, 864, 864, 864, 864, nil, nil, nil,
- 864, 864, 867, 867, 867, nil, 867, nil, nil, nil,
- 867, 867, nil, nil, nil, 867, nil, 867, 867, 867,
- 867, 867, 867, 867, nil, nil, nil, nil, 867, 867,
- 867, 867, 867, 867, 867, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 867, nil, nil, 867, 867, 867,
- 867, 867, 867, 867, 867, 867, 867, nil, 867, 867,
- nil, 867, 867, 867, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 867, nil, nil, 867, nil, nil, 867,
- 867, nil, nil, 867, nil, nil, nil, nil, nil, 867,
- nil, nil, nil, nil, nil, nil, nil, 867, nil, nil,
- nil, nil, 867, 867, 867, 867, 867, 867, nil, nil,
- nil, 867, 867, 875, 875, 875, nil, 875, nil, nil,
- nil, 875, 875, nil, nil, nil, 875, nil, 875, 875,
- 875, 875, 875, 875, 875, nil, nil, nil, nil, 875,
- 875, 875, 875, 875, 875, 875, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 875, nil, nil, 875, 875,
- 875, 875, 875, 875, 875, 875, 875, 875, nil, 875,
- 875, nil, nil, nil, 875, nil, 689, 689, 689, 689,
- 689, 689, 689, 689, 689, 689, 689, nil, 689, 689,
- nil, nil, 689, 689, 875, nil, nil, 875, nil, nil,
- 875, 875, nil, nil, 875, nil, nil, nil, 689, nil,
- 689, nil, 689, 689, 689, 689, 689, 689, 689, nil,
- 689, nil, nil, 875, 875, 875, 875, 875, 875, nil,
- nil, nil, 875, 875, 880, 880, 880, 689, 880, nil,
- nil, nil, 880, 880, nil, nil, nil, 880, nil, 880,
- 880, 880, 880, 880, 880, 880, nil, nil, nil, nil,
- 880, 880, 880, 880, 880, 880, 880, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 880, nil, nil, 880,
- 880, 880, 880, 880, 880, 880, 880, 880, 880, nil,
- 880, 880, nil, 880, 880, 880, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 880, nil, nil, 880, nil,
- nil, 880, 880, nil, nil, 880, nil, 880, nil, 880,
- nil, 880, nil, nil, nil, nil, nil, nil, nil, 880,
- nil, nil, nil, nil, 880, 880, 880, 880, 880, 880,
- nil, nil, nil, 880, 880, 886, 886, 886, nil, 886,
- nil, nil, nil, 886, 886, nil, nil, nil, 886, nil,
- 886, 886, 886, 886, 886, 886, 886, nil, nil, nil,
- nil, 886, 886, 886, 886, 886, 886, 886, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 886, nil, nil,
- 886, 886, 886, 886, 886, 886, 886, 886, 886, 886,
- nil, 886, 886, nil, nil, nil, 886, nil, 694, 694,
- 694, 694, 694, 694, 694, 694, 694, 694, 694, nil,
- 694, 694, nil, nil, 694, 694, 886, nil, nil, 886,
- nil, nil, 886, 886, nil, nil, 886, nil, nil, nil,
- 694, nil, 694, nil, 694, 694, 694, 694, 694, 694,
- 694, nil, 694, nil, nil, 886, 886, 886, 886, 886,
- 886, nil, nil, nil, 886, 886, 889, 889, 889, 694,
- 889, nil, nil, nil, 889, 889, nil, nil, nil, 889,
- nil, 889, 889, 889, 889, 889, 889, 889, nil, nil,
- nil, nil, 889, 889, 889, 889, 889, 889, 889, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 889, nil,
- nil, 889, 889, 889, 889, 889, 889, 889, 889, 889,
- 889, nil, 889, 889, nil, 889, 889, 889, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 889, nil, nil,
- 889, nil, nil, 889, 889, nil, nil, 889, nil, nil,
- nil, nil, nil, 889, nil, nil, nil, nil, nil, nil,
- nil, 889, nil, nil, nil, nil, 889, 889, 889, 889,
- 889, 889, nil, nil, nil, 889, 889, 64, 64, 64,
- 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
- 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
- 64, nil, nil, 64, 64, 64, 64, 64, 64, 64,
- 64, 64, 64, nil, nil, nil, nil, nil, 64, 64,
- 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
- nil, nil, nil, nil, nil, nil, 64, 64, nil, 64,
- 64, 64, 64, nil, 64, 64, nil, nil, 64, nil,
- nil, nil, nil, 64, 64, 64, 64, nil, nil, nil,
- nil, nil, 64, nil, nil, nil, nil, nil, nil, nil,
- 64, 64, nil, 64, 64, 64, 64, 64, 64, 64,
- 64, 64, nil, 64, nil, nil, 64, 664, 664, 664,
- 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
- 664, 664, 664, 664, 664, 664, 664, 664, 664, 664,
- 664, nil, nil, 664, 664, 664, 664, 664, 664, 664,
- 664, 664, 664, nil, nil, nil, nil, nil, 664, 664,
- 664, 664, 664, 664, 664, 664, nil, nil, 664, nil,
- nil, nil, nil, nil, nil, nil, 664, 664, nil, 664,
- 664, 664, 664, nil, 664, 664, nil, nil, 664, nil,
- nil, nil, nil, 664, 664, 664, 664, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 664, 664, nil, 664, 664, 664, 664, 664, 664, 664,
- 664, 664, nil, 664, nil, nil, 664, 581, 581, 581,
- 581, 581, 581, 581, 581, 581, 581, 581, nil, 581,
- 581, nil, nil, 581, 581, nil, nil, nil, 581, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 581,
- nil, 581, nil, 581, 581, 581, 581, 581, 581, 581,
- nil, 581, nil, nil, nil, nil, nil, nil, nil, 192,
- 192, nil, nil, 192, nil, nil, nil, nil, 581, nil,
- 581, 192, 192, nil, 192, 192, 192, 192, nil, 192,
- 192, nil, nil, 192, nil, nil, nil, nil, 192, 192,
- 192, 192, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 192, 192, nil, 192, 192,
- 192, 192, 192, 192, 192, 192, 192, nil, 192, 193,
- 193, 192, nil, 193, nil, nil, nil, nil, nil, nil,
- nil, 193, 193, nil, 193, 193, 193, 193, nil, 193,
- 193, nil, nil, 193, nil, nil, nil, nil, 193, 193,
- 193, 193, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 193, 193, nil, 193, 193,
- 193, 193, 193, 193, 193, 193, 193, nil, 193, 251,
- 251, 193, nil, 251, nil, nil, nil, nil, nil, nil,
- nil, 251, 251, nil, 251, 251, 251, 251, nil, 251,
- 251, nil, nil, 251, nil, nil, nil, nil, 251, 251,
- 251, 251, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 251, 251, nil, 251, 251,
- 251, 251, 251, 251, 251, 251, 251, nil, 251, 252,
- 252, 251, nil, 252, nil, nil, nil, nil, nil, nil,
- nil, 252, 252, nil, 252, 252, 252, 252, nil, 252,
- 252, nil, nil, 252, nil, nil, nil, nil, 252, 252,
- 252, 252, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 252, 252, nil, 252, 252,
- 252, 252, 252, 252, 252, 252, 252, nil, 252, 391,
- 391, 252, nil, 391, nil, nil, nil, nil, nil, nil,
- nil, 391, 391, nil, 391, 391, 391, 391, nil, 391,
- 391, nil, nil, 391, nil, nil, nil, nil, 391, 391,
- 391, 391, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 391, 391, nil, 391, 391,
- 391, 391, 391, 391, 391, 391, 391, nil, 391, 392,
- 392, 391, nil, 392, nil, nil, nil, nil, nil, nil,
- nil, 392, 392, nil, 392, 392, 392, 392, nil, 392,
- 392, nil, nil, 392, nil, nil, nil, nil, 392, 392,
- 392, 392, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 392, 392, nil, 392, 392,
- 392, 392, 392, 392, 392, 392, 392, nil, 392, nil,
- nil, 392, 423, 423, 423, 423, 423, 423, 423, 423,
- 423, 423, 423, nil, 423, 423, nil, nil, 423, 423,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 423, nil, 423, nil, 423, 423,
- 423, 423, 423, 423, 423, nil, 423, nil, nil, nil,
- nil, nil, nil, 457, 457, nil, nil, 457, nil, nil,
- nil, nil, nil, 423, 423, 457, 457, nil, 457, 457,
- 457, 457, nil, 457, 457, nil, nil, 457, nil, nil,
- nil, nil, 457, 457, 457, 457, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 457,
- 457, nil, 457, 457, 457, 457, 457, 457, 457, 457,
- 457, nil, 457, 458, 458, 457, nil, 458, nil, nil,
- nil, nil, nil, nil, nil, 458, 458, nil, 458, 458,
- 458, 458, nil, 458, 458, nil, nil, 458, nil, nil,
- nil, nil, 458, 458, 458, 458, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 458,
- 458, nil, 458, 458, 458, 458, 458, 458, 458, 458,
- 458, nil, 458, 466, 466, 458, nil, 466, nil, nil,
- nil, nil, nil, nil, nil, 466, 466, nil, 466, 466,
- 466, 466, nil, 466, 466, nil, nil, 466, nil, nil,
- nil, nil, 466, 466, 466, 466, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 466,
- 466, nil, 466, 466, 466, 466, 466, 466, 466, 466,
- 466, nil, 466, 467, 467, 466, nil, 467, nil, nil,
- nil, nil, nil, nil, nil, 467, 467, nil, 467, 467,
- 467, 467, nil, 467, 467, nil, nil, 467, nil, nil,
- nil, nil, 467, 467, 467, 467, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 467,
- 467, nil, 467, 467, 467, 467, 467, 467, 467, 467,
- 467, nil, 467, 498, 498, 467, nil, 498, nil, nil,
- nil, nil, nil, nil, nil, 498, 498, nil, 498, 498,
- 498, 498, nil, 498, 498, nil, nil, 498, nil, nil,
- nil, nil, 498, 498, 498, 498, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 498,
- 498, nil, 498, 498, 498, 498, 498, 498, 498, 498,
- 498, nil, 498, 499, 499, 498, nil, 499, nil, nil,
- nil, nil, nil, nil, nil, 499, 499, nil, 499, 499,
- 499, 499, nil, 499, 499, nil, nil, 499, nil, nil,
- nil, nil, 499, 499, 499, 499, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 499,
- 499, nil, 499, 499, 499, 499, 499, 499, 499, 499,
- 499, nil, 499, 505, 505, 499, nil, 505, nil, nil,
- nil, nil, nil, nil, nil, 505, 505, nil, 505, 505,
- 505, 505, nil, 505, 505, nil, nil, 505, nil, nil,
- nil, nil, 505, 505, 505, 505, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 505,
- 505, nil, 505, 505, 505, 505, 505, 505, 505, 505,
- 505, nil, 505, 507, 507, 505, nil, 507, nil, nil,
- nil, nil, nil, nil, nil, 507, 507, nil, 507, 507,
- 507, 507, nil, 507, 507, nil, nil, 507, nil, nil,
- nil, nil, 507, 507, 507, 507, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 507,
- 507, nil, 507, 507, 507, 507, 507, 507, 507, 507,
- 507, nil, 507, 578, 578, 507, nil, 578, nil, nil,
- nil, nil, nil, nil, nil, 578, 578, nil, 578, 578,
- 578, 578, nil, 578, 578, nil, nil, 578, nil, nil,
- nil, nil, 578, 578, 578, 578, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 578,
- 578, nil, 578, 578, 578, 578, 578, 578, 578, 578,
- 578, nil, 578, 579, 579, 578, nil, 579, nil, nil,
- nil, nil, nil, nil, nil, 579, 579, nil, 579, 579,
- 579, 579, nil, 579, 579, nil, nil, 579, nil, nil,
- nil, nil, 579, 579, 579, 579, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 579,
- 579, nil, 579, 579, 579, 579, 579, 579, 579, 579,
- 579, nil, 579, 823, 823, 579, nil, 823, nil, nil,
- nil, nil, nil, nil, nil, 823, 823, nil, 823, 823,
- 823, 823, nil, 823, 823, nil, nil, 823, nil, nil,
- nil, nil, 823, 823, 823, 823, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 823,
- 823, nil, 823, 823, 823, 823, 823, 823, 823, 823,
- 823, nil, 823, 824, 824, 823, nil, 824, nil, nil,
- nil, nil, nil, nil, nil, 824, 824, nil, 824, 824,
- 824, 824, nil, 824, 824, nil, nil, 824, nil, nil,
- nil, nil, 824, 824, 824, 824, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 824,
- 824, nil, 824, 824, 824, 824, 824, 824, 824, 824,
- 824, nil, 824, nil, nil, 824, 480, 480, 480, 480,
- 480, 480, 480, 480, 480, 480, 480, nil, 480, 480,
- nil, nil, 480, 480, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 480, nil,
- 480, nil, 480, 480, 480, 480, 480, 480, 480, nil,
- 480, nil, 731, 731, 731, 731, 731, 731, 731, 731,
- 731, 731, 731, nil, 731, 731, 480, 480, 731, 731,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 731, nil, 731, nil, 731, 731,
- 731, 731, 731, 731, 731, nil, 731, nil, 767, 767,
- 767, 767, 767, 767, 767, 767, 767, 767, 767, nil,
- 767, 767, 731, 731, 767, 767, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 767, nil, 767, nil, 767, 767, 767, 767, 767, 767,
- 767, nil, 767, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 767 ]
-
-racc_action_pointer = [
- 1233, 30, nil, -98, 863, 4770, 4891, 5012, -53, 2,
- 71, 90, 160, 218, 174, 130, nil, 5125, 5246, 6094,
- 234, nil, 5367, 5488, 5609, 292, 138, 5730, 5851, nil,
- 1355, 5972, 6093, nil, 146, 316, 245, 346, 6214, 6335,
- 6456, 183, 300, nil, nil, nil, nil, nil, nil, nil,
- 214, 1477, 6577, 6698, 6819, 58, 6940, 7061, nil, nil,
- 735, 7182, 7303, 7424, 22775, nil, nil, nil, nil, nil,
- -92, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 7545, nil, nil, nil, 7666, nil, nil, nil,
- nil, nil, nil, nil, nil, 311, nil, 863, nil, nil,
- nil, 7787, 7908, 8029, 8150, 8271, 981, nil, 221, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 196, nil, 1599, 1721, 8392, 8513,
- 8634, 8755, 23000, 23060, 8876, 8997, 9118, nil, 377, -67,
- 279, -52, 212, 274, 1843, nil, nil, 9239, 9360, 9481,
- 9602, 9723, 9844, 9965, 10086, 10207, 10328, 10449, 10570, 10691,
- 10812, 10933, 11054, 11175, 11296, 11417, 11538, 11659, 11780, 11901,
- 12022, 12143, 12264, 12385, nil, nil, nil, 7183, nil, 242,
- 254, 12506, nil, 12627, 310, nil, nil, nil, nil, nil,
- nil, 23120, 23180, 313, 12748, 12869, nil, nil, nil, nil,
- nil, nil, nil, 12990, 325, 1965, 333, 352, 315, 13111,
- 2087, 399, 496, 430, 520, 411, 382, 161, nil, 443,
- 430, nil, nil, 335, 472, 486, 521, nil, 498, nil,
- 13232, nil, 565, 566, 457, nil, 460, 119, 136, 13353,
- 493, 147, 479, 244, nil, 482, -7, 8, 13474, 13595,
- -67, 32, 464, -9, 522, 545, -1, 575, nil, nil,
- 319, 345, 115, nil, 614, nil, 9, 13716, nil, nil,
- 311, 419, 453, 456, 457, 478, 488, 499, nil, 519,
- nil, 13837, nil, 149, 207, 235, 246, -35, 279, nil,
- 1103, nil, nil, nil, nil, nil, nil, 13958, nil, nil,
- nil, nil, 509, 511, nil, nil, 735, nil, 495, 14071,
- nil, 499, nil, nil, 7304, 535, 340, 342, 14192, nil,
- nil, 0, 541, 107, nil, 14313, 14434, nil, 7425, nil,
- nil, 23240, 23300, 14555, -33, 14676, 14797, 14918, 614, 863,
- 377, 384, 566, 574, 575, 576, 2941, 3063, 3185, 1599,
- 980, 1721, 1843, 1965, 2087, 2209, 2331, 2453, 2575, 249,
- 465, 2697, 2819, 23348, -48, nil, 15039, nil, 15160, 514,
- nil, 15281, 321, nil, nil, 376, nil, nil, 563, 531,
- -64, 529, 630, nil, nil, 15402, -27, -13, 571, nil,
- 572, 544, nil, nil, nil, 586, 15523, 23414, 23474, 617,
- 606, nil, nil, 15644, 15765, 15886, 23534, 23594, 13112, 16007,
- 688, 16128, nil, 582, nil, nil, 16249, nil, nil, 16370,
- 24122, nil, 16491, nil, nil, nil, 2209, 711, nil, nil,
- 2331, 68, 109, 708, 716, 2453, 16612, 16733, 23654, 23714,
- 4, nil, nil, 658, nil, 23774, 16854, 23834, nil, nil,
- 16975, 100, -34, 2575, 997, nil, nil, nil, -32, nil,
- nil, nil, 598, nil, nil, nil, 609, nil, 147, nil,
- nil, 606, nil, nil, 17096, nil, nil, 17209, 17330, nil,
- 349, 17451, 17572, 648, nil, nil, 17693, 649, nil, 17814,
- 86, 115, 493, 614, 655, 1106, 17935, 18056, nil, 2697,
- 18177, 621, nil, 666, 18298, nil, 674, nil, 663, nil,
- nil, nil, nil, nil, 113, nil, 673, 674, 23894, 23954,
- 18419, 22933, 69, 643, 18540, nil, 683, nil, 2819, 2941,
- nil, 1, nil, 681, 63, 112, 687, 347, 735, 688,
- 19630, 712, 714, -2, 772, nil, 3063, 654, 707, nil,
- nil, 707, 18661, nil, nil, 506, nil, 800, nil, nil,
- nil, nil, nil, 810, nil, 814, 700, 15, 18782, 738,
- 13, 23, 25, 75, 18903, 348, 788, nil, 740, 3185,
- 331, nil, nil, 835, 3307, 1284, 337, 718, 719, 726,
- nil, nil, nil, nil, nil, 724, nil, nil, nil, nil,
- 806, nil, nil, 809, 22885, 773, nil, nil, nil, nil,
- nil, 3429, nil, nil, nil, nil, nil, 20114, 744, 19024,
- 19145, nil, 21324, nil, 21566, nil, nil, 21929, nil, 22292,
- 19266, 19387, 19508, 167, 22534, nil, 745, 984, 19629, nil,
- 770, 868, 760, nil, 19750, 761, 3551, nil, nil, 802,
- 803, -63, 871, 19871, nil, 19992, 772, nil, 832, 813,
- 933, 738, nil, nil, 3673, nil, nil, 31, 20113, nil,
- nil, 24168, 938, nil, 20234, 941, 3795, 3917, nil, nil,
- 20355, 4039, nil, 26, 133, nil, 942, nil, 4161, nil,
- 946, 836, nil, 1406, nil, -43, nil, nil, 436, 20476,
- nil, nil, nil, nil, 862, nil, nil, 24214, 20597, 20718,
- 863, 866, 920, 907, 847, 884, nil, nil, nil, nil,
- 20839, nil, 873, 903, 869, nil, 20960, 870, 21081, nil,
- nil, nil, nil, nil, 4283, nil, nil, nil, 32, nil,
- 999, 1001, 21202, 332, nil, nil, 1002, nil, 936, 898,
- 899, nil, nil, 900, 899, nil, nil, 1528, nil, nil,
- 21323, 1106, 21444, 24014, 24074, 918, 933, 21565, 5973, nil,
- nil, nil, 21686, 914, nil, 21807, 918, 1046, 4405, nil,
- nil, nil, nil, nil, nil, 4527, nil, nil, 282, nil,
- nil, nil, 4649, nil, 927, 959, 965, 362, 400, 482,
- 977, 21928, nil, nil, 22049, 931, nil, 22170, nil, nil,
- 545, 1054, 938, 1057, 972, 22291, 980, nil, 945, nil,
- 22412, 948, nil, nil, nil, nil, 22533, nil, nil, 22654,
- nil, nil, 952, nil ]
-
-racc_action_default = [
- -4, -497, -1, -485, -5, -497, -497, -497, -497, -497,
- -497, -497, -497, -497, -271, -32, -33, -497, -497, -38,
- -40, -41, -282, -315, -316, -45, -249, -361, -285, -58,
- -4, -62, -67, -68, -497, -428, -497, -497, -497, -497,
- -497, -487, -214, -264, -265, -266, -267, -268, -269, -270,
- -475, -4, -497, -496, -467, -288, -497, -497, -292, -295,
- -485, -497, -497, -497, -497, -317, -318, -381, -382, -383,
- -384, -385, -399, -388, -401, -401, -392, -397, -411, -401,
- -413, -414, -417, -418, -419, -420, -421, -422, -423, -424,
- -425, -426, -427, -430, -431, -497, -3, -486, -492, -493,
- -494, -497, -497, -497, -497, -497, -6, -8, -497, -93,
- -94, -95, -96, -97, -98, -99, -100, -101, -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, -13, -102, -4, -4, -497, -497,
- -497, -496, -497, -497, -497, -497, -497, -36, -497, -428,
- -497, -271, -497, -497, -4, -37, -206, -497, -497, -497,
- -497, -497, -497, -497, -497, -497, -497, -497, -497, -497,
- -497, -497, -497, -497, -497, -497, -497, -497, -497, -497,
- -497, -497, -497, -497, -351, -353, -42, -215, -228, -258,
- -258, -497, -236, -497, -259, -282, -315, -316, -470, -43,
- -44, -497, -497, -50, -496, -497, -287, -356, -362, -364,
- -56, -360, -57, -497, -58, -4, -497, -497, -63, -65,
- -4, -72, -497, -497, -79, -285, -487, -497, -319, -361,
- -497, -66, -70, -278, -415, -416, -497, -191, -192, -207,
- -497, -488, -373, -497, -274, -216, -487, -489, -489, -497,
- -497, -489, -497, -489, -289, -39, -497, -497, -497, -497,
- -485, -497, -486, -428, -497, -497, -271, -497, -331, -332,
- -88, -89, -497, -91, -497, -271, -497, -497, -428, -308,
- -93, -94, -131, -132, -148, -153, -160, -163, -310, -497,
- -465, -497, -386, -497, -497, -497, -497, -497, -497, 894,
- -7, -495, -14, -15, -16, -17, -18, -497, -10, -11,
- -12, -103, -497, -497, -21, -29, -171, -259, -497, -497,
- -22, -30, -31, -23, -173, -497, -476, -477, -226, -478,
- -479, -476, -249, -477, -359, -481, -482, -28, -180, -34,
- -35, -497, -497, -496, -278, -497, -497, -497, -181, -182,
- -183, -184, -185, -186, -187, -188, -193, -194, -195, -196,
- -197, -198, -199, -200, -201, -202, -203, -204, -205, -208,
- -209, -210, -211, -497, -347, -229, -497, -231, -497, -258,
- -256, -497, -249, -476, -477, -249, -48, -51, -497, -487,
- -487, -258, -228, -250, -251, -252, -347, -347, -497, -284,
- -497, -59, -276, -71, -64, -497, -496, -497, -497, -78,
- -497, -415, -416, -497, -497, -497, -497, -497, -212, -497,
- -496, -496, -273, -487, -217, -218, -491, -490, -220, -491,
- -487, -280, -491, -469, -281, -468, -4, -320, -321, -322,
- -4, -497, -497, -497, -497, -4, -497, -496, -497, -497,
- -278, -301, -88, -89, -90, -497, -496, -497, -304, -432,
- -497, -497, -497, -4, -445, -312, -483, -484, -487, -387,
- -400, -403, -497, -405, -389, -402, -497, -391, -497, -394,
- -396, -497, -412, -9, -497, -19, -20, -497, -497, -263,
- -279, -497, -497, -52, -227, -357, -497, -54, -358, -497,
- -476, -477, -480, -277, -497, -171, -497, -497, -349, -4,
- -497, -258, -257, -260, -497, -471, -497, -235, -497, -472,
- -46, -354, -47, -355, -347, -222, -497, -497, -497, -497,
- -497, -38, -497, -258, -497, -248, -497, -254, -4, -4,
- -283, -59, -69, -497, -476, -477, -226, -75, -77, -497,
- -179, -189, -190, -497, -496, -329, -4, -374, -496, -375,
- -376, -497, -497, -260, -221, -496, -323, -496, -293, -324,
- -325, -326, -296, -497, -299, -497, -367, -497, -497, -497,
- -476, -477, -480, -277, -497, -88, -89, -92, -497, -4,
- -497, -434, -306, -497, -4, -445, -497, -464, -464, -464,
- -444, -446, -447, -448, -449, -450, -451, -454, -456, -457,
- -459, -460, -461, -497, -497, -497, -404, -407, -408, -409,
- -410, -4, -390, -393, -395, -398, -104, -172, -261, -497,
- -497, -25, -175, -26, -176, -53, -27, -177, -55, -178,
- -497, -497, -497, -279, -213, -333, -335, -345, -497, -348,
- -497, -497, -258, -233, -497, -258, -4, -223, -224, -226,
- -226, -487, -497, -497, -241, -497, -258, -253, -497, -497,
- -497, -73, -286, -2, -4, -380, -330, -497, -497, -378,
- -275, -487, -497, -327, -497, -497, -4, -4, -298, -300,
- -497, -4, -369, -279, -497, -279, -497, -433, -4, -309,
- -497, -487, -436, -497, -440, -497, -442, -443, -497, -497,
- -458, -462, -313, -466, -497, -262, -24, -174, -497, -336,
- -80, -497, -497, -87, -344, -497, -346, -350, -352, -230,
- -497, -232, -497, -497, -258, -238, -497, -258, -497, -247,
- -255, -363, -365, -379, -4, -377, -219, -290, -497, -291,
- -497, -497, -497, -496, -302, -305, -497, -311, -497, -464,
- -464, -452, -463, -464, -497, -455, -453, -445, -406, -334,
- -497, -341, -496, -497, -497, -86, -497, -497, -258, -49,
- -225, -237, -497, -258, -243, -497, -258, -373, -4, -294,
- -297, -368, -366, -370, -371, -4, -307, -435, -497, -438,
- -439, -441, -4, -337, -340, -497, -497, -82, -84, -83,
- -85, -497, -343, -234, -497, -258, -239, -497, -242, -372,
- -496, -497, -464, -497, -497, -497, -81, -342, -258, -244,
- -497, -258, -328, -303, -437, -314, -497, -339, -240, -497,
- -245, -338, -258, -246 ]
-
-racc_goto_table = [
- 10, 205, 240, 240, 240, 10, 268, 438, 112, 112,
- 100, 300, 338, 470, 293, 644, 242, 242, 242, 440,
- 107, 185, 238, 238, 238, 115, 115, 117, 117, 494,
- 10, 486, 490, 650, 303, 437, 239, 239, 239, 253,
- 260, 262, 604, 290, 365, 372, 732, 618, 622, 96,
- 565, 10, 815, 296, 257, 261, 281, 571, 504, 520,
- 573, 318, 529, 236, 249, 250, 112, 100, 301, 559,
- 810, 264, 813, 266, 106, 475, 478, 344, 345, 483,
- 1, 485, 348, 723, 754, 756, 757, 326, 329, 306,
- 307, 588, 589, 310, 97, 13, 184, 10, 319, 357,
- 13, 565, 574, 534, 587, 10, 311, 443, 586, 718,
- 340, 302, 198, 198, 304, 317, 508, 198, 198, 198,
- 339, 515, 473, 308, 736, 13, 272, 272, 309, 737,
- 634, 278, 278, 845, 352, 353, 354, 355, 639, 748,
- 513, 197, 514, 664, 817, 815, 13, 198, 198, 375,
- 696, 198, 198, 700, 424, 198, 314, 324, 324, 446,
- 447, 278, 278, 278, 650, 872, 350, 627, 842, 608,
- 727, 364, 370, 373, 356, 342, 294, 387, 343, 346,
- 305, 305, 528, 347, 305, 666, 10, 10, 671, 735,
- 751, 296, 13, 809, 811, 386, 198, 198, 198, 198,
- 13, 2, 368, 368, 10, nil, nil, nil, nil, nil,
- nil, 623, nil, nil, nil, nil, nil, nil, nil, 706,
- nil, nil, nil, 605, 610, 305, 305, 305, 305, nil,
- nil, 267, nil, nil, 240, 240, nil, nil, nil, nil,
- nil, 637, nil, 240, 674, nil, 849, 850, 242, 242,
- 851, nil, nil, nil, 442, 238, nil, 242, nil, nil,
- nil, nil, nil, 238, nil, 10, nil, nil, 441, 239,
- 10, nil, nil, nil, nil, nil, nil, 239, 460, nil,
- nil, 13, 13, 198, 198, 198, 198, nil, nil, 198,
- 198, 198, 14, 454, nil, 439, 444, 14, 474, 13,
- 804, 882, nil, 427, 448, 257, 264, 261, 450, 884,
- nil, 264, nil, 455, nil, nil, nil, 100, 852, 389,
- 390, nil, 14, 274, 274, 685, 565, 609, nil, 688,
- nil, nil, nil, 509, 571, 573, 650, 565, nil, nil,
- nil, 491, 492, 14, nil, 711, nil, nil, nil, 198,
- 198, 554, 741, 316, 325, 325, 493, 725, 198, 112,
- 13, 729, nil, nil, 272, 13, nil, nil, 605, 278,
- 605, 533, nil, nil, nil, 843, 115, nil, 117, nil,
- nil, nil, nil, nil, nil, nil, nil, 362, 363, 14,
- nil, 543, nil, 296, 386, 547, nil, 14, nil, nil,
- nil, nil, nil, 198, 198, 267, 561, nil, nil, nil,
- 548, nil, nil, nil, 593, nil, nil, nil, nil, nil,
- nil, nil, 198, nil, nil, 583, nil, nil, nil, nil,
- nil, nil, 305, 305, nil, nil, 198, nil, nil, 585,
- nil, 576, 577, nil, nil, 570, nil, nil, 572, nil,
- nil, 512, 794, nil, nil, 629, 296, 565, nil, nil,
- 386, nil, nil, nil, 638, 518, 267, nil, nil, 386,
- nil, 267, nil, nil, nil, 611, 643, nil, 14, 14,
- nil, nil, 614, nil, nil, 368, 10, nil, 198, nil,
- 10, nil, 567, nil, nil, 10, 14, 296, 619, 619,
- nil, 386, 565, nil, nil, nil, 296, 386, nil, nil,
- 626, nil, nil, 10, nil, nil, nil, nil, 641, 642,
- 665, 844, nil, 838, 681, 683, nil, nil, nil, 686,
- nil, nil, 695, nil, nil, nil, 112, nil, nil, nil,
- 198, nil, nil, 640, nil, nil, nil, nil, 676, nil,
- nil, 198, nil, 115, nil, 117, 605, 14, 869, 10,
- 561, 274, 14, nil, 198, nil, nil, nil, nil, 294,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 712, 13, nil, nil, nil, 13, nil, nil, 10, 10,
- 13, nil, 198, 603, nil, nil, 378, 382, 35, nil,
- nil, 198, 746, 35, nil, 198, 10, 750, 13, nil,
- nil, nil, 762, 12, nil, nil, nil, nil, 12, nil,
- nil, nil, nil, 605, 703, nil, nil, 548, 35, 271,
- 271, nil, nil, nil, 305, nil, 198, 198, nil, 10,
- nil, 198, nil, 12, 10, nil, 714, 747, nil, 35,
- nil, nil, 272, 752, 13, 432, 435, 278, nil, 313,
- 328, 328, 328, 766, 12, nil, 112, 744, nil, nil,
- nil, 10, nil, nil, nil, 198, nil, nil, nil, nil,
- nil, nil, nil, 13, 13, nil, nil, 615, nil, nil,
- nil, 617, nil, 787, nil, 35, 625, 774, 776, nil,
- nil, 13, nil, 35, nil, nil, 10, 785, nil, nil,
- 12, 806, nil, 783, nil, nil, nil, nil, 12, nil,
- nil, nil, nil, nil, 10, nil, nil, 784, 795, 198,
- nil, nil, nil, 796, 13, nil, 10, 10, nil, 13,
- nil, 10, nil, nil, 819, nil, nil, nil, 10, nil,
- nil, 619, nil, 808, nil, nil, nil, nil, 305, nil,
- 701, nil, nil, nil, nil, 779, 13, 798, 781, nil,
- nil, nil, nil, nil, nil, 198, nil, nil, 14, 789,
- 856, nil, 14, nil, 35, 35, nil, 14, nil, 719,
- 720, nil, 771, 771, 10, 378, 382, 278, 278, 12,
- 12, 13, 35, nil, nil, 14, nil, 726, nil, nil,
- nil, nil, 865, nil, 670, 873, nil, 12, nil, 13,
- 853, 854, 296, 771, nil, nil, 386, 862, 278, 198,
- nil, 13, 13, nil, nil, nil, 13, nil, 10, nil,
- nil, nil, nil, 13, nil, 10, nil, 831, nil, 274,
- 834, 14, 10, nil, nil, nil, nil, nil, 305, nil,
- nil, 877, 599, 35, 272, nil, nil, 271, 35, 278,
- nil, 599, 764, nil, nil, 887, nil, nil, 12, nil,
- 14, 14, nil, 12, nil, nil, 891, nil, nil, 13,
- nil, 863, nil, nil, nil, nil, 866, nil, 14, 868,
- nil, nil, nil, 599, nil, nil, nil, 782, nil, 599,
- nil, nil, nil, nil, nil, 771, 771, 198, nil, nil,
- 278, 278, 771, nil, nil, 793, nil, 278, 879, nil,
- nil, 14, nil, 13, nil, nil, 14, 800, 801, nil,
- 13, 888, 803, nil, 890, nil, nil, 13, nil, nil,
- nil, nil, nil, nil, nil, 893, 771, nil, nil, nil,
- nil, 278, nil, 14, nil, nil, nil, nil, nil, nil,
- 771, nil, nil, nil, nil, 278, nil, nil, nil, nil,
- nil, 771, 709, 710, nil, nil, 278, nil, nil, 773,
- 773, nil, nil, nil, nil, 837, nil, nil, 14, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 14, nil, nil, nil,
- 773, nil, nil, nil, nil, nil, nil, nil, 14, 14,
- nil, nil, nil, 14, nil, nil, nil, nil, nil, 870,
- 14, nil, nil, nil, nil, nil, 871, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 274, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 35, nil, 14, nil, 35, nil,
- nil, nil, nil, 35, nil, nil, nil, nil, nil, 12,
- nil, nil, nil, 12, nil, nil, nil, nil, 12, nil,
- nil, 35, 773, 773, nil, nil, nil, nil, nil, 773,
- nil, nil, nil, nil, nil, nil, 12, nil, nil, nil,
- 14, nil, nil, nil, nil, nil, nil, 14, nil, nil,
- nil, nil, nil, nil, 14, nil, nil, nil, nil, nil,
- nil, nil, nil, 773, nil, 271, nil, 35, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 773, nil, nil,
- nil, nil, 12, nil, nil, nil, nil, nil, 773, nil,
- nil, nil, nil, nil, nil, nil, 35, 35, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 12, 12, nil, 35, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 12,
- nil, nil, nil, nil, nil, nil, nil, nil, 599, nil,
- nil, nil, nil, nil, nil, nil, nil, 35, nil, nil,
- nil, nil, 35, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 12, nil, nil, nil, nil, 12, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 35,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 12, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 770, 770, nil, nil, nil,
- nil, nil, nil, nil, 35, nil, nil, 206, nil, nil,
- nil, 237, 237, 237, nil, nil, nil, nil, nil, 12,
- nil, nil, 35, nil, nil, nil, 770, 287, 288, 289,
- nil, nil, nil, nil, 35, 35, nil, 12, nil, 35,
- nil, nil, 237, 237, nil, nil, 35, nil, nil, 12,
- 12, nil, nil, nil, 12, nil, nil, nil, nil, 367,
- 371, 12, nil, nil, nil, nil, nil, 271, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 35, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 12, nil, nil,
- nil, nil, 429, nil, 430, nil, nil, nil, 770, 770,
- nil, nil, nil, nil, nil, 770, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 35, nil, nil, nil,
- nil, nil, nil, 35, nil, nil, nil, nil, nil, nil,
- 35, 12, nil, nil, nil, nil, nil, nil, 12, 770,
- nil, nil, nil, nil, nil, 12, nil, nil, nil, nil,
- nil, nil, nil, 770, nil, nil, nil, 366, 237, 374,
- 237, nil, nil, 388, 770, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 206, 398, 399, 400,
- 401, 402, 403, 404, 405, 406, 407, 408, 409, 410,
- 411, 412, 413, 414, 415, 416, 417, 418, 419, 420,
- 421, 422, 423, nil, nil, nil, nil, nil, nil, nil,
- 237, nil, 237, nil, nil, nil, nil, nil, nil, nil,
- 539, nil, nil, 237, 237, nil, nil, nil, nil, nil,
- nil, nil, 237, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 468,
- nil, nil, nil, nil, nil, nil, nil, nil, 480, nil,
- nil, nil, nil, nil, nil, nil, nil, 563, nil, 566,
- nil, nil, 569, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 582, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 607, nil, nil, nil, nil, 613, nil, nil,
- 566, nil, nil, 613, nil, nil, nil, nil, 237, nil,
- nil, nil, nil, nil, nil, nil, nil, 367, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 237, nil, 388, 555, 374, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 678,
- nil, nil, nil, nil, nil, 237, nil, 237, nil, nil,
- 237, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 702, nil, nil, 581, 705, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 237, nil, nil, nil, nil,
- nil, 563, 600, 601, 602, 716, nil, 26, nil, nil,
- 237, nil, 26, nil, nil, 237, nil, nil, 237, nil,
- nil, 237, nil, nil, 26, 26, nil, nil, nil, 26,
- 26, 26, nil, nil, nil, 237, 237, 26, nil, nil,
- nil, nil, nil, nil, nil, 237, nil, nil, nil, 742,
- nil, nil, nil, nil, nil, nil, nil, nil, 26, 26,
- 26, nil, nil, 26, 26, nil, nil, 26, nil, nil,
- nil, nil, nil, nil, nil, nil, 677, 237, nil, nil,
- 682, 684, nil, nil, nil, 687, nil, nil, 689, nil,
- nil, nil, nil, nil, nil, 694, nil, nil, nil, 237,
- 765, nil, nil, 237, 26, nil, nil, nil, 26, 26,
- 26, 26, 26, nil, nil, nil, nil, nil, nil, 237,
- nil, nil, nil, 237, nil, 566, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 566, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 731, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 613, nil, nil, nil, nil, nil, 237, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 816, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 26, 26, 26, 26, 26, 26, nil,
- nil, 26, 26, 26, nil, nil, nil, 833, nil, 836,
- nil, 26, nil, nil, nil, nil, nil, nil, 237, 767,
- nil, nil, nil, 841, nil, nil, nil, nil, nil, 682,
- 684, 687, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 237, nil, nil, nil, nil, nil, nil,
- nil, nil, 237, 563, 237, nil, 566, nil, nil, nil,
- nil, 26, 26, nil, nil, nil, nil, nil, nil, nil,
- 26, nil, 26, nil, nil, nil, nil, 26, nil, 237,
- nil, nil, nil, nil, nil, 878, nil, nil, 881, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 237, nil,
- nil, 566, nil, nil, nil, nil, nil, 767, nil, nil,
- 892, nil, nil, nil, nil, 26, 26, nil, nil, 828,
- nil, nil, nil, nil, nil, 237, nil, 237, nil, nil,
- nil, nil, nil, nil, 26, nil, nil, nil, nil, nil,
- nil, 237, nil, nil, nil, nil, nil, nil, 26, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 237, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 237, nil, nil, 237, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 26, nil, nil, 237, nil, nil, 237, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 237,
- nil, nil, nil, nil, nil, nil, nil, nil, 237, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 26, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 26, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 26, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 26, nil, nil, nil, 26, nil, nil,
- nil, nil, 26, nil, 26, nil, nil, nil, nil, nil,
- nil, nil, nil, 26, nil, nil, nil, 26, nil, nil,
- 26, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 26, 26,
- nil, nil, nil, 26, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 26, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 26, nil, nil,
- nil, nil, nil, nil, nil, 26, 26, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 26, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 26, nil, nil, nil, nil, 26, nil, nil, nil,
- nil, 26, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 26, nil,
- nil, nil, nil, nil, nil, nil, nil, 26, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 26, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 26, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 26, nil, 26, 26, nil, nil, nil, 26, nil,
- nil, nil, nil, nil, nil, 26, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 26, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 26,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 26, nil, nil, nil, nil,
- nil, nil, 26, nil, nil, nil, nil, nil, nil, 26 ]
-
-racc_goto_check = [
- 14, 15, 56, 56, 56, 14, 39, 53, 45, 45,
- 82, 19, 44, 4, 3, 83, 60, 60, 60, 29,
- 11, 11, 26, 26, 26, 48, 48, 49, 49, 79,
- 14, 76, 76, 126, 56, 32, 54, 54, 54, 31,
- 31, 31, 5, 51, 21, 21, 77, 78, 78, 8,
- 131, 14, 128, 26, 57, 57, 40, 58, 42, 117,
- 58, 14, 117, 28, 28, 28, 45, 82, 54, 33,
- 124, 36, 124, 37, 9, 55, 55, 114, 114, 55,
- 1, 55, 114, 6, 125, 125, 125, 43, 43, 13,
- 13, 33, 33, 13, 10, 18, 12, 14, 16, 24,
- 18, 131, 34, 50, 61, 14, 8, 62, 64, 65,
- 72, 73, 18, 18, 74, 80, 81, 18, 18, 18,
- 84, 85, 86, 87, 88, 18, 18, 18, 89, 90,
- 91, 52, 52, 92, 13, 13, 13, 13, 93, 94,
- 95, 23, 96, 97, 98, 128, 18, 18, 18, 19,
- 99, 18, 18, 100, 102, 18, 18, 18, 18, 104,
- 105, 52, 52, 52, 126, 124, 9, 106, 107, 108,
- 109, 15, 15, 15, 9, 112, 23, 15, 113, 115,
- 23, 23, 116, 118, 23, 119, 14, 14, 120, 5,
- 121, 26, 18, 123, 127, 45, 18, 18, 18, 18,
- 18, 2, 54, 54, 14, nil, nil, nil, nil, nil,
- nil, 79, nil, nil, nil, nil, nil, nil, nil, 33,
- nil, nil, nil, 53, 53, 23, 23, 23, 23, nil,
- nil, 2, nil, nil, 56, 56, nil, nil, nil, nil,
- nil, 42, nil, 56, 117, nil, 125, 125, 60, 60,
- 125, nil, nil, nil, 26, 26, nil, 60, nil, nil,
- nil, nil, nil, 26, nil, 14, nil, nil, 54, 54,
- 14, nil, nil, nil, nil, nil, nil, 54, 51, nil,
- nil, 18, 18, 18, 18, 18, 18, nil, nil, 18,
- 18, 18, 20, 40, nil, 28, 28, 20, 51, 18,
- 78, 77, nil, 59, 28, 57, 36, 57, 37, 125,
- nil, 36, nil, 37, nil, nil, nil, 82, 83, 23,
- 23, nil, 20, 20, 20, 32, 131, 21, nil, 32,
- nil, nil, nil, 82, 58, 58, 126, 131, nil, nil,
- nil, 13, 13, 20, nil, 29, nil, nil, nil, 18,
- 18, 19, 76, 20, 20, 20, 8, 53, 18, 45,
- 18, 53, nil, nil, 18, 18, nil, nil, 53, 52,
- 53, 11, nil, nil, nil, 5, 48, nil, 49, nil,
- nil, nil, nil, nil, nil, nil, nil, 2, 2, 20,
- nil, 31, nil, 26, 45, 31, nil, 20, nil, nil,
- nil, nil, nil, 18, 18, 2, 56, nil, nil, nil,
- 57, nil, nil, nil, 19, nil, nil, nil, nil, nil,
- nil, nil, 18, nil, nil, 56, nil, nil, nil, nil,
- nil, nil, 23, 23, nil, nil, 18, nil, nil, 60,
- nil, 51, 51, nil, nil, 31, nil, nil, 31, nil,
- nil, 23, 76, nil, nil, 19, 26, 131, nil, nil,
- 45, nil, nil, nil, 19, 23, 2, nil, nil, 45,
- nil, 2, nil, nil, nil, 51, 3, nil, 20, 20,
- nil, nil, 51, nil, nil, 54, 14, nil, 18, nil,
- 14, nil, 59, nil, nil, 14, 20, 26, 82, 82,
- nil, 45, 131, nil, nil, nil, 26, 45, nil, nil,
- 54, nil, nil, 14, nil, nil, nil, nil, 82, 82,
- 51, 79, nil, 76, 15, 15, nil, nil, nil, 15,
- nil, nil, 39, nil, nil, nil, 45, nil, nil, nil,
- 18, nil, nil, 13, nil, nil, nil, nil, 11, nil,
- nil, 18, nil, 48, nil, 49, 53, 20, 4, 14,
- 56, 20, 20, nil, 18, nil, nil, nil, nil, 23,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 26, 18, nil, nil, nil, 18, nil, nil, 14, 14,
- 18, nil, 18, 23, nil, nil, 30, 30, 41, nil,
- nil, 18, 3, 41, nil, 18, 14, 3, 18, nil,
- nil, nil, 44, 17, nil, nil, nil, nil, 17, nil,
- nil, nil, nil, 53, 59, nil, nil, 57, 41, 41,
- 41, nil, nil, nil, 23, nil, 18, 18, nil, 14,
- nil, 18, nil, 17, 14, nil, 59, 82, nil, 41,
- nil, nil, 18, 82, 18, 30, 30, 52, nil, 41,
- 41, 41, 41, 15, 17, nil, 45, 13, nil, nil,
- nil, 14, nil, nil, nil, 18, nil, nil, nil, nil,
- nil, nil, nil, 18, 18, nil, nil, 2, nil, nil,
- nil, 2, nil, 56, nil, 41, 2, 14, 14, nil,
- nil, 18, nil, 41, nil, nil, 14, 60, nil, nil,
- 17, 3, nil, 51, nil, nil, nil, nil, 17, nil,
- nil, nil, nil, nil, 14, nil, nil, 54, 14, 18,
- nil, nil, nil, 51, 18, nil, 14, 14, nil, 18,
- nil, 14, nil, nil, 39, nil, nil, nil, 14, nil,
- nil, 82, nil, 51, nil, nil, nil, nil, 23, nil,
- 2, nil, nil, nil, nil, 59, 18, 13, 59, nil,
- nil, nil, nil, nil, nil, 18, nil, nil, 20, 59,
- 19, nil, 20, nil, 41, 41, nil, 20, nil, 2,
- 2, nil, 18, 18, 14, 30, 30, 52, 52, 17,
- 17, 18, 41, nil, nil, 20, nil, 2, nil, nil,
- nil, nil, 56, nil, 20, 3, nil, 17, nil, 18,
- 14, 14, 26, 18, nil, nil, 45, 14, 52, 18,
- nil, 18, 18, nil, nil, nil, 18, nil, 14, nil,
- nil, nil, nil, 18, nil, 14, nil, 59, nil, 20,
- 59, 20, 14, nil, nil, nil, nil, nil, 23, nil,
- nil, 14, 30, 41, 18, nil, nil, 41, 41, 52,
- nil, 30, 2, nil, nil, 14, nil, nil, 17, nil,
- 20, 20, nil, 17, nil, nil, 14, nil, nil, 18,
- nil, 59, nil, nil, nil, nil, 59, nil, 20, 59,
- nil, nil, nil, 30, nil, nil, nil, 2, nil, 30,
- nil, nil, nil, nil, nil, 18, 18, 18, nil, nil,
- 52, 52, 18, nil, nil, 2, nil, 52, 59, nil,
- nil, 20, nil, 18, nil, nil, 20, 2, 2, nil,
- 18, 59, 2, nil, 59, nil, nil, 18, nil, nil,
- nil, nil, nil, nil, nil, 59, 18, nil, nil, nil,
- nil, 52, nil, 20, nil, nil, nil, nil, nil, nil,
- 18, nil, nil, nil, nil, 52, nil, nil, nil, nil,
- nil, 18, 30, 30, nil, nil, 52, nil, nil, 20,
- 20, nil, nil, nil, nil, 2, nil, nil, 20, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 20, nil, nil, nil,
- 20, nil, nil, nil, nil, nil, nil, nil, 20, 20,
- nil, nil, nil, 20, nil, nil, nil, nil, nil, 2,
- 20, nil, nil, nil, nil, nil, 2, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 20, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 41, nil, 20, nil, 41, nil,
- nil, nil, nil, 41, nil, nil, nil, nil, nil, 17,
- nil, nil, nil, 17, nil, nil, nil, nil, 17, nil,
- nil, 41, 20, 20, nil, nil, nil, nil, nil, 20,
- nil, nil, nil, nil, nil, nil, 17, nil, nil, nil,
- 20, nil, nil, nil, nil, nil, nil, 20, nil, nil,
- nil, nil, nil, nil, 20, nil, nil, nil, nil, nil,
- nil, nil, nil, 20, nil, 41, nil, 41, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 20, nil, nil,
- nil, nil, 17, nil, nil, nil, nil, nil, 20, nil,
- nil, nil, nil, nil, nil, nil, 41, 41, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 17, 17, nil, 41, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 17,
- nil, nil, nil, nil, nil, nil, nil, nil, 30, nil,
- nil, nil, nil, nil, nil, nil, nil, 41, nil, nil,
- nil, nil, 41, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 17, nil, nil, nil, nil, 17, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 41,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 17, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 41, 41, nil, nil, nil,
- nil, nil, nil, nil, 41, nil, nil, 25, nil, nil,
- nil, 25, 25, 25, nil, nil, nil, nil, nil, 17,
- nil, nil, 41, nil, nil, nil, 41, 25, 25, 25,
- nil, nil, nil, nil, 41, 41, nil, 17, nil, 41,
- nil, nil, 25, 25, nil, nil, 41, nil, nil, 17,
- 17, nil, nil, nil, 17, nil, nil, nil, nil, 22,
- 22, 17, nil, nil, nil, nil, nil, 41, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 41, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 17, nil, nil,
- nil, nil, 22, nil, 22, nil, nil, nil, 41, 41,
- nil, nil, nil, nil, nil, 41, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 41, nil, nil, nil,
- nil, nil, nil, 41, nil, nil, nil, nil, nil, nil,
- 41, 17, nil, nil, nil, nil, nil, nil, 17, 41,
- nil, nil, nil, nil, nil, 17, nil, nil, nil, nil,
- nil, nil, nil, 41, nil, nil, nil, 25, 25, 25,
- 25, nil, nil, 25, 41, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
- 25, 25, 25, nil, nil, nil, nil, nil, nil, nil,
- 25, nil, 25, nil, nil, nil, nil, nil, nil, nil,
- 22, nil, nil, 25, 25, nil, nil, nil, nil, nil,
- nil, nil, 25, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 25,
- nil, nil, nil, nil, nil, nil, nil, nil, 25, nil,
- nil, nil, nil, nil, nil, nil, nil, 22, nil, 22,
- nil, nil, 22, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 22, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 22, nil, nil, nil, nil, 22, nil, nil,
- 22, nil, nil, 22, nil, nil, nil, nil, 25, nil,
- nil, nil, nil, nil, nil, nil, nil, 22, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 25, nil, 25, 25, 25, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 22,
- nil, nil, nil, nil, nil, 25, nil, 25, nil, nil,
- 25, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 22, nil, nil, 25, 22, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 25, nil, nil, nil, nil,
- nil, 22, 25, 25, 25, 22, nil, 35, nil, nil,
- 25, nil, 35, nil, nil, 25, nil, nil, 25, nil,
- nil, 25, nil, nil, 35, 35, nil, nil, nil, 35,
- 35, 35, nil, nil, nil, 25, 25, 35, nil, nil,
- nil, nil, nil, nil, nil, 25, nil, nil, nil, 22,
- nil, nil, nil, nil, nil, nil, nil, nil, 35, 35,
- 35, nil, nil, 35, 35, nil, nil, 35, nil, nil,
- nil, nil, nil, nil, nil, nil, 25, 25, nil, nil,
- 25, 25, nil, nil, nil, 25, nil, nil, 25, nil,
- nil, nil, nil, nil, nil, 25, nil, nil, nil, 25,
- 22, nil, nil, 25, 35, nil, nil, nil, 35, 35,
- 35, 35, 35, nil, nil, nil, nil, nil, nil, 25,
- nil, nil, nil, 25, nil, 22, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 22, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 25, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 22, nil, nil, nil, nil, nil, 25, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 22, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 35, 35, 35, 35, 35, 35, nil,
- nil, 35, 35, 35, nil, nil, nil, 22, nil, 22,
- nil, 35, nil, nil, nil, nil, nil, nil, 25, 25,
- nil, nil, nil, 22, nil, nil, nil, nil, nil, 25,
- 25, 25, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 25, nil, nil, nil, nil, nil, nil,
- nil, nil, 25, 22, 25, nil, 22, nil, nil, nil,
- nil, 35, 35, nil, nil, nil, nil, nil, nil, nil,
- 35, nil, 35, nil, nil, nil, nil, 35, nil, 25,
- nil, nil, nil, nil, nil, 22, nil, nil, 22, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 25, nil,
- nil, 22, nil, nil, nil, nil, nil, 25, nil, nil,
- 22, nil, nil, nil, nil, 35, 35, nil, nil, 25,
- nil, nil, nil, nil, nil, 25, nil, 25, nil, nil,
- nil, nil, nil, nil, 35, nil, nil, nil, nil, nil,
- nil, 25, nil, nil, nil, nil, nil, nil, 35, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 25, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 25, nil, nil, 25, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 35, nil, nil, 25, nil, nil, 25, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 25,
- nil, nil, nil, nil, nil, nil, nil, nil, 25, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 35, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 35, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 35, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 35, nil, nil, nil, 35, nil, nil,
- nil, nil, 35, nil, 35, nil, nil, nil, nil, nil,
- nil, nil, nil, 35, nil, nil, nil, 35, nil, nil,
- 35, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 35, 35,
- nil, nil, nil, 35, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 35, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 35, nil, nil,
- nil, nil, nil, nil, nil, 35, 35, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 35, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 35, nil, nil, nil, nil, 35, nil, nil, nil,
- nil, 35, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 35, nil,
- nil, nil, nil, nil, nil, nil, nil, 35, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 35, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 35, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 35, nil, 35, 35, nil, nil, nil, 35, nil,
- nil, nil, nil, nil, nil, 35, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 35, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 35,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 35, nil, nil, nil, nil,
- nil, nil, 35, nil, nil, nil, nil, nil, nil, 35 ]
-
-racc_goto_pointer = [
- nil, 80, 201, -37, -279, -428, -521, nil, 46, 69,
- 91, 14, 89, 33, 0, -17, 37, 613, 95, -42,
- 292, -144, 1171, 124, -8, 1289, 0, nil, 41, -235,
- 404, 13, -218, -355, -334, 1757, 41, 43, nil, -25,
- 24, 598, -264, 25, -52, 2, nil, nil, 19, 21,
- -258, 2, 100, -247, 14, -222, -20, 28, -375, 63,
- -6, -341, -148, nil, -337, -478, nil, nil, nil, nil,
- nil, nil, 46, 57, 59, nil, -275, -569, -444, -282,
- 54, -210, 7, -499, 56, -218, -172, 65, -494, 69,
- -493, -371, -671, -370, -503, -189, -196, -372, -618, -407,
- -404, nil, -80, nil, -99, -99, -329, -635, -302, -438,
- nil, nil, 105, 106, 3, 103, -164, -284, 106, -337,
- -335, -455, nil, -560, -683, -563, -481, -559, -703, nil,
- nil, -378 ]
-
-racc_goto_default = [
- nil, nil, 292, nil, nil, 733, nil, 3, nil, 4,
- 312, nil, nil, nil, 202, 16, 11, 203, 286, nil,
- 201, nil, 244, 15, nil, 19, 20, 21, nil, 25,
- 596, nil, nil, nil, nil, 277, 29, nil, 31, 34,
- 33, 199, 323, nil, 114, 380, 113, 116, 68, 69,
- nil, nil, 42, 295, 297, nil, 298, 544, 545, 425,
- 562, nil, nil, 255, nil, nil, 43, 44, 45, 46,
- 47, 48, 49, nil, 256, 55, nil, nil, nil, nil,
- nil, nil, 487, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 235, nil, 384, nil, nil, nil, nil, nil, nil,
- 67, 70, 71, nil, nil, nil, nil, 525, nil, nil,
- nil, 646, 647, 648, 649, nil, 812, 656, 657, 660,
- 663, 248 ]
-
-racc_reduce_table = [
- 0, 0, :racc_error,
- 1, 133, :_reduce_1,
- 4, 135, :_reduce_2,
- 2, 134, :_reduce_3,
- 0, 139, :_reduce_4,
- 1, 139, :_reduce_5,
- 2, 139, :_reduce_6,
- 3, 139, :_reduce_7,
- 0, 156, :_reduce_8,
- 4, 141, :_reduce_9,
- 3, 141, :_reduce_10,
- 3, 141, :_reduce_11,
- 3, 141, :_reduce_12,
- 2, 141, :_reduce_13,
- 3, 141, :_reduce_14,
- 3, 141, :_reduce_15,
- 3, 141, :_reduce_16,
- 3, 141, :_reduce_17,
- 3, 141, :_reduce_18,
- 4, 141, :_reduce_19,
- 4, 141, :_reduce_20,
- 3, 141, :_reduce_21,
- 3, 141, :_reduce_22,
- 3, 141, :_reduce_23,
- 6, 141, :_reduce_24,
- 5, 141, :_reduce_25,
- 5, 141, :_reduce_26,
- 5, 141, :_reduce_27,
- 3, 141, :_reduce_28,
- 3, 141, :_reduce_29,
- 3, 141, :_reduce_30,
- 3, 141, :_reduce_31,
- 1, 141, :_reduce_none,
- 1, 155, :_reduce_none,
- 3, 155, :_reduce_34,
- 3, 155, :_reduce_35,
- 2, 155, :_reduce_36,
- 2, 155, :_reduce_37,
- 1, 155, :_reduce_none,
- 1, 145, :_reduce_none,
- 1, 147, :_reduce_none,
- 1, 147, :_reduce_none,
- 2, 147, :_reduce_42,
- 2, 147, :_reduce_43,
- 2, 147, :_reduce_44,
- 1, 159, :_reduce_none,
- 4, 159, :_reduce_46,
- 4, 159, :_reduce_47,
- 0, 166, :_reduce_48,
- 5, 164, :_reduce_49,
- 2, 158, :_reduce_50,
- 3, 158, :_reduce_51,
- 4, 158, :_reduce_52,
- 5, 158, :_reduce_53,
- 4, 158, :_reduce_54,
- 5, 158, :_reduce_55,
- 2, 158, :_reduce_56,
- 2, 158, :_reduce_57,
- 1, 148, :_reduce_58,
- 3, 148, :_reduce_59,
- 1, 169, :_reduce_60,
- 3, 169, :_reduce_61,
- 1, 168, :_reduce_62,
- 2, 168, :_reduce_63,
- 3, 168, :_reduce_64,
- 2, 168, :_reduce_65,
- 2, 168, :_reduce_66,
- 1, 168, :_reduce_67,
- 1, 171, :_reduce_none,
- 3, 171, :_reduce_69,
- 2, 170, :_reduce_70,
- 3, 170, :_reduce_71,
- 1, 172, :_reduce_72,
- 4, 172, :_reduce_73,
- 3, 172, :_reduce_74,
- 3, 172, :_reduce_75,
- 3, 172, :_reduce_76,
- 3, 172, :_reduce_77,
- 2, 172, :_reduce_78,
- 1, 172, :_reduce_79,
- 1, 146, :_reduce_80,
- 4, 146, :_reduce_81,
- 3, 146, :_reduce_82,
- 3, 146, :_reduce_83,
- 3, 146, :_reduce_84,
- 3, 146, :_reduce_85,
- 2, 146, :_reduce_86,
- 1, 146, :_reduce_87,
- 1, 174, :_reduce_88,
- 1, 174, :_reduce_none,
- 2, 175, :_reduce_90,
- 1, 175, :_reduce_91,
- 3, 175, :_reduce_92,
- 1, 176, :_reduce_none,
- 1, 176, :_reduce_none,
- 1, 176, :_reduce_none,
- 1, 176, :_reduce_none,
- 1, 176, :_reduce_none,
- 1, 179, :_reduce_98,
- 1, 179, :_reduce_none,
- 1, 143, :_reduce_none,
- 1, 143, :_reduce_none,
- 1, 144, :_reduce_102,
- 0, 182, :_reduce_103,
- 4, 144, :_reduce_104,
- 1, 177, :_reduce_none,
- 1, 177, :_reduce_none,
- 1, 177, :_reduce_none,
- 1, 177, :_reduce_none,
- 1, 177, :_reduce_none,
- 1, 177, :_reduce_none,
- 1, 177, :_reduce_none,
- 1, 177, :_reduce_none,
- 1, 177, :_reduce_none,
- 1, 177, :_reduce_none,
- 1, 177, :_reduce_none,
- 1, 177, :_reduce_none,
- 1, 177, :_reduce_none,
- 1, 177, :_reduce_none,
- 1, 177, :_reduce_none,
- 1, 177, :_reduce_none,
- 1, 177, :_reduce_none,
- 1, 177, :_reduce_none,
- 1, 177, :_reduce_none,
- 1, 177, :_reduce_none,
- 1, 177, :_reduce_none,
- 1, 177, :_reduce_none,
- 1, 177, :_reduce_none,
- 1, 177, :_reduce_none,
- 1, 177, :_reduce_none,
- 1, 177, :_reduce_none,
- 1, 178, :_reduce_none,
- 1, 178, :_reduce_none,
- 1, 178, :_reduce_none,
- 1, 178, :_reduce_none,
- 1, 178, :_reduce_none,
- 1, 178, :_reduce_none,
- 1, 178, :_reduce_none,
- 1, 178, :_reduce_none,
- 1, 178, :_reduce_none,
- 1, 178, :_reduce_none,
- 1, 178, :_reduce_none,
- 1, 178, :_reduce_none,
- 1, 178, :_reduce_none,
- 1, 178, :_reduce_none,
- 1, 178, :_reduce_none,
- 1, 178, :_reduce_none,
- 1, 178, :_reduce_none,
- 1, 178, :_reduce_none,
- 1, 178, :_reduce_none,
- 1, 178, :_reduce_none,
- 1, 178, :_reduce_none,
- 1, 178, :_reduce_none,
- 1, 178, :_reduce_none,
- 1, 178, :_reduce_none,
- 1, 178, :_reduce_none,
- 1, 178, :_reduce_none,
- 1, 178, :_reduce_none,
- 1, 178, :_reduce_none,
- 1, 178, :_reduce_none,
- 1, 178, :_reduce_none,
- 1, 178, :_reduce_none,
- 1, 178, :_reduce_none,
- 1, 178, :_reduce_none,
- 1, 178, :_reduce_none,
- 1, 178, :_reduce_none,
- 1, 178, :_reduce_none,
- 1, 178, :_reduce_none,
- 1, 178, :_reduce_none,
- 1, 178, :_reduce_none,
- 1, 178, :_reduce_none,
- 3, 157, :_reduce_171,
- 5, 157, :_reduce_172,
- 3, 157, :_reduce_173,
- 6, 157, :_reduce_174,
- 5, 157, :_reduce_175,
- 5, 157, :_reduce_176,
- 5, 157, :_reduce_177,
- 5, 157, :_reduce_178,
- 4, 157, :_reduce_179,
- 3, 157, :_reduce_180,
- 3, 157, :_reduce_181,
- 3, 157, :_reduce_182,
- 3, 157, :_reduce_183,
- 3, 157, :_reduce_184,
- 3, 157, :_reduce_185,
- 3, 157, :_reduce_186,
- 3, 157, :_reduce_187,
- 3, 157, :_reduce_188,
- 4, 157, :_reduce_189,
- 4, 157, :_reduce_190,
- 2, 157, :_reduce_191,
- 2, 157, :_reduce_192,
- 3, 157, :_reduce_193,
- 3, 157, :_reduce_194,
- 3, 157, :_reduce_195,
- 3, 157, :_reduce_196,
- 3, 157, :_reduce_197,
- 3, 157, :_reduce_198,
- 3, 157, :_reduce_199,
- 3, 157, :_reduce_200,
- 3, 157, :_reduce_201,
- 3, 157, :_reduce_202,
- 3, 157, :_reduce_203,
- 3, 157, :_reduce_204,
- 3, 157, :_reduce_205,
- 2, 157, :_reduce_206,
- 2, 157, :_reduce_207,
- 3, 157, :_reduce_208,
- 3, 157, :_reduce_209,
- 3, 157, :_reduce_210,
- 3, 157, :_reduce_211,
- 3, 157, :_reduce_212,
- 5, 157, :_reduce_213,
- 1, 157, :_reduce_none,
- 1, 154, :_reduce_none,
- 1, 151, :_reduce_none,
- 2, 151, :_reduce_217,
- 2, 151, :_reduce_218,
- 5, 151, :_reduce_219,
- 2, 151, :_reduce_220,
- 3, 151, :_reduce_221,
- 3, 189, :_reduce_222,
- 4, 189, :_reduce_223,
- 4, 189, :_reduce_224,
- 6, 189, :_reduce_225,
- 0, 190, :_reduce_226,
- 1, 190, :_reduce_none,
- 1, 160, :_reduce_228,
- 2, 160, :_reduce_229,
- 5, 160, :_reduce_230,
- 2, 160, :_reduce_231,
- 5, 160, :_reduce_232,
- 4, 160, :_reduce_233,
- 7, 160, :_reduce_234,
- 3, 160, :_reduce_235,
- 1, 160, :_reduce_236,
- 4, 193, :_reduce_237,
- 3, 193, :_reduce_238,
- 5, 193, :_reduce_239,
- 7, 193, :_reduce_240,
- 2, 193, :_reduce_241,
- 5, 193, :_reduce_242,
- 4, 193, :_reduce_243,
- 6, 193, :_reduce_244,
- 7, 193, :_reduce_245,
- 9, 193, :_reduce_246,
- 3, 193, :_reduce_247,
- 1, 193, :_reduce_248,
- 0, 195, :_reduce_249,
- 2, 163, :_reduce_250,
- 1, 194, :_reduce_251,
- 0, 196, :_reduce_252,
- 3, 194, :_reduce_253,
- 0, 197, :_reduce_254,
- 4, 194, :_reduce_255,
- 2, 192, :_reduce_256,
- 2, 191, :_reduce_257,
- 0, 191, :_reduce_258,
- 1, 186, :_reduce_259,
- 3, 186, :_reduce_260,
- 3, 153, :_reduce_261,
- 4, 153, :_reduce_262,
- 2, 153, :_reduce_263,
- 1, 184, :_reduce_none,
- 1, 184, :_reduce_none,
- 1, 184, :_reduce_none,
- 1, 184, :_reduce_none,
- 1, 184, :_reduce_none,
- 1, 184, :_reduce_none,
- 1, 184, :_reduce_none,
- 1, 184, :_reduce_none,
- 1, 184, :_reduce_272,
- 3, 184, :_reduce_273,
- 0, 218, :_reduce_274,
- 5, 184, :_reduce_275,
- 3, 184, :_reduce_276,
- 3, 184, :_reduce_277,
- 2, 184, :_reduce_278,
- 4, 184, :_reduce_279,
- 3, 184, :_reduce_280,
- 3, 184, :_reduce_281,
- 1, 184, :_reduce_282,
- 4, 184, :_reduce_283,
- 3, 184, :_reduce_284,
- 1, 184, :_reduce_285,
- 5, 184, :_reduce_286,
- 2, 184, :_reduce_287,
- 1, 184, :_reduce_none,
- 2, 184, :_reduce_289,
- 6, 184, :_reduce_290,
- 6, 184, :_reduce_291,
- 0, 219, :_reduce_292,
- 0, 220, :_reduce_293,
- 7, 184, :_reduce_294,
- 0, 221, :_reduce_295,
- 0, 222, :_reduce_296,
- 7, 184, :_reduce_297,
- 5, 184, :_reduce_298,
- 4, 184, :_reduce_299,
- 5, 184, :_reduce_300,
- 0, 223, :_reduce_301,
- 0, 224, :_reduce_302,
- 9, 184, :_reduce_303,
- 0, 225, :_reduce_304,
- 6, 184, :_reduce_305,
- 0, 226, :_reduce_306,
- 7, 184, :_reduce_307,
- 0, 227, :_reduce_308,
- 5, 184, :_reduce_309,
- 0, 228, :_reduce_310,
- 6, 184, :_reduce_311,
- 0, 229, :_reduce_312,
- 0, 230, :_reduce_313,
- 9, 184, :_reduce_314,
- 1, 184, :_reduce_315,
- 1, 184, :_reduce_316,
- 1, 184, :_reduce_317,
- 1, 184, :_reduce_318,
- 1, 150, :_reduce_none,
- 1, 208, :_reduce_none,
- 1, 208, :_reduce_none,
- 1, 208, :_reduce_none,
- 2, 208, :_reduce_323,
- 1, 210, :_reduce_none,
- 1, 210, :_reduce_none,
- 1, 210, :_reduce_none,
- 1, 209, :_reduce_none,
- 5, 209, :_reduce_328,
- 1, 137, :_reduce_none,
- 2, 137, :_reduce_330,
- 1, 212, :_reduce_none,
- 1, 212, :_reduce_none,
- 1, 231, :_reduce_333,
- 3, 231, :_reduce_334,
- 1, 232, :_reduce_none,
- 2, 232, :_reduce_none,
- 4, 232, :_reduce_337,
- 7, 232, :_reduce_338,
- 6, 232, :_reduce_339,
- 4, 232, :_reduce_340,
- 3, 232, :_reduce_341,
- 5, 232, :_reduce_342,
- 4, 232, :_reduce_343,
- 2, 232, :_reduce_344,
- 1, 232, :_reduce_345,
- 2, 232, :_reduce_346,
- 0, 165, :_reduce_347,
- 2, 165, :_reduce_348,
- 1, 165, :_reduce_349,
- 3, 165, :_reduce_350,
- 0, 234, :_reduce_351,
- 5, 233, :_reduce_352,
- 2, 161, :_reduce_353,
- 4, 161, :_reduce_354,
- 4, 161, :_reduce_355,
- 2, 207, :_reduce_356,
- 4, 207, :_reduce_357,
- 4, 207, :_reduce_358,
- 3, 207, :_reduce_359,
- 2, 207, :_reduce_360,
- 1, 207, :_reduce_361,
- 0, 236, :_reduce_362,
- 5, 206, :_reduce_363,
- 0, 237, :_reduce_364,
- 5, 206, :_reduce_365,
- 5, 211, :_reduce_366,
- 1, 238, :_reduce_none,
- 4, 238, :_reduce_368,
- 2, 238, :_reduce_369,
- 1, 239, :_reduce_370,
- 1, 239, :_reduce_none,
- 6, 136, :_reduce_372,
- 0, 136, :_reduce_373,
- 1, 240, :_reduce_374,
- 1, 240, :_reduce_none,
- 1, 240, :_reduce_none,
- 2, 241, :_reduce_377,
- 1, 241, :_reduce_none,
- 2, 138, :_reduce_379,
- 1, 138, :_reduce_none,
- 1, 198, :_reduce_none,
- 1, 198, :_reduce_none,
- 1, 198, :_reduce_none,
- 1, 199, :_reduce_384,
- 1, 243, :_reduce_385,
- 2, 243, :_reduce_386,
- 3, 244, :_reduce_387,
- 1, 244, :_reduce_388,
- 3, 200, :_reduce_389,
- 4, 201, :_reduce_390,
- 3, 202, :_reduce_391,
- 0, 247, :_reduce_392,
- 3, 247, :_reduce_393,
- 1, 248, :_reduce_394,
- 2, 248, :_reduce_395,
- 3, 203, :_reduce_396,
- 0, 250, :_reduce_397,
- 3, 250, :_reduce_398,
- 0, 245, :_reduce_399,
- 2, 245, :_reduce_400,
- 0, 246, :_reduce_401,
- 2, 246, :_reduce_402,
- 1, 249, :_reduce_403,
- 2, 249, :_reduce_404,
- 0, 252, :_reduce_405,
- 4, 249, :_reduce_406,
- 1, 251, :_reduce_407,
- 1, 251, :_reduce_408,
- 1, 251, :_reduce_409,
- 1, 251, :_reduce_none,
- 1, 180, :_reduce_411,
- 3, 181, :_reduce_412,
- 1, 242, :_reduce_413,
- 1, 242, :_reduce_414,
- 2, 242, :_reduce_415,
- 2, 242, :_reduce_416,
- 1, 173, :_reduce_417,
- 1, 173, :_reduce_418,
- 1, 173, :_reduce_419,
- 1, 173, :_reduce_420,
- 1, 173, :_reduce_421,
- 1, 173, :_reduce_422,
- 1, 173, :_reduce_423,
- 1, 173, :_reduce_424,
- 1, 173, :_reduce_425,
- 1, 173, :_reduce_426,
- 1, 173, :_reduce_427,
- 1, 204, :_reduce_428,
- 1, 149, :_reduce_429,
- 1, 152, :_reduce_430,
- 1, 152, :_reduce_431,
- 1, 213, :_reduce_432,
- 3, 213, :_reduce_433,
- 2, 213, :_reduce_434,
- 4, 215, :_reduce_435,
- 2, 215, :_reduce_436,
- 6, 253, :_reduce_437,
- 4, 253, :_reduce_438,
- 4, 253, :_reduce_439,
- 2, 253, :_reduce_440,
- 4, 253, :_reduce_441,
- 2, 253, :_reduce_442,
- 2, 253, :_reduce_443,
- 1, 253, :_reduce_444,
- 0, 253, :_reduce_445,
- 1, 259, :_reduce_446,
- 1, 259, :_reduce_447,
- 1, 259, :_reduce_448,
- 1, 259, :_reduce_449,
- 1, 259, :_reduce_450,
- 1, 254, :_reduce_451,
- 3, 254, :_reduce_452,
- 3, 260, :_reduce_453,
- 1, 255, :_reduce_454,
- 3, 255, :_reduce_455,
- 1, 261, :_reduce_none,
- 1, 261, :_reduce_none,
- 2, 256, :_reduce_458,
- 1, 256, :_reduce_459,
- 1, 262, :_reduce_none,
- 1, 262, :_reduce_none,
- 2, 258, :_reduce_462,
- 2, 257, :_reduce_463,
- 0, 257, :_reduce_464,
- 1, 216, :_reduce_none,
- 4, 216, :_reduce_466,
- 0, 205, :_reduce_467,
- 2, 205, :_reduce_468,
- 2, 205, :_reduce_469,
- 1, 188, :_reduce_470,
- 3, 188, :_reduce_471,
- 3, 263, :_reduce_472,
- 1, 167, :_reduce_none,
- 1, 167, :_reduce_none,
- 1, 167, :_reduce_none,
- 1, 162, :_reduce_none,
- 1, 162, :_reduce_none,
- 1, 162, :_reduce_none,
- 1, 162, :_reduce_none,
- 1, 235, :_reduce_none,
- 1, 235, :_reduce_none,
- 1, 235, :_reduce_none,
- 1, 217, :_reduce_none,
- 1, 217, :_reduce_none,
- 0, 140, :_reduce_none,
- 1, 140, :_reduce_none,
- 0, 183, :_reduce_none,
- 1, 183, :_reduce_none,
- 0, 187, :_reduce_none,
- 1, 187, :_reduce_none,
- 1, 187, :_reduce_none,
- 1, 214, :_reduce_492,
- 1, 214, :_reduce_none,
- 1, 142, :_reduce_none,
- 2, 142, :_reduce_none,
- 0, 185, :_reduce_496 ]
-
-racc_reduce_n = 497
-
-racc_shift_n = 894
-
-racc_token_table = {
- false => 0,
- :error => 1,
- :kCLASS => 2,
- :kMODULE => 3,
- :kDEF => 4,
- :kUNDEF => 5,
- :kBEGIN => 6,
- :kRESCUE => 7,
- :kENSURE => 8,
- :kEND => 9,
- :kIF => 10,
- :kUNLESS => 11,
- :kTHEN => 12,
- :kELSIF => 13,
- :kELSE => 14,
- :kCASE => 15,
- :kWHEN => 16,
- :kWHILE => 17,
- :kUNTIL => 18,
- :kFOR => 19,
- :kBREAK => 20,
- :kNEXT => 21,
- :kREDO => 22,
- :kRETRY => 23,
- :kIN => 24,
- :kDO => 25,
- :kDO_COND => 26,
- :kDO_BLOCK => 27,
- :kRETURN => 28,
- :kYIELD => 29,
- :kSUPER => 30,
- :kSELF => 31,
- :kNIL => 32,
- :kTRUE => 33,
- :kFALSE => 34,
- :kAND => 35,
- :kOR => 36,
- :kNOT => 37,
- :kIF_MOD => 38,
- :kUNLESS_MOD => 39,
- :kWHILE_MOD => 40,
- :kUNTIL_MOD => 41,
- :kRESCUE_MOD => 42,
- :kALIAS => 43,
- :kDEFINED => 44,
- :klBEGIN => 45,
- :klEND => 46,
- :k__LINE__ => 47,
- :k__FILE__ => 48,
- :tIDENTIFIER => 49,
- :tFID => 50,
- :tGVAR => 51,
- :tIVAR => 52,
- :tCONSTANT => 53,
- :tCVAR => 54,
- :tNTH_REF => 55,
- :tBACK_REF => 56,
- :tSTRING_CONTENT => 57,
- :tINTEGER => 58,
- :tFLOAT => 59,
- :tREGEXP_END => 60,
- :tUPLUS => 61,
- :tUMINUS => 62,
- :tUMINUS_NUM => 63,
- :tPOW => 64,
- :tCMP => 65,
- :tEQ => 66,
- :tEQQ => 67,
- :tNEQ => 68,
- :tGEQ => 69,
- :tLEQ => 70,
- :tANDOP => 71,
- :tOROP => 72,
- :tMATCH => 73,
- :tNMATCH => 74,
- :tDOT => 75,
- :tDOT2 => 76,
- :tDOT3 => 77,
- :tAREF => 78,
- :tASET => 79,
- :tLSHFT => 80,
- :tRSHFT => 81,
- :tCOLON2 => 82,
- :tCOLON3 => 83,
- :tOP_ASGN => 84,
- :tASSOC => 85,
- :tLPAREN => 86,
- :tLPAREN2 => 87,
- :tRPAREN => 88,
- :tLPAREN_ARG => 89,
- :tLBRACK => 90,
- :tLBRACK2 => 91,
- :tRBRACK => 92,
- :tLBRACE => 93,
- :tLBRACE_ARG => 94,
- :tSTAR => 95,
- :tSTAR2 => 96,
- :tAMPER => 97,
- :tAMPER2 => 98,
- :tTILDE => 99,
- :tPERCENT => 100,
- :tDIVIDE => 101,
- :tPLUS => 102,
- :tMINUS => 103,
- :tLT => 104,
- :tGT => 105,
- :tPIPE => 106,
- :tBANG => 107,
- :tCARET => 108,
- :tLCURLY => 109,
- :tRCURLY => 110,
- :tBACK_REF2 => 111,
- :tSYMBEG => 112,
- :tSTRING_BEG => 113,
- :tXSTRING_BEG => 114,
- :tREGEXP_BEG => 115,
- :tWORDS_BEG => 116,
- :tQWORDS_BEG => 117,
- :tSTRING_DBEG => 118,
- :tSTRING_DVAR => 119,
- :tSTRING_END => 120,
- :tSTRING => 121,
- :tSYMBOL => 122,
- :tREGEXP_OPT => 123,
- :tNL => 124,
- :tEH => 125,
- :tCOLON => 126,
- :tCOMMA => 127,
- :tSPACE => 128,
- :tSEMI => 129,
- :tEQL => 130,
- :tLOWEST => 131 }
-
-racc_nt_base = 132
-
-racc_use_result_var = true
-
-Racc_arg = [
- racc_action_table,
- racc_action_check,
- racc_action_default,
- racc_action_pointer,
- racc_goto_table,
- racc_goto_check,
- racc_goto_default,
- racc_goto_pointer,
- racc_nt_base,
- racc_reduce_table,
- racc_token_table,
- racc_shift_n,
- racc_reduce_n,
- racc_use_result_var ]
-
-Racc_token_to_s_table = [
- "$end",
- "error",
- "kCLASS",
- "kMODULE",
- "kDEF",
- "kUNDEF",
- "kBEGIN",
- "kRESCUE",
- "kENSURE",
- "kEND",
- "kIF",
- "kUNLESS",
- "kTHEN",
- "kELSIF",
- "kELSE",
- "kCASE",
- "kWHEN",
- "kWHILE",
- "kUNTIL",
- "kFOR",
- "kBREAK",
- "kNEXT",
- "kREDO",
- "kRETRY",
- "kIN",
- "kDO",
- "kDO_COND",
- "kDO_BLOCK",
- "kRETURN",
- "kYIELD",
- "kSUPER",
- "kSELF",
- "kNIL",
- "kTRUE",
- "kFALSE",
- "kAND",
- "kOR",
- "kNOT",
- "kIF_MOD",
- "kUNLESS_MOD",
- "kWHILE_MOD",
- "kUNTIL_MOD",
- "kRESCUE_MOD",
- "kALIAS",
- "kDEFINED",
- "klBEGIN",
- "klEND",
- "k__LINE__",
- "k__FILE__",
- "tIDENTIFIER",
- "tFID",
- "tGVAR",
- "tIVAR",
- "tCONSTANT",
- "tCVAR",
- "tNTH_REF",
- "tBACK_REF",
- "tSTRING_CONTENT",
- "tINTEGER",
- "tFLOAT",
- "tREGEXP_END",
- "tUPLUS",
- "tUMINUS",
- "tUMINUS_NUM",
- "tPOW",
- "tCMP",
- "tEQ",
- "tEQQ",
- "tNEQ",
- "tGEQ",
- "tLEQ",
- "tANDOP",
- "tOROP",
- "tMATCH",
- "tNMATCH",
- "tDOT",
- "tDOT2",
- "tDOT3",
- "tAREF",
- "tASET",
- "tLSHFT",
- "tRSHFT",
- "tCOLON2",
- "tCOLON3",
- "tOP_ASGN",
- "tASSOC",
- "tLPAREN",
- "tLPAREN2",
- "tRPAREN",
- "tLPAREN_ARG",
- "tLBRACK",
- "tLBRACK2",
- "tRBRACK",
- "tLBRACE",
- "tLBRACE_ARG",
- "tSTAR",
- "tSTAR2",
- "tAMPER",
- "tAMPER2",
- "tTILDE",
- "tPERCENT",
- "tDIVIDE",
- "tPLUS",
- "tMINUS",
- "tLT",
- "tGT",
- "tPIPE",
- "tBANG",
- "tCARET",
- "tLCURLY",
- "tRCURLY",
- "tBACK_REF2",
- "tSYMBEG",
- "tSTRING_BEG",
- "tXSTRING_BEG",
- "tREGEXP_BEG",
- "tWORDS_BEG",
- "tQWORDS_BEG",
- "tSTRING_DBEG",
- "tSTRING_DVAR",
- "tSTRING_END",
- "tSTRING",
- "tSYMBOL",
- "tREGEXP_OPT",
- "tNL",
- "tEH",
- "tCOLON",
- "tCOMMA",
- "tSPACE",
- "tSEMI",
- "tEQL",
- "tLOWEST",
- "$start",
- "program",
- "compstmt",
- "bodystmt",
- "opt_rescue",
- "opt_else",
- "opt_ensure",
- "stmts",
- "opt_terms",
- "stmt",
- "terms",
- "fitem",
- "undef_list",
- "expr_value",
- "lhs",
- "command_call",
- "mlhs",
- "var_lhs",
- "primary_value",
- "aref_args",
- "backref",
- "mrhs",
- "arg_value",
- "expr",
- "@1",
- "arg",
- "command",
- "block_command",
- "call_args",
- "block_call",
- "operation2",
- "command_args",
- "cmd_brace_block",
- "opt_block_var",
- "@2",
- "operation",
- "mlhs_basic",
- "mlhs_entry",
- "mlhs_head",
- "mlhs_item",
- "mlhs_node",
- "variable",
- "cname",
- "cpath",
- "fname",
- "op",
- "reswords",
- "fsym",
- "symbol",
- "dsym",
- "@3",
- "opt_nl",
- "primary",
- "none",
- "args",
- "trailer",
- "assocs",
- "paren_args",
- "opt_paren_args",
- "opt_block_arg",
- "block_arg",
- "call_args2",
- "open_args",
- "@4",
- "@5",
- "@6",
- "literal",
- "strings",
- "xstring",
- "regexp",
- "words",
- "qwords",
- "var_ref",
- "assoc_list",
- "brace_block",
- "method_call",
- "then",
- "if_tail",
- "do",
- "case_body",
- "for_var",
- "superclass",
- "term",
- "f_arglist",
- "singleton",
- "dot_or_colon",
- "@7",
- "@8",
- "@9",
- "@10",
- "@11",
- "@12",
- "@13",
- "@14",
- "@15",
- "@16",
- "@17",
- "@18",
- "@19",
- "block_par",
- "block_var",
- "do_block",
- "@20",
- "operation3",
- "@21",
- "@22",
- "when_args",
- "cases",
- "exc_list",
- "exc_var",
- "numeric",
- "string",
- "string1",
- "string_contents",
- "xstring_contents",
- "word_list",
- "word",
- "string_content",
- "qword_list",
- "string_dvar",
- "@23",
- "f_args",
- "f_arg",
- "f_optarg",
- "f_rest_arg",
- "opt_f_block_arg",
- "f_block_arg",
- "f_norm_arg",
- "f_opt",
- "restarg_mark",
- "blkarg_mark",
- "assoc" ]
-
-Racc_debug_parser = false
-
-##### State transition tables end #####
-
-# reduce 0 omitted
-
-module_eval(<<'.,.,', 'ruby18.y', 73)
- def _reduce_1(val, _values, result)
- result = val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 78)
- def _reduce_2(val, _values, result)
- rescue_bodies = val[1]
- else_t, else_ = val[2]
- ensure_t, ensure_ = val[3]
-
- if rescue_bodies.empty? && !else_.nil?
- diagnostic :warning, :useless_else, nil, else_t
- end
-
- result = @builder.begin_body(val[0],
- rescue_bodies,
- else_t, else_,
- ensure_t, ensure_)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 94)
- def _reduce_3(val, _values, result)
- result = @builder.compstmt(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 99)
- def _reduce_4(val, _values, result)
- result = []
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 103)
- def _reduce_5(val, _values, result)
- result = [ val[0] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 107)
- def _reduce_6(val, _values, result)
- result = [ val[1] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 111)
- def _reduce_7(val, _values, result)
- result = val[0] << val[2]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 116)
- def _reduce_8(val, _values, result)
- @lexer.state = :expr_fname
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 120)
- def _reduce_9(val, _values, result)
- result = @builder.alias(val[0], val[1], val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 124)
- def _reduce_10(val, _values, result)
- result = @builder.alias(val[0],
- @builder.gvar(val[1]),
- @builder.gvar(val[2]))
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 130)
- def _reduce_11(val, _values, result)
- result = @builder.alias(val[0],
- @builder.gvar(val[1]),
- @builder.back_ref(val[2]))
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 136)
- def _reduce_12(val, _values, result)
- diagnostic :error, :nth_ref_alias, nil, val[2]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 140)
- def _reduce_13(val, _values, result)
- result = @builder.undef_method(val[0], val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 144)
- def _reduce_14(val, _values, result)
- result = @builder.condition_mod(val[0], nil,
- val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 149)
- def _reduce_15(val, _values, result)
- result = @builder.condition_mod(nil, val[0],
- val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 154)
- def _reduce_16(val, _values, result)
- result = @builder.loop_mod(:while, val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 158)
- def _reduce_17(val, _values, result)
- result = @builder.loop_mod(:until, val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 162)
- def _reduce_18(val, _values, result)
- rescue_body = @builder.rescue_body(val[1],
- nil, nil, nil,
- nil, val[2])
-
- result = @builder.begin_body(val[0], [ rescue_body ])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 170)
- def _reduce_19(val, _values, result)
- if in_def?
- diagnostic :error, :begin_in_method, nil, val[0]
- end
-
- result = @builder.preexe(val[0], val[1], val[2], val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 178)
- def _reduce_20(val, _values, result)
- result = @builder.postexe(val[0], val[1], val[2], val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 182)
- def _reduce_21(val, _values, result)
- result = @builder.assign(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 186)
- def _reduce_22(val, _values, result)
- result = @builder.multi_assign(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 190)
- def _reduce_23(val, _values, result)
- result = @builder.op_assign(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 194)
- def _reduce_24(val, _values, result)
- result = @builder.op_assign(
- @builder.index(
- val[0], val[1], val[2], val[3]),
- val[4], val[5])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 201)
- def _reduce_25(val, _values, result)
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 208)
- def _reduce_26(val, _values, result)
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 215)
- def _reduce_27(val, _values, result)
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 222)
- def _reduce_28(val, _values, result)
- @builder.op_assign(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 226)
- def _reduce_29(val, _values, result)
- result = @builder.assign(val[0], val[1],
- @builder.array(nil, val[2], nil))
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 231)
- def _reduce_30(val, _values, result)
- result = @builder.multi_assign(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 235)
- def _reduce_31(val, _values, result)
- result = @builder.multi_assign(val[0], val[1],
- @builder.array(nil, val[2], nil))
-
- result
- end
-.,.,
-
-# reduce 32 omitted
-
-# reduce 33 omitted
-
-module_eval(<<'.,.,', 'ruby18.y', 243)
- def _reduce_34(val, _values, result)
- result = @builder.logical_op(:and, val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 247)
- def _reduce_35(val, _values, result)
- result = @builder.logical_op(:or, val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 251)
- def _reduce_36(val, _values, result)
- result = @builder.not_op(val[0], nil, val[1], nil)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 255)
- def _reduce_37(val, _values, result)
- result = @builder.not_op(val[0], nil, val[1], nil)
-
- result
- end
-.,.,
-
-# reduce 38 omitted
-
-# reduce 39 omitted
-
-# reduce 40 omitted
-
-# reduce 41 omitted
-
-module_eval(<<'.,.,', 'ruby18.y', 265)
- def _reduce_42(val, _values, result)
- result = @builder.keyword_cmd(:return, val[0],
- nil, val[1], nil)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 270)
- def _reduce_43(val, _values, result)
- result = @builder.keyword_cmd(:break, val[0],
- nil, val[1], nil)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 275)
- def _reduce_44(val, _values, result)
- result = @builder.keyword_cmd(:next, val[0],
- nil, val[1], nil)
-
- result
- end
-.,.,
-
-# reduce 45 omitted
-
-module_eval(<<'.,.,', 'ruby18.y', 282)
- def _reduce_46(val, _values, result)
- lparen_t, args, rparen_t = val[3]
- result = @builder.call_method(val[0], val[1], val[2],
- lparen_t, args, rparen_t)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 288)
- def _reduce_47(val, _values, result)
- lparen_t, args, rparen_t = val[3]
- result = @builder.call_method(val[0], val[1], val[2],
- lparen_t, args, rparen_t)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 295)
- def _reduce_48(val, _values, result)
- @static_env.extend_dynamic
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 299)
- def _reduce_49(val, _values, result)
- result = [ val[0], val[2], val[3], val[4] ]
-
- @static_env.unextend
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 306)
- def _reduce_50(val, _values, result)
- lparen_t, args, rparen_t = val[1]
- result = @builder.call_method(nil, nil, val[0],
- lparen_t, args, rparen_t)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 312)
- def _reduce_51(val, _values, result)
- lparen_t, args, rparen_t = val[1]
- method_call = @builder.call_method(nil, nil, val[0],
- lparen_t, args, rparen_t)
-
- begin_t, block_args, body, end_t = val[2]
- result = @builder.block(method_call,
- begin_t, block_args, body, end_t)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 322)
- def _reduce_52(val, _values, result)
- lparen_t, args, rparen_t = val[3]
- result = @builder.call_method(val[0], val[1], val[2],
- lparen_t, args, rparen_t)
-
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 329)
- def _reduce_53(val, _values, result)
- lparen_t, args, rparen_t = val[3]
- method_call = @builder.call_method(val[0], val[1], val[2],
- lparen_t, args, rparen_t)
-
- begin_t, block_args, body, end_t = val[4]
- result = @builder.block(method_call,
- begin_t, block_args, body, end_t)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 339)
- def _reduce_54(val, _values, result)
- lparen_t, args, rparen_t = val[3]
- result = @builder.call_method(val[0], val[1], val[2],
- lparen_t, args, rparen_t)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 345)
- def _reduce_55(val, _values, result)
- lparen_t, args, rparen_t = val[3]
- method_call = @builder.call_method(val[0], val[1], val[2],
- lparen_t, args, rparen_t)
-
- begin_t, block_args, body, end_t = val[4]
- result = @builder.block(method_call,
- begin_t, block_args, body, end_t)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 355)
- def _reduce_56(val, _values, result)
- lparen_t, args, rparen_t = val[1]
- result = @builder.keyword_cmd(:super, val[0],
- lparen_t, args, rparen_t)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 361)
- def _reduce_57(val, _values, result)
- lparen_t, args, rparen_t = val[1]
- result = @builder.keyword_cmd(:yield, val[0],
- lparen_t, args, rparen_t)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 368)
- def _reduce_58(val, _values, result)
- result = @builder.multi_lhs(nil, val[0], nil)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 372)
- def _reduce_59(val, _values, result)
- result = @builder.begin(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 377)
- def _reduce_60(val, _values, result)
- result = @builder.multi_lhs(nil, val[0], nil)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 381)
- def _reduce_61(val, _values, result)
- result = @builder.multi_lhs(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 386)
- def _reduce_62(val, _values, result)
- result = val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 390)
- def _reduce_63(val, _values, result)
- result = val[0] << val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 394)
- def _reduce_64(val, _values, result)
- result = val[0] << @builder.splat(val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 398)
- def _reduce_65(val, _values, result)
- result = val[0] << @builder.splat(val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 402)
- def _reduce_66(val, _values, result)
- result = [ @builder.splat(val[0], val[1]) ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 406)
- def _reduce_67(val, _values, result)
- result = [ @builder.splat(val[0]) ]
-
- result
- end
-.,.,
-
-# reduce 68 omitted
-
-module_eval(<<'.,.,', 'ruby18.y', 412)
- def _reduce_69(val, _values, result)
- result = @builder.begin(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 417)
- def _reduce_70(val, _values, result)
- result = [ val[0] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 421)
- def _reduce_71(val, _values, result)
- result = val[0] << val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 426)
- def _reduce_72(val, _values, result)
- result = @builder.assignable(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 430)
- def _reduce_73(val, _values, result)
- result = @builder.index_asgn(val[0], val[1], val[2], val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 434)
- def _reduce_74(val, _values, result)
- result = @builder.attr_asgn(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 438)
- def _reduce_75(val, _values, result)
- result = @builder.attr_asgn(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 442)
- def _reduce_76(val, _values, result)
- result = @builder.attr_asgn(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 446)
- def _reduce_77(val, _values, result)
- result = @builder.assignable(
- @builder.const_fetch(val[0], val[1], val[2]))
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 451)
- def _reduce_78(val, _values, result)
- result = @builder.assignable(
- @builder.const_global(val[0], val[1]))
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 456)
- def _reduce_79(val, _values, result)
- result = @builder.assignable(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 461)
- def _reduce_80(val, _values, result)
- result = @builder.assignable(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 465)
- def _reduce_81(val, _values, result)
- result = @builder.index_asgn(val[0], val[1], val[2], val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 469)
- def _reduce_82(val, _values, result)
- result = @builder.attr_asgn(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 473)
- def _reduce_83(val, _values, result)
- result = @builder.attr_asgn(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 477)
- def _reduce_84(val, _values, result)
- result = @builder.attr_asgn(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 481)
- def _reduce_85(val, _values, result)
- result = @builder.assignable(
- @builder.const_fetch(val[0], val[1], val[2]))
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 486)
- def _reduce_86(val, _values, result)
- result = @builder.assignable(
- @builder.const_global(val[0], val[1]))
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 491)
- def _reduce_87(val, _values, result)
- result = @builder.assignable(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 496)
- def _reduce_88(val, _values, result)
- diagnostic :error, :module_name_const, nil, val[0]
-
- result
- end
-.,.,
-
-# reduce 89 omitted
-
-module_eval(<<'.,.,', 'ruby18.y', 502)
- def _reduce_90(val, _values, result)
- result = @builder.const_global(val[0], val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 506)
- def _reduce_91(val, _values, result)
- result = @builder.const(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 510)
- def _reduce_92(val, _values, result)
- result = @builder.const_fetch(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-# reduce 93 omitted
-
-# reduce 94 omitted
-
-# reduce 95 omitted
-
-# reduce 96 omitted
-
-# reduce 97 omitted
-
-module_eval(<<'.,.,', 'ruby18.y', 519)
- def _reduce_98(val, _values, result)
- result = @builder.symbol(val[0])
-
- result
- end
-.,.,
-
-# reduce 99 omitted
-
-# reduce 100 omitted
-
-# reduce 101 omitted
-
-module_eval(<<'.,.,', 'ruby18.y', 528)
- def _reduce_102(val, _values, result)
- result = [ val[0] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 532)
- def _reduce_103(val, _values, result)
- @lexer.state = :expr_fname
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 536)
- def _reduce_104(val, _values, result)
- result = val[0] << val[3]
-
- result
- end
-.,.,
-
-# reduce 105 omitted
-
-# reduce 106 omitted
-
-# reduce 107 omitted
-
-# reduce 108 omitted
-
-# reduce 109 omitted
-
-# reduce 110 omitted
-
-# reduce 111 omitted
-
-# reduce 112 omitted
-
-# reduce 113 omitted
-
-# reduce 114 omitted
-
-# reduce 115 omitted
-
-# reduce 116 omitted
-
-# reduce 117 omitted
-
-# reduce 118 omitted
-
-# reduce 119 omitted
-
-# reduce 120 omitted
-
-# reduce 121 omitted
-
-# reduce 122 omitted
-
-# reduce 123 omitted
-
-# reduce 124 omitted
-
-# reduce 125 omitted
-
-# reduce 126 omitted
-
-# reduce 127 omitted
-
-# reduce 128 omitted
-
-# reduce 129 omitted
-
-# reduce 130 omitted
-
-# reduce 131 omitted
-
-# reduce 132 omitted
-
-# reduce 133 omitted
-
-# reduce 134 omitted
-
-# reduce 135 omitted
-
-# reduce 136 omitted
-
-# reduce 137 omitted
-
-# reduce 138 omitted
-
-# reduce 139 omitted
-
-# reduce 140 omitted
-
-# reduce 141 omitted
-
-# reduce 142 omitted
-
-# reduce 143 omitted
-
-# reduce 144 omitted
-
-# reduce 145 omitted
-
-# reduce 146 omitted
-
-# reduce 147 omitted
-
-# reduce 148 omitted
-
-# reduce 149 omitted
-
-# reduce 150 omitted
-
-# reduce 151 omitted
-
-# reduce 152 omitted
-
-# reduce 153 omitted
-
-# reduce 154 omitted
-
-# reduce 155 omitted
-
-# reduce 156 omitted
-
-# reduce 157 omitted
-
-# reduce 158 omitted
-
-# reduce 159 omitted
-
-# reduce 160 omitted
-
-# reduce 161 omitted
-
-# reduce 162 omitted
-
-# reduce 163 omitted
-
-# reduce 164 omitted
-
-# reduce 165 omitted
-
-# reduce 166 omitted
-
-# reduce 167 omitted
-
-# reduce 168 omitted
-
-# reduce 169 omitted
-
-# reduce 170 omitted
-
-module_eval(<<'.,.,', 'ruby18.y', 555)
- def _reduce_171(val, _values, result)
- result = @builder.assign(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 559)
- def _reduce_172(val, _values, result)
- rescue_body = @builder.rescue_body(val[3],
- nil, nil, nil,
- nil, val[4])
-
- rescue_ = @builder.begin_body(val[2], [ rescue_body ])
-
- result = @builder.assign(val[0], val[1], rescue_)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 569)
- def _reduce_173(val, _values, result)
- result = @builder.op_assign(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 573)
- def _reduce_174(val, _values, result)
- result = @builder.op_assign(
- @builder.index(
- val[0], val[1], val[2], val[3]),
- val[4], val[5])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 580)
- def _reduce_175(val, _values, result)
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 587)
- def _reduce_176(val, _values, result)
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 594)
- def _reduce_177(val, _values, result)
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 601)
- def _reduce_178(val, _values, result)
- diagnostic :error, :dynamic_const, nil, val[2], [ val[3] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 605)
- def _reduce_179(val, _values, result)
- diagnostic :error, :dynamic_const, nil, val[1], [ val[2] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 609)
- def _reduce_180(val, _values, result)
- result = @builder.op_assign(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 613)
- def _reduce_181(val, _values, result)
- result = @builder.range_inclusive(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 617)
- def _reduce_182(val, _values, result)
- result = @builder.range_exclusive(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 621)
- def _reduce_183(val, _values, result)
- result = @builder.binary_op(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 625)
- def _reduce_184(val, _values, result)
- result = @builder.binary_op(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 629)
- def _reduce_185(val, _values, result)
- result = @builder.binary_op(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 633)
- def _reduce_186(val, _values, result)
- result = @builder.binary_op(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 637)
- def _reduce_187(val, _values, result)
- result = @builder.binary_op(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 641)
- def _reduce_188(val, _values, result)
- result = @builder.binary_op(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 645)
- def _reduce_189(val, _values, result)
- result = @builder.unary_op(val[0],
- @builder.binary_op(
- @builder.integer(val[1]),
- val[2], val[3]))
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 652)
- def _reduce_190(val, _values, result)
- result = @builder.unary_op(val[0],
- @builder.binary_op(
- @builder.float(val[1]),
- val[2], val[3]))
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 659)
- def _reduce_191(val, _values, result)
- result = @builder.unary_op(val[0], val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 663)
- def _reduce_192(val, _values, result)
- result = @builder.unary_op(val[0], val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 667)
- def _reduce_193(val, _values, result)
- result = @builder.binary_op(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 671)
- def _reduce_194(val, _values, result)
- result = @builder.binary_op(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 675)
- def _reduce_195(val, _values, result)
- result = @builder.binary_op(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 679)
- def _reduce_196(val, _values, result)
- result = @builder.binary_op(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 683)
- def _reduce_197(val, _values, result)
- result = @builder.binary_op(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 687)
- def _reduce_198(val, _values, result)
- result = @builder.binary_op(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 691)
- def _reduce_199(val, _values, result)
- result = @builder.binary_op(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 695)
- def _reduce_200(val, _values, result)
- result = @builder.binary_op(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 699)
- def _reduce_201(val, _values, result)
- result = @builder.binary_op(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 703)
- def _reduce_202(val, _values, result)
- result = @builder.binary_op(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 707)
- def _reduce_203(val, _values, result)
- result = @builder.binary_op(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 711)
- def _reduce_204(val, _values, result)
- result = @builder.binary_op(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 715)
- def _reduce_205(val, _values, result)
- result = @builder.binary_op(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 719)
- def _reduce_206(val, _values, result)
- result = @builder.not_op(val[0], nil, val[1], nil)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 723)
- def _reduce_207(val, _values, result)
- result = @builder.unary_op(val[0], val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 727)
- def _reduce_208(val, _values, result)
- result = @builder.binary_op(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 731)
- def _reduce_209(val, _values, result)
- result = @builder.binary_op(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 735)
- def _reduce_210(val, _values, result)
- result = @builder.logical_op(:and, val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 739)
- def _reduce_211(val, _values, result)
- result = @builder.logical_op(:or, val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 743)
- def _reduce_212(val, _values, result)
- result = @builder.keyword_cmd(:defined?, val[0], nil, [ val[2] ], nil)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 747)
- def _reduce_213(val, _values, result)
- result = @builder.ternary(val[0], val[1],
- val[2], val[3], val[4])
-
- result
- end
-.,.,
-
-# reduce 214 omitted
-
-# reduce 215 omitted
-
-# reduce 216 omitted
-
-module_eval(<<'.,.,', 'ruby18.y', 757)
- def _reduce_217(val, _values, result)
- result = [ val[0] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 761)
- def _reduce_218(val, _values, result)
- result = val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 765)
- def _reduce_219(val, _values, result)
- result = val[0] << @builder.splat(val[2], val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 769)
- def _reduce_220(val, _values, result)
- result = [ @builder.associate(nil, val[0], nil) ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 773)
- def _reduce_221(val, _values, result)
- result = [ @builder.splat(val[0], val[1]) ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 778)
- def _reduce_222(val, _values, result)
- result = [ val[0], [], val[2] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 782)
- def _reduce_223(val, _values, result)
- result = [ val[0], val[1], val[3] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 786)
- def _reduce_224(val, _values, result)
- result = [ val[0], [ val[1] ], val[3] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 790)
- def _reduce_225(val, _values, result)
- result = [ val[0], val[1] << val[3], val[5] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 795)
- def _reduce_226(val, _values, result)
- result = [ nil, [], nil ]
-
- result
- end
-.,.,
-
-# reduce 227 omitted
-
-module_eval(<<'.,.,', 'ruby18.y', 801)
- def _reduce_228(val, _values, result)
- result = [ val[0] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 805)
- def _reduce_229(val, _values, result)
- result = val[0].concat(val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 809)
- def _reduce_230(val, _values, result)
- result = val[0].concat(
- [ @builder.splat(val[2], val[3]),
- *val[4] ])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 815)
- def _reduce_231(val, _values, result)
- result = [ @builder.associate(nil, val[0], nil),
- *val[1] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 820)
- def _reduce_232(val, _values, result)
- result = [ @builder.associate(nil, val[0], nil),
- @builder.splat(val[2], val[3]),
- *val[4] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 826)
- def _reduce_233(val, _values, result)
- result = val[0].concat(
- [ @builder.associate(nil, val[2], nil),
- *val[3] ])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 832)
- def _reduce_234(val, _values, result)
- result = val[0].concat(
- [ @builder.associate(nil, val[2], nil),
- @builder.splat(val[4], val[5]),
- *val[6] ])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 839)
- def _reduce_235(val, _values, result)
- result = [ @builder.splat(val[0], val[1]),
- *val[2] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 844)
- def _reduce_236(val, _values, result)
- result = [ val[0] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 849)
- def _reduce_237(val, _values, result)
- result = [ val[0], *val[2].concat(val[3]) ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 853)
- def _reduce_238(val, _values, result)
- result = [ val[0], val[2] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 857)
- def _reduce_239(val, _values, result)
- result = [ val[0],
- @builder.splat(val[2], val[3]),
- *val[4] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 863)
- def _reduce_240(val, _values, result)
- result = [ val[0],
- *val[2].
- push(@builder.splat(val[4], val[5])).
- concat(val[6]) ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 870)
- def _reduce_241(val, _values, result)
- result = [ @builder.associate(nil, val[0], nil),
- *val[1] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 875)
- def _reduce_242(val, _values, result)
- result = [ @builder.associate(nil, val[0], nil),
- @builder.splat(val[2], val[3]),
- *val[4] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 881)
- def _reduce_243(val, _values, result)
- result = [ val[0],
- @builder.associate(nil, val[2], nil),
- *val[3] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 887)
- def _reduce_244(val, _values, result)
- result = [ val[0],
- *val[2].
- push(@builder.associate(nil, val[4], nil)).
- concat(val[5]) ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 894)
- def _reduce_245(val, _values, result)
- result = [ val[0],
- @builder.associate(nil, val[2], nil),
- @builder.splat(val[4], val[5]),
- *val[6] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 901)
- def _reduce_246(val, _values, result)
- result = [ val[0],
- *val[2].
- push(@builder.associate(nil, val[4], nil)).
- push(@builder.splat(val[6], val[7])).
- concat(val[8]) ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 909)
- def _reduce_247(val, _values, result)
- result = [ @builder.splat(val[0], val[1]),
- *val[2] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 914)
- def _reduce_248(val, _values, result)
- result = [ val[0] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 918)
- def _reduce_249(val, _values, result)
- result = @lexer.cmdarg.dup
- @lexer.cmdarg.push(true)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 923)
- def _reduce_250(val, _values, result)
- @lexer.cmdarg = val[0]
-
- result = val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 930)
- def _reduce_251(val, _values, result)
- result = [ nil, val[0], nil ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 934)
- def _reduce_252(val, _values, result)
- @lexer.state = :expr_endarg
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 938)
- def _reduce_253(val, _values, result)
- result = [ val[0], [], val[2] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 942)
- def _reduce_254(val, _values, result)
- @lexer.state = :expr_endarg
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 946)
- def _reduce_255(val, _values, result)
- result = [ val[0], val[1], val[3] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 951)
- def _reduce_256(val, _values, result)
- result = @builder.block_pass(val[0], val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 956)
- def _reduce_257(val, _values, result)
- result = [ val[1] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 960)
- def _reduce_258(val, _values, result)
- result = []
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 965)
- def _reduce_259(val, _values, result)
- result = [ val[0] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 969)
- def _reduce_260(val, _values, result)
- result = val[0] << val[2]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 974)
- def _reduce_261(val, _values, result)
- result = val[0] << val[2]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 978)
- def _reduce_262(val, _values, result)
- result = val[0] << @builder.splat(val[2], val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 982)
- def _reduce_263(val, _values, result)
- result = [ @builder.splat(val[0], val[1]) ]
-
- result
- end
-.,.,
-
-# reduce 264 omitted
-
-# reduce 265 omitted
-
-# reduce 266 omitted
-
-# reduce 267 omitted
-
-# reduce 268 omitted
-
-# reduce 269 omitted
-
-# reduce 270 omitted
-
-# reduce 271 omitted
-
-module_eval(<<'.,.,', 'ruby18.y', 995)
- def _reduce_272(val, _values, result)
- result = @builder.call_method(nil, nil, val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 999)
- def _reduce_273(val, _values, result)
- result = @builder.begin_keyword(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1003)
- def _reduce_274(val, _values, result)
- @lexer.state = :expr_endarg
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1007)
- def _reduce_275(val, _values, result)
- result = @builder.begin(val[0], val[1], val[4])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1011)
- def _reduce_276(val, _values, result)
- result = @builder.begin(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1015)
- def _reduce_277(val, _values, result)
- result = @builder.const_fetch(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1019)
- def _reduce_278(val, _values, result)
- result = @builder.const_global(val[0], val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1023)
- def _reduce_279(val, _values, result)
- result = @builder.index(val[0], val[1], val[2], val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1027)
- def _reduce_280(val, _values, result)
- result = @builder.array(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1031)
- def _reduce_281(val, _values, result)
- result = @builder.associate(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1035)
- def _reduce_282(val, _values, result)
- result = @builder.keyword_cmd(:return, val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1039)
- def _reduce_283(val, _values, result)
- result = @builder.keyword_cmd(:yield, val[0], val[1], val[2], val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1043)
- def _reduce_284(val, _values, result)
- result = @builder.keyword_cmd(:yield, val[0], val[1], [], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1047)
- def _reduce_285(val, _values, result)
- result = @builder.keyword_cmd(:yield, val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1051)
- def _reduce_286(val, _values, result)
- result = @builder.keyword_cmd(:defined?, val[0],
- val[2], [ val[3] ], val[4])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1056)
- def _reduce_287(val, _values, result)
- method_call = @builder.call_method(nil, nil, val[0])
-
- begin_t, args, body, end_t = val[1]
- result = @builder.block(method_call,
- begin_t, args, body, end_t)
-
- result
- end
-.,.,
-
-# reduce 288 omitted
-
-module_eval(<<'.,.,', 'ruby18.y', 1065)
- def _reduce_289(val, _values, result)
- begin_t, args, body, end_t = val[1]
- result = @builder.block(val[0],
- begin_t, args, body, end_t)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1071)
- def _reduce_290(val, _values, result)
- else_t, else_ = val[4]
- result = @builder.condition(val[0], val[1], val[2],
- val[3], else_t,
- else_, val[5])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1078)
- def _reduce_291(val, _values, result)
- else_t, else_ = val[4]
- result = @builder.condition(val[0], val[1], val[2],
- else_, else_t,
- val[3], val[5])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1085)
- def _reduce_292(val, _values, result)
- @lexer.cond.push(true)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1089)
- def _reduce_293(val, _values, result)
- @lexer.cond.pop
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1093)
- def _reduce_294(val, _values, result)
- result = @builder.loop(:while, val[0], val[2], val[3],
- val[5], val[6])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1098)
- def _reduce_295(val, _values, result)
- @lexer.cond.push(true)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1102)
- def _reduce_296(val, _values, result)
- @lexer.cond.pop
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1106)
- def _reduce_297(val, _values, result)
- result = @builder.loop(:until, val[0], val[2], val[3],
- val[5], val[6])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1111)
- def _reduce_298(val, _values, result)
- when_bodies = val[3][0..-2]
- else_t, else_body = val[3][-1]
-
- result = @builder.case(val[0], val[1],
- when_bodies, else_t, else_body,
- val[4])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1120)
- def _reduce_299(val, _values, result)
- when_bodies = val[2][0..-2]
- else_t, else_body = val[2][-1]
-
- result = @builder.case(val[0], nil,
- when_bodies, else_t, else_body,
- val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1129)
- def _reduce_300(val, _values, result)
- result = @builder.case(val[0], nil,
- [], val[2], val[3],
- val[4])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1135)
- def _reduce_301(val, _values, result)
- @lexer.cond.push(true)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1139)
- def _reduce_302(val, _values, result)
- @lexer.cond.pop
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1143)
- def _reduce_303(val, _values, result)
- result = @builder.for(val[0], val[1],
- val[2], val[4],
- val[5], val[7], val[8])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1149)
- def _reduce_304(val, _values, result)
- @static_env.extend_static
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1153)
- def _reduce_305(val, _values, result)
- if in_def?
- diagnostic :error, :class_in_def, nil, val[0]
- end
-
- lt_t, superclass = val[2]
- result = @builder.def_class(val[0], val[1],
- lt_t, superclass,
- val[4], val[5])
-
- @static_env.unextend
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1166)
- def _reduce_306(val, _values, result)
- result = @def_level
- @def_level = 0
-
- @static_env.extend_static
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1173)
- def _reduce_307(val, _values, result)
- result = @builder.def_sclass(val[0], val[1], val[2],
- val[5], val[6])
-
- @static_env.unextend
-
- @def_level = val[4]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1182)
- def _reduce_308(val, _values, result)
- @static_env.extend_static
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1186)
- def _reduce_309(val, _values, result)
- if in_def?
- diagnostic :error, :module_in_def, nil, val[0]
- end
-
- result = @builder.def_module(val[0], val[1],
- val[3], val[4])
-
- @static_env.unextend
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1197)
- def _reduce_310(val, _values, result)
- @def_level += 1
- @static_env.extend_static
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1202)
- def _reduce_311(val, _values, result)
- result = @builder.def_method(val[0], val[1],
- val[3], val[4], val[5])
-
- @static_env.unextend
- @def_level -= 1
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1210)
- def _reduce_312(val, _values, result)
- @lexer.state = :expr_fname
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1214)
- def _reduce_313(val, _values, result)
- @def_level += 1
- @static_env.extend_static
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1219)
- def _reduce_314(val, _values, result)
- result = @builder.def_singleton(val[0], val[1], val[2],
- val[4], val[6], val[7], val[8])
-
- @static_env.unextend
- @def_level -= 1
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1227)
- def _reduce_315(val, _values, result)
- result = @builder.keyword_cmd(:break, val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1231)
- def _reduce_316(val, _values, result)
- result = @builder.keyword_cmd(:next, val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1235)
- def _reduce_317(val, _values, result)
- result = @builder.keyword_cmd(:redo, val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1239)
- def _reduce_318(val, _values, result)
- result = @builder.keyword_cmd(:retry, val[0])
-
- result
- end
-.,.,
-
-# reduce 319 omitted
-
-# reduce 320 omitted
-
-# reduce 321 omitted
-
-# reduce 322 omitted
-
-module_eval(<<'.,.,', 'ruby18.y', 1249)
- def _reduce_323(val, _values, result)
- result = val[1]
-
- result
- end
-.,.,
-
-# reduce 324 omitted
-
-# reduce 325 omitted
-
-# reduce 326 omitted
-
-# reduce 327 omitted
-
-module_eval(<<'.,.,', 'ruby18.y', 1259)
- def _reduce_328(val, _values, result)
- else_t, else_ = val[4]
- result = [ val[0],
- @builder.condition(val[0], val[1], val[2],
- val[3], else_t,
- else_, nil),
- ]
-
- result
- end
-.,.,
-
-# reduce 329 omitted
-
-module_eval(<<'.,.,', 'ruby18.y', 1270)
- def _reduce_330(val, _values, result)
- result = val
-
- result
- end
-.,.,
-
-# reduce 331 omitted
-
-# reduce 332 omitted
-
-module_eval(<<'.,.,', 'ruby18.y', 1278)
- def _reduce_333(val, _values, result)
- result = [ @builder.arg_expr(val[0]) ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1282)
- def _reduce_334(val, _values, result)
- result = val[0] << @builder.arg_expr(val[2])
-
- result
- end
-.,.,
-
-# reduce 335 omitted
-
-# reduce 336 omitted
-
-module_eval(<<'.,.,', 'ruby18.y', 1289)
- def _reduce_337(val, _values, result)
- result = val[0].
- push(@builder.blockarg_expr(val[2], val[3]))
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1294)
- def _reduce_338(val, _values, result)
- result = val[0].
- push(@builder.restarg_expr(val[2], val[3])).
- push(@builder.blockarg_expr(val[5], val[6]))
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1300)
- def _reduce_339(val, _values, result)
- result = val[0].
- push(@builder.restarg_expr(val[2])).
- push(@builder.blockarg_expr(val[4], val[5]))
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1306)
- def _reduce_340(val, _values, result)
- result = val[0].
- push(@builder.restarg_expr(val[2], val[3]))
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1311)
- def _reduce_341(val, _values, result)
- result = val[0].
- push(@builder.restarg_expr(val[2]))
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1316)
- def _reduce_342(val, _values, result)
- result = [ @builder.restarg_expr(val[0], val[1]),
- @builder.blockarg_expr(val[3], val[4]) ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1321)
- def _reduce_343(val, _values, result)
- result = [ @builder.restarg_expr(val[0]),
- @builder.blockarg_expr(val[2], val[3]) ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1326)
- def _reduce_344(val, _values, result)
- result = [ @builder.restarg_expr(val[0], val[1]) ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1330)
- def _reduce_345(val, _values, result)
- result = [ @builder.restarg_expr(val[0]) ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1334)
- def _reduce_346(val, _values, result)
- result = [ @builder.blockarg_expr(val[0], val[1]) ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1340)
- def _reduce_347(val, _values, result)
- result = @builder.args(nil, [], nil)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1344)
- def _reduce_348(val, _values, result)
- result = @builder.args(val[0], [], val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1348)
- def _reduce_349(val, _values, result)
- result = @builder.args(val[0], [], val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1352)
- def _reduce_350(val, _values, result)
- result = @builder.args(val[0], val[1], val[2], false)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1357)
- def _reduce_351(val, _values, result)
- @static_env.extend_dynamic
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1361)
- def _reduce_352(val, _values, result)
- result = [ val[0], val[2], val[3], val[4] ]
-
- @static_env.unextend
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1368)
- def _reduce_353(val, _values, result)
- begin_t, block_args, body, end_t = val[1]
- result = @builder.block(val[0],
- begin_t, block_args, body, end_t)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1374)
- def _reduce_354(val, _values, result)
- lparen_t, args, rparen_t = val[3]
- result = @builder.call_method(val[0], val[1], val[2],
- lparen_t, args, rparen_t)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1380)
- def _reduce_355(val, _values, result)
- lparen_t, args, rparen_t = val[3]
- result = @builder.call_method(val[0], val[1], val[2],
- lparen_t, args, rparen_t)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1387)
- def _reduce_356(val, _values, result)
- lparen_t, args, rparen_t = val[1]
- result = @builder.call_method(nil, nil, val[0],
- lparen_t, args, rparen_t)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1393)
- def _reduce_357(val, _values, result)
- lparen_t, args, rparen_t = val[3]
- result = @builder.call_method(val[0], val[1], val[2],
- lparen_t, args, rparen_t)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1399)
- def _reduce_358(val, _values, result)
- lparen_t, args, rparen_t = val[3]
- result = @builder.call_method(val[0], val[1], val[2],
- lparen_t, args, rparen_t)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1405)
- def _reduce_359(val, _values, result)
- result = @builder.call_method(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1409)
- def _reduce_360(val, _values, result)
- lparen_t, args, rparen_t = val[1]
- result = @builder.keyword_cmd(:super, val[0],
- lparen_t, args, rparen_t)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1415)
- def _reduce_361(val, _values, result)
- result = @builder.keyword_cmd(:zsuper, val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1420)
- def _reduce_362(val, _values, result)
- @static_env.extend_dynamic
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1424)
- def _reduce_363(val, _values, result)
- result = [ val[0], val[2], val[3], val[4] ]
-
- @static_env.unextend
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1430)
- def _reduce_364(val, _values, result)
- @static_env.extend_dynamic
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1434)
- def _reduce_365(val, _values, result)
- result = [ val[0], val[2], val[3], val[4] ]
-
- @static_env.unextend
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1441)
- def _reduce_366(val, _values, result)
- result = [ @builder.when(val[0], val[1], val[2], val[3]),
- *val[4] ]
-
- result
- end
-.,.,
-
-# reduce 367 omitted
-
-module_eval(<<'.,.,', 'ruby18.y', 1448)
- def _reduce_368(val, _values, result)
- result = val[0] << @builder.splat(val[2], val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1452)
- def _reduce_369(val, _values, result)
- result = [ @builder.splat(val[0], val[1]) ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1457)
- def _reduce_370(val, _values, result)
- result = [ val[0] ]
-
- result
- end
-.,.,
-
-# reduce 371 omitted
-
-module_eval(<<'.,.,', 'ruby18.y', 1463)
- def _reduce_372(val, _values, result)
- assoc_t, exc_var = val[2]
-
- if val[1]
- exc_list = @builder.array(nil, val[1], nil)
- end
-
- result = [ @builder.rescue_body(val[0],
- exc_list, assoc_t, exc_var,
- val[3], val[4]),
- *val[5] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1476)
- def _reduce_373(val, _values, result)
- result = []
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1481)
- def _reduce_374(val, _values, result)
- result = [ val[0] ]
-
- result
- end
-.,.,
-
-# reduce 375 omitted
-
-# reduce 376 omitted
-
-module_eval(<<'.,.,', 'ruby18.y', 1488)
- def _reduce_377(val, _values, result)
- result = [ val[0], val[1] ]
-
- result
- end
-.,.,
-
-# reduce 378 omitted
-
-module_eval(<<'.,.,', 'ruby18.y', 1494)
- def _reduce_379(val, _values, result)
- result = [ val[0], val[1] ]
-
- result
- end
-.,.,
-
-# reduce 380 omitted
-
-# reduce 381 omitted
-
-# reduce 382 omitted
-
-# reduce 383 omitted
-
-module_eval(<<'.,.,', 'ruby18.y', 1504)
- def _reduce_384(val, _values, result)
- result = @builder.string_compose(nil, val[0], nil)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1509)
- def _reduce_385(val, _values, result)
- result = [ val[0] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1513)
- def _reduce_386(val, _values, result)
- result = val[0] << val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1518)
- def _reduce_387(val, _values, result)
- result = @builder.string_compose(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1522)
- def _reduce_388(val, _values, result)
- result = @builder.string(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1527)
- def _reduce_389(val, _values, result)
- result = @builder.xstring_compose(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1532)
- def _reduce_390(val, _values, result)
- opts = @builder.regexp_options(val[3])
- result = @builder.regexp_compose(val[0], val[1], val[2], opts)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1538)
- def _reduce_391(val, _values, result)
- result = @builder.words_compose(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1543)
- def _reduce_392(val, _values, result)
- result = []
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1547)
- def _reduce_393(val, _values, result)
- result = val[0] << @builder.word(val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1552)
- def _reduce_394(val, _values, result)
- result = [ val[0] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1556)
- def _reduce_395(val, _values, result)
- result = val[0] << val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1561)
- def _reduce_396(val, _values, result)
- result = @builder.words_compose(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1566)
- def _reduce_397(val, _values, result)
- result = []
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1570)
- def _reduce_398(val, _values, result)
- result = val[0] << @builder.string_internal(val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1575)
- def _reduce_399(val, _values, result)
- result = []
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1579)
- def _reduce_400(val, _values, result)
- result = val[0] << val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1584)
- def _reduce_401(val, _values, result)
- result = []
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1588)
- def _reduce_402(val, _values, result)
- result = val[0] << val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1593)
- def _reduce_403(val, _values, result)
- result = @builder.string_internal(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1597)
- def _reduce_404(val, _values, result)
- result = val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1601)
- def _reduce_405(val, _values, result)
- @lexer.cond.push(false)
- @lexer.cmdarg.push(false)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1606)
- def _reduce_406(val, _values, result)
- @lexer.cond.lexpop
- @lexer.cmdarg.lexpop
-
- result = @builder.begin(val[0], val[2], val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1614)
- def _reduce_407(val, _values, result)
- result = @builder.gvar(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1618)
- def _reduce_408(val, _values, result)
- result = @builder.ivar(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1622)
- def _reduce_409(val, _values, result)
- result = @builder.cvar(val[0])
-
- result
- end
-.,.,
-
-# reduce 410 omitted
-
-module_eval(<<'.,.,', 'ruby18.y', 1629)
- def _reduce_411(val, _values, result)
- result = @builder.symbol(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1634)
- def _reduce_412(val, _values, result)
- result = @builder.symbol_compose(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1639)
- def _reduce_413(val, _values, result)
- result = @builder.integer(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1643)
- def _reduce_414(val, _values, result)
- result = @builder.float(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1647)
- def _reduce_415(val, _values, result)
- result = @builder.negate(val[0],
- @builder.integer(val[1]))
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1652)
- def _reduce_416(val, _values, result)
- result = @builder.negate(val[0],
- @builder.float(val[1]))
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1658)
- def _reduce_417(val, _values, result)
- result = @builder.ident(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1662)
- def _reduce_418(val, _values, result)
- result = @builder.ivar(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1666)
- def _reduce_419(val, _values, result)
- result = @builder.gvar(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1670)
- def _reduce_420(val, _values, result)
- result = @builder.cvar(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1674)
- def _reduce_421(val, _values, result)
- result = @builder.const(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1678)
- def _reduce_422(val, _values, result)
- result = @builder.nil(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1682)
- def _reduce_423(val, _values, result)
- result = @builder.self(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1686)
- def _reduce_424(val, _values, result)
- result = @builder.true(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1690)
- def _reduce_425(val, _values, result)
- result = @builder.false(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1694)
- def _reduce_426(val, _values, result)
- result = @builder.__FILE__(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1698)
- def _reduce_427(val, _values, result)
- result = @builder.__LINE__(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1703)
- def _reduce_428(val, _values, result)
- result = @builder.accessible(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1708)
- def _reduce_429(val, _values, result)
- result = @builder.assignable(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1713)
- def _reduce_430(val, _values, result)
- result = @builder.nth_ref(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1717)
- def _reduce_431(val, _values, result)
- result = @builder.back_ref(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1722)
- def _reduce_432(val, _values, result)
- result = nil
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1726)
- def _reduce_433(val, _values, result)
- result = [ val[0], val[1] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1730)
- def _reduce_434(val, _values, result)
- yyerrok
- result = nil
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1736)
- def _reduce_435(val, _values, result)
- result = @builder.args(val[0], val[1], val[3])
-
- @lexer.state = :expr_beg
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1742)
- def _reduce_436(val, _values, result)
- result = @builder.args(nil, val[0], nil)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1747)
- def _reduce_437(val, _values, result)
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1754)
- def _reduce_438(val, _values, result)
- result = val[0].
- concat(val[2]).
- concat(val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1760)
- def _reduce_439(val, _values, result)
- result = val[0].
- concat(val[2]).
- concat(val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1766)
- def _reduce_440(val, _values, result)
- result = val[0].
- concat(val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1771)
- def _reduce_441(val, _values, result)
- result = val[0].
- concat(val[2]).
- concat(val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1777)
- def _reduce_442(val, _values, result)
- result = val[0].
- concat(val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1782)
- def _reduce_443(val, _values, result)
- result = val[0].
- concat(val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1787)
- def _reduce_444(val, _values, result)
- result = [ val[0] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1791)
- def _reduce_445(val, _values, result)
- result = []
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1796)
- def _reduce_446(val, _values, result)
- diagnostic :error, :argument_const, nil, val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1800)
- def _reduce_447(val, _values, result)
- diagnostic :error, :argument_ivar, nil, val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1804)
- def _reduce_448(val, _values, result)
- diagnostic :error, :argument_gvar, nil, val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1808)
- def _reduce_449(val, _values, result)
- diagnostic :error, :argument_cvar, nil, val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1812)
- def _reduce_450(val, _values, result)
- @static_env.declare val[0][0]
-
- result = @builder.arg(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1819)
- def _reduce_451(val, _values, result)
- result = [ val[0] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1823)
- def _reduce_452(val, _values, result)
- result = val[0] << val[2]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1828)
- def _reduce_453(val, _values, result)
- @static_env.declare val[0][0]
-
- result = @builder.optarg(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1835)
- def _reduce_454(val, _values, result)
- result = [ val[0] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1839)
- def _reduce_455(val, _values, result)
- result = val[0] << val[2]
-
- result
- end
-.,.,
-
-# reduce 456 omitted
-
-# reduce 457 omitted
-
-module_eval(<<'.,.,', 'ruby18.y', 1846)
- def _reduce_458(val, _values, result)
- @static_env.declare val[1][0]
-
- result = [ @builder.restarg(val[0], val[1]) ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1852)
- def _reduce_459(val, _values, result)
- result = [ @builder.restarg(val[0]) ]
-
- result
- end
-.,.,
-
-# reduce 460 omitted
-
-# reduce 461 omitted
-
-module_eval(<<'.,.,', 'ruby18.y', 1859)
- def _reduce_462(val, _values, result)
- @static_env.declare val[1][0]
-
- result = @builder.blockarg(val[0], val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1866)
- def _reduce_463(val, _values, result)
- result = [ val[1] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1870)
- def _reduce_464(val, _values, result)
- result = []
-
- result
- end
-.,.,
-
-# reduce 465 omitted
-
-module_eval(<<'.,.,', 'ruby18.y', 1876)
- def _reduce_466(val, _values, result)
- result = val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1881)
- def _reduce_467(val, _values, result)
- result = []
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1885)
- def _reduce_468(val, _values, result)
- result = val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1889)
- def _reduce_469(val, _values, result)
- result = @builder.pair_list_18(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1894)
- def _reduce_470(val, _values, result)
- result = [ val[0] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1898)
- def _reduce_471(val, _values, result)
- result = val[0] << val[2]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby18.y', 1903)
- def _reduce_472(val, _values, result)
- result = @builder.pair(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-# reduce 473 omitted
-
-# reduce 474 omitted
-
-# reduce 475 omitted
-
-# reduce 476 omitted
-
-# reduce 477 omitted
-
-# reduce 478 omitted
-
-# reduce 479 omitted
-
-# reduce 480 omitted
-
-# reduce 481 omitted
-
-# reduce 482 omitted
-
-# reduce 483 omitted
-
-# reduce 484 omitted
-
-# reduce 485 omitted
-
-# reduce 486 omitted
-
-# reduce 487 omitted
-
-# reduce 488 omitted
-
-# reduce 489 omitted
-
-# reduce 490 omitted
-
-# reduce 491 omitted
-
-module_eval(<<'.,.,', 'ruby18.y', 1916)
- def _reduce_492(val, _values, result)
- yyerrok
-
- result
- end
-.,.,
-
-# reduce 493 omitted
-
-# reduce 494 omitted
-
-# reduce 495 omitted
-
-module_eval(<<'.,.,', 'ruby18.y', 1925)
- def _reduce_496(val, _values, result)
- result = nil
-
- result
- end
-.,.,
-
-def _reduce_none(val, _values, result)
- val[0]
-end
-
- end # class Ruby18
-end # module Parser
diff --git a/test/racc/regress/ruby22 b/test/racc/regress/ruby22
deleted file mode 100644
index 4731071275..0000000000
--- a/test/racc/regress/ruby22
+++ /dev/null
@@ -1,11180 +0,0 @@
-#
-# DO NOT MODIFY!!!!
-# This file is automatically generated by Racc 1.5.2
-# from Racc grammar file "".
-#
-
-require 'racc/parser.rb'
-
-
-require 'parser'
-
-Parser.check_for_encoding_support
-
-module Parser
- class Ruby22 < Racc::Parser
-
-module_eval(<<'...end ruby22.y/module_eval...', 'ruby22.y', 2374)
-
- def version
- 22
- end
-
- def default_encoding
- Encoding::UTF_8
- end
-...end ruby22.y/module_eval...
-##### State transition tables begin ###
-
-racc_action_table = [
- -476, -97, 268, 214, 215, -98, -105, -476, -476, -476,
- -490, 568, -476, -476, -476, 610, -476, 580, 217, 612,
- -288, 581, 214, 215, -476, -491, -476, -476, -476, 647,
- 268, 268, 214, 215, -104, 589, -476, -476, 568, -476,
- -476, -476, -476, -476, 568, 568, 212, 109, 568, 815,
- -100, 121, -100, -83, -102, -99, 214, 215, 268, 218,
- -288, 806, -69, 574, 646, -102, -97, -476, -476, -476,
- -476, -476, -476, -476, -476, -476, -476, -476, -476, -476,
- -476, -98, 609, -476, -476, -476, 611, -476, -476, 715,
- 267, -476, 206, -96, -476, -476, 263, -476, 218, -476,
- 207, -476, -105, -476, -476, -99, -476, -476, -476, -476,
- -476, -88, -476, -479, -476, -89, -96, 218, 267, 267,
- -479, -479, -479, 263, -101, -479, -479, -479, -476, -479,
- 113, -476, -476, -476, -476, 112, -476, -479, -476, -479,
- -479, -479, 588, -476, -95, 715, 267, -101, 715, -479,
- -479, 218, -479, -479, -479, -479, -479, 113, 208, 814,
- -91, -91, 112, 113, 113, 113, 842, 113, 112, 112,
- 112, -100, 112, -102, -99, -93, -100, 213, -102, -99,
- -479, -479, -479, -479, -479, -479, -479, -479, -479, -479,
- -479, -479, -479, -479, 113, 257, -479, -479, -479, 112,
- -479, -479, -574, -93, -479, 316, -103, -479, -479, 317,
- -479, 597, -479, -574, -479, -90, -479, -479, 444, -479,
- -479, -479, -479, -479, -291, -479, 218, -479, -91, 214,
- 215, -291, -291, -291, 647, 260, 527, -291, -291, 526,
- -291, -479, 261, -101, -479, -479, -479, -479, -101, -479,
- 113, -479, -571, 113, 113, 112, -479, -92, 112, 112,
- -291, -291, 386, -291, -291, -291, -291, -291, -91, 646,
- -93, -91, -575, 396, -105, 399, 599, 598, 398, 397,
- -91, 548, 597, 545, 544, 543, 747, 546, 443, 91,
- 92, -291, -291, -291, -291, -291, -291, -291, -291, -291,
- -291, -291, -291, -291, -291, -476, -572, -291, -291, -291,
- -93, 630, -476, -93, -490, -291, -94, -571, -291, 91,
- 92, -476, -93, -291, 113, -291, 515, -291, -291, 112,
- -291, -291, -291, -291, -291, 597, -291, -578, -291, 445,
- -571, -491, -476, 446, -578, -578, -578, 599, 598, -476,
- -578, -578, -291, -578, 647, -291, -291, 749, -94, -479,
- -291, -88, -578, 217, 833, -578, -479, -103, 93, 94,
- -97, -572, 477, -578, -578, -479, -578, -578, -578, -578,
- -578, 548, -104, 545, 544, 543, 515, 546, -89, 646,
- 527, 647, 597, 529, -572, 597, 486, -98, 93, 94,
- 599, 598, 595, -412, -578, -578, -578, -578, -578, -578,
- -578, -578, -578, -578, -578, -578, -578, -578, -578, 625,
- -578, -578, -578, 597, 631, -578, 646, 113, -578, 626,
- -574, -578, 112, -95, -578, 597, -578, 770, -578, -578,
- -578, -578, -104, -578, -578, -578, -578, -578, 488, -578,
- -578, -578, 597, -578, 490, 597, -412, 599, 598, 595,
- 599, 598, 600, -412, 957, -578, -91, 756, -578, -578,
- -578, -92, -412, -578, 662, -100, -93, -578, -578, -578,
- -101, 498, -578, -578, -578, -102, -578, -479, 599, 598,
- 602, -412, -578, -100, -479, -578, -578, -578, -578, -578,
- 599, 598, 604, 771, -574, -68, -578, -578, -578, -578,
- -578, -578, -578, -578, -90, 218, 860, 599, 598, 608,
- 599, 598, 613, -99, 214, 215, -486, -578, 548, -485,
- 545, 544, 543, -486, 546, 501, -485, -578, -578, -578,
- -578, -578, -578, -578, -578, -578, -578, -578, -578, -578,
- -578, 553, 502, -578, -578, -578, -487, 772, -578, -102,
- 509, -578, 556, -487, -578, -578, 701, -578, 272, -578,
- 218, -578, -99, -578, -578, 704, -578, -578, -578, -578,
- -578, 553, -578, -578, -578, 527, -484, 79, 529, 113,
- -481, 263, 556, -484, 112, 564, 563, -481, -578, 80,
- 557, -578, -578, -578, -578, 238, -578, -291, -578, 81,
- -482, 210, 512, -101, -291, -291, -291, -482, 211, -291,
- -291, -291, -334, -291, 440, 564, 563, 209, 516, -334,
- 557, 441, -483, -291, -291, -291, 238, 235, -334, -483,
- 442, 237, 236, -291, -291, 260, -291, -291, -291, -291,
- -291, 548, 261, 545, 544, 543, -488, 546, 548, 218,
- 545, 544, 543, -488, 546, 548, 530, 545, 544, 543,
- 527, 546, -488, 529, -291, -291, -291, -291, -291, -291,
- -291, -291, -291, -291, -291, -291, -291, -291, 238, 701,
- -291, -291, -291, -489, 773, -291, 701, 238, -291, 531,
- -489, -291, -291, 701, -291, 704, -291, 490, -291, -489,
- -291, -291, 904, -291, -291, -291, -291, -291, 113, -291,
- 235, -291, 574, 112, 237, 236, 238, 233, 234, 235,
- 214, 215, 388, 237, 236, -291, 233, 234, -291, -291,
- -291, -291, 113, -291, 113, -291, 578, 112, 579, 112,
- -103, 5, 69, 70, 71, 9, 57, 614, 235, 507,
- 63, 64, 237, 236, 617, 67, 508, 65, 66, 68,
- 30, 31, 72, 73, 218, 506, -263, 981, 619, 29,
- 28, 27, 101, 100, 102, 103, 741, 742, 19, 218,
- 743, 107, 108, 635, 8, 45, 7, 10, 105, 104,
- 106, 95, 56, 97, 96, 98, 623, 99, 107, 108,
- 624, 91, 92, 263, 42, 43, 41, 238, 242, 247,
- 248, 249, 244, 246, 254, 255, 250, 251, -281, 231,
- 232, 517, 634, 252, 253, -281, 40, 637, 518, 33,
- 564, 563, 58, 59, -281, 238, 60, 442, 35, 235,
- 238, 241, 44, 237, 236, 238, 233, 234, 245, 243,
- 239, 20, 240, 837, 806, 238, 89, 79, 82, 83,
- 576, 84, 86, 85, 87, 837, 806, 577, 218, 80,
- 88, 218, 256, 218, -240, -83, 575, 62, 666, 81,
- 93, 94, 290, 69, 70, 71, 9, 57, 218, 520,
- 584, 63, 64, 677, 682, 683, 67, 583, 65, 66,
- 68, 30, 31, 72, 73, 685, 585, 689, 692, 693,
- 29, 28, 27, 101, 100, 102, 103, 695, 697, 19,
- 699, 707, 708, 709, 620, 8, 45, 292, 10, 105,
- 104, 106, 95, 56, 97, 96, 98, 711, 99, 107,
- 108, 574, 91, 92, 718, 42, 43, 41, 238, 242,
- 247, 248, 249, 244, 246, 254, 255, 250, 251, -292,
- 231, 232, -292, 736, 252, 253, -292, 40, 746, -292,
- 294, 750, 751, 58, 59, -292, -264, 60, -292, 35,
- 235, 757, 241, 44, 237, 236, 477, 233, 234, 245,
- 243, 239, 20, 240, 477, 218, 257, 89, 79, 82,
- 83, 584, 84, 86, 85, 87, 488, 490, 939, 799,
- 80, 88, 677, 256, 218, 263, 263, 585, 62, 677,
- 81, 93, 94, 5, 69, 70, 71, 9, 57, 238,
- 806, 584, 63, 64, 218, 218, 831, 67, 939, 65,
- 66, 68, 30, 31, 72, 73, 218, 585, 806, 841,
- 218, 29, 28, 27, 101, 100, 102, 103, 218, 850,
- 19, -265, 859, 861, 862, 635, 8, 45, 7, 10,
- 105, 104, 106, 95, 56, 97, 96, 98, 692, 99,
- 107, 108, 865, 91, 92, 867, 42, 43, 41, 238,
- 242, 247, 248, 249, 244, 246, 254, 255, 250, 251,
- -291, 231, 232, -488, 869, 252, 253, -291, 40, 871,
- -488, 33, -575, 218, 58, 59, -291, 873, 60, -488,
- 35, 235, 874, 241, 44, 237, 236, 877, 233, 234,
- 245, 243, 239, 20, 240, 879, 880, 677, 89, 79,
- 82, 83, -489, 84, 86, 85, 87, 882, -263, -489,
- 886, 80, 88, 888, 256, 891, 692, 893, -489, 62,
- 895, 81, 93, 94, 290, 69, 70, 71, 9, 57,
- 897, 899, 986, 63, 64, 899, 218, 905, 67, 987,
- 65, 66, 68, 30, 31, 72, 73, 907, 985, 909,
- 915, 918, 29, 28, 27, 101, 100, 102, 103, 218,
- 936, 19, 545, 544, 543, 922, 546, 8, 45, 292,
- 10, 105, 104, 106, 95, 56, 97, 96, 98, -266,
- 99, 107, 108, 933, 91, 92, 940, 42, 43, 41,
- 238, 242, 247, 248, 249, 244, 246, 254, 255, 250,
- 251, -291, 231, 232, -281, 941, 252, 253, -291, 40,
- 950, -281, 33, -575, 951, 58, 59, -291, 959, 60,
- -281, 35, 235, 961, 241, 44, 237, 236, 962, 233,
- 234, 245, 243, 239, 20, 240, 967, 736, 692, 89,
- 79, 82, 83, -292, 84, 86, 85, 87, 971, 973,
- -292, 975, 80, 88, 977, 256, 977, 988, 989, -292,
- 62, 899, 81, 93, 94, 290, 69, 70, 71, 9,
- 57, 899, 899, 994, 63, 64, 959, -575, -574, 67,
- 682, 65, 66, 68, 30, 31, 72, 73, 116, 117,
- 118, 119, 120, 29, 28, 27, 101, 100, 102, 103,
- 959, 936, 19, 545, 544, 543, 1013, 546, 8, 45,
- 292, 10, 105, 104, 106, 95, 56, 97, 96, 98,
- 1014, 99, 107, 108, 1015, 91, 92, 977, 42, 43,
- 41, 238, 242, 247, 248, 249, 244, 246, 254, 255,
- 250, 251, -291, 231, 232, 977, 977, 252, 253, -291,
- 40, 218, 899, 33, -575, 959, 58, 59, -291, 977,
- 60, nil, 35, 235, nil, 241, 44, 237, 236, nil,
- 233, 234, 245, 243, 239, 20, 240, nil, nil, nil,
- 89, 79, 82, 83, nil, 84, 86, 85, 87, nil,
- nil, nil, nil, 80, 88, nil, 256, nil, nil, nil,
- nil, 62, nil, 81, 93, 94, 290, 69, 70, 71,
- 9, 57, nil, nil, nil, 63, 64, nil, nil, nil,
- 67, nil, 65, 66, 68, 30, 31, 72, 73, 116,
- 117, 118, 119, 120, 29, 28, 27, 101, 100, 102,
- 103, nil, nil, 19, 116, 117, 118, 119, 120, 8,
- 45, 292, 10, 105, 104, 106, 95, 56, 97, 96,
- 98, nil, 99, 107, 108, nil, 91, 92, nil, 42,
- 43, 41, 238, 242, 247, 248, 249, 244, 246, 254,
- 255, 250, 251, nil, 231, 232, nil, nil, 252, 253,
- nil, 40, nil, nil, 294, nil, nil, 58, 59, nil,
- nil, 60, nil, 35, 235, nil, 241, 44, 237, 236,
- nil, 233, 234, 245, 243, 239, 20, 240, nil, nil,
- nil, 89, 79, 82, 83, nil, 84, 86, 85, 87,
- nil, nil, nil, nil, 80, 88, nil, 256, nil, nil,
- nil, nil, 62, nil, 81, 93, 94, 290, 69, 70,
- 71, 9, 57, nil, nil, nil, 63, 64, nil, nil,
- nil, 67, nil, 65, 66, 68, 30, 31, 72, 73,
- nil, nil, nil, nil, nil, 29, 28, 27, 101, 100,
- 102, 103, nil, nil, 19, nil, nil, nil, nil, nil,
- 8, 45, 292, 10, 105, 104, 106, 95, 56, 97,
- 96, 98, nil, 99, 107, 108, nil, 91, 92, nil,
- 42, 43, 41, 238, 242, 247, 248, 249, 244, 246,
- 254, 255, 250, 251, nil, 231, 232, nil, nil, 252,
- 253, nil, 40, nil, nil, 294, nil, nil, 58, 59,
- nil, nil, 60, nil, 35, 235, nil, 241, 44, 237,
- 236, nil, 233, 234, 245, 243, 239, 20, 240, nil,
- nil, nil, 89, 79, 82, 83, nil, 84, 86, 85,
- 87, nil, nil, nil, nil, 80, 88, nil, 256, nil,
- nil, nil, nil, 62, nil, 81, 93, 94, 290, 69,
- 70, 71, 9, 57, nil, nil, nil, 63, 64, nil,
- nil, nil, 67, nil, 65, 66, 68, 30, 31, 72,
- 73, nil, nil, nil, nil, nil, 29, 28, 27, 101,
- 100, 102, 103, nil, nil, 19, nil, nil, nil, nil,
- nil, 8, 45, 292, 10, 105, 104, 106, 95, 56,
- 97, 96, 98, nil, 99, 107, 108, nil, 91, 92,
- nil, 42, 43, 41, 238, 242, 247, 248, 249, 244,
- 246, 254, 255, 250, 251, nil, 231, 232, nil, nil,
- 252, 253, nil, 40, nil, nil, 33, nil, nil, 58,
- 59, nil, nil, 60, nil, 35, 235, nil, 241, 44,
- 237, 236, nil, 233, 234, 245, 243, 239, 20, 240,
- nil, nil, nil, 89, 79, 82, 83, nil, 84, 86,
- 85, 87, nil, nil, nil, nil, 80, 88, 218, 256,
- nil, nil, nil, nil, 62, nil, 81, 93, 94, 5,
- 69, 70, 71, 9, 57, nil, nil, nil, 63, 64,
- nil, nil, nil, 67, nil, 65, 66, 68, 30, 31,
- 72, 73, nil, nil, nil, nil, nil, 29, 28, 27,
- 101, 100, 102, 103, nil, nil, 19, nil, nil, nil,
- nil, nil, 8, 45, 7, 10, 105, 104, 106, 95,
- 56, 97, 96, 98, nil, 99, 107, 108, nil, 91,
- 92, nil, 42, 43, 41, 238, 242, 247, 248, 249,
- 244, 246, 254, 255, 250, 251, nil, 231, 232, nil,
- nil, 252, 253, nil, 40, nil, nil, 33, nil, nil,
- 58, 59, nil, nil, 60, nil, 35, 235, nil, 241,
- 44, 237, 236, nil, 233, 234, 245, 243, 239, 20,
- 240, nil, nil, nil, 89, 79, 82, 83, nil, 84,
- 86, 85, 87, nil, nil, nil, nil, 80, 88, nil,
- 256, nil, nil, nil, nil, 62, nil, 81, 93, 94,
- 290, 69, 70, 71, 9, 57, nil, nil, nil, 63,
- 64, nil, nil, nil, 67, nil, 65, 66, 68, 30,
- 31, 72, 73, nil, nil, nil, nil, nil, 29, 28,
- 27, 101, 100, 102, 103, nil, nil, 19, nil, nil,
- nil, nil, nil, 8, 45, 292, 10, 105, 104, 106,
- 95, 56, 97, 96, 98, nil, 99, 107, 108, nil,
- 91, 92, nil, 42, 43, 41, 238, 242, 247, 248,
- 249, 244, 246, 254, 255, 250, 251, nil, 231, 232,
- nil, nil, 252, 253, nil, 40, nil, nil, 33, nil,
- nil, 58, 59, nil, nil, 60, nil, 35, 235, nil,
- 241, 44, 237, 236, nil, 233, 234, 245, 243, 239,
- 20, 240, nil, nil, nil, 89, 79, 82, 83, nil,
- 84, 86, 85, 87, nil, nil, nil, nil, 80, 88,
- nil, 256, nil, nil, nil, nil, 62, nil, 81, 93,
- 94, 290, 69, 70, 71, 9, 57, nil, nil, nil,
- 63, 64, nil, nil, nil, 67, nil, 65, 66, 68,
- 30, 31, 72, 73, nil, nil, nil, nil, nil, 29,
- 28, 27, 101, 100, 102, 103, nil, nil, 19, nil,
- nil, nil, nil, nil, 8, 45, 292, 10, 105, 104,
- 106, 95, 56, 97, 96, 98, nil, 99, 107, 108,
- nil, 91, 92, nil, 42, 43, 41, 238, 242, 247,
- 248, 249, 244, 246, 254, 255, 250, 251, nil, 231,
- 232, nil, nil, 252, 253, nil, 40, nil, nil, 33,
- nil, nil, 58, 59, nil, nil, 60, nil, 35, 235,
- nil, 241, 44, 237, 236, nil, 233, 234, 245, 243,
- 239, 20, 240, nil, nil, nil, 89, 79, 82, 83,
- nil, 84, 86, 85, 87, nil, nil, nil, nil, 80,
- 88, nil, 256, nil, nil, nil, nil, 62, nil, 81,
- 93, 94, 290, 69, 70, 71, 9, 57, nil, nil,
- nil, 63, 64, nil, nil, nil, 67, nil, 65, 66,
- 68, 30, 31, 72, 73, nil, nil, nil, nil, nil,
- 29, 28, 27, 101, 100, 102, 103, nil, nil, 19,
- nil, nil, nil, nil, nil, 8, 45, 292, 10, 105,
- 104, 106, 95, 56, 97, 96, 98, nil, 99, 107,
- 108, nil, 91, 92, nil, 42, 43, 41, 238, 242,
- 247, 248, 249, 244, 246, 254, 255, 250, 251, nil,
- 231, 232, nil, nil, 252, 253, nil, 40, nil, nil,
- 33, nil, nil, 58, 59, nil, nil, 60, nil, 35,
- 235, nil, 241, 44, 237, 236, nil, 233, 234, 245,
- 243, 239, 20, 240, nil, nil, nil, 89, 79, 82,
- 83, nil, 84, 86, 85, 87, nil, nil, nil, nil,
- 80, 88, nil, 256, nil, nil, nil, nil, 62, nil,
- 81, 93, 94, 290, 69, 70, 71, 9, 57, nil,
- nil, nil, 63, 64, nil, nil, nil, 67, nil, 65,
- 66, 68, 30, 31, 72, 73, nil, nil, nil, nil,
- nil, 29, 28, 27, 101, 100, 102, 103, nil, nil,
- 19, nil, nil, nil, nil, nil, 8, 45, 292, 10,
- 105, 104, 106, 95, 56, 97, 96, 98, nil, 99,
- 107, 108, nil, 91, 92, nil, 42, 43, 41, 238,
- 242, 247, 248, 249, 244, 246, 254, 255, 250, 251,
- nil, 231, 232, nil, nil, 252, 253, nil, 40, nil,
- nil, 33, nil, nil, 58, 59, nil, nil, 60, nil,
- 35, 235, nil, 241, 44, 237, 236, nil, 233, 234,
- 245, 243, 239, 20, 240, nil, nil, nil, 89, 79,
- 82, 83, nil, 84, 86, 85, 87, nil, nil, nil,
- nil, 80, 88, nil, 256, nil, nil, nil, nil, 62,
- nil, 81, 93, 94, 290, 69, 70, 71, 9, 57,
- nil, nil, nil, 63, 64, nil, nil, nil, 67, nil,
- 65, 66, 68, 30, 31, 72, 73, nil, nil, nil,
- nil, nil, 29, 28, 27, 101, 100, 102, 103, nil,
- nil, 19, nil, nil, nil, nil, nil, 8, 45, 292,
- 10, 105, 104, 106, 95, 56, 97, 96, 98, nil,
- 99, 107, 108, nil, 91, 92, nil, 42, 43, 41,
- 238, 242, 247, 248, 249, 244, 246, 254, 255, 250,
- 251, nil, 231, 232, nil, nil, 252, 253, nil, 40,
- nil, nil, 33, nil, nil, 58, 59, nil, nil, 60,
- nil, 35, 235, nil, 241, 44, 237, 236, nil, 233,
- 234, 245, 243, 239, 20, 240, nil, nil, nil, 89,
- 79, 82, 83, nil, 84, 86, 85, 87, nil, nil,
- nil, nil, 80, 88, nil, 256, nil, nil, nil, nil,
- 62, nil, 81, 93, 94, 290, 69, 70, 71, 9,
- 57, nil, nil, nil, 63, 64, nil, nil, nil, 67,
- nil, 65, 66, 68, 30, 31, 72, 73, nil, nil,
- nil, nil, nil, 29, 28, 27, 101, 100, 102, 103,
- nil, nil, 19, nil, nil, nil, nil, nil, 8, 45,
- 292, 10, 105, 104, 106, 95, 56, 97, 96, 98,
- nil, 99, 107, 108, nil, 91, 92, nil, 42, 43,
- 41, 238, 242, 247, 248, 249, 244, 246, 254, 255,
- 250, 251, nil, 231, 232, nil, nil, 252, 253, nil,
- 40, nil, nil, 33, nil, nil, 58, 59, nil, nil,
- 60, nil, 35, 235, nil, 241, 44, 237, 236, nil,
- 233, 234, 245, 243, 239, 20, 240, nil, nil, nil,
- 89, 79, 82, 83, nil, 84, 86, 85, 87, nil,
- nil, nil, nil, 80, 88, nil, 256, nil, nil, nil,
- nil, 62, nil, 81, 93, 94, 290, 69, 70, 71,
- 9, 57, nil, nil, nil, 63, 64, nil, nil, nil,
- 67, nil, 65, 66, 68, 30, 31, 72, 73, nil,
- nil, nil, nil, nil, 29, 28, 27, 101, 100, 102,
- 103, nil, nil, 19, nil, nil, nil, nil, nil, 8,
- 45, 292, 10, 105, 104, 106, 95, 56, 97, 96,
- 98, nil, 99, 107, 108, nil, 91, 92, nil, 42,
- 43, 41, 238, 242, 247, 248, 249, 244, 246, 254,
- 255, 250, 251, nil, 231, 232, nil, nil, 252, 253,
- nil, 40, nil, nil, 33, nil, nil, 58, 59, nil,
- nil, 60, nil, 35, 235, nil, 241, 44, 237, 236,
- nil, 233, 234, 245, 243, 239, 20, 240, nil, nil,
- nil, 89, 79, 82, 83, nil, 84, 86, 85, 87,
- nil, nil, nil, nil, 80, 88, nil, 256, nil, nil,
- nil, nil, 62, nil, 81, 93, 94, 290, 69, 70,
- 71, 9, 57, nil, nil, nil, 63, 64, nil, nil,
- nil, 67, nil, 65, 66, 68, 30, 31, 72, 73,
- nil, nil, nil, nil, nil, 29, 28, 27, 101, 100,
- 102, 103, nil, nil, 19, nil, nil, nil, nil, nil,
- 8, 45, 292, 10, 105, 104, 106, 95, 56, 97,
- 96, 98, nil, 99, 107, 108, nil, 91, 92, nil,
- 42, 43, 41, 238, 242, 247, 248, 249, 244, 246,
- 254, 255, 250, 251, nil, 231, 232, nil, nil, 252,
- 253, nil, 40, nil, nil, 33, nil, nil, 58, 59,
- nil, nil, 60, nil, 35, 235, nil, 241, 44, 237,
- 236, nil, 233, 234, 245, 243, 239, 20, 240, nil,
- nil, nil, 89, 79, 82, 83, nil, 84, 86, 85,
- 87, nil, nil, nil, nil, 80, 88, nil, 256, nil,
- nil, nil, nil, 62, nil, 81, 93, 94, 290, 69,
- 70, 71, 9, 57, nil, nil, nil, 63, 64, nil,
- nil, nil, 67, nil, 65, 66, 68, 30, 31, 72,
- 73, nil, nil, nil, nil, nil, 29, 28, 27, 101,
- 100, 102, 103, nil, nil, 19, nil, nil, nil, nil,
- nil, 8, 45, 292, 10, 105, 104, 106, 95, 56,
- 97, 96, 98, nil, 99, 107, 108, nil, 91, 92,
- nil, 42, 43, 41, 238, 242, 247, 248, 249, 244,
- 246, 254, 255, 250, 251, nil, -597, -597, nil, nil,
- 252, 253, nil, 40, nil, nil, 33, nil, nil, 58,
- 59, nil, nil, 60, nil, 35, 235, nil, 241, 44,
- 237, 236, nil, 233, 234, 245, 243, 239, 20, 240,
- nil, nil, nil, 89, 79, 82, 83, nil, 84, 86,
- 85, 87, nil, nil, nil, nil, 80, 88, nil, nil,
- nil, nil, nil, nil, 62, nil, 81, 93, 94, 290,
- 69, 70, 71, 9, 57, nil, nil, nil, 63, 64,
- nil, nil, nil, 67, nil, 65, 66, 68, 30, 31,
- 72, 73, nil, nil, nil, nil, nil, 29, 28, 27,
- 101, 100, 102, 103, nil, nil, 19, nil, nil, nil,
- nil, nil, 8, 45, 292, 10, 105, 104, 106, 95,
- 56, 97, 96, 98, nil, 99, 107, 108, nil, 91,
- 92, nil, 42, 43, 41, 238, 242, 247, 248, 249,
- 244, 246, 254, 255, 250, 251, nil, -597, -597, nil,
- nil, 252, 253, nil, 40, nil, nil, 33, nil, nil,
- 58, 59, nil, nil, 60, nil, 35, 235, nil, 241,
- 44, 237, 236, nil, 233, 234, 245, 243, 239, 20,
- 240, nil, nil, nil, 89, 79, 82, 83, nil, 84,
- 86, 85, 87, nil, nil, nil, nil, 80, 88, nil,
- nil, nil, nil, nil, nil, 62, nil, 81, 93, 94,
- 290, 69, 70, 71, 9, 57, nil, nil, nil, 63,
- 64, nil, nil, nil, 67, nil, 65, 66, 68, 30,
- 31, 72, 73, nil, nil, nil, nil, nil, 29, 28,
- 27, 101, 100, 102, 103, nil, 548, 19, 545, 544,
- 543, nil, 546, 8, 45, 292, 10, 105, 104, 106,
- 95, 56, 97, 96, 98, nil, 99, 107, 108, nil,
- 91, 92, nil, 42, 43, 41, 238, -597, -597, -597,
- -597, 244, 246, nil, 701, -597, -597, nil, nil, nil,
- nil, nil, 252, 253, nil, 40, nil, nil, 33, nil,
- nil, 58, 59, nil, nil, 60, nil, 35, 235, nil,
- 241, 44, 237, 236, nil, 233, 234, 245, 243, 239,
- 20, 240, nil, nil, nil, 89, 79, 82, 83, nil,
- 84, 86, 85, 87, nil, nil, nil, nil, 80, 88,
- nil, nil, nil, nil, nil, nil, 62, nil, 81, 93,
- 94, 290, 69, 70, 71, 9, 57, nil, nil, nil,
- 63, 64, nil, nil, nil, 67, nil, 65, 66, 68,
- 30, 31, 72, 73, nil, nil, nil, nil, nil, 29,
- 28, 27, 101, 100, 102, 103, nil, 548, 19, 545,
- 544, 543, nil, 546, 8, 45, 292, 10, 105, 104,
- 106, 95, 56, 97, 96, 98, nil, 99, 107, 108,
- nil, 91, 92, nil, 42, 43, 41, 238, nil, nil,
- 548, nil, 545, 544, 543, 701, 546, nil, nil, nil,
- nil, nil, nil, 252, 253, nil, 40, nil, nil, 33,
- nil, nil, 58, 59, nil, nil, 60, nil, 35, 235,
- nil, 241, 44, 237, 236, nil, 233, 234, 701, nil,
- 239, 20, 240, nil, nil, nil, 89, 79, 82, 83,
- nil, 84, 86, 85, 87, nil, nil, nil, nil, 80,
- 88, nil, nil, nil, nil, nil, nil, 62, nil, 81,
- 93, 94, 290, 69, 70, 71, 9, 57, nil, nil,
- nil, 63, 64, nil, nil, nil, 67, nil, 65, 66,
- 68, 30, 31, 72, 73, nil, nil, nil, nil, nil,
- 29, 28, 27, 101, 100, 102, 103, nil, 548, 19,
- 545, 544, 543, nil, 546, 8, 45, 292, 10, 105,
- 104, 106, 95, 56, 97, 96, 98, nil, 99, 107,
- 108, nil, 91, 92, nil, 42, 43, 41, 238, nil,
- nil, nil, nil, nil, nil, nil, 701, nil, nil, nil,
- nil, nil, nil, nil, 252, 253, nil, 40, nil, nil,
- 33, nil, nil, 58, 59, nil, nil, 60, nil, 35,
- 235, nil, 241, 44, 237, 236, nil, 233, 234, nil,
- nil, 239, 20, 240, nil, nil, nil, 89, 79, 82,
- 83, nil, 84, 86, 85, 87, nil, nil, nil, nil,
- 80, 88, nil, nil, nil, nil, nil, nil, 62, nil,
- 81, 93, 94, 290, 69, 70, 71, 9, 57, nil,
- nil, nil, 63, 64, nil, nil, nil, 67, nil, 65,
- 66, 68, 30, 31, 72, 73, nil, nil, nil, nil,
- nil, 29, 28, 27, 101, 100, 102, 103, nil, nil,
- 19, nil, nil, nil, nil, nil, 8, 45, 292, 10,
- 105, 104, 106, 95, 56, 97, 96, 98, nil, 99,
- 107, 108, nil, 91, 92, nil, 42, 43, 41, 238,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 252, 253, nil, 40, nil,
- nil, 33, nil, nil, 58, 59, nil, nil, 60, nil,
- 35, 235, nil, 241, 44, 237, 236, nil, 233, 234,
- nil, nil, 239, 20, 240, nil, nil, nil, 89, 79,
- 82, 83, nil, 84, 86, 85, 87, nil, nil, nil,
- nil, 80, 88, nil, nil, nil, nil, nil, nil, 62,
- nil, 81, 93, 94, 290, 69, 70, 71, 9, 57,
- nil, nil, nil, 63, 64, nil, nil, nil, 67, nil,
- 65, 66, 68, 30, 31, 72, 73, nil, nil, nil,
- nil, nil, 29, 28, 27, 101, 100, 102, 103, nil,
- nil, 19, nil, nil, nil, nil, nil, 8, 45, 292,
- 10, 105, 104, 106, 95, 56, 97, 96, 98, nil,
- 99, 107, 108, nil, 91, 92, nil, 42, 43, 41,
- 238, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 252, 253, nil, 40,
- nil, nil, 33, nil, nil, 58, 59, nil, nil, 60,
- nil, 35, 235, nil, 241, 44, 237, 236, nil, 233,
- 234, nil, nil, 239, 20, 240, nil, nil, nil, 89,
- 79, 82, 83, nil, 84, 86, 85, 87, nil, nil,
- nil, nil, 80, 88, nil, nil, nil, nil, nil, nil,
- 62, nil, 81, 93, 94, 290, 69, 70, 71, 9,
- 57, nil, nil, nil, 63, 64, nil, nil, nil, 67,
- nil, 65, 66, 68, 30, 31, 72, 73, nil, nil,
- nil, nil, nil, 29, 28, 27, 101, 100, 102, 103,
- nil, nil, 19, nil, nil, nil, nil, nil, 8, 45,
- 292, 10, 105, 104, 106, 95, 56, 97, 96, 98,
- nil, 99, 107, 108, nil, 91, 92, nil, 42, 43,
- 41, 238, -597, -597, -597, -597, 244, 246, nil, nil,
- -597, -597, nil, nil, nil, nil, nil, 252, 253, nil,
- 40, nil, nil, 33, nil, nil, 58, 59, nil, nil,
- 60, nil, 35, 235, nil, 241, 44, 237, 236, nil,
- 233, 234, 245, 243, 239, 20, 240, nil, nil, nil,
- 89, 79, 82, 83, nil, 84, 86, 85, 87, nil,
- nil, nil, nil, 80, 88, nil, nil, nil, nil, nil,
- nil, 62, nil, 81, 93, 94, 290, 69, 70, 71,
- 9, 57, nil, nil, nil, 63, 64, nil, nil, nil,
- 67, nil, 65, 66, 68, 30, 31, 72, 73, nil,
- nil, nil, nil, nil, 29, 28, 27, 101, 100, 102,
- 103, nil, nil, 19, nil, nil, nil, nil, nil, 8,
- 45, 292, 10, 105, 104, 106, 95, 56, 97, 96,
- 98, nil, 99, 107, 108, nil, 91, 92, nil, 42,
- 43, 41, 238, -597, -597, -597, -597, 244, 246, nil,
- nil, -597, -597, nil, nil, nil, nil, nil, 252, 253,
- nil, 40, nil, nil, 33, nil, nil, 58, 59, nil,
- nil, 60, nil, 35, 235, nil, 241, 44, 237, 236,
- nil, 233, 234, 245, 243, 239, 20, 240, nil, nil,
- nil, 89, 79, 82, 83, nil, 84, 86, 85, 87,
- nil, nil, nil, nil, 80, 88, nil, nil, nil, nil,
- nil, nil, 62, nil, 81, 93, 94, 290, 69, 70,
- 71, 9, 57, nil, nil, nil, 63, 64, nil, nil,
- nil, 67, nil, 65, 66, 68, 30, 31, 72, 73,
- nil, nil, nil, nil, nil, 29, 28, 27, 101, 100,
- 102, 103, nil, nil, 19, nil, nil, nil, nil, nil,
- 8, 45, 292, 10, 105, 104, 106, 95, 56, 97,
- 96, 98, nil, 99, 107, 108, nil, 91, 92, nil,
- 42, 43, 41, 238, -597, -597, -597, -597, 244, 246,
- nil, nil, -597, -597, nil, nil, nil, nil, nil, 252,
- 253, nil, 40, nil, nil, 33, nil, nil, 58, 59,
- nil, nil, 60, nil, 35, 235, nil, 241, 44, 237,
- 236, nil, 233, 234, 245, 243, 239, 20, 240, nil,
- nil, nil, 89, 79, 82, 83, nil, 84, 86, 85,
- 87, nil, nil, nil, nil, 80, 88, nil, nil, nil,
- nil, nil, nil, 62, nil, 81, 93, 94, 290, 69,
- 70, 71, 9, 57, nil, nil, nil, 63, 64, nil,
- nil, nil, 67, nil, 65, 66, 68, 30, 31, 72,
- 73, nil, nil, nil, nil, nil, 29, 28, 27, 101,
- 100, 102, 103, nil, nil, 19, nil, nil, nil, nil,
- nil, 8, 45, 292, 10, 105, 104, 106, 95, 56,
- 97, 96, 98, nil, 99, 107, 108, nil, 91, 92,
- nil, 42, 43, 41, 238, -597, -597, -597, -597, 244,
- 246, nil, nil, -597, -597, nil, nil, nil, nil, nil,
- 252, 253, nil, 40, nil, nil, 33, nil, nil, 58,
- 59, nil, nil, 60, nil, 35, 235, nil, 241, 44,
- 237, 236, nil, 233, 234, 245, 243, 239, 20, 240,
- nil, nil, nil, 89, 79, 82, 83, nil, 84, 86,
- 85, 87, nil, nil, nil, nil, 80, 88, nil, nil,
- nil, nil, nil, nil, 62, nil, 81, 93, 94, 290,
- 69, 70, 71, 9, 57, nil, nil, nil, 63, 64,
- nil, nil, nil, 67, nil, 65, 66, 68, 30, 31,
- 72, 73, nil, nil, nil, nil, nil, 29, 28, 27,
- 101, 100, 102, 103, nil, nil, 19, nil, nil, nil,
- nil, nil, 8, 45, 292, 10, 105, 104, 106, 95,
- 56, 97, 96, 98, nil, 99, 107, 108, nil, 91,
- 92, nil, 42, 43, 41, 238, -597, -597, -597, -597,
- 244, 246, nil, nil, -597, -597, nil, nil, nil, nil,
- nil, 252, 253, nil, 40, nil, nil, 33, nil, nil,
- 58, 59, nil, nil, 60, nil, 35, 235, nil, 241,
- 44, 237, 236, nil, 233, 234, 245, 243, 239, 20,
- 240, nil, nil, nil, 89, 79, 82, 83, nil, 84,
- 86, 85, 87, nil, nil, nil, nil, 80, 88, nil,
- nil, nil, nil, nil, nil, 62, nil, 81, 93, 94,
- 290, 69, 70, 71, 9, 57, nil, nil, nil, 63,
- 64, nil, nil, nil, 67, nil, 65, 66, 68, 30,
- 31, 72, 73, nil, nil, nil, nil, nil, 29, 28,
- 27, 101, 100, 102, 103, nil, nil, 19, nil, nil,
- nil, nil, nil, 8, 45, 292, 10, 105, 104, 106,
- 95, 56, 97, 96, 98, nil, 99, 107, 108, nil,
- 91, 92, nil, 42, 43, 41, 238, 242, 247, 248,
- 249, 244, 246, nil, nil, 250, 251, nil, nil, nil,
- nil, nil, 252, 253, nil, 40, nil, nil, 33, nil,
- nil, 58, 59, nil, nil, 60, nil, 35, 235, nil,
- 241, 44, 237, 236, nil, 233, 234, 245, 243, 239,
- 20, 240, nil, nil, nil, 89, 79, 82, 83, nil,
- 84, 86, 85, 87, nil, nil, nil, nil, 80, 88,
- nil, nil, nil, nil, nil, nil, 62, nil, 81, 93,
- 94, 290, 69, 70, 71, 9, 57, nil, nil, nil,
- 63, 64, nil, nil, nil, 67, nil, 65, 66, 68,
- 30, 31, 72, 73, nil, nil, nil, nil, nil, 29,
- 28, 27, 101, 100, 102, 103, nil, nil, 19, nil,
- nil, nil, nil, nil, 8, 45, 292, 10, 105, 104,
- 106, 95, 56, 97, 96, 98, nil, 99, 107, 108,
- nil, 91, 92, nil, 42, 43, 41, 238, 242, 247,
- 248, 249, 244, 246, 254, nil, 250, 251, nil, nil,
- nil, nil, nil, 252, 253, nil, 40, nil, nil, 33,
- nil, nil, 58, 59, nil, nil, 60, nil, 35, 235,
- nil, 241, 44, 237, 236, nil, 233, 234, 245, 243,
- 239, 20, 240, nil, nil, nil, 89, 79, 82, 83,
- nil, 84, 86, 85, 87, nil, nil, nil, nil, 80,
- 88, nil, nil, nil, nil, nil, nil, 62, nil, 81,
- 93, 94, 69, 70, 71, 9, 57, nil, nil, nil,
- 63, 64, nil, nil, nil, 67, nil, 65, 66, 68,
- 30, 31, 72, 73, nil, nil, nil, nil, nil, 29,
- 28, 27, 101, 100, 102, 103, nil, nil, 19, nil,
- nil, nil, nil, nil, 8, 45, 7, 10, 105, 104,
- 106, 95, 56, 97, 96, 98, nil, 99, 107, 108,
- nil, 91, 92, nil, 42, 43, 41, 238, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 252, 253, nil, 40, nil, nil, 33,
- nil, nil, 58, 59, nil, nil, 60, nil, 35, 235,
- nil, 241, 44, 237, 236, nil, 233, 234, nil, nil,
- nil, 20, nil, nil, nil, nil, 89, 79, 82, 83,
- nil, 84, 86, 85, 87, nil, nil, nil, nil, 80,
- 88, nil, nil, nil, 69, 70, 71, 62, 57, 81,
- 93, 94, 63, 64, nil, nil, nil, 67, nil, 65,
- 66, 68, 30, 31, 72, 73, nil, nil, nil, nil,
- nil, 29, 28, 27, 101, 100, 102, 103, nil, nil,
- 230, nil, nil, nil, nil, nil, nil, 45, nil, nil,
- 105, 104, 106, 95, 56, 97, 96, 98, nil, 99,
- 107, 108, nil, 91, 92, nil, 42, 43, 41, 238,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 252, 253, nil, 223, nil,
- nil, 229, nil, nil, 58, 59, nil, nil, 60, nil,
- nil, 235, nil, 241, 44, 237, 236, nil, 233, 234,
- nil, nil, nil, 228, nil, nil, nil, nil, 89, 79,
- 82, 83, nil, 84, 86, 85, 87, nil, nil, nil,
- nil, 80, 88, nil, nil, nil, 69, 70, 71, 62,
- 57, 81, 93, 94, 63, 64, nil, nil, nil, 67,
- nil, 65, 66, 68, 30, 31, 72, 73, nil, nil,
- nil, nil, nil, 29, 28, 27, 101, 100, 102, 103,
- nil, nil, 230, nil, nil, nil, nil, nil, nil, 45,
- nil, nil, 105, 104, 106, 95, 56, 97, 96, 98,
- 284, 99, 107, 108, nil, 91, 92, nil, 42, 43,
- 41, 238, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 252, 253, nil,
- 223, nil, nil, 229, nil, nil, 58, 59, nil, nil,
- 60, nil, 281, 235, 279, nil, 44, 237, 236, 285,
- 233, 234, nil, nil, nil, 228, nil, nil, nil, nil,
- 89, 282, 82, 83, nil, 84, 86, 85, 87, nil,
- nil, nil, nil, 80, 88, nil, nil, nil, 69, 70,
- 71, 62, 57, 81, 93, 94, 63, 64, nil, nil,
- nil, 67, nil, 65, 66, 68, 30, 31, 72, 73,
- nil, nil, nil, nil, nil, 29, 28, 27, 101, 100,
- 102, 103, nil, nil, 230, nil, nil, nil, nil, nil,
- nil, 45, nil, nil, 105, 104, 106, 95, 56, 97,
- 96, 98, 284, 99, 107, 108, nil, 91, 92, nil,
- 42, 43, 41, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 223, nil, nil, 229, nil, nil, 58, 59,
- nil, nil, 60, nil, 281, nil, 279, nil, 44, nil,
- nil, 285, nil, nil, nil, nil, nil, 228, nil, nil,
- nil, nil, 89, 282, 82, 83, nil, 84, 86, 85,
- 87, nil, nil, nil, nil, 80, 88, nil, nil, nil,
- 69, 70, 71, 62, 57, 81, 93, 94, 63, 64,
- nil, nil, nil, 67, nil, 65, 66, 68, 30, 31,
- 72, 73, nil, nil, nil, nil, nil, 29, 28, 27,
- 101, 100, 102, 103, nil, nil, 230, nil, nil, nil,
- nil, nil, nil, 45, nil, nil, 105, 104, 106, 95,
- 56, 97, 96, 98, 284, 99, 107, 108, nil, 91,
- 92, nil, 42, 43, 41, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 223, nil, nil, 229, nil, nil,
- 58, 59, nil, nil, 60, nil, 281, nil, 279, nil,
- 44, nil, nil, 285, nil, nil, nil, nil, nil, 228,
- nil, nil, nil, nil, 89, 282, 82, 83, nil, 84,
- 86, 85, 87, nil, nil, nil, nil, 80, 88, nil,
- nil, nil, 69, 70, 71, 62, 57, 81, 93, 94,
- 63, 64, nil, nil, nil, 67, nil, 65, 66, 68,
- 309, 310, 72, 73, nil, nil, nil, nil, nil, 305,
- 306, 312, 101, 100, 102, 103, nil, nil, 230, nil,
- nil, nil, nil, nil, nil, 307, nil, nil, 105, 104,
- 106, 95, 56, 97, 96, 98, nil, 99, 107, 108,
- nil, 91, 92, nil, nil, nil, 313, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 303, nil, nil, 299,
- nil, nil, 58, 59, nil, nil, 60, nil, 298, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 89, 79, 82, 83,
- nil, 84, 86, 85, 87, nil, nil, nil, nil, 80,
- 88, nil, nil, nil, 69, 70, 71, 62, 57, 81,
- 93, 94, 63, 64, nil, nil, nil, 67, nil, 65,
- 66, 68, 309, 310, 72, 73, nil, nil, nil, nil,
- nil, 305, 306, 312, 101, 100, 102, 103, nil, nil,
- 230, nil, nil, nil, nil, nil, nil, 307, nil, nil,
- 105, 104, 106, 95, 56, 97, 96, 98, nil, 99,
- 107, 108, nil, 91, 92, nil, nil, nil, 313, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 303, nil,
- nil, 229, nil, nil, 58, 59, nil, nil, 60, nil,
- 548, nil, 545, 544, 543, 553, 546, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 556, nil, 89, 79,
- 82, 83, nil, 84, 86, 85, 87, nil, nil, nil,
- nil, 80, 88, nil, nil, nil, 315, nil, 551, 62,
- nil, 81, 93, 94, 69, 70, 71, nil, 57, 564,
- 563, nil, 63, 64, 557, nil, nil, 67, nil, 65,
- 66, 68, 309, 310, 72, 73, nil, nil, nil, nil,
- nil, 305, 306, 312, 101, 100, 102, 103, nil, nil,
- 230, nil, nil, nil, nil, nil, nil, 45, nil, nil,
- 105, 104, 106, 95, 56, 97, 96, 98, nil, 99,
- 107, 108, nil, 91, 92, nil, 42, 43, 41, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 223, nil,
- nil, 229, nil, nil, 58, 59, nil, nil, 60, nil,
- nil, nil, nil, nil, 44, nil, nil, nil, nil, nil,
- nil, nil, nil, 228, nil, nil, nil, nil, 89, 79,
- 82, 83, nil, 84, 86, 85, 87, nil, nil, nil,
- nil, 80, 88, nil, nil, nil, 69, 70, 71, 62,
- 57, 81, 93, 94, 63, 64, nil, nil, nil, 67,
- nil, 65, 66, 68, 309, 310, 72, 73, nil, nil,
- nil, nil, nil, 305, 306, 312, 101, 100, 102, 103,
- nil, nil, 230, nil, nil, nil, nil, nil, nil, 45,
- nil, nil, 105, 104, 106, 95, 56, 97, 96, 98,
- nil, 99, 107, 108, nil, 91, 92, nil, 42, 43,
- 41, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 223, nil, nil, 229, nil, nil, 58, 59, nil, nil,
- 60, nil, nil, nil, nil, nil, 44, nil, nil, nil,
- nil, nil, nil, nil, nil, 228, nil, nil, nil, nil,
- 89, 79, 82, 83, nil, 84, 86, 85, 87, nil,
- nil, nil, nil, 80, 88, nil, nil, nil, 69, 70,
- 71, 62, 57, 81, 93, 94, 63, 64, nil, nil,
- nil, 67, nil, 65, 66, 68, 309, 310, 72, 73,
- nil, nil, nil, nil, nil, 305, 306, 312, 101, 100,
- 102, 103, nil, nil, 230, nil, nil, nil, nil, nil,
- nil, 45, nil, nil, 105, 104, 106, 95, 56, 97,
- 96, 98, nil, 99, 107, 108, nil, 91, 92, nil,
- 42, 43, 41, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 223, nil, nil, 229, nil, nil, 58, 59,
- nil, nil, 60, nil, nil, nil, nil, nil, 44, nil,
- nil, nil, nil, nil, nil, nil, nil, 228, nil, nil,
- nil, nil, 89, 79, 82, 83, nil, 84, 86, 85,
- 87, nil, nil, nil, nil, 80, 88, nil, nil, nil,
- 69, 70, 71, 62, 57, 81, 93, 94, 63, 64,
- nil, nil, nil, 67, nil, 65, 66, 68, 309, 310,
- 72, 73, nil, nil, nil, nil, nil, 305, 306, 312,
- 101, 100, 102, 103, nil, nil, 230, nil, nil, nil,
- nil, nil, nil, 45, nil, nil, 105, 104, 106, 95,
- 56, 97, 96, 98, 284, 99, 107, 108, nil, 91,
- 92, nil, 42, 43, 41, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 223, nil, nil, 229, nil, nil,
- 58, 59, nil, nil, 60, nil, 281, nil, nil, nil,
- 44, nil, nil, 285, nil, nil, nil, nil, nil, 228,
- nil, nil, nil, nil, 89, 282, 82, 83, nil, 84,
- 86, 85, 87, nil, nil, nil, nil, 80, 88, nil,
- nil, nil, 69, 70, 71, 62, 57, 81, 93, 94,
- 63, 64, nil, nil, nil, 67, nil, 65, 66, 68,
- 309, 310, 72, 73, nil, nil, nil, nil, nil, 305,
- 306, 312, 101, 100, 102, 103, nil, nil, 230, nil,
- nil, nil, nil, nil, nil, 45, nil, nil, 105, 104,
- 106, 95, 56, 97, 96, 98, 284, 99, 107, 108,
- nil, 91, 92, nil, 42, 43, 41, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 223, nil, nil, 229,
- nil, nil, 58, 59, nil, nil, 60, nil, nil, nil,
- nil, nil, 44, nil, nil, 285, nil, nil, nil, nil,
- nil, 228, nil, nil, nil, nil, 89, 282, 82, 83,
- nil, 84, 86, 85, 87, nil, nil, nil, nil, 80,
- 88, nil, nil, nil, 69, 70, 71, 62, 57, 81,
- 93, 94, 63, 64, nil, nil, nil, 67, nil, 65,
- 66, 68, 30, 31, 72, 73, nil, nil, nil, nil,
- nil, 29, 28, 27, 101, 100, 102, 103, nil, nil,
- 19, nil, nil, nil, nil, nil, nil, 45, nil, nil,
- 105, 104, 106, 95, 56, 97, 96, 98, nil, 99,
- 107, 108, nil, 91, 92, nil, 42, 43, 41, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 223, nil,
- nil, 229, nil, nil, 58, 59, nil, nil, 60, nil,
- nil, nil, nil, nil, 44, nil, nil, nil, nil, nil,
- nil, nil, nil, 20, nil, nil, nil, nil, 89, 79,
- 82, 83, nil, 84, 86, 85, 87, nil, nil, nil,
- nil, 80, 88, nil, nil, nil, 69, 70, 71, 62,
- 57, 81, 93, 94, 63, 64, nil, nil, nil, 67,
- nil, 65, 66, 68, 30, 31, 72, 73, nil, nil,
- nil, nil, nil, 29, 28, 27, 101, 100, 102, 103,
- nil, nil, 19, nil, nil, nil, nil, nil, nil, 45,
- nil, nil, 105, 104, 106, 95, 56, 97, 96, 98,
- nil, 99, 107, 108, nil, 91, 92, nil, 42, 43,
- 41, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 223, nil, nil, 229, nil, nil, 58, 59, nil, nil,
- 60, nil, nil, nil, nil, nil, 44, nil, nil, nil,
- nil, nil, nil, nil, nil, 20, nil, nil, nil, nil,
- 89, 79, 82, 83, nil, 84, 86, 85, 87, nil,
- nil, nil, nil, 80, 88, nil, nil, nil, 69, 70,
- 71, 62, 57, 81, 93, 94, 63, 64, nil, nil,
- nil, 67, nil, 65, 66, 68, 30, 31, 72, 73,
- nil, nil, nil, nil, nil, 29, 28, 27, 101, 100,
- 102, 103, nil, nil, 19, nil, nil, nil, nil, nil,
- nil, 45, nil, nil, 105, 104, 106, 95, 56, 97,
- 96, 98, nil, 99, 107, 108, nil, 91, 92, nil,
- 42, 43, 41, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 223, nil, nil, 229, nil, nil, 58, 59,
- nil, nil, 60, nil, nil, nil, nil, nil, 44, nil,
- nil, nil, nil, nil, nil, nil, nil, 20, nil, nil,
- nil, nil, 89, 79, 82, 83, nil, 84, 86, 85,
- 87, nil, nil, nil, nil, 80, 88, 113, nil, nil,
- nil, nil, 112, 62, nil, 81, 93, 94, 69, 70,
- 71, nil, 57, nil, nil, nil, 63, 64, nil, nil,
- nil, 67, nil, 65, 66, 68, 309, 310, 72, 73,
- nil, nil, nil, nil, nil, 305, 306, 312, 101, 100,
- 102, 103, nil, nil, 230, nil, nil, nil, nil, nil,
- nil, 307, nil, nil, 105, 104, 106, 95, 56, 97,
- 96, 98, nil, 99, 107, 108, nil, 91, 92, nil,
- nil, nil, 313, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 348, nil, nil, 33, nil, nil, 58, 59,
- nil, nil, 60, nil, 35, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 89, 79, 82, 83, nil, 84, 86, 85,
- 87, nil, nil, nil, nil, 80, 88, nil, nil, nil,
- 69, 70, 71, 62, 57, 81, 93, 94, 63, 64,
- nil, nil, nil, 67, nil, 65, 66, 68, 309, 310,
- 72, 73, nil, nil, nil, nil, nil, 305, 306, 312,
- 101, 100, 102, 103, nil, nil, 230, nil, nil, nil,
- nil, nil, nil, 307, nil, nil, 105, 104, 106, 353,
- 56, 97, 96, 354, nil, 99, 107, 108, nil, 91,
- 92, nil, nil, nil, 313, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 360, nil, nil, 355, nil, nil, 229, nil, nil,
- 58, 59, nil, nil, 60, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 89, 79, 82, 83, nil, 84,
- 86, 85, 87, nil, nil, nil, nil, 80, 88, nil,
- nil, nil, 69, 70, 71, 62, 57, 81, 93, 94,
- 63, 64, nil, nil, nil, 67, nil, 65, 66, 68,
- 309, 310, 72, 73, nil, nil, nil, nil, nil, 305,
- 306, 312, 101, 100, 102, 103, nil, nil, 230, nil,
- nil, nil, nil, nil, nil, 307, nil, nil, 105, 104,
- 106, 353, 56, 97, 96, 354, nil, 99, 107, 108,
- nil, 91, 92, nil, nil, nil, 313, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 355, nil, nil, 229,
- nil, nil, 58, 59, nil, nil, 60, nil, 548, nil,
- 545, 544, 543, 553, 546, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 556, nil, 89, 79, 82, 83,
- nil, 84, 86, 85, 87, nil, nil, nil, nil, 80,
- 88, nil, nil, nil, nil, nil, 551, 62, nil, 81,
- 93, 94, 69, 70, 71, 9, 57, 564, 563, nil,
- 63, 64, 557, nil, nil, 67, nil, 65, 66, 68,
- 30, 31, 72, 73, nil, nil, nil, nil, nil, 29,
- 28, 27, 101, 100, 102, 103, nil, nil, 19, nil,
- nil, nil, nil, nil, 8, 45, 7, 10, 105, 104,
- 106, 95, 56, 97, 96, 98, nil, 99, 107, 108,
- nil, 91, 92, nil, 42, 43, 41, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 40, nil, nil, 33,
- nil, nil, 58, 59, nil, nil, 60, nil, 35, nil,
- nil, nil, 44, nil, nil, nil, nil, nil, nil, nil,
- nil, 20, nil, nil, nil, nil, 89, 79, 82, 83,
- nil, 84, 86, 85, 87, nil, nil, nil, nil, 80,
- 88, nil, nil, nil, nil, nil, 388, 62, nil, 81,
- 93, 94, 69, 70, 71, nil, 57, nil, nil, nil,
- 63, 64, nil, nil, nil, 67, nil, 65, 66, 68,
- 30, 31, 72, 73, nil, nil, nil, nil, nil, 29,
- 28, 27, 101, 100, 102, 103, nil, nil, 19, nil,
- nil, nil, nil, nil, nil, 45, nil, nil, 105, 104,
- 106, 95, 56, 97, 96, 98, nil, 99, 107, 108,
- nil, 91, 92, nil, 42, 43, 41, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 223, nil, nil, 229,
- nil, nil, 58, 59, nil, nil, 60, nil, nil, nil,
- nil, nil, 44, nil, nil, nil, nil, nil, nil, nil,
- nil, 20, nil, nil, nil, nil, 89, 79, 82, 83,
- nil, 84, 86, 85, 87, nil, nil, nil, nil, 80,
- 88, nil, nil, nil, 69, 70, 71, 62, 57, 81,
- 93, 94, 63, 64, nil, nil, nil, 67, nil, 65,
- 66, 68, 30, 31, 72, 73, nil, nil, nil, nil,
- nil, 29, 28, 27, 101, 100, 102, 103, nil, nil,
- 19, nil, nil, nil, nil, nil, nil, 45, nil, nil,
- 105, 104, 106, 95, 56, 97, 96, 98, nil, 99,
- 107, 108, nil, 91, 92, nil, 42, 43, 41, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 223, nil,
- nil, 229, nil, nil, 58, 59, nil, nil, 60, nil,
- nil, nil, nil, nil, 44, nil, nil, nil, nil, nil,
- nil, nil, nil, 20, nil, nil, nil, nil, 89, 79,
- 82, 83, nil, 84, 86, 85, 87, nil, nil, nil,
- nil, 80, 88, nil, nil, nil, 69, 70, 71, 62,
- 57, 81, 93, 94, 63, 64, nil, nil, nil, 67,
- nil, 65, 66, 68, 30, 31, 72, 73, nil, nil,
- nil, nil, nil, 29, 28, 27, 101, 100, 102, 103,
- nil, nil, 19, nil, nil, nil, nil, nil, nil, 45,
- nil, nil, 105, 104, 106, 95, 56, 97, 96, 98,
- nil, 99, 107, 108, nil, 91, 92, nil, 42, 43,
- 41, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 223, nil, nil, 229, nil, nil, 58, 59, nil, nil,
- 60, nil, nil, nil, nil, nil, 44, nil, nil, nil,
- nil, nil, nil, nil, nil, 20, nil, nil, nil, nil,
- 89, 79, 82, 83, nil, 84, 86, 85, 87, nil,
- nil, nil, nil, 80, 88, nil, nil, nil, 69, 70,
- 71, 62, 57, 81, 93, 94, 63, 64, nil, nil,
- nil, 67, nil, 65, 66, 68, 30, 31, 72, 73,
- nil, nil, nil, nil, nil, 29, 28, 27, 101, 100,
- 102, 103, nil, nil, 19, nil, nil, nil, nil, nil,
- nil, 45, nil, nil, 105, 104, 106, 95, 56, 97,
- 96, 98, nil, 99, 107, 108, nil, 91, 92, nil,
- 42, 43, 41, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 223, nil, nil, 229, nil, nil, 58, 59,
- nil, nil, 60, nil, nil, nil, nil, nil, 44, nil,
- nil, nil, nil, nil, nil, nil, nil, 20, nil, nil,
- nil, nil, 89, 79, 82, 83, nil, 84, 86, 85,
- 87, nil, nil, nil, nil, 80, 88, nil, nil, nil,
- nil, nil, nil, 62, nil, 81, 93, 94, 69, 70,
- 71, 9, 57, nil, nil, nil, 63, 64, nil, nil,
- nil, 67, nil, 65, 66, 68, 30, 31, 72, 73,
- nil, nil, nil, nil, nil, 29, 28, 27, 101, 100,
- 102, 103, nil, nil, 19, nil, nil, nil, nil, nil,
- 8, 45, nil, 10, 105, 104, 106, 95, 56, 97,
- 96, 98, nil, 99, 107, 108, nil, 91, 92, nil,
- 42, 43, 41, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 40, nil, nil, 33, nil, nil, 58, 59,
- nil, nil, 60, nil, 35, nil, nil, nil, 44, nil,
- nil, nil, nil, nil, nil, nil, nil, 20, nil, nil,
- nil, nil, 89, 79, 82, 83, nil, 84, 86, 85,
- 87, nil, nil, nil, nil, 80, 88, nil, nil, nil,
- 69, 70, 71, 62, 57, 81, 93, 94, 63, 64,
- nil, nil, nil, 67, nil, 65, 66, 68, 30, 31,
- 72, 73, nil, nil, nil, nil, nil, 29, 28, 27,
- 101, 100, 102, 103, nil, nil, 230, nil, nil, nil,
- nil, nil, nil, 45, nil, nil, 105, 104, 106, 95,
- 56, 97, 96, 98, nil, 99, 107, 108, nil, 91,
- 92, nil, 42, 43, 41, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 223, nil, nil, 229, nil, nil,
- 58, 59, nil, nil, 60, nil, 404, nil, nil, nil,
- 44, nil, nil, nil, nil, nil, nil, nil, nil, 228,
- nil, nil, nil, nil, 89, 79, 82, 83, nil, 84,
- 86, 85, 87, nil, nil, nil, nil, 80, 88, nil,
- nil, nil, 69, 70, 71, 62, 57, 81, 93, 94,
- 63, 64, nil, nil, nil, 67, nil, 65, 66, 68,
- 30, 31, 72, 73, nil, nil, nil, nil, nil, 29,
- 28, 27, 101, 100, 102, 103, nil, nil, 230, nil,
- nil, nil, nil, nil, nil, 45, nil, nil, 105, 104,
- 106, 95, 56, 97, 96, 98, nil, 99, 107, 108,
- nil, 91, 92, nil, 42, 43, 41, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 223, nil, nil, 229,
- nil, nil, 58, 59, nil, nil, 60, nil, nil, nil,
- nil, nil, 44, nil, nil, nil, nil, nil, nil, nil,
- nil, 228, nil, nil, nil, nil, 89, 79, 82, 83,
- nil, 84, 86, 85, 87, nil, nil, nil, nil, 80,
- 88, nil, nil, nil, 69, 70, 71, 62, 57, 81,
- 93, 94, 63, 64, nil, nil, nil, 67, nil, 65,
- 66, 68, 30, 31, 72, 73, nil, nil, nil, nil,
- nil, 29, 28, 27, 101, 100, 102, 103, nil, nil,
- 230, nil, nil, nil, nil, nil, nil, 45, nil, nil,
- 105, 104, 106, 95, 56, 97, 96, 98, 284, 99,
- 107, 108, nil, 91, 92, nil, 42, 43, 41, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 223, nil,
- nil, 229, nil, nil, 58, 59, nil, nil, 60, nil,
- 281, nil, 279, nil, 44, nil, nil, 285, nil, nil,
- nil, nil, nil, 228, nil, nil, nil, nil, 89, 282,
- 82, 83, nil, 84, 86, 85, 87, nil, nil, nil,
- nil, 80, 88, nil, nil, nil, 69, 70, 71, 62,
- 57, 81, 93, 94, 63, 64, nil, nil, nil, 67,
- nil, 65, 66, 68, 30, 31, 72, 73, nil, nil,
- nil, nil, nil, 29, 28, 27, 101, 100, 102, 103,
- nil, nil, 230, nil, nil, nil, nil, nil, nil, 45,
- nil, nil, 105, 104, 106, 95, 56, 97, 96, 98,
- nil, 99, 107, 108, nil, 91, 92, nil, 42, 43,
- 41, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 223, nil, nil, 229, nil, nil, 58, 59, nil, nil,
- 60, nil, nil, nil, nil, nil, 44, nil, nil, nil,
- nil, nil, nil, nil, nil, 228, nil, nil, nil, nil,
- 89, 79, 82, 83, nil, 84, 86, 85, 87, nil,
- nil, nil, nil, 80, 88, nil, nil, nil, 69, 70,
- 71, 62, 57, 81, 93, 94, 63, 64, nil, nil,
- nil, 67, nil, 65, 66, 68, 30, 31, 72, 73,
- nil, nil, nil, nil, nil, 29, 28, 27, 101, 100,
- 102, 103, nil, nil, 230, nil, nil, nil, nil, nil,
- nil, 45, nil, nil, 105, 104, 106, 95, 56, 97,
- 96, 98, nil, 99, 107, 108, nil, 91, 92, nil,
- 42, 43, 41, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 223, nil, nil, 229, nil, nil, 58, 59,
- nil, nil, 60, nil, 404, nil, nil, nil, 44, nil,
- nil, nil, nil, nil, nil, nil, nil, 228, nil, nil,
- nil, nil, 89, 79, 82, 83, nil, 84, 86, 85,
- 87, nil, nil, nil, nil, 80, 88, nil, nil, nil,
- 69, 70, 71, 62, 57, 81, 93, 94, 63, 64,
- nil, nil, nil, 67, nil, 65, 66, 68, 30, 31,
- 72, 73, nil, nil, nil, nil, nil, 29, 28, 27,
- 101, 100, 102, 103, nil, nil, 19, nil, nil, nil,
- nil, nil, nil, 45, nil, nil, 105, 104, 106, 95,
- 56, 97, 96, 98, nil, 99, 107, 108, nil, 91,
- 92, nil, 42, 43, 41, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 223, nil, nil, 229, nil, nil,
- 58, 59, nil, nil, 60, nil, nil, nil, nil, nil,
- 44, nil, nil, nil, nil, nil, nil, nil, nil, 20,
- nil, nil, nil, nil, 89, 79, 82, 83, nil, 84,
- 86, 85, 87, nil, nil, nil, nil, 80, 88, nil,
- nil, nil, 69, 70, 71, 62, 57, 81, 93, 94,
- 63, 64, nil, nil, nil, 67, nil, 65, 66, 68,
- 30, 31, 72, 73, nil, nil, nil, nil, nil, 29,
- 28, 27, 101, 100, 102, 103, nil, nil, 19, nil,
- nil, nil, nil, nil, nil, 45, nil, nil, 105, 104,
- 106, 95, 56, 97, 96, 98, nil, 99, 107, 108,
- nil, 91, 92, nil, 42, 43, 41, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 223, nil, nil, 229,
- nil, nil, 58, 59, nil, nil, 60, nil, nil, nil,
- nil, nil, 44, nil, nil, nil, nil, nil, nil, nil,
- nil, 20, nil, nil, nil, nil, 89, 79, 82, 83,
- nil, 84, 86, 85, 87, nil, nil, nil, nil, 80,
- 88, nil, nil, nil, 69, 70, 71, 62, 57, 81,
- 93, 94, 63, 64, nil, nil, nil, 67, nil, 65,
- 66, 68, 30, 31, 72, 73, nil, nil, nil, nil,
- nil, 29, 28, 27, 101, 100, 102, 103, nil, nil,
- 19, nil, nil, nil, nil, nil, nil, 45, nil, nil,
- 105, 104, 106, 95, 56, 97, 96, 98, nil, 99,
- 107, 108, nil, 91, 92, nil, 42, 43, 41, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 223, nil,
- nil, 229, nil, nil, 58, 59, nil, nil, 60, nil,
- nil, nil, nil, nil, 44, nil, nil, nil, nil, nil,
- nil, nil, nil, 20, nil, nil, nil, nil, 89, 79,
- 82, 83, nil, 84, 86, 85, 87, nil, nil, nil,
- nil, 80, 88, nil, nil, nil, 69, 70, 71, 62,
- 57, 81, 93, 94, 63, 64, nil, nil, nil, 67,
- nil, 65, 66, 68, 30, 31, 72, 73, nil, nil,
- nil, nil, nil, 29, 28, 27, 101, 100, 102, 103,
- nil, nil, 19, nil, nil, nil, nil, nil, nil, 45,
- nil, nil, 105, 104, 106, 95, 56, 97, 96, 98,
- nil, 99, 107, 108, nil, 91, 92, nil, 42, 43,
- 41, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 223, nil, nil, 229, nil, nil, 58, 59, nil, nil,
- 60, nil, nil, nil, nil, nil, 44, nil, nil, nil,
- nil, nil, nil, nil, nil, 20, nil, nil, nil, nil,
- 89, 79, 82, 83, nil, 84, 86, 85, 87, nil,
- nil, nil, nil, 80, 88, 218, nil, nil, 69, 70,
- 71, 62, 57, 81, 93, 94, 63, 64, nil, nil,
- nil, 67, nil, 65, 66, 68, 309, 310, 72, 73,
- nil, nil, nil, nil, nil, 305, 306, 312, 101, 100,
- 102, 103, nil, nil, 230, nil, nil, nil, nil, nil,
- nil, 45, nil, nil, 105, 104, 106, 95, 56, 97,
- 96, 98, nil, 99, 107, 108, nil, 91, 92, nil,
- 42, 43, 41, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 223, nil, nil, 229, nil, nil, 58, 59,
- nil, nil, 60, nil, nil, nil, nil, nil, 44, nil,
- nil, nil, nil, nil, nil, nil, nil, 228, nil, nil,
- nil, nil, 89, 79, 82, 83, nil, 84, 86, 85,
- 87, nil, nil, nil, nil, 80, 88, nil, nil, nil,
- 69, 70, 71, 62, 57, 81, 93, 94, 63, 64,
- nil, nil, nil, 67, nil, 65, 66, 68, 309, 310,
- 72, 73, nil, nil, nil, nil, nil, 305, 306, 312,
- 101, 100, 102, 103, nil, nil, 230, nil, nil, nil,
- nil, nil, nil, 45, nil, nil, 105, 104, 106, 95,
- 56, 97, 96, 98, nil, 99, 107, 108, nil, 91,
- 92, nil, 42, 43, 41, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 223, nil, nil, 229, nil, nil,
- 58, 59, nil, nil, 60, nil, nil, nil, nil, nil,
- 44, nil, nil, nil, nil, nil, nil, nil, nil, 228,
- nil, nil, nil, nil, 89, 79, 82, 83, nil, 84,
- 86, 85, 87, nil, nil, nil, nil, 80, 88, nil,
- nil, nil, 69, 70, 71, 62, 57, 81, 93, 94,
- 63, 64, nil, nil, nil, 67, nil, 65, 66, 68,
- 309, 310, 72, 73, nil, nil, nil, nil, nil, 305,
- 306, 312, 101, 100, 102, 103, nil, nil, 230, nil,
- nil, nil, nil, nil, nil, 45, nil, nil, 105, 104,
- 106, 95, 56, 97, 96, 98, nil, 99, 107, 108,
- nil, 91, 92, nil, 42, 43, 41, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 223, nil, nil, 229,
- nil, nil, 58, 59, nil, nil, 60, nil, nil, nil,
- nil, nil, 44, nil, nil, nil, nil, nil, nil, nil,
- nil, 228, nil, nil, nil, nil, 89, 79, 82, 83,
- nil, 84, 86, 85, 87, nil, nil, nil, nil, 80,
- 88, nil, nil, nil, 69, 70, 71, 62, 57, 81,
- 93, 94, 63, 64, nil, nil, nil, 67, nil, 65,
- 66, 68, 309, 310, 72, 73, nil, nil, nil, nil,
- nil, 305, 306, 312, 101, 100, 102, 103, nil, nil,
- 230, nil, nil, nil, nil, nil, nil, 45, nil, nil,
- 105, 104, 106, 95, 56, 97, 96, 98, nil, 99,
- 107, 108, nil, 91, 92, nil, 42, 43, 41, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 223, nil,
- nil, 229, nil, nil, 58, 59, nil, nil, 60, nil,
- nil, nil, nil, nil, 44, nil, nil, nil, nil, nil,
- nil, nil, nil, 228, nil, nil, nil, nil, 89, 79,
- 82, 83, nil, 84, 86, 85, 87, nil, nil, nil,
- nil, 80, 88, nil, nil, nil, 69, 70, 71, 62,
- 57, 81, 93, 94, 63, 64, nil, nil, nil, 67,
- nil, 65, 66, 68, 309, 310, 72, 73, nil, nil,
- nil, nil, nil, 305, 306, 312, 101, 100, 102, 103,
- nil, nil, 230, nil, nil, nil, nil, nil, nil, 45,
- nil, nil, 105, 104, 106, 95, 56, 97, 96, 98,
- nil, 99, 107, 108, nil, 91, 92, nil, 42, 43,
- 41, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 223, nil, nil, 229, nil, nil, 58, 59, nil, nil,
- 60, nil, nil, nil, nil, nil, 44, nil, nil, nil,
- nil, nil, nil, nil, nil, 228, nil, nil, nil, nil,
- 89, 79, 82, 83, nil, 84, 86, 85, 87, nil,
- nil, nil, nil, 80, 88, nil, nil, nil, 69, 70,
- 71, 62, 57, 81, 93, 94, 63, 64, nil, nil,
- nil, 67, nil, 65, 66, 68, 309, 310, 72, 73,
- nil, nil, nil, nil, nil, 305, 306, 312, 101, 100,
- 102, 103, nil, nil, 230, nil, nil, nil, nil, nil,
- nil, 45, nil, nil, 105, 104, 106, 95, 56, 97,
- 96, 98, nil, 99, 107, 108, nil, 91, 92, nil,
- 42, 43, 41, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 223, nil, nil, 229, nil, nil, 58, 59,
- nil, nil, 60, nil, nil, nil, nil, nil, 44, nil,
- nil, nil, nil, nil, nil, nil, nil, 228, nil, nil,
- nil, nil, 89, 79, 82, 83, nil, 84, 86, 85,
- 87, nil, nil, nil, nil, 80, 88, nil, nil, nil,
- 69, 70, 71, 62, 57, 81, 93, 94, 63, 64,
- nil, nil, nil, 67, nil, 65, 66, 68, 309, 310,
- 72, 73, nil, nil, nil, nil, nil, 305, 306, 312,
- 101, 100, 102, 103, nil, nil, 230, nil, nil, nil,
- nil, nil, nil, 45, nil, nil, 105, 104, 106, 95,
- 56, 97, 96, 98, nil, 99, 107, 108, nil, 91,
- 92, nil, 42, 43, 41, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 223, nil, nil, 229, nil, nil,
- 58, 59, nil, nil, 60, nil, nil, nil, nil, nil,
- 44, nil, nil, nil, nil, nil, nil, nil, nil, 228,
- nil, nil, nil, nil, 89, 79, 82, 83, nil, 84,
- 86, 85, 87, nil, nil, nil, nil, 80, 88, nil,
- nil, nil, 69, 70, 71, 62, 57, 81, 93, 94,
- 63, 64, nil, nil, nil, 67, nil, 65, 66, 68,
- 309, 310, 72, 73, nil, nil, nil, nil, nil, 305,
- 306, 312, 101, 100, 102, 103, nil, nil, 230, nil,
- nil, nil, nil, nil, nil, 45, nil, nil, 105, 104,
- 106, 95, 56, 97, 96, 98, nil, 99, 107, 108,
- nil, 91, 92, nil, 42, 43, 41, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 223, nil, nil, 229,
- nil, nil, 58, 59, nil, nil, 60, nil, nil, nil,
- nil, nil, 44, nil, nil, nil, nil, nil, nil, nil,
- nil, 228, nil, nil, nil, nil, 89, 79, 82, 83,
- nil, 84, 86, 85, 87, nil, nil, nil, nil, 80,
- 88, nil, nil, nil, 69, 70, 71, 62, 57, 81,
- 93, 94, 63, 64, nil, nil, nil, 67, nil, 65,
- 66, 68, 309, 310, 72, 73, nil, nil, nil, nil,
- nil, 305, 306, 312, 101, 100, 102, 103, nil, nil,
- 230, nil, nil, nil, nil, nil, nil, 45, nil, nil,
- 105, 104, 106, 95, 56, 97, 96, 98, nil, 99,
- 107, 108, nil, 91, 92, nil, 42, 43, 41, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 223, nil,
- nil, 229, nil, nil, 58, 59, nil, nil, 60, nil,
- nil, nil, nil, nil, 44, nil, nil, nil, nil, nil,
- nil, nil, nil, 228, nil, nil, nil, nil, 89, 79,
- 82, 83, nil, 84, 86, 85, 87, nil, nil, nil,
- nil, 80, 88, nil, nil, nil, 69, 70, 71, 62,
- 57, 81, 93, 94, 63, 64, nil, nil, nil, 67,
- nil, 65, 66, 68, 309, 310, 72, 73, nil, nil,
- nil, nil, nil, 305, 306, 312, 101, 100, 102, 103,
- nil, nil, 230, nil, nil, nil, nil, nil, nil, 45,
- nil, nil, 105, 104, 106, 95, 56, 97, 96, 98,
- nil, 99, 107, 108, nil, 91, 92, nil, 42, 43,
- 41, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 223, nil, nil, 229, nil, nil, 58, 59, nil, nil,
- 60, nil, nil, nil, nil, nil, 44, nil, nil, nil,
- nil, nil, nil, nil, nil, 228, nil, nil, nil, nil,
- 89, 79, 82, 83, nil, 84, 86, 85, 87, nil,
- nil, nil, nil, 80, 88, nil, nil, nil, 69, 70,
- 71, 62, 57, 81, 93, 94, 63, 64, nil, nil,
- nil, 67, nil, 65, 66, 68, 309, 310, 72, 73,
- nil, nil, nil, nil, nil, 305, 306, 312, 101, 100,
- 102, 103, nil, nil, 230, nil, nil, nil, nil, nil,
- nil, 45, nil, nil, 105, 104, 106, 95, 56, 97,
- 96, 98, nil, 99, 107, 108, nil, 91, 92, nil,
- 42, 43, 41, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 223, nil, nil, 229, nil, nil, 58, 59,
- nil, nil, 60, nil, nil, nil, nil, nil, 44, nil,
- nil, nil, nil, nil, nil, nil, nil, 228, nil, nil,
- nil, nil, 89, 79, 82, 83, nil, 84, 86, 85,
- 87, nil, nil, nil, nil, 80, 88, nil, nil, nil,
- 69, 70, 71, 62, 57, 81, 93, 94, 63, 64,
- nil, nil, nil, 67, nil, 65, 66, 68, 309, 310,
- 72, 73, nil, nil, nil, nil, nil, 305, 306, 312,
- 101, 100, 102, 103, nil, nil, 230, nil, nil, nil,
- nil, nil, nil, 45, nil, nil, 105, 104, 106, 95,
- 56, 97, 96, 98, nil, 99, 107, 108, nil, 91,
- 92, nil, 42, 43, 41, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 223, nil, nil, 229, nil, nil,
- 58, 59, nil, nil, 60, nil, nil, nil, nil, nil,
- 44, nil, nil, nil, nil, nil, nil, nil, nil, 228,
- nil, nil, nil, nil, 89, 79, 82, 83, nil, 84,
- 86, 85, 87, nil, nil, nil, nil, 80, 88, nil,
- nil, nil, 69, 70, 71, 62, 57, 81, 93, 94,
- 63, 64, nil, nil, nil, 67, nil, 65, 66, 68,
- 309, 310, 72, 73, nil, nil, nil, nil, nil, 305,
- 306, 312, 101, 100, 102, 103, nil, nil, 230, nil,
- nil, nil, nil, nil, nil, 45, nil, nil, 105, 104,
- 106, 95, 56, 97, 96, 98, nil, 99, 107, 108,
- nil, 91, 92, nil, 42, 43, 41, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 223, nil, nil, 229,
- nil, nil, 58, 59, nil, nil, 60, nil, nil, nil,
- nil, nil, 44, nil, nil, nil, nil, nil, nil, nil,
- nil, 228, nil, nil, nil, nil, 89, 79, 82, 83,
- nil, 84, 86, 85, 87, nil, nil, nil, nil, 80,
- 88, nil, nil, nil, 69, 70, 71, 62, 57, 81,
- 93, 94, 63, 64, nil, nil, nil, 67, nil, 65,
- 66, 68, 309, 310, 72, 73, nil, nil, nil, nil,
- nil, 305, 306, 312, 101, 100, 102, 103, nil, nil,
- 230, nil, nil, nil, nil, nil, nil, 45, nil, nil,
- 105, 104, 106, 95, 56, 97, 96, 98, nil, 99,
- 107, 108, nil, 91, 92, nil, 42, 43, 41, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 223, nil,
- nil, 229, nil, nil, 58, 59, nil, nil, 60, nil,
- nil, nil, nil, nil, 44, nil, nil, nil, nil, nil,
- nil, nil, nil, 228, nil, nil, nil, nil, 89, 79,
- 82, 83, nil, 84, 86, 85, 87, nil, nil, nil,
- nil, 80, 88, nil, nil, nil, 69, 70, 71, 62,
- 57, 81, 93, 94, 63, 64, nil, nil, nil, 67,
- nil, 65, 66, 68, 309, 310, 72, 73, nil, nil,
- nil, nil, nil, 305, 306, 312, 101, 100, 102, 103,
- nil, nil, 230, nil, nil, nil, nil, nil, nil, 45,
- nil, nil, 105, 104, 106, 95, 56, 97, 96, 98,
- nil, 99, 107, 108, nil, 91, 92, nil, 42, 43,
- 41, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 223, nil, nil, 229, nil, nil, 58, 59, nil, nil,
- 60, nil, nil, nil, nil, nil, 44, nil, nil, nil,
- nil, nil, nil, nil, nil, 228, nil, nil, nil, nil,
- 89, 79, 82, 83, nil, 84, 86, 85, 87, nil,
- nil, nil, nil, 80, 88, nil, nil, nil, 69, 70,
- 71, 62, 57, 81, 93, 94, 63, 64, nil, nil,
- nil, 67, nil, 65, 66, 68, 309, 310, 72, 73,
- nil, nil, nil, nil, nil, 305, 306, 312, 101, 100,
- 102, 103, nil, nil, 230, nil, nil, nil, nil, nil,
- nil, 45, nil, nil, 105, 104, 106, 95, 56, 97,
- 96, 98, nil, 99, 107, 108, nil, 91, 92, nil,
- 42, 43, 41, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 223, nil, nil, 229, nil, nil, 58, 59,
- nil, nil, 60, nil, nil, nil, nil, nil, 44, nil,
- nil, nil, nil, nil, nil, nil, nil, 228, nil, nil,
- nil, nil, 89, 79, 82, 83, nil, 84, 86, 85,
- 87, nil, nil, nil, nil, 80, 88, nil, nil, nil,
- 69, 70, 71, 62, 57, 81, 93, 94, 63, 64,
- nil, nil, nil, 67, nil, 65, 66, 68, 309, 310,
- 72, 73, nil, nil, nil, nil, nil, 305, 306, 312,
- 101, 100, 102, 103, nil, nil, 230, nil, nil, nil,
- nil, nil, nil, 45, nil, nil, 105, 104, 106, 95,
- 56, 97, 96, 98, nil, 99, 107, 108, nil, 91,
- 92, nil, 42, 43, 41, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 223, nil, nil, 229, nil, nil,
- 58, 59, nil, nil, 60, nil, nil, nil, nil, nil,
- 44, nil, nil, nil, nil, nil, nil, nil, nil, 228,
- nil, nil, nil, nil, 89, 79, 82, 83, nil, 84,
- 86, 85, 87, nil, nil, nil, nil, 80, 88, nil,
- nil, nil, 69, 70, 71, 62, 57, 81, 93, 94,
- 63, 64, nil, nil, nil, 67, nil, 65, 66, 68,
- 309, 310, 72, 73, nil, nil, nil, nil, nil, 305,
- 306, 312, 101, 100, 102, 103, nil, nil, 230, nil,
- nil, nil, nil, nil, nil, 45, nil, nil, 105, 104,
- 106, 95, 56, 97, 96, 98, nil, 99, 107, 108,
- nil, 91, 92, nil, 42, 43, 41, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 223, nil, nil, 229,
- nil, nil, 58, 59, nil, nil, 60, nil, nil, nil,
- nil, nil, 44, nil, nil, nil, nil, nil, nil, nil,
- nil, 228, nil, nil, nil, nil, 89, 79, 82, 83,
- nil, 84, 86, 85, 87, nil, nil, nil, nil, 80,
- 88, nil, nil, nil, 69, 70, 71, 62, 57, 81,
- 93, 94, 63, 64, nil, nil, nil, 67, nil, 65,
- 66, 68, 309, 310, 72, 73, nil, nil, nil, nil,
- nil, 305, 306, 312, 101, 100, 102, 103, nil, nil,
- 230, nil, nil, nil, nil, nil, nil, 45, nil, nil,
- 105, 104, 106, 95, 56, 97, 96, 98, nil, 99,
- 107, 108, nil, 91, 92, nil, 42, 43, 41, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 223, nil,
- nil, 229, nil, nil, 58, 59, nil, nil, 60, nil,
- nil, nil, nil, nil, 44, nil, nil, nil, nil, nil,
- nil, nil, nil, 228, nil, nil, nil, nil, 89, 79,
- 82, 83, nil, 84, 86, 85, 87, nil, nil, nil,
- nil, 80, 88, nil, nil, nil, 69, 70, 71, 62,
- 57, 81, 93, 94, 63, 64, nil, nil, nil, 67,
- nil, 65, 66, 68, 309, 310, 72, 73, nil, nil,
- nil, nil, nil, 305, 306, 312, 101, 100, 102, 103,
- nil, nil, 230, nil, nil, nil, nil, nil, nil, 45,
- nil, nil, 105, 104, 106, 95, 56, 97, 96, 98,
- nil, 99, 107, 108, nil, 91, 92, nil, 42, 43,
- 41, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 223, nil, nil, 229, nil, nil, 58, 59, nil, nil,
- 60, nil, nil, nil, nil, nil, 44, nil, nil, nil,
- nil, nil, nil, nil, nil, 228, nil, nil, nil, nil,
- 89, 79, 82, 83, nil, 84, 86, 85, 87, nil,
- nil, nil, nil, 80, 88, nil, nil, nil, 69, 70,
- 71, 62, 57, 81, 93, 94, 63, 64, nil, nil,
- nil, 67, nil, 65, 66, 68, 309, 310, 72, 73,
- nil, nil, nil, nil, nil, 305, 306, 312, 101, 100,
- 102, 103, nil, nil, 230, nil, nil, nil, nil, nil,
- nil, 45, nil, nil, 105, 104, 106, 95, 56, 97,
- 96, 98, nil, 99, 107, 108, nil, 91, 92, nil,
- 42, 43, 41, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 223, nil, nil, 229, nil, nil, 58, 59,
- nil, nil, 60, nil, nil, nil, nil, nil, 44, nil,
- nil, nil, nil, nil, nil, nil, nil, 228, nil, nil,
- nil, nil, 89, 79, 82, 83, nil, 84, 86, 85,
- 87, nil, nil, nil, nil, 80, 88, nil, nil, nil,
- 69, 70, 71, 62, 57, 81, 93, 94, 63, 64,
- nil, nil, nil, 67, nil, 65, 66, 68, 309, 310,
- 72, 73, nil, nil, nil, nil, nil, 305, 306, 312,
- 101, 100, 102, 103, nil, nil, 230, nil, nil, nil,
- nil, nil, nil, 45, nil, nil, 105, 104, 106, 95,
- 56, 97, 96, 98, nil, 99, 107, 108, nil, 91,
- 92, nil, 42, 43, 41, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 223, nil, nil, 229, nil, nil,
- 58, 59, nil, nil, 60, nil, nil, nil, nil, nil,
- 44, nil, nil, nil, nil, nil, nil, nil, nil, 228,
- nil, nil, nil, nil, 89, 79, 82, 83, nil, 84,
- 86, 85, 87, nil, nil, nil, nil, 80, 88, nil,
- nil, nil, 69, 70, 71, 62, 57, 81, 93, 94,
- 63, 64, nil, nil, nil, 67, nil, 65, 66, 68,
- 309, 310, 72, 73, nil, nil, nil, nil, nil, 305,
- 306, 312, 101, 100, 102, 103, nil, nil, 230, nil,
- nil, nil, nil, nil, nil, 45, nil, nil, 105, 104,
- 106, 95, 56, 97, 96, 98, nil, 99, 107, 108,
- nil, 91, 92, nil, 42, 43, 41, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 223, nil, nil, 229,
- nil, nil, 58, 59, nil, nil, 60, nil, nil, nil,
- nil, nil, 44, nil, nil, nil, nil, nil, nil, nil,
- nil, 228, nil, nil, nil, nil, 89, 79, 82, 83,
- nil, 84, 86, 85, 87, nil, nil, nil, nil, 80,
- 88, nil, nil, nil, 69, 70, 71, 62, 57, 81,
- 93, 94, 63, 64, nil, nil, nil, 67, nil, 65,
- 66, 68, 309, 310, 72, 73, nil, nil, nil, nil,
- nil, 305, 306, 312, 101, 100, 102, 103, nil, nil,
- 230, nil, nil, nil, nil, nil, nil, 45, nil, nil,
- 105, 104, 106, 95, 56, 97, 96, 98, nil, 99,
- 107, 108, nil, 91, 92, nil, 42, 43, 41, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 223, nil,
- nil, 229, nil, nil, 58, 59, nil, nil, 60, nil,
- nil, nil, nil, nil, 44, nil, nil, nil, nil, nil,
- nil, nil, nil, 228, nil, nil, nil, nil, 89, 79,
- 82, 83, nil, 84, 86, 85, 87, nil, nil, nil,
- nil, 80, 88, nil, nil, nil, 69, 70, 71, 62,
- 57, 81, 93, 94, 63, 64, nil, nil, nil, 67,
- nil, 65, 66, 68, 309, 310, 72, 73, nil, nil,
- nil, nil, nil, 305, 306, 312, 101, 100, 102, 103,
- nil, nil, 230, nil, nil, nil, nil, nil, nil, 45,
- nil, nil, 105, 104, 106, 95, 56, 97, 96, 98,
- nil, 99, 107, 108, nil, 91, 92, nil, 42, 43,
- 41, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 223, nil, nil, 229, nil, nil, 58, 59, nil, nil,
- 60, nil, nil, nil, nil, nil, 44, nil, nil, nil,
- nil, nil, nil, nil, nil, 228, nil, nil, nil, nil,
- 89, 79, 82, 83, nil, 84, 86, 85, 87, nil,
- nil, nil, nil, 80, 88, nil, nil, nil, 69, 70,
- 71, 62, 57, 81, 93, 94, 63, 64, nil, nil,
- nil, 67, nil, 65, 66, 68, 309, 310, 72, 73,
- nil, nil, nil, nil, nil, 305, 306, 312, 101, 100,
- 102, 103, nil, nil, 230, nil, nil, nil, nil, nil,
- nil, 45, nil, nil, 105, 104, 106, 95, 56, 97,
- 96, 98, nil, 99, 107, 108, nil, 91, 92, nil,
- 42, 43, 41, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 223, nil, nil, 229, nil, nil, 58, 59,
- nil, nil, 60, nil, nil, nil, nil, nil, 44, nil,
- nil, nil, nil, nil, nil, nil, nil, 228, nil, nil,
- nil, nil, 89, 79, 82, 83, nil, 84, 86, 85,
- 87, nil, nil, nil, nil, 80, 88, nil, nil, nil,
- 69, 70, 71, 62, 57, 81, 93, 94, 63, 64,
- nil, nil, nil, 67, nil, 65, 66, 68, 30, 31,
- 72, 73, nil, nil, nil, nil, nil, 29, 28, 27,
- 101, 100, 102, 103, nil, nil, 230, nil, nil, nil,
- nil, nil, nil, 45, nil, nil, 105, 104, 106, 95,
- 56, 97, 96, 98, 284, 99, 107, 108, nil, 91,
- 92, nil, 42, 43, 41, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 223, nil, nil, 229, nil, nil,
- 58, 59, nil, nil, 60, nil, 281, nil, 279, nil,
- 44, nil, nil, 285, nil, nil, nil, nil, nil, 228,
- nil, nil, nil, nil, 89, 282, 82, 83, nil, 84,
- 86, 85, 87, nil, nil, nil, nil, 80, 88, nil,
- nil, nil, 69, 70, 71, 62, 57, 81, 93, 94,
- 63, 64, nil, nil, nil, 67, nil, 65, 66, 68,
- 30, 31, 72, 73, nil, nil, nil, nil, nil, 29,
- 28, 27, 101, 100, 102, 103, nil, nil, 230, nil,
- nil, nil, nil, nil, nil, 45, nil, nil, 105, 104,
- 106, 95, 56, 97, 96, 98, 284, 99, 107, 108,
- nil, 91, 92, nil, 42, 43, 41, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 223, nil, nil, 229,
- nil, nil, 58, 59, nil, nil, 60, nil, 281, nil,
- 279, nil, 44, nil, nil, 285, nil, nil, nil, nil,
- nil, 228, nil, nil, nil, nil, 89, 282, 82, 83,
- nil, 84, 86, 85, 87, nil, nil, nil, nil, 80,
- 88, nil, nil, nil, 69, 70, 71, 62, 57, 81,
- 93, 94, 63, 64, nil, nil, nil, 67, nil, 65,
- 66, 68, 30, 31, 72, 73, nil, nil, nil, nil,
- nil, 29, 28, 27, 101, 100, 102, 103, nil, nil,
- 230, nil, nil, nil, nil, nil, nil, 45, nil, nil,
- 105, 104, 106, 95, 56, 97, 96, 98, 284, 99,
- 107, 108, nil, 91, 92, nil, 42, 43, 41, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 223, nil,
- nil, 229, nil, nil, 58, 59, nil, nil, 60, nil,
- 281, nil, 279, nil, 44, nil, nil, 285, nil, nil,
- nil, nil, nil, 228, nil, nil, nil, nil, 89, 282,
- 82, 83, nil, 84, 86, 85, 87, nil, nil, nil,
- nil, 80, 88, 218, nil, nil, 69, 70, 71, 62,
- 57, 81, 93, 94, 63, 64, nil, nil, nil, 67,
- nil, 65, 66, 68, 309, 310, 72, 73, nil, nil,
- nil, nil, nil, 305, 306, 312, 101, 100, 102, 103,
- nil, nil, 230, nil, nil, nil, nil, nil, nil, 45,
- nil, nil, 105, 104, 106, 95, 56, 97, 96, 98,
- nil, 99, 107, 108, nil, 91, 92, nil, 42, 43,
- 41, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 223, nil, nil, 229, nil, nil, 58, 59, nil, nil,
- 60, nil, nil, nil, nil, nil, 44, nil, nil, nil,
- nil, nil, nil, nil, nil, 228, nil, nil, nil, nil,
- 89, 79, 82, 83, nil, 84, 86, 85, 87, nil,
- nil, nil, nil, 80, 88, nil, nil, nil, 69, 70,
- 71, 62, 57, 81, 93, 94, 63, 64, nil, nil,
- nil, 67, nil, 65, 66, 68, 309, 310, 72, 73,
- nil, nil, nil, nil, nil, 305, 306, 312, 101, 100,
- 102, 103, nil, nil, 230, nil, nil, nil, nil, nil,
- nil, 45, nil, nil, 105, 104, 106, 95, 56, 97,
- 96, 98, nil, 99, 107, 108, nil, 91, 92, nil,
- 42, 43, 41, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 223, nil, nil, 229, nil, nil, 58, 59,
- nil, nil, 60, nil, nil, nil, nil, nil, 44, nil,
- nil, nil, nil, nil, nil, nil, nil, 228, nil, nil,
- nil, nil, 89, 79, 82, 83, nil, 84, 86, 85,
- 87, nil, nil, nil, nil, 80, 88, nil, nil, nil,
- 69, 70, 71, 62, 57, 81, 93, 94, 63, 64,
- nil, nil, nil, 67, nil, 65, 66, 68, 309, 310,
- 72, 73, nil, nil, nil, nil, nil, 305, 306, 312,
- 101, 100, 102, 103, nil, nil, 230, nil, nil, nil,
- nil, nil, nil, 45, nil, nil, 105, 104, 106, 95,
- 56, 97, 96, 98, nil, 99, 107, 108, nil, 91,
- 92, nil, 42, 43, 41, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 223, nil, nil, 229, nil, nil,
- 58, 59, nil, nil, 60, nil, nil, nil, nil, nil,
- 44, nil, nil, nil, nil, nil, nil, nil, nil, 228,
- nil, nil, nil, nil, 89, 79, 82, 83, nil, 84,
- 86, 85, 87, nil, nil, nil, nil, 80, 88, nil,
- nil, nil, 69, 70, 71, 62, 57, 81, 93, 94,
- 63, 64, nil, nil, nil, 67, nil, 65, 66, 68,
- 309, 310, 72, 73, nil, nil, nil, nil, nil, 305,
- 306, 312, 101, 100, 102, 103, nil, nil, 230, nil,
- nil, nil, nil, nil, nil, 45, nil, nil, 105, 104,
- 106, 95, 56, 97, 96, 98, nil, 99, 107, 108,
- nil, 91, 92, nil, 42, 43, 41, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 223, nil, nil, 229,
- nil, nil, 58, 59, nil, nil, 60, nil, nil, nil,
- nil, nil, 44, nil, nil, nil, nil, nil, nil, nil,
- nil, 228, nil, nil, nil, nil, 89, 79, 82, 83,
- nil, 84, 86, 85, 87, nil, nil, nil, nil, 80,
- 88, nil, nil, nil, nil, nil, nil, 62, nil, 81,
- 93, 94, 69, 70, 71, 9, 57, nil, nil, nil,
- 63, 64, nil, nil, nil, 67, nil, 65, 66, 68,
- 30, 31, 72, 73, nil, nil, nil, nil, nil, 29,
- 28, 27, 101, 100, 102, 103, nil, nil, 19, nil,
- nil, nil, nil, nil, 8, 45, nil, 10, 105, 104,
- 106, 95, 56, 97, 96, 98, nil, 99, 107, 108,
- nil, 91, 92, nil, 42, 43, 41, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 40, nil, nil, 33,
- nil, nil, 58, 59, nil, nil, 60, nil, 35, nil,
- nil, nil, 44, nil, nil, nil, nil, nil, nil, nil,
- nil, 20, nil, nil, nil, nil, 89, 79, 82, 83,
- nil, 84, 86, 85, 87, nil, nil, nil, nil, 80,
- 88, nil, nil, nil, 69, 70, 71, 62, 57, 81,
- 93, 94, 63, 64, nil, nil, nil, 67, nil, 65,
- 66, 68, 309, 310, 72, 73, nil, nil, nil, nil,
- nil, 305, 306, 312, 101, 100, 102, 103, nil, nil,
- 230, nil, nil, nil, nil, nil, nil, 307, nil, nil,
- 105, 104, 106, 95, 56, 97, 96, 98, nil, 99,
- 107, 108, nil, 91, 92, nil, nil, nil, 313, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 303, nil,
- nil, 229, nil, nil, 58, 59, nil, nil, 60, nil,
- 548, nil, 545, 544, 543, 553, 546, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 556, nil, 89, 79,
- 82, 83, nil, 84, 86, 85, 87, nil, nil, nil,
- nil, 80, 88, nil, nil, nil, 504, nil, 551, 62,
- nil, 81, 93, 94, 69, 70, 71, nil, 57, 564,
- 563, nil, 63, 64, 557, nil, nil, 67, nil, 65,
- 66, 68, 309, 310, 72, 73, nil, nil, nil, nil,
- nil, 305, 306, 312, 101, 100, 102, 103, nil, nil,
- 230, nil, nil, nil, nil, nil, nil, 307, nil, nil,
- 105, 104, 106, 95, 56, 97, 96, 98, nil, 99,
- 107, 108, nil, 91, 92, nil, nil, nil, 313, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 303, nil,
- nil, 299, nil, nil, 58, 59, nil, nil, 60, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 89, 79,
- 82, 83, nil, 84, 86, 85, 87, nil, nil, nil,
- nil, 80, 88, nil, nil, nil, 69, 70, 71, 62,
- 57, 81, 93, 94, 63, 64, nil, nil, nil, 67,
- nil, 65, 66, 68, 309, 310, 72, 73, nil, nil,
- nil, nil, nil, 305, 306, 312, 101, 100, 102, 103,
- nil, nil, 230, nil, nil, nil, nil, nil, nil, 45,
- nil, nil, 105, 104, 106, 95, 56, 97, 96, 98,
- nil, 99, 107, 108, nil, 91, 92, nil, 42, 43,
- 41, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 223, nil, nil, 229, 520, nil, 58, 59, nil, nil,
- 60, nil, nil, nil, nil, nil, 44, nil, nil, nil,
- nil, nil, nil, nil, nil, 228, nil, nil, nil, nil,
- 89, 79, 82, 83, nil, 84, 86, 85, 87, nil,
- nil, nil, nil, 80, 88, nil, nil, nil, 69, 70,
- 71, 62, 57, 81, 93, 94, 63, 64, nil, nil,
- nil, 67, nil, 65, 66, 68, 30, 31, 72, 73,
- nil, nil, nil, nil, nil, 29, 28, 27, 101, 100,
- 102, 103, nil, nil, 19, nil, nil, nil, nil, nil,
- nil, 45, nil, nil, 105, 104, 106, 95, 56, 97,
- 96, 98, nil, 99, 107, 108, nil, 91, 92, nil,
- 42, 43, 41, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 223, nil, nil, 229, nil, nil, 58, 59,
- nil, nil, 60, nil, nil, nil, nil, nil, 44, nil,
- nil, nil, nil, nil, nil, nil, nil, 20, nil, nil,
- nil, nil, 89, 79, 82, 83, nil, 84, 86, 85,
- 87, nil, nil, nil, nil, 80, 88, nil, nil, nil,
- 69, 70, 71, 62, 57, 81, 93, 94, 63, 64,
- nil, nil, nil, 67, nil, 65, 66, 68, 30, 31,
- 72, 73, nil, nil, nil, nil, nil, 29, 28, 27,
- 101, 100, 102, 103, nil, nil, 19, nil, nil, nil,
- nil, nil, nil, 45, nil, nil, 105, 104, 106, 95,
- 56, 97, 96, 98, nil, 99, 107, 108, nil, 91,
- 92, nil, 42, 43, 41, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 223, nil, nil, 229, nil, nil,
- 58, 59, nil, nil, 60, nil, nil, nil, nil, nil,
- 44, nil, nil, nil, nil, nil, nil, nil, nil, 20,
- nil, nil, nil, nil, 89, 79, 82, 83, nil, 84,
- 86, 85, 87, nil, nil, nil, nil, 80, 88, nil,
- nil, nil, 69, 70, 71, 62, 57, 81, 93, 94,
- 63, 64, nil, nil, nil, 67, nil, 65, 66, 68,
- 30, 31, 72, 73, nil, nil, nil, nil, nil, 29,
- 28, 27, 101, 100, 102, 103, nil, nil, 19, nil,
- nil, nil, nil, nil, nil, 45, nil, nil, 105, 104,
- 106, 95, 56, 97, 96, 98, nil, 99, 107, 108,
- nil, 91, 92, nil, 42, 43, 41, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 223, nil, nil, 229,
- nil, nil, 58, 59, nil, nil, 60, nil, nil, nil,
- nil, nil, 44, nil, nil, nil, nil, nil, nil, nil,
- nil, 20, nil, nil, nil, nil, 89, 79, 82, 83,
- nil, 84, 86, 85, 87, nil, nil, nil, nil, 80,
- 88, nil, nil, nil, 69, 70, 71, 62, 57, 81,
- 93, 94, 63, 64, nil, nil, nil, 67, nil, 65,
- 66, 68, 30, 31, 72, 73, nil, nil, nil, nil,
- nil, 29, 28, 27, 101, 100, 102, 103, nil, nil,
- 19, nil, nil, nil, nil, nil, nil, 45, nil, nil,
- 105, 104, 106, 95, 56, 97, 96, 98, nil, 99,
- 107, 108, nil, 91, 92, nil, 42, 43, 41, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 223, nil,
- nil, 229, nil, nil, 58, 59, nil, nil, 60, nil,
- nil, nil, nil, nil, 44, nil, nil, nil, nil, nil,
- nil, nil, nil, 20, nil, nil, nil, nil, 89, 79,
- 82, 83, nil, 84, 86, 85, 87, nil, nil, nil,
- nil, 80, 88, nil, nil, nil, 69, 70, 71, 62,
- 57, 81, 93, 94, 63, 64, nil, nil, nil, 67,
- nil, 65, 66, 68, 30, 31, 72, 73, nil, nil,
- nil, nil, nil, 29, 28, 27, 101, 100, 102, 103,
- nil, nil, 19, nil, nil, nil, nil, nil, nil, 45,
- nil, nil, 105, 104, 106, 95, 56, 97, 96, 98,
- nil, 99, 107, 108, nil, 91, 92, nil, 42, 43,
- 41, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 223, nil, nil, 229, nil, nil, 58, 59, nil, nil,
- 60, nil, nil, nil, nil, nil, 44, nil, nil, nil,
- nil, nil, nil, nil, nil, 20, nil, nil, nil, nil,
- 89, 79, 82, 83, nil, 84, 86, 85, 87, nil,
- nil, nil, nil, 80, 88, nil, nil, nil, 69, 70,
- 71, 62, 57, 81, 93, 94, 63, 64, nil, nil,
- nil, 67, nil, 65, 66, 68, 309, 310, 72, 73,
- nil, nil, nil, nil, nil, 305, 306, 312, 101, 100,
- 102, 103, nil, nil, 230, nil, nil, nil, nil, nil,
- nil, 45, nil, nil, 105, 104, 106, 95, 56, 97,
- 96, 98, nil, 99, 107, 108, nil, 91, 92, nil,
- 42, 43, 41, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 223, nil, nil, 229, nil, nil, 58, 59,
- nil, nil, 60, nil, nil, nil, nil, nil, 44, nil,
- nil, nil, nil, nil, nil, nil, nil, 228, nil, nil,
- nil, nil, 89, 79, 82, 83, nil, 84, 86, 85,
- 87, nil, nil, nil, nil, 80, 88, nil, nil, nil,
- 69, 70, 71, 62, 57, 81, 93, 94, 63, 64,
- nil, nil, nil, 67, nil, 65, 66, 68, 30, 31,
- 72, 73, nil, nil, nil, nil, nil, 29, 28, 27,
- 101, 100, 102, 103, nil, nil, 230, nil, nil, nil,
- nil, nil, nil, 45, nil, nil, 105, 104, 106, 95,
- 56, 97, 96, 98, 284, 99, 107, 108, nil, 91,
- 92, nil, 42, 43, 41, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 223, nil, nil, 229, nil, nil,
- 58, 59, nil, nil, 60, nil, 281, nil, 279, nil,
- 44, nil, nil, 285, nil, nil, nil, nil, nil, 228,
- nil, nil, nil, nil, 89, 282, 82, 83, nil, 84,
- 86, 85, 87, nil, nil, nil, nil, 80, 88, nil,
- nil, nil, 69, 70, 71, 62, 57, 81, 93, 94,
- 63, 64, nil, nil, nil, 67, nil, 65, 66, 68,
- 309, 310, 72, 73, nil, nil, nil, nil, nil, 305,
- 306, 312, 101, 100, 102, 103, nil, nil, 230, nil,
- nil, nil, nil, nil, nil, 45, nil, nil, 105, 104,
- 106, 95, 56, 97, 96, 98, nil, 99, 107, 108,
- nil, 91, 92, nil, 42, 43, 41, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 223, nil, nil, 229,
- nil, nil, 58, 59, nil, nil, 60, nil, nil, nil,
- nil, nil, 44, nil, nil, nil, nil, nil, nil, nil,
- nil, 228, nil, nil, nil, nil, 89, 79, 82, 83,
- nil, 84, 86, 85, 87, nil, nil, nil, nil, 80,
- 88, nil, nil, nil, 69, 70, 71, 62, 57, 81,
- 93, 94, 63, 64, nil, nil, nil, 67, nil, 65,
- 66, 68, 309, 310, 72, 73, nil, nil, nil, nil,
- nil, 305, 306, 312, 101, 100, 102, 103, nil, nil,
- 230, nil, nil, nil, nil, nil, nil, 45, nil, nil,
- 105, 104, 106, 95, 56, 97, 96, 98, nil, 99,
- 107, 108, nil, 91, 92, nil, 42, 43, 41, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 223, nil,
- nil, 229, nil, nil, 58, 59, nil, nil, 60, nil,
- nil, nil, nil, nil, 44, nil, nil, nil, nil, nil,
- nil, nil, nil, 228, nil, nil, nil, nil, 89, 79,
- 82, 83, nil, 84, 86, 85, 87, nil, nil, nil,
- nil, 80, 88, nil, nil, nil, 69, 70, 71, 62,
- 57, 81, 93, 94, 63, 64, nil, nil, nil, 67,
- nil, 65, 66, 68, 309, 310, 72, 73, nil, nil,
- nil, nil, nil, 305, 306, 312, 101, 100, 102, 103,
- nil, nil, 230, nil, nil, nil, nil, nil, nil, 45,
- nil, nil, 105, 104, 106, 95, 56, 97, 96, 98,
- nil, 99, 107, 108, nil, 91, 92, nil, 42, 43,
- 41, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 223, nil, nil, 229, nil, nil, 58, 59, nil, nil,
- 60, nil, nil, nil, nil, nil, 44, nil, nil, nil,
- nil, nil, nil, nil, nil, 228, nil, nil, nil, nil,
- 89, 79, 82, 83, nil, 84, 86, 85, 87, nil,
- nil, nil, nil, 80, 88, nil, nil, nil, 69, 70,
- 71, 62, 57, 81, 93, 94, 63, 64, nil, nil,
- nil, 67, nil, 65, 66, 68, 309, 310, 72, 73,
- nil, nil, nil, nil, nil, 305, 306, 312, 101, 100,
- 102, 103, nil, nil, 230, nil, nil, nil, nil, nil,
- nil, 45, nil, nil, 105, 104, 106, 95, 56, 97,
- 96, 98, nil, 99, 107, 108, nil, 91, 92, nil,
- 42, 43, 41, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 223, nil, nil, 229, nil, nil, 58, 59,
- nil, nil, 60, nil, nil, nil, nil, nil, 44, nil,
- nil, nil, nil, nil, nil, nil, nil, 228, nil, nil,
- nil, nil, 89, 79, 82, 83, nil, 84, 86, 85,
- 87, nil, nil, nil, nil, 80, 88, nil, nil, nil,
- 69, 70, 71, 62, 57, 81, 93, 94, 63, 64,
- nil, nil, nil, 67, nil, 65, 66, 68, 309, 310,
- 72, 73, nil, nil, nil, nil, nil, 305, 306, 312,
- 101, 100, 102, 103, nil, nil, 230, nil, nil, nil,
- nil, nil, nil, 45, nil, nil, 105, 104, 106, 95,
- 56, 97, 96, 98, 284, 99, 107, 108, nil, 91,
- 92, nil, 42, 43, 41, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 223, nil, nil, 229, nil, nil,
- 58, 59, nil, nil, 60, nil, 659, nil, 279, nil,
- 44, nil, nil, 285, nil, nil, nil, nil, nil, 228,
- nil, nil, nil, nil, 89, 282, 82, 83, nil, 84,
- 86, 85, 87, nil, nil, nil, nil, 80, 88, nil,
- nil, nil, 69, 70, 71, 62, 57, 81, 93, 94,
- 63, 64, nil, nil, nil, 67, nil, 65, 66, 68,
- 309, 310, 72, 73, nil, nil, nil, nil, nil, 305,
- 306, 312, 101, 100, 102, 103, nil, nil, 230, nil,
- nil, nil, nil, nil, nil, 45, nil, nil, 105, 104,
- 106, 95, 56, 97, 96, 98, 284, 99, 107, 108,
- nil, 91, 92, nil, 42, 43, 41, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 223, nil, nil, 229,
- nil, nil, 58, 59, nil, nil, 60, nil, nil, nil,
- 279, nil, 44, nil, nil, 285, nil, nil, nil, nil,
- nil, 228, nil, nil, nil, nil, 89, 282, 82, 83,
- nil, 84, 86, 85, 87, nil, nil, nil, nil, 80,
- 88, nil, nil, nil, 69, 70, 71, 62, 57, 81,
- 93, 94, 63, 64, nil, nil, nil, 67, nil, 65,
- 66, 68, 309, 310, 72, 73, nil, nil, nil, nil,
- nil, 305, 306, 312, 101, 100, 102, 103, nil, nil,
- 230, nil, nil, nil, nil, nil, nil, 45, nil, nil,
- 105, 104, 106, 95, 56, 97, 96, 98, nil, 99,
- 107, 108, nil, 91, 92, nil, 42, 43, 41, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 223, nil,
- nil, 229, nil, nil, 58, 59, nil, nil, 60, nil,
- nil, nil, nil, nil, 44, nil, nil, nil, nil, nil,
- nil, nil, nil, 228, nil, nil, nil, nil, 89, 79,
- 82, 83, nil, 84, 86, 85, 87, nil, nil, nil,
- nil, 80, 88, nil, nil, nil, nil, nil, nil, 62,
- nil, 81, 93, 94, 69, 70, 71, 9, 57, nil,
- nil, nil, 63, 64, nil, nil, nil, 67, nil, 65,
- 66, 68, 30, 31, 72, 73, nil, nil, nil, nil,
- nil, 29, 28, 27, 101, 100, 102, 103, nil, nil,
- 19, nil, nil, nil, nil, nil, 8, 45, 292, 10,
- 105, 104, 106, 95, 56, 97, 96, 98, nil, 99,
- 107, 108, nil, 91, 92, nil, 42, 43, 41, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 40, nil,
- nil, 33, nil, nil, 58, 59, nil, nil, 60, nil,
- 35, nil, nil, nil, 44, nil, nil, nil, nil, nil,
- nil, nil, nil, 20, nil, nil, nil, nil, 89, 79,
- 82, 83, nil, 84, 86, 85, 87, nil, nil, nil,
- nil, 80, 88, nil, nil, nil, nil, nil, 388, 62,
- nil, 81, 93, 94, 69, 70, 71, nil, 57, nil,
- nil, nil, 63, 64, nil, nil, nil, 67, nil, 65,
- 66, 68, 309, 310, 72, 73, nil, nil, nil, nil,
- nil, 305, 306, 312, 101, 100, 102, 103, nil, nil,
- 230, nil, nil, nil, nil, nil, nil, 307, nil, nil,
- 105, 104, 106, 95, 56, 97, 96, 98, nil, 99,
- 107, 108, nil, 91, 92, nil, nil, nil, 313, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 303, nil,
- nil, 299, nil, nil, 58, 59, nil, nil, 60, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 89, 79,
- 82, 83, nil, 84, 86, 85, 87, nil, nil, nil,
- nil, 80, 88, nil, nil, nil, 69, 70, 71, 62,
- 57, 81, 93, 94, 63, 64, nil, nil, nil, 67,
- nil, 65, 66, 68, 30, 31, 72, 73, nil, nil,
- nil, nil, nil, 29, 28, 27, 101, 100, 102, 103,
- nil, nil, 230, nil, nil, nil, nil, nil, nil, 45,
- nil, nil, 105, 104, 106, 95, 56, 97, 96, 98,
- 284, 99, 107, 108, nil, 91, 92, nil, 42, 43,
- 41, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 223, nil, nil, 229, nil, nil, 58, 59, nil, nil,
- 60, nil, 281, nil, 279, nil, 44, nil, nil, 285,
- nil, nil, nil, nil, nil, 228, nil, nil, nil, nil,
- 89, 282, 82, 83, nil, 84, 86, 85, 87, nil,
- nil, nil, nil, 80, 88, nil, nil, nil, 69, 70,
- 71, 62, 57, 81, 93, 94, 63, 64, nil, nil,
- nil, 67, nil, 65, 66, 68, 309, 310, 72, 73,
- nil, nil, nil, nil, nil, 305, 306, 312, 101, 100,
- 102, 103, nil, nil, 230, nil, nil, nil, nil, nil,
- nil, 307, nil, nil, 105, 104, 106, 95, 56, 97,
- 96, 98, nil, 99, 107, 108, nil, 91, 92, nil,
- nil, nil, 313, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 303, nil, nil, 299, nil, nil, 58, 59,
- nil, nil, 60, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 89, 79, 82, 83, nil, 84, 86, 85,
- 87, nil, nil, nil, nil, 80, 88, nil, nil, nil,
- 69, 70, 71, 62, 57, 81, 93, 94, 63, 64,
- nil, nil, nil, 67, nil, 65, 66, 68, 309, 310,
- 72, 73, nil, nil, nil, nil, nil, 305, 306, 312,
- 101, 100, 102, 103, nil, nil, 230, nil, nil, nil,
- nil, nil, nil, 45, nil, nil, 105, 104, 106, 95,
- 56, 97, 96, 98, nil, 99, 107, 108, nil, 91,
- 92, nil, 42, 43, 41, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 223, nil, nil, 229, nil, nil,
- 58, 59, nil, nil, 60, nil, nil, nil, nil, nil,
- 44, nil, nil, nil, nil, nil, nil, nil, nil, 228,
- nil, nil, nil, nil, 89, 79, 82, 83, nil, 84,
- 86, 85, 87, nil, nil, nil, nil, 80, 88, nil,
- nil, nil, 69, 70, 71, 62, 57, 81, 93, 94,
- 63, 64, nil, nil, nil, 67, nil, 65, 66, 68,
- 309, 310, 72, 73, nil, nil, nil, nil, nil, 305,
- 306, 312, 101, 100, 102, 103, nil, nil, 230, nil,
- nil, nil, nil, nil, nil, 45, nil, nil, 105, 104,
- 106, 95, 56, 97, 96, 98, nil, 99, 107, 108,
- nil, 91, 92, nil, 42, 43, 41, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 223, nil, nil, 229,
- nil, nil, 58, 59, nil, nil, 60, nil, nil, nil,
- nil, nil, 44, nil, nil, nil, nil, nil, nil, nil,
- nil, 228, nil, nil, nil, nil, 89, 79, 82, 83,
- nil, 84, 86, 85, 87, nil, nil, nil, nil, 80,
- 88, nil, nil, nil, 69, 70, 71, 62, 57, 81,
- 93, 94, 63, 64, nil, nil, nil, 67, nil, 65,
- 66, 68, 30, 31, 72, 73, nil, nil, nil, nil,
- nil, 29, 28, 27, 101, 100, 102, 103, nil, nil,
- 19, nil, nil, nil, nil, nil, nil, 45, nil, nil,
- 105, 104, 106, 95, 56, 97, 96, 98, nil, 99,
- 107, 108, nil, 91, 92, nil, 42, 43, 41, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 223, nil,
- nil, 229, nil, nil, 58, 59, nil, nil, 60, nil,
- nil, nil, nil, nil, 44, nil, nil, nil, nil, nil,
- nil, nil, nil, 20, nil, nil, nil, nil, 89, 79,
- 82, 83, nil, 84, 86, 85, 87, nil, nil, nil,
- nil, 80, 88, nil, nil, nil, 69, 70, 71, 62,
- 57, 81, 93, 94, 63, 64, nil, nil, nil, 67,
- nil, 65, 66, 68, 309, 310, 72, 73, nil, nil,
- nil, nil, nil, 305, 306, 312, 101, 100, 102, 103,
- nil, nil, 230, nil, nil, nil, nil, nil, nil, 45,
- nil, nil, 105, 104, 106, 95, 56, 97, 96, 98,
- 284, 99, 107, 108, nil, 91, 92, nil, 42, 43,
- 41, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 223, nil, nil, 229, nil, nil, 58, 59, nil, nil,
- 60, nil, 659, nil, nil, nil, 44, nil, nil, 285,
- nil, nil, nil, nil, nil, 228, nil, nil, nil, nil,
- 89, 282, 82, 83, nil, 84, 86, 85, 87, nil,
- nil, nil, nil, 80, 88, nil, nil, nil, 69, 70,
- 71, 62, 57, 81, 93, 94, 63, 64, nil, nil,
- nil, 67, nil, 65, 66, 68, 309, 310, 72, 73,
- nil, nil, nil, nil, nil, 305, 306, 312, 101, 100,
- 102, 103, nil, nil, 230, nil, nil, nil, nil, nil,
- nil, 45, nil, nil, 105, 104, 106, 95, 56, 97,
- 96, 98, 284, 99, 107, 108, nil, 91, 92, nil,
- 42, 43, 41, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 223, nil, nil, 229, nil, nil, 58, 59,
- nil, nil, 60, nil, nil, nil, nil, nil, 44, nil,
- nil, 285, nil, nil, nil, nil, nil, 228, nil, nil,
- nil, nil, 89, 282, 82, 83, nil, 84, 86, 85,
- 87, nil, nil, nil, nil, 80, 88, nil, nil, nil,
- 69, 70, 71, 62, 57, 81, 93, 94, 63, 64,
- nil, nil, nil, 67, nil, 65, 66, 68, 309, 310,
- 72, 73, nil, nil, nil, nil, nil, 305, 306, 312,
- 101, 100, 102, 103, nil, nil, 230, nil, nil, nil,
- nil, nil, nil, 45, nil, nil, 105, 104, 106, 95,
- 56, 97, 96, 98, nil, 99, 107, 108, nil, 91,
- 92, nil, 42, 43, 41, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 223, nil, nil, 229, nil, nil,
- 58, 59, nil, nil, 60, nil, nil, nil, nil, nil,
- 44, nil, nil, nil, nil, nil, nil, nil, nil, 228,
- nil, nil, nil, nil, 89, 79, 82, 83, nil, 84,
- 86, 85, 87, nil, nil, nil, nil, 80, 88, nil,
- nil, nil, 69, 70, 71, 62, 57, 81, 93, 94,
- 63, 64, nil, nil, nil, 67, nil, 65, 66, 68,
- 309, 310, 72, 73, nil, nil, nil, nil, nil, 305,
- 306, 312, 101, 100, 102, 103, nil, nil, 230, nil,
- nil, nil, nil, nil, nil, 45, nil, nil, 105, 104,
- 106, 95, 56, 97, 96, 98, nil, 99, 107, 108,
- nil, 91, 92, nil, 42, 43, 41, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 223, nil, nil, 229,
- nil, nil, 58, 59, nil, nil, 60, nil, 281, nil,
- nil, nil, 44, nil, nil, nil, nil, nil, nil, nil,
- nil, 228, nil, nil, nil, nil, 89, 79, 82, 83,
- nil, 84, 86, 85, 87, nil, nil, nil, nil, 80,
- 88, nil, nil, nil, 69, 70, 71, 62, 57, 81,
- 93, 94, 63, 64, nil, nil, nil, 67, nil, 65,
- 66, 68, 30, 31, 72, 73, nil, nil, nil, nil,
- nil, 29, 28, 27, 101, 100, 102, 103, nil, nil,
- 230, nil, nil, nil, nil, nil, nil, 45, nil, nil,
- 105, 104, 106, 95, 56, 97, 96, 98, 284, 99,
- 107, 108, nil, 91, 92, nil, 42, 43, 41, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 223, nil,
- nil, 229, nil, nil, 58, 59, nil, nil, 60, nil,
- 281, nil, 279, nil, 44, nil, nil, 285, nil, nil,
- nil, nil, nil, 228, nil, nil, nil, nil, 89, 282,
- 82, 83, nil, 84, 86, 85, 87, nil, nil, nil,
- nil, 80, 88, nil, nil, nil, 69, 70, 71, 62,
- 57, 81, 93, 94, 63, 64, nil, nil, nil, 67,
- nil, 65, 66, 68, 30, 31, 72, 73, nil, nil,
- nil, nil, nil, 29, 28, 27, 101, 100, 102, 103,
- nil, nil, 230, nil, nil, nil, nil, nil, nil, 45,
- nil, nil, 105, 104, 106, 95, 56, 97, 96, 98,
- 284, 99, 107, 108, nil, 91, 92, nil, 42, 43,
- 41, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 223, nil, nil, 229, nil, nil, 58, 59, nil, nil,
- 60, nil, 281, nil, 279, nil, 44, nil, nil, 285,
- nil, nil, nil, nil, nil, 228, nil, nil, nil, nil,
- 89, 282, 82, 83, nil, 84, 86, 85, 87, nil,
- nil, nil, nil, 80, 88, nil, nil, nil, 69, 70,
- 71, 62, 57, 81, 93, 94, 63, 64, nil, nil,
- nil, 67, nil, 65, 66, 68, 309, 310, 72, 73,
- nil, nil, nil, nil, nil, 305, 306, 312, 101, 100,
- 102, 103, nil, nil, 230, nil, nil, nil, nil, nil,
- nil, 45, nil, nil, 105, 104, 106, 95, 56, 97,
- 96, 98, nil, 99, 107, 108, nil, 91, 92, nil,
- 42, 43, 41, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 223, nil, nil, 229, nil, nil, 58, 59,
- nil, nil, 60, nil, 754, nil, nil, nil, 44, nil,
- nil, nil, nil, nil, nil, nil, nil, 228, nil, nil,
- nil, nil, 89, 79, 82, 83, nil, 84, 86, 85,
- 87, nil, nil, nil, nil, 80, 88, nil, nil, nil,
- 69, 70, 71, 62, 57, 81, 93, 94, 63, 64,
- nil, nil, nil, 67, nil, 65, 66, 68, 309, 310,
- 72, 73, nil, nil, nil, nil, nil, 305, 306, 312,
- 101, 100, 102, 103, nil, nil, 230, nil, nil, nil,
- nil, nil, nil, 45, nil, nil, 105, 104, 106, 95,
- 56, 97, 96, 98, nil, 99, 107, 108, nil, 91,
- 92, nil, 42, 43, 41, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 223, nil, nil, 229, nil, nil,
- 58, 59, nil, nil, 60, nil, nil, nil, nil, nil,
- 44, nil, nil, nil, nil, nil, nil, nil, nil, 228,
- nil, nil, nil, nil, 89, 79, 82, 83, nil, 84,
- 86, 85, 87, nil, nil, nil, nil, 80, 88, nil,
- nil, nil, 69, 70, 71, 62, 57, 81, 93, 94,
- 63, 64, nil, nil, nil, 67, nil, 65, 66, 68,
- 309, 310, 72, 73, nil, nil, nil, nil, nil, 305,
- 306, 312, 101, 100, 102, 103, nil, nil, 230, nil,
- nil, nil, nil, nil, nil, 45, nil, nil, 105, 104,
- 106, 95, 56, 97, 96, 98, 284, 99, 107, 108,
- nil, 91, 92, nil, 42, 43, 41, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 223, nil, nil, 229,
- nil, nil, 58, 59, nil, nil, 60, nil, 659, nil,
- 279, nil, 44, nil, nil, 285, nil, nil, nil, nil,
- nil, 228, nil, nil, nil, nil, 89, 282, 82, 83,
- nil, 84, 86, 85, 87, nil, nil, nil, nil, 80,
- 88, nil, nil, nil, 69, 70, 71, 62, 57, 81,
- 93, 94, 63, 64, nil, nil, nil, 67, nil, 65,
- 66, 68, 309, 310, 72, 73, nil, nil, nil, nil,
- nil, 305, 306, 312, 101, 100, 102, 103, nil, nil,
- 230, nil, nil, nil, nil, nil, nil, 45, nil, nil,
- 105, 104, 106, 95, 56, 97, 96, 98, 284, 99,
- 107, 108, nil, 91, 92, nil, 42, 43, 41, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 223, nil,
- nil, 229, nil, nil, 58, 59, nil, nil, 60, nil,
- nil, nil, 279, nil, 44, nil, nil, 285, nil, nil,
- nil, nil, nil, 228, nil, nil, nil, nil, 89, 282,
- 82, 83, nil, 84, 86, 85, 87, nil, nil, nil,
- nil, 80, 88, nil, nil, nil, 69, 70, 71, 62,
- 57, 81, 93, 94, 63, 64, nil, nil, nil, 67,
- nil, 65, 66, 68, 30, 31, 72, 73, nil, nil,
- nil, nil, nil, 29, 28, 27, 101, 100, 102, 103,
- nil, nil, 230, nil, nil, nil, nil, nil, nil, 45,
- nil, nil, 105, 104, 106, 95, 56, 97, 96, 98,
- nil, 99, 107, 108, nil, 91, 92, nil, 42, 43,
- 41, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 223, nil, nil, 229, nil, nil, 58, 59, nil, nil,
- 60, nil, nil, nil, nil, nil, 44, nil, nil, nil,
- nil, nil, nil, nil, nil, 228, nil, nil, nil, nil,
- 89, 79, 82, 83, nil, 84, 86, 85, 87, nil,
- nil, nil, nil, 80, 88, nil, nil, nil, 69, 70,
- 71, 62, 57, 81, 93, 94, 63, 64, nil, nil,
- nil, 67, nil, 65, 66, 68, 30, 31, 72, 73,
- nil, nil, nil, nil, nil, 29, 28, 27, 101, 100,
- 102, 103, nil, nil, 230, nil, nil, nil, nil, nil,
- nil, 45, nil, nil, 105, 104, 106, 95, 56, 97,
- 96, 98, nil, 99, 107, 108, nil, 91, 92, nil,
- 42, 43, 41, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 223, nil, nil, 229, nil, nil, 58, 59,
- nil, nil, 60, nil, nil, nil, nil, nil, 44, nil,
- nil, nil, nil, nil, nil, nil, nil, 228, nil, nil,
- nil, nil, 89, 79, 82, 83, nil, 84, 86, 85,
- 87, nil, nil, nil, nil, 80, 88, nil, nil, nil,
- 69, 70, 71, 62, 57, 81, 93, 94, 63, 64,
- nil, nil, nil, 67, nil, 65, 66, 68, 30, 31,
- 72, 73, nil, nil, nil, nil, nil, 29, 28, 27,
- 101, 100, 102, 103, nil, nil, 230, nil, nil, nil,
- nil, nil, nil, 45, nil, nil, 105, 104, 106, 95,
- 56, 97, 96, 98, nil, 99, 107, 108, nil, 91,
- 92, nil, 42, 43, 41, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 223, nil, nil, 229, nil, nil,
- 58, 59, nil, nil, 60, nil, nil, nil, nil, nil,
- 44, nil, nil, nil, nil, nil, nil, nil, nil, 228,
- nil, nil, nil, nil, 89, 79, 82, 83, nil, 84,
- 86, 85, 87, nil, nil, nil, nil, 80, 88, nil,
- nil, nil, 69, 70, 71, 62, 57, 81, 93, 94,
- 63, 64, nil, nil, nil, 67, nil, 65, 66, 68,
- 30, 31, 72, 73, nil, nil, nil, nil, nil, 29,
- 28, 27, 101, 100, 102, 103, nil, nil, 230, nil,
- nil, nil, nil, nil, nil, 45, nil, nil, 105, 104,
- 106, 95, 56, 97, 96, 98, nil, 99, 107, 108,
- nil, 91, 92, nil, 42, 43, 41, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 223, nil, nil, 229,
- nil, nil, 58, 59, nil, nil, 60, nil, nil, nil,
- nil, nil, 44, nil, nil, nil, nil, nil, nil, nil,
- nil, 228, nil, nil, nil, nil, 89, 79, 82, 83,
- nil, 84, 86, 85, 87, nil, nil, nil, nil, 80,
- 88, nil, nil, nil, 69, 70, 71, 62, 57, 81,
- 93, 94, 63, 64, nil, nil, nil, 67, nil, 65,
- 66, 68, 30, 31, 72, 73, nil, nil, nil, nil,
- nil, 29, 28, 27, 101, 100, 102, 103, nil, nil,
- 230, nil, nil, nil, nil, nil, nil, 45, nil, nil,
- 105, 104, 106, 95, 56, 97, 96, 98, nil, 99,
- 107, 108, nil, 91, 92, nil, 42, 43, 41, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 223, nil,
- nil, 229, nil, nil, 58, 59, nil, nil, 60, nil,
- nil, nil, nil, nil, 44, nil, nil, nil, nil, nil,
- nil, nil, nil, 228, nil, nil, nil, nil, 89, 79,
- 82, 83, nil, 84, 86, 85, 87, nil, nil, nil,
- nil, 80, 88, nil, nil, nil, 69, 70, 71, 62,
- 57, 81, 93, 94, 63, 64, nil, nil, nil, 67,
- nil, 65, 66, 68, 309, 310, 72, 73, nil, nil,
- nil, nil, nil, 305, 306, 312, 101, 100, 102, 103,
- nil, nil, 230, nil, nil, nil, nil, nil, nil, 45,
- nil, nil, 105, 104, 106, 95, 56, 97, 96, 98,
- nil, 99, 107, 108, nil, 91, 92, nil, 42, 43,
- 41, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 223, nil, nil, 229, nil, nil, 58, 59, nil, nil,
- 60, nil, nil, nil, nil, nil, 44, nil, nil, nil,
- nil, nil, nil, nil, nil, 228, nil, nil, nil, nil,
- 89, 79, 82, 83, nil, 84, 86, 85, 87, nil,
- nil, nil, nil, 80, 88, nil, nil, nil, 69, 70,
- 71, 62, 57, 81, 93, 94, 63, 64, nil, nil,
- nil, 67, nil, 65, 66, 68, 309, 310, 72, 73,
- nil, nil, nil, nil, nil, 305, 306, 312, 101, 100,
- 102, 103, nil, nil, 230, nil, nil, nil, nil, nil,
- nil, 45, nil, nil, 105, 104, 106, 95, 56, 97,
- 96, 98, nil, 99, 107, 108, nil, 91, 92, nil,
- 42, 43, 41, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 223, nil, nil, 229, nil, nil, 58, 59,
- nil, nil, 60, nil, nil, nil, nil, nil, 44, nil,
- nil, nil, nil, nil, nil, nil, nil, 228, nil, nil,
- nil, nil, 89, 79, 82, 83, nil, 84, 86, 85,
- 87, nil, nil, nil, nil, 80, 88, nil, nil, nil,
- 69, 70, 71, 62, 57, 81, 93, 94, 63, 64,
- nil, nil, nil, 67, nil, 65, 66, 68, 309, 310,
- 72, 73, nil, nil, nil, nil, nil, 305, 306, 312,
- 101, 100, 102, 103, nil, nil, 230, nil, nil, nil,
- nil, nil, nil, 45, nil, nil, 105, 104, 106, 95,
- 56, 97, 96, 98, nil, 99, 107, 108, nil, 91,
- 92, nil, 42, 43, 41, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 223, nil, nil, 229, nil, nil,
- 58, 59, nil, nil, 60, nil, nil, nil, nil, nil,
- 44, nil, nil, nil, nil, nil, nil, nil, nil, 228,
- nil, nil, nil, nil, 89, 79, 82, 83, nil, 84,
- 86, 85, 87, nil, nil, nil, nil, 80, 88, nil,
- nil, nil, 69, 70, 71, 62, 57, 81, 93, 94,
- 63, 64, nil, nil, nil, 67, nil, 65, 66, 68,
- 309, 310, 72, 73, nil, nil, nil, nil, nil, 305,
- 306, 312, 101, 100, 102, 103, nil, nil, 230, nil,
- nil, nil, nil, nil, nil, 307, nil, nil, 105, 104,
- 106, 95, 56, 97, 96, 98, nil, 99, 107, 108,
- nil, 91, 92, nil, nil, nil, 313, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 303, nil, nil, 299,
- nil, nil, 58, 59, nil, nil, 60, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 89, 79, 82, 83,
- nil, 84, 86, 85, 87, nil, nil, nil, nil, 80,
- 88, nil, nil, nil, 69, 70, 71, 62, 57, 81,
- 93, 94, 63, 64, nil, nil, nil, 67, nil, 65,
- 66, 68, 309, 310, 72, 73, nil, nil, nil, nil,
- nil, 305, 306, 312, 101, 100, 102, 103, nil, nil,
- 230, nil, nil, nil, nil, nil, nil, 307, nil, nil,
- 105, 104, 106, 95, 56, 97, 96, 98, nil, 99,
- 107, 108, nil, 91, 92, nil, nil, nil, 313, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 303, nil,
- nil, 299, nil, nil, 58, 59, nil, nil, 60, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 89, 79,
- 82, 83, nil, 84, 86, 85, 87, nil, nil, nil,
- nil, 80, 88, nil, nil, nil, 69, 70, 71, 62,
- 57, 81, 93, 94, 63, 64, nil, nil, nil, 67,
- nil, 65, 66, 68, 309, 310, 72, 73, nil, nil,
- nil, nil, nil, 305, 306, 312, 101, 100, 102, 103,
- nil, nil, 230, nil, nil, nil, nil, nil, nil, 45,
- nil, nil, 105, 104, 106, 95, 56, 97, 96, 98,
- nil, 99, 107, 108, nil, 91, 92, nil, 42, 43,
- 41, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 223, nil, nil, 229, nil, nil, 58, 59, nil, nil,
- 60, nil, 404, nil, nil, nil, 44, nil, nil, nil,
- nil, nil, nil, nil, nil, 228, nil, nil, nil, nil,
- 89, 79, 82, 83, nil, 84, 86, 85, 87, nil,
- nil, nil, nil, 80, 88, nil, nil, nil, 69, 70,
- 71, 62, 57, 81, 93, 94, 63, 64, nil, nil,
- nil, 67, nil, 65, 66, 68, 309, 310, 72, 73,
- nil, nil, nil, nil, nil, 305, 306, 312, 101, 100,
- 102, 103, nil, nil, 230, nil, nil, nil, nil, nil,
- nil, 45, nil, nil, 105, 104, 106, 95, 56, 97,
- 96, 98, nil, 99, 107, 108, nil, 91, 92, nil,
- 42, 43, 41, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 223, nil, nil, 229, nil, nil, 58, 59,
- nil, nil, 60, nil, nil, nil, nil, nil, 44, nil,
- nil, nil, nil, nil, nil, nil, nil, 228, nil, nil,
- nil, nil, 89, 79, 82, 83, nil, 84, 86, 85,
- 87, nil, nil, nil, nil, 80, 88, nil, nil, nil,
- 69, 70, 71, 62, 57, 81, 93, 94, 63, 64,
- nil, nil, nil, 67, nil, 65, 66, 68, 30, 31,
- 72, 73, nil, nil, nil, nil, nil, 29, 28, 27,
- 101, 100, 102, 103, nil, nil, 19, nil, nil, nil,
- nil, nil, nil, 45, nil, nil, 105, 104, 106, 95,
- 56, 97, 96, 98, nil, 99, 107, 108, nil, 91,
- 92, nil, 42, 43, 41, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 223, nil, nil, 229, nil, nil,
- 58, 59, nil, nil, 60, nil, nil, nil, nil, nil,
- 44, nil, nil, nil, nil, nil, nil, nil, nil, 20,
- nil, nil, nil, nil, 89, 79, 82, 83, nil, 84,
- 86, 85, 87, nil, nil, nil, nil, 80, 88, nil,
- nil, nil, 69, 70, 71, 62, 57, 81, 93, 94,
- 63, 64, nil, nil, nil, 67, nil, 65, 66, 68,
- 30, 31, 72, 73, nil, nil, nil, nil, nil, 29,
- 28, 27, 101, 100, 102, 103, nil, nil, 19, nil,
- nil, nil, nil, nil, nil, 45, nil, nil, 105, 104,
- 106, 95, 56, 97, 96, 98, nil, 99, 107, 108,
- nil, 91, 92, nil, 42, 43, 41, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 223, nil, nil, 229,
- nil, nil, 58, 59, nil, nil, 60, nil, nil, nil,
- nil, nil, 44, nil, nil, nil, nil, nil, nil, nil,
- nil, 20, nil, nil, nil, nil, 89, 79, 82, 83,
- nil, 84, 86, 85, 87, nil, nil, nil, nil, 80,
- 88, nil, nil, nil, 69, 70, 71, 62, 57, 81,
- 93, 94, 63, 64, nil, nil, nil, 67, nil, 65,
- 66, 68, 309, 310, 72, 73, nil, nil, nil, nil,
- nil, 305, 306, 312, 101, 100, 102, 103, nil, nil,
- 230, nil, nil, nil, nil, nil, nil, 45, nil, nil,
- 105, 104, 106, 95, 56, 97, 96, 98, nil, 99,
- 107, 108, nil, 91, 92, nil, 42, 43, 41, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 223, nil,
- nil, 229, nil, nil, 58, 59, nil, nil, 60, nil,
- nil, nil, nil, nil, 44, nil, nil, nil, nil, nil,
- nil, nil, nil, 228, nil, nil, nil, nil, 89, 79,
- 82, 83, nil, 84, 86, 85, 87, nil, nil, nil,
- nil, 80, 88, nil, nil, nil, 69, 70, 71, 62,
- 57, 81, 93, 94, 63, 64, nil, nil, nil, 67,
- nil, 65, 66, 68, 30, 31, 72, 73, nil, nil,
- nil, nil, nil, 29, 28, 27, 101, 100, 102, 103,
- nil, nil, 230, nil, nil, nil, nil, nil, nil, 45,
- nil, nil, 105, 104, 106, 95, 56, 97, 96, 98,
- nil, 99, 107, 108, nil, 91, 92, nil, 42, 43,
- 41, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 223, nil, nil, 229, nil, nil, 58, 59, nil, nil,
- 60, nil, nil, nil, nil, nil, 44, nil, nil, nil,
- nil, nil, nil, nil, nil, 228, nil, nil, nil, nil,
- 89, 79, 82, 83, nil, 84, 86, 85, 87, nil,
- nil, nil, nil, 80, 88, nil, nil, nil, 69, 70,
- 71, 62, 57, 81, 93, 94, 63, 64, nil, nil,
- nil, 67, nil, 65, 66, 68, 309, 310, 72, 73,
- nil, nil, nil, nil, nil, 305, 306, 312, 101, 100,
- 102, 103, nil, nil, 230, nil, nil, nil, nil, nil,
- nil, 45, nil, nil, 105, 104, 106, 95, 56, 97,
- 96, 98, nil, 99, 107, 108, nil, 91, 92, nil,
- 42, 43, 41, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 223, nil, nil, 229, nil, nil, 58, 59,
- nil, nil, 60, nil, nil, nil, nil, nil, 44, nil,
- nil, nil, nil, nil, nil, nil, nil, 228, nil, nil,
- nil, nil, 89, 79, 82, 83, nil, 84, 86, 85,
- 87, nil, nil, nil, nil, 80, 88, nil, nil, nil,
- 69, 70, 71, 62, 57, 81, 93, 94, 63, 64,
- nil, nil, nil, 67, nil, 65, 66, 68, 309, 310,
- 72, 73, nil, nil, nil, nil, nil, 305, 306, 312,
- 101, 100, 102, 103, nil, nil, 230, nil, nil, nil,
- nil, nil, nil, 45, nil, nil, 105, 104, 106, 95,
- 56, 97, 96, 98, nil, 99, 107, 108, nil, 91,
- 92, nil, 42, 43, 41, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 223, nil, nil, 229, nil, nil,
- 58, 59, nil, nil, 60, nil, nil, nil, nil, nil,
- 44, nil, nil, nil, nil, nil, nil, nil, nil, 228,
- nil, nil, nil, nil, 89, 79, 82, 83, nil, 84,
- 86, 85, 87, nil, nil, nil, nil, 80, 88, nil,
- nil, nil, 69, 70, 71, 62, 57, 81, 93, 94,
- 63, 64, nil, nil, nil, 67, nil, 65, 66, 68,
- 309, 310, 72, 73, nil, nil, nil, nil, nil, 305,
- 306, 312, 101, 100, 102, 103, nil, nil, 230, nil,
- nil, nil, nil, nil, nil, 45, nil, nil, 105, 104,
- 106, 95, 56, 97, 96, 98, nil, 99, 107, 108,
- nil, 91, 92, nil, 42, 43, 41, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 223, nil, nil, 229,
- nil, nil, 58, 59, nil, nil, 60, nil, nil, nil,
- nil, nil, 44, nil, nil, nil, nil, nil, nil, nil,
- nil, 228, nil, nil, nil, nil, 89, 79, 82, 83,
- nil, 84, 86, 85, 87, nil, nil, nil, nil, 80,
- 88, nil, nil, nil, 69, 70, 71, 62, 57, 81,
- 93, 94, 63, 64, nil, nil, nil, 67, nil, 65,
- 66, 68, 309, 310, 72, 73, nil, nil, nil, nil,
- nil, 305, 306, 312, 101, 100, 102, 103, nil, nil,
- 230, nil, nil, nil, nil, nil, nil, 45, nil, nil,
- 105, 104, 106, 95, 56, 97, 96, 98, nil, 99,
- 107, 108, nil, 91, 92, nil, 42, 43, 41, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 223, nil,
- nil, 229, nil, nil, 58, 59, nil, nil, 60, nil,
- nil, nil, nil, nil, 44, nil, nil, nil, nil, nil,
- nil, nil, nil, 228, nil, nil, nil, nil, 89, 79,
- 82, 83, nil, 84, 86, 85, 87, nil, nil, nil,
- nil, 80, 88, nil, nil, nil, 69, 70, 71, 62,
- 57, 81, 93, 94, 63, 64, nil, nil, nil, 67,
- nil, 65, 66, 68, 309, 310, 72, 73, nil, nil,
- nil, nil, nil, 305, 306, 312, 101, 100, 102, 103,
- nil, nil, 230, nil, nil, nil, nil, nil, nil, 307,
- nil, nil, 105, 104, 106, 95, 56, 97, 96, 98,
- nil, 99, 107, 108, nil, 91, 92, nil, nil, nil,
- 313, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 876, nil, nil, 229, nil, nil, 58, 59, nil, nil,
- 60, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 89, 79, 82, 83, nil, 84, 86, 85, 87, nil,
- nil, nil, nil, 80, 88, nil, nil, nil, 69, 70,
- 71, 62, 57, 81, 93, 94, 63, 64, nil, nil,
- nil, 67, nil, 65, 66, 68, 30, 31, 72, 73,
- nil, nil, nil, nil, nil, 29, 28, 27, 101, 100,
- 102, 103, nil, nil, 19, nil, nil, nil, nil, nil,
- nil, 45, nil, nil, 105, 104, 106, 95, 56, 97,
- 96, 98, nil, 99, 107, 108, nil, 91, 92, nil,
- 42, 43, 41, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 223, nil, nil, 229, nil, nil, 58, 59,
- nil, nil, 60, nil, nil, nil, nil, nil, 44, nil,
- nil, nil, nil, nil, nil, nil, nil, 20, nil, nil,
- nil, nil, 89, 79, 82, 83, nil, 84, 86, 85,
- 87, nil, nil, nil, nil, 80, 88, nil, nil, nil,
- 69, 70, 71, 62, 57, 81, 93, 94, 63, 64,
- nil, nil, nil, 67, nil, 65, 66, 68, 309, 310,
- 72, 73, nil, nil, nil, nil, nil, 305, 306, 312,
- 101, 100, 102, 103, nil, nil, 230, nil, nil, nil,
- nil, nil, nil, 45, nil, nil, 105, 104, 106, 95,
- 56, 97, 96, 98, nil, 99, 107, 108, nil, 91,
- 92, nil, 42, 43, 41, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 223, nil, nil, 229, nil, nil,
- 58, 59, nil, nil, 60, nil, 659, nil, nil, nil,
- 44, nil, nil, nil, nil, nil, nil, nil, nil, 228,
- nil, nil, nil, nil, 89, 79, 82, 83, nil, 84,
- 86, 85, 87, nil, nil, nil, nil, 80, 88, nil,
- nil, nil, 69, 70, 71, 62, 57, 81, 93, 94,
- 63, 64, nil, nil, nil, 67, nil, 65, 66, 68,
- 309, 310, 72, 73, nil, nil, nil, nil, nil, 305,
- 306, 312, 101, 100, 102, 103, nil, nil, 230, nil,
- nil, nil, nil, nil, nil, 45, nil, nil, 105, 104,
- 106, 95, 56, 97, 96, 98, 284, 99, 107, 108,
- nil, 91, 92, nil, 42, 43, 41, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 223, nil, nil, 229,
- nil, nil, 58, 59, nil, nil, 60, nil, nil, nil,
- 279, nil, 44, nil, nil, 285, nil, nil, nil, nil,
- nil, 228, nil, nil, nil, nil, 89, 282, 82, 83,
- nil, 84, 86, 85, 87, nil, nil, nil, nil, 80,
- 88, nil, nil, nil, 69, 70, 71, 62, 57, 81,
- 93, 94, 63, 64, nil, nil, nil, 67, nil, 65,
- 66, 68, 309, 310, 72, 73, nil, nil, nil, nil,
- nil, 305, 306, 312, 101, 100, 102, 103, nil, nil,
- 230, nil, nil, nil, nil, nil, nil, 45, nil, nil,
- 105, 104, 106, 95, 56, 97, 96, 98, nil, 99,
- 107, 108, nil, 91, 92, nil, 42, 43, 41, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 223, nil,
- nil, 229, nil, nil, 58, 59, nil, nil, 60, nil,
- nil, nil, nil, nil, 44, nil, nil, nil, nil, nil,
- nil, nil, nil, 228, nil, nil, nil, nil, 89, 79,
- 82, 83, nil, 84, 86, 85, 87, nil, nil, nil,
- nil, 80, 88, nil, nil, nil, 69, 70, 71, 62,
- 57, 81, 93, 94, 63, 64, nil, nil, nil, 67,
- nil, 65, 66, 68, 309, 310, 72, 73, nil, nil,
- nil, nil, nil, 305, 306, 312, 101, 100, 102, 103,
- nil, nil, 230, nil, nil, nil, nil, nil, nil, 307,
- nil, nil, 105, 104, 106, 95, 56, 97, 96, 98,
- nil, 99, 107, 108, nil, 91, 92, nil, nil, nil,
- 313, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 876, nil, nil, 229, nil, nil, 58, 59, nil, nil,
- 60, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 89, 79, 82, 83, nil, 84, 86, 85, 87, nil,
- nil, nil, nil, 80, 88, nil, nil, nil, 69, 70,
- 71, 62, 57, 81, 93, 94, 63, 64, nil, nil,
- nil, 67, nil, 65, 66, 68, 309, 310, 72, 73,
- nil, nil, nil, nil, nil, 305, 306, 312, 101, 100,
- 102, 103, nil, nil, 230, nil, nil, nil, nil, nil,
- nil, 307, nil, nil, 105, 104, 106, 95, 56, 97,
- 96, 98, nil, 99, 107, 108, nil, 91, 92, nil,
- nil, nil, 313, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 947, nil, nil, 229, nil, nil, 58, 59,
- nil, nil, 60, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 89, 79, 82, 83, nil, 84, 86, 85,
- 87, nil, nil, nil, nil, 80, 88, nil, nil, nil,
- 69, 70, 71, 62, 57, 81, 93, 94, 63, 64,
- nil, nil, nil, 67, nil, 65, 66, 68, 309, 310,
- 72, 73, nil, nil, nil, nil, nil, 305, 306, 312,
- 101, 100, 102, 103, nil, nil, 230, nil, nil, nil,
- nil, nil, nil, 45, nil, nil, 105, 104, 106, 95,
- 56, 97, 96, 98, nil, 99, 107, 108, nil, 91,
- 92, nil, 42, 43, 41, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 223, nil, nil, 229, nil, nil,
- 58, 59, nil, nil, 60, nil, nil, nil, nil, nil,
- 44, nil, nil, nil, nil, nil, nil, nil, nil, 228,
- nil, nil, nil, nil, 89, 79, 82, 83, nil, 84,
- 86, 85, 87, nil, nil, nil, nil, 80, 88, nil,
- nil, nil, 69, 70, 71, 62, 57, 81, 93, 94,
- 63, 64, nil, nil, nil, 67, nil, 65, 66, 68,
- 30, 31, 72, 73, nil, nil, nil, nil, nil, 29,
- 28, 27, 101, 100, 102, 103, nil, nil, 230, nil,
- nil, nil, nil, nil, nil, 45, nil, nil, 105, 104,
- 106, 95, 56, 97, 96, 98, 284, 99, 107, 108,
- nil, 91, 92, nil, 42, 43, 41, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 223, nil, nil, 229,
- nil, nil, 58, 59, nil, nil, 60, nil, 281, nil,
- 279, nil, 44, nil, nil, 285, nil, nil, nil, nil,
- nil, 228, nil, nil, nil, nil, 89, 282, 82, 83,
- nil, 84, 86, 85, 87, nil, nil, nil, nil, 80,
- 88, nil, nil, nil, nil, -282, nil, 62, nil, 81,
- 93, 94, -282, -282, -282, nil, nil, -282, -282, -282,
- nil, -282, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, -282, -282, -282, nil, nil, nil, nil, nil, nil,
- nil, -282, -282, nil, -282, -282, -282, -282, -282, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, -282, -282, -282, -282, -282, -282, -282, -282,
- -282, -282, -282, -282, -282, -282, nil, nil, -282, -282,
- -282, nil, nil, -282, nil, nil, -282, nil, nil, -282,
- -282, nil, -282, nil, -282, nil, -282, nil, -282, -282,
- nil, -282, -282, -282, -282, -282, nil, -282, nil, -282,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, -282, nil, nil, -282, -282, -282, -282,
- -579, -282, nil, -282, nil, nil, nil, -579, -579, -579,
- nil, nil, -579, -579, -579, nil, -579, nil, nil, nil,
- nil, nil, nil, nil, nil, -579, -579, -579, -579, nil,
- nil, nil, nil, nil, nil, nil, -579, -579, nil, -579,
- -579, -579, -579, -579, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, -579, -579, -579,
- -579, -579, -579, -579, -579, -579, -579, -579, -579, -579,
- -579, nil, nil, -579, -579, -579, nil, nil, -579, nil,
- nil, -579, nil, nil, -579, -579, nil, -579, nil, -579,
- nil, -579, nil, -579, -579, nil, -579, -579, -579, -579,
- -579, nil, -579, -579, -579, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, -579, nil,
- nil, -579, -579, -579, -579, -580, -579, nil, -579, nil,
- nil, nil, -580, -580, -580, nil, nil, -580, -580, -580,
- nil, -580, nil, nil, nil, nil, nil, nil, nil, nil,
- -580, -580, -580, -580, nil, nil, nil, nil, nil, nil,
- nil, -580, -580, nil, -580, -580, -580, -580, -580, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, -580, -580, -580, -580, -580, -580, -580, -580,
- -580, -580, -580, -580, -580, -580, nil, nil, -580, -580,
- -580, nil, nil, -580, nil, nil, -580, nil, nil, -580,
- -580, nil, -580, nil, -580, nil, -580, nil, -580, -580,
- nil, -580, -580, -580, -580, -580, nil, -580, -580, -580,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, -580, nil, nil, -580, -580, -580, -580,
- -411, -580, nil, -580, nil, nil, nil, -411, -411, -411,
- nil, nil, -411, -411, -411, nil, -411, nil, nil, nil,
- nil, nil, nil, nil, nil, -411, -411, -411, nil, nil,
- nil, nil, nil, nil, nil, nil, -411, -411, nil, -411,
- -411, -411, -411, -411, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, -411, -411, -411,
- -411, -411, -411, -411, -411, -411, -411, -411, -411, -411,
- -411, nil, nil, -411, -411, -411, nil, nil, -411, nil,
- 263, -411, nil, nil, -411, -411, nil, -411, nil, -411,
- nil, -411, nil, -411, -411, nil, -411, -411, -411, -411,
- -411, -298, -411, -411, -411, nil, nil, nil, -298, -298,
- -298, nil, nil, -298, -298, -298, nil, -298, -411, nil,
- nil, -411, -411, nil, -411, nil, -411, -298, -298, nil,
- nil, nil, nil, nil, nil, nil, nil, -298, -298, nil,
- -298, -298, -298, -298, -298, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, -298, -298,
- -298, -298, -298, -298, -298, -298, -298, -298, -298, -298,
- -298, -298, nil, nil, -298, -298, -298, nil, nil, -298,
- nil, 272, -298, nil, nil, -298, -298, nil, -298, nil,
- -298, nil, -298, nil, -298, -298, nil, -298, -298, -298,
- -298, -298, nil, -298, -246, -298, nil, nil, nil, nil,
- nil, -246, -246, -246, nil, nil, -246, -246, -246, -298,
- -246, nil, -298, -298, nil, -298, nil, -298, nil, -246,
- -246, -246, nil, nil, nil, nil, nil, nil, nil, nil,
- -246, -246, nil, -246, -246, -246, -246, -246, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, -246, -246, -246, -246, -246, -246, -246, -246, -246,
- -246, -246, -246, -246, -246, nil, nil, -246, -246, -246,
- nil, nil, -246, nil, 263, -246, nil, nil, -246, -246,
- nil, -246, nil, -246, nil, -246, nil, -246, -246, nil,
- -246, -246, -246, -246, -246, nil, -246, -246, -246, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, -246, nil, -246, -246, -246, nil, -246, nil,
- -246, -246, -246, -246, nil, nil, -246, -246, -246, 548,
- -246, 545, 544, 543, 553, 546, nil, nil, nil, -246,
- -246, nil, nil, nil, nil, 556, nil, nil, nil, nil,
- -246, -246, nil, -246, -246, -246, -246, -246, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 551, 548, nil,
- 545, 544, 543, 553, 546, nil, 561, 560, 564, 563,
- nil, nil, nil, 557, 556, 548, nil, 545, 544, 543,
- 553, 546, -246, nil, nil, nil, nil, nil, nil, -246,
- nil, 556, nil, nil, 263, -246, 551, 534, nil, 218,
- nil, nil, nil, nil, nil, 561, 560, 564, 563, nil,
- nil, nil, 557, 551, nil, nil, nil, -246, -246, nil,
- nil, nil, 561, 560, 564, 563, nil, nil, nil, 557,
- nil, nil, -246, nil, nil, -246, nil, nil, nil, nil,
- -246, 173, 184, 174, 197, 170, 190, 180, 179, 200,
- 201, 195, 178, 177, 172, 198, 202, 203, 182, 171,
- 185, 189, 191, 183, 176, nil, nil, nil, 192, 199,
- 194, 193, 186, 196, 181, 169, 188, 187, nil, nil,
- nil, nil, nil, 168, 175, 166, 167, 163, 164, 165,
- 124, 126, 123, nil, 125, nil, nil, nil, nil, nil,
- nil, nil, nil, 157, 158, nil, 154, 136, 137, 138,
- 145, 142, 144, nil, nil, 139, 140, nil, nil, nil,
- 159, 160, 146, 147, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 151, 150, nil,
- 135, 156, 153, 152, 161, 148, 149, 143, 141, 133,
- 155, 134, nil, nil, 162, 89, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 88,
- 173, 184, 174, 197, 170, 190, 180, 179, 200, 201,
- 195, 178, 177, 172, 198, 202, 203, 182, 171, 185,
- 189, 191, 183, 176, nil, nil, nil, 192, 199, 194,
- 193, 186, 196, 181, 169, 188, 187, nil, nil, nil,
- nil, nil, 168, 175, 166, 167, 163, 164, 165, 124,
- 126, nil, nil, 125, nil, nil, nil, nil, nil, nil,
- nil, nil, 157, 158, nil, 154, 136, 137, 138, 145,
- 142, 144, nil, nil, 139, 140, nil, nil, nil, 159,
- 160, 146, 147, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 151, 150, nil, 135,
- 156, 153, 152, 161, 148, 149, 143, 141, 133, 155,
- 134, nil, nil, 162, 89, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 88, 173,
- 184, 174, 197, 170, 190, 180, 179, 200, 201, 195,
- 178, 177, 172, 198, 202, 203, 182, 171, 185, 189,
- 191, 183, 176, nil, nil, nil, 192, 199, 194, 193,
- 186, 196, 181, 169, 188, 187, nil, nil, nil, nil,
- nil, 168, 175, 166, 167, 163, 164, 165, 124, 126,
- nil, nil, 125, nil, nil, nil, nil, nil, nil, nil,
- nil, 157, 158, nil, 154, 136, 137, 138, 145, 142,
- 144, nil, nil, 139, 140, nil, nil, nil, 159, 160,
- 146, 147, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 151, 150, nil, 135, 156,
- 153, 152, 161, 148, 149, 143, 141, 133, 155, 134,
- nil, nil, 162, 89, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 88, 173, 184,
- 174, 197, 170, 190, 180, 179, 200, 201, 195, 178,
- 177, 172, 198, 202, 203, 182, 171, 185, 189, 191,
- 183, 176, nil, nil, nil, 192, 199, 194, 193, 186,
- 196, 181, 169, 188, 187, nil, nil, nil, nil, nil,
- 168, 175, 166, 167, 163, 164, 165, 124, 126, nil,
- nil, 125, nil, nil, nil, nil, nil, nil, nil, nil,
- 157, 158, nil, 154, 136, 137, 138, 145, 142, 144,
- nil, nil, 139, 140, nil, nil, nil, 159, 160, 146,
- 147, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 151, 150, nil, 135, 156, 153,
- 152, 161, 148, 149, 143, 141, 133, 155, 134, nil,
- nil, 162, 89, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 88, 173, 184, 174,
- 197, 170, 190, 180, 179, 200, 201, 195, 178, 177,
- 172, 198, 202, 203, 182, 171, 185, 189, 191, 183,
- 176, nil, nil, nil, 192, 199, 194, 371, 370, 372,
- 369, 169, 188, 187, nil, nil, nil, nil, nil, 168,
- 175, 166, 167, 366, 367, 368, 364, 126, 97, 96,
- 365, nil, 99, nil, nil, nil, nil, nil, nil, 157,
- 158, nil, 154, 136, 137, 138, 145, 142, 144, nil,
- nil, 139, 140, nil, nil, nil, 159, 160, 146, 147,
- nil, nil, nil, nil, nil, 376, nil, nil, nil, nil,
- nil, nil, nil, 151, 150, nil, 135, 156, 153, 152,
- 161, 148, 149, 143, 141, 133, 155, 134, nil, nil,
- 162, 173, 184, 174, 197, 170, 190, 180, 179, 200,
- 201, 195, 178, 177, 172, 198, 202, 203, 182, 171,
- 185, 189, 191, 183, 176, nil, nil, nil, 192, 199,
- 194, 193, 186, 196, 181, 169, 188, 187, nil, nil,
- nil, nil, nil, 168, 175, 166, 167, 163, 164, 165,
- 124, 126, nil, nil, 125, nil, nil, nil, nil, nil,
- nil, nil, nil, 157, 158, nil, 154, 136, 137, 138,
- 145, 142, 144, nil, nil, 139, 140, nil, nil, nil,
- 159, 160, 146, 147, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 151, 150, nil,
- 135, 156, 153, 152, 161, 148, 149, 143, 141, 133,
- 155, 134, 413, 417, 162, nil, 414, nil, nil, nil,
- nil, nil, nil, nil, nil, 157, 158, nil, 154, 136,
- 137, 138, 145, 142, 144, nil, nil, 139, 140, nil,
- nil, nil, 159, 160, 146, 147, nil, nil, nil, nil,
- nil, 263, nil, nil, nil, nil, nil, nil, nil, 151,
- 150, nil, 135, 156, 153, 152, 161, 148, 149, 143,
- 141, 133, 155, 134, 420, 424, 162, nil, 419, nil,
- nil, nil, nil, nil, nil, nil, nil, 157, 158, nil,
- 154, 136, 137, 138, 145, 142, 144, nil, nil, 139,
- 140, nil, nil, nil, 159, 160, 146, 147, nil, nil,
- nil, nil, nil, 263, nil, nil, nil, nil, nil, nil,
- nil, 151, 150, nil, 135, 156, 153, 152, 161, 148,
- 149, 143, 141, 133, 155, 134, 475, 417, 162, nil,
- 476, nil, nil, nil, nil, nil, nil, nil, nil, 157,
- 158, nil, 154, 136, 137, 138, 145, 142, 144, nil,
- nil, 139, 140, nil, nil, nil, 159, 160, 146, 147,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 151, 150, nil, 135, 156, 153, 152,
- 161, 148, 149, 143, 141, 133, 155, 134, 638, 417,
- 162, nil, 639, nil, nil, nil, nil, nil, nil, nil,
- nil, 157, 158, nil, 154, 136, 137, 138, 145, 142,
- 144, nil, nil, 139, 140, nil, nil, nil, 159, 160,
- 146, 147, nil, nil, nil, nil, nil, 263, nil, nil,
- nil, nil, nil, nil, nil, 151, 150, nil, 135, 156,
- 153, 152, 161, 148, 149, 143, 141, 133, 155, 134,
- 640, 424, 162, nil, 641, nil, nil, nil, nil, nil,
- nil, nil, nil, 157, 158, nil, 154, 136, 137, 138,
- 145, 142, 144, nil, nil, 139, 140, nil, nil, nil,
- 159, 160, 146, 147, nil, nil, nil, nil, nil, 263,
- nil, nil, nil, nil, nil, nil, nil, 151, 150, nil,
- 135, 156, 153, 152, 161, 148, 149, 143, 141, 133,
- 155, 134, 670, 417, 162, nil, 671, nil, nil, nil,
- nil, nil, nil, nil, nil, 157, 158, nil, 154, 136,
- 137, 138, 145, 142, 144, nil, nil, 139, 140, nil,
- nil, nil, 159, 160, 146, 147, nil, nil, nil, nil,
- nil, 263, nil, nil, nil, nil, nil, nil, nil, 151,
- 150, nil, 135, 156, 153, 152, 161, 148, 149, 143,
- 141, 133, 155, 134, 673, 424, 162, nil, 674, nil,
- nil, nil, nil, nil, nil, nil, nil, 157, 158, nil,
- 154, 136, 137, 138, 145, 142, 144, nil, nil, 139,
- 140, nil, nil, nil, 159, 160, 146, 147, nil, nil,
- nil, nil, nil, 263, nil, nil, nil, nil, nil, nil,
- nil, 151, 150, nil, 135, 156, 153, 152, 161, 148,
- 149, 143, 141, 133, 155, 134, 638, 417, 162, nil,
- 639, nil, nil, nil, nil, nil, nil, nil, nil, 157,
- 158, nil, 154, 136, 137, 138, 145, 142, 144, nil,
- nil, 139, 140, nil, nil, nil, 159, 160, 146, 147,
- nil, nil, nil, nil, nil, 263, nil, nil, nil, nil,
- nil, nil, nil, 151, 150, nil, 135, 156, 153, 152,
- 161, 148, 149, 143, 141, 133, 155, 134, 640, 424,
- 162, nil, 641, nil, nil, nil, nil, nil, nil, nil,
- nil, 157, 158, nil, 154, 136, 137, 138, 145, 142,
- 144, nil, nil, 139, 140, nil, nil, nil, 159, 160,
- 146, 147, nil, nil, nil, nil, nil, 263, nil, nil,
- nil, nil, nil, nil, nil, 151, 150, nil, 135, 156,
- 153, 152, 161, 148, 149, 143, 141, 133, 155, 134,
- 721, 417, 162, nil, 722, nil, nil, nil, nil, nil,
- nil, nil, nil, 157, 158, nil, 154, 136, 137, 138,
- 145, 142, 144, nil, nil, 139, 140, nil, nil, nil,
- 159, 160, 146, 147, nil, nil, nil, nil, nil, 263,
- nil, nil, nil, nil, nil, nil, nil, 151, 150, nil,
- 135, 156, 153, 152, 161, 148, 149, 143, 141, 133,
- 155, 134, 723, 424, 162, nil, 724, nil, nil, nil,
- nil, nil, nil, nil, nil, 157, 158, nil, 154, 136,
- 137, 138, 145, 142, 144, nil, nil, 139, 140, nil,
- nil, nil, 159, 160, 146, 147, nil, nil, nil, nil,
- nil, 263, nil, nil, nil, nil, nil, nil, nil, 151,
- 150, nil, 135, 156, 153, 152, 161, 148, 149, 143,
- 141, 133, 155, 134, 726, 424, 162, nil, 727, nil,
- nil, nil, nil, nil, nil, nil, nil, 157, 158, nil,
- 154, 136, 137, 138, 145, 142, 144, nil, nil, 139,
- 140, nil, nil, nil, 159, 160, 146, 147, nil, nil,
- nil, nil, nil, 263, nil, nil, nil, nil, nil, nil,
- nil, 151, 150, nil, 135, 156, 153, 152, 161, 148,
- 149, 143, 141, 133, 155, 134, 475, 417, 162, nil,
- 476, nil, nil, nil, nil, nil, nil, nil, nil, 157,
- 158, nil, 154, 136, 137, 138, 145, 142, 144, nil,
- nil, 139, 140, nil, nil, nil, 159, 160, 146, 147,
- nil, nil, nil, nil, nil, 263, nil, nil, nil, nil,
- nil, nil, nil, 151, 150, nil, 135, 156, 153, 152,
- 161, 148, 149, 143, 141, 133, 155, 134, 983, 424,
- 162, nil, 982, nil, nil, nil, nil, nil, nil, nil,
- nil, 157, 158, nil, 154, 136, 137, 138, 145, 142,
- 144, nil, nil, 139, 140, nil, nil, nil, 159, 160,
- 146, 147, nil, nil, nil, nil, nil, 263, nil, nil,
- nil, nil, nil, nil, nil, 151, 150, nil, 135, 156,
- 153, 152, 161, 148, 149, 143, 141, 133, 155, 134,
- 1006, 417, 162, nil, 1007, nil, nil, nil, nil, nil,
- nil, nil, nil, 157, 158, nil, 154, 136, 137, 138,
- 145, 142, 144, nil, nil, 139, 140, nil, nil, nil,
- 159, 160, 146, 147, nil, nil, nil, nil, nil, 263,
- nil, nil, nil, nil, nil, nil, nil, 151, 150, nil,
- 135, 156, 153, 152, 161, 148, 149, 143, 141, 133,
- 155, 134, 1008, 424, 162, nil, 1009, nil, nil, nil,
- nil, nil, nil, nil, nil, 157, 158, nil, 154, 136,
- 137, 138, 145, 142, 144, nil, nil, 139, 140, nil,
- nil, nil, 159, 160, 146, 147, nil, nil, nil, nil,
- nil, 263, nil, nil, nil, nil, nil, nil, nil, 151,
- 150, nil, 135, 156, 153, 152, 161, 148, 149, 143,
- 141, 133, 155, 134, nil, 548, 162, 545, 544, 543,
- 553, 546, nil, 548, nil, 545, 544, 543, 553, 546,
- nil, 556, nil, nil, nil, nil, nil, nil, 548, 556,
- 545, 544, 543, 553, 546, nil, nil, nil, nil, nil,
- nil, nil, nil, 551, 556, nil, nil, nil, nil, nil,
- nil, 551, 561, 560, 564, 563, nil, nil, nil, 557,
- 561, 560, 564, 563, nil, nil, 551, 557, 548, nil,
- 545, 544, 543, 553, 546, 561, 560, 564, 563, nil,
- nil, nil, 557, 548, 556, 545, 544, 543, 553, 546,
- nil, 548, nil, 545, 544, 543, 553, 546, nil, 556,
- nil, nil, nil, nil, nil, nil, 551, 556, 548, nil,
- 545, 544, 543, 553, 546, 561, 560, 564, 563, nil,
- nil, 551, 557, nil, 556, nil, nil, nil, nil, 551,
- 561, 560, 564, 563, nil, nil, nil, 557, 561, 560,
- 564, 563, nil, nil, nil, 557, 551, 548, nil, 545,
- 544, 543, 553, 546, nil, 561, 560, 564, 563, nil,
- nil, nil, 557, 556, 548, nil, 545, 544, 543, 553,
- 546, nil, 548, nil, 545, 544, 543, 553, 546, nil,
- 556, nil, nil, nil, nil, 551, nil, 548, 556, 545,
- 544, 543, 553, 546, nil, nil, 564, 563, nil, nil,
- nil, 557, 551, 556, nil, nil, nil, nil, nil, nil,
- 551, nil, nil, 564, 563, nil, nil, nil, 557, 561,
- 560, 564, 563, nil, nil, 551, 557, 548, nil, 545,
- 544, 543, 553, 546, nil, nil, 564, 563, nil, nil,
- nil, 557, 548, 556, 545, 544, 543, 553, 546, nil,
- 548, nil, 545, 544, 543, 553, 546, 548, 556, 545,
- 544, 543, 553, 546, nil, 551, 556, nil, nil, nil,
- nil, nil, nil, 556, nil, nil, 564, 563, nil, nil,
- 551, 557, nil, nil, nil, nil, nil, nil, 551, nil,
- nil, 564, 563, nil, nil, 551, 557, nil, nil, 564,
- 563, nil, nil, nil, 557, nil, 564, 563, nil, nil,
- nil, 557 ]
-
-racc_action_check = [
- 95, 345, 61, 437, 437, 346, 349, 95, 95, 95,
- 221, 338, 95, 95, 95, 383, 95, 355, 19, 384,
- 58, 355, 594, 594, 95, 222, 95, 95, 95, 473,
- 650, 26, 17, 17, 578, 359, 95, 95, 339, 95,
- 95, 95, 95, 95, 719, 885, 15, 1, 908, 687,
- 721, 7, 1006, 665, 1007, 1020, 680, 680, 308, 19,
- 58, 913, 665, 913, 473, 722, 221, 95, 95, 95,
- 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
- 95, 222, 383, 95, 95, 95, 384, 95, 95, 570,
- 61, 95, 10, 15, 95, 95, 26, 95, 437, 95,
- 12, 95, 15, 95, 95, 844, 95, 95, 95, 95,
- 95, 345, 95, 98, 95, 346, 349, 594, 650, 26,
- 98, 98, 98, 308, 1008, 98, 98, 98, 95, 98,
- 338, 95, 95, 95, 95, 338, 95, 98, 95, 98,
- 98, 98, 359, 95, 578, 571, 308, 723, 845, 98,
- 98, 680, 98, 98, 98, 98, 98, 339, 13, 687,
- 721, 670, 339, 719, 885, 359, 719, 908, 719, 885,
- 359, 1006, 908, 1007, 1020, 722, 1006, 16, 1007, 1020,
- 98, 98, 98, 98, 98, 98, 98, 98, 98, 98,
- 98, 98, 98, 98, 570, 22, 98, 98, 98, 570,
- 98, 98, 1008, 671, 98, 37, 724, 98, 98, 40,
- 98, 605, 98, 723, 98, 844, 98, 98, 224, 98,
- 98, 98, 98, 98, 419, 98, 45, 98, 670, 590,
- 590, 419, 419, 419, 481, 24, 328, 419, 419, 328,
- 419, 98, 24, 1008, 98, 98, 98, 98, 1008, 98,
- 571, 98, 353, 845, 3, 571, 98, 723, 845, 3,
- 419, 419, 109, 419, 419, 419, 419, 419, 670, 481,
- 671, 670, 724, 123, 224, 204, 605, 605, 123, 123,
- 670, 704, 607, 704, 704, 704, 605, 704, 223, 41,
- 41, 419, 419, 419, 419, 419, 419, 419, 419, 419,
- 419, 419, 419, 419, 419, 353, 354, 419, 419, 419,
- 671, 419, 353, 671, 38, 419, 724, 353, 419, 313,
- 313, 353, 671, 419, 590, 419, 443, 419, 419, 590,
- 419, 419, 419, 419, 419, 378, 419, 420, 419, 225,
- 353, 39, 364, 226, 420, 420, 420, 607, 607, 364,
- 420, 420, 419, 420, 482, 419, 419, 607, 419, 354,
- 419, 38, 420, 230, 704, 673, 354, 419, 41, 41,
- 38, 354, 262, 420, 420, 354, 420, 420, 420, 420,
- 420, 904, 443, 904, 904, 904, 317, 904, 39, 482,
- 329, 651, 492, 329, 354, 379, 276, 39, 313, 313,
- 378, 378, 378, 801, 420, 420, 420, 420, 420, 420,
- 420, 420, 420, 420, 420, 420, 420, 420, 673, 413,
- 420, 420, 420, 380, 420, 673, 651, 288, 420, 414,
- 673, 420, 288, 317, 673, 381, 420, 638, 420, 726,
- 420, 420, 317, 420, 420, 420, 420, 420, 277, 420,
- 420, 420, 382, 673, 280, 385, 801, 492, 492, 492,
- 379, 379, 379, 801, 904, 420, 413, 621, 420, 420,
- 640, 420, 801, 420, 492, 413, 414, 640, 640, 640,
- 420, 292, 640, 640, 640, 414, 640, 365, 380, 380,
- 380, 801, 726, 638, 365, 640, 640, 640, 640, 726,
- 381, 381, 381, 639, 726, 293, 640, 640, 726, 640,
- 640, 640, 640, 640, 621, 295, 774, 382, 382, 382,
- 385, 385, 385, 621, 337, 337, 366, 726, 551, 367,
- 551, 551, 551, 366, 551, 296, 367, 640, 640, 640,
- 640, 640, 640, 640, 640, 640, 640, 640, 640, 640,
- 640, 689, 297, 640, 640, 640, 368, 640, 640, 639,
- 303, 640, 689, 368, 640, 640, 551, 640, 306, 640,
- 307, 640, 774, 640, 640, 551, 640, 640, 640, 640,
- 640, 862, 640, 640, 640, 332, 369, 77, 332, 342,
- 370, 312, 862, 369, 342, 689, 689, 370, 640, 77,
- 689, 640, 640, 640, 640, 449, 640, 641, 640, 77,
- 371, 14, 314, 640, 641, 641, 641, 371, 14, 641,
- 641, 641, 46, 641, 220, 862, 862, 14, 318, 46,
- 862, 220, 372, 641, 641, 641, 321, 449, 46, 372,
- 220, 449, 449, 641, 641, 374, 641, 641, 641, 641,
- 641, 833, 374, 833, 833, 833, 300, 833, 701, 326,
- 701, 701, 701, 300, 701, 831, 330, 831, 831, 831,
- 686, 831, 300, 686, 641, 641, 641, 641, 641, 641,
- 641, 641, 641, 641, 641, 641, 641, 641, 468, 833,
- 641, 641, 641, 301, 641, 641, 701, 469, 641, 331,
- 301, 641, 641, 831, 641, 701, 641, 333, 641, 301,
- 641, 641, 831, 641, 641, 641, 641, 641, 589, 641,
- 468, 641, 343, 589, 468, 468, 450, 468, 468, 469,
- 523, 523, 344, 469, 469, 641, 469, 469, 641, 641,
- 641, 641, 848, 641, 853, 641, 348, 848, 350, 853,
- 641, 0, 0, 0, 0, 0, 0, 394, 450, 302,
- 0, 0, 450, 450, 400, 0, 302, 0, 0, 0,
- 0, 0, 0, 0, 934, 302, 403, 934, 405, 0,
- 0, 0, 0, 0, 0, 0, 598, 598, 0, 409,
- 598, 598, 598, 432, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 411, 0, 0, 0,
- 412, 0, 0, 421, 0, 0, 0, 432, 432, 432,
- 432, 432, 432, 432, 432, 432, 432, 432, 304, 432,
- 432, 319, 429, 432, 432, 304, 0, 439, 319, 0,
- 692, 692, 0, 0, 304, 451, 0, 319, 0, 432,
- 452, 432, 0, 432, 432, 453, 432, 432, 432, 432,
- 432, 0, 432, 710, 710, 454, 0, 0, 0, 0,
- 347, 0, 0, 0, 0, 996, 996, 347, 479, 0,
- 0, 483, 432, 499, 432, 500, 347, 0, 503, 0,
- 0, 0, 33, 33, 33, 33, 33, 33, 505, 510,
- 357, 33, 33, 513, 521, 522, 33, 357, 33, 33,
- 33, 33, 33, 33, 33, 524, 357, 536, 537, 539,
- 33, 33, 33, 33, 33, 33, 33, 540, 541, 33,
- 550, 558, 562, 565, 408, 33, 33, 33, 33, 33,
- 33, 33, 33, 33, 33, 33, 33, 567, 33, 33,
- 33, 572, 33, 33, 573, 33, 33, 33, 408, 408,
- 408, 408, 408, 408, 408, 408, 408, 408, 408, 509,
- 408, 408, 581, 592, 408, 408, 509, 33, 602, 581,
- 33, 610, 612, 33, 33, 509, 618, 33, 581, 33,
- 408, 622, 408, 33, 408, 408, 627, 408, 408, 408,
- 408, 408, 33, 408, 632, 642, 649, 33, 33, 33,
- 33, 875, 33, 33, 33, 33, 656, 658, 875, 664,
- 33, 33, 667, 408, 669, 672, 675, 875, 33, 676,
- 33, 33, 33, 121, 121, 121, 121, 121, 121, 679,
- 681, 938, 121, 121, 684, 688, 703, 121, 938, 121,
- 121, 121, 121, 121, 121, 121, 705, 938, 712, 717,
- 720, 121, 121, 121, 121, 121, 121, 121, 729, 734,
- 121, 753, 758, 775, 776, 643, 121, 121, 121, 121,
- 121, 121, 121, 121, 121, 121, 121, 121, 777, 121,
- 121, 121, 779, 121, 121, 780, 121, 121, 121, 643,
- 643, 643, 643, 643, 643, 643, 643, 643, 643, 643,
- 674, 643, 643, 944, 781, 643, 643, 674, 121, 783,
- 944, 121, 674, 784, 121, 121, 674, 785, 121, 944,
- 121, 643, 786, 643, 121, 643, 643, 790, 643, 643,
- 643, 643, 643, 121, 643, 794, 795, 800, 121, 121,
- 121, 121, 945, 121, 121, 121, 121, 804, 807, 945,
- 808, 121, 121, 811, 643, 816, 817, 821, 945, 121,
- 822, 121, 121, 121, 206, 206, 206, 206, 206, 206,
- 824, 825, 946, 206, 206, 827, 830, 832, 206, 946,
- 206, 206, 206, 206, 206, 206, 206, 835, 946, 838,
- 847, 851, 206, 206, 206, 206, 206, 206, 206, 852,
- 873, 206, 873, 873, 873, 855, 873, 206, 206, 206,
- 206, 206, 206, 206, 206, 206, 206, 206, 206, 856,
- 206, 206, 206, 872, 206, 206, 876, 206, 206, 206,
- 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,
- 21, 727, 21, 21, 948, 878, 21, 21, 727, 206,
- 889, 948, 206, 727, 890, 206, 206, 727, 906, 206,
- 948, 206, 21, 910, 21, 206, 21, 21, 911, 21,
- 21, 21, 21, 21, 206, 21, 917, 921, 924, 206,
- 206, 206, 206, 988, 206, 206, 206, 206, 927, 928,
- 988, 929, 206, 206, 930, 21, 932, 947, 952, 988,
- 206, 953, 206, 206, 206, 229, 229, 229, 229, 229,
- 229, 954, 955, 956, 229, 229, 958, 982, 983, 229,
- 984, 229, 229, 229, 229, 229, 229, 229, 6, 6,
- 6, 6, 6, 229, 229, 229, 229, 229, 229, 229,
- 995, 981, 229, 981, 981, 981, 997, 981, 229, 229,
- 229, 229, 229, 229, 229, 229, 229, 229, 229, 229,
- 998, 229, 229, 229, 999, 229, 229, 1000, 229, 229,
- 229, 274, 274, 274, 274, 274, 274, 274, 274, 274,
- 274, 274, 1009, 274, 274, 1001, 1002, 274, 274, 1009,
- 229, 1005, 1010, 229, 1009, 1011, 229, 229, 1009, 1022,
- 229, nil, 229, 274, nil, 274, 229, 274, 274, nil,
- 274, 274, 274, 274, 274, 229, 274, nil, nil, nil,
- 229, 229, 229, 229, nil, 229, 229, 229, 229, nil,
- nil, nil, nil, 229, 229, nil, 274, nil, nil, nil,
- nil, 229, nil, 229, 229, 229, 294, 294, 294, 294,
- 294, 294, nil, nil, nil, 294, 294, nil, nil, nil,
- 294, nil, 294, 294, 294, 294, 294, 294, 294, 291,
- 291, 291, 291, 291, 294, 294, 294, 294, 294, 294,
- 294, nil, nil, 294, 497, 497, 497, 497, 497, 294,
- 294, 294, 294, 294, 294, 294, 294, 294, 294, 294,
- 294, nil, 294, 294, 294, nil, 294, 294, nil, 294,
- 294, 294, 427, 427, 427, 427, 427, 427, 427, 427,
- 427, 427, 427, nil, 427, 427, nil, nil, 427, 427,
- nil, 294, nil, nil, 294, nil, nil, 294, 294, nil,
- nil, 294, nil, 294, 427, nil, 427, 294, 427, 427,
- nil, 427, 427, 427, 427, 427, 294, 427, nil, nil,
- nil, 294, 294, 294, 294, nil, 294, 294, 294, 294,
- nil, nil, nil, nil, 294, 294, nil, 427, nil, nil,
- nil, nil, 294, nil, 294, 294, 294, 299, 299, 299,
- 299, 299, 299, nil, nil, nil, 299, 299, nil, nil,
- nil, 299, nil, 299, 299, 299, 299, 299, 299, 299,
- nil, nil, nil, nil, nil, 299, 299, 299, 299, 299,
- 299, 299, nil, nil, 299, nil, nil, nil, nil, nil,
- 299, 299, 299, 299, 299, 299, 299, 299, 299, 299,
- 299, 299, nil, 299, 299, 299, nil, 299, 299, nil,
- 299, 299, 299, 519, 519, 519, 519, 519, 519, 519,
- 519, 519, 519, 519, nil, 519, 519, nil, nil, 519,
- 519, nil, 299, nil, nil, 299, nil, nil, 299, 299,
- nil, nil, 299, nil, 299, 519, nil, 519, 299, 519,
- 519, nil, 519, 519, 519, 519, 519, 299, 519, nil,
- nil, nil, 299, 299, 299, 299, nil, 299, 299, 299,
- 299, nil, nil, nil, nil, 299, 299, nil, 519, nil,
- nil, nil, nil, 299, nil, 299, 299, 299, 324, 324,
- 324, 324, 324, 324, nil, nil, nil, 324, 324, nil,
- nil, nil, 324, nil, 324, 324, 324, 324, 324, 324,
- 324, nil, nil, nil, nil, nil, 324, 324, 324, 324,
- 324, 324, 324, nil, nil, 324, nil, nil, nil, nil,
- nil, 324, 324, 324, 324, 324, 324, 324, 324, 324,
- 324, 324, 324, nil, 324, 324, 324, nil, 324, 324,
- nil, 324, 324, 324, 644, 644, 644, 644, 644, 644,
- 644, 644, 644, 644, 644, nil, 644, 644, nil, nil,
- 644, 644, nil, 324, nil, nil, 324, nil, nil, 324,
- 324, nil, nil, 324, nil, 324, 644, nil, 644, 324,
- 644, 644, nil, 644, 644, 644, 644, 644, 324, 644,
- nil, nil, nil, 324, 324, 324, 324, nil, 324, 324,
- 324, 324, nil, nil, nil, nil, 324, 324, 644, 644,
- nil, nil, nil, nil, 324, nil, 324, 324, 324, 498,
- 498, 498, 498, 498, 498, nil, nil, nil, 498, 498,
- nil, nil, nil, 498, nil, 498, 498, 498, 498, 498,
- 498, 498, nil, nil, nil, nil, nil, 498, 498, 498,
- 498, 498, 498, 498, nil, nil, 498, nil, nil, nil,
- nil, nil, 498, 498, 498, 498, 498, 498, 498, 498,
- 498, 498, 498, 498, nil, 498, 498, 498, nil, 498,
- 498, nil, 498, 498, 498, 678, 678, 678, 678, 678,
- 678, 678, 678, 678, 678, 678, nil, 678, 678, nil,
- nil, 678, 678, nil, 498, nil, nil, 498, nil, nil,
- 498, 498, nil, nil, 498, nil, 498, 678, nil, 678,
- 498, 678, 678, nil, 678, 678, 678, 678, 678, 498,
- 678, nil, nil, nil, 498, 498, 498, 498, nil, 498,
- 498, 498, 498, nil, nil, nil, nil, 498, 498, nil,
- 678, nil, nil, nil, nil, 498, nil, 498, 498, 498,
- 566, 566, 566, 566, 566, 566, nil, nil, nil, 566,
- 566, nil, nil, nil, 566, nil, 566, 566, 566, 566,
- 566, 566, 566, nil, nil, nil, nil, nil, 566, 566,
- 566, 566, 566, 566, 566, nil, nil, 566, nil, nil,
- nil, nil, nil, 566, 566, 566, 566, 566, 566, 566,
- 566, 566, 566, 566, 566, nil, 566, 566, 566, nil,
- 566, 566, nil, 566, 566, 566, 755, 755, 755, 755,
- 755, 755, 755, 755, 755, 755, 755, nil, 755, 755,
- nil, nil, 755, 755, nil, 566, nil, nil, 566, nil,
- nil, 566, 566, nil, nil, 566, nil, 566, 755, nil,
- 755, 566, 755, 755, nil, 755, 755, 755, 755, 755,
- 566, 755, nil, nil, nil, 566, 566, 566, 566, nil,
- 566, 566, 566, 566, nil, nil, nil, nil, 566, 566,
- nil, 755, nil, nil, nil, nil, 566, nil, 566, 566,
- 566, 569, 569, 569, 569, 569, 569, nil, nil, nil,
- 569, 569, nil, nil, nil, 569, nil, 569, 569, 569,
- 569, 569, 569, 569, nil, nil, nil, nil, nil, 569,
- 569, 569, 569, 569, 569, 569, nil, nil, 569, nil,
- nil, nil, nil, nil, 569, 569, 569, 569, 569, 569,
- 569, 569, 569, 569, 569, 569, nil, 569, 569, 569,
- nil, 569, 569, nil, 569, 569, 569, 760, 760, 760,
- 760, 760, 760, 760, 760, 760, 760, 760, nil, 760,
- 760, nil, nil, 760, 760, nil, 569, nil, nil, 569,
- nil, nil, 569, 569, nil, nil, 569, nil, 569, 760,
- nil, 760, 569, 760, 760, nil, 760, 760, 760, 760,
- 760, 569, 760, nil, nil, nil, 569, 569, 569, 569,
- nil, 569, 569, 569, 569, nil, nil, nil, nil, 569,
- 569, nil, 760, nil, nil, nil, nil, 569, nil, 569,
- 569, 569, 591, 591, 591, 591, 591, 591, nil, nil,
- nil, 591, 591, nil, nil, nil, 591, nil, 591, 591,
- 591, 591, 591, 591, 591, nil, nil, nil, nil, nil,
- 591, 591, 591, 591, 591, 591, 591, nil, nil, 591,
- nil, nil, nil, nil, nil, 591, 591, 591, 591, 591,
- 591, 591, 591, 591, 591, 591, 591, nil, 591, 591,
- 591, nil, 591, 591, nil, 591, 591, 591, 762, 762,
- 762, 762, 762, 762, 762, 762, 762, 762, 762, nil,
- 762, 762, nil, nil, 762, 762, nil, 591, nil, nil,
- 591, nil, nil, 591, 591, nil, nil, 591, nil, 591,
- 762, nil, 762, 591, 762, 762, nil, 762, 762, 762,
- 762, 762, 591, 762, nil, nil, nil, 591, 591, 591,
- 591, nil, 591, 591, 591, 591, nil, nil, nil, nil,
- 591, 591, nil, 762, nil, nil, nil, nil, 591, nil,
- 591, 591, 591, 648, 648, 648, 648, 648, 648, nil,
- nil, nil, 648, 648, nil, nil, nil, 648, nil, 648,
- 648, 648, 648, 648, 648, 648, nil, nil, nil, nil,
- nil, 648, 648, 648, 648, 648, 648, 648, nil, nil,
- 648, nil, nil, nil, nil, nil, 648, 648, 648, 648,
- 648, 648, 648, 648, 648, 648, 648, 648, nil, 648,
- 648, 648, nil, 648, 648, nil, 648, 648, 648, 765,
- 765, 765, 765, 765, 765, 765, 765, 765, 765, 765,
- nil, 765, 765, nil, nil, 765, 765, nil, 648, nil,
- nil, 648, nil, nil, 648, 648, nil, nil, 648, nil,
- 648, 765, nil, 765, 648, 765, 765, nil, 765, 765,
- 765, 765, 765, 648, 765, nil, nil, nil, 648, 648,
- 648, 648, nil, 648, 648, 648, 648, nil, nil, nil,
- nil, 648, 648, nil, 765, nil, nil, nil, nil, 648,
- nil, 648, 648, 648, 653, 653, 653, 653, 653, 653,
- nil, nil, nil, 653, 653, nil, nil, nil, 653, nil,
- 653, 653, 653, 653, 653, 653, 653, nil, nil, nil,
- nil, nil, 653, 653, 653, 653, 653, 653, 653, nil,
- nil, 653, nil, nil, nil, nil, nil, 653, 653, 653,
- 653, 653, 653, 653, 653, 653, 653, 653, 653, nil,
- 653, 653, 653, nil, 653, 653, nil, 653, 653, 653,
- 767, 767, 767, 767, 767, 767, 767, 767, 767, 767,
- 767, nil, 767, 767, nil, nil, 767, 767, nil, 653,
- nil, nil, 653, nil, nil, 653, 653, nil, nil, 653,
- nil, 653, 767, nil, 767, 653, 767, 767, nil, 767,
- 767, 767, 767, 767, 653, 767, nil, nil, nil, 653,
- 653, 653, 653, nil, 653, 653, 653, 653, nil, nil,
- nil, nil, 653, 653, nil, 767, nil, nil, nil, nil,
- 653, nil, 653, 653, 653, 654, 654, 654, 654, 654,
- 654, nil, nil, nil, 654, 654, nil, nil, nil, 654,
- nil, 654, 654, 654, 654, 654, 654, 654, nil, nil,
- nil, nil, nil, 654, 654, 654, 654, 654, 654, 654,
- nil, nil, 654, nil, nil, nil, nil, nil, 654, 654,
- 654, 654, 654, 654, 654, 654, 654, 654, 654, 654,
- nil, 654, 654, 654, nil, 654, 654, nil, 654, 654,
- 654, 769, 769, 769, 769, 769, 769, 769, 769, 769,
- 769, 769, nil, 769, 769, nil, nil, 769, 769, nil,
- 654, nil, nil, 654, nil, nil, 654, 654, nil, nil,
- 654, nil, 654, 769, nil, 769, 654, 769, 769, nil,
- 769, 769, 769, 769, 769, 654, 769, nil, nil, nil,
- 654, 654, 654, 654, nil, 654, 654, 654, 654, nil,
- nil, nil, nil, 654, 654, nil, 769, nil, nil, nil,
- nil, 654, nil, 654, 654, 654, 730, 730, 730, 730,
- 730, 730, nil, nil, nil, 730, 730, nil, nil, nil,
- 730, nil, 730, 730, 730, 730, 730, 730, 730, nil,
- nil, nil, nil, nil, 730, 730, 730, 730, 730, 730,
- 730, nil, nil, 730, nil, nil, nil, nil, nil, 730,
- 730, 730, 730, 730, 730, 730, 730, 730, 730, 730,
- 730, nil, 730, 730, 730, nil, 730, 730, nil, 730,
- 730, 730, 858, 858, 858, 858, 858, 858, 858, 858,
- 858, 858, 858, nil, 858, 858, nil, nil, 858, 858,
- nil, 730, nil, nil, 730, nil, nil, 730, 730, nil,
- nil, 730, nil, 730, 858, nil, 858, 730, 858, 858,
- nil, 858, 858, 858, 858, 858, 730, 858, nil, nil,
- nil, 730, 730, 730, 730, nil, 730, 730, 730, 730,
- nil, nil, nil, nil, 730, 730, nil, 858, nil, nil,
- nil, nil, 730, nil, 730, 730, 730, 735, 735, 735,
- 735, 735, 735, nil, nil, nil, 735, 735, nil, nil,
- nil, 735, nil, 735, 735, 735, 735, 735, 735, 735,
- nil, nil, nil, nil, nil, 735, 735, 735, 735, 735,
- 735, 735, nil, nil, 735, nil, nil, nil, nil, nil,
- 735, 735, 735, 735, 735, 735, 735, 735, 735, 735,
- 735, 735, nil, 735, 735, 735, nil, 735, 735, nil,
- 735, 735, 735, 969, 969, 969, 969, 969, 969, 969,
- 969, 969, 969, 969, nil, 969, 969, nil, nil, 969,
- 969, nil, 735, nil, nil, 735, nil, nil, 735, 735,
- nil, nil, 735, nil, 735, 969, nil, 969, 735, 969,
- 969, nil, 969, 969, 969, 969, 969, 735, 969, nil,
- nil, nil, 735, 735, 735, 735, nil, 735, 735, 735,
- 735, nil, nil, nil, nil, 735, 735, nil, 969, nil,
- nil, nil, nil, 735, nil, 735, 735, 735, 745, 745,
- 745, 745, 745, 745, nil, nil, nil, 745, 745, nil,
- nil, nil, 745, nil, 745, 745, 745, 745, 745, 745,
- 745, nil, nil, nil, nil, nil, 745, 745, 745, 745,
- 745, 745, 745, nil, nil, 745, nil, nil, nil, nil,
- nil, 745, 745, 745, 745, 745, 745, 745, 745, 745,
- 745, 745, 745, nil, 745, 745, 745, nil, 745, 745,
- nil, 745, 745, 745, 447, 447, 447, 447, 447, 447,
- 447, 447, 447, 447, 447, nil, 447, 447, nil, nil,
- 447, 447, nil, 745, nil, nil, 745, nil, nil, 745,
- 745, nil, nil, 745, nil, 745, 447, nil, 447, 745,
- 447, 447, nil, 447, 447, 447, 447, 447, 745, 447,
- nil, nil, nil, 745, 745, 745, 745, nil, 745, 745,
- 745, 745, nil, nil, nil, nil, 745, 745, nil, nil,
- nil, nil, nil, nil, 745, nil, 745, 745, 745, 793,
- 793, 793, 793, 793, 793, nil, nil, nil, 793, 793,
- nil, nil, nil, 793, nil, 793, 793, 793, 793, 793,
- 793, 793, nil, nil, nil, nil, nil, 793, 793, 793,
- 793, 793, 793, 793, nil, nil, 793, nil, nil, nil,
- nil, nil, 793, 793, 793, 793, 793, 793, 793, 793,
- 793, 793, 793, 793, nil, 793, 793, 793, nil, 793,
- 793, nil, 793, 793, 793, 448, 448, 448, 448, 448,
- 448, 448, 448, 448, 448, 448, nil, 448, 448, nil,
- nil, 448, 448, nil, 793, nil, nil, 793, nil, nil,
- 793, 793, nil, nil, 793, nil, 793, 448, nil, 448,
- 793, 448, 448, nil, 448, 448, 448, 448, 448, 793,
- 448, nil, nil, nil, 793, 793, 793, 793, nil, 793,
- 793, 793, 793, nil, nil, nil, nil, 793, 793, nil,
- nil, nil, nil, nil, nil, 793, nil, 793, 793, 793,
- 806, 806, 806, 806, 806, 806, nil, nil, nil, 806,
- 806, nil, nil, nil, 806, nil, 806, 806, 806, 806,
- 806, 806, 806, nil, nil, nil, nil, nil, 806, 806,
- 806, 806, 806, 806, 806, nil, 905, 806, 905, 905,
- 905, nil, 905, 806, 806, 806, 806, 806, 806, 806,
- 806, 806, 806, 806, 806, nil, 806, 806, 806, nil,
- 806, 806, nil, 806, 806, 806, 458, 458, 458, 458,
- 458, 458, 458, nil, 905, 458, 458, nil, nil, nil,
- nil, nil, 458, 458, nil, 806, nil, nil, 806, nil,
- nil, 806, 806, nil, nil, 806, nil, 806, 458, nil,
- 458, 806, 458, 458, nil, 458, 458, 458, 458, 458,
- 806, 458, nil, nil, nil, 806, 806, 806, 806, nil,
- 806, 806, 806, 806, nil, nil, nil, nil, 806, 806,
- nil, nil, nil, nil, nil, nil, 806, nil, 806, 806,
- 806, 814, 814, 814, 814, 814, 814, nil, nil, nil,
- 814, 814, nil, nil, nil, 814, nil, 814, 814, 814,
- 814, 814, 814, 814, nil, nil, nil, nil, nil, 814,
- 814, 814, 814, 814, 814, 814, nil, 957, 814, 957,
- 957, 957, nil, 957, 814, 814, 814, 814, 814, 814,
- 814, 814, 814, 814, 814, 814, nil, 814, 814, 814,
- nil, 814, 814, nil, 814, 814, 814, 459, nil, nil,
- 959, nil, 959, 959, 959, 957, 959, nil, nil, nil,
- nil, nil, nil, 459, 459, nil, 814, nil, nil, 814,
- nil, nil, 814, 814, nil, nil, 814, nil, 814, 459,
- nil, 459, 814, 459, 459, nil, 459, 459, 959, nil,
- 459, 814, 459, nil, nil, nil, 814, 814, 814, 814,
- nil, 814, 814, 814, 814, nil, nil, nil, nil, 814,
- 814, nil, nil, nil, nil, nil, nil, 814, nil, 814,
- 814, 814, 815, 815, 815, 815, 815, 815, nil, nil,
- nil, 815, 815, nil, nil, nil, 815, nil, 815, 815,
- 815, 815, 815, 815, 815, nil, nil, nil, nil, nil,
- 815, 815, 815, 815, 815, 815, 815, nil, 994, 815,
- 994, 994, 994, nil, 994, 815, 815, 815, 815, 815,
- 815, 815, 815, 815, 815, 815, 815, nil, 815, 815,
- 815, nil, 815, 815, nil, 815, 815, 815, 460, nil,
- nil, nil, nil, nil, nil, nil, 994, nil, nil, nil,
- nil, nil, nil, nil, 460, 460, nil, 815, nil, nil,
- 815, nil, nil, 815, 815, nil, nil, 815, nil, 815,
- 460, nil, 460, 815, 460, 460, nil, 460, 460, nil,
- nil, 460, 815, 460, nil, nil, nil, 815, 815, 815,
- 815, nil, 815, 815, 815, 815, nil, nil, nil, nil,
- 815, 815, nil, nil, nil, nil, nil, nil, 815, nil,
- 815, 815, 815, 839, 839, 839, 839, 839, 839, nil,
- nil, nil, 839, 839, nil, nil, nil, 839, nil, 839,
- 839, 839, 839, 839, 839, 839, nil, nil, nil, nil,
- nil, 839, 839, 839, 839, 839, 839, 839, nil, nil,
- 839, nil, nil, nil, nil, nil, 839, 839, 839, 839,
- 839, 839, 839, 839, 839, 839, 839, 839, nil, 839,
- 839, 839, nil, 839, 839, nil, 839, 839, 839, 461,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 461, 461, nil, 839, nil,
- nil, 839, nil, nil, 839, 839, nil, nil, 839, nil,
- 839, 461, nil, 461, 839, 461, 461, nil, 461, 461,
- nil, nil, 461, 839, 461, nil, nil, nil, 839, 839,
- 839, 839, nil, 839, 839, 839, 839, nil, nil, nil,
- nil, 839, 839, nil, nil, nil, nil, nil, nil, 839,
- nil, 839, 839, 839, 840, 840, 840, 840, 840, 840,
- nil, nil, nil, 840, 840, nil, nil, nil, 840, nil,
- 840, 840, 840, 840, 840, 840, 840, nil, nil, nil,
- nil, nil, 840, 840, 840, 840, 840, 840, 840, nil,
- nil, 840, nil, nil, nil, nil, nil, 840, 840, 840,
- 840, 840, 840, 840, 840, 840, 840, 840, 840, nil,
- 840, 840, 840, nil, 840, 840, nil, 840, 840, 840,
- 462, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 462, 462, nil, 840,
- nil, nil, 840, nil, nil, 840, 840, nil, nil, 840,
- nil, 840, 462, nil, 462, 840, 462, 462, nil, 462,
- 462, nil, nil, 462, 840, 462, nil, nil, nil, 840,
- 840, 840, 840, nil, 840, 840, 840, 840, nil, nil,
- nil, nil, 840, 840, nil, nil, nil, nil, nil, nil,
- 840, nil, 840, 840, 840, 843, 843, 843, 843, 843,
- 843, nil, nil, nil, 843, 843, nil, nil, nil, 843,
- nil, 843, 843, 843, 843, 843, 843, 843, nil, nil,
- nil, nil, nil, 843, 843, 843, 843, 843, 843, 843,
- nil, nil, 843, nil, nil, nil, nil, nil, 843, 843,
- 843, 843, 843, 843, 843, 843, 843, 843, 843, 843,
- nil, 843, 843, 843, nil, 843, 843, nil, 843, 843,
- 843, 463, 463, 463, 463, 463, 463, 463, nil, nil,
- 463, 463, nil, nil, nil, nil, nil, 463, 463, nil,
- 843, nil, nil, 843, nil, nil, 843, 843, nil, nil,
- 843, nil, 843, 463, nil, 463, 843, 463, 463, nil,
- 463, 463, 463, 463, 463, 843, 463, nil, nil, nil,
- 843, 843, 843, 843, nil, 843, 843, 843, 843, nil,
- nil, nil, nil, 843, 843, nil, nil, nil, nil, nil,
- nil, 843, nil, 843, 843, 843, 849, 849, 849, 849,
- 849, 849, nil, nil, nil, 849, 849, nil, nil, nil,
- 849, nil, 849, 849, 849, 849, 849, 849, 849, nil,
- nil, nil, nil, nil, 849, 849, 849, 849, 849, 849,
- 849, nil, nil, 849, nil, nil, nil, nil, nil, 849,
- 849, 849, 849, 849, 849, 849, 849, 849, 849, 849,
- 849, nil, 849, 849, 849, nil, 849, 849, nil, 849,
- 849, 849, 464, 464, 464, 464, 464, 464, 464, nil,
- nil, 464, 464, nil, nil, nil, nil, nil, 464, 464,
- nil, 849, nil, nil, 849, nil, nil, 849, 849, nil,
- nil, 849, nil, 849, 464, nil, 464, 849, 464, 464,
- nil, 464, 464, 464, 464, 464, 849, 464, nil, nil,
- nil, 849, 849, 849, 849, nil, 849, 849, 849, 849,
- nil, nil, nil, nil, 849, 849, nil, nil, nil, nil,
- nil, nil, 849, nil, 849, 849, 849, 882, 882, 882,
- 882, 882, 882, nil, nil, nil, 882, 882, nil, nil,
- nil, 882, nil, 882, 882, 882, 882, 882, 882, 882,
- nil, nil, nil, nil, nil, 882, 882, 882, 882, 882,
- 882, 882, nil, nil, 882, nil, nil, nil, nil, nil,
- 882, 882, 882, 882, 882, 882, 882, 882, 882, 882,
- 882, 882, nil, 882, 882, 882, nil, 882, 882, nil,
- 882, 882, 882, 465, 465, 465, 465, 465, 465, 465,
- nil, nil, 465, 465, nil, nil, nil, nil, nil, 465,
- 465, nil, 882, nil, nil, 882, nil, nil, 882, 882,
- nil, nil, 882, nil, 882, 465, nil, 465, 882, 465,
- 465, nil, 465, 465, 465, 465, 465, 882, 465, nil,
- nil, nil, 882, 882, 882, 882, nil, 882, 882, 882,
- 882, nil, nil, nil, nil, 882, 882, nil, nil, nil,
- nil, nil, nil, 882, nil, 882, 882, 882, 943, 943,
- 943, 943, 943, 943, nil, nil, nil, 943, 943, nil,
- nil, nil, 943, nil, 943, 943, 943, 943, 943, 943,
- 943, nil, nil, nil, nil, nil, 943, 943, 943, 943,
- 943, 943, 943, nil, nil, 943, nil, nil, nil, nil,
- nil, 943, 943, 943, 943, 943, 943, 943, 943, 943,
- 943, 943, 943, nil, 943, 943, 943, nil, 943, 943,
- nil, 943, 943, 943, 466, 466, 466, 466, 466, 466,
- 466, nil, nil, 466, 466, nil, nil, nil, nil, nil,
- 466, 466, nil, 943, nil, nil, 943, nil, nil, 943,
- 943, nil, nil, 943, nil, 943, 466, nil, 466, 943,
- 466, 466, nil, 466, 466, 466, 466, 466, 943, 466,
- nil, nil, nil, 943, 943, 943, 943, nil, 943, 943,
- 943, 943, nil, nil, nil, nil, 943, 943, nil, nil,
- nil, nil, nil, nil, 943, nil, 943, 943, 943, 960,
- 960, 960, 960, 960, 960, nil, nil, nil, 960, 960,
- nil, nil, nil, 960, nil, 960, 960, 960, 960, 960,
- 960, 960, nil, nil, nil, nil, nil, 960, 960, 960,
- 960, 960, 960, 960, nil, nil, 960, nil, nil, nil,
- nil, nil, 960, 960, 960, 960, 960, 960, 960, 960,
- 960, 960, 960, 960, nil, 960, 960, 960, nil, 960,
- 960, nil, 960, 960, 960, 467, 467, 467, 467, 467,
- 467, 467, nil, nil, 467, 467, nil, nil, nil, nil,
- nil, 467, 467, nil, 960, nil, nil, 960, nil, nil,
- 960, 960, nil, nil, 960, nil, 960, 467, nil, 467,
- 960, 467, 467, nil, 467, 467, 467, 467, 467, 960,
- 467, nil, nil, nil, 960, 960, 960, 960, nil, 960,
- 960, 960, 960, nil, nil, nil, nil, 960, 960, nil,
- nil, nil, nil, nil, nil, 960, nil, 960, 960, 960,
- 966, 966, 966, 966, 966, 966, nil, nil, nil, 966,
- 966, nil, nil, nil, 966, nil, 966, 966, 966, 966,
- 966, 966, 966, nil, nil, nil, nil, nil, 966, 966,
- 966, 966, 966, 966, 966, nil, nil, 966, nil, nil,
- nil, nil, nil, 966, 966, 966, 966, 966, 966, 966,
- 966, 966, 966, 966, 966, nil, 966, 966, 966, nil,
- 966, 966, nil, 966, 966, 966, 470, 470, 470, 470,
- 470, 470, 470, nil, nil, 470, 470, nil, nil, nil,
- nil, nil, 470, 470, nil, 966, nil, nil, 966, nil,
- nil, 966, 966, nil, nil, 966, nil, 966, 470, nil,
- 470, 966, 470, 470, nil, 470, 470, 470, 470, 470,
- 966, 470, nil, nil, nil, 966, 966, 966, 966, nil,
- 966, 966, 966, 966, nil, nil, nil, nil, 966, 966,
- nil, nil, nil, nil, nil, nil, 966, nil, 966, 966,
- 966, 968, 968, 968, 968, 968, 968, nil, nil, nil,
- 968, 968, nil, nil, nil, 968, nil, 968, 968, 968,
- 968, 968, 968, 968, nil, nil, nil, nil, nil, 968,
- 968, 968, 968, 968, 968, 968, nil, nil, 968, nil,
- nil, nil, nil, nil, 968, 968, 968, 968, 968, 968,
- 968, 968, 968, 968, 968, 968, nil, 968, 968, 968,
- nil, 968, 968, nil, 968, 968, 968, 471, 471, 471,
- 471, 471, 471, 471, 471, nil, 471, 471, nil, nil,
- nil, nil, nil, 471, 471, nil, 968, nil, nil, 968,
- nil, nil, 968, 968, nil, nil, 968, nil, 968, 471,
- nil, 471, 968, 471, 471, nil, 471, 471, 471, 471,
- 471, 968, 471, nil, nil, nil, 968, 968, 968, 968,
- nil, 968, 968, 968, 968, nil, nil, nil, nil, 968,
- 968, nil, nil, nil, nil, nil, nil, 968, nil, 968,
- 968, 968, 5, 5, 5, 5, 5, nil, nil, nil,
- 5, 5, nil, nil, nil, 5, nil, 5, 5, 5,
- 5, 5, 5, 5, nil, nil, nil, nil, nil, 5,
- 5, 5, 5, 5, 5, 5, nil, nil, 5, nil,
- nil, nil, nil, nil, 5, 5, 5, 5, 5, 5,
- 5, 5, 5, 5, 5, 5, nil, 5, 5, 5,
- nil, 5, 5, nil, 5, 5, 5, 455, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 455, 455, nil, 5, nil, nil, 5,
- nil, nil, 5, 5, nil, nil, 5, nil, 5, 455,
- nil, 455, 5, 455, 455, nil, 455, 455, nil, nil,
- nil, 5, nil, nil, nil, nil, 5, 5, 5, 5,
- nil, 5, 5, 5, 5, nil, nil, nil, nil, 5,
- 5, nil, nil, nil, 20, 20, 20, 5, 20, 5,
- 5, 5, 20, 20, nil, nil, nil, 20, nil, 20,
- 20, 20, 20, 20, 20, 20, nil, nil, nil, nil,
- nil, 20, 20, 20, 20, 20, 20, 20, nil, nil,
- 20, nil, nil, nil, nil, nil, nil, 20, nil, nil,
- 20, 20, 20, 20, 20, 20, 20, 20, nil, 20,
- 20, 20, nil, 20, 20, nil, 20, 20, 20, 456,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 456, 456, nil, 20, nil,
- nil, 20, nil, nil, 20, 20, nil, nil, 20, nil,
- nil, 456, nil, 456, 20, 456, 456, nil, 456, 456,
- nil, nil, nil, 20, nil, nil, nil, nil, 20, 20,
- 20, 20, nil, 20, 20, 20, 20, nil, nil, nil,
- nil, 20, 20, nil, nil, nil, 29, 29, 29, 20,
- 29, 20, 20, 20, 29, 29, nil, nil, nil, 29,
- nil, 29, 29, 29, 29, 29, 29, 29, nil, nil,
- nil, nil, nil, 29, 29, 29, 29, 29, 29, 29,
- nil, nil, 29, nil, nil, nil, nil, nil, nil, 29,
- nil, nil, 29, 29, 29, 29, 29, 29, 29, 29,
- 29, 29, 29, 29, nil, 29, 29, nil, 29, 29,
- 29, 457, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 457, 457, nil,
- 29, nil, nil, 29, nil, nil, 29, 29, nil, nil,
- 29, nil, 29, 457, 29, nil, 29, 457, 457, 29,
- 457, 457, nil, nil, nil, 29, nil, nil, nil, nil,
- 29, 29, 29, 29, nil, 29, 29, 29, 29, nil,
- nil, nil, nil, 29, 29, nil, nil, nil, 30, 30,
- 30, 29, 30, 29, 29, 29, 30, 30, nil, nil,
- nil, 30, nil, 30, 30, 30, 30, 30, 30, 30,
- nil, nil, nil, nil, nil, 30, 30, 30, 30, 30,
- 30, 30, nil, nil, 30, nil, nil, nil, nil, nil,
- nil, 30, nil, nil, 30, 30, 30, 30, 30, 30,
- 30, 30, 30, 30, 30, 30, nil, 30, 30, nil,
- 30, 30, 30, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 30, nil, nil, 30, nil, nil, 30, 30,
- nil, nil, 30, nil, 30, nil, 30, nil, 30, nil,
- nil, 30, nil, nil, nil, nil, nil, 30, nil, nil,
- nil, nil, 30, 30, 30, 30, nil, 30, 30, 30,
- 30, nil, nil, nil, nil, 30, 30, nil, nil, nil,
- 31, 31, 31, 30, 31, 30, 30, 30, 31, 31,
- nil, nil, nil, 31, nil, 31, 31, 31, 31, 31,
- 31, 31, nil, nil, nil, nil, nil, 31, 31, 31,
- 31, 31, 31, 31, nil, nil, 31, nil, nil, nil,
- nil, nil, nil, 31, nil, nil, 31, 31, 31, 31,
- 31, 31, 31, 31, 31, 31, 31, 31, nil, 31,
- 31, nil, 31, 31, 31, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 31, nil, nil, 31, nil, nil,
- 31, 31, nil, nil, 31, nil, 31, nil, 31, nil,
- 31, nil, nil, 31, nil, nil, nil, nil, nil, 31,
- nil, nil, nil, nil, 31, 31, 31, 31, nil, 31,
- 31, 31, 31, nil, nil, nil, nil, 31, 31, nil,
- nil, nil, 34, 34, 34, 31, 34, 31, 31, 31,
- 34, 34, nil, nil, nil, 34, nil, 34, 34, 34,
- 34, 34, 34, 34, nil, nil, nil, nil, nil, 34,
- 34, 34, 34, 34, 34, 34, nil, nil, 34, nil,
- nil, nil, nil, nil, nil, 34, nil, nil, 34, 34,
- 34, 34, 34, 34, 34, 34, nil, 34, 34, 34,
- nil, 34, 34, nil, nil, nil, 34, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 34, nil, nil, 34,
- nil, nil, 34, 34, nil, nil, 34, nil, 34, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 34, 34, 34, 34,
- nil, 34, 34, 34, 34, nil, nil, nil, nil, 34,
- 34, nil, nil, nil, 35, 35, 35, 34, 35, 34,
- 34, 34, 35, 35, nil, nil, nil, 35, nil, 35,
- 35, 35, 35, 35, 35, 35, nil, nil, nil, nil,
- nil, 35, 35, 35, 35, 35, 35, 35, nil, nil,
- 35, nil, nil, nil, nil, nil, nil, 35, nil, nil,
- 35, 35, 35, 35, 35, 35, 35, 35, nil, 35,
- 35, 35, nil, 35, 35, nil, nil, nil, 35, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 35, nil,
- nil, 35, nil, nil, 35, 35, nil, nil, 35, nil,
- 697, nil, 697, 697, 697, 697, 697, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 697, nil, 35, 35,
- 35, 35, nil, 35, 35, 35, 35, nil, nil, nil,
- nil, 35, 35, nil, nil, nil, 35, nil, 697, 35,
- nil, 35, 35, 35, 42, 42, 42, nil, 42, 697,
- 697, nil, 42, 42, 697, nil, nil, 42, nil, 42,
- 42, 42, 42, 42, 42, 42, nil, nil, nil, nil,
- nil, 42, 42, 42, 42, 42, 42, 42, nil, nil,
- 42, nil, nil, nil, nil, nil, nil, 42, nil, nil,
- 42, 42, 42, 42, 42, 42, 42, 42, nil, 42,
- 42, 42, nil, 42, 42, nil, 42, 42, 42, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 42, nil,
- nil, 42, nil, nil, 42, 42, nil, nil, 42, nil,
- nil, nil, nil, nil, 42, nil, nil, nil, nil, nil,
- nil, nil, nil, 42, nil, nil, nil, nil, 42, 42,
- 42, 42, nil, 42, 42, 42, 42, nil, nil, nil,
- nil, 42, 42, nil, nil, nil, 43, 43, 43, 42,
- 43, 42, 42, 42, 43, 43, nil, nil, nil, 43,
- nil, 43, 43, 43, 43, 43, 43, 43, nil, nil,
- nil, nil, nil, 43, 43, 43, 43, 43, 43, 43,
- nil, nil, 43, nil, nil, nil, nil, nil, nil, 43,
- nil, nil, 43, 43, 43, 43, 43, 43, 43, 43,
- nil, 43, 43, 43, nil, 43, 43, nil, 43, 43,
- 43, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 43, nil, nil, 43, nil, nil, 43, 43, nil, nil,
- 43, nil, nil, nil, nil, nil, 43, nil, nil, nil,
- nil, nil, nil, nil, nil, 43, nil, nil, nil, nil,
- 43, 43, 43, 43, nil, 43, 43, 43, 43, nil,
- nil, nil, nil, 43, 43, nil, nil, nil, 44, 44,
- 44, 43, 44, 43, 43, 43, 44, 44, nil, nil,
- nil, 44, nil, 44, 44, 44, 44, 44, 44, 44,
- nil, nil, nil, nil, nil, 44, 44, 44, 44, 44,
- 44, 44, nil, nil, 44, nil, nil, nil, nil, nil,
- nil, 44, nil, nil, 44, 44, 44, 44, 44, 44,
- 44, 44, nil, 44, 44, 44, nil, 44, 44, nil,
- 44, 44, 44, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 44, nil, nil, 44, nil, nil, 44, 44,
- nil, nil, 44, nil, nil, nil, nil, nil, 44, nil,
- nil, nil, nil, nil, nil, nil, nil, 44, nil, nil,
- nil, nil, 44, 44, 44, 44, nil, 44, 44, 44,
- 44, nil, nil, nil, nil, 44, 44, nil, nil, nil,
- 59, 59, 59, 44, 59, 44, 44, 44, 59, 59,
- nil, nil, nil, 59, nil, 59, 59, 59, 59, 59,
- 59, 59, nil, nil, nil, nil, nil, 59, 59, 59,
- 59, 59, 59, 59, nil, nil, 59, nil, nil, nil,
- nil, nil, nil, 59, nil, nil, 59, 59, 59, 59,
- 59, 59, 59, 59, 59, 59, 59, 59, nil, 59,
- 59, nil, 59, 59, 59, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 59, nil, nil, 59, nil, nil,
- 59, 59, nil, nil, 59, nil, 59, nil, nil, nil,
- 59, nil, nil, 59, nil, nil, nil, nil, nil, 59,
- nil, nil, nil, nil, 59, 59, 59, 59, nil, 59,
- 59, 59, 59, nil, nil, nil, nil, 59, 59, nil,
- nil, nil, 60, 60, 60, 59, 60, 59, 59, 59,
- 60, 60, nil, nil, nil, 60, nil, 60, 60, 60,
- 60, 60, 60, 60, nil, nil, nil, nil, nil, 60,
- 60, 60, 60, 60, 60, 60, nil, nil, 60, nil,
- nil, nil, nil, nil, nil, 60, nil, nil, 60, 60,
- 60, 60, 60, 60, 60, 60, 60, 60, 60, 60,
- nil, 60, 60, nil, 60, 60, 60, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 60, nil, nil, 60,
- nil, nil, 60, 60, nil, nil, 60, nil, nil, nil,
- nil, nil, 60, nil, nil, 60, nil, nil, nil, nil,
- nil, 60, nil, nil, nil, nil, 60, 60, 60, 60,
- nil, 60, 60, 60, 60, nil, nil, nil, nil, 60,
- 60, nil, nil, nil, 63, 63, 63, 60, 63, 60,
- 60, 60, 63, 63, nil, nil, nil, 63, nil, 63,
- 63, 63, 63, 63, 63, 63, nil, nil, nil, nil,
- nil, 63, 63, 63, 63, 63, 63, 63, nil, nil,
- 63, nil, nil, nil, nil, nil, nil, 63, nil, nil,
- 63, 63, 63, 63, 63, 63, 63, 63, nil, 63,
- 63, 63, nil, 63, 63, nil, 63, 63, 63, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 63, nil,
- nil, 63, nil, nil, 63, 63, nil, nil, 63, nil,
- nil, nil, nil, nil, 63, nil, nil, nil, nil, nil,
- nil, nil, nil, 63, nil, nil, nil, nil, 63, 63,
- 63, 63, nil, 63, 63, 63, 63, nil, nil, nil,
- nil, 63, 63, nil, nil, nil, 64, 64, 64, 63,
- 64, 63, 63, 63, 64, 64, nil, nil, nil, 64,
- nil, 64, 64, 64, 64, 64, 64, 64, nil, nil,
- nil, nil, nil, 64, 64, 64, 64, 64, 64, 64,
- nil, nil, 64, nil, nil, nil, nil, nil, nil, 64,
- nil, nil, 64, 64, 64, 64, 64, 64, 64, 64,
- nil, 64, 64, 64, nil, 64, 64, nil, 64, 64,
- 64, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 64, nil, nil, 64, nil, nil, 64, 64, nil, nil,
- 64, nil, nil, nil, nil, nil, 64, nil, nil, nil,
- nil, nil, nil, nil, nil, 64, nil, nil, nil, nil,
- 64, 64, 64, 64, nil, 64, 64, 64, 64, nil,
- nil, nil, nil, 64, 64, nil, nil, nil, 67, 67,
- 67, 64, 67, 64, 64, 64, 67, 67, nil, nil,
- nil, 67, nil, 67, 67, 67, 67, 67, 67, 67,
- nil, nil, nil, nil, nil, 67, 67, 67, 67, 67,
- 67, 67, nil, nil, 67, nil, nil, nil, nil, nil,
- nil, 67, nil, nil, 67, 67, 67, 67, 67, 67,
- 67, 67, nil, 67, 67, 67, nil, 67, 67, nil,
- 67, 67, 67, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 67, nil, nil, 67, nil, nil, 67, 67,
- nil, nil, 67, nil, nil, nil, nil, nil, 67, nil,
- nil, nil, nil, nil, nil, nil, nil, 67, nil, nil,
- nil, nil, 67, 67, 67, 67, nil, 67, 67, 67,
- 67, nil, nil, nil, nil, 67, 67, 67, nil, nil,
- nil, nil, 67, 67, nil, 67, 67, 67, 68, 68,
- 68, nil, 68, nil, nil, nil, 68, 68, nil, nil,
- nil, 68, nil, 68, 68, 68, 68, 68, 68, 68,
- nil, nil, nil, nil, nil, 68, 68, 68, 68, 68,
- 68, 68, nil, nil, 68, nil, nil, nil, nil, nil,
- nil, 68, nil, nil, 68, 68, 68, 68, 68, 68,
- 68, 68, nil, 68, 68, 68, nil, 68, 68, nil,
- nil, nil, 68, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 68, nil, nil, 68, nil, nil, 68, 68,
- nil, nil, 68, nil, 68, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 68, 68, 68, 68, nil, 68, 68, 68,
- 68, nil, nil, nil, nil, 68, 68, nil, nil, nil,
- 69, 69, 69, 68, 69, 68, 68, 68, 69, 69,
- nil, nil, nil, 69, nil, 69, 69, 69, 69, 69,
- 69, 69, nil, nil, nil, nil, nil, 69, 69, 69,
- 69, 69, 69, 69, nil, nil, 69, nil, nil, nil,
- nil, nil, nil, 69, nil, nil, 69, 69, 69, 69,
- 69, 69, 69, 69, nil, 69, 69, 69, nil, 69,
- 69, nil, nil, nil, 69, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 69, nil, nil, 69, nil, nil, 69, nil, nil,
- 69, 69, nil, nil, 69, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 69, 69, 69, 69, nil, 69,
- 69, 69, 69, nil, nil, nil, nil, 69, 69, nil,
- nil, nil, 70, 70, 70, 69, 70, 69, 69, 69,
- 70, 70, nil, nil, nil, 70, nil, 70, 70, 70,
- 70, 70, 70, 70, nil, nil, nil, nil, nil, 70,
- 70, 70, 70, 70, 70, 70, nil, nil, 70, nil,
- nil, nil, nil, nil, nil, 70, nil, nil, 70, 70,
- 70, 70, 70, 70, 70, 70, nil, 70, 70, 70,
- nil, 70, 70, nil, nil, nil, 70, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 70, nil, nil, 70,
- nil, nil, 70, 70, nil, nil, 70, nil, 869, nil,
- 869, 869, 869, 869, 869, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 869, nil, 70, 70, 70, 70,
- nil, 70, 70, 70, 70, nil, nil, nil, nil, 70,
- 70, nil, nil, nil, nil, nil, 869, 70, nil, 70,
- 70, 70, 111, 111, 111, 111, 111, 869, 869, nil,
- 111, 111, 869, nil, nil, 111, nil, 111, 111, 111,
- 111, 111, 111, 111, nil, nil, nil, nil, nil, 111,
- 111, 111, 111, 111, 111, 111, nil, nil, 111, nil,
- nil, nil, nil, nil, 111, 111, 111, 111, 111, 111,
- 111, 111, 111, 111, 111, 111, nil, 111, 111, 111,
- nil, 111, 111, nil, 111, 111, 111, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 111, nil, nil, 111,
- nil, nil, 111, 111, nil, nil, 111, nil, 111, nil,
- nil, nil, 111, nil, nil, nil, nil, nil, nil, nil,
- nil, 111, nil, nil, nil, nil, 111, 111, 111, 111,
- nil, 111, 111, 111, 111, nil, nil, nil, nil, 111,
- 111, nil, nil, nil, nil, nil, 111, 111, nil, 111,
- 111, 111, 116, 116, 116, nil, 116, nil, nil, nil,
- 116, 116, nil, nil, nil, 116, nil, 116, 116, 116,
- 116, 116, 116, 116, nil, nil, nil, nil, nil, 116,
- 116, 116, 116, 116, 116, 116, nil, nil, 116, nil,
- nil, nil, nil, nil, nil, 116, nil, nil, 116, 116,
- 116, 116, 116, 116, 116, 116, nil, 116, 116, 116,
- nil, 116, 116, nil, 116, 116, 116, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 116, nil, nil, 116,
- nil, nil, 116, 116, nil, nil, 116, nil, nil, nil,
- nil, nil, 116, nil, nil, nil, nil, nil, nil, nil,
- nil, 116, nil, nil, nil, nil, 116, 116, 116, 116,
- nil, 116, 116, 116, 116, nil, nil, nil, nil, 116,
- 116, nil, nil, nil, 117, 117, 117, 116, 117, 116,
- 116, 116, 117, 117, nil, nil, nil, 117, nil, 117,
- 117, 117, 117, 117, 117, 117, nil, nil, nil, nil,
- nil, 117, 117, 117, 117, 117, 117, 117, nil, nil,
- 117, nil, nil, nil, nil, nil, nil, 117, nil, nil,
- 117, 117, 117, 117, 117, 117, 117, 117, nil, 117,
- 117, 117, nil, 117, 117, nil, 117, 117, 117, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 117, nil,
- nil, 117, nil, nil, 117, 117, nil, nil, 117, nil,
- nil, nil, nil, nil, 117, nil, nil, nil, nil, nil,
- nil, nil, nil, 117, nil, nil, nil, nil, 117, 117,
- 117, 117, nil, 117, 117, 117, 117, nil, nil, nil,
- nil, 117, 117, nil, nil, nil, 118, 118, 118, 117,
- 118, 117, 117, 117, 118, 118, nil, nil, nil, 118,
- nil, 118, 118, 118, 118, 118, 118, 118, nil, nil,
- nil, nil, nil, 118, 118, 118, 118, 118, 118, 118,
- nil, nil, 118, nil, nil, nil, nil, nil, nil, 118,
- nil, nil, 118, 118, 118, 118, 118, 118, 118, 118,
- nil, 118, 118, 118, nil, 118, 118, nil, 118, 118,
- 118, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 118, nil, nil, 118, nil, nil, 118, 118, nil, nil,
- 118, nil, nil, nil, nil, nil, 118, nil, nil, nil,
- nil, nil, nil, nil, nil, 118, nil, nil, nil, nil,
- 118, 118, 118, 118, nil, 118, 118, 118, 118, nil,
- nil, nil, nil, 118, 118, nil, nil, nil, 119, 119,
- 119, 118, 119, 118, 118, 118, 119, 119, nil, nil,
- nil, 119, nil, 119, 119, 119, 119, 119, 119, 119,
- nil, nil, nil, nil, nil, 119, 119, 119, 119, 119,
- 119, 119, nil, nil, 119, nil, nil, nil, nil, nil,
- nil, 119, nil, nil, 119, 119, 119, 119, 119, 119,
- 119, 119, nil, 119, 119, 119, nil, 119, 119, nil,
- 119, 119, 119, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 119, nil, nil, 119, nil, nil, 119, 119,
- nil, nil, 119, nil, nil, nil, nil, nil, 119, nil,
- nil, nil, nil, nil, nil, nil, nil, 119, nil, nil,
- nil, nil, 119, 119, 119, 119, nil, 119, 119, 119,
- 119, nil, nil, nil, nil, 119, 119, nil, nil, nil,
- nil, nil, nil, 119, nil, 119, 119, 119, 120, 120,
- 120, 120, 120, nil, nil, nil, 120, 120, nil, nil,
- nil, 120, nil, 120, 120, 120, 120, 120, 120, 120,
- nil, nil, nil, nil, nil, 120, 120, 120, 120, 120,
- 120, 120, nil, nil, 120, nil, nil, nil, nil, nil,
- 120, 120, nil, 120, 120, 120, 120, 120, 120, 120,
- 120, 120, nil, 120, 120, 120, nil, 120, 120, nil,
- 120, 120, 120, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 120, nil, nil, 120, nil, nil, 120, 120,
- nil, nil, 120, nil, 120, nil, nil, nil, 120, nil,
- nil, nil, nil, nil, nil, nil, nil, 120, nil, nil,
- nil, nil, 120, 120, 120, 120, nil, 120, 120, 120,
- 120, nil, nil, nil, nil, 120, 120, nil, nil, nil,
- 207, 207, 207, 120, 207, 120, 120, 120, 207, 207,
- nil, nil, nil, 207, nil, 207, 207, 207, 207, 207,
- 207, 207, nil, nil, nil, nil, nil, 207, 207, 207,
- 207, 207, 207, 207, nil, nil, 207, nil, nil, nil,
- nil, nil, nil, 207, nil, nil, 207, 207, 207, 207,
- 207, 207, 207, 207, nil, 207, 207, 207, nil, 207,
- 207, nil, 207, 207, 207, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 207, nil, nil, 207, nil, nil,
- 207, 207, nil, nil, 207, nil, 207, nil, nil, nil,
- 207, nil, nil, nil, nil, nil, nil, nil, nil, 207,
- nil, nil, nil, nil, 207, 207, 207, 207, nil, 207,
- 207, 207, 207, nil, nil, nil, nil, 207, 207, nil,
- nil, nil, 208, 208, 208, 207, 208, 207, 207, 207,
- 208, 208, nil, nil, nil, 208, nil, 208, 208, 208,
- 208, 208, 208, 208, nil, nil, nil, nil, nil, 208,
- 208, 208, 208, 208, 208, 208, nil, nil, 208, nil,
- nil, nil, nil, nil, nil, 208, nil, nil, 208, 208,
- 208, 208, 208, 208, 208, 208, nil, 208, 208, 208,
- nil, 208, 208, nil, 208, 208, 208, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 208, nil, nil, 208,
- nil, nil, 208, 208, nil, nil, 208, nil, nil, nil,
- nil, nil, 208, nil, nil, nil, nil, nil, nil, nil,
- nil, 208, nil, nil, nil, nil, 208, 208, 208, 208,
- nil, 208, 208, 208, 208, nil, nil, nil, nil, 208,
- 208, nil, nil, nil, 209, 209, 209, 208, 209, 208,
- 208, 208, 209, 209, nil, nil, nil, 209, nil, 209,
- 209, 209, 209, 209, 209, 209, nil, nil, nil, nil,
- nil, 209, 209, 209, 209, 209, 209, 209, nil, nil,
- 209, nil, nil, nil, nil, nil, nil, 209, nil, nil,
- 209, 209, 209, 209, 209, 209, 209, 209, 209, 209,
- 209, 209, nil, 209, 209, nil, 209, 209, 209, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 209, nil,
- nil, 209, nil, nil, 209, 209, nil, nil, 209, nil,
- 209, nil, 209, nil, 209, nil, nil, 209, nil, nil,
- nil, nil, nil, 209, nil, nil, nil, nil, 209, 209,
- 209, 209, nil, 209, 209, 209, 209, nil, nil, nil,
- nil, 209, 209, nil, nil, nil, 212, 212, 212, 209,
- 212, 209, 209, 209, 212, 212, nil, nil, nil, 212,
- nil, 212, 212, 212, 212, 212, 212, 212, nil, nil,
- nil, nil, nil, 212, 212, 212, 212, 212, 212, 212,
- nil, nil, 212, nil, nil, nil, nil, nil, nil, 212,
- nil, nil, 212, 212, 212, 212, 212, 212, 212, 212,
- nil, 212, 212, 212, nil, 212, 212, nil, 212, 212,
- 212, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 212, nil, nil, 212, nil, nil, 212, 212, nil, nil,
- 212, nil, nil, nil, nil, nil, 212, nil, nil, nil,
- nil, nil, nil, nil, nil, 212, nil, nil, nil, nil,
- 212, 212, 212, 212, nil, 212, 212, 212, 212, nil,
- nil, nil, nil, 212, 212, nil, nil, nil, 213, 213,
- 213, 212, 213, 212, 212, 212, 213, 213, nil, nil,
- nil, 213, nil, 213, 213, 213, 213, 213, 213, 213,
- nil, nil, nil, nil, nil, 213, 213, 213, 213, 213,
- 213, 213, nil, nil, 213, nil, nil, nil, nil, nil,
- nil, 213, nil, nil, 213, 213, 213, 213, 213, 213,
- 213, 213, nil, 213, 213, 213, nil, 213, 213, nil,
- 213, 213, 213, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 213, nil, nil, 213, nil, nil, 213, 213,
- nil, nil, 213, nil, 213, nil, nil, nil, 213, nil,
- nil, nil, nil, nil, nil, nil, nil, 213, nil, nil,
- nil, nil, 213, 213, 213, 213, nil, 213, 213, 213,
- 213, nil, nil, nil, nil, 213, 213, nil, nil, nil,
- 214, 214, 214, 213, 214, 213, 213, 213, 214, 214,
- nil, nil, nil, 214, nil, 214, 214, 214, 214, 214,
- 214, 214, nil, nil, nil, nil, nil, 214, 214, 214,
- 214, 214, 214, 214, nil, nil, 214, nil, nil, nil,
- nil, nil, nil, 214, nil, nil, 214, 214, 214, 214,
- 214, 214, 214, 214, nil, 214, 214, 214, nil, 214,
- 214, nil, 214, 214, 214, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 214, nil, nil, 214, nil, nil,
- 214, 214, nil, nil, 214, nil, nil, nil, nil, nil,
- 214, nil, nil, nil, nil, nil, nil, nil, nil, 214,
- nil, nil, nil, nil, 214, 214, 214, 214, nil, 214,
- 214, 214, 214, nil, nil, nil, nil, 214, 214, nil,
- nil, nil, 215, 215, 215, 214, 215, 214, 214, 214,
- 215, 215, nil, nil, nil, 215, nil, 215, 215, 215,
- 215, 215, 215, 215, nil, nil, nil, nil, nil, 215,
- 215, 215, 215, 215, 215, 215, nil, nil, 215, nil,
- nil, nil, nil, nil, nil, 215, nil, nil, 215, 215,
- 215, 215, 215, 215, 215, 215, nil, 215, 215, 215,
- nil, 215, 215, nil, 215, 215, 215, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 215, nil, nil, 215,
- nil, nil, 215, 215, nil, nil, 215, nil, nil, nil,
- nil, nil, 215, nil, nil, nil, nil, nil, nil, nil,
- nil, 215, nil, nil, nil, nil, 215, 215, 215, 215,
- nil, 215, 215, 215, 215, nil, nil, nil, nil, 215,
- 215, nil, nil, nil, 216, 216, 216, 215, 216, 215,
- 215, 215, 216, 216, nil, nil, nil, 216, nil, 216,
- 216, 216, 216, 216, 216, 216, nil, nil, nil, nil,
- nil, 216, 216, 216, 216, 216, 216, 216, nil, nil,
- 216, nil, nil, nil, nil, nil, nil, 216, nil, nil,
- 216, 216, 216, 216, 216, 216, 216, 216, nil, 216,
- 216, 216, nil, 216, 216, nil, 216, 216, 216, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 216, nil,
- nil, 216, nil, nil, 216, 216, nil, nil, 216, nil,
- nil, nil, nil, nil, 216, nil, nil, nil, nil, nil,
- nil, nil, nil, 216, nil, nil, nil, nil, 216, 216,
- 216, 216, nil, 216, 216, 216, 216, nil, nil, nil,
- nil, 216, 216, nil, nil, nil, 217, 217, 217, 216,
- 217, 216, 216, 216, 217, 217, nil, nil, nil, 217,
- nil, 217, 217, 217, 217, 217, 217, 217, nil, nil,
- nil, nil, nil, 217, 217, 217, 217, 217, 217, 217,
- nil, nil, 217, nil, nil, nil, nil, nil, nil, 217,
- nil, nil, 217, 217, 217, 217, 217, 217, 217, 217,
- nil, 217, 217, 217, nil, 217, 217, nil, 217, 217,
- 217, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 217, nil, nil, 217, nil, nil, 217, 217, nil, nil,
- 217, nil, nil, nil, nil, nil, 217, nil, nil, nil,
- nil, nil, nil, nil, nil, 217, nil, nil, nil, nil,
- 217, 217, 217, 217, nil, 217, 217, 217, 217, nil,
- nil, nil, nil, 217, 217, 217, nil, nil, 228, 228,
- 228, 217, 228, 217, 217, 217, 228, 228, nil, nil,
- nil, 228, nil, 228, 228, 228, 228, 228, 228, 228,
- nil, nil, nil, nil, nil, 228, 228, 228, 228, 228,
- 228, 228, nil, nil, 228, nil, nil, nil, nil, nil,
- nil, 228, nil, nil, 228, 228, 228, 228, 228, 228,
- 228, 228, nil, 228, 228, 228, nil, 228, 228, nil,
- 228, 228, 228, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 228, nil, nil, 228, nil, nil, 228, 228,
- nil, nil, 228, nil, nil, nil, nil, nil, 228, nil,
- nil, nil, nil, nil, nil, nil, nil, 228, nil, nil,
- nil, nil, 228, 228, 228, 228, nil, 228, 228, 228,
- 228, nil, nil, nil, nil, 228, 228, nil, nil, nil,
- 231, 231, 231, 228, 231, 228, 228, 228, 231, 231,
- nil, nil, nil, 231, nil, 231, 231, 231, 231, 231,
- 231, 231, nil, nil, nil, nil, nil, 231, 231, 231,
- 231, 231, 231, 231, nil, nil, 231, nil, nil, nil,
- nil, nil, nil, 231, nil, nil, 231, 231, 231, 231,
- 231, 231, 231, 231, nil, 231, 231, 231, nil, 231,
- 231, nil, 231, 231, 231, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 231, nil, nil, 231, nil, nil,
- 231, 231, nil, nil, 231, nil, nil, nil, nil, nil,
- 231, nil, nil, nil, nil, nil, nil, nil, nil, 231,
- nil, nil, nil, nil, 231, 231, 231, 231, nil, 231,
- 231, 231, 231, nil, nil, nil, nil, 231, 231, nil,
- nil, nil, 232, 232, 232, 231, 232, 231, 231, 231,
- 232, 232, nil, nil, nil, 232, nil, 232, 232, 232,
- 232, 232, 232, 232, nil, nil, nil, nil, nil, 232,
- 232, 232, 232, 232, 232, 232, nil, nil, 232, nil,
- nil, nil, nil, nil, nil, 232, nil, nil, 232, 232,
- 232, 232, 232, 232, 232, 232, nil, 232, 232, 232,
- nil, 232, 232, nil, 232, 232, 232, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 232, nil, nil, 232,
- nil, nil, 232, 232, nil, nil, 232, nil, nil, nil,
- nil, nil, 232, nil, nil, nil, nil, nil, nil, nil,
- nil, 232, nil, nil, nil, nil, 232, 232, 232, 232,
- nil, 232, 232, 232, 232, nil, nil, nil, nil, 232,
- 232, nil, nil, nil, 233, 233, 233, 232, 233, 232,
- 232, 232, 233, 233, nil, nil, nil, 233, nil, 233,
- 233, 233, 233, 233, 233, 233, nil, nil, nil, nil,
- nil, 233, 233, 233, 233, 233, 233, 233, nil, nil,
- 233, nil, nil, nil, nil, nil, nil, 233, nil, nil,
- 233, 233, 233, 233, 233, 233, 233, 233, nil, 233,
- 233, 233, nil, 233, 233, nil, 233, 233, 233, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 233, nil,
- nil, 233, nil, nil, 233, 233, nil, nil, 233, nil,
- nil, nil, nil, nil, 233, nil, nil, nil, nil, nil,
- nil, nil, nil, 233, nil, nil, nil, nil, 233, 233,
- 233, 233, nil, 233, 233, 233, 233, nil, nil, nil,
- nil, 233, 233, nil, nil, nil, 234, 234, 234, 233,
- 234, 233, 233, 233, 234, 234, nil, nil, nil, 234,
- nil, 234, 234, 234, 234, 234, 234, 234, nil, nil,
- nil, nil, nil, 234, 234, 234, 234, 234, 234, 234,
- nil, nil, 234, nil, nil, nil, nil, nil, nil, 234,
- nil, nil, 234, 234, 234, 234, 234, 234, 234, 234,
- nil, 234, 234, 234, nil, 234, 234, nil, 234, 234,
- 234, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 234, nil, nil, 234, nil, nil, 234, 234, nil, nil,
- 234, nil, nil, nil, nil, nil, 234, nil, nil, nil,
- nil, nil, nil, nil, nil, 234, nil, nil, nil, nil,
- 234, 234, 234, 234, nil, 234, 234, 234, 234, nil,
- nil, nil, nil, 234, 234, nil, nil, nil, 235, 235,
- 235, 234, 235, 234, 234, 234, 235, 235, nil, nil,
- nil, 235, nil, 235, 235, 235, 235, 235, 235, 235,
- nil, nil, nil, nil, nil, 235, 235, 235, 235, 235,
- 235, 235, nil, nil, 235, nil, nil, nil, nil, nil,
- nil, 235, nil, nil, 235, 235, 235, 235, 235, 235,
- 235, 235, nil, 235, 235, 235, nil, 235, 235, nil,
- 235, 235, 235, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 235, nil, nil, 235, nil, nil, 235, 235,
- nil, nil, 235, nil, nil, nil, nil, nil, 235, nil,
- nil, nil, nil, nil, nil, nil, nil, 235, nil, nil,
- nil, nil, 235, 235, 235, 235, nil, 235, 235, 235,
- 235, nil, nil, nil, nil, 235, 235, nil, nil, nil,
- 236, 236, 236, 235, 236, 235, 235, 235, 236, 236,
- nil, nil, nil, 236, nil, 236, 236, 236, 236, 236,
- 236, 236, nil, nil, nil, nil, nil, 236, 236, 236,
- 236, 236, 236, 236, nil, nil, 236, nil, nil, nil,
- nil, nil, nil, 236, nil, nil, 236, 236, 236, 236,
- 236, 236, 236, 236, nil, 236, 236, 236, nil, 236,
- 236, nil, 236, 236, 236, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 236, nil, nil, 236, nil, nil,
- 236, 236, nil, nil, 236, nil, nil, nil, nil, nil,
- 236, nil, nil, nil, nil, nil, nil, nil, nil, 236,
- nil, nil, nil, nil, 236, 236, 236, 236, nil, 236,
- 236, 236, 236, nil, nil, nil, nil, 236, 236, nil,
- nil, nil, 237, 237, 237, 236, 237, 236, 236, 236,
- 237, 237, nil, nil, nil, 237, nil, 237, 237, 237,
- 237, 237, 237, 237, nil, nil, nil, nil, nil, 237,
- 237, 237, 237, 237, 237, 237, nil, nil, 237, nil,
- nil, nil, nil, nil, nil, 237, nil, nil, 237, 237,
- 237, 237, 237, 237, 237, 237, nil, 237, 237, 237,
- nil, 237, 237, nil, 237, 237, 237, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 237, nil, nil, 237,
- nil, nil, 237, 237, nil, nil, 237, nil, nil, nil,
- nil, nil, 237, nil, nil, nil, nil, nil, nil, nil,
- nil, 237, nil, nil, nil, nil, 237, 237, 237, 237,
- nil, 237, 237, 237, 237, nil, nil, nil, nil, 237,
- 237, nil, nil, nil, 238, 238, 238, 237, 238, 237,
- 237, 237, 238, 238, nil, nil, nil, 238, nil, 238,
- 238, 238, 238, 238, 238, 238, nil, nil, nil, nil,
- nil, 238, 238, 238, 238, 238, 238, 238, nil, nil,
- 238, nil, nil, nil, nil, nil, nil, 238, nil, nil,
- 238, 238, 238, 238, 238, 238, 238, 238, nil, 238,
- 238, 238, nil, 238, 238, nil, 238, 238, 238, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 238, nil,
- nil, 238, nil, nil, 238, 238, nil, nil, 238, nil,
- nil, nil, nil, nil, 238, nil, nil, nil, nil, nil,
- nil, nil, nil, 238, nil, nil, nil, nil, 238, 238,
- 238, 238, nil, 238, 238, 238, 238, nil, nil, nil,
- nil, 238, 238, nil, nil, nil, 239, 239, 239, 238,
- 239, 238, 238, 238, 239, 239, nil, nil, nil, 239,
- nil, 239, 239, 239, 239, 239, 239, 239, nil, nil,
- nil, nil, nil, 239, 239, 239, 239, 239, 239, 239,
- nil, nil, 239, nil, nil, nil, nil, nil, nil, 239,
- nil, nil, 239, 239, 239, 239, 239, 239, 239, 239,
- nil, 239, 239, 239, nil, 239, 239, nil, 239, 239,
- 239, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 239, nil, nil, 239, nil, nil, 239, 239, nil, nil,
- 239, nil, nil, nil, nil, nil, 239, nil, nil, nil,
- nil, nil, nil, nil, nil, 239, nil, nil, nil, nil,
- 239, 239, 239, 239, nil, 239, 239, 239, 239, nil,
- nil, nil, nil, 239, 239, nil, nil, nil, 240, 240,
- 240, 239, 240, 239, 239, 239, 240, 240, nil, nil,
- nil, 240, nil, 240, 240, 240, 240, 240, 240, 240,
- nil, nil, nil, nil, nil, 240, 240, 240, 240, 240,
- 240, 240, nil, nil, 240, nil, nil, nil, nil, nil,
- nil, 240, nil, nil, 240, 240, 240, 240, 240, 240,
- 240, 240, nil, 240, 240, 240, nil, 240, 240, nil,
- 240, 240, 240, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 240, nil, nil, 240, nil, nil, 240, 240,
- nil, nil, 240, nil, nil, nil, nil, nil, 240, nil,
- nil, nil, nil, nil, nil, nil, nil, 240, nil, nil,
- nil, nil, 240, 240, 240, 240, nil, 240, 240, 240,
- 240, nil, nil, nil, nil, 240, 240, nil, nil, nil,
- 241, 241, 241, 240, 241, 240, 240, 240, 241, 241,
- nil, nil, nil, 241, nil, 241, 241, 241, 241, 241,
- 241, 241, nil, nil, nil, nil, nil, 241, 241, 241,
- 241, 241, 241, 241, nil, nil, 241, nil, nil, nil,
- nil, nil, nil, 241, nil, nil, 241, 241, 241, 241,
- 241, 241, 241, 241, nil, 241, 241, 241, nil, 241,
- 241, nil, 241, 241, 241, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 241, nil, nil, 241, nil, nil,
- 241, 241, nil, nil, 241, nil, nil, nil, nil, nil,
- 241, nil, nil, nil, nil, nil, nil, nil, nil, 241,
- nil, nil, nil, nil, 241, 241, 241, 241, nil, 241,
- 241, 241, 241, nil, nil, nil, nil, 241, 241, nil,
- nil, nil, 242, 242, 242, 241, 242, 241, 241, 241,
- 242, 242, nil, nil, nil, 242, nil, 242, 242, 242,
- 242, 242, 242, 242, nil, nil, nil, nil, nil, 242,
- 242, 242, 242, 242, 242, 242, nil, nil, 242, nil,
- nil, nil, nil, nil, nil, 242, nil, nil, 242, 242,
- 242, 242, 242, 242, 242, 242, nil, 242, 242, 242,
- nil, 242, 242, nil, 242, 242, 242, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 242, nil, nil, 242,
- nil, nil, 242, 242, nil, nil, 242, nil, nil, nil,
- nil, nil, 242, nil, nil, nil, nil, nil, nil, nil,
- nil, 242, nil, nil, nil, nil, 242, 242, 242, 242,
- nil, 242, 242, 242, 242, nil, nil, nil, nil, 242,
- 242, nil, nil, nil, 243, 243, 243, 242, 243, 242,
- 242, 242, 243, 243, nil, nil, nil, 243, nil, 243,
- 243, 243, 243, 243, 243, 243, nil, nil, nil, nil,
- nil, 243, 243, 243, 243, 243, 243, 243, nil, nil,
- 243, nil, nil, nil, nil, nil, nil, 243, nil, nil,
- 243, 243, 243, 243, 243, 243, 243, 243, nil, 243,
- 243, 243, nil, 243, 243, nil, 243, 243, 243, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 243, nil,
- nil, 243, nil, nil, 243, 243, nil, nil, 243, nil,
- nil, nil, nil, nil, 243, nil, nil, nil, nil, nil,
- nil, nil, nil, 243, nil, nil, nil, nil, 243, 243,
- 243, 243, nil, 243, 243, 243, 243, nil, nil, nil,
- nil, 243, 243, nil, nil, nil, 244, 244, 244, 243,
- 244, 243, 243, 243, 244, 244, nil, nil, nil, 244,
- nil, 244, 244, 244, 244, 244, 244, 244, nil, nil,
- nil, nil, nil, 244, 244, 244, 244, 244, 244, 244,
- nil, nil, 244, nil, nil, nil, nil, nil, nil, 244,
- nil, nil, 244, 244, 244, 244, 244, 244, 244, 244,
- nil, 244, 244, 244, nil, 244, 244, nil, 244, 244,
- 244, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 244, nil, nil, 244, nil, nil, 244, 244, nil, nil,
- 244, nil, nil, nil, nil, nil, 244, nil, nil, nil,
- nil, nil, nil, nil, nil, 244, nil, nil, nil, nil,
- 244, 244, 244, 244, nil, 244, 244, 244, 244, nil,
- nil, nil, nil, 244, 244, nil, nil, nil, 245, 245,
- 245, 244, 245, 244, 244, 244, 245, 245, nil, nil,
- nil, 245, nil, 245, 245, 245, 245, 245, 245, 245,
- nil, nil, nil, nil, nil, 245, 245, 245, 245, 245,
- 245, 245, nil, nil, 245, nil, nil, nil, nil, nil,
- nil, 245, nil, nil, 245, 245, 245, 245, 245, 245,
- 245, 245, nil, 245, 245, 245, nil, 245, 245, nil,
- 245, 245, 245, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 245, nil, nil, 245, nil, nil, 245, 245,
- nil, nil, 245, nil, nil, nil, nil, nil, 245, nil,
- nil, nil, nil, nil, nil, nil, nil, 245, nil, nil,
- nil, nil, 245, 245, 245, 245, nil, 245, 245, 245,
- 245, nil, nil, nil, nil, 245, 245, nil, nil, nil,
- 246, 246, 246, 245, 246, 245, 245, 245, 246, 246,
- nil, nil, nil, 246, nil, 246, 246, 246, 246, 246,
- 246, 246, nil, nil, nil, nil, nil, 246, 246, 246,
- 246, 246, 246, 246, nil, nil, 246, nil, nil, nil,
- nil, nil, nil, 246, nil, nil, 246, 246, 246, 246,
- 246, 246, 246, 246, nil, 246, 246, 246, nil, 246,
- 246, nil, 246, 246, 246, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 246, nil, nil, 246, nil, nil,
- 246, 246, nil, nil, 246, nil, nil, nil, nil, nil,
- 246, nil, nil, nil, nil, nil, nil, nil, nil, 246,
- nil, nil, nil, nil, 246, 246, 246, 246, nil, 246,
- 246, 246, 246, nil, nil, nil, nil, 246, 246, nil,
- nil, nil, 247, 247, 247, 246, 247, 246, 246, 246,
- 247, 247, nil, nil, nil, 247, nil, 247, 247, 247,
- 247, 247, 247, 247, nil, nil, nil, nil, nil, 247,
- 247, 247, 247, 247, 247, 247, nil, nil, 247, nil,
- nil, nil, nil, nil, nil, 247, nil, nil, 247, 247,
- 247, 247, 247, 247, 247, 247, nil, 247, 247, 247,
- nil, 247, 247, nil, 247, 247, 247, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 247, nil, nil, 247,
- nil, nil, 247, 247, nil, nil, 247, nil, nil, nil,
- nil, nil, 247, nil, nil, nil, nil, nil, nil, nil,
- nil, 247, nil, nil, nil, nil, 247, 247, 247, 247,
- nil, 247, 247, 247, 247, nil, nil, nil, nil, 247,
- 247, nil, nil, nil, 248, 248, 248, 247, 248, 247,
- 247, 247, 248, 248, nil, nil, nil, 248, nil, 248,
- 248, 248, 248, 248, 248, 248, nil, nil, nil, nil,
- nil, 248, 248, 248, 248, 248, 248, 248, nil, nil,
- 248, nil, nil, nil, nil, nil, nil, 248, nil, nil,
- 248, 248, 248, 248, 248, 248, 248, 248, nil, 248,
- 248, 248, nil, 248, 248, nil, 248, 248, 248, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 248, nil,
- nil, 248, nil, nil, 248, 248, nil, nil, 248, nil,
- nil, nil, nil, nil, 248, nil, nil, nil, nil, nil,
- nil, nil, nil, 248, nil, nil, nil, nil, 248, 248,
- 248, 248, nil, 248, 248, 248, 248, nil, nil, nil,
- nil, 248, 248, nil, nil, nil, 249, 249, 249, 248,
- 249, 248, 248, 248, 249, 249, nil, nil, nil, 249,
- nil, 249, 249, 249, 249, 249, 249, 249, nil, nil,
- nil, nil, nil, 249, 249, 249, 249, 249, 249, 249,
- nil, nil, 249, nil, nil, nil, nil, nil, nil, 249,
- nil, nil, 249, 249, 249, 249, 249, 249, 249, 249,
- nil, 249, 249, 249, nil, 249, 249, nil, 249, 249,
- 249, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 249, nil, nil, 249, nil, nil, 249, 249, nil, nil,
- 249, nil, nil, nil, nil, nil, 249, nil, nil, nil,
- nil, nil, nil, nil, nil, 249, nil, nil, nil, nil,
- 249, 249, 249, 249, nil, 249, 249, 249, 249, nil,
- nil, nil, nil, 249, 249, nil, nil, nil, 250, 250,
- 250, 249, 250, 249, 249, 249, 250, 250, nil, nil,
- nil, 250, nil, 250, 250, 250, 250, 250, 250, 250,
- nil, nil, nil, nil, nil, 250, 250, 250, 250, 250,
- 250, 250, nil, nil, 250, nil, nil, nil, nil, nil,
- nil, 250, nil, nil, 250, 250, 250, 250, 250, 250,
- 250, 250, nil, 250, 250, 250, nil, 250, 250, nil,
- 250, 250, 250, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 250, nil, nil, 250, nil, nil, 250, 250,
- nil, nil, 250, nil, nil, nil, nil, nil, 250, nil,
- nil, nil, nil, nil, nil, nil, nil, 250, nil, nil,
- nil, nil, 250, 250, 250, 250, nil, 250, 250, 250,
- 250, nil, nil, nil, nil, 250, 250, nil, nil, nil,
- 251, 251, 251, 250, 251, 250, 250, 250, 251, 251,
- nil, nil, nil, 251, nil, 251, 251, 251, 251, 251,
- 251, 251, nil, nil, nil, nil, nil, 251, 251, 251,
- 251, 251, 251, 251, nil, nil, 251, nil, nil, nil,
- nil, nil, nil, 251, nil, nil, 251, 251, 251, 251,
- 251, 251, 251, 251, nil, 251, 251, 251, nil, 251,
- 251, nil, 251, 251, 251, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 251, nil, nil, 251, nil, nil,
- 251, 251, nil, nil, 251, nil, nil, nil, nil, nil,
- 251, nil, nil, nil, nil, nil, nil, nil, nil, 251,
- nil, nil, nil, nil, 251, 251, 251, 251, nil, 251,
- 251, 251, 251, nil, nil, nil, nil, 251, 251, nil,
- nil, nil, 252, 252, 252, 251, 252, 251, 251, 251,
- 252, 252, nil, nil, nil, 252, nil, 252, 252, 252,
- 252, 252, 252, 252, nil, nil, nil, nil, nil, 252,
- 252, 252, 252, 252, 252, 252, nil, nil, 252, nil,
- nil, nil, nil, nil, nil, 252, nil, nil, 252, 252,
- 252, 252, 252, 252, 252, 252, nil, 252, 252, 252,
- nil, 252, 252, nil, 252, 252, 252, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 252, nil, nil, 252,
- nil, nil, 252, 252, nil, nil, 252, nil, nil, nil,
- nil, nil, 252, nil, nil, nil, nil, nil, nil, nil,
- nil, 252, nil, nil, nil, nil, 252, 252, 252, 252,
- nil, 252, 252, 252, 252, nil, nil, nil, nil, 252,
- 252, nil, nil, nil, 253, 253, 253, 252, 253, 252,
- 252, 252, 253, 253, nil, nil, nil, 253, nil, 253,
- 253, 253, 253, 253, 253, 253, nil, nil, nil, nil,
- nil, 253, 253, 253, 253, 253, 253, 253, nil, nil,
- 253, nil, nil, nil, nil, nil, nil, 253, nil, nil,
- 253, 253, 253, 253, 253, 253, 253, 253, nil, 253,
- 253, 253, nil, 253, 253, nil, 253, 253, 253, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 253, nil,
- nil, 253, nil, nil, 253, 253, nil, nil, 253, nil,
- nil, nil, nil, nil, 253, nil, nil, nil, nil, nil,
- nil, nil, nil, 253, nil, nil, nil, nil, 253, 253,
- 253, 253, nil, 253, 253, 253, 253, nil, nil, nil,
- nil, 253, 253, nil, nil, nil, 254, 254, 254, 253,
- 254, 253, 253, 253, 254, 254, nil, nil, nil, 254,
- nil, 254, 254, 254, 254, 254, 254, 254, nil, nil,
- nil, nil, nil, 254, 254, 254, 254, 254, 254, 254,
- nil, nil, 254, nil, nil, nil, nil, nil, nil, 254,
- nil, nil, 254, 254, 254, 254, 254, 254, 254, 254,
- nil, 254, 254, 254, nil, 254, 254, nil, 254, 254,
- 254, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 254, nil, nil, 254, nil, nil, 254, 254, nil, nil,
- 254, nil, nil, nil, nil, nil, 254, nil, nil, nil,
- nil, nil, nil, nil, nil, 254, nil, nil, nil, nil,
- 254, 254, 254, 254, nil, 254, 254, 254, 254, nil,
- nil, nil, nil, 254, 254, nil, nil, nil, 255, 255,
- 255, 254, 255, 254, 254, 254, 255, 255, nil, nil,
- nil, 255, nil, 255, 255, 255, 255, 255, 255, 255,
- nil, nil, nil, nil, nil, 255, 255, 255, 255, 255,
- 255, 255, nil, nil, 255, nil, nil, nil, nil, nil,
- nil, 255, nil, nil, 255, 255, 255, 255, 255, 255,
- 255, 255, nil, 255, 255, 255, nil, 255, 255, nil,
- 255, 255, 255, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 255, nil, nil, 255, nil, nil, 255, 255,
- nil, nil, 255, nil, nil, nil, nil, nil, 255, nil,
- nil, nil, nil, nil, nil, nil, nil, 255, nil, nil,
- nil, nil, 255, 255, 255, 255, nil, 255, 255, 255,
- 255, nil, nil, nil, nil, 255, 255, nil, nil, nil,
- 263, 263, 263, 255, 263, 255, 255, 255, 263, 263,
- nil, nil, nil, 263, nil, 263, 263, 263, 263, 263,
- 263, 263, nil, nil, nil, nil, nil, 263, 263, 263,
- 263, 263, 263, 263, nil, nil, 263, nil, nil, nil,
- nil, nil, nil, 263, nil, nil, 263, 263, 263, 263,
- 263, 263, 263, 263, 263, 263, 263, 263, nil, 263,
- 263, nil, 263, 263, 263, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 263, nil, nil, 263, nil, nil,
- 263, 263, nil, nil, 263, nil, 263, nil, 263, nil,
- 263, nil, nil, 263, nil, nil, nil, nil, nil, 263,
- nil, nil, nil, nil, 263, 263, 263, 263, nil, 263,
- 263, 263, 263, nil, nil, nil, nil, 263, 263, nil,
- nil, nil, 264, 264, 264, 263, 264, 263, 263, 263,
- 264, 264, nil, nil, nil, 264, nil, 264, 264, 264,
- 264, 264, 264, 264, nil, nil, nil, nil, nil, 264,
- 264, 264, 264, 264, 264, 264, nil, nil, 264, nil,
- nil, nil, nil, nil, nil, 264, nil, nil, 264, 264,
- 264, 264, 264, 264, 264, 264, 264, 264, 264, 264,
- nil, 264, 264, nil, 264, 264, 264, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 264, nil, nil, 264,
- nil, nil, 264, 264, nil, nil, 264, nil, 264, nil,
- 264, nil, 264, nil, nil, 264, nil, nil, nil, nil,
- nil, 264, nil, nil, nil, nil, 264, 264, 264, 264,
- nil, 264, 264, 264, 264, nil, nil, nil, nil, 264,
- 264, nil, nil, nil, 272, 272, 272, 264, 272, 264,
- 264, 264, 272, 272, nil, nil, nil, 272, nil, 272,
- 272, 272, 272, 272, 272, 272, nil, nil, nil, nil,
- nil, 272, 272, 272, 272, 272, 272, 272, nil, nil,
- 272, nil, nil, nil, nil, nil, nil, 272, nil, nil,
- 272, 272, 272, 272, 272, 272, 272, 272, 272, 272,
- 272, 272, nil, 272, 272, nil, 272, 272, 272, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 272, nil,
- nil, 272, nil, nil, 272, 272, nil, nil, 272, nil,
- 272, nil, 272, nil, 272, nil, nil, 272, nil, nil,
- nil, nil, nil, 272, nil, nil, nil, nil, 272, 272,
- 272, 272, nil, 272, 272, 272, 272, nil, nil, nil,
- nil, 272, 272, 272, nil, nil, 279, 279, 279, 272,
- 279, 272, 272, 272, 279, 279, nil, nil, nil, 279,
- nil, 279, 279, 279, 279, 279, 279, 279, nil, nil,
- nil, nil, nil, 279, 279, 279, 279, 279, 279, 279,
- nil, nil, 279, nil, nil, nil, nil, nil, nil, 279,
- nil, nil, 279, 279, 279, 279, 279, 279, 279, 279,
- nil, 279, 279, 279, nil, 279, 279, nil, 279, 279,
- 279, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 279, nil, nil, 279, nil, nil, 279, 279, nil, nil,
- 279, nil, nil, nil, nil, nil, 279, nil, nil, nil,
- nil, nil, nil, nil, nil, 279, nil, nil, nil, nil,
- 279, 279, 279, 279, nil, 279, 279, 279, 279, nil,
- nil, nil, nil, 279, 279, nil, nil, nil, 281, 281,
- 281, 279, 281, 279, 279, 279, 281, 281, nil, nil,
- nil, 281, nil, 281, 281, 281, 281, 281, 281, 281,
- nil, nil, nil, nil, nil, 281, 281, 281, 281, 281,
- 281, 281, nil, nil, 281, nil, nil, nil, nil, nil,
- nil, 281, nil, nil, 281, 281, 281, 281, 281, 281,
- 281, 281, nil, 281, 281, 281, nil, 281, 281, nil,
- 281, 281, 281, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 281, nil, nil, 281, nil, nil, 281, 281,
- nil, nil, 281, nil, nil, nil, nil, nil, 281, nil,
- nil, nil, nil, nil, nil, nil, nil, 281, nil, nil,
- nil, nil, 281, 281, 281, 281, nil, 281, 281, 281,
- 281, nil, nil, nil, nil, 281, 281, nil, nil, nil,
- 284, 284, 284, 281, 284, 281, 281, 281, 284, 284,
- nil, nil, nil, 284, nil, 284, 284, 284, 284, 284,
- 284, 284, nil, nil, nil, nil, nil, 284, 284, 284,
- 284, 284, 284, 284, nil, nil, 284, nil, nil, nil,
- nil, nil, nil, 284, nil, nil, 284, 284, 284, 284,
- 284, 284, 284, 284, nil, 284, 284, 284, nil, 284,
- 284, nil, 284, 284, 284, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 284, nil, nil, 284, nil, nil,
- 284, 284, nil, nil, 284, nil, nil, nil, nil, nil,
- 284, nil, nil, nil, nil, nil, nil, nil, nil, 284,
- nil, nil, nil, nil, 284, 284, 284, 284, nil, 284,
- 284, 284, 284, nil, nil, nil, nil, 284, 284, nil,
- nil, nil, 285, 285, 285, 284, 285, 284, 284, 284,
- 285, 285, nil, nil, nil, 285, nil, 285, 285, 285,
- 285, 285, 285, 285, nil, nil, nil, nil, nil, 285,
- 285, 285, 285, 285, 285, 285, nil, nil, 285, nil,
- nil, nil, nil, nil, nil, 285, nil, nil, 285, 285,
- 285, 285, 285, 285, 285, 285, nil, 285, 285, 285,
- nil, 285, 285, nil, 285, 285, 285, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 285, nil, nil, 285,
- nil, nil, 285, 285, nil, nil, 285, nil, nil, nil,
- nil, nil, 285, nil, nil, nil, nil, nil, nil, nil,
- nil, 285, nil, nil, nil, nil, 285, 285, 285, 285,
- nil, 285, 285, 285, 285, nil, nil, nil, nil, 285,
- 285, nil, nil, nil, nil, nil, nil, 285, nil, 285,
- 285, 285, 290, 290, 290, 290, 290, nil, nil, nil,
- 290, 290, nil, nil, nil, 290, nil, 290, 290, 290,
- 290, 290, 290, 290, nil, nil, nil, nil, nil, 290,
- 290, 290, 290, 290, 290, 290, nil, nil, 290, nil,
- nil, nil, nil, nil, 290, 290, nil, 290, 290, 290,
- 290, 290, 290, 290, 290, 290, nil, 290, 290, 290,
- nil, 290, 290, nil, 290, 290, 290, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 290, nil, nil, 290,
- nil, nil, 290, 290, nil, nil, 290, nil, 290, nil,
- nil, nil, 290, nil, nil, nil, nil, nil, nil, nil,
- nil, 290, nil, nil, nil, nil, 290, 290, 290, 290,
- nil, 290, 290, 290, 290, nil, nil, nil, nil, 290,
- 290, nil, nil, nil, 298, 298, 298, 290, 298, 290,
- 290, 290, 298, 298, nil, nil, nil, 298, nil, 298,
- 298, 298, 298, 298, 298, 298, nil, nil, nil, nil,
- nil, 298, 298, 298, 298, 298, 298, 298, nil, nil,
- 298, nil, nil, nil, nil, nil, nil, 298, nil, nil,
- 298, 298, 298, 298, 298, 298, 298, 298, nil, 298,
- 298, 298, nil, 298, 298, nil, nil, nil, 298, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 298, nil,
- nil, 298, nil, nil, 298, 298, nil, nil, 298, nil,
- 895, nil, 895, 895, 895, 895, 895, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 895, nil, 298, 298,
- 298, 298, nil, 298, 298, 298, 298, nil, nil, nil,
- nil, 298, 298, nil, nil, nil, 298, nil, 895, 298,
- nil, 298, 298, 298, 315, 315, 315, nil, 315, 895,
- 895, nil, 315, 315, 895, nil, nil, 315, nil, 315,
- 315, 315, 315, 315, 315, 315, nil, nil, nil, nil,
- nil, 315, 315, 315, 315, 315, 315, 315, nil, nil,
- 315, nil, nil, nil, nil, nil, nil, 315, nil, nil,
- 315, 315, 315, 315, 315, 315, 315, 315, nil, 315,
- 315, 315, nil, 315, 315, nil, nil, nil, 315, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 315, nil,
- nil, 315, nil, nil, 315, 315, nil, nil, 315, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 315, 315,
- 315, 315, nil, 315, 315, 315, 315, nil, nil, nil,
- nil, 315, 315, nil, nil, nil, 323, 323, 323, 315,
- 323, 315, 315, 315, 323, 323, nil, nil, nil, 323,
- nil, 323, 323, 323, 323, 323, 323, 323, nil, nil,
- nil, nil, nil, 323, 323, 323, 323, 323, 323, 323,
- nil, nil, 323, nil, nil, nil, nil, nil, nil, 323,
- nil, nil, 323, 323, 323, 323, 323, 323, 323, 323,
- nil, 323, 323, 323, nil, 323, 323, nil, 323, 323,
- 323, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 323, nil, nil, 323, 323, nil, 323, 323, nil, nil,
- 323, nil, nil, nil, nil, nil, 323, nil, nil, nil,
- nil, nil, nil, nil, nil, 323, nil, nil, nil, nil,
- 323, 323, 323, 323, nil, 323, 323, 323, 323, nil,
- nil, nil, nil, 323, 323, nil, nil, nil, 325, 325,
- 325, 323, 325, 323, 323, 323, 325, 325, nil, nil,
- nil, 325, nil, 325, 325, 325, 325, 325, 325, 325,
- nil, nil, nil, nil, nil, 325, 325, 325, 325, 325,
- 325, 325, nil, nil, 325, nil, nil, nil, nil, nil,
- nil, 325, nil, nil, 325, 325, 325, 325, 325, 325,
- 325, 325, nil, 325, 325, 325, nil, 325, 325, nil,
- 325, 325, 325, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 325, nil, nil, 325, nil, nil, 325, 325,
- nil, nil, 325, nil, nil, nil, nil, nil, 325, nil,
- nil, nil, nil, nil, nil, nil, nil, 325, nil, nil,
- nil, nil, 325, 325, 325, 325, nil, 325, 325, 325,
- 325, nil, nil, nil, nil, 325, 325, nil, nil, nil,
- 340, 340, 340, 325, 340, 325, 325, 325, 340, 340,
- nil, nil, nil, 340, nil, 340, 340, 340, 340, 340,
- 340, 340, nil, nil, nil, nil, nil, 340, 340, 340,
- 340, 340, 340, 340, nil, nil, 340, nil, nil, nil,
- nil, nil, nil, 340, nil, nil, 340, 340, 340, 340,
- 340, 340, 340, 340, nil, 340, 340, 340, nil, 340,
- 340, nil, 340, 340, 340, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 340, nil, nil, 340, nil, nil,
- 340, 340, nil, nil, 340, nil, nil, nil, nil, nil,
- 340, nil, nil, nil, nil, nil, nil, nil, nil, 340,
- nil, nil, nil, nil, 340, 340, 340, 340, nil, 340,
- 340, 340, 340, nil, nil, nil, nil, 340, 340, nil,
- nil, nil, 341, 341, 341, 340, 341, 340, 340, 340,
- 341, 341, nil, nil, nil, 341, nil, 341, 341, 341,
- 341, 341, 341, 341, nil, nil, nil, nil, nil, 341,
- 341, 341, 341, 341, 341, 341, nil, nil, 341, nil,
- nil, nil, nil, nil, nil, 341, nil, nil, 341, 341,
- 341, 341, 341, 341, 341, 341, nil, 341, 341, 341,
- nil, 341, 341, nil, 341, 341, 341, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 341, nil, nil, 341,
- nil, nil, 341, 341, nil, nil, 341, nil, nil, nil,
- nil, nil, 341, nil, nil, nil, nil, nil, nil, nil,
- nil, 341, nil, nil, nil, nil, 341, 341, 341, 341,
- nil, 341, 341, 341, 341, nil, nil, nil, nil, 341,
- 341, nil, nil, nil, 360, 360, 360, 341, 360, 341,
- 341, 341, 360, 360, nil, nil, nil, 360, nil, 360,
- 360, 360, 360, 360, 360, 360, nil, nil, nil, nil,
- nil, 360, 360, 360, 360, 360, 360, 360, nil, nil,
- 360, nil, nil, nil, nil, nil, nil, 360, nil, nil,
- 360, 360, 360, 360, 360, 360, 360, 360, nil, 360,
- 360, 360, nil, 360, 360, nil, 360, 360, 360, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 360, nil,
- nil, 360, nil, nil, 360, 360, nil, nil, 360, nil,
- nil, nil, nil, nil, 360, nil, nil, nil, nil, nil,
- nil, nil, nil, 360, nil, nil, nil, nil, 360, 360,
- 360, 360, nil, 360, 360, 360, 360, nil, nil, nil,
- nil, 360, 360, nil, nil, nil, 376, 376, 376, 360,
- 376, 360, 360, 360, 376, 376, nil, nil, nil, 376,
- nil, 376, 376, 376, 376, 376, 376, 376, nil, nil,
- nil, nil, nil, 376, 376, 376, 376, 376, 376, 376,
- nil, nil, 376, nil, nil, nil, nil, nil, nil, 376,
- nil, nil, 376, 376, 376, 376, 376, 376, 376, 376,
- nil, 376, 376, 376, nil, 376, 376, nil, 376, 376,
- 376, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 376, nil, nil, 376, nil, nil, 376, 376, nil, nil,
- 376, nil, nil, nil, nil, nil, 376, nil, nil, nil,
- nil, nil, nil, nil, nil, 376, nil, nil, nil, nil,
- 376, 376, 376, 376, nil, 376, 376, 376, 376, nil,
- nil, nil, nil, 376, 376, nil, nil, nil, 404, 404,
- 404, 376, 404, 376, 376, 376, 404, 404, nil, nil,
- nil, 404, nil, 404, 404, 404, 404, 404, 404, 404,
- nil, nil, nil, nil, nil, 404, 404, 404, 404, 404,
- 404, 404, nil, nil, 404, nil, nil, nil, nil, nil,
- nil, 404, nil, nil, 404, 404, 404, 404, 404, 404,
- 404, 404, nil, 404, 404, 404, nil, 404, 404, nil,
- 404, 404, 404, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 404, nil, nil, 404, nil, nil, 404, 404,
- nil, nil, 404, nil, nil, nil, nil, nil, 404, nil,
- nil, nil, nil, nil, nil, nil, nil, 404, nil, nil,
- nil, nil, 404, 404, 404, 404, nil, 404, 404, 404,
- 404, nil, nil, nil, nil, 404, 404, nil, nil, nil,
- 442, 442, 442, 404, 442, 404, 404, 404, 442, 442,
- nil, nil, nil, 442, nil, 442, 442, 442, 442, 442,
- 442, 442, nil, nil, nil, nil, nil, 442, 442, 442,
- 442, 442, 442, 442, nil, nil, 442, nil, nil, nil,
- nil, nil, nil, 442, nil, nil, 442, 442, 442, 442,
- 442, 442, 442, 442, 442, 442, 442, 442, nil, 442,
- 442, nil, 442, 442, 442, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 442, nil, nil, 442, nil, nil,
- 442, 442, nil, nil, 442, nil, 442, nil, 442, nil,
- 442, nil, nil, 442, nil, nil, nil, nil, nil, 442,
- nil, nil, nil, nil, 442, 442, 442, 442, nil, 442,
- 442, 442, 442, nil, nil, nil, nil, 442, 442, nil,
- nil, nil, 444, 444, 444, 442, 444, 442, 442, 442,
- 444, 444, nil, nil, nil, 444, nil, 444, 444, 444,
- 444, 444, 444, 444, nil, nil, nil, nil, nil, 444,
- 444, 444, 444, 444, 444, 444, nil, nil, 444, nil,
- nil, nil, nil, nil, nil, 444, nil, nil, 444, 444,
- 444, 444, 444, 444, 444, 444, nil, 444, 444, 444,
- nil, 444, 444, nil, 444, 444, 444, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 444, nil, nil, 444,
- nil, nil, 444, 444, nil, nil, 444, nil, nil, nil,
- nil, nil, 444, nil, nil, nil, nil, nil, nil, nil,
- nil, 444, nil, nil, nil, nil, 444, 444, 444, 444,
- nil, 444, 444, 444, 444, nil, nil, nil, nil, 444,
- 444, nil, nil, nil, 445, 445, 445, 444, 445, 444,
- 444, 444, 445, 445, nil, nil, nil, 445, nil, 445,
- 445, 445, 445, 445, 445, 445, nil, nil, nil, nil,
- nil, 445, 445, 445, 445, 445, 445, 445, nil, nil,
- 445, nil, nil, nil, nil, nil, nil, 445, nil, nil,
- 445, 445, 445, 445, 445, 445, 445, 445, nil, 445,
- 445, 445, nil, 445, 445, nil, 445, 445, 445, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 445, nil,
- nil, 445, nil, nil, 445, 445, nil, nil, 445, nil,
- nil, nil, nil, nil, 445, nil, nil, nil, nil, nil,
- nil, nil, nil, 445, nil, nil, nil, nil, 445, 445,
- 445, 445, nil, 445, 445, 445, 445, nil, nil, nil,
- nil, 445, 445, nil, nil, nil, 446, 446, 446, 445,
- 446, 445, 445, 445, 446, 446, nil, nil, nil, 446,
- nil, 446, 446, 446, 446, 446, 446, 446, nil, nil,
- nil, nil, nil, 446, 446, 446, 446, 446, 446, 446,
- nil, nil, 446, nil, nil, nil, nil, nil, nil, 446,
- nil, nil, 446, 446, 446, 446, 446, 446, 446, 446,
- nil, 446, 446, 446, nil, 446, 446, nil, 446, 446,
- 446, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 446, nil, nil, 446, nil, nil, 446, 446, nil, nil,
- 446, nil, nil, nil, nil, nil, 446, nil, nil, nil,
- nil, nil, nil, nil, nil, 446, nil, nil, nil, nil,
- 446, 446, 446, 446, nil, 446, 446, 446, 446, nil,
- nil, nil, nil, 446, 446, nil, nil, nil, 472, 472,
- 472, 446, 472, 446, 446, 446, 472, 472, nil, nil,
- nil, 472, nil, 472, 472, 472, 472, 472, 472, 472,
- nil, nil, nil, nil, nil, 472, 472, 472, 472, 472,
- 472, 472, nil, nil, 472, nil, nil, nil, nil, nil,
- nil, 472, nil, nil, 472, 472, 472, 472, 472, 472,
- 472, 472, nil, 472, 472, 472, nil, 472, 472, nil,
- 472, 472, 472, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 472, nil, nil, 472, nil, nil, 472, 472,
- nil, nil, 472, nil, nil, nil, nil, nil, 472, nil,
- nil, nil, nil, nil, nil, nil, nil, 472, nil, nil,
- nil, nil, 472, 472, 472, 472, nil, 472, 472, 472,
- 472, nil, nil, nil, nil, 472, 472, nil, nil, nil,
- 486, 486, 486, 472, 486, 472, 472, 472, 486, 486,
- nil, nil, nil, 486, nil, 486, 486, 486, 486, 486,
- 486, 486, nil, nil, nil, nil, nil, 486, 486, 486,
- 486, 486, 486, 486, nil, nil, 486, nil, nil, nil,
- nil, nil, nil, 486, nil, nil, 486, 486, 486, 486,
- 486, 486, 486, 486, 486, 486, 486, 486, nil, 486,
- 486, nil, 486, 486, 486, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 486, nil, nil, 486, nil, nil,
- 486, 486, nil, nil, 486, nil, 486, nil, 486, nil,
- 486, nil, nil, 486, nil, nil, nil, nil, nil, 486,
- nil, nil, nil, nil, 486, 486, 486, 486, nil, 486,
- 486, 486, 486, nil, nil, nil, nil, 486, 486, nil,
- nil, nil, 488, 488, 488, 486, 488, 486, 486, 486,
- 488, 488, nil, nil, nil, 488, nil, 488, 488, 488,
- 488, 488, 488, 488, nil, nil, nil, nil, nil, 488,
- 488, 488, 488, 488, 488, 488, nil, nil, 488, nil,
- nil, nil, nil, nil, nil, 488, nil, nil, 488, 488,
- 488, 488, 488, 488, 488, 488, 488, 488, 488, 488,
- nil, 488, 488, nil, 488, 488, 488, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 488, nil, nil, 488,
- nil, nil, 488, 488, nil, nil, 488, nil, nil, nil,
- 488, nil, 488, nil, nil, 488, nil, nil, nil, nil,
- nil, 488, nil, nil, nil, nil, 488, 488, 488, 488,
- nil, 488, 488, 488, 488, nil, nil, nil, nil, 488,
- 488, nil, nil, nil, 490, 490, 490, 488, 490, 488,
- 488, 488, 490, 490, nil, nil, nil, 490, nil, 490,
- 490, 490, 490, 490, 490, 490, nil, nil, nil, nil,
- nil, 490, 490, 490, 490, 490, 490, 490, nil, nil,
- 490, nil, nil, nil, nil, nil, nil, 490, nil, nil,
- 490, 490, 490, 490, 490, 490, 490, 490, nil, 490,
- 490, 490, nil, 490, 490, nil, 490, 490, 490, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 490, nil,
- nil, 490, nil, nil, 490, 490, nil, nil, 490, nil,
- nil, nil, nil, nil, 490, nil, nil, nil, nil, nil,
- nil, nil, nil, 490, nil, nil, nil, nil, 490, 490,
- 490, 490, nil, 490, 490, 490, 490, nil, nil, nil,
- nil, 490, 490, nil, nil, nil, nil, nil, nil, 490,
- nil, 490, 490, 490, 496, 496, 496, 496, 496, nil,
- nil, nil, 496, 496, nil, nil, nil, 496, nil, 496,
- 496, 496, 496, 496, 496, 496, nil, nil, nil, nil,
- nil, 496, 496, 496, 496, 496, 496, 496, nil, nil,
- 496, nil, nil, nil, nil, nil, 496, 496, 496, 496,
- 496, 496, 496, 496, 496, 496, 496, 496, nil, 496,
- 496, 496, nil, 496, 496, nil, 496, 496, 496, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 496, nil,
- nil, 496, nil, nil, 496, 496, nil, nil, 496, nil,
- 496, nil, nil, nil, 496, nil, nil, nil, nil, nil,
- nil, nil, nil, 496, nil, nil, nil, nil, 496, 496,
- 496, 496, nil, 496, 496, 496, 496, nil, nil, nil,
- nil, 496, 496, nil, nil, nil, nil, nil, 496, 496,
- nil, 496, 496, 496, 504, 504, 504, nil, 504, nil,
- nil, nil, 504, 504, nil, nil, nil, 504, nil, 504,
- 504, 504, 504, 504, 504, 504, nil, nil, nil, nil,
- nil, 504, 504, 504, 504, 504, 504, 504, nil, nil,
- 504, nil, nil, nil, nil, nil, nil, 504, nil, nil,
- 504, 504, 504, 504, 504, 504, 504, 504, nil, 504,
- 504, 504, nil, 504, 504, nil, nil, nil, 504, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 504, nil,
- nil, 504, nil, nil, 504, 504, nil, nil, 504, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 504, 504,
- 504, 504, nil, 504, 504, 504, 504, nil, nil, nil,
- nil, 504, 504, nil, nil, nil, 506, 506, 506, 504,
- 506, 504, 504, 504, 506, 506, nil, nil, nil, 506,
- nil, 506, 506, 506, 506, 506, 506, 506, nil, nil,
- nil, nil, nil, 506, 506, 506, 506, 506, 506, 506,
- nil, nil, 506, nil, nil, nil, nil, nil, nil, 506,
- nil, nil, 506, 506, 506, 506, 506, 506, 506, 506,
- 506, 506, 506, 506, nil, 506, 506, nil, 506, 506,
- 506, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 506, nil, nil, 506, nil, nil, 506, 506, nil, nil,
- 506, nil, 506, nil, 506, nil, 506, nil, nil, 506,
- nil, nil, nil, nil, nil, 506, nil, nil, nil, nil,
- 506, 506, 506, 506, nil, 506, 506, 506, 506, nil,
- nil, nil, nil, 506, 506, nil, nil, nil, 512, 512,
- 512, 506, 512, 506, 506, 506, 512, 512, nil, nil,
- nil, 512, nil, 512, 512, 512, 512, 512, 512, 512,
- nil, nil, nil, nil, nil, 512, 512, 512, 512, 512,
- 512, 512, nil, nil, 512, nil, nil, nil, nil, nil,
- nil, 512, nil, nil, 512, 512, 512, 512, 512, 512,
- 512, 512, nil, 512, 512, 512, nil, 512, 512, nil,
- nil, nil, 512, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 512, nil, nil, 512, nil, nil, 512, 512,
- nil, nil, 512, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 512, 512, 512, 512, nil, 512, 512, 512,
- 512, nil, nil, nil, nil, 512, 512, nil, nil, nil,
- 515, 515, 515, 512, 515, 512, 512, 512, 515, 515,
- nil, nil, nil, 515, nil, 515, 515, 515, 515, 515,
- 515, 515, nil, nil, nil, nil, nil, 515, 515, 515,
- 515, 515, 515, 515, nil, nil, 515, nil, nil, nil,
- nil, nil, nil, 515, nil, nil, 515, 515, 515, 515,
- 515, 515, 515, 515, nil, 515, 515, 515, nil, 515,
- 515, nil, 515, 515, 515, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 515, nil, nil, 515, nil, nil,
- 515, 515, nil, nil, 515, nil, nil, nil, nil, nil,
- 515, nil, nil, nil, nil, nil, nil, nil, nil, 515,
- nil, nil, nil, nil, 515, 515, 515, 515, nil, 515,
- 515, 515, 515, nil, nil, nil, nil, 515, 515, nil,
- nil, nil, 516, 516, 516, 515, 516, 515, 515, 515,
- 516, 516, nil, nil, nil, 516, nil, 516, 516, 516,
- 516, 516, 516, 516, nil, nil, nil, nil, nil, 516,
- 516, 516, 516, 516, 516, 516, nil, nil, 516, nil,
- nil, nil, nil, nil, nil, 516, nil, nil, 516, 516,
- 516, 516, 516, 516, 516, 516, nil, 516, 516, 516,
- nil, 516, 516, nil, 516, 516, 516, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 516, nil, nil, 516,
- nil, nil, 516, 516, nil, nil, 516, nil, nil, nil,
- nil, nil, 516, nil, nil, nil, nil, nil, nil, nil,
- nil, 516, nil, nil, nil, nil, 516, 516, 516, 516,
- nil, 516, 516, 516, 516, nil, nil, nil, nil, 516,
- 516, nil, nil, nil, 520, 520, 520, 516, 520, 516,
- 516, 516, 520, 520, nil, nil, nil, 520, nil, 520,
- 520, 520, 520, 520, 520, 520, nil, nil, nil, nil,
- nil, 520, 520, 520, 520, 520, 520, 520, nil, nil,
- 520, nil, nil, nil, nil, nil, nil, 520, nil, nil,
- 520, 520, 520, 520, 520, 520, 520, 520, nil, 520,
- 520, 520, nil, 520, 520, nil, 520, 520, 520, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 520, nil,
- nil, 520, nil, nil, 520, 520, nil, nil, 520, nil,
- nil, nil, nil, nil, 520, nil, nil, nil, nil, nil,
- nil, nil, nil, 520, nil, nil, nil, nil, 520, 520,
- 520, 520, nil, 520, 520, 520, 520, nil, nil, nil,
- nil, 520, 520, nil, nil, nil, 526, 526, 526, 520,
- 526, 520, 520, 520, 526, 526, nil, nil, nil, 526,
- nil, 526, 526, 526, 526, 526, 526, 526, nil, nil,
- nil, nil, nil, 526, 526, 526, 526, 526, 526, 526,
- nil, nil, 526, nil, nil, nil, nil, nil, nil, 526,
- nil, nil, 526, 526, 526, 526, 526, 526, 526, 526,
- 526, 526, 526, 526, nil, 526, 526, nil, 526, 526,
- 526, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 526, nil, nil, 526, nil, nil, 526, 526, nil, nil,
- 526, nil, 526, nil, nil, nil, 526, nil, nil, 526,
- nil, nil, nil, nil, nil, 526, nil, nil, nil, nil,
- 526, 526, 526, 526, nil, 526, 526, 526, 526, nil,
- nil, nil, nil, 526, 526, nil, nil, nil, 529, 529,
- 529, 526, 529, 526, 526, 526, 529, 529, nil, nil,
- nil, 529, nil, 529, 529, 529, 529, 529, 529, 529,
- nil, nil, nil, nil, nil, 529, 529, 529, 529, 529,
- 529, 529, nil, nil, 529, nil, nil, nil, nil, nil,
- nil, 529, nil, nil, 529, 529, 529, 529, 529, 529,
- 529, 529, 529, 529, 529, 529, nil, 529, 529, nil,
- 529, 529, 529, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 529, nil, nil, 529, nil, nil, 529, 529,
- nil, nil, 529, nil, nil, nil, nil, nil, 529, nil,
- nil, 529, nil, nil, nil, nil, nil, 529, nil, nil,
- nil, nil, 529, 529, 529, 529, nil, 529, 529, 529,
- 529, nil, nil, nil, nil, 529, 529, nil, nil, nil,
- 554, 554, 554, 529, 554, 529, 529, 529, 554, 554,
- nil, nil, nil, 554, nil, 554, 554, 554, 554, 554,
- 554, 554, nil, nil, nil, nil, nil, 554, 554, 554,
- 554, 554, 554, 554, nil, nil, 554, nil, nil, nil,
- nil, nil, nil, 554, nil, nil, 554, 554, 554, 554,
- 554, 554, 554, 554, nil, 554, 554, 554, nil, 554,
- 554, nil, 554, 554, 554, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 554, nil, nil, 554, nil, nil,
- 554, 554, nil, nil, 554, nil, nil, nil, nil, nil,
- 554, nil, nil, nil, nil, nil, nil, nil, nil, 554,
- nil, nil, nil, nil, 554, 554, 554, 554, nil, 554,
- 554, 554, 554, nil, nil, nil, nil, 554, 554, nil,
- nil, nil, 574, 574, 574, 554, 574, 554, 554, 554,
- 574, 574, nil, nil, nil, 574, nil, 574, 574, 574,
- 574, 574, 574, 574, nil, nil, nil, nil, nil, 574,
- 574, 574, 574, 574, 574, 574, nil, nil, 574, nil,
- nil, nil, nil, nil, nil, 574, nil, nil, 574, 574,
- 574, 574, 574, 574, 574, 574, nil, 574, 574, 574,
- nil, 574, 574, nil, 574, 574, 574, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 574, nil, nil, 574,
- nil, nil, 574, 574, nil, nil, 574, nil, 574, nil,
- nil, nil, 574, nil, nil, nil, nil, nil, nil, nil,
- nil, 574, nil, nil, nil, nil, 574, 574, 574, 574,
- nil, 574, 574, 574, 574, nil, nil, nil, nil, 574,
- 574, nil, nil, nil, 575, 575, 575, 574, 575, 574,
- 574, 574, 575, 575, nil, nil, nil, 575, nil, 575,
- 575, 575, 575, 575, 575, 575, nil, nil, nil, nil,
- nil, 575, 575, 575, 575, 575, 575, 575, nil, nil,
- 575, nil, nil, nil, nil, nil, nil, 575, nil, nil,
- 575, 575, 575, 575, 575, 575, 575, 575, 575, 575,
- 575, 575, nil, 575, 575, nil, 575, 575, 575, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 575, nil,
- nil, 575, nil, nil, 575, 575, nil, nil, 575, nil,
- 575, nil, 575, nil, 575, nil, nil, 575, nil, nil,
- nil, nil, nil, 575, nil, nil, nil, nil, 575, 575,
- 575, 575, nil, 575, 575, 575, 575, nil, nil, nil,
- nil, 575, 575, nil, nil, nil, 585, 585, 585, 575,
- 585, 575, 575, 575, 585, 585, nil, nil, nil, 585,
- nil, 585, 585, 585, 585, 585, 585, 585, nil, nil,
- nil, nil, nil, 585, 585, 585, 585, 585, 585, 585,
- nil, nil, 585, nil, nil, nil, nil, nil, nil, 585,
- nil, nil, 585, 585, 585, 585, 585, 585, 585, 585,
- 585, 585, 585, 585, nil, 585, 585, nil, 585, 585,
- 585, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 585, nil, nil, 585, nil, nil, 585, 585, nil, nil,
- 585, nil, 585, nil, 585, nil, 585, nil, nil, 585,
- nil, nil, nil, nil, nil, 585, nil, nil, nil, nil,
- 585, 585, 585, 585, nil, 585, 585, 585, 585, nil,
- nil, nil, nil, 585, 585, nil, nil, nil, 619, 619,
- 619, 585, 619, 585, 585, 585, 619, 619, nil, nil,
- nil, 619, nil, 619, 619, 619, 619, 619, 619, 619,
- nil, nil, nil, nil, nil, 619, 619, 619, 619, 619,
- 619, 619, nil, nil, 619, nil, nil, nil, nil, nil,
- nil, 619, nil, nil, 619, 619, 619, 619, 619, 619,
- 619, 619, nil, 619, 619, 619, nil, 619, 619, nil,
- 619, 619, 619, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 619, nil, nil, 619, nil, nil, 619, 619,
- nil, nil, 619, nil, 619, nil, nil, nil, 619, nil,
- nil, nil, nil, nil, nil, nil, nil, 619, nil, nil,
- nil, nil, 619, 619, 619, 619, nil, 619, 619, 619,
- 619, nil, nil, nil, nil, 619, 619, nil, nil, nil,
- 620, 620, 620, 619, 620, 619, 619, 619, 620, 620,
- nil, nil, nil, 620, nil, 620, 620, 620, 620, 620,
- 620, 620, nil, nil, nil, nil, nil, 620, 620, 620,
- 620, 620, 620, 620, nil, nil, 620, nil, nil, nil,
- nil, nil, nil, 620, nil, nil, 620, 620, 620, 620,
- 620, 620, 620, 620, nil, 620, 620, 620, nil, 620,
- 620, nil, 620, 620, 620, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 620, nil, nil, 620, nil, nil,
- 620, 620, nil, nil, 620, nil, nil, nil, nil, nil,
- 620, nil, nil, nil, nil, nil, nil, nil, nil, 620,
- nil, nil, nil, nil, 620, 620, 620, 620, nil, 620,
- 620, 620, 620, nil, nil, nil, nil, 620, 620, nil,
- nil, nil, 623, 623, 623, 620, 623, 620, 620, 620,
- 623, 623, nil, nil, nil, 623, nil, 623, 623, 623,
- 623, 623, 623, 623, nil, nil, nil, nil, nil, 623,
- 623, 623, 623, 623, 623, 623, nil, nil, 623, nil,
- nil, nil, nil, nil, nil, 623, nil, nil, 623, 623,
- 623, 623, 623, 623, 623, 623, 623, 623, 623, 623,
- nil, 623, 623, nil, 623, 623, 623, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 623, nil, nil, 623,
- nil, nil, 623, 623, nil, nil, 623, nil, 623, nil,
- 623, nil, 623, nil, nil, 623, nil, nil, nil, nil,
- nil, 623, nil, nil, nil, nil, 623, 623, 623, 623,
- nil, 623, 623, 623, 623, nil, nil, nil, nil, 623,
- 623, nil, nil, nil, 624, 624, 624, 623, 624, 623,
- 623, 623, 624, 624, nil, nil, nil, 624, nil, 624,
- 624, 624, 624, 624, 624, 624, nil, nil, nil, nil,
- nil, 624, 624, 624, 624, 624, 624, 624, nil, nil,
- 624, nil, nil, nil, nil, nil, nil, 624, nil, nil,
- 624, 624, 624, 624, 624, 624, 624, 624, 624, 624,
- 624, 624, nil, 624, 624, nil, 624, 624, 624, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 624, nil,
- nil, 624, nil, nil, 624, 624, nil, nil, 624, nil,
- nil, nil, 624, nil, 624, nil, nil, 624, nil, nil,
- nil, nil, nil, 624, nil, nil, nil, nil, 624, 624,
- 624, 624, nil, 624, 624, 624, 624, nil, nil, nil,
- nil, 624, 624, nil, nil, nil, 625, 625, 625, 624,
- 625, 624, 624, 624, 625, 625, nil, nil, nil, 625,
- nil, 625, 625, 625, 625, 625, 625, 625, nil, nil,
- nil, nil, nil, 625, 625, 625, 625, 625, 625, 625,
- nil, nil, 625, nil, nil, nil, nil, nil, nil, 625,
- nil, nil, 625, 625, 625, 625, 625, 625, 625, 625,
- nil, 625, 625, 625, nil, 625, 625, nil, 625, 625,
- 625, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 625, nil, nil, 625, nil, nil, 625, 625, nil, nil,
- 625, nil, nil, nil, nil, nil, 625, nil, nil, nil,
- nil, nil, nil, nil, nil, 625, nil, nil, nil, nil,
- 625, 625, 625, 625, nil, 625, 625, 625, 625, nil,
- nil, nil, nil, 625, 625, nil, nil, nil, 626, 626,
- 626, 625, 626, 625, 625, 625, 626, 626, nil, nil,
- nil, 626, nil, 626, 626, 626, 626, 626, 626, 626,
- nil, nil, nil, nil, nil, 626, 626, 626, 626, 626,
- 626, 626, nil, nil, 626, nil, nil, nil, nil, nil,
- nil, 626, nil, nil, 626, 626, 626, 626, 626, 626,
- 626, 626, nil, 626, 626, 626, nil, 626, 626, nil,
- 626, 626, 626, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 626, nil, nil, 626, nil, nil, 626, 626,
- nil, nil, 626, nil, nil, nil, nil, nil, 626, nil,
- nil, nil, nil, nil, nil, nil, nil, 626, nil, nil,
- nil, nil, 626, 626, 626, 626, nil, 626, 626, 626,
- 626, nil, nil, nil, nil, 626, 626, nil, nil, nil,
- 630, 630, 630, 626, 630, 626, 626, 626, 630, 630,
- nil, nil, nil, 630, nil, 630, 630, 630, 630, 630,
- 630, 630, nil, nil, nil, nil, nil, 630, 630, 630,
- 630, 630, 630, 630, nil, nil, 630, nil, nil, nil,
- nil, nil, nil, 630, nil, nil, 630, 630, 630, 630,
- 630, 630, 630, 630, nil, 630, 630, 630, nil, 630,
- 630, nil, 630, 630, 630, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 630, nil, nil, 630, nil, nil,
- 630, 630, nil, nil, 630, nil, nil, nil, nil, nil,
- 630, nil, nil, nil, nil, nil, nil, nil, nil, 630,
- nil, nil, nil, nil, 630, 630, 630, 630, nil, 630,
- 630, 630, 630, nil, nil, nil, nil, 630, 630, nil,
- nil, nil, 631, 631, 631, 630, 631, 630, 630, 630,
- 631, 631, nil, nil, nil, 631, nil, 631, 631, 631,
- 631, 631, 631, 631, nil, nil, nil, nil, nil, 631,
- 631, 631, 631, 631, 631, 631, nil, nil, 631, nil,
- nil, nil, nil, nil, nil, 631, nil, nil, 631, 631,
- 631, 631, 631, 631, 631, 631, nil, 631, 631, 631,
- nil, 631, 631, nil, 631, 631, 631, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 631, nil, nil, 631,
- nil, nil, 631, 631, nil, nil, 631, nil, nil, nil,
- nil, nil, 631, nil, nil, nil, nil, nil, nil, nil,
- nil, 631, nil, nil, nil, nil, 631, 631, 631, 631,
- nil, 631, 631, 631, 631, nil, nil, nil, nil, 631,
- 631, nil, nil, nil, 634, 634, 634, 631, 634, 631,
- 631, 631, 634, 634, nil, nil, nil, 634, nil, 634,
- 634, 634, 634, 634, 634, 634, nil, nil, nil, nil,
- nil, 634, 634, 634, 634, 634, 634, 634, nil, nil,
- 634, nil, nil, nil, nil, nil, nil, 634, nil, nil,
- 634, 634, 634, 634, 634, 634, 634, 634, nil, 634,
- 634, 634, nil, 634, 634, nil, 634, 634, 634, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 634, nil,
- nil, 634, nil, nil, 634, 634, nil, nil, 634, nil,
- nil, nil, nil, nil, 634, nil, nil, nil, nil, nil,
- nil, nil, nil, 634, nil, nil, nil, nil, 634, 634,
- 634, 634, nil, 634, 634, 634, 634, nil, nil, nil,
- nil, 634, 634, nil, nil, nil, 635, 635, 635, 634,
- 635, 634, 634, 634, 635, 635, nil, nil, nil, 635,
- nil, 635, 635, 635, 635, 635, 635, 635, nil, nil,
- nil, nil, nil, 635, 635, 635, 635, 635, 635, 635,
- nil, nil, 635, nil, nil, nil, nil, nil, nil, 635,
- nil, nil, 635, 635, 635, 635, 635, 635, 635, 635,
- nil, 635, 635, 635, nil, 635, 635, nil, 635, 635,
- 635, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 635, nil, nil, 635, nil, nil, 635, 635, nil, nil,
- 635, nil, nil, nil, nil, nil, 635, nil, nil, nil,
- nil, nil, nil, nil, nil, 635, nil, nil, nil, nil,
- 635, 635, 635, 635, nil, 635, 635, 635, 635, nil,
- nil, nil, nil, 635, 635, nil, nil, nil, 659, 659,
- 659, 635, 659, 635, 635, 635, 659, 659, nil, nil,
- nil, 659, nil, 659, 659, 659, 659, 659, 659, 659,
- nil, nil, nil, nil, nil, 659, 659, 659, 659, 659,
- 659, 659, nil, nil, 659, nil, nil, nil, nil, nil,
- nil, 659, nil, nil, 659, 659, 659, 659, 659, 659,
- 659, 659, nil, 659, 659, 659, nil, 659, 659, nil,
- 659, 659, 659, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 659, nil, nil, 659, nil, nil, 659, 659,
- nil, nil, 659, nil, nil, nil, nil, nil, 659, nil,
- nil, nil, nil, nil, nil, nil, nil, 659, nil, nil,
- nil, nil, 659, 659, 659, 659, nil, 659, 659, 659,
- 659, nil, nil, nil, nil, 659, 659, nil, nil, nil,
- 662, 662, 662, 659, 662, 659, 659, 659, 662, 662,
- nil, nil, nil, 662, nil, 662, 662, 662, 662, 662,
- 662, 662, nil, nil, nil, nil, nil, 662, 662, 662,
- 662, 662, 662, 662, nil, nil, 662, nil, nil, nil,
- nil, nil, nil, 662, nil, nil, 662, 662, 662, 662,
- 662, 662, 662, 662, nil, 662, 662, 662, nil, 662,
- 662, nil, 662, 662, 662, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 662, nil, nil, 662, nil, nil,
- 662, 662, nil, nil, 662, nil, nil, nil, nil, nil,
- 662, nil, nil, nil, nil, nil, nil, nil, nil, 662,
- nil, nil, nil, nil, 662, 662, 662, 662, nil, 662,
- 662, 662, 662, nil, nil, nil, nil, 662, 662, nil,
- nil, nil, 666, 666, 666, 662, 666, 662, 662, 662,
- 666, 666, nil, nil, nil, 666, nil, 666, 666, 666,
- 666, 666, 666, 666, nil, nil, nil, nil, nil, 666,
- 666, 666, 666, 666, 666, 666, nil, nil, 666, nil,
- nil, nil, nil, nil, nil, 666, nil, nil, 666, 666,
- 666, 666, 666, 666, 666, 666, nil, 666, 666, 666,
- nil, 666, 666, nil, nil, nil, 666, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 666, nil, nil, 666,
- nil, nil, 666, 666, nil, nil, 666, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 666, 666, 666, 666,
- nil, 666, 666, 666, 666, nil, nil, nil, nil, 666,
- 666, nil, nil, nil, 677, 677, 677, 666, 677, 666,
- 666, 666, 677, 677, nil, nil, nil, 677, nil, 677,
- 677, 677, 677, 677, 677, 677, nil, nil, nil, nil,
- nil, 677, 677, 677, 677, 677, 677, 677, nil, nil,
- 677, nil, nil, nil, nil, nil, nil, 677, nil, nil,
- 677, 677, 677, 677, 677, 677, 677, 677, nil, 677,
- 677, 677, nil, 677, 677, nil, nil, nil, 677, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 677, nil,
- nil, 677, nil, nil, 677, 677, nil, nil, 677, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 677, 677,
- 677, 677, nil, 677, 677, 677, 677, nil, nil, nil,
- nil, 677, 677, nil, nil, nil, 682, 682, 682, 677,
- 682, 677, 677, 677, 682, 682, nil, nil, nil, 682,
- nil, 682, 682, 682, 682, 682, 682, 682, nil, nil,
- nil, nil, nil, 682, 682, 682, 682, 682, 682, 682,
- nil, nil, 682, nil, nil, nil, nil, nil, nil, 682,
- nil, nil, 682, 682, 682, 682, 682, 682, 682, 682,
- nil, 682, 682, 682, nil, 682, 682, nil, 682, 682,
- 682, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 682, nil, nil, 682, nil, nil, 682, 682, nil, nil,
- 682, nil, 682, nil, nil, nil, 682, nil, nil, nil,
- nil, nil, nil, nil, nil, 682, nil, nil, nil, nil,
- 682, 682, 682, 682, nil, 682, 682, 682, 682, nil,
- nil, nil, nil, 682, 682, nil, nil, nil, 699, 699,
- 699, 682, 699, 682, 682, 682, 699, 699, nil, nil,
- nil, 699, nil, 699, 699, 699, 699, 699, 699, 699,
- nil, nil, nil, nil, nil, 699, 699, 699, 699, 699,
- 699, 699, nil, nil, 699, nil, nil, nil, nil, nil,
- nil, 699, nil, nil, 699, 699, 699, 699, 699, 699,
- 699, 699, nil, 699, 699, 699, nil, 699, 699, nil,
- 699, 699, 699, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 699, nil, nil, 699, nil, nil, 699, 699,
- nil, nil, 699, nil, nil, nil, nil, nil, 699, nil,
- nil, nil, nil, nil, nil, nil, nil, 699, nil, nil,
- nil, nil, 699, 699, 699, 699, nil, 699, 699, 699,
- 699, nil, nil, nil, nil, 699, 699, nil, nil, nil,
- 725, 725, 725, 699, 725, 699, 699, 699, 725, 725,
- nil, nil, nil, 725, nil, 725, 725, 725, 725, 725,
- 725, 725, nil, nil, nil, nil, nil, 725, 725, 725,
- 725, 725, 725, 725, nil, nil, 725, nil, nil, nil,
- nil, nil, nil, 725, nil, nil, 725, 725, 725, 725,
- 725, 725, 725, 725, nil, 725, 725, 725, nil, 725,
- 725, nil, 725, 725, 725, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 725, nil, nil, 725, nil, nil,
- 725, 725, nil, nil, 725, nil, nil, nil, nil, nil,
- 725, nil, nil, nil, nil, nil, nil, nil, nil, 725,
- nil, nil, nil, nil, 725, 725, 725, 725, nil, 725,
- 725, 725, 725, nil, nil, nil, nil, 725, 725, nil,
- nil, nil, 731, 731, 731, 725, 731, 725, 725, 725,
- 731, 731, nil, nil, nil, 731, nil, 731, 731, 731,
- 731, 731, 731, 731, nil, nil, nil, nil, nil, 731,
- 731, 731, 731, 731, 731, 731, nil, nil, 731, nil,
- nil, nil, nil, nil, nil, 731, nil, nil, 731, 731,
- 731, 731, 731, 731, 731, 731, nil, 731, 731, 731,
- nil, 731, 731, nil, 731, 731, 731, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 731, nil, nil, 731,
- nil, nil, 731, 731, nil, nil, 731, nil, nil, nil,
- nil, nil, 731, nil, nil, nil, nil, nil, nil, nil,
- nil, 731, nil, nil, nil, nil, 731, 731, 731, 731,
- nil, 731, 731, 731, 731, nil, nil, nil, nil, 731,
- 731, nil, nil, nil, 754, 754, 754, 731, 754, 731,
- 731, 731, 754, 754, nil, nil, nil, 754, nil, 754,
- 754, 754, 754, 754, 754, 754, nil, nil, nil, nil,
- nil, 754, 754, 754, 754, 754, 754, 754, nil, nil,
- 754, nil, nil, nil, nil, nil, nil, 754, nil, nil,
- 754, 754, 754, 754, 754, 754, 754, 754, nil, 754,
- 754, 754, nil, 754, 754, nil, 754, 754, 754, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 754, nil,
- nil, 754, nil, nil, 754, 754, nil, nil, 754, nil,
- nil, nil, nil, nil, 754, nil, nil, nil, nil, nil,
- nil, nil, nil, 754, nil, nil, nil, nil, 754, 754,
- 754, 754, nil, 754, 754, 754, 754, nil, nil, nil,
- nil, 754, 754, nil, nil, nil, 756, 756, 756, 754,
- 756, 754, 754, 754, 756, 756, nil, nil, nil, 756,
- nil, 756, 756, 756, 756, 756, 756, 756, nil, nil,
- nil, nil, nil, 756, 756, 756, 756, 756, 756, 756,
- nil, nil, 756, nil, nil, nil, nil, nil, nil, 756,
- nil, nil, 756, 756, 756, 756, 756, 756, 756, 756,
- nil, 756, 756, 756, nil, 756, 756, nil, 756, 756,
- 756, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 756, nil, nil, 756, nil, nil, 756, 756, nil, nil,
- 756, nil, nil, nil, nil, nil, 756, nil, nil, nil,
- nil, nil, nil, nil, nil, 756, nil, nil, nil, nil,
- 756, 756, 756, 756, nil, 756, 756, 756, 756, nil,
- nil, nil, nil, 756, 756, nil, nil, nil, 770, 770,
- 770, 756, 770, 756, 756, 756, 770, 770, nil, nil,
- nil, 770, nil, 770, 770, 770, 770, 770, 770, 770,
- nil, nil, nil, nil, nil, 770, 770, 770, 770, 770,
- 770, 770, nil, nil, 770, nil, nil, nil, nil, nil,
- nil, 770, nil, nil, 770, 770, 770, 770, 770, 770,
- 770, 770, nil, 770, 770, 770, nil, 770, 770, nil,
- 770, 770, 770, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 770, nil, nil, 770, nil, nil, 770, 770,
- nil, nil, 770, nil, nil, nil, nil, nil, 770, nil,
- nil, nil, nil, nil, nil, nil, nil, 770, nil, nil,
- nil, nil, 770, 770, 770, 770, nil, 770, 770, 770,
- 770, nil, nil, nil, nil, 770, 770, nil, nil, nil,
- 771, 771, 771, 770, 771, 770, 770, 770, 771, 771,
- nil, nil, nil, 771, nil, 771, 771, 771, 771, 771,
- 771, 771, nil, nil, nil, nil, nil, 771, 771, 771,
- 771, 771, 771, 771, nil, nil, 771, nil, nil, nil,
- nil, nil, nil, 771, nil, nil, 771, 771, 771, 771,
- 771, 771, 771, 771, nil, 771, 771, 771, nil, 771,
- 771, nil, 771, 771, 771, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 771, nil, nil, 771, nil, nil,
- 771, 771, nil, nil, 771, nil, nil, nil, nil, nil,
- 771, nil, nil, nil, nil, nil, nil, nil, nil, 771,
- nil, nil, nil, nil, 771, 771, 771, 771, nil, 771,
- 771, 771, 771, nil, nil, nil, nil, 771, 771, nil,
- nil, nil, 772, 772, 772, 771, 772, 771, 771, 771,
- 772, 772, nil, nil, nil, 772, nil, 772, 772, 772,
- 772, 772, 772, 772, nil, nil, nil, nil, nil, 772,
- 772, 772, 772, 772, 772, 772, nil, nil, 772, nil,
- nil, nil, nil, nil, nil, 772, nil, nil, 772, 772,
- 772, 772, 772, 772, 772, 772, nil, 772, 772, 772,
- nil, 772, 772, nil, 772, 772, 772, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 772, nil, nil, 772,
- nil, nil, 772, 772, nil, nil, 772, nil, nil, nil,
- nil, nil, 772, nil, nil, nil, nil, nil, nil, nil,
- nil, 772, nil, nil, nil, nil, 772, 772, 772, 772,
- nil, 772, 772, 772, 772, nil, nil, nil, nil, 772,
- 772, nil, nil, nil, 773, 773, 773, 772, 773, 772,
- 772, 772, 773, 773, nil, nil, nil, 773, nil, 773,
- 773, 773, 773, 773, 773, 773, nil, nil, nil, nil,
- nil, 773, 773, 773, 773, 773, 773, 773, nil, nil,
- 773, nil, nil, nil, nil, nil, nil, 773, nil, nil,
- 773, 773, 773, 773, 773, 773, 773, 773, nil, 773,
- 773, 773, nil, 773, 773, nil, 773, 773, 773, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 773, nil,
- nil, 773, nil, nil, 773, 773, nil, nil, 773, nil,
- nil, nil, nil, nil, 773, nil, nil, nil, nil, nil,
- nil, nil, nil, 773, nil, nil, nil, nil, 773, 773,
- 773, 773, nil, 773, 773, 773, 773, nil, nil, nil,
- nil, 773, 773, nil, nil, nil, 787, 787, 787, 773,
- 787, 773, 773, 773, 787, 787, nil, nil, nil, 787,
- nil, 787, 787, 787, 787, 787, 787, 787, nil, nil,
- nil, nil, nil, 787, 787, 787, 787, 787, 787, 787,
- nil, nil, 787, nil, nil, nil, nil, nil, nil, 787,
- nil, nil, 787, 787, 787, 787, 787, 787, 787, 787,
- nil, 787, 787, 787, nil, 787, 787, nil, nil, nil,
- 787, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 787, nil, nil, 787, nil, nil, 787, 787, nil, nil,
- 787, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 787, 787, 787, 787, nil, 787, 787, 787, 787, nil,
- nil, nil, nil, 787, 787, nil, nil, nil, 837, 837,
- 837, 787, 837, 787, 787, 787, 837, 837, nil, nil,
- nil, 837, nil, 837, 837, 837, 837, 837, 837, 837,
- nil, nil, nil, nil, nil, 837, 837, 837, 837, 837,
- 837, 837, nil, nil, 837, nil, nil, nil, nil, nil,
- nil, 837, nil, nil, 837, 837, 837, 837, 837, 837,
- 837, 837, nil, 837, 837, 837, nil, 837, 837, nil,
- 837, 837, 837, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 837, nil, nil, 837, nil, nil, 837, 837,
- nil, nil, 837, nil, nil, nil, nil, nil, 837, nil,
- nil, nil, nil, nil, nil, nil, nil, 837, nil, nil,
- nil, nil, 837, 837, 837, 837, nil, 837, 837, 837,
- 837, nil, nil, nil, nil, 837, 837, nil, nil, nil,
- 842, 842, 842, 837, 842, 837, 837, 837, 842, 842,
- nil, nil, nil, 842, nil, 842, 842, 842, 842, 842,
- 842, 842, nil, nil, nil, nil, nil, 842, 842, 842,
- 842, 842, 842, 842, nil, nil, 842, nil, nil, nil,
- nil, nil, nil, 842, nil, nil, 842, 842, 842, 842,
- 842, 842, 842, 842, nil, 842, 842, 842, nil, 842,
- 842, nil, 842, 842, 842, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 842, nil, nil, 842, nil, nil,
- 842, 842, nil, nil, 842, nil, 842, nil, nil, nil,
- 842, nil, nil, nil, nil, nil, nil, nil, nil, 842,
- nil, nil, nil, nil, 842, 842, 842, 842, nil, 842,
- 842, 842, 842, nil, nil, nil, nil, 842, 842, nil,
- nil, nil, 859, 859, 859, 842, 859, 842, 842, 842,
- 859, 859, nil, nil, nil, 859, nil, 859, 859, 859,
- 859, 859, 859, 859, nil, nil, nil, nil, nil, 859,
- 859, 859, 859, 859, 859, 859, nil, nil, 859, nil,
- nil, nil, nil, nil, nil, 859, nil, nil, 859, 859,
- 859, 859, 859, 859, 859, 859, 859, 859, 859, 859,
- nil, 859, 859, nil, 859, 859, 859, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 859, nil, nil, 859,
- nil, nil, 859, 859, nil, nil, 859, nil, nil, nil,
- 859, nil, 859, nil, nil, 859, nil, nil, nil, nil,
- nil, 859, nil, nil, nil, nil, 859, 859, 859, 859,
- nil, 859, 859, 859, 859, nil, nil, nil, nil, 859,
- 859, nil, nil, nil, 860, 860, 860, 859, 860, 859,
- 859, 859, 860, 860, nil, nil, nil, 860, nil, 860,
- 860, 860, 860, 860, 860, 860, nil, nil, nil, nil,
- nil, 860, 860, 860, 860, 860, 860, 860, nil, nil,
- 860, nil, nil, nil, nil, nil, nil, 860, nil, nil,
- 860, 860, 860, 860, 860, 860, 860, 860, nil, 860,
- 860, 860, nil, 860, 860, nil, 860, 860, 860, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 860, nil,
- nil, 860, nil, nil, 860, 860, nil, nil, 860, nil,
- nil, nil, nil, nil, 860, nil, nil, nil, nil, nil,
- nil, nil, nil, 860, nil, nil, nil, nil, 860, 860,
- 860, 860, nil, 860, 860, 860, 860, nil, nil, nil,
- nil, 860, 860, nil, nil, nil, 874, 874, 874, 860,
- 874, 860, 860, 860, 874, 874, nil, nil, nil, 874,
- nil, 874, 874, 874, 874, 874, 874, 874, nil, nil,
- nil, nil, nil, 874, 874, 874, 874, 874, 874, 874,
- nil, nil, 874, nil, nil, nil, nil, nil, nil, 874,
- nil, nil, 874, 874, 874, 874, 874, 874, 874, 874,
- nil, 874, 874, 874, nil, 874, 874, nil, nil, nil,
- 874, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 874, nil, nil, 874, nil, nil, 874, 874, nil, nil,
- 874, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 874, 874, 874, 874, nil, 874, 874, 874, 874, nil,
- nil, nil, nil, 874, 874, nil, nil, nil, 886, 886,
- 886, 874, 886, 874, 874, 874, 886, 886, nil, nil,
- nil, 886, nil, 886, 886, 886, 886, 886, 886, 886,
- nil, nil, nil, nil, nil, 886, 886, 886, 886, 886,
- 886, 886, nil, nil, 886, nil, nil, nil, nil, nil,
- nil, 886, nil, nil, 886, 886, 886, 886, 886, 886,
- 886, 886, nil, 886, 886, 886, nil, 886, 886, nil,
- nil, nil, 886, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 886, nil, nil, 886, nil, nil, 886, 886,
- nil, nil, 886, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 886, 886, 886, 886, nil, 886, 886, 886,
- 886, nil, nil, nil, nil, 886, 886, nil, nil, nil,
- 923, 923, 923, 886, 923, 886, 886, 886, 923, 923,
- nil, nil, nil, 923, nil, 923, 923, 923, 923, 923,
- 923, 923, nil, nil, nil, nil, nil, 923, 923, 923,
- 923, 923, 923, 923, nil, nil, 923, nil, nil, nil,
- nil, nil, nil, 923, nil, nil, 923, 923, 923, 923,
- 923, 923, 923, 923, nil, 923, 923, 923, nil, 923,
- 923, nil, 923, 923, 923, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 923, nil, nil, 923, nil, nil,
- 923, 923, nil, nil, 923, nil, nil, nil, nil, nil,
- 923, nil, nil, nil, nil, nil, nil, nil, nil, 923,
- nil, nil, nil, nil, 923, 923, 923, 923, nil, 923,
- 923, 923, 923, nil, nil, nil, nil, 923, 923, nil,
- nil, nil, 985, 985, 985, 923, 985, 923, 923, 923,
- 985, 985, nil, nil, nil, 985, nil, 985, 985, 985,
- 985, 985, 985, 985, nil, nil, nil, nil, nil, 985,
- 985, 985, 985, 985, 985, 985, nil, nil, 985, nil,
- nil, nil, nil, nil, nil, 985, nil, nil, 985, 985,
- 985, 985, 985, 985, 985, 985, 985, 985, 985, 985,
- nil, 985, 985, nil, 985, 985, 985, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 985, nil, nil, 985,
- nil, nil, 985, 985, nil, nil, 985, nil, 985, nil,
- 985, nil, 985, nil, nil, 985, nil, nil, nil, nil,
- nil, 985, nil, nil, nil, nil, 985, 985, 985, 985,
- nil, 985, 985, 985, 985, nil, nil, nil, nil, 985,
- 985, nil, nil, nil, nil, 56, nil, 985, nil, 985,
- 985, 985, 56, 56, 56, nil, nil, 56, 56, 56,
- nil, 56, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 56, 56, 56, nil, nil, nil, nil, nil, nil,
- nil, 56, 56, nil, 56, 56, 56, 56, 56, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 56, 56, 56, 56, 56, 56, 56, 56,
- 56, 56, 56, 56, 56, 56, nil, nil, 56, 56,
- 56, nil, nil, 56, nil, nil, 56, nil, nil, 56,
- 56, nil, 56, nil, 56, nil, 56, nil, 56, 56,
- nil, 56, 56, 56, 56, 56, nil, 56, nil, 56,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 56, nil, nil, 56, 56, 56, 56,
- 424, 56, nil, 56, nil, nil, nil, 424, 424, 424,
- nil, nil, 424, 424, 424, nil, 424, nil, nil, nil,
- nil, nil, nil, nil, nil, 424, 424, 424, 424, nil,
- nil, nil, nil, nil, nil, nil, 424, 424, nil, 424,
- 424, 424, 424, 424, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 424, 424, 424,
- 424, 424, 424, 424, 424, 424, 424, 424, 424, 424,
- 424, nil, nil, 424, 424, 424, nil, nil, 424, nil,
- nil, 424, nil, nil, 424, 424, nil, 424, nil, 424,
- nil, 424, nil, 424, 424, nil, 424, 424, 424, 424,
- 424, nil, 424, 424, 424, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 424, nil,
- nil, 424, 424, 424, 424, 425, 424, nil, 424, nil,
- nil, nil, 425, 425, 425, nil, nil, 425, 425, 425,
- nil, 425, nil, nil, nil, nil, nil, nil, nil, nil,
- 425, 425, 425, 425, nil, nil, nil, nil, nil, nil,
- nil, 425, 425, nil, 425, 425, 425, 425, 425, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 425, 425, 425, 425, 425, 425, 425, 425,
- 425, 425, 425, 425, 425, 425, nil, nil, 425, 425,
- 425, nil, nil, 425, nil, nil, 425, nil, nil, 425,
- 425, nil, 425, nil, 425, nil, 425, nil, 425, 425,
- nil, 425, 425, 425, 425, 425, nil, 425, 425, 425,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 425, nil, nil, 425, 425, 425, 425,
- 27, 425, nil, 425, nil, nil, nil, 27, 27, 27,
- nil, nil, 27, 27, 27, nil, 27, nil, nil, nil,
- nil, nil, nil, nil, nil, 27, 27, 27, nil, nil,
- nil, nil, nil, nil, nil, nil, 27, 27, nil, 27,
- 27, 27, 27, 27, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 27, 27, 27,
- 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
- 27, nil, nil, 27, 27, 27, nil, nil, 27, nil,
- 27, 27, nil, nil, 27, 27, nil, 27, nil, 27,
- nil, 27, nil, 27, 27, nil, 27, 27, 27, 27,
- 27, 28, 27, 27, 27, nil, nil, nil, 28, 28,
- 28, nil, nil, 28, 28, 28, nil, 28, 27, nil,
- nil, 27, 27, nil, 27, nil, 27, 28, 28, nil,
- nil, nil, nil, nil, nil, nil, nil, 28, 28, nil,
- 28, 28, 28, 28, 28, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 28, 28,
- 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
- 28, 28, nil, nil, 28, 28, 28, nil, nil, 28,
- nil, 28, 28, nil, nil, 28, 28, nil, 28, nil,
- 28, nil, 28, nil, 28, 28, nil, 28, 28, 28,
- 28, 28, nil, 28, 415, 28, nil, nil, nil, nil,
- nil, 415, 415, 415, nil, nil, 415, 415, 415, 28,
- 415, nil, 28, 28, nil, 28, nil, 28, nil, 415,
- 415, 415, nil, nil, nil, nil, nil, nil, nil, nil,
- 415, 415, nil, 415, 415, 415, 415, 415, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 415, 415, 415, 415, 415, 415, 415, 415, 415,
- 415, 415, 415, 415, 415, nil, nil, 415, 415, 415,
- nil, nil, 415, nil, 415, 415, nil, nil, 415, 415,
- nil, 415, nil, 415, nil, 415, nil, 415, 415, nil,
- 415, 415, 415, 415, 415, nil, 415, 415, 415, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 415, nil, 474, 415, 415, nil, 415, nil,
- 415, 474, 474, 474, nil, nil, 474, 474, 474, 646,
- 474, 646, 646, 646, 646, 646, nil, nil, nil, 474,
- 474, nil, nil, nil, nil, 646, nil, nil, nil, nil,
- 474, 474, nil, 474, 474, 474, 474, 474, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 646, 336, nil,
- 336, 336, 336, 336, 336, nil, 646, 646, 646, 646,
- nil, nil, nil, 646, 336, 534, nil, 534, 534, 534,
- 534, 534, 474, nil, nil, nil, nil, nil, nil, 474,
- nil, 534, nil, nil, 474, 474, 336, 336, nil, 646,
- nil, nil, nil, nil, nil, 336, 336, 336, 336, nil,
- nil, nil, 336, 534, nil, nil, nil, 474, 474, nil,
- nil, nil, 534, 534, 534, 534, nil, nil, nil, 534,
- nil, nil, 474, nil, nil, 474, nil, nil, nil, nil,
- 474, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, 8, 8, nil, nil, nil, 8, 8,
- 8, 8, 8, 8, 8, 8, 8, 8, nil, nil,
- nil, nil, nil, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, 8, nil, 8, nil, nil, nil, nil, nil,
- nil, nil, nil, 8, 8, nil, 8, 8, 8, 8,
- 8, 8, 8, nil, nil, 8, 8, nil, nil, nil,
- 8, 8, 8, 8, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 8, 8, nil,
- 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
- 8, 8, nil, nil, 8, 8, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 8,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, 9, 9, 9, nil, nil, nil, 9, 9, 9,
- 9, 9, 9, 9, 9, 9, 9, nil, nil, nil,
- nil, nil, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, nil, nil, 9, nil, nil, nil, nil, nil, nil,
- nil, nil, 9, 9, nil, 9, 9, 9, 9, 9,
- 9, 9, nil, nil, 9, 9, nil, nil, nil, 9,
- 9, 9, 9, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 9, 9, nil, 9,
- 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
- 9, nil, nil, 9, 9, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 9, 395,
- 395, 395, 395, 395, 395, 395, 395, 395, 395, 395,
- 395, 395, 395, 395, 395, 395, 395, 395, 395, 395,
- 395, 395, 395, nil, nil, nil, 395, 395, 395, 395,
- 395, 395, 395, 395, 395, 395, nil, nil, nil, nil,
- nil, 395, 395, 395, 395, 395, 395, 395, 395, 395,
- nil, nil, 395, nil, nil, nil, nil, nil, nil, nil,
- nil, 395, 395, nil, 395, 395, 395, 395, 395, 395,
- 395, nil, nil, 395, 395, nil, nil, nil, 395, 395,
- 395, 395, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 395, 395, nil, 395, 395,
- 395, 395, 395, 395, 395, 395, 395, 395, 395, 395,
- nil, nil, 395, 395, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 395, 616, 616,
- 616, 616, 616, 616, 616, 616, 616, 616, 616, 616,
- 616, 616, 616, 616, 616, 616, 616, 616, 616, 616,
- 616, 616, nil, nil, nil, 616, 616, 616, 616, 616,
- 616, 616, 616, 616, 616, nil, nil, nil, nil, nil,
- 616, 616, 616, 616, 616, 616, 616, 616, 616, nil,
- nil, 616, nil, nil, nil, nil, nil, nil, nil, nil,
- 616, 616, nil, 616, 616, 616, 616, 616, 616, 616,
- nil, nil, 616, 616, nil, nil, nil, 616, 616, 616,
- 616, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 616, 616, nil, 616, 616, 616,
- 616, 616, 616, 616, 616, 616, 616, 616, 616, nil,
- nil, 616, 616, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 616, 71, 71, 71,
- 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
- 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
- 71, nil, nil, nil, 71, 71, 71, 71, 71, 71,
- 71, 71, 71, 71, nil, nil, nil, nil, nil, 71,
- 71, 71, 71, 71, 71, 71, 71, 71, 71, 71,
- 71, nil, 71, nil, nil, nil, nil, nil, nil, 71,
- 71, nil, 71, 71, 71, 71, 71, 71, 71, nil,
- nil, 71, 71, nil, nil, nil, 71, 71, 71, 71,
- nil, nil, nil, nil, nil, 71, nil, nil, nil, nil,
- nil, nil, nil, 71, 71, nil, 71, 71, 71, 71,
- 71, 71, 71, 71, 71, 71, 71, 71, nil, nil,
- 71, 738, 738, 738, 738, 738, 738, 738, 738, 738,
- 738, 738, 738, 738, 738, 738, 738, 738, 738, 738,
- 738, 738, 738, 738, 738, nil, nil, nil, 738, 738,
- 738, 738, 738, 738, 738, 738, 738, 738, nil, nil,
- nil, nil, nil, 738, 738, 738, 738, 738, 738, 738,
- 738, 738, nil, nil, 738, nil, nil, nil, nil, nil,
- nil, nil, nil, 738, 738, nil, 738, 738, 738, 738,
- 738, 738, 738, nil, nil, 738, 738, nil, nil, nil,
- 738, 738, 738, 738, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 738, 738, nil,
- 738, 738, 738, 738, 738, 738, 738, 738, 738, 738,
- 738, 738, 210, 210, 738, nil, 210, nil, nil, nil,
- nil, nil, nil, nil, nil, 210, 210, nil, 210, 210,
- 210, 210, 210, 210, 210, nil, nil, 210, 210, nil,
- nil, nil, 210, 210, 210, 210, nil, nil, nil, nil,
- nil, 210, nil, nil, nil, nil, nil, nil, nil, 210,
- 210, nil, 210, 210, 210, 210, 210, 210, 210, 210,
- 210, 210, 210, 210, 211, 211, 210, nil, 211, nil,
- nil, nil, nil, nil, nil, nil, nil, 211, 211, nil,
- 211, 211, 211, 211, 211, 211, 211, nil, nil, 211,
- 211, nil, nil, nil, 211, 211, 211, 211, nil, nil,
- nil, nil, nil, 211, nil, nil, nil, nil, nil, nil,
- nil, 211, 211, nil, 211, 211, 211, 211, 211, 211,
- 211, 211, 211, 211, 211, 211, 259, 259, 211, nil,
- 259, nil, nil, nil, nil, nil, nil, nil, nil, 259,
- 259, nil, 259, 259, 259, 259, 259, 259, 259, nil,
- nil, 259, 259, nil, nil, nil, 259, 259, 259, 259,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 259, 259, nil, 259, 259, 259, 259,
- 259, 259, 259, 259, 259, 259, 259, 259, 440, 440,
- 259, nil, 440, nil, nil, nil, nil, nil, nil, nil,
- nil, 440, 440, nil, 440, 440, 440, 440, 440, 440,
- 440, nil, nil, 440, 440, nil, nil, nil, 440, 440,
- 440, 440, nil, nil, nil, nil, nil, 440, nil, nil,
- nil, nil, nil, nil, nil, 440, 440, nil, 440, 440,
- 440, 440, 440, 440, 440, 440, 440, 440, 440, 440,
- 441, 441, 440, nil, 441, nil, nil, nil, nil, nil,
- nil, nil, nil, 441, 441, nil, 441, 441, 441, 441,
- 441, 441, 441, nil, nil, 441, 441, nil, nil, nil,
- 441, 441, 441, 441, nil, nil, nil, nil, nil, 441,
- nil, nil, nil, nil, nil, nil, nil, 441, 441, nil,
- 441, 441, 441, 441, 441, 441, 441, 441, 441, 441,
- 441, 441, 507, 507, 441, nil, 507, nil, nil, nil,
- nil, nil, nil, nil, nil, 507, 507, nil, 507, 507,
- 507, 507, 507, 507, 507, nil, nil, 507, 507, nil,
- nil, nil, 507, 507, 507, 507, nil, nil, nil, nil,
- nil, 507, nil, nil, nil, nil, nil, nil, nil, 507,
- 507, nil, 507, 507, 507, 507, 507, 507, 507, 507,
- 507, 507, 507, 507, 508, 508, 507, nil, 508, nil,
- nil, nil, nil, nil, nil, nil, nil, 508, 508, nil,
- 508, 508, 508, 508, 508, 508, 508, nil, nil, 508,
- 508, nil, nil, nil, 508, 508, 508, 508, nil, nil,
- nil, nil, nil, 508, nil, nil, nil, nil, nil, nil,
- nil, 508, 508, nil, 508, 508, 508, 508, 508, 508,
- 508, 508, 508, 508, 508, 508, 517, 517, 508, nil,
- 517, nil, nil, nil, nil, nil, nil, nil, nil, 517,
- 517, nil, 517, 517, 517, 517, 517, 517, 517, nil,
- nil, 517, 517, nil, nil, nil, 517, 517, 517, 517,
- nil, nil, nil, nil, nil, 517, nil, nil, nil, nil,
- nil, nil, nil, 517, 517, nil, 517, 517, 517, 517,
- 517, 517, 517, 517, 517, 517, 517, 517, 518, 518,
- 517, nil, 518, nil, nil, nil, nil, nil, nil, nil,
- nil, 518, 518, nil, 518, 518, 518, 518, 518, 518,
- 518, nil, nil, 518, 518, nil, nil, nil, 518, 518,
- 518, 518, nil, nil, nil, nil, nil, 518, nil, nil,
- nil, nil, nil, nil, nil, 518, 518, nil, 518, 518,
- 518, 518, 518, 518, 518, 518, 518, 518, 518, 518,
- 576, 576, 518, nil, 576, nil, nil, nil, nil, nil,
- nil, nil, nil, 576, 576, nil, 576, 576, 576, 576,
- 576, 576, 576, nil, nil, 576, 576, nil, nil, nil,
- 576, 576, 576, 576, nil, nil, nil, nil, nil, 576,
- nil, nil, nil, nil, nil, nil, nil, 576, 576, nil,
- 576, 576, 576, 576, 576, 576, 576, 576, 576, 576,
- 576, 576, 577, 577, 576, nil, 577, nil, nil, nil,
- nil, nil, nil, nil, nil, 577, 577, nil, 577, 577,
- 577, 577, 577, 577, 577, nil, nil, 577, 577, nil,
- nil, nil, 577, 577, 577, 577, nil, nil, nil, nil,
- nil, 577, nil, nil, nil, nil, nil, nil, nil, 577,
- 577, nil, 577, 577, 577, 577, 577, 577, 577, 577,
- 577, 577, 577, 577, 583, 583, 577, nil, 583, nil,
- nil, nil, nil, nil, nil, nil, nil, 583, 583, nil,
- 583, 583, 583, 583, 583, 583, 583, nil, nil, 583,
- 583, nil, nil, nil, 583, 583, 583, 583, nil, nil,
- nil, nil, nil, 583, nil, nil, nil, nil, nil, nil,
- nil, 583, 583, nil, 583, 583, 583, 583, 583, 583,
- 583, 583, 583, 583, 583, 583, 584, 584, 583, nil,
- 584, nil, nil, nil, nil, nil, nil, nil, nil, 584,
- 584, nil, 584, 584, 584, 584, 584, 584, 584, nil,
- nil, 584, 584, nil, nil, nil, 584, 584, 584, 584,
- nil, nil, nil, nil, nil, 584, nil, nil, nil, nil,
- nil, nil, nil, 584, 584, nil, 584, 584, 584, 584,
- 584, 584, 584, 584, 584, 584, 584, 584, 939, 939,
- 584, nil, 939, nil, nil, nil, nil, nil, nil, nil,
- nil, 939, 939, nil, 939, 939, 939, 939, 939, 939,
- 939, nil, nil, 939, 939, nil, nil, nil, 939, 939,
- 939, 939, nil, nil, nil, nil, nil, 939, nil, nil,
- nil, nil, nil, nil, nil, 939, 939, nil, 939, 939,
- 939, 939, 939, 939, 939, 939, 939, 939, 939, 939,
- 986, 986, 939, nil, 986, nil, nil, nil, nil, nil,
- nil, nil, nil, 986, 986, nil, 986, 986, 986, 986,
- 986, 986, 986, nil, nil, 986, 986, nil, nil, nil,
- 986, 986, 986, 986, nil, nil, nil, nil, nil, 986,
- nil, nil, nil, nil, nil, nil, nil, 986, 986, nil,
- 986, 986, 986, 986, 986, 986, 986, 986, 986, 986,
- 986, 986, 987, 987, 986, nil, 987, nil, nil, nil,
- nil, nil, nil, nil, nil, 987, 987, nil, 987, 987,
- 987, 987, 987, 987, 987, nil, nil, 987, 987, nil,
- nil, nil, 987, 987, 987, 987, nil, nil, nil, nil,
- nil, 987, nil, nil, nil, nil, nil, nil, nil, 987,
- 987, nil, 987, 987, 987, 987, 987, 987, 987, 987,
- 987, 987, 987, 987, nil, 693, 987, 693, 693, 693,
- 693, 693, nil, 695, nil, 695, 695, 695, 695, 695,
- nil, 693, nil, nil, nil, nil, nil, nil, 736, 695,
- 736, 736, 736, 736, 736, nil, nil, nil, nil, nil,
- nil, nil, nil, 693, 736, nil, nil, nil, nil, nil,
- nil, 695, 693, 693, 693, 693, nil, nil, nil, 693,
- 695, 695, 695, 695, nil, nil, 736, 695, 737, nil,
- 737, 737, 737, 737, 737, 736, 736, 736, 736, nil,
- nil, nil, 736, 865, 737, 865, 865, 865, 865, 865,
- nil, 867, nil, 867, 867, 867, 867, 867, nil, 865,
- nil, nil, nil, nil, nil, nil, 737, 867, 893, nil,
- 893, 893, 893, 893, 893, 737, 737, 737, 737, nil,
- nil, 865, 737, nil, 893, nil, nil, nil, nil, 867,
- 865, 865, 865, 865, nil, nil, nil, 865, 867, 867,
- 867, 867, nil, nil, nil, 867, 893, 897, nil, 897,
- 897, 897, 897, 897, nil, 893, 893, 893, 893, nil,
- nil, nil, 893, 897, 899, nil, 899, 899, 899, 899,
- 899, nil, 971, nil, 971, 971, 971, 971, 971, nil,
- 899, nil, nil, nil, nil, 897, nil, 973, 971, 973,
- 973, 973, 973, 973, nil, nil, 897, 897, nil, nil,
- nil, 897, 899, 973, nil, nil, nil, nil, nil, nil,
- 971, nil, nil, 899, 899, nil, nil, nil, 899, 971,
- 971, 971, 971, nil, nil, 973, 971, 975, nil, 975,
- 975, 975, 975, 975, nil, nil, 973, 973, nil, nil,
- nil, 973, 977, 975, 977, 977, 977, 977, 977, nil,
- 989, nil, 989, 989, 989, 989, 989, 1015, 977, 1015,
- 1015, 1015, 1015, 1015, nil, 975, 989, nil, nil, nil,
- nil, nil, nil, 1015, nil, nil, 975, 975, nil, nil,
- 977, 975, nil, nil, nil, nil, nil, nil, 989, nil,
- nil, 977, 977, nil, nil, 1015, 977, nil, nil, 989,
- 989, nil, nil, nil, 989, nil, 1015, 1015, nil, nil,
- nil, 1015 ]
-
-racc_action_pointer = [
- 750, 47, nil, 123, nil, 5120, 1299, -62, 23249, 23378,
- -21, nil, -43, 71, 533, -41, 34, -4, nil, -72,
- 5252, 1173, 168, nil, 157, nil, 6, 22760, 22871, 5384,
- 5516, 5648, nil, 891, 5780, 5912, nil, 71, 227, 254,
- 154, 228, 6052, 6184, 6316, 95, 544, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 22355, nil, -71, 6448,
- 6580, -23, nil, 6712, 6844, nil, nil, 6976, 7116, 7248,
- 7380, 23765, nil, nil, nil, nil, nil, 470, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 0, nil, nil, 113, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 262,
- nil, 7520, nil, nil, nil, nil, 7660, 7792, 7924, 8056,
- 8196, 1032, nil, 220, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 141, nil, 1173, 8328, 8460, 8592,
- 23941, 24003, 8724, 8856, 8988, 9120, 9252, 9384, nil, nil,
- 546, -77, -62, 233, 131, 196, 256, nil, 9516, 1314,
- 273, 9648, 9780, 9912, 10044, 10176, 10308, 10440, 10572, 10704,
- 10836, 10968, 11100, 11232, 11364, 11496, 11628, 11760, 11892, 12024,
- 12156, 12288, 12420, 12552, 12684, 12816, nil, nil, nil, 24065,
- nil, nil, 275, 12948, 13080, nil, nil, nil, nil, nil,
- nil, nil, 13212, nil, 1314, nil, 262, 314, nil, 13344,
- 366, 13476, nil, nil, 13608, 13740, nil, nil, 296, nil,
- 13880, 1440, 368, 362, 1455, 384, 444, 418, 14012, 1596,
- 578, 615, 681, 505, 750, nil, 478, 439, 33, nil,
- nil, nil, 501, 258, 478, 14152, nil, 299, 561, 753,
- nil, 569, nil, 14284, 1737, 14416, 528, nil, 105, 259,
- 571, 585, 454, 619, nil, nil, 23117, 488, -1, 26,
- 14548, 14680, 458, 706, 596, -23, -19, 792, 691, -18,
- 724, nil, nil, 227, 281, -34, nil, 822, nil, 34,
- 14812, nil, nil, nil, 264, 409, 448, 451, 478, 508,
- 512, 532, 554, nil, 567, nil, 14944, nil, 275, 335,
- 363, 375, 392, -45, -41, 395, nil, nil, nil, nil,
- nil, nil, nil, nil, 643, 23507, nil, nil, nil, nil,
- 650, nil, nil, 642, 15076, 644, nil, nil, 891, 658,
- nil, 672, 676, 332, 342, 22984, nil, nil, nil, 224,
- 337, 723, nil, nil, 22490, 22625, nil, 1455, nil, 689,
- nil, nil, 750, nil, nil, nil, nil, -33, nil, 746,
- 24127, 24189, 15208, 239, 15340, 15472, 15604, 3147, 3288, 538,
- 659, 778, 783, 788, 798, 5120, 5252, 5384, 3429, 3570,
- 3711, 3852, 3993, 4134, 4275, 4416, 4557, 4698, 621, 630,
- 4839, 4980, 15736, -46, 23114, nil, nil, nil, nil, 747,
- nil, 159, 279, 750, nil, nil, 15868, nil, 16000, nil,
- 16132, nil, 332, nil, nil, nil, 16272, 1455, 1878, 752,
- 751, nil, nil, 754, 16412, 767, 16544, 24251, 24313, 891,
- 809, nil, 16676, 769, nil, 16808, 16940, 24375, 24437, 1596,
- 17072, 897, 896, 694, 824, nil, 17204, nil, nil, 17336,
- nil, nil, nil, nil, 23134, nil, 783, 784, nil, 785,
- 793, 794, nil, nil, nil, nil, nil, nil, nil, nil,
- 787, 477, nil, nil, 17468, nil, nil, nil, 880, nil,
- nil, nil, 881, nil, nil, 882, 2019, 935, nil, 2160,
- 63, 119, 935, 945, 17600, 17732, 24499, 24561, 10, nil,
- nil, 894, nil, 24623, 24685, 17864, nil, nil, nil, 587,
- 193, 2301, 883, nil, -14, nil, nil, nil, 733, nil,
- nil, nil, 858, nil, nil, 151, nil, 222, nil, nil,
- 846, nil, 847, nil, nil, nil, 23636, nil, 852, 17996,
- 18128, 380, 896, 18260, 18392, 18524, 18656, 899, nil, nil,
- 18788, 18920, 907, nil, 19052, 19184, nil, nil, 350, 416,
- 470, 607, 874, 1032, 1737, nil, 23078, nil, 2442, 979,
- 5, 316, nil, 2583, 2724, nil, 882, nil, 929, 19316,
- nil, nil, 19448, nil, 905, -81, 19580, 888, nil, 893,
- 137, 179, 935, 340, 1032, 936, 895, 19712, 1878, 972,
- 20, 1026, 19844, nil, 913, nil, 539, 21, 914, 495,
- nil, nil, 740, 24934, nil, 24942, nil, 5959, nil, 19976,
- nil, 607, nil, 912, 230, 925, nil, nil, nil, nil,
- 850, nil, 1044, nil, nil, nil, nil, 1050, nil, 32,
- 929, 26, 41, 123, 182, 20108, 414, 1173, nil, 937,
- 2865, 20240, nil, nil, 1060, 3006, 24957, 24997, 23879, nil,
- nil, nil, nil, nil, nil, 3147, nil, nil, nil, nil,
- nil, nil, nil, 937, 20372, 2019, 20504, nil, 938, nil,
- 2160, nil, 2301, nil, nil, 2442, nil, 2583, nil, 2724,
- 20636, 20768, 20900, 21032, 429, 940, 940, 954, nil, 958,
- 961, 980, nil, 1009, 992, 991, 989, 21164, nil, nil,
- 1128, nil, nil, 3288, 1031, 1137, nil, nil, nil, nil,
- 1013, 378, nil, nil, 1149, nil, 3429, 1024, 1072, nil,
- nil, 1072, nil, nil, 3570, 3711, 1074, 1032, nil, nil,
- nil, 1033, 1036, nil, 1046, 1047, nil, 1051, nil, nil,
- 1055, 614, 1053, 600, nil, 1188, nil, 21296, 1190, 3852,
- 3993, nil, 21428, 4134, 81, 122, nil, 1191, 611, 4275,
- nil, 1192, 1078, 613, nil, 1087, 1095, nil, 2865, 21560,
- 21692, nil, 525, nil, nil, 25012, nil, 25020, nil, 7427,
- nil, nil, 1123, 1159, 21824, 933, 1181, nil, 1141, nil,
- nil, nil, 4416, nil, nil, 33, 21956, nil, nil, 1146,
- 1255, nil, nil, 25037, nil, 14059, nil, 25076, nil, 25093,
- nil, nil, nil, nil, 330, 3415, 1134, nil, 36, nil,
- 1264, 1269, nil, 47, nil, nil, nil, 1277, nil, nil,
- nil, 1197, nil, 22088, 1154, nil, nil, 1164, 1165, 1167,
- 1170, nil, 1172, nil, 643, nil, nil, nil, 963, 24747,
- nil, nil, nil, 4557, 1035, 1074, 1104, 1252, 1176, nil,
- nil, nil, 1174, 1177, 1187, 1188, 1189, 3556, 1192, 3589,
- 4698, nil, nil, nil, nil, nil, 4839, nil, 4980, 3006,
- nil, 25101, nil, 25116, nil, 25156, nil, 25171, nil, nil,
- nil, 1300, 1237, 1238, 1323, 22220, 24809, 24871, 1215, 25179,
- nil, nil, nil, nil, 3697, 1216, 862, 1347, 1361, 1240,
- 1243, 1261, 1262, nil, nil, 1270, 40, 42, 112, 1314,
- 1268, 1271, nil, nil, nil, 25186, nil, nil, nil, nil,
- 43, nil, 1275, nil ]
-
-racc_action_default = [
- -3, -597, -1, -583, -4, -597, -7, -597, -597, -597,
- -597, -29, -597, -597, -597, -281, -597, -40, -43, -585,
- -597, -48, -50, -51, -52, -56, -258, -258, -258, -295,
- -330, -331, -68, -11, -72, -80, -82, -597, -488, -489,
- -597, -597, -597, -597, -597, -585, -239, -272, -273, -274,
- -275, -276, -277, -278, -279, -280, -573, -283, -285, -596,
- -563, -303, -391, -597, -597, -308, -311, -583, -597, -597,
- -597, -597, -332, -333, -429, -430, -431, -432, -433, -454,
- -436, -437, -456, -458, -441, -446, -450, -452, -468, -456,
- -470, -472, -473, -474, -475, -571, -477, -478, -572, -480,
- -481, -482, -483, -484, -485, -486, -487, -492, -493, -597,
- -2, -584, -592, -593, -594, -6, -597, -597, -597, -597,
- -597, -3, -17, -597, -111, -112, -113, -114, -115, -116,
- -117, -118, -119, -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, -22, -120, -11, -597, -597, -248,
- -597, -597, -597, -597, -597, -597, -597, -585, -586, -47,
- -597, -488, -489, -597, -281, -597, -597, -229, -597, -11,
- -597, -597, -597, -597, -597, -597, -597, -597, -597, -597,
- -597, -597, -597, -597, -597, -597, -597, -597, -597, -597,
- -597, -597, -597, -597, -597, -597, -236, -398, -400, -597,
- -581, -582, -57, -248, -597, -302, -404, -413, -415, -63,
- -410, -64, -585, -65, -240, -253, -262, -262, -257, -597,
- -263, -597, -454, -565, -597, -597, -66, -67, -583, -12,
- -597, -15, -597, -70, -11, -585, -597, -73, -76, -11,
- -88, -89, -597, -597, -96, -295, -298, -585, -597, -330,
- -331, -334, -411, -597, -78, -597, -84, -292, -471, -597,
- -214, -215, -230, -597, -11, -597, -585, -241, -589, -589,
- -597, -597, -589, -597, -304, -305, -521, -49, -597, -597,
- -597, -597, -583, -597, -584, -488, -489, -597, -597, -281,
- -597, -344, -345, -106, -107, -597, -109, -597, -281, -597,
- -597, -488, -489, -323, -111, -112, -153, -154, -155, -171,
- -176, -183, -186, -325, -597, -561, -597, -434, -597, -597,
- -597, -597, -597, -597, -597, -597, 1024, -5, -595, -23,
- -24, -25, -26, -27, -597, -597, -19, -20, -21, -121,
- -597, -30, -39, -268, -597, -597, -267, -31, -196, -585,
- -249, -262, -262, -574, -575, -258, -408, -576, -577, -575,
- -574, -258, -407, -409, -576, -577, -37, -204, -38, -597,
- -41, -42, -194, -263, -44, -45, -46, -585, -301, -597,
- -597, -597, -248, -292, -597, -597, -597, -205, -206, -207,
- -208, -209, -210, -211, -212, -216, -217, -218, -219, -220,
- -221, -222, -223, -224, -225, -226, -227, -228, -231, -232,
- -233, -234, -597, -380, -258, -574, -575, -54, -58, -585,
- -259, -380, -380, -585, -297, -254, -597, -255, -597, -260,
- -597, -264, -597, -568, -570, -10, -584, -14, -3, -585,
- -69, -290, -85, -74, -597, -585, -248, -597, -597, -95,
- -597, -471, -597, -81, -86, -597, -597, -597, -597, -235,
- -597, -421, -597, -286, -597, -242, -591, -590, -244, -591,
- -293, -294, -564, -392, -521, -395, -560, -560, -504, -506,
- -506, -506, -520, -522, -523, -524, -525, -526, -527, -528,
- -529, -597, -531, -533, -535, -540, -542, -543, -545, -550,
- -552, -553, -555, -556, -557, -597, -11, -335, -336, -11,
- -597, -597, -597, -597, -597, -248, -597, -597, -292, -316,
- -106, -107, -108, -597, -597, -248, -319, -494, -495, -597,
- -597, -11, -499, -327, -585, -435, -455, -460, -597, -462,
- -438, -457, -597, -459, -440, -597, -443, -597, -445, -448,
- -597, -449, -597, -469, -8, -18, -597, -28, -271, -597,
- -597, -412, -597, -250, -252, -597, -597, -59, -247, -405,
- -597, -597, -61, -406, -597, -597, -300, -587, -574, -575,
- -574, -575, -585, -194, -585, -381, -585, -383, -11, -53,
- -401, -380, -245, -11, -11, -296, -262, -261, -265, -597,
- -566, -567, -597, -13, -597, -71, -597, -77, -83, -585,
- -574, -575, -246, -92, -94, -597, -79, -597, -203, -213,
- -585, -596, -596, -284, -585, -289, -589, -597, -585, -597,
- -502, -503, -597, -597, -513, -597, -516, -597, -518, -597,
- -346, -597, -348, -350, -357, -585, -534, -544, -554, -558,
- -596, -337, -596, -309, -338, -339, -312, -597, -315, -597,
- -585, -574, -575, -578, -291, -597, -106, -107, -110, -585,
- -11, -597, -497, -321, -597, -11, -521, -521, -597, -562,
- -461, -464, -465, -466, -467, -11, -439, -442, -444, -447,
- -451, -453, -122, -269, -597, -197, -597, -588, -262, -33,
- -199, -34, -200, -60, -35, -202, -36, -201, -62, -195,
- -597, -597, -597, -597, -412, -597, -560, -560, -362, -364,
- -364, -364, -379, -597, -585, -385, -529, -537, -538, -548,
- -597, -403, -402, -11, -597, -597, -256, -266, -569, -16,
- -75, -90, -87, -299, -596, -342, -11, -422, -596, -423,
- -424, -597, -243, -393, -11, -11, -597, -560, -541, -559,
- -505, -506, -506, -532, -506, -506, -551, -506, -529, -546,
- -585, -597, -355, -597, -530, -597, -340, -597, -597, -11,
- -11, -314, -597, -11, -412, -597, -412, -597, -597, -11,
- -324, -597, -585, -597, -328, -597, -270, -32, -198, -251,
- -597, -237, -597, -360, -361, -370, -372, -597, -375, -597,
- -377, -382, -597, -597, -597, -536, -597, -399, -597, -414,
- -416, -9, -11, -428, -343, -597, -597, -426, -287, -597,
- -597, -394, -501, -597, -509, -597, -511, -597, -514, -597,
- -517, -519, -347, -349, -353, -597, -358, -306, -597, -307,
- -597, -597, -265, -596, -317, -320, -496, -597, -326, -498,
- -500, -499, -463, -597, -560, -539, -363, -364, -364, -364,
- -364, -549, -364, -384, -585, -387, -389, -390, -547, -597,
- -292, -55, -427, -11, -97, -98, -597, -597, -105, -425,
- -396, -397, -506, -506, -506, -506, -351, -597, -356, -597,
- -11, -310, -313, -417, -418, -419, -11, -322, -11, -238,
- -359, -597, -367, -597, -369, -597, -373, -597, -376, -378,
- -386, -597, -291, -578, -421, -248, -597, -597, -104, -597,
- -507, -510, -512, -515, -597, -354, -596, -597, -597, -364,
- -364, -364, -364, -388, -420, -585, -574, -575, -578, -103,
- -506, -352, -341, -318, -329, -597, -365, -368, -371, -374,
- -412, -508, -364, -366 ]
-
-racc_goto_table = [
- 216, 275, 275, 275, 14, 327, 373, 409, 573, 14,
- 522, 276, 276, 276, 266, 270, 311, 311, 258, 2,
- 415, 421, 334, 431, 220, 681, 323, 259, 122, 205,
- 535, 127, 127, 220, 220, 220, 406, 14, 302, 302,
- 550, 328, 428, 478, 297, 130, 130, 132, 132, 542,
- 311, 311, 311, 110, 114, 338, 339, 487, 438, 342,
- 513, 479, 735, 835, 582, 318, 660, 220, 220, 474,
- 111, 220, 347, 357, 357, 705, 621, 826, 219, 6,
- 314, 690, 691, 804, 6, 783, 566, 569, 713, 716,
- 378, 293, 295, 780, 127, 262, 269, 271, 906, 903,
- 525, 528, 115, 931, 532, 379, 935, 660, 389, 390,
- 391, 392, 385, 484, 838, 14, 937, 343, 114, 1,
- 220, 220, 220, 220, 14, 14, 881, 816, 359, 363,
- 648, 273, 286, 287, 605, 607, 500, 663, 653, 654,
- 394, 823, 204, 352, 402, 395, 277, 277, 277, 651,
- 616, 472, 657, 13, 657, 923, 330, 650, 13, 375,
- 331, 335, 350, 586, 374, 324, 325, 684, 326, 340,
- 958, 694, 696, 698, 839, 341, 329, 332, 840, 725,
- 966, 275, 730, 849, 591, 592, 13, 738, 921, 405,
- 6, 782, 487, 784, 934, 405, 533, 813, 416, 393,
- 6, 700, 660, 336, 687, 473, 481, 931, 387, 482,
- 14, 220, 220, 220, 1003, 963, 220, 220, 220, 220,
- 220, 220, 995, 872, 937, 830, 808, 903, 688, 885,
- 377, 296, 380, 14, 425, 275, 275, 717, 550, 381,
- 642, 382, 383, 384, 275, 740, 276, 542, 745, 667,
- 415, 421, 731, 821, 276, 818, 925, 676, nil, 1011,
- nil, nil, nil, nil, 13, 401, 407, 220, 220, nil,
- 426, 430, nil, 13, 13, 826, 220, 734, 636, nil,
- 311, 601, 603, 606, 606, nil, nil, 601, 510, 657,
- 657, nil, 728, 492, 14, nil, 266, 311, 14, nil,
- 270, nil, 302, 14, 669, nil, nil, 524, 793, 774,
- nil, nil, 927, 823, nil, 964, nil, 672, nil, 302,
- 652, 863, 864, nil, 655, 514, nil, 672, 14, 220,
- nil, nil, 570, 571, nil, nil, 801, 511, 495, 114,
- 665, nil, nil, 503, 220, 220, 668, 823, nil, 1012,
- 786, 700, 293, 499, 832, 496, nil, 293, 505, 13,
- nil, nil, 892, 914, 220, nil, 480, nil, nil, 497,
- nil, nil, nil, 720, 483, nil, nil, 593, nil, nil,
- 220, 277, 13, 729, nil, nil, 672, 844, nil, 277,
- 622, 968, 572, 114, 672, nil, 846, 550, nil, 550,
- nil, nil, nil, 628, 400, nil, nil, nil, 763, 633,
- 587, 800, nil, 768, 275, 615, 847, nil, 127, nil,
- nil, 851, nil, nil, nil, 823, nil, 296, 416, nil,
- 852, 853, 130, nil, 132, 739, 796, 660, nil, nil,
- 550, 550, nil, 13, 431, nil, 220, 13, nil, 542,
- 542, nil, 13, 894, 896, nil, 898, 900, 812, 901,
- nil, 333, 628, nil, 425, nil, nil, 843, nil, 970,
- nil, nil, nil, nil, nil, nil, nil, 13, 275, nil,
- nil, 700, nil, 700, 627, nil, 311, nil, 1004, nil,
- 632, nil, 296, nil, 311, 416, nil, 296, nil, 26,
- 14, nil, 14, nil, 26, 416, nil, 748, 302, 748,
- 220, 809, 781, nil, 514, nil, 302, 664, nil, 26,
- nil, 803, 514, nil, 220, 657, nil, nil, 26, 26,
- 26, 425, 26, nil, nil, 917, nil, nil, 796, nil,
- nil, 425, nil, 649, nil, nil, 834, 275, nil, nil,
- nil, nil, nil, nil, 956, 700, 719, 275, nil, 822,
- nil, 824, 26, 26, 416, nil, 26, nil, nil, 786,
- 14, 786, 416, 14, nil, nil, nil, 6, 965, 220,
- nil, nil, nil, nil, 990, 991, 992, 993, nil, 220,
- nil, nil, nil, nil, nil, 14, nil, 550, nil, nil,
- 425, nil, nil, 656, nil, nil, 425, 700, 403, 700,
- 26, 792, nil, nil, 433, 26, 26, 26, 26, 26,
- 26, 714, 714, 622, nil, 775, nil, 785, 810, 220,
- 220, nil, nil, 943, 220, 220, 752, nil, 220, 127,
- 732, 733, 1021, 686, 700, 791, nil, nil, 311, 13,
- 622, 13, 14, 130, 998, 132, 960, 14, 14, 311,
- 628, nil, nil, 633, 405, 811, nil, nil, nil, 785,
- 302, 902, 1020, 854, nil, 786, 514, nil, nil, nil,
- 489, 302, 491, 759, 761, 493, 494, 802, 764, 766,
- nil, nil, 430, 919, nil, nil, nil, nil, nil, nil,
- nil, 622, nil, nil, nil, 26, 26, 26, 26, nil,
- 622, 26, 26, 26, 26, 26, 26, 845, nil, 13,
- nil, nil, 13, 848, nil, nil, nil, nil, 26, 220,
- nil, 928, nil, 929, 14, 220, nil, nil, nil, 14,
- 758, nil, nil, nil, 13, nil, nil, nil, nil, 14,
- 883, nil, 15, nil, 887, nil, nil, 15, nil, 952,
- 220, 127, 26, 26, 710, 785, nil, 712, nil, 311,
- nil, 26, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 1005, nil, 15, 304, 304, nil, 26,
- nil, 875, nil, 26, nil, nil, 672, 14, 26, nil,
- nil, 13, nil, 16, nil, 618, 13, 13, 16, nil,
- 14, nil, nil, nil, 857, nil, nil, nil, 14, 14,
- 349, 358, 358, 26, 26, nil, nil, nil, nil, 908,
- nil, nil, nil, nil, nil, nil, 16, 999, nil, 26,
- 26, 220, nil, 14, 14, nil, 790, 14, nil, nil,
- nil, 794, 795, 14, 777, nil, 311, nil, nil, 26,
- nil, nil, nil, 15, nil, nil, 778, nil, 311, nil,
- nil, 351, 15, 15, nil, 26, nil, nil, 938, nil,
- nil, nil, nil, 13, nil, nil, 14, 658, 13, 333,
- 946, 661, nil, 779, nil, nil, 714, 817, 13, 916,
- nil, nil, nil, nil, 920, nil, nil, nil, nil, 819,
- nil, nil, 819, nil, 16, 980, nil, nil, nil, nil,
- nil, nil, nil, 16, 16, nil, nil, 658, nil, nil,
- 333, nil, nil, nil, nil, nil, nil, nil, 787, nil,
- nil, 26, 825, 855, 827, nil, 13, 14, nil, nil,
- nil, nil, nil, nil, nil, 706, nil, 275, 15, 13,
- nil, nil, 425, nil, 14, nil, nil, 13, 13, nil,
- 14, nil, 14, nil, 416, 433, nil, nil, nil, nil,
- nil, 15, nil, nil, nil, nil, 622, nil, nil, 220,
- nil, 878, 13, 13, nil, 26, 13, 26, nil, nil,
- nil, nil, 13, nil, 884, 26, nil, nil, nil, 16,
- 425, nil, 889, 890, nil, nil, 429, nil, nil, 26,
- 753, nil, nil, nil, 658, 333, nil, nil, nil, nil,
- nil, nil, 16, nil, nil, 13, nil, 910, 911, nil,
- nil, 913, 15, nil, nil, nil, 15, nil, nil, nil,
- 304, 15, nil, nil, nil, 337, 337, nil, nil, 337,
- 797, nil, nil, 798, nil, 26, nil, 304, 26, nil,
- 924, nil, nil, 777, 26, 777, 15, 777, nil, nil,
- 942, nil, 819, 807, 26, 778, nil, 778, nil, 778,
- 26, nil, nil, 16, nil, nil, 13, 16, nil, nil,
- 829, nil, 16, nil, nil, nil, nil, nil, 337, 337,
- 337, 337, nil, 13, 930, nil, 932, nil, nil, 13,
- nil, 13, nil, nil, 26, 26, nil, 16, nil, 26,
- 26, nil, nil, 26, 866, 868, 870, nil, nil, nil,
- 953, 984, 954, nil, 955, nil, nil, 26, nil, nil,
- nil, nil, 26, 26, 787, 856, nil, 787, 996, 787,
- nil, 787, nil, nil, 997, nil, nil, nil, nil, nil,
- 38, nil, nil, nil, nil, 38, nil, nil, nil, 777,
- nil, 777, nil, 777, nil, 777, nil, nil, nil, nil,
- nil, 778, nil, 778, nil, 778, nil, 778, nil, nil,
- nil, nil, nil, 38, 300, 300, 434, 435, 436, 437,
- nil, nil, nil, nil, nil, nil, nil, nil, 1000, nil,
- 1001, nil, 1002, 777, 26, nil, nil, nil, nil, 26,
- 26, nil, nil, nil, 26, 778, 1010, nil, 345, 361,
- 361, 361, nil, 912, 26, nil, nil, nil, 15, nil,
- 15, nil, nil, nil, nil, 26, 304, nil, nil, nil,
- 333, nil, 1022, 787, 304, 787, nil, 787, nil, 787,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 38, 972, 974, 976, 978, nil, 979, nil, nil,
- 38, 38, 26, nil, nil, nil, nil, nil, nil, 16,
- nil, 16, nil, nil, nil, 26, nil, 787, nil, nil,
- nil, nil, nil, 26, 26, nil, nil, 523, 15, nil,
- nil, 15, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 337, 337, nil, nil, 26, nil, 26, 26,
- nil, nil, 26, 15, nil, nil, nil, nil, 26, nil,
- 744, nil, 590, nil, 1016, 1017, 1018, 1019, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 594, 16,
- nil, nil, 16, nil, nil, nil, 38, 1023, nil, nil,
- nil, 26, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 16, nil, nil, nil, nil, 38,
- 15, nil, nil, nil, nil, 15, 15, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 304, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 304,
- nil, nil, nil, nil, nil, nil, nil, 429, nil, nil,
- nil, nil, 26, nil, nil, nil, nil, nil, nil, nil,
- nil, 16, nil, nil, nil, nil, 16, 16, 39, 26,
- 38, nil, nil, 39, 38, 26, nil, 26, 300, 38,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 15, nil, 26, 300, nil, 15, nil, nil,
- nil, 39, 301, 301, 38, nil, nil, 15, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 680, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 346, 362, 362, 362,
- nil, nil, nil, 16, nil, nil, nil, nil, 16, 358,
- nil, nil, nil, nil, nil, 15, nil, nil, 16, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 15, nil,
- nil, nil, nil, nil, nil, nil, 15, 15, nil, 39,
- nil, nil, nil, nil, nil, nil, nil, nil, 39, 39,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 15, 15, nil, nil, 15, 16, nil, nil, nil,
- nil, 15, nil, nil, nil, nil, nil, nil, nil, 16,
- nil, nil, nil, nil, nil, nil, nil, 16, 16, nil,
- nil, nil, nil, nil, nil, nil, 358, nil, nil, nil,
- nil, nil, nil, nil, 15, nil, nil, nil, 948, nil,
- nil, nil, 16, 16, nil, nil, 16, nil, nil, nil,
- nil, nil, 16, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 39, nil, 38, nil, 38, nil,
- nil, nil, nil, nil, 300, nil, nil, nil, nil, nil,
- nil, nil, 300, nil, nil, 16, nil, 39, nil, 949,
- nil, nil, nil, nil, nil, 15, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 15, nil, nil, nil, nil, 337, 15, nil,
- 15, nil, nil, 337, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 38, nil, nil, 38,
- nil, nil, nil, nil, nil, nil, 16, nil, 39, nil,
- nil, nil, 39, nil, nil, nil, 301, 39, nil, nil,
- nil, 38, nil, 16, nil, nil, nil, nil, nil, 16,
- nil, 16, nil, 301, nil, nil, nil, nil, nil, nil,
- nil, nil, 39, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 38, nil,
- nil, nil, nil, 38, 38, nil, nil, nil, nil, 337,
- nil, nil, nil, nil, nil, nil, 300, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 300, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 38, nil, nil, nil, nil, 38, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 38, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 39, nil, 39, 361, nil, nil,
- nil, nil, 301, 38, nil, nil, nil, nil, nil, nil,
- 301, nil, nil, nil, nil, nil, 38, nil, nil, nil,
- nil, nil, nil, nil, 38, 38, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 38,
- 38, nil, nil, 38, nil, nil, nil, nil, nil, 38,
- nil, nil, nil, nil, 39, nil, nil, 39, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 361, nil, nil, nil, nil, 39,
- nil, nil, 38, nil, nil, nil, 944, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 39, nil, nil, nil,
- nil, 39, 39, 38, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 301, nil, nil, nil, nil, nil,
- 38, nil, nil, nil, 227, 301, 38, nil, 38, nil,
- nil, nil, nil, 274, 274, 274, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 320, 321, 322, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 274, 274, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 39, nil,
- nil, nil, nil, 39, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 39, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 362, nil, nil, nil, nil,
- nil, 39, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 39, nil, nil, nil, nil, nil,
- nil, nil, 39, 39, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 39, 39, nil,
- nil, 39, nil, nil, nil, nil, nil, 39, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 274, 408, 274, nil, nil, 427, 432, nil, nil,
- nil, nil, 362, nil, nil, nil, nil, nil, nil, nil,
- 39, nil, 227, nil, 945, 447, 448, 449, 450, 451,
- 452, 453, 454, 455, 456, 457, 458, 459, 460, 461,
- 462, 463, 464, 465, 466, 467, 468, 469, 470, 471,
- nil, nil, nil, nil, nil, nil, nil, 274, 274, nil,
- nil, nil, nil, nil, nil, nil, 274, nil, nil, nil,
- nil, nil, nil, 274, nil, 274, nil, nil, 274, 274,
- nil, 39, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 39, nil,
- nil, nil, nil, nil, 39, nil, 39, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 519, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 274, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 274, nil, 427, 643,
- 408, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 644, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 274, nil, 274, nil, 274, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 274, nil, nil, nil, nil, nil, nil, nil, nil, 678,
- 679, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 274, nil, nil, 274, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 274, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 274, 274,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 274,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 274, 755, nil, nil, 274, 274, 760,
- 762, nil, nil, nil, 765, 767, nil, nil, 643, 769,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 274, nil, nil, 274, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 274, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 274, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 274, nil,
- 858, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 760, 762, 767, 765, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 274, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 274, 858, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 969, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 274 ]
-
-racc_goto_check = [
- 31, 33, 33, 33, 22, 69, 56, 23, 94, 22,
- 8, 70, 70, 70, 73, 73, 64, 64, 140, 2,
- 37, 37, 88, 18, 22, 10, 31, 36, 15, 15,
- 139, 57, 57, 22, 22, 22, 27, 22, 22, 22,
- 168, 70, 27, 39, 49, 60, 60, 61, 61, 163,
- 64, 64, 64, 4, 97, 17, 17, 75, 47, 17,
- 51, 23, 98, 92, 54, 63, 178, 22, 22, 37,
- 6, 22, 22, 22, 22, 118, 24, 174, 20, 7,
- 50, 123, 123, 11, 7, 131, 91, 91, 93, 93,
- 151, 45, 46, 128, 57, 38, 38, 38, 119, 116,
- 71, 71, 5, 175, 71, 152, 133, 178, 17, 17,
- 17, 17, 152, 47, 11, 22, 134, 4, 97, 1,
- 22, 22, 22, 22, 22, 22, 12, 131, 55, 55,
- 40, 44, 44, 44, 155, 155, 47, 14, 40, 40,
- 2, 169, 16, 19, 28, 30, 72, 72, 72, 42,
- 62, 66, 76, 21, 76, 67, 68, 74, 21, 86,
- 87, 90, 95, 96, 99, 100, 101, 102, 103, 104,
- 119, 166, 166, 166, 105, 106, 72, 72, 107, 108,
- 109, 33, 110, 111, 112, 113, 21, 114, 115, 70,
- 7, 120, 75, 126, 132, 70, 135, 136, 73, 7,
- 7, 117, 178, 137, 138, 141, 143, 175, 5, 144,
- 22, 22, 22, 22, 133, 145, 22, 22, 22, 22,
- 22, 22, 119, 131, 134, 118, 146, 116, 139, 147,
- 150, 9, 153, 22, 57, 33, 33, 94, 168, 154,
- 23, 157, 158, 159, 33, 160, 70, 163, 161, 51,
- 37, 37, 162, 167, 70, 171, 172, 51, nil, 119,
- nil, nil, nil, nil, 21, 20, 20, 22, 22, nil,
- 20, 20, nil, 21, 21, 174, 22, 8, 47, nil,
- 64, 156, 156, 156, 156, nil, nil, 156, 31, 76,
- 76, nil, 54, 151, 22, nil, 73, 64, 22, nil,
- 73, nil, 22, 22, 23, nil, nil, 31, 40, 24,
- nil, nil, 128, 169, nil, 11, nil, 37, nil, 22,
- 47, 123, 123, nil, 47, 49, nil, 37, 22, 22,
- nil, nil, 17, 17, nil, nil, 24, 63, 4, 97,
- 47, nil, nil, 50, 22, 22, 47, 169, nil, 92,
- 168, 117, 45, 46, 117, 6, nil, 45, 46, 21,
- nil, nil, 123, 93, 22, nil, 44, nil, nil, 7,
- nil, nil, nil, 23, 44, nil, nil, 36, nil, nil,
- 22, 72, 21, 23, nil, nil, 37, 24, nil, 72,
- 31, 98, 4, 97, 37, nil, 24, 168, nil, 168,
- nil, nil, nil, 73, 9, nil, nil, nil, 39, 73,
- 97, 51, nil, 39, 33, 15, 8, nil, 57, nil,
- nil, 8, nil, nil, nil, 169, nil, 9, 73, nil,
- 139, 139, 60, nil, 61, 47, 75, 178, nil, nil,
- 168, 168, nil, 21, 18, nil, 22, 21, nil, 163,
- 163, nil, 21, 166, 166, nil, 166, 166, 71, 166,
- nil, 65, 73, nil, 57, nil, nil, 91, nil, 123,
- nil, nil, nil, nil, nil, nil, nil, 21, 33, nil,
- nil, 117, nil, 117, 38, nil, 64, nil, 10, nil,
- 38, nil, 9, nil, 64, 73, nil, 9, nil, 41,
- 22, nil, 22, nil, 41, 73, nil, 156, 22, 156,
- 22, 27, 129, nil, 49, nil, 22, 2, nil, 41,
- nil, 47, 49, nil, 22, 76, nil, nil, 41, 41,
- 41, 57, 41, nil, nil, 8, nil, nil, 75, nil,
- nil, 57, nil, 38, nil, nil, 47, 33, nil, nil,
- nil, nil, nil, nil, 117, 117, 70, 33, nil, 129,
- nil, 129, 41, 41, 73, nil, 41, nil, nil, 168,
- 22, 168, 73, 22, nil, nil, nil, 7, 94, 22,
- nil, nil, nil, nil, 166, 166, 166, 166, nil, 22,
- nil, nil, nil, nil, nil, 22, nil, 168, nil, nil,
- 57, nil, nil, 72, nil, nil, 57, 117, 65, 117,
- 41, 88, nil, nil, 65, 41, 41, 41, 41, 41,
- 41, 97, 97, 31, nil, 31, nil, 31, 69, 22,
- 22, nil, nil, 91, 22, 22, 15, nil, 22, 57,
- 97, 97, 166, 72, 117, 140, nil, nil, 64, 21,
- 31, 21, 22, 60, 8, 61, 91, 22, 22, 64,
- 73, nil, nil, 73, 70, 31, nil, nil, nil, 31,
- 22, 47, 24, 56, nil, 168, 49, nil, nil, nil,
- 65, 22, 65, 20, 20, 65, 65, 49, 20, 20,
- nil, nil, 20, 47, nil, nil, nil, nil, nil, nil,
- nil, 31, nil, nil, nil, 41, 41, 41, 41, nil,
- 31, 41, 41, 41, 41, 41, 41, 17, nil, 21,
- nil, nil, 21, 17, nil, nil, nil, nil, 41, 22,
- nil, 129, nil, 129, 22, 22, nil, nil, nil, 22,
- 72, nil, nil, nil, 21, nil, nil, nil, nil, 22,
- 69, nil, 25, nil, 69, nil, nil, 25, nil, 129,
- 22, 57, 41, 41, 9, 31, nil, 9, nil, 64,
- nil, 41, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 23, nil, 25, 25, 25, nil, 41,
- nil, 22, nil, 41, nil, nil, 37, 22, 41, nil,
- nil, 21, nil, 26, nil, 65, 21, 21, 26, nil,
- 22, nil, nil, nil, 20, nil, nil, nil, 22, 22,
- 25, 25, 25, 41, 41, nil, nil, nil, nil, 17,
- nil, nil, nil, nil, nil, nil, 26, 129, nil, 41,
- 41, 22, nil, 22, 22, nil, 9, 22, nil, nil,
- nil, 9, 9, 22, 122, nil, 64, nil, nil, 41,
- nil, nil, nil, 25, nil, nil, 124, nil, 64, nil,
- nil, 26, 25, 25, nil, 41, nil, nil, 22, nil,
- nil, nil, nil, 21, nil, nil, 22, 65, 21, 65,
- 22, 65, nil, 127, nil, nil, 97, 122, 21, 97,
- nil, nil, nil, nil, 97, nil, nil, nil, nil, 124,
- nil, nil, 124, nil, 26, 31, nil, nil, nil, nil,
- nil, nil, nil, 26, 26, nil, nil, 65, nil, nil,
- 65, nil, nil, nil, nil, nil, nil, nil, 170, nil,
- nil, 41, 127, 9, 127, nil, 21, 22, nil, nil,
- nil, nil, nil, nil, nil, 65, nil, 33, 25, 21,
- nil, nil, 57, nil, 22, nil, nil, 21, 21, nil,
- 22, nil, 22, nil, 73, 65, nil, nil, nil, nil,
- nil, 25, nil, nil, nil, nil, 31, nil, nil, 22,
- nil, 9, 21, 21, nil, 41, 21, 41, nil, nil,
- nil, nil, 21, nil, 9, 41, nil, nil, nil, 26,
- 57, nil, 9, 9, nil, nil, 26, nil, nil, 41,
- 65, nil, nil, nil, 65, 65, nil, nil, nil, nil,
- nil, nil, 26, nil, nil, 21, nil, 9, 9, nil,
- nil, 9, 25, nil, nil, nil, 25, nil, nil, nil,
- 25, 25, nil, nil, nil, 29, 29, nil, nil, 29,
- 65, nil, nil, 65, nil, 41, nil, 25, 41, nil,
- 122, nil, nil, 122, 41, 122, 25, 122, nil, nil,
- 9, nil, 124, 65, 41, 124, nil, 124, nil, 124,
- 41, nil, nil, 26, nil, nil, 21, 26, nil, nil,
- 65, nil, 26, nil, nil, nil, nil, nil, 29, 29,
- 29, 29, nil, 21, 127, nil, 127, nil, nil, 21,
- nil, 21, nil, nil, 41, 41, nil, 26, nil, 41,
- 41, nil, nil, 41, 125, 125, 125, nil, nil, nil,
- 127, 9, 127, nil, 127, nil, nil, 41, nil, nil,
- nil, nil, 41, 41, 170, 65, nil, 170, 9, 170,
- nil, 170, nil, nil, 9, nil, nil, nil, nil, nil,
- 52, nil, nil, nil, nil, 52, nil, nil, nil, 122,
- nil, 122, nil, 122, nil, 122, nil, nil, nil, nil,
- nil, 124, nil, 124, nil, 124, nil, 124, nil, nil,
- nil, nil, nil, 52, 52, 52, 29, 29, 29, 29,
- nil, nil, nil, nil, nil, nil, nil, nil, 127, nil,
- 127, nil, 127, 122, 41, nil, nil, nil, nil, 41,
- 41, nil, nil, nil, 41, 124, 127, nil, 52, 52,
- 52, 52, nil, 65, 41, nil, nil, nil, 25, nil,
- 25, nil, nil, nil, nil, 41, 25, nil, nil, nil,
- 65, nil, 127, 170, 25, 170, nil, 170, nil, 170,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 52, 125, 125, 125, 125, nil, 125, nil, nil,
- 52, 52, 41, nil, nil, nil, nil, nil, nil, 26,
- nil, 26, nil, nil, nil, 41, nil, 170, nil, nil,
- nil, nil, nil, 41, 41, nil, nil, 29, 25, nil,
- nil, 25, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 29, 29, nil, nil, 41, nil, 41, 41,
- nil, nil, 41, 25, nil, nil, nil, nil, 41, nil,
- 25, nil, 29, nil, 125, 125, 125, 125, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 29, 26,
- nil, nil, 26, nil, nil, nil, 52, 125, nil, nil,
- nil, 41, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 26, nil, nil, nil, nil, 52,
- 25, nil, nil, nil, nil, 25, 25, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 25, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 25,
- nil, nil, nil, nil, nil, nil, nil, 26, nil, nil,
- nil, nil, 41, nil, nil, nil, nil, nil, nil, nil,
- nil, 26, nil, nil, nil, nil, 26, 26, 53, 41,
- 52, nil, nil, 53, 52, 41, nil, 41, 52, 52,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 25, nil, 41, 52, nil, 25, nil, nil,
- nil, 53, 53, 53, 52, nil, nil, 25, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 29, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 53, 53, 53, 53,
- nil, nil, nil, 26, nil, nil, nil, nil, 26, 25,
- nil, nil, nil, nil, nil, 25, nil, nil, 26, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 25, nil,
- nil, nil, nil, nil, nil, nil, 25, 25, nil, 53,
- nil, nil, nil, nil, nil, nil, nil, nil, 53, 53,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 25, 25, nil, nil, 25, 26, nil, nil, nil,
- nil, 25, nil, nil, nil, nil, nil, nil, nil, 26,
- nil, nil, nil, nil, nil, nil, nil, 26, 26, nil,
- nil, nil, nil, nil, nil, nil, 25, nil, nil, nil,
- nil, nil, nil, nil, 25, nil, nil, nil, 25, nil,
- nil, nil, 26, 26, nil, nil, 26, nil, nil, nil,
- nil, nil, 26, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 53, nil, 52, nil, 52, nil,
- nil, nil, nil, nil, 52, nil, nil, nil, nil, nil,
- nil, nil, 52, nil, nil, 26, nil, 53, nil, 26,
- nil, nil, nil, nil, nil, 25, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 25, nil, nil, nil, nil, 29, 25, nil,
- 25, nil, nil, 29, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 52, nil, nil, 52,
- nil, nil, nil, nil, nil, nil, 26, nil, 53, nil,
- nil, nil, 53, nil, nil, nil, 53, 53, nil, nil,
- nil, 52, nil, 26, nil, nil, nil, nil, nil, 26,
- nil, 26, nil, 53, nil, nil, nil, nil, nil, nil,
- nil, nil, 53, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 52, nil,
- nil, nil, nil, 52, 52, nil, nil, nil, nil, 29,
- nil, nil, nil, nil, nil, nil, 52, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 52, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 52, nil, nil, nil, nil, 52, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 52, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 53, nil, 53, 52, nil, nil,
- nil, nil, 53, 52, nil, nil, nil, nil, nil, nil,
- 53, nil, nil, nil, nil, nil, 52, nil, nil, nil,
- nil, nil, nil, nil, 52, 52, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 52,
- 52, nil, nil, 52, nil, nil, nil, nil, nil, 52,
- nil, nil, nil, nil, 53, nil, nil, 53, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 52, nil, nil, nil, nil, 53,
- nil, nil, 52, nil, nil, nil, 52, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 53, nil, nil, nil,
- nil, 53, 53, 52, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 53, nil, nil, nil, nil, nil,
- 52, nil, nil, nil, 32, 53, 52, nil, 52, nil,
- nil, nil, nil, 32, 32, 32, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 32, 32, 32, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 32, 32, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 53, nil,
- nil, nil, nil, 53, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 53, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 53, nil, nil, nil, nil,
- nil, 53, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 53, nil, nil, nil, nil, nil,
- nil, nil, 53, 53, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 53, 53, nil,
- nil, 53, nil, nil, nil, nil, nil, 53, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 32, 32, 32, nil, nil, 32, 32, nil, nil,
- nil, nil, 53, nil, nil, nil, nil, nil, nil, nil,
- 53, nil, 32, nil, 53, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
- nil, nil, nil, nil, nil, nil, nil, 32, 32, nil,
- nil, nil, nil, nil, nil, nil, 32, nil, nil, nil,
- nil, nil, nil, 32, nil, 32, nil, nil, 32, 32,
- nil, 53, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 53, nil,
- nil, nil, nil, nil, 53, nil, 53, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 32, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 32, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 32, nil, 32, 32,
- 32, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 32, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 32, nil, 32, nil, 32, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 32, nil, nil, nil, nil, nil, nil, nil, nil, 32,
- 32, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 32, nil, nil, 32, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 32, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 32, 32,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 32,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 32, 32, nil, nil, 32, 32, 32,
- 32, nil, nil, nil, 32, 32, nil, nil, 32, 32,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 32, nil, nil, 32, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 32, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 32, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, 32, nil,
- 32, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, 32, 32, 32, 32, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 32, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 32, 32, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 32, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, 32 ]
-
-racc_goto_pointer = [
- nil, 119, 19, nil, 50, 97, 67, 79, -314, 198,
- -496, -598, -678, nil, -359, 20, 133, -8, -190, 75,
- 58, 153, 4, -202, -333, 752, 803, -171, -63, 992,
- 23, -19, 2114, -28, nil, nil, 3, -190, 69, -219,
- -343, 499, -328, nil, 102, 58, 59, -159, nil, 10,
- 45, -255, 1170, 1458, -291, 59, -65, 23, nil, nil,
- 37, 39, -249, 24, -18, 401, -105, -706, 97, -54,
- -18, -228, 117, -12, -317, -220, -334, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 88, 100, -39, nil,
- 99, -252, -647, -482, -335, 94, -196, 51, -530, 93,
- 108, 108, -356, 110, 104, -539, 109, -538, -400, -734,
- -404, -550, -179, -188, -406, -666, -732, -350, -476, -735,
- -455, nil, 208, -455, 220, 355, -453, 247, -553, -134,
- nil, -561, -679, -767, -757, -140, -490, 141, -329, -306,
- -4, -52, nil, -61, -59, -698, -456, -579, nil, nil,
- 153, 11, 23, 149, 155, -247, -98, 156, 156, 156,
- -353, -351, -336, -287, nil, nil, -368, -440, -296, -552,
- 292, -434, -606, nil, -618, -764, nil, nil, -422 ]
-
-racc_goto_default = [
- nil, nil, nil, 3, nil, 4, 344, 291, nil, 521,
- nil, 836, nil, 288, 289, nil, nil, nil, 11, 12,
- 18, 226, 319, nil, nil, 224, 225, nil, nil, 17,
- nil, 439, 21, 22, 23, 24, nil, 675, nil, nil,
- nil, 308, nil, 25, 410, 32, nil, nil, 34, 37,
- 36, nil, 221, 222, 356, nil, 129, 418, 128, 131,
- 75, 76, nil, 90, 46, 280, nil, nil, nil, 805,
- 411, nil, 412, 423, 629, 485, 278, 264, 47, 48,
- 49, 50, 51, 52, 53, 54, 55, nil, 265, 61,
- nil, nil, nil, nil, nil, nil, nil, 567, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 702, 549, nil, 703,
- 926, 776, 537, nil, 538, nil, nil, 539, nil, 541,
- 645, nil, nil, nil, 547, nil, nil, nil, nil, nil,
- nil, nil, 422, nil, nil, nil, nil, nil, 74, 77,
- 78, nil, nil, nil, nil, nil, 596, nil, nil, nil,
- nil, nil, nil, 820, 737, 536, nil, 540, 828, 552,
- 554, 555, 788, 558, 559, 789, 562, 565, 283 ]
-
-racc_reduce_table = [
- 0, 0, :racc_error,
- 1, 146, :_reduce_none,
- 2, 147, :_reduce_2,
- 0, 148, :_reduce_3,
- 1, 148, :_reduce_4,
- 3, 148, :_reduce_5,
- 2, 148, :_reduce_6,
- 1, 150, :_reduce_none,
- 4, 150, :_reduce_8,
- 4, 153, :_reduce_9,
- 2, 154, :_reduce_10,
- 0, 158, :_reduce_11,
- 1, 158, :_reduce_12,
- 3, 158, :_reduce_13,
- 2, 158, :_reduce_14,
- 1, 159, :_reduce_none,
- 4, 159, :_reduce_16,
- 0, 175, :_reduce_17,
- 4, 152, :_reduce_18,
- 3, 152, :_reduce_19,
- 3, 152, :_reduce_20,
- 3, 152, :_reduce_21,
- 2, 152, :_reduce_22,
- 3, 152, :_reduce_23,
- 3, 152, :_reduce_24,
- 3, 152, :_reduce_25,
- 3, 152, :_reduce_26,
- 3, 152, :_reduce_27,
- 4, 152, :_reduce_28,
- 1, 152, :_reduce_none,
- 3, 152, :_reduce_30,
- 3, 152, :_reduce_31,
- 6, 152, :_reduce_32,
- 5, 152, :_reduce_33,
- 5, 152, :_reduce_34,
- 5, 152, :_reduce_35,
- 5, 152, :_reduce_36,
- 3, 152, :_reduce_37,
- 3, 152, :_reduce_38,
- 3, 152, :_reduce_39,
- 1, 152, :_reduce_none,
- 3, 163, :_reduce_41,
- 3, 163, :_reduce_42,
- 1, 174, :_reduce_none,
- 3, 174, :_reduce_44,
- 3, 174, :_reduce_45,
- 3, 174, :_reduce_46,
- 2, 174, :_reduce_47,
- 1, 174, :_reduce_none,
- 1, 162, :_reduce_none,
- 1, 165, :_reduce_none,
- 1, 165, :_reduce_none,
- 1, 179, :_reduce_none,
- 4, 179, :_reduce_53,
- 0, 187, :_reduce_54,
- 5, 184, :_reduce_55,
- 1, 186, :_reduce_none,
- 2, 178, :_reduce_57,
- 3, 178, :_reduce_58,
- 4, 178, :_reduce_59,
- 5, 178, :_reduce_60,
- 4, 178, :_reduce_61,
- 5, 178, :_reduce_62,
- 2, 178, :_reduce_63,
- 2, 178, :_reduce_64,
- 2, 178, :_reduce_65,
- 2, 178, :_reduce_66,
- 2, 178, :_reduce_67,
- 1, 164, :_reduce_68,
- 3, 164, :_reduce_69,
- 1, 191, :_reduce_70,
- 3, 191, :_reduce_71,
- 1, 190, :_reduce_none,
- 2, 190, :_reduce_73,
- 3, 190, :_reduce_74,
- 5, 190, :_reduce_75,
- 2, 190, :_reduce_76,
- 4, 190, :_reduce_77,
- 2, 190, :_reduce_78,
- 4, 190, :_reduce_79,
- 1, 190, :_reduce_80,
- 3, 190, :_reduce_81,
- 1, 194, :_reduce_none,
- 3, 194, :_reduce_83,
- 2, 193, :_reduce_84,
- 3, 193, :_reduce_85,
- 1, 196, :_reduce_86,
- 3, 196, :_reduce_87,
- 1, 195, :_reduce_88,
- 1, 195, :_reduce_89,
- 4, 195, :_reduce_90,
- 3, 195, :_reduce_91,
- 3, 195, :_reduce_92,
- 3, 195, :_reduce_93,
- 3, 195, :_reduce_94,
- 2, 195, :_reduce_95,
- 1, 195, :_reduce_96,
- 1, 171, :_reduce_97,
- 1, 171, :_reduce_98,
- 4, 171, :_reduce_99,
- 3, 171, :_reduce_100,
- 3, 171, :_reduce_101,
- 3, 171, :_reduce_102,
- 3, 171, :_reduce_103,
- 2, 171, :_reduce_104,
- 1, 171, :_reduce_105,
- 1, 199, :_reduce_106,
- 1, 199, :_reduce_none,
- 2, 200, :_reduce_108,
- 1, 200, :_reduce_109,
- 3, 200, :_reduce_110,
- 1, 201, :_reduce_none,
- 1, 201, :_reduce_none,
- 1, 201, :_reduce_none,
- 1, 201, :_reduce_none,
- 1, 201, :_reduce_none,
- 1, 204, :_reduce_116,
- 1, 204, :_reduce_none,
- 1, 160, :_reduce_none,
- 1, 160, :_reduce_none,
- 1, 161, :_reduce_120,
- 0, 207, :_reduce_121,
- 4, 161, :_reduce_122,
- 1, 202, :_reduce_none,
- 1, 202, :_reduce_none,
- 1, 202, :_reduce_none,
- 1, 202, :_reduce_none,
- 1, 202, :_reduce_none,
- 1, 202, :_reduce_none,
- 1, 202, :_reduce_none,
- 1, 202, :_reduce_none,
- 1, 202, :_reduce_none,
- 1, 202, :_reduce_none,
- 1, 202, :_reduce_none,
- 1, 202, :_reduce_none,
- 1, 202, :_reduce_none,
- 1, 202, :_reduce_none,
- 1, 202, :_reduce_none,
- 1, 202, :_reduce_none,
- 1, 202, :_reduce_none,
- 1, 202, :_reduce_none,
- 1, 202, :_reduce_none,
- 1, 202, :_reduce_none,
- 1, 202, :_reduce_none,
- 1, 202, :_reduce_none,
- 1, 202, :_reduce_none,
- 1, 202, :_reduce_none,
- 1, 202, :_reduce_none,
- 1, 202, :_reduce_none,
- 1, 202, :_reduce_none,
- 1, 202, :_reduce_none,
- 1, 202, :_reduce_none,
- 1, 202, :_reduce_none,
- 1, 203, :_reduce_none,
- 1, 203, :_reduce_none,
- 1, 203, :_reduce_none,
- 1, 203, :_reduce_none,
- 1, 203, :_reduce_none,
- 1, 203, :_reduce_none,
- 1, 203, :_reduce_none,
- 1, 203, :_reduce_none,
- 1, 203, :_reduce_none,
- 1, 203, :_reduce_none,
- 1, 203, :_reduce_none,
- 1, 203, :_reduce_none,
- 1, 203, :_reduce_none,
- 1, 203, :_reduce_none,
- 1, 203, :_reduce_none,
- 1, 203, :_reduce_none,
- 1, 203, :_reduce_none,
- 1, 203, :_reduce_none,
- 1, 203, :_reduce_none,
- 1, 203, :_reduce_none,
- 1, 203, :_reduce_none,
- 1, 203, :_reduce_none,
- 1, 203, :_reduce_none,
- 1, 203, :_reduce_none,
- 1, 203, :_reduce_none,
- 1, 203, :_reduce_none,
- 1, 203, :_reduce_none,
- 1, 203, :_reduce_none,
- 1, 203, :_reduce_none,
- 1, 203, :_reduce_none,
- 1, 203, :_reduce_none,
- 1, 203, :_reduce_none,
- 1, 203, :_reduce_none,
- 1, 203, :_reduce_none,
- 1, 203, :_reduce_none,
- 1, 203, :_reduce_none,
- 1, 203, :_reduce_none,
- 1, 203, :_reduce_none,
- 1, 203, :_reduce_none,
- 1, 203, :_reduce_none,
- 1, 203, :_reduce_none,
- 3, 177, :_reduce_194,
- 5, 177, :_reduce_195,
- 3, 177, :_reduce_196,
- 5, 177, :_reduce_197,
- 6, 177, :_reduce_198,
- 5, 177, :_reduce_199,
- 5, 177, :_reduce_200,
- 5, 177, :_reduce_201,
- 5, 177, :_reduce_202,
- 4, 177, :_reduce_203,
- 3, 177, :_reduce_204,
- 3, 177, :_reduce_205,
- 3, 177, :_reduce_206,
- 3, 177, :_reduce_207,
- 3, 177, :_reduce_208,
- 3, 177, :_reduce_209,
- 3, 177, :_reduce_210,
- 3, 177, :_reduce_211,
- 3, 177, :_reduce_212,
- 4, 177, :_reduce_213,
- 2, 177, :_reduce_214,
- 2, 177, :_reduce_215,
- 3, 177, :_reduce_216,
- 3, 177, :_reduce_217,
- 3, 177, :_reduce_218,
- 3, 177, :_reduce_219,
- 3, 177, :_reduce_220,
- 3, 177, :_reduce_221,
- 3, 177, :_reduce_222,
- 3, 177, :_reduce_223,
- 3, 177, :_reduce_224,
- 3, 177, :_reduce_225,
- 3, 177, :_reduce_226,
- 3, 177, :_reduce_227,
- 3, 177, :_reduce_228,
- 2, 177, :_reduce_229,
- 2, 177, :_reduce_230,
- 3, 177, :_reduce_231,
- 3, 177, :_reduce_232,
- 3, 177, :_reduce_233,
- 3, 177, :_reduce_234,
- 3, 177, :_reduce_235,
- 0, 211, :_reduce_236,
- 0, 212, :_reduce_237,
- 8, 177, :_reduce_238,
- 1, 177, :_reduce_none,
- 1, 210, :_reduce_none,
- 1, 213, :_reduce_none,
- 2, 213, :_reduce_none,
- 4, 213, :_reduce_243,
- 2, 213, :_reduce_244,
- 3, 218, :_reduce_245,
- 0, 219, :_reduce_246,
- 1, 219, :_reduce_none,
- 0, 168, :_reduce_248,
- 1, 168, :_reduce_none,
- 2, 168, :_reduce_none,
- 4, 168, :_reduce_251,
- 2, 168, :_reduce_252,
- 1, 189, :_reduce_253,
- 2, 189, :_reduce_254,
- 2, 189, :_reduce_255,
- 4, 189, :_reduce_256,
- 1, 189, :_reduce_257,
- 0, 222, :_reduce_258,
- 2, 183, :_reduce_259,
- 2, 221, :_reduce_260,
- 2, 220, :_reduce_261,
- 0, 220, :_reduce_262,
- 1, 215, :_reduce_263,
- 2, 215, :_reduce_264,
- 3, 215, :_reduce_265,
- 4, 215, :_reduce_266,
- 1, 173, :_reduce_267,
- 1, 173, :_reduce_none,
- 3, 172, :_reduce_269,
- 4, 172, :_reduce_270,
- 2, 172, :_reduce_271,
- 1, 209, :_reduce_none,
- 1, 209, :_reduce_none,
- 1, 209, :_reduce_none,
- 1, 209, :_reduce_none,
- 1, 209, :_reduce_none,
- 1, 209, :_reduce_none,
- 1, 209, :_reduce_none,
- 1, 209, :_reduce_none,
- 1, 209, :_reduce_none,
- 1, 209, :_reduce_none,
- 1, 209, :_reduce_282,
- 0, 245, :_reduce_283,
- 4, 209, :_reduce_284,
- 0, 246, :_reduce_285,
- 0, 247, :_reduce_286,
- 6, 209, :_reduce_287,
- 0, 248, :_reduce_288,
- 4, 209, :_reduce_289,
- 3, 209, :_reduce_290,
- 3, 209, :_reduce_291,
- 2, 209, :_reduce_292,
- 3, 209, :_reduce_293,
- 3, 209, :_reduce_294,
- 1, 209, :_reduce_295,
- 4, 209, :_reduce_296,
- 3, 209, :_reduce_297,
- 1, 209, :_reduce_298,
- 5, 209, :_reduce_299,
- 4, 209, :_reduce_300,
- 3, 209, :_reduce_301,
- 2, 209, :_reduce_302,
- 1, 209, :_reduce_none,
- 2, 209, :_reduce_304,
- 2, 209, :_reduce_305,
- 6, 209, :_reduce_306,
- 6, 209, :_reduce_307,
- 0, 249, :_reduce_308,
- 0, 250, :_reduce_309,
- 7, 209, :_reduce_310,
- 0, 251, :_reduce_311,
- 0, 252, :_reduce_312,
- 7, 209, :_reduce_313,
- 5, 209, :_reduce_314,
- 4, 209, :_reduce_315,
- 0, 253, :_reduce_316,
- 0, 254, :_reduce_317,
- 9, 209, :_reduce_318,
- 0, 255, :_reduce_319,
- 6, 209, :_reduce_320,
- 0, 256, :_reduce_321,
- 7, 209, :_reduce_322,
- 0, 257, :_reduce_323,
- 5, 209, :_reduce_324,
- 0, 258, :_reduce_325,
- 6, 209, :_reduce_326,
- 0, 259, :_reduce_327,
- 0, 260, :_reduce_328,
- 9, 209, :_reduce_329,
- 1, 209, :_reduce_330,
- 1, 209, :_reduce_331,
- 1, 209, :_reduce_332,
- 1, 209, :_reduce_333,
- 1, 167, :_reduce_none,
- 1, 236, :_reduce_none,
- 1, 236, :_reduce_none,
- 2, 236, :_reduce_337,
- 1, 238, :_reduce_none,
- 1, 238, :_reduce_none,
- 1, 237, :_reduce_none,
- 5, 237, :_reduce_341,
- 1, 156, :_reduce_none,
- 2, 156, :_reduce_343,
- 1, 240, :_reduce_none,
- 1, 240, :_reduce_none,
- 1, 261, :_reduce_346,
- 3, 261, :_reduce_347,
- 1, 264, :_reduce_348,
- 3, 264, :_reduce_349,
- 1, 263, :_reduce_none,
- 4, 263, :_reduce_351,
- 6, 263, :_reduce_352,
- 3, 263, :_reduce_353,
- 5, 263, :_reduce_354,
- 2, 263, :_reduce_355,
- 4, 263, :_reduce_356,
- 1, 263, :_reduce_357,
- 3, 263, :_reduce_358,
- 4, 265, :_reduce_359,
- 2, 265, :_reduce_360,
- 2, 265, :_reduce_361,
- 1, 265, :_reduce_362,
- 2, 270, :_reduce_363,
- 0, 270, :_reduce_364,
- 6, 271, :_reduce_365,
- 8, 271, :_reduce_366,
- 4, 271, :_reduce_367,
- 6, 271, :_reduce_368,
- 4, 271, :_reduce_369,
- 2, 271, :_reduce_none,
- 6, 271, :_reduce_371,
- 2, 271, :_reduce_372,
- 4, 271, :_reduce_373,
- 6, 271, :_reduce_374,
- 2, 271, :_reduce_375,
- 4, 271, :_reduce_376,
- 2, 271, :_reduce_377,
- 4, 271, :_reduce_378,
- 1, 271, :_reduce_none,
- 0, 185, :_reduce_380,
- 1, 185, :_reduce_381,
- 3, 275, :_reduce_382,
- 1, 275, :_reduce_383,
- 4, 275, :_reduce_384,
- 1, 276, :_reduce_385,
- 4, 276, :_reduce_386,
- 1, 277, :_reduce_387,
- 3, 277, :_reduce_388,
- 1, 278, :_reduce_389,
- 1, 278, :_reduce_none,
- 0, 282, :_reduce_391,
- 0, 283, :_reduce_392,
- 4, 235, :_reduce_393,
- 4, 280, :_reduce_394,
- 1, 280, :_reduce_395,
- 3, 281, :_reduce_396,
- 3, 281, :_reduce_397,
- 0, 286, :_reduce_398,
- 5, 285, :_reduce_399,
- 2, 180, :_reduce_400,
- 4, 180, :_reduce_401,
- 5, 180, :_reduce_402,
- 5, 180, :_reduce_403,
- 2, 234, :_reduce_404,
- 4, 234, :_reduce_405,
- 4, 234, :_reduce_406,
- 3, 234, :_reduce_407,
- 3, 234, :_reduce_408,
- 3, 234, :_reduce_409,
- 2, 234, :_reduce_410,
- 1, 234, :_reduce_411,
- 4, 234, :_reduce_412,
- 0, 288, :_reduce_413,
- 5, 233, :_reduce_414,
- 0, 289, :_reduce_415,
- 5, 233, :_reduce_416,
- 5, 239, :_reduce_417,
- 1, 290, :_reduce_418,
- 1, 290, :_reduce_none,
- 6, 155, :_reduce_420,
- 0, 155, :_reduce_421,
- 1, 291, :_reduce_422,
- 1, 291, :_reduce_none,
- 1, 291, :_reduce_none,
- 2, 292, :_reduce_425,
- 1, 292, :_reduce_none,
- 2, 157, :_reduce_427,
- 1, 157, :_reduce_none,
- 1, 223, :_reduce_none,
- 1, 223, :_reduce_none,
- 1, 223, :_reduce_none,
- 1, 224, :_reduce_432,
- 1, 294, :_reduce_433,
- 2, 294, :_reduce_434,
- 3, 295, :_reduce_435,
- 1, 295, :_reduce_436,
- 1, 295, :_reduce_437,
- 3, 225, :_reduce_438,
- 4, 226, :_reduce_439,
- 3, 227, :_reduce_440,
- 0, 299, :_reduce_441,
- 3, 299, :_reduce_442,
- 1, 300, :_reduce_443,
- 2, 300, :_reduce_444,
- 3, 229, :_reduce_445,
- 0, 302, :_reduce_446,
- 3, 302, :_reduce_447,
- 3, 228, :_reduce_448,
- 3, 230, :_reduce_449,
- 0, 303, :_reduce_450,
- 3, 303, :_reduce_451,
- 0, 304, :_reduce_452,
- 3, 304, :_reduce_453,
- 0, 296, :_reduce_454,
- 2, 296, :_reduce_455,
- 0, 297, :_reduce_456,
- 2, 297, :_reduce_457,
- 0, 298, :_reduce_458,
- 2, 298, :_reduce_459,
- 1, 301, :_reduce_460,
- 2, 301, :_reduce_461,
- 0, 306, :_reduce_462,
- 4, 301, :_reduce_463,
- 1, 305, :_reduce_464,
- 1, 305, :_reduce_465,
- 1, 305, :_reduce_466,
- 1, 305, :_reduce_none,
- 1, 205, :_reduce_468,
- 3, 206, :_reduce_469,
- 1, 293, :_reduce_470,
- 2, 293, :_reduce_471,
- 1, 208, :_reduce_472,
- 1, 208, :_reduce_473,
- 1, 208, :_reduce_474,
- 1, 208, :_reduce_475,
- 1, 197, :_reduce_476,
- 1, 197, :_reduce_477,
- 1, 197, :_reduce_478,
- 1, 197, :_reduce_479,
- 1, 197, :_reduce_480,
- 1, 198, :_reduce_481,
- 1, 198, :_reduce_482,
- 1, 198, :_reduce_483,
- 1, 198, :_reduce_484,
- 1, 198, :_reduce_485,
- 1, 198, :_reduce_486,
- 1, 198, :_reduce_487,
- 1, 231, :_reduce_488,
- 1, 231, :_reduce_489,
- 1, 166, :_reduce_490,
- 1, 166, :_reduce_491,
- 1, 170, :_reduce_492,
- 1, 170, :_reduce_493,
- 1, 241, :_reduce_494,
- 0, 307, :_reduce_495,
- 4, 241, :_reduce_496,
- 2, 241, :_reduce_497,
- 3, 243, :_reduce_498,
- 0, 309, :_reduce_499,
- 3, 243, :_reduce_500,
- 4, 308, :_reduce_501,
- 2, 308, :_reduce_502,
- 2, 308, :_reduce_503,
- 1, 308, :_reduce_504,
- 2, 311, :_reduce_505,
- 0, 311, :_reduce_506,
- 6, 284, :_reduce_507,
- 8, 284, :_reduce_508,
- 4, 284, :_reduce_509,
- 6, 284, :_reduce_510,
- 4, 284, :_reduce_511,
- 6, 284, :_reduce_512,
- 2, 284, :_reduce_513,
- 4, 284, :_reduce_514,
- 6, 284, :_reduce_515,
- 2, 284, :_reduce_516,
- 4, 284, :_reduce_517,
- 2, 284, :_reduce_518,
- 4, 284, :_reduce_519,
- 1, 284, :_reduce_520,
- 0, 284, :_reduce_521,
- 1, 279, :_reduce_522,
- 1, 279, :_reduce_523,
- 1, 279, :_reduce_524,
- 1, 279, :_reduce_525,
- 1, 262, :_reduce_none,
- 1, 262, :_reduce_527,
- 1, 313, :_reduce_528,
- 1, 314, :_reduce_529,
- 3, 314, :_reduce_530,
- 1, 272, :_reduce_531,
- 3, 272, :_reduce_532,
- 1, 315, :_reduce_533,
- 2, 316, :_reduce_534,
- 1, 316, :_reduce_535,
- 2, 317, :_reduce_536,
- 1, 317, :_reduce_537,
- 1, 266, :_reduce_538,
- 3, 266, :_reduce_539,
- 1, 310, :_reduce_540,
- 3, 310, :_reduce_541,
- 1, 318, :_reduce_none,
- 1, 318, :_reduce_none,
- 2, 267, :_reduce_544,
- 1, 267, :_reduce_545,
- 3, 319, :_reduce_546,
- 3, 320, :_reduce_547,
- 1, 273, :_reduce_548,
- 3, 273, :_reduce_549,
- 1, 312, :_reduce_550,
- 3, 312, :_reduce_551,
- 1, 321, :_reduce_none,
- 1, 321, :_reduce_none,
- 2, 274, :_reduce_554,
- 1, 274, :_reduce_555,
- 1, 322, :_reduce_none,
- 1, 322, :_reduce_none,
- 2, 269, :_reduce_558,
- 2, 268, :_reduce_559,
- 0, 268, :_reduce_560,
- 1, 244, :_reduce_none,
- 3, 244, :_reduce_562,
- 0, 232, :_reduce_563,
- 2, 232, :_reduce_none,
- 1, 217, :_reduce_565,
- 3, 217, :_reduce_566,
- 3, 323, :_reduce_567,
- 2, 323, :_reduce_568,
- 4, 323, :_reduce_569,
- 2, 323, :_reduce_570,
- 1, 188, :_reduce_none,
- 1, 188, :_reduce_none,
- 1, 188, :_reduce_none,
- 1, 182, :_reduce_none,
- 1, 182, :_reduce_none,
- 1, 182, :_reduce_none,
- 1, 182, :_reduce_none,
- 1, 287, :_reduce_none,
- 1, 287, :_reduce_none,
- 1, 287, :_reduce_none,
- 1, 181, :_reduce_none,
- 1, 181, :_reduce_none,
- 0, 149, :_reduce_none,
- 1, 149, :_reduce_none,
- 0, 176, :_reduce_none,
- 1, 176, :_reduce_none,
- 2, 192, :_reduce_587,
- 2, 169, :_reduce_588,
- 0, 216, :_reduce_none,
- 1, 216, :_reduce_none,
- 1, 216, :_reduce_none,
- 1, 242, :_reduce_592,
- 1, 242, :_reduce_none,
- 1, 151, :_reduce_none,
- 2, 151, :_reduce_none,
- 0, 214, :_reduce_596 ]
-
-racc_reduce_n = 597
-
-racc_shift_n = 1024
-
-racc_token_table = {
- false => 0,
- :error => 1,
- :kCLASS => 2,
- :kMODULE => 3,
- :kDEF => 4,
- :kUNDEF => 5,
- :kBEGIN => 6,
- :kRESCUE => 7,
- :kENSURE => 8,
- :kEND => 9,
- :kIF => 10,
- :kUNLESS => 11,
- :kTHEN => 12,
- :kELSIF => 13,
- :kELSE => 14,
- :kCASE => 15,
- :kWHEN => 16,
- :kWHILE => 17,
- :kUNTIL => 18,
- :kFOR => 19,
- :kBREAK => 20,
- :kNEXT => 21,
- :kREDO => 22,
- :kRETRY => 23,
- :kIN => 24,
- :kDO => 25,
- :kDO_COND => 26,
- :kDO_BLOCK => 27,
- :kDO_LAMBDA => 28,
- :kRETURN => 29,
- :kYIELD => 30,
- :kSUPER => 31,
- :kSELF => 32,
- :kNIL => 33,
- :kTRUE => 34,
- :kFALSE => 35,
- :kAND => 36,
- :kOR => 37,
- :kNOT => 38,
- :kIF_MOD => 39,
- :kUNLESS_MOD => 40,
- :kWHILE_MOD => 41,
- :kUNTIL_MOD => 42,
- :kRESCUE_MOD => 43,
- :kALIAS => 44,
- :kDEFINED => 45,
- :klBEGIN => 46,
- :klEND => 47,
- :k__LINE__ => 48,
- :k__FILE__ => 49,
- :k__ENCODING__ => 50,
- :tIDENTIFIER => 51,
- :tFID => 52,
- :tGVAR => 53,
- :tIVAR => 54,
- :tCONSTANT => 55,
- :tLABEL => 56,
- :tCVAR => 57,
- :tNTH_REF => 58,
- :tBACK_REF => 59,
- :tSTRING_CONTENT => 60,
- :tINTEGER => 61,
- :tFLOAT => 62,
- :tREGEXP_END => 63,
- :tUPLUS => 64,
- :tUMINUS => 65,
- :tUMINUS_NUM => 66,
- :tPOW => 67,
- :tCMP => 68,
- :tEQ => 69,
- :tEQQ => 70,
- :tNEQ => 71,
- :tGEQ => 72,
- :tLEQ => 73,
- :tANDOP => 74,
- :tOROP => 75,
- :tMATCH => 76,
- :tNMATCH => 77,
- :tDOT => 78,
- :tDOT2 => 79,
- :tDOT3 => 80,
- :tAREF => 81,
- :tASET => 82,
- :tLSHFT => 83,
- :tRSHFT => 84,
- :tCOLON2 => 85,
- :tCOLON3 => 86,
- :tOP_ASGN => 87,
- :tASSOC => 88,
- :tLPAREN => 89,
- :tLPAREN2 => 90,
- :tRPAREN => 91,
- :tLPAREN_ARG => 92,
- :tLBRACK => 93,
- :tLBRACK2 => 94,
- :tRBRACK => 95,
- :tLBRACE => 96,
- :tLBRACE_ARG => 97,
- :tSTAR => 98,
- :tSTAR2 => 99,
- :tAMPER => 100,
- :tAMPER2 => 101,
- :tTILDE => 102,
- :tPERCENT => 103,
- :tDIVIDE => 104,
- :tDSTAR => 105,
- :tPLUS => 106,
- :tMINUS => 107,
- :tLT => 108,
- :tGT => 109,
- :tPIPE => 110,
- :tBANG => 111,
- :tCARET => 112,
- :tLCURLY => 113,
- :tRCURLY => 114,
- :tBACK_REF2 => 115,
- :tSYMBEG => 116,
- :tSTRING_BEG => 117,
- :tXSTRING_BEG => 118,
- :tREGEXP_BEG => 119,
- :tREGEXP_OPT => 120,
- :tWORDS_BEG => 121,
- :tQWORDS_BEG => 122,
- :tSYMBOLS_BEG => 123,
- :tQSYMBOLS_BEG => 124,
- :tSTRING_DBEG => 125,
- :tSTRING_DVAR => 126,
- :tSTRING_END => 127,
- :tSTRING_DEND => 128,
- :tSTRING => 129,
- :tSYMBOL => 130,
- :tNL => 131,
- :tEH => 132,
- :tCOLON => 133,
- :tCOMMA => 134,
- :tSPACE => 135,
- :tSEMI => 136,
- :tLAMBDA => 137,
- :tLAMBEG => 138,
- :tCHARACTER => 139,
- :tRATIONAL => 140,
- :tIMAGINARY => 141,
- :tLABEL_END => 142,
- :tEQL => 143,
- :tLOWEST => 144 }
-
-racc_nt_base = 145
-
-racc_use_result_var = true
-
-Racc_arg = [
- racc_action_table,
- racc_action_check,
- racc_action_default,
- racc_action_pointer,
- racc_goto_table,
- racc_goto_check,
- racc_goto_default,
- racc_goto_pointer,
- racc_nt_base,
- racc_reduce_table,
- racc_token_table,
- racc_shift_n,
- racc_reduce_n,
- racc_use_result_var ]
-
-Racc_token_to_s_table = [
- "$end",
- "error",
- "kCLASS",
- "kMODULE",
- "kDEF",
- "kUNDEF",
- "kBEGIN",
- "kRESCUE",
- "kENSURE",
- "kEND",
- "kIF",
- "kUNLESS",
- "kTHEN",
- "kELSIF",
- "kELSE",
- "kCASE",
- "kWHEN",
- "kWHILE",
- "kUNTIL",
- "kFOR",
- "kBREAK",
- "kNEXT",
- "kREDO",
- "kRETRY",
- "kIN",
- "kDO",
- "kDO_COND",
- "kDO_BLOCK",
- "kDO_LAMBDA",
- "kRETURN",
- "kYIELD",
- "kSUPER",
- "kSELF",
- "kNIL",
- "kTRUE",
- "kFALSE",
- "kAND",
- "kOR",
- "kNOT",
- "kIF_MOD",
- "kUNLESS_MOD",
- "kWHILE_MOD",
- "kUNTIL_MOD",
- "kRESCUE_MOD",
- "kALIAS",
- "kDEFINED",
- "klBEGIN",
- "klEND",
- "k__LINE__",
- "k__FILE__",
- "k__ENCODING__",
- "tIDENTIFIER",
- "tFID",
- "tGVAR",
- "tIVAR",
- "tCONSTANT",
- "tLABEL",
- "tCVAR",
- "tNTH_REF",
- "tBACK_REF",
- "tSTRING_CONTENT",
- "tINTEGER",
- "tFLOAT",
- "tREGEXP_END",
- "tUPLUS",
- "tUMINUS",
- "tUMINUS_NUM",
- "tPOW",
- "tCMP",
- "tEQ",
- "tEQQ",
- "tNEQ",
- "tGEQ",
- "tLEQ",
- "tANDOP",
- "tOROP",
- "tMATCH",
- "tNMATCH",
- "tDOT",
- "tDOT2",
- "tDOT3",
- "tAREF",
- "tASET",
- "tLSHFT",
- "tRSHFT",
- "tCOLON2",
- "tCOLON3",
- "tOP_ASGN",
- "tASSOC",
- "tLPAREN",
- "tLPAREN2",
- "tRPAREN",
- "tLPAREN_ARG",
- "tLBRACK",
- "tLBRACK2",
- "tRBRACK",
- "tLBRACE",
- "tLBRACE_ARG",
- "tSTAR",
- "tSTAR2",
- "tAMPER",
- "tAMPER2",
- "tTILDE",
- "tPERCENT",
- "tDIVIDE",
- "tDSTAR",
- "tPLUS",
- "tMINUS",
- "tLT",
- "tGT",
- "tPIPE",
- "tBANG",
- "tCARET",
- "tLCURLY",
- "tRCURLY",
- "tBACK_REF2",
- "tSYMBEG",
- "tSTRING_BEG",
- "tXSTRING_BEG",
- "tREGEXP_BEG",
- "tREGEXP_OPT",
- "tWORDS_BEG",
- "tQWORDS_BEG",
- "tSYMBOLS_BEG",
- "tQSYMBOLS_BEG",
- "tSTRING_DBEG",
- "tSTRING_DVAR",
- "tSTRING_END",
- "tSTRING_DEND",
- "tSTRING",
- "tSYMBOL",
- "tNL",
- "tEH",
- "tCOLON",
- "tCOMMA",
- "tSPACE",
- "tSEMI",
- "tLAMBDA",
- "tLAMBEG",
- "tCHARACTER",
- "tRATIONAL",
- "tIMAGINARY",
- "tLABEL_END",
- "tEQL",
- "tLOWEST",
- "$start",
- "program",
- "top_compstmt",
- "top_stmts",
- "opt_terms",
- "top_stmt",
- "terms",
- "stmt",
- "bodystmt",
- "compstmt",
- "opt_rescue",
- "opt_else",
- "opt_ensure",
- "stmts",
- "stmt_or_begin",
- "fitem",
- "undef_list",
- "expr_value",
- "command_asgn",
- "mlhs",
- "command_call",
- "var_lhs",
- "primary_value",
- "opt_call_args",
- "rbracket",
- "backref",
- "lhs",
- "mrhs",
- "mrhs_arg",
- "expr",
- "@1",
- "opt_nl",
- "arg",
- "command",
- "block_command",
- "block_call",
- "dot_or_colon",
- "operation2",
- "command_args",
- "cmd_brace_block",
- "opt_block_param",
- "fcall",
- "@2",
- "operation",
- "call_args",
- "mlhs_basic",
- "mlhs_inner",
- "rparen",
- "mlhs_head",
- "mlhs_item",
- "mlhs_node",
- "mlhs_post",
- "user_variable",
- "keyword_variable",
- "cname",
- "cpath",
- "fname",
- "op",
- "reswords",
- "fsym",
- "symbol",
- "dsym",
- "@3",
- "simple_numeric",
- "primary",
- "arg_value",
- "@4",
- "@5",
- "aref_args",
- "none",
- "args",
- "trailer",
- "assocs",
- "paren_args",
- "opt_paren_args",
- "opt_block_arg",
- "block_arg",
- "@6",
- "literal",
- "strings",
- "xstring",
- "regexp",
- "words",
- "qwords",
- "symbols",
- "qsymbols",
- "var_ref",
- "assoc_list",
- "brace_block",
- "method_call",
- "lambda",
- "then",
- "if_tail",
- "do",
- "case_body",
- "for_var",
- "superclass",
- "term",
- "f_arglist",
- "singleton",
- "@7",
- "@8",
- "@9",
- "@10",
- "@11",
- "@12",
- "@13",
- "@14",
- "@15",
- "@16",
- "@17",
- "@18",
- "@19",
- "@20",
- "@21",
- "@22",
- "f_marg",
- "f_norm_arg",
- "f_margs",
- "f_marg_list",
- "block_args_tail",
- "f_block_kwarg",
- "f_kwrest",
- "opt_f_block_arg",
- "f_block_arg",
- "opt_block_args_tail",
- "block_param",
- "f_arg",
- "f_block_optarg",
- "f_rest_arg",
- "block_param_def",
- "opt_bv_decl",
- "bv_decls",
- "bvar",
- "f_bad_arg",
- "f_larglist",
- "lambda_body",
- "@23",
- "@24",
- "f_args",
- "do_block",
- "@25",
- "operation3",
- "@26",
- "@27",
- "cases",
- "exc_list",
- "exc_var",
- "numeric",
- "string",
- "string1",
- "string_contents",
- "xstring_contents",
- "regexp_contents",
- "word_list",
- "word",
- "string_content",
- "symbol_list",
- "qword_list",
- "qsym_list",
- "string_dvar",
- "@28",
- "@29",
- "args_tail",
- "@30",
- "f_kwarg",
- "opt_args_tail",
- "f_optarg",
- "f_arg_asgn",
- "f_arg_item",
- "f_label",
- "f_kw",
- "f_block_kw",
- "kwrest_mark",
- "f_opt",
- "f_block_opt",
- "restarg_mark",
- "blkarg_mark",
- "assoc" ]
-
-Racc_debug_parser = false
-
-##### State transition tables end #####
-
-# reduce 0 omitted
-
-# reduce 1 omitted
-
-module_eval(<<'.,.,', 'ruby22.y', 78)
- def _reduce_2(val, _values, result)
- result = @builder.compstmt(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 83)
- def _reduce_3(val, _values, result)
- result = []
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 87)
- def _reduce_4(val, _values, result)
- result = [ val[0] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 91)
- def _reduce_5(val, _values, result)
- result = val[0] << val[2]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 95)
- def _reduce_6(val, _values, result)
- result = [ val[1] ]
-
- result
- end
-.,.,
-
-# reduce 7 omitted
-
-module_eval(<<'.,.,', 'ruby22.y', 101)
- def _reduce_8(val, _values, result)
- result = @builder.preexe(val[0], val[1], val[2], val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 106)
- def _reduce_9(val, _values, result)
- rescue_bodies = val[1]
- else_t, else_ = val[2]
- ensure_t, ensure_ = val[3]
-
- if rescue_bodies.empty? && !else_.nil?
- diagnostic :warning, :useless_else, nil, else_t
- end
-
- result = @builder.begin_body(val[0],
- rescue_bodies,
- else_t, else_,
- ensure_t, ensure_)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 122)
- def _reduce_10(val, _values, result)
- result = @builder.compstmt(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 127)
- def _reduce_11(val, _values, result)
- result = []
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 131)
- def _reduce_12(val, _values, result)
- result = [ val[0] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 135)
- def _reduce_13(val, _values, result)
- result = val[0] << val[2]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 139)
- def _reduce_14(val, _values, result)
- result = [ val[1] ]
-
- result
- end
-.,.,
-
-# reduce 15 omitted
-
-module_eval(<<'.,.,', 'ruby22.y', 145)
- def _reduce_16(val, _values, result)
- diagnostic :error, :begin_in_method, nil, val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 150)
- def _reduce_17(val, _values, result)
- @lexer.state = :expr_fname
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 154)
- def _reduce_18(val, _values, result)
- result = @builder.alias(val[0], val[1], val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 158)
- def _reduce_19(val, _values, result)
- result = @builder.alias(val[0],
- @builder.gvar(val[1]),
- @builder.gvar(val[2]))
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 164)
- def _reduce_20(val, _values, result)
- result = @builder.alias(val[0],
- @builder.gvar(val[1]),
- @builder.back_ref(val[2]))
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 170)
- def _reduce_21(val, _values, result)
- diagnostic :error, :nth_ref_alias, nil, val[2]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 174)
- def _reduce_22(val, _values, result)
- result = @builder.undef_method(val[0], val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 178)
- def _reduce_23(val, _values, result)
- result = @builder.condition_mod(val[0], nil,
- val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 183)
- def _reduce_24(val, _values, result)
- result = @builder.condition_mod(nil, val[0],
- val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 188)
- def _reduce_25(val, _values, result)
- result = @builder.loop_mod(:while, val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 192)
- def _reduce_26(val, _values, result)
- result = @builder.loop_mod(:until, val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 196)
- def _reduce_27(val, _values, result)
- rescue_body = @builder.rescue_body(val[1],
- nil, nil, nil,
- nil, val[2])
-
- result = @builder.begin_body(val[0], [ rescue_body ])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 204)
- def _reduce_28(val, _values, result)
- result = @builder.postexe(val[0], val[1], val[2], val[3])
-
- result
- end
-.,.,
-
-# reduce 29 omitted
-
-module_eval(<<'.,.,', 'ruby22.y', 209)
- def _reduce_30(val, _values, result)
- result = @builder.multi_assign(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 213)
- def _reduce_31(val, _values, result)
- result = @builder.op_assign(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 217)
- def _reduce_32(val, _values, result)
- result = @builder.op_assign(
- @builder.index(
- val[0], val[1], val[2], val[3]),
- val[4], val[5])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 224)
- def _reduce_33(val, _values, result)
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 231)
- def _reduce_34(val, _values, result)
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 238)
- def _reduce_35(val, _values, result)
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 245)
- def _reduce_36(val, _values, result)
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 252)
- def _reduce_37(val, _values, result)
- @builder.op_assign(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 256)
- def _reduce_38(val, _values, result)
- result = @builder.assign(val[0], val[1],
- @builder.array(nil, val[2], nil))
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 261)
- def _reduce_39(val, _values, result)
- result = @builder.multi_assign(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-# reduce 40 omitted
-
-module_eval(<<'.,.,', 'ruby22.y', 267)
- def _reduce_41(val, _values, result)
- result = @builder.assign(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 271)
- def _reduce_42(val, _values, result)
- result = @builder.assign(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-# reduce 43 omitted
-
-module_eval(<<'.,.,', 'ruby22.y', 277)
- def _reduce_44(val, _values, result)
- result = @builder.logical_op(:and, val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 281)
- def _reduce_45(val, _values, result)
- result = @builder.logical_op(:or, val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 285)
- def _reduce_46(val, _values, result)
- result = @builder.not_op(val[0], nil, val[2], nil)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 289)
- def _reduce_47(val, _values, result)
- result = @builder.not_op(val[0], nil, val[1], nil)
-
- result
- end
-.,.,
-
-# reduce 48 omitted
-
-# reduce 49 omitted
-
-# reduce 50 omitted
-
-# reduce 51 omitted
-
-# reduce 52 omitted
-
-module_eval(<<'.,.,', 'ruby22.y', 301)
- def _reduce_53(val, _values, result)
- result = @builder.call_method(val[0], val[1], val[2],
- nil, val[3], nil)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 307)
- def _reduce_54(val, _values, result)
- @static_env.extend_dynamic
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 311)
- def _reduce_55(val, _values, result)
- result = [ val[0], val[2], val[3], val[4] ]
-
- @static_env.unextend
-
- result
- end
-.,.,
-
-# reduce 56 omitted
-
-module_eval(<<'.,.,', 'ruby22.y', 320)
- def _reduce_57(val, _values, result)
- result = @builder.call_method(nil, nil, val[0],
- nil, val[1], nil)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 325)
- def _reduce_58(val, _values, result)
- method_call = @builder.call_method(nil, nil, val[0],
- nil, val[1], nil)
-
- begin_t, args, body, end_t = val[2]
- result = @builder.block(method_call,
- begin_t, args, body, end_t)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 334)
- def _reduce_59(val, _values, result)
- result = @builder.call_method(val[0], val[1], val[2],
- nil, val[3], nil)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 339)
- def _reduce_60(val, _values, result)
- method_call = @builder.call_method(val[0], val[1], val[2],
- nil, val[3], nil)
-
- begin_t, args, body, end_t = val[4]
- result = @builder.block(method_call,
- begin_t, args, body, end_t)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 348)
- def _reduce_61(val, _values, result)
- result = @builder.call_method(val[0], val[1], val[2],
- nil, val[3], nil)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 353)
- def _reduce_62(val, _values, result)
- method_call = @builder.call_method(val[0], val[1], val[2],
- nil, val[3], nil)
-
- begin_t, args, body, end_t = val[4]
- result = @builder.block(method_call,
- begin_t, args, body, end_t)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 362)
- def _reduce_63(val, _values, result)
- result = @builder.keyword_cmd(:super, val[0],
- nil, val[1], nil)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 367)
- def _reduce_64(val, _values, result)
- result = @builder.keyword_cmd(:yield, val[0],
- nil, val[1], nil)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 372)
- def _reduce_65(val, _values, result)
- result = @builder.keyword_cmd(:return, val[0],
- nil, val[1], nil)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 377)
- def _reduce_66(val, _values, result)
- result = @builder.keyword_cmd(:break, val[0],
- nil, val[1], nil)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 382)
- def _reduce_67(val, _values, result)
- result = @builder.keyword_cmd(:next, val[0],
- nil, val[1], nil)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 388)
- def _reduce_68(val, _values, result)
- result = @builder.multi_lhs(nil, val[0], nil)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 392)
- def _reduce_69(val, _values, result)
- result = @builder.begin(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 397)
- def _reduce_70(val, _values, result)
- result = @builder.multi_lhs(nil, val[0], nil)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 401)
- def _reduce_71(val, _values, result)
- result = @builder.multi_lhs(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-# reduce 72 omitted
-
-module_eval(<<'.,.,', 'ruby22.y', 407)
- def _reduce_73(val, _values, result)
- result = val[0].
- push(val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 412)
- def _reduce_74(val, _values, result)
- result = val[0].
- push(@builder.splat(val[1], val[2]))
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 417)
- def _reduce_75(val, _values, result)
- result = val[0].
- push(@builder.splat(val[1], val[2])).
- concat(val[4])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 423)
- def _reduce_76(val, _values, result)
- result = val[0].
- push(@builder.splat(val[1]))
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 428)
- def _reduce_77(val, _values, result)
- result = val[0].
- push(@builder.splat(val[1])).
- concat(val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 434)
- def _reduce_78(val, _values, result)
- result = [ @builder.splat(val[0], val[1]) ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 438)
- def _reduce_79(val, _values, result)
- result = [ @builder.splat(val[0], val[1]),
- *val[3] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 443)
- def _reduce_80(val, _values, result)
- result = [ @builder.splat(val[0]) ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 447)
- def _reduce_81(val, _values, result)
- result = [ @builder.splat(val[0]),
- *val[2] ]
-
- result
- end
-.,.,
-
-# reduce 82 omitted
-
-module_eval(<<'.,.,', 'ruby22.y', 454)
- def _reduce_83(val, _values, result)
- result = @builder.begin(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 459)
- def _reduce_84(val, _values, result)
- result = [ val[0] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 463)
- def _reduce_85(val, _values, result)
- result = val[0] << val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 468)
- def _reduce_86(val, _values, result)
- result = [ val[0] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 472)
- def _reduce_87(val, _values, result)
- result = val[0] << val[2]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 477)
- def _reduce_88(val, _values, result)
- result = @builder.assignable(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 481)
- def _reduce_89(val, _values, result)
- result = @builder.assignable(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 485)
- def _reduce_90(val, _values, result)
- result = @builder.index_asgn(val[0], val[1], val[2], val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 489)
- def _reduce_91(val, _values, result)
- result = @builder.attr_asgn(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 493)
- def _reduce_92(val, _values, result)
- result = @builder.attr_asgn(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 497)
- def _reduce_93(val, _values, result)
- result = @builder.attr_asgn(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 501)
- def _reduce_94(val, _values, result)
- result = @builder.assignable(
- @builder.const_fetch(val[0], val[1], val[2]))
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 506)
- def _reduce_95(val, _values, result)
- result = @builder.assignable(
- @builder.const_global(val[0], val[1]))
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 511)
- def _reduce_96(val, _values, result)
- result = @builder.assignable(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 516)
- def _reduce_97(val, _values, result)
- result = @builder.assignable(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 520)
- def _reduce_98(val, _values, result)
- result = @builder.assignable(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 524)
- def _reduce_99(val, _values, result)
- result = @builder.index_asgn(val[0], val[1], val[2], val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 528)
- def _reduce_100(val, _values, result)
- result = @builder.attr_asgn(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 532)
- def _reduce_101(val, _values, result)
- result = @builder.attr_asgn(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 536)
- def _reduce_102(val, _values, result)
- result = @builder.attr_asgn(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 540)
- def _reduce_103(val, _values, result)
- result = @builder.assignable(
- @builder.const_fetch(val[0], val[1], val[2]))
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 545)
- def _reduce_104(val, _values, result)
- result = @builder.assignable(
- @builder.const_global(val[0], val[1]))
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 550)
- def _reduce_105(val, _values, result)
- result = @builder.assignable(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 555)
- def _reduce_106(val, _values, result)
- diagnostic :error, :module_name_const, nil, val[0]
-
- result
- end
-.,.,
-
-# reduce 107 omitted
-
-module_eval(<<'.,.,', 'ruby22.y', 561)
- def _reduce_108(val, _values, result)
- result = @builder.const_global(val[0], val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 565)
- def _reduce_109(val, _values, result)
- result = @builder.const(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 569)
- def _reduce_110(val, _values, result)
- result = @builder.const_fetch(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-# reduce 111 omitted
-
-# reduce 112 omitted
-
-# reduce 113 omitted
-
-# reduce 114 omitted
-
-# reduce 115 omitted
-
-module_eval(<<'.,.,', 'ruby22.y', 578)
- def _reduce_116(val, _values, result)
- result = @builder.symbol(val[0])
-
- result
- end
-.,.,
-
-# reduce 117 omitted
-
-# reduce 118 omitted
-
-# reduce 119 omitted
-
-module_eval(<<'.,.,', 'ruby22.y', 587)
- def _reduce_120(val, _values, result)
- result = [ val[0] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 591)
- def _reduce_121(val, _values, result)
- @lexer.state = :expr_fname
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 595)
- def _reduce_122(val, _values, result)
- result = val[0] << val[3]
-
- result
- end
-.,.,
-
-# reduce 123 omitted
-
-# reduce 124 omitted
-
-# reduce 125 omitted
-
-# reduce 126 omitted
-
-# reduce 127 omitted
-
-# reduce 128 omitted
-
-# reduce 129 omitted
-
-# reduce 130 omitted
-
-# reduce 131 omitted
-
-# reduce 132 omitted
-
-# reduce 133 omitted
-
-# reduce 134 omitted
-
-# reduce 135 omitted
-
-# reduce 136 omitted
-
-# reduce 137 omitted
-
-# reduce 138 omitted
-
-# reduce 139 omitted
-
-# reduce 140 omitted
-
-# reduce 141 omitted
-
-# reduce 142 omitted
-
-# reduce 143 omitted
-
-# reduce 144 omitted
-
-# reduce 145 omitted
-
-# reduce 146 omitted
-
-# reduce 147 omitted
-
-# reduce 148 omitted
-
-# reduce 149 omitted
-
-# reduce 150 omitted
-
-# reduce 151 omitted
-
-# reduce 152 omitted
-
-# reduce 153 omitted
-
-# reduce 154 omitted
-
-# reduce 155 omitted
-
-# reduce 156 omitted
-
-# reduce 157 omitted
-
-# reduce 158 omitted
-
-# reduce 159 omitted
-
-# reduce 160 omitted
-
-# reduce 161 omitted
-
-# reduce 162 omitted
-
-# reduce 163 omitted
-
-# reduce 164 omitted
-
-# reduce 165 omitted
-
-# reduce 166 omitted
-
-# reduce 167 omitted
-
-# reduce 168 omitted
-
-# reduce 169 omitted
-
-# reduce 170 omitted
-
-# reduce 171 omitted
-
-# reduce 172 omitted
-
-# reduce 173 omitted
-
-# reduce 174 omitted
-
-# reduce 175 omitted
-
-# reduce 176 omitted
-
-# reduce 177 omitted
-
-# reduce 178 omitted
-
-# reduce 179 omitted
-
-# reduce 180 omitted
-
-# reduce 181 omitted
-
-# reduce 182 omitted
-
-# reduce 183 omitted
-
-# reduce 184 omitted
-
-# reduce 185 omitted
-
-# reduce 186 omitted
-
-# reduce 187 omitted
-
-# reduce 188 omitted
-
-# reduce 189 omitted
-
-# reduce 190 omitted
-
-# reduce 191 omitted
-
-# reduce 192 omitted
-
-# reduce 193 omitted
-
-module_eval(<<'.,.,', 'ruby22.y', 616)
- def _reduce_194(val, _values, result)
- result = @builder.assign(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 620)
- def _reduce_195(val, _values, result)
- rescue_body = @builder.rescue_body(val[3],
- nil, nil, nil,
- nil, val[4])
-
- rescue_ = @builder.begin_body(val[2], [ rescue_body ])
-
- result = @builder.assign(val[0], val[1], rescue_)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 630)
- def _reduce_196(val, _values, result)
- result = @builder.op_assign(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 634)
- def _reduce_197(val, _values, result)
- rescue_body = @builder.rescue_body(val[3],
- nil, nil, nil,
- nil, val[4])
-
- rescue_ = @builder.begin_body(val[2], [ rescue_body ])
-
- result = @builder.op_assign(val[0], val[1], rescue_)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 644)
- def _reduce_198(val, _values, result)
- result = @builder.op_assign(
- @builder.index(
- val[0], val[1], val[2], val[3]),
- val[4], val[5])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 651)
- def _reduce_199(val, _values, result)
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 658)
- def _reduce_200(val, _values, result)
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 665)
- def _reduce_201(val, _values, result)
- result = @builder.op_assign(
- @builder.call_method(
- val[0], val[1], val[2]),
- val[3], val[4])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 672)
- def _reduce_202(val, _values, result)
- const = @builder.const_op_assignable(
- @builder.const_fetch(val[0], val[1], val[2]))
- result = @builder.op_assign(const, val[3], val[4])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 678)
- def _reduce_203(val, _values, result)
- const = @builder.const_op_assignable(
- @builder.const_global(val[0], val[1]))
- result = @builder.op_assign(const, val[2], val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 684)
- def _reduce_204(val, _values, result)
- result = @builder.op_assign(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 688)
- def _reduce_205(val, _values, result)
- result = @builder.range_inclusive(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 692)
- def _reduce_206(val, _values, result)
- result = @builder.range_exclusive(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 696)
- def _reduce_207(val, _values, result)
- result = @builder.binary_op(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 700)
- def _reduce_208(val, _values, result)
- result = @builder.binary_op(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 704)
- def _reduce_209(val, _values, result)
- result = @builder.binary_op(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 708)
- def _reduce_210(val, _values, result)
- result = @builder.binary_op(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 712)
- def _reduce_211(val, _values, result)
- result = @builder.binary_op(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 716)
- def _reduce_212(val, _values, result)
- result = @builder.binary_op(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 720)
- def _reduce_213(val, _values, result)
- result = @builder.unary_op(val[0],
- @builder.binary_op(
- val[1], val[2], val[3]))
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 726)
- def _reduce_214(val, _values, result)
- result = @builder.unary_op(val[0], val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 730)
- def _reduce_215(val, _values, result)
- result = @builder.unary_op(val[0], val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 734)
- def _reduce_216(val, _values, result)
- result = @builder.binary_op(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 738)
- def _reduce_217(val, _values, result)
- result = @builder.binary_op(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 742)
- def _reduce_218(val, _values, result)
- result = @builder.binary_op(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 746)
- def _reduce_219(val, _values, result)
- result = @builder.binary_op(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 750)
- def _reduce_220(val, _values, result)
- result = @builder.binary_op(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 754)
- def _reduce_221(val, _values, result)
- result = @builder.binary_op(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 758)
- def _reduce_222(val, _values, result)
- result = @builder.binary_op(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 762)
- def _reduce_223(val, _values, result)
- result = @builder.binary_op(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 766)
- def _reduce_224(val, _values, result)
- result = @builder.binary_op(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 770)
- def _reduce_225(val, _values, result)
- result = @builder.binary_op(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 774)
- def _reduce_226(val, _values, result)
- result = @builder.binary_op(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 778)
- def _reduce_227(val, _values, result)
- result = @builder.match_op(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 782)
- def _reduce_228(val, _values, result)
- result = @builder.binary_op(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 786)
- def _reduce_229(val, _values, result)
- result = @builder.not_op(val[0], nil, val[1], nil)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 790)
- def _reduce_230(val, _values, result)
- result = @builder.unary_op(val[0], val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 794)
- def _reduce_231(val, _values, result)
- result = @builder.binary_op(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 798)
- def _reduce_232(val, _values, result)
- result = @builder.binary_op(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 802)
- def _reduce_233(val, _values, result)
- result = @builder.logical_op(:and, val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 806)
- def _reduce_234(val, _values, result)
- result = @builder.logical_op(:or, val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 810)
- def _reduce_235(val, _values, result)
- result = @builder.keyword_cmd(:defined?, val[0], nil, [ val[2] ], nil)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 820)
- def _reduce_236(val, _values, result)
- @lexer.push_cond
- @lexer.cond.push(true)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 825)
- def _reduce_237(val, _values, result)
- @lexer.pop_cond
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 829)
- def _reduce_238(val, _values, result)
- result = @builder.ternary(val[0], val[1],
- val[3], val[5], val[7])
-
- result
- end
-.,.,
-
-# reduce 239 omitted
-
-# reduce 240 omitted
-
-# reduce 241 omitted
-
-# reduce 242 omitted
-
-module_eval(<<'.,.,', 'ruby22.y', 840)
- def _reduce_243(val, _values, result)
- result = val[0] << @builder.associate(nil, val[2], nil)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 844)
- def _reduce_244(val, _values, result)
- result = [ @builder.associate(nil, val[0], nil) ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 849)
- def _reduce_245(val, _values, result)
- result = val
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 854)
- def _reduce_246(val, _values, result)
- result = [ nil, [], nil ]
-
- result
- end
-.,.,
-
-# reduce 247 omitted
-
-module_eval(<<'.,.,', 'ruby22.y', 860)
- def _reduce_248(val, _values, result)
- result = []
-
- result
- end
-.,.,
-
-# reduce 249 omitted
-
-# reduce 250 omitted
-
-module_eval(<<'.,.,', 'ruby22.y', 866)
- def _reduce_251(val, _values, result)
- result = val[0] << @builder.associate(nil, val[2], nil)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 870)
- def _reduce_252(val, _values, result)
- result = [ @builder.associate(nil, val[0], nil) ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 875)
- def _reduce_253(val, _values, result)
- result = [ val[0] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 879)
- def _reduce_254(val, _values, result)
- result = val[0].concat(val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 883)
- def _reduce_255(val, _values, result)
- result = [ @builder.associate(nil, val[0], nil) ]
- result.concat(val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 888)
- def _reduce_256(val, _values, result)
- assocs = @builder.associate(nil, val[2], nil)
- result = val[0] << assocs
- result.concat(val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 894)
- def _reduce_257(val, _values, result)
- result = [ val[0] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 898)
- def _reduce_258(val, _values, result)
- result = @lexer.cmdarg.dup
- @lexer.cmdarg.push(true)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 903)
- def _reduce_259(val, _values, result)
- @lexer.cmdarg = val[0]
-
- result = val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 910)
- def _reduce_260(val, _values, result)
- result = @builder.block_pass(val[0], val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 915)
- def _reduce_261(val, _values, result)
- result = [ val[1] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 919)
- def _reduce_262(val, _values, result)
- result = []
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 924)
- def _reduce_263(val, _values, result)
- result = [ val[0] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 928)
- def _reduce_264(val, _values, result)
- result = [ @builder.splat(val[0], val[1]) ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 932)
- def _reduce_265(val, _values, result)
- result = val[0] << val[2]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 936)
- def _reduce_266(val, _values, result)
- result = val[0] << @builder.splat(val[2], val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 941)
- def _reduce_267(val, _values, result)
- result = @builder.array(nil, val[0], nil)
-
- result
- end
-.,.,
-
-# reduce 268 omitted
-
-module_eval(<<'.,.,', 'ruby22.y', 947)
- def _reduce_269(val, _values, result)
- result = val[0] << val[2]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 951)
- def _reduce_270(val, _values, result)
- result = val[0] << @builder.splat(val[2], val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 955)
- def _reduce_271(val, _values, result)
- result = [ @builder.splat(val[0], val[1]) ]
-
- result
- end
-.,.,
-
-# reduce 272 omitted
-
-# reduce 273 omitted
-
-# reduce 274 omitted
-
-# reduce 275 omitted
-
-# reduce 276 omitted
-
-# reduce 277 omitted
-
-# reduce 278 omitted
-
-# reduce 279 omitted
-
-# reduce 280 omitted
-
-# reduce 281 omitted
-
-module_eval(<<'.,.,', 'ruby22.y', 970)
- def _reduce_282(val, _values, result)
- result = @builder.call_method(nil, nil, val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 974)
- def _reduce_283(val, _values, result)
- result = @lexer.cmdarg.dup
- @lexer.cmdarg.clear
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 979)
- def _reduce_284(val, _values, result)
- @lexer.cmdarg = val[1]
-
- result = @builder.begin_keyword(val[0], val[2], val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 985)
- def _reduce_285(val, _values, result)
- result = @lexer.cmdarg.dup
- @lexer.cmdarg.clear
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 990)
- def _reduce_286(val, _values, result)
- @lexer.state = :expr_endarg
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 994)
- def _reduce_287(val, _values, result)
- @lexer.cmdarg = val[1]
-
- result = @builder.begin(val[0], val[2], val[5])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1000)
- def _reduce_288(val, _values, result)
- @lexer.state = :expr_endarg
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1004)
- def _reduce_289(val, _values, result)
- result = @builder.begin(val[0], nil, val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1008)
- def _reduce_290(val, _values, result)
- result = @builder.begin(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1012)
- def _reduce_291(val, _values, result)
- result = @builder.const_fetch(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1016)
- def _reduce_292(val, _values, result)
- result = @builder.const_global(val[0], val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1020)
- def _reduce_293(val, _values, result)
- result = @builder.array(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1024)
- def _reduce_294(val, _values, result)
- result = @builder.associate(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1028)
- def _reduce_295(val, _values, result)
- result = @builder.keyword_cmd(:return, val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1032)
- def _reduce_296(val, _values, result)
- result = @builder.keyword_cmd(:yield, val[0], val[1], val[2], val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1036)
- def _reduce_297(val, _values, result)
- result = @builder.keyword_cmd(:yield, val[0], val[1], [], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1040)
- def _reduce_298(val, _values, result)
- result = @builder.keyword_cmd(:yield, val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1044)
- def _reduce_299(val, _values, result)
- result = @builder.keyword_cmd(:defined?, val[0],
- val[2], [ val[3] ], val[4])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1049)
- def _reduce_300(val, _values, result)
- result = @builder.not_op(val[0], val[1], val[2], val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1053)
- def _reduce_301(val, _values, result)
- result = @builder.not_op(val[0], val[1], nil, val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1057)
- def _reduce_302(val, _values, result)
- method_call = @builder.call_method(nil, nil, val[0])
-
- begin_t, args, body, end_t = val[1]
- result = @builder.block(method_call,
- begin_t, args, body, end_t)
-
- result
- end
-.,.,
-
-# reduce 303 omitted
-
-module_eval(<<'.,.,', 'ruby22.y', 1066)
- def _reduce_304(val, _values, result)
- begin_t, args, body, end_t = val[1]
- result = @builder.block(val[0],
- begin_t, args, body, end_t)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1072)
- def _reduce_305(val, _values, result)
- lambda_call = @builder.call_lambda(val[0])
-
- args, (begin_t, body, end_t) = val[1]
- result = @builder.block(lambda_call,
- begin_t, args, body, end_t)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1080)
- def _reduce_306(val, _values, result)
- else_t, else_ = val[4]
- result = @builder.condition(val[0], val[1], val[2],
- val[3], else_t,
- else_, val[5])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1087)
- def _reduce_307(val, _values, result)
- else_t, else_ = val[4]
- result = @builder.condition(val[0], val[1], val[2],
- else_, else_t,
- val[3], val[5])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1094)
- def _reduce_308(val, _values, result)
- @lexer.cond.push(true)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1098)
- def _reduce_309(val, _values, result)
- @lexer.cond.pop
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1102)
- def _reduce_310(val, _values, result)
- result = @builder.loop(:while, val[0], val[2], val[3],
- val[5], val[6])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1107)
- def _reduce_311(val, _values, result)
- @lexer.cond.push(true)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1111)
- def _reduce_312(val, _values, result)
- @lexer.cond.pop
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1115)
- def _reduce_313(val, _values, result)
- result = @builder.loop(:until, val[0], val[2], val[3],
- val[5], val[6])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1120)
- def _reduce_314(val, _values, result)
- *when_bodies, (else_t, else_body) = *val[3]
-
- result = @builder.case(val[0], val[1],
- when_bodies, else_t, else_body,
- val[4])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1128)
- def _reduce_315(val, _values, result)
- *when_bodies, (else_t, else_body) = *val[2]
-
- result = @builder.case(val[0], nil,
- when_bodies, else_t, else_body,
- val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1136)
- def _reduce_316(val, _values, result)
- @lexer.cond.push(true)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1140)
- def _reduce_317(val, _values, result)
- @lexer.cond.pop
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1144)
- def _reduce_318(val, _values, result)
- result = @builder.for(val[0], val[1],
- val[2], val[4],
- val[5], val[7], val[8])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1150)
- def _reduce_319(val, _values, result)
- @static_env.extend_static
- @lexer.push_cmdarg
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1155)
- def _reduce_320(val, _values, result)
- if in_def?
- diagnostic :error, :class_in_def, nil, val[0]
- end
-
- lt_t, superclass = val[2]
- result = @builder.def_class(val[0], val[1],
- lt_t, superclass,
- val[4], val[5])
-
- @lexer.pop_cmdarg
- @static_env.unextend
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1169)
- def _reduce_321(val, _values, result)
- result = @def_level
- @def_level = 0
-
- @static_env.extend_static
- @lexer.push_cmdarg
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1177)
- def _reduce_322(val, _values, result)
- result = @builder.def_sclass(val[0], val[1], val[2],
- val[5], val[6])
-
- @lexer.pop_cmdarg
- @static_env.unextend
-
- @def_level = val[4]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1187)
- def _reduce_323(val, _values, result)
- @static_env.extend_static
- @lexer.push_cmdarg
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1192)
- def _reduce_324(val, _values, result)
- if in_def?
- diagnostic :error, :module_in_def, nil, val[0]
- end
-
- result = @builder.def_module(val[0], val[1],
- val[3], val[4])
-
- @lexer.pop_cmdarg
- @static_env.unextend
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1204)
- def _reduce_325(val, _values, result)
- @def_level += 1
- @static_env.extend_static
- @lexer.push_cmdarg
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1210)
- def _reduce_326(val, _values, result)
- result = @builder.def_method(val[0], val[1],
- val[3], val[4], val[5])
-
- @lexer.pop_cmdarg
- @static_env.unextend
- @def_level -= 1
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1219)
- def _reduce_327(val, _values, result)
- @lexer.state = :expr_fname
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1223)
- def _reduce_328(val, _values, result)
- @def_level += 1
- @static_env.extend_static
- @lexer.push_cmdarg
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1229)
- def _reduce_329(val, _values, result)
- result = @builder.def_singleton(val[0], val[1], val[2],
- val[4], val[6], val[7], val[8])
-
- @lexer.pop_cmdarg
- @static_env.unextend
- @def_level -= 1
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1238)
- def _reduce_330(val, _values, result)
- result = @builder.keyword_cmd(:break, val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1242)
- def _reduce_331(val, _values, result)
- result = @builder.keyword_cmd(:next, val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1246)
- def _reduce_332(val, _values, result)
- result = @builder.keyword_cmd(:redo, val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1250)
- def _reduce_333(val, _values, result)
- result = @builder.keyword_cmd(:retry, val[0])
-
- result
- end
-.,.,
-
-# reduce 334 omitted
-
-# reduce 335 omitted
-
-# reduce 336 omitted
-
-module_eval(<<'.,.,', 'ruby22.y', 1259)
- def _reduce_337(val, _values, result)
- result = val[1]
-
- result
- end
-.,.,
-
-# reduce 338 omitted
-
-# reduce 339 omitted
-
-# reduce 340 omitted
-
-module_eval(<<'.,.,', 'ruby22.y', 1268)
- def _reduce_341(val, _values, result)
- else_t, else_ = val[4]
- result = [ val[0],
- @builder.condition(val[0], val[1], val[2],
- val[3], else_t,
- else_, nil),
- ]
-
- result
- end
-.,.,
-
-# reduce 342 omitted
-
-module_eval(<<'.,.,', 'ruby22.y', 1279)
- def _reduce_343(val, _values, result)
- result = val
-
- result
- end
-.,.,
-
-# reduce 344 omitted
-
-# reduce 345 omitted
-
-module_eval(<<'.,.,', 'ruby22.y', 1287)
- def _reduce_346(val, _values, result)
- result = @builder.arg(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1291)
- def _reduce_347(val, _values, result)
- result = @builder.multi_lhs(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1296)
- def _reduce_348(val, _values, result)
- result = [ val[0] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1300)
- def _reduce_349(val, _values, result)
- result = val[0] << val[2]
-
- result
- end
-.,.,
-
-# reduce 350 omitted
-
-module_eval(<<'.,.,', 'ruby22.y', 1306)
- def _reduce_351(val, _values, result)
- result = val[0].
- push(@builder.restarg(val[2], val[3]))
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1311)
- def _reduce_352(val, _values, result)
- result = val[0].
- push(@builder.restarg(val[2], val[3])).
- concat(val[5])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1317)
- def _reduce_353(val, _values, result)
- result = val[0].
- push(@builder.restarg(val[2]))
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1322)
- def _reduce_354(val, _values, result)
- result = val[0].
- push(@builder.restarg(val[2])).
- concat(val[4])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1328)
- def _reduce_355(val, _values, result)
- result = [ @builder.restarg(val[0], val[1]) ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1332)
- def _reduce_356(val, _values, result)
- result = [ @builder.restarg(val[0], val[1]),
- *val[3] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1337)
- def _reduce_357(val, _values, result)
- result = [ @builder.restarg(val[0]) ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1341)
- def _reduce_358(val, _values, result)
- result = [ @builder.restarg(val[0]),
- *val[2] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1347)
- def _reduce_359(val, _values, result)
- result = val[0].concat(val[2]).concat(val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1351)
- def _reduce_360(val, _values, result)
- result = val[0].concat(val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1355)
- def _reduce_361(val, _values, result)
- result = val[0].concat(val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1359)
- def _reduce_362(val, _values, result)
- result = [ val[0] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1365)
- def _reduce_363(val, _values, result)
- result = val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1369)
- def _reduce_364(val, _values, result)
- result = []
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1374)
- def _reduce_365(val, _values, result)
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1381)
- def _reduce_366(val, _values, result)
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[6]).
- concat(val[7])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1389)
- def _reduce_367(val, _values, result)
- result = val[0].
- concat(val[2]).
- concat(val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1395)
- def _reduce_368(val, _values, result)
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1402)
- def _reduce_369(val, _values, result)
- result = val[0].
- concat(val[2]).
- concat(val[3])
-
- result
- end
-.,.,
-
-# reduce 370 omitted
-
-module_eval(<<'.,.,', 'ruby22.y', 1409)
- def _reduce_371(val, _values, result)
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1416)
- def _reduce_372(val, _values, result)
- result = val[0].concat(val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1420)
- def _reduce_373(val, _values, result)
- result = val[0].
- concat(val[2]).
- concat(val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1426)
- def _reduce_374(val, _values, result)
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1433)
- def _reduce_375(val, _values, result)
- result = val[0].
- concat(val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1438)
- def _reduce_376(val, _values, result)
- result = val[0].
- concat(val[2]).
- concat(val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1444)
- def _reduce_377(val, _values, result)
- result = val[0].
- concat(val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1449)
- def _reduce_378(val, _values, result)
- result = val[0].
- concat(val[2]).
- concat(val[3])
-
- result
- end
-.,.,
-
-# reduce 379 omitted
-
-module_eval(<<'.,.,', 'ruby22.y', 1457)
- def _reduce_380(val, _values, result)
- result = @builder.args(nil, [], nil)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1461)
- def _reduce_381(val, _values, result)
- @lexer.state = :expr_value
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1466)
- def _reduce_382(val, _values, result)
- result = @builder.args(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1470)
- def _reduce_383(val, _values, result)
- result = @builder.args(val[0], [], val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1474)
- def _reduce_384(val, _values, result)
- result = @builder.args(val[0], val[1].concat(val[2]), val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1479)
- def _reduce_385(val, _values, result)
- result = []
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1483)
- def _reduce_386(val, _values, result)
- result = val[2]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1488)
- def _reduce_387(val, _values, result)
- result = [ val[0] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1492)
- def _reduce_388(val, _values, result)
- result = val[0] << val[2]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1497)
- def _reduce_389(val, _values, result)
- result = @builder.shadowarg(val[0])
-
- result
- end
-.,.,
-
-# reduce 390 omitted
-
-module_eval(<<'.,.,', 'ruby22.y', 1502)
- def _reduce_391(val, _values, result)
- @static_env.extend_dynamic
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1506)
- def _reduce_392(val, _values, result)
- result = @lexer.cmdarg.dup
- @lexer.cmdarg.clear
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1511)
- def _reduce_393(val, _values, result)
- @lexer.cmdarg = val[2]
- @lexer.cmdarg.lexpop
-
- result = [ val[1], val[3] ]
-
- @static_env.unextend
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1521)
- def _reduce_394(val, _values, result)
- result = @builder.args(val[0], val[1].concat(val[2]), val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1525)
- def _reduce_395(val, _values, result)
- result = @builder.args(nil, val[0], nil)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1530)
- def _reduce_396(val, _values, result)
- result = [ val[0], val[1], val[2] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1534)
- def _reduce_397(val, _values, result)
- result = [ val[0], val[1], val[2] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1539)
- def _reduce_398(val, _values, result)
- @static_env.extend_dynamic
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1543)
- def _reduce_399(val, _values, result)
- result = [ val[0], val[2], val[3], val[4] ]
-
- @static_env.unextend
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1550)
- def _reduce_400(val, _values, result)
- begin_t, block_args, body, end_t = val[1]
- result = @builder.block(val[0],
- begin_t, block_args, body, end_t)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1556)
- def _reduce_401(val, _values, result)
- lparen_t, args, rparen_t = val[3]
- result = @builder.call_method(val[0], val[1], val[2],
- lparen_t, args, rparen_t)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1562)
- def _reduce_402(val, _values, result)
- lparen_t, args, rparen_t = val[3]
- method_call = @builder.call_method(val[0], val[1], val[2],
- lparen_t, args, rparen_t)
-
- begin_t, args, body, end_t = val[4]
- result = @builder.block(method_call,
- begin_t, args, body, end_t)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1572)
- def _reduce_403(val, _values, result)
- method_call = @builder.call_method(val[0], val[1], val[2],
- nil, val[3], nil)
-
- begin_t, args, body, end_t = val[4]
- result = @builder.block(method_call,
- begin_t, args, body, end_t)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1582)
- def _reduce_404(val, _values, result)
- lparen_t, args, rparen_t = val[1]
- result = @builder.call_method(nil, nil, val[0],
- lparen_t, args, rparen_t)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1588)
- def _reduce_405(val, _values, result)
- lparen_t, args, rparen_t = val[3]
- result = @builder.call_method(val[0], val[1], val[2],
- lparen_t, args, rparen_t)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1594)
- def _reduce_406(val, _values, result)
- lparen_t, args, rparen_t = val[3]
- result = @builder.call_method(val[0], val[1], val[2],
- lparen_t, args, rparen_t)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1600)
- def _reduce_407(val, _values, result)
- result = @builder.call_method(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1604)
- def _reduce_408(val, _values, result)
- lparen_t, args, rparen_t = val[2]
- result = @builder.call_method(val[0], val[1], nil,
- lparen_t, args, rparen_t)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1610)
- def _reduce_409(val, _values, result)
- lparen_t, args, rparen_t = val[2]
- result = @builder.call_method(val[0], val[1], nil,
- lparen_t, args, rparen_t)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1616)
- def _reduce_410(val, _values, result)
- lparen_t, args, rparen_t = val[1]
- result = @builder.keyword_cmd(:super, val[0],
- lparen_t, args, rparen_t)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1622)
- def _reduce_411(val, _values, result)
- result = @builder.keyword_cmd(:zsuper, val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1626)
- def _reduce_412(val, _values, result)
- result = @builder.index(val[0], val[1], val[2], val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1631)
- def _reduce_413(val, _values, result)
- @static_env.extend_dynamic
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1635)
- def _reduce_414(val, _values, result)
- result = [ val[0], val[2], val[3], val[4] ]
-
- @static_env.unextend
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1641)
- def _reduce_415(val, _values, result)
- @static_env.extend_dynamic
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1645)
- def _reduce_416(val, _values, result)
- result = [ val[0], val[2], val[3], val[4] ]
-
- @static_env.unextend
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1652)
- def _reduce_417(val, _values, result)
- result = [ @builder.when(val[0], val[1], val[2], val[3]),
- *val[4] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1658)
- def _reduce_418(val, _values, result)
- result = [ val[0] ]
-
- result
- end
-.,.,
-
-# reduce 419 omitted
-
-module_eval(<<'.,.,', 'ruby22.y', 1664)
- def _reduce_420(val, _values, result)
- assoc_t, exc_var = val[2]
-
- if val[1]
- exc_list = @builder.array(nil, val[1], nil)
- end
-
- result = [ @builder.rescue_body(val[0],
- exc_list, assoc_t, exc_var,
- val[3], val[4]),
- *val[5] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1677)
- def _reduce_421(val, _values, result)
- result = []
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1682)
- def _reduce_422(val, _values, result)
- result = [ val[0] ]
-
- result
- end
-.,.,
-
-# reduce 423 omitted
-
-# reduce 424 omitted
-
-module_eval(<<'.,.,', 'ruby22.y', 1689)
- def _reduce_425(val, _values, result)
- result = [ val[0], val[1] ]
-
- result
- end
-.,.,
-
-# reduce 426 omitted
-
-module_eval(<<'.,.,', 'ruby22.y', 1695)
- def _reduce_427(val, _values, result)
- result = [ val[0], val[1] ]
-
- result
- end
-.,.,
-
-# reduce 428 omitted
-
-# reduce 429 omitted
-
-# reduce 430 omitted
-
-# reduce 431 omitted
-
-module_eval(<<'.,.,', 'ruby22.y', 1705)
- def _reduce_432(val, _values, result)
- result = @builder.string_compose(nil, val[0], nil)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1710)
- def _reduce_433(val, _values, result)
- result = [ val[0] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1714)
- def _reduce_434(val, _values, result)
- result = val[0] << val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1719)
- def _reduce_435(val, _values, result)
- result = @builder.string_compose(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1723)
- def _reduce_436(val, _values, result)
- result = @builder.string(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1727)
- def _reduce_437(val, _values, result)
- result = @builder.character(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1732)
- def _reduce_438(val, _values, result)
- result = @builder.xstring_compose(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1737)
- def _reduce_439(val, _values, result)
- opts = @builder.regexp_options(val[3])
- result = @builder.regexp_compose(val[0], val[1], val[2], opts)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1743)
- def _reduce_440(val, _values, result)
- result = @builder.words_compose(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1748)
- def _reduce_441(val, _values, result)
- result = []
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1752)
- def _reduce_442(val, _values, result)
- result = val[0] << @builder.word(val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1757)
- def _reduce_443(val, _values, result)
- result = [ val[0] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1761)
- def _reduce_444(val, _values, result)
- result = val[0] << val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1766)
- def _reduce_445(val, _values, result)
- result = @builder.symbols_compose(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1771)
- def _reduce_446(val, _values, result)
- result = []
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1775)
- def _reduce_447(val, _values, result)
- result = val[0] << @builder.word(val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1780)
- def _reduce_448(val, _values, result)
- result = @builder.words_compose(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1785)
- def _reduce_449(val, _values, result)
- result = @builder.symbols_compose(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1790)
- def _reduce_450(val, _values, result)
- result = []
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1794)
- def _reduce_451(val, _values, result)
- result = val[0] << @builder.string_internal(val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1799)
- def _reduce_452(val, _values, result)
- result = []
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1803)
- def _reduce_453(val, _values, result)
- result = val[0] << @builder.symbol_internal(val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1808)
- def _reduce_454(val, _values, result)
- result = []
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1812)
- def _reduce_455(val, _values, result)
- result = val[0] << val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1817)
- def _reduce_456(val, _values, result)
- result = []
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1821)
- def _reduce_457(val, _values, result)
- result = val[0] << val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1826)
- def _reduce_458(val, _values, result)
- result = []
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1830)
- def _reduce_459(val, _values, result)
- result = val[0] << val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1835)
- def _reduce_460(val, _values, result)
- result = @builder.string_internal(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1839)
- def _reduce_461(val, _values, result)
- result = val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1843)
- def _reduce_462(val, _values, result)
- @lexer.cond.push(false)
- @lexer.cmdarg.push(false)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1848)
- def _reduce_463(val, _values, result)
- @lexer.cond.lexpop
- @lexer.cmdarg.lexpop
-
- result = @builder.begin(val[0], val[2], val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1856)
- def _reduce_464(val, _values, result)
- result = @builder.gvar(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1860)
- def _reduce_465(val, _values, result)
- result = @builder.ivar(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1864)
- def _reduce_466(val, _values, result)
- result = @builder.cvar(val[0])
-
- result
- end
-.,.,
-
-# reduce 467 omitted
-
-module_eval(<<'.,.,', 'ruby22.y', 1871)
- def _reduce_468(val, _values, result)
- result = @builder.symbol(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1876)
- def _reduce_469(val, _values, result)
- result = @builder.symbol_compose(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1881)
- def _reduce_470(val, _values, result)
- result = val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1885)
- def _reduce_471(val, _values, result)
- result = @builder.negate(val[0], val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1890)
- def _reduce_472(val, _values, result)
- result = @builder.integer(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1894)
- def _reduce_473(val, _values, result)
- result = @builder.float(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1898)
- def _reduce_474(val, _values, result)
- result = @builder.rational(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1902)
- def _reduce_475(val, _values, result)
- result = @builder.complex(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1907)
- def _reduce_476(val, _values, result)
- result = @builder.ident(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1911)
- def _reduce_477(val, _values, result)
- result = @builder.ivar(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1915)
- def _reduce_478(val, _values, result)
- result = @builder.gvar(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1919)
- def _reduce_479(val, _values, result)
- result = @builder.const(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1923)
- def _reduce_480(val, _values, result)
- result = @builder.cvar(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1928)
- def _reduce_481(val, _values, result)
- result = @builder.nil(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1932)
- def _reduce_482(val, _values, result)
- result = @builder.self(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1936)
- def _reduce_483(val, _values, result)
- result = @builder.true(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1940)
- def _reduce_484(val, _values, result)
- result = @builder.false(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1944)
- def _reduce_485(val, _values, result)
- result = @builder.__FILE__(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1948)
- def _reduce_486(val, _values, result)
- result = @builder.__LINE__(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1952)
- def _reduce_487(val, _values, result)
- result = @builder.__ENCODING__(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1957)
- def _reduce_488(val, _values, result)
- result = @builder.accessible(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1961)
- def _reduce_489(val, _values, result)
- result = @builder.accessible(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1966)
- def _reduce_490(val, _values, result)
- result = @builder.assignable(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1970)
- def _reduce_491(val, _values, result)
- result = @builder.assignable(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1975)
- def _reduce_492(val, _values, result)
- result = @builder.nth_ref(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1979)
- def _reduce_493(val, _values, result)
- result = @builder.back_ref(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1984)
- def _reduce_494(val, _values, result)
- result = nil
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1988)
- def _reduce_495(val, _values, result)
- @lexer.state = :expr_value
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1992)
- def _reduce_496(val, _values, result)
- result = [ val[0], val[2] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 1996)
- def _reduce_497(val, _values, result)
- yyerrok
- result = nil
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2002)
- def _reduce_498(val, _values, result)
- result = @builder.args(val[0], val[1], val[2])
-
- @lexer.state = :expr_value
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2007)
- def _reduce_499(val, _values, result)
- result = @lexer.in_kwarg
- @lexer.in_kwarg = true
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2012)
- def _reduce_500(val, _values, result)
- @lexer.in_kwarg = val[0]
- result = @builder.args(nil, val[1], nil)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2018)
- def _reduce_501(val, _values, result)
- result = val[0].concat(val[2]).concat(val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2022)
- def _reduce_502(val, _values, result)
- result = val[0].concat(val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2026)
- def _reduce_503(val, _values, result)
- result = val[0].concat(val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2030)
- def _reduce_504(val, _values, result)
- result = [ val[0] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2035)
- def _reduce_505(val, _values, result)
- result = val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2039)
- def _reduce_506(val, _values, result)
- result = []
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2044)
- def _reduce_507(val, _values, result)
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2051)
- def _reduce_508(val, _values, result)
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[6]).
- concat(val[7])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2059)
- def _reduce_509(val, _values, result)
- result = val[0].
- concat(val[2]).
- concat(val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2065)
- def _reduce_510(val, _values, result)
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2072)
- def _reduce_511(val, _values, result)
- result = val[0].
- concat(val[2]).
- concat(val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2078)
- def _reduce_512(val, _values, result)
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2085)
- def _reduce_513(val, _values, result)
- result = val[0].
- concat(val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2090)
- def _reduce_514(val, _values, result)
- result = val[0].
- concat(val[2]).
- concat(val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2096)
- def _reduce_515(val, _values, result)
- result = val[0].
- concat(val[2]).
- concat(val[4]).
- concat(val[5])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2103)
- def _reduce_516(val, _values, result)
- result = val[0].
- concat(val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2108)
- def _reduce_517(val, _values, result)
- result = val[0].
- concat(val[2]).
- concat(val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2114)
- def _reduce_518(val, _values, result)
- result = val[0].
- concat(val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2119)
- def _reduce_519(val, _values, result)
- result = val[0].
- concat(val[2]).
- concat(val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2125)
- def _reduce_520(val, _values, result)
- result = val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2129)
- def _reduce_521(val, _values, result)
- result = []
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2134)
- def _reduce_522(val, _values, result)
- diagnostic :error, :argument_const, nil, val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2138)
- def _reduce_523(val, _values, result)
- diagnostic :error, :argument_ivar, nil, val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2142)
- def _reduce_524(val, _values, result)
- diagnostic :error, :argument_gvar, nil, val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2146)
- def _reduce_525(val, _values, result)
- diagnostic :error, :argument_cvar, nil, val[0]
-
- result
- end
-.,.,
-
-# reduce 526 omitted
-
-module_eval(<<'.,.,', 'ruby22.y', 2152)
- def _reduce_527(val, _values, result)
- @static_env.declare val[0][0]
-
- result = val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2159)
- def _reduce_528(val, _values, result)
- result = val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2164)
- def _reduce_529(val, _values, result)
- result = @builder.arg(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2168)
- def _reduce_530(val, _values, result)
- result = @builder.multi_lhs(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2173)
- def _reduce_531(val, _values, result)
- result = [ val[0] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2177)
- def _reduce_532(val, _values, result)
- result = val[0] << val[2]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2182)
- def _reduce_533(val, _values, result)
- check_kwarg_name(val[0])
-
- @static_env.declare val[0][0]
-
- result = val[0]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2191)
- def _reduce_534(val, _values, result)
- result = @builder.kwoptarg(val[0], val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2195)
- def _reduce_535(val, _values, result)
- result = @builder.kwarg(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2200)
- def _reduce_536(val, _values, result)
- result = @builder.kwoptarg(val[0], val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2204)
- def _reduce_537(val, _values, result)
- result = @builder.kwarg(val[0])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2209)
- def _reduce_538(val, _values, result)
- result = [ val[0] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2213)
- def _reduce_539(val, _values, result)
- result = val[0] << val[2]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2218)
- def _reduce_540(val, _values, result)
- result = [ val[0] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2222)
- def _reduce_541(val, _values, result)
- result = val[0] << val[2]
-
- result
- end
-.,.,
-
-# reduce 542 omitted
-
-# reduce 543 omitted
-
-module_eval(<<'.,.,', 'ruby22.y', 2229)
- def _reduce_544(val, _values, result)
- @static_env.declare val[1][0]
-
- result = [ @builder.kwrestarg(val[0], val[1]) ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2235)
- def _reduce_545(val, _values, result)
- result = [ @builder.kwrestarg(val[0]) ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2240)
- def _reduce_546(val, _values, result)
- result = @builder.optarg(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2245)
- def _reduce_547(val, _values, result)
- result = @builder.optarg(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2250)
- def _reduce_548(val, _values, result)
- result = [ val[0] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2254)
- def _reduce_549(val, _values, result)
- result = val[0] << val[2]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2259)
- def _reduce_550(val, _values, result)
- result = [ val[0] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2263)
- def _reduce_551(val, _values, result)
- result = val[0] << val[2]
-
- result
- end
-.,.,
-
-# reduce 552 omitted
-
-# reduce 553 omitted
-
-module_eval(<<'.,.,', 'ruby22.y', 2270)
- def _reduce_554(val, _values, result)
- @static_env.declare val[1][0]
-
- result = [ @builder.restarg(val[0], val[1]) ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2276)
- def _reduce_555(val, _values, result)
- result = [ @builder.restarg(val[0]) ]
-
- result
- end
-.,.,
-
-# reduce 556 omitted
-
-# reduce 557 omitted
-
-module_eval(<<'.,.,', 'ruby22.y', 2283)
- def _reduce_558(val, _values, result)
- @static_env.declare val[1][0]
-
- result = @builder.blockarg(val[0], val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2290)
- def _reduce_559(val, _values, result)
- result = [ val[1] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2294)
- def _reduce_560(val, _values, result)
- result = []
-
- result
- end
-.,.,
-
-# reduce 561 omitted
-
-module_eval(<<'.,.,', 'ruby22.y', 2300)
- def _reduce_562(val, _values, result)
- result = val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2305)
- def _reduce_563(val, _values, result)
- result = []
-
- result
- end
-.,.,
-
-# reduce 564 omitted
-
-module_eval(<<'.,.,', 'ruby22.y', 2311)
- def _reduce_565(val, _values, result)
- result = [ val[0] ]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2315)
- def _reduce_566(val, _values, result)
- result = val[0] << val[2]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2320)
- def _reduce_567(val, _values, result)
- result = @builder.pair(val[0], val[1], val[2])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2324)
- def _reduce_568(val, _values, result)
- result = @builder.pair_keyword(val[0], val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2328)
- def _reduce_569(val, _values, result)
- result = @builder.pair_quoted(val[0], val[1], val[2], val[3])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2332)
- def _reduce_570(val, _values, result)
- result = @builder.kwsplat(val[0], val[1])
-
- result
- end
-.,.,
-
-# reduce 571 omitted
-
-# reduce 572 omitted
-
-# reduce 573 omitted
-
-# reduce 574 omitted
-
-# reduce 575 omitted
-
-# reduce 576 omitted
-
-# reduce 577 omitted
-
-# reduce 578 omitted
-
-# reduce 579 omitted
-
-# reduce 580 omitted
-
-# reduce 581 omitted
-
-# reduce 582 omitted
-
-# reduce 583 omitted
-
-# reduce 584 omitted
-
-# reduce 585 omitted
-
-# reduce 586 omitted
-
-module_eval(<<'.,.,', 'ruby22.y', 2343)
- def _reduce_587(val, _values, result)
- result = val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'ruby22.y', 2347)
- def _reduce_588(val, _values, result)
- result = val[1]
-
- result
- end
-.,.,
-
-# reduce 589 omitted
-
-# reduce 590 omitted
-
-# reduce 591 omitted
-
-module_eval(<<'.,.,', 'ruby22.y', 2353)
- def _reduce_592(val, _values, result)
- yyerrok
-
- result
- end
-.,.,
-
-# reduce 593 omitted
-
-# reduce 594 omitted
-
-# reduce 595 omitted
-
-module_eval(<<'.,.,', 'ruby22.y', 2362)
- def _reduce_596(val, _values, result)
- result = nil
-
- result
- end
-.,.,
-
-def _reduce_none(val, _values, result)
- val[0]
-end
-
- end # class Ruby22
-end # module Parser
diff --git a/test/racc/regress/tp_plus b/test/racc/regress/tp_plus
deleted file mode 100644
index 34b6284db7..0000000000
--- a/test/racc/regress/tp_plus
+++ /dev/null
@@ -1,1933 +0,0 @@
-#
-# DO NOT MODIFY!!!!
-# This file is automatically generated by Racc 1.5.0
-# from Racc grammar file "".
-#
-
-require 'racc/parser.rb'
-module TPPlus
- class Parser < Racc::Parser
-
-module_eval(<<'...end tp_plus.y/module_eval...', 'tp_plus.y', 592)
-
- include TPPlus::Nodes
-
- attr_reader :interpreter
- def initialize(scanner, interpreter = TPPlus::Interpreter.new)
- @scanner = scanner
- @interpreter = interpreter
- super()
- end
-
- def next_token
- t = @scanner.next_token
- @interpreter.line_count += 1 if t && t[0] == :NEWLINE
-
- #puts t.inspect
- t
- end
-
- def parse
- #@yydebug =true
-
- do_parse
- @interpreter
- end
-
- def on_error(t, val, vstack)
- raise ParseError, sprintf("Parse error on line #{@scanner.tok_line} column #{@scanner.tok_col}: %s (%s)",
- val.inspect, token_to_str(t) || '?')
- end
-
- class ParseError < StandardError ; end
-...end tp_plus.y/module_eval...
-##### State transition tables begin ###
-
-racc_action_table = [
- 62, 62, 62, 62, 101, 122, 62, 41, 38, 130,
- 275, 265, 72, 41, 72, 98, 113, 72, 53, 114,
- 41, 67, 67, 67, 67, 234, 38, 26, 152, 151,
- 101, 36, 64, 159, 81, 82, 72, 308, 159, 81,
- 82, 72, 122, 70, 308, 60, 74, 60, 42, 308,
- 60, 43, 44, 131, 45, 31, 32, 300, 75, 34,
- 35, 46, 47, 102, 60, 273, 30, 72, 29, 28,
- 25, 63, 76, 37, 27, 24, 62, 41, 38, 37,
- 69, 69, 69, 69, 33, 61, 37, 97, 53, 102,
- 61, 37, 81, 82, 355, 61, 103, 26, 82, 72,
- 60, 36, 159, 81, 82, 72, 208, 221, 209, 371,
- 82, 72, 105, 220, 33, 81, 82, 72, 42, 72,
- 317, 43, 44, 111, 45, 31, 32, 96, 72, 34,
- 35, 46, 47, 96, 60, 223, 30, 224, 29, 28,
- 25, 63, 115, 37, 27, 24, 62, 41, 38, 72,
- 60, 81, 82, 72, 33, 61, 121, 116, 53, 61,
- 122, 88, 94, 96, 321, 117, 118, 26, 317, 352,
- 125, 36, 323, 127, 203, 349, 350, 351, 353, 303,
- 304, 96, 367, 81, 82, 72, 60, 255, 42, 209,
- 101, 43, 44, 122, 45, 31, 32, 185, 94, 34,
- 35, 46, 47, 186, 60, 191, 30, 61, 29, 28,
- 25, 63, 321, 37, 27, 24, 62, 41, 38, 188,
- 323, 122, 203, 122, 33, 61, 82, 72, 53, 336,
- 335, 182, 181, 179, 180, 177, 173, 26, 176, 174,
- 199, 36, 81, 82, 72, 81, 82, 72, 81, 82,
- 72, 81, 82, 81, 82, 72, 200, 201, 42, 203,
- 204, 43, 44, 96, 45, 31, 32, 210, 211, 34,
- 35, 46, 47, 212, 60, 213, 30, 214, 29, 28,
- 25, 63, 215, 37, 27, 24, 216, 178, 217, 175,
- 81, 82, 72, 218, 33, 61, 81, 82, 72, 219,
- 88, 317, 96, 81, 82, 72, 88, 227, 96, 81,
- 82, 72, 227, 88, 96, 96, 81, 82, 72, 88,
- 229, 96, 81, 82, 72, 60, 88, 230, 96, 231,
- 234, 60, 88, 235, 96, 238, 122, 94, 60, 81,
- 82, 72, 122, 94, 60, 321, 61, 81, 82, 72,
- 94, 60, 61, 323, 241, 203, 94, 60, 242, 61,
- 244, 245, 246, 94, 247, 61, 248, 249, 250, 94,
- 251, 252, 61, 81, 82, 72, 253, 254, 61, 81,
- 82, 72, 257, 88, 188, 96, 81, 82, 72, 88,
- 259, 96, 81, 82, 72, 269, 88, 271, 96, 81,
- 82, 72, 88, 276, 96, 122, 281, 282, 60, 88,
- 283, 96, 284, 285, 60, 286, 287, 288, 289, 290,
- 94, 60, 82, 292, 293, 294, 94, 60, 122, 61,
- 122, 72, 298, 94, 60, 61, 301, 302, 305, 94,
- 306, 313, 61, 314, 122, 122, 94, 325, 61, 135,
- 136, 139, 140, 137, 138, 61, 141, 142, 144, 145,
- 146, 148, 143, 147, 135, 136, 139, 140, 137, 138,
- 326, 141, 142, 144, 145, 146, 148, 143, 147, 327,
- 328, 188, 97, 333, 275, 122, 33, 135, 136, 139,
- 140, 137, 138, 205, 141, 142, 144, 145, 146, 148,
- 143, 147, 188, 188, 333, 122, 346, 347, 207, 135,
- 136, 139, 140, 137, 138, 348, 141, 142, 144, 145,
- 146, 148, 143, 147, 188, 356, 357, 358, 359, 360,
- 135, 136, 139, 140, 137, 138, 361, 141, 142, 144,
- 145, 146, 148, 143, 147, 135, 136, 139, 140, 137,
- 138, 362, 141, 142, 144, 145, 146, 148, 143, 147,
- 135, 136, 139, 140, 137, 138, 122, 141, 142, 144,
- 145, 146, 148, 143, 147, 135, 136, 139, 140, 137,
- 138, 364, 141, 142, 144, 145, 146, 148, 143, 147,
- 135, 136, 139, 140, 137, 138, 72, 141, 142, 144,
- 145, 146, 148, 143, 147, 135, 136, 139, 140, 137,
- 138, 33, 141, 142, 144, 145, 146, 148, 143, 147,
- 135, 136, 139, 140, 137, 138, 378, 141, 142, 144,
- 145, 146, 148, 143, 147, 135, 136, 139, 140, 137,
- 138, 379, 141, 142, 144, 145, 146, 148, 143, 147,
- 380, 381, 382, 383, 385, 386, 390, 72, 392 ]
-
-racc_action_check = [
- 3, 65, 309, 312, 72, 272, 0, 0, 0, 70,
- 240, 232, 28, 295, 29, 36, 48, 105, 0, 48,
- 296, 3, 65, 309, 312, 232, 383, 0, 95, 95,
- 36, 0, 1, 97, 97, 97, 97, 295, 186, 186,
- 186, 186, 343, 27, 296, 28, 30, 29, 0, 383,
- 105, 0, 0, 70, 0, 0, 0, 272, 31, 0,
- 0, 0, 0, 72, 0, 240, 0, 38, 0, 0,
- 0, 0, 32, 0, 0, 0, 2, 2, 2, 295,
- 3, 65, 309, 312, 0, 0, 296, 36, 2, 36,
- 97, 383, 224, 224, 343, 186, 37, 2, 358, 358,
- 38, 2, 209, 209, 209, 209, 153, 184, 153, 358,
- 229, 229, 38, 184, 41, 88, 88, 88, 2, 44,
- 301, 2, 2, 46, 2, 2, 2, 88, 47, 2,
- 2, 2, 2, 301, 2, 187, 2, 187, 2, 2,
- 2, 2, 53, 2, 2, 2, 188, 188, 188, 58,
- 88, 35, 35, 35, 2, 2, 60, 55, 188, 209,
- 63, 35, 88, 35, 301, 55, 55, 188, 337, 342,
- 64, 188, 301, 68, 301, 342, 342, 342, 342, 280,
- 280, 337, 357, 357, 357, 357, 35, 222, 188, 222,
- 99, 188, 188, 101, 188, 188, 188, 102, 35, 188,
- 188, 188, 188, 103, 188, 109, 188, 35, 188, 188,
- 188, 188, 337, 188, 188, 188, 225, 225, 225, 111,
- 337, 112, 337, 115, 188, 188, 293, 293, 225, 320,
- 320, 98, 98, 98, 98, 98, 98, 225, 98, 98,
- 117, 225, 34, 34, 34, 75, 75, 75, 234, 234,
- 234, 98, 98, 238, 238, 238, 118, 121, 225, 123,
- 132, 225, 225, 98, 225, 225, 225, 173, 174, 225,
- 225, 225, 225, 175, 225, 176, 225, 177, 225, 225,
- 225, 225, 178, 225, 225, 225, 179, 98, 180, 98,
- 42, 42, 42, 181, 225, 225, 43, 43, 43, 182,
- 42, 363, 42, 45, 45, 45, 43, 189, 43, 76,
- 76, 76, 190, 45, 363, 45, 94, 94, 94, 76,
- 191, 76, 113, 113, 113, 42, 94, 192, 94, 193,
- 194, 43, 113, 197, 113, 201, 202, 42, 45, 326,
- 326, 326, 203, 43, 76, 363, 42, 360, 360, 360,
- 45, 94, 43, 363, 204, 363, 76, 113, 205, 45,
- 210, 211, 212, 94, 213, 76, 214, 215, 216, 113,
- 217, 218, 94, 114, 114, 114, 219, 221, 113, 116,
- 116, 116, 226, 114, 227, 114, 134, 134, 134, 116,
- 228, 116, 199, 199, 199, 235, 134, 239, 134, 200,
- 200, 200, 199, 241, 199, 242, 244, 245, 114, 200,
- 246, 200, 247, 248, 116, 249, 250, 251, 252, 253,
- 114, 134, 254, 256, 260, 263, 116, 199, 265, 114,
- 266, 269, 270, 134, 200, 116, 275, 277, 291, 199,
- 292, 297, 134, 299, 300, 302, 200, 303, 199, 133,
- 133, 133, 133, 133, 133, 200, 133, 133, 133, 133,
- 133, 133, 133, 133, 150, 150, 150, 150, 150, 150,
- 304, 150, 150, 150, 150, 150, 150, 150, 150, 306,
- 307, 107, 308, 313, 315, 323, 325, 107, 107, 107,
- 107, 107, 107, 133, 107, 107, 107, 107, 107, 107,
- 107, 107, 328, 108, 331, 333, 338, 339, 150, 108,
- 108, 108, 108, 108, 108, 340, 108, 108, 108, 108,
- 108, 108, 108, 108, 110, 347, 349, 350, 351, 352,
- 110, 110, 110, 110, 110, 110, 353, 110, 110, 110,
- 110, 110, 110, 110, 110, 83, 83, 83, 83, 83,
- 83, 354, 83, 83, 83, 83, 83, 83, 83, 83,
- 195, 195, 195, 195, 195, 195, 355, 195, 195, 195,
- 195, 195, 195, 195, 195, 196, 196, 196, 196, 196,
- 196, 356, 196, 196, 196, 196, 196, 196, 196, 196,
- 198, 198, 198, 198, 198, 198, 359, 198, 198, 198,
- 198, 198, 198, 198, 198, 206, 206, 206, 206, 206,
- 206, 361, 206, 206, 206, 206, 206, 206, 206, 206,
- 236, 236, 236, 236, 236, 236, 365, 236, 236, 236,
- 236, 236, 236, 236, 236, 237, 237, 237, 237, 237,
- 237, 366, 237, 237, 237, 237, 237, 237, 237, 237,
- 368, 371, 372, 373, 376, 379, 384, 385, 387 ]
-
-racc_action_pointer = [
- 2, 32, 72, -4, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 13, -17, -15,
- 20, -16, -2, nil, 215, 124, 13, 67, 38, nil,
- nil, 32, 263, 269, 90, 276, 94, 99, -30, nil,
- nil, nil, nil, 125, nil, 127, nil, nil, 120, nil,
- 82, nil, nil, 135, 170, -3, nil, nil, 148, nil,
- -17, nil, -13, nil, nil, 218, 282, nil, nil, nil,
- nil, nil, nil, 514, nil, nil, nil, nil, 88, nil,
- nil, nil, nil, nil, 289, 1, nil, 7, 224, 173,
- nil, 168, 121, 129, nil, -12, nil, 456, 478, 154,
- 499, 194, 196, 295, 346, 198, 352, 210, 226, nil,
- nil, 231, nil, 179, nil, nil, nil, nil, nil, nil,
- nil, nil, 183, 418, 359, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- 433, nil, nil, 31, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 189, 190, 195, 197, 199, 204, 208,
- 210, 215, 221, nil, 84, nil, 12, 60, 142, 260,
- 265, 246, 279, 281, 269, 529, 544, 315, 559, 365,
- 372, 258, 311, 317, 328, 341, 574, nil, nil, 76,
- 332, 333, 334, 336, 338, 339, 340, 342, 343, 348,
- nil, 303, 112, nil, 65, 212, 334, 359, 342, 82,
- nil, nil, -36, nil, 221, 321, 589, 604, 226, 349,
- -16, 328, 380, nil, 327, 328, 331, 333, 334, 336,
- 337, 338, 339, 340, 394, nil, 346, nil, nil, nil,
- 406, nil, nil, 377, nil, 403, 405, nil, nil, 402,
- 357, nil, -20, nil, nil, 360, nil, 420, nil, nil,
- 124, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 363, 414, 198, nil, 8, 15, 366, nil, 362,
- 419, 94, 420, 373, 396, nil, 404, 405, 408, -2,
- nil, nil, -1, 466, nil, 458, nil, nil, nil, nil,
- 202, nil, nil, 460, nil, 404, 312, nil, 477, nil,
- nil, 487, nil, 480, nil, nil, nil, 142, 431, 430,
- 467, nil, 156, 17, nil, nil, nil, 499, nil, 452,
- 453, 454, 455, 462, 472, 541, 506, 156, 70, 567,
- 320, 529, nil, 275, nil, 551, 564, nil, 575, nil,
- nil, 623, 577, 576, nil, nil, 577, nil, nil, 629,
- nil, nil, nil, 20, 581, 628, nil, 583, nil, nil,
- nil, nil, nil ]
-
-racc_action_default = [
- -2, -210, -1, -188, -8, -9, -10, -11, -12, -13,
- -14, -15, -16, -17, -18, -19, -20, -21, -22, -23,
- -24, -25, -26, -27, -28, -29, -30, -210, -210, -210,
- -210, -210, -210, -45, -210, -210, -118, -210, -210, -61,
- -62, -210, -210, -210, -210, -210, -210, -210, -81, -84,
- -85, -86, -87, -210, -111, -210, -116, -117, -210, -125,
- -210, -183, -184, -190, -210, -188, -3, -185, -7, -187,
- -210, -34, -118, -35, -36, -210, -210, -46, -103, -104,
- -158, -159, -160, -47, -128, -129, -130, -131, -210, -148,
- -149, -150, -151, -152, -210, -210, -157, -52, -210, -119,
- -121, -190, -210, -210, -58, -210, -63, -210, -210, -210,
- -210, -210, -190, -210, -210, -190, -210, -210, -210, -120,
- -126, -210, -189, -210, -192, 393, -4, -6, -186, -31,
- -32, -33, -210, -210, -210, -134, -135, -136, -137, -138,
- -139, -140, -141, -142, -143, -144, -145, -146, -147, -132,
- -210, -155, -156, -210, -50, -53, -54, -55, -56, -57,
- -112, -161, -162, -163, -164, -165, -166, -167, -168, -169,
- -170, -171, -172, -210, -210, -210, -210, -210, -210, -210,
- -210, -210, -210, -122, -210, -127, -52, -210, -210, -89,
- -89, -210, -210, -210, -210, -82, -83, -210, -113, -210,
- -210, -210, -190, -190, -210, -38, -133, -153, -48, -210,
- -210, -210, -210, -210, -210, -210, -210, -210, -210, -210,
- -123, -210, -210, -59, -210, -5, -210, -210, -210, -210,
- -67, -70, -78, -72, -210, -210, -114, -115, -210, -210,
- -210, -210, -190, -51, -210, -210, -210, -210, -210, -210,
- -210, -210, -210, -210, -210, -49, -210, -64, -88, -65,
- -210, -68, -69, -210, -73, -190, -190, -75, -76, -210,
- -210, -191, -190, -194, -195, -210, -37, -39, -41, -42,
- -210, -173, -174, -175, -176, -177, -178, -179, -180, -181,
- -182, -210, -210, -210, -71, -210, -210, -210, -154, -210,
- -190, -205, -190, -210, -210, -124, -210, -210, -210, -188,
- -79, -80, -188, -210, -193, -210, -197, -198, -199, -200,
- -210, -203, -204, -190, -40, -210, -210, -60, -210, -77,
- -74, -90, -91, -190, -196, -201, -202, -205, -210, -210,
- -210, -92, -210, -190, -207, -209, -43, -210, -66, -210,
- -210, -210, -210, -210, -210, -190, -210, -210, -210, -210,
- -210, -210, -206, -205, -44, -210, -210, -110, -210, -98,
- -99, -210, -210, -210, -107, -108, -102, -208, -93, -210,
- -94, -100, -95, -210, -210, -210, -109, -210, -105, -106,
- -97, -101, -96 ]
-
-racc_goto_table = [
- 39, 106, 39, 66, 78, 65, 123, 68, 77, 184,
- 9, 2, 9, 153, 40, 261, 40, 274, 310, 310,
- 194, 189, 190, 197, 192, 193, 71, 73, 39, 39,
- 277, 260, 233, 344, 79, 1, 104, 322, 39, 332,
- 291, 128, 40, 40, 109, 78, 129, 112, 243, 132,
- 311, 311, 40, 83, 226, 228, 389, 341, 232, 377,
- 107, 108, 263, 110, 266, 126, 331, 155, 167, 68,
- 264, 309, 312, 322, 365, 79, 368, 373, 387, 261,
- 384, 160, 119, 183, 120, 149, 168, 161, 162, 163,
- 324, 164, 334, 165, 133, 307, 166, 156, 169, 322,
- 170, 171, 222, 187, 172, 39, 388, 158, 202, 272,
- 316, 343, 150, nil, nil, nil, nil, nil, nil, 40,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 195, 196, nil, 198, nil, nil, nil, nil, nil,
- nil, 258, nil, nil, 369, 239, 240, nil, nil, nil,
- 280, nil, 206, nil, nil, nil, 155, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 295, 296, nil, nil, nil, nil, 155,
- nil, nil, nil, nil, nil, nil, 156, nil, 39, nil,
- nil, nil, nil, nil, 256, nil, 158, nil, 9, 225,
- nil, nil, 40, nil, 267, nil, nil, nil, 78, 156,
- 280, nil, 270, nil, nil, 299, nil, 236, 237, 158,
- nil, nil, nil, nil, nil, 39, nil, nil, 65, 262,
- nil, nil, nil, nil, 268, 9, nil, nil, 79, 40,
- nil, 342, 340, 315, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 337, nil, nil, 297,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 338, 354, nil, nil, nil,
- nil, nil, nil, 262, nil, nil, 78, nil, 363, nil,
- 339, nil, nil, nil, nil, nil, nil, nil, nil, 329,
- nil, nil, 330, 68, nil, nil, 68, nil, nil, nil,
- nil, 376, nil, nil, nil, nil, 79, 78, nil, nil,
- 375, 366, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 79, 370, 372,
- 374, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 391 ]
-
-racc_goto_check = [
- 40, 35, 40, 4, 39, 3, 86, 7, 29, 34,
- 12, 2, 12, 37, 43, 47, 43, 89, 36, 36,
- 34, 5, 5, 34, 5, 5, 28, 28, 40, 40,
- 31, 46, 50, 94, 40, 1, 28, 75, 40, 56,
- 47, 6, 43, 43, 40, 39, 27, 40, 38, 29,
- 44, 44, 43, 30, 45, 45, 42, 56, 48, 94,
- 30, 30, 49, 30, 51, 4, 55, 39, 39, 7,
- 50, 52, 52, 75, 57, 40, 58, 59, 60, 47,
- 61, 62, 63, 67, 68, 71, 73, 76, 77, 78,
- 31, 79, 89, 80, 30, 46, 81, 40, 82, 75,
- 83, 84, 37, 28, 85, 40, 36, 12, 87, 88,
- 90, 93, 30, nil, nil, nil, nil, nil, nil, 43,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 30, 30, nil, 30, nil, nil, nil, nil, nil,
- nil, 5, nil, nil, 47, 86, 86, nil, nil, nil,
- 34, nil, 30, nil, nil, nil, 39, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, 34, 34, nil, nil, nil, nil, 39,
- nil, nil, nil, nil, nil, nil, 40, nil, 40, nil,
- nil, nil, nil, nil, 39, nil, 12, nil, 12, 2,
- nil, nil, 43, nil, 39, nil, nil, nil, 39, 40,
- 34, nil, 29, nil, nil, 86, nil, 30, 30, 12,
- nil, nil, nil, nil, nil, 40, nil, nil, 3, 40,
- nil, nil, nil, nil, 40, 12, nil, nil, 40, 43,
- nil, 34, 5, 86, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, 86, nil, nil, 40,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 35, 86, nil, nil, nil,
- nil, nil, nil, 40, nil, nil, 39, nil, 86, nil,
- 29, nil, nil, nil, nil, nil, nil, nil, nil, 4,
- nil, nil, 4, 7, nil, nil, 7, nil, nil, nil,
- nil, 35, nil, nil, nil, nil, 40, 39, nil, nil,
- 39, 29, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 40, 40, 40,
- 40, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, 40 ]
-
-racc_goto_pointer = [
- nil, 35, 11, 3, 0, -86, -27, 4, nil, nil,
- nil, nil, 10, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, -24, -2, -26,
- 18, -212, nil, nil, -92, -40, -277, -84, -161, -30,
- 0, nil, -327, 14, -245, -135, -198, -214, -136, -170,
- -162, -170, -224, nil, nil, -247, -274, -283, -282, -283,
- -305, -296, -17, 24, nil, nil, nil, -16, 26, nil,
- nil, -3, nil, -12, nil, -264, -11, -10, -9, -7,
- -5, -2, 0, 2, 3, 6, -57, -15, -131, -223,
- -191, nil, nil, -226, -304 ]
-
-racc_goto_default = [
- nil, nil, nil, 3, nil, nil, nil, 4, 5, 6,
- 7, 8, 87, 10, 11, 12, 13, 14, 15, 16,
- 17, 18, 19, 20, 21, 22, 23, nil, 55, nil,
- nil, nil, 278, 279, 124, 54, 52, nil, 154, 89,
- 91, 157, 51, 92, 49, nil, nil, 80, nil, nil,
- nil, nil, nil, 48, 50, nil, nil, nil, nil, nil,
- nil, nil, nil, 56, 57, 99, 58, 100, 59, 84,
- 85, 86, 134, 90, 93, 95, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, 318, nil, nil,
- 345, 319, 320, nil, nil ]
-
-racc_reduce_table = [
- 0, 0, :racc_error,
- 1, 86, :_reduce_1,
- 0, 86, :_reduce_none,
- 2, 87, :_reduce_3,
- 3, 87, :_reduce_4,
- 2, 90, :_reduce_5,
- 1, 91, :_reduce_none,
- 0, 91, :_reduce_none,
- 1, 88, :_reduce_none,
- 1, 88, :_reduce_none,
- 1, 88, :_reduce_none,
- 1, 88, :_reduce_none,
- 1, 88, :_reduce_none,
- 1, 88, :_reduce_none,
- 1, 88, :_reduce_none,
- 1, 88, :_reduce_none,
- 1, 88, :_reduce_none,
- 1, 88, :_reduce_none,
- 1, 88, :_reduce_none,
- 1, 88, :_reduce_none,
- 1, 88, :_reduce_none,
- 1, 88, :_reduce_none,
- 1, 88, :_reduce_none,
- 1, 88, :_reduce_none,
- 1, 88, :_reduce_none,
- 1, 88, :_reduce_none,
- 1, 88, :_reduce_none,
- 1, 88, :_reduce_none,
- 1, 88, :_reduce_28,
- 1, 88, :_reduce_29,
- 1, 111, :_reduce_30,
- 3, 110, :_reduce_31,
- 1, 112, :_reduce_none,
- 1, 112, :_reduce_none,
- 2, 109, :_reduce_34,
- 2, 107, :_reduce_35,
- 2, 106, :_reduce_36,
- 6, 104, :_reduce_37,
- 4, 104, :_reduce_38,
- 6, 104, :_reduce_39,
- 8, 104, :_reduce_40,
- 1, 116, :_reduce_none,
- 1, 116, :_reduce_none,
- 5, 117, :_reduce_43,
- 7, 118, :_reduce_44,
- 1, 120, :_reduce_45,
- 2, 102, :_reduce_46,
- 2, 103, :_reduce_47,
- 4, 121, :_reduce_48,
- 5, 121, :_reduce_49,
- 1, 122, :_reduce_50,
- 3, 122, :_reduce_51,
- 0, 122, :_reduce_52,
- 1, 123, :_reduce_none,
- 1, 123, :_reduce_none,
- 1, 123, :_reduce_none,
- 1, 123, :_reduce_none,
- 1, 126, :_reduce_57,
- 2, 127, :_reduce_58,
- 4, 127, :_reduce_59,
- 8, 127, :_reduce_60,
- 1, 113, :_reduce_none,
- 1, 113, :_reduce_none,
- 2, 129, :_reduce_63,
- 5, 98, :_reduce_64,
- 5, 98, :_reduce_65,
- 10, 100, :_reduce_66,
- 4, 101, :_reduce_67,
- 1, 131, :_reduce_none,
- 1, 131, :_reduce_none,
- 4, 94, :_reduce_70,
- 6, 105, :_reduce_71,
- 1, 133, :_reduce_72,
- 2, 133, :_reduce_73,
- 5, 135, :_reduce_74,
- 1, 136, :_reduce_none,
- 1, 136, :_reduce_none,
- 4, 134, :_reduce_77,
- 0, 134, :_reduce_none,
- 1, 137, :_reduce_none,
- 1, 137, :_reduce_none,
- 1, 99, :_reduce_none,
- 3, 99, :_reduce_82,
- 3, 99, :_reduce_83,
- 1, 138, :_reduce_none,
- 1, 138, :_reduce_none,
- 1, 138, :_reduce_none,
- 1, 138, :_reduce_none,
- 2, 130, :_reduce_88,
- 0, 130, :_reduce_89,
- 8, 95, :_reduce_90,
- 1, 140, :_reduce_91,
- 2, 140, :_reduce_92,
- 6, 141, :_reduce_93,
- 6, 141, :_reduce_94,
- 6, 141, :_reduce_95,
- 8, 141, :_reduce_96,
- 7, 141, :_reduce_97,
- 1, 143, :_reduce_none,
- 1, 143, :_reduce_none,
- 2, 143, :_reduce_100,
- 2, 146, :_reduce_101,
- 0, 146, :_reduce_none,
- 1, 114, :_reduce_none,
- 1, 114, :_reduce_none,
- 1, 145, :_reduce_none,
- 1, 145, :_reduce_none,
- 1, 144, :_reduce_none,
- 1, 144, :_reduce_none,
- 3, 142, :_reduce_109,
- 1, 142, :_reduce_110,
- 1, 96, :_reduce_111,
- 3, 93, :_reduce_112,
- 3, 139, :_reduce_113,
- 4, 139, :_reduce_114,
- 4, 139, :_reduce_115,
- 1, 125, :_reduce_none,
- 1, 125, :_reduce_none,
- 1, 148, :_reduce_118,
- 2, 148, :_reduce_119,
- 2, 149, :_reduce_120,
- 1, 150, :_reduce_121,
- 2, 150, :_reduce_122,
- 3, 152, :_reduce_123,
- 6, 152, :_reduce_124,
- 1, 151, :_reduce_125,
- 2, 151, :_reduce_126,
- 3, 153, :_reduce_127,
- 1, 115, :_reduce_none,
- 1, 115, :_reduce_none,
- 1, 154, :_reduce_130,
- 1, 154, :_reduce_none,
- 2, 154, :_reduce_132,
- 3, 155, :_reduce_133,
- 1, 157, :_reduce_134,
- 1, 157, :_reduce_135,
- 1, 157, :_reduce_136,
- 1, 157, :_reduce_137,
- 1, 157, :_reduce_138,
- 1, 157, :_reduce_139,
- 1, 157, :_reduce_140,
- 1, 157, :_reduce_141,
- 1, 157, :_reduce_142,
- 1, 157, :_reduce_143,
- 1, 157, :_reduce_144,
- 1, 157, :_reduce_145,
- 1, 157, :_reduce_146,
- 1, 157, :_reduce_147,
- 1, 156, :_reduce_none,
- 1, 156, :_reduce_none,
- 1, 156, :_reduce_none,
- 1, 156, :_reduce_none,
- 1, 156, :_reduce_none,
- 3, 159, :_reduce_153,
- 6, 128, :_reduce_154,
- 2, 158, :_reduce_155,
- 2, 158, :_reduce_156,
- 1, 160, :_reduce_157,
- 1, 124, :_reduce_none,
- 1, 124, :_reduce_159,
- 1, 132, :_reduce_160,
- 1, 147, :_reduce_none,
- 1, 147, :_reduce_none,
- 1, 147, :_reduce_none,
- 1, 147, :_reduce_none,
- 1, 147, :_reduce_none,
- 1, 147, :_reduce_none,
- 1, 147, :_reduce_none,
- 1, 147, :_reduce_none,
- 1, 147, :_reduce_none,
- 1, 147, :_reduce_none,
- 1, 147, :_reduce_none,
- 1, 147, :_reduce_none,
- 4, 170, :_reduce_173,
- 4, 169, :_reduce_174,
- 4, 168, :_reduce_175,
- 4, 167, :_reduce_176,
- 4, 166, :_reduce_177,
- 4, 165, :_reduce_178,
- 4, 161, :_reduce_179,
- 4, 164, :_reduce_180,
- 4, 162, :_reduce_181,
- 4, 163, :_reduce_182,
- 1, 97, :_reduce_183,
- 1, 92, :_reduce_184,
- 1, 89, :_reduce_185,
- 2, 89, :_reduce_186,
- 1, 89, :_reduce_none,
- 0, 89, :_reduce_none,
- 1, 119, :_reduce_189,
- 0, 119, :_reduce_none,
- 5, 108, :_reduce_191,
- 1, 171, :_reduce_none,
- 5, 172, :_reduce_193,
- 3, 172, :_reduce_194,
- 1, 173, :_reduce_195,
- 4, 173, :_reduce_196,
- 3, 174, :_reduce_197,
- 1, 175, :_reduce_none,
- 1, 175, :_reduce_none,
- 1, 175, :_reduce_none,
- 2, 175, :_reduce_201,
- 2, 175, :_reduce_202,
- 1, 175, :_reduce_203,
- 1, 177, :_reduce_none,
- 0, 177, :_reduce_none,
- 5, 176, :_reduce_206,
- 1, 178, :_reduce_207,
- 4, 178, :_reduce_208,
- 1, 179, :_reduce_none ]
-
-racc_reduce_n = 210
-
-racc_shift_n = 393
-
-racc_token_table = {
- false => 0,
- :error => 1,
- :ASSIGN => 2,
- :AT_SYM => 3,
- :COMMENT => 4,
- :JUMP => 5,
- :IO_METHOD => 6,
- :INPUT => 7,
- :OUTPUT => 8,
- :NUMREG => 9,
- :POSREG => 10,
- :VREG => 11,
- :SREG => 12,
- :TIME_SEGMENT => 13,
- :ARG => 14,
- :UALM => 15,
- :MOVE => 16,
- :DOT => 17,
- :TO => 18,
- :AT => 19,
- :TERM => 20,
- :OFFSET => 21,
- :SKIP => 22,
- :GROUP => 23,
- :SEMICOLON => 24,
- :NEWLINE => 25,
- :STRING => 26,
- :REAL => 27,
- :DIGIT => 28,
- :WORD => 29,
- :EQUAL => 30,
- :EEQUAL => 31,
- :NOTEQUAL => 32,
- :GTE => 33,
- :LTE => 34,
- :LT => 35,
- :GT => 36,
- :BANG => 37,
- :PLUS => 38,
- :MINUS => 39,
- :STAR => 40,
- :SLASH => 41,
- :DIV => 42,
- :AND => 43,
- :OR => 44,
- :MOD => 45,
- :IF => 46,
- :ELSE => 47,
- :END => 48,
- :UNLESS => 49,
- :FOR => 50,
- :IN => 51,
- :WHILE => 52,
- :WAIT_FOR => 53,
- :WAIT_UNTIL => 54,
- :TIMEOUT => 55,
- :AFTER => 56,
- :FANUC_USE => 57,
- :SET_SKIP_CONDITION => 58,
- :NAMESPACE => 59,
- :CASE => 60,
- :WHEN => 61,
- :INDIRECT => 62,
- :POSITION => 63,
- :EVAL => 64,
- :TIMER => 65,
- :TIMER_METHOD => 66,
- :RAISE => 67,
- :ABORT => 68,
- :POSITION_DATA => 69,
- :TRUE_FALSE => 70,
- :RUN => 71,
- :TP_HEADER => 72,
- :PAUSE => 73,
- :LPAREN => 74,
- :RPAREN => 75,
- :COLON => 76,
- :COMMA => 77,
- :LBRACK => 78,
- :RBRACK => 79,
- :LBRACE => 80,
- :RBRACE => 81,
- :LABEL => 82,
- :ADDRESS => 83,
- :false => 84 }
-
-racc_nt_base = 85
-
-racc_use_result_var = true
-
-Racc_arg = [
- racc_action_table,
- racc_action_check,
- racc_action_default,
- racc_action_pointer,
- racc_goto_table,
- racc_goto_check,
- racc_goto_default,
- racc_goto_pointer,
- racc_nt_base,
- racc_reduce_table,
- racc_token_table,
- racc_shift_n,
- racc_reduce_n,
- racc_use_result_var ]
-
-Racc_token_to_s_table = [
- "$end",
- "error",
- "ASSIGN",
- "AT_SYM",
- "COMMENT",
- "JUMP",
- "IO_METHOD",
- "INPUT",
- "OUTPUT",
- "NUMREG",
- "POSREG",
- "VREG",
- "SREG",
- "TIME_SEGMENT",
- "ARG",
- "UALM",
- "MOVE",
- "DOT",
- "TO",
- "AT",
- "TERM",
- "OFFSET",
- "SKIP",
- "GROUP",
- "SEMICOLON",
- "NEWLINE",
- "STRING",
- "REAL",
- "DIGIT",
- "WORD",
- "EQUAL",
- "EEQUAL",
- "NOTEQUAL",
- "GTE",
- "LTE",
- "LT",
- "GT",
- "BANG",
- "PLUS",
- "MINUS",
- "STAR",
- "SLASH",
- "DIV",
- "AND",
- "OR",
- "MOD",
- "IF",
- "ELSE",
- "END",
- "UNLESS",
- "FOR",
- "IN",
- "WHILE",
- "WAIT_FOR",
- "WAIT_UNTIL",
- "TIMEOUT",
- "AFTER",
- "FANUC_USE",
- "SET_SKIP_CONDITION",
- "NAMESPACE",
- "CASE",
- "WHEN",
- "INDIRECT",
- "POSITION",
- "EVAL",
- "TIMER",
- "TIMER_METHOD",
- "RAISE",
- "ABORT",
- "POSITION_DATA",
- "TRUE_FALSE",
- "RUN",
- "TP_HEADER",
- "PAUSE",
- "LPAREN",
- "RPAREN",
- "COLON",
- "COMMA",
- "LBRACK",
- "RBRACK",
- "LBRACE",
- "RBRACE",
- "LABEL",
- "ADDRESS",
- "false",
- "$start",
- "program",
- "statements",
- "statement",
- "terminator",
- "block",
- "optional_newline",
- "comment",
- "definition",
- "namespace",
- "motion_statement",
- "label_definition",
- "address",
- "conditional",
- "inline_conditional",
- "forloop",
- "while_loop",
- "use_statement",
- "set_skip_statement",
- "wait_statement",
- "case_statement",
- "fanuc_eval",
- "timer_method",
- "position_data",
- "raise",
- "tp_header_definition",
- "empty_stmt",
- "tp_header_value",
- "var_or_indirect",
- "indirectable",
- "expression",
- "wait_modifier",
- "timeout_modifier",
- "after_modifier",
- "swallow_newlines",
- "label",
- "program_call",
- "args",
- "arg",
- "number",
- "var",
- "string",
- "io_method",
- "indirect_thing",
- "jump",
- "else_block",
- "minmax_val",
- "integer",
- "case_conditions",
- "case_else",
- "case_condition",
- "case_allowed_condition",
- "case_allowed_statement",
- "inlineable",
- "assignment",
- "motion_modifiers",
- "motion_modifier",
- "speed",
- "valid_terminations",
- "time",
- "time_seg_actions",
- "optional_lpos_arg",
- "definable",
- "var_without_namespaces",
- "var_with_namespaces",
- "var_method_modifiers",
- "namespaces",
- "var_method_modifier",
- "ns",
- "unary_expression",
- "binary_expression",
- "factor",
- "operator",
- "signed_number",
- "paren_expr",
- "sign",
- "numreg",
- "output",
- "input",
- "posreg",
- "position",
- "vreg",
- "argument",
- "timer",
- "ualm",
- "sreg",
- "sn",
- "hash",
- "hash_attributes",
- "hash_attribute",
- "hash_value",
- "array",
- "optional_sign",
- "array_values",
- "array_value" ]
-
-Racc_debug_parser = false
-
-##### State transition tables end #####
-
-# reduce 0 omitted
-
-module_eval(<<'.,.,', 'tp_plus.y', 35)
- def _reduce_1(val, _values, result)
- @interpreter.nodes = val[0]
- result
- end
-.,.,
-
-# reduce 2 omitted
-
-module_eval(<<'.,.,', 'tp_plus.y', 42)
- def _reduce_3(val, _values, result)
- result = [val[0]]
- result << val[1] unless val[1].nil?
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 46)
- def _reduce_4(val, _values, result)
- result = val[0] << val[1]
- result << val[2] unless val[2].nil?
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 52)
- def _reduce_5(val, _values, result)
- result = val[1]
- result
- end
-.,.,
-
-# reduce 6 omitted
-
-# reduce 7 omitted
-
-# reduce 8 omitted
-
-# reduce 9 omitted
-
-# reduce 10 omitted
-
-# reduce 11 omitted
-
-# reduce 12 omitted
-
-# reduce 13 omitted
-
-# reduce 14 omitted
-
-# reduce 15 omitted
-
-# reduce 16 omitted
-
-# reduce 17 omitted
-
-# reduce 18 omitted
-
-# reduce 19 omitted
-
-# reduce 20 omitted
-
-# reduce 21 omitted
-
-# reduce 22 omitted
-
-# reduce 23 omitted
-
-# reduce 24 omitted
-
-# reduce 25 omitted
-
-# reduce 26 omitted
-
-# reduce 27 omitted
-
-module_eval(<<'.,.,', 'tp_plus.y', 85)
- def _reduce_28(val, _values, result)
- result = PauseNode.new
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 86)
- def _reduce_29(val, _values, result)
- result = AbortNode.new
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 90)
- def _reduce_30(val, _values, result)
- result = EmptyStmtNode.new()
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 94)
- def _reduce_31(val, _values, result)
- result = HeaderNode.new(val[0],val[2])
- result
- end
-.,.,
-
-# reduce 32 omitted
-
-# reduce 33 omitted
-
-module_eval(<<'.,.,', 'tp_plus.y', 103)
- def _reduce_34(val, _values, result)
- result = RaiseNode.new(val[1])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 107)
- def _reduce_35(val, _values, result)
- result = TimerMethodNode.new(val[0],val[1])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 111)
- def _reduce_36(val, _values, result)
- result = EvalNode.new(val[1])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 116)
- def _reduce_37(val, _values, result)
- result = WaitForNode.new(val[2], val[4])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 118)
- def _reduce_38(val, _values, result)
- result = WaitUntilNode.new(val[2], nil)
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 120)
- def _reduce_39(val, _values, result)
- result = WaitUntilNode.new(val[2],val[5])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 122)
- def _reduce_40(val, _values, result)
- result = WaitUntilNode.new(val[2],val[5].merge(val[7]))
- result
- end
-.,.,
-
-# reduce 41 omitted
-
-# reduce 42 omitted
-
-module_eval(<<'.,.,', 'tp_plus.y', 132)
- def _reduce_43(val, _values, result)
- result = { label: val[3] }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 137)
- def _reduce_44(val, _values, result)
- result = { timeout: [val[3],val[5]] }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 141)
- def _reduce_45(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 145)
- def _reduce_46(val, _values, result)
- result = UseNode.new(val[0],val[1])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 150)
- def _reduce_47(val, _values, result)
- result = SetSkipNode.new(val[1])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 154)
- def _reduce_48(val, _values, result)
- result = CallNode.new(val[0],val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 155)
- def _reduce_49(val, _values, result)
- result = CallNode.new(val[1],val[3],async: true)
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 159)
- def _reduce_50(val, _values, result)
- result = [val[0]]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 160)
- def _reduce_51(val, _values, result)
- result = val[0] << val[2]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 161)
- def _reduce_52(val, _values, result)
- result = []
- result
- end
-.,.,
-
-# reduce 53 omitted
-
-# reduce 54 omitted
-
-# reduce 55 omitted
-
-# reduce 56 omitted
-
-module_eval(<<'.,.,', 'tp_plus.y', 172)
- def _reduce_57(val, _values, result)
- result = StringNode.new(val[0])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 176)
- def _reduce_58(val, _values, result)
- result = IOMethodNode.new(val[0],val[1])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 178)
- def _reduce_59(val, _values, result)
- result = IOMethodNode.new(val[0],val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 180)
- def _reduce_60(val, _values, result)
- result = IOMethodNode.new(val[0],val[2],{ pulse_time: val[4], pulse_units: val[6] })
- result
- end
-.,.,
-
-# reduce 61 omitted
-
-# reduce 62 omitted
-
-module_eval(<<'.,.,', 'tp_plus.y', 190)
- def _reduce_63(val, _values, result)
- result = JumpNode.new(val[1])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 195)
- def _reduce_64(val, _values, result)
- result = ConditionalNode.new("if",val[1],val[2],val[3])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 197)
- def _reduce_65(val, _values, result)
- result = ConditionalNode.new("unless",val[1],val[2],val[3])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 202)
- def _reduce_66(val, _values, result)
- result = ForNode.new(val[1],val[4],val[6],val[8])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 206)
- def _reduce_67(val, _values, result)
- result = WhileNode.new(val[1],val[2])
- result
- end
-.,.,
-
-# reduce 68 omitted
-
-# reduce 69 omitted
-
-module_eval(<<'.,.,', 'tp_plus.y', 215)
- def _reduce_70(val, _values, result)
- result = NamespaceNode.new(val[1],val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 222)
- def _reduce_71(val, _values, result)
- result = CaseNode.new(val[1],val[3],val[4])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 226)
- def _reduce_72(val, _values, result)
- result = val
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 228)
- def _reduce_73(val, _values, result)
- result = val[0] << val[1] << val[2]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 233)
- def _reduce_74(val, _values, result)
- result = CaseConditionNode.new(val[1],val[3])
- result
- end
-.,.,
-
-# reduce 75 omitted
-
-# reduce 76 omitted
-
-module_eval(<<'.,.,', 'tp_plus.y', 243)
- def _reduce_77(val, _values, result)
- result = CaseConditionNode.new(nil,val[2])
- result
- end
-.,.,
-
-# reduce 78 omitted
-
-# reduce 79 omitted
-
-# reduce 80 omitted
-
-# reduce 81 omitted
-
-module_eval(<<'.,.,', 'tp_plus.y', 254)
- def _reduce_82(val, _values, result)
- result = InlineConditionalNode.new(val[1], val[2], val[0])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 255)
- def _reduce_83(val, _values, result)
- result = InlineConditionalNode.new(val[1], val[2], val[0])
- result
- end
-.,.,
-
-# reduce 84 omitted
-
-# reduce 85 omitted
-
-# reduce 86 omitted
-
-# reduce 87 omitted
-
-module_eval(<<'.,.,', 'tp_plus.y', 266)
- def _reduce_88(val, _values, result)
- result = val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 267)
- def _reduce_89(val, _values, result)
- result = []
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 272)
- def _reduce_90(val, _values, result)
- result = MotionNode.new(val[0],val[5],val[7])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 276)
- def _reduce_91(val, _values, result)
- result = val
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 278)
- def _reduce_92(val, _values, result)
- result = val[0] << val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 283)
- def _reduce_93(val, _values, result)
- result = SpeedNode.new(val[4])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 285)
- def _reduce_94(val, _values, result)
- result = TerminationNode.new(val[4])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 287)
- def _reduce_95(val, _values, result)
- result = OffsetNode.new(val[2],val[4])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 289)
- def _reduce_96(val, _values, result)
- result = TimeNode.new(val[2],val[4],val[6])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 291)
- def _reduce_97(val, _values, result)
- result = SkipNode.new(val[4],val[5])
- result
- end
-.,.,
-
-# reduce 98 omitted
-
-# reduce 99 omitted
-
-module_eval(<<'.,.,', 'tp_plus.y', 298)
- def _reduce_100(val, _values, result)
- raise Racc::ParseError, sprintf("\ninvalid termination type: (%s)", val[1]) if val[1] != 1
-
- result = DigitNode.new(val[1].to_i * -1)
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 305)
- def _reduce_101(val, _values, result)
- result = val[1]
- result
- end
-.,.,
-
-# reduce 102 omitted
-
-# reduce 103 omitted
-
-# reduce 104 omitted
-
-# reduce 105 omitted
-
-# reduce 106 omitted
-
-# reduce 107 omitted
-
-# reduce 108 omitted
-
-module_eval(<<'.,.,', 'tp_plus.y', 325)
- def _reduce_109(val, _values, result)
- result = { speed: val[0], units: val[2] }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 326)
- def _reduce_110(val, _values, result)
- result = { speed: val[0], units: nil }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 330)
- def _reduce_111(val, _values, result)
- result = LabelDefinitionNode.new(val[0])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 334)
- def _reduce_112(val, _values, result)
- result = DefinitionNode.new(val[0],val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 338)
- def _reduce_113(val, _values, result)
- result = AssignmentNode.new(val[0],val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 339)
- def _reduce_114(val, _values, result)
- result = AssignmentNode.new(
- val[0],
- ExpressionNode.new(val[0],"+",val[3])
- )
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 344)
- def _reduce_115(val, _values, result)
- result = AssignmentNode.new(
- val[0],
- ExpressionNode.new(val[0],"-",val[3])
- )
-
- result
- end
-.,.,
-
-# reduce 116 omitted
-
-# reduce 117 omitted
-
-module_eval(<<'.,.,', 'tp_plus.y', 357)
- def _reduce_118(val, _values, result)
- result = VarNode.new(val[0])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 358)
- def _reduce_119(val, _values, result)
- result = VarMethodNode.new(val[0],val[1])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 363)
- def _reduce_120(val, _values, result)
- result = NamespacedVarNode.new(val[0],val[1])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 367)
- def _reduce_121(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 369)
- def _reduce_122(val, _values, result)
- result = val[0].merge(val[1])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 373)
- def _reduce_123(val, _values, result)
- result = { method: val[2] }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 375)
- def _reduce_124(val, _values, result)
- result = { group: val[4] }
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 379)
- def _reduce_125(val, _values, result)
- result = [val[0]]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 380)
- def _reduce_126(val, _values, result)
- result = val[0] << val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 384)
- def _reduce_127(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-# reduce 128 omitted
-
-# reduce 129 omitted
-
-module_eval(<<'.,.,', 'tp_plus.y', 394)
- def _reduce_130(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-# reduce 131 omitted
-
-module_eval(<<'.,.,', 'tp_plus.y', 396)
- def _reduce_132(val, _values, result)
- result = ExpressionNode.new(val[1], "!", nil)
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 401)
- def _reduce_133(val, _values, result)
- result = ExpressionNode.new(val[0], val[1], val[2])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 405)
- def _reduce_134(val, _values, result)
- result = "=="
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 406)
- def _reduce_135(val, _values, result)
- result = "<>"
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 407)
- def _reduce_136(val, _values, result)
- result = "<"
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 408)
- def _reduce_137(val, _values, result)
- result = ">"
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 409)
- def _reduce_138(val, _values, result)
- result = ">="
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 410)
- def _reduce_139(val, _values, result)
- result = "<="
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 411)
- def _reduce_140(val, _values, result)
- result = "+"
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 412)
- def _reduce_141(val, _values, result)
- result = "-"
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 413)
- def _reduce_142(val, _values, result)
- result = "||"
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 414)
- def _reduce_143(val, _values, result)
- result = "*"
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 415)
- def _reduce_144(val, _values, result)
- result = "/"
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 416)
- def _reduce_145(val, _values, result)
- result = "DIV"
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 417)
- def _reduce_146(val, _values, result)
- result = "%"
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 418)
- def _reduce_147(val, _values, result)
- result = "&&"
- result
- end
-.,.,
-
-# reduce 148 omitted
-
-# reduce 149 omitted
-
-# reduce 150 omitted
-
-# reduce 151 omitted
-
-# reduce 152 omitted
-
-module_eval(<<'.,.,', 'tp_plus.y', 430)
- def _reduce_153(val, _values, result)
- result = ParenExpressionNode.new(val[1])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 435)
- def _reduce_154(val, _values, result)
- result = IndirectNode.new(val[2].to_sym, val[4])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 440)
- def _reduce_155(val, _values, result)
- val[1] = val[1].to_i * -1 if val[0] == "-"
- result = DigitNode.new(val[1])
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 443)
- def _reduce_156(val, _values, result)
- val[1] = val[1].to_f * -1 if val[0] == "-"; result = RealNode.new(val[1])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 447)
- def _reduce_157(val, _values, result)
- result = "-"
- result
- end
-.,.,
-
-# reduce 158 omitted
-
-module_eval(<<'.,.,', 'tp_plus.y', 452)
- def _reduce_159(val, _values, result)
- result = RealNode.new(val[0])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 456)
- def _reduce_160(val, _values, result)
- result = DigitNode.new(val[0])
- result
- end
-.,.,
-
-# reduce 161 omitted
-
-# reduce 162 omitted
-
-# reduce 163 omitted
-
-# reduce 164 omitted
-
-# reduce 165 omitted
-
-# reduce 166 omitted
-
-# reduce 167 omitted
-
-# reduce 168 omitted
-
-# reduce 169 omitted
-
-# reduce 170 omitted
-
-# reduce 171 omitted
-
-# reduce 172 omitted
-
-module_eval(<<'.,.,', 'tp_plus.y', 476)
- def _reduce_173(val, _values, result)
- result = StringRegisterNode.new(val[2].to_i)
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 480)
- def _reduce_174(val, _values, result)
- result = UserAlarmNode.new(val[2].to_i)
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 484)
- def _reduce_175(val, _values, result)
- result = TimerNode.new(val[2].to_i)
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 488)
- def _reduce_176(val, _values, result)
- result = ArgumentNode.new(val[2].to_i)
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 492)
- def _reduce_177(val, _values, result)
- result = VisionRegisterNode.new(val[2].to_i)
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 496)
- def _reduce_178(val, _values, result)
- result = PositionNode.new(val[2].to_i)
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 500)
- def _reduce_179(val, _values, result)
- result = NumregNode.new(val[2].to_i)
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 504)
- def _reduce_180(val, _values, result)
- result = PosregNode.new(val[2].to_i)
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 508)
- def _reduce_181(val, _values, result)
- result = IONode.new(val[0], val[2].to_i)
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 512)
- def _reduce_182(val, _values, result)
- result = IONode.new(val[0], val[2].to_i)
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 516)
- def _reduce_183(val, _values, result)
- result = AddressNode.new(val[0])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 520)
- def _reduce_184(val, _values, result)
- result = CommentNode.new(val[0])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 524)
- def _reduce_185(val, _values, result)
- result = TerminatorNode.new
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 525)
- def _reduce_186(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-# reduce 187 omitted
-
-# reduce 188 omitted
-
-module_eval(<<'.,.,', 'tp_plus.y', 532)
- def _reduce_189(val, _values, result)
- result = TerminatorNode.new
- result
- end
-.,.,
-
-# reduce 190 omitted
-
-module_eval(<<'.,.,', 'tp_plus.y', 538)
- def _reduce_191(val, _values, result)
- result = PositionDataNode.new(val[2])
- result
- end
-.,.,
-
-# reduce 192 omitted
-
-module_eval(<<'.,.,', 'tp_plus.y', 546)
- def _reduce_193(val, _values, result)
- result = val[2]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 547)
- def _reduce_194(val, _values, result)
- result = {}
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 551)
- def _reduce_195(val, _values, result)
- result = val[0]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 553)
- def _reduce_196(val, _values, result)
- result = val[0].merge(val[3])
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 557)
- def _reduce_197(val, _values, result)
- result = { val[0].to_sym => val[2] }
- result
- end
-.,.,
-
-# reduce 198 omitted
-
-# reduce 199 omitted
-
-# reduce 200 omitted
-
-module_eval(<<'.,.,', 'tp_plus.y', 564)
- def _reduce_201(val, _values, result)
- val[1] = val[1].to_i * -1 if val[0] == "-"; result = val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 565)
- def _reduce_202(val, _values, result)
- val[1] = val[1].to_f * -1 if val[0] == "-"; result = val[1]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 566)
- def _reduce_203(val, _values, result)
- result = val[0] == "true"
- result
- end
-.,.,
-
-# reduce 204 omitted
-
-# reduce 205 omitted
-
-module_eval(<<'.,.,', 'tp_plus.y', 575)
- def _reduce_206(val, _values, result)
- result = val[2]
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 579)
- def _reduce_207(val, _values, result)
- result = val
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'tp_plus.y', 580)
- def _reduce_208(val, _values, result)
- result = val[0] << val[3]
- result
- end
-.,.,
-
-# reduce 209 omitted
-
-def _reduce_none(val, _values, result)
- val[0]
-end
-
- end # class Parser
-end # module TPPlus
diff --git a/test/racc/regress/twowaysql b/test/racc/regress/twowaysql
deleted file mode 100644
index 219f1a8b04..0000000000
--- a/test/racc/regress/twowaysql
+++ /dev/null
@@ -1,556 +0,0 @@
-#
-# DO NOT MODIFY!!!!
-# This file is automatically generated by Racc 1.5.0
-# from Racc grammar file "".
-#
-
-require 'racc/parser.rb'
-module TwoWaySQL
- class Parser < Racc::Parser
-
-module_eval(<<'...end twowaysql.y/module_eval...', 'twowaysql.y', 148)
-
-require 'strscan'
-
-def initialize(opts={})
- opts = {
- :debug => false,
- :preserve_space => true,
- :preserve_comment => false
- }.merge(opts)
- @yydebug = opts[:debug]
- @preserve_space = opts[:preserve_space]
- @preserve_comment = opts[:preserve_comment]
- @num_questions = 0
-end
-
-
-PAREN_EXAMPLE = '\([^\)]+\)'
-BEGIN_BIND_VARIABLE = '(\/|\#)\*([^\*]+)\*\1'
-BIND_VARIABLE_PATTERN = /\A#{BEGIN_BIND_VARIABLE}\s*/
-PAREN_BIND_VARIABLE_PATTERN = /\A#{BEGIN_BIND_VARIABLE}\s*#{PAREN_EXAMPLE}/
-EMBED_VARIABLE_PATTERN = /\A(\/|\#)\*\$([^\*]+)\*\1\s*/
-
-CONDITIONAL_PATTERN = /\A(\/|\#)\*(IF)\s+([^\*]+)\s*\*\1/
-BEGIN_END_PATTERN = /\A(\/|\#)\*(BEGIN|END)\s*\*\1/
-STRING_LITERAL_PATTERN = /\A(\'(?:[^\']+|\'\')*\')/ ## quoted string
-SPLIT_TOKEN_PATTERN = /\A(\S+?)(?=\s*(?:(?:\/|\#)\*|-{2,}|\(|\)|\,))/ ## stop on delimiters --,/*,#*,',',(,)
-LITERAL_PATTERN = /\A([^;\s]+)/
-SPACES_PATTERN = /\A(\s+)/
-QUESTION_PATTERN = /\A\?/
-COMMA_PATTERN = /\A\,/
-LPAREN_PATTERN = /\A\(/
-RPAREN_PATTERN = /\A\)/
-ACTUAL_COMMENT_PATTERN = /\A(\/|\#)\*(\s{1,}(?:.*?))\*\1/m ## start with spaces
-SEMICOLON_AT_INPUT_END_PATTERN = /\A\;\s*\Z/
-UNMATCHED_COMMENT_START_PATTERN = /\A(?:(?:\/|\#)\*)/
-
-#TODO: remove trailing spaces for S2Dao compatibility, but this spec sometimes causes SQL bugs...
-ELSE_PATTERN = /\A\-{2,}\s*ELSE\s*/
-AND_PATTERN = /\A(\ *AND)\b/i
-OR_PATTERN = /\A(\ *OR)\b/i
-
-
-def parse( io )
- @q = []
- io.each_line(nil) do |whole|
- @s = StringScanner.new(whole)
- end
- scan_str
-
- # @q.push [ false, nil ]
- @q.push [ false, [@s.pos, nil] ]
-
- ## call racc's private parse method
- do_parse
-end
-
-
-## called by racc
-def next_token
- @q.shift
-end
-
-
-def scan_str
- until @s.eos? do
- case
- when @s.scan(AND_PATTERN)
- @q.push [ :AND, [@s.pos, @s[1]] ]
- when @s.scan(OR_PATTERN)
- @q.push [ :OR, [@s.pos, @s[1]] ]
- when @s.scan(SPACES_PATTERN)
- @q.push [ :SPACES, [@s.pos, @s[1]] ]
- when @s.scan(QUESTION_PATTERN)
- @q.push [ :QUESTION, [@s.pos, nil] ]
- when @s.scan(COMMA_PATTERN)
- @q.push [ :COMMA, [@s.pos, ','] ]
- when @s.scan(LPAREN_PATTERN)
- @q.push [ :LPAREN, [@s.pos, '('] ]
- when @s.scan(RPAREN_PATTERN)
- @q.push [ :RPAREN, [@s.pos, ')'] ]
- when @s.scan(ELSE_PATTERN)
- @q.push [ :ELSE, [@s.pos, nil] ]
- when @s.scan(ACTUAL_COMMENT_PATTERN)
- @q.push [ :ACTUAL_COMMENT, [@s.pos, @s[1], @s[2]] ] if @preserve_comment
- when @s.scan(BEGIN_END_PATTERN)
- @q.push [ @s[2].intern, [@s.pos, nil] ]
- when @s.scan(CONDITIONAL_PATTERN)
- @q.push [ @s[2].intern, [@s.pos, @s[3]] ]
- when @s.scan(EMBED_VARIABLE_PATTERN)
- @q.push [ :EMBED_VARIABLE, [@s.pos, @s[2]] ]
- when @s.scan(PAREN_BIND_VARIABLE_PATTERN)
- @q.push [ :PAREN_BIND_VARIABLE, [@s.pos, @s[2]] ]
- when @s.scan(BIND_VARIABLE_PATTERN)
- @q.push [ :BIND_VARIABLE, [@s.pos, @s[2]] ]
- when @s.scan(STRING_LITERAL_PATTERN)
- @q.push [ :STRING_LITERAL, [@s.pos, @s[1]] ]
- when @s.scan(SPLIT_TOKEN_PATTERN)
- @q.push [ :IDENT, [@s.pos, @s[1]] ]
- when @s.scan(UNMATCHED_COMMENT_START_PATTERN) ## unmatched comment start, '/*','#*'
- raise Racc::ParseError, "unmatched comment. line:[#{line_no(@s.pos)}], str:[#{@s.rest}]"
- when @s.scan(LITERAL_PATTERN) ## other string token
- @q.push [ :IDENT, [@s.pos, @s[1]] ]
- when @s.scan(SEMICOLON_AT_INPUT_END_PATTERN)
- #drop semicolon at input end
- else
- raise Racc::ParseError, "syntax error at or near line:[#{line_no(@s.pos)}], str:[#{@s.rest}]"
- end
- end
-end
-
-
-## override racc's default on_error method
-def on_error(t, v, vstack)
- ## cursor in value-stack is an array of two items,
- ## that have position value as 0th item. like [731, "ctx[:limit] "]
- cursor = vstack.find do |tokens|
- tokens.size == 2 and tokens[0].kind_of?(Fixnum)
- end
- pos = cursor[0]
- line = line_no(pos)
- rest = @s.string[pos .. -1]
- raise Racc::ParseError, "syntax error at or near line:[#{line}], str:[#{rest}]"
-end
-
-
-def line_no(pos)
- lines = 0
- scanned = @s.string[0..(pos)]
- scanned.each_line { lines += 1 }
- lines
-end
-...end twowaysql.y/module_eval...
-##### State transition tables begin ###
-
-racc_action_table = [
- 8, 36, 9, 37, 12, 13, 10, 11, 14, 15,
- 16, 17, 18, 19, 22, 23, 24, 8, 38, 9,
- 3, 12, 13, 10, 11, 14, 15, 16, 17, 18,
- 19, 22, 23, 24, 8, 25, 9, 40, 12, 13,
- 10, 11, 14, 15, 16, 17, 18, 19, 22, 23,
- 24, 8, 45, 9, 46, 12, 13, 10, 11, 14,
- 15, 16, 17, 18, 19, 22, 23, 24, 8, nil,
- 9, nil, 12, 13, 10, 11, 14, 15, 16, 17,
- 18, 19, 22, 23, 24, 35, 33, 34, 31, 32,
- 44, 43, 31, 32 ]
-
-racc_action_check = [
- 2, 24, 2, 24, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 26, 26, 26,
- 1, 26, 26, 26, 26, 26, 26, 26, 26, 26,
- 26, 26, 26, 26, 27, 3, 27, 28, 27, 27,
- 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
- 27, 41, 37, 41, 39, 41, 41, 41, 41, 41,
- 41, 41, 41, 41, 41, 41, 41, 41, 42, nil,
- 42, nil, 42, 42, 42, 42, 42, 42, 42, 42,
- 42, 42, 42, 42, 42, 22, 22, 22, 9, 9,
- 34, 34, 40, 40 ]
-
-racc_action_pointer = [
- nil, 20, -2, 35, nil, nil, nil, nil, nil, 82,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, 77, nil, -7, nil, 15, 32, 32, nil,
- nil, nil, nil, nil, 82, nil, nil, 44, nil, 51,
- 86, 49, 66, nil, nil, nil, nil, nil ]
-
-racc_action_default = [
- -2, -35, -1, -35, -3, -4, -5, -6, -2, -2,
- -16, -17, -18, -19, -20, -21, -22, -23, -24, -25,
- -26, -27, -35, -32, -35, 48, -35, -13, -10, -11,
- -12, -2, -2, -28, -35, -30, -33, -35, -7, -35,
- -2, -14, -15, -29, -31, -34, -8, -9 ]
-
-racc_goto_table = [
- 2, 1, 28, 39, nil, nil, nil, nil, 26, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 41, 42, 47 ]
-
-racc_goto_check = [
- 2, 1, 7, 8, nil, nil, nil, nil, 2, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
- nil, 2, 2, 7 ]
-
-racc_goto_pointer = [
- nil, 1, 0, nil, nil, nil, nil, -7, -25, nil,
- nil, nil, nil ]
-
-racc_goto_default = [
- nil, nil, 27, 4, 5, 6, 7, nil, nil, 29,
- 30, 20, 21 ]
-
-racc_reduce_table = [
- 0, 0, :racc_error,
- 1, 20, :_reduce_1,
- 0, 21, :_reduce_2,
- 2, 21, :_reduce_3,
- 1, 22, :_reduce_none,
- 1, 22, :_reduce_none,
- 1, 22, :_reduce_none,
- 3, 25, :_reduce_7,
- 4, 24, :_reduce_8,
- 2, 27, :_reduce_9,
- 0, 27, :_reduce_10,
- 1, 26, :_reduce_none,
- 1, 26, :_reduce_none,
- 1, 26, :_reduce_none,
- 2, 28, :_reduce_14,
- 2, 29, :_reduce_15,
- 1, 23, :_reduce_16,
- 1, 23, :_reduce_17,
- 1, 23, :_reduce_18,
- 1, 23, :_reduce_19,
- 1, 23, :_reduce_20,
- 1, 23, :_reduce_21,
- 1, 23, :_reduce_22,
- 1, 23, :_reduce_23,
- 1, 23, :_reduce_24,
- 1, 23, :_reduce_25,
- 1, 23, :_reduce_none,
- 1, 23, :_reduce_none,
- 2, 30, :_reduce_28,
- 3, 30, :_reduce_29,
- 2, 30, :_reduce_30,
- 3, 30, :_reduce_31,
- 1, 30, :_reduce_32,
- 2, 31, :_reduce_33,
- 3, 31, :_reduce_34 ]
-
-racc_reduce_n = 35
-
-racc_shift_n = 48
-
-racc_token_table = {
- false => 0,
- :error => 1,
- :BEGIN => 2,
- :END => 3,
- :IF => 4,
- :ELSE => 5,
- :AND => 6,
- :OR => 7,
- :IDENT => 8,
- :STRING_LITERAL => 9,
- :SPACES => 10,
- :COMMA => 11,
- :LPAREN => 12,
- :RPAREN => 13,
- :QUESTION => 14,
- :ACTUAL_COMMENT => 15,
- :BIND_VARIABLE => 16,
- :PAREN_BIND_VARIABLE => 17,
- :EMBED_VARIABLE => 18 }
-
-racc_nt_base = 19
-
-racc_use_result_var = true
-
-Racc_arg = [
- racc_action_table,
- racc_action_check,
- racc_action_default,
- racc_action_pointer,
- racc_goto_table,
- racc_goto_check,
- racc_goto_default,
- racc_goto_pointer,
- racc_nt_base,
- racc_reduce_table,
- racc_token_table,
- racc_shift_n,
- racc_reduce_n,
- racc_use_result_var ]
-
-Racc_token_to_s_table = [
- "$end",
- "error",
- "BEGIN",
- "END",
- "IF",
- "ELSE",
- "AND",
- "OR",
- "IDENT",
- "STRING_LITERAL",
- "SPACES",
- "COMMA",
- "LPAREN",
- "RPAREN",
- "QUESTION",
- "ACTUAL_COMMENT",
- "BIND_VARIABLE",
- "PAREN_BIND_VARIABLE",
- "EMBED_VARIABLE",
- "$start",
- "sql",
- "stmt_list",
- "stmt",
- "primary",
- "if_stmt",
- "begin_stmt",
- "sub_stmt",
- "else_stmt",
- "and_stmt",
- "or_stmt",
- "bind_var",
- "embed_var" ]
-
-Racc_debug_parser = false
-
-##### State transition tables end #####
-
-# reduce 0 omitted
-
-module_eval(<<'.,.,', 'twowaysql.y', 20)
- def _reduce_1(val, _values, result)
- result = RootNode.new( val[0] )
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'twowaysql.y', 25)
- def _reduce_2(val, _values, result)
- result = []
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'twowaysql.y', 29)
- def _reduce_3(val, _values, result)
- result.push val[1]
-
- result
- end
-.,.,
-
-# reduce 4 omitted
-
-# reduce 5 omitted
-
-# reduce 6 omitted
-
-module_eval(<<'.,.,', 'twowaysql.y', 38)
- def _reduce_7(val, _values, result)
- result = BeginNode.new( val[1] )
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'twowaysql.y', 43)
- def _reduce_8(val, _values, result)
- result = IfNode.new( val[0][1], val[1], val[2] )
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'twowaysql.y', 48)
- def _reduce_9(val, _values, result)
- result = val[1]
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'twowaysql.y', 52)
- def _reduce_10(val, _values, result)
- result = nil
-
- result
- end
-.,.,
-
-# reduce 11 omitted
-
-# reduce 12 omitted
-
-# reduce 13 omitted
-
-module_eval(<<'.,.,', 'twowaysql.y', 61)
- def _reduce_14(val, _values, result)
- result = SubStatementNode.new( val[0][1], val[1] )
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'twowaysql.y', 66)
- def _reduce_15(val, _values, result)
- result = SubStatementNode.new( val[0][1], val[1] )
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'twowaysql.y', 71)
- def _reduce_16(val, _values, result)
- result = LiteralNode.new( val[0][1] )
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'twowaysql.y', 75)
- def _reduce_17(val, _values, result)
- result = LiteralNode.new( val[0][1] )
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'twowaysql.y', 79)
- def _reduce_18(val, _values, result)
- result = LiteralNode.new( val[0][1] )
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'twowaysql.y', 83)
- def _reduce_19(val, _values, result)
- result = LiteralNode.new( val[0][1] )
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'twowaysql.y', 87)
- def _reduce_20(val, _values, result)
- result = WhiteSpaceNode.new( val[0][1], @preserve_space )
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'twowaysql.y', 91)
- def _reduce_21(val, _values, result)
- result = LiteralNode.new( val[0][1] )
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'twowaysql.y', 95)
- def _reduce_22(val, _values, result)
- result = LiteralNode.new( val[0][1] )
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'twowaysql.y', 99)
- def _reduce_23(val, _values, result)
- result = LiteralNode.new( val[0][1] )
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'twowaysql.y', 103)
- def _reduce_24(val, _values, result)
- @num_questions += 1
- result = QuestionNode.new( @num_questions )
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'twowaysql.y', 108)
- def _reduce_25(val, _values, result)
- result = ActualCommentNode.new( val[0][1] , val[0][2] )
-
- result
- end
-.,.,
-
-# reduce 26 omitted
-
-# reduce 27 omitted
-
-module_eval(<<'.,.,', 'twowaysql.y', 115)
- def _reduce_28(val, _values, result)
- result = BindVariableNode.new( val[0][1] )
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'twowaysql.y', 119)
- def _reduce_29(val, _values, result)
- result = BindVariableNode.new( val[0][1] )
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'twowaysql.y', 123)
- def _reduce_30(val, _values, result)
- result = BindVariableNode.new( val[0][1] )
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'twowaysql.y', 127)
- def _reduce_31(val, _values, result)
- result = BindVariableNode.new( val[0][1] )
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'twowaysql.y', 131)
- def _reduce_32(val, _values, result)
- result = ParenBindVariableNode.new( val[0][1] )
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'twowaysql.y', 136)
- def _reduce_33(val, _values, result)
- result = EmbedVariableNode.new( val[0][1] )
-
- result
- end
-.,.,
-
-module_eval(<<'.,.,', 'twowaysql.y', 140)
- def _reduce_34(val, _values, result)
- result = EmbedVariableNode.new( val[0][1] )
-
- result
- end
-.,.,
-
-def _reduce_none(val, _values, result)
- val[0]
-end
-
- end # class Parser
-end # module TwoWaySQL
diff --git a/test/racc/scandata/brace b/test/racc/scandata/brace
deleted file mode 100644
index f6c843853e..0000000000
--- a/test/racc/scandata/brace
+++ /dev/null
@@ -1,7 +0,0 @@
-{ {
- } { } {
- { { { } } }
- { { { {} } } }
- {} {} {}
- }
-}
diff --git a/test/racc/scandata/gvar b/test/racc/scandata/gvar
deleted file mode 100644
index 50528ce97b..0000000000
--- a/test/racc/scandata/gvar
+++ /dev/null
@@ -1 +0,0 @@
-{ $' $" $& $-a $/ $\ $( $1 $2 $3 $? $-i }
diff --git a/test/racc/scandata/normal b/test/racc/scandata/normal
deleted file mode 100644
index e705131536..0000000000
--- a/test/racc/scandata/normal
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- # comment
- result = "string".match(/regexp/)[0]
-}
diff --git a/test/racc/scandata/percent b/test/racc/scandata/percent
deleted file mode 100644
index fded9a385c..0000000000
--- a/test/racc/scandata/percent
+++ /dev/null
@@ -1,18 +0,0 @@
-{
- 3 % 5 # mod
- 3%5 # mod
- 3% 5 # mod
- i % 5 # mod
- i%5 # mod
- i% 5 # mod
- call %{str} # string
- call(%{str}) # string
- %q{string} # string
- %Q{string} # string
- %r{string} # string
- %w(array) # array
- %x{array} # command string
- %{string} # string
- %_string_ # string
- %/string/ # regexp
-}
diff --git a/test/racc/scandata/slash b/test/racc/scandata/slash
deleted file mode 100644
index 190135b3bd..0000000000
--- a/test/racc/scandata/slash
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- # here's many '/'s
- i = 5/1 # div
- re = /regex/ # regexp
- i /= 5 # div
- result = 5 / 1 # div
- result = 5/ 1 # div
- call(/regex/) # regexp
- call /regex/ # regexp
-}
diff --git a/test/racc/src.intp b/test/racc/src.intp
deleted file mode 100644
index 4d2460e8ed..0000000000
--- a/test/racc/src.intp
+++ /dev/null
@@ -1,34 +0,0 @@
-def assert( no, cond )
- if cond then
- else
- raise( 'assert ' + to_s(no) + ' failed' )
- end
-end
-
-assert( 1, concat(concat(concat('str=', 'a'), "b"), 'c') == 'str=abc' )
-assert( 2, 'operator' + ' ok' == 'operator ok' )
-assert( 3, 1 + 1 == 2 )
-assert( 4, 4 * 1 + 10 * 1 == 14 )
-
-if true then
- assert( 5, true )
-else
- assert( 6, false )
-end
-
-i = 1
-while i == 1 do
- i = false
-end
-assert( 7, i == false )
-assert( 8, nil == nil )
-
-def func
- assert( 9, true )
-end
-func
-
-def argfunc( str )
- assert( 10, str == 'ok' )
-end
-argfunc 'ok'
diff --git a/test/racc/start.y b/test/racc/start.y
deleted file mode 100644
index 86296899b8..0000000000
--- a/test/racc/start.y
+++ /dev/null
@@ -1,20 +0,0 @@
-class S
-
-start st
-
-rule
-
-n: D { result = 'no' }
-st : A B C n { result = 'ok' }
-
-end
-
----- inner
-
- def parse
- do_parse
- end
-
----- footer
-
-S.new.parse == 'ok' or raise 'start stmt not worked'
diff --git a/test/racc/test_chk_y.rb b/test/racc/test_chk_y.rb
deleted file mode 100644
index 883737c45f..0000000000
--- a/test/racc/test_chk_y.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-require File.expand_path(File.join(__dir__, 'case'))
-
-module Racc
- class TestChkY < TestCase
- def setup
- super
- file = File.join(ASSET_DIR, 'chk.y')
- @debug_flags = Racc::DebugFlags.parse_option_string('o')
- parser = Racc::GrammarFileParser.new(@debug_flags)
- @result = parser.parse(File.read(file), File.basename(file))
- @states = Racc::States.new(@result.grammar).nfa
- @states.dfa
- end
-
- def test_compile_chk_y
- generator = Racc::ParserFileGenerator.new(@states, @result.params.dup)
-
- # it generates valid ruby
- assert Module.new {
- self.instance_eval(generator.generate_parser, __FILE__, __LINE__)
- }
-
- grammar = @states.grammar
-
- assert_equal 0, @states.n_srconflicts
- assert_equal 0, @states.n_rrconflicts
- assert_equal 0, grammar.n_useless_nonterminals
- assert_equal 0, grammar.n_useless_rules
- assert_nil grammar.n_expected_srconflicts
- end
-
- def test_compile_chk_y_line_convert
- params = @result.params.dup
- params.convert_line_all = true
-
- generator = Racc::ParserFileGenerator.new(@states, @result.params.dup)
-
- # it generates valid ruby
- assert Module.new {
- self.instance_eval(generator.generate_parser, __FILE__, __LINE__)
- }
-
- grammar = @states.grammar
-
- assert_equal 0, @states.n_srconflicts
- assert_equal 0, @states.n_rrconflicts
- assert_equal 0, grammar.n_useless_nonterminals
- assert_equal 0, grammar.n_useless_rules
- assert_nil grammar.n_expected_srconflicts
- end
- end
-end
diff --git a/test/racc/test_grammar_file_parser.rb b/test/racc/test_grammar_file_parser.rb
deleted file mode 100644
index 8f6e090cb2..0000000000
--- a/test/racc/test_grammar_file_parser.rb
+++ /dev/null
@@ -1,15 +0,0 @@
-require File.expand_path(File.join(__dir__, 'case'))
-
-module Racc
- class TestGrammarFileParser < TestCase
- def test_parse
- file = File.join(ASSET_DIR, 'yyerr.y')
-
- debug_flags = Racc::DebugFlags.parse_option_string('o')
- assert debug_flags.status_logging
-
- parser = Racc::GrammarFileParser.new(debug_flags)
- parser.parse(File.read(file), File.basename(file))
- end
- end
-end
diff --git a/test/racc/test_racc_command.rb b/test/racc/test_racc_command.rb
deleted file mode 100644
index 5bfebf150b..0000000000
--- a/test/racc/test_racc_command.rb
+++ /dev/null
@@ -1,339 +0,0 @@
-require File.expand_path(File.join(__dir__, 'case'))
-
-module Racc
- class TestRaccCommand < TestCase
- def test_syntax_y
- assert_compile 'syntax.y', '-v'
- assert_debugfile 'syntax.y', [0,0,0,0,0]
- end
-
- def test_percent_y
- assert_compile 'percent.y'
- assert_debugfile 'percent.y', []
- assert_exec 'percent.y'
- end
-
- def test_scan_y
- assert_compile 'scan.y'
- assert_debugfile 'scan.y', []
- assert_exec 'scan.y'
- end
-
- def test_newsyn_y
- assert_compile 'newsyn.y'
- assert_debugfile 'newsyn.y', []
- end
-
- def test_normal_y
- assert_compile 'normal.y'
- assert_debugfile 'normal.y', []
-
- assert_compile 'normal.y', '-vg'
- assert_debugfile 'normal.y', []
- end
-
- def test_chk_y
- assert_compile 'chk.y', '-vg'
- assert_debugfile 'chk.y', []
- assert_exec 'chk.y'
-
- assert_compile 'chk.y', '--line-convert-all'
- assert_debugfile 'chk.y', []
- assert_exec 'chk.y'
- end
-
- def test_echk_y
- assert_compile 'echk.y', '-E'
- assert_debugfile 'echk.y', []
- assert_exec 'echk.y'
- end
-
- def test_err_y
- assert_compile 'err.y'
- assert_debugfile 'err.y', []
- assert_exec 'err.y'
- end
-
- def test_mailp_y
- assert_compile 'mailp.y'
- assert_debugfile 'mailp.y', []
- end
-
- def test_conf_y
- assert_compile 'conf.y', '-v'
- assert_debugfile 'conf.y', [4,1,1,2]
- end
-
- def test_rrconf_y
- assert_compile 'rrconf.y'
- assert_debugfile 'rrconf.y', [1,1,0,0]
- end
-
- def test_useless_y
- assert_compile 'useless.y'
- assert_debugfile 'useless.y', [0,0,1,2]
- end
-
- def test_opt_y
- assert_compile 'opt.y'
- assert_debugfile 'opt.y', []
- assert_exec 'opt.y'
- end
-
- def test_yyerr_y
- assert_compile 'yyerr.y'
- assert_debugfile 'yyerr.y', []
- assert_exec 'yyerr.y'
- end
-
- def test_recv_y
- assert_compile 'recv.y'
- assert_debugfile 'recv.y', [5,10,1,4]
- end
-
- def test_ichk_y
- assert_compile 'ichk.y'
- assert_debugfile 'ichk.y', []
- assert_exec 'ichk.y'
- end
-
- def test_intp_y
- assert_compile 'intp.y'
- assert_debugfile 'intp.y', []
- assert_exec 'intp.y'
- end
-
- def test_expect_y
- assert_compile 'expect.y'
- assert_debugfile 'expect.y', [1,0,0,0,1]
- end
-
- def test_nullbug1_y
- assert_compile 'nullbug1.y'
- assert_debugfile 'nullbug1.y', [0,0,0,0]
- end
-
- def test_nullbug2_y
- assert_compile 'nullbug2.y'
- assert_debugfile 'nullbug2.y', [0,0,0,0]
- end
-
- def test_firstline_y
- assert_compile 'firstline.y'
- assert_debugfile 'firstline.y', []
- end
-
- def test_nonass_y
- assert_compile 'nonass.y'
- assert_debugfile 'nonass.y', []
- assert_exec 'nonass.y'
- end
-
- def test_digraph_y
- assert_compile 'digraph.y'
- assert_debugfile 'digraph.y', []
- assert_exec 'digraph.y'
- end
-
- def test_noend_y
- assert_compile 'noend.y'
- assert_debugfile 'noend.y', []
- end
-
- def test_norule_y
- assert_raise(Test::Unit::AssertionFailedError) {
- assert_compile 'norule.y'
- }
- end
-
- def test_unterm_y
- assert_raise(Test::Unit::AssertionFailedError) {
- assert_compile 'unterm.y'
- }
- end
-
- # Regression test for a problem where error recovery at EOF would cause
- # a Racc-generated parser to go into an infinite loop (on some grammars)
- def test_error_recovery_y
- assert_compile 'error_recovery.y'
- Timeout.timeout(10) do
- assert_exec 'error_recovery.y'
- end
- end
-
- # .y files from `parser` gem
-
- def test_ruby18
- assert_compile 'ruby18.y', [], timeout: 60
- assert_debugfile 'ruby18.y', []
- assert_output_unchanged 'ruby18.y'
- end
-
- def test_ruby22
- assert_compile 'ruby22.y', [], timeout: 60
- assert_debugfile 'ruby22.y', []
- assert_output_unchanged 'ruby22.y'
- end
-
- # .y file from csspool gem
-
- def test_csspool
- assert_compile 'csspool.y'
- assert_debugfile 'csspool.y', [5, 3]
- assert_output_unchanged 'csspool.y'
- end
-
- # .y file from opal gem
-
- def test_opal
- assert_compile 'opal.y', [], timeout: 60
- assert_debugfile 'opal.y', []
- assert_output_unchanged 'opal.y'
- end
-
- # .y file from journey gem
-
- def test_journey
- assert_compile 'journey.y'
- assert_debugfile 'journey.y', []
- assert_output_unchanged 'journey.y'
- end
-
- # .y file from nokogiri gem
-
- def test_nokogiri_css
- assert_compile 'nokogiri-css.y'
- assert_debugfile 'nokogiri-css.y', [0, 1]
- assert_output_unchanged 'nokogiri-css.y'
- end
-
- # .y file from edtf-ruby gem
-
- def test_edtf
- assert_compile 'edtf.y'
- assert_debugfile 'edtf.y', [0, 0, 0, 0, 0]
- assert_output_unchanged 'edtf.y'
- end
-
- # .y file from namae gem
-
- def test_namae
- assert_compile 'namae.y'
- assert_debugfile 'namae.y', [0, 0, 0, 0, 0]
- assert_output_unchanged 'namae.y'
- end
-
- # .y file from liquor gem
-
- def test_liquor
- assert_compile 'liquor.y'
- assert_debugfile 'liquor.y', [0, 0, 0, 0, 15]
- assert_output_unchanged 'liquor.y'
- end
-
- # .y file from nasl gem
-
- def test_nasl
- assert_compile 'nasl.y'
- assert_debugfile 'nasl.y', [0, 0, 0, 0, 1]
- assert_output_unchanged 'nasl.y'
- end
-
- # .y file from riml gem
-
- def test_riml
- assert_compile 'riml.y'
- assert_debugfile 'riml.y', [289, 0, 0, 0]
- assert_output_unchanged 'riml.y'
- end
-
- # .y file from ruby-php-serialization gem
-
- def test_php_serialization
- assert_compile 'php_serialization.y'
- assert_debugfile 'php_serialization.y', [0, 0, 0, 0]
- assert_output_unchanged 'php_serialization.y'
- end
-
- # .y file from huia language implementation
-
- def test_huia
- assert_compile 'huia.y'
- assert_debugfile 'huia.y', [285, 0, 0, 0]
- assert_output_unchanged 'huia.y'
- end
-
- # .y file from cast gem
-
- def test_cast
- assert_compile 'cast.y'
- assert_debugfile 'cast.y', [0, 0, 0, 0, 1]
- assert_output_unchanged 'cast.y'
- end
-
- # .y file from cadenza gem
-
- def test_cadenza
- assert_compile 'cadenza.y'
- assert_debugfile 'cadenza.y', [0, 0, 0, 0, 37]
- assert_output_unchanged 'cadenza.y'
- end
-
- # .y file from mediacloth gem
-
- def test_mediacloth
- assert_compile 'mediacloth.y'
- assert_debugfile 'mediacloth.y', [0, 0, 0, 0]
- assert_output_unchanged 'mediacloth.y'
- end
-
- # .y file from twowaysql gem
-
- def test_twowaysql
- assert_compile 'twowaysql.y'
- assert_debugfile 'twowaysql.y', [4, 0, 0, 0]
- assert_output_unchanged 'twowaysql.y'
- end
-
- # .y file from machete gem
-
- def test_machete
- assert_compile 'machete.y'
- assert_debugfile 'machete.y', [0, 0, 0, 0]
- assert_output_unchanged 'machete.y'
- end
-
- # .y file from mof gem
-
- def test_mof
- assert_compile 'mof.y'
- assert_debugfile 'mof.y', [7, 4, 0, 0]
- assert_output_unchanged 'mof.y'
- end
-
- # .y file from tp_plus gem
-
- def test_tp_plus
- assert_compile 'tp_plus.y'
- assert_debugfile 'tp_plus.y', [21, 0, 0, 0]
- assert_output_unchanged 'tp_plus.y'
- end
-
- def test_ifelse
- omit if RUBY_PLATFORM =~ /java/
-
- stderr = nil
- racc "-o#{@TAB_DIR}/ifelse", "#{ASSET_DIR}/ifelse.y", stdout_filter: ->(s) { stderr = s }
- stderr = stderr.lines[1..-1].join if RUBY_PLATFORM.match?(/java/)
- assert_equal(<<~STDERR, stderr)
- 1 useless nonterminals:
- dummy
- 2 useless rules:
- #4 (dummy)
- #5 (dummy)
- 1 shift/reduce conflicts
- Turn on logging with "-v" and check ".output" file for details
- STDERR
- end
- end
-end
diff --git a/test/racc/test_scan_y.rb b/test/racc/test_scan_y.rb
deleted file mode 100644
index fcd7e53c99..0000000000
--- a/test/racc/test_scan_y.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-require File.expand_path(File.join(__dir__, 'case'))
-
-module Racc
- class TestScanY < TestCase
- def setup
- super
- file = File.join(ASSET_DIR, 'scan.y')
- @debug_flags = Racc::DebugFlags.parse_option_string('o')
- parser = Racc::GrammarFileParser.new(@debug_flags)
- @result = parser.parse(File.read(file), File.basename(file))
- @states = Racc::States.new(@result.grammar).nfa
- @states.dfa
- end
-
- def test_compile
- generator = Racc::ParserFileGenerator.new(@states, @result.params.dup)
-
- # it generates valid ruby
- assert Module.new {
- self.class_eval(generator.generate_parser)
- }
-
- grammar = @states.grammar
-
- assert_equal 0, @states.n_srconflicts
- assert_equal 0, @states.n_rrconflicts
- assert_equal 0, grammar.n_useless_nonterminals
- assert_equal 0, grammar.n_useless_rules
- assert_nil grammar.n_expected_srconflicts
- end
-
- def test_compile_line_convert
- params = @result.params.dup
- params.convert_line_all = true
-
- generator = Racc::ParserFileGenerator.new(@states, @result.params.dup)
-
- # it generates valid ruby
- assert Module.new {
- self.class_eval(generator.generate_parser)
- }
-
- grammar = @states.grammar
-
- assert_equal 0, @states.n_srconflicts
- assert_equal 0, @states.n_rrconflicts
- assert_equal 0, grammar.n_useless_nonterminals
- assert_equal 0, grammar.n_useless_rules
- assert_nil grammar.n_expected_srconflicts
- end
- end
-end
diff --git a/test/racc/testscanner.rb b/test/racc/testscanner.rb
deleted file mode 100644
index d7877511ec..0000000000
--- a/test/racc/testscanner.rb
+++ /dev/null
@@ -1,51 +0,0 @@
-#
-# racc scanner tester
-#
-
-require 'racc/raccs'
-
-
-class ScanError < StandardError; end
-
-def testdata( dir, argv )
- if argv.empty? then
- Dir.glob( dir + '/*' ) -
- Dir.glob( dir + '/*.swp' ) -
- [ dir + '/CVS' ]
- else
- argv.collect {|i| dir + '/' + i }
- end
-end
-
-
-if ARGV.delete '--print' then
- $raccs_print_type = true
- printonly = true
-else
- printonly = false
-end
-
-testdata( File.dirname($0) + '/scandata', ARGV ).each do |file|
- $stderr.print File.basename(file) + ': '
- begin
- ok = File.read(file)
- s = Racc::GrammarFileScanner.new( ok )
- sym, (val, _lineno) = s.scan
- if printonly then
- $stderr.puts
- $stderr.puts val
- next
- end
-
- val = '{' + val + "}\n"
- sym == :ACTION or raise ScanError, 'is not action!'
- val == ok or raise ScanError, "\n>>>\n#{ok}----\n#{val}<<<"
-
- $stderr.puts 'ok'
- rescue => err
- $stderr.puts 'fail (' + err.type.to_s + ')'
- $stderr.puts err.message
- $stderr.puts err.backtrace
- $stderr.puts
- end
-end
diff --git a/test/rdoc/MarkdownTest_1.0.3/Markdown Documentation - Syntax.text b/test/rdoc/MarkdownTest_1.0.3/Markdown Documentation - Syntax.text
index 184018a5ac..2fe1e3f00e 100644
--- a/test/rdoc/MarkdownTest_1.0.3/Markdown Documentation - Syntax.text
+++ b/test/rdoc/MarkdownTest_1.0.3/Markdown Documentation - Syntax.text
@@ -608,7 +608,7 @@ or tabs for padding, which tends to look better with longer URLs:
Link definitions are only used for creating links during Markdown
processing, and are stripped from your document in the HTML output.
-Link definition names may constist of letters, numbers, spaces, and punctuation -- but they are *not* case sensitive. E.g. these two links:
+Link definition names may consist of letters, numbers, spaces, and punctuation -- but they are *not* case sensitive. E.g. these two links:
[link text][a]
[link text][A]
diff --git a/test/rdoc/MarkdownTest_1.0.3/Tidyness.text b/test/rdoc/MarkdownTest_1.0.3/Tidiness.text
index 5f18b8da21..5f18b8da21 100644
--- a/test/rdoc/MarkdownTest_1.0.3/Tidyness.text
+++ b/test/rdoc/MarkdownTest_1.0.3/Tidiness.text
diff --git a/test/rdoc/helper.rb b/test/rdoc/helper.rb
index 2ba26c296b..7985433060 100644
--- a/test/rdoc/helper.rb
+++ b/test/rdoc/helper.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require_relative './support/test_case'
-require_relative './support/formatter_test_case'
-require_relative './support/text_formatter_test_case'
+require_relative 'support/test_case'
+require_relative 'support/formatter_test_case'
+require_relative 'support/text_formatter_test_case'
diff --git a/test/rdoc/support/test_case.rb b/test/rdoc/support/test_case.rb
index 7617fc8471..d98dbe0d7b 100644
--- a/test/rdoc/support/test_case.rb
+++ b/test/rdoc/support/test_case.rb
@@ -13,7 +13,7 @@ require 'tempfile'
require 'tmpdir'
require 'stringio'
-require 'rdoc'
+require_relative '../../../lib/rdoc'
##
# RDoc::TestCase is an abstract TestCase to provide common setup and teardown
@@ -37,7 +37,8 @@ class RDoc::TestCase < Test::Unit::TestCase
super
@orig_home = ENV["HOME"]
- ENV["HOME"] = Dir.tmpdir
+ FileUtils.mkdir_p(@test_home = Dir.mktmpdir("test_rdoc_"))
+ ENV["HOME"] = @test_home
@top_level = nil
@@ -64,6 +65,7 @@ class RDoc::TestCase < Test::Unit::TestCase
def teardown
ENV["HOME"] = @orig_home if defined?(@orig_home)
+ defined?(@test_home) and FileUtils.rm_rf @test_home
super
end
diff --git a/test/rdoc/support/text_formatter_test_case.rb b/test/rdoc/support/text_formatter_test_case.rb
index 22a762b5f0..e359028a29 100644
--- a/test/rdoc/support/text_formatter_test_case.rb
+++ b/test/rdoc/support/text_formatter_test_case.rb
@@ -112,4 +112,3 @@ class RDoc::Markup::TextFormatterTestCase < RDoc::Markup::FormatterTestCase
end
end
-
diff --git a/test/rdoc/test_rdoc_alias.rb b/test/rdoc/test_rdoc_alias.rb
index 89ae2d5a56..3c096a49b4 100644
--- a/test/rdoc/test_rdoc_alias.rb
+++ b/test/rdoc/test_rdoc_alias.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require File.expand_path '../xref_test_case', __FILE__
+require_relative 'xref_test_case'
class TestRDocAlias < XrefTestCase
@@ -11,4 +11,3 @@ class TestRDocAlias < XrefTestCase
end
end
-
diff --git a/test/rdoc/test_rdoc_any_method.rb b/test/rdoc/test_rdoc_any_method.rb
index 615789dfb3..b11c15420c 100644
--- a/test/rdoc/test_rdoc_any_method.rb
+++ b/test/rdoc/test_rdoc_any_method.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require File.expand_path '../xref_test_case', __FILE__
+require_relative 'xref_test_case'
class TestRDocAnyMethod < XrefTestCase
@@ -51,10 +51,38 @@ method(a, b) { |c, d| ... }
assert_equal 'foo', m.call_seq
end
+ def test_call_seq_alias_for
+ a = RDoc::AnyMethod.new nil, "each"
+ m = RDoc::AnyMethod.new nil, "each_line"
+
+ a.call_seq = <<-CALLSEQ
+each(foo)
+each_line(foo)
+ CALLSEQ
+
+ m.is_alias_for = a
+
+ assert_equal "each_line(foo)", m.call_seq
+ end
+
def test_full_name
assert_equal 'C1::m', @c1.method_list.first.full_name
end
+ def test_has_call_seq?
+ m = RDoc::AnyMethod.new nil, "each_line"
+ m2 = RDoc::AnyMethod.new nil, "each"
+ assert_equal false, m.has_call_seq?
+ m.call_seq = "each_line()"
+ assert_equal true, m.has_call_seq?
+
+ m = RDoc::AnyMethod.new nil, "each_line"
+ m.is_alias_for = m2
+ assert_equal false, m.has_call_seq?
+ m2.call_seq = "each_line()"
+ assert_equal true, m.has_call_seq?
+ end
+
def test_is_alias_for
assert_equal @c2_b, @c2_a.is_alias_for
@@ -72,6 +100,54 @@ method(a, b) { |c, d| ... }
assert_nil m1.is_alias_for, 'missing alias'
end
+ def test_call_seq_handles_aliases
+ # see 0ead786
+ @store.path = Dir.tmpdir
+ top_level = @store.add_file 'file.rb'
+ cm = top_level.add_class RDoc::ClassModule, 'Klass'
+
+ method_with_call_seq = RDoc::AnyMethod.new(nil, "method_with_call_seq")
+ method_with_call_seq.call_seq = <<~SEQ
+ method_with_call_seq(a)
+ method_with_call_seq(a, b)
+ alias_to_method(a)
+ alias_to_method(a, b)
+ SEQ
+ cm.add_method(method_with_call_seq)
+
+ alias_to_method = method_with_call_seq.add_alias(
+ RDoc::Alias.new(nil, "method_with_call_seq", "alias_to_method", "comment"),
+ cm
+ )
+
+ assert_equal("method_with_call_seq(a)\nmethod_with_call_seq(a, b)",
+ method_with_call_seq.call_seq)
+ assert_equal("alias_to_method(a)\nalias_to_method(a, b)",
+ alias_to_method.call_seq)
+ end
+
+ def test_call_seq_returns_nil_if_alias_is_missing_from_call_seq
+ @store.path = Dir.tmpdir
+ top_level = @store.add_file 'file.rb'
+ cm = top_level.add_class RDoc::ClassModule, 'Klass'
+
+ method_with_call_seq = RDoc::AnyMethod.new(nil, "method_with_call_seq")
+ method_with_call_seq.call_seq = <<~SEQ
+ method_with_call_seq(a)
+ method_with_call_seq(a, b)
+ SEQ
+ cm.add_method(method_with_call_seq)
+
+ alias_to_method = method_with_call_seq.add_alias(
+ RDoc::Alias.new(nil, "method_with_call_seq", "alias_to_method", "comment"),
+ cm
+ )
+
+ assert_equal("method_with_call_seq(a)\nmethod_with_call_seq(a, b)",
+ method_with_call_seq.call_seq)
+ assert_nil(alias_to_method.call_seq)
+ end
+
def test_markup_code
tokens = [
{ :line_no => 0, :char_no => 0, :kind => :on_const, :text => 'CONSTANT' },
@@ -453,6 +529,30 @@ method(a, b) { |c, d| ... }
assert_equal 'C1', @c1.method_list.last.parent_name
end
+ def test_skip_description?
+ m = RDoc::AnyMethod.new nil, "each_line"
+ m2 = RDoc::AnyMethod.new nil, "each"
+ assert_equal false, m.skip_description?
+ assert_equal false, m2.skip_description?
+
+ m.is_alias_for = m2
+ m2.aliases << m
+ assert_equal false, m.skip_description?
+ assert_equal false, m2.skip_description?
+
+ m2.call_seq = "each()"
+ assert_equal true, m.skip_description?
+ assert_equal false, m2.skip_description?
+
+ m2.call_seq = "each_line()"
+ assert_equal false, m.skip_description?
+ assert_equal true, m2.skip_description?
+
+ m2.call_seq = "each()\neach_line()"
+ assert_equal false, m.skip_description?
+ assert_equal false, m2.skip_description?
+ end
+
def test_store_equals
loaded = Marshal.load Marshal.dump(@c1.method_list.last)
diff --git a/test/rdoc/test_rdoc_class_module.rb b/test/rdoc/test_rdoc_class_module.rb
index 4dcc5d15ab..27d37cb7dd 100644
--- a/test/rdoc/test_rdoc_class_module.rb
+++ b/test/rdoc/test_rdoc_class_module.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require File.expand_path '../xref_test_case', __FILE__
+require_relative 'xref_test_case'
class TestRDocClassModule < XrefTestCase
@@ -63,7 +63,7 @@ class TestRDocClassModule < XrefTestCase
end
def test_ancestors
- assert_equal [@parent, "Object"], @child.ancestors
+ assert_equal [@parent, @object, "BasicObject"], @child.ancestors
end
def test_comment_equals
@@ -89,7 +89,7 @@ class TestRDocClassModule < XrefTestCase
assert_equal 'comment', cm.comment.text
end
- def test_docuent_self_or_methods
+ def test_document_self_or_methods
assert @c1.document_self_or_methods
@c1.document_self = false
@@ -129,7 +129,7 @@ class TestRDocClassModule < XrefTestCase
end
def test_each_ancestor
- assert_equal [@parent], @child.each_ancestor.to_a
+ assert_equal [@parent, @object], @child.each_ancestor.to_a
end
def test_each_ancestor_cycle
@@ -238,7 +238,7 @@ class TestRDocClassModule < XrefTestCase
assert_equal tl, loaded.method_list.first.file
end
- def test_marshal_dump_visibilty
+ def test_marshal_dump_visibility
@store.path = Dir.tmpdir
tl = @store.add_file 'file.rb'
@@ -1501,4 +1501,3 @@ class TestRDocClassModule < XrefTestCase
end
end
-
diff --git a/test/rdoc/test_rdoc_code_object.rb b/test/rdoc/test_rdoc_code_object.rb
index fad182722a..24e228cce1 100644
--- a/test/rdoc/test_rdoc_code_object.rb
+++ b/test/rdoc/test_rdoc_code_object.rb
@@ -1,7 +1,7 @@
# coding: US-ASCII
# frozen_string_literal: true
-require File.expand_path '../xref_test_case', __FILE__
+require_relative 'xref_test_case'
class TestRDocCodeObject < XrefTestCase
diff --git a/test/rdoc/test_rdoc_comment.rb b/test/rdoc/test_rdoc_comment.rb
index d3c16bceca..28e8cf76b4 100644
--- a/test/rdoc/test_rdoc_comment.rb
+++ b/test/rdoc/test_rdoc_comment.rb
@@ -206,6 +206,15 @@ lines, one line per element. Lines are assumed to be separated by _sep_.
assert_equal expected, comment.text
end
+ def test_extract_call_linear_performance
+ pre = ->(n) {[n, RDoc::Comment.new("\n"*n + 'call-seq:' + 'a'*n)]}
+ method_obj = RDoc::AnyMethod.new nil, 'blah'
+ assert_linear_performance((2..5).map {|i| 10**i}, pre: pre) do |n, comment|
+ comment.extract_call_seq method_obj
+ assert_equal n, method_obj.call_seq.size
+ end
+ end
+
def test_force_encoding
@comment = RDoc::Encoding.change_encoding @comment, Encoding::UTF_8
diff --git a/test/rdoc/test_rdoc_constant.rb b/test/rdoc/test_rdoc_constant.rb
index 79dcdad57e..32ffe3f84d 100644
--- a/test/rdoc/test_rdoc_constant.rb
+++ b/test/rdoc/test_rdoc_constant.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require File.expand_path '../xref_test_case', __FILE__
+require_relative 'xref_test_case'
class TestRDocConstant < XrefTestCase
diff --git a/test/rdoc/test_rdoc_context.rb b/test/rdoc/test_rdoc_context.rb
index ecdb3cbd67..c4de04e083 100644
--- a/test/rdoc/test_rdoc_context.rb
+++ b/test/rdoc/test_rdoc_context.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require File.expand_path '../xref_test_case', __FILE__
+require_relative 'xref_test_case'
class TestRDocContext < XrefTestCase
@@ -125,7 +125,7 @@ class TestRDocContext < XrefTestCase
basic = @c1.find_module_named 'BasicObject'
- assert_equal 'Object', basic.superclass
+ assert_equal @object, basic.superclass
end
def test_add_class_object
@@ -927,6 +927,12 @@ class TestRDocContext < XrefTestCase
assert_equal :private, @c6.find_method_named('priv6').visibility
assert_equal :protected, @c6.find_method_named('prot6').visibility
assert_equal :public, @c6.find_method_named('pub6').visibility
+ assert_equal :public, @c6.find_method_named('s_pub1').visibility
+ assert_equal :public, @c6.find_method_named('s_pub2').visibility
+ assert_equal :public, @c6.find_method_named('s_pub3').visibility
+ assert_equal :public, @c6.find_method_named('s_pub4').visibility
+ assert_equal :private, @c6.find_method_named('s_priv1').visibility
+ assert_equal :protected, @c6.find_method_named('s_prot1').visibility
end
def util_visibilities
diff --git a/test/rdoc/test_rdoc_context_section.rb b/test/rdoc/test_rdoc_context_section.rb
index 24c68c49dd..6834cccafb 100644
--- a/test/rdoc/test_rdoc_context_section.rb
+++ b/test/rdoc/test_rdoc_context_section.rb
@@ -144,4 +144,3 @@ class TestRDocContextSection < RDoc::TestCase
end
end
-
diff --git a/test/rdoc/test_rdoc_cross_reference.rb b/test/rdoc/test_rdoc_cross_reference.rb
index 183de0930d..cbda77a798 100644
--- a/test/rdoc/test_rdoc_cross_reference.rb
+++ b/test/rdoc/test_rdoc_cross_reference.rb
@@ -1,7 +1,10 @@
# frozen_string_literal: true
-require File.expand_path '../xref_test_case', __FILE__
+require_relative 'xref_test_case'
class TestRDocCrossReference < XrefTestCase
+ EXAMPLE_METHODS = %w'== === != =~ !~ < > <= >= <=> [] []= << >>
+ -@ +@ ! - + * / % ** !@ ` | & ^ ~ __id__
+ '
def setup
super
@@ -18,9 +21,9 @@ class TestRDocCrossReference < XrefTestCase
end
def test_METHOD_REGEXP_STR
- re = /#{RDoc::CrossReference::METHOD_REGEXP_STR}/
+ re = /\A(?:#{RDoc::CrossReference::METHOD_REGEXP_STR})\z/
- %w'=== [] []= << >>'.each do |x|
+ EXAMPLE_METHODS.each do |x|
re =~ x
assert_equal x, $&
end
@@ -88,6 +91,15 @@ class TestRDocCrossReference < XrefTestCase
assert_ref @c4_c4, 'C4'
end
+ def test_resolve_class_and_method_of_the_same_name
+ assert_ref @c10_class, 'C10'
+ assert_ref @c10_method, '#C10'
+ assert_ref @c11_class, 'C11'
+ assert_ref @c11_method, '#C11'
+ assert_ref @c10_c11_class, 'C10::C11'
+ assert_ref @c10_c11_method, 'C10#C11'
+ end
+
def test_resolve_class
assert_ref @c1, 'C1'
refute_ref 'H1'
@@ -154,34 +166,35 @@ class TestRDocCrossReference < XrefTestCase
assert_ref @c9_a_c_bar, 'C9::B.bar'
end
- def test_resolve_method_equals3
- m = RDoc::AnyMethod.new '', '==='
- @c1.add_method m
-
- assert_ref m, '==='
- end
-
def test_resolve_page
page = @store.add_file 'README.txt', parser: RDoc::Parser::Simple
assert_ref page, 'README'
end
- def test_resolve_percent
- i_percent = RDoc::AnyMethod.new nil, '%'
- i_percent.singleton = false
- @c1.add_method i_percent
+ def assert_resolve_method(x)
+ @c1.methods_hash.clear
- c_percent = RDoc::AnyMethod.new nil, '%'
- c_percent.singleton = true
- @c1.add_method c_percent
+ i_op = RDoc::AnyMethod.new nil, x
+ i_op.singleton = false
+ @c1.add_method i_op
- assert_ref i_percent, '%'
- assert_ref i_percent, '#%'
- assert_ref c_percent, '::%'
+ c_op = RDoc::AnyMethod.new nil, x
+ c_op.singleton = true
+ @c1.add_method c_op
- assert_ref i_percent, 'C1#%'
- assert_ref c_percent, 'C1::%'
+ assert_ref i_op, x
+ assert_ref i_op, "##{x}"
+ assert_ref c_op, "::#{x}"
+
+ assert_ref i_op, "C1##{x}"
+ assert_ref c_op, "C1::#{x}"
+ end
+
+ EXAMPLE_METHODS.each do |x|
+ define_method("test_resolve_method:#{x}") do
+ assert_resolve_method(x)
+ end
end
def test_resolve_no_ref
@@ -204,4 +217,3 @@ class TestRDocCrossReference < XrefTestCase
end
end
-
diff --git a/test/rdoc/test_rdoc_extend.rb b/test/rdoc/test_rdoc_extend.rb
index f4c8425864..cc5038cc51 100644
--- a/test/rdoc/test_rdoc_extend.rb
+++ b/test/rdoc/test_rdoc_extend.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require File.expand_path '../xref_test_case', __FILE__
+require_relative 'xref_test_case'
class TestRDocExtend < XrefTestCase
@@ -43,7 +43,7 @@ class TestRDocExtend < XrefTestCase
m1_m2_k0.add_extend e0_m3
assert_equal [e0_m4, e0_m5, e0_m6, e0_m1, e0_m2, e0_m3], m1_m2_k0.extends
- assert_equal ['Object'], m1_m2_k0.ancestors
+ assert_equal [@object, 'BasicObject'], m1_m2_k0.ancestors
m1_k1 = m1.add_class RDoc::NormalClass, 'Klass1'
@@ -60,7 +60,7 @@ class TestRDocExtend < XrefTestCase
m1_k1.add_extend e1_k0_m4
assert_equal [e1_m1, e1_m2, e1_m3, e1_m4, e1_k0_m4], m1_k1.extends
- assert_equal ['Object'], m1_k1.ancestors
+ assert_equal [@object, 'BasicObject'], m1_k1.ancestors
m1_k2 = m1.add_class RDoc::NormalClass, 'Klass2'
@@ -75,7 +75,7 @@ class TestRDocExtend < XrefTestCase
m1_k2.add_extend e2_k0_m4
assert_equal [e2_m1, e2_m3, e2_m2, e2_k0_m4], m1_k2.extends
- assert_equal ['Object'], m1_k2.ancestors
+ assert_equal [@object, 'BasicObject'], m1_k2.ancestors
m1_k3 = m1.add_class RDoc::NormalClass, 'Klass3'
@@ -88,8 +88,7 @@ class TestRDocExtend < XrefTestCase
m1_k3.add_extend e3_m4
assert_equal [e3_m1, e3_m2, e3_m4], m1_k3.extends
- assert_equal ['Object'], m1_k3.ancestors
+ assert_equal [@object, 'BasicObject'], m1_k3.ancestors
end
end
-
diff --git a/test/rdoc/test_rdoc_generator_darkfish.rb b/test/rdoc/test_rdoc_generator_darkfish.rb
index b78a3fb45f..899e697de6 100644
--- a/test/rdoc/test_rdoc_generator_darkfish.rb
+++ b/test/rdoc/test_rdoc_generator_darkfish.rb
@@ -72,11 +72,30 @@ class TestRDocGeneratorDarkfish < RDoc::TestCase
def test_generate
top_level = @store.add_file 'file.rb'
top_level.add_class @klass.class, @klass.name
+ @klass.add_class RDoc::NormalClass, 'Inner'
+ @klass.add_comment <<~RDOC, top_level
+ = Heading 1
+ Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
+ == Heading 1.1
+ tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
+ === Heading 1.1.1
+ quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
+ ==== Heading 1.1.1.1
+ consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
+ == Heading 1.2
+ cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat
+ == Heading 1.3
+ non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
+ === Heading 1.3.1
+ etc etc...
+ RDOC
@g.generate
assert_file 'index.html'
assert_file 'Object.html'
+ assert_file 'Klass.html'
+ assert_file 'Klass/Inner.html'
assert_file 'table_of_contents.html'
assert_file 'js/search_index.js'
@@ -88,10 +107,48 @@ class TestRDocGeneratorDarkfish < RDoc::TestCase
encoding = Regexp.escape Encoding::UTF_8.name
- assert_match %r%<meta charset="#{encoding}">%, File.read('index.html')
- assert_match %r%<meta charset="#{encoding}">%, File.read('Object.html')
+ assert_match %r%<meta charset="#{encoding}">%, File.binread('index.html')
+ assert_match %r%<meta charset="#{encoding}">%, File.binread('Object.html')
+
+ refute_match(/Ignored/, File.binread('index.html'))
+ summary = File.binread('index.html')[%r[<summary.*Klass\.html.*</summary>.*</details>]m]
+ assert_match(%r[Klass/Inner\.html".*>Inner<], summary)
+
+ klass = File.binread('Klass.html')
+ klassnav = klass[%r[<div class="nav-section">.*]m]
+ assert_match(
+ %r[<li>\s*<details open>\s*<summary>\s*<a href=\S+>Heading 1</a>\s*</summary>\s*<ul]m,
+ klassnav
+ )
+ assert_match(
+ %r[<li>\s*<a href=\S+>Heading 1.1.1.1</a>\s*</ul>\s*</details>\s*</li>]m,
+ klassnav
+ )
+
+ assert_match(/<h1 id="class-Klass-label-Heading\+1">Heading 1(?!\.)/,
+ klass[%r[<section class=\"description\">.*</section>]m])
+ toc = File.binread('table_of_contents.html')
+ assert_match(
+ %r[<a\s+href="Klass\.html#class-Klass-label-Heading\+1">Heading 1</a>]m,
+ toc[%r[<h2\s+id=\"classes\">.*(?=<h2\b)]m][%r[<a\s+href="Klass\.html".*(?=</li\b)]m]
+ )
+ end
- refute_match(/Ignored/, File.read('index.html'))
+ def test_generate_page
+ @store.add_file 'outer.rdoc', parser: RDoc::Parser::Simple
+ @store.add_file 'outer/inner.rdoc', parser: RDoc::Parser::Simple
+ @g.generate
+ assert_file 'outer_rdoc.html'
+ assert_file 'outer/inner_rdoc.html'
+ index = File.binread('index.html')
+ re = %r[<summary><a href="\./outer_rdoc\.html">outer</a></summary>.*?</details>]m
+ assert_match(re, index)
+ summary = index[re]
+ assert_match %r[<a href="\./outer/inner_rdoc.html">inner</a>], summary
+ re = %r[<details open><summary><a href="\./outer_rdoc\.html">outer</a></summary>.*?</details>]m
+ assert_match(re, File.binread('outer_rdoc.html'))
+ re = %r[<details open><summary><a href="\.\./outer_rdoc\.html">outer</a></summary>.*?</details>]m
+ assert_match(re, File.binread('outer/inner_rdoc.html'))
end
def test_generate_dry_run
@@ -211,6 +268,29 @@ class TestRDocGeneratorDarkfish < RDoc::TestCase
assert_includes method_name, '{ |%&lt;&lt;script&gt;alert(&quot;atui&quot;)&lt;/script&gt;&gt;, yield_arg| ... }'
end
+ def test_generated_filename_with_html_tag
+ filename = '"><em>should be escaped'
+ begin # in @tmpdir
+ File.write(filename, '')
+ rescue SystemCallError
+ # ", <, > chars are prohibited as filename
+ return
+ else
+ File.unlink(filename)
+ end
+ @store.add_file filename
+ doc = @store.all_files.last
+ doc.parser = RDoc::Parser::Simple
+
+ @g.generate
+
+ Dir.glob("*.html", base: @tmpdir) do |html|
+ File.binread(File.join(@tmpdir, html)).scan(/.*should be escaped.*/) do |line|
+ assert_not_include line, "<em>", html
+ end
+ end
+ end
+
def test_template_stylesheets
css = Tempfile.create(%W'hoge .css', Dir.mktmpdir('tmp', '.'))
File.write(css, '')
@@ -223,7 +303,23 @@ class TestRDocGeneratorDarkfish < RDoc::TestCase
@g.generate
assert_file base
- assert_include File.read('index.html'), %Q[href="./#{base}"]
+ assert_include File.binread('index.html'), %Q[href="./#{base}"]
+ end
+
+ def test_title
+ title = "RDoc Test".freeze
+ @options.title = title
+ @g.generate
+
+ assert_main_title(File.binread('index.html'), title)
+ end
+
+ def test_title_escape
+ title = %[<script>alert("RDoc")</script>].freeze
+ @options.title = title
+ @g.generate
+
+ assert_main_title(File.binread('index.html'), title)
end
##
@@ -249,4 +345,9 @@ class TestRDocGeneratorDarkfish < RDoc::TestCase
"#{filename} is not hard-linked"
end
+ def assert_main_title(content, title)
+ title = CGI.escapeHTML(title)
+ assert_equal(title, content[%r[<title>(.*?)<\/title>]im, 1])
+ assert_include(content[%r[<main\s[^<>]*+>\s*(.*?)</main>]im, 1], title)
+ end
end
diff --git a/test/rdoc/test_rdoc_generator_json_index.rb b/test/rdoc/test_rdoc_generator_json_index.rb
index 6b69337b45..62d1ccec95 100644
--- a/test/rdoc/test_rdoc_generator_json_index.rb
+++ b/test/rdoc/test_rdoc_generator_json_index.rb
@@ -104,8 +104,20 @@ class TestRDocGeneratorJsonIndex < RDoc::TestCase
orig_file = Pathname(File.join srcdir, 'generator/template/json_index/js/navigation.js')
generated_file = Pathname(File.join @tmpdir, 'js/navigation.js')
+ # The following assertion for the generated file's modified time randomly
+ # fails in a ppc64le environment.
+ # https://github.com/ruby/rdoc/issues/1048
+ if orig_file.mtime.inspect != generated_file.mtime.inspect &&
+ RUBY_PLATFORM =~ /powerpc64le/
+ pend <<~EOC
+ Unstable test in ppc64le.
+ <#{orig_file.mtime.inspect}> expected but was
+ <#{generated_file.mtime.inspect}>.
+ EOC
+ end
+
# This is dirty hack on JRuby
- assert orig_file.mtime.inspect == generated_file.mtime.inspect,
+ assert_equal orig_file.mtime.inspect, generated_file.mtime.inspect,
'.js files should be the same timestamp of original'
json = File.read 'js/search_index.js'
diff --git a/test/rdoc/test_rdoc_generator_markup.rb b/test/rdoc/test_rdoc_generator_markup.rb
index 5491b7c61e..7c021e432e 100644
--- a/test/rdoc/test_rdoc_generator_markup.rb
+++ b/test/rdoc/test_rdoc_generator_markup.rb
@@ -57,4 +57,3 @@ class TestRDocGeneratorMarkup < RDoc::TestCase
end
end
-
diff --git a/test/rdoc/test_rdoc_include.rb b/test/rdoc/test_rdoc_include.rb
index 67d3dfd88e..380464f6cc 100644
--- a/test/rdoc/test_rdoc_include.rb
+++ b/test/rdoc/test_rdoc_include.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require File.expand_path '../xref_test_case', __FILE__
+require_relative 'xref_test_case'
class TestRDocInclude < XrefTestCase
@@ -46,7 +46,7 @@ class TestRDocInclude < XrefTestCase
assert_equal [i0_m4, i0_m5, i0_m6, i0_m1, i0_m2, i0_m3], m1_m2_k0.includes
assert_equal [m1_m2_m3, m1_m2, m1, m1_m2_k0_m4_m6, m1_m2_k0_m5,
- m1_m2_k0_m4, 'Object'], m1_m2_k0.ancestors
+ m1_m2_k0_m4, @object, 'BasicObject'], m1_m2_k0.ancestors
m1_k1 = m1.add_class RDoc::NormalClass, 'Klass1'
@@ -63,8 +63,8 @@ class TestRDocInclude < XrefTestCase
m1_k1.add_include i1_k0_m4
assert_equal [i1_m1, i1_m2, i1_m3, i1_m4, i1_k0_m4], m1_k1.includes
- assert_equal [m1_m2_k0_m4, m1_m2_m3_m4, m1_m2_m3, m1_m2, m1, 'Object'],
- m1_k1.ancestors
+ assert_equal [m1_m2_k0_m4, m1_m2_m3_m4, m1_m2_m3, m1_m2, m1, @object,
+ 'BasicObject'], m1_k1.ancestors
m1_k2 = m1.add_class RDoc::NormalClass, 'Klass2'
@@ -79,7 +79,8 @@ class TestRDocInclude < XrefTestCase
m1_k2.add_include i2_k0_m4
assert_equal [i2_m1, i2_m3, i2_m2, i2_k0_m4], m1_k2.includes
- assert_equal [m1_m2_k0_m4, m1_m2, m1_m3, m1, 'Object'], m1_k2.ancestors
+ assert_equal [m1_m2_k0_m4, m1_m2, m1_m3, m1, @object, 'BasicObject'],
+ m1_k2.ancestors
m1_k3 = m1.add_class RDoc::NormalClass, 'Klass3'
@@ -92,7 +93,7 @@ class TestRDocInclude < XrefTestCase
m1_k3.add_include i3_m4
assert_equal [i3_m1, i3_m2, i3_m4], m1_k3.includes
- assert_equal [m1_m2_m4, m1_m2, m1, 'Object'], m1_k3.ancestors
+ assert_equal [m1_m2_m4, m1_m2, m1, @object, 'BasicObject'], m1_k3.ancestors
end
def test_store_equals
@@ -106,4 +107,3 @@ class TestRDocInclude < XrefTestCase
end
end
-
diff --git a/test/rdoc/test_rdoc_markdown.rb b/test/rdoc/test_rdoc_markdown.rb
index ad53e9473c..72587caf46 100644
--- a/test/rdoc/test_rdoc_markdown.rb
+++ b/test/rdoc/test_rdoc_markdown.rb
@@ -2,8 +2,8 @@
# frozen_string_literal: true
require_relative 'helper'
-require 'rdoc/markup/block_quote'
-require 'rdoc/markdown'
+require_relative '../../lib/rdoc/markup/block_quote'
+require_relative '../../lib/rdoc/markdown'
class TestRDocMarkdown < RDoc::TestCase
@@ -305,6 +305,25 @@ that also extends to two lines
assert_equal expected, doc
end
+ def test_parse_definition_list_rich_label
+ doc = parse <<-MD
+`one`
+: This is a definition
+
+**two**
+: This is another definition
+ MD
+
+ expected = doc(
+ list(:NOTE,
+ item(%w[<code>one</code>],
+ para("This is a definition")),
+ item(%w[*two*],
+ para("This is another definition"))))
+
+ assert_equal expected, doc
+ end
+
def test_parse_definition_list_no
@parser.definition_lists = false
@@ -395,10 +414,23 @@ two
end
def test_parse_heading_atx
- doc = parse "# heading\n"
+ # CommonMark Example 62
+ (1..6).each do |level|
+ doc = parse "#{"#" * level} heading\n"
+
+ expected = @RM::Document.new(
+ @RM::Heading.new(level, "heading"))
+
+ assert_equal expected, doc
+ end
+
+ # CommonMark Example 64
+ doc = parse "#5 bolt\n\n#hashtag\n"
expected = @RM::Document.new(
- @RM::Heading.new(1, "heading"))
+ para("#5 bolt"),
+ para("#hashtag"),
+ )
assert_equal expected, doc
end
@@ -761,7 +793,6 @@ with inline notes^[like this]
and an extra note.[^2]
[^1]: With a footnote
-
[^2]: Which should be numbered correctly
MD
@@ -1063,9 +1094,29 @@ and an extra note.[^2]
assert_equal expected, doc
end
+ def test_gfm_table_2
+ doc = parse <<~'MD'
+ | Cmd | Returns | Meaning
+ ----- | :-----: | -------
+ |"b" | boolean | True if file1 is a block device
+ "c" | boolean | True if file1 is a character device
+ |"\|" | boolean | escaped bar \| test
+ MD
+
+ head = %w[Cmd Returns Meaning]
+ align = [nil, :center, nil]
+ body = [
+ ['"b"', 'boolean', 'True if file1 is a block device'],
+ ['"c"', 'boolean', 'True if file1 is a character device'],
+ ['"|"', 'boolean', 'escaped bar | test'],
+ ]
+ expected = doc(@RM::Table.new(head, align, body))
+
+ assert_equal expected, doc
+ end
+
def parse text
@parser.parse text
end
end
-
diff --git a/test/rdoc/test_rdoc_markdown_test.rb b/test/rdoc/test_rdoc_markdown_test.rb
index 0ecd000136..193d648253 100644
--- a/test/rdoc/test_rdoc_markdown_test.rb
+++ b/test/rdoc/test_rdoc_markdown_test.rb
@@ -2,8 +2,8 @@
require_relative 'helper'
require 'pp'
-require 'rdoc'
-require 'rdoc/markdown'
+require_relative '../../lib/rdoc'
+require_relative '../../lib/rdoc/markdown'
class TestRDocMarkdownTest < RDoc::TestCase
@@ -1401,7 +1401,7 @@ foo
para("Link definitions are only used for creating links during Markdown\n" +
"processing, and are stripped from your document in the HTML output."),
- para("Link definition names may constist of letters, numbers, spaces, and punctuation -- but they are _not_ case sensitive. E.g. these two links:"),
+ para("Link definition names may consist of letters, numbers, spaces, and punctuation -- but they are _not_ case sensitive. E.g. these two links:"),
verb("[link text][a]\n",
"[link text][A]\n"),
@@ -1863,8 +1863,8 @@ foo
assert_equal expected, doc
end
- def test_tidyness
- input = File.read "#{MARKDOWN_TEST_PATH}/Tidyness.text"
+ def test_tidiness
+ input = File.read "#{MARKDOWN_TEST_PATH}/Tidiness.text"
doc = @parser.parse input
diff --git a/test/rdoc/test_rdoc_markup.rb b/test/rdoc/test_rdoc_markup.rb
index b9bdafab2a..4d79f8bc3f 100644
--- a/test/rdoc/test_rdoc_markup.rb
+++ b/test/rdoc/test_rdoc_markup.rb
@@ -93,4 +93,3 @@ the time
end
end
-
diff --git a/test/rdoc/test_rdoc_markup_attribute_manager.rb b/test/rdoc/test_rdoc_markup_attribute_manager.rb
index 944364ba89..dcae48525d 100644
--- a/test/rdoc/test_rdoc_markup_attribute_manager.rb
+++ b/test/rdoc/test_rdoc_markup_attribute_manager.rb
@@ -145,6 +145,8 @@ class TestRDocMarkupAttributeManager < RDoc::TestCase
assert_equal(["cat and ", @em_on, "5", @em_off, " dogs"],
@am.flow("cat and _5_ dogs"))
+
+ assert_equal([@tt_on, "__id__", @tt_off], @am.flow("+__id__+"))
end
def test_bold
@@ -391,4 +393,3 @@ class TestRDocMarkupAttributeManager < RDoc::TestCase
end
end
-
diff --git a/test/rdoc/test_rdoc_markup_attributes.rb b/test/rdoc/test_rdoc_markup_attributes.rb
index 0dfd72bdb6..1ab408d801 100644
--- a/test/rdoc/test_rdoc_markup_attributes.rb
+++ b/test/rdoc/test_rdoc_markup_attributes.rb
@@ -37,4 +37,3 @@ class TestRDocMarkupAttributes < RDoc::TestCase
end
end
-
diff --git a/test/rdoc/test_rdoc_markup_document.rb b/test/rdoc/test_rdoc_markup_document.rb
index 3db834b85d..e4f3b9daf1 100644
--- a/test/rdoc/test_rdoc_markup_document.rb
+++ b/test/rdoc/test_rdoc_markup_document.rb
@@ -205,4 +205,3 @@ class TestRDocMarkupDocument < RDoc::TestCase
end
end
-
diff --git a/test/rdoc/test_rdoc_markup_formatter.rb b/test/rdoc/test_rdoc_markup_formatter.rb
index 8702db379d..af19d832ca 100644
--- a/test/rdoc/test_rdoc_markup_formatter.rb
+++ b/test/rdoc/test_rdoc_markup_formatter.rb
@@ -104,6 +104,12 @@ class TestRDocMarkupFormatter < RDoc::TestCase
formatted = document.accept @to
assert_equal '<{foo}[rdoc-label:bar]>.', formatted
+
+ document = doc(para('<tt>{abc}</tt>: {foo}[rdoc-label:bar].'))
+
+ formatted = document.accept @to
+
+ assert_equal '<code>{abc}</code>: <{foo}[rdoc-label:bar]>.', formatted
end
def test_parse_url
diff --git a/test/rdoc/test_rdoc_markup_hard_break.rb b/test/rdoc/test_rdoc_markup_hard_break.rb
index adebfdc311..ac67c68d10 100644
--- a/test/rdoc/test_rdoc_markup_hard_break.rb
+++ b/test/rdoc/test_rdoc_markup_hard_break.rb
@@ -29,4 +29,3 @@ class TestRDocMarkupHardBreak < RDoc::TestCase
end
end
-
diff --git a/test/rdoc/test_rdoc_markup_heading.rb b/test/rdoc/test_rdoc_markup_heading.rb
index 05a8e005ba..de92af91a0 100644
--- a/test/rdoc/test_rdoc_markup_heading.rb
+++ b/test/rdoc/test_rdoc_markup_heading.rb
@@ -27,4 +27,3 @@ class TestRDocMarkupHeading < RDoc::TestCase
end
end
-
diff --git a/test/rdoc/test_rdoc_markup_include.rb b/test/rdoc/test_rdoc_markup_include.rb
index 9126526b73..b3e9b845c3 100644
--- a/test/rdoc/test_rdoc_markup_include.rb
+++ b/test/rdoc/test_rdoc_markup_include.rb
@@ -17,4 +17,3 @@ class TestRDocMarkupInclude < RDoc::TestCase
end
end
-
diff --git a/test/rdoc/test_rdoc_markup_indented_paragraph.rb b/test/rdoc/test_rdoc_markup_indented_paragraph.rb
index 7b5758998f..d2a9cbe5ca 100644
--- a/test/rdoc/test_rdoc_markup_indented_paragraph.rb
+++ b/test/rdoc/test_rdoc_markup_indented_paragraph.rb
@@ -51,4 +51,3 @@ class TestRDocMarkupIndentedParagraph < RDoc::TestCase
end
end
-
diff --git a/test/rdoc/test_rdoc_markup_paragraph.rb b/test/rdoc/test_rdoc_markup_paragraph.rb
index ca89a74fc3..1b26846eb3 100644
--- a/test/rdoc/test_rdoc_markup_paragraph.rb
+++ b/test/rdoc/test_rdoc_markup_paragraph.rb
@@ -30,4 +30,3 @@ class TestRDocMarkupParagraph < RDoc::TestCase
end
end
-
diff --git a/test/rdoc/test_rdoc_markup_raw.rb b/test/rdoc/test_rdoc_markup_raw.rb
index c7795b24e1..52887e6f6c 100644
--- a/test/rdoc/test_rdoc_markup_raw.rb
+++ b/test/rdoc/test_rdoc_markup_raw.rb
@@ -20,4 +20,3 @@ class TestRDocMarkupRaw < RDoc::TestCase
end
end
-
diff --git a/test/rdoc/test_rdoc_markup_to_ansi.rb b/test/rdoc/test_rdoc_markup_to_ansi.rb
index 1d1fc7db46..81372c64d2 100644
--- a/test/rdoc/test_rdoc_markup_to_ansi.rb
+++ b/test/rdoc/test_rdoc_markup_to_ansi.rb
@@ -367,4 +367,3 @@ bar:
end
end
-
diff --git a/test/rdoc/test_rdoc_markup_to_html.rb b/test/rdoc/test_rdoc_markup_to_html.rb
index b2b21de806..e3affa533c 100644
--- a/test/rdoc/test_rdoc_markup_to_html.rb
+++ b/test/rdoc/test_rdoc_markup_to_html.rb
@@ -391,11 +391,43 @@ class TestRDocMarkupToHtml < RDoc::Markup::FormatterTestCase
end
def test_accept_paragraph_newline
+ hellos = ["hello", "\u{393 3b5 3b9 3ac} \u{3c3 3bf 3c5}"]
+ worlds = ["world", "\u{3ba 3cc 3c3 3bc 3bf 3c2}"]
+ ohayo, sekai = %W"\u{304a 306f 3088 3046} \u{4e16 754c}"
+
+ hellos.product(worlds) do |hello, world|
+ @to.start_accepting
+ @to.accept_paragraph para("#{hello}\n", "#{world}\n")
+ assert_equal "\n<p>#{hello} #{world}</p>\n", @to.res.join
+ end
+
+ hellos.each do |hello|
+ @to.start_accepting
+ @to.accept_paragraph para("#{hello}\n", "#{sekai}\n")
+ assert_equal "\n<p>#{hello}#{sekai}</p>\n", @to.res.join
+ end
+
+ worlds.each do |world|
+ @to.start_accepting
+ @to.accept_paragraph para("#{ohayo}\n", "#{world}\n")
+ assert_equal "\n<p>#{ohayo}#{world}</p>\n", @to.res.join
+ end
+
@to.start_accepting
+ @to.accept_paragraph para("#{ohayo}\n", "#{sekai}\n")
+ assert_equal "\n<p>#{ohayo}#{sekai}</p>\n", @to.res.join
- @to.accept_paragraph para("hello\n", "world\n")
+ @to.start_accepting
+ @to.accept_paragraph para("+hello+\n", "world\n")
+ assert_equal "\n<p><code>hello</code> world</p>\n", @to.res.join
+
+ @to.start_accepting
+ @to.accept_paragraph para("hello\n", "+world+\n")
+ assert_equal "\n<p>hello <code>world</code></p>\n", @to.res.join
- assert_equal "\n<p>hello world </p>\n", @to.res.join
+ @to.start_accepting
+ @to.accept_paragraph para("+hello+\n", "+world+\n")
+ assert_equal "\n<p><code>hello</code> <code>world</code></p>\n", @to.res.join
end
def test_accept_heading_output_decoration
@@ -602,9 +634,9 @@ end
end
def test_accept_verbatim_redefinable_operators
- functions = %w[| ^ & <=> == === =~ > >= < <= << >> + - * / % ** ~ +@ -@ [] []= ` ! != !~].map { |redefinable_op|
+ functions = %w[| ^ & <=> == === =~ > >= < <= << >> + - * / % ** ~ +@ -@ [] []= ` ! != !~].flat_map { |redefinable_op|
["def #{redefinable_op}\n", "end\n"]
- }.flatten
+ }
verb = @RM::Verbatim.new(*functions)
@@ -665,6 +697,26 @@ EXPECTED
assert_equal "\n<p>C</p>\n", result
end
+ def test_convert_RDOCLINK_escape_image
+ assert_escaped '<script>', 'rdoc-image:"><script>alert(`rdoc-image`)</script>"'
+ end
+
+ def test_convert_RDOCLINK_escape_label_id
+ assert_escaped '<script>', 'rdoc-label::path::"><script>alert(`rdoc-label_id`)</script>"'
+ end
+
+ def test_convert_RDOCLINK_escape_label_path
+ assert_escaped '<script>', 'rdoc-label::"><script>alert(`rdoc-label_path`)</script>"'
+ end
+
+ def test_convert_RDOCLINK_escape_ref
+ assert_escaped '<script>', 'rdoc-ref:"><script>alert(`rdoc-ref`)</script>"'
+ end
+
+ def test_convert_RDOCLINK_escape_xxx
+ assert_escaped '<script>', 'rdoc-xxx:"><script>alert(`rdoc-xxx`)</script>"'
+ end
+
def test_convert_TIDYLINK_footnote
result = @to.convert 'text{*1}[rdoc-label:foottext-1:footmark-1]'
@@ -690,6 +742,11 @@ EXPECTED
"\n<p><a href=\"http://example.com\"><img src=\"path/to/image.jpg\"></a></p>\n"
assert_equal expected, result
+
+ result =
+ @to.convert '{rdoc-image:<script>alert`link text`</script>}[http://example.com]'
+
+ assert_not_include result, "<script>"
end
def test_convert_TIDYLINK_rdoc_label
@@ -704,9 +761,27 @@ EXPECTED
assert_equal "\n<p><a href=\"irc://irc.freenode.net/#ruby-lang\">ruby-lang</a></p>\n", result
end
+ def test_convert_TIDYLINK_escape_text
+ assert_escaped '<script>', '{<script>alert`link text`</script>}[a]'
+ assert_escaped '<script>', 'x:/<script>alert(1);</script>[[]'
+ end
+
+ def test_convert_TIDYLINK_escape_javascript
+ assert_not_include '{click}[javascript:alert`javascript_scheme`]', '<a href="javascript:'
+ end
+
+ def test_convert_TIDYLINK_escape_onmouseover
+ assert_escaped '"/onmouseover="', '{onmouseover}[http://"/onmouseover="alert`on_mouse_link`"]'
+ end
+
+ def test_convert_TIDYLINK_escape_onerror
+ assert_escaped '"onerror="', '{link_image}[http://"onerror="alert`link_image`".png]'
+ end
+
def test_convert_with_exclude_tag
assert_equal "\n<p><code>aaa</code>[:symbol]</p>\n", @to.convert('+aaa+[:symbol]')
assert_equal "\n<p><code>aaa[:symbol]</code></p>\n", @to.convert('+aaa[:symbol]+')
+ assert_equal "\n<p><code>https:</code>-foobar</p>\n", @to.convert('<tt>https:</tt>-foobar')
assert_equal "\n<p><a href=\":symbol\">aaa</a></p>\n", @to.convert('aaa[:symbol]')
end
@@ -793,6 +868,11 @@ EXPECTED
assert_equal '<a href="irc://irc.freenode.net/#ruby-lang">irc.freenode.net/#ruby-lang</a>', link
end
+ def test_handle_regexp_HYPERLINK_escape
+ code = 'irc://irc.freenode.net/"><script>alert(`irc`)</script><a"'
+ assert_escaped '<script>', code
+ end
+
def test_list_verbatim_2
str = "* one\n verb1\n verb2\n* two\n"
@@ -811,6 +891,26 @@ EXPECTED
assert_equal expected, @m.convert(str, @to)
end
+ def test_block_quote_in_verbatim
+ str = "BlockQuote\n >>>\n"
+
+ expected = <<-EXPECTED
+<p>BlockQuote</p>
+<pre>&gt;&gt;&gt;</pre>
+ EXPECTED
+
+ assert_equal expected, @m.convert(str, @to).gsub(/^\n/, "")
+
+ str = "BlockQuote\n >>> word\n"
+
+ expected = <<-EXPECTED
+<p>BlockQuote</p>
+<pre>&gt;&gt;&gt; word</pre>
+ EXPECTED
+
+ assert_equal expected, @m.convert(str, @to).gsub(/^\n/, "")
+ end
+
def test_parseable_eh
valid_syntax = [
'def x() end',
@@ -855,5 +955,37 @@ EXPECTED
@to.end_accepting
end
+ def test_accept_table
+ header = %w[Col1 Col2 Col3]
+ body = [
+ %w[cell1_1 cell1_2 cell1_3],
+ %w[cell2_1 cell2_2 cell2_3],
+ ['<script>alert("foo");</script>',],
+ %w[+code+ _em_ **strong**],
+ ]
+ aligns = [:left, :right, nil]
+ @to.start_accepting
+ @to.accept_table(header, body, aligns)
+ res = @to.end_accepting
+ assert_include(res[%r<<th[^<>]*>Col1</th>>], 'align="left"')
+ assert_include(res[%r<<th[^<>]*>Col2</th>>], 'align="right"')
+ assert_not_include(res[%r<<th[^<>]*>Col3</th>>], 'align=')
+ assert_include(res[%r<<td[^<>]*>cell1_1</td>>], 'align="left"')
+ assert_include(res[%r<<td[^<>]*>cell1_2</td>>], 'align="right"')
+ assert_not_include(res[%r<<td[^<>]*>cell1_3</td>>], 'align=')
+ assert_include(res[%r<<td[^<>]*>cell2_1</td>>], 'align="left"')
+ assert_include(res[%r<<td[^<>]*>cell2_2</td>>], 'align="right"')
+ assert_not_include(res[%r<<td[^<>]*>cell2_3</td>>], 'align=')
+ assert_not_include(res, '<script>')
+ assert_include(res[%r<<td[^<>]*>.*script.*</td>>], '&lt;script&gt;')
+ assert_include(res[%r<<td[^<>]*>.*code.*</td>>], '<code>code</code>')
+ assert_include(res[%r<<td[^<>]*>.*em.*</td>>], '<em>em</em>')
+ assert_include(res[%r<<td[^<>]*>.*strong.*</td>>], '<strong>strong</strong>')
+ end
+
+ def assert_escaped(unexpected, code)
+ result = @to.convert(code)
+ assert_not_include result, unexpected
+ assert_include result, CGI.escapeHTML(unexpected)
+ end
end
-
diff --git a/test/rdoc/test_rdoc_markup_to_html_crossref.rb b/test/rdoc/test_rdoc_markup_to_html_crossref.rb
index f6fabfb7db..dc4488195a 100644
--- a/test/rdoc/test_rdoc_markup_to_html_crossref.rb
+++ b/test/rdoc/test_rdoc_markup_to_html_crossref.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require File.expand_path '../xref_test_case', __FILE__
+require_relative 'xref_test_case'
class TestRDocMarkupToHtmlCrossref < XrefTestCase
@@ -17,6 +17,12 @@ class TestRDocMarkupToHtmlCrossref < XrefTestCase
assert_equal para("<a href=\"C1.html\"><code>C1</code></a>"), result
end
+ def test_convert_CROSSREF_method
+ result = @to.convert 'C1#m(foo, bar, baz)'
+
+ assert_equal para("<a href=\"C1.html#method-i-m\"><code>C1#m(foo, bar, baz)</code></a>"), result
+ end
+
def test_convert_CROSSREF_label
result = @to.convert 'C1@foo'
assert_equal para("<a href=\"C1.html#class-C1-label-foo\">foo at <code>C1</code></a>"), result
@@ -127,6 +133,18 @@ class TestRDocMarkupToHtmlCrossref < XrefTestCase
'rdoc-ref:C1@foo'
end
+ def test_convert_RDOCLINK_rdoc_ref_label_in_current_file
+ result = @to.convert 'rdoc-ref:@foo'
+
+ assert_equal para("<a href=\"#label-foo\">foo</a>"), result,
+ 'rdoc-ref:@foo'
+
+ result = @to.convert '{Foo}[rdoc-ref:@foo]'
+
+ assert_equal para("<a href=\"#label-foo\">Foo</a>"), result,
+ '{Foo}[rdoc-ref:@foo]'
+ end
+
def test_gen_url
assert_equal '<a href="C1.html">Some class</a>',
@to.gen_url('rdoc-ref:C1', 'Some class')
@@ -260,4 +278,3 @@ class TestRDocMarkupToHtmlCrossref < XrefTestCase
end
end
-
diff --git a/test/rdoc/test_rdoc_markup_to_joined_paragraph.rb b/test/rdoc/test_rdoc_markup_to_joined_paragraph.rb
index cbaf75a04e..8bd2d67247 100644
--- a/test/rdoc/test_rdoc_markup_to_joined_paragraph.rb
+++ b/test/rdoc/test_rdoc_markup_to_joined_paragraph.rb
@@ -30,4 +30,3 @@ class TestRDocMarkupToJoinedParagraph < RDoc::TestCase
end
end
-
diff --git a/test/rdoc/test_rdoc_markup_to_label.rb b/test/rdoc/test_rdoc_markup_to_label.rb
index 70ea7f0f1b..2bf2e0ecdf 100644
--- a/test/rdoc/test_rdoc_markup_to_label.rb
+++ b/test/rdoc/test_rdoc_markup_to_label.rb
@@ -110,4 +110,3 @@ class TestRDocMarkupToLabel < RDoc::Markup::FormatterTestCase
end
end
-
diff --git a/test/rdoc/test_rdoc_markup_to_markdown.rb b/test/rdoc/test_rdoc_markup_to_markdown.rb
index c8c5fd4d52..92ed37bc50 100644
--- a/test/rdoc/test_rdoc_markup_to_markdown.rb
+++ b/test/rdoc/test_rdoc_markup_to_markdown.rb
@@ -69,7 +69,7 @@ class TestRDocMarkupToMarkdown < RDoc::Markup::TextFormatterTestCase
end
def accept_list_item_end_label
- assert_equal "cat\n: ", @to.res.join
+ assert_equal "cat\n: \n", @to.res.join
assert_equal 0, @to.indent, 'indent'
end
@@ -79,7 +79,7 @@ class TestRDocMarkupToMarkdown < RDoc::Markup::TextFormatterTestCase
end
def accept_list_item_end_note
- assert_equal "cat\n: ", @to.res.join
+ assert_equal "cat\n: \n", @to.res.join
assert_equal 0, @to.indent, 'indent'
end
@@ -319,9 +319,7 @@ words words words words
expected = <<-EXPECTED
* l1
* l1.1
-
* l2
-
EXPECTED
assert_equal expected, @to.end_accepting
@@ -343,7 +341,6 @@ words words words words
* second
-
EXPECTED
assert_equal expected, @to.end_accepting
@@ -387,4 +384,3 @@ words words words words
end
end
-
diff --git a/test/rdoc/test_rdoc_markup_to_rdoc.rb b/test/rdoc/test_rdoc_markup_to_rdoc.rb
index 1d833b156a..50f4b6dc8b 100644
--- a/test/rdoc/test_rdoc_markup_to_rdoc.rb
+++ b/test/rdoc/test_rdoc_markup_to_rdoc.rb
@@ -69,7 +69,7 @@ class TestRDocMarkupToRDoc < RDoc::Markup::TextFormatterTestCase
end
def accept_list_item_end_label
- assert_equal "cat:\n", @to.res.join
+ assert_equal "[cat]\n", @to.res.join
assert_equal 0, @to.indent, 'indent'
end
@@ -79,7 +79,7 @@ class TestRDocMarkupToRDoc < RDoc::Markup::TextFormatterTestCase
end
def accept_list_item_end_note
- assert_equal "cat:\n", @to.res.join
+ assert_equal "cat::\n", @to.res.join
assert_equal 0, @to.indent, 'indent'
end
@@ -100,7 +100,7 @@ class TestRDocMarkupToRDoc < RDoc::Markup::TextFormatterTestCase
def accept_list_item_start_label
assert_equal [""], @to.res
- assert_equal "cat:\n ", @to.prefix
+ assert_equal "[cat]\n ", @to.prefix
assert_equal 2, @to.indent
end
@@ -115,7 +115,7 @@ class TestRDocMarkupToRDoc < RDoc::Markup::TextFormatterTestCase
def accept_list_item_start_note
assert_equal [""], @to.res
- assert_equal "cat:\n ", @to.prefix
+ assert_equal "cat::\n ", @to.prefix
assert_equal 2, @to.indent
end
@@ -243,16 +243,16 @@ class TestRDocMarkupToRDoc < RDoc::Markup::TextFormatterTestCase
end
def accept_list_item_start_note_2
- assert_equal "<tt>teletype</tt>:\n teletype description\n\n", @to.res.join
+ assert_equal "<tt>teletype</tt>::\n teletype description\n\n", @to.res.join
end
def accept_list_item_start_note_multi_description
- assert_equal "label:\n description one\n\n description two\n\n",
+ assert_equal "label::\n description one\n\n description two\n\n",
@to.res.join
end
def accept_list_item_start_note_multi_label
- assert_equal "one\ntwo:\n two headers\n\n", @to.res.join
+ assert_equal "one::\ntwo::\n two headers\n\n", @to.res.join
end
def accept_paragraph_b
@@ -355,8 +355,8 @@ bar ::
NOTE_LIST
expected = <<-EXPECTED
-foo
-bar:
+foo::
+bar::
hi
EXPECTED
@@ -375,4 +375,3 @@ bar:
end
end
-
diff --git a/test/rdoc/test_rdoc_markup_to_table_of_contents.rb b/test/rdoc/test_rdoc_markup_to_table_of_contents.rb
index 11ab6f197b..7512495aec 100644
--- a/test/rdoc/test_rdoc_markup_to_table_of_contents.rb
+++ b/test/rdoc/test_rdoc_markup_to_table_of_contents.rb
@@ -124,4 +124,3 @@ class TestRDocMarkupToTableOfContents < RDoc::Markup::FormatterTestCase
end
end
-
diff --git a/test/rdoc/test_rdoc_markup_to_tt_only.rb b/test/rdoc/test_rdoc_markup_to_tt_only.rb
index 8508f823df..c709d7a4d5 100644
--- a/test/rdoc/test_rdoc_markup_to_tt_only.rb
+++ b/test/rdoc/test_rdoc_markup_to_tt_only.rb
@@ -244,4 +244,3 @@ class TestRDocMarkupToTtOnly < RDoc::Markup::FormatterTestCase
end
end
-
diff --git a/test/rdoc/test_rdoc_markup_verbatim.rb b/test/rdoc/test_rdoc_markup_verbatim.rb
index 1a650c44ef..2f8a57266a 100644
--- a/test/rdoc/test_rdoc_markup_verbatim.rb
+++ b/test/rdoc/test_rdoc_markup_verbatim.rb
@@ -27,4 +27,3 @@ class TestRDocMarkupVerbatim < RDoc::TestCase
end
end
-
diff --git a/test/rdoc/test_rdoc_method_attr.rb b/test/rdoc/test_rdoc_method_attr.rb
index 68a9d6cc21..d607619a60 100644
--- a/test/rdoc/test_rdoc_method_attr.rb
+++ b/test/rdoc/test_rdoc_method_attr.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require File.expand_path '../xref_test_case', __FILE__
+require_relative 'xref_test_case'
class TestRDocMethodAttr < XrefTestCase
@@ -191,4 +191,3 @@ class TestRDocMethodAttr < XrefTestCase
end
end
-
diff --git a/test/rdoc/test_rdoc_normal_class.rb b/test/rdoc/test_rdoc_normal_class.rb
index 874eaaa88c..3d097ebb52 100644
--- a/test/rdoc/test_rdoc_normal_class.rb
+++ b/test/rdoc/test_rdoc_normal_class.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require File.expand_path '../xref_test_case', __FILE__
+require_relative 'xref_test_case'
class TestRDocNormalClass < XrefTestCase
@@ -11,7 +11,7 @@ class TestRDocNormalClass < XrefTestCase
sub_klass.superclass = klass
sub_klass.add_include incl
- assert_equal [incl.name, klass, 'Object'], sub_klass.ancestors
+ assert_equal [incl.name, klass, @object, 'BasicObject'], sub_klass.ancestors
end
def test_ancestors_multilevel
@@ -19,7 +19,7 @@ class TestRDocNormalClass < XrefTestCase
c2 = @top_level.add_class RDoc::NormalClass, 'Middle', c1.full_name
c3 = @top_level.add_class RDoc::NormalClass, 'Inner', c2.full_name
- assert_equal [c2, c1, 'Object'], c3.ancestors
+ assert_equal [c2, c1, @object, 'BasicObject'], c3.ancestors
end
def test_aref
@@ -45,4 +45,3 @@ class TestRDocNormalClass < XrefTestCase
end
end
-
diff --git a/test/rdoc/test_rdoc_normal_module.rb b/test/rdoc/test_rdoc_normal_module.rb
index 68e776c41f..cccee5c44c 100644
--- a/test/rdoc/test_rdoc_normal_module.rb
+++ b/test/rdoc/test_rdoc_normal_module.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require File.expand_path '../xref_test_case', __FILE__
+require_relative 'xref_test_case'
class TestRDocNormalModule < XrefTestCase
@@ -40,4 +40,3 @@ class TestRDocNormalModule < XrefTestCase
end
end
-
diff --git a/test/rdoc/test_rdoc_options.rb b/test/rdoc/test_rdoc_options.rb
index 7c264c5e86..5e8b1ae3d8 100644
--- a/test/rdoc/test_rdoc_options.rb
+++ b/test/rdoc/test_rdoc_options.rb
@@ -55,11 +55,10 @@ class TestRDocOptions < RDoc::TestCase
refute @options.dry_run
end
- def test_encode_with
- coder = {}
- class << coder; alias add []=; end
+ def test_to_yaml
+ RDoc.load_yaml
- @options.encode_with coder
+ coder = YAML.load(@options.to_yaml)
encoding = 'UTF-8'
@@ -69,7 +68,6 @@ class TestRDocOptions < RDoc::TestCase
'exclude' => %w[~\z \.orig\z \.rej\z \.bak\z \.gemspec\z],
'hyperlink_all' => false,
'line_numbers' => false,
- 'locale' => nil,
'locale_dir' => 'locale',
'locale_name' => nil,
'main_page' => nil,
@@ -84,15 +82,17 @@ class TestRDocOptions < RDoc::TestCase
'title' => nil,
'visibility' => :protected,
'webcvs' => nil,
+ 'skip_tests' => true,
}
assert_equal expected, coder
end
- def test_encode_with_trim_paths
+ def test_to_yaml_trim_paths
+ RDoc.load_yaml
+
subdir = nil
- coder = {}
- class << coder; alias add []=; end
+ coder = nil
temp_dir do |dir|
FileUtils.mkdir 'project'
@@ -113,7 +113,7 @@ class TestRDocOptions < RDoc::TestCase
--include /
]
- @options.encode_with coder
+ coder = YAML.load(@options.to_yaml)
end
end
@@ -145,7 +145,9 @@ class TestRDocOptions < RDoc::TestCase
@options.encoding = Encoding::IBM437
- options = YAML.safe_load(YAML.dump(@options), permitted_classes: [RDoc::Options, Symbol])
+ options = @options.to_yaml
+ options = YAML.safe_load(options, permitted_classes: [Symbol])
+ options = RDoc::Options.new(options)
assert_equal Encoding::IBM437, options.encoding
end
@@ -154,14 +156,15 @@ class TestRDocOptions < RDoc::TestCase
RDoc.load_yaml
yaml = <<-YAML
---- !ruby/object:RDoc::Options
+---
static_path:
- /etc
rdoc_include:
- /etc
YAML
- options = YAML.safe_load(yaml, permitted_classes: [RDoc::Options, Symbol])
+ options = YAML.safe_load(yaml, permitted_classes: [Symbol])
+ options = RDoc::Options.new(options)
assert_empty options.rdoc_include
assert_empty options.static_path
@@ -205,6 +208,13 @@ rdoc_include:
assert @options.force_update
end
+ def test_parse_coverage_C
+ @options.parse %w[-C]
+
+ assert @options.coverage_report
+ assert @options.force_update
+ end
+
def test_parse_coverage_no
@options.parse %w[--no-dcov]
@@ -217,6 +227,19 @@ rdoc_include:
assert_equal 1, @options.coverage_report
end
+ def test_parse_coverage_C_level_1
+ @options.parse %w[-C1]
+
+ assert_equal 1, @options.coverage_report
+ end
+
+ def test_parse_coverage_C_level_0
+ @options.parse %w[-C0]
+
+ assert_equal 0, @options.coverage_report
+ assert @options.force_update
+ end
+
def test_parse_dash_p
out, err = capture_output do
@options.parse %w[-p]
@@ -243,6 +266,7 @@ rdoc_include:
def test_parse_default
@options.parse []
+ @options.finish
assert_equal RDoc::Generator::Darkfish, @options.generator
assert_equal 'darkfish', @options.template
@@ -502,6 +526,7 @@ rdoc_include:
out, err = capture_output do
@options.parse %W[--page-dir #{Dir.tmpdir}]
+ @options.finish
end
assert_empty out
@@ -530,6 +555,7 @@ rdoc_include:
out, err = capture_output do
@options.parse %W[--page-dir #{abs_page_dir} --root #{abs_root}]
+ @options.finish
end
assert_empty out
@@ -558,6 +584,8 @@ rdoc_include:
assert_empty err
assert_equal Pathname(Dir.tmpdir), @options.root
+
+ @options.finish
assert_includes @options.rdoc_include, @options.root.to_s
end
@@ -602,6 +630,7 @@ rdoc_include:
assert_empty out
assert_equal "could not find template NONEXISTENT\n", err
+ @options.finish
assert_equal 'darkfish', @options.template
assert_match %r%rdoc/generator/template/darkfish$%, @options.template_dir
end
@@ -668,6 +697,7 @@ rdoc_include:
Dir.chdir tmpdir do
e = assert_raise SystemExit do
@options.parse %w[--write-options]
+ @options.finish
end
assert_equal 0, e.status
@@ -689,6 +719,28 @@ rdoc_include:
assert_empty err
end
+ def test_parse_locale_name_default
+ temp_dir do
+ @options.parse %w[]
+ assert_equal 'locale', @options.instance_variable_get(:@locale_dir)
+ assert_nil @options.instance_variable_get(:@locale_name)
+ assert_nil @options.locale
+ @options.finish
+ assert_nil @options.locale
+ end
+ end
+
+ def test_parse_locale_name
+ temp_dir do
+ @options.parse %w[--locale fr]
+ assert_equal 'locale', @options.instance_variable_get(:@locale_dir)
+ assert_equal 'fr', @options.instance_variable_get(:@locale_name)
+ assert_nil @options.locale
+ @options.finish
+ assert_equal 'fr', @options.locale.name
+ end
+ end
+
def test_setup_generator
test_generator = Class.new do
def self.setup_options op
@@ -764,7 +816,9 @@ rdoc_include:
assert File.exist? '.rdoc_options'
- assert_equal @options, YAML.safe_load(File.read('.rdoc_options'), permitted_classes: [RDoc::Options, Symbol])
+ options = File.read('.rdoc_options')
+ options = YAML.safe_load(options, permitted_classes: [Symbol])
+ assert_equal @options, RDoc::Options.new(options)
end
end
@@ -834,20 +888,44 @@ rdoc_include:
def test_load_options_partial_override
temp_dir do
File.open '.rdoc_options', 'w' do |io|
- io.write "markup: Markdown"
+ io.puts "markup: Markdown"
+ io.puts "encoding: iso-8859-1"
+ io.puts "static_path: [static]"
+ io.puts "rdoc_include: [.]"
+ io.puts "page_dir: pages"
end
options = RDoc::Options.load_options
assert_equal 'Markdown', options.markup
+ assert_equal Encoding::ISO_8859_1, options.encoding
+ assert_equal ["static"], options.static_path
+ assert_equal ["."], options.rdoc_include
+ assert_equal "pages", options.page_dir
end
end
- def load_options_no_file
+ def test_load_options_no_file
temp_dir do
options = RDoc::Options.load_options
assert_kind_of RDoc::Options, options
end
end
+
+ def test_skip_test_default_value
+ @options.parse %w[]
+ assert_equal true, @options.skip_tests
+ end
+
+ def test_no_skip_test_value
+ @options.parse %w[--no-skipping-tests]
+ assert_equal false, @options.skip_tests
+ end
+
+ class DummyCoder < Hash
+ alias add :[]=
+ def tag=(tag)
+ end
+ end
end
diff --git a/test/rdoc/test_rdoc_parser.rb b/test/rdoc/test_rdoc_parser.rb
index 7cc3c2d926..51a16ce361 100644
--- a/test/rdoc/test_rdoc_parser.rb
+++ b/test/rdoc/test_rdoc_parser.rb
@@ -3,16 +3,12 @@
require_relative 'helper'
-class TestRDocParser < RDoc::TestCase
-
+class RDocParserTest < RDoc::TestCase
def setup
super
@RP = RDoc::Parser
- @binary_dat = File.expand_path '../binary.dat', __FILE__
-
- @fn = 'file.rb'
- @top_level = RDoc::TopLevel.new @fn
+ @binary_dat_fixture_path = File.expand_path '../binary.dat', __FILE__
@options = RDoc::Options.new
end
@@ -71,7 +67,7 @@ class TestRDocParser < RDoc::TestCase
assert_equal @RP::Simple, @RP.can_parse(readme_file_name)
- assert_equal @RP::Simple, @RP.can_parse(@binary_dat)
+ assert_equal @RP::Simple, @RP.can_parse(@binary_dat_fixture_path)
jtest_file_name = File.expand_path '../test.ja.txt', __FILE__
assert_equal @RP::Simple, @RP.can_parse(jtest_file_name)
@@ -90,16 +86,12 @@ class TestRDocParser < RDoc::TestCase
end
def test_class_for_executable
- temp_dir do
- content = "#!/usr/bin/env ruby -w\n"
- File.open 'app', 'w' do |io| io.write content end
- app = @store.add_file 'app'
-
- parser = @RP.for app, 'app', content, @options, :stats
+ with_top_level("app", "#!/usr/bin/env ruby -w\n") do |top_level, content|
+ parser = @RP.for top_level, content, @options, :stats
assert_kind_of RDoc::Parser::Ruby, parser
- assert_equal 'app', parser.file_name
+ assert_equal top_level.absolute_name, parser.file_name
end
end
@@ -111,7 +103,7 @@ class TestRDocParser < RDoc::TestCase
File.chmod 0000, io.path
forbidden = @store.add_file io.path
- parser = @RP.for forbidden, 'forbidden', '', @options, :stats
+ parser = @RP.for forbidden, '', @options, :stats
assert_nil parser
ensure
@@ -123,13 +115,8 @@ class TestRDocParser < RDoc::TestCase
end
def test_class_for_modeline
- temp_dir do
- content = "# -*- rdoc -*-\n= NEWS\n"
-
- File.open 'NEWS', 'w' do |io| io.write content end
- app = @store.add_file 'NEWS'
-
- parser = @RP.for app, 'NEWS', content, @options, :stats
+ with_top_level("NEWS", "# -*- rdoc -*-\n= NEWS\n") do |top_level, content|
+ parser = @RP.for top_level, content, @options, :stats
assert_kind_of RDoc::Parser::Simple, parser
@@ -151,6 +138,20 @@ class TestRDocParser < RDoc::TestCase
File.unlink readme_ext
end
+ def test_can_parse_modeline_c
+ readme_inc = File.join Dir.tmpdir, "README.inc.#{$$}"
+
+ File.open readme_inc, 'w' do |io|
+ io.puts "/* README.inc - -*- c -*- created at: Mon Aug 7 16:45:54 JST 1995 */"
+ io.puts
+ io.puts "/* This document explains how to make extension libraries for Ruby. */"
+ end
+
+ assert_equal RDoc::Parser::C, @RP.can_parse(readme_inc)
+ ensure
+ File.unlink readme_inc
+ end
+
##
# Selenium hides a .jar file using a .txt extension.
@@ -212,25 +213,18 @@ class TestRDocParser < RDoc::TestCase
end
def test_class_for_binary
- rp = @RP.dup
-
- class << rp
- alias old_can_parse can_parse
+ dat_fixture = File.read(@binary_dat_fixture_path)
+ with_top_level("binary.dat", dat_fixture) do |top_level, content|
+ assert_nil @RP.for(top_level, content, @options, nil)
end
-
- def rp.can_parse(*args) nil end
-
- assert_nil @RP.for(nil, @binary_dat, nil, nil, nil)
end
def test_class_for_markup
- content = <<-CONTENT
-# coding: utf-8 markup: rd
- CONTENT
+ with_top_level("file.rb", "# coding: utf-8 markup: rd") do |top_level, content|
+ parser = @RP.for top_level, content, @options, nil
- parser = @RP.for @top_level, __FILE__, content, @options, nil
-
- assert_kind_of @RP::RD, parser
+ assert_kind_of @RP::RD, parser
+ end
end
def test_class_use_markup
@@ -315,9 +309,26 @@ class TestRDocParser < RDoc::TestCase
end
def test_initialize
- @RP.new @top_level, @fn, '', @options, nil
+ with_top_level("file.rb", "") do |top_level, content|
+ @RP.new top_level, top_level.absolute_name, content, @options, nil
+
+ assert_equal @RP, top_level.parser
+ end
+ end
- assert_equal @RP, @top_level.parser
+ private
+
+ def with_top_level(filename, content, &block)
+ absoluate_filename = File.join Dir.tmpdir, filename
+ File.open absoluate_filename, 'w' do |io|
+ io.write content
+ end
+
+ top_level = RDoc::TopLevel.new absoluate_filename
+
+ yield(top_level, content)
+ ensure
+ File.unlink absoluate_filename
end
end
diff --git a/test/rdoc/test_rdoc_parser_c.rb b/test/rdoc/test_rdoc_parser_c.rb
index 6601d28f60..ab4f149869 100644
--- a/test/rdoc/test_rdoc_parser_c.rb
+++ b/test/rdoc/test_rdoc_parser_c.rb
@@ -101,6 +101,31 @@ class TestRDocParserC < RDoc::TestCase
end
end
+ def test_known_classes
+ RDoc::KNOWN_CLASSES.each do |var, name|
+ case name
+ when "Refinement"
+ next unless defined?(Refinement)
+ when "RubyVM"
+ next unless defined?(RubyVM)
+ when "Bignum", "Fixnum", "Data", "Socket", /\A(?![A-Z])/
+ next
+ end
+ obj = Object.const_get(name)
+ assert_equal obj.name, name
+ case var
+ when /\Arb_c/
+ assert_kind_of Class, obj
+ when /\Arb_m/
+ assert_kind_of Module, obj
+ when /\Arb_e/
+ assert_operator obj, :<=, Exception
+ else
+ raise "unknown prefix: #{var} => #{name}"
+ end
+ end
+ end
+
def test_initialize
some_ext = @top_level.add_class RDoc::NormalClass, 'SomeExt'
@top_level.add_class RDoc::SingleClass, 'SomeExtSingle'
@@ -132,7 +157,7 @@ class TestRDocParserC < RDoc::TestCase
assert_equal expected, known_classes
end
- def test_do_attr_rb_attr
+ def assert_do_attr(flags)
content = <<-EOF
void Init_Blah(void) {
cBlah = rb_define_class("Blah", rb_cObject);
@@ -140,17 +165,17 @@ void Init_Blah(void) {
/*
* This is an accessor
*/
- rb_attr(cBlah, rb_intern("accessor"), 1, 1, Qfalse);
+ #{yield "cBlah", "accessor", flags[1], flags[1]};
/*
* This is a reader
*/
- rb_attr(cBlah, rb_intern("reader"), 1, 0, Qfalse);
+ #{yield "cBlah", "reader", flags[1], flags[0]};
/*
* This is a writer
*/
- rb_attr(cBlah, rb_intern("writer"), 0, 1, Qfalse);
+ #{yield "cBlah", "writer", flags[0], flags[1]};
}
EOF
@@ -176,72 +201,21 @@ void Init_Blah(void) {
assert_equal 'This is a writer', writer.comment.text
end
- def test_do_attr_rb_attr_2
- content = <<-EOF
-void Init_Blah(void) {
- cBlah = rb_define_class("Blah", rb_cObject);
-
- /*
- * This is an accessor
- */
- rb_attr(cBlah, rb_intern_const("accessor"), 1, 1, Qfalse);
-
- /*
- * This is a reader
- */
- rb_attr(cBlah, rb_intern_const("reader"), 1, 0, Qfalse);
-
- /*
- * This is a writer
- */
- rb_attr(cBlah, rb_intern_const("writer"), 0, 1, Qfalse);
-}
- EOF
-
- klass = util_get_class content, 'cBlah'
-
- attrs = klass.attributes
- assert_equal 3, attrs.length, attrs.inspect
-
- accessor = attrs.shift
- assert_equal 'accessor', accessor.name
- assert_equal 'RW', accessor.rw
- assert_equal 'This is an accessor', accessor.comment.text
- assert_equal @top_level, accessor.file
-
- reader = attrs.shift
- assert_equal 'reader', reader.name
- assert_equal 'R', reader.rw
- assert_equal 'This is a reader', reader.comment.text
-
- writer = attrs.shift
- assert_equal 'writer', writer.name
- assert_equal 'W', writer.rw
- assert_equal 'This is a writer', writer.comment.text
- end
-
- def test_do_attr_rb_define_attr
- content = <<-EOF
-void Init_Blah(void) {
- cBlah = rb_define_class("Blah", rb_cObject);
-
- /*
- * This is an accessor
- */
- rb_define_attr(cBlah, "accessor", 1, 1);
-}
- EOF
-
- klass = util_get_class content, 'cBlah'
-
- attrs = klass.attributes
- assert_equal 1, attrs.length, attrs.inspect
-
- accessor = attrs.shift
- assert_equal 'accessor', accessor.name
- assert_equal 'RW', accessor.rw
- assert_equal 'This is an accessor', accessor.comment.text
- assert_equal @top_level, accessor.file
+ {
+ num: %w[0 1],
+ macro: %w[FALSE TRUE],
+ ruby: %w[Qfalse Qtrue],
+ bool: %w[false true],
+ }.each_pair do |name, values|
+ define_method("test_do_attr:rb_attr:intern:#{name}") do
+ assert_do_attr(values) {|c, name, r, w| %[rb_attr(#{c}, rb_intern("#{name}"), #{r}, #{w}, Qfalse)]}
+ end
+ define_method("test_do_attr:rb_attr:intern_const:#{name}") do
+ assert_do_attr(values) {|c, name, r, w| %[rb_attr(#{c}, rb_intern_const("#{name}"), #{r}, #{w}, Qfalse)]}
+ end
+ define_method("test_do_attr:rb_define_attr:#{name}") do
+ assert_do_attr(values) {|c, name, r, w| %[rb_define_attr(#{c}, "#{name}", #{r}, #{w})]}
+ end
end
def test_do_aliases
@@ -355,6 +329,47 @@ VALUE cFoo = rb_define_class("Foo", rb_cObject);
/* Document-class: Foo
* this is the Foo class
*/
+VALUE cFoo = rb_struct_define(
+ "Foo",
+ "some", "various", "fields", NULL);
+ EOF
+
+ klass = util_get_class content, 'cFoo'
+ assert_equal "this is the Foo class", klass.comment.text
+
+ attributes = klass.attributes
+ assert_equal 3, attributes.size, -> {attributes}
+ ["some", "various", "fields"].zip(attributes) do |name, attr|
+ assert_equal RDoc::Attr.new("", name, "RW", ""), attr
+ end
+ end
+
+ def test_do_classes_struct_under
+ content = <<-EOF
+/* Document-class: Kernel::Foo
+ * this is the Foo class under Kernel
+ */
+VALUE cFoo = rb_struct_define_under(
+ rb_mKernel, "Foo",
+ "some", "various", "fields", NULL);
+ EOF
+
+ klass = util_get_class content, 'cFoo'
+ assert_equal 'Kernel::Foo', klass.full_name
+ assert_equal "this is the Foo class under Kernel", klass.comment.text
+
+ attributes = klass.attributes
+ assert_equal 3, attributes.size, -> {attributes}
+ ["some", "various", "fields"].zip(attributes) do |name, attr|
+ assert_equal RDoc::Attr.new("", name, "RW", ""), attr
+ end
+ end
+
+ def test_do_classes_struct_without_accessor
+ content = <<-EOF
+/* Document-class: Foo
+ * this is the Foo class
+ */
VALUE cFoo = rb_struct_define_without_accessor(
"Foo", rb_cObject, foo_alloc,
"some", "various", "fields", NULL);
@@ -362,6 +377,23 @@ VALUE cFoo = rb_struct_define_without_accessor(
klass = util_get_class content, 'cFoo'
assert_equal "this is the Foo class", klass.comment.text
+ assert_empty klass.attributes
+ end
+
+ def test_do_classes_struct_without_accessor_under
+ content = <<-EOF
+/* Document-class: Kernel::Foo
+ * this is the Foo class under Kernel
+ */
+VALUE cFoo = rb_struct_define_without_accessor_under(
+ rb_mKernel, "Foo", rb_cObject, foo_alloc,
+ "some", "various", "fields", NULL);
+ EOF
+
+ klass = util_get_class content, 'cFoo'
+ assert_equal 'Kernel::Foo', klass.full_name
+ assert_equal "this is the Foo class under Kernel", klass.comment.text
+ assert_empty klass.attributes
end
def test_do_classes_class_under
@@ -428,7 +460,7 @@ VALUE mFoo = rb_define_module_under(rb_mKernel, "Foo");
end
def test_do_constants
- content = <<-EOF
+ content = <<-'EOF'
#include <ruby.h>
void Init_foo(){
@@ -443,6 +475,9 @@ void Init_foo(){
/* TEST\:TEST: Checking to see if escaped colon works */
rb_define_const(cFoo, "TEST", rb_str_new2("TEST:TEST"));
+ /* TEST: TEST:Checking to see if only word-ending colon works */
+ rb_define_const(cFoo, "TEST2", rb_str_new2("TEST:TEST"));
+
/* \\: The file separator on MS Windows */
rb_define_const(cFoo, "MSEPARATOR", rb_str_new2("\\"));
@@ -506,6 +541,9 @@ void Init_foo(){
assert_equal ['TEST', 'TEST:TEST',
'Checking to see if escaped colon works '],
constants.shift
+ assert_equal ['TEST2', 'TEST',
+ 'TEST:Checking to see if only word-ending colon works '],
+ constants.shift
assert_equal ['MSEPARATOR', '\\',
'The file separator on MS Windows '],
constants.shift
@@ -545,8 +583,6 @@ void Init_curses(){
mCurses = rb_define_module("Curses");
/*
- * Document-const: Curses::COLOR_BLACK
- *
* Value of the color black
*/
rb_curses_define_const(COLOR_BLACK);
@@ -571,8 +607,7 @@ void Init_curses(){
def test_do_constants_file
content = <<-EOF
void Init_File(void) {
- /* Document-const: LOCK_SH
- *
+ /*
* Shared lock
*/
rb_file_const("LOCK_SH", INT2FIX(LOCK_SH));
@@ -594,6 +629,17 @@ void Init_File(void) {
assert_equal 'LOCK_SH', constant.name
assert_equal 'INT2FIX(LOCK_SH)', constant.value
assert_equal 'Shared lock', constant.comment.text
+
+ @parser = util_parser <<-EOF
+void Init_File(void) {
+ rb_cFile = rb_define_class("File", rb_cIO);
+ rb_mFConst = rb_define_module_under(rb_cFile, "Constants");
+}
+ EOF
+ @parser.do_classes_and_modules
+ @parser.do_constants
+
+ assert_equal 'File::Constants', klass.full_name
end
def test_do_includes
@@ -853,6 +899,23 @@ Init_Foo(void) {
assert_equal "a comment for class Foo", klass.comment.text
end
+
+ def test_find_class_comment_initvm
+ content = <<-EOF
+/*
+ * a comment for class Foo
+ */
+void
+InitVM_Foo(void) {
+ VALUE foo = rb_define_class("Foo", rb_cObject);
+}
+ EOF
+
+ klass = util_get_class content, 'foo'
+
+ assert_equal "a comment for class Foo", klass.comment.text
+ end
+
def test_find_class_comment_define_class
content = <<-EOF
/*
@@ -1313,6 +1376,36 @@ Init_Foo(void) {
assert_equal "DLL_LOCAL VALUE\nother_function() {\n}", code
end
+ def test_find_body_static_inline
+ content = <<-EOF
+/*
+ * a comment for other_function
+ */
+static inline VALUE
+other_function() {
+}
+
+void
+Init_Foo(void) {
+ VALUE foo = rb_define_class("Foo", rb_cObject);
+
+ rb_define_method(foo, "my_method", other_function, 0);
+}
+ EOF
+
+ klass = util_get_class content, 'foo'
+ other_function = klass.method_list.first
+
+ assert_equal 'my_method', other_function.name
+ assert_equal "a comment for other_function",
+ other_function.comment.text
+ assert_equal '()', other_function.params
+
+ code = other_function.token_stream.first[:text]
+
+ assert_equal "static inline VALUE\nother_function() {\n}", code
+ end
+
def test_find_modifiers_call_seq
comment = RDoc::Comment.new <<-COMMENT
call-seq:
@@ -1600,6 +1693,39 @@ Init_IO(void) {
assert_equal "Method Comment! ", read_method.comment.text
assert_equal "rb_io_s_read", read_method.c_function
assert read_method.singleton
+ assert_nil read_method.section.title
+ end
+
+ def test_define_method_with_category
+ content = <<-EOF
+/* :category: Awesome Methods
+ Method Comment!
+ */
+static VALUE
+rb_io_s_read(argc, argv, io)
+ int argc;
+ VALUE *argv;
+ VALUE io;
+{
+}
+
+void
+Init_IO(void) {
+ /*
+ * a comment for class Foo on rb_define_class
+ */
+ VALUE rb_cIO = rb_define_class("IO", rb_cObject);
+ rb_define_singleton_method(rb_cIO, "read", rb_io_s_read, -1);
+}
+ EOF
+
+ klass = util_get_class content, 'rb_cIO'
+ read_method = klass.method_list.first
+ assert_equal "read", read_method.name
+ assert_equal "Method Comment!", read_method.comment.text.strip
+ assert_equal "rb_io_s_read", read_method.c_function
+ assert read_method.singleton
+ assert_equal "Awesome Methods", read_method.section.title
end
def test_define_method_dynamically
@@ -1930,6 +2056,39 @@ void d(void) {
@store.all_classes_and_modules.map { |m| m.full_name }.sort
end
+ def test_markup_format_default
+ content = <<-EOF
+void Init_Blah(void) {
+ cBlah = rb_define_class("Blah", rb_cObject);
+
+ /*
+ * This should be interpreted in the default format.
+ */
+ rb_attr(cBlah, rb_intern("default_format"), 1, 1, Qfalse);
+}
+ EOF
+
+ klass = util_get_class content, 'cBlah'
+ assert_equal("rdoc", klass.attributes.find {|a| a.name == "default_format"}.comment.format)
+ end
+
+ def test_markup_format_override
+ content = <<-EOF
+void Init_Blah(void) {
+ cBlah = rb_define_class("Blah", rb_cObject);
+
+ /*
+ * This should be interpreted in the default format.
+ */
+ rb_attr(cBlah, rb_intern("default_format"), 1, 1, Qfalse);
+}
+ EOF
+
+ @options.markup = "markdown"
+ klass = util_get_class content, 'cBlah'
+ assert_equal("markdown", klass.attributes.find {|a| a.name == "default_format"}.comment.format)
+ end
+
def util_get_class content, name = nil
@parser = util_parser content
@parser.scan
@@ -1942,4 +2101,3 @@ void d(void) {
end
end
-
diff --git a/test/rdoc/test_rdoc_parser_changelog.rb b/test/rdoc/test_rdoc_parser_changelog.rb
index 6584840572..587a156d3a 100644
--- a/test/rdoc/test_rdoc_parser_changelog.rb
+++ b/test/rdoc/test_rdoc_parser_changelog.rb
@@ -482,4 +482,3 @@ ChangeLog
RDoc::Parser::ChangeLog::Git::LogEntry.new(*a)
end
end
-
diff --git a/test/rdoc/test_rdoc_parser_markdown.rb b/test/rdoc/test_rdoc_parser_markdown.rb
index 06c6700d96..cca9c1ddfd 100644
--- a/test/rdoc/test_rdoc_parser_markdown.rb
+++ b/test/rdoc/test_rdoc_parser_markdown.rb
@@ -59,4 +59,3 @@ class TestRDocParserMarkdown < RDoc::TestCase
end
end
-
diff --git a/test/rdoc/test_rdoc_parser_prism_ruby.rb b/test/rdoc/test_rdoc_parser_prism_ruby.rb
new file mode 100644
index 0000000000..2ff11bb1a7
--- /dev/null
+++ b/test/rdoc/test_rdoc_parser_prism_ruby.rb
@@ -0,0 +1,1997 @@
+# frozen_string_literal: true
+
+require_relative 'helper'
+require 'rdoc/parser'
+require 'rdoc/parser/prism_ruby'
+
+module RDocParserPrismTestCases
+ def setup
+ super
+
+ @tempfile = Tempfile.new self.class.name
+ @filename = @tempfile.path
+
+ @top_level = @store.add_file @filename
+
+ @options = RDoc::Options.new
+ @options.quiet = true
+ @options.option_parser = OptionParser.new
+
+ @comment = RDoc::Comment.new '', @top_level
+
+ @stats = RDoc::Stats.new @store, 0
+ end
+
+ def teardown
+ super
+
+ @tempfile.close!
+ end
+
+ def test_look_for_directives_in_section
+ util_parser <<~RUBY
+ # :section: new section
+ RUBY
+ section = @top_level.current_section
+ assert_equal 'new section', section.title
+ end
+
+ def test_look_for_directives_in_commented
+ util_parser <<~RUBY
+ # how to make a section:
+ # # :section: new section
+ RUBY
+ section = @top_level.current_section
+ assert_nil section.title
+ end
+
+ def test_look_for_directives_in_unhandled
+ util_parser <<~RUBY
+ # :unhandled: blah
+ RUBY
+ assert_equal 'blah', @top_level.metadata['unhandled']
+ end
+
+ def test_block_comment
+ util_parser <<~RUBY
+ =begin rdoc
+ foo
+ =end
+ class A
+ =begin
+ bar
+ baz
+ =end
+ def f; end
+ end
+ RUBY
+ klass = @top_level.classes.first
+ meth = klass.method_list.first
+ assert_equal 'foo', klass.comment.text.strip
+ assert_equal "bar\nbaz", meth.comment.text.strip
+ end
+
+ def test_module
+ util_parser <<~RUBY
+ # my module
+ module Foo
+ end
+ RUBY
+ mod = @top_level.modules.first
+ assert_equal 'Foo', mod.full_name
+ assert_equal 'my module', mod.comment.text
+ assert_equal [@top_level], mod.in_files
+ end
+
+ def test_nested_module_with_colon
+ util_parser <<~RUBY
+ module Foo
+ module Bar; end
+ module Bar::Baz1; end
+ module ::Foo
+ module Bar2; end
+ end
+ end
+ module ::Baz; end
+ module Foo::Bar::Baz2
+ module ::Foo2
+ module Bar; end
+ end
+ module Blah; end
+ end
+ RUBY
+ module_names = @store.all_modules.map(&:full_name)
+ expected = %w[
+ Foo Foo::Bar Foo::Bar::Baz1 Foo::Bar2 Baz Foo::Bar::Baz2 Foo2 Foo2::Bar Foo::Bar::Baz2::Blah
+ ]
+ assert_equal expected.sort, module_names.sort
+ end
+
+ def test_class
+ util_parser <<~RUBY
+ # my class
+ class Foo
+ end
+ RUBY
+ klass = @top_level.classes.first
+ assert_equal 'Foo', klass.full_name
+ assert_equal 'my class', klass.comment.text
+ assert_equal [@top_level], klass.in_files
+ assert_equal 2, klass.line
+ end
+
+ def test_nested_class_with_colon
+ util_parser <<~RUBY
+ class Foo
+ class Bar; end
+ class Bar::Baz1; end
+ class ::Foo
+ class Bar2; end
+ end
+ end
+ class ::Baz; end
+ class Foo::Bar::Baz2
+ class ::Foo2
+ class Bar; end
+ end
+ class Blah; end
+ end
+ RUBY
+ class_names = @store.all_classes.map(&:full_name)
+ expected = %w[
+ Foo Foo::Bar Foo::Bar::Baz1 Foo::Bar2 Baz Foo::Bar::Baz2 Foo2 Foo2::Bar Foo::Bar::Baz2::Blah
+ ]
+ assert_equal expected.sort, class_names.sort
+ end
+
+ def test_open_class_with_superclass
+ util_parser <<~RUBY
+ class A; end
+
+ class B < A
+ def m1; end
+ end
+
+ class B < A
+ def m2; end
+ end
+
+ class C < String
+ def m1; end
+ end
+
+ class C < String
+ def m2; end
+ end
+ RUBY
+ classes = @top_level.classes
+ assert_equal 3, classes.size
+ _a, b, c = classes
+ assert_equal 'A', b.superclass.full_name
+ assert_equal 'String', c.superclass
+ assert_equal ['m1', 'm2'], b.method_list.map(&:name)
+ assert_equal ['m1', 'm2'], c.method_list.map(&:name)
+ end
+
+ def test_confusing_superclass
+ util_parser <<~RUBY
+ module A
+ class B; end
+ end
+
+ module A
+ class C1 < A::B; end
+ end
+
+ class A::C2 < A::B; end
+
+ module A::A
+ class B; end
+ end
+
+ module A
+ class C3 < A::B; end
+ end
+
+ class A::C4 < A::B; end
+ RUBY
+ mod = @top_level.modules.first
+ classes = mod.classes
+ assert_equal ['A::B', 'A::C1', 'A::C2', 'A::C3', 'A::C4'], classes.map(&:full_name)
+ assert_equal ['A::B', 'A::B', 'A::A::B', 'A::B'], classes.drop(1).map(&:superclass).map(&:full_name)
+ end
+
+ def test_class_module_nodoc
+ util_parser <<~RUBY
+ class Foo # :nodoc:
+ end
+
+ class Bar
+ end # :nodoc:
+
+ class Baz; end
+
+ class Baz::A; end # :nodoc:
+
+ module MFoo # :nodoc:
+ end
+
+ module MBar
+ end # :nodoc:
+
+ module MBaz; end
+
+ module MBaz::M; end; # :nodoc:
+ RUBY
+ documentables = @store.all_classes_and_modules.select(&:document_self)
+ assert_equal ['Baz', 'MBaz'], documentables.map(&:full_name) unless accept_legacy_bug?
+ end
+
+ def test_class_module_stopdoc
+ util_parser <<~RUBY
+ # comment
+ class Foo
+ class A; end
+ # :stopdoc:
+ class B; end
+ end
+
+ # comment
+ module Bar
+ module A; end
+ # :stopdoc:
+ module B; end
+ end
+ RUBY
+ klass = @top_level.classes.first
+ mod = @top_level.modules.first
+ assert_equal 'comment', klass.comment.text.strip
+ assert_equal 'comment', mod.comment.text.strip
+ assert_equal ['Foo::A'], klass.classes.select(&:document_self).map(&:full_name)
+ assert_equal ['Bar::A'], mod.modules.select(&:document_self).map(&:full_name)
+ end
+
+ def test_class_superclass
+ util_parser <<~RUBY
+ class Foo; end
+ class Bar < Foo
+ end
+ class Baz < (any expression)
+ end
+ RUBY
+ assert_equal ['Foo', 'Bar', 'Baz'], @top_level.classes.map(&:full_name)
+ foo, bar, baz = @top_level.classes
+ assert_equal foo, bar.superclass
+ assert_equal 'Object', baz.superclass unless accept_legacy_bug?
+ end
+
+ def test_class_new_notnew
+ util_parser <<~RUBY
+ class A
+ def initialize(*args); end
+ end
+
+ class B
+ ##
+ # :args: a, b, c
+ def initialize(*args); end
+ end
+
+ class C
+ def self.initialize(*args); end
+ end
+
+ class D
+ ##
+ # :args: a, b, c
+ def initialize(*args); end # :notnew:
+ end
+
+ class E
+ def initialize(*args); end # :not-new:
+ end
+
+ class F
+ def initialize(*args); end # :not_new:
+ end
+
+ class G
+ def initialize(*args)
+ end # :notnew:
+ end
+ RUBY
+
+ expected = [
+ 'new(*args)', 'new(a, b, c)',
+ 'initialize(*args)', 'initialize(a, b, c)',
+ 'initialize(*args)', 'initialize(*args)',
+ 'initialize(*args)'
+ ]
+ arglists = @top_level.classes.map { |c| c.method_list.first.arglists }
+ assert_equal expected, arglists
+ end
+
+ def test_class_mistaken_for_module
+ util_parser <<~RUBY
+ class A::Foo; end
+ class B::Foo; end
+ module C::Bar; end
+ module D::Baz; end
+ class A; end
+ class X < C; end
+ RUBY
+ assert_equal ['A', 'C', 'X'], @top_level.classes.map(&:full_name)
+ assert_equal ['B', 'D'], @top_level.modules.map(&:full_name)
+ end
+
+ def test_parenthesized_cdecl
+ util_parser <<~RUBY
+ module DidYouMean
+ # Not a module, but creates a dummy module for document
+ class << (NameErrorCheckers = Object.new)
+ def new; end
+ end
+ end
+ RUBY
+
+ mod = @store.find_class_or_module('DidYouMean').modules.first
+ assert_equal 'DidYouMean::NameErrorCheckers', mod.full_name
+ assert_equal ['DidYouMean::NameErrorCheckers::new'], mod.method_list.map(&:full_name)
+ end
+
+
+ def test_ghost_method
+ util_parser <<~RUBY
+ class Foo
+ ##
+ # :method: one
+ #
+ # my method one
+
+ ##
+ # :method:
+ # :call-seq:
+ # two(name)
+ #
+ # my method two
+
+ ##
+ # :method: three
+ # :args: a, b
+ #
+ # my method three
+
+ # :stopdoc:
+
+ ##
+ # :method: hidden1
+ #
+ # comment
+
+ ##
+ # :method:
+ # :call-seq:
+ # hidden2(name)
+ #
+ # comment
+ end
+ RUBY
+
+ klass = @store.find_class_named 'Foo'
+ assert_equal 3, klass.method_list.size
+ one, two, three = klass.method_list
+ assert_equal 'Foo#one', one.full_name
+ assert_equal 'Foo#two', two.full_name
+ assert_equal 'Foo#three', three.full_name
+ assert_equal 'two(name)', two.call_seq.chomp
+ assert_equal 'three(a, b)', three.arglists
+ assert_equal 'my method one', one.comment.text.strip
+ assert_equal 'my method two', two.comment.text.strip
+ assert_equal 'my method three', three.comment.text.strip
+ assert_equal 3, one.line
+ assert_equal 8, two.line
+ assert_equal 15, three.line
+ assert_equal @top_level, one.file
+ assert_equal @top_level, two.file
+ assert_equal @top_level, three.file
+ end
+
+ def test_invalid_meta_method
+ util_parser <<~RUBY
+ class Foo
+ # These are invalid meta method comments
+ # because meta method comment should start with `##`
+ # but rdoc accepts them as meta method comments for now.
+
+ # :method: m1
+
+ # :singleton-method: sm1
+
+ # :attr: a1
+
+ # :attr_reader: ar1
+
+ # :attr_writer: aw1
+
+ # :attr_accessor: arw1
+
+ # If there is a node following meta-like normal comment, it is not a meta method comment
+
+ # :method: m2
+ add_my_method(name)
+
+ # :singleton-method: sm2
+ add_my_singleton_method(name)
+
+ # :method:
+ add_my_method(:m3)
+
+ # :singleton-method:
+ add_my_singleton_method(:sm3)
+
+ # :attr:
+ add_my_attribute(:a2)
+
+ # :attr-reader:
+ add_my_attribute(:ar2)
+
+ # :attr-writer:
+ add_my_attribute(:aw2)
+
+ # :attr-accessor:
+ add_my_attribute(:arw2)
+
+ # :attr: a3
+ add_my_attribute_a3
+
+ # :attr-reader: ar3
+ add_my_attribute_ar3
+
+ # :attr-writer: aw3
+ add_my_attribute_aw2
+
+ # :attr-accessor: arw3
+ add_my_attribute_arw3
+ end
+ RUBY
+
+ klass = @store.find_class_named 'Foo'
+ assert_equal ['m1', 'sm1'], klass.method_list.map(&:name)
+ assert_equal ['a1', 'ar1', 'aw1', 'arw1'], klass.attributes.map(&:name)
+ end
+
+ def test_unknown_meta_method
+ util_parser <<~RUBY
+ class Foo
+ ##
+ # :call-seq:
+ # two(name)
+ #
+ # method or singleton-method directive is missing
+ end
+
+ class Bar
+ ##
+ # unknown meta method
+ add_my_method("foo" + "bar")
+ end
+ RUBY
+
+ foo = @store.find_class_named 'Foo'
+ bar = @store.find_class_named 'Bar'
+ assert_equal [], foo.method_list.map(&:name)
+ assert_equal ['unknown'], bar.method_list.map(&:name)
+ end
+
+ def test_method
+ util_parser <<~RUBY
+ class Foo
+ # my method one
+ def one; end
+ # my method two
+ def two(x); end
+ # my method three
+ def three x; end
+ end
+ RUBY
+
+ klass = @store.find_class_named 'Foo'
+ assert_equal 3, klass.method_list.size
+ one, two, three = klass.method_list
+ assert_equal 'Foo#one', one.full_name
+ assert_equal 'Foo#two', two.full_name
+ assert_equal 'Foo#three', three.full_name
+ assert_equal 'one()', one.arglists
+ assert_equal 'two(x)', two.arglists
+ assert_equal 'three(x)', three.arglists unless accept_legacy_bug?
+ assert_equal 'my method one', one.comment.text.strip
+ assert_equal 'my method two', two.comment.text.strip
+ assert_equal 'my method three', three.comment.text.strip
+ assert_equal 3, one.line
+ assert_equal 5, two.line
+ assert_equal 7, three.line
+ assert_equal @top_level, one.file
+ assert_equal @top_level, two.file
+ assert_equal @top_level, three.file
+ end
+
+ def test_method_toplevel
+ util_parser <<~RUBY
+ # comment
+ def foo; end
+ RUBY
+
+ object = @store.find_class_named 'Object'
+ foo = object.method_list.first
+ assert_equal 'Object#foo', foo.full_name
+ assert_equal 'comment', foo.comment.text.strip
+ assert_equal @top_level, foo.file
+ end
+
+ def test_meta_method
+ util_parser <<~RUBY
+ class Foo
+ ##
+ # my method
+ add_my_method :method_foo, :arg
+ end
+ RUBY
+
+ klass = @store.find_class_named 'Foo'
+ assert_equal 1, klass.method_list.size
+ method = klass.method_list.first
+ assert_equal 'Foo#method_foo', method.full_name
+ assert_equal 'my method', method.comment.text.strip
+ assert_equal 4, method.line
+ assert_equal @top_level, method.file
+ end
+
+ def test_first_comment_is_not_a_meta_method
+ util_parser <<~RUBY
+ ##
+ # first comment is not a meta method
+ add_my_method :foo
+
+ ##
+ # this is a meta method
+ add_my_method :bar
+ RUBY
+
+ object = @store.find_class_named 'Object'
+ assert_equal ['bar'], object.method_list.map(&:name)
+ end
+
+ def test_meta_method_unknown
+ util_parser <<~RUBY
+ class Foo
+ ##
+ # my method
+ add_my_method (:foo), :bar
+ end
+ RUBY
+
+ klass = @store.find_class_named 'Foo'
+ assert_equal 1, klass.method_list.size
+ method = klass.method_list.first
+ assert_equal 'Foo#unknown', method.full_name
+ assert_equal 'my method', method.comment.text.strip
+ assert_equal 4, method.line
+ assert_equal @top_level, method.file
+ end
+
+ def test_meta_define_method
+ util_parser <<~RUBY
+ class Foo
+ ##
+ # comment 1
+ define_method :foo do end
+ ##
+ # comment 2
+ define_method :bar, ->{}
+ # not a meta comment, not a meta method
+ define_method :ignored do end
+ class << self
+ ##
+ # comment 3
+ define_method :baz do end
+ end
+ end
+ RUBY
+
+ klass = @store.find_class_named 'Foo'
+ klass.method_list.last.singleton = true if accept_legacy_bug?
+ assert_equal 3, klass.method_list.size
+ assert_equal ['Foo#foo', 'Foo#bar', 'Foo::baz'], klass.method_list.map(&:full_name)
+ assert_equal [false, false, true], klass.method_list.map(&:singleton)
+ assert_equal ['comment 1', 'comment 2', 'comment 3'], klass.method_list.map { |m| m.comment.text.strip }
+ assert_equal [4, 7, 13], klass.method_list.map(&:line)
+ assert_equal [@top_level] * 3, klass.method_list.map(&:file)
+ end
+
+ def test_method_definition_nested_inside_block
+ util_parser <<~RUBY
+ module A
+ extend ActiveSupport::Concern
+ included do
+ ##
+ # :singleton-method:
+ # comment foo
+ mattr_accessor :foo
+
+ ##
+ # :method: bar
+ # comment bar
+ add_my_method :bar
+ end
+
+ tap do
+ # comment baz1
+ def baz1; end
+ end
+
+ self.tap do
+ # comment baz2
+ def baz2; end
+ end
+
+ my_decorator def self.baz3; end
+
+ self.my_decorator def baz4; end
+ end
+ RUBY
+ mod = @store.find_module_named 'A'
+ methods = mod.method_list
+ assert_equal ['A::foo', 'A#bar', 'A#baz1', 'A#baz2', 'A::baz3', 'A#baz4'], methods.map(&:full_name)
+ assert_equal ['comment foo', 'comment bar', 'comment baz1', 'comment baz2'], methods.take(4).map { |m| m.comment.text.strip }
+ end
+
+ def test_method_yields_directive
+ util_parser <<~RUBY
+ class Foo
+ def f1(a, &b); end
+
+ def f2
+ def o.foo
+ yield :dummy
+ end
+ yield
+ end
+
+ def f3(&b)
+ yield a, *b, c: 1
+ yield 1, 2, 3
+ end
+
+ def f4(a, &b) # :yields: d, e
+ yields 1, 2
+ end
+
+ def f5 # :yield: f
+ yields 1, 2
+ end
+
+ def f6; end # :yields:
+
+ ##
+ # :yields: g, h
+ add_my_method :f7
+ end
+ RUBY
+
+ klass = @top_level.classes.first
+ methods = klass.method_list
+ expected = [
+ 'f1(a, &b)',
+ 'f2() { || ... }',
+ 'f3() { |a, *b, c: 1| ... }',
+ 'f4(a) { |d, e| ... }',
+ 'f5() { |f| ... }',
+ 'f6() { || ... }',
+ 'f7() { |g, h| ... }'
+ ]
+ assert_equal expected, methods.map(&:arglists)
+ end
+
+ def test_calls_super
+ util_parser <<~RUBY
+ class A
+ def m1; foo; bar; end
+ def m2; if cond; super(a); end; end # SuperNode
+ def m3; tap do; super; end; end # ForwardingSuperNode
+ def m4; def a.b; super; end; end # super inside another method
+ end
+ RUBY
+
+ klass = @store.find_class_named 'A'
+ methods = klass.method_list
+ assert_equal ['m1', 'm2', 'm3', 'm4'], methods.map(&:name)
+ assert_equal [false, true, true, false], methods.map(&:calls_super)
+ end
+
+ def test_method_args_directive
+ util_parser <<~RUBY
+ class Foo
+ def method1 # :args: a, b, c
+ end
+
+ ##
+ # :args: d, e, f
+ def method2(*args); end
+
+ ##
+ # :args: g, h
+ add_my_method :method3
+ end
+ RUBY
+
+ klass = @top_level.classes.first
+ methods = klass.method_list
+ assert_equal ['method1(a, b, c)', 'method2(d, e, f)', 'method3(g, h)'], methods.map(&:arglists)
+ end
+
+ def test_class_repeatedly
+ util_parser <<~RUBY
+ class Foo
+ def foo; end
+ end
+ class Foo
+ def bar; end
+ end
+ RUBY
+ util_parser <<~RUBY
+ class Foo
+ def baz; end
+ end
+ RUBY
+
+ klass = @store.find_class_named 'Foo'
+ assert_equal ['Foo#foo', 'Foo#bar', 'Foo#baz'], klass.method_list.map(&:full_name)
+ end
+
+ def test_undefined_singleton_class_defines_module
+ util_parser <<~RUBY
+ class << Foo
+ end
+ class << ::Bar
+ end
+ RUBY
+
+ modules = @store.all_modules
+ assert_equal ['Foo', 'Bar'], modules.map(&:name)
+ end
+
+ def test_singleton_class
+ util_parser <<~RUBY
+ class A; end
+ class Foo
+ def self.m1; end
+ def (any expression).dummy1; end
+ class << self
+ def m2; end
+ def self.dummy2; end
+ end
+ class << A
+ def dummy3; end
+ end
+ class << Foo
+ def m3; end
+ def self.dummy4; end
+ end
+ class << ::Foo
+ def m4; end
+ end
+ class << (any expression)
+ def dummy5; end
+ end
+ end
+ class << Foo
+ def m5; end
+ end
+ class << ::Foo
+ def m6; end
+ end
+ RUBY
+
+ klass = @store.find_class_named 'Foo'
+ methods = klass.method_list
+ methods = methods.reject {|m| m.name =~ /dummy2|dummy4/ } if accept_legacy_bug?
+ assert_equal ['m1', 'm2', 'm3', 'm4', 'm5', 'm6'], methods.map(&:name)
+ assert_equal [true] * 6, methods.map(&:singleton)
+ end
+
+ def test_singleton_class_meta_method
+ util_parser <<~RUBY
+ class Foo
+ ##
+ # :singleton-method: m1
+
+ ##
+ # :singleton-method:
+ add_my_smethod :m2, :arg
+
+ ##
+ # :singleton-method:
+ add_my_smethod 'm3', :arg
+
+ # comment
+ class << self
+ ##
+ # method of a singleton class is a singleton method
+ # :method: m4
+
+ ##
+ # :singleton-method: m5
+ end
+ end
+ RUBY
+
+ klass = @store.find_class_named 'Foo'
+ assert_equal ['m1', 'm2', 'm3', 'm4', 'm5'], klass.method_list.map(&:name)
+ klass.method_list[3].singleton = true if accept_legacy_bug?
+ assert_equal [true] * 5, klass.method_list.map(&:singleton)
+ end
+
+ def test_method_nested_visibility
+ util_parser <<~RUBY
+ class A
+ def pub1; end
+ private
+ def pri1; end
+ class B
+ def pub_b1; end
+ private
+ def pri_b1; end
+ public
+ def pub_b2; end
+ end
+ def pri2; end
+ end
+ class A
+ def pub2; end
+ private
+ def pri2; end
+ end
+ RUBY
+ klass_a = @store.find_class_named 'A'
+ klass_b = klass_a.find_class_named 'B'
+ public_a = klass_a.method_list.select { |m| m.visibility == :public }.map(&:name)
+ public_b = klass_b.method_list.select { |m| m.visibility == :public }.map(&:name)
+ assert_equal ['pub1', 'pub2'], public_a
+ assert_equal ['pub_b1', 'pub_b2'], public_b
+ end
+
+ def test_attributes_visibility
+ util_parser <<~RUBY
+ class A
+ attr :pub_a
+ attr_reader :pub_r
+ attr_writer :pub_w
+ attr_accessor :pub_rw
+ private
+ attr :pri_a
+ attr_reader :pri_r
+ attr_writer :pri_w
+ attr_accessor :pri_rw
+ end
+ RUBY
+ klass = @store.find_class_named 'A'
+ assert_equal ['pub_a', 'pub_r', 'pub_w', 'pub_rw', 'pri_a', 'pri_r', 'pri_w', 'pri_rw'], klass.attributes.map(&:name)
+ assert_equal [:public] * 4 + [:private] * 4, klass.attributes.map(&:visibility)
+ end
+
+ def test_method_singleton_class_visibility
+ util_parser <<~RUBY
+ class A
+ def self.pub1; end
+ private
+ def self.pub2; end
+ class << self
+ def pub3; end
+ private
+ def pri1; end
+ public
+ def pub4; end
+ private
+ end
+ end
+ RUBY
+ klass = @store.find_class_named 'A'
+ public_singleton_methods = klass.method_list.select { |m| m.singleton && m.visibility == :public }
+ assert_equal ['pub1', 'pub2', 'pub3', 'pub4'], public_singleton_methods.map(&:name)
+ end
+
+ def test_private_def_public_def
+ util_parser <<~RUBY
+ class A
+ private def m1; end
+ public def m2; end
+ private
+ public def m3; end
+ end
+ RUBY
+ klass = @store.find_class_named 'A'
+ public_methods = klass.method_list.select { |m| m.visibility == :public }
+ assert_equal ['m2', 'm3'], public_methods.map(&:name)
+ end
+
+ def test_define_method_visibility
+ util_parser <<~RUBY
+ class A
+ private
+ ##
+ # my private method
+ define_method :m1 do end
+ public
+ ##
+ # my public method
+ define_method :m2 do end
+ end
+ RUBY
+ klass = @store.find_class_named 'A'
+ methods = klass.method_list
+ assert_equal ['m1', 'm2'], methods.map(&:name)
+ assert_equal [:private, :public], methods.map(&:visibility)
+ end
+
+ def test_module_function
+ util_parser <<~RUBY
+ class A
+ def m1; end
+ def m2; end
+ def m3; end
+ module_function :m1, :m3
+ module_function def m4; end
+ end
+ RUBY
+ klass = @store.find_class_named 'A'
+ instance_methods = klass.method_list.reject(&:singleton)
+ singleton_methods = klass.method_list.select(&:singleton)
+ if accept_legacy_bug?
+ instance_methods.last.visibility = :private
+ singleton_methods << singleton_methods.last.dup
+ singleton_methods.last.name = 'm4'
+ end
+ assert_equal ['m1', 'm2', 'm3', 'm4'], instance_methods.map(&:name)
+ assert_equal [:private, :public, :private, :private], instance_methods.map(&:visibility)
+ assert_equal ['m1', 'm3', 'm4'], singleton_methods.map(&:name)
+ assert_equal [:public, :public, :public], singleton_methods.map(&:visibility)
+ end
+
+ def test_class_method_visibility
+ util_parser <<~RUBY
+ class A
+ def self.m1; end
+ def self.m2; end
+ def self.m3; end
+ private_class_method :m1, :m2
+ public_class_method :m1, :m3
+ private_class_method def self.m4; end
+ public_class_method def self.m5; end
+ end
+ RUBY
+ klass = @store.find_class_named 'A'
+ public_methods = klass.method_list.select { |m| m.visibility == :public }
+ assert_equal ['m1', 'm3', 'm5'], public_methods.map(&:name) unless accept_legacy_bug?
+ end
+
+ def test_method_change_visibility
+ util_parser <<~RUBY
+ class A
+ def m1; end
+ def m2; end
+ def m3; end
+ def m4; end
+ def m5; end
+ private :m2, :m3, :m4
+ public :m1, :m3
+ end
+ class << A
+ def m1; end
+ def m2; end
+ def m3; end
+ def m4; end
+ def m5; end
+ private :m1, :m2, :m3
+ public :m2, :m4
+ end
+ RUBY
+ klass = @store.find_class_named 'A'
+ public_methods = klass.method_list.select { |m| !m.singleton && m.visibility == :public }
+ public_singleton_methods = klass.method_list.select { |m| m.singleton && m.visibility == :public }
+ assert_equal ['m1', 'm3', 'm5'], public_methods.map(&:name)
+ assert_equal ['m2', 'm4', 'm5'], public_singleton_methods.map(&:name)
+ end
+
+ def test_undocumentable_change_visibility
+ pend if accept_legacy_bug?
+ util_parser <<~RUBY
+ class A
+ def m1; end
+ def self.m2; end
+ private 42, :m # maybe not Module#private
+ # ignore all non-standard `private def` and `private_class_method def`
+ private def self.m1; end
+ private_class_method def m2; end
+ private def to_s.m1; end
+ private_class_method def to_s.m2; end
+ end
+ RUBY
+ klass = @store.find_class_named 'A'
+ assert_equal [:public] * 4, klass.method_list.map(&:visibility)
+ end
+
+ def test_method_visibility_change_in_subclass
+ pend 'not implemented' if accept_legacy_bug?
+ util_parser <<~RUBY
+ class A
+ def m1; end
+ def m2; end
+ private :m2
+ end
+ class B < A
+ private :m1
+ public :m2
+ end
+ RUBY
+
+ superclass = @store.find_class_named('A')
+ klass = @store.find_class_named('B')
+ assert_equal ['m1', 'm2'], superclass.method_list.map(&:name)
+ assert_equal ['m1', 'm2'], klass.method_list.map(&:name)
+ assert_equal [:public, :private], superclass.method_list.map(&:visibility)
+ assert_equal [:private, :public], klass.method_list.map(&:visibility)
+ end
+
+ def test_singleton_method_visibility_change_in_subclass
+ util_parser <<~RUBY
+ class A
+ def self.m1; end
+ def self.m2; end
+ private_class_method :m2
+ end
+ class B < A
+ private_class_method :m1
+ public_class_method :m2
+ end
+ RUBY
+
+ superclass = @store.find_class_named('A')
+ klass = @store.find_class_named('B')
+ assert_equal ['m1', 'm2'], superclass.method_list.map(&:name)
+ assert_equal ['m1', 'm2'], klass.method_list.map(&:name)
+ assert_equal [:public, :private], superclass.method_list.map(&:visibility)
+ assert_equal [:private, :public], klass.method_list.map(&:visibility)
+ end
+
+ def test_alias
+ util_parser <<~RUBY
+ class Foo
+ def bar; end
+ def bar2; alias :dummy :bar; end
+ # comment
+ alias :baz1 :bar # :nodoc:
+ alias :baz2 :bar
+ # :stopdoc:
+ alias :baz3 :bar
+ end
+ RUBY
+ klass = @store.find_class_named 'Foo'
+ assert_equal ['Foo#bar', 'Foo#bar2', 'Foo#baz2'], klass.method_list.map(&:full_name)
+ m = klass.method_list.last
+ assert_equal 'Foo#bar', m.is_alias_for.full_name
+ assert_equal 'Foo#baz2', m.full_name
+ assert_equal klass, m.parent
+ end
+
+ def test_alias_singleton
+ util_parser <<~RUBY
+ class Foo
+ class << self
+ def bar; end
+ # comment
+ alias :baz :bar
+ # :stopdoc:
+ alias :baz2 :bar
+ end
+ end
+ RUBY
+ klass = @store.find_class_named 'Foo'
+ m = klass.class_method_list.last
+ assert_equal 'Foo::bar', m.is_alias_for.full_name
+ assert_equal 'Foo::baz', m.full_name
+ assert_equal 'comment', m.comment.text
+ assert_equal klass, m.parent
+ end
+
+ def test_alias_method
+ util_parser <<~RUBY
+ class Foo
+ def foo; end
+ private
+ alias_method :foo2, :foo
+ def bar; end
+ public
+ alias_method :bar2, :bar
+ private :foo
+ public :bar
+ end
+ RUBY
+ foo, foo2, bar, bar2 = @top_level.classes.first.method_list
+ assert_equal 'foo', foo.name
+ assert_equal 'bar', bar.name
+ assert_equal 'foo2', foo2.name
+ assert_equal 'bar2', bar2.name
+ assert_equal 'foo', foo2.is_alias_for.name
+ assert_equal 'bar', bar2.is_alias_for.name
+ unless accept_legacy_bug?
+ assert_equal :private, foo.visibility
+ assert_equal :public, foo2.visibility
+ assert_equal :public, bar.visibility
+ assert_equal :private, bar2.visibility
+ end
+ end
+
+ def test_invalid_alias_method
+ pend if accept_legacy_bug?
+ util_parser <<~RUBY
+ class Foo
+ def foo; end
+ alias_method
+ alias_method :foo
+ alias_method :foo, :bar, :baz
+ alias_method 42, :foo
+ end
+ RUBY
+ assert_equal ['foo'], @top_level.classes.first.method_list.map(&:name)
+ end
+
+ def test_alias_method_stopdoc_nodoc
+ util_parser <<~RUBY
+ class Foo
+ def foo; end
+ # :stopdoc:
+ alias_method :foo2, :foo
+ # :startdoc:
+ alias_method :foo3, :foo # :nodoc:
+ alias_method :foo4, :foo
+ end
+ RUBY
+ assert_equal ['foo', 'foo4'], @top_level.classes.first.method_list.map(&:name)
+ end
+
+ def test_attributes
+ util_parser <<~RUBY
+ class Foo
+ # attrs
+ attr :attr1, :attr2
+ # readers
+ attr_reader :reader1, :reader2
+ # writers
+ attr_writer :writer1, :writer2
+ # accessors
+ attr_accessor :accessor1, :accessor2
+ # :stopdoc:
+ attr :attr3, :attr4
+ attr_reader :reader3, :reader4
+ attr_writer :write3, :writer4
+ attr_accessor :accessor3, :accessor4
+ end
+ RUBY
+ klass = @store.find_class_named 'Foo'
+ if accept_legacy_bug?
+ a, r1, r2, w1, w2, rw1, rw2 = klass.attributes
+ a1 = a.dup
+ a2 = a.dup
+ a1.rw = a2.rw = 'R'
+ a2.name = 'attr2'
+ else
+ assert_equal 8, klass.attributes.size
+ a1, a2, r1, r2, w1, w2, rw1, rw2 = klass.attributes
+ end
+ assert_equal ['attr1', 'attr2'], [a1.name, a2.name]
+ assert_equal ['reader1', 'reader2'], [r1.name, r2.name]
+ assert_equal ['writer1', 'writer2'], [w1.name, w2.name]
+ assert_equal ['accessor1', 'accessor2'], [rw1.name, rw2.name]
+ assert_equal ['R', 'R'], [a1.rw, a2.rw]
+ assert_equal ['R', 'R'], [r1.rw, r2.rw]
+ assert_equal ['W', 'W'], [w1.rw, w2.rw]
+ assert_equal ['RW', 'RW'], [rw1.rw, rw2.rw]
+ assert_equal ['attrs', 'attrs'], [a1.comment.text, a2.comment.text]
+ assert_equal ['readers', 'readers'], [r1.comment.text, r2.comment.text]
+ assert_equal ['writers', 'writers'], [w1.comment.text, w2.comment.text]
+ assert_equal ['accessors', 'accessors'], [rw1.comment.text, rw2.comment.text]
+ assert_equal [3, 3], [a1.line, a2.line]
+ assert_equal [5, 5], [r1.line, r2.line]
+ assert_equal [7, 7], [w1.line, w2.line]
+ assert_equal [9, 9], [rw1.line, rw2.line]
+ assert_equal [@top_level] * 8, [a1, a2, r1, r2, w1, w2, rw1, rw2].map(&:file)
+ end
+
+ def test_undocumentable_attributes
+ util_parser <<~RUBY
+ class Foo
+ attr
+ attr 42, :foo
+ end
+ RUBY
+ klass = @store.find_class_named 'Foo'
+ assert_empty klass.method_list
+ assert_empty klass.attributes
+ end
+
+ def test_singleton_class_attributes
+ util_parser <<~RUBY
+ class Foo
+ class << self
+ attr :a
+ attr_reader :r
+ attr_writer :w
+ attr_accessor :rw
+ end
+ end
+ RUBY
+ klass = @store.find_class_named 'Foo'
+ attributes = klass.attributes
+ assert_equal ['a', 'r', 'w', 'rw'], attributes.map(&:name)
+ assert_equal [true] * 4, attributes.map(&:singleton)
+ end
+
+ def test_attributes_nodoc
+ util_parser <<~RUBY
+ class Foo
+ attr :attr1, :attr2 # :nodoc:
+ attr :attr3
+ attr_reader :reader1, :reader2 # :nodoc:
+ attr_reader :reader3
+ attr_writer :writer1, :writer2 # :nodoc:
+ attr_writer :writer3
+ attr_accessor :accessor1, :accessor2 # :nodoc:
+ attr_accessor :accessor3
+ end
+ RUBY
+ klass = @store.find_class_named 'Foo'
+ unless accept_legacy_bug?
+ assert_equal 4, klass.attributes.size
+ end
+ end
+
+ def test_attributes_nodoc_track
+ @options.visibility = :nodoc
+ util_parser <<~RUBY
+ class Foo
+ attr :attr1, :attr2 # :nodoc:
+ attr :attr3
+ attr_reader :reader1, :reader2 # :nodoc:
+ attr_reader :reader3
+ attr_writer :writer1, :writer2 # :nodoc:
+ attr_writer :writer3
+ attr_accessor :accessor1, :accessor2 # :nodoc:
+ attr_accessor :accessor3
+ end
+ RUBY
+ klass = @store.find_class_named 'Foo'
+ unless accept_legacy_bug?
+ assert_equal 12, klass.attributes.size
+ end
+ end
+
+ def test_method_nodoc_stopdoc
+ util_parser <<~RUBY
+ class Foo
+ def doc1; end
+ def nodoc1; end # :nodoc:
+ def doc2; end
+ def nodoc2 # :nodoc:
+ end
+ def doc3; end
+ def nodoc3
+ end # :nodoc:
+ def doc4; end
+ # :stopdoc:
+ def nodoc4; end
+ end
+ RUBY
+ klass = @store.find_class_named 'Foo'
+ assert_equal ['doc1', 'doc2', 'doc3', 'doc4'], klass.method_list.map(&:name)
+ end
+
+ def test_method_nodoc_track
+ @options.visibility = :nodoc
+ util_parser <<~RUBY
+ class Foo
+ def doc1; end
+ def nodoc1; end # :nodoc:
+ def doc2; end
+ def nodoc2 # :nodoc:
+ end
+ def doc3; end
+ def nodoc3
+ end # :nodoc:
+ def doc4; end
+ end
+ RUBY
+ klass = @store.find_class_named 'Foo'
+ assert_equal ['doc1', 'nodoc1', 'doc2', 'nodoc2', 'doc3', 'nodoc3', 'doc4'], klass.method_list.map(&:name)
+ assert_equal [true, nil, true, nil, true, nil, true], klass.method_list.map(&:document_self)
+ end
+
+ def test_meta_attributes
+ util_parser <<~RUBY
+ class Foo
+ ##
+ # :attr:
+ # attrs
+ add_my_method :attr1, :attr2
+ ##
+ # :attr_reader:
+ # readers
+ add_my_method :reader1, :reader2
+ ##
+ # :attr_writer:
+ # writers
+ add_my_method :writer1, :writer2
+ ##
+ # :attr_accessor:
+ # accessors
+ add_my_method :accessor1, :accessor2
+
+ # :stopdoc:
+
+ ##
+ # :attr:
+ add_my_method :attr3
+ ##
+ # :attr_reader:
+ add_my_method :reader3
+ ##
+ # :attr_writer:
+ add_my_method :writer3
+ ##
+ # :attr_accessor:
+ add_my_method :accessor3
+ end
+ RUBY
+ klass = @store.find_class_named 'Foo'
+ assert_equal 8, klass.attributes.size
+ a1, a2, r1, r2, w1, w2, rw1, rw2 = klass.attributes
+ assert_equal ['attr1', 'attr2'], [a1.name, a2.name]
+ assert_equal ['reader1', 'reader2'], [r1.name, r2.name]
+ assert_equal ['writer1', 'writer2'], [w1.name, w2.name]
+ assert_equal ['accessor1', 'accessor2'], [rw1.name, rw2.name]
+ a1.rw = a2.rw = 'R' if accept_legacy_bug?
+ assert_equal ['R', 'R'], [a1.rw, a2.rw]
+ assert_equal ['R', 'R'], [r1.rw, r2.rw]
+ assert_equal ['W', 'W'], [w1.rw, w2.rw]
+ assert_equal ['RW', 'RW'], [rw1.rw, rw2.rw]
+ assert_equal ['attrs', 'attrs'], [a1.comment.text, a2.comment.text]
+ assert_equal ['readers', 'readers'], [r1.comment.text, r2.comment.text]
+ assert_equal ['writers', 'writers'], [w1.comment.text, w2.comment.text]
+ assert_equal ['accessors', 'accessors'], [rw1.comment.text, rw2.comment.text]
+ assert_equal [@top_level] * 8, [a1, a2, r1, r2, w1, w2, rw1, rw2].map(&:file)
+ end
+
+ def test_meta_attributes_named
+ util_parser <<~RUBY
+ class Foo
+ ##
+ # comment a
+ # :attr: attr1
+ add_my_method :a1
+ ##
+ # comment r
+ # :attr_reader: reader1
+ add_my_method :r1
+ ##
+ # comment w
+ # :attr_writer: writer1
+ add_my_method :w1
+ ##
+ # comment rw
+ # :attr_accessor: accessor1
+ add_my_method :rw1
+
+ # :stopdoc:
+
+ ##
+ # :attr: attr2
+ add_my_method :a2
+ ##
+ # :attr_reader: reader2
+ add_my_method :r2
+ ##
+ # :attr_writer: writer2
+ add_my_method :w2
+ ##
+ # :attr_accessor: accessor2
+ add_my_method :rw2
+ end
+ RUBY
+ klass = @store.find_class_named 'Foo'
+ assert_equal 4, klass.attributes.size
+ a, r, w, rw = klass.attributes
+ assert_equal 'attr1', a.name
+ assert_equal 'reader1', r.name
+ assert_equal 'writer1', w.name
+ assert_equal 'accessor1', rw.name
+ a.rw = 'R' if accept_legacy_bug?
+ assert_equal 'R', a.rw
+ assert_equal 'R', r.rw
+ assert_equal 'W', w.rw
+ assert_equal 'RW', rw.rw
+ assert_equal 'comment a', a.comment.text
+ assert_equal 'comment r', r.comment.text
+ assert_equal 'comment w', w.comment.text
+ assert_equal 'comment rw', rw.comment.text
+ assert_equal [@top_level] * 4, [a, r, w, rw].map(&:file)
+ end
+
+ def test_constant
+ util_parser <<~RUBY
+ class Foo
+ A = (any expression 1)
+ def f
+ DUMMY1 = (any expression 2)
+ end
+ class Bar; end
+ Bar::B = (any expression 3)
+ ::C = (any expression 4)
+ # :stopdoc:
+ DUMMY2 = 1
+ # :startdoc:
+ D = (any expression 5)
+ E = (any expression 6) # :nodoc:
+ F = (
+ any expression 7
+ ) # :nodoc:
+ end
+ G = (any expression 8)
+ RUBY
+ foo = @top_level.classes.first
+ bar = foo.classes.first
+ object = @top_level.find_class_or_module('Object')
+ assert_equal ['A', 'D', 'E', 'F'], foo.constants.map(&:name) unless accept_legacy_bug?
+ assert_equal '(any expression 1)', foo.constants.first.value
+ assert_equal ['B'], bar.constants.map(&:name)
+ assert_equal ['C', 'G'], object.constants.map(&:name) unless accept_legacy_bug?
+ all_constants = foo.constants + bar.constants + object.constants
+ assert_equal [@top_level] * 7, all_constants.map(&:file) unless accept_legacy_bug?
+ assert_equal [2, 12, 13, 14, 7, 8, 18], all_constants.map(&:line) unless accept_legacy_bug?
+ end
+
+ def test_nodoc_constant_assigned_without_nodoc_comment
+ util_parser <<~RUBY
+ module Foo
+ A = 1
+ B = 1 # :nodoc:
+ begin
+ C = 1 # :nodoc:
+ rescue
+ C = 2
+ end
+ end
+ Foo::B = 2
+ Foo::D = 2
+ RUBY
+ mod = @top_level.modules.first
+ assert_equal ['A', 'B', 'C', 'D'], mod.constants.map(&:name)
+ assert_equal [false, true, true, false], mod.constants.map(&:received_nodoc)
+ end
+
+ def test_constant_visibility
+ util_parser <<~RUBY
+ class C
+ A = 1
+ B = 2
+ C = 3
+ private_constant
+ private_constant foo
+ private_constant :A
+ private_constant :B, :C
+ public_constant :B
+ end
+ RUBY
+ klass = @store.find_class_named 'C'
+ const_a, const_b, const_c = klass.constants.sort_by(&:name)
+
+ assert_equal 'A', const_a.name
+ assert_equal :private, const_a.visibility
+
+ assert_equal 'B', const_b.name
+ assert_equal :public, const_b.visibility
+
+ assert_equal 'C', const_c.name
+ assert_equal :private, const_c.visibility
+ end
+
+ def test_constant_assignment_to_undefined_module_path
+ util_parser <<~RUBY
+ A::B::C = 1
+ RUBY
+ a = @top_level.find_module_named 'A'
+ b = a.find_module_named 'B'
+ c = b.constants.first
+ assert_equal 'A::B::C', c.full_name
+ end
+
+ def test_constant_alias
+ util_parser <<~RUBY
+ class Foo
+ class Bar; end
+ A = Bar
+ # B = ::Foo # master branch has bug
+ C = Foo::Bar
+ end
+ RUBY
+ klass = @top_level.classes.first
+ assert_equal [], klass.modules.map(&:full_name)
+ assert_equal ['Foo::Bar', 'Foo::A', 'Foo::C'], klass.classes.map(&:full_name)
+ assert_equal ['Foo::A', 'Foo::C'], klass.constants.map(&:full_name)
+ assert_equal 'Foo::A', klass.find_module_named('A').full_name
+ assert_equal 'Foo::C', klass.find_module_named('C').full_name
+ end
+
+ def test_constant_method
+ util_parser <<~RUBY
+ def Object.foo; end
+ class A
+ class B
+ class C
+ def B.bar; end
+ end
+ end
+ end
+ def UNKNOWN.baz; end
+ RUBY
+
+ object = @store.find_class_named 'Object'
+ klass = @store.find_class_named 'A::B'
+ unknown = @store.find_module_named('UNKNOWN')
+ assert_equal 'Object::foo', object.method_list.first.full_name
+ assert_equal 'A::B::bar', klass.method_list.first.full_name
+ assert_equal 'UNKNOWN::baz', unknown.method_list.first.full_name
+ end
+
+ def test_true_false_nil_method
+ util_parser <<~RUBY
+ def nil.foo; end
+ def true.bar; end
+ def false.baz; end
+ RUBY
+ sep = accept_legacy_bug? ? '::' : '#'
+ assert_equal "NilClass#{sep}foo", @store.find_class_named('NilClass').method_list.first.full_name
+ assert_equal "TrueClass#{sep}bar", @store.find_class_named('TrueClass').method_list.first.full_name
+ assert_equal "FalseClass#{sep}baz", @store.find_class_named('FalseClass').method_list.first.full_name
+ end
+
+ def test_include_extend
+ util_parser <<~RUBY
+ module I; end
+ module E; end
+ class C
+ # my include
+ include I
+ # my extend
+ extend E
+ end
+ module M
+ include I
+ extend E
+ end
+ RUBY
+ klass = @store.find_class_named 'C'
+ mod = @store.find_module_named 'M'
+ assert_equal ['I'], klass.includes.map(&:name)
+ assert_equal ['E'], klass.extends.map(&:name)
+ assert_equal ['I'], mod.includes.map(&:name)
+ assert_equal ['E'], mod.extends.map(&:name)
+ assert_equal 'my include', klass.includes.first.comment.text.strip
+ assert_equal 'my extend', klass.extends.first.comment.text.strip
+ end
+
+ def test_include_extend_to_singleton_class
+ pend 'not implemented' if accept_legacy_bug?
+ util_parser <<~RUBY
+ class Foo
+ class << self
+ # include to singleton class is extend
+ include I
+ # extend to singleton class is not documentable
+ extend E
+ end
+ end
+ RUBY
+
+ klass = @top_level.classes.first
+ assert_equal [], klass.includes.map(&:name)
+ assert_equal ['I'], klass.extends.map(&:name)
+ end
+
+ def test_include_with_module_nesting
+ util_parser <<~RUBY
+ module A
+ module M; end
+ module B
+ module M; end
+ module C
+ module M; end
+ module D
+ module M; end
+ end
+ end
+ end
+ end
+
+ module A::B
+ class C::D::Foo
+ include M
+ end
+ end
+ # TODO: make test pass with the following code appended
+ # module A::B::C
+ # class D::Foo
+ # include M
+ # end
+ # end
+ RUBY
+ klass = @store.find_class_named 'A::B::C::D::Foo'
+ assert_equal 'A::B::M', klass.includes.first.module.full_name
+ end
+
+ def test_various_argument_include
+ pend 'not implemented' if accept_legacy_bug?
+ util_parser <<~RUBY
+ module A; end
+ module B; end
+ module C; end
+ class A
+ include
+ include A, B
+ include 42, C # Maybe not Module#include
+ end
+ RUBY
+ klass = @top_level.classes.first
+ assert_equal ['A', 'B'], klass.includes.map(&:name)
+ end
+
+ def test_require
+ util_parser <<~RUBY
+ require
+ require 'foo/bar'
+ require_relative 'is/not/supported/yet'
+ require "\#{embed}"
+ require (any expression)
+ RUBY
+ assert_equal ['foo/bar'], @top_level.requires.map(&:name)
+ end
+
+ def test_statements_identifier_alias_method_before_original_method
+ # This is not strictly legal Ruby code, but it simulates finding an alias
+ # for a method before finding the original method, which might happen
+ # to rdoc if the alias is in a different file than the original method
+ # and rdoc processes the alias' file first.
+ util_parser <<~RUBY
+ class Foo
+ alias_method :foo2, :foo
+ alias_method :foo3, :foo
+ end
+
+ class Foo
+ def foo(); end
+ alias_method :foo4, :foo
+ alias_method :foo5, :unknown
+ end
+ RUBY
+
+ foo = @top_level.classes.first.method_list[0]
+ assert_equal 'foo', foo.name
+
+ foo2 = @top_level.classes.first.method_list[1]
+ assert_equal 'foo2', foo2.name
+ assert_equal 'foo', foo2.is_alias_for.name
+
+ foo3 = @top_level.classes.first.method_list[2]
+ assert_equal 'foo3', foo3.name
+ assert_equal 'foo', foo3.is_alias_for.name
+
+ foo4 = @top_level.classes.first.method_list.last
+ assert_equal 'foo4', foo4.name
+ assert_equal 'foo', foo4.is_alias_for.name
+
+ assert_equal 'unknown', @top_level.classes.first.external_aliases[0].old_name
+ end
+
+ def test_class_definition_encountered_after_class_reference
+ # The code below is not legal Ruby (Foo must have been defined before
+ # Foo.bar is encountered), but RDoc might encounter Foo.bar before Foo if
+ # they live in different files.
+
+ util_parser <<-RUBY
+ def Foo.bar
+ end
+
+ class Foo < IO
+ end
+ RUBY
+
+ assert_empty @store.modules_hash
+ assert_empty @store.all_modules
+
+ klass = @top_level.classes.first
+ assert_equal 'Foo', klass.full_name
+ assert_equal 'IO', klass.superclass
+
+ assert_equal 'bar', klass.method_list.first.name
+ end
+
+ def test_scan_duplicate_module
+ util_parser <<~RUBY
+ # comment a
+ module Foo
+ end
+
+ # comment b
+ module Foo
+ end
+ RUBY
+
+ mod = @top_level.modules.first
+
+ expected = [
+ RDoc::Comment.new('comment a', @top_level),
+ RDoc::Comment.new('comment b', @top_level)
+ ]
+
+ assert_equal expected, mod.comment_location.map { |c, _l| c }
+ end
+
+ def test_enddoc
+ util_parser <<~RUBY
+ class A
+ class B; end
+ # :enddoc:
+ # :startdoc:
+ class C; end
+ end
+ class D; end
+ # :enddoc:
+ # :startdoc:
+ class E; end
+ RUBY
+
+ assert_equal ['A', 'A::B', 'D'], @store.all_classes.reject(&:ignored?).map(&:full_name)
+ end
+
+ def test_top_level_enddoc
+ util_parser <<~RUBY
+ class A; end
+ # :enddoc:
+ class B; end
+ # :startdoc:
+ class C; end
+ RUBY
+
+ assert_equal ['A'], @top_level.classes.reject(&:ignored?).map(&:name)
+ end
+
+ def test_section
+ util_parser <<~RUBY
+ class Foo
+ # :section: section1
+ attr :a1
+ def m1; end
+ # :section:
+ def m2; end
+ attr :a2
+ # :section: section2
+ def m3; end
+ attr :a3
+ module Bar
+ def m4; end
+ attr :a4
+ # :section: section3
+ def m5; end
+ attr :a5
+ end
+ attr :a6
+ def m6; end
+ end
+ RUBY
+ foo = @top_level.classes.first
+ bar = foo.modules.first
+ assert_equal ['section1', nil, 'section2', 'section2'], foo.attributes.map { |m| m.section.title }
+ assert_equal ['section1', nil, 'section2', 'section2'], foo.method_list.map { |m| m.section.title }
+ assert_equal [nil, 'section3'], bar.attributes.map { |m| m.section.title }
+ assert_equal [nil, 'section3'], bar.method_list.map { |m| m.section.title }
+ end
+
+ def test_category
+ util_parser <<~RUBY
+ class A
+ # :category: cat1
+
+ # comment
+ attr :a1
+ attr :a2
+ def m1; end
+ # :category: cat2
+
+ # comment
+ def m2; end
+ def m3; end
+ attr :a3
+
+ # :category:
+ attr :a4
+ # :category:
+ def m4; end
+
+ ##
+ # :category: cat3
+ def m5; end
+
+ ##
+ # :category: cat4
+ # :method: m6
+ end
+ RUBY
+ klass = @top_level.classes.first
+ assert_equal ['cat1', nil, nil, nil], klass.attributes.map { |m| m.section.title }
+ assert_equal [nil, 'cat2', nil, nil, 'cat3', 'cat4'], klass.method_list.map { |m| m.section.title }
+ end
+
+ def test_ignore_constant_assign_rhs
+ # Struct is not supported yet. Right hand side of constant assignment should be ignored.
+ util_parser <<~RUBY
+ module Foo
+ def a; end
+ Bar = Struct.new do
+ def b; end
+ ##
+ # :method: c
+ end
+ Bar::Baz = Struct.new do
+ def d; end
+ ##
+ # :method: e
+ end
+ ##
+ # :method: f
+ end
+ RUBY
+ mod = @top_level.modules.first
+ assert_equal ['a', 'f'], mod.method_list.map(&:name)
+ end
+
+ def test_multibyte_method_name
+ content = <<~RUBY
+ class Foo
+ # comment ω
+ def ω() end
+ end
+ RUBY
+ util_parser content
+ assert_equal Encoding::UTF_8, content.encoding
+ method = @top_level.classes.first.method_list.first
+ assert_equal 'comment ω', method.comment.text.strip
+ assert_equal 'ω', method.name
+ end
+
+ def test_options_encoding
+ @options.encoding = Encoding::CP852
+ util_parser <<~RUBY
+ class Foo
+ ##
+ # this is my method
+ add_my_method :foo
+ end
+ RUBY
+ foo = @top_level.classes.first.method_list.first
+ assert_equal 'foo', foo.name
+ assert_equal 'this is my method', foo.comment.text
+ assert_equal Encoding::CP852, foo.comment.text.encoding
+ end
+
+ def test_read_directive_linear_performance
+ assert_linear_performance((1..5).map{|i|10**i}) do |i|
+ util_parser '# ' + '0'*i + '=000:' + "\n def f; end"
+ end
+ end
+
+
+ def test_markup_first_comment
+ util_parser <<~RUBY
+ # :markup: rd
+
+ # ((*awesome*))
+ class C
+ # ((*radical*))
+ def m
+ end
+ end
+ RUBY
+
+ c = @top_level.classes.first
+ assert_equal 'rd', c.comment.format
+ assert_equal 'rd', c.method_list.first.comment.format
+ end
+
+ def test_markup_override
+ util_parser <<~RUBY
+ # *awesome*
+ class C
+ # :markup: rd
+ # ((*radical*))
+ def m1; end
+
+ # *awesome*
+ def m2; end
+ end
+ RUBY
+
+ c = @top_level.classes.first
+
+ assert_equal 'rdoc', c.comment.format
+
+ assert_equal ['rd', 'rdoc'], c.method_list.map { |m| m.comment.format }
+ end
+
+ def test_tomdoc_meta
+ util_parser <<~RUBY
+ # :markup: tomdoc
+
+ class C
+
+ # Signature
+ #
+ # find_by_<field>[_and_<field>...](args)
+ #
+ # field - A field name.
+
+ end
+ RUBY
+
+ c = @top_level.classes.first
+
+ m = c.method_list.first
+
+ assert_equal "find_by_<field>[_and_<field>...]", m.name
+ assert_equal "find_by_<field>[_and_<field>...](args)\n", m.call_seq
+
+ expected =
+ doc(
+ head(3, 'Signature'),
+ list(:NOTE,
+ item(%w[field],
+ para('A field name.'))))
+ expected.file = @top_level
+
+ assert_equal expected, m.comment.parse
+ end
+end
+
+class TestRDocParserPrismRuby < RDoc::TestCase
+ include RDocParserPrismTestCases
+
+ def accept_legacy_bug?
+ false
+ end
+
+ def util_parser(content)
+ @parser = RDoc::Parser::PrismRuby.new @top_level, @filename, content, @options, @stats
+ @parser.scan
+ end
+end
+
+# Run the same test with the original RDoc::Parser::Ruby
+class TestRDocParserRubyWithPrismRubyTestCases < RDoc::TestCase
+ include RDocParserPrismTestCases
+
+ def accept_legacy_bug?
+ true
+ end
+
+ def util_parser(content)
+ @parser = RDoc::Parser::Ruby.new @top_level, @filename, content, @options, @stats
+ @parser.scan
+ end
+end unless ENV['RDOC_USE_PRISM_PARSER']
diff --git a/test/rdoc/test_rdoc_parser_rd.rb b/test/rdoc/test_rdoc_parser_rd.rb
index bac9c65592..48663e6d7d 100644
--- a/test/rdoc/test_rdoc_parser_rd.rb
+++ b/test/rdoc/test_rdoc_parser_rd.rb
@@ -53,4 +53,3 @@ class TestRDocParserRd < RDoc::TestCase
end
end
-
diff --git a/test/rdoc/test_rdoc_parser_ruby.rb b/test/rdoc/test_rdoc_parser_ruby.rb
index 337cf9ea1a..cf02a035a6 100644
--- a/test/rdoc/test_rdoc_parser_ruby.rb
+++ b/test/rdoc/test_rdoc_parser_ruby.rb
@@ -2,6 +2,8 @@
require_relative 'helper'
+return if ENV['RDOC_USE_PRISM_PARSER']
+
class TestRDocParserRuby < RDoc::TestCase
def setup
@@ -921,7 +923,7 @@ end
@parser.parse_class @top_level, RDoc::Parser::Ruby::NORMAL, tk, @comment
end
err = stds[1]
- assert_match(/Expected class name or '<<'\. Got/, err)
+ assert_match(/Expected class name or '<<\'\. Got/, err)
end
def test_parse_syntax_error_code
@@ -1960,10 +1962,10 @@ end
def test_parse_method_bracket
util_parser <<-RUBY
class C
- def [] end
- def self.[] end
- def []= end
- def self.[]= end
+ def []; end
+ def self.[]; end
+ def []=; end
+ def self.[]=; end
end
RUBY
@@ -3065,6 +3067,28 @@ RUBY
assert_nil m.params, 'Module parameter not removed'
end
+ def test_parse_statements_nodoc_identifier_alias
+ klass = @top_level.add_class RDoc::NormalClass, 'Foo'
+
+ util_parser "\nalias :old :new # :nodoc:"
+
+ @parser.parse_statements klass, RDoc::Parser::Ruby::NORMAL, nil
+
+ assert_empty klass.aliases
+ assert_empty klass.unmatched_alias_lists
+ end
+
+ def test_parse_statements_nodoc_identifier_alias_method
+ klass = @top_level.add_class RDoc::NormalClass, 'Foo'
+
+ util_parser "\nalias_method :old :new # :nodoc:"
+
+ @parser.parse_statements klass, RDoc::Parser::Ruby::NORMAL, nil
+
+ assert_empty klass.aliases
+ assert_empty klass.unmatched_alias_lists
+ end
+
def test_parse_statements_stopdoc_alias
klass = @top_level.add_class RDoc::NormalClass, 'Foo'
@@ -3205,6 +3229,14 @@ RUBY
assert_nil @parser.parse_symbol_in_arg
end
+ def test_parse_percent_symbol
+ content = '%s[foo bar]'
+ util_parser content
+ tk = @parser.get_tk
+ assert_equal :on_symbol, tk[:kind]
+ assert_equal content, tk[:text]
+ end
+
def test_parse_statements_alias_method
content = <<-CONTENT
class A
@@ -3350,6 +3382,13 @@ end
assert_equal :on_const, parser.get_tk[:kind]
end
+ def test_read_directive_linear_performance
+ pre = ->(i) {util_parser '# ' + '0'*i + '=000:'}
+ assert_linear_performance((1..5).map{|i|10**i}, pre: pre) do |parser|
+ assert_nil parser.read_directive []
+ end
+ end
+
def test_read_documentation_modifiers
c = RDoc::Context.new
@@ -4345,4 +4384,17 @@ end
assert_equal 'Hello', meth.comment.text
end
+ def test_parenthesized_cdecl
+ util_parser <<-RUBY
+module DidYouMean
+ class << (NameErrorCheckers = Object.new)
+ end
+end
+ RUBY
+
+ @parser.scan
+
+ refute_predicate @store.find_class_or_module('DidYouMean'), :nil?
+ refute_predicate @store.find_class_or_module('DidYouMean::NameErrorCheckers'), :nil?
+ end
end
diff --git a/test/rdoc/test_rdoc_parser_simple.rb b/test/rdoc/test_rdoc_parser_simple.rb
index 2f1ad00de4..4255cb97d8 100644
--- a/test/rdoc/test_rdoc_parser_simple.rb
+++ b/test/rdoc/test_rdoc_parser_simple.rb
@@ -113,4 +113,3 @@ contents of a string.
end
end
-
diff --git a/test/rdoc/test_rdoc_rd.rb b/test/rdoc/test_rdoc_rd.rb
index 83ee423455..38de575bb0 100644
--- a/test/rdoc/test_rdoc_rd.rb
+++ b/test/rdoc/test_rdoc_rd.rb
@@ -28,4 +28,3 @@ class TestRDocRd < RDoc::TestCase
end
end
-
diff --git a/test/rdoc/test_rdoc_rd_block_parser.rb b/test/rdoc/test_rdoc_rd_block_parser.rb
index 22f432eaf4..ca0ac9f9e9 100644
--- a/test/rdoc/test_rdoc_rd_block_parser.rb
+++ b/test/rdoc/test_rdoc_rd_block_parser.rb
@@ -168,6 +168,27 @@ class TestRDocRdBlockParser < RDoc::TestCase
tf.close!
end
+=begin
+ def test_parse_include_other_format
+ @block_parser.include_path = [Dir.tmpdir]
+
+ expected =
+ doc(
+ blank_line,
+ para("include ((*worked*))"),
+ blank_line,
+ blank_line)
+
+ str = <<~STR
+ =begin nonrd
+ <<< worked
+ =end
+ STR
+
+ assert_equal(expected, @block_parser.parse str.lines.to_a)
+ end
+=end
+
def test_parse_heading
assert_equal doc(head(1, "H")), parse("= H")
assert_equal doc(head(2, "H")), parse("== H")
diff --git a/test/rdoc/test_rdoc_rd_inline.rb b/test/rdoc/test_rdoc_rd_inline.rb
index 13ab86d3d9..6bfb229933 100644
--- a/test/rdoc/test_rdoc_rd_inline.rb
+++ b/test/rdoc/test_rdoc_rd_inline.rb
@@ -61,4 +61,3 @@ class TestRDocRdInline < RDoc::TestCase
end
end
-
diff --git a/test/rdoc/test_rdoc_rdoc.rb b/test/rdoc/test_rdoc_rdoc.rb
index eaf92c8a9f..9c94988ffd 100644
--- a/test/rdoc/test_rdoc_rdoc.rb
+++ b/test/rdoc/test_rdoc_rdoc.rb
@@ -165,12 +165,7 @@ class TestRDocRDoc < RDoc::TestCase
b = Dir.glob(b).first
c = Dir.glob(c).first
- dot_doc = File.expand_path('.document')
- FileUtils.touch dot_doc
- open(dot_doc, 'w') do |f|
- f.puts 'a.rb'
- f.puts 'b.rb'
- end
+ File.write('.document', "a.rb\n""b.rb\n")
expected_files << a
expected_files << b
@@ -196,15 +191,10 @@ class TestRDocRDoc < RDoc::TestCase
b = Dir.glob(b).first
c = Dir.glob(c).first
- dot_doc = File.expand_path('.document')
- FileUtils.touch dot_doc
- open(dot_doc, 'w') do |f|
- f.puts 'a.rb'
- f.puts 'b.rb'
- end
+ File.write('.document', "a.rb\n""b.rb\n")
expected_files << a
- @rdoc.options.exclude = Regexp.new(['b.rb'].join('|'))
+ @rdoc.options.exclude = /b\.rb$/
@rdoc.normalized_file_list [File.realpath(dir)]
end
@@ -213,6 +203,48 @@ class TestRDocRDoc < RDoc::TestCase
assert_equal expected_files, files
end
+ def test_normalized_file_list_with_skipping_tests_enabled
+ files = temp_dir do |dir|
+ @a = File.expand_path('a.rb')
+ spec_dir = File.expand_path('spec')
+ spec_file = File.expand_path(File.join('spec', 'my_spec.rb'))
+ test_dir = File.expand_path('test')
+ test_file = File.expand_path(File.join('test', 'my_test.rb'))
+ FileUtils.touch @a
+ FileUtils.mkdir_p spec_dir
+ FileUtils.touch spec_file
+ FileUtils.mkdir_p test_dir
+ FileUtils.touch test_file
+
+ @rdoc.options.skip_tests = true
+ @rdoc.normalized_file_list [File.realpath(dir)]
+ end
+
+ files = files.map { |file, *| File.expand_path file }
+ assert_equal [@a], files
+ end
+
+ def test_normalized_file_list_with_skipping_tests_disabled
+ files = temp_dir do |dir|
+ @a = File.expand_path('a.rb')
+ spec_dir = File.expand_path('spec')
+ @spec_file = File.expand_path(File.join('spec', 'my_spec.rb'))
+ test_dir = File.expand_path('test')
+ @test_file = File.expand_path(File.join('test', 'my_test.rb'))
+ FileUtils.touch @a
+ FileUtils.mkdir_p spec_dir
+ FileUtils.touch @spec_file
+ FileUtils.mkdir_p test_dir
+ FileUtils.touch @test_file
+
+ @rdoc.options.skip_tests = false
+ @rdoc.normalized_file_list [File.realpath(dir)]
+ end
+
+ files = files.map { |file, *| File.expand_path file }
+ assert_equal [@a, @spec_file, @test_file], files.sort
+ end
+
def test_parse_file
@rdoc.store = RDoc::Store.new
@@ -254,6 +286,7 @@ class TestRDocRDoc < RDoc::TestCase
top_level = nil
temp_dir do |dir|
@rdoc.options.parse %W[--root #{test_path}]
+ @rdoc.options.finish
File.open 'include.txt', 'w' do |io|
io.puts ':include: test.txt'
diff --git a/test/rdoc/test_rdoc_require.rb b/test/rdoc/test_rdoc_require.rb
index 46c225299a..4cc53e6c6c 100644
--- a/test/rdoc/test_rdoc_require.rb
+++ b/test/rdoc/test_rdoc_require.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require File.expand_path '../xref_test_case', __FILE__
+require_relative 'xref_test_case'
class TestRDocRequire < XrefTestCase
@@ -23,4 +23,3 @@ class TestRDocRequire < XrefTestCase
end
end
-
diff --git a/test/rdoc/test_rdoc_ri_driver.rb b/test/rdoc/test_rdoc_ri_driver.rb
index 87e4ebd2b1..39e6e67759 100644
--- a/test/rdoc/test_rdoc_ri_driver.rb
+++ b/test/rdoc/test_rdoc_ri_driver.rb
@@ -6,17 +6,13 @@ class TestRDocRIDriver < RDoc::TestCase
def setup
super
- @tmpdir = File.join Dir.tmpdir, "test_rdoc_ri_driver_#{$$}"
- @home_ri = File.join @tmpdir, 'dot_ri'
+ @home_ri = File.join @test_home, 'dot_ri'
- FileUtils.mkdir_p @tmpdir
FileUtils.mkdir_p @home_ri
- @orig_ri = ENV['RI']
- ENV['HOME'] = @tmpdir
- @rdoc_home = File.join ENV["HOME"], ".rdoc"
+ @orig_ri = ENV.delete('RI')
+ @rdoc_home = File.join @test_home, ".rdoc"
FileUtils.mkdir_p @rdoc_home
- ENV.delete 'RI'
@options = RDoc::RI::Driver.default_options
@options[:use_system] = false
@@ -24,7 +20,7 @@ class TestRDocRIDriver < RDoc::TestCase
@options[:use_home] = false
@options[:use_gems] = false
- @options[:home] = @tmpdir
+ @options[:home] = @rdoc_home
@options[:use_stdout] = true
@options[:formatter] = @RM::ToRdoc
@@ -32,13 +28,17 @@ class TestRDocRIDriver < RDoc::TestCase
end
def teardown
- ENV['RI'] = @orig_ri
- FileUtils.rm_rf @tmpdir
+ defined?(@orig_ri) and ENV['RI'] = @orig_ri
super
end
- DUMMY_PAGER = ":;\n"
+ case RUBY_PLATFORM
+ when /mswin|mingw/
+ DUMMY_PAGER = "type nul"
+ else
+ DUMMY_PAGER = "true"
+ end
def with_dummy_pager
pager_env, ENV['RI_PAGER'] = ENV['RI_PAGER'], DUMMY_PAGER
@@ -598,7 +598,7 @@ class TestRDocRIDriver < RDoc::TestCase
assert_match %r%^= Attributes:%, out
assert_match %r%^ attr_accessor attr%, out
- assert_equal 1, out.scan(/-\n/).length
+ assert_equal 1, out.scan(/^-{50,}$/).length, out
refute_match %r%Foo::Bar#blah%, out
end
@@ -622,7 +622,7 @@ class TestRDocRIDriver < RDoc::TestCase
assert_match %r%^= Attributes:%, out
assert_match %r%^ attr_accessor attr%, out
- assert_equal 6, out.scan(/-\n/).length
+ assert_equal 6, out.scan(/^-{50,}$/).length, out
assert_match %r%Foo::Bar#blah%, out
end
@@ -1091,23 +1091,6 @@ Foo::Bar#bother
assert_instance_of @RM::ToBs, driver.formatter(StringIO.new)
end
- def test_in_path_eh
- path = ENV['PATH']
-
- test_path = File.expand_path '..', __FILE__
-
- temp_dir do |dir|
- nonexistent = File.join dir, 'nonexistent'
- refute @driver.in_path?(nonexistent)
-
- ENV['PATH'] = test_path
-
- assert @driver.in_path?(File.basename(__FILE__))
- end
- ensure
- ENV['PATH'] = path
- end
-
def test_method_type
assert_equal :both, @driver.method_type(nil)
assert_equal :both, @driver.method_type('.')
@@ -1246,7 +1229,7 @@ Foo::Bar#bother
assert_equal '(unknown)#inherit', method.full_name
end
- def _test_page # this test doesn't do anything anymore :(
+ def test_page
@driver.use_stdout = false
with_dummy_pager do
@@ -1260,9 +1243,7 @@ Foo::Bar#bother
refute @driver.paging?
end
- # this test is too fragile. Perhaps using Process.spawn will make this
- # reliable
- def _test_page_in_presence_of_child_status
+ def test_page_in_presence_of_child_status
@driver.use_stdout = false
with_dummy_pager do
@@ -1425,7 +1406,7 @@ Foo::Bar#bother
end
end
- def _test_setup_pager # this test doesn't do anything anymore :(
+ def test_setup_pager # this test doesn't do anything anymore :(
@driver.use_stdout = false
pager = with_dummy_pager do @driver.setup_pager end
diff --git a/test/rdoc/test_rdoc_ri_paths.rb b/test/rdoc/test_rdoc_ri_paths.rb
index c01a4711ee..6dccd6dbdd 100644
--- a/test/rdoc/test_rdoc_ri_paths.rb
+++ b/test/rdoc/test_rdoc_ri_paths.rb
@@ -155,4 +155,3 @@ class TestRDocRIPaths < RDoc::TestCase
end
end
-
diff --git a/test/rdoc/test_rdoc_rubygems_hook.rb b/test/rdoc/test_rdoc_rubygems_hook.rb
index 04f84d4bcc..59a7ed0f89 100644
--- a/test/rdoc/test_rdoc_rubygems_hook.rb
+++ b/test/rdoc/test_rdoc_rubygems_hook.rb
@@ -1,9 +1,9 @@
# frozen_string_literal: true
-require "rubygems"
-require "fileutils"
-require "tmpdir"
-require 'rdoc/rubygems_hook'
-require "test/unit"
+require 'rubygems'
+require 'fileutils'
+require 'tmpdir'
+require_relative '../../lib/rdoc/rubygems_hook'
+require 'test/unit'
class TestRDocRubygemsHook < Test::Unit::TestCase
def setup
diff --git a/test/rdoc/test_rdoc_single_class.rb b/test/rdoc/test_rdoc_single_class.rb
index ee242d7bc9..e81a1498ba 100644
--- a/test/rdoc/test_rdoc_single_class.rb
+++ b/test/rdoc/test_rdoc_single_class.rb
@@ -18,4 +18,3 @@ class TestRDocSingleClass < RDoc::TestCase
end
end
-
diff --git a/test/rdoc/test_rdoc_stats.rb b/test/rdoc/test_rdoc_stats.rb
index b9918e4fd3..ce272d36cf 100644
--- a/test/rdoc/test_rdoc_stats.rb
+++ b/test/rdoc/test_rdoc_stats.rb
@@ -720,4 +720,3 @@ m(a, b) { |c, d| ... }
end
end
-
diff --git a/test/rdoc/test_rdoc_store.rb b/test/rdoc/test_rdoc_store.rb
index 82340e6b7a..50e8667d81 100644
--- a/test/rdoc/test_rdoc_store.rb
+++ b/test/rdoc/test_rdoc_store.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require File.expand_path '../xref_test_case', __FILE__
+require_relative 'xref_test_case'
class TestRDocStore < XrefTestCase
@@ -161,9 +161,10 @@ class TestRDocStore < XrefTestCase
def test_all_classes_and_modules
expected = %w[
- C1 C2 C2::C3 C2::C3::H1 C3 C3::H1 C3::H2 C4 C4::C4 C5 C5::C1 C6 C7 C8 C8::S1 C9 C9::A C9::B
+ C1 C10 C10::C11 C11 C2 C2::C3 C2::C3::H1 C3 C3::H1 C3::H2 C4 C4::C4 C5 C5::C1 C6 C7 C8 C8::S1 C9 C9::A C9::B
Child
M1 M1::M2
+ Object
Parent
]
@@ -212,8 +213,9 @@ class TestRDocStore < XrefTestCase
def test_classes
expected = %w[
- C1 C2 C2::C3 C2::C3::H1 C3 C3::H1 C3::H2 C4 C4::C4 C5 C5::C1 C6 C7 C8 C8::S1 C9 C9::A C9::B
+ C1 C10 C10::C11 C11 C2 C2::C3 C2::C3::H1 C3 C3::H1 C3::H2 C4 C4::C4 C5 C5::C1 C6 C7 C8 C8::S1 C9 C9::A C9::B
Child
+ Object
Parent
]
@@ -317,8 +319,7 @@ class TestRDocStore < XrefTestCase
end
def test_friendly_path
- @orig_xdg_data_home = ENV['XDG_DATA_HOME']
- ENV.delete('XDG_DATA_HOME')
+ @orig_xdg_data_home = ENV.delete('XDG_DATA_HOME')
@s.path = @tmpdir
@s.type = nil
@@ -372,9 +373,9 @@ class TestRDocStore < XrefTestCase
assert_equal [@mod], s.all_modules.sort
assert_equal [@page, @top_level], s.all_files.sort
- methods = s.all_classes_and_modules.map do |mod|
+ methods = s.all_classes_and_modules.flat_map do |mod|
mod.method_list
- end.flatten.sort
+ end.sort
_meth_bang_alias = RDoc::AnyMethod.new nil, 'method_bang'
_meth_bang_alias.parent = @klass
@@ -387,9 +388,9 @@ class TestRDocStore < XrefTestCase
assert_equal @klass, methods.last.parent
- attributes = s.all_classes_and_modules.map do |mod|
+ attributes = s.all_classes_and_modules.flat_map do |mod|
mod.attributes
- end.flatten.sort
+ end.sort
assert_equal [@attr], attributes
diff --git a/test/rdoc/test_rdoc_task.rb b/test/rdoc/test_rdoc_task.rb
index 77f2af33a3..67d223087b 100644
--- a/test/rdoc/test_rdoc_task.rb
+++ b/test/rdoc/test_rdoc_task.rb
@@ -50,6 +50,7 @@ class TestRDocTask < RDoc::TestCase
assert Rake::Task[:rdoc]
assert Rake::Task[:clobber_rdoc]
assert Rake::Task[:rerdoc]
+ assert Rake::Task[:"rdoc:coverage"]
assert_equal ["html/created.rid"], Rake::Task[:rdoc].prerequisites
end
@@ -58,6 +59,7 @@ class TestRDocTask < RDoc::TestCase
assert Rake::Task[:rdoc_dev]
assert Rake::Task[:clobber_rdoc_dev]
assert Rake::Task[:rerdoc_dev]
+ assert Rake::Task[:"rdoc_dev:coverage"]
assert_equal :rdoc_dev, rd.name
end
@@ -110,11 +112,16 @@ class TestRDocTask < RDoc::TestCase
assert_equal 'Rebuild RDoc HTML files', @t.rerdoc_task_description
end
+ def test_coverage_task_description
+ assert_equal 'Print RDoc coverage report', @t.coverage_task_description
+ end
+
def test_tasks_creation_with_custom_name_string
rd = RDoc::Task.new("rdoc_dev")
assert Rake::Task[:rdoc_dev]
assert Rake::Task[:clobber_rdoc_dev]
assert Rake::Task[:rerdoc_dev]
+ assert Rake::Task[:"rdoc_dev:coverage"]
assert_equal "rdoc_dev", rd.name
end
@@ -131,6 +138,7 @@ class TestRDocTask < RDoc::TestCase
assert Rake::Task[:"rdoc"]
assert Rake::Task[:"rdoc:clean"]
assert Rake::Task[:"rdoc:force"]
+ assert Rake::Task[:"rdoc:coverage"]
assert_raise(RuntimeError) { Rake::Task[:clobber_rdoc] }
assert_equal options, rd.name
end
@@ -140,6 +148,7 @@ class TestRDocTask < RDoc::TestCase
assert Rake::Task[:rdoc]
assert Rake::Task[:"rdoc:clean"]
assert Rake::Task[:rerdoc]
+ assert Rake::Task[:"rdoc:coverage"]
end
def test_tasks_creation_with_custom_name_hash_raises_exception_if_invalid_option_given
@@ -171,4 +180,3 @@ class TestRDocTask < RDoc::TestCase
end
end if defined?(Rake::Task)
-
diff --git a/test/rdoc/test_rdoc_token_stream.rb b/test/rdoc/test_rdoc_token_stream.rb
index cdfa615dae..8fcd3d8f68 100644
--- a/test/rdoc/test_rdoc_token_stream.rb
+++ b/test/rdoc/test_rdoc_token_stream.rb
@@ -39,6 +39,49 @@ class TestRDocTokenStream < RDoc::TestCase
assert_equal '', RDoc::TokenStream.to_html([])
end
+ def test_add_tokens
+ foo = Class.new do
+ include RDoc::TokenStream
+ end.new
+ foo.collect_tokens
+ foo.add_tokens([:token])
+ assert_equal [:token], foo.token_stream
+ end
+
+ def test_add_token
+ foo = Class.new do
+ include RDoc::TokenStream
+ end.new
+ foo.collect_tokens
+ foo.add_token(:token)
+ assert_equal [:token], foo.token_stream
+ end
+
+ def test_collect_tokens
+ foo = Class.new do
+ include RDoc::TokenStream
+ end.new
+ foo.collect_tokens
+ assert_equal [], foo.token_stream
+ end
+
+ def test_pop_token
+ foo = Class.new do
+ include RDoc::TokenStream
+ end.new
+ foo.collect_tokens
+ foo.add_token(:token)
+ foo.pop_token
+ assert_equal [], foo.token_stream
+ end
+
+ def test_token_stream
+ foo = Class.new do
+ include RDoc::TokenStream
+ end.new
+ assert_equal nil, foo.token_stream
+ end
+
def test_tokens_to_s
foo = Class.new do
include RDoc::TokenStream
@@ -53,6 +96,14 @@ class TestRDocTokenStream < RDoc::TestCase
end.new
assert_equal "foo 'bar'", foo.tokens_to_s
+
+ foo = Class.new do
+ include RDoc::TokenStream
+
+ def initialize
+ @token_stream = nil
+ end
+ end.new
+ assert_equal "", foo.tokens_to_s
end
end
-
diff --git a/test/rdoc/test_rdoc_top_level.rb b/test/rdoc/test_rdoc_top_level.rb
index a954fde981..3cfaa9b763 100644
--- a/test/rdoc/test_rdoc_top_level.rb
+++ b/test/rdoc/test_rdoc_top_level.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
-require File.expand_path '../xref_test_case', __FILE__
+require_relative 'xref_test_case'
class TestRDocTopLevel < XrefTestCase
@@ -90,7 +90,7 @@ class TestRDocTopLevel < XrefTestCase
@top_level.add_method method
object = @store.find_class_named 'Object'
- assert_equal [method], object.method_list
+ assert_equal [@c10_method, @c11_method, method], object.method_list
assert_includes object.in_files, @top_level
end
@@ -101,7 +101,7 @@ class TestRDocTopLevel < XrefTestCase
@top_level.add_method method
object = @store.find_class_named('Object')
- assert_empty object.method_list
+ assert_equal [@c10_method, @c11_method], object.method_list
assert_includes object.in_files, @top_level
end
@@ -288,4 +288,3 @@ class TestRDocTopLevel < XrefTestCase
end
end
-
diff --git a/test/rdoc/xref_data.rb b/test/rdoc/xref_data.rb
index aa9faaecd9..257b821f4f 100644
--- a/test/rdoc/xref_data.rb
+++ b/test/rdoc/xref_data.rb
@@ -74,6 +74,12 @@ class C6
def priv4() end
public def pub5() end
def priv5() end
+ def self.s_pub1() end
+ class << self
+ def s_pub2() end
+ private
+ def s_priv1() end
+ end
protected
private def priv6() end
@@ -82,6 +88,12 @@ class C6
def prot5() end
public def pub6() end
def prot6() end
+ def self.s_pub3() end
+ class << self
+ def s_pub4() end
+ protected
+ def s_prot1() end
+ end
end
class C7
@@ -115,6 +127,23 @@ class C9
end
end
+class C10
+ class C11
+ end
+
+ def C11
+ end
+end
+
+def C10
+end
+
+class C11
+end
+
+def C11
+end
+
module M1
def m
end
@@ -132,4 +161,3 @@ class Child < Parent
end
XREF_DATA
-
diff --git a/test/rdoc/xref_test_case.rb b/test/rdoc/xref_test_case.rb
index 729e4a70b7..0f7395e516 100644
--- a/test/rdoc/xref_test_case.rb
+++ b/test/rdoc/xref_test_case.rb
@@ -70,6 +70,14 @@ class XrefTestCase < RDoc::TestCase
@c9_b_c_foo = @c9_b.method_list.first
@c9_b_i_bar = @c9_b.method_list.last
+ @object = @xref_data.find_module_named 'Object'
+ @c10_class = @xref_data.find_module_named 'C10'
+ @c10_method = @object.find_method_named 'C10'
+ @c11_class = @xref_data.find_module_named 'C11'
+ @c10_c11_class = @c10_class.find_module_named 'C11'
+ @c10_c11_method = @c10_class.find_method_named 'C11'
+ @c11_method = @object.find_method_named 'C11'
+
@m1 = @xref_data.find_module_named 'M1'
@m1_m = @m1.method_list.first
@@ -83,4 +91,3 @@ class XrefTestCase < RDoc::TestCase
end
end
-
diff --git a/test/readline/helper.rb b/test/readline/helper.rb
deleted file mode 100644
index 2d28d18a7e..0000000000
--- a/test/readline/helper.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-begin
- require "readline.so"
- ReadlineSo = Readline
-rescue LoadError
-end
-
-def use_ext_readline # Use ext/readline as Readline
- Object.send(:remove_const, :Readline) if Object.const_defined?(:Readline)
- Object.const_set(:Readline, ReadlineSo)
-end
-
-begin
- require "reline"
-rescue LoadError
- Object.class_eval {remove_const :Reline} if defined?(Reline)
-else
- def use_lib_reline # Use lib/reline as Readline
- Reline.send(:remove_const, 'IOGate') if Reline.const_defined?('IOGate')
- Reline.const_set('IOGate', Reline::GeneralIO)
- Reline.send(:core).config.instance_variable_set(:@test_mode, true)
- Reline.send(:core).config.reset
- Object.send(:remove_const, :Readline) if Object.const_defined?(:Readline)
- Object.const_set(:Readline, Reline)
- end
-
- def finish_using_lib_reline
- Reline.instance_variable_set(:@core, nil)
- end
-end
diff --git a/test/readline/test_readline.rb b/test/readline/test_readline.rb
deleted file mode 100644
index a0438aa1fd..0000000000
--- a/test/readline/test_readline.rb
+++ /dev/null
@@ -1,930 +0,0 @@
-# frozen_string_literal: false
-require_relative "helper"
-require "test/unit"
-require "tempfile"
-require "timeout"
-require "open3"
-
-module BasetestReadline
- INPUTRC = "INPUTRC"
- SAVED_ENV = %w[COLUMNS LINES]
-
- TIMEOUT = 8
-
- def setup
- @saved_env = ENV.values_at(*SAVED_ENV)
- @inputrc, ENV[INPUTRC] = ENV[INPUTRC], IO::NULL
- end
-
- def teardown
- ENV[INPUTRC] = @inputrc
- Readline.instance_variable_set("@completion_proc", nil)
- begin
- Readline.delete_text
- Readline.point = 0
- rescue NotImplementedError
- end
- Readline.special_prefixes = ""
- Readline.completion_append_character = nil
- Readline.input = nil
- Readline.output = nil
- SAVED_ENV.each_with_index {|k, i| ENV[k] = @saved_env[i] }
- end
-
- def test_readline
- Readline::HISTORY.clear
- omit "Skip Editline" if /EditLine/n.match(Readline::VERSION)
- with_temp_stdio do |stdin, stdout|
- stdin.write("hello\n")
- stdin.close
- stdout.flush
- line = replace_stdio(stdin.path, stdout.path) {
- Readline.readline("> ", true)
- }
- assert_equal("hello", line)
- assert_equal(true, line.tainted?) if RUBY_VERSION < '2.7'
- stdout.rewind
- assert_equal("> ", stdout.read(2))
- assert_equal(1, Readline::HISTORY.length)
- assert_equal("hello", Readline::HISTORY[0])
-
- # Work around lack of SecurityError in Reline
- # test mode with tainted prompt.
- # Also skip test on Ruby 2.7+, where $SAFE/taint is deprecated.
- if RUBY_VERSION < '2.7' && defined?(TestRelineAsReadline) && !kind_of?(TestRelineAsReadline)
- begin
- Thread.start {
- $SAFE = 1
- assert_raise(SecurityError) do
- replace_stdio(stdin.path, stdout.path) do
- Readline.readline("> ".taint)
- end
- end
- }.join
- ensure
- $SAFE = 0
- end
- end
- end
- end
-
- # line_buffer
- # point
- def test_line_buffer__point
- omit "Skip Editline" if /EditLine/n.match(Readline::VERSION)
- omit "GNU Readline has special behaviors" if defined?(Reline) and Readline == Reline
- begin
- Readline.line_buffer
- Readline.point
- rescue NotImplementedError
- return
- end
-
- with_temp_stdio do |stdin, stdout|
- actual_text = nil
- actual_line_buffer = nil
- actual_point = nil
- Readline.completion_proc = ->(text) {
- actual_text = text
- actual_point = Readline.point
- actual_line_buffer = Readline.line_buffer
- stdin.write(" finish\n")
- stdin.flush
- stdout.flush
- return ["complete"]
- }
-
- stdin.write("first second\t")
- stdin.flush
- Readline.completion_append_character = " "
- replace_stdio(stdin.path, stdout.path) {
- Readline.readline("> ", false)
- }
- assert_equal("second", actual_text)
- assert_equal("first second", actual_line_buffer)
- assert_equal(12, actual_point)
- assert_equal("first complete finish", Readline.line_buffer)
- assert_equal(Encoding.find("locale"), Readline.line_buffer.encoding)
- assert_equal(true, Readline.line_buffer.tainted?) if RUBY_VERSION < '2.7'
-
- assert_equal(22, Readline.point)
-
- stdin.rewind
- stdout.rewind
-
- stdin.write("first second\t")
- stdin.flush
- Readline.completion_append_character = nil
- replace_stdio(stdin.path, stdout.path) {
- Readline.readline("> ", false)
- }
- assert_equal("second", actual_text)
- assert_equal("first second", actual_line_buffer)
- assert_equal(12, actual_point)
- assert_equal("first complete finish", Readline.line_buffer)
- assert_equal(Encoding.find("locale"), Readline.line_buffer.encoding)
- assert_equal(true, Readline.line_buffer.tainted?) if RUBY_VERSION < '2.7'
-
- assert_equal(21, Readline.point)
- end
- end
-
- 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"}]
- completion_case_fold = Readline.completion_case_fold
- expected.each do |e|
- Readline.completion_case_fold = e
- assert_equal(e, Readline.completion_case_fold)
- end
- ensure
- Readline.completion_case_fold = completion_case_fold
- end
-
- def test_completion_proc_empty_result
- omit "Skip Editline" if /EditLine/n.match(Readline::VERSION)
- with_temp_stdio do |stdin, stdout|
- stdin.write("first\t")
- stdin.flush
- Readline.completion_proc = ->(text) {[]}
- line1 = line2 = nil
- replace_stdio(stdin.path, stdout.path) {
- assert_nothing_raised(NoMemoryError) {line1 = Readline.readline("> ")}
- stdin.write("\n")
- stdin.flush
- assert_nothing_raised(NoMemoryError) {line2 = Readline.readline("> ")}
- }
- assert_equal("first", line1)
- assert_equal("", line2)
- begin
- assert_equal("", Readline.line_buffer)
- rescue NotImplementedError
- end
- end
- end
-
- def test_get_screen_size
- begin
- res = Readline.get_screen_size
- assert(res.is_a?(Array))
- rows, columns = *res
- assert(rows.is_a?(Integer))
- assert(rows >= 0)
- assert(columns.is_a?(Integer))
- assert(columns >= 0)
- rescue NotImplementedError
- 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
- enc = get_default_internal_encoding
- data_expected = [
- ["x", "x"],
- ["xyx", "x"],
- [" ", " "],
- ["\t", "\t"],
- ]
- data_expected.each do |(data, expected)|
- Readline.completion_append_character = data
- assert_equal(expected, Readline.completion_append_character)
- assert_equal(enc, Readline.completion_append_character.encoding)
- end
- Readline.completion_append_character = ""
- assert_equal(nil, Readline.completion_append_character)
- rescue NotImplementedError
- end
- end
-
- def test_completion_encoding
- omit "Skip Editline" if /EditLine/n.match(Readline::VERSION)
- bug5941 = '[Bug #5941]'
- append_character = Readline.completion_append_character
- Readline.completion_append_character = ""
- completion_case_fold = Readline.completion_case_fold
- locale = get_default_internal_encoding
- if locale == Encoding::UTF_8
- enc1 = Encoding::EUC_JP
- else
- enc1 = Encoding::UTF_8
- end
- results = nil
- Readline.completion_proc = ->(text) {results}
-
- [%W"\u{3042 3042} \u{3042 3044}", %W"\u{fe5b fe5b} \u{fe5b fe5c}"].any? do |w|
- begin
- results = w.map {|s| s.encode(locale)}
- rescue Encoding::UndefinedConversionError
- end
- end or
- begin
- "\xa1\xa2".encode(Encoding::UTF_8, locale)
- rescue
- else
- results = %W"\xa1\xa1 \xa1\xa2".map {|s| s.force_encoding(locale)}
- end or
- begin
- return if assert_under_utf8
- omit("missing test for locale #{locale.name}")
- end
- expected = results[0][0...1]
- Readline.completion_case_fold = false
- assert_equal(expected, with_pipe {|r, w| w << "\t"}, bug5941)
- Readline.completion_case_fold = true
- assert_equal(expected, with_pipe {|r, w| w << "\t"}, bug5941)
- results.map! {|s| s.encode(enc1)}
- assert_raise(Encoding::CompatibilityError, bug5941) do
- with_pipe {|r, w| w << "\t"}
- end
- ensure
- return if /EditLine/n.match(Readline::VERSION)
- Readline.completion_case_fold = completion_case_fold
- Readline.completion_append_character = append_character
- end
-
- # basic_word_break_characters
- # completer_word_break_characters
- # basic_quote_characters
- # completer_quote_characters
- # filename_quote_characters
- # special_prefixes
- def test_some_characters_methods
- end
-
- def test_closed_outstream
- bug5803 = '[ruby-dev:45043]'
- IO.pipe do |r, w|
- Readline.input = r
- Readline.output = w
- (w << "##\t").close
- assert_raise(IOError, bug5803) {Readline.readline}
- end
- end
-
- def test_pre_input_hook
- begin
- pr = proc {}
- Readline.pre_input_hook = pr
- assert_equal(pr, Readline.pre_input_hook)
- Readline.pre_input_hook = nil
- assert_nil(Readline.pre_input_hook)
- rescue NotImplementedError
- end
- end
-
- def test_point
- omit "Skip Editline" if /EditLine/n.match(Readline::VERSION)
- assert_equal(0, Readline.point)
- Readline.insert_text('12345')
- assert_equal(5, Readline.point)
-
- assert_equal(4, Readline.point=(4))
-
- Readline.insert_text('abc')
- assert_equal(7, Readline.point)
-
- assert_equal('1234abc5', Readline.line_buffer)
- rescue NotImplementedError
- end
-
- def test_insert_text
- omit "Skip Editline" if /EditLine/n.match(Readline::VERSION)
- str = "test_insert_text"
- assert_equal(0, Readline.point)
- assert_equal(Readline, Readline.insert_text(str))
- assert_equal(str, Readline.line_buffer)
- assert_equal(16, Readline.point)
- assert_equal(get_default_internal_encoding,
- Readline.line_buffer.encoding)
-
- Readline.delete_text(1, 3)
- assert_equal("t_insert_text", Readline.line_buffer)
- Readline.delete_text(11)
- assert_equal("t_insert_te", Readline.line_buffer)
- Readline.delete_text(-3...-1)
- assert_equal("t_inserte", Readline.line_buffer)
- Readline.delete_text(-3..-1)
- assert_equal("t_inse", Readline.line_buffer)
- Readline.delete_text(3..-3)
- assert_equal("t_ise", Readline.line_buffer)
- Readline.delete_text(3, 1)
- assert_equal("t_ie", Readline.line_buffer)
- Readline.delete_text(1..1)
- assert_equal("tie", Readline.line_buffer)
- Readline.delete_text(1...2)
- assert_equal("te", Readline.line_buffer)
- Readline.delete_text
- assert_equal("", Readline.line_buffer)
- rescue NotImplementedError
- end
-
- def test_delete_text
- omit "Skip Editline" if /EditLine/n.match(Readline::VERSION)
- str = "test_insert_text"
- assert_equal(0, Readline.point)
- assert_equal(Readline, Readline.insert_text(str))
- assert_equal(16, Readline.point)
- assert_equal(str, Readline.line_buffer)
- Readline.delete_text
-
- if !defined?(Reline) or Readline != Reline
- # NOTE: unexpected but GNU Readline's spec
- assert_equal(16, Readline.point)
- assert_equal("", Readline.line_buffer)
- assert_equal(Readline, Readline.insert_text(str))
- assert_equal(32, Readline.point)
- assert_equal("", Readline.line_buffer)
- end
- rescue NotImplementedError
- end
-
- def test_modify_text_in_pre_input_hook
- omit "Skip Editline" if /EditLine/n.match(Readline::VERSION)
- with_temp_stdio {|stdin, stdout|
- begin
- stdin.write("world\n")
- stdin.close
- Readline.pre_input_hook = proc do
- assert_equal("", Readline.line_buffer)
- Readline.insert_text("hello ")
- Readline.redisplay
- end
- replace_stdio(stdin.path, stdout.path) do
- line = Readline.readline("> ")
- assert_equal("hello world", line)
- end
- # Readline 4.3 doesn't include inserted text or input
- # Reline's rendering logic is tricky
- if Readline::VERSION != '4.3' and (!defined?(Reline) or Readline != Reline)
- assert_equal("> hello world\n", stdout.read)
- end
- stdout.close
- rescue NotImplementedError
- ensure
- begin
- Readline.pre_input_hook = nil
- rescue NotImplementedError
- end
- end
- }
- end
-
- def test_input_metachar
- omit "Skip Editline" if /EditLine/n.match(Readline::VERSION)
- # test will pass on Windows reline, but not readline
- omit "Won't pass on mingw readline.so using 8.0.001" if /mingw/ =~ RUBY_PLATFORM and defined?(TestReadline) and kind_of?(TestReadline)
- omit 'Needs GNU Readline 6 or later' if /mswin|mingw/ =~ RUBY_PLATFORM and defined?(TestReadline) and kind_of?(TestReadline) and Readline::VERSION < '6.0'
- bug6601 = '[ruby-core:45682]'
- Readline::HISTORY << "hello"
- wo = nil
- line = with_pipe do |r, w|
- wo = w.dup
- wo.write("\C-re\ef\n")
- end
- assert_equal("hello", line, bug6601)
- ensure
- wo&.close
- return if /EditLine/n.match(Readline::VERSION)
- Readline.delete_text
- Readline::HISTORY.clear
- end
-
- def test_input_metachar_multibyte
- omit "Skip Editline" if /EditLine/n.match(Readline::VERSION)
- unless Encoding.find("locale") == Encoding::UTF_8
- return if assert_under_utf8
- omit 'this test needs UTF-8 locale'
- end
- bug6602 = '[ruby-core:45683]'
- Readline::HISTORY << "\u3042\u3093"
- Readline::HISTORY << "\u3044\u3093"
- Readline::HISTORY << "\u3046\u3093"
- open(IO::NULL, 'w') do |null|
- IO.pipe do |r, w|
- Readline.input = r
- Readline.output = null
- w << "\cr\u3093\n\n"
- w << "\cr\u3042\u3093"
- w.reopen(IO::NULL)
- assert_equal("\u3046\u3093", Readline.readline("", true), bug6602)
- Timeout.timeout(TIMEOUT) do
- assert_equal("\u3042\u3093", Readline.readline("", true), bug6602)
- end
- assert_equal(nil, Readline.readline("", true), bug6602)
- end
- end
- ensure
- return if /EditLine/n.match(Readline::VERSION)
- Readline.delete_text
- Readline::HISTORY.clear
- end
-
- def test_refresh_line
- omit "Only when refresh_line exists" unless Readline.respond_to?(:refresh_line)
- omit unless respond_to?(:assert_ruby_status)
- bug6232 = '[ruby-core:43957] [Bug #6232] refresh_line after set_screen_size'
- with_temp_stdio do |stdin, stdout|
- replace_stdio(stdin.path, stdout.path) do
- assert_ruby_status(%w[-rreadline -], <<-'end;', bug6232)
- Readline.set_screen_size(40, 80)
- Readline.refresh_line
- end;
- end
- end
- end
-
- # TODO Green CI for arm32-linux (Travis CI), and Readline 7.0.
- def test_interrupt_in_other_thread
- # Editline and Readline 7.0 can't treat I/O that is not tty.
- omit "Skip Editline" if /EditLine/n.match(Readline::VERSION)
- omit "Skip Readline 7.0" if Readline::VERSION == "7.0"
- omit unless respond_to?(:assert_ruby_status)
- omit if /mswin|mingw/ =~ RUBY_PLATFORM
- code = <<-"end;"
- $stdout.sync = true
- require 'readline'
- require 'helper'
- puts "Readline::VERSION is \#{Readline::VERSION}."
- #{
- if defined?(TestReadline) && self.class == TestReadline
- "use_ext_readline"
- elsif defined?(TestRelineAsReadline) && self.class == TestRelineAsReadline
- "use_lib_reline"
- end
- }
- Readline.input = STDIN
- # 0. Send SIGINT to this script.
- begin
- Thread.new{
- trap(:INT) {
- puts 'TRAP' # 2. Show 'TRAP' message.
- }
- Readline.readline('input> ') # 1. Should keep working and call old trap.
- # 4. Receive "\\n" and return because still working.
- }.value
- rescue Interrupt
- puts 'FAILED' # 3. "Interrupt" shouldn't be raised because trapped.
- raise
- end
- puts 'SUCCEEDED' # 5. Finish correctly.
- end;
-
- script = Tempfile.new("interrupt_in_other_thread")
- script.write code
- script.close
-
- log = String.new
-
- EnvUtil.invoke_ruby(["-I#{__dir__}", script.path], "", true, :merge_to_stdout) do |_in, _out, _, pid|
- Timeout.timeout(TIMEOUT) do
- log << "** START **"
- loop do
- c = _out.read(1)
- log << c if c
- break if log.include?('input>')
- end
- log << "** SIGINT **"
- Process.kill(:INT, pid)
- sleep 0.1
- loop do
- c = _out.read(1)
- log << c if c
- break if log.include?('TRAP')
- end
- begin
- log << "** NEWLINE **"
- _in.write "\n"
- rescue Errno::EPIPE
- log << "** Errno::EPIPE **"
- # The "write" will fail if Reline crashed by SIGINT.
- end
- interrupt_suppressed = nil
- loop do
- c = _out.read(1)
- log << c if c
- if log.include?('FAILED')
- interrupt_suppressed = false
- break
- end
- if log.include?('SUCCEEDED')
- interrupt_suppressed = true
- break
- end
- end
- assert interrupt_suppressed, "Should handle SIGINT correctly but raised interrupt.\nLog: #{log}\n----"
- end
- rescue Timeout::Error => e
- assert false, "Timed out to handle SIGINT!\nLog: #{log}\nBacktrace:\n#{e.full_message(highlight: false)}\n----"
- ensure
- status = Process.wait2(pid).last
- assert status.success?, "Unknown failure with exit status #{status}\nLog: #{log}\n----"
- end
-
- assert log.include?('INT'), "Interrupt was handled correctly."
- ensure
- script&.close!
- end
-
- def test_setting_quoting_detection_proc
- return unless Readline.respond_to?(:quoting_detection_proc=)
-
- expected = proc { |text, index| false }
- Readline.quoting_detection_proc = expected
- assert_equal(expected, Readline.quoting_detection_proc)
-
- assert_raise(ArgumentError) do
- Readline.quoting_detection_proc = "This does not have call method."
- end
- end
-
- def test_using_quoting_detection_proc
- saved_completer_quote_characters = Readline.completer_quote_characters
- saved_completer_word_break_characters = Readline.completer_word_break_characters
-
- # skip if previous value is nil because Readline... = nil is not allowed.
- omit "No completer_quote_characters" unless saved_completer_quote_characters
- omit "No completer_word_break_characters" unless saved_completer_word_break_characters
-
- return unless Readline.respond_to?(:quoting_detection_proc=)
-
- begin
- passed_text = nil
- line = nil
-
- with_temp_stdio do |stdin, stdout|
- replace_stdio(stdin.path, stdout.path) do
- Readline.completion_proc = ->(text) do
- passed_text = text
- ['completion'].map { |i|
- i.encode(Encoding.default_external)
- }
- end
- Readline.completer_quote_characters = '\'"'
- Readline.completer_word_break_characters = ' '
- Readline.quoting_detection_proc = ->(text, index) do
- index > 0 && text[index-1] == '\\'
- end
-
- stdin.write("first second\\ third\t")
- stdin.flush
- line = Readline.readline('> ', false)
- end
- end
-
- assert_equal('second\\ third', passed_text)
- assert_equal('first completion', line.chomp(' '))
- ensure
- Readline.completer_quote_characters = saved_completer_quote_characters
- Readline.completer_word_break_characters = saved_completer_word_break_characters
- end
- end
-
- def test_using_quoting_detection_proc_with_multibyte_input
- Readline.completion_append_character = nil
- saved_completer_quote_characters = Readline.completer_quote_characters
- saved_completer_word_break_characters = Readline.completer_word_break_characters
-
- # skip if previous value is nil because Readline... = nil is not allowed.
- omit "No completer_quote_characters" unless saved_completer_quote_characters
- omit "No completer_word_break_characters" unless saved_completer_word_break_characters
-
- return unless Readline.respond_to?(:quoting_detection_proc=)
- unless get_default_internal_encoding == Encoding::UTF_8
- return if assert_under_utf8
- omit 'this test needs UTF-8 locale'
- end
-
- begin
- passed_text = nil
- escaped_char_indexes = []
- line = nil
-
- with_temp_stdio do |stdin, stdout|
- replace_stdio(stdin.path, stdout.path) do
- Readline.completion_proc = ->(text) do
- passed_text = text
- ['completion'].map { |i|
- i.encode(Encoding.default_external)
- }
- end
- Readline.completer_quote_characters = '\'"'
- Readline.completer_word_break_characters = ' '
- Readline.quoting_detection_proc = ->(text, index) do
- escaped = index > 0 && text[index-1] == '\\'
- escaped_char_indexes << index if escaped
- escaped
- end
-
- stdin.write("\u3042\u3093 second\\ third\t")
- stdin.flush
- line = Readline.readline('> ', false)
- end
- end
-
- assert_equal([10], escaped_char_indexes)
- assert_equal('second\\ third', passed_text)
- assert_equal("\u3042\u3093 completion#{Readline.completion_append_character}", line)
- ensure
- Readline.completer_quote_characters = saved_completer_quote_characters
- Readline.completer_word_break_characters = saved_completer_word_break_characters
- end
- end
-
- def test_simple_completion
- omit "Skip Editline" if /EditLine/n.match(Readline::VERSION)
-
- line = nil
-
- open(IO::NULL, 'w') do |null|
- IO.pipe do |r, w|
- Readline.input = r
- Readline.output = null
- Readline.completion_proc = ->(text) do
- ['abcde', 'abc12'].map { |i|
- i.encode(get_default_internal_encoding)
- }
- end
- w.write("a\t\n")
- w.flush
- begin
- stderr = $stderr.dup
- $stderr.reopen(null)
- line = Readline.readline('> ', false)
- ensure
- $stderr.reopen(stderr)
- stderr.close
- end
- end
- end
-
- assert_equal('abc', line)
- end
-
- def test_completion_with_completion_append_character
- omit "Skip Editline" if /EditLine/n.match(Readline::VERSION)
- omit "Readline.completion_append_character is not implemented" unless Readline.respond_to?(:completion_append_character=)
- line = nil
-
- append_character = Readline.completion_append_character
- open(IO::NULL, 'w') do |null|
- IO.pipe do |r, w|
- Readline.input = r
- Readline.output = null
- Readline.completion_append_character = '!'
- Readline.completion_proc = ->(text) do
- ['abcde'].map { |i|
- i.encode(get_default_internal_encoding)
- }
- end
- w.write("a\t\n")
- w.flush
- line = Readline.readline('> ', false)
- end
- end
-
- assert_equal('abcde!', line)
- ensure
- return if /EditLine/n.match(Readline::VERSION)
- return unless Readline.respond_to?(:completion_append_character=)
- Readline.completion_append_character = append_character
- end
-
- def test_completion_quote_character_completing_unquoted_argument
- return unless Readline.respond_to?(:completion_quote_character)
-
- saved_completer_quote_characters = Readline.completer_quote_characters
-
- quote_character = "original value"
- Readline.completion_proc = -> (_) do
- quote_character = Readline.completion_quote_character
- []
- end
- Readline.completer_quote_characters = "'\""
-
- with_temp_stdio do |stdin, stdout|
- replace_stdio(stdin.path, stdout.path) do
- stdin.write("input\t")
- stdin.flush
- Readline.readline("> ", false)
- end
- end
-
- assert_nil(quote_character)
- ensure
- Readline.completer_quote_characters = saved_completer_quote_characters if saved_completer_quote_characters
- end
-
- def test_completion_quote_character_completing_quoted_argument
- return unless Readline.respond_to?(:completion_quote_character)
-
- saved_completer_quote_characters = Readline.completer_quote_characters
-
- quote_character = "original value"
- Readline.completion_proc = -> (_) do
- quote_character = Readline.completion_quote_character
- []
- end
- Readline.completer_quote_characters = "'\""
-
- with_temp_stdio do |stdin, stdout|
- replace_stdio(stdin.path, stdout.path) do
- stdin.write("'input\t")
- stdin.flush
- Readline.readline("> ", false)
- end
- end
-
- assert_equal("'", quote_character)
- ensure
- Readline.completer_quote_characters = saved_completer_quote_characters if saved_completer_quote_characters
- end
-
- def test_completion_quote_character_after_completion
- return unless Readline.respond_to?(:completion_quote_character)
- if /solaris/i =~ RUBY_PLATFORM
- # http://rubyci.s3.amazonaws.com/solaris11s-sunc/ruby-trunk/log/20181228T102505Z.fail.html.gz
- omit 'This test does not succeed on Oracle Developer Studio for now'
- end
- omit 'Needs GNU Readline 6 or later' if /mswin|mingw/ =~ RUBY_PLATFORM and defined?(TestReadline) and kind_of?(TestReadline) and Readline::VERSION < '6.0'
-
- saved_completer_quote_characters = Readline.completer_quote_characters
-
- Readline.completion_proc = -> (_) { [] }
- Readline.completer_quote_characters = "'\""
-
- with_temp_stdio do |stdin, stdout|
- replace_stdio(stdin.path, stdout.path) do
- stdin.write("'input\t")
- stdin.flush
- Readline.readline("> ", false)
- end
- end
-
- assert_nil(Readline.completion_quote_character)
- ensure
- Readline.completer_quote_characters = saved_completer_quote_characters if saved_completer_quote_characters
- end
-
- def test_without_tty
- omit "Skip Editline" if /EditLine/n.match(Readline::VERSION)
- loader = nil
- if defined?(TestReadline) && self.class == TestReadline
- loader = "use_ext_readline"
- elsif defined?(TestRelineAsReadline) && self.class == TestRelineAsReadline
- loader = "use_lib_reline"
- end
- if loader
- res, exit_status = Open3.capture2e("ruby -I#{__dir__} -Ilib -rhelper -e '#{loader}; Readline.readline(%{y or n?})'", stdin_data: "y\n")
- assert exit_status.success?, "It should work fine without tty, but it failed.\nError output:\n#{res}"
- 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
- orig_stderr = STDERR.dup
- STDIN.reopen(stdin)
- STDOUT.reopen(stdout)
- STDERR.reopen(stdout)
- begin
- Readline.input = STDIN
- Readline.output = STDOUT
- yield
- ensure
- STDERR.reopen(orig_stderr)
- STDIN.reopen(orig_stdin)
- STDOUT.reopen(orig_stdout)
- orig_stdin.close
- orig_stdout.close
- orig_stderr.close
- end
- }
- }
- end
-
- def with_temp_stdio
- Tempfile.create("test_readline_stdin") {|stdin|
- Tempfile.create("test_readline_stdout") {|stdout|
- yield stdin, stdout
- if /mswin|mingw/ =~ RUBY_PLATFORM
- # needed since readline holds refs to tempfiles, can't delete on Windows
- Readline.input = STDIN
- Readline.output = STDOUT
- end
- }
- }
- end
-
- def with_pipe
- stderr = nil
- IO.pipe do |r, w|
- yield(r, w)
- Readline.input = r
- Readline.output = w.reopen(IO::NULL)
- stderr = STDERR.dup
- STDERR.reopen(w)
- Readline.readline
- end
- ensure
- if stderr
- STDERR.reopen(stderr)
- stderr.close
- end
- Readline.input = STDIN
- Readline.output = STDOUT
- end
-
- def get_default_internal_encoding
- return Encoding.default_internal || Encoding.find("locale")
- end
-
- def assert_under_utf8
- return false if ENV['LC_ALL'] == 'UTF-8'
- loc = caller_locations(1, 1)[0].base_label.to_s
- assert_separately([{"LC_ALL"=>"UTF-8"}, "-r", __FILE__], <<SRC)
-#omit "test \#{ENV['LC_ALL']}"
-#{self.class.name}.new(#{loc.dump}).run(Test::Unit::Runner.new)
-SRC
- return true
- end
-end
-
-class TestReadline < Test::Unit::TestCase
- include BasetestReadline
-
- def setup
- use_ext_readline
- super
- end
-end if defined?(ReadlineSo) && ENV["TEST_READLINE_OR_RELINE"] != "Reline"
-
-class TestRelineAsReadline < Test::Unit::TestCase
- include BasetestReadline
-
- def setup
- use_lib_reline
- super
- end
-
- def teardown
- finish_using_lib_reline
- super
- end
-
- def get_default_internal_encoding
- if RUBY_PLATFORM =~ /mswin|mingw/
- Encoding.default_internal || Encoding::UTF_8
- else
- Reline::IOGate.encoding
- end
- end
-end if defined?(Reline) && ENV["TEST_READLINE_OR_RELINE"] != "Readline"
diff --git a/test/readline/test_readline_history.rb b/test/readline/test_readline_history.rb
deleted file mode 100644
index 39ad4fe85a..0000000000
--- a/test/readline/test_readline_history.rb
+++ /dev/null
@@ -1,292 +0,0 @@
-# frozen_string_literal: false
-require_relative "helper"
-require "test/unit"
-
-module BasetestReadlineHistory
- def setup
- Readline::HISTORY.clear
- end
-
- def test_to_s
- expected = "HISTORY"
- assert_equal(expected, Readline::HISTORY.to_s)
- end
-
- def test_get
- lines = push_history(5)
- lines.each_with_index do |s, i|
- assert_external_string_equal(s, Readline::HISTORY[i])
- end
- end
-
- def test_get__negative
- lines = push_history(5)
- (1..5).each do |i|
- assert_equal(lines[-i], Readline::HISTORY[-i])
- end
- end
-
- def test_get__out_of_range
- push_history(5)
- invalid_indexes = [5, 6, 100, -6, -7, -100]
- invalid_indexes.each do |i|
- assert_raise(IndexError, "i=<#{i}>") do
- Readline::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
- Readline::HISTORY[i]
- end
- end
- end
-
- def test_set
- begin
- push_history(5)
- 5.times do |i|
- expected = "set: #{i}"
- Readline::HISTORY[i] = expected
- assert_external_string_equal(expected, Readline::HISTORY[i])
- end
- rescue NotImplementedError
- end
- end
-
- def test_set__out_of_range
- assert_raise(IndexError, NotImplementedError, "index=<0>") do
- Readline::HISTORY[0] = "set: 0"
- end
-
- push_history(5)
- invalid_indexes = [5, 6, 100, -6, -7, -100]
- invalid_indexes.each do |i|
- assert_raise(IndexError, NotImplementedError, "index=<#{i}>") do
- Readline::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
- Readline::HISTORY[i] = "set: #{i}"
- end
- end
- end
-
- def test_push
- 5.times do |i|
- s = i.to_s
- assert_equal(Readline::HISTORY, Readline::HISTORY.push(s))
- assert_external_string_equal(s, Readline::HISTORY[i])
- end
- assert_equal(5, Readline::HISTORY.length)
- end
-
- def test_push__operator
- 5.times do |i|
- s = i.to_s
- assert_equal(Readline::HISTORY, Readline::HISTORY << s)
- assert_external_string_equal(s, Readline::HISTORY[i])
- end
- assert_equal(5, Readline::HISTORY.length)
- end
-
- def test_push__plural
- assert_equal(Readline::HISTORY, Readline::HISTORY.push("0", "1", "2", "3", "4"))
- (0..4).each do |i|
- assert_external_string_equal(i.to_s, Readline::HISTORY[i])
- end
- assert_equal(5, Readline::HISTORY.length)
-
- assert_equal(Readline::HISTORY, Readline::HISTORY.push("5", "6", "7", "8", "9"))
- (5..9).each do |i|
- assert_external_string_equal(i.to_s, Readline::HISTORY[i])
- end
- assert_equal(10, Readline::HISTORY.length)
- end
-
- def test_pop
- begin
- assert_equal(nil, Readline::HISTORY.pop)
-
- lines = push_history(5)
- (1..5).each do |i|
- assert_external_string_equal(lines[-i], Readline::HISTORY.pop)
- assert_equal(lines.length - i, Readline::HISTORY.length)
- end
-
- assert_equal(nil, Readline::HISTORY.pop)
- rescue NotImplementedError
- end
- end
-
- def test_shift
- begin
- assert_equal(nil, Readline::HISTORY.shift)
-
- lines = push_history(5)
- (0..4).each do |i|
- assert_external_string_equal(lines[i], Readline::HISTORY.shift)
- assert_equal(lines.length - (i + 1), Readline::HISTORY.length)
- end
-
- assert_equal(nil, Readline::HISTORY.shift)
- rescue NotImplementedError
- end
- end
-
- def test_each
- e = Readline::HISTORY.each do |s|
- assert(false) # not reachable
- end
- assert_equal(Readline::HISTORY, e)
- lines = push_history(5)
- i = 0
- e = Readline::HISTORY.each do |s|
- assert_external_string_equal(Readline::HISTORY[i], s)
- assert_external_string_equal(lines[i], s)
- i += 1
- end
- assert_equal(Readline::HISTORY, e)
- end
-
- def test_each__enumerator
- e = Readline::HISTORY.each
- assert_instance_of(Enumerator, e)
- end
-
- def test_length
- assert_equal(0, Readline::HISTORY.length)
- push_history(1)
- assert_equal(1, Readline::HISTORY.length)
- push_history(4)
- assert_equal(5, Readline::HISTORY.length)
- Readline::HISTORY.clear
- assert_equal(0, Readline::HISTORY.length)
- end
-
- def test_empty_p
- 2.times do
- assert(Readline::HISTORY.empty?)
- Readline::HISTORY.push("s")
- assert_equal(false, Readline::HISTORY.empty?)
- Readline::HISTORY.clear
- assert(Readline::HISTORY.empty?)
- end
- end
-
- def test_delete_at
- begin
- lines = push_history(5)
- (0..4).each do |i|
- assert_external_string_equal(lines[i], Readline::HISTORY.delete_at(0))
- end
- assert(Readline::HISTORY.empty?)
-
- lines = push_history(5)
- (1..5).each do |i|
- assert_external_string_equal(lines[lines.length - i], Readline::HISTORY.delete_at(-1))
- end
- assert(Readline::HISTORY.empty?)
-
- lines = push_history(5)
- assert_external_string_equal(lines[0], Readline::HISTORY.delete_at(0))
- assert_external_string_equal(lines[4], Readline::HISTORY.delete_at(3))
- assert_external_string_equal(lines[1], Readline::HISTORY.delete_at(0))
- assert_external_string_equal(lines[3], Readline::HISTORY.delete_at(1))
- assert_external_string_equal(lines[2], Readline::HISTORY.delete_at(0))
- assert(Readline::HISTORY.empty?)
- rescue NotImplementedError
- end
- end
-
- def test_delete_at__out_of_range
- assert_raise(IndexError, NotImplementedError, "index=<0>") do
- Readline::HISTORY.delete_at(0)
- end
-
- push_history(5)
- invalid_indexes = [5, 6, 100, -6, -7, -100]
- invalid_indexes.each do |i|
- assert_raise(IndexError, NotImplementedError, "index=<#{i}>") do
- Readline::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_raise(RangeError, NotImplementedError, "index=<#{i}>") do
- Readline::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
- Readline::HISTORY.push(*lines)
- return lines
- end
-
- def assert_external_string_equal(expected, actual)
- assert_equal(expected, actual)
- assert_equal(get_default_internal_encoding, actual.encoding)
- end
-
- def get_default_internal_encoding
- return Encoding.default_internal || Encoding.find("locale")
- end
-end
-
-class TestReadlineHistory < Test::Unit::TestCase
- include BasetestReadlineHistory
-
- def setup
- use_ext_readline
- super
- end
-end if defined?(::ReadlineSo) && defined?(::ReadlineSo::HISTORY) &&
- ENV["TEST_READLINE_OR_RELINE"] != "Reline" &&
- (
- begin
- ReadlineSo::HISTORY.clear
- rescue NotImplementedError
- false
- end
- )
-
-class TestRelineAsReadlineHistory < Test::Unit::TestCase
- include BasetestReadlineHistory
-
- def setup
- use_lib_reline
- super
- end
-
- def teardown
- finish_using_lib_reline
- super
- end
-
- def get_default_internal_encoding
- if RUBY_PLATFORM =~ /mswin|mingw/
- Encoding.default_internal || Encoding::UTF_8
- else
- Reline::IOGate.encoding
- end
- end
-end if defined?(Reline) && ENV["TEST_READLINE_OR_RELINE"] != "Readline"
diff --git a/test/reline/helper.rb b/test/reline/helper.rb
index cd3783ddb8..3d7dc7d812 100644
--- a/test/reline/helper.rb
+++ b/test/reline/helper.rb
@@ -5,33 +5,84 @@ ENV['TERM'] = 'xterm' # for some CI environments
require 'reline'
require 'test/unit'
+begin
+ require 'rbconfig'
+rescue LoadError
+end
+
+begin
+ # This should exist and available in load path when this file is mirrored to ruby/ruby and running at there
+ if File.exist?(File.expand_path('../../tool/lib/envutil.rb', __dir__))
+ require 'envutil'
+ end
+rescue LoadError
+end
+
module Reline
class <<self
- def test_mode
- remove_const('IOGate') if const_defined?('IOGate')
- const_set('IOGate', Reline::GeneralIO)
- if ENV['RELINE_TEST_ENCODING']
- encoding = Encoding.find(ENV['RELINE_TEST_ENCODING'])
- else
- encoding = Encoding::UTF_8
+ def test_mode(ansi: false)
+ @original_iogate = IOGate
+
+ if ENV['RELINE_TEST_ENCODING']
+ encoding = Encoding.find(ENV['RELINE_TEST_ENCODING'])
+ else
+ encoding = Encoding::UTF_8
+ end
+
+ if ansi
+ new_io_gate = ANSI.new
+ # Setting ANSI gate's screen size through set_screen_size will also change the tester's stdin's screen size
+ # Let's avoid that side-effect by stubbing the get_screen_size method
+ new_io_gate.define_singleton_method(:get_screen_size) do
+ [24, 80]
end
- Reline::GeneralIO.reset(encoding: encoding)
- send(:core).config.instance_variable_set(:@test_mode, true)
- send(:core).config.reset
+ new_io_gate.define_singleton_method(:encoding) do
+ encoding
+ end
+ else
+ new_io_gate = Dumb.new(encoding: encoding)
+ end
+
+ remove_const('IOGate')
+ const_set('IOGate', new_io_gate)
+ core.config.instance_variable_set(:@test_mode, true)
+ core.config.reset
end
def test_reset
+ remove_const('IOGate')
+ const_set('IOGate', @original_iogate)
Reline.instance_variable_set(:@core, nil)
end
- end
-end
-def start_pasting
- Reline::GeneralIO.start_pasting
-end
+ # Return a executable name to spawn Ruby process. In certain build configuration,
+ # "ruby" may not be available.
+ def test_rubybin
+ # When this test suite is running in ruby/ruby, prefer EnvUtil result over original implementation
+ if const_defined?(:EnvUtil)
+ return EnvUtil.rubybin
+ end
-def finish_pasting
- Reline::GeneralIO.finish_pasting
+ # The following is a simplified port of EnvUtil.rubybin in ruby/ruby
+ if ruby = ENV["RUBY"]
+ return ruby
+ end
+ ruby = "ruby"
+ exeext = RbConfig::CONFIG["EXEEXT"]
+ rubyexe = (ruby + exeext if exeext and !exeext.empty?)
+ if File.exist? ruby and File.executable? ruby and !File.directory? ruby
+ return File.expand_path(ruby)
+ end
+ if rubyexe and File.exist? rubyexe and File.executable? rubyexe
+ return File.expand_path(rubyexe)
+ end
+ if defined?(RbConfig.ruby)
+ RbConfig.ruby
+ else
+ "ruby"
+ end
+ end
+ end
end
class Reline::TestCase < Test::Unit::TestCase
@@ -45,7 +96,7 @@ class Reline::TestCase < Test::Unit::TestCase
end
}.join
rescue Encoding::UndefinedConversionError, Encoding::InvalidByteSequenceError
- input.unicode_normalize!(:nfc)
+ input = input.unicode_normalize(:nfc)
if normalized
options[:undef] = :replace
options[:replace] = '?'
@@ -77,25 +128,33 @@ class Reline::TestCase < Test::Unit::TestCase
end
end
- def assert_line(expected)
- expected = convert_str(expected)
- assert_equal(expected, @line_editor.line)
+ def input_raw_keys(input, convert = true)
+ input = convert_str(input) if convert
+ input.bytes.each do |b|
+ @line_editor.input_key(Reline::Key.new(b, b, false))
+ end
+ end
+
+ def assert_line_around_cursor(before, after)
+ before = convert_str(before)
+ after = convert_str(after)
+ line = @line_editor.current_line
+ byte_pointer = @line_editor.instance_variable_get(:@byte_pointer)
+ actual_before = line.byteslice(0, byte_pointer)
+ actual_after = line.byteslice(byte_pointer..)
+ assert_equal([before, after], [actual_before, actual_after])
end
def assert_byte_pointer_size(expected)
expected = convert_str(expected)
byte_pointer = @line_editor.instance_variable_get(:@byte_pointer)
+ chunk = @line_editor.line.byteslice(0, byte_pointer)
assert_equal(
expected.bytesize, byte_pointer,
- "<#{expected.inspect}> expected but was\n<#{@line_editor.line.byteslice(0, byte_pointer).inspect}>")
- end
-
- def assert_cursor(expected)
- assert_equal(expected, @line_editor.instance_variable_get(:@cursor))
- end
-
- def assert_cursor_max(expected)
- assert_equal(expected, @line_editor.instance_variable_get(:@cursor_max))
+ <<~EOM)
+ <#{expected.inspect} (#{expected.encoding.inspect})> expected but was
+ <#{chunk.inspect} (#{chunk.encoding.inspect})> in <Terminal #{Reline::Dumb.new.encoding.inspect}>
+ EOM
end
def assert_line_index(expected)
@@ -103,12 +162,13 @@ class Reline::TestCase < Test::Unit::TestCase
end
def assert_whole_lines(expected)
- previous_line_index = @line_editor.instance_variable_get(:@previous_line_index)
- if previous_line_index
- lines = @line_editor.whole_lines(index: previous_line_index)
- else
- lines = @line_editor.whole_lines
+ assert_equal(expected, @line_editor.whole_lines)
+ end
+
+ def assert_key_binding(input, method_symbol, editing_modes = [:emacs, :vi_insert, :vi_command])
+ editing_modes.each do |editing_mode|
+ @config.editing_mode = editing_mode
+ assert_equal(method_symbol, @config.editing_mode.get(input.bytes))
end
- assert_equal(expected, lines)
end
end
diff --git a/test/reline/test_ansi_with_terminfo.rb b/test/reline/test_ansi_with_terminfo.rb
new file mode 100644
index 0000000000..3adda10716
--- /dev/null
+++ b/test/reline/test_ansi_with_terminfo.rb
@@ -0,0 +1,112 @@
+require_relative 'helper'
+require 'reline'
+
+class Reline::ANSI::WithTerminfoTest < Reline::TestCase
+ def setup
+ Reline.send(:test_mode, ansi: true)
+ @config = Reline::Config.new
+ Reline.core.io_gate.set_default_key_bindings(@config, allow_terminfo: true)
+ end
+
+ def teardown
+ Reline.test_reset
+ end
+
+ # Home key
+ def test_khome
+ assert_key_binding(Reline::Terminfo.tigetstr('khome'), :ed_move_to_beg)
+ rescue Reline::Terminfo::TerminfoError => e
+ omit e.message
+ end
+
+ # End key
+ def test_kend
+ assert_key_binding(Reline::Terminfo.tigetstr('kend'), :ed_move_to_end)
+ rescue Reline::Terminfo::TerminfoError => e
+ omit e.message
+ end
+
+ # Delete key
+ def test_kdch1
+ assert_key_binding(Reline::Terminfo.tigetstr('kdch1'), :key_delete)
+ rescue Reline::Terminfo::TerminfoError => e
+ omit e.message
+ end
+
+ # PgUp key
+ def test_kpp
+ assert_key_binding(Reline::Terminfo.tigetstr('kpp'), :ed_search_prev_history)
+ rescue Reline::Terminfo::TerminfoError => e
+ omit e.message
+ end
+
+ # PgDn key
+ def test_knp
+ assert_key_binding(Reline::Terminfo.tigetstr('knp'), :ed_search_next_history)
+ rescue Reline::Terminfo::TerminfoError => e
+ omit e.message
+ end
+
+ # Up arrow key
+ def test_kcuu1
+ assert_key_binding(Reline::Terminfo.tigetstr('kcuu1'), :ed_prev_history)
+ rescue Reline::Terminfo::TerminfoError => e
+ omit e.message
+ end
+
+ # Down arrow key
+ def test_kcud1
+ assert_key_binding(Reline::Terminfo.tigetstr('kcud1'), :ed_next_history)
+ rescue Reline::Terminfo::TerminfoError => e
+ omit e.message
+ end
+
+ # Right arrow key
+ def test_kcuf1
+ assert_key_binding(Reline::Terminfo.tigetstr('kcuf1'), :ed_next_char)
+ rescue Reline::Terminfo::TerminfoError => e
+ omit e.message
+ end
+
+ # Left arrow key
+ def test_kcub1
+ assert_key_binding(Reline::Terminfo.tigetstr('kcub1'), :ed_prev_char)
+ rescue Reline::Terminfo::TerminfoError => e
+ omit e.message
+ end
+
+ # Home and End; always mapped regardless of terminfo enabled or not
+ def test_home_end
+ assert_key_binding("\e[H", :ed_move_to_beg)
+ assert_key_binding("\e[F", :ed_move_to_end)
+ end
+
+ # Arrow; always mapped regardless of terminfo enabled or not
+ def test_arrow
+ assert_key_binding("\e[A", :ed_prev_history)
+ assert_key_binding("\e[B", :ed_next_history)
+ assert_key_binding("\e[C", :ed_next_char)
+ assert_key_binding("\e[D", :ed_prev_char)
+ end
+
+ # Ctrl+arrow and Meta+arrow; always mapped regardless of terminfo enabled or not
+ def test_extended
+ assert_key_binding("\e[1;5C", :em_next_word) # Ctrl+→
+ assert_key_binding("\e[1;5D", :ed_prev_word) # Ctrl+â†
+ assert_key_binding("\e[1;3C", :em_next_word) # Meta+→
+ assert_key_binding("\e[1;3D", :ed_prev_word) # Meta+â†
+ assert_key_binding("\e\e[C", :em_next_word) # Meta+→
+ assert_key_binding("\e\e[D", :ed_prev_word) # Meta+â†
+ end
+
+ # Shift-Tab; always mapped regardless of terminfo enabled or not
+ def test_shift_tab
+ assert_key_binding("\e[Z", :completion_journey_up, [:emacs, :vi_insert])
+ end
+
+ # A few emacs bindings that are always mapped regardless of terminfo enabled or not
+ def test_more_emacs
+ assert_key_binding("\e ", :em_set_mark, [:emacs])
+ assert_key_binding("\C-x\C-x", :em_exchange_mark, [:emacs])
+ end
+end if Reline::Terminfo.enabled? && Reline::Terminfo.term_supported?
diff --git a/test/reline/test_ansi_without_terminfo.rb b/test/reline/test_ansi_without_terminfo.rb
new file mode 100644
index 0000000000..2db14cf0a0
--- /dev/null
+++ b/test/reline/test_ansi_without_terminfo.rb
@@ -0,0 +1,77 @@
+require_relative 'helper'
+require 'reline'
+
+class Reline::ANSI::WithoutTerminfoTest < Reline::TestCase
+ def setup
+ Reline.send(:test_mode, ansi: true)
+ @config = Reline::Config.new
+ Reline.core.io_gate.set_default_key_bindings(@config, allow_terminfo: false)
+ end
+
+ def teardown
+ Reline.test_reset
+ end
+
+ def test_home
+ assert_key_binding("\e[1~", :ed_move_to_beg) # Console (80x25)
+ assert_key_binding("\e[H", :ed_move_to_beg) # KDE
+ assert_key_binding("\e[7~", :ed_move_to_beg) # urxvt / exoterm
+ assert_key_binding("\eOH", :ed_move_to_beg) # GNOME
+ end
+
+ def test_end
+ assert_key_binding("\e[4~", :ed_move_to_end) # Console (80x25)
+ assert_key_binding("\e[F", :ed_move_to_end) # KDE
+ assert_key_binding("\e[8~", :ed_move_to_end) # urxvt / exoterm
+ assert_key_binding("\eOF", :ed_move_to_end) # GNOME
+ end
+
+ def test_delete
+ assert_key_binding("\e[3~", :key_delete)
+ end
+
+ def test_up_arrow
+ assert_key_binding("\e[A", :ed_prev_history) # Console (80x25)
+ assert_key_binding("\eGA", :ed_prev_history) # KDE
+ assert_key_binding("\eOA", :ed_prev_history)
+ end
+
+ def test_down_arrow
+ assert_key_binding("\e[B", :ed_next_history) # Console (80x25)
+ assert_key_binding("\eGB", :ed_next_history) # KDE
+ assert_key_binding("\eOB", :ed_next_history)
+ end
+
+ def test_right_arrow
+ assert_key_binding("\e[C", :ed_next_char) # Console (80x25)
+ assert_key_binding("\eGC", :ed_next_char) # KDE
+ assert_key_binding("\eOC", :ed_next_char)
+ end
+
+ def test_left_arrow
+ assert_key_binding("\e[D", :ed_prev_char) # Console (80x25)
+ assert_key_binding("\eGD", :ed_prev_char) # KDE
+ assert_key_binding("\eOD", :ed_prev_char)
+ end
+
+ # Ctrl+arrow and Meta+arrow; always mapped regardless of terminfo enabled or not
+ def test_extended
+ assert_key_binding("\e[1;5C", :em_next_word) # Ctrl+→
+ assert_key_binding("\e[1;5D", :ed_prev_word) # Ctrl+â†
+ assert_key_binding("\e[1;3C", :em_next_word) # Meta+→
+ assert_key_binding("\e[1;3D", :ed_prev_word) # Meta+â†
+ assert_key_binding("\e\e[C", :em_next_word) # Meta+→
+ assert_key_binding("\e\e[D", :ed_prev_word) # Meta+â†
+ end
+
+ # Shift-Tab; always mapped regardless of terminfo enabled or not
+ def test_shift_tab
+ assert_key_binding("\e[Z", :completion_journey_up, [:emacs, :vi_insert])
+ end
+
+ # A few emacs bindings that are always mapped regardless of terminfo enabled or not
+ def test_more_emacs
+ assert_key_binding("\e ", :em_set_mark, [:emacs])
+ assert_key_binding("\C-x\C-x", :em_exchange_mark, [:emacs])
+ end
+end
diff --git a/test/reline/test_config.rb b/test/reline/test_config.rb
index aa549a392d..68a102a599 100644
--- a/test/reline/test_config.rb
+++ b/test/reline/test_config.rb
@@ -11,21 +11,38 @@ class Reline::Config::Test < Reline::TestCase
Dir.mkdir(@tmpdir)
end
Dir.chdir(@tmpdir)
+ Reline.test_mode
@config = Reline::Config.new
+ @inputrc_backup = ENV['INPUTRC']
end
def teardown
Dir.chdir(@pwd)
FileUtils.rm_rf(@tmpdir)
+ Reline.test_reset
@config.reset
+ ENV['INPUTRC'] = @inputrc_backup
+ end
+
+ def get_config_variable(variable)
+ @config.instance_variable_get(variable)
+ end
+
+ def additional_key_bindings(keymap_label)
+ get_config_variable(:@additional_key_bindings)[keymap_label].instance_variable_get(:@key_bindings)
+ end
+
+ def registered_key_bindings(keys)
+ key_bindings = @config.key_bindings
+ keys.to_h { |key| [key, key_bindings.get(key)] }
end
def test_read_lines
@config.read_lines(<<~LINES.lines)
- set bell-style on
+ set show-mode-in-prompt on
LINES
- assert_equal :audible, @config.instance_variable_get(:@bell_style)
+ assert_equal true, get_config_variable(:@show_mode_in_prompt)
end
def test_read_lines_with_variable
@@ -33,7 +50,7 @@ class Reline::Config::Test < Reline::TestCase
set disable-completion on
LINES
- assert_equal true, @config.instance_variable_get(:@disable_completion)
+ assert_equal true, get_config_variable(:@disable_completion)
end
def test_string_value
@@ -42,7 +59,7 @@ class Reline::Config::Test < Reline::TestCase
set emacs-mode-string Emacs
LINES
- assert_equal 'Emacs', @config.instance_variable_get(:@emacs_mode_string)
+ assert_equal 'Emacs', get_config_variable(:@emacs_mode_string)
end
def test_string_value_with_brackets
@@ -51,7 +68,7 @@ class Reline::Config::Test < Reline::TestCase
set emacs-mode-string [Emacs]
LINES
- assert_equal '[Emacs]', @config.instance_variable_get(:@emacs_mode_string)
+ assert_equal '[Emacs]', get_config_variable(:@emacs_mode_string)
end
def test_string_value_with_brackets_and_quotes
@@ -60,7 +77,7 @@ class Reline::Config::Test < Reline::TestCase
set emacs-mode-string "[Emacs]"
LINES
- assert_equal '[Emacs]', @config.instance_variable_get(:@emacs_mode_string)
+ assert_equal '[Emacs]', get_config_variable(:@emacs_mode_string)
end
def test_string_value_with_parens
@@ -69,7 +86,7 @@ class Reline::Config::Test < Reline::TestCase
set emacs-mode-string (Emacs)
LINES
- assert_equal '(Emacs)', @config.instance_variable_get(:@emacs_mode_string)
+ assert_equal '(Emacs)', get_config_variable(:@emacs_mode_string)
end
def test_string_value_with_parens_and_quotes
@@ -78,17 +95,34 @@ class Reline::Config::Test < Reline::TestCase
set emacs-mode-string "(Emacs)"
LINES
- assert_equal '(Emacs)', @config.instance_variable_get(:@emacs_mode_string)
+ assert_equal '(Emacs)', get_config_variable(:@emacs_mode_string)
end
- def test_comment_line
- @config.read_lines([" #a: error\n"])
- assert_not_include @config.key_bindings, nil
+ def test_encoding_is_ascii
+ @config.reset
+ Reline.core.io_gate.instance_variable_set(:@encoding, Encoding::US_ASCII)
+ @config = Reline::Config.new
+
+ assert_equal true, @config.convert_meta
+ end
+
+ def test_encoding_is_not_ascii
+ @config = Reline::Config.new
+
+ assert_equal false, @config.convert_meta
end
def test_invalid_keystroke
- @config.read_lines(["a: error\n"])
- assert_not_include @config.key_bindings, nil
+ @config.read_lines(<<~LINES.lines)
+ #"a": comment
+ a: error
+ "b": no-error
+ LINES
+ key_bindings = additional_key_bindings(:emacs)
+ assert_not_include key_bindings, 'a'.bytes
+ assert_not_include key_bindings, nil
+ assert_not_include key_bindings, []
+ assert_include key_bindings, 'b'.bytes
end
def test_bind_key
@@ -132,55 +166,104 @@ class Reline::Config::Test < Reline::TestCase
def test_include
File.open('included_partial', 'wt') do |f|
f.write(<<~PARTIAL_LINES)
- set bell-style on
+ set show-mode-in-prompt on
PARTIAL_LINES
end
@config.read_lines(<<~LINES.lines)
$include included_partial
LINES
- assert_equal :audible, @config.instance_variable_get(:@bell_style)
+ assert_equal true, get_config_variable(:@show_mode_in_prompt)
+ end
+
+ def test_include_expand_path
+ home_backup = ENV['HOME']
+ File.open('included_partial', 'wt') do |f|
+ f.write(<<~PARTIAL_LINES)
+ set show-mode-in-prompt on
+ PARTIAL_LINES
+ end
+ ENV['HOME'] = Dir.pwd
+ @config.read_lines(<<~LINES.lines)
+ $include ~/included_partial
+ LINES
+
+ assert_equal true, get_config_variable(:@show_mode_in_prompt)
+ ensure
+ ENV['HOME'] = home_backup
end
def test_if
@config.read_lines(<<~LINES.lines)
$if Ruby
- set bell-style audible
+ set vi-cmd-mode-string (cmd)
$else
- set bell-style visible
+ set vi-cmd-mode-string [cmd]
$endif
LINES
- assert_equal :audible, @config.instance_variable_get(:@bell_style)
+ assert_equal '(cmd)', get_config_variable(:@vi_cmd_mode_string)
end
def test_if_with_false
@config.read_lines(<<~LINES.lines)
$if Python
- set bell-style audible
+ set vi-cmd-mode-string (cmd)
$else
- set bell-style visible
+ set vi-cmd-mode-string [cmd]
$endif
LINES
- assert_equal :visible, @config.instance_variable_get(:@bell_style)
+ assert_equal '[cmd]', get_config_variable(:@vi_cmd_mode_string)
end
def test_if_with_indent
%w[Ruby Reline].each do |cond|
@config.read_lines(<<~LINES.lines)
- set bell-style none
+ set vi-cmd-mode-string {cmd}
$if #{cond}
- set bell-style audible
+ set vi-cmd-mode-string (cmd)
$else
- set bell-style visible
+ set vi-cmd-mode-string [cmd]
$endif
LINES
- assert_equal :audible, @config.instance_variable_get(:@bell_style)
+ assert_equal '(cmd)', get_config_variable(:@vi_cmd_mode_string)
end
end
+ def test_nested_if_else
+ @config.read_lines(<<~LINES.lines)
+ $if Ruby
+ "\x1": "O"
+ $if NotRuby
+ "\x2": "X"
+ $else
+ "\x3": "O"
+ $if Ruby
+ "\x4": "O"
+ $else
+ "\x5": "X"
+ $endif
+ "\x6": "O"
+ $endif
+ "\x7": "O"
+ $else
+ "\x8": "X"
+ $if NotRuby
+ "\x9": "X"
+ $else
+ "\xA": "X"
+ $endif
+ "\xB": "X"
+ $endif
+ "\xC": "O"
+ LINES
+ keys = [0x1, 0x3, 0x4, 0x6, 0x7, 0xC]
+ key_bindings = keys.to_h { |k| [[k], ['O'.ord]] }
+ assert_equal(key_bindings, additional_key_bindings(:emacs))
+ end
+
def test_unclosed_if
e = assert_raise(Reline::Config::InvalidInputrc) do
@config.read_lines(<<~LINES.lines, "INPUTRC")
@@ -208,6 +291,78 @@ class Reline::Config::Test < Reline::TestCase
assert_equal "INPUTRC:1: unmatched endif", e.message
end
+ def test_if_with_mode
+ @config.read_lines(<<~LINES.lines)
+ $if mode=emacs
+ "\C-e": history-search-backward # comment
+ $else
+ "\C-f": history-search-forward
+ $endif
+ LINES
+
+ assert_equal({[5] => :history_search_backward}, additional_key_bindings(:emacs))
+ assert_equal({}, additional_key_bindings(:vi_insert))
+ assert_equal({}, additional_key_bindings(:vi_command))
+ end
+
+ def test_else
+ @config.read_lines(<<~LINES.lines)
+ $if mode=vi
+ "\C-e": history-search-backward # comment
+ $else
+ "\C-f": history-search-forward
+ $endif
+ LINES
+
+ assert_equal({[6] => :history_search_forward}, additional_key_bindings(:emacs))
+ assert_equal({}, additional_key_bindings(:vi_insert))
+ assert_equal({}, additional_key_bindings(:vi_command))
+ end
+
+ def test_if_with_invalid_mode
+ @config.read_lines(<<~LINES.lines)
+ $if mode=vim
+ "\C-e": history-search-backward
+ $else
+ "\C-f": history-search-forward # comment
+ $endif
+ LINES
+
+ assert_equal({[6] => :history_search_forward}, additional_key_bindings(:emacs))
+ assert_equal({}, additional_key_bindings(:vi_insert))
+ assert_equal({}, additional_key_bindings(:vi_command))
+ end
+
+ def test_mode_label_differs_from_keymap_label
+ @config.read_lines(<<~LINES.lines)
+ # Sets mode_label and keymap_label to vi
+ set editing-mode vi
+ # Change keymap_label to emacs. mode_label is still vi.
+ set keymap emacs
+ # condition=true because current mode_label is vi
+ $if mode=vi
+ # sets keybinding to current keymap_label=emacs
+ "\C-e": history-search-backward
+ $endif
+ LINES
+ assert_equal({[5] => :history_search_backward}, additional_key_bindings(:emacs))
+ assert_equal({}, additional_key_bindings(:vi_insert))
+ assert_equal({}, additional_key_bindings(:vi_command))
+ end
+
+ def test_if_without_else_condition
+ @config.read_lines(<<~LINES.lines)
+ set editing-mode vi
+ $if mode=vi
+ "\C-e": history-search-backward
+ $endif
+ LINES
+
+ assert_equal({}, additional_key_bindings(:emacs))
+ assert_equal({[5] => :history_search_backward}, additional_key_bindings(:vi_insert))
+ assert_equal({}, additional_key_bindings(:vi_command))
+ end
+
def test_default_key_bindings
@config.add_default_key_binding('abcd'.bytes, 'EFGH'.bytes)
@config.read_lines(<<~'LINES'.lines)
@@ -216,7 +371,7 @@ class Reline::Config::Test < Reline::TestCase
LINES
expected = { 'abcd'.bytes => 'ABCD'.bytes, 'ijkl'.bytes => 'IJKL'.bytes }
- assert_equal expected, @config.key_bindings
+ assert_equal expected, registered_key_bindings(expected.keys)
end
def test_additional_key_bindings
@@ -226,7 +381,7 @@ class Reline::Config::Test < Reline::TestCase
LINES
expected = { 'ef'.bytes => 'EF'.bytes, 'gh'.bytes => 'GH'.bytes }
- assert_equal expected, @config.key_bindings
+ assert_equal expected, registered_key_bindings(expected.keys)
end
def test_additional_key_bindings_with_nesting_and_comment_out
@@ -238,7 +393,7 @@ class Reline::Config::Test < Reline::TestCase
LINES
expected = { 'ef'.bytes => 'EF'.bytes, 'gh'.bytes => 'GH'.bytes }
- assert_equal expected, @config.key_bindings
+ assert_equal expected, registered_key_bindings(expected.keys)
end
def test_additional_key_bindings_for_other_keymap
@@ -253,7 +408,41 @@ class Reline::Config::Test < Reline::TestCase
LINES
expected = { 'cd'.bytes => 'CD'.bytes }
- assert_equal expected, @config.key_bindings
+ assert_equal expected, registered_key_bindings(expected.keys)
+ end
+
+ def test_additional_key_bindings_for_auxiliary_emacs_keymaps
+ @config.read_lines(<<~'LINES'.lines)
+ set keymap emacs
+ "ab": "AB"
+ set keymap emacs-standard
+ "cd": "CD"
+ set keymap emacs-ctlx
+ "ef": "EF"
+ set keymap emacs-meta
+ "gh": "GH"
+ set editing-mode emacs # keymap changes to be emacs
+ LINES
+
+ expected = {
+ 'ab'.bytes => 'AB'.bytes,
+ 'cd'.bytes => 'CD'.bytes,
+ "\C-xef".bytes => 'EF'.bytes,
+ "\egh".bytes => 'GH'.bytes,
+ }
+ assert_equal expected, registered_key_bindings(expected.keys)
+ end
+
+ def test_key_bindings_with_reset
+ # @config.reset is called after each readline.
+ # inputrc file is read once, so key binding shouldn't be cleared by @config.reset
+ @config.add_default_key_binding('default'.bytes, 'DEFAULT'.bytes)
+ @config.read_lines(<<~'LINES'.lines)
+ "additional": "ADDITIONAL"
+ LINES
+ @config.reset
+ expected = { 'default'.bytes => 'DEFAULT'.bytes, 'additional'.bytes => 'ADDITIONAL'.bytes }
+ assert_equal expected, registered_key_bindings(expected.keys)
end
def test_history_size
@@ -261,7 +450,7 @@ class Reline::Config::Test < Reline::TestCase
set history-size 5000
LINES
- assert_equal 5000, @config.instance_variable_get(:@history_size)
+ assert_equal 5000, get_config_variable(:@history_size)
history = Reline::History.new(@config)
history << "a\n"
assert_equal 1, history.size
@@ -286,6 +475,17 @@ class Reline::Config::Test < Reline::TestCase
ENV['INPUTRC'] = inputrc_backup
end
+ def test_inputrc_raw_value
+ @config.read_lines(<<~'LINES'.lines)
+ set editing-mode vi ignored-string
+ set vi-ins-mode-string aaa aaa
+ set vi-cmd-mode-string bbb ccc # comment
+ LINES
+ assert_equal :vi_insert, get_config_variable(:@editing_mode_label)
+ assert_equal 'aaa aaa', @config.vi_ins_mode_string
+ assert_equal 'bbb ccc # comment', @config.vi_cmd_mode_string
+ end
+
def test_inputrc_with_utf8
# This file is encoded by UTF-8 so this heredoc string is also UTF-8.
@config.read_lines(<<~'LINES'.lines)
@@ -368,4 +568,21 @@ class Reline::Config::Test < Reline::TestCase
ENV['XDG_CONFIG_HOME'] = xdg_config_home_backup
ENV['HOME'] = home_backup
end
+
+ def test_reload
+ inputrc = "#{@tmpdir}/inputrc"
+ ENV['INPUTRC'] = inputrc
+
+ File.write(inputrc, "set emacs-mode-string !")
+ @config.read
+ assert_equal '!', @config.emacs_mode_string
+
+ File.write(inputrc, "set emacs-mode-string ?")
+ @config.reload
+ assert_equal '?', @config.emacs_mode_string
+
+ File.write(inputrc, "")
+ @config.reload
+ assert_equal '@', @config.emacs_mode_string
+ end
end
diff --git a/test/reline/test_face.rb b/test/reline/test_face.rb
new file mode 100644
index 0000000000..8fa2be8fa4
--- /dev/null
+++ b/test/reline/test_face.rb
@@ -0,0 +1,257 @@
+# frozen_string_literal: true
+
+require_relative 'helper'
+
+class Reline::Face::Test < Reline::TestCase
+ RESET_SGR = "\e[0m"
+
+ def setup
+ @colorterm_backup = ENV['COLORTERM']
+ ENV['COLORTERM'] = 'truecolor'
+ end
+
+ def teardown
+ Reline::Face.reset_to_initial_configs
+ ENV['COLORTERM'] = @colorterm_backup
+ end
+
+ class WithInsufficientSetupTest < self
+ def setup
+ super
+ Reline::Face.config(:my_insufficient_config) do |face|
+ end
+ @face = Reline::Face[:my_insufficient_config]
+ end
+
+ def test_my_insufficient_config_line
+ assert_equal RESET_SGR, @face[:default]
+ assert_equal RESET_SGR, @face[:enhanced]
+ assert_equal RESET_SGR, @face[:scrollbar]
+ end
+
+ def test_my_insufficient_configs
+ my_configs = Reline::Face.configs[:my_insufficient_config]
+ assert_equal(
+ {
+ default: { style: :reset, escape_sequence: RESET_SGR },
+ enhanced: { style: :reset, escape_sequence: RESET_SGR },
+ scrollbar: { style: :reset, escape_sequence: RESET_SGR }
+ },
+ my_configs
+ )
+ end
+ end
+
+ class WithSetupTest < self
+ def setup
+ super
+ Reline::Face.config(:my_config) do |face|
+ face.define :default, foreground: :blue
+ face.define :enhanced, foreground: "#FF1020", background: :black, style: [:bold, :underlined]
+ end
+ Reline::Face.config(:another_config) do |face|
+ face.define :another_label, foreground: :red
+ end
+ @face = Reline::Face[:my_config]
+ end
+
+ def test_now_there_are_four_configs
+ assert_equal %i(default completion_dialog my_config another_config), Reline::Face.configs.keys
+ end
+
+ def test_resetting_config_discards_user_defined_configs
+ Reline::Face.reset_to_initial_configs
+ assert_equal %i(default completion_dialog), Reline::Face.configs.keys
+ end
+
+ def test_my_configs
+ my_configs = Reline::Face.configs[:my_config]
+ assert_equal(
+ {
+ default: {
+ escape_sequence: "#{RESET_SGR}\e[34m", foreground: :blue
+ },
+ enhanced: {
+ background: :black,
+ foreground: "#FF1020",
+ style: [:bold, :underlined],
+ escape_sequence: "\e[0m\e[38;2;255;16;32;40;1;4m"
+ },
+ scrollbar: {
+ style: :reset,
+ escape_sequence: "\e[0m"
+ }
+ },
+ my_configs
+ )
+ end
+
+ def test_my_config_line
+ assert_equal "#{RESET_SGR}\e[34m", @face[:default]
+ end
+
+ def test_my_config_enhanced
+ assert_equal "#{RESET_SGR}\e[38;2;255;16;32;40;1;4m", @face[:enhanced]
+ end
+
+ def test_not_respond_to_another_label
+ assert_equal false, @face.respond_to?(:another_label)
+ end
+ end
+
+ class WithoutSetupTest < self
+ def test_my_config_default
+ Reline::Face.config(:my_config) do |face|
+ # do nothing
+ end
+ face = Reline::Face[:my_config]
+ assert_equal RESET_SGR, face[:default]
+ end
+
+ def test_style_does_not_exist
+ face = Reline::Face[:default]
+ assert_raise ArgumentError do
+ face[:style_does_not_exist]
+ end
+ end
+
+ def test_invalid_keyword
+ assert_raise ArgumentError do
+ Reline::Face.config(:invalid_config) do |face|
+ face.define :default, invalid_keyword: :red
+ end
+ end
+ end
+
+ def test_invalid_foreground_name
+ assert_raise ArgumentError do
+ Reline::Face.config(:invalid_config) do |face|
+ face.define :default, foreground: :invalid_name
+ end
+ end
+ end
+
+ def test_invalid_background_name
+ assert_raise ArgumentError do
+ Reline::Face.config(:invalid_config) do |face|
+ face.define :default, background: :invalid_name
+ end
+ end
+ end
+
+ def test_invalid_style_name
+ assert_raise ArgumentError do
+ Reline::Face.config(:invalid_config) do |face|
+ face.define :default, style: :invalid_name
+ end
+ end
+ end
+
+ def test_private_constants
+ [:SGR_PARAMETER, :Config, :CONFIGS].each do |name|
+ assert_equal false, Reline::Face.constants.include?(name)
+ end
+ end
+ end
+
+ class ConfigTest < self
+ def setup
+ super
+ @config = Reline::Face.const_get(:Config).new(:my_config) { }
+ end
+
+ def teardown
+ super
+ Reline::Face.instance_variable_set(:@force_truecolor, nil)
+ end
+
+ def test_rgb?
+ assert_equal true, @config.send(:rgb_expression?, "#FFFFFF")
+ end
+
+ def test_invalid_rgb?
+ assert_equal false, @config.send(:rgb_expression?, "FFFFFF")
+ assert_equal false, @config.send(:rgb_expression?, "#FFFFF")
+ end
+
+ def test_format_to_sgr_preserves_order
+ assert_equal(
+ "#{RESET_SGR}\e[37;41;1;3m",
+ @config.send(:format_to_sgr, foreground: :white, background: :red, style: [:bold, :italicized])
+ )
+
+ assert_equal(
+ "#{RESET_SGR}\e[37;1;3;41m",
+ @config.send(:format_to_sgr, foreground: :white, style: [:bold, :italicized], background: :red)
+ )
+ end
+
+ def test_format_to_sgr_with_reset
+ assert_equal(
+ RESET_SGR,
+ @config.send(:format_to_sgr, style: :reset)
+ )
+ assert_equal(
+ "#{RESET_SGR}\e[37;0;41m",
+ @config.send(:format_to_sgr, foreground: :white, style: :reset, background: :red)
+ )
+ end
+
+ def test_format_to_sgr_with_single_style
+ assert_equal(
+ "#{RESET_SGR}\e[37;41;1m",
+ @config.send(:format_to_sgr, foreground: :white, background: :red, style: :bold)
+ )
+ end
+
+ def test_truecolor
+ ENV['COLORTERM'] = 'truecolor'
+ assert_equal true, Reline::Face.truecolor?
+ ENV['COLORTERM'] = '24bit'
+ assert_equal true, Reline::Face.truecolor?
+ ENV['COLORTERM'] = nil
+ assert_equal false, Reline::Face.truecolor?
+ Reline::Face.force_truecolor
+ assert_equal true, Reline::Face.truecolor?
+ end
+
+ def test_sgr_rgb_truecolor
+ ENV['COLORTERM'] = 'truecolor'
+ assert_equal "38;2;255;255;255", @config.send(:sgr_rgb, :foreground, "#ffffff")
+ assert_equal "48;2;18;52;86", @config.send(:sgr_rgb, :background, "#123456")
+ end
+
+ def test_sgr_rgb_256color
+ ENV['COLORTERM'] = nil
+ assert_equal '38;5;231', @config.send(:sgr_rgb, :foreground, '#ffffff')
+ assert_equal '48;5;16', @config.send(:sgr_rgb, :background, '#000000')
+ # Color steps are [0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff]
+ assert_equal '38;5;24', @config.send(:sgr_rgb, :foreground, '#005f87')
+ assert_equal '38;5;67', @config.send(:sgr_rgb, :foreground, '#5f87af')
+ assert_equal '48;5;110', @config.send(:sgr_rgb, :background, '#87afd7')
+ assert_equal '48;5;153', @config.send(:sgr_rgb, :background, '#afd7ff')
+ # Boundary values are [0x30, 0x73, 0x9b, 0xc3, 0xeb]
+ assert_equal '38;5;24', @config.send(:sgr_rgb, :foreground, '#2f729a')
+ assert_equal '38;5;67', @config.send(:sgr_rgb, :foreground, '#30739b')
+ assert_equal '48;5;110', @config.send(:sgr_rgb, :background, '#9ac2ea')
+ assert_equal '48;5;153', @config.send(:sgr_rgb, :background, '#9bc3eb')
+ end
+
+ def test_force_truecolor_reconfigure
+ ENV['COLORTERM'] = nil
+
+ Reline::Face.config(:my_config) do |face|
+ face.define :default, foreground: '#005f87'
+ face.define :enhanced, background: '#afd7ff'
+ end
+
+ assert_equal "\e[0m\e[38;5;24m", Reline::Face[:my_config][:default]
+ assert_equal "\e[0m\e[48;5;153m", Reline::Face[:my_config][:enhanced]
+
+ Reline::Face.force_truecolor
+
+ assert_equal "\e[0m\e[38;2;0;95;135m", Reline::Face[:my_config][:default]
+ assert_equal "\e[0m\e[48;2;175;215;255m", Reline::Face[:my_config][:enhanced]
+ end
+ end
+end
diff --git a/test/reline/test_history.rb b/test/reline/test_history.rb
index 53360409bc..ddf8fb1472 100644
--- a/test/reline/test_history.rb
+++ b/test/reline/test_history.rb
@@ -297,7 +297,7 @@ class Reline::History::Test < Reline::TestCase
end
def get_default_internal_encoding
- if encoding = Reline::IOGate.encoding
+ if encoding = Reline.core.encoding
encoding
elsif RUBY_PLATFORM =~ /mswin|mingw/
Encoding.default_internal || Encoding::UTF_8
diff --git a/test/reline/test_key_actor_emacs.rb b/test/reline/test_key_actor_emacs.rb
index 6a6cbdc59f..4dddf9c890 100644
--- a/test/reline/test_key_actor_emacs.rb
+++ b/test/reline/test_key_actor_emacs.rb
@@ -1,6 +1,6 @@
require_relative 'helper'
-class Reline::KeyActor::Emacs::Test < Reline::TestCase
+class Reline::KeyActor::EmacsTest < Reline::TestCase
def setup
Reline.send(:test_mode)
@prompt = '> '
@@ -8,7 +8,7 @@ class Reline::KeyActor::Emacs::Test < Reline::TestCase
@config.autocompletion = false
Reline::HISTORY.instance_variable_set(:@config, @config)
Reline::HISTORY.clear
- @encoding = Reline::IOGate.encoding
+ @encoding = Reline.core.encoding
@line_editor = Reline::LineEditor.new(@config, @encoding)
@line_editor.reset(@prompt, encoding: @encoding)
end
@@ -19,1234 +19,699 @@ class Reline::KeyActor::Emacs::Test < Reline::TestCase
def test_ed_insert_one
input_keys('a')
- assert_line('a')
- assert_byte_pointer_size('a')
- assert_cursor(1)
- assert_cursor_max(1)
+ assert_line_around_cursor('a', '')
end
def test_ed_insert_two
input_keys('ab')
- assert_line('ab')
- assert_byte_pointer_size('ab')
- assert_cursor(2)
- assert_cursor_max(2)
+ assert_line_around_cursor('ab', '')
end
def test_ed_insert_mbchar_one
input_keys('ã‹')
- assert_line('ã‹')
- assert_byte_pointer_size('ã‹')
- assert_cursor(2)
- assert_cursor_max(2)
+ assert_line_around_cursor('ã‹', '')
end
def test_ed_insert_mbchar_two
input_keys('ã‹ã')
- assert_line('ã‹ã')
- assert_byte_pointer_size('ã‹ã')
- assert_cursor(4)
- assert_cursor_max(4)
+ assert_line_around_cursor('ã‹ã', '')
end
def test_ed_insert_for_mbchar_by_plural_code_points
input_keys("ã‹\u3099")
- assert_line("ã‹\u3099")
- assert_byte_pointer_size("ã‹\u3099")
- assert_cursor(2)
- assert_cursor_max(2)
+ assert_line_around_cursor("ã‹\u3099", '')
end
def test_ed_insert_for_plural_mbchar_by_plural_code_points
input_keys("ã‹\u3099ã\u3099")
- assert_line("ã‹\u3099ã\u3099")
- assert_byte_pointer_size("ã‹\u3099ã\u3099")
- assert_cursor(4)
- assert_cursor_max(4)
+ assert_line_around_cursor("ã‹\u3099ã\u3099", '')
end
def test_move_next_and_prev
input_keys('abd')
- assert_byte_pointer_size('abd')
- assert_cursor(3)
- assert_cursor_max(3)
+ assert_line_around_cursor('abd', '')
input_keys("\C-b", false)
- assert_byte_pointer_size('ab')
- assert_cursor(2)
- assert_cursor_max(3)
+ assert_line_around_cursor('ab', 'd')
input_keys("\C-b", false)
- assert_byte_pointer_size('a')
- assert_cursor(1)
- assert_cursor_max(3)
+ assert_line_around_cursor('a', 'bd')
input_keys("\C-f", false)
- assert_byte_pointer_size('ab')
- assert_cursor(2)
- assert_cursor_max(3)
+ assert_line_around_cursor('ab', 'd')
input_keys('c')
- assert_byte_pointer_size('abc')
- assert_cursor(3)
- assert_cursor_max(4)
- assert_line('abcd')
+ assert_line_around_cursor('abc', 'd')
end
def test_move_next_and_prev_for_mbchar
input_keys('ã‹ãã‘')
- assert_byte_pointer_size('ã‹ãã‘')
- assert_cursor(6)
- assert_cursor_max(6)
+ assert_line_around_cursor('ã‹ãã‘', '')
input_keys("\C-b", false)
- assert_byte_pointer_size('ã‹ã')
- assert_cursor(4)
- assert_cursor_max(6)
+ assert_line_around_cursor('ã‹ã', 'ã‘')
input_keys("\C-b", false)
- assert_byte_pointer_size('ã‹')
- assert_cursor(2)
- assert_cursor_max(6)
+ assert_line_around_cursor('ã‹', 'ãã‘')
input_keys("\C-f", false)
- assert_byte_pointer_size('ã‹ã')
- assert_cursor(4)
- assert_cursor_max(6)
+ assert_line_around_cursor('ã‹ã', 'ã‘')
input_keys('ã')
- assert_byte_pointer_size('ã‹ãã')
- assert_cursor(6)
- assert_cursor_max(8)
- assert_line('ã‹ããã‘')
+ assert_line_around_cursor('ã‹ãã', 'ã‘')
end
def test_move_next_and_prev_for_mbchar_by_plural_code_points
input_keys("ã‹\u3099ã\u3099ã‘\u3099")
- assert_byte_pointer_size("ã‹\u3099ã\u3099ã‘\u3099")
- assert_cursor(6)
- assert_cursor_max(6)
+ assert_line_around_cursor("ã‹\u3099ã\u3099ã‘\u3099", '')
input_keys("\C-b", false)
- assert_byte_pointer_size("ã‹\u3099ã\u3099")
- assert_cursor(4)
- assert_cursor_max(6)
+ assert_line_around_cursor("ã‹\u3099ã\u3099", "ã‘\u3099")
input_keys("\C-b", false)
- assert_byte_pointer_size("ã‹\u3099")
- assert_cursor(2)
- assert_cursor_max(6)
+ assert_line_around_cursor("ã‹\u3099", "ã\u3099ã‘\u3099")
input_keys("\C-f", false)
- assert_byte_pointer_size("ã‹\u3099ã\u3099")
- assert_cursor(4)
- assert_cursor_max(6)
+ assert_line_around_cursor("ã‹\u3099ã\u3099", "ã‘\u3099")
input_keys("ã\u3099")
- assert_byte_pointer_size("ã‹\u3099ã\u3099ã\u3099")
- assert_cursor(6)
- assert_cursor_max(8)
- assert_line("ã‹\u3099ã\u3099ã\u3099ã‘\u3099")
+ assert_line_around_cursor("ã‹\u3099ã\u3099ã\u3099", "ã‘\u3099")
end
def test_move_to_beg_end
input_keys('bcd')
- assert_byte_pointer_size('bcd')
- assert_cursor(3)
- assert_cursor_max(3)
+ assert_line_around_cursor('bcd', '')
input_keys("\C-a", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(3)
+ assert_line_around_cursor('', 'bcd')
input_keys('a')
- assert_byte_pointer_size('a')
- assert_cursor(1)
- assert_cursor_max(4)
+ assert_line_around_cursor('a', 'bcd')
input_keys("\C-e", false)
- assert_byte_pointer_size('abcd')
- assert_cursor(4)
- assert_cursor_max(4)
+ assert_line_around_cursor('abcd', '')
input_keys('e')
- assert_byte_pointer_size('abcde')
- assert_cursor(5)
- assert_cursor_max(5)
- assert_line('abcde')
+ assert_line_around_cursor('abcde', '')
end
def test_ed_newline_with_cr
input_keys('ab')
- assert_byte_pointer_size('ab')
- assert_cursor(2)
- assert_cursor_max(2)
+ assert_line_around_cursor('ab', '')
refute(@line_editor.finished?)
input_keys("\C-m", false)
- assert_line('ab')
+ assert_line_around_cursor('ab', '')
assert(@line_editor.finished?)
end
def test_ed_newline_with_lf
input_keys('ab')
- assert_byte_pointer_size('ab')
- assert_cursor(2)
- assert_cursor_max(2)
+ assert_line_around_cursor('ab', '')
refute(@line_editor.finished?)
input_keys("\C-j", false)
- assert_line('ab')
+ assert_line_around_cursor('ab', '')
assert(@line_editor.finished?)
end
def test_em_delete_prev_char
input_keys('ab')
- assert_byte_pointer_size('ab')
- assert_cursor(2)
- assert_cursor_max(2)
+ assert_line_around_cursor('ab', '')
input_keys("\C-h", false)
- assert_byte_pointer_size('a')
- assert_cursor(1)
- assert_cursor_max(1)
- assert_line('a')
+ assert_line_around_cursor('a', '')
end
def test_em_delete_prev_char_for_mbchar
input_keys('ã‹ã')
- assert_byte_pointer_size('ã‹ã')
- assert_cursor(4)
- assert_cursor_max(4)
+ assert_line_around_cursor('ã‹ã', '')
input_keys("\C-h", false)
- assert_byte_pointer_size('ã‹')
- assert_cursor(2)
- assert_cursor_max(2)
- assert_line('ã‹')
+ assert_line_around_cursor('ã‹', '')
end
def test_em_delete_prev_char_for_mbchar_by_plural_code_points
input_keys("ã‹\u3099ã\u3099")
- assert_byte_pointer_size("ã‹\u3099ã\u3099")
- assert_cursor(4)
- assert_cursor_max(4)
+ assert_line_around_cursor("ã‹\u3099ã\u3099", '')
input_keys("\C-h", false)
- assert_byte_pointer_size("ã‹\u3099")
- assert_cursor(2)
- assert_cursor_max(2)
- assert_line("ã‹\u3099")
+ assert_line_around_cursor("ã‹\u3099", '')
end
def test_ed_quoted_insert
input_keys("ab\C-v\C-acd")
- assert_line("ab\C-acd")
- assert_byte_pointer_size("ab\C-acd")
- assert_cursor(6)
- assert_cursor_max(6)
+ assert_line_around_cursor("ab\C-acd", '')
input_keys("\C-q\C-b")
- assert_line("ab\C-acd\C-b")
- assert_byte_pointer_size("ab\C-acd\C-b")
- assert_cursor(8)
- assert_cursor_max(8)
+ assert_line_around_cursor("ab\C-acd\C-b", '')
end
def test_ed_kill_line
input_keys("\C-k", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
- assert_line('')
+ assert_line_around_cursor('', '')
input_keys('abc')
- assert_byte_pointer_size('abc')
- assert_cursor(3)
- assert_cursor_max(3)
+ assert_line_around_cursor('abc', '')
input_keys("\C-k", false)
- assert_byte_pointer_size('abc')
- assert_cursor(3)
- assert_cursor_max(3)
- assert_line('abc')
+ assert_line_around_cursor('abc', '')
input_keys("\C-b\C-k", false)
- assert_byte_pointer_size('ab')
- assert_cursor(2)
- assert_cursor_max(2)
- assert_line('ab')
+ assert_line_around_cursor('ab', '')
end
def test_em_kill_line
- input_keys("\C-u", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
- assert_line('')
+ @line_editor.input_key(Reline::Key.new(:em_kill_line, :em_kill_line, false))
+ assert_line_around_cursor('', '')
input_keys('abc')
- assert_byte_pointer_size('abc')
- assert_cursor(3)
- assert_cursor_max(3)
- input_keys("\C-u", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
- assert_line('')
+ @line_editor.input_key(Reline::Key.new(:em_kill_line, :em_kill_line, false))
+ assert_line_around_cursor('', '')
input_keys('abc')
- input_keys("\C-b\C-u", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(1)
- assert_line('c')
- input_keys("\C-u", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(1)
- assert_line('c')
+ input_keys("\C-b", false)
+ @line_editor.input_key(Reline::Key.new(:em_kill_line, :em_kill_line, false))
+ assert_line_around_cursor('', '')
+ input_keys('abc')
+ input_keys("\C-a", false)
+ @line_editor.input_key(Reline::Key.new(:em_kill_line, :em_kill_line, false))
+ assert_line_around_cursor('', '')
end
def test_ed_move_to_beg
input_keys('abd')
- assert_byte_pointer_size('abd')
- assert_cursor(3)
- assert_cursor_max(3)
+ assert_line_around_cursor('abd', '')
input_keys("\C-b", false)
- assert_byte_pointer_size('ab')
- assert_cursor(2)
- assert_cursor_max(3)
+ assert_line_around_cursor('ab', 'd')
input_keys('c')
- assert_byte_pointer_size('abc')
- assert_cursor(3)
- assert_cursor_max(4)
+ assert_line_around_cursor('abc', 'd')
input_keys("\C-a", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(4)
+ assert_line_around_cursor('', 'abcd')
input_keys('012')
- assert_byte_pointer_size('012')
- assert_cursor(3)
- assert_cursor_max(7)
- assert_line('012abcd')
+ assert_line_around_cursor('012', 'abcd')
input_keys("\C-a", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(7)
+ assert_line_around_cursor('', '012abcd')
input_keys('ABC')
- assert_byte_pointer_size('ABC')
- assert_cursor(3)
- assert_cursor_max(10)
- assert_line('ABC012abcd')
+ assert_line_around_cursor('ABC', '012abcd')
input_keys("\C-f" * 10 + "\C-a", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(10)
+ assert_line_around_cursor('', 'ABC012abcd')
input_keys('a')
- assert_byte_pointer_size('a')
- assert_cursor(1)
- assert_cursor_max(11)
- assert_line('aABC012abcd')
+ assert_line_around_cursor('a', 'ABC012abcd')
end
def test_ed_move_to_beg_with_blank
input_keys(' abc')
- assert_byte_pointer_size(' abc')
- assert_cursor(5)
- assert_cursor_max(5)
+ assert_line_around_cursor(' abc', '')
input_keys("\C-a", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(5)
+ assert_line_around_cursor('', ' abc')
end
def test_ed_move_to_end
input_keys('abd')
- assert_byte_pointer_size('abd')
- assert_cursor(3)
- assert_cursor_max(3)
+ assert_line_around_cursor('abd', '')
input_keys("\C-b", false)
- assert_byte_pointer_size('ab')
- assert_cursor(2)
- assert_cursor_max(3)
+ assert_line_around_cursor('ab', 'd')
input_keys('c')
- assert_byte_pointer_size('abc')
- assert_cursor(3)
- assert_cursor_max(4)
+ assert_line_around_cursor('abc', 'd')
input_keys("\C-e", false)
- assert_byte_pointer_size('abcd')
- assert_cursor(4)
- assert_cursor_max(4)
+ assert_line_around_cursor('abcd', '')
input_keys('012')
- assert_byte_pointer_size('abcd012')
- assert_cursor(7)
- assert_cursor_max(7)
- assert_line('abcd012')
+ assert_line_around_cursor('abcd012', '')
input_keys("\C-e", false)
- assert_byte_pointer_size('abcd012')
- assert_cursor(7)
- assert_cursor_max(7)
+ assert_line_around_cursor('abcd012', '')
input_keys('ABC')
- assert_byte_pointer_size('abcd012ABC')
- assert_cursor(10)
- assert_cursor_max(10)
- assert_line('abcd012ABC')
+ assert_line_around_cursor('abcd012ABC', '')
input_keys("\C-b" * 10 + "\C-e", false)
- assert_byte_pointer_size('abcd012ABC')
- assert_cursor(10)
- assert_cursor_max(10)
+ assert_line_around_cursor('abcd012ABC', '')
input_keys('a')
- assert_byte_pointer_size('abcd012ABCa')
- assert_cursor(11)
- assert_cursor_max(11)
- assert_line('abcd012ABCa')
+ assert_line_around_cursor('abcd012ABCa', '')
end
def test_em_delete
input_keys('ab')
- assert_byte_pointer_size('ab')
- assert_cursor(2)
- assert_cursor_max(2)
+ assert_line_around_cursor('ab', '')
input_keys("\C-a", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(2)
+ assert_line_around_cursor('', 'ab')
input_keys("\C-d", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(1)
- assert_line('b')
+ assert_line_around_cursor('', 'b')
end
def test_em_delete_for_mbchar
input_keys('ã‹ã')
- assert_byte_pointer_size('ã‹ã')
- assert_cursor(4)
- assert_cursor_max(4)
+ assert_line_around_cursor('ã‹ã', '')
input_keys("\C-a", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(4)
+ assert_line_around_cursor('', 'ã‹ã')
input_keys("\C-d", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(2)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(2)
- assert_line('ã')
+ assert_line_around_cursor('', 'ã')
end
def test_em_delete_for_mbchar_by_plural_code_points
input_keys("ã‹\u3099ã\u3099")
- assert_byte_pointer_size("ã‹\u3099ã\u3099")
- assert_cursor(4)
- assert_cursor_max(4)
+ assert_line_around_cursor("ã‹\u3099ã\u3099", '')
input_keys("\C-a", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(4)
+ assert_line_around_cursor('', "ã‹\u3099ã\u3099")
input_keys("\C-d", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(2)
- assert_line("ã\u3099")
+ assert_line_around_cursor('', "ã\u3099")
+ end
+
+ def test_em_delete_ends_editing
+ input_keys("\C-d") # quit from inputing
+ assert_nil(@line_editor.line)
+ assert(@line_editor.finished?)
end
def test_ed_clear_screen
- refute(@line_editor.instance_variable_get(:@cleared))
+ @line_editor.instance_variable_get(:@rendered_screen).lines = [[]]
input_keys("\C-l", false)
- assert(@line_editor.instance_variable_get(:@cleared))
+ assert_empty(@line_editor.instance_variable_get(:@rendered_screen).lines)
end
def test_ed_clear_screen_with_inputed
input_keys('abc')
input_keys("\C-b", false)
- refute(@line_editor.instance_variable_get(:@cleared))
- assert_byte_pointer_size('ab')
- assert_cursor(2)
- assert_cursor_max(3)
+ @line_editor.instance_variable_get(:@rendered_screen).lines = [[]]
+ assert_line_around_cursor('ab', 'c')
input_keys("\C-l", false)
- assert(@line_editor.instance_variable_get(:@cleared))
- assert_byte_pointer_size('ab')
- assert_cursor(2)
- assert_cursor_max(3)
- assert_line('abc')
+ assert_empty(@line_editor.instance_variable_get(:@rendered_screen).lines)
+ assert_line_around_cursor('ab', 'c')
end
- def test_ed_delete_next_char
+ def test_key_delete
input_keys('abc')
- assert_cursor(3)
- assert_cursor_max(3)
+ assert_line_around_cursor('abc', '')
@line_editor.input_key(Reline::Key.new(:key_delete, :key_delete, false))
- assert_cursor(3)
- assert_cursor_max(3)
- assert_line('abc')
+ assert_line_around_cursor('abc', '')
+ end
+
+ def test_key_delete_does_not_end_editing
+ @line_editor.input_key(Reline::Key.new(:key_delete, :key_delete, false))
+ assert_line_around_cursor('', '')
+ refute(@line_editor.finished?)
+ end
+
+ def test_key_delete_preserves_cursor
+ input_keys('abc')
+ input_keys("\C-b", false)
+ assert_line_around_cursor('ab', 'c')
+ @line_editor.input_key(Reline::Key.new(:key_delete, :key_delete, false))
+ assert_line_around_cursor('ab', '')
end
def test_em_next_word
- assert_byte_pointer_size('')
- assert_cursor(0)
+ assert_line_around_cursor('', '')
input_keys('abc def{bbb}ccc')
input_keys("\C-a\M-F", false)
- assert_byte_pointer_size('abc')
- assert_cursor(3)
+ assert_line_around_cursor('abc', ' def{bbb}ccc')
input_keys("\M-F", false)
- assert_byte_pointer_size('abc def')
- assert_cursor(7)
+ assert_line_around_cursor('abc def', '{bbb}ccc')
input_keys("\M-F", false)
- assert_byte_pointer_size('abc def{bbb')
- assert_cursor(11)
+ assert_line_around_cursor('abc def{bbb', '}ccc')
input_keys("\M-F", false)
- assert_byte_pointer_size('abc def{bbb}ccc')
- assert_cursor(15)
+ assert_line_around_cursor('abc def{bbb}ccc', '')
input_keys("\M-F", false)
- assert_byte_pointer_size('abc def{bbb}ccc')
- assert_cursor(15)
+ assert_line_around_cursor('abc def{bbb}ccc', '')
end
def test_em_next_word_for_mbchar
- assert_cursor(0)
+ assert_line_around_cursor('', '')
input_keys('ã‚ã„ㆠã‹ãã{ã•ã—ã™}ãŸã¡ã¤')
input_keys("\C-a\M-F", false)
- assert_byte_pointer_size('ã‚ã„ã†')
- assert_cursor(6)
+ assert_line_around_cursor('ã‚ã„ã†', ' ã‹ãã{ã•ã—ã™}ãŸã¡ã¤')
input_keys("\M-F", false)
- assert_byte_pointer_size('ã‚ã„ㆠã‹ãã')
- assert_cursor(13)
+ assert_line_around_cursor('ã‚ã„ㆠã‹ãã', '{ã•ã—ã™}ãŸã¡ã¤')
input_keys("\M-F", false)
- assert_byte_pointer_size('ã‚ã„ㆠã‹ãã{ã•ã—ã™')
- assert_cursor(20)
+ assert_line_around_cursor('ã‚ã„ㆠã‹ãã{ã•ã—ã™', '}ãŸã¡ã¤')
input_keys("\M-F", false)
- assert_byte_pointer_size('ã‚ã„ㆠã‹ãã{ã•ã—ã™}ãŸã¡ã¤')
- assert_cursor(27)
+ assert_line_around_cursor('ã‚ã„ㆠã‹ãã{ã•ã—ã™}ãŸã¡ã¤', '')
input_keys("\M-F", false)
- assert_byte_pointer_size('ã‚ã„ㆠã‹ãã{ã•ã—ã™}ãŸã¡ã¤')
- assert_cursor(27)
+ assert_line_around_cursor('ã‚ã„ㆠã‹ãã{ã•ã—ã™}ãŸã¡ã¤', '')
end
def test_em_next_word_for_mbchar_by_plural_code_points
- assert_cursor(0)
+ assert_line_around_cursor("", "")
input_keys("ã‚ã„ㆠã‹\u3099ã\u3099ã\u3099{ã•ã—ã™}ãŸã¡ã¤")
input_keys("\C-a\M-F", false)
- assert_byte_pointer_size("ã‚ã„ã†")
- assert_cursor(6)
+ assert_line_around_cursor("ã‚ã„ã†", " ã‹\u3099ã\u3099ã\u3099{ã•ã—ã™}ãŸã¡ã¤")
input_keys("\M-F", false)
- assert_byte_pointer_size("ã‚ã„ㆠã‹\u3099ã\u3099ã\u3099")
- assert_cursor(13)
+ assert_line_around_cursor("ã‚ã„ㆠã‹\u3099ã\u3099ã\u3099", "{ã•ã—ã™}ãŸã¡ã¤")
input_keys("\M-F", false)
- assert_byte_pointer_size("ã‚ã„ㆠã‹\u3099ã\u3099ã\u3099{ã•ã—ã™")
- assert_cursor(20)
+ assert_line_around_cursor("ã‚ã„ㆠã‹\u3099ã\u3099ã\u3099{ã•ã—ã™", "}ãŸã¡ã¤")
input_keys("\M-F", false)
- assert_byte_pointer_size("ã‚ã„ㆠã‹\u3099ã\u3099ã\u3099{ã•ã—ã™}ãŸã¡ã¤")
- assert_cursor(27)
+ assert_line_around_cursor("ã‚ã„ㆠã‹\u3099ã\u3099ã\u3099{ã•ã—ã™}ãŸã¡ã¤", "")
input_keys("\M-F", false)
- assert_byte_pointer_size("ã‚ã„ㆠã‹\u3099ã\u3099ã\u3099{ã•ã—ã™}ãŸã¡ã¤")
- assert_cursor(27)
+ assert_line_around_cursor("ã‚ã„ㆠã‹\u3099ã\u3099ã\u3099{ã•ã—ã™}ãŸã¡ã¤", "")
end
def test_em_prev_word
input_keys('abc def{bbb}ccc')
- assert_byte_pointer_size('abc def{bbb}ccc')
- assert_cursor(15)
+ assert_line_around_cursor('abc def{bbb}ccc', '')
input_keys("\M-B", false)
- assert_byte_pointer_size('abc def{bbb}')
- assert_cursor(12)
+ assert_line_around_cursor('abc def{bbb}', 'ccc')
input_keys("\M-B", false)
- assert_byte_pointer_size('abc def{')
- assert_cursor(8)
+ assert_line_around_cursor('abc def{', 'bbb}ccc')
input_keys("\M-B", false)
- assert_byte_pointer_size('abc ')
- assert_cursor(4)
+ assert_line_around_cursor('abc ', 'def{bbb}ccc')
input_keys("\M-B", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
+ assert_line_around_cursor('', 'abc def{bbb}ccc')
input_keys("\M-B", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
+ assert_line_around_cursor('', 'abc def{bbb}ccc')
end
def test_em_prev_word_for_mbchar
input_keys('ã‚ã„ㆠã‹ãã{ã•ã—ã™}ãŸã¡ã¤')
- assert_byte_pointer_size('ã‚ã„ㆠã‹ãã{ã•ã—ã™}ãŸã¡ã¤')
- assert_cursor(27)
+ assert_line_around_cursor('ã‚ã„ㆠã‹ãã{ã•ã—ã™}ãŸã¡ã¤', '')
input_keys("\M-B", false)
- assert_byte_pointer_size('ã‚ã„ㆠã‹ãã{ã•ã—ã™}')
- assert_cursor(21)
+ assert_line_around_cursor('ã‚ã„ㆠã‹ãã{ã•ã—ã™}', 'ãŸã¡ã¤')
input_keys("\M-B", false)
- assert_byte_pointer_size('ã‚ã„ㆠã‹ãã{')
- assert_cursor(14)
+ assert_line_around_cursor('ã‚ã„ㆠã‹ãã{', 'ã•ã—ã™}ãŸã¡ã¤')
input_keys("\M-B", false)
- assert_byte_pointer_size('ã‚ã„ㆠ')
- assert_cursor(7)
+ assert_line_around_cursor('ã‚ã„ㆠ', 'ã‹ãã{ã•ã—ã™}ãŸã¡ã¤')
input_keys("\M-B", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
+ assert_line_around_cursor('', 'ã‚ã„ㆠã‹ãã{ã•ã—ã™}ãŸã¡ã¤')
input_keys("\M-B", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
+ assert_line_around_cursor('', 'ã‚ã„ㆠã‹ãã{ã•ã—ã™}ãŸã¡ã¤')
end
def test_em_prev_word_for_mbchar_by_plural_code_points
input_keys("ã‚ã„ㆠã‹\u3099ã\u3099ã\u3099{ã•ã—ã™}ãŸã¡ã¤")
- assert_byte_pointer_size("ã‚ã„ㆠã‹\u3099ã\u3099ã\u3099{ã•ã—ã™}ãŸã¡ã¤")
- assert_cursor(27)
+ assert_line_around_cursor("ã‚ã„ㆠã‹\u3099ã\u3099ã\u3099{ã•ã—ã™}ãŸã¡ã¤", "")
input_keys("\M-B", false)
- assert_byte_pointer_size("ã‚ã„ㆠã‹\u3099ã\u3099ã\u3099{ã•ã—ã™}")
- assert_cursor(21)
+ assert_line_around_cursor("ã‚ã„ㆠã‹\u3099ã\u3099ã\u3099{ã•ã—ã™}", "ãŸã¡ã¤")
input_keys("\M-B", false)
- assert_byte_pointer_size("ã‚ã„ㆠã‹\u3099ã\u3099ã\u3099{")
- assert_cursor(14)
+ assert_line_around_cursor("ã‚ã„ㆠã‹\u3099ã\u3099ã\u3099{", "ã•ã—ã™}ãŸã¡ã¤")
input_keys("\M-B", false)
- assert_byte_pointer_size('ã‚ã„ㆠ')
- assert_cursor(7)
+ assert_line_around_cursor("ã‚ã„ㆠ", "ã‹\u3099ã\u3099ã\u3099{ã•ã—ã™}ãŸã¡ã¤")
input_keys("\M-B", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
+ assert_line_around_cursor("", "ã‚ã„ㆠã‹\u3099ã\u3099ã\u3099{ã•ã—ã™}ãŸã¡ã¤")
input_keys("\M-B", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
+ assert_line_around_cursor("", "ã‚ã„ㆠã‹\u3099ã\u3099ã\u3099{ã•ã—ã™}ãŸã¡ã¤")
end
def test_em_delete_next_word
input_keys('abc def{bbb}ccc')
input_keys("\C-a", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(15)
+ assert_line_around_cursor('', 'abc def{bbb}ccc')
input_keys("\M-d", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(12)
- assert_line(' def{bbb}ccc')
+ assert_line_around_cursor('', ' def{bbb}ccc')
input_keys("\M-d", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(8)
- assert_line('{bbb}ccc')
+ assert_line_around_cursor('', '{bbb}ccc')
input_keys("\M-d", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(4)
- assert_line('}ccc')
+ assert_line_around_cursor('', '}ccc')
input_keys("\M-d", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
- assert_line('')
+ assert_line_around_cursor('', '')
end
def test_em_delete_next_word_for_mbchar
input_keys('ã‚ã„ㆠã‹ãã{ã•ã—ã™}ãŸã¡ã¤')
input_keys("\C-a", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(27)
+ assert_line_around_cursor('', 'ã‚ã„ㆠã‹ãã{ã•ã—ã™}ãŸã¡ã¤')
input_keys("\M-d", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(21)
- assert_line(' ã‹ãã{ã•ã—ã™}ãŸã¡ã¤')
+ assert_line_around_cursor('', ' ã‹ãã{ã•ã—ã™}ãŸã¡ã¤')
input_keys("\M-d", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(14)
- assert_line('{ã•ã—ã™}ãŸã¡ã¤')
+ assert_line_around_cursor('', '{ã•ã—ã™}ãŸã¡ã¤')
input_keys("\M-d", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(7)
- assert_line('}ãŸã¡ã¤')
+ assert_line_around_cursor('', '}ãŸã¡ã¤')
input_keys("\M-d", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
- assert_line('')
+ assert_line_around_cursor('', '')
end
def test_em_delete_next_word_for_mbchar_by_plural_code_points
input_keys("ã‚ã„ㆠã‹\u3099ã\u3099ã\u3099{ã•ã—ã™}ãŸã¡ã¤")
input_keys("\C-a", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(27)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(27)
+ assert_line_around_cursor('', "ã‚ã„ㆠã‹\u3099ã\u3099ã\u3099{ã•ã—ã™}ãŸã¡ã¤")
input_keys("\M-d", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(21)
- assert_line(" ã‹\u3099ã\u3099ã\u3099{ã•ã—ã™}ãŸã¡ã¤")
+ assert_line_around_cursor('', " ã‹\u3099ã\u3099ã\u3099{ã•ã—ã™}ãŸã¡ã¤")
input_keys("\M-d", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(14)
- assert_line('{ã•ã—ã™}ãŸã¡ã¤')
+ assert_line_around_cursor('', '{ã•ã—ã™}ãŸã¡ã¤')
input_keys("\M-d", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(7)
- assert_line('}ãŸã¡ã¤')
+ assert_line_around_cursor('', '}ãŸã¡ã¤')
input_keys("\M-d", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
- assert_line('')
+ assert_line_around_cursor('', '')
end
def test_ed_delete_prev_word
input_keys('abc def{bbb}ccc')
- assert_byte_pointer_size('abc def{bbb}ccc')
- assert_cursor(15)
- assert_cursor_max(15)
+ assert_line_around_cursor('abc def{bbb}ccc', '')
input_keys("\M-\C-H", false)
- assert_byte_pointer_size('abc def{bbb}')
- assert_cursor(12)
- assert_cursor_max(12)
- assert_line('abc def{bbb}')
+ assert_line_around_cursor('abc def{bbb}', '')
input_keys("\M-\C-H", false)
- assert_byte_pointer_size('abc def{')
- assert_cursor(8)
- assert_cursor_max(8)
- assert_line('abc def{')
+ assert_line_around_cursor('abc def{', '')
input_keys("\M-\C-H", false)
- assert_byte_pointer_size('abc ')
- assert_cursor(4)
- assert_cursor_max(4)
- assert_line('abc ')
+ assert_line_around_cursor('abc ', '')
input_keys("\M-\C-H", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
- assert_line('')
+ assert_line_around_cursor('', '')
end
def test_ed_delete_prev_word_for_mbchar
input_keys('ã‚ã„ㆠã‹ãã{ã•ã—ã™}ãŸã¡ã¤')
- assert_byte_pointer_size('ã‚ã„ㆠã‹ãã{ã•ã—ã™}ãŸã¡ã¤')
- assert_cursor(27)
- assert_cursor_max(27)
+ assert_line_around_cursor('ã‚ã„ㆠã‹ãã{ã•ã—ã™}ãŸã¡ã¤', '')
input_keys("\M-\C-H", false)
- assert_byte_pointer_size('ã‚ã„ㆠã‹ãã{ã•ã—ã™}')
- assert_cursor(21)
- assert_cursor_max(21)
- assert_line('ã‚ã„ㆠã‹ãã{ã•ã—ã™}')
+ assert_line_around_cursor('ã‚ã„ㆠã‹ãã{ã•ã—ã™}', '')
input_keys("\M-\C-H", false)
- assert_byte_pointer_size('ã‚ã„ㆠã‹ãã{')
- assert_cursor(14)
- assert_cursor_max(14)
- assert_line('ã‚ã„ㆠã‹ãã{')
+ assert_line_around_cursor('ã‚ã„ㆠã‹ãã{', '')
input_keys("\M-\C-H", false)
- assert_byte_pointer_size('ã‚ã„ㆠ')
- assert_cursor(7)
- assert_cursor_max(7)
- assert_line('ã‚ã„ㆠ')
+ assert_line_around_cursor('ã‚ã„ㆠ', '')
input_keys("\M-\C-H", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
- assert_line('')
+ assert_line_around_cursor('', '')
end
def test_ed_delete_prev_word_for_mbchar_by_plural_code_points
input_keys("ã‚ã„ㆠã‹\u3099ã\u3099ã\u3099{ã•ã—ã™}ãŸã¡ã¤")
- assert_byte_pointer_size("ã‚ã„ㆠã‹\u3099ã\u3099ã\u3099{ã•ã—ã™}ãŸã¡ã¤")
- assert_cursor(27)
- assert_cursor_max(27)
+ assert_line_around_cursor("ã‚ã„ㆠã‹\u3099ã\u3099ã\u3099{ã•ã—ã™}ãŸã¡ã¤", '')
input_keys("\M-\C-H", false)
- assert_byte_pointer_size("ã‚ã„ㆠã‹\u3099ã\u3099ã\u3099{ã•ã—ã™}")
- assert_cursor(21)
- assert_cursor_max(21)
- assert_line("ã‚ã„ㆠã‹\u3099ã\u3099ã\u3099{ã•ã—ã™}")
+ assert_line_around_cursor("ã‚ã„ㆠã‹\u3099ã\u3099ã\u3099{ã•ã—ã™}", '')
input_keys("\M-\C-H", false)
- assert_byte_pointer_size("ã‚ã„ㆠã‹\u3099ã\u3099ã\u3099{")
- assert_cursor(14)
- assert_cursor_max(14)
- assert_line("ã‚ã„ㆠã‹\u3099ã\u3099ã\u3099{")
+ assert_line_around_cursor("ã‚ã„ㆠã‹\u3099ã\u3099ã\u3099{", '')
input_keys("\M-\C-H", false)
- assert_byte_pointer_size("ã‚ã„ㆠ")
- assert_cursor(7)
- assert_cursor_max(7)
- assert_line('ã‚ã„ㆠ')
+ assert_line_around_cursor('ã‚ã„ㆠ', '')
input_keys("\M-\C-H", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
- assert_line('')
+ assert_line_around_cursor('', '')
end
def test_ed_transpose_chars
input_keys('abc')
input_keys("\C-a", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(3)
+ assert_line_around_cursor('', 'abc')
input_keys("\C-t", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(3)
- assert_line('abc')
+ assert_line_around_cursor('', 'abc')
input_keys("\C-f\C-t", false)
- assert_byte_pointer_size('ba')
- assert_cursor(2)
- assert_cursor_max(3)
- assert_line('bac')
+ assert_line_around_cursor('ba', 'c')
input_keys("\C-t", false)
- assert_byte_pointer_size('bca')
- assert_cursor(3)
- assert_cursor_max(3)
- assert_line('bca')
+ assert_line_around_cursor('bca', '')
input_keys("\C-t", false)
- assert_byte_pointer_size('bac')
- assert_cursor(3)
- assert_cursor_max(3)
- assert_line('bac')
+ assert_line_around_cursor('bac', '')
end
def test_ed_transpose_chars_for_mbchar
input_keys('ã‚ã‹ã•')
input_keys("\C-a", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(6)
+ assert_line_around_cursor('', 'ã‚ã‹ã•')
input_keys("\C-t", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(6)
- assert_line('ã‚ã‹ã•')
+ assert_line_around_cursor('', 'ã‚ã‹ã•')
input_keys("\C-f\C-t", false)
- assert_byte_pointer_size('ã‹ã‚')
- assert_cursor(4)
- assert_cursor_max(6)
- assert_line('ã‹ã‚ã•')
+ assert_line_around_cursor('ã‹ã‚', 'ã•')
input_keys("\C-t", false)
- assert_byte_pointer_size('ã‹ã•ã‚')
- assert_cursor(6)
- assert_cursor_max(6)
- assert_line('ã‹ã•ã‚')
+ assert_line_around_cursor('ã‹ã•ã‚', '')
input_keys("\C-t", false)
- assert_byte_pointer_size('ã‹ã‚ã•')
- assert_cursor(6)
- assert_cursor_max(6)
- assert_line('ã‹ã‚ã•')
+ assert_line_around_cursor('ã‹ã‚ã•', '')
end
def test_ed_transpose_chars_for_mbchar_by_plural_code_points
input_keys("ã‚ã‹\u3099ã•")
input_keys("\C-a", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(6)
+ assert_line_around_cursor('', "ã‚ã‹\u3099ã•")
input_keys("\C-t", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(6)
- assert_line("ã‚ã‹\u3099ã•")
+ assert_line_around_cursor('', "ã‚ã‹\u3099ã•")
input_keys("\C-f\C-t", false)
- assert_byte_pointer_size("ã‹\u3099ã‚")
- assert_cursor(4)
- assert_cursor_max(6)
- assert_line("ã‹\u3099ã‚ã•")
+ assert_line_around_cursor("ã‹\u3099ã‚", 'ã•')
input_keys("\C-t", false)
- assert_byte_pointer_size("ã‹\u3099ã•ã‚")
- assert_cursor(6)
- assert_cursor_max(6)
- assert_line("ã‹\u3099ã•ã‚")
+ assert_line_around_cursor("ã‹\u3099ã•ã‚", '')
input_keys("\C-t", false)
- assert_byte_pointer_size("ã‹\u3099ã‚ã•")
- assert_cursor(6)
- assert_cursor_max(6)
- assert_line("ã‹\u3099ã‚ã•")
+ assert_line_around_cursor("ã‹\u3099ã‚ã•", '')
end
def test_ed_transpose_words
input_keys('abc def')
- assert_line('abc def')
- assert_byte_pointer_size('abc def')
- assert_cursor(7)
- assert_cursor_max(7)
+ assert_line_around_cursor('abc def', '')
input_keys("\M-t", false)
- assert_line('def abc')
- assert_byte_pointer_size('def abc')
- assert_cursor(7)
- assert_cursor_max(7)
+ assert_line_around_cursor('def abc', '')
input_keys("\C-a\C-k", false)
input_keys(' abc def ')
input_keys("\C-b" * 4, false)
- assert_line(' abc def ')
- assert_byte_pointer_size(' abc de')
- assert_cursor(8)
- assert_cursor_max(12)
+ assert_line_around_cursor(' abc de', 'f ')
input_keys("\M-t", false)
- assert_line(' def abc ')
- assert_byte_pointer_size(' def abc')
- assert_cursor(9)
- assert_cursor_max(12)
+ assert_line_around_cursor(' def abc', ' ')
input_keys("\C-a\C-k", false)
input_keys(' abc def ')
input_keys("\C-b" * 6, false)
- assert_line(' abc def ')
- assert_byte_pointer_size(' abc ')
- assert_cursor(6)
- assert_cursor_max(12)
+ assert_line_around_cursor(' abc ', 'def ')
input_keys("\M-t", false)
- assert_line(' def abc ')
- assert_byte_pointer_size(' def abc')
- assert_cursor(9)
- assert_cursor_max(12)
+ assert_line_around_cursor(' def abc', ' ')
input_keys("\M-t", false)
- assert_line(' abc def')
- assert_byte_pointer_size(' abc def')
- assert_cursor(12)
- assert_cursor_max(12)
+ assert_line_around_cursor(' abc def', '')
end
def test_ed_transpose_words_for_mbchar
input_keys('ã‚ã„ㆠã‹ãã')
- assert_line('ã‚ã„ㆠã‹ãã')
- assert_byte_pointer_size('ã‚ã„ㆠã‹ãã')
- assert_cursor(13)
- assert_cursor_max(13)
+ assert_line_around_cursor('ã‚ã„ㆠã‹ãã', '')
input_keys("\M-t", false)
- assert_line('ã‹ãã ã‚ã„ã†')
- assert_byte_pointer_size('ã‹ãã ã‚ã„ã†')
- assert_cursor(13)
- assert_cursor_max(13)
+ assert_line_around_cursor('ã‹ãã ã‚ã„ã†', '')
input_keys("\C-a\C-k", false)
input_keys(' ã‚ã„ㆠã‹ãã ')
input_keys("\C-b" * 4, false)
- assert_line(' ã‚ã„ㆠã‹ãã ')
- assert_byte_pointer_size(' ã‚ã„ㆠã‹ã')
- assert_cursor(13)
- assert_cursor_max(18)
+ assert_line_around_cursor(' ã‚ã„ㆠã‹ã', 'ã ')
input_keys("\M-t", false)
- assert_line(' ã‹ãã ã‚ã„ㆠ')
- assert_byte_pointer_size(' ã‹ãã ã‚ã„ã†')
- assert_cursor(15)
- assert_cursor_max(18)
+ assert_line_around_cursor(' ã‹ãã ã‚ã„ã†', ' ')
input_keys("\C-a\C-k", false)
input_keys(' ã‚ã„ㆠã‹ãã ')
input_keys("\C-b" * 6, false)
- assert_line(' ã‚ã„ㆠã‹ãã ')
- assert_byte_pointer_size(' ã‚ã„ㆠ')
- assert_cursor(9)
- assert_cursor_max(18)
+ assert_line_around_cursor(' ã‚ã„ㆠ', 'ã‹ãã ')
input_keys("\M-t", false)
- assert_line(' ã‹ãã ã‚ã„ㆠ')
- assert_byte_pointer_size(' ã‹ãã ã‚ã„ã†')
- assert_cursor(15)
- assert_cursor_max(18)
+ assert_line_around_cursor(' ã‹ãã ã‚ã„ã†', ' ')
input_keys("\M-t", false)
- assert_line(' ã‚ã„ㆠã‹ãã')
- assert_byte_pointer_size(' ã‚ã„ㆠã‹ãã')
- assert_cursor(18)
- assert_cursor_max(18)
+ assert_line_around_cursor(' ã‚ã„ㆠã‹ãã', '')
end
def test_ed_transpose_words_with_one_word
input_keys('abc ')
- assert_line('abc ')
- assert_byte_pointer_size('abc ')
- assert_cursor(5)
- assert_cursor_max(5)
+ assert_line_around_cursor('abc ', '')
input_keys("\M-t", false)
- assert_line('abc ')
- assert_byte_pointer_size('abc ')
- assert_cursor(5)
- assert_cursor_max(5)
+ assert_line_around_cursor('abc ', '')
input_keys("\C-b", false)
- assert_line('abc ')
- assert_byte_pointer_size('abc ')
- assert_cursor(4)
- assert_cursor_max(5)
+ assert_line_around_cursor('abc ', ' ')
input_keys("\M-t", false)
- assert_line('abc ')
- assert_byte_pointer_size('abc ')
- assert_cursor(4)
- assert_cursor_max(5)
+ assert_line_around_cursor('abc ', ' ')
input_keys("\C-b" * 2, false)
- assert_line('abc ')
- assert_byte_pointer_size('ab')
- assert_cursor(2)
- assert_cursor_max(5)
+ assert_line_around_cursor('ab', 'c ')
input_keys("\M-t", false)
- assert_line('abc ')
- assert_byte_pointer_size('ab')
- assert_cursor(2)
- assert_cursor_max(5)
+ assert_line_around_cursor('ab', 'c ')
input_keys("\M-t", false)
- assert_line('abc ')
- assert_byte_pointer_size('ab')
- assert_cursor(2)
- assert_cursor_max(5)
+ assert_line_around_cursor('ab', 'c ')
end
def test_ed_transpose_words_with_one_word_for_mbchar
input_keys('ã‚ã„ㆠ')
- assert_line('ã‚ã„ㆠ')
- assert_byte_pointer_size('ã‚ã„ㆠ')
- assert_cursor(8)
- assert_cursor_max(8)
+ assert_line_around_cursor('ã‚ã„ㆠ', '')
input_keys("\M-t", false)
- assert_line('ã‚ã„ㆠ')
- assert_byte_pointer_size('ã‚ã„ㆠ')
- assert_cursor(8)
- assert_cursor_max(8)
+ assert_line_around_cursor('ã‚ã„ㆠ', '')
input_keys("\C-b", false)
- assert_line('ã‚ã„ㆠ')
- assert_byte_pointer_size('ã‚ã„ㆠ')
- assert_cursor(7)
- assert_cursor_max(8)
+ assert_line_around_cursor('ã‚ã„ㆠ', ' ')
input_keys("\M-t", false)
- assert_line('ã‚ã„ㆠ')
- assert_byte_pointer_size('ã‚ã„ㆠ')
- assert_cursor(7)
- assert_cursor_max(8)
+ assert_line_around_cursor('ã‚ã„ㆠ', ' ')
input_keys("\C-b" * 2, false)
- assert_line('ã‚ã„ㆠ')
- assert_byte_pointer_size('ã‚ã„')
- assert_cursor(4)
- assert_cursor_max(8)
+ assert_line_around_cursor('ã‚ã„', 'ㆠ')
input_keys("\M-t", false)
- assert_line('ã‚ã„ㆠ')
- assert_byte_pointer_size('ã‚ã„')
- assert_cursor(4)
- assert_cursor_max(8)
+ assert_line_around_cursor('ã‚ã„', 'ㆠ')
input_keys("\M-t", false)
- assert_line('ã‚ã„ㆠ')
- assert_byte_pointer_size('ã‚ã„')
- assert_cursor(4)
- assert_cursor_max(8)
+ assert_line_around_cursor('ã‚ã„', 'ㆠ')
end
def test_ed_digit
input_keys('0123')
- assert_byte_pointer_size('0123')
- assert_cursor(4)
- assert_cursor_max(4)
- assert_line('0123')
+ assert_line_around_cursor('0123', '')
end
def test_ed_next_and_prev_char
input_keys('abc')
- assert_byte_pointer_size('abc')
- assert_cursor(3)
- assert_cursor_max(3)
+ assert_line_around_cursor('abc', '')
input_keys("\C-b", false)
- assert_byte_pointer_size('ab')
- assert_cursor(2)
- assert_cursor_max(3)
+ assert_line_around_cursor('ab', 'c')
input_keys("\C-b", false)
- assert_byte_pointer_size('a')
- assert_cursor(1)
- assert_cursor_max(3)
+ assert_line_around_cursor('a', 'bc')
input_keys("\C-b", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(3)
+ assert_line_around_cursor('', 'abc')
input_keys("\C-b", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(3)
+ assert_line_around_cursor('', 'abc')
input_keys("\C-f", false)
- assert_byte_pointer_size('a')
- assert_cursor(1)
- assert_cursor_max(3)
+ assert_line_around_cursor('a', 'bc')
input_keys("\C-f", false)
- assert_byte_pointer_size('ab')
- assert_cursor(2)
- assert_cursor_max(3)
+ assert_line_around_cursor('ab', 'c')
input_keys("\C-f", false)
- assert_byte_pointer_size('abc')
- assert_cursor(3)
- assert_cursor_max(3)
+ assert_line_around_cursor('abc', '')
input_keys("\C-f", false)
- assert_byte_pointer_size('abc')
- assert_cursor(3)
- assert_cursor_max(3)
+ assert_line_around_cursor('abc', '')
end
def test_ed_next_and_prev_char_for_mbchar
input_keys('ã‚ã„ã†')
- assert_byte_pointer_size('ã‚ã„ã†')
- assert_cursor(6)
- assert_cursor_max(6)
+ assert_line_around_cursor('ã‚ã„ã†', '')
input_keys("\C-b", false)
- assert_byte_pointer_size('ã‚ã„')
- assert_cursor(4)
- assert_cursor_max(6)
+ assert_line_around_cursor('ã‚ã„', 'ã†')
input_keys("\C-b", false)
- assert_byte_pointer_size('ã‚')
- assert_cursor(2)
- assert_cursor_max(6)
+ assert_line_around_cursor('ã‚', 'ã„ã†')
input_keys("\C-b", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(6)
+ assert_line_around_cursor('', 'ã‚ã„ã†')
input_keys("\C-b", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(6)
+ assert_line_around_cursor('', 'ã‚ã„ã†')
input_keys("\C-f", false)
- assert_byte_pointer_size('ã‚')
- assert_cursor(2)
- assert_cursor_max(6)
+ assert_line_around_cursor('ã‚', 'ã„ã†')
input_keys("\C-f", false)
- assert_byte_pointer_size('ã‚ã„')
- assert_cursor(4)
- assert_cursor_max(6)
+ assert_line_around_cursor('ã‚ã„', 'ã†')
input_keys("\C-f", false)
- assert_byte_pointer_size('ã‚ã„ã†')
- assert_cursor(6)
- assert_cursor_max(6)
+ assert_line_around_cursor('ã‚ã„ã†', '')
input_keys("\C-f", false)
- assert_byte_pointer_size('ã‚ã„ã†')
- assert_cursor(6)
- assert_cursor_max(6)
+ assert_line_around_cursor('ã‚ã„ã†', '')
end
def test_ed_next_and_prev_char_for_mbchar_by_plural_code_points
input_keys("ã‹\u3099ã\u3099ã\u3099")
- assert_byte_pointer_size("ã‹\u3099ã\u3099ã\u3099")
- assert_cursor(6)
- assert_cursor_max(6)
+ assert_line_around_cursor("ã‹\u3099ã\u3099ã\u3099", '')
input_keys("\C-b", false)
- assert_byte_pointer_size("ã‹\u3099ã\u3099")
- assert_cursor(4)
- assert_cursor_max(6)
+ assert_line_around_cursor("ã‹\u3099ã\u3099", "ã\u3099")
input_keys("\C-b", false)
- assert_byte_pointer_size("ã‹\u3099")
- assert_cursor(2)
- assert_cursor_max(6)
+ assert_line_around_cursor("ã‹\u3099", "ã\u3099ã\u3099")
input_keys("\C-b", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(6)
+ assert_line_around_cursor('', "ã‹\u3099ã\u3099ã\u3099")
input_keys("\C-b", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(6)
+ assert_line_around_cursor('', "ã‹\u3099ã\u3099ã\u3099")
input_keys("\C-f", false)
- assert_byte_pointer_size("ã‹\u3099")
- assert_cursor(2)
- assert_cursor_max(6)
+ assert_line_around_cursor("ã‹\u3099", "ã\u3099ã\u3099")
input_keys("\C-f", false)
- assert_byte_pointer_size("ã‹\u3099ã\u3099")
- assert_cursor(4)
- assert_cursor_max(6)
+ assert_line_around_cursor("ã‹\u3099ã\u3099", "ã\u3099")
input_keys("\C-f", false)
- assert_byte_pointer_size("ã‹\u3099ã\u3099ã\u3099")
- assert_cursor(6)
- assert_cursor_max(6)
+ assert_line_around_cursor("ã‹\u3099ã\u3099ã\u3099", '')
input_keys("\C-f", false)
- assert_byte_pointer_size("ã‹\u3099ã\u3099ã\u3099")
- assert_cursor(6)
- assert_cursor_max(6)
+ assert_line_around_cursor("ã‹\u3099ã\u3099ã\u3099", '')
end
def test_em_capitol_case
input_keys('abc def{bbb}ccc')
input_keys("\C-a\M-c", false)
- assert_byte_pointer_size('Abc')
- assert_cursor(3)
- assert_cursor_max(15)
- assert_line('Abc def{bbb}ccc')
+ assert_line_around_cursor('Abc', ' def{bbb}ccc')
input_keys("\M-c", false)
- assert_byte_pointer_size('Abc Def')
- assert_cursor(7)
- assert_cursor_max(15)
- assert_line('Abc Def{bbb}ccc')
+ assert_line_around_cursor('Abc Def', '{bbb}ccc')
input_keys("\M-c", false)
- assert_byte_pointer_size('Abc Def{Bbb')
- assert_cursor(11)
- assert_cursor_max(15)
- assert_line('Abc Def{Bbb}ccc')
+ assert_line_around_cursor('Abc Def{Bbb', '}ccc')
input_keys("\M-c", false)
- assert_byte_pointer_size('Abc Def{Bbb}Ccc')
- assert_cursor(15)
- assert_cursor_max(15)
- assert_line('Abc Def{Bbb}Ccc')
+ assert_line_around_cursor('Abc Def{Bbb}Ccc', '')
end
def test_em_capitol_case_with_complex_example
input_keys('{}#* AaA!!!cCc ')
input_keys("\C-a\M-c", false)
- assert_byte_pointer_size('{}#* Aaa')
- assert_cursor(11)
- assert_cursor_max(20)
- assert_line('{}#* Aaa!!!cCc ')
+ assert_line_around_cursor('{}#* Aaa', '!!!cCc ')
input_keys("\M-c", false)
- assert_byte_pointer_size('{}#* Aaa!!!Ccc')
- assert_cursor(17)
- assert_cursor_max(20)
- assert_line('{}#* Aaa!!!Ccc ')
+ assert_line_around_cursor('{}#* Aaa!!!Ccc', ' ')
input_keys("\M-c", false)
- assert_byte_pointer_size('{}#* Aaa!!!Ccc ')
- assert_cursor(20)
- assert_cursor_max(20)
- assert_line('{}#* Aaa!!!Ccc ')
+ assert_line_around_cursor('{}#* Aaa!!!Ccc ', '')
end
def test_em_lower_case
input_keys('AbC def{bBb}CCC')
input_keys("\C-a\M-l", false)
- assert_byte_pointer_size('abc')
- assert_cursor(3)
- assert_cursor_max(15)
- assert_line('abc def{bBb}CCC')
+ assert_line_around_cursor('abc', ' def{bBb}CCC')
input_keys("\M-l", false)
- assert_byte_pointer_size('abc def')
- assert_cursor(7)
- assert_cursor_max(15)
- assert_line('abc def{bBb}CCC')
+ assert_line_around_cursor('abc def', '{bBb}CCC')
input_keys("\M-l", false)
- assert_byte_pointer_size('abc def{bbb')
- assert_cursor(11)
- assert_cursor_max(15)
- assert_line('abc def{bbb}CCC')
+ assert_line_around_cursor('abc def{bbb', '}CCC')
input_keys("\M-l", false)
- assert_byte_pointer_size('abc def{bbb}ccc')
- assert_cursor(15)
- assert_cursor_max(15)
- assert_line('abc def{bbb}ccc')
+ assert_line_around_cursor('abc def{bbb}ccc', '')
end
def test_em_lower_case_with_complex_example
input_keys('{}#* AaA!!!cCc ')
input_keys("\C-a\M-l", false)
- assert_byte_pointer_size('{}#* aaa')
- assert_cursor(11)
- assert_cursor_max(20)
- assert_line('{}#* aaa!!!cCc ')
+ assert_line_around_cursor('{}#* aaa', '!!!cCc ')
input_keys("\M-l", false)
- assert_byte_pointer_size('{}#* aaa!!!ccc')
- assert_cursor(17)
- assert_cursor_max(20)
- assert_line('{}#* aaa!!!ccc ')
+ assert_line_around_cursor('{}#* aaa!!!ccc', ' ')
input_keys("\M-l", false)
- assert_byte_pointer_size('{}#* aaa!!!ccc ')
- assert_cursor(20)
- assert_cursor_max(20)
- assert_line('{}#* aaa!!!ccc ')
+ assert_line_around_cursor('{}#* aaa!!!ccc ', '')
end
def test_em_upper_case
input_keys('AbC def{bBb}CCC')
input_keys("\C-a\M-u", false)
- assert_byte_pointer_size('ABC')
- assert_cursor(3)
- assert_cursor_max(15)
- assert_line('ABC def{bBb}CCC')
+ assert_line_around_cursor('ABC', ' def{bBb}CCC')
input_keys("\M-u", false)
- assert_byte_pointer_size('ABC DEF')
- assert_cursor(7)
- assert_cursor_max(15)
- assert_line('ABC DEF{bBb}CCC')
+ assert_line_around_cursor('ABC DEF', '{bBb}CCC')
input_keys("\M-u", false)
- assert_byte_pointer_size('ABC DEF{BBB')
- assert_cursor(11)
- assert_cursor_max(15)
- assert_line('ABC DEF{BBB}CCC')
+ assert_line_around_cursor('ABC DEF{BBB', '}CCC')
input_keys("\M-u", false)
- assert_byte_pointer_size('ABC DEF{BBB}CCC')
- assert_cursor(15)
- assert_cursor_max(15)
- assert_line('ABC DEF{BBB}CCC')
+ assert_line_around_cursor('ABC DEF{BBB}CCC', '')
end
def test_em_upper_case_with_complex_example
input_keys('{}#* AaA!!!cCc ')
input_keys("\C-a\M-u", false)
- assert_byte_pointer_size('{}#* AAA')
- assert_cursor(11)
- assert_cursor_max(20)
- assert_line('{}#* AAA!!!cCc ')
+ assert_line_around_cursor('{}#* AAA', '!!!cCc ')
input_keys("\M-u", false)
- assert_byte_pointer_size('{}#* AAA!!!CCC')
- assert_cursor(17)
- assert_cursor_max(20)
- assert_line('{}#* AAA!!!CCC ')
+ assert_line_around_cursor('{}#* AAA!!!CCC', ' ')
input_keys("\M-u", false)
- assert_byte_pointer_size('{}#* AAA!!!CCC ')
- assert_cursor(20)
- assert_cursor_max(20)
- assert_line('{}#* AAA!!!CCC ')
+ assert_line_around_cursor('{}#* AAA!!!CCC ', '')
end
def test_em_delete_or_list
@@ -1261,28 +726,16 @@ class Reline::KeyActor::Emacs::Test < Reline::TestCase
}
}
input_keys('fooo')
- assert_byte_pointer_size('fooo')
- assert_cursor(4)
- assert_cursor_max(4)
- assert_line('fooo')
+ assert_line_around_cursor('fooo', '')
assert_equal(nil, @line_editor.instance_variable_get(:@menu_info))
input_keys("\C-b", false)
- assert_byte_pointer_size('foo')
- assert_cursor(3)
- assert_cursor_max(4)
- assert_line('fooo')
+ assert_line_around_cursor('foo', 'o')
assert_equal(nil, @line_editor.instance_variable_get(:@menu_info))
@line_editor.input_key(Reline::Key.new(:em_delete_or_list, :em_delete_or_list, false))
- assert_byte_pointer_size('foo')
- assert_cursor(3)
- assert_cursor_max(3)
- assert_line('foo')
+ assert_line_around_cursor('foo', '')
assert_equal(nil, @line_editor.instance_variable_get(:@menu_info))
@line_editor.input_key(Reline::Key.new(:em_delete_or_list, :em_delete_or_list, false))
- assert_byte_pointer_size('foo')
- assert_cursor(3)
- assert_cursor_max(3)
- assert_line('foo')
+ assert_line_around_cursor('foo', '')
assert_equal(%w{foo_foo foo_bar foo_baz}, @line_editor.instance_variable_get(:@menu_info).list)
end
@@ -1297,22 +750,13 @@ class Reline::KeyActor::Emacs::Test < Reline::TestCase
}
}
input_keys('foo_')
- assert_byte_pointer_size('foo_')
- assert_cursor(4)
- assert_cursor_max(4)
- assert_line('foo_')
+ assert_line_around_cursor('foo_', '')
assert_equal(nil, @line_editor.instance_variable_get(:@menu_info))
input_keys("\C-i", false)
- assert_byte_pointer_size('foo_')
- assert_cursor(4)
- assert_cursor_max(4)
- assert_line('foo_')
+ assert_line_around_cursor('foo_', '')
assert_equal(nil, @line_editor.instance_variable_get(:@menu_info))
input_keys("\C-i", false)
- assert_byte_pointer_size('foo_')
- assert_cursor(4)
- assert_cursor_max(4)
- assert_line('foo_')
+ assert_line_around_cursor('foo_', '')
assert_equal(%w{foo_foo foo_bar}, @line_editor.instance_variable_get(:@menu_info).list)
end
@@ -1328,36 +772,63 @@ class Reline::KeyActor::Emacs::Test < Reline::TestCase
}
}
input_keys('fo')
- assert_byte_pointer_size('fo')
- assert_cursor(2)
- assert_cursor_max(2)
- assert_line('fo')
+ assert_line_around_cursor('fo', '')
assert_equal(nil, @line_editor.instance_variable_get(:@menu_info))
input_keys("\C-i", false)
- assert_byte_pointer_size('foo_')
- assert_cursor(4)
- assert_cursor_max(4)
- assert_line('foo_')
+ assert_line_around_cursor('foo_', '')
assert_equal(nil, @line_editor.instance_variable_get(:@menu_info))
input_keys("\C-i", false)
- assert_byte_pointer_size('foo_')
- assert_cursor(4)
- assert_cursor_max(4)
- assert_line('foo_')
+ assert_line_around_cursor('foo_', '')
assert_equal(%w{foo_foo foo_bar foo_baz}, @line_editor.instance_variable_get(:@menu_info).list)
input_keys('a')
input_keys("\C-i", false)
- assert_byte_pointer_size('foo_a')
- assert_cursor(5)
- assert_cursor_max(5)
- assert_line('foo_a')
+ assert_line_around_cursor('foo_a', '')
input_keys("\C-h", false)
input_keys('b')
input_keys("\C-i", false)
- assert_byte_pointer_size('foo_ba')
- assert_cursor(6)
- assert_cursor_max(6)
- assert_line('foo_ba')
+ assert_line_around_cursor('foo_ba', '')
+ input_keys("\C-h")
+ input_key_by_symbol(:complete)
+ assert_line_around_cursor('foo_ba', '')
+ input_keys("\C-h", false)
+ input_key_by_symbol(:menu_complete)
+ assert_line_around_cursor('foo_bar', '')
+ input_key_by_symbol(:menu_complete)
+ assert_line_around_cursor('foo_baz', '')
+ input_keys("\C-h", false)
+ input_key_by_symbol(:menu_complete_backward)
+ assert_line_around_cursor('foo_baz', '')
+ input_key_by_symbol(:menu_complete_backward)
+ assert_line_around_cursor('foo_bar', '')
+ end
+
+ def test_autocompletion
+ @config.autocompletion = true
+ @line_editor.completion_proc = proc { |word|
+ %w{
+ Readline
+ Regexp
+ RegexpError
+ }.map { |i|
+ i.encode(@encoding)
+ }
+ }
+ input_keys('Re')
+ assert_line_around_cursor('Re', '')
+ input_keys("\C-i", false)
+ assert_line_around_cursor('Readline', '')
+ input_keys("\C-i", false)
+ assert_line_around_cursor('Regexp', '')
+ input_key_by_symbol(:completion_journey_up)
+ assert_line_around_cursor('Readline', '')
+ input_key_by_symbol(:complete)
+ assert_line_around_cursor('Regexp', '')
+ input_key_by_symbol(:menu_complete_backward)
+ assert_line_around_cursor('Readline', '')
+ input_key_by_symbol(:menu_complete)
+ assert_line_around_cursor('Regexp', '')
+ ensure
+ @config.autocompletion = false
end
def test_completion_with_indent
@@ -1372,22 +843,13 @@ class Reline::KeyActor::Emacs::Test < Reline::TestCase
}
}
input_keys(' fo')
- assert_byte_pointer_size(' fo')
- assert_cursor(4)
- assert_cursor_max(4)
- assert_line(' fo')
+ assert_line_around_cursor(' fo', '')
assert_equal(nil, @line_editor.instance_variable_get(:@menu_info))
input_keys("\C-i", false)
- assert_byte_pointer_size(' foo_')
- assert_cursor(6)
- assert_cursor_max(6)
- assert_line(' foo_')
+ assert_line_around_cursor(' foo_', '')
assert_equal(nil, @line_editor.instance_variable_get(:@menu_info))
input_keys("\C-i", false)
- assert_byte_pointer_size(' foo_')
- assert_cursor(6)
- assert_cursor_max(6)
- assert_line(' foo_')
+ assert_line_around_cursor(' foo_', '')
assert_equal(%w{foo_foo foo_bar foo_baz}, @line_editor.instance_variable_get(:@menu_info).list)
end
@@ -1403,22 +865,13 @@ class Reline::KeyActor::Emacs::Test < Reline::TestCase
}
}
input_keys(' "".fo')
- assert_byte_pointer_size(' "".fo')
- assert_cursor(7)
- assert_cursor_max(7)
- assert_line(' "".fo')
+ assert_line_around_cursor(' "".fo', '')
assert_equal(nil, @line_editor.instance_variable_get(:@menu_info))
input_keys("\C-i", false)
- assert_byte_pointer_size(' "".foo_')
- assert_cursor(9)
- assert_cursor_max(9)
- assert_line(' "".foo_')
+ assert_line_around_cursor(' "".foo_', '')
assert_equal(nil, @line_editor.instance_variable_get(:@menu_info))
input_keys("\C-i", false)
- assert_byte_pointer_size(' "".foo_')
- assert_cursor(9)
- assert_cursor_max(9)
- assert_line(' "".foo_')
+ assert_line_around_cursor(' "".foo_', '')
assert_equal(%w{"".foo_foo "".foo_bar "".foo_baz}, @line_editor.instance_variable_get(:@menu_info).list)
end
@@ -1436,54 +889,33 @@ class Reline::KeyActor::Emacs::Test < Reline::TestCase
matched = m
}
input_keys('fo')
- assert_byte_pointer_size('fo')
- assert_cursor(2)
- assert_cursor_max(2)
- assert_line('fo')
+ assert_line_around_cursor('fo', '')
assert_equal(Reline::LineEditor::CompletionState::NORMAL, @line_editor.instance_variable_get(:@completion_state))
assert_equal(nil, matched)
input_keys("\C-i", false)
- assert_byte_pointer_size('foo')
- assert_cursor(3)
- assert_cursor_max(3)
- assert_line('foo')
+ assert_line_around_cursor('foo', '')
assert_equal(Reline::LineEditor::CompletionState::MENU_WITH_PERFECT_MATCH, @line_editor.instance_variable_get(:@completion_state))
assert_equal(nil, matched)
input_keys("\C-i", false)
- assert_byte_pointer_size('foo')
- assert_cursor(3)
- assert_cursor_max(3)
- assert_line('foo')
+ assert_line_around_cursor('foo', '')
assert_equal(Reline::LineEditor::CompletionState::PERFECT_MATCH, @line_editor.instance_variable_get(:@completion_state))
assert_equal(nil, matched)
input_keys("\C-i", false)
- assert_byte_pointer_size('foo')
- assert_cursor(3)
- assert_cursor_max(3)
- assert_line('foo')
+ assert_line_around_cursor('foo', '')
assert_equal(Reline::LineEditor::CompletionState::PERFECT_MATCH, @line_editor.instance_variable_get(:@completion_state))
assert_equal('foo', matched)
matched = nil
input_keys('_')
input_keys("\C-i", false)
- assert_byte_pointer_size('foo_bar')
- assert_cursor(7)
- assert_cursor_max(7)
- assert_line('foo_bar')
+ assert_line_around_cursor('foo_bar', '')
assert_equal(Reline::LineEditor::CompletionState::MENU_WITH_PERFECT_MATCH, @line_editor.instance_variable_get(:@completion_state))
assert_equal(nil, matched)
input_keys("\C-i", false)
- assert_byte_pointer_size('foo_bar')
- assert_cursor(7)
- assert_cursor_max(7)
- assert_line('foo_bar')
+ assert_line_around_cursor('foo_bar', '')
assert_equal(Reline::LineEditor::CompletionState::PERFECT_MATCH, @line_editor.instance_variable_get(:@completion_state))
assert_equal(nil, matched)
input_keys("\C-i", false)
- assert_byte_pointer_size('foo_bar')
- assert_cursor(7)
- assert_cursor_max(7)
- assert_line('foo_bar')
+ assert_line_around_cursor('foo_bar', '')
assert_equal(Reline::LineEditor::CompletionState::PERFECT_MATCH, @line_editor.instance_variable_get(:@completion_state))
assert_equal('foo_bar', matched)
end
@@ -1500,43 +932,25 @@ class Reline::KeyActor::Emacs::Test < Reline::TestCase
}
}
input_keys('fo')
- assert_byte_pointer_size('fo')
- assert_cursor(2)
- assert_cursor_max(2)
- assert_line('fo')
+ assert_line_around_cursor('fo', '')
assert_equal(nil, @line_editor.instance_variable_get(:@menu_info))
input_keys("\C-i", false)
- assert_byte_pointer_size('foo_')
- assert_cursor(4)
- assert_cursor_max(4)
- assert_line('foo_')
+ assert_line_around_cursor('foo_', '')
assert_equal(nil, @line_editor.instance_variable_get(:@menu_info))
input_keys("\C-i", false)
- assert_byte_pointer_size('foo_')
- assert_cursor(4)
- assert_cursor_max(4)
- assert_line('foo_')
+ assert_line_around_cursor('foo_', '')
assert_equal(%w{foo_foo foo_bar}, @line_editor.instance_variable_get(:@menu_info).list)
@config.completion_ignore_case = true
input_keys("\C-i", false)
- assert_byte_pointer_size('foo_')
- assert_cursor(4)
- assert_cursor_max(4)
- assert_line('foo_')
+ assert_line_around_cursor('foo_', '')
assert_equal(%w{foo_foo foo_bar Foo_baz}, @line_editor.instance_variable_get(:@menu_info).list)
input_keys('a')
input_keys("\C-i", false)
- assert_byte_pointer_size('foo_a')
- assert_cursor(5)
- assert_cursor_max(5)
- assert_line('foo_a')
+ assert_line_around_cursor('foo_a', '')
input_keys("\C-h", false)
input_keys('b')
input_keys("\C-i", false)
- assert_byte_pointer_size('foo_ba')
- assert_cursor(6)
- assert_cursor_max(6)
- assert_line('foo_ba')
+ assert_line_around_cursor('foo_ba', '')
end
def test_completion_in_middle_of_line
@@ -1551,17 +965,11 @@ class Reline::KeyActor::Emacs::Test < Reline::TestCase
}
}
input_keys('abcde fo ABCDE')
- assert_line('abcde fo ABCDE')
+ assert_line_around_cursor('abcde fo ABCDE', '')
input_keys("\C-b" * 6 + "\C-i", false)
- assert_byte_pointer_size('abcde foo_')
- assert_cursor(10)
- assert_cursor_max(16)
- assert_line('abcde foo_ ABCDE')
+ assert_line_around_cursor('abcde foo_', ' ABCDE')
input_keys("\C-b" * 2 + "\C-i", false)
- assert_byte_pointer_size('abcde foo_')
- assert_cursor(10)
- assert_cursor_max(18)
- assert_line('abcde foo_o_ ABCDE')
+ assert_line_around_cursor('abcde foo_', 'o_ ABCDE')
end
def test_completion_with_nil_value
@@ -1577,125 +985,65 @@ class Reline::KeyActor::Emacs::Test < Reline::TestCase
}
@config.completion_ignore_case = true
input_keys('fo')
- assert_byte_pointer_size('fo')
- assert_cursor(2)
- assert_cursor_max(2)
- assert_line('fo')
+ assert_line_around_cursor('fo', '')
assert_equal(nil, @line_editor.instance_variable_get(:@menu_info))
input_keys("\C-i", false)
- assert_byte_pointer_size('foo_')
- assert_cursor(4)
- assert_cursor_max(4)
- assert_line('foo_')
+ assert_line_around_cursor('foo_', '')
assert_equal(nil, @line_editor.instance_variable_get(:@menu_info))
input_keys("\C-i", false)
- assert_byte_pointer_size('foo_')
- assert_cursor(4)
- assert_cursor_max(4)
- assert_line('foo_')
+ assert_line_around_cursor('foo_', '')
assert_equal(%w{foo_foo foo_bar Foo_baz}, @line_editor.instance_variable_get(:@menu_info).list)
input_keys('a')
input_keys("\C-i", false)
- assert_byte_pointer_size('foo_a')
- assert_cursor(5)
- assert_cursor_max(5)
- assert_line('foo_a')
+ assert_line_around_cursor('foo_a', '')
input_keys("\C-h", false)
input_keys('b')
input_keys("\C-i", false)
- assert_byte_pointer_size('foo_ba')
- assert_cursor(6)
- assert_cursor_max(6)
- assert_line('foo_ba')
+ assert_line_around_cursor('foo_ba', '')
end
def test_em_kill_region
input_keys('abc def{bbb}ccc ddd ')
- assert_byte_pointer_size('abc def{bbb}ccc ddd ')
- assert_cursor(26)
- assert_cursor_max(26)
- assert_line('abc def{bbb}ccc ddd ')
+ assert_line_around_cursor('abc def{bbb}ccc ddd ', '')
input_keys("\C-w", false)
- assert_byte_pointer_size('abc def{bbb}ccc ')
- assert_cursor(20)
- assert_cursor_max(20)
- assert_line('abc def{bbb}ccc ')
+ assert_line_around_cursor('abc def{bbb}ccc ', '')
input_keys("\C-w", false)
- assert_byte_pointer_size('abc ')
- assert_cursor(6)
- assert_cursor_max(6)
- assert_line('abc ')
+ assert_line_around_cursor('abc ', '')
input_keys("\C-w", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
- assert_line('')
+ assert_line_around_cursor('', '')
input_keys("\C-w", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
- assert_line('')
+ assert_line_around_cursor('', '')
end
def test_em_kill_region_mbchar
input_keys('ã‚ ã„ ã†{ã†}ㆠ')
- assert_byte_pointer_size('ã‚ ã„ ã†{ã†}ㆠ')
- assert_cursor(21)
- assert_cursor_max(21)
- assert_line('ã‚ ã„ ã†{ã†}ㆠ')
+ assert_line_around_cursor('ã‚ ã„ ã†{ã†}ㆠ', '')
input_keys("\C-w", false)
- assert_byte_pointer_size('ã‚ ã„ ')
- assert_cursor(10)
- assert_cursor_max(10)
- assert_line('ã‚ ã„ ')
+ assert_line_around_cursor('ã‚ ã„ ', '')
input_keys("\C-w", false)
- assert_byte_pointer_size('ã‚ ')
- assert_cursor(5)
- assert_cursor_max(5)
- assert_line('ã‚ ')
+ assert_line_around_cursor('ã‚ ', '')
input_keys("\C-w", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
- assert_line('')
+ assert_line_around_cursor('', '')
end
def test_vi_search_prev
Reline::HISTORY.concat(%w{abc 123 AAA})
- assert_line('')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
+ assert_line_around_cursor('', '')
input_keys("\C-ra\C-j")
- assert_line('abc')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(3)
+ assert_line_around_cursor('', 'abc')
end
def test_larger_histories_than_history_size
history_size = @config.history_size
@config.history_size = 2
Reline::HISTORY.concat(%w{abc 123 AAA})
- assert_line('')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
+ assert_line_around_cursor('', '')
input_keys("\C-p")
- assert_line('AAA')
- assert_byte_pointer_size('AAA')
- assert_cursor(3)
- assert_cursor_max(3)
+ assert_line_around_cursor('AAA', '')
input_keys("\C-p")
- assert_line('123')
- assert_byte_pointer_size('123')
- assert_cursor(3)
- assert_cursor_max(3)
+ assert_line_around_cursor('123', '')
input_keys("\C-p")
- assert_line('123')
- assert_byte_pointer_size('123')
- assert_cursor(3)
- assert_cursor_max(3)
+ assert_line_around_cursor('123', '')
ensure
@config.history_size = history_size
end
@@ -1706,25 +1054,13 @@ class Reline::KeyActor::Emacs::Test < Reline::TestCase
'12aa',
'1234' # new
])
- assert_line('')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
+ assert_line_around_cursor('', '')
input_keys("\C-r123")
- assert_line('1234')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0) # doesn't determine yet
+ assert_line_around_cursor('1234', '')
input_keys("\C-ha")
- assert_line('12aa')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
+ assert_line_around_cursor('12aa', '')
input_keys("\C-h3")
- assert_line('1235')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
+ assert_line_around_cursor('1235', '')
end
def test_search_history_to_front
@@ -1733,25 +1069,13 @@ class Reline::KeyActor::Emacs::Test < Reline::TestCase
'12aa',
'1234' # new
])
- assert_line('')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
+ assert_line_around_cursor('', '')
input_keys("\C-s123")
- assert_line('1235')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0) # doesn't determine yet
+ assert_line_around_cursor('1235', '')
input_keys("\C-ha")
- assert_line('12aa')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
+ assert_line_around_cursor('12aa', '')
input_keys("\C-h3")
- assert_line('1234')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
+ assert_line_around_cursor('1234', '')
end
def test_search_history_front_and_back
@@ -1760,30 +1084,15 @@ class Reline::KeyActor::Emacs::Test < Reline::TestCase
'12aa',
'1234' # new
])
- assert_line('')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
+ assert_line_around_cursor('', '')
input_keys("\C-s12")
- assert_line('1235')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0) # doesn't determine yet
+ assert_line_around_cursor('1235', '')
input_keys("\C-s")
- assert_line('12aa')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
+ assert_line_around_cursor('12aa', '')
input_keys("\C-r")
- assert_line('12aa')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
+ assert_line_around_cursor('12aa', '')
input_keys("\C-r")
- assert_line('1235')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
+ assert_line_around_cursor('1235', '')
end
def test_search_history_back_and_front
@@ -1792,30 +1101,15 @@ class Reline::KeyActor::Emacs::Test < Reline::TestCase
'12aa',
'1234' # new
])
- assert_line('')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
+ assert_line_around_cursor('', '')
input_keys("\C-r12")
- assert_line('1234')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0) # doesn't determine yet
+ assert_line_around_cursor('1234', '')
input_keys("\C-r")
- assert_line('12aa')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
+ assert_line_around_cursor('12aa', '')
input_keys("\C-s")
- assert_line('12aa')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
+ assert_line_around_cursor('12aa', '')
input_keys("\C-s")
- assert_line('1234')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
+ assert_line_around_cursor('1234', '')
end
def test_search_history_to_back_in_the_middle_of_histories
@@ -1824,20 +1118,11 @@ class Reline::KeyActor::Emacs::Test < Reline::TestCase
'12aa',
'1234' # new
])
- assert_line('')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
+ assert_line_around_cursor('', '')
input_keys("\C-p\C-p")
- assert_line('12aa')
- assert_byte_pointer_size('12aa')
- assert_cursor(4)
- assert_cursor_max(4)
+ assert_line_around_cursor('12aa', '')
input_keys("\C-r123")
- assert_line('1235')
- assert_byte_pointer_size('1235')
- assert_cursor(4)
- assert_cursor_max(4)
+ assert_line_around_cursor('1235', '')
end
def test_search_history_twice
@@ -1846,20 +1131,11 @@ class Reline::KeyActor::Emacs::Test < Reline::TestCase
'12aa',
'1234' # new
])
- assert_line('')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
+ assert_line_around_cursor('', '')
input_keys("\C-r123")
- assert_line('1234')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0) # doesn't determine yet
+ assert_line_around_cursor('1234', '')
input_keys("\C-r")
- assert_line('1235')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
+ assert_line_around_cursor('1235', '')
end
def test_search_history_by_last_determined
@@ -1868,35 +1144,17 @@ class Reline::KeyActor::Emacs::Test < Reline::TestCase
'12aa',
'1234' # new
])
- assert_line('')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
+ assert_line_around_cursor('', '')
input_keys("\C-r123")
- assert_line('1234')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0) # doesn't determine yet
+ assert_line_around_cursor('1234', '')
input_keys("\C-j")
- assert_line('1234')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(4)
+ assert_line_around_cursor('', '1234')
input_keys("\C-k") # delete
- assert_line('')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
+ assert_line_around_cursor('', '')
input_keys("\C-r")
- assert_line('')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
+ assert_line_around_cursor('', '')
input_keys("\C-r")
- assert_line('1235')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
+ assert_line_around_cursor('1235', '')
end
def test_search_history_with_isearch_terminator
@@ -1908,76 +1166,40 @@ class Reline::KeyActor::Emacs::Test < Reline::TestCase
'12aa',
'1234' # new
])
- assert_line('')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
+ assert_line_around_cursor('', '')
input_keys("\C-r12a")
- assert_line('12aa')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0) # doesn't determine yet
+ assert_line_around_cursor('12aa', '')
input_keys('Y')
- assert_line('12aa')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(4)
+ assert_line_around_cursor('', '12aa')
input_keys('x')
- assert_line('x12aa')
- assert_byte_pointer_size('x')
- assert_cursor(1)
- assert_cursor_max(5)
+ assert_line_around_cursor('x', '12aa')
end
def test_em_set_mark_and_em_exchange_mark
input_keys('aaa bbb ccc ddd')
- assert_byte_pointer_size('aaa bbb ccc ddd')
- assert_cursor(15)
- assert_cursor_max(15)
- assert_line('aaa bbb ccc ddd')
+ assert_line_around_cursor('aaa bbb ccc ddd', '')
input_keys("\C-a\M-F\M-F", false)
- assert_byte_pointer_size('aaa bbb')
- assert_cursor(7)
- assert_cursor_max(15)
- assert_line('aaa bbb ccc ddd')
+ assert_line_around_cursor('aaa bbb', ' ccc ddd')
assert_equal(nil, @line_editor.instance_variable_get(:@mark_pointer))
input_keys("\x00", false) # C-Space
- assert_byte_pointer_size('aaa bbb')
- assert_cursor(7)
- assert_cursor_max(15)
- assert_line('aaa bbb ccc ddd')
+ assert_line_around_cursor('aaa bbb', ' ccc ddd')
assert_equal([7, 0], @line_editor.instance_variable_get(:@mark_pointer))
input_keys("\C-a", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(15)
- assert_line('aaa bbb ccc ddd')
+ assert_line_around_cursor('', 'aaa bbb ccc ddd')
assert_equal([7, 0], @line_editor.instance_variable_get(:@mark_pointer))
input_key_by_symbol(:em_exchange_mark)
- assert_byte_pointer_size('aaa bbb')
- assert_cursor(7)
- assert_cursor_max(15)
- assert_line('aaa bbb ccc ddd')
+ assert_line_around_cursor('aaa bbb', ' ccc ddd')
assert_equal([0, 0], @line_editor.instance_variable_get(:@mark_pointer))
end
def test_em_exchange_mark_without_mark
input_keys('aaa bbb ccc ddd')
- assert_byte_pointer_size('aaa bbb ccc ddd')
- assert_cursor(15)
- assert_cursor_max(15)
- assert_line('aaa bbb ccc ddd')
+ assert_line_around_cursor('aaa bbb ccc ddd', '')
input_keys("\C-a\M-f", false)
- assert_byte_pointer_size('aaa')
- assert_cursor(3)
- assert_cursor_max(15)
- assert_line('aaa bbb ccc ddd')
+ assert_line_around_cursor('aaa', ' bbb ccc ddd')
assert_equal(nil, @line_editor.instance_variable_get(:@mark_pointer))
input_key_by_symbol(:em_exchange_mark)
- assert_byte_pointer_size('aaa')
- assert_cursor(3)
- assert_cursor_max(15)
- assert_line('aaa bbb ccc ddd')
+ assert_line_around_cursor('aaa', ' bbb ccc ddd')
assert_equal(nil, @line_editor.instance_variable_get(:@mark_pointer))
end
@@ -1988,7 +1210,7 @@ class Reline::KeyActor::Emacs::Test < Reline::TestCase
$VERBOSE = verbose
@line_editor.output_modifier_proc = proc { |output| Reline::Unicode.escape_for_print(output) }
input_keys("abcdef\n")
- result = @line_editor.__send__(:modify_lines, @line_editor.whole_lines)
+ result = @line_editor.__send__(:modify_lines, @line_editor.whole_lines, @line_editor.finished?)
$/ = nil
assert_equal(['abcdef'], result)
ensure
@@ -2006,20 +1228,11 @@ class Reline::KeyActor::Emacs::Test < Reline::TestCase
input_keys('123')
# The ed_search_prev_history doesn't have default binding
@line_editor.__send__(:ed_search_prev_history, "\C-p".ord)
- assert_byte_pointer_size('123')
- assert_cursor(3)
- assert_cursor_max(5)
- assert_line('12345')
+ assert_line_around_cursor('123', '45')
@line_editor.__send__(:ed_search_prev_history, "\C-p".ord)
- assert_byte_pointer_size('123')
- assert_cursor(3)
- assert_cursor_max(5)
- assert_line('12356')
+ assert_line_around_cursor('123', '56')
@line_editor.__send__(:ed_search_prev_history, "\C-p".ord)
- assert_byte_pointer_size('123')
- assert_cursor(3)
- assert_cursor_max(5)
- assert_line('12356')
+ assert_line_around_cursor('123', '56')
end
def test_ed_search_prev_history_with_empty
@@ -2029,26 +1242,22 @@ class Reline::KeyActor::Emacs::Test < Reline::TestCase
'12345' # new
])
# The ed_search_prev_history doesn't have default binding
- @line_editor.__send__(:ed_search_prev_history, "\C-p".ord)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(5)
- assert_line('12345')
- @line_editor.__send__(:ed_search_prev_history, "\C-p".ord)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(5)
- assert_line('12aaa')
- @line_editor.__send__(:ed_search_prev_history, "\C-p".ord)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(5)
- assert_line('12356')
- @line_editor.__send__(:ed_search_prev_history, "\C-p".ord)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(5)
- assert_line('12356')
+ input_key_by_symbol(:ed_search_prev_history)
+ assert_line_around_cursor('12345', '')
+ input_key_by_symbol(:ed_search_prev_history)
+ assert_line_around_cursor('12aaa', '')
+ input_key_by_symbol(:ed_search_prev_history)
+ assert_line_around_cursor('12356', '')
+ input_key_by_symbol(:ed_search_next_history)
+ assert_line_around_cursor('12aaa', '')
+ input_key_by_symbol(:ed_prev_char)
+ input_key_by_symbol(:ed_next_char)
+ assert_line_around_cursor('12aaa', '')
+ input_key_by_symbol(:ed_search_prev_history)
+ assert_line_around_cursor('12aaa', '')
+ 3.times { input_key_by_symbol(:ed_prev_char) }
+ input_key_by_symbol(:ed_search_prev_history)
+ assert_line_around_cursor('12', '356')
end
def test_ed_search_prev_history_without_match
@@ -2060,10 +1269,7 @@ class Reline::KeyActor::Emacs::Test < Reline::TestCase
input_keys('ABC')
# The ed_search_prev_history doesn't have default binding
@line_editor.__send__(:ed_search_prev_history, "\C-p".ord)
- assert_byte_pointer_size('ABC')
- assert_cursor(3)
- assert_cursor_max(3)
- assert_line('ABC')
+ assert_line_around_cursor('ABC', '')
end
def test_ed_search_next_history
@@ -2075,30 +1281,15 @@ class Reline::KeyActor::Emacs::Test < Reline::TestCase
input_keys('123')
# The ed_search_prev_history and ed_search_next_history doesn't have default binding
@line_editor.__send__(:ed_search_prev_history, "\C-p".ord)
- assert_byte_pointer_size('123')
- assert_cursor(3)
- assert_cursor_max(5)
- assert_line('12345')
+ assert_line_around_cursor('123', '45')
@line_editor.__send__(:ed_search_prev_history, "\C-p".ord)
- assert_byte_pointer_size('123')
- assert_cursor(3)
- assert_cursor_max(5)
- assert_line('12356')
+ assert_line_around_cursor('123', '56')
@line_editor.__send__(:ed_search_prev_history, "\C-p".ord)
- assert_byte_pointer_size('123')
- assert_cursor(3)
- assert_cursor_max(5)
- assert_line('12356')
+ assert_line_around_cursor('123', '56')
@line_editor.__send__(:ed_search_next_history, "\C-n".ord)
- assert_byte_pointer_size('123')
- assert_cursor(3)
- assert_cursor_max(5)
- assert_line('12345')
+ assert_line_around_cursor('123', '45')
@line_editor.__send__(:ed_search_next_history, "\C-n".ord)
- assert_byte_pointer_size('123')
- assert_cursor(3)
- assert_cursor_max(5)
- assert_line('12345')
+ assert_line_around_cursor('123', '45')
end
def test_ed_search_next_history_with_empty
@@ -2108,134 +1299,83 @@ class Reline::KeyActor::Emacs::Test < Reline::TestCase
'12345' # new
])
# The ed_search_prev_history and ed_search_next_history doesn't have default binding
- @line_editor.__send__(:ed_search_prev_history, "\C-p".ord)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(5)
- assert_line('12345')
- @line_editor.__send__(:ed_search_prev_history, "\C-p".ord)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(5)
- assert_line('12aaa')
- @line_editor.__send__(:ed_search_prev_history, "\C-p".ord)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(5)
- assert_line('12356')
- @line_editor.__send__(:ed_search_next_history, "\C-n".ord)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(5)
- assert_line('12aaa')
- @line_editor.__send__(:ed_search_next_history, "\C-n".ord)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(5)
- assert_line('12345')
- @line_editor.__send__(:ed_search_next_history, "\C-n".ord)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
- assert_line('')
+ input_key_by_symbol(:ed_search_prev_history)
+ assert_line_around_cursor('12345', '')
+ input_key_by_symbol(:ed_search_prev_history)
+ assert_line_around_cursor('12aaa', '')
+ input_key_by_symbol(:ed_search_prev_history)
+ assert_line_around_cursor('12356', '')
+ input_key_by_symbol(:ed_search_next_history)
+ assert_line_around_cursor('12aaa', '')
+ input_key_by_symbol(:ed_search_next_history)
+ assert_line_around_cursor('12345', '')
+ input_key_by_symbol(:ed_search_prev_history)
+ assert_line_around_cursor('12aaa', '')
+ input_key_by_symbol(:ed_prev_char)
+ input_key_by_symbol(:ed_next_char)
+ input_key_by_symbol(:ed_search_next_history)
+ assert_line_around_cursor('12aaa', '')
+ 3.times { input_key_by_symbol(:ed_prev_char) }
+ input_key_by_symbol(:ed_search_next_history)
+ assert_line_around_cursor('12', '345')
+ end
+
+ def test_incremental_search_history_cancel_by_symbol_key
+ # ed_prev_char should move cursor left and cancel incremental search
+ input_keys("abc\C-r")
+ input_key_by_symbol(:ed_prev_char)
+ input_keys('d')
+ assert_line_around_cursor('abd', 'c')
end
# Unicode emoji test
def test_ed_insert_for_include_zwj_emoji
- omit "This test is for UTF-8 but the locale is #{Reline::IOGate.encoding}" if Reline::IOGate.encoding != Encoding::UTF_8
+ omit "This test is for UTF-8 but the locale is #{Reline.core.encoding}" if Reline.core.encoding != Encoding::UTF_8
# U+1F468 U+200D U+1F469 U+200D U+1F467 U+200D U+1F466 is family: man, woman, girl, boy "👨â€ðŸ‘©â€ðŸ‘§â€ðŸ‘¦"
input_keys("\u{1F468}") # U+1F468 is man "👨"
- assert_line("\u{1F468}")
- assert_byte_pointer_size("\u{1F468}")
- assert_cursor(2)
- assert_cursor_max(2)
+ assert_line_around_cursor('👨', '')
input_keys("\u200D") # U+200D is ZERO WIDTH JOINER
- assert_line("\u{1F468 200D}")
- assert_byte_pointer_size("\u{1F468 200D}")
- assert_cursor(2)
- assert_cursor_max(2)
+ assert_line_around_cursor('👨â€', '')
input_keys("\u{1F469}") # U+1F469 is woman "👩"
- assert_line("\u{1F468 200D 1F469}")
- assert_byte_pointer_size("\u{1F468 200D 1F469}")
- assert_cursor(2)
- assert_cursor_max(2)
+ assert_line_around_cursor('👨â€ðŸ‘©', '')
input_keys("\u200D") # U+200D is ZERO WIDTH JOINER
- assert_line("\u{1F468 200D 1F469 200D}")
- assert_byte_pointer_size("\u{1F468 200D 1F469 200D}")
- assert_cursor(2)
- assert_cursor_max(2)
+ assert_line_around_cursor('👨â€ðŸ‘©â€', '')
input_keys("\u{1F467}") # U+1F467 is girl "👧"
- assert_line("\u{1F468 200D 1F469 200D 1F467}")
- assert_byte_pointer_size("\u{1F468 200D 1F469 200D 1F467}")
- assert_cursor(2)
- assert_cursor_max(2)
+ assert_line_around_cursor('👨â€ðŸ‘©â€ðŸ‘§', '')
input_keys("\u200D") # U+200D is ZERO WIDTH JOINER
- assert_line("\u{1F468 200D 1F469 200D 1F467 200D}")
- assert_byte_pointer_size("\u{1F468 200D 1F469 200D 1F467 200D}")
- assert_cursor(2)
- assert_cursor_max(2)
+ assert_line_around_cursor('👨â€ðŸ‘©â€ðŸ‘§â€', '')
input_keys("\u{1F466}") # U+1F466 is boy "👦"
- assert_line("\u{1F468 200D 1F469 200D 1F467 200D 1F466}")
- assert_byte_pointer_size("\u{1F468 200D 1F469 200D 1F467 200D 1F466}")
- assert_cursor(2)
- assert_cursor_max(2)
+ assert_line_around_cursor('👨â€ðŸ‘©â€ðŸ‘§â€ðŸ‘¦', '')
# U+1F468 U+200D U+1F469 U+200D U+1F467 U+200D U+1F466 is family: man, woman, girl, boy "👨â€ðŸ‘©â€ðŸ‘§â€ðŸ‘¦"
input_keys("\u{1F468 200D 1F469 200D 1F467 200D 1F466}")
- assert_line("\u{1F468 200D 1F469 200D 1F467 200D 1F466 1F468 200D 1F469 200D 1F467 200D 1F466}")
- assert_byte_pointer_size("\u{1F468 200D 1F469 200D 1F467 200D 1F466 1F468 200D 1F469 200D 1F467 200D 1F466}")
- assert_cursor(4)
- assert_cursor_max(4)
+ assert_line_around_cursor('👨â€ðŸ‘©â€ðŸ‘§â€ðŸ‘¦ðŸ‘¨â€ðŸ‘©â€ðŸ‘§â€ðŸ‘¦', '')
end
def test_ed_insert_for_include_valiation_selector
- omit "This test is for UTF-8 but the locale is #{Reline::IOGate.encoding}" if Reline::IOGate.encoding != Encoding::UTF_8
+ omit "This test is for UTF-8 but the locale is #{Reline.core.encoding}" if Reline.core.encoding != Encoding::UTF_8
# U+0030 U+FE00 is DIGIT ZERO + VARIATION SELECTOR-1 "0︀"
input_keys("\u0030") # U+0030 is DIGIT ZERO
- assert_line("\u0030")
- assert_byte_pointer_size("\u0030")
- assert_cursor(1)
- assert_cursor_max(1)
+ assert_line_around_cursor('0', '')
input_keys("\uFE00") # U+FE00 is VARIATION SELECTOR-1
- assert_line("\u{0030 FE00}")
- assert_byte_pointer_size("\u{0030 FE00}")
- assert_cursor(1)
- assert_cursor_max(1)
+ assert_line_around_cursor('0︀', '')
end
def test_em_yank_pop
input_keys("def hoge\C-w\C-b\C-f\C-w", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
- assert_line('')
+ assert_line_around_cursor('', '')
input_keys("\C-y", false)
- assert_byte_pointer_size('def ')
- assert_cursor(4)
- assert_cursor_max(4)
- assert_line('def ')
+ assert_line_around_cursor('def ', '')
input_keys("\M-\C-y", false)
- assert_byte_pointer_size('hoge')
- assert_cursor(4)
- assert_cursor_max(4)
- assert_line('hoge')
+ assert_line_around_cursor('hoge', '')
end
def test_em_kill_region_with_kill_ring
input_keys("def hoge\C-b\C-b\C-b\C-b", false)
- assert_byte_pointer_size('def ')
- assert_cursor(4)
- assert_cursor_max(8)
- assert_line('def hoge')
+ assert_line_around_cursor('def ', 'hoge')
input_keys("\C-k\C-w", false)
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
- assert_line('')
+ assert_line_around_cursor('', '')
input_keys("\C-y", false)
- assert_byte_pointer_size('def hoge')
- assert_cursor(8)
- assert_cursor_max(8)
- assert_line('def hoge')
+ assert_line_around_cursor('def hoge', '')
end
def test_ed_search_prev_next_history_in_multibyte
@@ -2251,45 +1391,237 @@ class Reline::KeyActor::Emacs::Test < Reline::TestCase
assert_whole_lines(['def foo', ' 12345', 'end'])
assert_line_index(1)
assert_whole_lines(['def foo', ' 12345', 'end'])
- assert_byte_pointer_size(' 123')
- assert_cursor(5)
- assert_cursor_max(7)
- assert_line(' 12345')
+ assert_line_around_cursor(' 123', '45')
@line_editor.__send__(:ed_search_prev_history, "\C-p".ord)
assert_line_index(2)
assert_whole_lines(['def hoge', ' 67890', ' 12345', 'end'])
- assert_byte_pointer_size(' 123')
- assert_cursor(5)
- assert_cursor_max(7)
- assert_line(' 12345')
+ assert_line_around_cursor(' 123', '45')
@line_editor.__send__(:ed_search_prev_history, "\C-p".ord)
assert_line_index(2)
assert_whole_lines(['def hoge', ' 67890', ' 12345', 'end'])
- assert_byte_pointer_size(' 123')
- assert_cursor(5)
- assert_cursor_max(7)
- assert_line(' 12345')
+ assert_line_around_cursor(' 123', '45')
@line_editor.__send__(:ed_search_next_history, "\C-n".ord)
assert_line_index(1)
assert_whole_lines(['def foo', ' 12345', 'end'])
- assert_byte_pointer_size(' 123')
- assert_cursor(5)
- assert_cursor_max(7)
- assert_line(' 12345')
+ assert_line_around_cursor(' 123', '45')
@line_editor.__send__(:ed_search_next_history, "\C-n".ord)
assert_line_index(1)
assert_whole_lines(['def foo', ' 12345', 'end'])
- assert_byte_pointer_size(' 123')
- assert_cursor(5)
- assert_cursor_max(7)
- assert_line(' 12345')
+ assert_line_around_cursor(' 123', '45')
+ end
+
+ def test_ignore_NUL_by_ed_quoted_insert
+ input_keys(%Q{"\C-v\C-@"}, false)
+ assert_line_around_cursor('""', '')
+ end
+
+ def test_ed_argument_digit_by_meta_num
+ input_keys('abcdef')
+ assert_line_around_cursor('abcdef', '')
+ input_keys("\M-2", false)
+ input_keys("\C-h", false)
+ assert_line_around_cursor('abcd', '')
+ end
+
+ def test_halfwidth_kana_width_dakuten
+ input_raw_keys('ガギゲゴ')
+ assert_line_around_cursor('ガギゲゴ', '')
+ input_keys("\C-b\C-b", false)
+ assert_line_around_cursor('ガギ', 'ゲゴ')
+ input_raw_keys('グ', false)
+ assert_line_around_cursor('ガギグ', 'ゲゴ')
end
def test_input_unknown_char
input_keys('͸') # U+0378 (unassigned)
- assert_line('͸')
- assert_byte_pointer_size('͸')
- assert_cursor(1)
- assert_cursor_max(1)
+ assert_line_around_cursor('͸', '')
+ end
+
+ def test_unix_line_discard
+ input_keys("\C-u", false)
+ assert_line_around_cursor('', '')
+ input_keys('abc')
+ assert_line_around_cursor('abc', '')
+ input_keys("\C-b\C-u", false)
+ assert_line_around_cursor('', 'c')
+ input_keys("\C-f\C-u", false)
+ assert_line_around_cursor('', '')
+ end
+
+ def test_vi_editing_mode
+ @line_editor.__send__(:vi_editing_mode, nil)
+ assert(@config.editing_mode_is?(:vi_insert))
+ end
+
+ def test_undo
+ input_keys("\C-_", false)
+ assert_line_around_cursor('', '')
+ input_keys("aã‚b\C-h\C-h\C-h", false)
+ assert_line_around_cursor('', '')
+ input_keys("\C-_", false)
+ assert_line_around_cursor('a', '')
+ input_keys("\C-_", false)
+ assert_line_around_cursor('aã‚', '')
+ input_keys("\C-_", false)
+ assert_line_around_cursor('aã‚b', '')
+ input_keys("\C-_", false)
+ assert_line_around_cursor('aã‚', '')
+ input_keys("\C-_", false)
+ assert_line_around_cursor('a', '')
+ input_keys("\C-_", false)
+ assert_line_around_cursor('', '')
+ end
+
+ def test_undo_with_cursor_position
+ input_keys("abc\C-b\C-h", false)
+ assert_line_around_cursor('a', 'c')
+ input_keys("\C-_", false)
+ assert_line_around_cursor('ab', 'c')
+ input_keys("ã‚ã„ã†\C-b\C-h", false)
+ assert_line_around_cursor('abã‚', 'ã†c')
+ input_keys("\C-_", false)
+ assert_line_around_cursor('abã‚ã„', 'ã†c')
+ end
+
+ def test_undo_with_multiline
+ @line_editor.multiline_on
+ @line_editor.confirm_multiline_termination_proc = proc {}
+ input_keys("1\n2\n3", false)
+ assert_whole_lines(["1", "2", "3"])
+ assert_line_index(2)
+ assert_line_around_cursor('3', '')
+ input_keys("\C-p\C-h\C-h", false)
+ assert_whole_lines(["1", "3"])
+ assert_line_index(0)
+ assert_line_around_cursor('1', '')
+ input_keys("\C-_", false)
+ assert_whole_lines(["1", "", "3"])
+ assert_line_index(1)
+ assert_line_around_cursor('', '')
+ input_keys("\C-_", false)
+ assert_whole_lines(["1", "2", "3"])
+ assert_line_index(1)
+ assert_line_around_cursor('2', '')
+ input_keys("\C-_", false)
+ assert_whole_lines(["1", "2", ""])
+ assert_line_index(2)
+ assert_line_around_cursor('', '')
+ input_keys("\C-_", false)
+ assert_whole_lines(["1", "2"])
+ assert_line_index(1)
+ assert_line_around_cursor('2', '')
+ end
+
+ def test_undo_with_many_times
+ str = "a" + "b" * 99
+ input_keys(str, false)
+ 100.times { input_keys("\C-_", false) }
+ assert_line_around_cursor('a', '')
+ input_keys("\C-_", false)
+ assert_line_around_cursor('a', '')
+ end
+
+ def test_redo
+ input_keys("aã‚b", false)
+ assert_line_around_cursor('aã‚b', '')
+ input_keys("\M-\C-_", false)
+ assert_line_around_cursor('aã‚b', '')
+ input_keys("\C-_", false)
+ assert_line_around_cursor('aã‚', '')
+ input_keys("\C-_", false)
+ assert_line_around_cursor('a', '')
+ input_keys("\M-\C-_", false)
+ assert_line_around_cursor('aã‚', '')
+ input_keys("\M-\C-_", false)
+ assert_line_around_cursor('aã‚b', '')
+ input_keys("\C-_", false)
+ assert_line_around_cursor('aã‚', '')
+ input_keys("c", false)
+ assert_line_around_cursor('aã‚c', '')
+ input_keys("\M-\C-_", false)
+ assert_line_around_cursor('aã‚c', '')
+ end
+
+ def test_redo_with_cursor_position
+ input_keys("abc\C-b\C-h", false)
+ assert_line_around_cursor('a', 'c')
+ input_keys("\M-\C-_", false)
+ assert_line_around_cursor('a', 'c')
+ input_keys("\C-_", false)
+ assert_line_around_cursor('ab', 'c')
+ input_keys("\M-\C-_", false)
+ assert_line_around_cursor('a', 'c')
+ end
+
+ def test_redo_with_multiline
+ @line_editor.multiline_on
+ @line_editor.confirm_multiline_termination_proc = proc {}
+ input_keys("1\n2\n3", false)
+ assert_whole_lines(["1", "2", "3"])
+ assert_line_index(2)
+ assert_line_around_cursor('3', '')
+
+ input_keys("\C-_", false)
+ assert_whole_lines(["1", "2", ""])
+ assert_line_index(2)
+ assert_line_around_cursor('', '')
+
+ input_keys("\C-_", false)
+ assert_whole_lines(["1", "2"])
+ assert_line_index(1)
+ assert_line_around_cursor('2', '')
+
+ input_keys("\M-\C-_", false)
+ assert_whole_lines(["1", "2", ""])
+ assert_line_index(2)
+ assert_line_around_cursor('', '')
+
+ input_keys("\M-\C-_", false)
+ assert_whole_lines(["1", "2", "3"])
+ assert_line_index(2)
+ assert_line_around_cursor('3', '')
+
+ input_keys("\C-p\C-h\C-h", false)
+ assert_whole_lines(["1", "3"])
+ assert_line_index(0)
+ assert_line_around_cursor('1', '')
+
+ input_keys("\C-n", false)
+ assert_whole_lines(["1", "3"])
+ assert_line_index(1)
+ assert_line_around_cursor('3', '')
+
+ input_keys("\C-_", false)
+ assert_whole_lines(["1", "", "3"])
+ assert_line_index(1)
+ assert_line_around_cursor('', '')
+
+ input_keys("\C-_", false)
+ assert_whole_lines(["1", "2", "3"])
+ assert_line_index(1)
+ assert_line_around_cursor('2', '')
+
+ input_keys("\M-\C-_", false)
+ assert_whole_lines(["1", "", "3"])
+ assert_line_index(1)
+ assert_line_around_cursor('', '')
+
+ input_keys("\M-\C-_", false)
+ assert_whole_lines(["1", "3"])
+ assert_line_index(1)
+ assert_line_around_cursor('3', '')
+ end
+
+ def test_redo_with_many_times
+ str = "a" + "b" * 98 + "c"
+ input_keys(str, false)
+ 100.times { input_keys("\C-_", false) }
+ assert_line_around_cursor('a', '')
+ input_keys("\C-_", false)
+ assert_line_around_cursor('a', '')
+ 100.times { input_keys("\M-\C-_", false) }
+ assert_line_around_cursor(str, '')
+ input_keys("\M-\C-_", false)
+ assert_line_around_cursor(str, '')
end
end
diff --git a/test/reline/test_key_actor_vi.rb b/test/reline/test_key_actor_vi.rb
index 722cdc0b75..07ca873ce3 100644
--- a/test/reline/test_key_actor_vi.rb
+++ b/test/reline/test_key_actor_vi.rb
@@ -1,6 +1,6 @@
require_relative 'helper'
-class Reline::KeyActor::ViInsert::Test < Reline::TestCase
+class Reline::ViInsertTest < Reline::TestCase
def setup
Reline.send(:test_mode)
@prompt = '> '
@@ -8,967 +8,534 @@ class Reline::KeyActor::ViInsert::Test < Reline::TestCase
@config.read_lines(<<~LINES.split(/(?<=\n)/))
set editing-mode vi
LINES
- @encoding = Reline::IOGate.encoding
+ @encoding = Reline.core.encoding
@line_editor = Reline::LineEditor.new(@config, @encoding)
@line_editor.reset(@prompt, encoding: @encoding)
end
+ def editing_mode_label
+ @config.instance_variable_get(:@editing_mode_label)
+ end
+
def teardown
Reline.test_reset
end
def test_vi_command_mode
input_keys("\C-[")
- assert_instance_of(Reline::KeyActor::ViCommand, @config.editing_mode)
+ assert_equal(:vi_command, editing_mode_label)
end
def test_vi_command_mode_with_input
input_keys("abc\C-[")
- assert_instance_of(Reline::KeyActor::ViCommand, @config.editing_mode)
- assert_line('abc')
+ assert_equal(:vi_command, editing_mode_label)
+ assert_line_around_cursor('ab', 'c')
end
def test_vi_insert
- assert_instance_of(Reline::KeyActor::ViInsert, @config.editing_mode)
+ assert_equal(:vi_insert, editing_mode_label)
input_keys('i')
- assert_line('i')
- assert_cursor(1)
- assert_instance_of(Reline::KeyActor::ViInsert, @config.editing_mode)
+ assert_line_around_cursor('i', '')
+ assert_equal(:vi_insert, editing_mode_label)
input_keys("\C-[")
- assert_line('i')
- assert_cursor(0)
- assert_instance_of(Reline::KeyActor::ViCommand, @config.editing_mode)
+ assert_line_around_cursor('', 'i')
+ assert_equal(:vi_command, editing_mode_label)
input_keys('i')
- assert_line('i')
- assert_cursor(0)
- assert_instance_of(Reline::KeyActor::ViInsert, @config.editing_mode)
+ assert_line_around_cursor('', 'i')
+ assert_equal(:vi_insert, editing_mode_label)
end
def test_vi_add
- assert_instance_of(Reline::KeyActor::ViInsert, @config.editing_mode)
+ assert_equal(:vi_insert, editing_mode_label)
input_keys('a')
- assert_line('a')
- assert_cursor(1)
- assert_instance_of(Reline::KeyActor::ViInsert, @config.editing_mode)
+ assert_line_around_cursor('a', '')
+ assert_equal(:vi_insert, editing_mode_label)
input_keys("\C-[")
- assert_line('a')
- assert_cursor(0)
- assert_instance_of(Reline::KeyActor::ViCommand, @config.editing_mode)
+ assert_line_around_cursor('', 'a')
+ assert_equal(:vi_command, editing_mode_label)
input_keys('a')
- assert_line('a')
- assert_cursor(1)
- assert_instance_of(Reline::KeyActor::ViInsert, @config.editing_mode)
+ assert_line_around_cursor('a', '')
+ assert_equal(:vi_insert, editing_mode_label)
end
def test_vi_insert_at_bol
input_keys('I')
- assert_line('I')
- assert_instance_of(Reline::KeyActor::ViInsert, @config.editing_mode)
+ assert_line_around_cursor('I', '')
+ assert_equal(:vi_insert, editing_mode_label)
input_keys("12345\C-[hh")
- assert_line('I12345')
- assert_byte_pointer_size('I12')
- assert_cursor(3)
- assert_cursor_max(6)
- assert_instance_of(Reline::KeyActor::ViCommand, @config.editing_mode)
+ assert_line_around_cursor('I12', '345')
+ assert_equal(:vi_command, editing_mode_label)
input_keys('I')
- assert_line('I12345')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(6)
- assert_instance_of(Reline::KeyActor::ViInsert, @config.editing_mode)
+ assert_line_around_cursor('', 'I12345')
+ assert_equal(:vi_insert, editing_mode_label)
end
def test_vi_add_at_eol
input_keys('A')
- assert_line('A')
- assert_instance_of(Reline::KeyActor::ViInsert, @config.editing_mode)
+ assert_line_around_cursor('A', '')
+ assert_equal(:vi_insert, editing_mode_label)
input_keys("12345\C-[hh")
- assert_line('A12345')
- assert_byte_pointer_size('A12')
- assert_cursor(3)
- assert_cursor_max(6)
- assert_instance_of(Reline::KeyActor::ViCommand, @config.editing_mode)
+ assert_line_around_cursor('A12', '345')
+ assert_equal(:vi_command, editing_mode_label)
input_keys('A')
- assert_line('A12345')
- assert_byte_pointer_size('A12345')
- assert_cursor(6)
- assert_cursor_max(6)
- assert_instance_of(Reline::KeyActor::ViInsert, @config.editing_mode)
+ assert_line_around_cursor('A12345', '')
+ assert_equal(:vi_insert, editing_mode_label)
end
def test_ed_insert_one
input_keys('a')
- assert_line('a')
- assert_byte_pointer_size('a')
- assert_cursor(1)
- assert_cursor_max(1)
+ assert_line_around_cursor('a', '')
end
def test_ed_insert_two
input_keys('ab')
- assert_line('ab')
- assert_byte_pointer_size('ab')
- assert_cursor(2)
- assert_cursor_max(2)
+ assert_line_around_cursor('ab', '')
end
def test_ed_insert_mbchar_one
input_keys('ã‹')
- assert_line('ã‹')
- assert_byte_pointer_size('ã‹')
- assert_cursor(2)
- assert_cursor_max(2)
+ assert_line_around_cursor('ã‹', '')
end
def test_ed_insert_mbchar_two
input_keys('ã‹ã')
- assert_line('ã‹ã')
- assert_byte_pointer_size('ã‹ã')
- assert_cursor(4)
- assert_cursor_max(4)
+ assert_line_around_cursor('ã‹ã', '')
end
def test_ed_insert_for_mbchar_by_plural_code_points
input_keys("ã‹\u3099")
- assert_line("ã‹\u3099")
- assert_byte_pointer_size("ã‹\u3099")
- assert_cursor(2)
- assert_cursor_max(2)
+ assert_line_around_cursor("ã‹\u3099", '')
end
def test_ed_insert_for_plural_mbchar_by_plural_code_points
input_keys("ã‹\u3099ã\u3099")
- assert_line("ã‹\u3099ã\u3099")
- assert_byte_pointer_size("ã‹\u3099ã\u3099")
- assert_cursor(4)
- assert_cursor_max(4)
+ assert_line_around_cursor("ã‹\u3099ã\u3099", '')
end
def test_ed_next_char
input_keys("abcdef\C-[0")
- assert_line('abcdef')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(6)
+ assert_line_around_cursor('', 'abcdef')
input_keys('l')
- assert_line('abcdef')
- assert_byte_pointer_size('a')
- assert_cursor(1)
- assert_cursor_max(6)
+ assert_line_around_cursor('a', 'bcdef')
input_keys('2l')
- assert_line('abcdef')
- assert_byte_pointer_size('abc')
- assert_cursor(3)
- assert_cursor_max(6)
+ assert_line_around_cursor('abc', 'def')
end
def test_ed_prev_char
input_keys("abcdef\C-[")
- assert_line('abcdef')
- assert_byte_pointer_size('abcde')
- assert_cursor(5)
- assert_cursor_max(6)
+ assert_line_around_cursor('abcde', 'f')
input_keys('h')
- assert_line('abcdef')
- assert_byte_pointer_size('abcd')
- assert_cursor(4)
- assert_cursor_max(6)
+ assert_line_around_cursor('abcd', 'ef')
input_keys('2h')
- assert_line('abcdef')
- assert_byte_pointer_size('ab')
- assert_cursor(2)
- assert_cursor_max(6)
+ assert_line_around_cursor('ab', 'cdef')
end
def test_history
Reline::HISTORY.concat(%w{abc 123 AAA})
input_keys("\C-[")
- assert_line('')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
+ assert_line_around_cursor('', '')
input_keys('k')
- assert_line('AAA')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(3)
+ assert_line_around_cursor('', 'AAA')
input_keys('2k')
- assert_line('abc')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(3)
+ assert_line_around_cursor('', 'abc')
input_keys('j')
- assert_line('123')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(3)
+ assert_line_around_cursor('', '123')
input_keys('2j')
- assert_line('')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
+ assert_line_around_cursor('', '')
end
def test_vi_paste_prev
input_keys("abcde\C-[3h")
- assert_line('abcde')
- assert_byte_pointer_size('a')
- assert_cursor(1)
- assert_cursor_max(5)
+ assert_line_around_cursor('a', 'bcde')
input_keys('P')
- assert_line('abcde')
- assert_byte_pointer_size('a')
- assert_cursor(1)
- assert_cursor_max(5)
+ assert_line_around_cursor('a', 'bcde')
input_keys('d$')
- assert_line('a')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(1)
+ assert_line_around_cursor('', 'a')
input_keys('P')
- assert_line('bcdea')
- assert_byte_pointer_size('bcd')
- assert_cursor(3)
- assert_cursor_max(5)
+ assert_line_around_cursor('bcd', 'ea')
input_keys('2P')
- assert_line('bcdbcdbcdeeea')
- assert_byte_pointer_size('bcdbcdbcd')
- assert_cursor(9)
- assert_cursor_max(13)
+ assert_line_around_cursor('bcdbcdbcd', 'eeea')
end
def test_vi_paste_next
input_keys("abcde\C-[3h")
- assert_line('abcde')
- assert_byte_pointer_size('a')
- assert_cursor(1)
- assert_cursor_max(5)
+ assert_line_around_cursor('a', 'bcde')
input_keys('p')
- assert_line('abcde')
- assert_byte_pointer_size('a')
- assert_cursor(1)
- assert_cursor_max(5)
+ assert_line_around_cursor('a', 'bcde')
input_keys('d$')
- assert_line('a')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(1)
+ assert_line_around_cursor('', 'a')
input_keys('p')
- assert_line('abcde')
- assert_byte_pointer_size('abcd')
- assert_cursor(4)
- assert_cursor_max(5)
+ assert_line_around_cursor('abcd', 'e')
input_keys('2p')
- assert_line('abcdebcdebcde')
- assert_byte_pointer_size('abcdebcdebcd')
- assert_cursor(12)
- assert_cursor_max(13)
+ assert_line_around_cursor('abcdebcdebcd', 'e')
end
def test_vi_paste_prev_for_mbchar
input_keys("ã‚ã„ã†ãˆãŠ\C-[3h")
- assert_line('ã‚ã„ã†ãˆãŠ')
- assert_byte_pointer_size('ã‚')
- assert_cursor(2)
- assert_cursor_max(10)
+ assert_line_around_cursor('ã‚', 'ã„ã†ãˆãŠ')
input_keys('P')
- assert_line('ã‚ã„ã†ãˆãŠ')
- assert_byte_pointer_size('ã‚')
- assert_cursor(2)
- assert_cursor_max(10)
+ assert_line_around_cursor('ã‚', 'ã„ã†ãˆãŠ')
input_keys('d$')
- assert_line('ã‚')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(2)
+ assert_line_around_cursor('', 'ã‚')
input_keys('P')
- assert_line('ã„ã†ãˆãŠã‚')
- assert_byte_pointer_size('ã„ã†ãˆ')
- assert_cursor(6)
- assert_cursor_max(10)
+ assert_line_around_cursor('ã„ã†ãˆ', 'ãŠã‚')
input_keys('2P')
- assert_line('ã„ã†ãˆã„ã†ãˆã„ã†ãˆãŠãŠãŠã‚')
- assert_byte_pointer_size('ã„ã†ãˆã„ã†ãˆã„ã†ãˆ')
- assert_cursor(18)
- assert_cursor_max(26)
+ assert_line_around_cursor('ã„ã†ãˆã„ã†ãˆã„ã†ãˆ', 'ãŠãŠãŠã‚')
end
def test_vi_paste_next_for_mbchar
input_keys("ã‚ã„ã†ãˆãŠ\C-[3h")
- assert_line('ã‚ã„ã†ãˆãŠ')
- assert_byte_pointer_size('ã‚')
- assert_cursor(2)
- assert_cursor_max(10)
+ assert_line_around_cursor('ã‚', 'ã„ã†ãˆãŠ')
input_keys('p')
- assert_line('ã‚ã„ã†ãˆãŠ')
- assert_byte_pointer_size('ã‚')
- assert_cursor(2)
- assert_cursor_max(10)
+ assert_line_around_cursor('ã‚', 'ã„ã†ãˆãŠ')
input_keys('d$')
- assert_line('ã‚')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(2)
+ assert_line_around_cursor('', 'ã‚')
input_keys('p')
- assert_line('ã‚ã„ã†ãˆãŠ')
- assert_byte_pointer_size('ã‚ã„ã†ãˆ')
- assert_cursor(8)
- assert_cursor_max(10)
+ assert_line_around_cursor('ã‚ã„ã†ãˆ', 'ãŠ')
input_keys('2p')
- assert_line('ã‚ã„ã†ãˆãŠã„ã†ãˆãŠã„ã†ãˆãŠ')
- assert_byte_pointer_size('ã‚ã„ã†ãˆãŠã„ã†ãˆãŠã„ã†ãˆ')
- assert_cursor(24)
- assert_cursor_max(26)
+ assert_line_around_cursor('ã‚ã„ã†ãˆãŠã„ã†ãˆãŠã„ã†ãˆ', 'ãŠ')
end
def test_vi_paste_prev_for_mbchar_by_plural_code_points
input_keys("ã‹\u3099ã\u3099ã\u3099ã‘\u3099ã“\u3099\C-[3h")
- assert_line("ã‹\u3099ã\u3099ã\u3099ã‘\u3099ã“\u3099")
- assert_byte_pointer_size("ã‹\u3099")
- assert_cursor(2)
- assert_cursor_max(10)
+ assert_line_around_cursor("ã‹\u3099", "ã\u3099ã\u3099ã‘\u3099ã“\u3099")
input_keys('P')
- assert_line("ã‹\u3099ã\u3099ã\u3099ã‘\u3099ã“\u3099")
- assert_byte_pointer_size("ã‹\u3099")
- assert_cursor(2)
- assert_cursor_max(10)
+ assert_line_around_cursor("ã‹\u3099", "ã\u3099ã\u3099ã‘\u3099ã“\u3099")
input_keys('d$')
- assert_line("ã‹\u3099")
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(2)
+ assert_line_around_cursor('', "ã‹\u3099")
input_keys('P')
- assert_line("ã\u3099ã\u3099ã‘\u3099ã“\u3099ã‹\u3099")
- assert_byte_pointer_size("ã\u3099ã\u3099ã‘\u3099")
- assert_cursor(6)
- assert_cursor_max(10)
+ assert_line_around_cursor("ã\u3099ã\u3099ã‘\u3099", "ã“\u3099ã‹\u3099")
input_keys('2P')
- assert_line("ã\u3099ã\u3099ã‘\u3099ã\u3099ã\u3099ã‘\u3099ã\u3099ã\u3099ã‘\u3099ã“\u3099ã“\u3099ã“\u3099ã‹\u3099")
- assert_byte_pointer_size("ã\u3099ã\u3099ã‘\u3099ã\u3099ã\u3099ã‘\u3099ã\u3099ã\u3099ã‘\u3099")
- assert_cursor(18)
- assert_cursor_max(26)
+ assert_line_around_cursor("ã\u3099ã\u3099ã‘\u3099ã\u3099ã\u3099ã‘\u3099ã\u3099ã\u3099ã‘\u3099", "ã“\u3099ã“\u3099ã“\u3099ã‹\u3099")
end
def test_vi_paste_next_for_mbchar_by_plural_code_points
input_keys("ã‹\u3099ã\u3099ã\u3099ã‘\u3099ã“\u3099\C-[3h")
- assert_line("ã‹\u3099ã\u3099ã\u3099ã‘\u3099ã“\u3099")
- assert_byte_pointer_size("ã‹\u3099")
- assert_cursor(2)
- assert_cursor_max(10)
+ assert_line_around_cursor("ã‹\u3099", "ã\u3099ã\u3099ã‘\u3099ã“\u3099")
input_keys('p')
- assert_line("ã‹\u3099ã\u3099ã\u3099ã‘\u3099ã“\u3099")
- assert_byte_pointer_size("ã‹\u3099")
- assert_cursor(2)
- assert_cursor_max(10)
+ assert_line_around_cursor("ã‹\u3099", "ã\u3099ã\u3099ã‘\u3099ã“\u3099")
input_keys('d$')
- assert_line("ã‹\u3099")
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(2)
+ assert_line_around_cursor('', "ã‹\u3099")
input_keys('p')
- assert_line("ã‹\u3099ã\u3099ã\u3099ã‘\u3099ã“\u3099")
- assert_byte_pointer_size("ã‹\u3099ã\u3099ã\u3099ã‘\u3099")
- assert_cursor(8)
- assert_cursor_max(10)
+ assert_line_around_cursor("ã‹\u3099ã\u3099ã\u3099ã‘\u3099", "ã“\u3099")
input_keys('2p')
- assert_line("ã‹\u3099ã\u3099ã\u3099ã‘\u3099ã“\u3099ã\u3099ã\u3099ã‘\u3099ã“\u3099ã\u3099ã\u3099ã‘\u3099ã“\u3099")
- assert_byte_pointer_size("ã‹\u3099ã\u3099ã\u3099ã‘\u3099ã“\u3099ã\u3099ã\u3099ã‘\u3099ã“\u3099ã\u3099ã\u3099ã‘\u3099")
- assert_cursor(24)
- assert_cursor_max(26)
+ assert_line_around_cursor("ã‹\u3099ã\u3099ã\u3099ã‘\u3099ã“\u3099ã\u3099ã\u3099ã‘\u3099ã“\u3099ã\u3099ã\u3099ã‘\u3099", "ã“\u3099")
end
def test_vi_prev_next_word
input_keys("aaa b{b}b ccc\C-[0")
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(13)
+ assert_line_around_cursor('', 'aaa b{b}b ccc')
input_keys('w')
- assert_byte_pointer_size('aaa ')
- assert_cursor(4)
- assert_cursor_max(13)
+ assert_line_around_cursor('aaa ', 'b{b}b ccc')
input_keys('w')
- assert_byte_pointer_size('aaa b')
- assert_cursor(5)
- assert_cursor_max(13)
+ assert_line_around_cursor('aaa b', '{b}b ccc')
input_keys('w')
- assert_byte_pointer_size('aaa b{')
- assert_cursor(6)
- assert_cursor_max(13)
+ assert_line_around_cursor('aaa b{', 'b}b ccc')
input_keys('w')
- assert_byte_pointer_size('aaa b{b')
- assert_cursor(7)
- assert_cursor_max(13)
+ assert_line_around_cursor('aaa b{b', '}b ccc')
input_keys('w')
- assert_byte_pointer_size('aaa b{b}')
- assert_cursor(8)
- assert_cursor_max(13)
+ assert_line_around_cursor('aaa b{b}', 'b ccc')
input_keys('w')
- assert_byte_pointer_size('aaa b{b}b ')
- assert_cursor(10)
- assert_cursor_max(13)
+ assert_line_around_cursor('aaa b{b}b ', 'ccc')
input_keys('w')
- assert_byte_pointer_size('aaa b{b}b cc')
- assert_cursor(12)
- assert_cursor_max(13)
+ assert_line_around_cursor('aaa b{b}b cc', 'c')
input_keys('b')
- assert_byte_pointer_size('aaa b{b}b ')
- assert_cursor(10)
- assert_cursor_max(13)
+ assert_line_around_cursor('aaa b{b}b ', 'ccc')
input_keys('b')
- assert_byte_pointer_size('aaa b{b}')
- assert_cursor(8)
- assert_cursor_max(13)
+ assert_line_around_cursor('aaa b{b}', 'b ccc')
input_keys('b')
- assert_byte_pointer_size('aaa b{b')
- assert_cursor(7)
- assert_cursor_max(13)
+ assert_line_around_cursor('aaa b{b', '}b ccc')
input_keys('b')
- assert_byte_pointer_size('aaa b{')
- assert_cursor(6)
- assert_cursor_max(13)
+ assert_line_around_cursor('aaa b{', 'b}b ccc')
input_keys('b')
- assert_byte_pointer_size('aaa b')
- assert_cursor(5)
- assert_cursor_max(13)
+ assert_line_around_cursor('aaa b', '{b}b ccc')
input_keys('b')
- assert_byte_pointer_size('aaa ')
- assert_cursor(4)
- assert_cursor_max(13)
+ assert_line_around_cursor('aaa ', 'b{b}b ccc')
input_keys('b')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(13)
+ assert_line_around_cursor('', 'aaa b{b}b ccc')
input_keys('3w')
- assert_byte_pointer_size('aaa b{')
- assert_cursor(6)
- assert_cursor_max(13)
+ assert_line_around_cursor('aaa b{', 'b}b ccc')
input_keys('3w')
- assert_byte_pointer_size('aaa b{b}b ')
- assert_cursor(10)
- assert_cursor_max(13)
+ assert_line_around_cursor('aaa b{b}b ', 'ccc')
input_keys('3w')
- assert_byte_pointer_size('aaa b{b}b cc')
- assert_cursor(12)
- assert_cursor_max(13)
+ assert_line_around_cursor('aaa b{b}b cc', 'c')
input_keys('3b')
- assert_byte_pointer_size('aaa b{b')
- assert_cursor(7)
- assert_cursor_max(13)
+ assert_line_around_cursor('aaa b{b', '}b ccc')
input_keys('3b')
- assert_byte_pointer_size('aaa ')
- assert_cursor(4)
- assert_cursor_max(13)
+ assert_line_around_cursor('aaa ', 'b{b}b ccc')
input_keys('3b')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(13)
+ assert_line_around_cursor('', 'aaa b{b}b ccc')
end
def test_vi_end_word
input_keys("aaa b{b}}}b ccc\C-[0")
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(19)
+ assert_line_around_cursor('', 'aaa b{b}}}b ccc')
input_keys('e')
- assert_byte_pointer_size('aa')
- assert_cursor(2)
- assert_cursor_max(19)
+ assert_line_around_cursor('aa', 'a b{b}}}b ccc')
input_keys('e')
- assert_byte_pointer_size('aaa ')
- assert_cursor(6)
- assert_cursor_max(19)
+ assert_line_around_cursor('aaa ', 'b{b}}}b ccc')
input_keys('e')
- assert_byte_pointer_size('aaa b')
- assert_cursor(7)
- assert_cursor_max(19)
+ assert_line_around_cursor('aaa b', '{b}}}b ccc')
input_keys('e')
- assert_byte_pointer_size('aaa b{')
- assert_cursor(8)
- assert_cursor_max(19)
+ assert_line_around_cursor('aaa b{', 'b}}}b ccc')
input_keys('e')
- assert_byte_pointer_size('aaa b{b}}')
- assert_cursor(11)
- assert_cursor_max(19)
+ assert_line_around_cursor('aaa b{b}}', '}b ccc')
input_keys('e')
- assert_byte_pointer_size('aaa b{b}}}')
- assert_cursor(12)
- assert_cursor_max(19)
+ assert_line_around_cursor('aaa b{b}}}', 'b ccc')
input_keys('e')
- assert_byte_pointer_size('aaa b{b}}}b cc')
- assert_cursor(18)
- assert_cursor_max(19)
+ assert_line_around_cursor('aaa b{b}}}b cc', 'c')
input_keys('e')
- assert_byte_pointer_size('aaa b{b}}}b cc')
- assert_cursor(18)
- assert_cursor_max(19)
+ assert_line_around_cursor('aaa b{b}}}b cc', 'c')
input_keys('03e')
- assert_byte_pointer_size('aaa b')
- assert_cursor(7)
- assert_cursor_max(19)
+ assert_line_around_cursor('aaa b', '{b}}}b ccc')
input_keys('3e')
- assert_byte_pointer_size('aaa b{b}}}')
- assert_cursor(12)
- assert_cursor_max(19)
+ assert_line_around_cursor('aaa b{b}}}', 'b ccc')
input_keys('3e')
- assert_byte_pointer_size('aaa b{b}}}b cc')
- assert_cursor(18)
- assert_cursor_max(19)
+ assert_line_around_cursor('aaa b{b}}}b cc', 'c')
end
def test_vi_prev_next_big_word
input_keys("aaa b{b}b ccc\C-[0")
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(13)
+ assert_line_around_cursor('', 'aaa b{b}b ccc')
input_keys('W')
- assert_byte_pointer_size('aaa ')
- assert_cursor(4)
- assert_cursor_max(13)
+ assert_line_around_cursor('aaa ', 'b{b}b ccc')
input_keys('W')
- assert_byte_pointer_size('aaa b{b}b ')
- assert_cursor(10)
- assert_cursor_max(13)
+ assert_line_around_cursor('aaa b{b}b ', 'ccc')
input_keys('W')
- assert_byte_pointer_size('aaa b{b}b cc')
- assert_cursor(12)
- assert_cursor_max(13)
+ assert_line_around_cursor('aaa b{b}b cc', 'c')
input_keys('B')
- assert_byte_pointer_size('aaa b{b}b ')
- assert_cursor(10)
- assert_cursor_max(13)
+ assert_line_around_cursor('aaa b{b}b ', 'ccc')
input_keys('B')
- assert_byte_pointer_size('aaa ')
- assert_cursor(4)
- assert_cursor_max(13)
+ assert_line_around_cursor('aaa ', 'b{b}b ccc')
input_keys('B')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(13)
+ assert_line_around_cursor('', 'aaa b{b}b ccc')
input_keys('2W')
- assert_byte_pointer_size('aaa b{b}b ')
- assert_cursor(10)
- assert_cursor_max(13)
+ assert_line_around_cursor('aaa b{b}b ', 'ccc')
input_keys('2W')
- assert_byte_pointer_size('aaa b{b}b cc')
- assert_cursor(12)
- assert_cursor_max(13)
+ assert_line_around_cursor('aaa b{b}b cc', 'c')
input_keys('2B')
- assert_byte_pointer_size('aaa ')
- assert_cursor(4)
- assert_cursor_max(13)
+ assert_line_around_cursor('aaa ', 'b{b}b ccc')
input_keys('2B')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(13)
+ assert_line_around_cursor('', 'aaa b{b}b ccc')
end
def test_vi_end_big_word
input_keys("aaa b{b}}}b ccc\C-[0")
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(19)
+ assert_line_around_cursor('', 'aaa b{b}}}b ccc')
input_keys('E')
- assert_byte_pointer_size('aa')
- assert_cursor(2)
- assert_cursor_max(19)
+ assert_line_around_cursor('aa', 'a b{b}}}b ccc')
input_keys('E')
- assert_byte_pointer_size('aaa b{b}}}')
- assert_cursor(12)
- assert_cursor_max(19)
+ assert_line_around_cursor('aaa b{b}}}', 'b ccc')
input_keys('E')
- assert_byte_pointer_size('aaa b{b}}}b cc')
- assert_cursor(18)
- assert_cursor_max(19)
+ assert_line_around_cursor('aaa b{b}}}b cc', 'c')
input_keys('E')
- assert_byte_pointer_size('aaa b{b}}}b cc')
- assert_cursor(18)
- assert_cursor_max(19)
+ assert_line_around_cursor('aaa b{b}}}b cc', 'c')
end
def test_ed_quoted_insert
input_keys("ab\C-v\C-acd")
- assert_line("ab\C-acd")
- assert_byte_pointer_size("ab\C-acd")
- assert_cursor(6)
- assert_cursor_max(6)
+ assert_line_around_cursor("ab\C-acd", '')
end
def test_ed_quoted_insert_with_vi_arg
input_keys("ab\C-[3\C-v\C-aacd")
- assert_line("a\C-a\C-a\C-abcd")
- assert_byte_pointer_size("a\C-a\C-a\C-abcd")
- assert_cursor(10)
- assert_cursor_max(10)
+ assert_line_around_cursor("a\C-a\C-a\C-abcd", '')
end
def test_vi_replace_char
input_keys("abcdef\C-[03l")
- assert_line('abcdef')
- assert_byte_pointer_size('abc')
- assert_cursor(3)
- assert_cursor_max(6)
+ assert_line_around_cursor('abc', 'def')
input_keys('rz')
- assert_line('abczef')
- assert_byte_pointer_size('abc')
- assert_cursor(3)
- assert_cursor_max(6)
+ assert_line_around_cursor('abc', 'zef')
input_keys('2rx')
- assert_line('abcxxf')
- assert_byte_pointer_size('abcxx')
- assert_cursor(5)
- assert_cursor_max(6)
+ assert_line_around_cursor('abcxx', 'f')
end
def test_vi_replace_char_with_mbchar
input_keys("ã‚ã„ã†ãˆãŠ\C-[0l")
- assert_line('ã‚ã„ã†ãˆãŠ')
- assert_byte_pointer_size('ã‚')
- assert_cursor(2)
- assert_cursor_max(10)
+ assert_line_around_cursor('ã‚', 'ã„ã†ãˆãŠ')
input_keys('rx')
- assert_line('ã‚xã†ãˆãŠ')
- assert_byte_pointer_size('ã‚')
- assert_cursor(2)
- assert_cursor_max(9)
+ assert_line_around_cursor('ã‚', 'xã†ãˆãŠ')
input_keys('l2ry')
- assert_line('ã‚xyyãŠ')
- assert_byte_pointer_size('ã‚xyy')
- assert_cursor(5)
- assert_cursor_max(7)
+ assert_line_around_cursor('ã‚xyy', 'ãŠ')
end
def test_vi_next_char
input_keys("abcdef\C-[0")
- assert_line('abcdef')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(6)
+ assert_line_around_cursor('', 'abcdef')
input_keys('fz')
- assert_line('abcdef')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(6)
+ assert_line_around_cursor('', 'abcdef')
input_keys('fe')
- assert_line('abcdef')
- assert_byte_pointer_size('abcd')
- assert_cursor(4)
- assert_cursor_max(6)
+ assert_line_around_cursor('abcd', 'ef')
end
def test_vi_to_next_char
input_keys("abcdef\C-[0")
- assert_line('abcdef')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(6)
+ assert_line_around_cursor('', 'abcdef')
input_keys('tz')
- assert_line('abcdef')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(6)
+ assert_line_around_cursor('', 'abcdef')
input_keys('te')
- assert_line('abcdef')
- assert_byte_pointer_size('abc')
- assert_cursor(3)
- assert_cursor_max(6)
+ assert_line_around_cursor('abc', 'def')
end
def test_vi_prev_char
input_keys("abcdef\C-[")
- assert_line('abcdef')
- assert_byte_pointer_size('abcde')
- assert_cursor(5)
- assert_cursor_max(6)
+ assert_line_around_cursor('abcde', 'f')
input_keys('Fz')
- assert_line('abcdef')
- assert_byte_pointer_size('abcde')
- assert_cursor(5)
- assert_cursor_max(6)
+ assert_line_around_cursor('abcde', 'f')
input_keys('Fa')
- assert_line('abcdef')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(6)
+ assert_line_around_cursor('', 'abcdef')
end
def test_vi_to_prev_char
input_keys("abcdef\C-[")
- assert_line('abcdef')
- assert_byte_pointer_size('abcde')
- assert_cursor(5)
- assert_cursor_max(6)
+ assert_line_around_cursor('abcde', 'f')
input_keys('Tz')
- assert_line('abcdef')
- assert_byte_pointer_size('abcde')
- assert_cursor(5)
- assert_cursor_max(6)
+ assert_line_around_cursor('abcde', 'f')
input_keys('Ta')
- assert_line('abcdef')
- assert_byte_pointer_size('a')
- assert_cursor(1)
- assert_cursor_max(6)
+ assert_line_around_cursor('a', 'bcdef')
end
def test_vi_delete_next_char
input_keys("abc\C-[h")
- assert_byte_pointer_size('a')
- assert_cursor(1)
- assert_cursor_max(3)
- assert_line('abc')
+ assert_line_around_cursor('a', 'bc')
input_keys('x')
- assert_byte_pointer_size('a')
- assert_cursor(1)
- assert_cursor_max(2)
- assert_line('ac')
+ assert_line_around_cursor('a', 'c')
input_keys('x')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(1)
- assert_line('a')
+ assert_line_around_cursor('', 'a')
input_keys('x')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
- assert_line('')
+ assert_line_around_cursor('', '')
input_keys('x')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
- assert_line('')
+ assert_line_around_cursor('', '')
end
def test_vi_delete_next_char_for_mbchar
input_keys("ã‚ã„ã†\C-[h")
- assert_byte_pointer_size('ã‚')
- assert_cursor(2)
- assert_cursor_max(6)
- assert_line('ã‚ã„ã†')
+ assert_line_around_cursor('ã‚', 'ã„ã†')
input_keys('x')
- assert_byte_pointer_size('ã‚')
- assert_cursor(2)
- assert_cursor_max(4)
- assert_line('ã‚ã†')
+ assert_line_around_cursor('ã‚', 'ã†')
input_keys('x')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(2)
- assert_line('ã‚')
+ assert_line_around_cursor('', 'ã‚')
input_keys('x')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
- assert_line('')
+ assert_line_around_cursor('', '')
input_keys('x')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
- assert_line('')
+ assert_line_around_cursor('', '')
end
def test_vi_delete_next_char_for_mbchar_by_plural_code_points
input_keys("ã‹\u3099ã\u3099ã\u3099\C-[h")
- assert_byte_pointer_size("ã‹\u3099")
- assert_cursor(2)
- assert_cursor_max(6)
- assert_line("ã‹\u3099ã\u3099ã\u3099")
+ assert_line_around_cursor("ã‹\u3099", "ã\u3099ã\u3099")
input_keys('x')
- assert_byte_pointer_size("ã‹\u3099")
- assert_cursor(2)
- assert_cursor_max(4)
- assert_line("ã‹\u3099ã\u3099")
+ assert_line_around_cursor("ã‹\u3099", "ã\u3099")
input_keys('x')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(2)
- assert_line("ã‹\u3099")
+ assert_line_around_cursor('', "ã‹\u3099")
input_keys('x')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
- assert_line('')
+ assert_line_around_cursor('', '')
input_keys('x')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
- assert_line('')
+ assert_line_around_cursor('', '')
end
def test_vi_delete_prev_char
input_keys('ab')
- assert_byte_pointer_size('ab')
- assert_cursor(2)
- assert_cursor_max(2)
+ assert_line_around_cursor('ab', '')
input_keys("\C-h")
- assert_byte_pointer_size('a')
- assert_cursor(1)
- assert_cursor_max(1)
- assert_line('a')
+ assert_line_around_cursor('a', '')
end
def test_vi_delete_prev_char_for_mbchar
input_keys('ã‹ã')
- assert_byte_pointer_size('ã‹ã')
- assert_cursor(4)
- assert_cursor_max(4)
+ assert_line_around_cursor('ã‹ã', '')
input_keys("\C-h")
- assert_byte_pointer_size('ã‹')
- assert_cursor(2)
- assert_cursor_max(2)
- assert_line('ã‹')
+ assert_line_around_cursor('ã‹', '')
end
def test_vi_delete_prev_char_for_mbchar_by_plural_code_points
input_keys("ã‹\u3099ã\u3099")
- assert_byte_pointer_size("ã‹\u3099ã\u3099")
- assert_cursor(4)
- assert_cursor_max(4)
+ assert_line_around_cursor("ã‹\u3099ã\u3099", '')
input_keys("\C-h")
- assert_byte_pointer_size("ã‹\u3099")
- assert_cursor(2)
- assert_cursor_max(2)
- assert_line("ã‹\u3099")
+ assert_line_around_cursor("ã‹\u3099", '')
end
def test_ed_delete_prev_char
input_keys("abcdefg\C-[h")
- assert_byte_pointer_size('abcde')
- assert_cursor(5)
- assert_cursor_max(7)
- assert_line('abcdefg')
+ assert_line_around_cursor('abcde', 'fg')
input_keys('X')
- assert_byte_pointer_size('abcd')
- assert_cursor(4)
- assert_cursor_max(6)
- assert_line('abcdfg')
+ assert_line_around_cursor('abcd', 'fg')
input_keys('3X')
- assert_byte_pointer_size('a')
- assert_cursor(1)
- assert_cursor_max(3)
- assert_line('afg')
+ assert_line_around_cursor('a', 'fg')
input_keys('p')
- assert_byte_pointer_size('abcd')
- assert_cursor(4)
- assert_cursor_max(6)
- assert_line('afbcdg')
+ assert_line_around_cursor('afbc', 'dg')
end
def test_ed_delete_prev_word
input_keys('abc def{bbb}ccc')
- assert_byte_pointer_size('abc def{bbb}ccc')
- assert_cursor(15)
- assert_cursor_max(15)
+ assert_line_around_cursor('abc def{bbb}ccc', '')
input_keys("\C-w")
- assert_byte_pointer_size('abc def{bbb}')
- assert_cursor(12)
- assert_cursor_max(12)
- assert_line('abc def{bbb}')
+ assert_line_around_cursor('abc def{bbb}', '')
input_keys("\C-w")
- assert_byte_pointer_size('abc def{')
- assert_cursor(8)
- assert_cursor_max(8)
- assert_line('abc def{')
+ assert_line_around_cursor('abc def{', '')
input_keys("\C-w")
- assert_byte_pointer_size('abc ')
- assert_cursor(4)
- assert_cursor_max(4)
- assert_line('abc ')
+ assert_line_around_cursor('abc ', '')
input_keys("\C-w")
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
- assert_line('')
+ assert_line_around_cursor('', '')
end
def test_ed_delete_prev_word_for_mbchar
input_keys('ã‚ã„ㆠã‹ãã{ã•ã—ã™}ãŸã¡ã¤')
- assert_byte_pointer_size('ã‚ã„ㆠã‹ãã{ã•ã—ã™}ãŸã¡ã¤')
- assert_cursor(27)
- assert_cursor_max(27)
+ assert_line_around_cursor('ã‚ã„ㆠã‹ãã{ã•ã—ã™}ãŸã¡ã¤', '')
input_keys("\C-w")
- assert_byte_pointer_size('ã‚ã„ㆠã‹ãã{ã•ã—ã™}')
- assert_cursor(21)
- assert_cursor_max(21)
- assert_line('ã‚ã„ㆠã‹ãã{ã•ã—ã™}')
+ assert_line_around_cursor('ã‚ã„ㆠã‹ãã{ã•ã—ã™}', '')
input_keys("\C-w")
- assert_byte_pointer_size('ã‚ã„ㆠã‹ãã{')
- assert_cursor(14)
- assert_cursor_max(14)
- assert_line('ã‚ã„ㆠã‹ãã{')
+ assert_line_around_cursor('ã‚ã„ㆠã‹ãã{', '')
input_keys("\C-w")
- assert_byte_pointer_size('ã‚ã„ㆠ')
- assert_cursor(7)
- assert_cursor_max(7)
- assert_line('ã‚ã„ㆠ')
+ assert_line_around_cursor('ã‚ã„ㆠ', '')
input_keys("\C-w")
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
- assert_line('')
+ assert_line_around_cursor('', '')
end
def test_ed_delete_prev_word_for_mbchar_by_plural_code_points
input_keys("ã‚ã„ㆠã‹\u3099ã\u3099ã\u3099{ã•ã—ã™}ãŸã¡ã¤")
- assert_byte_pointer_size("ã‚ã„ㆠã‹\u3099ã\u3099ã\u3099{ã•ã—ã™}ãŸã¡ã¤")
- assert_cursor(27)
- assert_cursor_max(27)
+ assert_line_around_cursor("ã‚ã„ㆠã‹\u3099ã\u3099ã\u3099{ã•ã—ã™}ãŸã¡ã¤", '')
input_keys("\C-w")
- assert_byte_pointer_size("ã‚ã„ㆠã‹\u3099ã\u3099ã\u3099{ã•ã—ã™}")
- assert_cursor(21)
- assert_cursor_max(21)
- assert_line("ã‚ã„ㆠã‹\u3099ã\u3099ã\u3099{ã•ã—ã™}")
+ assert_line_around_cursor("ã‚ã„ㆠã‹\u3099ã\u3099ã\u3099{ã•ã—ã™}", '')
input_keys("\C-w")
- assert_byte_pointer_size("ã‚ã„ㆠã‹\u3099ã\u3099ã\u3099{")
- assert_cursor(14)
- assert_cursor_max(14)
- assert_line("ã‚ã„ㆠã‹\u3099ã\u3099ã\u3099{")
+ assert_line_around_cursor("ã‚ã„ㆠã‹\u3099ã\u3099ã\u3099{", '')
input_keys("\C-w")
- assert_byte_pointer_size('ã‚ã„ㆠ')
- assert_cursor(7)
- assert_cursor_max(7)
- assert_line('ã‚ã„ㆠ')
+ assert_line_around_cursor('ã‚ã„ㆠ', '')
input_keys("\C-w")
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
- assert_line('')
+ assert_line_around_cursor('', '')
end
def test_ed_newline_with_cr
input_keys('ab')
- assert_byte_pointer_size('ab')
- assert_cursor(2)
- assert_cursor_max(2)
+ assert_line_around_cursor('ab', '')
refute(@line_editor.finished?)
input_keys("\C-m")
- assert_line('ab')
+ assert_line_around_cursor('ab', '')
assert(@line_editor.finished?)
end
def test_ed_newline_with_lf
input_keys('ab')
- assert_byte_pointer_size('ab')
- assert_cursor(2)
- assert_cursor_max(2)
+ assert_line_around_cursor('ab', '')
refute(@line_editor.finished?)
input_keys("\C-j")
- assert_line('ab')
+ assert_line_around_cursor('ab', '')
assert(@line_editor.finished?)
end
def test_vi_list_or_eof
input_keys("\C-d") # quit from inputing
- assert_line(nil)
+ assert_nil(@line_editor.line)
assert(@line_editor.finished?)
end
def test_vi_list_or_eof_with_non_empty_line
input_keys('ab')
- assert_byte_pointer_size('ab')
- assert_cursor(2)
- assert_cursor_max(2)
+ assert_line_around_cursor('ab', '')
refute(@line_editor.finished?)
input_keys("\C-d")
- assert_line('ab')
+ assert_line_around_cursor('ab', '')
assert(@line_editor.finished?)
end
@@ -982,40 +549,19 @@ class Reline::KeyActor::ViInsert::Test < Reline::TestCase
}
}
input_keys('foo')
- assert_byte_pointer_size('foo')
- assert_cursor(3)
- assert_cursor_max(3)
- assert_line('foo')
+ assert_line_around_cursor('foo', '')
input_keys("\C-n")
- assert_byte_pointer_size('foo_bar')
- assert_cursor(7)
- assert_cursor_max(7)
- assert_line('foo_bar')
+ assert_line_around_cursor('foo_bar', '')
input_keys("\C-n")
- assert_byte_pointer_size('foo_bar_baz')
- assert_cursor(11)
- assert_cursor_max(11)
- assert_line('foo_bar_baz')
+ assert_line_around_cursor('foo_bar_baz', '')
input_keys("\C-n")
- assert_byte_pointer_size('foo')
- assert_cursor(3)
- assert_cursor_max(3)
- assert_line('foo')
+ assert_line_around_cursor('foo', '')
input_keys("\C-n")
- assert_byte_pointer_size('foo_bar')
- assert_cursor(7)
- assert_cursor_max(7)
- assert_line('foo_bar')
+ assert_line_around_cursor('foo_bar', '')
input_keys("_\C-n")
- assert_byte_pointer_size('foo_bar_baz')
- assert_cursor(11)
- assert_cursor_max(11)
- assert_line('foo_bar_baz')
+ assert_line_around_cursor('foo_bar_baz', '')
input_keys("\C-n")
- assert_byte_pointer_size('foo_bar_')
- assert_cursor(8)
- assert_cursor_max(8)
- assert_line('foo_bar_')
+ assert_line_around_cursor('foo_bar_', '')
end
def test_completion_journey_reverse
@@ -1028,40 +574,19 @@ class Reline::KeyActor::ViInsert::Test < Reline::TestCase
}
}
input_keys('foo')
- assert_byte_pointer_size('foo')
- assert_cursor(3)
- assert_cursor_max(3)
- assert_line('foo')
+ assert_line_around_cursor('foo', '')
input_keys("\C-p")
- assert_byte_pointer_size('foo_bar_baz')
- assert_cursor(11)
- assert_cursor_max(11)
- assert_line('foo_bar_baz')
+ assert_line_around_cursor('foo_bar_baz', '')
input_keys("\C-p")
- assert_byte_pointer_size('foo_bar')
- assert_cursor(7)
- assert_cursor_max(7)
- assert_line('foo_bar')
+ assert_line_around_cursor('foo_bar', '')
input_keys("\C-p")
- assert_byte_pointer_size('foo')
- assert_cursor(3)
- assert_cursor_max(3)
- assert_line('foo')
+ assert_line_around_cursor('foo', '')
input_keys("\C-p")
- assert_byte_pointer_size('foo_bar_baz')
- assert_cursor(11)
- assert_cursor_max(11)
- assert_line('foo_bar_baz')
+ assert_line_around_cursor('foo_bar_baz', '')
input_keys("\C-h\C-p")
- assert_byte_pointer_size('foo_bar_baz')
- assert_cursor(11)
- assert_cursor_max(11)
- assert_line('foo_bar_baz')
+ assert_line_around_cursor('foo_bar_baz', '')
input_keys("\C-p")
- assert_byte_pointer_size('foo_bar_ba')
- assert_cursor(10)
- assert_cursor_max(10)
- assert_line('foo_bar_ba')
+ assert_line_around_cursor('foo_bar_ba', '')
end
def test_completion_journey_in_middle_of_line
@@ -1074,42 +599,21 @@ class Reline::KeyActor::ViInsert::Test < Reline::TestCase
}
}
input_keys('abcde fo ABCDE')
- assert_line('abcde fo ABCDE')
+ assert_line_around_cursor('abcde fo ABCDE', '')
input_keys("\C-[" + 'h' * 5 + "i\C-n")
- assert_byte_pointer_size('abcde foo_bar')
- assert_cursor(13)
- assert_cursor_max(19)
- assert_line('abcde foo_bar ABCDE')
+ assert_line_around_cursor('abcde foo_bar', ' ABCDE')
input_keys("\C-n")
- assert_byte_pointer_size('abcde foo_bar_baz')
- assert_cursor(17)
- assert_cursor_max(23)
- assert_line('abcde foo_bar_baz ABCDE')
+ assert_line_around_cursor('abcde foo_bar_baz', ' ABCDE')
input_keys("\C-n")
- assert_byte_pointer_size('abcde fo')
- assert_cursor(8)
- assert_cursor_max(14)
- assert_line('abcde fo ABCDE')
+ assert_line_around_cursor('abcde fo', ' ABCDE')
input_keys("\C-n")
- assert_byte_pointer_size('abcde foo_bar')
- assert_cursor(13)
- assert_cursor_max(19)
- assert_line('abcde foo_bar ABCDE')
+ assert_line_around_cursor('abcde foo_bar', ' ABCDE')
input_keys("_\C-n")
- assert_byte_pointer_size('abcde foo_bar_baz')
- assert_cursor(17)
- assert_cursor_max(23)
- assert_line('abcde foo_bar_baz ABCDE')
+ assert_line_around_cursor('abcde foo_bar_baz', ' ABCDE')
input_keys("\C-n")
- assert_byte_pointer_size('abcde foo_bar_')
- assert_cursor(14)
- assert_cursor_max(20)
- assert_line('abcde foo_bar_ ABCDE')
+ assert_line_around_cursor('abcde foo_bar_', ' ABCDE')
input_keys("\C-n")
- assert_byte_pointer_size('abcde foo_bar_baz')
- assert_cursor(17)
- assert_cursor_max(23)
- assert_line('abcde foo_bar_baz ABCDE')
+ assert_line_around_cursor('abcde foo_bar_baz', ' ABCDE')
end
def test_completion
@@ -1122,15 +626,55 @@ class Reline::KeyActor::ViInsert::Test < Reline::TestCase
}
}
input_keys('foo')
- assert_byte_pointer_size('foo')
- assert_cursor(3)
- assert_cursor_max(3)
- assert_line('foo')
+ assert_line_around_cursor('foo', '')
input_keys("\C-i")
- assert_byte_pointer_size('foo_bar')
- assert_cursor(7)
- assert_cursor_max(7)
- assert_line('foo_bar')
+ assert_line_around_cursor('foo_bar', '')
+ end
+
+ def test_autocompletion_with_upward_navigation
+ @config.autocompletion = true
+ @line_editor.completion_proc = proc { |word|
+ %w{
+ Readline
+ Regexp
+ RegexpError
+ }.map { |i|
+ i.encode(@encoding)
+ }
+ }
+ input_keys('Re')
+ assert_line_around_cursor('Re', '')
+ input_keys("\C-i", false)
+ assert_line_around_cursor('Readline', '')
+ input_keys("\C-i", false)
+ assert_line_around_cursor('Regexp', '')
+ @line_editor.input_key(Reline::Key.new(:completion_journey_up, :completion_journey_up, false))
+ assert_line_around_cursor('Readline', '')
+ ensure
+ @config.autocompletion = false
+ end
+
+ def test_autocompletion_with_upward_navigation_and_menu_complete_backward
+ @config.autocompletion = true
+ @line_editor.completion_proc = proc { |word|
+ %w{
+ Readline
+ Regexp
+ RegexpError
+ }.map { |i|
+ i.encode(@encoding)
+ }
+ }
+ input_keys('Re')
+ assert_line_around_cursor('Re', '')
+ input_keys("\C-i", false)
+ assert_line_around_cursor('Readline', '')
+ input_keys("\C-i", false)
+ assert_line_around_cursor('Regexp', '')
+ @line_editor.input_key(Reline::Key.new(:menu_complete_backward, :menu_complete_backward, false))
+ assert_line_around_cursor('Readline', '')
+ ensure
+ @config.autocompletion = false
end
def test_completion_with_disable_completion
@@ -1144,286 +688,250 @@ class Reline::KeyActor::ViInsert::Test < Reline::TestCase
}
}
input_keys('foo')
- assert_byte_pointer_size('foo')
- assert_cursor(3)
- assert_cursor_max(3)
- assert_line('foo')
+ assert_line_around_cursor('foo', '')
input_keys("\C-i")
- assert_byte_pointer_size('foo')
- assert_cursor(3)
- assert_cursor_max(3)
- assert_line('foo')
+ assert_line_around_cursor('foo', '')
end
def test_vi_first_print
input_keys("abcde\C-[^")
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(5)
+ assert_line_around_cursor('', 'abcde')
input_keys("0\C-ki")
input_keys(" abcde\C-[^")
- assert_byte_pointer_size(' ')
- assert_cursor(1)
- assert_cursor_max(6)
+ assert_line_around_cursor(' ', 'abcde')
input_keys("0\C-ki")
input_keys(" abcde ABCDE \C-[^")
- assert_byte_pointer_size(' ')
- assert_cursor(3)
- assert_cursor_max(17)
+ assert_line_around_cursor(' ', 'abcde ABCDE ')
end
def test_ed_move_to_beg
input_keys("abcde\C-[0")
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(5)
+ assert_line_around_cursor('', 'abcde')
input_keys("0\C-ki")
input_keys(" abcde\C-[0")
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(6)
+ assert_line_around_cursor('', ' abcde')
input_keys("0\C-ki")
input_keys(" abcde ABCDE \C-[0")
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(17)
+ assert_line_around_cursor('', ' abcde ABCDE ')
+ end
+
+ def test_vi_to_column
+ input_keys("a一二三\C-[0")
+ input_keys('1|')
+ assert_line_around_cursor('', 'a一二三')
+ input_keys('2|')
+ assert_line_around_cursor('a', '一二三')
+ input_keys('3|')
+ assert_line_around_cursor('a', '一二三')
+ input_keys('4|')
+ assert_line_around_cursor('a一', '二三')
+ input_keys('9|')
+ assert_line_around_cursor('a一二', '三')
end
def test_vi_delete_meta
input_keys("aaa bbb ccc ddd eee\C-[02w")
- assert_byte_pointer_size('aaa bbb ')
- assert_cursor(8)
- assert_cursor_max(19)
- assert_line('aaa bbb ccc ddd eee')
+ assert_line_around_cursor('aaa bbb ', 'ccc ddd eee')
input_keys('dw')
- assert_byte_pointer_size('aaa bbb ')
- assert_cursor(8)
- assert_cursor_max(15)
- assert_line('aaa bbb ddd eee')
+ assert_line_around_cursor('aaa bbb ', 'ddd eee')
input_keys('db')
- assert_byte_pointer_size('aaa ')
- assert_cursor(4)
- assert_cursor_max(11)
- assert_line('aaa ddd eee')
+ assert_line_around_cursor('aaa ', 'ddd eee')
+ end
+
+ def test_vi_delete_meta_nothing
+ input_keys("foo\C-[0")
+ assert_line_around_cursor('', 'foo')
+ input_keys('dhp')
+ assert_line_around_cursor('', 'foo')
end
def test_vi_delete_meta_with_vi_next_word_at_eol
input_keys("foo bar\C-[0w")
- assert_byte_pointer_size('foo ')
- assert_cursor(4)
- assert_cursor_max(7)
- assert_line('foo bar')
+ assert_line_around_cursor('foo ', 'bar')
input_keys('w')
- assert_byte_pointer_size('foo ba')
- assert_cursor(6)
- assert_cursor_max(7)
- assert_line('foo bar')
+ assert_line_around_cursor('foo ba', 'r')
input_keys('0dw')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(3)
- assert_line('bar')
+ assert_line_around_cursor('', 'bar')
input_keys('dw')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
- assert_line('')
+ assert_line_around_cursor('', '')
end
def test_vi_delete_meta_with_vi_next_char
input_keys("aaa bbb ccc ___ ddd\C-[02w")
- assert_byte_pointer_size('aaa bbb ')
- assert_cursor(8)
- assert_cursor_max(19)
- assert_line('aaa bbb ccc ___ ddd')
+ assert_line_around_cursor('aaa bbb ', 'ccc ___ ddd')
input_keys('df_')
- assert_byte_pointer_size('aaa bbb ')
- assert_cursor(8)
- assert_cursor_max(14)
- assert_line('aaa bbb __ ddd')
+ assert_line_around_cursor('aaa bbb ', '__ ddd')
end
def test_vi_delete_meta_with_arg
- input_keys("aaa bbb ccc\C-[02w")
- assert_byte_pointer_size('aaa bbb ')
- assert_cursor(8)
- assert_cursor_max(11)
- assert_line('aaa bbb ccc')
+ input_keys("aaa bbb ccc ddd\C-[03w")
+ assert_line_around_cursor('aaa bbb ccc ', 'ddd')
input_keys('2dl')
- assert_byte_pointer_size('aaa bbb ')
- assert_cursor(8)
- assert_cursor_max(9)
- assert_line('aaa bbb c')
+ assert_line_around_cursor('aaa bbb ccc ', 'd')
+ input_keys('d2h')
+ assert_line_around_cursor('aaa bbb cc', 'd')
+ input_keys('2d3h')
+ assert_line_around_cursor('aaa ', 'd')
+ input_keys('dd')
+ assert_line_around_cursor('', '')
end
def test_vi_change_meta
input_keys("aaa bbb ccc ddd eee\C-[02w")
- assert_byte_pointer_size('aaa bbb ')
- assert_cursor(8)
- assert_cursor_max(19)
- assert_line('aaa bbb ccc ddd eee')
+ assert_line_around_cursor('aaa bbb ', 'ccc ddd eee')
input_keys('cwaiueo')
- assert_byte_pointer_size('aaa bbb aiueo')
- assert_cursor(13)
- assert_cursor_max(21)
- assert_line('aaa bbb aiueo ddd eee')
+ assert_line_around_cursor('aaa bbb aiueo', ' ddd eee')
input_keys("\C-[")
- assert_byte_pointer_size('aaa bbb aiue')
- assert_cursor(12)
- assert_cursor_max(21)
- assert_line('aaa bbb aiueo ddd eee')
+ assert_line_around_cursor('aaa bbb aiue', 'o ddd eee')
input_keys('cb')
- assert_byte_pointer_size('aaa bbb ')
- assert_cursor(8)
- assert_cursor_max(17)
- assert_line('aaa bbb o ddd eee')
+ assert_line_around_cursor('aaa bbb ', 'o ddd eee')
end
def test_vi_change_meta_with_vi_next_word
input_keys("foo bar baz\C-[0w")
- assert_byte_pointer_size('foo ')
- assert_cursor(5)
- assert_cursor_max(13)
- assert_line('foo bar baz')
+ assert_line_around_cursor('foo ', 'bar baz')
input_keys('cwhoge')
- assert_byte_pointer_size('foo hoge')
- assert_cursor(9)
- assert_cursor_max(14)
- assert_line('foo hoge baz')
+ assert_line_around_cursor('foo hoge', ' baz')
input_keys("\C-[")
- assert_byte_pointer_size('foo hog')
- assert_cursor(8)
- assert_cursor_max(14)
- assert_line('foo hoge baz')
+ assert_line_around_cursor('foo hog', 'e baz')
+ end
+
+ def test_vi_waiting_operator_with_waiting_proc
+ input_keys("foo foo foo foo foo\C-[0")
+ input_keys('2d3fo')
+ assert_line_around_cursor('', ' foo foo')
+ input_keys('fo')
+ assert_line_around_cursor(' f', 'oo foo')
+ end
+
+ def test_vi_waiting_operator_cancel
+ input_keys("aaa bbb ccc\C-[02w")
+ assert_line_around_cursor('aaa bbb ', 'ccc')
+ # dc dy should cancel delete_meta
+ input_keys('dch')
+ input_keys('dyh')
+ # cd cy should cancel change_meta
+ input_keys('cdh')
+ input_keys('cyh')
+ # yd yc should cancel yank_meta
+ # P should not paste yanked text because yank_meta is canceled
+ input_keys('ydhP')
+ input_keys('ychP')
+ assert_line_around_cursor('aa', 'a bbb ccc')
+ end
+
+ def test_cancel_waiting_with_symbol_key
+ input_keys("aaa bbb lll\C-[0")
+ assert_line_around_cursor('', 'aaa bbb lll')
+ # ed_next_char should move cursor right and cancel vi_next_char
+ input_keys('f')
+ input_key_by_symbol(:ed_next_char)
+ input_keys('l')
+ assert_line_around_cursor('aa', 'a bbb lll')
+ # ed_next_char should move cursor right and cancel delete_meta
+ input_keys('d')
+ input_key_by_symbol(:ed_next_char)
+ input_keys('l')
+ assert_line_around_cursor('aaa ', 'bbb lll')
end
def test_unimplemented_vi_command_should_be_no_op
input_keys("abc\C-[h")
- assert_byte_pointer_size('a')
- assert_cursor(1)
- assert_cursor_max(3)
- assert_line('abc')
+ assert_line_around_cursor('a', 'bc')
input_keys('@')
- assert_byte_pointer_size('a')
- assert_cursor(1)
- assert_cursor_max(3)
- assert_line('abc')
+ assert_line_around_cursor('a', 'bc')
end
def test_vi_yank
- input_keys("foo bar\C-[0")
- assert_line('foo bar')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(7)
+ input_keys("foo bar\C-[2h")
+ assert_line_around_cursor('foo ', 'bar')
input_keys('y3l')
- assert_line('foo bar')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(7)
+ assert_line_around_cursor('foo ', 'bar')
input_keys('P')
- assert_line('foofoo bar')
- assert_byte_pointer_size('fo')
- assert_cursor(2)
- assert_cursor_max(10)
+ assert_line_around_cursor('foo ba', 'rbar')
+ input_keys('3h3yhP')
+ assert_line_around_cursor('foofo', 'o barbar')
+ input_keys('yyP')
+ assert_line_around_cursor('foofofoofoo barba', 'ro barbar')
+ end
+
+ def test_vi_yank_nothing
+ input_keys("foo\C-[0")
+ assert_line_around_cursor('', 'foo')
+ input_keys('yhp')
+ assert_line_around_cursor('', 'foo')
end
def test_vi_end_word_with_operator
input_keys("foo bar\C-[0")
- assert_line('foo bar')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(7)
+ assert_line_around_cursor('', 'foo bar')
input_keys('de')
- assert_line(' bar')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(4)
+ assert_line_around_cursor('', ' bar')
input_keys('de')
- assert_line('')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
+ assert_line_around_cursor('', '')
input_keys('de')
- assert_line('')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
+ assert_line_around_cursor('', '')
end
def test_vi_end_big_word_with_operator
input_keys("aaa b{b}}}b\C-[0")
- assert_line('aaa b{b}}}b')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(13)
+ assert_line_around_cursor('', 'aaa b{b}}}b')
input_keys('dE')
- assert_line(' b{b}}}b')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(10)
+ assert_line_around_cursor('', ' b{b}}}b')
input_keys('dE')
- assert_line('')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
+ assert_line_around_cursor('', '')
input_keys('dE')
- assert_line('')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(0)
+ assert_line_around_cursor('', '')
end
def test_vi_next_char_with_operator
input_keys("foo bar\C-[0")
- assert_line('foo bar')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(7)
+ assert_line_around_cursor('', 'foo bar')
input_keys('df ')
- assert_line('bar')
- assert_byte_pointer_size('')
- assert_cursor(0)
- assert_cursor_max(3)
- end
-
- def test_pasting
- start_pasting
- input_keys('ab')
- finish_pasting
- input_keys('c')
- assert_line('abc')
- assert_byte_pointer_size('abc')
- assert_cursor(3)
- assert_cursor_max(3)
- end
-
- def test_pasting_fullwidth
- start_pasting
- input_keys('ã‚')
- finish_pasting
- input_keys('ã„')
- assert_line('ã‚ã„')
- assert_byte_pointer_size('ã‚ã„')
- assert_cursor(4)
- assert_cursor_max(4)
+ assert_line_around_cursor('', 'bar')
end
def test_ed_delete_next_char_at_eol
input_keys('"ã‚"')
- assert_line('"ã‚"')
- assert_byte_pointer_size('"ã‚"')
- assert_cursor(4)
- assert_cursor_max(4)
+ assert_line_around_cursor('"ã‚"', '')
input_keys("\C-[")
- assert_line('"ã‚"')
- assert_byte_pointer_size('"ã‚')
- assert_cursor(3)
- assert_cursor_max(4)
+ assert_line_around_cursor('"ã‚', '"')
input_keys('xa"')
- assert_line('"ã‚"')
- assert_byte_pointer_size('"ã‚"')
- assert_cursor(4)
- assert_cursor_max(4)
+ assert_line_around_cursor('"ã‚"', '')
+ end
+
+ def test_vi_kill_line_prev
+ input_keys("\C-u", false)
+ assert_line_around_cursor('', '')
+ input_keys('abc')
+ assert_line_around_cursor('abc', '')
+ input_keys("\C-u", false)
+ assert_line_around_cursor('', '')
+ input_keys('abc')
+ input_keys("\C-[\C-u", false)
+ assert_line_around_cursor('', 'c')
+ input_keys("\C-u", false)
+ assert_line_around_cursor('', 'c')
+ end
+
+ def test_vi_change_to_eol
+ input_keys("abcdef\C-[2hC")
+ assert_line_around_cursor('abc', '')
+ input_keys("\C-[0C")
+ assert_line_around_cursor('', '')
+ assert_equal(:vi_insert, editing_mode_label)
+ end
+
+ def test_vi_motion_operators
+ assert_equal(:vi_insert, editing_mode_label)
+
+ assert_nothing_raised do
+ input_keys("test = { foo: bar }\C-[BBBldt}b")
+ end
+ end
+
+ def test_emacs_editing_mode
+ @line_editor.__send__(:emacs_editing_mode, nil)
+ assert(@config.editing_mode_is?(:emacs))
end
end
diff --git a/test/reline/test_key_stroke.rb b/test/reline/test_key_stroke.rb
index d377a1e972..ec70a05957 100644
--- a/test/reline/test_key_stroke.rb
+++ b/test/reline/test_key_stroke.rb
@@ -24,27 +24,56 @@ class Reline::KeyStroke::Test < Reline::TestCase
config.add_default_key_binding(key.bytes, func.bytes)
end
stroke = Reline::KeyStroke.new(config)
- assert_equal(:matching, stroke.match_status("a".bytes))
- assert_equal(:matching, stroke.match_status("ab".bytes))
- assert_equal(:matched, stroke.match_status("abc".bytes))
- assert_equal(:matched, stroke.match_status("abz".bytes))
- assert_equal(:matched, stroke.match_status("abx".bytes))
- assert_equal(:matched, stroke.match_status("ac".bytes))
- assert_equal(:matched, stroke.match_status("aa".bytes))
- assert_equal(:matched, stroke.match_status("x".bytes))
- assert_equal(:unmatched, stroke.match_status("m".bytes))
- assert_equal(:matched, stroke.match_status("abzwabk".bytes))
+ assert_equal(Reline::KeyStroke::MATCHING_MATCHED, stroke.match_status("a".bytes))
+ assert_equal(Reline::KeyStroke::MATCHING_MATCHED, stroke.match_status("ab".bytes))
+ assert_equal(Reline::KeyStroke::MATCHED, stroke.match_status("abc".bytes))
+ assert_equal(Reline::KeyStroke::UNMATCHED, stroke.match_status("abz".bytes))
+ assert_equal(Reline::KeyStroke::UNMATCHED, stroke.match_status("abcx".bytes))
+ assert_equal(Reline::KeyStroke::UNMATCHED, stroke.match_status("aa".bytes))
+ assert_equal(Reline::KeyStroke::MATCHED, stroke.match_status("x".bytes))
+ assert_equal(Reline::KeyStroke::UNMATCHED, stroke.match_status("xa".bytes))
+ end
+
+ def test_match_unknown
+ config = Reline::Config.new
+ config.add_default_key_binding("\e[9abc".bytes, 'x')
+ stroke = Reline::KeyStroke.new(config)
+ sequences = [
+ "\e[9abc",
+ "\e[9d",
+ "\e[A", # Up
+ "\e[1;1R", # Cursor position report
+ "\e[15~", # F5
+ "\eOP", # F1
+ "\e\e[A", # Option+Up
+ "\eX",
+ "\e\eX"
+ ]
+ sequences.each do |seq|
+ assert_equal(Reline::KeyStroke::MATCHED, stroke.match_status(seq.bytes))
+ assert_equal(Reline::KeyStroke::UNMATCHED, stroke.match_status(seq.bytes + [32]))
+ (2...seq.size).each do |i|
+ assert_equal(Reline::KeyStroke::MATCHING, stroke.match_status(seq.bytes.take(i)))
+ end
+ end
end
def test_expand
config = Reline::Config.new
{
'abc' => '123',
+ 'ab' => '456'
}.each_pair do |key, func|
config.add_default_key_binding(key.bytes, func.bytes)
end
stroke = Reline::KeyStroke.new(config)
- assert_equal('123'.bytes, stroke.expand('abc'.bytes))
+ assert_equal(['123'.bytes.map { |c| Reline::Key.new(c, c, false) }, 'de'.bytes], stroke.expand('abcde'.bytes))
+ assert_equal(['456'.bytes.map { |c| Reline::Key.new(c, c, false) }, 'de'.bytes], stroke.expand('abde'.bytes))
+ # CSI sequence
+ assert_equal([[], 'bc'.bytes], stroke.expand("\e[1;2;3;4;5abc".bytes))
+ assert_equal([[], 'BC'.bytes], stroke.expand("\e\e[ABC".bytes))
+ # SS3 sequence
+ assert_equal([[], 'QR'.bytes], stroke.expand("\eOPQR".bytes))
end
def test_oneshot_key_bindings
@@ -55,25 +84,22 @@ class Reline::KeyStroke::Test < Reline::TestCase
config.add_default_key_binding(key.bytes, func.bytes)
end
stroke = Reline::KeyStroke.new(config)
- assert_equal(:unmatched, stroke.match_status('zzz'.bytes))
- assert_equal(:matched, stroke.match_status('abc'.bytes))
+ assert_equal(Reline::KeyStroke::UNMATCHED, stroke.match_status('zzz'.bytes))
+ assert_equal(Reline::KeyStroke::MATCHED, stroke.match_status('abc'.bytes))
end
def test_with_reline_key
config = Reline::Config.new
{
- [
- Reline::Key.new(100, 228, true), # Alt+d
- Reline::Key.new(97, 97, false) # a
- ] => 'abc',
+ "\eda".bytes => 'abc', # Alt+d a
[195, 164] => 'def'
}.each_pair do |key, func|
config.add_oneshot_key_binding(key, func.bytes)
end
stroke = Reline::KeyStroke.new(config)
- assert_equal(:unmatched, stroke.match_status('da'.bytes))
- assert_equal(:matched, stroke.match_status("\M-da".bytes))
- assert_equal(:unmatched, stroke.match_status([32, 195, 164]))
- assert_equal(:matched, stroke.match_status([195, 164]))
+ assert_equal(Reline::KeyStroke::UNMATCHED, stroke.match_status('da'.bytes))
+ assert_equal(Reline::KeyStroke::MATCHED, stroke.match_status("\eda".bytes))
+ assert_equal(Reline::KeyStroke::UNMATCHED, stroke.match_status([32, 195, 164]))
+ assert_equal(Reline::KeyStroke::MATCHED, stroke.match_status([195, 164]))
end
end
diff --git a/test/reline/test_line_editor.rb b/test/reline/test_line_editor.rb
new file mode 100644
index 0000000000..1859da8199
--- /dev/null
+++ b/test/reline/test_line_editor.rb
@@ -0,0 +1,183 @@
+require_relative 'helper'
+require 'reline/line_editor'
+require 'stringio'
+
+class Reline::LineEditor
+ class RenderLineDifferentialTest < Reline::TestCase
+ class TestIO < Reline::IO
+ def move_cursor_column(col)
+ @output << "[COL_#{col}]"
+ end
+
+ def erase_after_cursor
+ @output << '[ERASE]'
+ end
+ end
+
+ def setup
+ verbose, $VERBOSE = $VERBOSE, nil
+ @line_editor = Reline::LineEditor.new(nil, Encoding::UTF_8)
+ @original_iogate = Reline::IOGate
+ @output = StringIO.new
+ @line_editor.instance_variable_set(:@screen_size, [24, 80])
+ @line_editor.instance_variable_set(:@output, @output)
+ Reline.send(:remove_const, :IOGate)
+ Reline.const_set(:IOGate, TestIO.new)
+ Reline::IOGate.instance_variable_set(:@output, @output)
+ ensure
+ $VERBOSE = verbose
+ end
+
+ def assert_output(expected)
+ @output.reopen(+'')
+ yield
+ actual = @output.string
+ assert_equal(expected, actual.gsub("\e[0m", ''))
+ end
+
+ def teardown
+ Reline.send(:remove_const, :IOGate)
+ Reline.const_set(:IOGate, @original_iogate)
+ end
+
+ def test_line_increase_decrease
+ assert_output '[COL_0]bb' do
+ @line_editor.render_line_differential([[0, 1, 'a']], [[0, 2, 'bb']])
+ end
+
+ assert_output '[COL_0]b[COL_1][ERASE]' do
+ @line_editor.render_line_differential([[0, 2, 'aa']], [[0, 1, 'b']])
+ end
+ end
+
+ def test_dialog_appear_disappear
+ assert_output '[COL_3]dialog' do
+ @line_editor.render_line_differential([[0, 1, 'a']], [[0, 1, 'a'], [3, 6, 'dialog']])
+ end
+
+ assert_output '[COL_3]dialog' do
+ @line_editor.render_line_differential([[0, 10, 'a' * 10]], [[0, 10, 'a' * 10], [3, 6, 'dialog']])
+ end
+
+ assert_output '[COL_1][ERASE]' do
+ @line_editor.render_line_differential([[0, 1, 'a'], [3, 6, 'dialog']], [[0, 1, 'a']])
+ end
+
+ assert_output '[COL_3]aaaaaa' do
+ @line_editor.render_line_differential([[0, 10, 'a' * 10], [3, 6, 'dialog']], [[0, 10, 'a' * 10]])
+ end
+ end
+
+ def test_dialog_change
+ assert_output '[COL_3]DIALOG' do
+ @line_editor.render_line_differential([[0, 2, 'a'], [3, 6, 'dialog']], [[0, 2, 'a'], [3, 6, 'DIALOG']])
+ end
+
+ assert_output '[COL_3]DIALOG' do
+ @line_editor.render_line_differential([[0, 10, 'a' * 10], [3, 6, 'dialog']], [[0, 10, 'a' * 10], [3, 6, 'DIALOG']])
+ end
+ end
+
+ def test_update_under_dialog
+ assert_output '[COL_0]b[COL_1] ' do
+ @line_editor.render_line_differential([[0, 2, 'aa'], [4, 6, 'dialog']], [[0, 1, 'b'], [4, 6, 'dialog']])
+ end
+
+ assert_output '[COL_0]bbb[COL_9]b' do
+ @line_editor.render_line_differential([[0, 10, 'a' * 10], [3, 6, 'dialog']], [[0, 10, 'b' * 10], [3, 6, 'dialog']])
+ end
+
+ assert_output '[COL_0]b[COL_1] [COL_9][ERASE]' do
+ @line_editor.render_line_differential([[0, 10, 'a' * 10], [3, 6, 'dialog']], [[0, 1, 'b'], [3, 6, 'dialog']])
+ end
+ end
+
+ def test_dialog_move
+ assert_output '[COL_3]dialog[COL_9][ERASE]' do
+ @line_editor.render_line_differential([[0, 1, 'a'], [4, 6, 'dialog']], [[0, 1, 'a'], [3, 6, 'dialog']])
+ end
+
+ assert_output '[COL_4] [COL_5]dialog' do
+ @line_editor.render_line_differential([[0, 1, 'a'], [4, 6, 'dialog']], [[0, 1, 'a'], [5, 6, 'dialog']])
+ end
+
+ assert_output '[COL_2]dialog[COL_8]a' do
+ @line_editor.render_line_differential([[0, 10, 'a' * 10], [3, 6, 'dialog']], [[0, 10, 'a' * 10], [2, 6, 'dialog']])
+ end
+
+ assert_output '[COL_2]a[COL_3]dialog' do
+ @line_editor.render_line_differential([[0, 10, 'a' * 10], [2, 6, 'dialog']], [[0, 10, 'a' * 10], [3, 6, 'dialog']])
+ end
+ end
+
+ def test_multibyte
+ base = [0, 12, '一二三一二三']
+ left = [0, 3, 'LLL']
+ right = [9, 3, 'RRR']
+ front = [3, 6, 'FFFFFF']
+ # 一 FFFFFF 三
+ # 一二三一二三
+ assert_output '[COL_2]二三一二' do
+ @line_editor.render_line_differential([base, front], [base, nil])
+ end
+
+ # LLLFFFFFF 三
+ # LLL 三一二三
+ assert_output '[COL_3] 三一二' do
+ @line_editor.render_line_differential([base, left, front], [base, left, nil])
+ end
+
+ # 一 FFFFFFRRR
+ # 一二三一 RRR
+ assert_output '[COL_2]二三一 ' do
+ @line_editor.render_line_differential([base, right, front], [base, right, nil])
+ end
+
+ # LLLFFFFFFRRR
+ # LLL 三一 RRR
+ assert_output '[COL_3] 三一 ' do
+ @line_editor.render_line_differential([base, left, right, front], [base, left, right, nil])
+ end
+ end
+
+ def test_complicated
+ state_a = [nil, [19, 7, 'bbbbbbb'], [15, 8, 'cccccccc'], [10, 5, 'ddddd'], [18, 4, 'eeee'], [1, 3, 'fff'], [17, 2, 'gg'], [7, 1, 'h']]
+ state_b = [[5, 9, 'aaaaaaaaa'], nil, [15, 8, 'cccccccc'], nil, [18, 4, 'EEEE'], [25, 4, 'ffff'], [17, 2, 'gg'], [2, 2, 'hh']]
+ # state_a: " fff h dddddccggeeecbbb"
+ # state_b: " hh aaaaaaaaa ccggEEEc ffff"
+
+ assert_output '[COL_1] [COL_2]hh[COL_5]aaaaaaaaa[COL_14] [COL_19]EEE[COL_23] [COL_25]ffff' do
+ @line_editor.render_line_differential(state_a, state_b)
+ end
+
+ assert_output '[COL_1]fff[COL_5] [COL_7]h[COL_8] [COL_10]ddddd[COL_19]eee[COL_23]bbb[COL_26][ERASE]' do
+ @line_editor.render_line_differential(state_b, state_a)
+ end
+ end
+ end
+
+ def test_menu_info_format
+ list = %w[aa b c d e f g hhh i j k]
+ col3 = [
+ 'aa e i',
+ 'b f j',
+ 'c g k',
+ 'd hhh'
+ ]
+ col2 = [
+ 'aa g',
+ 'b hhh',
+ 'c i',
+ 'd j',
+ 'e k',
+ 'f'
+ ]
+ assert_equal(col3, Reline::LineEditor::MenuInfo.new(list).lines(19))
+ assert_equal(col3, Reline::LineEditor::MenuInfo.new(list).lines(15))
+ assert_equal(col2, Reline::LineEditor::MenuInfo.new(list).lines(14))
+ assert_equal(col2, Reline::LineEditor::MenuInfo.new(list).lines(10))
+ assert_equal(list, Reline::LineEditor::MenuInfo.new(list).lines(9))
+ assert_equal(list, Reline::LineEditor::MenuInfo.new(list).lines(0))
+ assert_equal([], Reline::LineEditor::MenuInfo.new([]).lines(10))
+ end
+end
diff --git a/test/reline/test_macro.rb b/test/reline/test_macro.rb
index 76a677c834..04aa6474b4 100644
--- a/test/reline/test_macro.rb
+++ b/test/reline/test_macro.rb
@@ -4,9 +4,8 @@ class Reline::MacroTest < Reline::TestCase
def setup
Reline.send(:test_mode)
@config = Reline::Config.new
- @encoding = Reline::IOGate.encoding
+ @encoding = Reline.core.encoding
@line_editor = Reline::LineEditor.new(@config, @encoding)
- @line_editor.instance_variable_set(:@screen_size, [24, 80])
@output = @line_editor.output = File.open(IO::NULL, "w")
end
diff --git a/test/reline/test_reline.rb b/test/reline/test_reline.rb
index 161b329740..515805467d 100644
--- a/test/reline/test_reline.rb
+++ b/test/reline/test_reline.rb
@@ -1,5 +1,6 @@
require_relative 'helper'
-require "reline"
+require 'reline'
+require 'stringio'
class Reline::Test < Reline::TestCase
class DummyCallbackObject
@@ -7,6 +8,7 @@ class Reline::Test < Reline::TestCase
end
def setup
+ Reline.send(:test_mode)
Reline.output_modifier_proc = nil
Reline.completion_proc = nil
Reline.prompt_proc = nil
@@ -136,14 +138,14 @@ class Reline::Test < Reline::TestCase
end
def test_completion_proc
- skip unless Reline.completion_proc == nil
+ omit unless Reline.completion_proc == nil
# Another test can set Reline.completion_proc
# assert_equal(nil, Reline.completion_proc)
- p = proc {}
- Reline.completion_proc = p
- assert_equal(p, Reline.completion_proc)
+ dummy_proc = proc {}
+ Reline.completion_proc = dummy_proc
+ assert_equal(dummy_proc, Reline.completion_proc)
l = lambda {}
Reline.completion_proc = l
@@ -160,9 +162,9 @@ class Reline::Test < Reline::TestCase
def test_output_modifier_proc
assert_equal(nil, Reline.output_modifier_proc)
- p = proc {}
- Reline.output_modifier_proc = p
- assert_equal(p, Reline.output_modifier_proc)
+ dummy_proc = proc {}
+ Reline.output_modifier_proc = dummy_proc
+ assert_equal(dummy_proc, Reline.output_modifier_proc)
l = lambda {}
Reline.output_modifier_proc = l
@@ -179,9 +181,9 @@ class Reline::Test < Reline::TestCase
def test_prompt_proc
assert_equal(nil, Reline.prompt_proc)
- p = proc {}
- Reline.prompt_proc = p
- assert_equal(p, Reline.prompt_proc)
+ dummy_proc = proc {}
+ Reline.prompt_proc = dummy_proc
+ assert_equal(dummy_proc, Reline.prompt_proc)
l = lambda {}
Reline.prompt_proc = l
@@ -198,9 +200,9 @@ class Reline::Test < Reline::TestCase
def test_auto_indent_proc
assert_equal(nil, Reline.auto_indent_proc)
- p = proc {}
- Reline.auto_indent_proc = p
- assert_equal(p, Reline.auto_indent_proc)
+ dummy_proc = proc {}
+ Reline.auto_indent_proc = dummy_proc
+ assert_equal(dummy_proc, Reline.auto_indent_proc)
l = lambda {}
Reline.auto_indent_proc = l
@@ -217,9 +219,9 @@ class Reline::Test < Reline::TestCase
def test_pre_input_hook
assert_equal(nil, Reline.pre_input_hook)
- p = proc {}
- Reline.pre_input_hook = p
- assert_equal(p, Reline.pre_input_hook)
+ dummy_proc = proc {}
+ Reline.pre_input_hook = dummy_proc
+ assert_equal(dummy_proc, Reline.pre_input_hook)
l = lambda {}
Reline.pre_input_hook = l
@@ -229,9 +231,9 @@ class Reline::Test < Reline::TestCase
def test_dig_perfect_match_proc
assert_equal(nil, Reline.dig_perfect_match_proc)
- p = proc {}
- Reline.dig_perfect_match_proc = p
- assert_equal(p, Reline.dig_perfect_match_proc)
+ dummy_proc = proc {}
+ Reline.dig_perfect_match_proc = dummy_proc
+ assert_equal(dummy_proc, Reline.dig_perfect_match_proc)
l = lambda {}
Reline.dig_perfect_match_proc = l
@@ -246,43 +248,112 @@ class Reline::Test < Reline::TestCase
end
def test_insert_text
- # TODO
- end
-
- def test_line_buffer
- # TODO
- end
-
- def test_point
- # TODO
- end
-
- def test_input=
- # TODO
+ assert_equal('', Reline.line_buffer)
+ assert_equal(0, Reline.point)
+ Reline.insert_text('abc')
+ assert_equal('abc', Reline.line_buffer)
+ assert_equal(3, Reline.point)
+ end
+
+ def test_delete_text
+ assert_equal('', Reline.line_buffer)
+ assert_equal(0, Reline.point)
+ Reline.insert_text('abc')
+ assert_equal('abc', Reline.line_buffer)
+ assert_equal(3, Reline.point)
+ Reline.delete_text()
+ assert_equal('', Reline.line_buffer)
+ assert_equal(0, Reline.point)
+ Reline.insert_text('abc')
+ Reline.delete_text(1)
+ assert_equal('a', Reline.line_buffer)
+ assert_equal(1, Reline.point)
+ Reline.insert_text('defghi')
+ Reline.delete_text(2, 2)
+ assert_equal('adghi', Reline.line_buffer)
+ assert_equal(5, Reline.point)
+ end
+
+ def test_set_input_and_output
assert_raise(TypeError) do
Reline.input = "This is not a file."
end
- end
-
- def test_output=
- # TODO
assert_raise(TypeError) do
Reline.output = "This is not a file."
end
+
+ input, to_write = IO.pipe
+ to_read, output = IO.pipe
+ unless Reline.__send__(:input=, input)
+ omit "Setting to input is not effective on #{Reline.core.io_gate}"
+ end
+ Reline.output = output
+
+ to_write.write "a\n"
+ result = Reline.readline
+ to_write.close
+ read_text = to_read.read_nonblock(100)
+ assert_equal('a', result)
+ refute(read_text.empty?)
+ ensure
+ input&.close
+ output&.close
+ to_read&.close
end
def test_vi_editing_mode
Reline.vi_editing_mode
- assert_equal(Reline::KeyActor::ViInsert, Reline.send(:core).config.editing_mode.class)
+ assert_equal(:vi_insert, Reline.core.config.instance_variable_get(:@editing_mode_label))
end
def test_emacs_editing_mode
Reline.emacs_editing_mode
- assert_equal(Reline::KeyActor::Emacs, Reline.send(:core).config.editing_mode.class)
+ assert_equal(:emacs, Reline.core.config.instance_variable_get(:@editing_mode_label))
+ end
+
+ def test_add_dialog_proc
+ dummy_proc = proc {}
+ Reline.add_dialog_proc(:test_proc, dummy_proc)
+ d = Reline.dialog_proc(:test_proc)
+ assert_equal(dummy_proc, d.dialog_proc)
+
+ dummy_proc_2 = proc {}
+ Reline.add_dialog_proc(:test_proc, dummy_proc_2)
+ d = Reline.dialog_proc(:test_proc)
+ assert_equal(dummy_proc_2, d.dialog_proc)
+
+ Reline.add_dialog_proc(:test_proc, nil)
+ assert_nil(Reline.dialog_proc(:test_proc))
+
+ l = lambda {}
+ Reline.add_dialog_proc(:test_lambda, l)
+ d = Reline.dialog_proc(:test_lambda)
+ assert_equal(l, d.dialog_proc)
+
+ assert_equal(nil, Reline.dialog_proc(:test_nothing))
+
+ assert_raise(ArgumentError) { Reline.add_dialog_proc(:error, 42) }
+ assert_raise(ArgumentError) { Reline.add_dialog_proc(:error, 'hoge') }
+ assert_raise(ArgumentError) { Reline.add_dialog_proc('error', proc {} ) }
+
+ dummy = DummyCallbackObject.new
+ Reline.add_dialog_proc(:dummy, dummy)
+ d = Reline.dialog_proc(:dummy)
+ assert_equal(dummy, d.dialog_proc)
end
- def test_editing_mode
- # TODO
+ def test_add_dialog_proc_with_context
+ dummy_proc = proc {}
+ array = Array.new
+ Reline.add_dialog_proc(:test_proc, dummy_proc, array)
+ d = Reline.dialog_proc(:test_proc)
+ assert_equal(dummy_proc, d.dialog_proc)
+ assert_equal(array, d.context)
+
+ Reline.add_dialog_proc(:test_proc, dummy_proc, nil)
+ d = Reline.dialog_proc(:test_proc)
+ assert_equal(dummy_proc, d.dialog_proc)
+ assert_equal(nil, d.context)
end
def test_readmultiline
@@ -297,26 +368,74 @@ class Reline::Test < Reline::TestCase
assert_include(Reline.private_instance_methods, :readline)
end
- def test_inner_readline
+ def test_read_io
# TODO in Reline::Core
end
- def test_read_io
- # TODO in Reline::Core
+ def test_dumb_terminal
+ lib = File.expand_path("../../lib", __dir__)
+ out = IO.popen([{"TERM"=>"dumb"}, Reline.test_rubybin, "-I#{lib}", "-rreline", "-e", "p Reline.core.io_gate"], &:read)
+ assert_match(/#<Reline::Dumb/, out.chomp)
end
- def test_read_escaped_key
- # TODO in Reline::Core
+ def test_print_prompt_before_everything_else
+ pend if win?
+ lib = File.expand_path("../../lib", __dir__)
+ code = "p Reline::IOGate.class; p Reline.readline 'prompt> '"
+ out = IO.popen([Reline.test_rubybin, "-I#{lib}", "-rreline", "-e", code], "r+") do |io|
+ io.write "abc\n"
+ io.close_write
+ io.read
+ end
+ assert_match(/\AReline::ANSI\nprompt> /, out)
end
- def test_may_req_ambiguous_char_width
- # TODO in Reline::Core
+ def test_read_eof_returns_input
+ pend if win?
+ lib = File.expand_path("../../lib", __dir__)
+ code = "p result: Reline.readline"
+ out = IO.popen([Reline.test_rubybin, "-I#{lib}", "-rreline", "-e", code], "r+") do |io|
+ io.write "a\C-a"
+ io.close_write
+ io.read
+ end
+ assert_include(out, { result: 'a' }.inspect)
+ end
+
+ def test_read_eof_returns_nil_if_empty
+ pend if win?
+ lib = File.expand_path("../../lib", __dir__)
+ code = "p result: Reline.readline"
+ out = IO.popen([Reline.test_rubybin, "-I#{lib}", "-rreline", "-e", code], "r+") do |io|
+ io.write "a\C-h"
+ io.close_write
+ io.read
+ end
+ assert_include(out, { result: nil }.inspect)
+ end
+
+ def test_require_reline_should_not_trigger_winsize
+ pend if win?
+ lib = File.expand_path("../../lib", __dir__)
+ code = <<~RUBY
+ require "io/console"
+ def STDIN.tty?; true; end
+ def STDOUT.tty?; true; end
+ def STDIN.winsize; raise; end
+ require("reline") && p(Reline.core.io_gate)
+ RUBY
+ out = IO.popen([{}, Reline.test_rubybin, "-I#{lib}", "-e", code], &:read)
+ assert_include(out.chomp, "Reline::ANSI")
+ end
+
+ def win?
+ /mswin|mingw/.match?(RUBY_PLATFORM)
end
def get_reline_encoding
- if encoding = Reline::IOGate.encoding
+ if encoding = Reline.core.encoding
encoding
- elsif RUBY_PLATFORM =~ /mswin|mingw/
+ elsif win?
Encoding::UTF_8
else
Encoding::default_external
diff --git a/test/reline/test_reline_key.rb b/test/reline/test_reline_key.rb
new file mode 100644
index 0000000000..1e6b9fcb6c
--- /dev/null
+++ b/test/reline/test_reline_key.rb
@@ -0,0 +1,11 @@
+require_relative 'helper'
+require "reline"
+
+class Reline::TestKey < Reline::TestCase
+ def test_match_symbol
+ assert(Reline::Key.new(:key1, :key1, false).match?(:key1))
+ refute(Reline::Key.new(:key1, :key1, false).match?(:key2))
+ refute(Reline::Key.new(:key1, :key1, false).match?(nil))
+ refute(Reline::Key.new(1, 1, false).match?(:key1))
+ end
+end
diff --git a/test/reline/test_string_processing.rb b/test/reline/test_string_processing.rb
index 5db97545da..c9b9e38643 100644
--- a/test/reline/test_string_processing.rb
+++ b/test/reline/test_string_processing.rb
@@ -6,7 +6,7 @@ class Reline::LineEditor::StringProcessingTest < Reline::TestCase
@prompt = '> '
@config = Reline::Config.new
Reline::HISTORY.instance_variable_set(:@config, @config)
- @encoding = Reline::IOGate.encoding
+ @encoding = Reline.core.encoding
@line_editor = Reline::LineEditor.new(@config, @encoding)
@line_editor.reset(@prompt, encoding: @encoding)
end
@@ -30,10 +30,7 @@ class Reline::LineEditor::StringProcessingTest < Reline::TestCase
@line_editor.instance_variable_set(:@is_multiline, true)
@line_editor.instance_variable_set(:@buffer_of_lines, buf)
- @line_editor.instance_variable_set(:@line, buf[1])
@line_editor.instance_variable_set(:@byte_pointer, 3)
- @line_editor.instance_variable_set(:@cursor, 3)
- @line_editor.instance_variable_set(:@cursor_max, 11)
@line_editor.instance_variable_set(:@line_index, 1)
@line_editor.instance_variable_set(:@completion_proc, proc { |target|
assert_equal('p', target)
@@ -42,10 +39,7 @@ class Reline::LineEditor::StringProcessingTest < Reline::TestCase
@line_editor.instance_variable_set(:@is_multiline, true)
@line_editor.instance_variable_set(:@buffer_of_lines, buf)
- @line_editor.instance_variable_set(:@line, buf[1])
@line_editor.instance_variable_set(:@byte_pointer, 6)
- @line_editor.instance_variable_set(:@cursor, 6)
- @line_editor.instance_variable_set(:@cursor_max, 11)
@line_editor.instance_variable_set(:@line_index, 1)
@line_editor.instance_variable_set(:@completion_proc, proc { |target, pre, post|
assert_equal('puts', target)
@@ -54,10 +48,7 @@ class Reline::LineEditor::StringProcessingTest < Reline::TestCase
})
@line_editor.__send__(:call_completion_proc)
- @line_editor.instance_variable_set(:@line, buf[0])
@line_editor.instance_variable_set(:@byte_pointer, 6)
- @line_editor.instance_variable_set(:@cursor, 6)
- @line_editor.instance_variable_set(:@cursor_max, 8)
@line_editor.instance_variable_set(:@line_index, 0)
@line_editor.instance_variable_set(:@completion_proc, proc { |target, pre, post|
assert_equal('ho', target)
@@ -66,10 +57,7 @@ class Reline::LineEditor::StringProcessingTest < Reline::TestCase
})
@line_editor.__send__(:call_completion_proc)
- @line_editor.instance_variable_set(:@line, buf[2])
@line_editor.instance_variable_set(:@byte_pointer, 1)
- @line_editor.instance_variable_set(:@cursor, 1)
- @line_editor.instance_variable_set(:@cursor_max, 3)
@line_editor.instance_variable_set(:@line_index, 2)
@line_editor.instance_variable_set(:@completion_proc, proc { |target, pre, post|
assert_equal('e', target)
diff --git a/test/reline/test_terminfo.rb b/test/reline/test_terminfo.rb
index f1bf197931..4e59c54838 100644
--- a/test/reline/test_terminfo.rb
+++ b/test/reline/test_terminfo.rb
@@ -9,24 +9,53 @@ class Reline::Terminfo::Test < Reline::TestCase
def test_tigetstr
assert Reline::Terminfo.tigetstr('khome')
rescue Reline::Terminfo::TerminfoError => e
- skip e.message
+ omit e.message
+ end
+
+ def test_tigetstr_with_error
+ assert_raise(Reline::Terminfo::TerminfoError) { Reline::Terminfo.tigetstr('unknown') }
+ assert_raise(Reline::Terminfo::TerminfoError) { Reline::Terminfo.tigetstr(nil) }
end
def test_tiparm
assert Reline::Terminfo.tigetstr('khome').tiparm
rescue Reline::Terminfo::TerminfoError => e
- skip e.message
+ omit e.message
end
def test_tigetstr_with_param
assert Reline::Terminfo.tigetstr('cuu').include?('%p1%d')
rescue Reline::Terminfo::TerminfoError => e
- skip e.message
+ omit e.message
end
def test_tiparm_with_param
assert Reline::Terminfo.tigetstr('cuu').tiparm(4649).include?('4649')
rescue Reline::Terminfo::TerminfoError => e
- skip e.message
+ omit e.message
+ end
+
+ def test_tigetflag
+ assert_instance_of Integer, Reline::Terminfo.tigetflag('xenl')
+ rescue Reline::Terminfo::TerminfoError => e
+ omit e.message
+ end
+
+ def test_tigetflag_with_error
+ assert_raise(Reline::Terminfo::TerminfoError) { Reline::Terminfo.tigetflag('cuu') }
+ assert_raise(Reline::Terminfo::TerminfoError) { Reline::Terminfo.tigetflag('unknown') }
+ assert_raise(Reline::Terminfo::TerminfoError) { Reline::Terminfo.tigetflag(nil) }
+ end
+
+ def test_tigetnum
+ assert_instance_of Integer, Reline::Terminfo.tigetnum('colors')
+ rescue Reline::Terminfo::TerminfoError => e
+ omit e.message
+ end
+
+ def test_tigetnum_with_error
+ assert_raise(Reline::Terminfo::TerminfoError) { Reline::Terminfo.tigetnum('cuu') }
+ assert_raise(Reline::Terminfo::TerminfoError) { Reline::Terminfo.tigetnum('unknown') }
+ assert_raise(Reline::Terminfo::TerminfoError) { Reline::Terminfo.tigetnum(nil) }
end
-end if Reline::Terminfo.enabled?
+end if Reline::Terminfo.enabled? && Reline::Terminfo.term_supported?
diff --git a/test/reline/test_unicode.rb b/test/reline/test_unicode.rb
index 1233e034e8..deba4d4681 100644
--- a/test/reline/test_unicode.rb
+++ b/test/reline/test_unicode.rb
@@ -18,8 +18,75 @@ class Reline::Unicode::Test < Reline::TestCase
assert_equal 2, Reline::Unicode.calculate_width('√', true)
end
+ def test_csi_regexp
+ csi_sequences = ["\e[m", "\e[1m", "\e[12;34m", "\e[12;34H"]
+ assert_equal(csi_sequences, "text#{csi_sequences.join('text')}text".scan(Reline::Unicode::CSI_REGEXP))
+ end
+
+ def test_osc_regexp
+ osc_sequences = ["\e]1\a", "\e]0;OSC\a", "\e]1\e\\", "\e]0;OSC\e\\"]
+ separator = "text\atext"
+ assert_equal(osc_sequences, "#{separator}#{osc_sequences.join(separator)}#{separator}".scan(Reline::Unicode::OSC_REGEXP))
+ end
+
+ def test_split_by_width
+ assert_equal [['abc', nil, 'de'], 2], Reline::Unicode.split_by_width('abcde', 3)
+ assert_equal [['abc', nil, 'def', nil, ''], 3], Reline::Unicode.split_by_width('abcdef', 3)
+ assert_equal [['ab', nil, 'ã‚d', nil, 'ef'], 3], Reline::Unicode.split_by_width('abã‚def', 3)
+ assert_equal [["ab\1zero\2c", nil, 'def', nil, ''], 3], Reline::Unicode.split_by_width("ab\1zero\2cdef", 3)
+ assert_equal [["\e[31mabc", nil, "\e[31md\e[42mef", nil, "\e[31m\e[42mg"], 3], Reline::Unicode.split_by_width("\e[31mabcd\e[42mefg", 3)
+ assert_equal [["ab\e]0;1\ac", nil, "\e]0;1\ad"], 2], Reline::Unicode.split_by_width("ab\e]0;1\acd", 3)
+ end
+
+ def test_split_by_width_csi_reset_sgr_optimization
+ assert_equal [["\e[1ma\e[mb\e[2mc", nil, "\e[2md\e[0me\e[3mf", nil, "\e[3mg"], 3], Reline::Unicode.split_by_width("\e[1ma\e[mb\e[2mcd\e[0me\e[3mfg", 3)
+ assert_equal [["\e[1ma\1\e[mzero\e[0m\2\e[2mb", nil, "\e[1m\e[2mc"], 2], Reline::Unicode.split_by_width("\e[1ma\1\e[mzero\e[0m\2\e[2mbc", 2)
+ end
+
def test_take_range
assert_equal 'cdef', Reline::Unicode.take_range('abcdefghi', 2, 4)
+ assert_equal 'ã‚de', Reline::Unicode.take_range('abã‚def', 2, 4)
+ assert_equal "\1zero\2cdef", Reline::Unicode.take_range("ab\1zero\2cdef", 2, 4)
+ assert_equal "b\1zero\2cde", Reline::Unicode.take_range("ab\1zero\2cdef", 1, 4)
+ assert_equal "\e[31mcd\e[42mef", Reline::Unicode.take_range("\e[31mabcd\e[42mefg", 2, 4)
+ assert_equal "\e]0;1\acd", Reline::Unicode.take_range("ab\e]0;1\acd", 2, 3)
assert_equal 'ã„ã†', Reline::Unicode.take_range('ã‚ã„ã†ãˆãŠ', 2, 4)
end
+
+ def test_calculate_width
+ assert_equal 9, Reline::Unicode.calculate_width('abcdefghi')
+ assert_equal 9, Reline::Unicode.calculate_width('abcdefghi', true)
+ assert_equal 7, Reline::Unicode.calculate_width('abã‚def')
+ assert_equal 7, Reline::Unicode.calculate_width('abã‚def', true)
+ assert_equal 14, Reline::Unicode.calculate_width("ab\1zero\2cdef")
+ assert_equal 6, Reline::Unicode.calculate_width("ab\1zero\2cdef", true)
+ assert_equal 19, Reline::Unicode.calculate_width("\e[31mabcd\e[42mefg")
+ assert_equal 7, Reline::Unicode.calculate_width("\e[31mabcd\e[42mefg", true)
+ assert_equal 12, Reline::Unicode.calculate_width("ab\e]0;1\acd")
+ assert_equal 4, Reline::Unicode.calculate_width("ab\e]0;1\acd", true)
+ assert_equal 10, Reline::Unicode.calculate_width('ã‚ã„ã†ãˆãŠ')
+ assert_equal 10, Reline::Unicode.calculate_width('ã‚ã„ã†ãˆãŠ', true)
+ end
+
+ def test_take_mbchar_range
+ assert_equal ['cdef', 2, 4], Reline::Unicode.take_mbchar_range('abcdefghi', 2, 4)
+ assert_equal ['cdef', 2, 4], Reline::Unicode.take_mbchar_range('abcdefghi', 2, 4, padding: true)
+ assert_equal ['cdef', 2, 4], Reline::Unicode.take_mbchar_range('abcdefghi', 2, 4, cover_begin: true)
+ assert_equal ['cdef', 2, 4], Reline::Unicode.take_mbchar_range('abcdefghi', 2, 4, cover_end: true)
+ assert_equal ['ã„ã†', 2, 4], Reline::Unicode.take_mbchar_range('ã‚ã„ã†ãˆãŠ', 2, 4)
+ assert_equal ['ã„ã†', 2, 4], Reline::Unicode.take_mbchar_range('ã‚ã„ã†ãˆãŠ', 2, 4, padding: true)
+ assert_equal ['ã„ã†', 2, 4], Reline::Unicode.take_mbchar_range('ã‚ã„ã†ãˆãŠ', 2, 4, cover_begin: true)
+ assert_equal ['ã„ã†', 2, 4], Reline::Unicode.take_mbchar_range('ã‚ã„ã†ãˆãŠ', 2, 4, cover_end: true)
+ assert_equal ['ã†', 4, 2], Reline::Unicode.take_mbchar_range('ã‚ã„ã†ãˆãŠ', 3, 4)
+ assert_equal [' ㆠ', 3, 4], Reline::Unicode.take_mbchar_range('ã‚ã„ã†ãˆãŠ', 3, 4, padding: true)
+ assert_equal ['ã„ã†', 2, 4], Reline::Unicode.take_mbchar_range('ã‚ã„ã†ãˆãŠ', 3, 4, cover_begin: true)
+ assert_equal ['ã†ãˆ', 4, 4], Reline::Unicode.take_mbchar_range('ã‚ã„ã†ãˆãŠ', 3, 4, cover_end: true)
+ assert_equal ['ã„ㆠ', 2, 5], Reline::Unicode.take_mbchar_range('ã‚ã„ã†ãˆãŠ', 3, 4, cover_begin: true, padding: true)
+ assert_equal [' ã†ãˆ', 3, 5], Reline::Unicode.take_mbchar_range('ã‚ã„ã†ãˆãŠ', 3, 4, cover_end: true, padding: true)
+ assert_equal [' ã†ãˆãŠ ', 3, 10], Reline::Unicode.take_mbchar_range('ã‚ã„ã†ãˆãŠ', 3, 10, padding: true)
+ assert_equal [" \e[41mã†ãˆãŠ\e[0m ", 3, 10], Reline::Unicode.take_mbchar_range("ã‚ã„\e[41mã†ãˆãŠ", 3, 10, padding: true)
+ assert_equal ["\e[41m \e[42mã„\e[43m ", 1, 4], Reline::Unicode.take_mbchar_range("\e[41mã‚\e[42mã„\e[43mã†", 1, 4, padding: true)
+ assert_equal ["\e[31mc\1ABC\2d\e[0mef", 2, 4], Reline::Unicode.take_mbchar_range("\e[31mabc\1ABC\2d\e[0mefghi", 2, 4)
+ assert_equal ["\e[41m \e[42mã„\e[43m ", 1, 4], Reline::Unicode.take_mbchar_range("\e[41mã‚\e[42mã„\e[43mã†", 1, 4, padding: true)
+ end
end
diff --git a/test/reline/test_within_pipe.rb b/test/reline/test_within_pipe.rb
index ff2d68bb82..4f05255301 100644
--- a/test/reline/test_within_pipe.rb
+++ b/test/reline/test_within_pipe.rb
@@ -3,14 +3,14 @@ require_relative 'helper'
class Reline::WithinPipeTest < Reline::TestCase
def setup
Reline.send(:test_mode)
- @encoding = Reline::IOGate.encoding
+ @encoding = Reline.core.encoding
@input_reader, @writer = IO.pipe(@encoding)
Reline.input = @input_reader
@reader, @output_writer = IO.pipe(@encoding)
@output = Reline.output = @output_writer
- @config = Reline.send(:core).config
- @config.keyseq_timeout *= 600 if defined?(RubyVM::JIT) && RubyVM::JIT.enabled? # for --jit-wait CI
- @line_editor = Reline.send(:core).line_editor
+ @config = Reline.core.config
+ @config.keyseq_timeout *= 600 if defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled? # for --jit-wait CI
+ @line_editor = Reline.core.line_editor
end
def teardown
@@ -23,7 +23,6 @@ class Reline::WithinPipeTest < Reline::TestCase
@reader.close
@output_writer.close
@config.reset
- @config.reset_default_key_bindings
Reline.test_reset
end
diff --git a/test/reline/yamatanooroti/multiline_repl b/test/reline/yamatanooroti/multiline_repl
index 473d9d0f00..8b82be60f4 100755
--- a/test/reline/yamatanooroti/multiline_repl
+++ b/test/reline/yamatanooroti/multiline_repl
@@ -1,18 +1,18 @@
#!/usr/bin/env ruby
+
+require 'bundler'
+Bundler.require
+
require 'reline'
require 'optparse'
require_relative 'termination_checker'
opt = OptionParser.new
-opt.on('--prompt-list-cache-timeout VAL') { |v|
- Reline::LineEditor.__send__(:remove_const, :PROMPT_LIST_CACHE_TIMEOUT)
- Reline::LineEditor::PROMPT_LIST_CACHE_TIMEOUT = v.to_f
-}
opt.on('--dynamic-prompt') {
Reline.prompt_proc = proc { |lines|
lines.each_with_index.map { |l, i|
- '[%04d]> ' % i
+ "\e[1m[%04d]>\e[m " % i
}
}
}
@@ -27,8 +27,54 @@ opt.on('--broken-dynamic-prompt') {
opt.on('--dynamic-prompt-returns-empty') {
Reline.prompt_proc = proc { |l| [] }
}
+opt.on('--dynamic-prompt-with-newline') {
+ Reline.prompt_proc = proc { |lines|
+ range = lines.size > 1 ? (0..(lines.size - 2)) : (0..0)
+ lines[range].each_with_index.map { |l, i|
+ '[%04d\n]> ' % i
+ }
+ }
+}
+opt.on('--broken-dynamic-prompt-assert-no-escape-sequence') {
+ Reline.prompt_proc = proc { |lines|
+ has_escape_sequence = lines.join.include?("\e")
+ (lines.size + 1).times.map { |i|
+ has_escape_sequence ? 'error>' : '[%04d]> ' % i
+ }
+ }
+}
+opt.on('--color-bold') {
+ Reline.output_modifier_proc = ->(output, complete:){
+ output.gsub(/./) { |c| "\e[1m#{c}\e[0m" }
+ }
+}
+opt.on('--dynamic-prompt-show-line') {
+ Reline.prompt_proc = proc { |lines|
+ lines.map { |l|
+ '[%4.4s]> ' % l
+ }
+ }
+}
+
+def assert_auto_indent_params(lines, line_index, byte_pointer, is_newline)
+ raise 'Wrong lines type' unless lines.all?(String)
+
+ line = lines[line_index]
+ raise 'Wrong line_index value' unless line
+
+ # The condition `byte_pointer <= line.bytesize` is not satisfied. Maybe bug.
+ # Instead, loose constraint `byte_pointer <= line.bytesize + 1` seems to be satisfied when is_newline is false.
+ return if is_newline
+
+ raise 'byte_pointer out of bounds' unless byte_pointer <= line.bytesize + 1
+ raise 'Invalid byte_pointer' unless line.byteslice(0, byte_pointer).valid_encoding?
+end
+
opt.on('--auto-indent') {
- AutoIndent.new
+ Reline.auto_indent_proc = lambda do |lines, line_index, byte_pointer, is_newline|
+ assert_auto_indent_params(lines, line_index, byte_pointer, is_newline)
+ AutoIndent.calculate_indent(lines, line_index, byte_pointer, is_newline)
+ end
}
opt.on('--dialog VAL') { |v|
Reline.add_dialog_proc(:simple_dialog, lambda {
@@ -55,6 +101,15 @@ opt.on('--dialog VAL') { |v|
natural to read
and easy to write.
RUBY
+ elsif v.include?('fullwidth')
+ contents = <<~RUBY.split("\n")
+ Rubyã¨ã¯...
+
+ オープンソースã®å‹•çš„ãªãƒ—ログラミン
+ グ言語ã§ã€ã‚·ãƒ³ãƒ—ルã•ã¨é«˜ã„生産性を
+ å‚™ãˆã¦ã„ã¾ã™ã€‚エレガントãªæ–‡æ³•ã‚’æŒ
+ ã¡ã€è‡ªç„¶ã«èª­ã¿æ›¸ããŒã§ãã¾ã™ã€‚
+ RUBY
end
if v.include?('scrollkey')
dialog.trap_key = nil
@@ -74,24 +129,89 @@ opt.on('--dialog VAL') { |v|
if v.include?('scrollbar')
scrollbar = true
end
- Reline::DialogRenderInfo.new(pos: cursor_pos, contents: contents, height: height, scrollbar: scrollbar)
+ if v.include?('alt-scrollbar')
+ scrollbar = true
+ end
+ Reline::DialogRenderInfo.new(pos: cursor_pos, contents: contents, height: height, scrollbar: scrollbar, face: :completion_dialog)
})
+ if v.include?('alt-scrollbar')
+ ENV['RELINE_ALT_SCROLLBAR'] = '1'
+ end
}
opt.on('--complete') {
Reline.completion_proc = lambda { |target, preposing = nil, postposing = nil|
%w{String ScriptError SyntaxError Signal}.select{ |c| c.start_with?(target) }
}
}
+opt.on('--complete-menu-with-perfect-match') {
+ Reline.completion_proc = lambda { |target, preposing = nil, postposing = nil|
+ %w{abs abs2}.select{ |c| c.start_with?(target) }
+ }
+}
opt.on('--autocomplete') {
Reline.autocompletion = true
Reline.completion_proc = lambda { |target, preposing = nil, postposing = nil|
%w{String Struct Symbol ScriptError SyntaxError Signal}.select{ |c| c.start_with?(target) }
}
}
+opt.on('--autocomplete-empty') {
+ Reline.autocompletion = true
+ Reline.completion_proc = lambda { |target, preposing = nil, postposing = nil| [] }
+}
opt.on('--autocomplete-long') {
Reline.autocompletion = true
Reline.completion_proc = lambda { |target, preposing = nil, postposing = nil|
- %w{String Struct Symbol StopIteration SystemCallError SystemExit SystemStackError ScriptError SyntaxError Signal SizedQueue Set SecureRandom Socket StringIO StringScanner Shellwords Syslog Singleton SDBM}.select{ |c| c.start_with?(target) }
+ %w{
+ String
+ Struct
+ Symbol
+ StopIteration
+ SystemCallError
+ SystemExit
+ SystemStackError
+ ScriptError
+ SyntaxError
+ Signal
+ SizedQueue
+ Set
+ SecureRandom
+ Socket
+ StringIO
+ StringScanner
+ Shellwords
+ Syslog
+ Singleton
+ SDBM
+ }.select{ |c| c.start_with?(target) }
+ }
+}
+opt.on('--autocomplete-super-long') {
+ Reline.autocompletion = true
+ Reline.completion_proc = lambda { |target, preposing = nil, postposing = nil|
+ c = +'A'
+ 2000.times.map{ s = "Str_#{c}"; c.succ!; s }.select{ |c| c.start_with?(target) }
+ }
+}
+
+opt.on('--autocomplete-width-long') {
+ Reline.autocompletion = true
+ Reline.completion_proc = lambda { |target, preposing = nil, postposing = nil|
+ %w{
+ remove_instance_variable
+ respond_to?
+ ruby2_keywords
+ rand
+ readline
+ readlines
+ require
+ require_relative
+ raise
+ respond_to_missing?
+ redo
+ rescue
+ retry
+ return
+ }.select{ |c| c.start_with?(target) }
}
}
opt.parse!(ARGV)
@@ -102,10 +222,9 @@ rescue
end
begin
- prompt = ENV['RELINE_TEST_PROMPT'] || 'prompt> '
+ prompt = ENV['RELINE_TEST_PROMPT'] || "\e[1mprompt>\e[m "
puts 'Multiline REPL.'
- checker = TerminationChecker.new
- while code = Reline.readmultiline(prompt, true) { |code| checker.terminated?(code) }
+ while code = Reline.readmultiline(prompt, true) { |code| TerminationChecker.terminated?(code) }
case code.chomp
when 'exit', 'quit', 'q'
exit 0
diff --git a/test/reline/yamatanooroti/termination_checker.rb b/test/reline/yamatanooroti/termination_checker.rb
index 9c2c3ae740..b97c798c59 100644
--- a/test/reline/yamatanooroti/termination_checker.rb
+++ b/test/reline/yamatanooroti/termination_checker.rb
@@ -1,30 +1,26 @@
require 'ripper'
-require 'irb/ruby-lex'
-class TerminationChecker < RubyLex
- def terminated?(code)
- code.gsub!(/\n*$/, '').concat("\n")
- @tokens = Ripper.lex(code)
- continue = process_continue
- code_block_open = check_code_block(code)
- indent = process_nesting_level
- ltype = process_literal_type
- if code_block_open or ltype or continue or indent > 0
- false
- else
- true
- end
+module TerminationChecker
+ def self.terminated?(code)
+ Ripper.sexp(code) ? true : false
end
end
-class AutoIndent < RubyLex
- def initialize
- set_input(self)
- context = Struct.new(:auto_indent_mode, :workspace).new(true, nil)
- set_auto_indent(context)
+module AutoIndent
+ def self.calculate_indent(lines, line_index, byte_pointer, is_newline)
+ if is_newline
+ 2 * nesting_level(lines[0..line_index - 1])
+ else
+ lines = lines.dup
+ lines[line_index] = lines[line_index]&.byteslice(0, byte_pointer)
+ prev_level = nesting_level(lines[0..line_index - 1])
+ level = nesting_level(lines[0..line_index])
+ 2 * level if level < prev_level
+ end
end
- def auto_indent(&block)
- Reline.auto_indent_proc = block
+ def self.nesting_level(lines)
+ code = lines.join("\n")
+ code.scan(/if|def|\(|\[|\{/).size - code.scan(/end|\)|\]|\}/).size
end
end
diff --git a/test/reline/yamatanooroti/test_rendering.rb b/test/reline/yamatanooroti/test_rendering.rb
index 58d23a40fd..c90d3d6a7f 100644
--- a/test/reline/yamatanooroti/test_rendering.rb
+++ b/test/reline/yamatanooroti/test_rendering.rb
@@ -3,7 +3,34 @@ require 'reline'
begin
require 'yamatanooroti'
- class Reline::TestRendering < Yamatanooroti::TestCase
+ class Reline::RenderingTest < Yamatanooroti::TestCase
+
+ FACE_CONFIGS = { no_config: "", valid_config: <<~VALID_CONFIG, incomplete_config: <<~INCOMPLETE_CONFIG }
+ require "reline"
+ Reline::Face.config(:completion_dialog) do |face|
+ face.define :default, foreground: :white, background: :blue
+ face.define :enhanced, foreground: :white, background: :magenta
+ face.define :scrollbar, foreground: :white, background: :blue
+ end
+ VALID_CONFIG
+ require "reline"
+ Reline::Face.config(:completion_dialog) do |face|
+ face.define :default, foreground: :white, background: :black
+ face.define :scrollbar, foreground: :white, background: :cyan
+ end
+ INCOMPLETE_CONFIG
+
+ def iterate_over_face_configs(&block)
+ FACE_CONFIGS.each do |config_name, face_config|
+ config_file = Tempfile.create(%w{face_config- .rb})
+ config_file.write face_config
+ block.call(config_name, config_file)
+ config_file.close
+ ensure
+ File.delete(config_file)
+ end
+ end
+
def setup
@pwd = Dir.pwd
suffix = '%010d' % Random.rand(0..65535)
@@ -121,6 +148,7 @@ begin
end
def test_finish_autowrapped_line_in_the_middle_of_multilines
+ omit if RUBY_VERSION < '2.7'
start_terminal(30, 16, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
write("<<~EOM\n ABCDEFG\nEOM\n")
close
@@ -169,9 +197,12 @@ begin
LINES
start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
write(":a\n\C-[k")
+ write("i\n:a")
+ write("\C-[h")
close
assert_screen(<<~EOC)
- Multiline REPL.
+ (ins)prompt> :a
+ => :a
(ins)prompt> :a
=> :a
(cmd)prompt> :a
@@ -236,6 +267,21 @@ begin
EOC
end
+ def test_esc_input
+ omit if Reline::IOGate.win?
+ start_terminal(5, 20, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
+ write("def\C-aabc")
+ write("\e") # single ESC
+ sleep 1
+ write("A")
+ write("B\eAC") # ESC + A (M-A, specified ed_unassigned in Reline::KeyActor::Emacs)
+ close
+ assert_screen(<<~EOC)
+ Multiline REPL.
+ prompt> abcABCdef
+ EOC
+ end
+
def test_prompt_with_escape_sequence
ENV['RELINE_TEST_PROMPT'] = "\1\e[30m\2prompt> \1\e[m\2"
start_terminal(5, 20, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
@@ -263,6 +309,21 @@ begin
EOC
end
+ def test_readline_with_multiline_input
+ start_terminal(5, 50, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --dynamic-prompt}, startup_message: 'Multiline REPL.')
+ write("def foo\n bar\nend\n")
+ write("Reline.readline('prompt> ')\n")
+ write("\C-p\C-p")
+ close
+ assert_screen(<<~EOC)
+ => :foo
+ [0000]> Reline.readline('prompt> ')
+ prompt> def foo
+ bar
+ end
+ EOC
+ end
+
def test_multiline_and_autowrap
start_terminal(10, 20, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
write("def aaaaaaaaaa\n 33333333\n end\C-a\C-pputs\C-e\e\C-m888888888888888")
@@ -280,6 +341,23 @@ begin
EOC
end
+ def test_multiline_add_new_line_and_autowrap
+ start_terminal(10, 20, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
+ write("def aaaaaaaaaa")
+ write("\n")
+ write(" bbbbbbbbbbbb")
+ write("\n")
+ close
+ assert_screen(<<~EOC)
+ Multiline REPL.
+ prompt> def aaaaaaaa
+ aa
+ prompt> bbbbbbbbbb
+ bb
+ prompt>
+ EOC
+ end
+
def test_clear
start_terminal(10, 15, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
write("3\C-l")
@@ -404,6 +482,9 @@ begin
write("def a\n 8\nend\ndef b\n 3\nend\C-s8")
close
assert_screen(<<~EOC)
+ prompt> 8
+ prompt> end
+ => :a
(i-search)`8'def a
(i-search)`8' 8
(i-search)`8'end
@@ -415,6 +496,9 @@ begin
write("def a\n 8\nend\ndef b\n 3\nend\C-r8\C-j")
close
assert_screen(<<~EOC)
+ prompt> 8
+ prompt> end
+ => :a
prompt> def a
prompt> 8
prompt> end
@@ -424,10 +508,10 @@ begin
def test_binding_for_vi_movement_mode
write_inputrc <<~LINES
set editing-mode vi
- "\\C-j": vi-movement-mode
+ "\\C-a": vi-movement-mode
LINES
start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
- write(":1234\C-jhhhi0")
+ write(":1234\C-ahhhi0")
close
assert_screen(<<~EOC)
Multiline REPL.
@@ -435,39 +519,34 @@ begin
EOC
end
- def test_prompt_list_caching
- start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --prompt-list-cache-timeout 10 --dynamic-prompt}, startup_message: 'Multiline REPL.')
+ def test_broken_prompt_list
+ start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --broken-dynamic-prompt}, startup_message: 'Multiline REPL.')
write("def hoge\n 3\nend")
close
assert_screen(<<~EOC)
Multiline REPL.
[0000]> def hoge
[0001]> 3
- [0002]> end
+ [0001]> end
EOC
end
- def test_broken_prompt_list
- start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --broken-dynamic-prompt}, startup_message: 'Multiline REPL.')
- write("def hoge\n 3\nend")
+ def test_no_escape_sequence_passed_to_dynamic_prompt
+ start_terminal(10, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --autocomplete --color-bold --broken-dynamic-prompt-assert-no-escape-sequence}, startup_message: 'Multiline REPL.')
+ write("%[ S")
+ write("\n")
close
assert_screen(<<~EOC)
Multiline REPL.
- [0000]> def hoge
- [0001]> 3
- [0001]> end
+ [0000]> %[ S
+ [0001]>
EOC
end
- def test_enable_bracketed_paste
- omit if Reline::IOGate.win?
- write_inputrc <<~LINES
- set enable-bracketed-paste on
- LINES
+ def test_bracketed_paste
+ omit if Reline.core.io_gate.win?
start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
- write("\e[200~,")
- write("def hoge\n 3\nend")
- write("\e[200~.")
+ write("\e[200~def hoge\r\t3\rend\e[201~")
close
assert_screen(<<~EOC)
Multiline REPL.
@@ -477,6 +556,35 @@ begin
EOC
end
+ def test_bracketed_paste_with_undo
+ omit if Reline.core.io_gate.win?
+ start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
+ write("abc")
+ write("\e[200~def hoge\r\t3\rend\e[201~")
+ write("\C-_")
+ close
+ assert_screen(<<~EOC)
+ Multiline REPL.
+ prompt> abc
+ EOC
+ end
+
+ def test_bracketed_paste_with_redo
+ omit if Reline.core.io_gate.win?
+ start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
+ write("abc")
+ write("\e[200~def hoge\r\t3\rend\e[201~")
+ write("\C-_")
+ write("\M-\C-_")
+ close
+ assert_screen(<<~EOC)
+ Multiline REPL.
+ prompt> abcdef hoge
+ prompt> 3
+ prompt> end
+ EOC
+ end
+
def test_backspace_until_returns_to_initial
start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
write("ABC")
@@ -631,6 +739,31 @@ begin
EOC
end
+ def test_longer_than_screen_height_nearest_cursor_with_scroll_back
+ start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
+ write(<<~EOC.chomp)
+ if 1
+ if 2
+ if 3
+ if 4
+ puts
+ end
+ end
+ end
+ end
+ EOC
+ write("\C-p" * 4 + "\C-e" + "\C-p" * 4)
+ write("2")
+ close
+ assert_screen(<<~EOC)
+ prompt> if 12
+ prompt> if 2
+ prompt> if 3
+ prompt> if 4
+ prompt> puts
+ EOC
+ end
+
def test_update_cursor_correctly_when_just_cursor_moving
start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
write("def hoge\n 01234678")
@@ -648,6 +781,66 @@ begin
EOC
end
+ def test_auto_indent
+ start_terminal(10, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --auto-indent}, startup_message: 'Multiline REPL.')
+ "def hoge\nputs(\n1,\n2\n)\nend".lines do |line|
+ write line
+ end
+ close
+ assert_screen(<<~EOC)
+ Multiline REPL.
+ prompt> def hoge
+ prompt> puts(
+ prompt> 1,
+ prompt> 2
+ prompt> )
+ prompt> end
+ EOC
+ end
+
+ def test_auto_indent_when_inserting_line
+ start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --auto-indent}, startup_message: 'Multiline REPL.')
+ write 'aa(bb(cc(dd(ee('
+ write "\C-b" * 5 + "\n"
+ close
+ assert_screen(<<~EOC)
+ Multiline REPL.
+ prompt> aa(bb(cc(d
+ prompt> d(ee(
+ EOC
+ end
+
+ def test_auto_indent_multibyte_insert_line
+ start_terminal(10, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --auto-indent}, startup_message: 'Multiline REPL.')
+ write "if true\n"
+ write "ã‚ã„ã†ãˆãŠ\n"
+ 4.times { write "\C-b\C-b\C-b\C-b\e\r" }
+ close
+ assert_screen(<<~EOC)
+ Multiline REPL.
+ prompt> if true
+ prompt> ã‚
+ prompt> ã„
+ prompt> ã†
+ prompt> ãˆ
+ prompt> ãŠ
+ prompt>
+ EOC
+ end
+
+ def test_newline_after_wrong_indent
+ start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --auto-indent}, startup_message: 'Multiline REPL.')
+ write "if 1\n aa"
+ write "\n"
+ close
+ assert_screen(<<~EOC)
+ Multiline REPL.
+ prompt> if 1
+ prompt> aa
+ prompt>
+ EOC
+ end
+
def test_suppress_auto_indent_just_after_pasted
start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --auto-indent}, startup_message: 'Multiline REPL.')
write("def hoge\n [[\n 3]]\ned")
@@ -677,6 +870,20 @@ begin
EOC
end
+ def test_auto_indent_with_various_spaces
+ start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --auto-indent}, startup_message: 'Multiline REPL.')
+ write "(\n\C-v"
+ write "\C-k\n\C-v"
+ write "\C-k)"
+ close
+ assert_screen(<<~EOC)
+ Multiline REPL.
+ prompt> (
+ prompt> ^K
+ prompt> )
+ EOC
+ end
+
def test_autowrap_in_the_middle_of_a_line
start_terminal(5, 20, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
write("def abcdefg; end\C-b\C-b\C-b\C-b\C-b")
@@ -730,7 +937,7 @@ begin
end
def test_meta_key
- start_terminal(50, 200, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
+ start_terminal(30, 20, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
write("def ge\M-bho")
close
assert_screen(<<~EOC)
@@ -739,8 +946,18 @@ begin
EOC
end
+ def test_not_meta_key
+ start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
+ write("ãŠã ã‚“ã”") # "ã " in UTF-8 contains "\xA0"
+ close
+ assert_screen(<<~EOC)
+ Multiline REPL.
+ prompt> ãŠã ã‚“ã”
+ EOC
+ end
+
def test_force_enter
- start_terminal(50, 200, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
+ start_terminal(30, 120, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
write("def hoge\nend\C-p\C-e")
write("\M-\x0D")
close
@@ -752,39 +969,42 @@ begin
EOC
end
- def test_cyrillic_chars
- omit unless Reline::IOGate.win?
- start_terminal(50, 50, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
- write("`chcp 850`\n")
- write("`chcp`\n")
- write("def гопота; 3; end\n")
- write("гопота\n")
- close
+ def test_nontty
+ omit if Reline.core.io_gate.win?
+ cmd = %Q{ruby -e 'puts(%Q{ello\C-ah\C-e})' | ruby -I#{@pwd}/lib -rreline -e 'p Reline.readline(%{> })' | ruby -e 'print STDIN.read'}
+ start_terminal(40, 50, ['bash', '-c', cmd])
+ sleep 1
+ close rescue nil
assert_screen(<<~'EOC')
- Multiline REPL.
- prompt> `chcp 850`
- => "Active code page: 850\n"
- prompt> `chcp`
- => "Active code page: 850\n"
- prompt> def гопота; 3; end
- => :гопота
- prompt> гопота
- => 3
- prompt>
+ > hello
+ "hello"
EOC
end
- def test_with_newline
- omit if Reline::IOGate.win?
+ def test_eof_with_newline
+ omit if Reline.core.io_gate.win?
cmd = %Q{ruby -e 'print(%Q{abc def \\e\\r})' | ruby -I#{@pwd}/lib -rreline -e 'p Reline.readline(%{> })'}
- start_terminal(50, 50, ['bash', '-c', cmd])
- close
+ start_terminal(40, 50, ['bash', '-c', cmd])
+ sleep 1
+ close rescue nil
assert_screen(<<~'EOC')
> abc def
"abc def "
EOC
end
+ def test_eof_without_newline
+ omit if Reline.core.io_gate.win?
+ cmd = %Q{ruby -e 'print(%{hello})' | ruby -I#{@pwd}/lib -rreline -e 'p Reline.readline(%{> })'}
+ start_terminal(40, 50, ['bash', '-c', cmd])
+ sleep 1
+ close rescue nil
+ assert_screen(<<~'EOC')
+ > hello
+ "hello"
+ EOC
+ end
+
def test_em_set_mark_and_em_exchange_mark
start_terminal(10, 50, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
write("aaa bbb ccc ddd\M-b\M-b\M-\x20\M-b\C-x\C-xX\C-x\C-xY")
@@ -795,6 +1015,18 @@ begin
EOC
end
+ def test_multiline_completion
+ start_terminal(10, 50, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --complete}, startup_message: 'Multiline REPL.')
+ write("def hoge\n St\n St\C-p\t")
+ close
+ assert_screen(<<~'EOC')
+ Multiline REPL.
+ prompt> def hoge
+ prompt> String
+ prompt> St
+ EOC
+ end
+
def test_completion_journey_2nd_line
write_inputrc <<~LINES
set editing-mode vi
@@ -822,44 +1054,127 @@ begin
EOC
end
- def test_simple_dialog
- start_terminal(20, 50, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --dialog simple}, startup_message: 'Multiline REPL.')
- write('a')
- write('b')
- write('c')
- write("\C-h")
+ def test_completion_menu_is_displayed_horizontally
+ start_terminal(20, 50, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --complete}, startup_message: 'Multiline REPL.')
+ write("S\t\t")
+ close
+ assert_screen(<<~'EOC')
+ Multiline REPL.
+ prompt> S
+ ScriptError String
+ Signal SyntaxError
+ EOC
+ end
+
+ def test_show_all_if_ambiguous_on
+ write_inputrc <<~LINES
+ set show-all-if-ambiguous on
+ LINES
+ start_terminal(20, 50, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --complete}, startup_message: 'Multiline REPL.')
+ write("S\t")
close
assert_screen(<<~'EOC')
Multiline REPL.
- prompt> ab
- Ruby is...
- A dynamic, open source programming
- language with a focus on simplicity
- and productivity. It has an elegant
- syntax that is natural to read and
- easy to write.
+ prompt> S
+ ScriptError String
+ Signal SyntaxError
EOC
end
- def test_simple_dialog_at_right_edge
- start_terminal(20, 40, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --dialog simple}, startup_message: 'Multiline REPL.')
- write('a')
- write('b')
- write('c')
- write("\C-h")
+ def test_show_all_if_ambiguous_on_and_menu_with_perfect_match
+ write_inputrc <<~LINES
+ set show-all-if-ambiguous on
+ LINES
+ start_terminal(20, 50, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --complete-menu-with-perfect-match}, startup_message: 'Multiline REPL.')
+ write("a\t")
close
assert_screen(<<~'EOC')
Multiline REPL.
- prompt> ab
- Ruby is...
- A dynamic, open source programming
- language with a focus on simplicity
- and productivity. It has an elegant
- syntax that is natural to read and
- easy to write.
+ prompt> abs
+ abs abs2
EOC
end
+ def test_simple_dialog
+ iterate_over_face_configs do |config_name, config_file|
+ start_terminal(20, 50, %W{ruby -I#{@pwd}/lib -r#{config_file.path} #{@pwd}/test/reline/yamatanooroti/multiline_repl --dialog simple}, startup_message: 'Multiline REPL.')
+ write('a')
+ write('b')
+ write('c')
+ write("\C-h")
+ close
+ assert_screen(<<~'EOC', "Failed with `#{config_name}` in Face")
+ Multiline REPL.
+ prompt> ab
+ Ruby is...
+ A dynamic, open source programming
+ language with a focus on simplicity
+ and productivity. It has an elegant
+ syntax that is natural to read and
+ easy to write.
+ EOC
+ end
+ end
+
+ def test_simple_dialog_at_right_edge
+ iterate_over_face_configs do |config_name, config_file|
+ start_terminal(20, 40, %W{ruby -I#{@pwd}/lib -r#{config_file.path} #{@pwd}/test/reline/yamatanooroti/multiline_repl --dialog simple}, startup_message: 'Multiline REPL.')
+ write('a')
+ write('b')
+ write('c')
+ write("\C-h")
+ close
+ assert_screen(<<~'EOC')
+ Multiline REPL.
+ prompt> ab
+ Ruby is...
+ A dynamic, open source programming
+ language with a focus on simplicity
+ and productivity. It has an elegant
+ syntax that is natural to read and
+ easy to write.
+ EOC
+ end
+ end
+
+ def test_dialog_scroll_pushup_condition
+ iterate_over_face_configs do |config_name, config_file|
+ start_terminal(10, 50, %W{ruby -I#{@pwd}/lib -r#{config_file.path} #{@pwd}/test/reline/yamatanooroti/multiline_repl --autocomplete}, startup_message: 'Multiline REPL.')
+ write("\n" * 10)
+ write("if 1\n sSts\nend")
+ write("\C-p\C-h\C-e\C-h")
+ close
+ assert_screen(<<~'EOC')
+ prompt>
+ prompt>
+ prompt>
+ prompt>
+ prompt>
+ prompt>
+ prompt> if 1
+ prompt> St
+ prompt> enString
+ Struct
+ EOC
+ end
+ end
+
+ def test_simple_dialog_with_scroll_screen
+ iterate_over_face_configs do |config_name, config_file|
+ start_terminal(5, 50, %W{ruby -I#{@pwd}/lib -r#{config_file.path} #{@pwd}/test/reline/yamatanooroti/multiline_repl --dialog simple}, startup_message: 'Multiline REPL.')
+ write("if 1\n 2\n 3\n 4\n 5\n 6")
+ write("\C-p\C-n\C-p\C-p\C-p#")
+ close
+ assert_screen(<<~'EOC')
+ prompt> 2
+ prompt> 3#
+ prompt> 4
+ prompt> 5 Ruby is...
+ prompt> 6 A dynamic, open source programming
+ EOC
+ end
+ end
+
def test_autocomplete_at_bottom
start_terminal(15, 50, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --autocomplete}, startup_message: 'Multiline REPL.')
write('def hoge' + "\C-m" * 10 + "end\C-p ")
@@ -906,8 +1221,50 @@ begin
assert_screen(<<~'EOC')
Multiline REPL.
prompt> St
- r String
- Struct
+ r
+ String
+ Struct
+ EOC
+ end
+
+ def test_autocomplete_target_at_end_of_line
+ start_terminal(20, 20, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --autocomplete}, startup_message: 'Multiline REPL.')
+ write(' ')
+ write('Str')
+ write("\C-i")
+ close
+ assert_screen(<<~'EOC')
+ Multiline REPL.
+ prompt> Str
+ ing String
+ Struct
+ EOC
+ end
+
+ def test_autocomplete_completed_input_is_wrapped
+ start_terminal(20, 20, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --autocomplete}, startup_message: 'Multiline REPL.')
+ write(' ')
+ write('Str')
+ write("\C-i")
+ close
+ assert_screen(<<~'EOC')
+ Multiline REPL.
+ prompt> Stri
+ ng String
+ Struct
+ EOC
+ end
+
+ def test_force_insert_before_autocomplete
+ start_terminal(20, 20, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --autocomplete}, startup_message: 'Multiline REPL.')
+ write('Sy')
+ write(";St\t\t")
+ close
+ assert_screen(<<~'EOC')
+ Multiline REPL.
+ prompt> Sy;Struct
+ String
+ Struct
EOC
end
@@ -957,6 +1314,40 @@ begin
EOC
end
+ def test_dialog_with_fullwidth_chars
+ ENV['RELINE_TEST_PROMPT'] = '> '
+ start_terminal(20, 5, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --dialog fullwidth,scrollkey,scrollbar}, startup_message: 'Multiline REPL.')
+ 6.times{ write('j') }
+ close
+ assert_screen(<<~'EOC')
+ Multi
+ line
+ REPL.
+ >
+ オー
+ グ言▄
+ å‚™ãˆâ–ˆ
+ ã¡ã€â–ˆ
+ EOC
+ end
+
+ def test_dialog_with_fullwidth_chars_split
+ ENV['RELINE_TEST_PROMPT'] = '> '
+ start_terminal(20, 6, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --dialog fullwidth,scrollkey,scrollbar}, startup_message: 'Multiline REPL.')
+ 6.times{ write('j') }
+ close
+ assert_screen(<<~'EOC')
+ Multil
+ ine RE
+ PL.
+ >
+ オー
+ グ言 ▄
+ 備㈠█
+ ã¡ã€ â–ˆ
+ EOC
+ end
+
def test_autocomplete_empty
start_terminal(20, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --autocomplete}, startup_message: 'Multiline REPL.')
write('Street')
@@ -979,6 +1370,32 @@ begin
EOC
end
+ def test_autocomplete_empty_string
+ start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --autocomplete}, startup_message: 'Multiline REPL.')
+ write("\C-i")
+ close
+ assert_screen(<<~'EOC')
+ Multiline REPL.
+ prompt> String
+ String â–ˆ
+ Struct â–€
+ Symbol
+ EOC
+ end
+
+ def test_paste_code_with_tab_indent_does_not_fail
+ start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --autocomplete-empty}, startup_message: 'Multiline REPL.')
+ write("2.times do\n\tputs\n\tputs\nend")
+ close
+ assert_screen(<<~'EOC')
+ Multiline REPL.
+ prompt> 2.times do
+ prompt> puts
+ prompt> puts
+ prompt> end
+ EOC
+ end
+
def test_autocomplete_after_2nd_line
start_terminal(20, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --autocomplete}, startup_message: 'Multiline REPL.')
write("def hoge\n Str")
@@ -1007,6 +1424,23 @@ begin
EOC
end
+ def test_rerender_multiple_dialog
+ start_terminal(20, 60, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --autocomplete --dialog simple}, startup_message: 'Multiline REPL.')
+ write("if\n abcdef\n 123456\n 456789\nend\C-p\C-p\C-p\C-p Str")
+ write("\t")
+ close
+ assert_screen(<<~'EOC')
+ Multiline REPL.
+ prompt> if String
+ prompt> aStringRuby is...
+ prompt> 1StructA dynamic, open source programming
+ prompt> 456789 language with a focus on simplicity
+ prompt> end and productivity. It has an elegant
+ syntax that is natural to read and
+ easy to write.
+ EOC
+ end
+
def test_autocomplete_long_with_scrollbar
start_terminal(20, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --autocomplete-long}, startup_message: 'Multiline REPL.')
write('S')
@@ -1057,6 +1491,59 @@ begin
EOC
end
+ def test_autocomplete_super_long_scroll_to_bottom
+ start_terminal(20, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --autocomplete-super-long}, startup_message: 'Multiline REPL.')
+ shift_tab = [27, 91, 90]
+ write('S' + shift_tab.map(&:chr).join)
+ close
+ assert_screen(<<~'EOC')
+ Multiline REPL.
+ prompt> Str_BXX
+ Str_BXJ
+ Str_BXK
+ Str_BXL
+ Str_BXM
+ Str_BXN
+ Str_BXO
+ Str_BXP
+ Str_BXQ
+ Str_BXR
+ Str_BXS
+ Str_BXT
+ Str_BXU
+ Str_BXV
+ Str_BXW
+ Str_BXXâ–„
+ EOC
+ end
+
+ def test_autocomplete_super_long_and_backspace
+ start_terminal(20, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --autocomplete-super-long}, startup_message: 'Multiline REPL.')
+ shift_tab = [27, 91, 90]
+ write('S' + shift_tab.map(&:chr).join)
+ write("\C-h")
+ close
+ assert_screen(<<~'EOC')
+ Multiline REPL.
+ prompt> Str_BX
+ Str_BX â–ˆ
+ Str_BXAâ–ˆ
+ Str_BXBâ–ˆ
+ Str_BXCâ–ˆ
+ Str_BXDâ–ˆ
+ Str_BXEâ–ˆ
+ Str_BXFâ–ˆ
+ Str_BXGâ–ˆ
+ Str_BXHâ–ˆ
+ Str_BXI
+ Str_BXJ
+ Str_BXK
+ Str_BXL
+ Str_BXM
+ Str_BXN
+ EOC
+ end
+
def test_dialog_callback_returns_nil
start_terminal(20, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --dialog nil}, startup_message: 'Multiline REPL.')
write('a')
@@ -1067,6 +1554,363 @@ begin
EOC
end
+ def test_dialog_narrower_than_screen
+ start_terminal(20, 11, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --dialog simple}, startup_message: 'Multiline REPL.')
+ close
+ assert_screen(<<~'EOC')
+ Multiline R
+ EPL.
+ prompt>
+ Ruby is...
+ A dynamic,
+ language wi
+ and product
+ syntax that
+ easy to wri
+ EOC
+ end
+
+ def test_dialog_narrower_than_screen_with_scrollbar
+ start_terminal(20, 11, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --autocomplete-long}, startup_message: 'Multiline REPL.')
+ write('S' + "\C-i" * 3)
+ close
+ assert_screen(<<~'EOC')
+ Multiline R
+ EPL.
+ prompt> Sym
+ String â–ˆ
+ Struct â–ˆ
+ Symbol â–ˆ
+ StopIteratâ–ˆ
+ SystemCallâ–ˆ
+ SystemExitâ–ˆ
+ SystemStacâ–ˆ
+ ScriptErroâ–ˆ
+ SyntaxErroâ–ˆ
+ Signal â–ˆ
+ SizedQueueâ–ˆ
+ Set
+ SecureRand
+ Socket
+ StringIO
+ EOC
+ end
+
+ def test_dialog_with_fullwidth_scrollbar
+ start_terminal(20, 40, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --dialog simple,scrollkey,alt-scrollbar}, startup_message: 'Multiline REPL.')
+ close
+ assert_screen(<<~'EOC')
+ Multiline REPL.
+ prompt>
+ Ruby is... ::
+ A dynamic, open source programming ::
+ language with a focus on simplicity''
+ and productivity. It has an elegant
+ EOC
+ end
+
+ def test_rerender_argument_prompt_after_pasting
+ start_terminal(20, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
+ write('abcdef')
+ write("\M-3\C-h")
+ close
+ assert_screen(<<~'EOC')
+ Multiline REPL.
+ prompt> abc
+ EOC
+ end
+
+ def test_autocomplete_old_dialog_width_greater_than_dialog_width
+ start_terminal(40, 40, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --autocomplete-width-long}, startup_message: 'Multiline REPL.')
+ write("0+ \n12345678901234")
+ write("\C-p")
+ write("r")
+ write("a")
+ close
+ assert_screen(<<~'EOC')
+ Multiline REPL.
+ prompt> 0+ ra
+ prompt> 123rand 901234
+ raise
+ EOC
+ end
+
+ def test_scroll_at_bottom_for_dialog
+ start_terminal(10, 40, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --autocomplete}, startup_message: 'Multiline REPL.')
+ write("\n\n\n\n\n\n\n\n\n\n\n")
+ write("def hoge\n\nend\C-p\C-e")
+ write(" S")
+ close
+ assert_screen(<<~'EOC')
+ prompt>
+ prompt>
+ prompt>
+ prompt>
+ prompt>
+ prompt> def hoge
+ prompt> S
+ prompt> enString â–ˆ
+ Struct â–€
+ Symbol
+ EOC
+ end
+
+ def test_clear_dialog_in_pasting
+ start_terminal(10, 40, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --autocomplete}, startup_message: 'Multiline REPL.')
+ write("S")
+ write("tring ")
+ close
+ assert_screen(<<~'EOC')
+ Multiline REPL.
+ prompt> String
+ EOC
+ end
+
+ def test_prompt_with_newline
+ ENV['RELINE_TEST_PROMPT'] = "::\n> "
+ start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
+ write("def hoge\n 3\nend")
+ close
+ assert_screen(<<~'EOC')
+ Multiline REPL.
+ ::\n> def hoge
+ ::\n> 3
+ ::\n> end
+ EOC
+ end
+
+ def test_dynamic_prompt_with_newline
+ start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --dynamic-prompt-with-newline}, startup_message: 'Multiline REPL.')
+ write("def hoge\n 3\nend")
+ close
+ assert_screen(<<~'EOC')
+ Multiline REPL.
+ [0000\n]> def hoge
+ [0001\n]> 3
+ [0001\n]> end
+ EOC
+ end
+
+ def test_lines_passed_to_dynamic_prompt
+ start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --dynamic-prompt-show-line}, startup_message: 'Multiline REPL.')
+ write("if true")
+ write("\n")
+ close
+ assert_screen(<<~EOC)
+ Multiline REPL.
+ [if t]> if true
+ [ ]>
+ EOC
+ end
+
+ def test_clear_dialog_when_just_move_cursor_at_last_line
+ start_terminal(10, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --autocomplete}, startup_message: 'Multiline REPL.')
+ write("class A\n 3\nend\n\n\n")
+ write("\C-p\C-p\C-e; S")
+ write("\C-n")
+ write(";")
+ close
+ assert_screen(<<~'EOC')
+ prompt> 3
+ prompt> end
+ => 3
+ prompt>
+ prompt>
+ prompt> class A
+ prompt> 3; S
+ prompt> end;
+ EOC
+ end
+
+ def test_clear_dialog_when_adding_new_line_to_end_of_buffer
+ start_terminal(10, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --autocomplete}, startup_message: 'Multiline REPL.')
+ write("class A\n def a\n 3\n 3\n end\nend")
+ write("\n")
+ write("class S")
+ write("\n")
+ write(" 3")
+ close
+ assert_screen(<<~'EOC')
+ prompt> def a
+ prompt> 3
+ prompt> 3
+ prompt> end
+ prompt> end
+ => :a
+ prompt> class S
+ prompt> 3
+ EOC
+ end
+
+ def test_insert_newline_in_the_middle_of_buffer_just_after_dialog
+ start_terminal(10, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --autocomplete}, startup_message: 'Multiline REPL.')
+ write("class A\n def a\n 3\n end\nend")
+ write("\n")
+ write("\C-p\C-p\C-p\C-p\C-p\C-e\C-hS")
+ write("\M-\x0D")
+ write(" 3")
+ close
+ assert_screen(<<~'EOC')
+ prompt> 3
+ prompt> end
+ prompt> end
+ => :a
+ prompt> class S
+ prompt> 3
+ prompt> def a
+ prompt> 3
+ prompt> end
+ prompt> end
+ EOC
+ end
+
+ def test_incremental_search_on_not_last_line
+ start_terminal(10, 40, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --autocomplete}, startup_message: 'Multiline REPL.')
+ write("def abc\nend\n")
+ write("def def\nend\n")
+ write("\C-p\C-p\C-e")
+ write("\C-r")
+ write("a")
+ write("\n\n")
+ close
+ assert_screen(<<~'EOC')
+ prompt> def abc
+ prompt> end
+ => :abc
+ prompt> def def
+ prompt> end
+ => :def
+ prompt> def abc
+ prompt> end
+ => :abc
+ prompt>
+ EOC
+ end
+
+ def test_bracket_newline_indent
+ start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --auto-indent}, startup_message: 'Multiline REPL.')
+ write("[\n")
+ write("1")
+ close
+ assert_screen(<<~EOC)
+ Multiline REPL.
+ prompt> [
+ prompt> 1
+ EOC
+ end
+
+ def test_repeated_input_delete
+ start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl}, startup_message: 'Multiline REPL.')
+ write("a\C-h" * 4000)
+ close
+ assert_screen(<<~'EOC')
+ Multiline REPL.
+ prompt>
+ EOC
+ end
+
+ def test_exit_with_ctrl_d
+ start_terminal(5, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --auto-indent}, startup_message: 'Multiline REPL.')
+ begin
+ write("\C-d")
+ close
+ rescue EOFError
+ # EOFError is raised when process terminated.
+ end
+ assert_screen(<<~EOC)
+ Multiline REPL.
+ prompt>
+ EOC
+ end
+
+ def test_print_before_readline
+ code = <<~RUBY
+ puts 'Multiline REPL.'
+ 2.times do
+ print 'a' * 10
+ Reline.readline '>'
+ end
+ RUBY
+ start_terminal(6, 30, ['ruby', "-I#{@pwd}/lib", '-rreline', '-e', code], startup_message: 'Multiline REPL.')
+ write "x\n"
+ close
+ assert_screen(<<~EOC)
+ Multiline REPL.
+ >x
+ >
+ EOC
+ end
+
+ def test_pre_input_hook_with_redisplay
+ code = <<~'RUBY'
+ puts 'Multiline REPL.'
+ Reline.pre_input_hook = -> do
+ Reline.insert_text 'abc'
+ Reline.redisplay # Reline doesn't need this but Readline requires calling redisplay
+ end
+ Reline.readline('prompt> ')
+ RUBY
+ start_terminal(6, 30, ['ruby', "-I#{@pwd}/lib", '-rreline', '-e', code], startup_message: 'Multiline REPL.')
+ assert_screen(<<~EOC)
+ Multiline REPL.
+ prompt> abc
+ EOC
+ end
+
+ def test_pre_input_hook_with_multiline_text_insert
+ # Frequently used pattern of pre_input_hook
+ code = <<~'RUBY'
+ puts 'Multiline REPL.'
+ Reline.pre_input_hook = -> do
+ Reline.insert_text "abc\nef"
+ end
+ Reline.readline('>')
+ RUBY
+ start_terminal(6, 30, ['ruby', "-I#{@pwd}/lib", '-rreline', '-e', code], startup_message: 'Multiline REPL.')
+ write("\C-ad")
+ assert_screen(<<~EOC)
+ Multiline REPL.
+ >abc
+ def
+ EOC
+ end
+
+ def test_thread_safe
+ start_terminal(6, 30, %W{ruby -I#{@pwd}/lib #{@pwd}/test/reline/yamatanooroti/multiline_repl --auto-indent}, startup_message: 'Multiline REPL.')
+ write("[Thread.new{Reline.readline'>'},Thread.new{Reline.readmultiline('>'){true}}].map(&:join).size\n")
+ write("exit\n")
+ write("exit\n")
+ write("42\n")
+ close
+ assert_screen(<<~EOC)
+ >exit
+ >exit
+ => 2
+ prompt> 42
+ => 42
+ prompt>
+ EOC
+ end
+
+ def test_stop_continue
+ pidfile = Tempfile.create('pidfile')
+ rubyfile = Tempfile.create('rubyfile')
+ rubyfile.write <<~RUBY
+ File.write(#{pidfile.path.inspect}, Process.pid)
+ p Reline.readmultiline('>'){false}
+ RUBY
+ rubyfile.close
+ start_terminal(40, 50, ['bash'])
+ write "ruby -I#{@pwd}/lib -rreline #{rubyfile.path}\n"
+ write "abc\ndef\nhi"
+ pid = pidfile.tap(&:rewind).read.to_i
+ Process.kill(:STOP, pid) unless pid.zero?
+ write "fg\n"
+ write "\ebg"
+ close
+ assert_include result.join("\n"), ">abc\n>def\n>ghi\n"
+ end
+
def write_inputrc(content)
File.open(@inputrc_file, 'w') do |f|
f.write content
diff --git a/test/resolv/test_addr.rb b/test/resolv/test_addr.rb
index 62092676ba..f701c31d3e 100644
--- a/test/resolv/test_addr.rb
+++ b/test/resolv/test_addr.rb
@@ -28,6 +28,10 @@ class TestResolvAddr < Test::Unit::TestCase
assert_match(Resolv::IPv6::Regex, "FE80:2:3:4:5:6:7:8%EM1", bug17112)
assert_match(Resolv::IPv6::Regex, "FE80::20D:3AFF:FE7D:9760%ETH0", bug17112)
assert_match(Resolv::IPv6::Regex, "FE80::1%EM1", bug17112)
+
+ bug17524 = "[ruby-core:101992]"
+ assert_match(Resolv::IPv6::Regex, "FE80::20D:3AFF:FE7D:9760%ruby_3.0.0-1", bug17524)
+ assert_match(Resolv::IPv6::Regex, "fe80::1%ruby_3.0.0-1", bug17524)
end
def test_valid_socket_ip_address_list
diff --git a/test/resolv/test_dns.rb b/test/resolv/test_dns.rb
index 5171604a82..03d997d5b9 100644
--- a/test/resolv/test_dns.rb
+++ b/test/resolv/test_dns.rb
@@ -44,6 +44,16 @@ class TestResolvDNS < Test::Unit::TestCase
BasicSocket.do_not_reverse_lookup = @save_do_not_reverse_lookup
end
+ def with_tcp(host, port)
+ t = TCPServer.new(host, port)
+ begin
+ t.listen(1)
+ yield t
+ ensure
+ t.close
+ end
+ end
+
def with_udp(host, port)
u = UDPSocket.new
begin
@@ -54,6 +64,50 @@ class TestResolvDNS < Test::Unit::TestCase
end
end
+ def with_udp_and_tcp(host, port)
+ if port == 0
+ # Automatic port; we might need to retry until we find a port which is free on both UDP _and_ TCP.
+ retries_remaining = 10
+ t = nil
+ u = nil
+ begin
+ begin
+ u = UDPSocket.new
+ u.bind(host, 0)
+ _, udp_port, _, _ = u.addr
+ t = TCPServer.new(host, udp_port)
+ t.listen(1)
+ rescue Errno::EADDRINUSE, Errno::EACCES
+ # ADDRINUSE is what should get thrown if we try and bind a port which is already bound on UNIXen,
+ # but windows can sometimes throw EACCESS.
+ # See: https://stackoverflow.com/questions/48478869/cannot-bind-to-some-ports-due-to-permission-denied
+ retries_remaining -= 1
+ if retries_remaining > 0
+ t&.close
+ t = nil
+ u&.close
+ u = nil
+ retry
+ end
+ raise
+ end
+
+ # If we get to this point, we have a valid t & u socket
+ yield u, t
+ ensure
+ t&.close
+ u&.close
+ end
+ else
+ # Explicitly specified port, don't retry the bind.
+ with_udp(host, port) do |u|
+ with_tcp(host, port) do |t|
+ yield u, t
+ end
+ end
+ end
+ end
+
# [ruby-core:65836]
def test_resolve_with_2_ndots
conf = Resolv::DNS::Config.new :nameserver => ['127.0.0.1'], :ndots => 2
@@ -72,7 +126,7 @@ class TestResolvDNS < Test::Unit::TestCase
begin
OpenSSL
rescue LoadError
- skip 'autoload problem. see [ruby-dev:45021][Bug #5786]'
+ omit 'autoload problem. see [ruby-dev:45021][Bug #5786]'
end if defined?(OpenSSL)
with_udp('127.0.0.1', 0) {|u|
@@ -157,13 +211,173 @@ class TestResolvDNS < Test::Unit::TestCase
}
end
- def test_query_ipv4_duplicate_responses
+ def test_query_ipv4_address_truncated_tcp_fallback
begin
OpenSSL
rescue LoadError
skip 'autoload problem. see [ruby-dev:45021][Bug #5786]'
end if defined?(OpenSSL)
+ num_records = 50
+
+ with_udp_and_tcp('127.0.0.1', 0) {|u, t|
+ _, server_port, _, server_address = u.addr
+ client_thread = Thread.new {
+ Resolv::DNS.open(:nameserver_port => [[server_address, server_port]]) {|dns|
+ dns.getresources("foo.example.org", Resolv::DNS::Resource::IN::A)
+ }
+ }
+ udp_server_thread = Thread.new {
+ msg, (_, client_port, _, client_address) = Timeout.timeout(5) {u.recvfrom(4096)}
+ id, word2, qdcount, ancount, nscount, arcount = msg.unpack("nnnnnn")
+ qr = (word2 & 0x8000) >> 15
+ opcode = (word2 & 0x7800) >> 11
+ aa = (word2 & 0x0400) >> 10
+ tc = (word2 & 0x0200) >> 9
+ rd = (word2 & 0x0100) >> 8
+ ra = (word2 & 0x0080) >> 7
+ z = (word2 & 0x0070) >> 4
+ rcode = word2 & 0x000f
+ rest = msg[12..-1]
+ assert_equal(0, qr) # 0:query 1:response
+ assert_equal(0, opcode) # 0:QUERY 1:IQUERY 2:STATUS
+ assert_equal(0, aa) # Authoritative Answer
+ assert_equal(0, tc) # TrunCation
+ assert_equal(1, rd) # Recursion Desired
+ assert_equal(0, ra) # Recursion Available
+ assert_equal(0, z) # Reserved for future use
+ assert_equal(0, rcode) # 0:No-error 1:Format-error 2:Server-failure 3:Name-Error 4:Not-Implemented 5:Refused
+ assert_equal(1, qdcount) # number of entries in the question section.
+ assert_equal(0, ancount) # number of entries in the answer section.
+ assert_equal(0, nscount) # number of entries in the authority records section.
+ assert_equal(0, arcount) # number of entries in the additional records section.
+ name = [3, "foo", 7, "example", 3, "org", 0].pack("Ca*Ca*Ca*C")
+ assert_operator(rest, :start_with?, name)
+ rest = rest[name.length..-1]
+ assert_equal(4, rest.length)
+ qtype, _ = rest.unpack("nn")
+ assert_equal(1, qtype) # A
+ assert_equal(1, qtype) # IN
+ id = id
+ qr = 1
+ opcode = opcode
+ aa = 0
+ tc = 1
+ rd = rd
+ ra = 1
+ z = 0
+ rcode = 0
+ qdcount = 0
+ ancount = num_records
+ nscount = 0
+ arcount = 0
+ word2 = (qr << 15) |
+ (opcode << 11) |
+ (aa << 10) |
+ (tc << 9) |
+ (rd << 8) |
+ (ra << 7) |
+ (z << 4) |
+ rcode
+ msg = [id, word2, qdcount, ancount, nscount, arcount].pack("nnnnnn")
+ type = 1
+ klass = 1
+ ttl = 3600
+ rdlength = 4
+ num_records.times do |i|
+ rdata = [192,0,2,i].pack("CCCC") # 192.0.2.x (TEST-NET address) RFC 3330
+ rr = [name, type, klass, ttl, rdlength, rdata].pack("a*nnNna*")
+ msg << rr
+ end
+ u.send(msg[0...512], 0, client_address, client_port)
+ }
+ tcp_server_thread = Thread.new {
+ ct = t.accept
+ msg = ct.recv(512)
+ msg.slice!(0..1) # Size (only for TCP)
+ id, word2, qdcount, ancount, nscount, arcount = msg.unpack("nnnnnn")
+ qr = (word2 & 0x8000) >> 15
+ opcode = (word2 & 0x7800) >> 11
+ aa = (word2 & 0x0400) >> 10
+ tc = (word2 & 0x0200) >> 9
+ rd = (word2 & 0x0100) >> 8
+ ra = (word2 & 0x0080) >> 7
+ z = (word2 & 0x0070) >> 4
+ rcode = word2 & 0x000f
+ rest = msg[12..-1]
+ assert_equal(0, qr) # 0:query 1:response
+ assert_equal(0, opcode) # 0:QUERY 1:IQUERY 2:STATUS
+ assert_equal(0, aa) # Authoritative Answer
+ assert_equal(0, tc) # TrunCation
+ assert_equal(1, rd) # Recursion Desired
+ assert_equal(0, ra) # Recursion Available
+ assert_equal(0, z) # Reserved for future use
+ assert_equal(0, rcode) # 0:No-error 1:Format-error 2:Server-failure 3:Name-Error 4:Not-Implemented 5:Refused
+ assert_equal(1, qdcount) # number of entries in the question section.
+ assert_equal(0, ancount) # number of entries in the answer section.
+ assert_equal(0, nscount) # number of entries in the authority records section.
+ assert_equal(0, arcount) # number of entries in the additional records section.
+ name = [3, "foo", 7, "example", 3, "org", 0].pack("Ca*Ca*Ca*C")
+ assert_operator(rest, :start_with?, name)
+ rest = rest[name.length..-1]
+ assert_equal(4, rest.length)
+ qtype, _ = rest.unpack("nn")
+ assert_equal(1, qtype) # A
+ assert_equal(1, qtype) # IN
+ id = id
+ qr = 1
+ opcode = opcode
+ aa = 0
+ tc = 0
+ rd = rd
+ ra = 1
+ z = 0
+ rcode = 0
+ qdcount = 0
+ ancount = num_records
+ nscount = 0
+ arcount = 0
+ word2 = (qr << 15) |
+ (opcode << 11) |
+ (aa << 10) |
+ (tc << 9) |
+ (rd << 8) |
+ (ra << 7) |
+ (z << 4) |
+ rcode
+ msg = [id, word2, qdcount, ancount, nscount, arcount].pack("nnnnnn")
+ type = 1
+ klass = 1
+ ttl = 3600
+ rdlength = 4
+ num_records.times do |i|
+ rdata = [192,0,2,i].pack("CCCC") # 192.0.2.x (TEST-NET address) RFC 3330
+ rr = [name, type, klass, ttl, rdlength, rdata].pack("a*nnNna*")
+ msg << rr
+ end
+ msg = "#{[msg.bytesize].pack("n")}#{msg}" # Prefix with size
+ ct.send(msg, 0)
+ ct.close
+ }
+ result, _ = assert_join_threads([client_thread, udp_server_thread, tcp_server_thread])
+ assert_instance_of(Array, result)
+ assert_equal(50, result.length)
+ result.each_with_index do |rr, i|
+ assert_instance_of(Resolv::DNS::Resource::IN::A, rr)
+ assert_instance_of(Resolv::IPv4, rr.address)
+ assert_equal("192.0.2.#{i}", rr.address.to_s)
+ assert_equal(3600, rr.ttl)
+ end
+ }
+ end
+
+ def test_query_ipv4_duplicate_responses
+ begin
+ OpenSSL
+ rescue LoadError
+ omit 'autoload problem. see [ruby-dev:45021][Bug #5786]'
+ end if defined?(OpenSSL)
+
with_udp('127.0.0.1', 0) {|u|
_, server_port, _, server_address = u.addr
begin
@@ -297,7 +511,7 @@ class TestResolvDNS < Test::Unit::TestCase
end
def test_no_server
- skip if /mswin/ =~ RUBY_PLATFORM && ENV.key?('GITHUB_ACTIONS') # not working from the beginning
+ omit if /mswin/ =~ RUBY_PLATFORM && ENV.key?('GITHUB_ACTIONS') # not working from the beginning
u = UDPSocket.new
u.bind("127.0.0.1", 0)
_, port, _, host = u.addr
@@ -314,7 +528,7 @@ class TestResolvDNS < Test::Unit::TestCase
rescue Timeout::Error
if RUBY_PLATFORM.match?(/mingw/)
# cannot repo locally
- skip 'Timeout Error on MinGW CI'
+ omit 'Timeout Error on MinGW CI'
else
raise Timeout::Error
end
@@ -374,7 +588,8 @@ class TestResolvDNS < Test::Unit::TestCase
["2001:db8::1", "2001:db8::0:1"],
["::", "0:0:0:0:0:0:0:0"],
["2001::", "2001::0"],
- ["2001:db8::1:1:1:1:1", "2001:db8:0:1:1:1:1:1"],
+ ["2001:db8:0:1:1:1:1:1", "2001:db8:0:1:1:1:1:1"], # RFC 5952 Section 4.2.2.
+ ["2001:db8::1:1:1:1", "2001:db8:0:0:1:1:1:1"],
["1::1:0:0:0:1", "1:0:0:1:0:0:0:1"],
["1::1:0:0:1", "1:0:0:0:1:0:0:1"],
]
@@ -457,4 +672,149 @@ class TestResolvDNS < Test::Unit::TestCase
end
assert_raise(Resolv::ResolvError) { dns.each_name('example.com') }
end
+
+ def test_unreachable_server
+ unreachable_ip = '127.0.0.1'
+ sock = UDPSocket.new
+ sock.connect(unreachable_ip, 53)
+ begin
+ sock.send('1', 0)
+ rescue Errno::ENETUNREACH, Errno::EHOSTUNREACH
+ else
+ omit('cannot test unreachable server, as IP used is reachable')
+ end
+
+ config = {
+ :nameserver => [unreachable_ip],
+ :search => ['lan'],
+ :ndots => 1
+ }
+ r = Resolv.new([Resolv::DNS.new(config)])
+ assert_equal([], r.getaddresses('www.google.com'))
+
+ config[:raise_timeout_errors] = true
+ r = Resolv.new([Resolv::DNS.new(config)])
+ assert_raise(Resolv::ResolvError) { r.getaddresses('www.google.com') }
+ ensure
+ sock&.close
+ end
+
+ def test_multiple_servers_with_timeout_and_truncated_tcp_fallback
+ begin
+ OpenSSL
+ rescue LoadError
+ skip 'autoload problem. see [ruby-dev:45021][Bug #5786]'
+ end if defined?(OpenSSL)
+
+ num_records = 50
+
+ with_udp_and_tcp('127.0.0.1', 0) do |u1, t1|
+ with_udp_and_tcp('127.0.0.1', 0) do |u2,t2|
+ u2.close # XXX: u2 UDP socket is not used, but using #with_udp_and_tcp to enable Windows EACCES workaround
+ _, server1_port, _, server1_address = u1.addr
+ _, server2_port, _, server2_address = t2.addr
+
+ client_thread = Thread.new do
+ Resolv::DNS.open(nameserver_port: [[server1_address, server1_port], [server2_address, server2_port]]) do |dns|
+ dns.timeouts = [0.1, 0.2]
+ dns.getresources('foo.example.org', Resolv::DNS::Resource::IN::A)
+ end
+ end
+
+ udp_server1_thread = Thread.new do
+ msg, (_, client_port, _, client_address) = Timeout.timeout(5) { u1.recvfrom(4096) }
+ id, word2, _qdcount, _ancount, _nscount, _arcount = msg.unpack('nnnnnn')
+ opcode = (word2 & 0x7800) >> 11
+ rd = (word2 & 0x0100) >> 8
+ name = [3, 'foo', 7, 'example', 3, 'org', 0].pack('Ca*Ca*Ca*C')
+ qr = 1
+ aa = 0
+ tc = 1
+ ra = 1
+ z = 0
+ rcode = 0
+ qdcount = 0
+ ancount = num_records
+ nscount = 0
+ arcount = 0
+ word2 = (qr << 15) |
+ (opcode << 11) |
+ (aa << 10) |
+ (tc << 9) |
+ (rd << 8) |
+ (ra << 7) |
+ (z << 4) |
+ rcode
+ msg = [id, word2, qdcount, ancount, nscount, arcount].pack('nnnnnn')
+ type = 1
+ klass = 1
+ ttl = 3600
+ rdlength = 4
+ num_records.times do |i|
+ rdata = [192, 0, 2, i].pack('CCCC') # 192.0.2.x (TEST-NET address) RFC 3330
+ rr = [name, type, klass, ttl, rdlength, rdata].pack('a*nnNna*')
+ msg << rr
+ end
+ u1.send(msg[0...512], 0, client_address, client_port)
+ end
+
+ tcp_server1_thread = Thread.new do
+ # Keep this socket open so that the client experiences a timeout
+ t1.accept
+ end
+
+ tcp_server2_thread = Thread.new do
+ ct = t2.accept
+ msg = ct.recv(512)
+ msg.slice!(0..1) # Size (only for TCP)
+ id, word2, _qdcount, _ancount, _nscount, _arcount = msg.unpack('nnnnnn')
+ rd = (word2 & 0x0100) >> 8
+ opcode = (word2 & 0x7800) >> 11
+ name = [3, 'foo', 7, 'example', 3, 'org', 0].pack('Ca*Ca*Ca*C')
+ qr = 1
+ aa = 0
+ tc = 0
+ ra = 1
+ z = 0
+ rcode = 0
+ qdcount = 0
+ ancount = num_records
+ nscount = 0
+ arcount = 0
+ word2 = (qr << 15) |
+ (opcode << 11) |
+ (aa << 10) |
+ (tc << 9) |
+ (rd << 8) |
+ (ra << 7) |
+ (z << 4) |
+ rcode
+ msg = [id, word2, qdcount, ancount, nscount, arcount].pack('nnnnnn')
+ type = 1
+ klass = 1
+ ttl = 3600
+ rdlength = 4
+ num_records.times do |i|
+ rdata = [192, 0, 2, i].pack('CCCC') # 192.0.2.x (TEST-NET address) RFC 3330
+ rr = [name, type, klass, ttl, rdlength, rdata].pack('a*nnNna*')
+ msg << rr
+ end
+ msg = "#{[msg.bytesize].pack('n')}#{msg}" # Prefix with size
+ ct.send(msg, 0)
+ ct.close
+ end
+ result, _, tcp_server1_socket, = assert_join_threads([client_thread, udp_server1_thread, tcp_server1_thread, tcp_server2_thread])
+ assert_instance_of(Array, result)
+ assert_equal(50, result.length)
+ result.each_with_index do |rr, i|
+ assert_instance_of(Resolv::DNS::Resource::IN::A, rr)
+ assert_instance_of(Resolv::IPv4, rr.address)
+ assert_equal("192.0.2.#{i}", rr.address.to_s)
+ assert_equal(3600, rr.ttl)
+ end
+ ensure
+ tcp_server1_socket&.close
+ end
+ end
+ end
end
diff --git a/test/resolv/test_resource.rb b/test/resolv/test_resource.rb
index b75cf67f31..434380236e 100644
--- a/test/resolv/test_resource.rb
+++ b/test/resolv/test_resource.rb
@@ -23,4 +23,80 @@ class TestResolvResource < Test::Unit::TestCase
def test_coord
Resolv::LOC::Coord.create('1 2 1.1 N')
end
+
+ def test_srv_no_compress
+ # Domain name in SRV RDATA should not be compressed
+ issue29 = 'https://github.com/ruby/resolv/issues/29'
+ m = Resolv::DNS::Message.new(0)
+ m.add_answer('example.com', 0, Resolv::DNS::Resource::IN::SRV.new(0, 0, 0, 'www.example.com'))
+ assert_equal "\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x07example\x03com\x00\x00\x21\x00\x01\x00\x00\x00\x00\x00\x17\x00\x00\x00\x00\x00\x00\x03www\x07example\x03com\x00", m.encode, issue29
+ end
+end
+
+class TestResolvResourceCAA < Test::Unit::TestCase
+ def test_caa_roundtrip
+ raw_msg = "\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x03new\x07example\x03com\x00\x01\x01\x00\x01\x00\x00\x00\x00\x00\x16\x00\x05issueca1.example.net\xC0\x0C\x01\x01\x00\x01\x00\x00\x00\x00\x00\x0C\x80\x03tbsUnknown".b
+
+ m = Resolv::DNS::Message.new(0)
+ m.add_answer('new.example.com', 0, Resolv::DNS::Resource::IN::CAA.new(0, 'issue', 'ca1.example.net'))
+ m.add_answer('new.example.com', 0, Resolv::DNS::Resource::IN::CAA.new(128, 'tbs', 'Unknown'))
+ assert_equal raw_msg, m.encode
+
+ m = Resolv::DNS::Message.decode(raw_msg)
+ assert_equal 2, m.answer.size
+ _, _, caa0 = m.answer[0]
+ assert_equal 0, caa0.flags
+ assert_equal false, caa0.critical?
+ assert_equal 'issue', caa0.tag
+ assert_equal 'ca1.example.net', caa0.value
+ _, _, caa1 = m.answer[1]
+ assert_equal true, caa1.critical?
+ assert_equal 128, caa1.flags
+ assert_equal 'tbs', caa1.tag
+ assert_equal 'Unknown', caa1.value
+ end
+
+ def test_caa_stackoverflow
+ # gathered in the wild
+ raw_msg = "\x8D\x32\x81\x80\x00\x01\x00\x0B\x00\x00\x00\x00\x0Dstackoverflow\x03com\x00\x01\x01\x00\x01\xC0\x0C\x01\x01\x00\x01\x00\x00\x01\x2C\x00\x13\x00\x05issuecomodoca.com\xC0\x0C\x01\x01\x00\x01\x00\x00\x01\x2C\x00\x2D\x00\x05issuedigicert.com; cansignhttpexchanges=yes\xC0\x0C\x01\x01\x00\x01\x00\x00\x01\x2C\x00\x16\x00\x05issueletsencrypt.org\xC0\x0C\x01\x01\x00\x01\x00\x00\x01\x2C\x00\x29\x00\x05issuepki.goog; cansignhttpexchanges=yes\xC0\x0C\x01\x01\x00\x01\x00\x00\x01\x2C\x00\x12\x00\x05issuesectigo.com\xC0\x0C\x01\x01\x00\x01\x00\x00\x01\x2C\x00\x17\x00\x09issuewildcomodoca.com\xC0\x0C\x01\x01\x00\x01\x00\x00\x01\x2C\x00\x31\x00\x09issuewilddigicert.com; cansignhttpexchanges=yes\xC0\x0C\x01\x01\x00\x01\x00\x00\x01\x2C\x00\x1A\x00\x09issuewildletsencrypt.org\xC0\x0C\x01\x01\x00\x01\x00\x00\x01\x2C\x00\x2D\x00\x09issuewildpki.goog; cansignhttpexchanges=yes\xC0\x0C\x01\x01\x00\x01\x00\x00\x01\x2C\x00\x16\x00\x09issuewildsectigo.com\xC0\x0C\x01\x01\x00\x01\x00\x00\x01\x2C\x00\x2D\x80\x05iodefmailto:sysadmin-team@stackoverflow.com".b
+
+ m = Resolv::DNS::Message.decode(raw_msg)
+ assert_equal 11, m.answer.size
+ _, _, caa3 = m.answer[3]
+ assert_equal 0, caa3.flags
+ assert_equal 'issue', caa3.tag
+ assert_equal 'pki.goog; cansignhttpexchanges=yes', caa3.value
+ _, _, caa8 = m.answer[8]
+ assert_equal 0, caa8.flags
+ assert_equal 'issuewild', caa8.tag
+ assert_equal 'pki.goog; cansignhttpexchanges=yes', caa8.value
+ _, _, caa10 = m.answer[10]
+ assert_equal 128, caa10.flags
+ assert_equal 'iodef', caa10.tag
+ assert_equal 'mailto:sysadmin-team@stackoverflow.com', caa10.value
+ end
+
+ def test_caa_flags
+ assert_equal 255,
+ Resolv::DNS::Resource::IN::CAA.new(255, 'issue', 'ca1.example.net').flags
+ assert_raise(ArgumentError) do
+ Resolv::DNS::Resource::IN::CAA.new(256, 'issue', 'ca1.example.net')
+ end
+
+ assert_raise(ArgumentError) do
+ Resolv::DNS::Resource::IN::CAA.new(-1, 'issue', 'ca1.example.net')
+ end
+ end
+
+ def test_caa_tag
+ assert_raise(ArgumentError, 'Empty tag should be rejected') do
+ Resolv::DNS::Resource::IN::CAA.new(0, '', 'ca1.example.net')
+ end
+
+ assert_equal '123456789012345',
+ Resolv::DNS::Resource::IN::CAA.new(0, '123456789012345', 'ca1.example.net').tag
+ assert_raise(ArgumentError, 'Tag longer than 15 bytes should be rejected') do
+ Resolv::DNS::Resource::IN::CAA.new(0, '1234567890123456', 'ca1.example.net')
+ end
+ end
end
diff --git a/test/resolv/test_svcb_https.rb b/test/resolv/test_svcb_https.rb
new file mode 100644
index 0000000000..5dc3163d9e
--- /dev/null
+++ b/test/resolv/test_svcb_https.rb
@@ -0,0 +1,231 @@
+# frozen_string_literal: false
+require 'test/unit'
+require 'resolv'
+
+class TestResolvSvcbHttps < Test::Unit::TestCase
+ # Wraps a RR in answer section
+ def wrap_rdata(rrtype, rrclass, rdata)
+ [
+ "\x00\x00\x00\x00", # ID/FLAGS
+ [0, 1, 0, 0].pack('nnnn'), # QDCOUNT/ANCOUNT/NSCOUNT/ARCOUNT
+ "\x07example\x03com\x00", # NAME
+ [rrtype, rrclass, 0, rdata.bytesize].pack('nnNn'), # TYPE/CLASS/TTL/RDLENGTH
+ rdata,
+ ].join.b
+ end
+
+ def test_svcparams
+ params = Resolv::DNS::SvcParams.new([Resolv::DNS::SvcParam::Mandatory.new([1])])
+
+ assert_equal 1, params.count
+
+ params.add Resolv::DNS::SvcParam::NoDefaultALPN.new
+ params.add Resolv::DNS::SvcParam::ALPN.new(%w[h2 h3])
+
+ assert_equal 3, params.count
+
+ assert_equal [1], params[:mandatory].keys
+ assert_equal [1], params[0].keys
+
+ assert_equal %w[h2 h3], params[:alpn].protocol_ids
+ assert_equal %w[h2 h3], params[1].protocol_ids
+
+ params.delete :mandatory
+ params.delete :alpn
+
+ assert_equal 1, params.count
+
+ assert_nil params[:mandatory]
+ assert_nil params[1]
+
+ ary = params.each.to_a
+
+ assert_instance_of Resolv::DNS::SvcParam::NoDefaultALPN, ary.first
+ end
+
+ def test_svcb
+ rr = Resolv::DNS::Resource::IN::SVCB.new(0, 'example.com.')
+
+ assert_equal 0, rr.priority
+ assert rr.alias_mode?
+ assert !rr.service_mode?
+ assert_equal Resolv::DNS::Name.create('example.com.'), rr.target
+ assert rr.params.empty?
+
+ rr = Resolv::DNS::Resource::IN::SVCB.new(16, 'example.com.', [
+ Resolv::DNS::SvcParam::ALPN.new(%w[h2 h3]),
+ ])
+
+ assert_equal 16, rr.priority
+ assert !rr.alias_mode?
+ assert rr.service_mode?
+
+ assert_equal 1, rr.params.count
+ assert_instance_of Resolv::DNS::SvcParam::ALPN, rr.params[:alpn]
+ end
+
+ def test_svcb_encode_order
+ msg = Resolv::DNS::Message.new(0)
+ msg.add_answer(
+ 'example.com.', 0,
+ Resolv::DNS::Resource::IN::SVCB.new(16, 'foo.example.org.', [
+ Resolv::DNS::SvcParam::ALPN.new(%w[h2 h3-19]),
+ Resolv::DNS::SvcParam::Mandatory.new([4, 1]),
+ Resolv::DNS::SvcParam::IPv4Hint.new(['192.0.2.1']),
+ ])
+ )
+
+ expected = wrap_rdata 64, 1, "\x00\x10\x03foo\x07example\x03org\x00" +
+ "\x00\x00\x00\x04\x00\x01\x00\x04" +
+ "\x00\x01\x00\x09\x02h2\x05h3-19" +
+ "\x00\x04\x00\x04\xc0\x00\x02\x01"
+
+ assert_equal expected, msg.encode
+ end
+
+ ## Test vectors from [RFC9460]
+
+ def test_alias_mode
+ wire = wrap_rdata 65, 1, "\x00\x00\x03foo\x07example\x03com\x00"
+ msg = Resolv::DNS::Message.decode(wire)
+ _, _, rr = msg.answer.first
+
+ assert_equal 0, rr.priority
+ assert_equal Resolv::DNS::Name.create('foo.example.com.'), rr.target
+ assert_equal 0, rr.params.count
+
+ assert_equal wire, msg.encode
+ end
+
+ def test_target_name_is_root
+ wire = wrap_rdata 64, 1, "\x00\x01\x00"
+ msg = Resolv::DNS::Message.decode(wire)
+ _, _, rr = msg.answer.first
+
+ assert_equal 1, rr.priority
+ assert_equal Resolv::DNS::Name.create('.'), rr.target
+ assert_equal 0, rr.params.count
+
+ assert_equal wire, msg.encode
+ end
+
+ def test_specifies_port
+ wire = wrap_rdata 64, 1, "\x00\x10\x03foo\x07example\x03com\x00" +
+ "\x00\x03\x00\x02\x00\x35"
+ msg = Resolv::DNS::Message.decode(wire)
+ _, _, rr = msg.answer.first
+
+ assert_equal 16, rr.priority
+ assert_equal Resolv::DNS::Name.create('foo.example.com.'), rr.target
+ assert_equal 1, rr.params.count
+ assert_equal 53, rr.params[:port].port
+
+ assert_equal wire, msg.encode
+ end
+
+ def test_generic_key
+ wire = wrap_rdata 64, 1, "\x00\x01\x03foo\x07example\x03com\x00" +
+ "\x02\x9b\x00\x05hello"
+ msg = Resolv::DNS::Message.decode(wire)
+ _, _, rr = msg.answer.first
+
+ assert_equal 1, rr.priority
+ assert_equal Resolv::DNS::Name.create('foo.example.com.'), rr.target
+ assert_equal 1, rr.params.count
+ assert_equal 'hello', rr.params[:key667].value
+
+ assert_equal wire, msg.encode
+ end
+
+ def test_two_ipv6hints
+ wire = wrap_rdata 64, 1, "\x00\x01\x03foo\x07example\x03com\x00" +
+ "\x00\x06\x00\x20" +
+ ("\x20\x01\x0d\xb8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01" +
+ "\x20\x01\x0d\xb8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x53\x00\x01")
+ msg = Resolv::DNS::Message.decode(wire)
+ _, _, rr = msg.answer.first
+
+ assert_equal 1, rr.priority
+ assert_equal Resolv::DNS::Name.create('foo.example.com.'), rr.target
+ assert_equal 1, rr.params.count
+ assert_equal [Resolv::IPv6.create('2001:db8::1'), Resolv::IPv6.create('2001:db8::53:1')],
+ rr.params[:ipv6hint].addresses
+
+ assert_equal wire, msg.encode
+ end
+
+ def test_ipv6hint_embedded_ipv4
+ wire = wrap_rdata 64, 1, "\x00\x01\x07example\x03com\x00" +
+ "\x00\x06\x00\x10\x20\x01\x0d\xb8\x01\x22\x03\x44\x00\x00\x00\x00\xc0\x00\x02\x21"
+ msg = Resolv::DNS::Message.decode(wire)
+ _, _, rr = msg.answer.first
+
+ assert_equal 1, rr.priority
+ assert_equal Resolv::DNS::Name.create('example.com.'), rr.target
+ assert_equal 1, rr.params.count
+ assert_equal [Resolv::IPv6.create('2001:db8:122:344::192.0.2.33')],
+ rr.params[:ipv6hint].addresses
+
+ assert_equal wire, msg.encode
+ end
+
+ def test_mandatory_alpn_ipv4hint
+ wire = wrap_rdata 64, 1, "\x00\x10\x03foo\x07example\x03org\x00" +
+ "\x00\x00\x00\x04\x00\x01\x00\x04" +
+ "\x00\x01\x00\x09\x02h2\x05h3-19" +
+ "\x00\x04\x00\x04\xc0\x00\x02\x01"
+ msg = Resolv::DNS::Message.decode(wire)
+ _, _, rr = msg.answer.first
+
+ assert_equal 16, rr.priority
+ assert_equal Resolv::DNS::Name.create('foo.example.org.'), rr.target
+ assert_equal 3, rr.params.count
+ assert_equal [1, 4], rr.params[:mandatory].keys
+ assert_equal ['h2', 'h3-19'], rr.params[:alpn].protocol_ids
+ assert_equal [Resolv::IPv4.create('192.0.2.1')], rr.params[:ipv4hint].addresses
+
+ assert_equal wire, msg.encode
+ end
+
+ def test_alpn_comma_backslash
+ wire = wrap_rdata 64, 1, "\x00\x10\x03foo\x07example\x03org\x00" +
+ "\x00\x01\x00\x0c\x08f\\oo,bar\x02h2"
+ msg = Resolv::DNS::Message.decode(wire)
+ _, _, rr = msg.answer.first
+
+ assert_equal 16, rr.priority
+ assert_equal Resolv::DNS::Name.create('foo.example.org.'), rr.target
+ assert_equal 1, rr.params.count
+ assert_equal ['f\oo,bar', 'h2'], rr.params[:alpn].protocol_ids
+
+ assert_equal wire, msg.encode
+ end
+
+ ## For [RFC9461]
+
+ def test_dohpath
+ wire = wrap_rdata 64, 1, "\x00\x01\x03one\x03one\x03one\x03one\x00" +
+ "\x00\x01\x00\x03\x02h2" +
+ "\x00\x03\x00\x02\x01\xbb" +
+ "\x00\x04\x00\x08\x01\x01\x01\x01\x01\x00\x00\x01" +
+ "\x00\x06\x00\x20" +
+ ("\x26\x06\x47\x00\x47\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x11" +
+ "\x26\x06\x47\x00\x47\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x01") +
+ "\x00\x07\x00\x10/dns-query{?dns}"
+ msg = Resolv::DNS::Message.decode(wire)
+ _, _, rr = msg.answer.first
+
+ assert_equal 1, rr.priority
+ assert_equal Resolv::DNS::Name.create('one.one.one.one.'), rr.target
+ assert_equal 5, rr.params.count
+ assert_equal ['h2'], rr.params[:alpn].protocol_ids
+ assert_equal 443, rr.params[:port].port
+ assert_equal [Resolv::IPv4.create('1.1.1.1'), Resolv::IPv4.create('1.0.0.1')],
+ rr.params[:ipv4hint].addresses
+ assert_equal [Resolv::IPv6.create('2606:4700:4700::1111'), Resolv::IPv6.create('2606:4700:4700::1001')],
+ rr.params[:ipv6hint].addresses
+ assert_equal '/dns-query{?dns}', rr.params[:dohpath].template
+
+ assert_equal wire, msg.encode
+ end
+end
diff --git a/test/rinda/test_rinda.rb b/test/rinda/test_rinda.rb
deleted file mode 100644
index f155e88de1..0000000000
--- a/test/rinda/test_rinda.rb
+++ /dev/null
@@ -1,894 +0,0 @@
-# frozen_string_literal: false
-require 'test/unit'
-require 'envutil'
-
-require 'drb/drb'
-require 'drb/eq'
-require 'rinda/ring'
-require 'rinda/tuplespace'
-require 'timeout'
-require 'singleton'
-
-module Rinda
-
-class MockClock
- include Singleton
-
- class MyTS < Rinda::TupleSpace
- def keeper_thread
- nil
- end
-
- def stop_keeper
- if @keeper
- @keeper.kill
- @keeper.join
- @keeper = nil
- end
- end
- end
-
- def initialize
- @now = 2
- @reso = 1
- @ts = nil
- @inf = 2**31 - 1
- end
-
- def start_keeper
- @now = 2
- @reso = 1
- @ts&.stop_keeper
- @ts = MyTS.new
- @ts.write([2, :now])
- @inf = 2**31 - 1
- end
-
- def stop_keeper
- @ts.stop_keeper
- end
-
- def now
- @now.to_f
- end
-
- def at(n)
- n
- end
-
- def _forward(n=nil)
- now ,= @ts.take([nil, :now])
- @now = now + n
- @ts.write([@now, :now])
- end
-
- def forward(n)
- while n > 0
- _forward(@reso)
- n -= @reso
- Thread.pass
- end
- end
-
- def rewind
- @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
- defined?(@m) && @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)
- Kernel.sleep(n * 0.01)
- end
-end
-
-module TupleSpaceTestModule
- def setup
- MockClock.instance.start_keeper
- end
-
- def teardown
- MockClock.instance.stop_keeper
- end
-
- 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_raise(Rinda::InvalidHashTupleKey) do
- 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_raise(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_raise(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_raise(Rinda::RequestExpiredError) do
- @ts.take([:empty], 0)
- end
-
- assert_raise(Rinda::RequestExpiredError) do
- @ts.read([:empty], 0)
- end
- end
-
- def test_ruby_talk_264062
- th = Thread.new {
- assert_raise(Rinda::RequestExpiredError) do
- @ts.take([:empty], 1)
- end
- }
- sleep(10)
- thread_join(th)
-
- th = Thread.new {
- assert_raise(Rinda::RequestExpiredError) do
- @ts.read([:empty], 1)
- end
- }
- sleep(10)
- thread_join(th)
- 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
- @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(5) do |count|
- s = 0
- count.times do
- tuple = @ts.take([:req, Integer])
- assert_equal(2, tuple[1])
- s += tuple[1]
- end
- @ts.write([:ans, s])
- s
- end
-
- assert_equal(10, thread_join(taker))
- assert_equal([:ans, 10], @ts.take([:ans, 10]))
- assert_equal([], @ts.read_all([nil, nil]))
- end
-
- def test_core_02
- taker = Thread.new(5) do |count|
- s = 0
- count.times do
- tuple = @ts.take([:req, Integer])
- assert_equal(2, tuple[1])
- s += tuple[1]
- end
- @ts.write([:ans, s])
- s
- end
-
- 5.times do
- @ts.write([:req, 2])
- end
-
- assert_equal(10, thread_join(taker))
- assert_equal([:ans, 10], @ts.take([:ans, 10]))
- assert_equal([], @ts.read_all([nil, nil]))
- end
-
- def test_core_03_notify
- notify1 = @ts.notify(nil, [:req, Integer])
- notify2 = @ts.notify(nil, {"message"=>String, "name"=>String})
-
- 5.times do
- @ts.write([:req, 2])
- end
-
- 5.times do
- tuple = @ts.take([:req, Integer])
- assert_equal(2, tuple[1])
- end
-
- 5.times do
- assert_equal(['write', [:req, 2]], notify1.pop)
- end
- 5.times do
- assert_equal(['take', [:req, 2]], notify1.pop)
- end
-
- @ts.write({"message"=>"first", "name"=>"3"})
- @ts.write({"message"=>"second", "name"=>"1"})
- @ts.write({"message"=>"third", "name"=>"0"})
- @ts.take({"message"=>"third", "name"=>"0"})
- @ts.take({"message"=>"first", "name"=>"3"})
-
- assert_equal(["write", {"message"=>"first", "name"=>"3"}], notify2.pop)
- assert_equal(["write", {"message"=>"second", "name"=>"1"}], notify2.pop)
- assert_equal(["write", {"message"=>"third", "name"=>"0"}], notify2.pop)
- assert_equal(["take", {"message"=>"third", "name"=>"0"}], notify2.pop)
- assert_equal(["take", {"message"=>"first", "name"=>"3"}], notify2.pop)
- 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
- assert_raise(Rinda::RequestCanceledError) do
- @ts.take([:take, nil], 10) do |t|
- template = t
- Thread.new do
- template.cancel
- end
- end
- end
- end
-
- sleep(2)
- thread_join(taker)
-
- assert(template.canceled?)
-
- @ts.write([:take, 1])
-
- assert_equal([[:take, 1]], @ts.read_all([nil, nil]))
- end
-
- def test_cancel_02
- skip 'this test is unstable with --jit-wait' if defined?(RubyVM::JIT) && RubyVM::JIT.enabled?
- 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
- assert_raise(Rinda::RequestCanceledError) do
- @ts.read([:take, nil], 10) do |t|
- template = t
- Thread.new do
- template.cancel
- end
- end
- end
- end
-
- sleep(2)
- thread_join(reader)
-
- 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
- super
- ThreadGroup.new.add(Thread.current)
- @ts = Rinda::TupleSpace.new(1)
- end
- def teardown
- # implementation-dependent
- @ts.instance_eval{
- if th = @keeper
- th.kill
- th.join
- end
- }
- super
- end
-end
-
-class TupleSpaceProxyTest < Test::Unit::TestCase
- include TupleSpaceTestModule
-
- def setup
- super
- ThreadGroup.new.add(Thread.current)
- @ts_base = Rinda::TupleSpace.new(1)
- @ts = Rinda::TupleSpaceProxy.new(@ts_base)
- @server = DRb.start_service("druby://localhost:0")
- end
- def teardown
- # implementation-dependent
- @ts_base.instance_eval{
- if th = @keeper
- th.kill
- th.join
- end
- }
- @server.stop_service
- DRb::DRbConn.stop_pool
- super
- end
-
- def test_remote_array_and_hash
- # Don't remove ary/hsh local variables.
- # These are necessary to protect objects from GC.
- ary = [1, 2, 3]
- @ts.write(DRbObject.new(ary))
- assert_equal([1, 2, 3], @ts.take([1, 2, 3], 0))
- hsh = {'head' => 1, 'tail' => 2}
- @ts.write(DRbObject.new(hsh))
- assert_equal({'head' => 1, 'tail' => 2},
- @ts.take({'head' => 1, 'tail' => 2}, 0))
- end
-
- def test_take_bug_8215
- skip "this test randomly fails on mswin" if /mswin/ =~ RUBY_PLATFORM
- service = DRb.start_service("druby://localhost:0", @ts_base)
-
- uri = service.uri
-
- args = [EnvUtil.rubybin, *%W[-rdrb/drb -rdrb/eq -rrinda/ring -rrinda/tuplespace -e]]
-
- take = spawn(*args, <<-'end;', uri)
- uri = ARGV[0]
- DRb.start_service("druby://localhost:0")
- ro = DRbObject.new_with_uri(uri)
- ts = Rinda::TupleSpaceProxy.new(ro)
- th = Thread.new do
- ts.take([:test_take, nil])
- rescue Interrupt
- # Expected
- end
- Kernel.sleep(0.1)
- th.raise(Interrupt) # causes loss of the taken tuple
- ts.write([:barrier, :continue])
- Kernel.sleep
- end;
-
- @ts_base.take([:barrier, :continue])
-
- write = spawn(*args, <<-'end;', uri)
- uri = ARGV[0]
- DRb.start_service("druby://localhost:0")
- ro = DRbObject.new_with_uri(uri)
- ts = Rinda::TupleSpaceProxy.new(ro)
- ts.write([:test_take, 42])
- end;
-
- status = Process.wait(write)
-
- assert_equal([[:test_take, 42]], @ts_base.read_all([:test_take, nil]),
- '[bug:8215] tuple lost')
- ensure
- service.stop_service if service
- DRb::DRbConn.stop_pool
- signal = /mswin|mingw/ =~ RUBY_PLATFORM ? "KILL" : "TERM"
- Process.kill(signal, write) if write && status.nil?
- Process.kill(signal, take) if take
- Process.wait(write) if write && status.nil?
- Process.wait(take) if take
- end
-end
-
-module RingIPv6
- def prepare_ipv6(r)
- begin
- Socket.getifaddrs.each do |ifaddr|
- next unless ifaddr.addr
- next unless ifaddr.addr.ipv6_linklocal?
- next if ifaddr.name[0, 2] == "lo"
- r.multicast_interface = ifaddr.ifindex
- return ifaddr
- end
- rescue NotImplementedError
- # ifindex() function may not be implemented on Windows.
- return if
- Socket.ip_address_list.any? { |addrinfo| addrinfo.ipv6? && !addrinfo.ipv6_loopback? }
- end
- skip 'IPv6 not available'
- end
-
- def ipv6_mc(rf, hops = nil)
- ifaddr = prepare_ipv6(rf)
- rf.multicast_hops = hops if hops
- begin
- v6mc = rf.make_socket("ff02::1")
- rescue Errno::EINVAL
- # somehow Debian 6.0.7 needs ifname
- v6mc = rf.make_socket("ff02::1%#{ifaddr.name}")
- rescue Errno::EADDRNOTAVAIL
- return # IPv6 address for multicast not available
- rescue Errno::ENETDOWN
- return # Network is down
- rescue Errno::EHOSTUNREACH
- return # Unreachable for some reason
- end
- begin
- yield v6mc
- ensure
- v6mc.close
- end
- end
-end
-
-class TestRingServer < Test::Unit::TestCase
-
- def setup
- @port = Rinda::Ring_PORT
-
- @ts = Rinda::TupleSpace.new
- @rs = Rinda::RingServer.new(@ts, [], @port)
- @server = DRb.start_service("druby://localhost:0")
- end
- def teardown
- @rs.shutdown
- # implementation-dependent
- @ts.instance_eval{
- if th = @keeper
- th.kill
- th.join
- end
- }
- @server.stop_service
- DRb::DRbConn.stop_pool
- end
-
- def test_do_reply
- with_timeout(30) {_test_do_reply}
- end
-
- def _test_do_reply
- called = nil
-
- callback_orig = proc { |ts|
- called = ts
- }
-
- callback = DRb::DRbObject.new callback_orig
-
- @ts.write [:lookup_ring, callback]
-
- @rs.do_reply
-
- wait_for(30) {called}
-
- assert_same @ts, called
- end
-
- def test_do_reply_local
- skip 'timeout-based test becomes unstable with --jit-wait' if defined?(RubyVM::JIT) && RubyVM::JIT.enabled?
- with_timeout(30) {_test_do_reply_local}
- end
-
- def _test_do_reply_local
- called = nil
-
- callback = proc { |ts|
- called = ts
- }
-
- @ts.write [:lookup_ring, callback]
-
- @rs.do_reply
-
- wait_for(30) {called}
-
- assert_same @ts, called
- end
-
- def test_make_socket_unicast
- v4 = @rs.make_socket('127.0.0.1')
-
- assert_equal('127.0.0.1', v4.local_address.ip_address)
- assert_equal(@port, v4.local_address.ip_port)
- end
-
- def test_make_socket_ipv4_multicast
- begin
- v4mc = @rs.make_socket('239.0.0.1')
- rescue Errno::ENOBUFS => e
- skip "Missing multicast support in OS: #{e.message}"
- end
-
- begin
- if Socket.const_defined?(:SO_REUSEPORT) then
- assert(v4mc.getsockopt(:SOCKET, :SO_REUSEPORT).bool)
- else
- assert(v4mc.getsockopt(:SOCKET, :SO_REUSEADDR).bool)
- end
- rescue TypeError
- if /aix/ =~ RUBY_PLATFORM
- skip "Known bug in getsockopt(2) on AIX"
- end
- raise $!
- end
-
- assert_equal('0.0.0.0', v4mc.local_address.ip_address)
- assert_equal(@port, v4mc.local_address.ip_port)
- end
-
- def test_make_socket_ipv6_multicast
- skip 'IPv6 not available' unless
- Socket.ip_address_list.any? { |addrinfo| addrinfo.ipv6? && !addrinfo.ipv6_loopback? }
-
- begin
- v6mc = @rs.make_socket('ff02::1')
- rescue Errno::EADDRNOTAVAIL
- return # IPv6 address for multicast not available
- rescue Errno::ENOBUFS => e
- skip "Missing multicast support in OS: #{e.message}"
- end
-
- if Socket.const_defined?(:SO_REUSEPORT) then
- assert v6mc.getsockopt(:SOCKET, :SO_REUSEPORT).bool
- else
- assert v6mc.getsockopt(:SOCKET, :SO_REUSEADDR).bool
- end
-
- assert_equal('::1', v6mc.local_address.ip_address)
- assert_equal(@port, v6mc.local_address.ip_port)
- end
-
- def test_ring_server_ipv4_multicast
- @rs.shutdown
- begin
- @rs = Rinda::RingServer.new(@ts, [['239.0.0.1', '0.0.0.0']], @port)
- rescue Errno::ENOBUFS => e
- skip "Missing multicast support in OS: #{e.message}"
- end
-
- v4mc = @rs.instance_variable_get('@sockets').first
-
- begin
- if Socket.const_defined?(:SO_REUSEPORT) then
- assert(v4mc.getsockopt(:SOCKET, :SO_REUSEPORT).bool)
- else
- assert(v4mc.getsockopt(:SOCKET, :SO_REUSEADDR).bool)
- end
- rescue TypeError
- if /aix/ =~ RUBY_PLATFORM
- skip "Known bug in getsockopt(2) on AIX"
- end
- raise $!
- end
-
- assert_equal('0.0.0.0', v4mc.local_address.ip_address)
- assert_equal(@port, v4mc.local_address.ip_port)
- end
-
- def test_ring_server_ipv6_multicast
- skip 'IPv6 not available' unless
- Socket.ip_address_list.any? { |addrinfo| addrinfo.ipv6? && !addrinfo.ipv6_loopback? }
-
- @rs.shutdown
- begin
- @rs = Rinda::RingServer.new(@ts, [['ff02::1', '::1', 0]], @port)
- rescue Errno::EADDRNOTAVAIL
- return # IPv6 address for multicast not available
- end
-
- v6mc = @rs.instance_variable_get('@sockets').first
-
- if Socket.const_defined?(:SO_REUSEPORT) then
- assert v6mc.getsockopt(:SOCKET, :SO_REUSEPORT).bool
- else
- assert v6mc.getsockopt(:SOCKET, :SO_REUSEADDR).bool
- end
-
- assert_equal('::1', v6mc.local_address.ip_address)
- assert_equal(@port, v6mc.local_address.ip_port)
- end
-
- def test_shutdown
- @rs.shutdown
-
- assert_nil(@rs.do_reply, 'otherwise should hang forever')
- end
-
- private
-
- def with_timeout(n)
- aoe = Thread.abort_on_exception
- Thread.abort_on_exception = true
- tl0 = Thread.list
- tl = nil
- th = Thread.new(Thread.current) do |mth|
- sleep n
- (tl = Thread.list - tl0).each {|t|t.raise(Timeout::Error)}
- mth.raise(Timeout::Error)
- end
- tl0 << th
- yield
- rescue Timeout::Error => e
- $stderr.puts "TestRingServer#with_timeout: timeout in #{n}s:"
- $stderr.puts caller
- if tl
- bt = e.backtrace
- tl.each do |t|
- begin
- t.value
- rescue Timeout::Error => e
- bt.unshift("")
- bt[0, 0] = e.backtrace
- end
- end
- end
- raise Timeout::Error, "timeout", bt
- ensure
- if th
- th.kill
- th.join
- end
- Thread.abort_on_exception = aoe
- end
-
- def wait_for(n)
- t = n + Process.clock_gettime(Process::CLOCK_MONOTONIC, :second)
- until yield
- if t < Process.clock_gettime(Process::CLOCK_MONOTONIC, :second)
- flunk "timeout during waiting call"
- end
- sleep 0.1
- end
- end
-end
-
-class TestRingFinger < Test::Unit::TestCase
- include RingIPv6
-
- def setup
- @rf = Rinda::RingFinger.new
- end
-
- def test_make_socket_unicast
- v4 = @rf.make_socket('127.0.0.1')
-
- assert(v4.getsockopt(:SOL_SOCKET, :SO_BROADCAST).bool)
- rescue TypeError
- if /aix/ =~ RUBY_PLATFORM
- skip "Known bug in getsockopt(2) on AIX"
- end
- raise $!
- ensure
- v4.close if v4
- end
-
- def test_make_socket_ipv4_multicast
- v4mc = @rf.make_socket('239.0.0.1')
-
- assert_equal(1, v4mc.getsockopt(:IPPROTO_IP, :IP_MULTICAST_LOOP).ipv4_multicast_loop)
- assert_equal(1, v4mc.getsockopt(:IPPROTO_IP, :IP_MULTICAST_TTL).ipv4_multicast_ttl)
- ensure
- v4mc.close if v4mc
- end
-
- def test_make_socket_ipv6_multicast
- ipv6_mc(@rf) do |v6mc|
- assert_equal(1, v6mc.getsockopt(:IPPROTO_IPV6, :IPV6_MULTICAST_LOOP).int)
- assert_equal(1, v6mc.getsockopt(:IPPROTO_IPV6, :IPV6_MULTICAST_HOPS).int)
- end
- end
-
- def test_make_socket_ipv4_multicast_hops
- @rf.multicast_hops = 2
- v4mc = @rf.make_socket('239.0.0.1')
- assert_equal(2, v4mc.getsockopt(:IPPROTO_IP, :IP_MULTICAST_TTL).ipv4_multicast_ttl)
- ensure
- v4mc.close if v4mc
- end
-
- def test_make_socket_ipv6_multicast_hops
- ipv6_mc(@rf, 2) do |v6mc|
- assert_equal(2, v6mc.getsockopt(:IPPROTO_IPV6, :IPV6_MULTICAST_HOPS).int)
- end
- end
-
-end
-
-end
diff --git a/test/rinda/test_tuplebag.rb b/test/rinda/test_tuplebag.rb
deleted file mode 100644
index ab17ca047c..0000000000
--- a/test/rinda/test_tuplebag.rb
+++ /dev/null
@@ -1,173 +0,0 @@
-# frozen_string_literal: false
-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 !@tb.has_expires?
-
- t = tup(:val, 1)
- @tb.push t
-
- assert @tb.has_expires?
-
- t.renew Object.new
-
- assert !@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/test/ripper/assert_parse_files.rb b/test/ripper/assert_parse_files.rb
index 85d20cf69e..0d583a99e3 100644
--- a/test/ripper/assert_parse_files.rb
+++ b/test/ripper/assert_parse_files.rb
@@ -5,26 +5,39 @@ module TestRipper; end
class TestRipper::Generic < Test::Unit::TestCase
SRCDIR = File.expand_path("../../..", __FILE__)
- def assert_parse_files(dir, pattern = "**/*.rb")
- assert_separately(%W[--disable-gem -rripper - #{SRCDIR}/#{dir} #{pattern}],
+ def assert_parse_files(dir, pattern = "**/*.rb", exclude: nil, gc_stress: GC.stress, test_ratio: nil)
+ test_ratio ||= ENV["TEST_RIPPER_RATIO"]&.tap {|s|break s.to_f} || 0.05 # testing all files needs too long time...
+ assert_separately(%W[-rripper - #{SRCDIR}/#{dir} #{pattern}],
__FILE__, __LINE__, "#{<<-"begin;"}\n#{<<-'end;'}", timeout: Float::INFINITY)
+ GC.stress = false
pattern = "#{pattern}"
+ exclude = (
+ #{exclude if exclude}
+ )
+ test_ratio = (
+ #{test_ratio}
+ )
+ gc_stress = (
+ #{gc_stress}
+ )
begin;
- TEST_RATIO = ENV["TEST_RIPPER_RATIO"]&.tap {|s|break s.to_f} || 0.05 # testing all files needs too long time...
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
dir = ARGV.shift
- scripts = Dir.chdir(dir) {Dir[pattern]}
- if (1...scripts.size).include?(num = scripts.size * TEST_RATIO)
+ scripts = Dir.glob(pattern, base: dir)
+ scripts.reject! {|script| File.fnmatch?(exclude, script, File::FNM_PATHNAME)} if exclude
+ if (1...scripts.size).include?(num = scripts.size * test_ratio)
scripts = scripts.sample(num)
end
scripts.sort!
for script in scripts
assert_nothing_raised {
parser = Parser.new(File.read("#{dir}/#{script}"), script)
- parser.instance_eval "parse", "<#{script}>"
+ EnvUtil.under_gc_stress(gc_stress) do
+ parser.instance_eval "parse", "<#{script}>"
+ end
}
end
end;
diff --git a/test/ripper/dummyparser.rb b/test/ripper/dummyparser.rb
index fa834bd0f7..ef5ea49b1f 100644
--- a/test/ripper/dummyparser.rb
+++ b/test/ripper/dummyparser.rb
@@ -4,8 +4,9 @@
#
require 'ripper'
+module TestRipper; end
-class Node
+class TestRipper::Node
def initialize(name, *nodes)
@name = name
@children = nodes
@@ -14,7 +15,7 @@ class Node
attr_reader :name, :children
def to_s
- "#{@name}(#{Node.trim_nil(@children).map {|n| n.to_s }.join(',')})"
+ "#{@name}(#{TestRipper::Node.trim_nil(@children).map {|n| n.to_s }.join(',')})"
end
def self.trim_nil(list)
@@ -36,7 +37,7 @@ class Node
end
end
-class NodeList
+class TestRipper::NodeList
def initialize(list = [])
@list = list
end
@@ -62,7 +63,7 @@ class NodeList
end
end
-class DummyParser < Ripper
+class TestRipper::DummyParser < Ripper
def hook(*names)
class << self; self; end.class_eval do
names.each do |name|
@@ -81,7 +82,7 @@ class DummyParser < Ripper
end
def on_stmts_new
- NodeList.new
+ TestRipper::NodeList.new
end
def on_stmts_add(stmts, st)
@@ -90,23 +91,23 @@ class DummyParser < Ripper
end
def on_void_stmt
- Node.new('void')
+ TestRipper::Node.new('void')
end
def on_var_ref(name)
- Node.new('ref', name)
+ TestRipper::Node.new('ref', name)
end
def on_var_alias(a, b)
- Node.new('valias', a, b)
+ TestRipper::Node.new('valias', a, b)
end
def on_assign_error(mesg = nil, a)
- Node.new('assign_error', a)
+ TestRipper::Node.new('assign_error', a)
end
def on_alias_error(mesg = nil, a)
- Node.new('aliaserr', a)
+ TestRipper::Node.new('aliaserr', a)
end
def on_arg_paren(args)
@@ -114,7 +115,7 @@ class DummyParser < Ripper
end
def on_args_new
- NodeList.new
+ TestRipper::NodeList.new
end
def on_args_add(list, arg)
@@ -156,7 +157,7 @@ class DummyParser < Ripper
end
def on_brace_block(params, code)
- Node.new('block', params, code)
+ TestRipper::Node.new('block', params, code)
end
def on_block_var(params, shadow)
@@ -176,7 +177,7 @@ class DummyParser < Ripper
end
def on_params(required, optional, rest, more, keyword, keyword_rest, block)
- args = NodeList.new
+ args = TestRipper::NodeList.new
required.each do |req|
args.push(req)
@@ -197,15 +198,15 @@ class DummyParser < Ripper
end
def on_assoc_new(a, b)
- Node.new('assoc', a, b)
+ TestRipper::Node.new('assoc', a, b)
end
def on_bare_assoc_hash(assoc_list)
- Node.new('assocs', *assoc_list)
+ TestRipper::Node.new('assocs', *assoc_list)
end
def on_assoclist_from_args(a)
- Node.new('assocs', *a)
+ TestRipper::Node.new('assocs', *a)
end
def on_word_new
@@ -217,7 +218,7 @@ class DummyParser < Ripper
end
def on_words_new
- NodeList.new
+ TestRipper::NodeList.new
end
def on_words_add(words, word)
@@ -225,7 +226,7 @@ class DummyParser < Ripper
end
def on_qwords_new
- NodeList.new
+ TestRipper::NodeList.new
end
def on_qwords_add(words, word)
@@ -233,27 +234,27 @@ class DummyParser < Ripper
end
def on_symbols_new
- NodeList.new
+ TestRipper::NodeList.new
end
def on_symbols_add(symbols, symbol)
- symbols.push Node::Sym.new(symbol)
+ symbols.push TestRipper::Node::Sym.new(symbol)
end
def on_qsymbols_new
- NodeList.new
+ TestRipper::NodeList.new
end
def on_qsymbols_add(symbols, symbol)
- symbols.push Node::Sym.new(symbol)
+ symbols.push TestRipper::Node::Sym.new(symbol)
end
def on_mlhs_new
- NodeList.new
+ TestRipper::NodeList.new
end
def on_mlhs_paren(list)
- Node.new(:mlhs, list)
+ TestRipper::Node.new(:mlhs, list)
end
def on_mlhs_add(list, node)
@@ -277,12 +278,12 @@ class DummyParser < Ripper
end
def on_rescue(exc, *rest)
- Node.new('rescue', (exc && NodeList.new(exc)), *rest)
+ TestRipper::Node.new('rescue', (exc && TestRipper::NodeList.new(exc)), *rest)
end
(Ripper::PARSER_EVENTS.map(&:to_s) - instance_methods(false).map {|n|n.to_s.sub(/^on_/, '')}).each do |event|
define_method(:"on_#{event}") do |*args|
- Node.new(event, *args)
+ TestRipper::Node.new(event, *args)
end
end
end
diff --git a/test/ripper/test_lexer.rb b/test/ripper/test_lexer.rb
index 83130668be..4e8c0003db 100644
--- a/test/ripper/test_lexer.rb
+++ b/test/ripper/test_lexer.rb
@@ -100,6 +100,20 @@ class TestRipper::Lexer < Test::Unit::TestCase
assert_equal expect, Ripper.lex(src).map {|e| e[1]}
end
+ def test_end_of_script_char
+ all_assertions do |all|
+ ["a", %w"[a ]", %w"{, }", "if"].each do |src, append|
+ expected = Ripper.lex(src).map {|e| e[1]}
+ ["\0b", "\4b", "\32b"].each do |eof|
+ c = "#{src}#{eof}#{append}"
+ all.for(c) do
+ assert_equal expected, Ripper.lex(c).map {|e| e[1]}
+ end
+ end
+ end
+ end
+ end
+
def test_slice
assert_equal "string\#{nil}\n",
Ripper.slice(%(<<HERE\nstring\#{nil}\nHERE), "heredoc_beg .*? nl $(.*?) heredoc_end", 1)
@@ -157,7 +171,7 @@ class TestRipper::Lexer < Test::Unit::TestCase
end
BAD_CODE = [
- [:parse_error, 'def req(true) end', %r[unexpected `true'], 'true'],
+ [:parse_error, 'def req(true) end', %r[unexpected 'true'], 'true'],
[:parse_error, 'def req(a, a) end', %r[duplicated argument name], 'a'],
[:assign_error, 'begin; nil = 1; end', %r[assign to nil], 'nil'],
[:alias_error, 'begin; alias $x $1; end', %r[number variables], '$1'],
@@ -228,4 +242,276 @@ class TestRipper::Lexer < Test::Unit::TestCase
EOF
assert_equal([[5, 0], :on_heredoc_end, "EOS\n", state(:EXPR_BEG)], Ripper.lex(s).last, bug)
end
+
+ def test_tokenize_with_here_document
+ bug = '[Bug #18963]'
+ code = %[
+<<A + "hello
+A
+world"
+]
+ assert_equal(code, Ripper.tokenize(code).join(""), bug)
+ end
+
+ InvalidHeredocInsideBlockParam = <<~CODE
+ a do |b
+ <<-C
+ C
+ |
+ end
+ CODE
+
+ def test_heredoc_inside_block_param
+ bug = '[Bug #19399]'
+ code = InvalidHeredocInsideBlockParam
+ assert_equal(code, Ripper.tokenize(code).join(""), bug)
+ end
+
+ def test_heredoc_no_memory_leak
+ assert_no_memory_leak([], "#{<<-"begin;"}", "#{<<-'end;'}", rss: true)
+ require "ripper"
+ source = "" #{InvalidHeredocInsideBlockParam.dump}
+ begin;
+ 400_000.times do
+ Ripper.new(source).parse
+ end
+ end;
+ end
+
+ def test_heredoc_unterminated_interpolation
+ code = <<~'HEREDOC'
+ <<A+1
+ #{
+ HEREDOC
+
+ assert_include(Ripper.tokenize(code).join(""), "+1")
+ end
+
+ def test_nested_heredoc
+ code = <<~'HEREDOC'
+ <<~H1
+ 1
+ #{<<~H2}
+ 2
+ H2
+ 3
+ H1
+ HEREDOC
+
+ expected = [
+ [[1, 0], :on_heredoc_beg, "<<~H1", state(:EXPR_BEG)],
+ [[1, 5], :on_nl, "\n", state(:EXPR_BEG)],
+ [[2, 0], :on_ignored_sp, " ", state(:EXPR_BEG)],
+ [[2, 2], :on_tstring_content, "1\n", state(:EXPR_BEG)],
+ [[3, 0], :on_ignored_sp, " ", state(:EXPR_BEG)],
+ [[3, 2], :on_embexpr_beg, "\#{", state(:EXPR_BEG)],
+ [[3, 4], :on_heredoc_beg, "<<~H2", state(:EXPR_BEG)],
+ [[3, 9], :on_embexpr_end, "}", state(:EXPR_END)],
+ [[3, 10], :on_tstring_content, "\n", state(:EXPR_BEG)],
+ [[4, 0], :on_ignored_sp, " ", state(:EXPR_BEG)],
+ [[4, 4], :on_tstring_content, "2\n", state(:EXPR_BEG)],
+ [[5, 0], :on_heredoc_end, " H2\n", state(:EXPR_BEG)],
+ [[6, 0], :on_ignored_sp, " ", state(:EXPR_BEG)],
+ [[6, 2], :on_tstring_content, "3\n", state(:EXPR_BEG)],
+ [[7, 0], :on_heredoc_end, "H1\n", state(:EXPR_BEG)],
+ ]
+
+ assert_lexer(expected, code)
+
+ code = <<~'HEREDOC'
+ <<-H1
+ 1
+ #{<<~H2}
+ 2
+ H2
+ 3
+ H1
+ HEREDOC
+
+ expected = [
+ [[1, 0], :on_heredoc_beg, "<<-H1", state(:EXPR_BEG)],
+ [[1, 5], :on_nl, "\n", state(:EXPR_BEG)],
+ [[2, 0], :on_tstring_content, " 1\n ", state(:EXPR_BEG)],
+ [[3, 2], :on_embexpr_beg, "\#{", state(:EXPR_BEG)],
+ [[3, 4], :on_heredoc_beg, "<<~H2", state(:EXPR_BEG)],
+ [[3, 9], :on_embexpr_end, "}", state(:EXPR_END)],
+ [[3, 10], :on_tstring_content, "\n", state(:EXPR_BEG)],
+ [[4, 0], :on_ignored_sp, " ", state(:EXPR_BEG)],
+ [[4, 4], :on_tstring_content, "2\n", state(:EXPR_BEG)],
+ [[5, 0], :on_heredoc_end, " H2\n", state(:EXPR_BEG)],
+ [[6, 0], :on_tstring_content, " 3\n", state(:EXPR_BEG)],
+ [[7, 0], :on_heredoc_end, "H1\n", state(:EXPR_BEG)],
+ ]
+
+ assert_lexer(expected, code)
+ end
+
+ def test_invalid_escape_ctrl_mbchar
+ code = %["\\C-\u{3042}"]
+ expected = [
+ [[1, 0], :on_tstring_beg, '"', state(:EXPR_BEG)],
+ [[1, 1], :on_tstring_content, "\\C-\u{3042}", state(:EXPR_BEG)],
+ [[1, 7], :on_tstring_end, '"', state(:EXPR_END)],
+ ]
+
+ assert_lexer(expected, code)
+ end
+
+ def test_invalid_escape_meta_mbchar
+ code = %["\\M-\u{3042}"]
+ expected = [
+ [[1, 0], :on_tstring_beg, '"', state(:EXPR_BEG)],
+ [[1, 1], :on_tstring_content, "\\M-\u{3042}", state(:EXPR_BEG)],
+ [[1, 7], :on_tstring_end, '"', state(:EXPR_END)],
+ ]
+
+ assert_lexer(expected, code)
+ end
+
+ def test_invalid_escape_meta_ctrl_mbchar
+ code = %["\\M-\\C-\u{3042}"]
+ expected = [
+ [[1, 0], :on_tstring_beg, '"', state(:EXPR_BEG)],
+ [[1, 1], :on_tstring_content, "\\M-\\C-\u{3042}", state(:EXPR_BEG)],
+ [[1, 10], :on_tstring_end, '"', state(:EXPR_END)],
+ ]
+
+ assert_lexer(expected, code)
+ end
+
+ def test_invalid_escape_ctrl_meta_mbchar
+ code = %["\\C-\\M-\u{3042}"]
+ expected = [
+ [[1, 0], :on_tstring_beg, '"', state(:EXPR_BEG)],
+ [[1, 1], :on_tstring_content, "\\C-\\M-\u{3042}", state(:EXPR_BEG)],
+ [[1, 10], :on_tstring_end, '"', state(:EXPR_END)],
+ ]
+
+ assert_lexer(expected, code)
+ end
+
+ def test_invalid_escape_string
+ code = "\"hello\\x world"
+ expected = [
+ [[1, 0], :on_tstring_beg, "\"", state(:EXPR_BEG)],
+ [[1, 1], :on_tstring_content, "hello", state(:EXPR_BEG)],
+ [[1, 5], :on_tstring_content, "\\x", state(:EXPR_BEG)],
+ [[1, 7], :on_tstring_content, " world", state(:EXPR_BEG)],
+ ]
+
+ code = "\"\nhello\\x world"
+ expected = [
+ [[1, 0], :on_tstring_beg, "\"", state(:EXPR_BEG)],
+ [[1, 1], :on_tstring_content, "\n" "hello", state(:EXPR_BEG)],
+ [[2, 5], :on_tstring_content, "\\x", state(:EXPR_BEG)],
+ [[2, 7], :on_tstring_content, " world", state(:EXPR_BEG)],
+ ]
+ assert_lexer(expected, code)
+
+ code = "\"\n\\Cxx\""
+ expected = [
+ [[1, 0], :on_tstring_beg, "\"", state(:EXPR_BEG)],
+ [[1, 1], :on_tstring_content, "\n", state(:EXPR_BEG)],
+ [[2, 0], :on_tstring_content, "\\Cx", state(:EXPR_BEG)],
+ [[2, 3], :on_tstring_content, "x", state(:EXPR_BEG)],
+ [[2, 4], :on_tstring_end, "\"", state(:EXPR_END)],
+ ]
+ assert_lexer(expected, code)
+
+ code = "\"\n\\Mxx\""
+ expected = [
+ [[1, 0], :on_tstring_beg, "\"", state(:EXPR_BEG)],
+ [[1, 1], :on_tstring_content, "\n", state(:EXPR_BEG)],
+ [[2, 0], :on_tstring_content, "\\Mx", state(:EXPR_BEG)],
+ [[2, 3], :on_tstring_content, "x", state(:EXPR_BEG)],
+ [[2, 4], :on_tstring_end, "\"", state(:EXPR_END)],
+ ]
+ assert_lexer(expected, code)
+
+ code = "\"\n\\c\\cx\""
+ expected = [
+ [[1, 0], :on_tstring_beg, "\"", state(:EXPR_BEG)],
+ [[1, 1], :on_tstring_content, "\n", state(:EXPR_BEG)],
+ [[2, 0], :on_tstring_content, "\\c\\c", state(:EXPR_BEG)],
+ [[2, 4], :on_tstring_content, "x", state(:EXPR_BEG)],
+ [[2, 5], :on_tstring_end, "\"", state(:EXPR_END)],
+ ]
+ assert_lexer(expected, code)
+
+ code = "\"\n\\ux\""
+ expected = [
+ [[1, 0], :on_tstring_beg, "\"", state(:EXPR_BEG)],
+ [[1, 1], :on_tstring_content, "\n", state(:EXPR_BEG)],
+ [[2, 0], :on_tstring_content, "\\u", state(:EXPR_BEG)],
+ [[2, 2], :on_tstring_content, "x", state(:EXPR_BEG)],
+ [[2, 3], :on_tstring_end, "\"", state(:EXPR_END)],
+ ]
+ assert_lexer(expected, code)
+
+ code = "\"\n\\xx\""
+ expected = [
+ [[1, 0], :on_tstring_beg, "\"", state(:EXPR_BEG)],
+ [[1, 1], :on_tstring_content, "\n", state(:EXPR_BEG)],
+ [[2, 0], :on_tstring_content, "\\x", state(:EXPR_BEG)],
+ [[2, 2], :on_tstring_content, "x", state(:EXPR_BEG)],
+ [[2, 3], :on_tstring_end, "\"", state(:EXPR_END)],
+ ]
+ assert_lexer(expected, code)
+
+ code = "<<A\n\n\\xyz"
+ expected = [
+ [[1, 0], :on_heredoc_beg, "<<A", state(:EXPR_BEG)],
+ [[1, 3], :on_nl, "\n", state(:EXPR_BEG)],
+ [[2, 0], :on_tstring_content, "\n", state(:EXPR_BEG)],
+ [[3, 0], :on_tstring_content, "\\x", state(:EXPR_BEG)],
+ [[3, 2], :on_tstring_content, "yz", state(:EXPR_BEG)],
+ ]
+ assert_lexer(expected, code)
+
+ code = "%(\n\\xyz)"
+ expected = [
+ [[1, 0], :on_tstring_beg, "%(", state(:EXPR_BEG)],
+ [[1, 2], :on_tstring_content, "\n", state(:EXPR_BEG)],
+ [[2, 0], :on_tstring_content, "\\x", state(:EXPR_BEG)],
+ [[2, 2], :on_tstring_content, "yz", state(:EXPR_BEG)],
+ [[2, 4], :on_tstring_end, ")", state(:EXPR_END)],
+ ]
+ assert_lexer(expected, code)
+
+ code = "%Q(\n\\xyz)"
+ expected = [
+ [[1, 0], :on_tstring_beg, "%Q(", state(:EXPR_BEG)],
+ [[1, 3], :on_tstring_content, "\n", state(:EXPR_BEG)],
+ [[2, 0], :on_tstring_content, "\\x", state(:EXPR_BEG)],
+ [[2, 2], :on_tstring_content, "yz", state(:EXPR_BEG)],
+ [[2, 4], :on_tstring_end, ")", state(:EXPR_END)],
+ ]
+ assert_lexer(expected, code)
+
+ code = ":\"\n\\xyz\""
+ expected = [
+ [[1, 0], :on_symbeg, ":\"", state(:EXPR_FNAME)],
+ [[1, 2], :on_tstring_content, "\n", state(:EXPR_FNAME)],
+ [[2, 0], :on_tstring_content, "\\x", state(:EXPR_FNAME)],
+ [[2, 2], :on_tstring_content, "yz", state(:EXPR_FNAME)],
+ [[2, 4], :on_tstring_end, "\"", state(:EXPR_END)],
+ ]
+ assert_lexer(expected, code)
+ end
+
+ def test_spaces_at_eof
+ code = "1\n\t \t"
+ expected = [
+ [[1, 0], :on_int, "1", state(:EXPR_END)],
+ [[1, 1], :on_nl, "\n", state(:EXPR_BEG)],
+ [[2, 0], :on_sp, "\t \t", state(:EXPR_END)],
+ ]
+ assert_lexer(expected, code)
+ end
+
+ def assert_lexer(expected, code)
+ assert_equal(code, Ripper.tokenize(code).join(""))
+ assert_equal(expected, result = Ripper.lex(code),
+ proc {expected.zip(result) {|e, r| break diff(e, r) unless e == r}})
+ end
end
diff --git a/test/ripper/test_parser_events.rb b/test/ripper/test_parser_events.rb
index 5bb8f120f2..aa7434c083 100644
--- a/test/ripper/test_parser_events.rb
+++ b/test/ripper/test_parser_events.rb
@@ -16,7 +16,7 @@ class TestRipper::ParserEvents < Test::Unit::TestCase
end
def parse(str, nm = nil, &bl)
- dp = DummyParser.new(str)
+ dp = TestRipper::DummyParser.new(str)
dp.hook(*nm, &bl) if nm
dp.parse.to_s
end
@@ -152,6 +152,45 @@ class TestRipper::ParserEvents < Test::Unit::TestCase
thru_args_forward = false
parse(code, :on_args_forward) {thru_args_forward = true}
assert_equal true, thru_args_forward, "no args_forward for: #{code}"
+ parse(code, :on_params) {|*, block| assert_nil(block)}
+ end
+ end
+
+ def test_anonymous_block_forwarding
+ thru_args_add_block = false
+ parse('def b(&); c(&); end', :on_args_add_block) {thru_args_add_block = true}
+ assert_equal true, thru_args_add_block
+ assert_match "no anonymous block parameter", compile_error('def b; c(&); end')
+ end
+
+ def test_anonymous_rest_forwarding
+ [
+ 'c(*)',
+ 'c(*, *)',
+ ].each do |code|
+ thru_args_add_star = false
+ src = "def b(*); #{code} end"
+ parse(src, :on_args_add_star) {thru_args_add_star = true}
+ assert_equal true, thru_args_add_star, src
+
+ src = "def b; #{code} end"
+ assert_match "no anonymous rest parameter", compile_error(src), src
+ end
+ end
+
+ def test_anonymous_keyword_rest_forwarding
+ [
+ 'c(**)',
+ 'c(k: 1, **)',
+ 'c(**, k: 1)',
+ ].each do |code|
+ thru_assoc_splat = false
+ src = "def b(**); #{code} end"
+ parse(src, :on_assoc_splat) {thru_assoc_splat = true}
+ assert_equal true, thru_assoc_splat, src
+
+ src = "def b; #{code} end"
+ assert_match "no anonymous keyword rest parameter", compile_error(src), src
end
end
@@ -228,17 +267,29 @@ class TestRipper::ParserEvents < Test::Unit::TestCase
end
def test_assign_error_backref
- thru_assign_error = false
+ errors = []
result =
- parse('$` = 1', :on_assign_error) {thru_assign_error = true}
- assert_equal true, thru_assign_error
- assert_equal '[assign(assign_error(var_field($`)),1)]', result
+ parse('$& = 1', %i[on_assign_error compile_error]) {|e, *| errors << e}
+ assert_equal %i[on_assign_error], errors
+ assert_equal '[assign(assign_error(var_field($&)),1)]', result
- thru_assign_error = false
+ errors = []
result =
- parse('$`, _ = 1', :on_assign_error) {thru_assign_error = true}
- assert_equal true, thru_assign_error
- assert_equal '[massign([assign_error(var_field($`)),var_field(_)],1)]', result
+ parse('$&, _ = 1', %i[on_assign_error compile_error]) {|e, *| errors << e}
+ assert_equal %i[on_assign_error], errors
+ assert_equal '[massign([assign_error(var_field($&)),var_field(_)],1)]', result
+
+ errors = []
+ result =
+ parse('$& += 1', %i[on_assign_error compile_error]) {|e, *| errors << e}
+ assert_equal %i[on_assign_error], errors
+ assert_equal '[assign_error(opassign(var_field($&),+=,1))]', result
+
+ errors = []
+ result =
+ parse('$& += cmd 1, 2', %i[on_assign_error compile_error]) {|e, *| errors << e}
+ assert_equal %i[on_assign_error], errors
+ assert_equal '[assign_error(opassign(var_field($&),+=,command(cmd,[1,2])))]', result
end
def test_assign_error_const_qualified
@@ -461,6 +512,23 @@ class TestRipper::ParserEvents < Test::Unit::TestCase
assert_equal "[call(ref(self),&.,foo,[])]", tree
end
+ def test_call_colon2
+ hook = Module.new do
+ def on_op(op)
+ super("(op: #{op.inspect})")
+ end
+ def on_call(recv, name, *args)
+ super(recv, "(method: #{name})", *args)
+ end
+ def on_ident(name)
+ super("(ident: #{name.inspect})")
+ end
+ end
+
+ parser = TestRipper::DummyParser.new("a::b").extend(hook)
+ assert_equal '[call(vcall((ident: "a")),(method: (op: "::")),(ident: "b"))]', parser.parse.to_s
+ end
+
def test_excessed_comma
thru_excessed_comma = false
parse("proc{|x,|}", :on_excessed_comma) {thru_excessed_comma = true}
@@ -1588,20 +1656,20 @@ class TestRipper::ParserEvents < Test::Unit::TestCase
end
def test_invalid_instance_variable_name
- assert_equal("`@1' is not allowed as an instance variable name", compile_error('proc{@1}'))
- assert_equal("`@' without identifiers is not allowed as an instance variable name", compile_error('@%'))
- assert_equal("`@' without identifiers is not allowed as an instance variable name", compile_error('@'))
+ assert_equal("'@1' is not allowed as an instance variable name", compile_error('proc{@1}'))
+ assert_equal("'@' without identifiers is not allowed as an instance variable name", compile_error('@%'))
+ assert_equal("'@' without identifiers is not allowed as an instance variable name", compile_error('@'))
end
def test_invalid_class_variable_name
- assert_equal("`@@1' is not allowed as a class variable name", compile_error('@@1'))
- assert_equal("`@@' without identifiers is not allowed as a class variable name", compile_error('@@%'))
- assert_equal("`@@' without identifiers is not allowed as a class variable name", compile_error('@@'))
+ assert_equal("'@@1' is not allowed as a class variable name", compile_error('@@1'))
+ assert_equal("'@@' without identifiers is not allowed as a class variable name", compile_error('@@%'))
+ assert_equal("'@@' without identifiers is not allowed as a class variable name", compile_error('@@'))
end
def test_invalid_global_variable_name
- assert_equal("`$%' is not allowed as a global variable name", compile_error('$%'))
- assert_equal("`$' without identifiers is not allowed as a global variable name", compile_error('$'))
+ assert_equal("'$%' is not allowed as a global variable name", compile_error('$%'))
+ assert_equal("'$' without identifiers is not allowed as a global variable name", compile_error('$'))
end
def test_warning_ignored_magic_comment
@@ -1616,6 +1684,26 @@ class TestRipper::ParserEvents < Test::Unit::TestCase
assert_equal(%w"frozen_string_literal nottrue", args)
end
+ def test_warning_duplicated_when_clause
+ fmt, *args = warning(<<~STR)
+ a = 1
+ case a
+ when 1
+ when 1
+ when 2
+ else
+ end
+ STR
+ assert_match(/duplicates 'when' clause/, fmt)
+ assert_equal([4, 3], args)
+ end
+
+ def test_warn_duplicated_hash_keys
+ fmt, *args = warn("{ a: 1, a: 2 }")
+ assert_match(/is duplicated and overwritten on line/, fmt)
+ assert_equal([:a, 1], args)
+ end
+
def test_warn_cr_in_middle
fmt = nil
assert_warn("") {fmt, = warn("\r;")}
@@ -1655,4 +1743,69 @@ class TestRipper::ParserEvents < Test::Unit::TestCase
parse('case 0; in {a:}; end', :on_hshptn) {thru_hshptn = true}
assert_equal true, thru_hshptn
end
+
+ def test_return_out_of_compile_error_no_memory_leak
+ assert_no_memory_leak(%w(-rripper), "#{<<~'begin;'}", "#{<<~'end;'}", rss: true)
+ class MyRipper < Ripper
+ def initialize(src, &blk)
+ super(src)
+ @blk = blk
+ end
+
+ def compile_error(msg) = @blk.call(msg)
+ end
+
+ def call_parse = MyRipper.new("/") { |msg| return msg }.parse
+
+ # Check that call_parse does return a syntax error
+ raise "call_parse should return a syntax error" unless call_parse
+ begin;
+ 100_000.times do
+ call_parse
+ end
+ end;
+ end
+
+ def test_return_out_of_warn_no_memory_leak
+ assert_no_memory_leak(%w(-rripper), "#{<<~'begin;'}", "#{<<~'end;'}", rss: true)
+ class MyRipper < Ripper
+ def initialize(src, &blk)
+ super(src)
+ @blk = blk
+ end
+
+ def warn(msg, *args) = @blk.call(msg)
+ end
+
+ def call_parse = MyRipper.new("{ a: 1, a: 2 }") { |msg| return msg }.parse
+
+ # Check that call_parse does warn
+ raise "call_parse should warn" unless call_parse
+ begin;
+ 500_000.times do
+ call_parse
+ end
+ end;
+
+ assert_no_memory_leak(%w(-rripper), "#{<<~'begin;'}", "#{<<~'end;'}", rss: true)
+ class MyRipper < Ripper
+ def initialize(src, &blk)
+ super(src)
+ @blk = blk
+ end
+
+ def warn(msg, *args) = @blk.call(msg)
+ end
+
+ $VERBOSE = true
+ def call_parse = MyRipper.new("if true\n end\n") { |msg| return msg }.parse
+
+ # Check that call_parse does warn
+ raise "call_parse should warn" unless call_parse
+ begin;
+ 1_000_000.times do
+ call_parse
+ end
+ end;
+ end
end if ripper_test
diff --git a/test/ripper/test_ripper.rb b/test/ripper/test_ripper.rb
index 76276c54ef..f129a41be9 100644
--- a/test/ripper/test_ripper.rb
+++ b/test/ripper/test_ripper.rb
@@ -14,6 +14,13 @@ class TestRipper::Ripper < Test::Unit::TestCase
@ripper = Ripper.new '1 + 1'
end
+ def test_new
+ assert_separately(%w[-rripper], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ assert_nil EnvUtil.under_gc_stress {Ripper.new("")}.state
+ end;
+ end
+
def test_column
assert_nil @ripper.column
end
@@ -81,7 +88,7 @@ class TestRipper::Ripper < Test::Unit::TestCase
ripper.yydebug = true
ripper.debug_output = out
ripper.parse
- assert_include out.string[/.*"literal content".*/], 'woot'
+ assert_include out.string[/.*"literal content".*/], '1.1-1.5'
end
def test_regexp_with_option
@@ -141,6 +148,36 @@ end
assert_nothing_raised { Ripper.lex src }
end
+ def test_no_memory_leak
+ assert_no_memory_leak(%w(-rripper), "", "#{<<~'end;'}", rss: true)
+ 2_000_000.times do
+ Ripper.parse("")
+ end
+ end;
+
+ # [Bug #19835]
+ assert_no_memory_leak(%w(-rripper), "", "#{<<~'end;'}", rss: true)
+ 1_000_000.times do
+ Ripper.parse("class Foo")
+ end
+ end;
+
+ # [Bug #19836]
+ assert_no_memory_leak(%w(-rripper), "", "#{<<~'end;'}", rss: true)
+ 1_000_000.times do
+ Ripper.parse("-> {")
+ end
+ end;
+ end
+
+ def test_sexp_no_memory_leak
+ assert_no_memory_leak(%w(-rripper), "", "#{<<~'end;'}", rss: true)
+ 1_000_000.times do
+ Ripper.sexp("")
+ end
+ end;
+ end
+
class TestInput < self
Input = Struct.new(:lines) do
def gets
diff --git a/test/ripper/test_scanner_events.rb b/test/ripper/test_scanner_events.rb
index cef584c157..261e259889 100644
--- a/test/ripper/test_scanner_events.rb
+++ b/test/ripper/test_scanner_events.rb
@@ -53,16 +53,18 @@ class TestRipper::ScannerEvents < Test::Unit::TestCase
Ripper.tokenize("1 .foo\n")
assert_equal ["1", "\n", " ", ".", "foo", "\n"],
Ripper.tokenize("1\n .foo\n")
+ assert_equal ["def", " ", "f", ";", " ", "(", "x", ")", "::", "A", " ", "="],
+ Ripper.tokenize("def f; (x)::A =")
end
def test_lex
- assert_equal [],
+ assert_lex [],
Ripper.lex('')
- assert_equal [[[1,0], :on_ident, "a", Ripper::EXPR_CMDARG]],
+ assert_lex [[[1,0], :on_ident, "a", Ripper::EXPR_CMDARG]],
Ripper.lex('a')
- assert_equal [[[1, 0], :on_kw, "nil", Ripper::EXPR_END]],
+ assert_lex [[[1, 0], :on_kw, "nil", Ripper::EXPR_END]],
Ripper.lex("nil")
- assert_equal [[[1, 0], :on_kw, "def", Ripper::EXPR_FNAME],
+ assert_lex [[[1, 0], :on_kw, "def", Ripper::EXPR_FNAME],
[[1, 3], :on_sp, " ", Ripper::EXPR_FNAME],
[[1, 4], :on_ident, "m", Ripper::EXPR_ENDFN],
[[1, 5], :on_lparen, "(", Ripper::EXPR_BEG | Ripper::EXPR_LABEL],
@@ -70,39 +72,39 @@ class TestRipper::ScannerEvents < Test::Unit::TestCase
[[1, 7], :on_rparen, ")", Ripper::EXPR_ENDFN],
[[1, 8], :on_kw, "end", Ripper::EXPR_END]],
Ripper.lex("def m(a)end")
- assert_equal [[[1, 0], :on_int, "1", Ripper::EXPR_END],
+ assert_lex [[[1, 0], :on_int, "1", Ripper::EXPR_END],
[[1, 1], :on_nl, "\n", Ripper::EXPR_BEG],
[[2, 0], :on_int, "2", Ripper::EXPR_END],
[[2, 1], :on_nl, "\n", Ripper::EXPR_BEG],
[[3, 0], :on_int, "3", Ripper::EXPR_END]],
Ripper.lex("1\n2\n3")
- assert_equal [[[1, 0], :on_heredoc_beg, "<<""EOS", Ripper::EXPR_BEG],
+ assert_lex [[[1, 0], :on_heredoc_beg, "<<""EOS", Ripper::EXPR_BEG],
[[1, 5], :on_nl, "\n", Ripper::EXPR_BEG],
[[2, 0], :on_tstring_content, "heredoc\n", Ripper::EXPR_BEG],
[[3, 0], :on_heredoc_end, "EOS", Ripper::EXPR_BEG]],
Ripper.lex("<<""EOS\nheredoc\nEOS")
- assert_equal [[[1, 0], :on_heredoc_beg, "<<""EOS", Ripper::EXPR_BEG],
+ assert_lex [[[1, 0], :on_heredoc_beg, "<<""EOS", Ripper::EXPR_BEG],
[[1, 5], :on_nl, "\n", Ripper::EXPR_BEG],
[[2, 0], :on_heredoc_end, "EOS", Ripper::EXPR_BEG]],
Ripper.lex("<<""EOS\nEOS"),
"bug#4543"
- assert_equal [[[1, 0], :on_regexp_beg, "/", Ripper::EXPR_BEG],
+ assert_lex [[[1, 0], :on_regexp_beg, "/", Ripper::EXPR_BEG],
[[1, 1], :on_tstring_content, "foo\nbar", Ripper::EXPR_BEG],
[[2, 3], :on_regexp_end, "/", Ripper::EXPR_BEG]],
Ripper.lex("/foo\nbar/")
- assert_equal [[[1, 0], :on_regexp_beg, "/", Ripper::EXPR_BEG],
+ assert_lex [[[1, 0], :on_regexp_beg, "/", Ripper::EXPR_BEG],
[[1, 1], :on_tstring_content, "foo\n\u3020", Ripper::EXPR_BEG],
[[2, 3], :on_regexp_end, "/", Ripper::EXPR_BEG]],
Ripper.lex("/foo\n\u3020/")
- assert_equal [[[1, 0], :on_tstring_beg, "'", Ripper::EXPR_BEG],
+ assert_lex [[[1, 0], :on_tstring_beg, "'", Ripper::EXPR_BEG],
[[1, 1], :on_tstring_content, "foo\n\xe3\x80\xa0", Ripper::EXPR_BEG],
[[2, 3], :on_tstring_end, "'", Ripper::EXPR_END]],
Ripper.lex("'foo\n\xe3\x80\xa0'")
- assert_equal [[[1, 0], :on_tstring_beg, "'", Ripper::EXPR_BEG],
+ assert_lex [[[1, 0], :on_tstring_beg, "'", Ripper::EXPR_BEG],
[[1, 1], :on_tstring_content, "\u3042\n\u3044", Ripper::EXPR_BEG],
[[2, 3], :on_tstring_end, "'", Ripper::EXPR_END]],
Ripper.lex("'\u3042\n\u3044'")
- assert_equal [[[1, 0], :on_rational, "1r", Ripper::EXPR_END],
+ assert_lex [[[1, 0], :on_rational, "1r", Ripper::EXPR_END],
[[1, 2], :on_nl, "\n", Ripper::EXPR_BEG],
[[2, 0], :on_imaginary, "2i", Ripper::EXPR_END],
[[2, 2], :on_nl, "\n", Ripper::EXPR_BEG],
@@ -113,18 +115,25 @@ class TestRipper::ScannerEvents < Test::Unit::TestCase
[[5, 0], :on_imaginary, "5.6ri", Ripper::EXPR_END],
],
Ripper.lex("1r\n2i\n3ri\n4.2r\n5.6ri")
- assert_equal [[[1, 0], :on_heredoc_beg, "<<~EOS", Ripper::EXPR_BEG],
- [[1, 6], :on_nl, "\n", Ripper::EXPR_BEG],
- [[2, 0], :on_ignored_sp, " ", Ripper::EXPR_BEG],
- [[2, 2], :on_tstring_content, "heredoc\n", Ripper::EXPR_BEG],
- [[3, 0], :on_heredoc_end, "EOS", Ripper::EXPR_BEG]
+ assert_lex [[[1, 0], :on_heredoc_beg, "<<~EOS", Ripper::EXPR_BEG],
+ [[1, 6], :on_nl, "\n", Ripper::EXPR_BEG],
+ [[2, 0], :on_ignored_sp, " ", Ripper::EXPR_BEG],
+ [[2, 2], :on_tstring_content, "heredoc\n", Ripper::EXPR_BEG],
+ [[3, 0], :on_heredoc_end, "EOS", Ripper::EXPR_BEG]
],
Ripper.lex("<<~EOS\n heredoc\nEOS")
- assert_equal [[[1, 0], :on_tstring_beg, "'", Ripper::EXPR_BEG],
+ assert_lex [[[1, 0], :on_tstring_beg, "'", Ripper::EXPR_BEG],
[[1, 1], :on_tstring_content, "foo", Ripper::EXPR_BEG]],
Ripper.lex("'foo")
end
+ def assert_lex(expected, *rest)
+ expected = expected.map do |pos, type, tok, state, *rest|
+ [pos, type, tok, Ripper::Lexer::State.new(state), *rest]
+ end
+ assert_equal(expected, *rest)
+ end
+
def test_location
assert_location ""
assert_location " "
@@ -172,6 +181,11 @@ class TestRipper::ScannerEvents < Test::Unit::TestCase
scan('backtick', %q[p `make all`])
end
+ def test_colon2_call
+ assert_equal ["::"],
+ scan('op', %q[ a::b ])
+ end
+
def test_comma
assert_equal [','] * 6,
scan('comma', %q[ m(0,1,2,3,4,5,6) ])
@@ -705,7 +719,7 @@ class TestRipper::ScannerEvents < Test::Unit::TestCase
scan('words_sep', '%w( w w w )')
assert_equal [' ', "\n", ' ', ' '],
scan('words_sep', "%w( w\nw w )")
- assert_equal ["\n\n", "\n ", ' ', ' '],
+ assert_equal ["\n", "\n", "\n", ' ', ' ', ' '],
scan('words_sep', "%w(\n\nw\n w w )")
end
@@ -979,13 +993,27 @@ class TestRipper::ScannerEvents < Test::Unit::TestCase
assert_equal("\e", err[2])
end
- def test_invalid_hex_escape
+ def test_invalid_escape
err = nil
- assert_equal ['U'], scan('tstring_content', '"\\xU"') {|*e| err = e}
+ assert_equal ["\\C-\u{3042}"], scan('tstring_content', %["\\C-\u{3042}"]) {|*e| err = e}
+ assert_equal [:on_parse_error, "Invalid escape character syntax", "\\C-\u{3042}"], err
+ end
+
+ def test_invalid_hex_escape_string
+ err = nil
+ assert_equal ['\\x', 'U'], scan('tstring_content', '"\\xU"') {|*e| err = e}
assert_equal [:on_parse_error, "invalid hex escape", "\\x"], err
+ end
+ def test_invalid_hex_escape_regexp
err = nil
- assert_equal ['U'], scan('tstring_content', '/\\xU/') {|*e| err = e}
+ assert_equal ['\\x', 'U'], scan('tstring_content', '/\\xU/') {|*e| err = e}
assert_equal [:on_parse_error, "invalid hex escape", "\\x"], err
end
+
+ def test_error_token
+ src = "{a:,aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n""hello}"
+ err = scan('parse_error', src) {|*e| break e}
+ assert_equal "", err[2]
+ end
end if ripper_test
diff --git a/test/ripper/test_sexp.rb b/test/ripper/test_sexp.rb
index 9faeaba782..3ebcf3062e 100644
--- a/test/ripper/test_sexp.rb
+++ b/test/ripper/test_sexp.rb
@@ -18,6 +18,11 @@ class TestRipper::Sexp < Test::Unit::TestCase
assert_nil Ripper.sexp("/*")
assert_nil Ripper.sexp("/*/")
assert_nil Ripper.sexp("/+/")
+ assert_nil Ripper.sexp("m(&nil) {}"), '[Bug #10436]'
+ assert_nil Ripper.sexp("/(?<a>)/ =~ ''; x = a **a, **a if false"), '[Bug #18988]'
+ assert_nil Ripper.sexp("return + return"), '[Bug #20055]'
+ assert_nil Ripper.sexp("1 in [a, a]"), '[Bug #20055]'
+ assert_nil Ripper.sexp("1 + (1 => [a, a])"), '[Bug #20055]'
end
def test_regexp_content
@@ -34,6 +39,14 @@ class TestRipper::Sexp < Test::Unit::TestCase
assert_equal '(?<n>a(b|\g<n>))', search_sexp(:@tstring_content, search_sexp(:regexp_literal, sexp))[1]
end
+ def test_regexp_named_capture
+ sexp = Ripper.sexp("/(?<a>)/ =~ ''; x = a **a, a if false")
+ assert_not_nil sexp, '[Bug #18988]'
+
+ sexp = Ripper.sexp("/(?<a>)/ =~ ''; a %(exit)")
+ assert_equal 'exit', search_sexp(:@ident, search_sexp(:paren, sexp))[1], '[Bug #18988]'
+ end
+
def test_heredoc_content
sexp = Ripper.sexp("<<E\nfoo\nE")
assert_equal "foo\n", search_sexp(:@tstring_content, sexp)[1]
@@ -110,6 +123,21 @@ eot
assert_equal(exp, named)
end
+ def test_command
+ sexp = Ripper.sexp("a::C {}")
+ assert_equal(
+ [:program,
+ [
+ [:method_add_block,
+ [:command_call,
+ [:vcall, [:@ident, "a", [1, 0]]],
+ [:@op, "::", [1, 1]],
+ [:@const, "C", [1, 3]],
+ nil],
+ [:brace_block, nil, [[:void_stmt]]]]]],
+ sexp)
+ end
+
def search_sexp(sym, sexp)
return sexp if !sexp or sexp[0] == sym
sexp.find do |e|
@@ -175,7 +203,7 @@ eot
[:aryptn,
nil,
[[:var_field, [:@ident, "a", [1, 11]]]],
- [:var_field, nil],
+ nil,
nil],
[[:void_stmt]],
nil]],
@@ -407,6 +435,14 @@ eot
[[:void_stmt]],
nil]],
+ [__LINE__, %q{ case 0; in [a,]; end }] =>
+ [:case,
+ [:@int, "0", [1, 5]],
+ [:in,
+ [:aryptn, nil, [[:var_field, [:@ident, "a", [1, 12]]]], nil, nil],
+ [[:void_stmt]],
+ nil]],
+
[__LINE__, %q{ case 0; in []; end }] =>
[:case,
[:@int, "0", [1, 5]],
@@ -486,6 +522,22 @@ eot
[:begin, [:binary, [:@int, "0", [1, 13]], :+, [:@int, "0", [1, 15]]]],
[[:void_stmt]],
nil]],
+
+ [__LINE__, %q{ case 0; in [*a]; a; end } ] =>
+ [:case,
+ [:@int, "0", [1, 5]],
+ [:in,
+ [:aryptn, nil, nil, [:var_field, [:@ident, "a", [1, 13]]], nil],
+ [[:var_ref, [:@ident, "a", [1, 17]]]],
+ nil]],
+
+ [__LINE__, %q{ case 0; in {a:}; a; end } ] =>
+ [:case,
+ [:@int, "0", [1, 5]],
+ [:in,
+ [:hshptn, nil, [[[:@label, "a:", [1, 12]], nil]], nil],
+ [[:var_ref, [:@ident, "a", [1, 17]]]],
+ nil]],
}
pattern_matching_data.each do |(i, src), expected|
define_method(:"test_pattern_matching_#{i}") do
diff --git a/test/ruby/enc/test_case_comprehensive.rb b/test/ruby/enc/test_case_comprehensive.rb
index bde47017a2..de18ac865c 100644
--- a/test/ruby/enc/test_case_comprehensive.rb
+++ b/test/ruby/enc/test_case_comprehensive.rb
@@ -24,7 +24,7 @@ class TestComprehensiveCaseMapping < Test::Unit::TestCase
def test_data_files_available
unless TestComprehensiveCaseMapping.data_files_available?
- skip "Unicode data files not available in #{UNICODE_DATA_PATH}."
+ omit "Unicode data files not available in #{UNICODE_DATA_PATH}."
end
end
end
@@ -37,7 +37,7 @@ TestComprehensiveCaseMapping.data_files_available? and class TestComprehensiveC
end
def self.read_data_file(filename)
- IO.foreach(expand_filename(filename), encoding: Encoding::ASCII_8BIT) do |line|
+ File.foreach(expand_filename(filename), encoding: Encoding::ASCII_8BIT) do |line|
if $. == 1
if filename == 'UnicodeData'
elsif line.start_with?("# #{filename}-#{UNICODE_VERSION}.txt")
diff --git a/test/ruby/enc/test_case_mapping.rb b/test/ruby/enc/test_case_mapping.rb
index 31acdc4331..a7d1ed0d16 100644
--- a/test/ruby/enc/test_case_mapping.rb
+++ b/test/ruby/enc/test_case_mapping.rb
@@ -47,7 +47,7 @@ class TestCaseMappingPreliminary < Test::Unit::TestCase
# different properties; careful: roundtrip isn't always guaranteed
def check_swapcase_properties(expected, start, *flags)
assert_equal expected, start.swapcase(*flags)
- temp = start
+ temp = +start
assert_equal expected, temp.swapcase!(*flags)
assert_equal start, start.swapcase(*flags).swapcase(*flags)
assert_equal expected, expected.swapcase(*flags).swapcase(*flags)
@@ -61,10 +61,10 @@ class TestCaseMappingPreliminary < Test::Unit::TestCase
end
def test_invalid
- assert_raise(ArgumentError, "Should not be possible to upcase invalid string.") { "\xEB".force_encoding('UTF-8').upcase }
- assert_raise(ArgumentError, "Should not be possible to downcase invalid string.") { "\xEB".force_encoding('UTF-8').downcase }
- assert_raise(ArgumentError, "Should not be possible to capitalize invalid string.") { "\xEB".force_encoding('UTF-8').capitalize }
- assert_raise(ArgumentError, "Should not be possible to swapcase invalid string.") { "\xEB".force_encoding('UTF-8').swapcase }
+ assert_raise(ArgumentError, "Should not be possible to upcase invalid string.") { "\xEB".dup.force_encoding('UTF-8').upcase }
+ assert_raise(ArgumentError, "Should not be possible to downcase invalid string.") { "\xEB".dup.force_encoding('UTF-8').downcase }
+ assert_raise(ArgumentError, "Should not be possible to capitalize invalid string.") { "\xEB".dup.force_encoding('UTF-8').capitalize }
+ assert_raise(ArgumentError, "Should not be possible to swapcase invalid string.") { "\xEB".dup.force_encoding('UTF-8').swapcase }
end
def test_general
diff --git a/test/ruby/enc/test_case_options.rb b/test/ruby/enc/test_case_options.rb
index e9bf50fcfc..e9c81d804e 100644
--- a/test/ruby/enc/test_case_options.rb
+++ b/test/ruby/enc/test_case_options.rb
@@ -19,7 +19,7 @@ class TestCaseOptions < Test::Unit::TestCase
def assert_raise_both_types(*options)
assert_raise_functional_operations 'a', *options
- assert_raise_bang_operations 'a', *options
+ assert_raise_bang_operations(+'a', *options)
assert_raise_functional_operations :a, *options
end
@@ -51,7 +51,7 @@ class TestCaseOptions < Test::Unit::TestCase
def assert_okay_both_types(*options)
assert_okay_functional_operations 'a', *options
- assert_okay_bang_operations 'a', *options
+ assert_okay_bang_operations(+'a', *options)
assert_okay_functional_operations :a, *options
end
@@ -69,10 +69,10 @@ class TestCaseOptions < Test::Unit::TestCase
assert_raise(ArgumentError) { 'a'.upcase :fold }
assert_raise(ArgumentError) { 'a'.capitalize :fold }
assert_raise(ArgumentError) { 'a'.swapcase :fold }
- assert_nothing_raised { 'a'.downcase! :fold }
- assert_raise(ArgumentError) { 'a'.upcase! :fold }
- assert_raise(ArgumentError) { 'a'.capitalize! :fold }
- assert_raise(ArgumentError) { 'a'.swapcase! :fold }
+ assert_nothing_raised { 'a'.dup.downcase! :fold }
+ assert_raise(ArgumentError) { 'a'.dup.upcase! :fold }
+ assert_raise(ArgumentError) { 'a'.dup.capitalize! :fold }
+ assert_raise(ArgumentError) { 'a'.dup.swapcase! :fold }
assert_nothing_raised { :a.downcase :fold }
assert_raise(ArgumentError) { :a.upcase :fold }
assert_raise(ArgumentError) { :a.capitalize :fold }
diff --git a/test/ruby/enc/test_cesu8.rb b/test/ruby/enc/test_cesu8.rb
index d9debe76cd..68a08389ea 100644
--- a/test/ruby/enc/test_cesu8.rb
+++ b/test/ruby/enc/test_cesu8.rb
@@ -106,4 +106,8 @@ EOT
assert_equal chr, ord.chr("cesu-8")
end
end
+
+ def test_cesu8_left_adjust_char_head
+ assert_equal("", "\u{10000}".encode("cesu-8").chop)
+ end
end
diff --git a/test/ruby/enc/test_emoji_breaks.rb b/test/ruby/enc/test_emoji_breaks.rb
index cdde4da9bf..bb5114680e 100644
--- a/test/ruby/enc/test_emoji_breaks.rb
+++ b/test/ruby/enc/test_emoji_breaks.rb
@@ -4,50 +4,47 @@
require "test/unit"
class TestEmojiBreaks < Test::Unit::TestCase
-end
-
-class TestEmojiBreaks::BreakTest
- attr_reader :string, :comment, :filename, :line_number, :type, :shortname
-
- def initialize(filename, line_number, data, comment='')
- @filename = filename
- @line_number = line_number
- @comment = comment.gsub(/\s+/, ' ').strip
- if filename=='emoji-test' or filename=='emoji-variation-sequences'
- codes, @type = data.split(/\s*;\s*/)
- @shortname = ''
- else
- codes, @type, @shortname = data.split(/\s*;\s*/)
+ class BreakTest
+ attr_reader :string, :comment, :filename, :line_number, :type, :shortname
+
+ def initialize(filename, line_number, data, comment='')
+ @filename = filename
+ @line_number = line_number
+ @comment = comment.gsub(/\s+/, ' ').strip
+ if filename=='emoji-test' or filename=='emoji-variation-sequences'
+ codes, @type = data.split(/\s*;\s*/)
+ @shortname = ''
+ else
+ codes, @type, @shortname = data.split(/\s*;\s*/)
+ end
+ @type = @type.gsub(/\s+/, ' ').strip
+ @shortname = @shortname.gsub(/\s+/, ' ').strip
+ @string = codes.split(/\s+/)
+ .map do |ch|
+ c = ch.to_i(16)
+ # eliminate cases with surrogates
+ # raise ArgumentError if 0xD800 <= c and c <= 0xDFFF
+ c.chr('UTF-8')
+ end.join
end
- @type = @type.gsub(/\s+/, ' ').strip
- @shortname = @shortname.gsub(/\s+/, ' ').strip
- @string = codes.split(/\s+/)
- .map do |ch|
- c = ch.to_i(16)
- # eliminate cases with surrogates
- # raise ArgumentError if 0xD800 <= c and c <= 0xDFFF
- c.chr('UTF-8')
- end.join
end
-end
-class TestEmojiBreaks::BreakFile
- attr_reader :basename, :fullname, :version
- FILES = []
+ class BreakFile
+ attr_reader :basename, :fullname, :version
+ FILES = []
- def initialize(basename, path, version)
- @basename = basename
- @fullname = "#{path}/#{basename}.txt" # File.expand_path(path + version, __dir__)
- @version = version
- FILES << self
- end
+ def initialize(basename, path, version)
+ @basename = basename
+ @fullname = "#{path}/#{basename}.txt" # File.expand_path(path + version, __dir__)
+ @version = version
+ FILES << self
+ end
- def self.files
- FILES
+ def self.files
+ FILES
+ end
end
-end
-class TestEmojiBreaks < Test::Unit::TestCase
UNICODE_VERSION = RbConfig::CONFIG['UNICODE_VERSION']
UNICODE_DATA_PATH = File.expand_path("../../../enc/unicode/data/#{UNICODE_VERSION}/ucd/emoji", __dir__)
EMOJI_VERSION = RbConfig::CONFIG['UNICODE_EMOJI_VERSION']
@@ -56,7 +53,7 @@ class TestEmojiBreaks < Test::Unit::TestCase
EMOJI_DATA_FILES = %w[emoji-sequences emoji-test emoji-zwj-sequences].map do |basename|
BreakFile.new(basename, EMOJI_DATA_PATH, EMOJI_VERSION)
end
- UNICODE_DATA_FILE = BreakFile.new('emoji-variation-sequences', UNICODE_DATA_PATH, UNICODE_VERSION[0..-3]) # [0..-3] deals with a versioning mismatch problem in Unicode
+ UNICODE_DATA_FILE = BreakFile.new('emoji-variation-sequences', UNICODE_DATA_PATH, UNICODE_VERSION)
EMOJI_DATA_FILES << UNICODE_DATA_FILE
def self.data_files_available?
@@ -68,83 +65,90 @@ class TestEmojiBreaks < Test::Unit::TestCase
def test_data_files_available
assert_equal 4, EMOJI_DATA_FILES.size # debugging test
unless TestEmojiBreaks.data_files_available?
- skip "Emoji data files not available in #{EMOJI_DATA_PATH}."
+ omit "Emoji data files not available in #{EMOJI_DATA_PATH}."
end
end
-end
-TestEmojiBreaks.data_files_available? and class TestEmojiBreaks
- def read_data
- tests = []
- EMOJI_DATA_FILES.each do |file|
- version_mismatch = true
- file_tests = []
- IO.foreach(file.fullname, encoding: Encoding::UTF_8) do |line|
- line.chomp!
- raise "File Name Mismatch: line: #{line}, expected filename: #{file.basename}.txt" if $.==1 and not line=="# #{file.basename}.txt"
- version_mismatch = false if line =~ /^# Version: #{file.version}/
- next if line.match?(/\A(#|\z)/)
- if line =~ /^(\h{4,6})\.\.(\h{4,6}) *(;.+)/ # deal with Unicode ranges in emoji-sequences.txt (Bug #18028)
- range_start = $1.to_i(16)
- range_end = $2.to_i(16)
- rest = $3
- (range_start..range_end).each do |code_point|
- file_tests << BreakTest.new(file.basename, $., *(code_point.to_s(16)+rest).split('#', 2))
+ if data_files_available?
+ def read_data
+ tests = []
+ EMOJI_DATA_FILES.each do |file|
+ version_mismatch = true
+ file_tests = []
+ File.foreach(file.fullname, encoding: Encoding::UTF_8) do |line|
+ line.chomp!
+ if $.==1
+ if line=="# #{file.basename}-#{file.version}.txt"
+ version_mismatch = false
+ elsif line!="# #{file.basename}.txt"
+ raise "File Name Mismatch: line: #{line}, expected filename: #{file.basename}.txt"
+ end
+ end
+ version_mismatch = false if line =~ /^# Version: #{file.version}/ # 13.0 and older
+ version_mismatch = false if line =~ /^# Used with Emoji Version #{EMOJI_VERSION}/ # 14.0 and newer
+ next if line.match?(/\A(#|\z)/)
+ if line =~ /^(\h{4,6})\.\.(\h{4,6}) *(;.+)/ # deal with Unicode ranges in emoji-sequences.txt (Bug #18028)
+ range_start = $1.to_i(16)
+ range_end = $2.to_i(16)
+ rest = $3
+ (range_start..range_end).each do |code_point|
+ file_tests << BreakTest.new(file.basename, $., *(code_point.to_s(16)+rest).split('#', 2))
+ end
+ else
+ file_tests << BreakTest.new(file.basename, $., *line.split('#', 2))
end
- else
- file_tests << BreakTest.new(file.basename, $., *line.split('#', 2))
end
+ raise "File Version Mismatch: file: #{file.fullname}, version: #{file.version}" if version_mismatch
+ tests += file_tests
end
- raise "File Version Mismatch: file: #{file.fullname}, version: #{file.version}" if version_mismatch
- tests += file_tests
+ tests
end
- tests
- end
-
- def all_tests
- @@tests ||= read_data
- rescue Errno::ENOENT
- @@tests ||= []
- end
- def test_single_emoji
- all_tests.each do |test|
- expected = [test.string]
- actual = test.string.each_grapheme_cluster.to_a
- assert_equal expected, actual,
- "file: #{test.filename}, line #{test.line_number}, " +
- "type: #{test.type}, shortname: #{test.shortname}, comment: #{test.comment}"
+ def all_tests
+ @@tests ||= read_data
+ rescue Errno::ENOENT
+ @@tests ||= []
end
- end
- def test_embedded_emoji
- all_tests.each do |test|
- expected = ["\t", test.string, "\t"]
- actual = "\t#{test.string}\t".each_grapheme_cluster.to_a
- assert_equal expected, actual,
- "file: #{test.filename}, line #{test.line_number}, " +
- "type: #{test.type}, shortname: #{test.shortname}, comment: #{test.comment}"
+ def test_single_emoji
+ all_tests.each do |test|
+ expected = [test.string]
+ actual = test.string.each_grapheme_cluster.to_a
+ assert_equal expected, actual,
+ "file: #{test.filename}, line #{test.line_number}, " +
+ "type: #{test.type}, shortname: #{test.shortname}, comment: #{test.comment}"
+ end
end
- end
- # test some pseodorandom combinations of emoji
- def test_mixed_emoji
- srand 0
- length = all_tests.length
- step = 503 # use a prime number
- all_tests.each do |test1|
- start = rand step
- start.step(by: step, to: length-1) do |t2|
- test2 = all_tests[t2]
- # exclude skin tones, because they glue to previous grapheme clusters
- next if (0x1F3FB..0x1F3FF).include? test2.string.ord
- expected = [test1.string, test2.string]
- actual = (test1.string+test2.string).each_grapheme_cluster.to_a
+ def test_embedded_emoji
+ all_tests.each do |test|
+ expected = ["\t", test.string, "\t"]
+ actual = "\t#{test.string}\t".each_grapheme_cluster.to_a
assert_equal expected, actual,
- "file1: #{test1.filename}, line1 #{test1.line_number}, " +
- "file2: #{test2.filename}, line2 #{test2.line_number},\n" +
- "type1: #{test1.type}, shortname1: #{test1.shortname}, comment1: #{test1.comment},\n" +
- "type2: #{test2.type}, shortname2: #{test2.shortname}, comment2: #{test2.comment}"
+ "file: #{test.filename}, line #{test.line_number}, " +
+ "type: #{test.type}, shortname: #{test.shortname}, comment: #{test.comment}"
+ end
+ end
+
+ # test some pseodorandom combinations of emoji
+ def test_mixed_emoji
+ srand 0
+ length = all_tests.length
+ step = 503 # use a prime number
+ all_tests.each do |test1|
+ start = rand step
+ start.step(by: step, to: length-1) do |t2|
+ test2 = all_tests[t2]
+ # exclude skin tones, because they glue to previous grapheme clusters
+ next if (0x1F3FB..0x1F3FF).include? test2.string.ord
+ expected = [test1.string, test2.string]
+ actual = (test1.string+test2.string).each_grapheme_cluster.to_a
+ assert_equal expected, actual,
+ "file1: #{test1.filename}, line1 #{test1.line_number}, " +
+ "file2: #{test2.filename}, line2 #{test2.line_number},\n" +
+ "type1: #{test1.type}, shortname1: #{test1.shortname}, comment1: #{test1.comment},\n" +
+ "type2: #{test2.type}, shortname2: #{test2.shortname}, comment2: #{test2.comment}"
+ end
end
end
end
diff --git a/test/ruby/enc/test_grapheme_breaks.rb b/test/ruby/enc/test_grapheme_breaks.rb
index 2d210946a9..7e6d722d40 100644
--- a/test/ruby/enc/test_grapheme_breaks.rb
+++ b/test/ruby/enc/test_grapheme_breaks.rb
@@ -4,31 +4,28 @@
require "test/unit"
class TestGraphemeBreaksFromFile < Test::Unit::TestCase
-end
-
-class TestGraphemeBreaksFromFile::BreakTest
- attr_reader :clusters, :string, :comment, :line_number
+ class BreakTest
+ attr_reader :clusters, :string, :comment, :line_number
- def initialize(line_number, data, comment)
- @line_number = line_number
- @comment = comment
- @clusters = data.sub(/\A\s*÷\s*/, '')
- .sub(/\s*÷\s*\z/, '')
- .split(/\s*÷\s*/)
- .map do |cl|
- cl.split(/\s*×\s*/)
- .map do |ch|
- c = ch.to_i(16)
- # eliminate cases with surrogates
- raise ArgumentError if 0xD800 <= c and c <= 0xDFFF
- c.chr('UTF-8')
- end.join
- end
- @string = @clusters.join
+ def initialize(line_number, data, comment)
+ @line_number = line_number
+ @comment = comment
+ @clusters = data.sub(/\A\s*÷\s*/, '')
+ .sub(/\s*÷\s*\z/, '')
+ .split(/\s*÷\s*/)
+ .map do |cl|
+ cl.split(/\s*×\s*/)
+ .map do |ch|
+ c = ch.to_i(16)
+ # eliminate cases with surrogates
+ raise ArgumentError if 0xD800 <= c and c <= 0xDFFF
+ c.chr('UTF-8')
+ end.join
+ end
+ @string = @clusters.join
+ end
end
-end
-class TestGraphemeBreaksFromFile < Test::Unit::TestCase
UNICODE_VERSION = RbConfig::CONFIG['UNICODE_VERSION']
path = File.expand_path("../../../enc/unicode/data/#{UNICODE_VERSION}", __dir__)
UNICODE_DATA_PATH = File.directory?("#{path}/ucd/auxiliary") ? "#{path}/ucd/auxiliary" : path
@@ -40,56 +37,56 @@ class TestGraphemeBreaksFromFile < Test::Unit::TestCase
def test_data_files_available
unless TestGraphemeBreaksFromFile.file_available?
- skip "Unicode data file GraphemeBreakTest not available in #{UNICODE_DATA_PATH}."
+ omit "Unicode data file GraphemeBreakTest not available in #{UNICODE_DATA_PATH}."
end
end
-end
-TestGraphemeBreaksFromFile.file_available? and class TestGraphemeBreaksFromFile
- def read_data
- tests = []
- IO.foreach(GRAPHEME_BREAK_TEST_FILE, encoding: Encoding::UTF_8) do |line|
- if $. == 1 and not line.start_with?("# GraphemeBreakTest-#{UNICODE_VERSION}.txt")
- raise "File Version Mismatch"
+ if file_available?
+ def read_data
+ tests = []
+ File.foreach(GRAPHEME_BREAK_TEST_FILE, encoding: Encoding::UTF_8) do |line|
+ if $. == 1 and not line.start_with?("# GraphemeBreakTest-#{UNICODE_VERSION}.txt")
+ raise "File Version Mismatch"
+ end
+ next if /\A#/.match? line
+ tests << BreakTest.new($., *line.chomp.split('#')) rescue 'whatever'
end
- next if /\A#/.match? line
- tests << BreakTest.new($., *line.chomp.split('#')) rescue 'whatever'
+ tests
end
- tests
- end
- def all_tests
- @@tests ||= read_data
- rescue Errno::ENOENT
- @@tests ||= []
- end
+ def all_tests
+ @@tests ||= read_data
+ rescue Errno::ENOENT
+ @@tests ||= []
+ end
- def test_each_grapheme_cluster
- all_tests.each do |test|
- expected = test.clusters
- actual = test.string.each_grapheme_cluster.to_a
- assert_equal expected, actual,
- "line #{test.line_number}, expected '#{expected}', " +
- "but got '#{actual}', comment: #{test.comment}"
+ def test_each_grapheme_cluster
+ all_tests.each do |test|
+ expected = test.clusters
+ actual = test.string.each_grapheme_cluster.to_a
+ assert_equal expected, actual,
+ "line #{test.line_number}, expected '#{expected}', " +
+ "but got '#{actual}', comment: #{test.comment}"
+ end
end
- end
- def test_backslash_X
- all_tests.each do |test|
- clusters = test.clusters.dup
- string = test.string.dup
- removals = 0
- while string.sub!(/\A\X/, '')
- removals += 1
- clusters.shift
- expected = clusters.join
+ def test_backslash_X
+ all_tests.each do |test|
+ clusters = test.clusters.dup
+ string = test.string.dup
+ removals = 0
+ while string.sub!(/\A\X/, '')
+ removals += 1
+ clusters.shift
+ expected = clusters.join
+ assert_equal expected, string,
+ "line #{test.line_number}, removals: #{removals}, expected '#{expected}', " +
+ "but got '#{string}', comment: #{test.comment}"
+ end
assert_equal expected, string,
- "line #{test.line_number}, removals: #{removals}, expected '#{expected}', " +
+ "line #{test.line_number}, after last removal, expected '#{expected}', " +
"but got '#{string}', comment: #{test.comment}"
end
- assert_equal expected, string,
- "line #{test.line_number}, after last removal, expected '#{expected}', " +
- "but got '#{string}', comment: #{test.comment}"
end
end
end
diff --git a/test/ruby/enc/test_regex_casefold.rb b/test/ruby/enc/test_regex_casefold.rb
index ec5dc7f220..b5d5c6e337 100644
--- a/test/ruby/enc/test_regex_casefold.rb
+++ b/test/ruby/enc/test_regex_casefold.rb
@@ -19,7 +19,7 @@ class TestCaseFold < Test::Unit::TestCase
end
def read_tests
- IO.readlines("#{UNICODE_DATA_PATH}/CaseFolding.txt", encoding: Encoding::ASCII_8BIT)
+ File.readlines("#{UNICODE_DATA_PATH}/CaseFolding.txt", encoding: Encoding::ASCII_8BIT)
.collect.with_index { |linedata, linenumber| [linenumber.to_i+1, linedata.chomp] }
.reject { |number, data| data =~ /^(#|$)/ }
.collect do |linenumber, linedata|
@@ -39,7 +39,7 @@ class TestCaseFold < Test::Unit::TestCase
@@tests ||= read_tests
rescue Errno::ENOENT => e
@@tests ||= []
- skip e.message
+ omit e.message
end
def self.generate_test_casefold(encoding)
diff --git a/test/ruby/rjit/test_assembler.rb b/test/ruby/rjit/test_assembler.rb
new file mode 100644
index 0000000000..fbf780d6c3
--- /dev/null
+++ b/test/ruby/rjit/test_assembler.rb
@@ -0,0 +1,368 @@
+require 'test/unit'
+require_relative '../../lib/jit_support'
+
+return unless JITSupport.rjit_supported?
+return unless RubyVM::RJIT.enabled?
+return unless RubyVM::RJIT::C.HAVE_LIBCAPSTONE
+
+require 'stringio'
+require 'ruby_vm/rjit/assembler'
+
+module RubyVM::RJIT
+ class TestAssembler < Test::Unit::TestCase
+ MEM_SIZE = 16 * 1024
+
+ def setup
+ @mem_block ||= C.mmap(MEM_SIZE)
+ @cb = CodeBlock.new(mem_block: @mem_block, mem_size: MEM_SIZE)
+ end
+
+ def test_add
+ asm = Assembler.new
+ asm.add([:rcx], 1) # ADD r/m64, imm8 (Mod 00: [reg])
+ asm.add(:rax, 0x7f) # ADD r/m64, imm8 (Mod 11: reg)
+ asm.add(:rbx, 0x7fffffff) # ADD r/m64 imm32 (Mod 11: reg)
+ asm.add(:rsi, :rdi) # ADD r/m64, r64 (Mod 11: reg)
+ assert_compile(asm, <<~EOS)
+ 0x0: add qword ptr [rcx], 1
+ 0x4: add rax, 0x7f
+ 0x8: add rbx, 0x7fffffff
+ 0xf: add rsi, rdi
+ EOS
+ end
+
+ def test_and
+ asm = Assembler.new
+ asm.and(:rax, 0) # AND r/m64, imm8 (Mod 11: reg)
+ asm.and(:rbx, 0x7fffffff) # AND r/m64, imm32 (Mod 11: reg)
+ asm.and(:rcx, [:rdi, 8]) # AND r64, r/m64 (Mod 01: [reg]+disp8)
+ assert_compile(asm, <<~EOS)
+ 0x0: and rax, 0
+ 0x4: and rbx, 0x7fffffff
+ 0xb: and rcx, qword ptr [rdi + 8]
+ EOS
+ end
+
+ def test_call
+ asm = Assembler.new
+ asm.call(rel32(0xff)) # CALL rel32
+ asm.call(:rax) # CALL r/m64 (Mod 11: reg)
+ assert_compile(asm, <<~EOS)
+ 0x0: call 0xff
+ 0x5: call rax
+ EOS
+ end
+
+ def test_cmove
+ asm = Assembler.new
+ asm.cmove(:rax, :rcx) # CMOVE r64, r/m64 (Mod 11: reg)
+ assert_compile(asm, <<~EOS)
+ 0x0: cmove rax, rcx
+ EOS
+ end
+
+ def test_cmovg
+ asm = Assembler.new
+ asm.cmovg(:rbx, :rdi) # CMOVG r64, r/m64 (Mod 11: reg)
+ assert_compile(asm, <<~EOS)
+ 0x0: cmovg rbx, rdi
+ EOS
+ end
+
+ def test_cmovge
+ asm = Assembler.new
+ asm.cmovge(:rsp, :rbp) # CMOVGE r64, r/m64 (Mod 11: reg)
+ assert_compile(asm, <<~EOS)
+ 0x0: cmovge rsp, rbp
+ EOS
+ end
+
+ def test_cmovl
+ asm = Assembler.new
+ asm.cmovl(:rdx, :rsp) # CMOVL r64, r/m64 (Mod 11: reg)
+ assert_compile(asm, <<~EOS)
+ 0x0: cmovl rdx, rsp
+ EOS
+ end
+
+ def test_cmovle
+ asm = Assembler.new
+ asm.cmovle(:rax, :rax) # CMOVLE r64, r/m64 (Mod 11: reg)
+ assert_compile(asm, <<~EOS)
+ 0x0: cmovle rax, rax
+ EOS
+ end
+
+ def test_cmovne
+ asm = Assembler.new
+ asm.cmovne(:rax, :rbx) # CMOVNE r64, r/m64 (Mod 11: reg)
+ assert_compile(asm, <<~EOS) # cmovne == cmovnz
+ 0x0: cmovne rax, rbx
+ EOS
+ end
+
+ def test_cmovnz
+ asm = Assembler.new
+ asm.cmovnz(:rax, :rbx) # CMOVNZ r64, r/m64 (Mod 11: reg)
+ assert_compile(asm, <<~EOS) # cmovne == cmovnz
+ 0x0: cmovne rax, rbx
+ EOS
+ end
+
+ def test_cmovz
+ asm = Assembler.new
+ asm.cmovz(:rax, :rbx) # CMOVZ r64, r/m64 (Mod 11: reg)
+ assert_compile(asm, <<~EOS) # cmove == cmovz
+ 0x0: cmove rax, rbx
+ EOS
+ end
+
+ def test_cmp
+ asm = Assembler.new
+ asm.cmp(BytePtr[:rax, 8], 8) # CMP r/m8, imm8 (Mod 01: [reg]+disp8)
+ asm.cmp(DwordPtr[:rax, 8], 0x100) # CMP r/m32, imm32 (Mod 01: [reg]+disp8)
+ asm.cmp([:rax, 8], 8) # CMP r/m64, imm8 (Mod 01: [reg]+disp8)
+ asm.cmp([:rbx, 8], 0x100) # CMP r/m64, imm32 (Mod 01: [reg]+disp8)
+ asm.cmp([:rax, 0x100], 8) # CMP r/m64, imm8 (Mod 10: [reg]+disp32)
+ asm.cmp(:rax, 8) # CMP r/m64, imm8 (Mod 11: reg)
+ asm.cmp(:rax, 0x100) # CMP r/m64, imm32 (Mod 11: reg)
+ asm.cmp([:rax, 8], :rbx) # CMP r/m64, r64 (Mod 01: [reg]+disp8)
+ asm.cmp([:rax, -0x100], :rbx) # CMP r/m64, r64 (Mod 10: [reg]+disp32)
+ asm.cmp(:rax, :rbx) # CMP r/m64, r64 (Mod 11: reg)
+ assert_compile(asm, <<~EOS)
+ 0x0: cmp byte ptr [rax + 8], 8
+ 0x4: cmp dword ptr [rax + 8], 0x100
+ 0xb: cmp qword ptr [rax + 8], 8
+ 0x10: cmp qword ptr [rbx + 8], 0x100
+ 0x18: cmp qword ptr [rax + 0x100], 8
+ 0x20: cmp rax, 8
+ 0x24: cmp rax, 0x100
+ 0x2b: cmp qword ptr [rax + 8], rbx
+ 0x2f: cmp qword ptr [rax - 0x100], rbx
+ 0x36: cmp rax, rbx
+ EOS
+ end
+
+ def test_jbe
+ asm = Assembler.new
+ asm.jbe(rel32(0xff)) # JBE rel32
+ assert_compile(asm, <<~EOS)
+ 0x0: jbe 0xff
+ EOS
+ end
+
+ def test_je
+ asm = Assembler.new
+ asm.je(rel32(0xff)) # JE rel32
+ assert_compile(asm, <<~EOS)
+ 0x0: je 0xff
+ EOS
+ end
+
+ def test_jl
+ asm = Assembler.new
+ asm.jl(rel32(0xff)) # JL rel32
+ assert_compile(asm, <<~EOS)
+ 0x0: jl 0xff
+ EOS
+ end
+
+ def test_jmp
+ asm = Assembler.new
+ label = asm.new_label('label')
+ asm.jmp(label) # JZ rel8
+ asm.write_label(label)
+ asm.jmp(rel32(0xff)) # JMP rel32
+ asm.jmp([:rax, 8]) # JMP r/m64 (Mod 01: [reg]+disp8)
+ asm.jmp(:rax) # JMP r/m64 (Mod 11: reg)
+ assert_compile(asm, <<~EOS)
+ 0x0: jmp 2
+ 0x2: jmp 0xff
+ 0x7: jmp qword ptr [rax + 8]
+ 0xa: jmp rax
+ EOS
+ end
+
+ def test_jne
+ asm = Assembler.new
+ asm.jne(rel32(0xff)) # JNE rel32
+ assert_compile(asm, <<~EOS)
+ 0x0: jne 0xff
+ EOS
+ end
+
+ def test_jnz
+ asm = Assembler.new
+ asm.jnz(rel32(0xff)) # JNZ rel32
+ assert_compile(asm, <<~EOS)
+ 0x0: jne 0xff
+ EOS
+ end
+
+ def test_jo
+ asm = Assembler.new
+ asm.jo(rel32(0xff)) # JO rel32
+ assert_compile(asm, <<~EOS)
+ 0x0: jo 0xff
+ EOS
+ end
+
+ def test_jz
+ asm = Assembler.new
+ asm.jz(rel32(0xff)) # JZ rel32
+ assert_compile(asm, <<~EOS)
+ 0x0: je 0xff
+ EOS
+ end
+
+ def test_lea
+ asm = Assembler.new
+ asm.lea(:rax, [:rax, 8]) # LEA r64,m (Mod 01: [reg]+disp8)
+ asm.lea(:rax, [:rax, 0xffff]) # LEA r64,m (Mod 10: [reg]+disp32)
+ assert_compile(asm, <<~EOS)
+ 0x0: lea rax, [rax + 8]
+ 0x4: lea rax, [rax + 0xffff]
+ EOS
+ end
+
+ def test_mov
+ asm = Assembler.new
+ asm.mov(:eax, DwordPtr[:rbx, 8]) # MOV r32 r/m32 (Mod 01: [reg]+disp8)
+ asm.mov(:eax, 0x100) # MOV r32, imm32 (Mod 11: reg)
+ asm.mov(:rax, [:rbx]) # MOV r64, r/m64 (Mod 00: [reg])
+ asm.mov(:rax, [:rbx, 8]) # MOV r64, r/m64 (Mod 01: [reg]+disp8)
+ asm.mov(:rax, [:rbx, 0x100]) # MOV r64, r/m64 (Mod 10: [reg]+disp32)
+ asm.mov(:rax, :rbx) # MOV r64, r/m64 (Mod 11: reg)
+ asm.mov(:rax, 0x100) # MOV r/m64, imm32 (Mod 11: reg)
+ asm.mov(:rax, 0x100000000) # MOV r64, imm64
+ asm.mov(DwordPtr[:rax, 8], 0x100) # MOV r/m32, imm32 (Mod 01: [reg]+disp8)
+ asm.mov([:rax], 0x100) # MOV r/m64, imm32 (Mod 00: [reg])
+ asm.mov([:rax], :rbx) # MOV r/m64, r64 (Mod 00: [reg])
+ asm.mov([:rax, 8], 0x100) # MOV r/m64, imm32 (Mod 01: [reg]+disp8)
+ asm.mov([:rax, 8], :rbx) # MOV r/m64, r64 (Mod 01: [reg]+disp8)
+ asm.mov([:rax, 0x100], 0x100) # MOV r/m64, imm32 (Mod 10: [reg]+disp32)
+ asm.mov([:rax, 0x100], :rbx) # MOV r/m64, r64 (Mod 10: [reg]+disp32)
+ assert_compile(asm, <<~EOS)
+ 0x0: mov eax, dword ptr [rbx + 8]
+ 0x3: mov eax, 0x100
+ 0x8: mov rax, qword ptr [rbx]
+ 0xb: mov rax, qword ptr [rbx + 8]
+ 0xf: mov rax, qword ptr [rbx + 0x100]
+ 0x16: mov rax, rbx
+ 0x19: mov rax, 0x100
+ 0x20: movabs rax, 0x100000000
+ 0x2a: mov dword ptr [rax + 8], 0x100
+ 0x31: mov qword ptr [rax], 0x100
+ 0x38: mov qword ptr [rax], rbx
+ 0x3b: mov qword ptr [rax + 8], 0x100
+ 0x43: mov qword ptr [rax + 8], rbx
+ 0x47: mov qword ptr [rax + 0x100], 0x100
+ 0x52: mov qword ptr [rax + 0x100], rbx
+ EOS
+ end
+
+ def test_or
+ asm = Assembler.new
+ asm.or(:rax, 0) # OR r/m64, imm8 (Mod 11: reg)
+ asm.or(:rax, 0xffff) # OR r/m64, imm32 (Mod 11: reg)
+ asm.or(:rax, [:rbx, 8]) # OR r64, r/m64 (Mod 01: [reg]+disp8)
+ assert_compile(asm, <<~EOS)
+ 0x0: or rax, 0
+ 0x4: or rax, 0xffff
+ 0xb: or rax, qword ptr [rbx + 8]
+ EOS
+ end
+
+ def test_push
+ asm = Assembler.new
+ asm.push(:rax) # PUSH r64
+ assert_compile(asm, <<~EOS)
+ 0x0: push rax
+ EOS
+ end
+
+ def test_pop
+ asm = Assembler.new
+ asm.pop(:rax) # POP r64
+ assert_compile(asm, <<~EOS)
+ 0x0: pop rax
+ EOS
+ end
+
+ def test_ret
+ asm = Assembler.new
+ asm.ret # RET
+ assert_compile(asm, "0x0: ret \n")
+ end
+
+ def test_sar
+ asm = Assembler.new
+ asm.sar(:rax, 0) # SAR r/m64, imm8 (Mod 11: reg)
+ assert_compile(asm, <<~EOS)
+ 0x0: sar rax, 0
+ EOS
+ end
+
+ def test_sub
+ asm = Assembler.new
+ asm.sub(:rax, 8) # SUB r/m64, imm8 (Mod 11: reg)
+ asm.sub(:rax, :rbx) # SUB r/m64, r64 (Mod 11: reg)
+ assert_compile(asm, <<~EOS)
+ 0x0: sub rax, 8
+ 0x4: sub rax, rbx
+ EOS
+ end
+
+ def test_test
+ asm = Assembler.new
+ asm.test(BytePtr[:rax, 8], 16) # TEST r/m8*, imm8 (Mod 01: [reg]+disp8)
+ asm.test([:rax, 8], 8) # TEST r/m64, imm32 (Mod 01: [reg]+disp8)
+ asm.test([:rax, 0xffff], 0xffff) # TEST r/m64, imm32 (Mod 10: [reg]+disp32)
+ asm.test(:rax, 0xffff) # TEST r/m64, imm32 (Mod 11: reg)
+ asm.test(:eax, :ebx) # TEST r/m32, r32 (Mod 11: reg)
+ asm.test(:rax, :rbx) # TEST r/m64, r64 (Mod 11: reg)
+ assert_compile(asm, <<~EOS)
+ 0x0: test byte ptr [rax + 8], 0x10
+ 0x4: test qword ptr [rax + 8], 8
+ 0xc: test qword ptr [rax + 0xffff], 0xffff
+ 0x17: test rax, 0xffff
+ 0x1e: test eax, ebx
+ 0x20: test rax, rbx
+ EOS
+ end
+
+ def test_xor
+ asm = Assembler.new
+ asm.xor(:rax, :rbx)
+ assert_compile(asm, <<~EOS)
+ 0x0: xor rax, rbx
+ EOS
+ end
+
+ private
+
+ def rel32(offset)
+ @cb.write_addr + 0xff
+ end
+
+ def assert_compile(asm, expected)
+ actual = compile(asm)
+ assert_equal expected, actual, "---\n#{actual}---"
+ end
+
+ def compile(asm)
+ start_addr = @cb.write_addr
+ @cb.write(asm)
+ end_addr = @cb.write_addr
+
+ io = StringIO.new
+ @cb.dump_disasm(start_addr, end_addr, io:, color: false, test: true)
+ io.seek(0)
+ disasm = io.read
+
+ disasm.gsub!(/^ /, '')
+ disasm.sub!(/\n\z/, '')
+ disasm
+ end
+ end
+end
diff --git a/test/ruby/test_alias.rb b/test/ruby/test_alias.rb
index 271d552bf5..0d33cb993c 100644
--- a/test/ruby/test_alias.rb
+++ b/test/ruby/test_alias.rb
@@ -253,4 +253,43 @@ class TestAlias < Test::Unit::TestCase
assert_equal(:foo, k.instance_method(:bar).original_name)
assert_equal(:foo, name)
end
+
+ def test_alias_suppressing_redefinition
+ assert_in_out_err(%w[-w], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ class A
+ def foo; end
+ alias foo foo
+ def foo; end
+ end
+ end;
+ end
+
+ class C2
+ public :system
+ alias_method :bar, :system
+ alias_method :system, :bar
+ end
+
+ def test_zsuper_alias_visibility
+ assert(C2.new.respond_to?(:system))
+ end
+
+ def test_alias_memory_leak
+ assert_no_memory_leak([], "#{<<~"begin;"}", "#{<<~'end;'}", rss: true)
+ begin;
+ class A
+ 500.times do
+ 1000.times do |i|
+ define_method(:"foo_#{i}") {}
+
+ alias :"foo_#{i}" :"foo_#{i}"
+
+ remove_method :"foo_#{i}"
+ end
+ GC.start
+ end
+ end
+ end;
+ end
end
diff --git a/test/ruby/test_allocation.rb b/test/ruby/test_allocation.rb
new file mode 100644
index 0000000000..9ba01dfcf9
--- /dev/null
+++ b/test/ruby/test_allocation.rb
@@ -0,0 +1,842 @@
+# frozen_string_literal: false
+require 'test/unit'
+
+class TestAllocation < Test::Unit::TestCase
+ def munge_checks(checks)
+ checks
+ end
+
+ def check_allocations(checks)
+ dups = checks.split("\n").reject(&:empty?).tally.select{|_,v| v > 1}
+ raise "duplicate checks:\n#{dups.keys.join("\n")}" unless dups.empty?
+
+ checks = munge_checks(checks)
+
+ assert_separately([], <<~RUBY)
+ $allocations = [0, 0]
+ $counts = {}
+ failures = []
+
+ def self.num_allocations
+ ObjectSpace.count_objects($counts)
+ arrays = $counts[:T_ARRAY]
+ hashes = $counts[:T_HASH]
+ yield
+ ObjectSpace.count_objects($counts)
+ arrays -= $counts[:T_ARRAY]
+ hashes -= $counts[:T_HASH]
+ $allocations[0] = -arrays
+ $allocations[1] = -hashes
+ end
+
+ define_singleton_method(:check_allocations) do |num_arrays, num_hashes, check_code|
+ instance_eval <<~RB
+ empty_array = empty_array = []
+ empty_hash = empty_hash = {}
+ array1 = array1 = [1]
+ r2k_array = r2k_array = [Hash.ruby2_keywords_hash(a: 3)]
+ r2k_array1 = r2k_array1 = [1, Hash.ruby2_keywords_hash(a: 3)]
+ r2k_empty_array = r2k_empty_array = [Hash.ruby2_keywords_hash({})]
+ r2k_empty_array1 = r2k_empty_array1 = [1, Hash.ruby2_keywords_hash({})]
+ hash1 = hash1 = {a: 2}
+ nill = nill = nil
+ block = block = lambda{}
+
+ num_allocations do
+ \#{check_code}
+ end
+ RB
+
+ if num_arrays != $allocations[0]
+ failures << "Expected \#{num_arrays} array allocations for \#{check_code.inspect}, but \#{$allocations[0]} arrays allocated"
+ end
+ if num_hashes != $allocations[1]
+ failures << "Expected \#{num_hashes} hash allocations for \#{check_code.inspect}, but \#{$allocations[1]} hashes allocated"
+ end
+ end
+
+ GC.start
+ GC.disable
+
+ #{checks}
+
+ unless failures.empty?
+ assert_equal(true, false, failures.join("\n"))
+ end
+ RUBY
+ end
+
+ class Literal < self
+ def test_array_literal
+ check_allocations(<<~RUBY)
+ check_allocations(1, 0, "[]")
+ check_allocations(1, 0, "[1]")
+ check_allocations(1, 0, "[*empty_array]")
+ check_allocations(1, 0, "[*empty_array, 1, *empty_array]")
+ check_allocations(1, 0, "[*empty_array, *empty_array]")
+ check_allocations(1, 0, "[#{'1,'*100000}]")
+ RUBY
+ end
+
+ def test_hash_literal
+ check_allocations(<<~RUBY)
+ check_allocations(0, 1, "{}")
+ check_allocations(0, 1, "{a: 1}")
+ check_allocations(0, 1, "{**empty_hash}")
+ check_allocations(0, 1, "{**empty_hash, a: 1, **empty_hash}")
+ check_allocations(0, 1, "{**empty_hash, **empty_hash}")
+ check_allocations(0, 1, "{#{100000.times.map{|i| "a#{i}: 1"}.join(',')}}")
+ RUBY
+ end
+ end
+
+ class MethodCall < self
+ def block
+ ''
+ end
+
+ def test_no_parameters
+ only_block = block.empty? ? block : block[2..]
+ check_allocations(<<~RUBY)
+ def self.none(#{only_block}); end
+
+ check_allocations(0, 0, "none(#{only_block})")
+ check_allocations(0, 0, "none(*empty_array#{block})")
+ check_allocations(0, 0, "none(**empty_hash#{block})")
+ check_allocations(0, 0, "none(*empty_array, **empty_hash#{block})")
+
+ check_allocations(1, 0, "none(*empty_array, *empty_array#{block})")
+ check_allocations(0, 1, "none(**empty_hash, **empty_hash#{block})")
+ check_allocations(1, 1, "none(*empty_array, *empty_array, **empty_hash, **empty_hash#{block})")
+
+ check_allocations(0, 0, "none(*r2k_empty_array#{block})")
+ RUBY
+ end
+
+ def test_required_parameter
+ check_allocations(<<~RUBY)
+ def self.required(x#{block}); end
+
+ check_allocations(0, 0, "required(1#{block})")
+ check_allocations(0, 0, "required(1, *empty_array#{block})")
+ check_allocations(0, 0, "required(1, **empty_hash#{block})")
+ check_allocations(0, 0, "required(1, *empty_array, **empty_hash#{block})")
+
+ check_allocations(0, 0, "required(*array1#{block})")
+ check_allocations(0, 1, "required(**hash1#{block})")
+
+ check_allocations(1, 0, "required(*array1, *empty_array#{block})")
+ check_allocations(0, 1, "required(**hash1, **empty_hash#{block})")
+ check_allocations(1, 0, "required(*array1, *empty_array, **empty_hash#{block})")
+
+ check_allocations(0, 0, "required(*r2k_empty_array1#{block})")
+ check_allocations(0, 1, "required(*r2k_array#{block})")
+
+ check_allocations(0, 1, "required(*empty_array, **hash1, **empty_hash#{block})")
+ RUBY
+ end
+
+ def test_optional_parameter
+ check_allocations(<<~RUBY)
+ def self.optional(x=nil#{block}); end
+
+ check_allocations(0, 0, "optional(1#{block})")
+ check_allocations(0, 0, "optional(1, *empty_array#{block})")
+ check_allocations(0, 0, "optional(1, **empty_hash#{block})")
+ check_allocations(0, 0, "optional(1, *empty_array, **empty_hash#{block})")
+
+ check_allocations(0, 0, "optional(*array1#{block})")
+ check_allocations(0, 1, "optional(**hash1#{block})")
+
+ check_allocations(1, 0, "optional(*array1, *empty_array#{block})")
+ check_allocations(0, 1, "optional(**hash1, **empty_hash#{block})")
+ check_allocations(1, 0, "optional(*array1, *empty_array, **empty_hash#{block})")
+
+ check_allocations(0, 0, "optional(*r2k_empty_array#{block})")
+ check_allocations(0, 0, "optional(*r2k_empty_array1#{block})")
+ check_allocations(0, 1, "optional(*r2k_array#{block})")
+
+ check_allocations(0, 1, "optional(*empty_array, **hash1, **empty_hash#{block})")
+ RUBY
+ end
+
+ def test_positional_splat_parameter
+ check_allocations(<<~RUBY)
+ def self.splat(*x#{block}); end
+
+ check_allocations(1, 0, "splat(1#{block})")
+ check_allocations(1, 0, "splat(1, *empty_array#{block})")
+ check_allocations(1, 0, "splat(1, **empty_hash#{block})")
+ check_allocations(1, 0, "splat(1, *empty_array, **empty_hash#{block})")
+
+ check_allocations(1, 0, "splat(*array1#{block})")
+ check_allocations(1, 0, "splat(*array1, *empty_array#{block})")
+ check_allocations(1, 0, "splat(*array1, **empty_hash#{block})")
+ check_allocations(1, 0, "splat(*array1, *empty_array, **empty_hash#{block})")
+
+ check_allocations(1, 0, "splat(1, *array1#{block})")
+ check_allocations(1, 0, "splat(1, *array1, *empty_array#{block})")
+ check_allocations(1, 0, "splat(1, *array1, **empty_hash#{block})")
+ check_allocations(1, 0, "splat(1, *array1, *empty_array, **empty_hash#{block})")
+
+ check_allocations(1, 1, "splat(**hash1#{block})")
+
+ check_allocations(1, 1, "splat(**hash1, **empty_hash#{block})")
+ check_allocations(1, 1, "splat(*empty_array, **hash1, **empty_hash#{block})")
+
+ check_allocations(1, 0, "splat(*r2k_empty_array#{block})")
+ check_allocations(1, 0, "splat(*r2k_empty_array1#{block})")
+ check_allocations(1, 1, "splat(*r2k_array#{block})")
+ check_allocations(1, 1, "splat(*r2k_array1#{block})")
+ RUBY
+ end
+
+ def test_required_and_positional_splat_parameters
+ check_allocations(<<~RUBY)
+ def self.req_splat(x, *y#{block}); end
+
+ check_allocations(1, 0, "req_splat(1#{block})")
+ check_allocations(1, 0, "req_splat(1, *empty_array#{block})")
+ check_allocations(1, 0, "req_splat(1, **empty_hash#{block})")
+ check_allocations(1, 0, "req_splat(1, *empty_array, **empty_hash#{block})")
+
+ check_allocations(1, 0, "req_splat(*array1#{block})")
+ check_allocations(1, 0, "req_splat(*array1, *empty_array#{block})")
+ check_allocations(1, 0, "req_splat(*array1, **empty_hash#{block})")
+ check_allocations(1, 0, "req_splat(*array1, *empty_array, **empty_hash#{block})")
+
+ check_allocations(1, 0, "req_splat(1, *array1#{block})")
+ check_allocations(1, 0, "req_splat(1, *array1, *empty_array#{block})")
+ check_allocations(1, 0, "req_splat(1, *array1, **empty_hash#{block})")
+ check_allocations(1, 0, "req_splat(1, *array1, *empty_array, **empty_hash#{block})")
+
+ check_allocations(1, 1, "req_splat(**hash1#{block})")
+
+ check_allocations(1, 1, "req_splat(**hash1, **empty_hash#{block})")
+ check_allocations(1, 1, "req_splat(*empty_array, **hash1, **empty_hash#{block})")
+
+ check_allocations(1, 0, "req_splat(*r2k_empty_array1#{block})")
+ check_allocations(1, 1, "req_splat(*r2k_array#{block})")
+ check_allocations(1, 1, "req_splat(*r2k_array1#{block})")
+ RUBY
+ end
+
+ def test_positional_splat_and_post_parameters
+ check_allocations(<<~RUBY)
+ def self.splat_post(*x, y#{block}); end
+
+ check_allocations(1, 0, "splat_post(1#{block})")
+ check_allocations(1, 0, "splat_post(1, *empty_array#{block})")
+ check_allocations(1, 0, "splat_post(1, **empty_hash#{block})")
+ check_allocations(1, 0, "splat_post(1, *empty_array, **empty_hash#{block})")
+
+ check_allocations(1, 0, "splat_post(*array1#{block})")
+ check_allocations(1, 0, "splat_post(*array1, *empty_array#{block})")
+ check_allocations(1, 0, "splat_post(*array1, **empty_hash#{block})")
+ check_allocations(1, 0, "splat_post(*array1, *empty_array, **empty_hash#{block})")
+
+ check_allocations(1, 0, "splat_post(1, *array1#{block})")
+ check_allocations(1, 0, "splat_post(1, *array1, *empty_array#{block})")
+ check_allocations(1, 0, "splat_post(1, *array1, **empty_hash#{block})")
+ check_allocations(1, 0, "splat_post(1, *array1, *empty_array, **empty_hash#{block})")
+
+ check_allocations(1, 1, "splat_post(**hash1#{block})")
+
+ check_allocations(1, 1, "splat_post(**hash1, **empty_hash#{block})")
+ check_allocations(1, 1, "splat_post(*empty_array, **hash1, **empty_hash#{block})")
+
+ check_allocations(1, 0, "splat_post(*r2k_empty_array1#{block})")
+ check_allocations(1, 1, "splat_post(*r2k_array#{block})")
+ check_allocations(1, 1, "splat_post(*r2k_array1#{block})")
+ RUBY
+ end
+
+ def test_keyword_parameter
+ check_allocations(<<~RUBY)
+ def self.keyword(a: nil#{block}); end
+
+ check_allocations(0, 0, "keyword(a: 2#{block})")
+ check_allocations(0, 0, "keyword(*empty_array, a: 2#{block})")
+ check_allocations(0, 1, "keyword(a:2, **empty_hash#{block})")
+ check_allocations(0, 1, "keyword(**empty_hash, a: 2#{block})")
+
+ check_allocations(0, 0, "keyword(**nil#{block})")
+ check_allocations(0, 0, "keyword(**empty_hash#{block})")
+ check_allocations(0, 0, "keyword(**hash1#{block})")
+ check_allocations(0, 0, "keyword(*empty_array, **hash1#{block})")
+ check_allocations(0, 1, "keyword(**hash1, **empty_hash#{block})")
+ check_allocations(0, 1, "keyword(**empty_hash, **hash1#{block})")
+
+ check_allocations(0, 0, "keyword(*empty_array#{block})")
+ check_allocations(1, 0, "keyword(*empty_array, *empty_array, **empty_hash#{block})")
+
+ check_allocations(0, 0, "keyword(*r2k_empty_array#{block})")
+ check_allocations(0, 0, "keyword(*r2k_array#{block})")
+
+ check_allocations(0, 1, "keyword(*empty_array, a: 2, **empty_hash#{block})")
+ check_allocations(0, 1, "keyword(*empty_array, **hash1, **empty_hash#{block})")
+ RUBY
+ end
+
+ def test_keyword_splat_parameter
+ check_allocations(<<~RUBY)
+ def self.keyword_splat(**kw#{block}); end
+
+ check_allocations(0, 1, "keyword_splat(a: 2#{block})")
+ check_allocations(0, 1, "keyword_splat(*empty_array, a: 2#{block})")
+ check_allocations(0, 1, "keyword_splat(a:2, **empty_hash#{block})")
+ check_allocations(0, 1, "keyword_splat(**empty_hash, a: 2#{block})")
+
+ check_allocations(0, 1, "keyword_splat(**nil#{block})")
+ check_allocations(0, 1, "keyword_splat(**empty_hash#{block})")
+ check_allocations(0, 1, "keyword_splat(**hash1#{block})")
+ check_allocations(0, 1, "keyword_splat(*empty_array, **hash1#{block})")
+ check_allocations(0, 1, "keyword_splat(**hash1, **empty_hash#{block})")
+ check_allocations(0, 1, "keyword_splat(**empty_hash, **hash1#{block})")
+
+ check_allocations(0, 1, "keyword_splat(*empty_array#{block})")
+ check_allocations(1, 1, "keyword_splat(*empty_array, *empty_array, **empty_hash#{block})")
+
+ check_allocations(0, 1, "keyword_splat(*r2k_empty_array#{block})")
+ check_allocations(0, 1, "keyword_splat(*r2k_array#{block})")
+
+ check_allocations(0, 1, "keyword_splat(*empty_array, a: 2, **empty_hash#{block})")
+ check_allocations(0, 1, "keyword_splat(*empty_array, **hash1, **empty_hash#{block})")
+ RUBY
+ end
+
+ def test_keyword_and_keyword_splat_parameter
+ check_allocations(<<~RUBY)
+ def self.keyword_and_keyword_splat(a: 1, **kw#{block}); end
+
+ check_allocations(0, 1, "keyword_and_keyword_splat(a: 2#{block})")
+ check_allocations(0, 1, "keyword_and_keyword_splat(*empty_array, a: 2#{block})")
+ check_allocations(0, 1, "keyword_and_keyword_splat(a:2, **empty_hash#{block})")
+ check_allocations(0, 1, "keyword_and_keyword_splat(**empty_hash, a: 2#{block})")
+
+ check_allocations(0, 1, "keyword_and_keyword_splat(**nil#{block})")
+ check_allocations(0, 1, "keyword_and_keyword_splat(**empty_hash#{block})")
+ check_allocations(0, 1, "keyword_and_keyword_splat(**hash1#{block})")
+ check_allocations(0, 1, "keyword_and_keyword_splat(*empty_array, **hash1#{block})")
+ check_allocations(0, 1, "keyword_and_keyword_splat(**hash1, **empty_hash#{block})")
+ check_allocations(0, 1, "keyword_and_keyword_splat(**empty_hash, **hash1#{block})")
+
+ check_allocations(0, 1, "keyword_and_keyword_splat(*empty_array#{block})")
+ check_allocations(1, 1, "keyword_and_keyword_splat(*empty_array, *empty_array, **empty_hash#{block})")
+
+ check_allocations(0, 1, "keyword_and_keyword_splat(*r2k_empty_array#{block})")
+ check_allocations(0, 1, "keyword_and_keyword_splat(*r2k_array#{block})")
+
+ check_allocations(0, 1, "keyword_and_keyword_splat(*empty_array, a: 2, **empty_hash#{block})")
+ check_allocations(0, 1, "keyword_and_keyword_splat(*empty_array, **hash1, **empty_hash#{block})")
+ RUBY
+ end
+
+ def test_required_positional_and_keyword_parameter
+ check_allocations(<<~RUBY)
+ def self.required_and_keyword(b, a: nil#{block}); end
+
+ check_allocations(0, 0, "required_and_keyword(1, a: 2#{block})")
+ check_allocations(0, 0, "required_and_keyword(1, *empty_array, a: 2#{block})")
+ check_allocations(0, 1, "required_and_keyword(1, a:2, **empty_hash#{block})")
+ check_allocations(0, 1, "required_and_keyword(1, **empty_hash, a: 2#{block})")
+
+ check_allocations(0, 0, "required_and_keyword(1, **nil#{block})")
+ check_allocations(0, 0, "required_and_keyword(1, **empty_hash#{block})")
+ check_allocations(0, 0, "required_and_keyword(1, **hash1#{block})")
+ check_allocations(0, 0, "required_and_keyword(1, *empty_array, **hash1#{block})")
+ check_allocations(0, 1, "required_and_keyword(1, **hash1, **empty_hash#{block})")
+ check_allocations(0, 1, "required_and_keyword(1, **empty_hash, **hash1#{block})")
+
+ check_allocations(0, 0, "required_and_keyword(1, *empty_array#{block})")
+ check_allocations(1, 0, "required_and_keyword(1, *empty_array, *empty_array, **empty_hash#{block})")
+
+ check_allocations(0, 0, "required_and_keyword(*array1, a: 2#{block})")
+
+ check_allocations(0, 0, "required_and_keyword(*array1, **nill#{block})")
+ check_allocations(0, 0, "required_and_keyword(*array1, **empty_hash#{block})")
+ check_allocations(0, 0, "required_and_keyword(*array1, **hash1#{block})")
+ check_allocations(1, 0, "required_and_keyword(*array1, *empty_array, **hash1#{block})")
+
+ check_allocations(1, 0, "required_and_keyword(*array1, *empty_array#{block})")
+ check_allocations(1, 0, "required_and_keyword(*array1, *empty_array, **empty_hash#{block})")
+
+ check_allocations(1, 1, "required_and_keyword(*array1, *empty_array, a: 2, **empty_hash#{block})")
+ check_allocations(1, 1, "required_and_keyword(*array1, *empty_array, **hash1, **empty_hash#{block})")
+
+ check_allocations(0, 0, "required_and_keyword(*r2k_empty_array1#{block})")
+ check_allocations(0, 0, "required_and_keyword(*r2k_array1#{block})")
+
+ check_allocations(0, 1, "required_and_keyword(1, *empty_array, a: 2, **empty_hash#{block})")
+ check_allocations(0, 1, "required_and_keyword(1, *empty_array, **hash1, **empty_hash#{block})")
+ check_allocations(0, 1, "required_and_keyword(*array1, **empty_hash, a: 2#{block})")
+ check_allocations(0, 1, "required_and_keyword(*array1, **hash1, **empty_hash#{block})")
+ check_allocations(0, 0, "required_and_keyword(*array1, **nil#{block})")
+ RUBY
+ end
+
+ def test_positional_splat_and_keyword_parameter
+ check_allocations(<<~RUBY)
+ def self.splat_and_keyword(*b, a: nil#{block}); end
+
+ check_allocations(1, 0, "splat_and_keyword(1, a: 2#{block})")
+ check_allocations(1, 0, "splat_and_keyword(1, *empty_array, a: 2#{block})")
+ check_allocations(1, 1, "splat_and_keyword(1, a:2, **empty_hash#{block})")
+ check_allocations(1, 1, "splat_and_keyword(1, **empty_hash, a: 2#{block})")
+
+ check_allocations(1, 0, "splat_and_keyword(1, **nil#{block})")
+ check_allocations(1, 0, "splat_and_keyword(1, **empty_hash#{block})")
+ check_allocations(1, 0, "splat_and_keyword(1, **hash1#{block})")
+ check_allocations(1, 0, "splat_and_keyword(1, *empty_array, **hash1#{block})")
+ check_allocations(1, 1, "splat_and_keyword(1, **hash1, **empty_hash#{block})")
+ check_allocations(1, 1, "splat_and_keyword(1, **empty_hash, **hash1#{block})")
+
+ check_allocations(1, 0, "splat_and_keyword(1, *empty_array#{block})")
+ check_allocations(1, 0, "splat_and_keyword(1, *empty_array, *empty_array, **empty_hash#{block})")
+
+ check_allocations(1, 0, "splat_and_keyword(*array1, a: 2#{block})")
+
+ check_allocations(1, 0, "splat_and_keyword(*array1, **nill#{block})")
+ check_allocations(1, 0, "splat_and_keyword(*array1, **empty_hash#{block})")
+ check_allocations(1, 0, "splat_and_keyword(*array1, **hash1#{block})")
+ check_allocations(1, 0, "splat_and_keyword(*array1, *empty_array, **hash1#{block})")
+
+ check_allocations(1, 0, "splat_and_keyword(*array1, *empty_array#{block})")
+ check_allocations(1, 0, "splat_and_keyword(*array1, *empty_array, **empty_hash#{block})")
+
+ check_allocations(1, 1, "splat_and_keyword(*array1, *empty_array, a: 2, **empty_hash#{block})")
+ check_allocations(1, 1, "splat_and_keyword(*array1, *empty_array, **hash1, **empty_hash#{block})")
+
+ check_allocations(1, 1, "splat_and_keyword(1, *empty_array, a: 2, **empty_hash#{block})")
+ check_allocations(1, 1, "splat_and_keyword(1, *empty_array, **hash1, **empty_hash#{block})")
+ check_allocations(1, 1, "splat_and_keyword(*array1, **empty_hash, a: 2#{block})")
+ check_allocations(1, 1, "splat_and_keyword(*array1, **hash1, **empty_hash#{block})")
+ check_allocations(1, 0, "splat_and_keyword(*array1, **nil#{block})")
+
+ check_allocations(1, 0, "splat_and_keyword(*r2k_empty_array#{block})")
+ check_allocations(1, 0, "splat_and_keyword(*r2k_array#{block})")
+ check_allocations(1, 0, "splat_and_keyword(*r2k_empty_array1#{block})")
+ check_allocations(1, 0, "splat_and_keyword(*r2k_array1#{block})")
+ RUBY
+ end
+
+ def test_required_and_keyword_splat_parameter
+ check_allocations(<<~RUBY)
+ def self.required_and_keyword_splat(b, **kw#{block}); end
+
+ check_allocations(0, 1, "required_and_keyword_splat(1, a: 2#{block})")
+ check_allocations(0, 1, "required_and_keyword_splat(1, *empty_array, a: 2#{block})")
+ check_allocations(0, 1, "required_and_keyword_splat(1, a:2, **empty_hash#{block})")
+ check_allocations(0, 1, "required_and_keyword_splat(1, **empty_hash, a: 2#{block})")
+
+ check_allocations(0, 1, "required_and_keyword_splat(1, **nil#{block})")
+ check_allocations(0, 1, "required_and_keyword_splat(1, **empty_hash#{block})")
+ check_allocations(0, 1, "required_and_keyword_splat(1, **hash1#{block})")
+ check_allocations(0, 1, "required_and_keyword_splat(1, *empty_array, **hash1#{block})")
+ check_allocations(0, 1, "required_and_keyword_splat(1, **hash1, **empty_hash#{block})")
+ check_allocations(0, 1, "required_and_keyword_splat(1, **empty_hash, **hash1#{block})")
+
+ check_allocations(0, 1, "required_and_keyword_splat(1, *empty_array#{block})")
+ check_allocations(1, 1, "required_and_keyword_splat(1, *empty_array, *empty_array, **empty_hash#{block})")
+
+ check_allocations(0, 1, "required_and_keyword_splat(*array1, a: 2#{block})")
+
+ check_allocations(0, 1, "required_and_keyword_splat(*array1, **nill#{block})")
+ check_allocations(0, 1, "required_and_keyword_splat(*array1, **empty_hash#{block})")
+ check_allocations(0, 1, "required_and_keyword_splat(*array1, **hash1#{block})")
+ check_allocations(1, 1, "required_and_keyword_splat(*array1, *empty_array, **hash1#{block})")
+
+ check_allocations(1, 1, "required_and_keyword_splat(*array1, *empty_array#{block})")
+ check_allocations(1, 1, "required_and_keyword_splat(*array1, *empty_array, **empty_hash#{block})")
+
+ check_allocations(1, 1, "required_and_keyword_splat(*array1, *empty_array, a: 2, **empty_hash#{block})")
+ check_allocations(1, 1, "required_and_keyword_splat(*array1, *empty_array, **hash1, **empty_hash#{block})")
+
+ check_allocations(0, 1, "required_and_keyword_splat(*r2k_empty_array1#{block})")
+ check_allocations(0, 1, "required_and_keyword_splat(*r2k_array1#{block})")
+
+ check_allocations(0, 1, "required_and_keyword_splat(1, *empty_array, a: 2, **empty_hash#{block})")
+ check_allocations(0, 1, "required_and_keyword_splat(1, *empty_array, **hash1, **empty_hash#{block})")
+ check_allocations(0, 1, "required_and_keyword_splat(*array1, **empty_hash, a: 2#{block})")
+ check_allocations(0, 1, "required_and_keyword_splat(*array1, **hash1, **empty_hash#{block})")
+ check_allocations(0, 1, "required_and_keyword_splat(*array1, **nil#{block})")
+ RUBY
+ end
+
+ def test_positional_splat_and_keyword_splat_parameter
+ check_allocations(<<~RUBY)
+ def self.splat_and_keyword_splat(*b, **kw#{block}); end
+
+ check_allocations(1, 1, "splat_and_keyword_splat(1, a: 2#{block})")
+ check_allocations(1, 1, "splat_and_keyword_splat(1, *empty_array, a: 2#{block})")
+ check_allocations(1, 1, "splat_and_keyword_splat(1, a:2, **empty_hash#{block})")
+ check_allocations(1, 1, "splat_and_keyword_splat(1, **empty_hash, a: 2#{block})")
+
+ check_allocations(1, 1, "splat_and_keyword_splat(1, **nil#{block})")
+ check_allocations(1, 1, "splat_and_keyword_splat(1, **empty_hash#{block})")
+ check_allocations(1, 1, "splat_and_keyword_splat(1, **hash1#{block})")
+ check_allocations(1, 1, "splat_and_keyword_splat(1, *empty_array, **hash1#{block})")
+ check_allocations(1, 1, "splat_and_keyword_splat(1, **hash1, **empty_hash#{block})")
+ check_allocations(1, 1, "splat_and_keyword_splat(1, **empty_hash, **hash1#{block})")
+
+ check_allocations(1, 1, "splat_and_keyword_splat(1, *empty_array#{block})")
+ check_allocations(1, 1, "splat_and_keyword_splat(1, *empty_array, *empty_array, **empty_hash#{block})")
+
+ check_allocations(1, 1, "splat_and_keyword_splat(*array1, a: 2#{block})")
+
+ check_allocations(1, 1, "splat_and_keyword_splat(*array1, **nill#{block})")
+ check_allocations(1, 1, "splat_and_keyword_splat(*array1, **empty_hash#{block})")
+ check_allocations(1, 1, "splat_and_keyword_splat(*array1, **hash1#{block})")
+ check_allocations(1, 1, "splat_and_keyword_splat(*array1, *empty_array, **hash1#{block})")
+
+ check_allocations(1, 1, "splat_and_keyword_splat(*array1, *empty_array#{block})")
+ check_allocations(1, 1, "splat_and_keyword_splat(*array1, *empty_array, **empty_hash#{block})")
+
+ check_allocations(1, 1, "splat_and_keyword_splat(*array1, *empty_array, a: 2, **empty_hash#{block})")
+ check_allocations(1, 1, "splat_and_keyword_splat(*array1, *empty_array, **hash1, **empty_hash#{block})")
+
+ check_allocations(1, 1, "splat_and_keyword_splat(1, *empty_array, a: 2, **empty_hash#{block})")
+ check_allocations(1, 1, "splat_and_keyword_splat(1, *empty_array, **hash1, **empty_hash#{block})")
+ check_allocations(1, 1, "splat_and_keyword_splat(*array1, **empty_hash, a: 2#{block})")
+ check_allocations(1, 1, "splat_and_keyword_splat(*array1, **hash1, **empty_hash#{block})")
+ check_allocations(1, 1, "splat_and_keyword_splat(*array1, **nil#{block})")
+
+ check_allocations(1, 1, "splat_and_keyword_splat(*r2k_empty_array#{block})")
+ check_allocations(1, 1, "splat_and_keyword_splat(*r2k_array#{block})")
+ check_allocations(1, 1, "splat_and_keyword_splat(*r2k_empty_array1#{block})")
+ check_allocations(1, 1, "splat_and_keyword_splat(*r2k_array1#{block})")
+ RUBY
+ end
+
+ def test_anonymous_splat_and_anonymous_keyword_splat_parameters
+ check_allocations(<<~RUBY)
+ def self.anon_splat_and_anon_keyword_splat(*, **#{block}); end
+
+ check_allocations(1, 1, "anon_splat_and_anon_keyword_splat(1, a: 2#{block})")
+ check_allocations(1, 0, "anon_splat_and_anon_keyword_splat(1, *empty_array, a: 2#{block})")
+ check_allocations(1, 1, "anon_splat_and_anon_keyword_splat(1, a:2, **empty_hash#{block})")
+ check_allocations(1, 1, "anon_splat_and_anon_keyword_splat(1, **empty_hash, a: 2#{block})")
+
+ check_allocations(1, 0, "anon_splat_and_anon_keyword_splat(1, **nil#{block})")
+ check_allocations(1, 0, "anon_splat_and_anon_keyword_splat(1, **empty_hash#{block})")
+ check_allocations(1, 0, "anon_splat_and_anon_keyword_splat(1, **hash1#{block})")
+ check_allocations(1, 0, "anon_splat_and_anon_keyword_splat(1, *empty_array, **hash1#{block})")
+ check_allocations(1, 1, "anon_splat_and_anon_keyword_splat(1, **hash1, **empty_hash#{block})")
+ check_allocations(1, 1, "anon_splat_and_anon_keyword_splat(1, **empty_hash, **hash1#{block})")
+
+ check_allocations(1, 0, "anon_splat_and_anon_keyword_splat(1, *empty_array#{block})")
+ check_allocations(1, 0, "anon_splat_and_anon_keyword_splat(1, *empty_array, *empty_array, **empty_hash#{block})")
+
+ check_allocations(0, 0, "anon_splat_and_anon_keyword_splat(*array1, a: 2#{block})")
+
+ check_allocations(0, 0, "anon_splat_and_anon_keyword_splat(*array1, **nill#{block})")
+ check_allocations(0, 0, "anon_splat_and_anon_keyword_splat(*array1, **empty_hash#{block})")
+ check_allocations(0, 0, "anon_splat_and_anon_keyword_splat(*array1, **hash1#{block})")
+ check_allocations(1, 0, "anon_splat_and_anon_keyword_splat(*array1, *empty_array, **hash1#{block})")
+
+ check_allocations(1, 0, "anon_splat_and_anon_keyword_splat(*array1, *empty_array#{block})")
+ check_allocations(1, 0, "anon_splat_and_anon_keyword_splat(*array1, *empty_array, **empty_hash#{block})")
+
+ check_allocations(1, 1, "anon_splat_and_anon_keyword_splat(*array1, *empty_array, a: 2, **empty_hash#{block})")
+ check_allocations(1, 1, "anon_splat_and_anon_keyword_splat(*array1, *empty_array, **hash1, **empty_hash#{block})")
+
+ check_allocations(1, 1, "anon_splat_and_anon_keyword_splat(1, *empty_array, a: 2, **empty_hash#{block})")
+ check_allocations(1, 1, "anon_splat_and_anon_keyword_splat(1, *empty_array, **hash1, **empty_hash#{block})")
+ check_allocations(0, 1, "anon_splat_and_anon_keyword_splat(*array1, **empty_hash, a: 2#{block})")
+ check_allocations(0, 1, "anon_splat_and_anon_keyword_splat(*array1, **hash1, **empty_hash#{block})")
+ check_allocations(0, 0, "anon_splat_and_anon_keyword_splat(*array1, **nil#{block})")
+
+ check_allocations(1, 1, "anon_splat_and_anon_keyword_splat(*r2k_empty_array#{block})")
+ check_allocations(1, 1, "anon_splat_and_anon_keyword_splat(*r2k_array#{block})")
+ check_allocations(1, 1, "anon_splat_and_anon_keyword_splat(*r2k_empty_array1#{block})")
+ check_allocations(1, 1, "anon_splat_and_anon_keyword_splat(*r2k_array1#{block})")
+ RUBY
+ end
+
+ def test_nested_anonymous_splat_and_anonymous_keyword_splat_parameters
+ check_allocations(<<~RUBY)
+ def self.t(*, **#{block}); end
+ def self.anon_splat_and_anon_keyword_splat(*, **#{block}); t(*, **) end
+
+ check_allocations(1, 1, "anon_splat_and_anon_keyword_splat(1, a: 2#{block})")
+ check_allocations(1, 0, "anon_splat_and_anon_keyword_splat(1, *empty_array, a: 2#{block})")
+ check_allocations(1, 1, "anon_splat_and_anon_keyword_splat(1, a:2, **empty_hash#{block})")
+ check_allocations(1, 1, "anon_splat_and_anon_keyword_splat(1, **empty_hash, a: 2#{block})")
+
+ check_allocations(1, 0, "anon_splat_and_anon_keyword_splat(1, **nil#{block})")
+ check_allocations(1, 0, "anon_splat_and_anon_keyword_splat(1, **empty_hash#{block})")
+ check_allocations(1, 0, "anon_splat_and_anon_keyword_splat(1, **hash1#{block})")
+ check_allocations(1, 0, "anon_splat_and_anon_keyword_splat(1, *empty_array, **hash1#{block})")
+ check_allocations(1, 1, "anon_splat_and_anon_keyword_splat(1, **hash1, **empty_hash#{block})")
+ check_allocations(1, 1, "anon_splat_and_anon_keyword_splat(1, **empty_hash, **hash1#{block})")
+
+ check_allocations(1, 0, "anon_splat_and_anon_keyword_splat(1, *empty_array#{block})")
+ check_allocations(1, 0, "anon_splat_and_anon_keyword_splat(1, *empty_array, *empty_array, **empty_hash#{block})")
+
+ check_allocations(0, 0, "anon_splat_and_anon_keyword_splat(*array1, a: 2#{block})")
+
+ check_allocations(0, 0, "anon_splat_and_anon_keyword_splat(*array1, **nill#{block})")
+ check_allocations(0, 0, "anon_splat_and_anon_keyword_splat(*array1, **empty_hash#{block})")
+ check_allocations(0, 0, "anon_splat_and_anon_keyword_splat(*array1, **hash1#{block})")
+ check_allocations(1, 0, "anon_splat_and_anon_keyword_splat(*array1, *empty_array, **hash1#{block})")
+
+ check_allocations(1, 0, "anon_splat_and_anon_keyword_splat(*array1, *empty_array#{block})")
+ check_allocations(1, 0, "anon_splat_and_anon_keyword_splat(*array1, *empty_array, **empty_hash#{block})")
+
+ check_allocations(1, 1, "anon_splat_and_anon_keyword_splat(*array1, *empty_array, a: 2, **empty_hash#{block})")
+ check_allocations(1, 1, "anon_splat_and_anon_keyword_splat(*array1, *empty_array, **hash1, **empty_hash#{block})")
+
+ check_allocations(1, 1, "anon_splat_and_anon_keyword_splat(1, *empty_array, a: 2, **empty_hash#{block})")
+ check_allocations(1, 1, "anon_splat_and_anon_keyword_splat(1, *empty_array, **hash1, **empty_hash#{block})")
+ check_allocations(0, 1, "anon_splat_and_anon_keyword_splat(*array1, **empty_hash, a: 2#{block})")
+ check_allocations(0, 1, "anon_splat_and_anon_keyword_splat(*array1, **hash1, **empty_hash#{block})")
+ check_allocations(0, 0, "anon_splat_and_anon_keyword_splat(*array1, **nil#{block})")
+
+ check_allocations(1, 1, "anon_splat_and_anon_keyword_splat(*r2k_empty_array#{block})")
+ check_allocations(1, 1, "anon_splat_and_anon_keyword_splat(*r2k_array#{block})")
+ check_allocations(1, 1, "anon_splat_and_anon_keyword_splat(*r2k_empty_array1#{block})")
+ check_allocations(1, 1, "anon_splat_and_anon_keyword_splat(*r2k_array1#{block})")
+ RUBY
+ end
+
+ def test_argument_forwarding
+ check_allocations(<<~RUBY)
+ def self.argument_forwarding(...); end
+
+ check_allocations(0, 0, "argument_forwarding(1, a: 2#{block})")
+ check_allocations(0, 0, "argument_forwarding(1, *empty_array, a: 2#{block})")
+ check_allocations(0, 1, "argument_forwarding(1, a:2, **empty_hash#{block})")
+ check_allocations(0, 1, "argument_forwarding(1, **empty_hash, a: 2#{block})")
+
+ check_allocations(0, 0, "argument_forwarding(1, **nil#{block})")
+ check_allocations(0, 0, "argument_forwarding(1, **empty_hash#{block})")
+ check_allocations(0, 0, "argument_forwarding(1, **hash1#{block})")
+ check_allocations(0, 0, "argument_forwarding(1, *empty_array, **hash1#{block})")
+ check_allocations(0, 1, "argument_forwarding(1, **hash1, **empty_hash#{block})")
+ check_allocations(0, 1, "argument_forwarding(1, **empty_hash, **hash1#{block})")
+
+ check_allocations(0, 0, "argument_forwarding(1, *empty_array#{block})")
+ check_allocations(1, 0, "argument_forwarding(1, *empty_array, *empty_array, **empty_hash#{block})")
+
+ check_allocations(0, 0, "argument_forwarding(*array1, a: 2#{block})")
+
+ check_allocations(0, 0, "argument_forwarding(*array1, **nill#{block})")
+ check_allocations(0, 0, "argument_forwarding(*array1, **empty_hash#{block})")
+ check_allocations(0, 0, "argument_forwarding(*array1, **hash1#{block})")
+ check_allocations(1, 0, "argument_forwarding(*array1, *empty_array, **hash1#{block})")
+
+ check_allocations(1, 0, "argument_forwarding(*array1, *empty_array#{block})")
+ check_allocations(1, 0, "argument_forwarding(*array1, *empty_array, **empty_hash#{block})")
+
+ check_allocations(1, 1, "argument_forwarding(*array1, *empty_array, a: 2, **empty_hash#{block})")
+ check_allocations(1, 1, "argument_forwarding(*array1, *empty_array, **hash1, **empty_hash#{block})")
+
+ check_allocations(0, 1, "argument_forwarding(1, *empty_array, a: 2, **empty_hash#{block})")
+ check_allocations(0, 1, "argument_forwarding(1, *empty_array, **hash1, **empty_hash#{block})")
+ check_allocations(0, 1, "argument_forwarding(*array1, **empty_hash, a: 2#{block})")
+ check_allocations(0, 1, "argument_forwarding(*array1, **hash1, **empty_hash#{block})")
+ check_allocations(0, 0, "argument_forwarding(*array1, **nil#{block})")
+
+ check_allocations(0, 0, "argument_forwarding(*r2k_empty_array#{block})")
+ check_allocations(0, 0, "argument_forwarding(*r2k_array#{block})")
+ check_allocations(0, 0, "argument_forwarding(*r2k_empty_array1#{block})")
+ check_allocations(0, 0, "argument_forwarding(*r2k_array1#{block})")
+ RUBY
+ end
+
+ def test_nested_argument_forwarding
+ check_allocations(<<~RUBY)
+ def self.t(...) end
+ def self.argument_forwarding(...); t(...) end
+
+ check_allocations(0, 0, "argument_forwarding(1, a: 2#{block})")
+ check_allocations(0, 0, "argument_forwarding(1, *empty_array, a: 2#{block})")
+ check_allocations(0, 1, "argument_forwarding(1, a:2, **empty_hash#{block})")
+ check_allocations(0, 1, "argument_forwarding(1, **empty_hash, a: 2#{block})")
+
+ check_allocations(0, 0, "argument_forwarding(1, **nil#{block})")
+ check_allocations(0, 0, "argument_forwarding(1, **empty_hash#{block})")
+ check_allocations(0, 0, "argument_forwarding(1, **hash1#{block})")
+ check_allocations(0, 0, "argument_forwarding(1, *empty_array, **hash1#{block})")
+ check_allocations(0, 1, "argument_forwarding(1, **hash1, **empty_hash#{block})")
+ check_allocations(0, 1, "argument_forwarding(1, **empty_hash, **hash1#{block})")
+
+ check_allocations(0, 0, "argument_forwarding(1, *empty_array#{block})")
+ check_allocations(1, 0, "argument_forwarding(1, *empty_array, *empty_array, **empty_hash#{block})")
+
+ check_allocations(0, 0, "argument_forwarding(*array1, a: 2#{block})")
+
+ check_allocations(0, 0, "argument_forwarding(*array1, **nill#{block})")
+ check_allocations(0, 0, "argument_forwarding(*array1, **empty_hash#{block})")
+ check_allocations(0, 0, "argument_forwarding(*array1, **hash1#{block})")
+ check_allocations(1, 0, "argument_forwarding(*array1, *empty_array, **hash1#{block})")
+
+ check_allocations(1, 0, "argument_forwarding(*array1, *empty_array#{block})")
+ check_allocations(1, 0, "argument_forwarding(*array1, *empty_array, **empty_hash#{block})")
+
+ check_allocations(1, 1, "argument_forwarding(*array1, *empty_array, a: 2, **empty_hash#{block})")
+ check_allocations(1, 1, "argument_forwarding(*array1, *empty_array, **hash1, **empty_hash#{block})")
+
+ check_allocations(0, 1, "argument_forwarding(1, *empty_array, a: 2, **empty_hash#{block})")
+ check_allocations(0, 1, "argument_forwarding(1, *empty_array, **hash1, **empty_hash#{block})")
+ check_allocations(0, 1, "argument_forwarding(*array1, **empty_hash, a: 2#{block})")
+ check_allocations(0, 1, "argument_forwarding(*array1, **hash1, **empty_hash#{block})")
+ check_allocations(0, 0, "argument_forwarding(*array1, **nil#{block})")
+
+ check_allocations(0, 0, "argument_forwarding(*r2k_empty_array#{block})")
+ check_allocations(0, 0, "argument_forwarding(*r2k_array#{block})")
+ check_allocations(0, 0, "argument_forwarding(*r2k_empty_array1#{block})")
+ check_allocations(0, 0, "argument_forwarding(*r2k_array1#{block})")
+ RUBY
+ end
+
+ def test_ruby2_keywords
+ check_allocations(<<~RUBY)
+ def self.r2k(*a#{block}); end
+ singleton_class.send(:ruby2_keywords, :r2k)
+
+ check_allocations(1, 1, "r2k(1, a: 2#{block})")
+ check_allocations(1, 1, "r2k(1, *empty_array, a: 2#{block})")
+ check_allocations(1, 1, "r2k(1, a:2, **empty_hash#{block})")
+ check_allocations(1, 1, "r2k(1, **empty_hash, a: 2#{block})")
+
+ check_allocations(1, 0, "r2k(1, **nil#{block})")
+ check_allocations(1, 0, "r2k(1, **empty_hash#{block})")
+ check_allocations(1, 1, "r2k(1, **hash1#{block})")
+ check_allocations(1, 1, "r2k(1, *empty_array, **hash1#{block})")
+ check_allocations(1, 1, "r2k(1, **hash1, **empty_hash#{block})")
+ check_allocations(1, 1, "r2k(1, **empty_hash, **hash1#{block})")
+
+ check_allocations(1, 0, "r2k(1, *empty_array#{block})")
+ check_allocations(1, 0, "r2k(1, *empty_array, *empty_array, **empty_hash#{block})")
+
+ check_allocations(1, 1, "r2k(*array1, a: 2#{block})")
+
+ check_allocations(1, 0, "r2k(*array1, **nill#{block})")
+ check_allocations(1, 0, "r2k(*array1, **empty_hash#{block})")
+ check_allocations(1, 1, "r2k(*array1, **hash1#{block})")
+ check_allocations(1, 1, "r2k(*array1, *empty_array, **hash1#{block})")
+
+ check_allocations(1, 0, "r2k(*array1, *empty_array#{block})")
+ check_allocations(1, 0, "r2k(*array1, *empty_array, **empty_hash#{block})")
+
+ check_allocations(1, 1, "r2k(*array1, *empty_array, a: 2, **empty_hash#{block})")
+ check_allocations(1, 1, "r2k(*array1, *empty_array, **hash1, **empty_hash#{block})")
+
+ check_allocations(1, 1, "r2k(1, *empty_array, a: 2, **empty_hash#{block})")
+ check_allocations(1, 1, "r2k(1, *empty_array, **hash1, **empty_hash#{block})")
+ check_allocations(1, 1, "r2k(*array1, **empty_hash, a: 2#{block})")
+ check_allocations(1, 1, "r2k(*array1, **hash1, **empty_hash#{block})")
+ check_allocations(1, 0, "r2k(*array1, **nil#{block})")
+
+ check_allocations(1, 0, "r2k(*r2k_empty_array#{block})")
+ check_allocations(1, 1, "r2k(*r2k_array#{block})")
+ unless defined?(RubyVM::YJIT.enabled?) && RubyVM::YJIT.enabled?
+ # YJIT may or may not allocate depending on arch?
+ check_allocations(1, 0, "r2k(*r2k_empty_array1#{block})")
+ check_allocations(1, 1, "r2k(*r2k_array1#{block})")
+ end
+ RUBY
+ end
+
+ def test_no_array_allocation_with_splat_and_nonstatic_keywords
+ check_allocations(<<~RUBY)
+ def self.keyword(a: nil, b: nil#{block}); end
+
+ check_allocations(0, 1, "keyword(*empty_array, a: empty_array#{block})") # LVAR
+ check_allocations(0, 1, "->{keyword(*empty_array, a: empty_array#{block})}.call") # DVAR
+ check_allocations(0, 1, "$x = empty_array; keyword(*empty_array, a: $x#{block})") # GVAR
+ check_allocations(0, 1, "@x = empty_array; keyword(*empty_array, a: @x#{block})") # IVAR
+ check_allocations(0, 1, "self.class.const_set(:X, empty_array); keyword(*empty_array, a: X#{block})") # CONST
+ check_allocations(0, 1, "keyword(*empty_array, a: Object::X#{block})") # COLON2
+ check_allocations(0, 1, "keyword(*empty_array, a: ::X#{block})") # COLON3
+ check_allocations(0, 1, "T = self; #{'B = block' unless block.empty?}; class Object; @@x = X; T.keyword(*X, a: @@x#{', &B' unless block.empty?}) end") # CVAR
+ check_allocations(0, 1, "keyword(*empty_array, a: empty_array, b: 1#{block})") # INTEGER
+ check_allocations(0, 1, "keyword(*empty_array, a: empty_array, b: 1.0#{block})") # FLOAT
+ check_allocations(0, 1, "keyword(*empty_array, a: empty_array, b: 1.0r#{block})") # RATIONAL
+ check_allocations(0, 1, "keyword(*empty_array, a: empty_array, b: 1.0i#{block})") # IMAGINARY
+ check_allocations(0, 1, "keyword(*empty_array, a: empty_array, b: 'a'#{block})") # STR
+ check_allocations(0, 1, "keyword(*empty_array, a: empty_array, b: :b#{block})") # SYM
+ check_allocations(0, 1, "keyword(*empty_array, a: empty_array, b: /a/#{block})") # REGX
+ check_allocations(0, 1, "keyword(*empty_array, a: self#{block})") # SELF
+ check_allocations(0, 1, "keyword(*empty_array, a: empty_array, b: nil#{block})") # NIL
+ check_allocations(0, 1, "keyword(*empty_array, a: empty_array, b: true#{block})") # TRUE
+ check_allocations(0, 1, "keyword(*empty_array, a: empty_array, b: false#{block})") # FALSE
+ check_allocations(0, 1, "keyword(*empty_array, a: ->{}#{block})") # LAMBDA
+ check_allocations(0, 1, "keyword(*empty_array, a: $1#{block})") # NTH_REF
+ check_allocations(0, 1, "keyword(*empty_array, a: $`#{block})") # BACK_REF
+ RUBY
+ end
+
+ class WithBlock < self
+ def block
+ ', &block'
+ end
+ end
+ end
+
+ class ProcCall < MethodCall
+ def munge_checks(checks)
+ return checks if @no_munge
+ sub = rep = nil
+ checks.split("\n").map do |line|
+ case line
+ when "singleton_class.send(:ruby2_keywords, :r2k)"
+ "r2k.ruby2_keywords"
+ when /\Adef self.([a-z0-9_]+)\((.*)\);(.*)end\z/
+ sub = $1 + '('
+ rep = $1 + '.('
+ "#{$1} = #{$1} = proc{ |#{$2}| #{$3} }"
+ when /check_allocations/
+ line.gsub(sub, rep)
+ else
+ line
+ end
+ end.join("\n")
+ end
+
+ # Generic argument forwarding not supported in proc definitions
+ undef_method :test_argument_forwarding
+ undef_method :test_nested_argument_forwarding
+
+ # Proc anonymous arguments cannot be used directly
+ undef_method :test_nested_anonymous_splat_and_anonymous_keyword_splat_parameters
+
+ def test_no_array_allocation_with_splat_and_nonstatic_keywords
+ @no_munge = true
+
+ check_allocations(<<~RUBY)
+ keyword = keyword = proc{ |a: nil, b: nil #{block}| }
+
+ check_allocations(0, 1, "keyword.(*empty_array, a: empty_array#{block})") # LVAR
+ check_allocations(0, 1, "->{keyword.(*empty_array, a: empty_array#{block})}.call") # DVAR
+ check_allocations(0, 1, "$x = empty_array; keyword.(*empty_array, a: $x#{block})") # GVAR
+ check_allocations(0, 1, "@x = empty_array; keyword.(*empty_array, a: @x#{block})") # IVAR
+ check_allocations(0, 1, "self.class.const_set(:X, empty_array); keyword.(*empty_array, a: X#{block})") # CONST
+ check_allocations(0, 1, "keyword.(*empty_array, a: Object::X#{block})") # COLON2
+ check_allocations(0, 1, "keyword.(*empty_array, a: ::X#{block})") # COLON3
+ check_allocations(0, 1, "T = keyword; #{'B = block' unless block.empty?}; class Object; @@x = X; T.(*X, a: @@x#{', &B' unless block.empty?}) end") # CVAR
+ check_allocations(0, 1, "keyword.(*empty_array, a: empty_array, b: 1#{block})") # INTEGER
+ check_allocations(0, 1, "keyword.(*empty_array, a: empty_array, b: 1.0#{block})") # FLOAT
+ check_allocations(0, 1, "keyword.(*empty_array, a: empty_array, b: 1.0r#{block})") # RATIONAL
+ check_allocations(0, 1, "keyword.(*empty_array, a: empty_array, b: 1.0i#{block})") # IMAGINARY
+ check_allocations(0, 1, "keyword.(*empty_array, a: empty_array, b: 'a'#{block})") # STR
+ check_allocations(0, 1, "keyword.(*empty_array, a: empty_array, b: :b#{block})") # SYM
+ check_allocations(0, 1, "keyword.(*empty_array, a: empty_array, b: /a/#{block})") # REGX
+ check_allocations(0, 1, "keyword.(*empty_array, a: self#{block})") # SELF
+ check_allocations(0, 1, "keyword.(*empty_array, a: empty_array, b: nil#{block})") # NIL
+ check_allocations(0, 1, "keyword.(*empty_array, a: empty_array, b: true#{block})") # TRUE
+ check_allocations(0, 1, "keyword.(*empty_array, a: empty_array, b: false#{block})") # FALSE
+ check_allocations(0, 1, "keyword.(*empty_array, a: ->{}#{block})") # LAMBDA
+ check_allocations(0, 1, "keyword.(*empty_array, a: $1#{block})") # NTH_REF
+ check_allocations(0, 1, "keyword.(*empty_array, a: $`#{block})") # BACK_REF
+ RUBY
+ end
+
+ class WithBlock < self
+ def block
+ ', &block'
+ end
+ end
+ end
+end
diff --git a/test/ruby/test_argf.rb b/test/ruby/test_argf.rb
index e3bd1cd075..55a06296aa 100644
--- a/test/ruby/test_argf.rb
+++ b/test/ruby/test_argf.rb
@@ -9,39 +9,23 @@ class TestArgf < Test::Unit::TestCase
def setup
@tmpdir = Dir.mktmpdir
@tmp_count = 0
- @t1 = make_tempfile0("argf-foo")
- @t1.binmode
- @t1.puts "1"
- @t1.puts "2"
- @t1.close
- @t2 = make_tempfile0("argf-bar")
- @t2.binmode
- @t2.puts "3"
- @t2.puts "4"
- @t2.close
- @t3 = make_tempfile0("argf-baz")
- @t3.binmode
- @t3.puts "5"
- @t3.puts "6"
- @t3.close
+ @t1 = make_tempfile("argf-foo", %w"1 2", binmode: true)
+ @t2 = make_tempfile("argf-bar", %w"3 4", binmode: true)
+ @t3 = make_tempfile("argf-baz", %w"5 6", binmode: true)
end
def teardown
FileUtils.rmtree(@tmpdir)
end
- def make_tempfile0(basename)
+ def make_tempfile(basename = "argf-qux", data = %w[foo bar baz], binmode: false)
@tmp_count += 1
- open("#{@tmpdir}/#{basename}-#{@tmp_count}", "w")
- end
-
- def make_tempfile(basename = "argf-qux")
- t = make_tempfile0(basename)
- t.puts "foo"
- t.puts "bar"
- t.puts "baz"
- t.close
- t
+ path = "#{@tmpdir}/#{basename}-#{@tmp_count}"
+ File.open(path, "w") do |f|
+ f.binmode if binmode
+ f.puts(*data)
+ f
+ end
end
def ruby(*args, external_encoding: Encoding::UTF_8)
@@ -143,6 +127,17 @@ class TestArgf < Test::Unit::TestCase
};
end
+ def test_lineno_after_shebang
+ expected = %w"1 1 1 2 2 2 3 3 1 4 4 2"
+ assert_in_out_err(["--enable=gems", "-", @t1.path, @t2.path], "#{<<~"{#"}\n#{<<~'};'}", expected)
+ #!/usr/bin/env ruby
+ {#
+ ARGF.each do |line|
+ puts [$., ARGF.lineno, ARGF.file.lineno]
+ end
+ };
+ end
+
def test_new_lineno_each
f = ARGF.class.new(@t1.path, @t2.path, @t3.path)
result = []
@@ -257,13 +252,13 @@ class TestArgf < Test::Unit::TestCase
def test_inplace_nonascii
ext = Encoding.default_external or
- skip "no default external encoding"
+ omit "no default external encoding"
t = nil
["\u{3042}", "\u{e9}"].any? do |n|
t = make_tempfile(n.encode(ext))
rescue Encoding::UndefinedConversionError
end
- t or skip "no name to test"
+ t or omit "no name to test"
assert_in_out_err(["-i.bak", "-", t.path],
"#{<<~"{#"}\n#{<<~'};'}")
{#
@@ -560,15 +555,11 @@ class TestArgf < Test::Unit::TestCase
end
end
- t1 = open("#{@tmpdir}/argf-hoge", "w")
- t1.binmode
- t1.puts "foo"
- t1.close
- t2 = open("#{@tmpdir}/argf-moge", "w")
- t2.binmode
- t2.puts "bar"
- t2.close
- ruby('-e', 'STDERR.reopen(STDOUT); ARGF.gets; ARGF.skip; p ARGF.eof?', t1.path, t2.path) do |f|
+ t1 = "#{@tmpdir}/argf-hoge"
+ t2 = "#{@tmpdir}/argf-moge"
+ File.binwrite(t1, "foo\n")
+ File.binwrite(t2, "bar\n")
+ ruby('-e', 'STDERR.reopen(STDOUT); ARGF.gets; ARGF.skip; p ARGF.eof?', t1, t2) do |f|
assert_equal(%w(false), f.read.split(/\n/))
end
end
@@ -582,7 +573,7 @@ class TestArgf < Test::Unit::TestCase
def test_read2
ruby('-e', "#{<<~"{#"}\n#{<<~'};'}", @t1.path, @t2.path, @t3.path) do |f|
{#
- s = ""
+ s = +""
ARGF.read(8, s)
p s
};
@@ -593,7 +584,7 @@ class TestArgf < Test::Unit::TestCase
def test_read2_with_not_empty_buffer
ruby('-e', "#{<<~"{#"}\n#{<<~'};'}", @t1.path, @t2.path, @t3.path) do |f|
{#
- s = "0123456789"
+ s = +"0123456789"
ARGF.read(8, s)
p s
};
@@ -606,7 +597,7 @@ class TestArgf < Test::Unit::TestCase
{#
nil while ARGF.gets
p ARGF.read
- p ARGF.read(0, "")
+ p ARGF.read(0, +"")
};
assert_equal("nil\n\"\"\n", f.read)
end
@@ -615,13 +606,13 @@ class TestArgf < Test::Unit::TestCase
def test_readpartial
ruby('-e', "#{<<~"{#"}\n#{<<~'};'}", @t1.path, @t2.path, @t3.path) do |f|
{#
- s = ""
+ s = +""
begin
loop do
s << ARGF.readpartial(1)
- t = ""; ARGF.readpartial(1, t); s << t
+ t = +""; ARGF.readpartial(1, t); s << t
# not empty buffer
- u = "abcdef"; ARGF.readpartial(1, u); s << u
+ u = +"abcdef"; ARGF.readpartial(1, u); s << u
end
rescue EOFError
puts s
@@ -634,11 +625,11 @@ class TestArgf < Test::Unit::TestCase
def test_readpartial2
ruby('-e', "#{<<~"{#"}\n#{<<~'};'}") do |f|
{#
- s = ""
+ s = +""
begin
loop do
s << ARGF.readpartial(1)
- t = ""; ARGF.readpartial(1, t); s << t
+ t = +""; ARGF.readpartial(1, t); s << t
end
rescue EOFError
$stdout.binmode
@@ -669,7 +660,7 @@ class TestArgf < Test::Unit::TestCase
def test_getc
ruby('-e', "#{<<~"{#"}\n#{<<~'};'}", @t1.path, @t2.path, @t3.path) do |f|
{#
- s = ""
+ s = +""
while c = ARGF.getc
s << c
end
@@ -695,7 +686,7 @@ class TestArgf < Test::Unit::TestCase
def test_readchar
ruby('-e', "#{<<~"{#"}\n#{<<~'};'}", @t1.path, @t2.path, @t3.path) do |f|
{#
- s = ""
+ s = +""
begin
while c = ARGF.readchar
s << c
@@ -773,7 +764,7 @@ class TestArgf < Test::Unit::TestCase
def test_each_char
ruby('-e', "#{<<~"{#"}\n#{<<~'};'}", @t1.path, @t2.path, @t3.path) do |f|
{#
- s = ""
+ s = +""
ARGF.each_char {|c| s << c }
puts s
};
@@ -843,7 +834,7 @@ class TestArgf < Test::Unit::TestCase
def test_binmode
bug5268 = '[ruby-core:39234]'
- open(@t3.path, "wb") {|f| f.write "5\r\n6\r\n"}
+ File.binwrite(@t3.path, "5\r\n6\r\n")
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\r\n6\r\n", f.read, bug5268)
@@ -852,7 +843,7 @@ class TestArgf < Test::Unit::TestCase
def test_textmode
bug5268 = '[ruby-core:39234]'
- open(@t3.path, "wb") {|f| f.write "5\r\n6\r\n"}
+ File.binwrite(@t3.path, "5\r\n6\r\n")
ruby('-e', "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, bug5268)
@@ -1062,7 +1053,7 @@ class TestArgf < Test::Unit::TestCase
ruby('-e', "#{<<~"{#"}\n#{<<~'};'}") do |f|
{#
$stdout.sync = true
- :wait_readable == ARGF.read_nonblock(1, "", exception: false) or
+ :wait_readable == ARGF.read_nonblock(1, +"", exception: false) or
abort "did not return :wait_readable"
begin
@@ -1075,7 +1066,7 @@ class TestArgf < Test::Unit::TestCase
IO.select([ARGF]) == [[ARGF], [], []] or
abort 'did not awaken for readability (before byte)'
- buf = ''
+ buf = +''
buf.object_id == ARGF.read_nonblock(1, buf).object_id or
abort "read destination buffer failed"
print buf
@@ -1129,4 +1120,34 @@ class TestArgf < Test::Unit::TestCase
argf.close
end
end
+
+ def test_putc
+ t = make_tempfile("argf-#{__method__}", 'bar')
+ ruby('-pi-', '-e', "print ARGF.putc('x')", t.path) do |f|
+ end
+ assert_equal("xxbar\n", File.read(t.path))
+ end
+
+ def test_puts
+ t = make_tempfile("argf-#{__method__}", 'bar')
+ err = "#{@tmpdir}/errout"
+ ruby('-pi-', '-W2', '-e', "print ARGF.puts('foo')", t.path, {err: err}) do |f|
+ end
+ assert_equal("foo\nbar\n", File.read(t.path))
+ assert_empty File.read(err)
+ end
+
+ def test_print
+ t = make_tempfile("argf-#{__method__}", 'bar')
+ ruby('-pi-', '-e', "print ARGF.print('foo')", t.path) do |f|
+ end
+ assert_equal("foobar\n", File.read(t.path))
+ end
+
+ def test_printf
+ t = make_tempfile("argf-#{__method__}", 'bar')
+ ruby('-pi-', '-e', "print ARGF.printf('%s', 'foo')", t.path) do |f|
+ end
+ assert_equal("foobar\n", File.read(t.path))
+ end
end
diff --git a/test/ruby/test_arity.rb b/test/ruby/test_arity.rb
index b98248f603..bd26d5f0f5 100644
--- a/test/ruby/test_arity.rb
+++ b/test/ruby/test_arity.rb
@@ -2,7 +2,7 @@
require 'test/unit'
class TestArity < Test::Unit::TestCase
- def err_mess(method_proc = nil, argc = 0)
+ def assert_arity(expected, method_proc = nil, argc = 0)
args = (1..argc).to_a
assert_raise_with_message(ArgumentError, /wrong number of arguments \(.*\b(\d+)\b.* (\d\S*?)\)/) do
case method_proc
@@ -14,7 +14,7 @@ class TestArity < Test::Unit::TestCase
method_proc.call(*args)
end
end
- [$1, $2]
+ assert_equal expected, [$1, $2]
end
def a
@@ -36,22 +36,22 @@ class TestArity < Test::Unit::TestCase
end
def test_method_err_mess
- assert_equal %w[1 0], err_mess(:a, 1)
- assert_equal %w[10 7..9], err_mess(:b, 10)
- assert_equal %w[2 3+], err_mess(:c, 2)
- assert_equal %w[2 1], err_mess(:d, 2)
- assert_equal %w[0 1], err_mess(:d, 0)
- assert_equal %w[2 1], err_mess(:e, 2)
- assert_equal %w[0 1], err_mess(:e, 0)
- assert_equal %w[1 2+], err_mess(:f, 1)
+ assert_arity(%w[1 0], :a, 1)
+ assert_arity(%w[10 7..9], :b, 10)
+ assert_arity(%w[2 3+], :c, 2)
+ assert_arity(%w[2 1], :d, 2)
+ assert_arity(%w[0 1], :d, 0)
+ assert_arity(%w[2 1], :e, 2)
+ assert_arity(%w[0 1], :e, 0)
+ assert_arity(%w[1 2+], :f, 1)
end
def test_proc_err_mess
- assert_equal %w[0 1..2], err_mess(->(b, c=42){}, 0)
- assert_equal %w[1 2+], err_mess(->(a, b, c=42, *d){}, 1)
- assert_equal %w[3 4+], err_mess(->(a, b, *c, d, e){}, 3)
- assert_equal %w[3 1..2], err_mess(->(b, c=42){}, 3)
- assert_equal %w[1 0], err_mess(->(&block){}, 1)
+ assert_arity(%w[0 1..2], ->(b, c=42){}, 0)
+ assert_arity(%w[1 2+], ->(a, b, c=42, *d){}, 1)
+ assert_arity(%w[3 4+], ->(a, b, *c, d, e){}, 3)
+ assert_arity(%w[3 1..2], ->(b, c=42){}, 3)
+ assert_arity(%w[1 0], ->(&block){}, 1)
# Double checking:
p = Proc.new{|b, c=42| :ok}
assert_equal :ok, p.call(1, 2, 3)
@@ -59,12 +59,11 @@ class TestArity < Test::Unit::TestCase
end
def test_message_change_issue_6085
- assert_equal %w[3 1..2], err_mess{ SignalException.new(1, "", nil) }
- assert_equal %w[1 0], err_mess{ Hash.new(1){} }
- assert_equal %w[3 1..2], err_mess{ Module.send :define_method, 1, 2, 3 }
- assert_equal %w[1 2], err_mess{ "".sub!(//) }
- assert_equal %w[0 1..2], err_mess{ "".sub!{} }
- assert_equal %w[0 1+], err_mess{ exec }
- assert_equal %w[0 1+], err_mess{ Struct.new }
+ assert_arity(%w[3 1..2]) { SignalException.new(1, "", nil) }
+ assert_arity(%w[1 0]) { Hash.new(1){} }
+ assert_arity(%w[3 1..2]) { Module.send :define_method, 1, 2, 3 }
+ assert_arity(%w[1 2]) { "".sub!(//) }
+ assert_arity(%w[0 1..2]) { "".sub!{} }
+ assert_arity(%w[0 1+]) { exec }
end
end
diff --git a/test/ruby/test_array.rb b/test/ruby/test_array.rb
index a97a9c2558..66251b9fb0 100644
--- a/test/ruby/test_array.rb
+++ b/test/ruby/test_array.rb
@@ -529,14 +529,19 @@ class TestArray < Test::Unit::TestCase
end
def test_assoc
+ def (a4 = Object.new).to_ary
+ %w( pork porcine )
+ end
+
a1 = @cls[*%w( cat feline )]
a2 = @cls[*%w( dog canine )]
a3 = @cls[*%w( mule asinine )]
- a = @cls[ a1, a2, a3 ]
+ a = @cls[ a1, a2, a3, a4 ]
assert_equal(a1, a.assoc('cat'))
assert_equal(a3, a.assoc('mule'))
+ assert_equal(%w( pork porcine ), a.assoc("pork"))
assert_equal(nil, a.assoc('asinine'))
assert_equal(nil, a.assoc('wombat'))
assert_equal(nil, a.assoc(1..2))
@@ -1210,6 +1215,17 @@ class TestArray < Test::Unit::TestCase
assert_equal(@cls[], a)
end
+ def test_pack_format_mutation
+ ary = [Object.new]
+ fmt = "c" * 0x20000
+ class << ary[0]; self end.send(:define_method, :to_int) {
+ fmt.replace ""
+ 1
+ }
+ e = assert_raise(RuntimeError) { ary.pack(fmt) }
+ assert_equal "format string modified", e.message
+ end
+
def test_pack
a = @cls[*%w( cat wombat x yy)]
assert_equal("catwomx yy ", a.pack("A3A3A3A3"))
@@ -1294,6 +1310,12 @@ class TestArray < Test::Unit::TestCase
=end
end
+ def test_pack_with_buffer
+ n = [ 65, 66, 67 ]
+ str = "a" * 100
+ assert_equal("aaaABC", n.pack("@3ccc", buffer: str.dup), "[Bug #19116]")
+ end
+
def test_pop
a = @cls[ 'cat', 'dog' ]
assert_equal('dog', a.pop)
@@ -1323,13 +1345,17 @@ class TestArray < Test::Unit::TestCase
end
def test_rassoc
+ def (a4 = Object.new).to_ary
+ %w( pork porcine )
+ end
a1 = @cls[*%w( cat feline )]
a2 = @cls[*%w( dog canine )]
a3 = @cls[*%w( mule asinine )]
- a = @cls[ a1, a2, a3 ]
+ a = @cls[ a1, a2, a3, a4 ]
assert_equal(a1, a.rassoc('feline'))
assert_equal(a3, a.rassoc('asinine'))
+ assert_equal(%w( pork porcine ), a.rassoc("porcine"))
assert_equal(nil, a.rassoc('dog'))
assert_equal(nil, a.rassoc('mule'))
assert_equal(nil, a.rassoc(1..2))
@@ -1439,6 +1465,14 @@ class TestArray < Test::Unit::TestCase
assert_raise(FrozenError) { fa.replace(42) }
end
+ def test_replace_wb_variable_width_alloc
+ small_embed = []
+ 4.times { GC.start } # age small_embed
+ large_embed = [1, 2, 3, 4, 5, Array.new] # new young object
+ small_embed.replace(large_embed) # adds old to young reference
+ GC.verify_internal_consistency
+ end
+
def test_reverse
a = @cls[*%w( dog cat bee ant )]
assert_equal(@cls[*%w(ant bee cat dog)], a.reverse)
@@ -1572,6 +1606,96 @@ class TestArray < Test::Unit::TestCase
assert_equal_instance(a.values_at(*idx), a.slice((3..90)%2))
idx = 90.step(3, -2).to_a
assert_equal_instance(a.values_at(*idx), a.slice((90 .. 3)% -2))
+
+ a = [0, 1, 2, 3, 4, 5]
+ assert_equal([2, 1, 0], a.slice((2..).step(-1)))
+ assert_equal([2, 0], a.slice((2..).step(-2)))
+ assert_equal([2], a.slice((2..).step(-3)))
+ assert_equal([2], a.slice((2..).step(-4)))
+
+ assert_equal([3, 2, 1, 0], a.slice((-3..).step(-1)))
+ assert_equal([3, 1], a.slice((-3..).step(-2)))
+ assert_equal([3, 0], a.slice((-3..).step(-3)))
+ assert_equal([3], a.slice((-3..).step(-4)))
+ assert_equal([3], a.slice((-3..).step(-5)))
+
+ assert_equal([5, 4, 3, 2, 1, 0], a.slice((..0).step(-1)))
+ assert_equal([5, 3, 1], a.slice((..0).step(-2)))
+ assert_equal([5, 2], a.slice((..0).step(-3)))
+ assert_equal([5, 1], a.slice((..0).step(-4)))
+ assert_equal([5, 0], a.slice((..0).step(-5)))
+ assert_equal([5], a.slice((..0).step(-6)))
+ assert_equal([5], a.slice((..0).step(-7)))
+
+ assert_equal([5, 4, 3, 2, 1], a.slice((...0).step(-1)))
+ assert_equal([5, 3, 1], a.slice((...0).step(-2)))
+ assert_equal([5, 2], a.slice((...0).step(-3)))
+ assert_equal([5, 1], a.slice((...0).step(-4)))
+ assert_equal([5], a.slice((...0).step(-5)))
+ assert_equal([5], a.slice((...0).step(-6)))
+
+ assert_equal([5, 4, 3, 2], a.slice((...1).step(-1)))
+ assert_equal([5, 3], a.slice((...1).step(-2)))
+ assert_equal([5, 2], a.slice((...1).step(-3)))
+ assert_equal([5], a.slice((...1).step(-4)))
+ assert_equal([5], a.slice((...1).step(-5)))
+
+ assert_equal([5, 4, 3, 2, 1], a.slice((..-5).step(-1)))
+ assert_equal([5, 3, 1], a.slice((..-5).step(-2)))
+ assert_equal([5, 2], a.slice((..-5).step(-3)))
+ assert_equal([5, 1], a.slice((..-5).step(-4)))
+ assert_equal([5], a.slice((..-5).step(-5)))
+ assert_equal([5], a.slice((..-5).step(-6)))
+
+ assert_equal([5, 4, 3, 2], a.slice((...-5).step(-1)))
+ assert_equal([5, 3], a.slice((...-5).step(-2)))
+ assert_equal([5, 2], a.slice((...-5).step(-3)))
+ assert_equal([5], a.slice((...-5).step(-4)))
+ assert_equal([5], a.slice((...-5).step(-5)))
+
+ assert_equal([4, 3, 2, 1], a.slice((4..1).step(-1)))
+ assert_equal([4, 2], a.slice((4..1).step(-2)))
+ assert_equal([4, 1], a.slice((4..1).step(-3)))
+ assert_equal([4], a.slice((4..1).step(-4)))
+ assert_equal([4], a.slice((4..1).step(-5)))
+
+ assert_equal([4, 3, 2], a.slice((4...1).step(-1)))
+ assert_equal([4, 2], a.slice((4...1).step(-2)))
+ assert_equal([4], a.slice((4...1).step(-3)))
+ assert_equal([4], a.slice((4...1).step(-4)))
+
+ assert_equal([4, 3, 2, 1], a.slice((-2..1).step(-1)))
+ assert_equal([4, 2], a.slice((-2..1).step(-2)))
+ assert_equal([4, 1], a.slice((-2..1).step(-3)))
+ assert_equal([4], a.slice((-2..1).step(-4)))
+ assert_equal([4], a.slice((-2..1).step(-5)))
+
+ assert_equal([4, 3, 2], a.slice((-2...1).step(-1)))
+ assert_equal([4, 2], a.slice((-2...1).step(-2)))
+ assert_equal([4], a.slice((-2...1).step(-3)))
+ assert_equal([4], a.slice((-2...1).step(-4)))
+
+ assert_equal([4, 3, 2, 1], a.slice((4..-5).step(-1)))
+ assert_equal([4, 2], a.slice((4..-5).step(-2)))
+ assert_equal([4, 1], a.slice((4..-5).step(-3)))
+ assert_equal([4], a.slice((4..-5).step(-4)))
+ assert_equal([4], a.slice((4..-5).step(-5)))
+
+ assert_equal([4, 3, 2], a.slice((4...-5).step(-1)))
+ assert_equal([4, 2], a.slice((4...-5).step(-2)))
+ assert_equal([4], a.slice((4...-5).step(-3)))
+ assert_equal([4], a.slice((4...-5).step(-4)))
+
+ assert_equal([4, 3, 2, 1], a.slice((-2..-5).step(-1)))
+ assert_equal([4, 2], a.slice((-2..-5).step(-2)))
+ assert_equal([4, 1], a.slice((-2..-5).step(-3)))
+ assert_equal([4], a.slice((-2..-5).step(-4)))
+ assert_equal([4], a.slice((-2..-5).step(-5)))
+
+ assert_equal([4, 3, 2], a.slice((-2...-5).step(-1)))
+ assert_equal([4, 2], a.slice((-2...-5).step(-2)))
+ assert_equal([4], a.slice((-2...-5).step(-3)))
+ assert_equal([4], a.slice((-2...-5).step(-4)))
end
def test_slice_out_of_range
@@ -1589,6 +1713,15 @@ class TestArray < Test::Unit::TestCase
assert_equal([100], a.slice(-1, 1_000_000_000))
end
+ def test_slice_gc_compact_stress
+ omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077
+ EnvUtil.under_gc_compact_stress { assert_equal([1, 2, 3, 4, 5], (0..10).to_a[1, 5]) }
+ EnvUtil.under_gc_compact_stress do
+ a = [0, 1, 2, 3, 4, 5]
+ assert_equal([2, 1, 0], a.slice((2..).step(-1)))
+ end
+ end
+
def test_slice!
a = @cls[1, 2, 3, 4, 5]
assert_equal(3, a.slice!(2))
@@ -2882,7 +3015,9 @@ class TestArray < Test::Unit::TestCase
assert_raise(RangeError) {
[*0..2].shuffle(random: gen)
}
+ end
+ def test_shuffle_random_clobbering
ary = (0...10000).to_a
gen = proc do
ary.replace([])
@@ -2892,7 +3027,9 @@ class TestArray < Test::Unit::TestCase
alias rand call
end
assert_raise(RuntimeError) {ary.shuffle!(random: gen)}
+ end
+ def test_shuffle_random_zero
zero = Object.new
def zero.to_int
0
@@ -2905,7 +3042,10 @@ class TestArray < Test::Unit::TestCase
end
ary = (0...10000).to_a
assert_equal(ary.rotate, ary.shuffle(random: gen_to_int))
+ end
+ def test_shuffle_random_invalid_generator
+ ary = (0...10).to_a
assert_raise(NoMethodError) {
ary.shuffle(random: Object.new)
}
@@ -2922,7 +3062,9 @@ class TestArray < Test::Unit::TestCase
assert_include([0, 1, 2], sample)
}
end
+ end
+ def test_sample_statistics
srand(0)
a = (1..18).to_a
(0..20).each do |n|
@@ -2939,9 +3081,13 @@ class TestArray < Test::Unit::TestCase
end
assert_operator(h.values.min * 2, :>=, h.values.max) if n != 0
end
+ end
+ def test_sample_invalid_argument
assert_raise(ArgumentError, '[ruby-core:23374]') {[1, 2].sample(-1)}
+ end
+ def test_sample_random_srand0
gen = Random.new(0)
srand(0)
a = (1..18).to_a
@@ -2950,13 +3096,15 @@ class TestArray < Test::Unit::TestCase
assert_equal(a.sample(n), a.sample(n, random: gen), "#{i}/#{n}")
end
end
+ end
+ def test_sample_unknown_keyword
assert_raise_with_message(ArgumentError, /unknown keyword/) do
[0, 1, 2].sample(xawqij: "a")
end
end
- def test_sample_random
+ def test_sample_random_generator
ary = (0...10000).to_a
assert_raise(ArgumentError) {ary.sample(1, 2, random: nil)}
gen0 = proc do |max|
@@ -2999,7 +3147,9 @@ class TestArray < Test::Unit::TestCase
assert_equal([5000, 0, 5001, 2, 5002, 4, 5003, 6, 5004, 8, 5005], ary.sample(11, random: gen0))
ary.sample(11, random: gen1) # implementation detail, may change in the future
assert_equal([], ary)
+ end
+ def test_sample_random_generator_half
half = Object.new
def half.to_int
5000
@@ -3012,7 +3162,10 @@ class TestArray < Test::Unit::TestCase
end
ary = (0...10000).to_a
assert_equal(5000, ary.sample(random: gen_to_int))
+ end
+ def test_sample_random_invalid_generator
+ ary = (0..10).to_a
assert_raise(NoMethodError) {
ary.sample(random: Object.new)
}
@@ -3212,6 +3365,8 @@ class TestArray < Test::Unit::TestCase
assert_equal(nil, a.bsearch {|x| 1 * (2**100) })
assert_equal(nil, a.bsearch {|x| (-1) * (2**100) })
+ assert_equal(4, a.bsearch {|x| (4 - x).to_r })
+
assert_include([4, 7], a.bsearch {|x| (2**100).coerce((1 - x / 4) * (2**100)).first })
end
@@ -3247,6 +3402,8 @@ class TestArray < Test::Unit::TestCase
assert_equal(nil, a.bsearch_index {|x| 1 * (2**100) })
assert_equal(nil, a.bsearch_index {|x| (-1) * (2**100) })
+ assert_equal(1, a.bsearch_index {|x| (4 - x).to_r })
+
assert_include([1, 2], a.bsearch_index {|x| (2**100).coerce((1 - x / 4) * (2**100)).first })
end
@@ -3270,7 +3427,7 @@ class TestArray < Test::Unit::TestCase
end
EOS
rescue Timeout::Error => e
- skip e.message
+ omit e.message
end
end
@@ -3336,6 +3493,17 @@ class TestArray < Test::Unit::TestCase
assert_typed_equal(e, v, Complex, msg)
end
+ def test_shrink_shared_array
+ assert_normal_exit(<<~'RUBY', '[Feature #20589]')
+ array = []
+ # Make sure the array is allocated
+ 10.times { |i| array << i }
+ # Simulate a C extension using OBJ_FREEZE
+ Object.instance_method(:freeze).bind_call(array)
+ array.dup
+ RUBY
+ end
+
def test_sum
assert_int_equal(0, [].sum)
assert_int_equal(3, [3].sum)
@@ -3410,11 +3578,21 @@ class TestArray < Test::Unit::TestCase
assert_equal(10000, eval(lit).size)
end
+ def test_array_safely_modified_by_sort_block
+ var_0 = (1..70).to_a
+ var_0.sort! do |var_0_block_129, var_1_block_129|
+ var_0.pop
+ var_1_block_129 <=> var_0_block_129
+ end.shift(3)
+ assert_equal((1..67).to_a.reverse, var_0)
+ end
+
private
def need_continuation
unless respond_to?(:callcc, true)
EnvUtil.suppress_warning {require 'continuation'}
end
+ omit 'requires callcc support' unless respond_to?(:callcc, true)
end
end
diff --git a/test/ruby/test_assignment.rb b/test/ruby/test_assignment.rb
index 41e8bffe82..3a8dafb7f0 100644
--- a/test/ruby/test_assignment.rb
+++ b/test/ruby/test_assignment.rb
@@ -139,6 +139,104 @@ class TestAssignment < Test::Unit::TestCase
order.clear
end
+ def test_massign_const_order
+ order = []
+
+ test_mod_class = Class.new(Module) do
+ define_method(:x1){order << :x1; self}
+ define_method(:y1){order << :y1; self}
+ define_method(:x2){order << :x2; self}
+ define_method(:x3){order << :x3; self}
+ define_method(:x4){order << :x4; self}
+ define_method(:[]){|*args| order << [:[], *args]; self}
+ define_method(:r1){order << :r1; :r1}
+ define_method(:r2){order << :r2; :r2}
+
+ define_method(:constant_values) do
+ h = {}
+ constants.each do |sym|
+ h[sym] = const_get(sym)
+ end
+ h
+ end
+
+ define_singleton_method(:run) do |code|
+ m = new
+ m.instance_eval(code)
+ ret = [order.dup, m.constant_values]
+ order.clear
+ ret
+ end
+ end
+
+ ord, constants = test_mod_class.run(
+ "x1.y1::A, x2[1, 2, 3]::B, self[4]::C = r1, 6, r2"
+ )
+ assert_equal([:x1, :y1, :x2, [:[], 1, 2, 3], [:[], 4], :r1, :r2], ord)
+ assert_equal({:A=>:r1, :B=>6, :C=>:r2}, constants)
+
+ ord, constants = test_mod_class.run(
+ "x1.y1::A, *x2[1, 2, 3]::B, self[4]::C = r1, 6, 7, r2"
+ )
+ assert_equal([:x1, :y1, :x2, [:[], 1, 2, 3], [:[], 4], :r1, :r2], ord)
+ assert_equal({:A=>:r1, :B=>[6, 7], :C=>:r2}, constants)
+
+ ord, constants = test_mod_class.run(
+ "x1.y1::A, *x2[1, 2, 3]::B, x3[4]::C = r1, 6, 7, r2"
+ )
+ assert_equal([:x1, :y1, :x2, [:[], 1, 2, 3], :x3, [:[], 4], :r1, :r2], ord)
+ assert_equal({:A=>:r1, :B=>[6, 7], :C=>:r2}, constants)
+
+
+ ord, constants = test_mod_class.run(
+ "x1.y1::A, *x2[1, 2, 3]::B, x3[4]::C, x4::D = r1, 6, 7, r2, 8"
+ )
+ assert_equal([:x1, :y1, :x2, [:[], 1, 2, 3], :x3, [:[], 4], :x4, :r1, :r2], ord)
+ assert_equal({:A=>:r1, :B=>[6, 7], :C=>:r2, :D=>8}, constants)
+
+ ord, constants = test_mod_class.run(
+ "(x1.y1::A, x2::B), _a = [r1, r2], 7"
+ )
+ assert_equal([:x1, :y1, :x2, :r1, :r2], ord)
+ assert_equal({:A=>:r1, :B=>:r2}, constants)
+
+ ord, constants = test_mod_class.run(
+ "(x1.y1::A, x1::B), *x2[1, 2, 3]::C = [r1, 5], 6, 7, r2, 8"
+ )
+ assert_equal([:x1, :y1, :x1, :x2, [:[], 1, 2, 3], :r1, :r2], ord)
+ assert_equal({:A=>:r1, :B=>5, :C=>[6, 7, :r2, 8]}, constants)
+
+ ord, constants = test_mod_class.run(
+ "*x2[1, 2, 3]::A, (x3[4]::B, x4::C) = 6, 7, [r2, 8]"
+ )
+ assert_equal([:x2, [:[], 1, 2, 3], :x3, [:[], 4], :x4, :r2], ord)
+ assert_equal({:A=>[6, 7], :B=>:r2, :C=>8}, constants)
+
+ ord, constants = test_mod_class.run(
+ "(x1.y1::A, x1::B), *x2[1, 2, 3]::C, x3[4]::D, x4::E = [r1, 5], 6, 7, r2, 8"
+ )
+ assert_equal([:x1, :y1, :x1, :x2, [:[], 1, 2, 3], :x3, [:[], 4], :x4, :r1, :r2], ord)
+ assert_equal({:A=>:r1, :B=>5, :C=>[6, 7], :D=>:r2, :E=>8}, constants)
+
+ ord, constants = test_mod_class.run(
+ "(x1.y1::A, x1::B), *x2[1, 2, 3]::C, (x3[4]::D, x4::E) = [r1, 5], 6, 7, [r2, 8]"
+ )
+ assert_equal([:x1, :y1, :x1, :x2, [:[], 1, 2, 3], :x3, [:[], 4], :x4, :r1, :r2], ord)
+ assert_equal({:A=>:r1, :B=>5, :C=>[6, 7], :D=>:r2, :E=>8}, constants)
+
+ ord, constants = test_mod_class.run(
+ "((x1.y1::A, x1::B), _a), *x2[1, 2, 3]::C, ((x3[4]::D, x4::E), _b) = [[r1, 5], 10], 6, 7, [[r2, 8], 11]"
+ )
+ assert_equal([:x1, :y1, :x1, :x2, [:[], 1, 2, 3], :x3, [:[], 4], :x4, :r1, :r2], ord)
+ assert_equal({:A=>:r1, :B=>5, :C=>[6, 7], :D=>:r2, :E=>8}, constants)
+
+ ord, constants = test_mod_class.run(
+ "((x1.y1::A, x1::B), _a), *x2[1, 2, 3]::C, ((*x3[4]::D, x4::E), _b) = [[r1, 5], 10], 6, 7, [[r2, 8], 11]"
+ )
+ assert_equal([:x1, :y1, :x1, :x2, [:[], 1, 2, 3], :x3, [:[], 4], :x4, :r1, :r2], ord)
+ assert_equal({:A=>:r1, :B=>5, :C=>[6, 7], :D=>[:r2], :E=>8}, constants)
+ end
+
def test_massign_splat
a,b,*c = *[]; assert_equal([nil,nil,[]], [a,b,c])
a,b,*c = *[1]; assert_equal([1,nil,[]], [a,b,c])
@@ -619,6 +717,16 @@ class TestAssignment < Test::Unit::TestCase
result = eval("if (a, b = MyObj.new); [a, b]; end", nil, __FILE__, __LINE__)
assert_equal [[1,2],[3,4]], result
end
+
+ def test_const_assign_order
+ assert_raise(RuntimeError) do
+ eval('raise("recv")::C = raise(ArgumentError, "bar")')
+ end
+
+ assert_raise(RuntimeError) do
+ eval('m = 1; m::C = raise("bar")')
+ end
+ end
end
require_relative 'sentence'
diff --git a/test/ruby/test_ast.rb b/test/ruby/test_ast.rb
index 953c8435c3..79077603e4 100644
--- a/test/ruby/test_ast.rb
+++ b/test/ruby/test_ast.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: false
require 'test/unit'
require 'tempfile'
+require 'pp'
+require_relative '../lib/parser_support'
class RubyVM
module AbstractSyntaxTree
@@ -131,6 +133,34 @@ class TestAst < Test::Unit::TestCase
end
end
+ Dir.glob("test/**/*.rb", base: SRCDIR).each do |path|
+ define_method("test_all_tokens:#{path}") do
+ node = RubyVM::AbstractSyntaxTree.parse_file("#{SRCDIR}/#{path}", keep_tokens: true)
+ tokens = node.all_tokens.sort_by { [_1.last[0], _1.last[1]] }
+ tokens_bytes = tokens.map { _1[2]}.join.bytes
+ source_bytes = File.read("#{SRCDIR}/#{path}").bytes
+
+ assert_equal(source_bytes, tokens_bytes)
+
+ (tokens.count - 1).times do |i|
+ token_0 = tokens[i]
+ token_1 = tokens[i + 1]
+ end_pos = token_0.last[2..3]
+ beg_pos = token_1.last[0..1]
+
+ if end_pos[0] == beg_pos[0]
+ # When both tokens are same line, column should be consecutives
+ assert_equal(beg_pos[1], end_pos[1], "#{token_0}. #{token_1}")
+ else
+ # Line should be next
+ assert_equal(beg_pos[0], end_pos[0] + 1, "#{token_0}. #{token_1}")
+ # It should be on the beginning of the line
+ assert_equal(0, beg_pos[1], "#{token_0}. #{token_1}")
+ end
+ end
+ end
+ end
+
private def parse(src)
EnvUtil.suppress_warning {
RubyVM::AbstractSyntaxTree.parse(src)
@@ -185,7 +215,152 @@ class TestAst < Test::Unit::TestCase
end
end
- def test_of
+ def assert_parse(code, warning: '')
+ node = assert_warning(warning) {RubyVM::AbstractSyntaxTree.parse(code)}
+ assert_kind_of(RubyVM::AbstractSyntaxTree::Node, node, code)
+ end
+
+ def assert_invalid_parse(msg, code)
+ assert_raise_with_message(SyntaxError, msg, code) do
+ RubyVM::AbstractSyntaxTree.parse(code)
+ end
+ end
+
+ def test_invalid_exit
+ [
+ "break",
+ "break true",
+ "next",
+ "next true",
+ "redo",
+ ].each do |code, *args|
+ msg = /Invalid #{code[/\A\w+/]}/
+ assert_parse("while false; #{code}; end")
+ assert_parse("until true; #{code}; end")
+ assert_parse("begin #{code}; end while false")
+ assert_parse("begin #{code}; end until true")
+ assert_parse("->{#{code}}")
+ assert_parse("->{class X; #{code}; end}")
+ assert_invalid_parse(msg, "#{code}")
+ assert_invalid_parse(msg, "def m; #{code}; end")
+ assert_invalid_parse(msg, "begin; #{code}; end")
+ assert_parse("END {#{code}}")
+
+ assert_parse("!defined?(#{code})")
+ assert_parse("def m; defined?(#{code}); end")
+ assert_parse("!begin; defined?(#{code}); end")
+
+ next if code.include?(" ")
+ assert_parse("!defined? #{code}")
+ assert_parse("def m; defined? #{code}; end")
+ assert_parse("!begin; defined? #{code}; end")
+ end
+ end
+
+ def test_invalid_retry
+ msg = /Invalid retry/
+ assert_invalid_parse(msg, "retry")
+ assert_invalid_parse(msg, "def m; retry; end")
+ assert_invalid_parse(msg, "begin retry; end")
+ assert_parse("begin rescue; retry; end")
+ assert_invalid_parse(msg, "begin rescue; else; retry; end")
+ assert_invalid_parse(msg, "begin rescue; ensure; retry; end")
+ assert_parse("nil rescue retry")
+ assert_invalid_parse(msg, "END {retry}")
+ assert_invalid_parse(msg, "begin rescue; END {retry}; end")
+
+ assert_parse("!defined?(retry)")
+ assert_parse("def m; defined?(retry); end")
+ assert_parse("!begin defined?(retry); end")
+ assert_parse("begin rescue; else; defined?(retry); end")
+ assert_parse("begin rescue; ensure; p defined?(retry); end")
+ assert_parse("END {defined?(retry)}")
+ assert_parse("begin rescue; END {defined?(retry)}; end")
+ assert_parse("!defined? retry")
+
+ assert_parse("def m; defined? retry; end")
+ assert_parse("!begin defined? retry; end")
+ assert_parse("begin rescue; else; defined? retry; end")
+ assert_parse("begin rescue; ensure; p defined? retry; end")
+ assert_parse("END {defined? retry}")
+ assert_parse("begin rescue; END {defined? retry}; end")
+
+ assert_parse("#{<<-"begin;"}\n#{<<-'end;'}")
+ begin;
+ def foo
+ begin
+ yield
+ rescue StandardError => e
+ begin
+ puts "hi"
+ retry
+ rescue
+ retry unless e
+ raise e
+ else
+ retry
+ ensure
+ retry
+ end
+ end
+ end
+ end;
+ end
+
+ def test_invalid_yield
+ msg = /Invalid yield/
+ assert_invalid_parse(msg, "yield")
+ assert_invalid_parse(msg, "class C; yield; end")
+ assert_invalid_parse(msg, "BEGIN {yield}")
+ assert_invalid_parse(msg, "END {yield}")
+ assert_invalid_parse(msg, "-> {yield}")
+
+ assert_invalid_parse(msg, "yield true")
+ assert_invalid_parse(msg, "class C; yield true; end")
+ assert_invalid_parse(msg, "BEGIN {yield true}")
+ assert_invalid_parse(msg, "END {yield true}")
+ assert_invalid_parse(msg, "-> {yield true}")
+
+ assert_parse("!defined?(yield)")
+ assert_parse("class C; defined?(yield); end")
+ assert_parse("BEGIN {defined?(yield)}")
+ assert_parse("END {defined?(yield)}")
+
+ assert_parse("!defined?(yield true)")
+ assert_parse("class C; defined?(yield true); end")
+ assert_parse("BEGIN {defined?(yield true)}")
+ assert_parse("END {defined?(yield true)}")
+
+ assert_parse("!defined? yield")
+ assert_parse("class C; defined? yield; end")
+ assert_parse("BEGIN {defined? yield}")
+ assert_parse("END {defined? yield}")
+ end
+
+ def test_node_id_for_location
+ omit if ParserSupport.prism_enabled?
+
+ exception = begin
+ raise
+ rescue => e
+ e
+ end
+ loc = exception.backtrace_locations.first
+ node_id = RubyVM::AbstractSyntaxTree.node_id_for_backtrace_location(loc)
+ node = RubyVM::AbstractSyntaxTree.of(loc, keep_script_lines: true)
+
+ assert_equal node.node_id, node_id
+ end
+
+ def test_node_id_for_backtrace_location_raises_argument_error
+ bug19262 = '[ruby-core:111435]'
+
+ assert_raise(TypeError, bug19262) { RubyVM::AbstractSyntaxTree.node_id_for_backtrace_location(1) }
+ end
+
+ def test_of_proc_and_method
+ omit if ParserSupport.prism_enabled? || ParserSupport.prism_enabled_in_subprocess?
+
proc = Proc.new { 1 + 2 }
method = self.method(__method__)
@@ -194,7 +369,6 @@ class TestAst < Test::Unit::TestCase
assert_instance_of(RubyVM::AbstractSyntaxTree::Node, node_proc)
assert_instance_of(RubyVM::AbstractSyntaxTree::Node, node_method)
- assert_raise(TypeError) { RubyVM::AbstractSyntaxTree.of("1 + 2") }
Tempfile.create(%w"test_of .rb") do |tmp|
tmp.print "#{<<-"begin;"}\n#{<<-'end;'}"
@@ -211,7 +385,29 @@ class TestAst < Test::Unit::TestCase
end
end
- def test_of_eval
+ def sample_backtrace_location
+ [caller_locations(0).first, __LINE__]
+ end
+
+ def test_of_backtrace_location
+ omit if ParserSupport.prism_enabled?
+
+ backtrace_location, lineno = sample_backtrace_location
+ node = RubyVM::AbstractSyntaxTree.of(backtrace_location)
+ assert_instance_of(RubyVM::AbstractSyntaxTree::Node, node)
+ assert_equal(lineno, node.first_lineno)
+ end
+
+ def test_of_error
+ assert_raise(TypeError) { RubyVM::AbstractSyntaxTree.of("1 + 2") }
+ end
+
+ def test_of_proc_and_method_under_eval
+ omit if ParserSupport.prism_enabled?
+
+ keep_script_lines_back = RubyVM.keep_script_lines
+ RubyVM.keep_script_lines = false
+
method = self.method(eval("def example_method_#{$$}; end"))
assert_raise(ArgumentError) { RubyVM::AbstractSyntaxTree.of(method) }
@@ -229,6 +425,87 @@ class TestAst < Test::Unit::TestCase
method = eval("Class.new{def example_method; end}.instance_method(:example_method)")
assert_raise(ArgumentError) { RubyVM::AbstractSyntaxTree.of(method) }
+
+ method = eval("Class.new{def example_method; end}.instance_method(:example_method)")
+ assert_raise(ArgumentError) { RubyVM::AbstractSyntaxTree.of(method) }
+
+ ensure
+ RubyVM.keep_script_lines = keep_script_lines_back
+ end
+
+ def test_of_proc_and_method_under_eval_with_keep_script_lines
+ omit if ParserSupport.prism_enabled?
+ pend if ENV['RUBY_ISEQ_DUMP_DEBUG'] # TODO
+
+ keep_script_lines_back = RubyVM.keep_script_lines
+ RubyVM.keep_script_lines = true
+
+ method = self.method(eval("def example_method_#{$$}_with_keep_script_lines; end"))
+ assert_instance_of(RubyVM::AbstractSyntaxTree::Node, RubyVM::AbstractSyntaxTree.of(method))
+
+ method = self.method(eval("def self.example_singleton_method_#{$$}_with_keep_script_lines; end"))
+ assert_instance_of(RubyVM::AbstractSyntaxTree::Node, RubyVM::AbstractSyntaxTree.of(method))
+
+ method = eval("proc{}")
+ assert_instance_of(RubyVM::AbstractSyntaxTree::Node, RubyVM::AbstractSyntaxTree.of(method))
+
+ method = self.method(eval("singleton_class.define_method(:example_define_method_#{$$}_with_keep_script_lines){}"))
+ assert_instance_of(RubyVM::AbstractSyntaxTree::Node, RubyVM::AbstractSyntaxTree.of(method))
+
+ method = self.method(eval("define_singleton_method(:example_dsm_#{$$}_with_keep_script_lines){}"))
+ assert_instance_of(RubyVM::AbstractSyntaxTree::Node, RubyVM::AbstractSyntaxTree.of(method))
+
+ method = eval("Class.new{def example_method_with_keep_script_lines; end}.instance_method(:example_method_with_keep_script_lines)")
+ assert_instance_of(RubyVM::AbstractSyntaxTree::Node, RubyVM::AbstractSyntaxTree.of(method))
+
+ method = eval("Class.new{def example_method_with_keep_script_lines; end}.instance_method(:example_method_with_keep_script_lines)")
+ assert_instance_of(RubyVM::AbstractSyntaxTree::Node, RubyVM::AbstractSyntaxTree.of(method))
+
+ ensure
+ RubyVM.keep_script_lines = keep_script_lines_back
+ end
+
+ def test_of_backtrace_location_under_eval
+ omit if ParserSupport.prism_enabled?
+
+ keep_script_lines_back = RubyVM.keep_script_lines
+ RubyVM.keep_script_lines = false
+
+ m = Module.new do
+ eval(<<-END, nil, __FILE__, __LINE__)
+ def self.sample_backtrace_location
+ caller_locations(0).first
+ end
+ END
+ end
+ backtrace_location = m.sample_backtrace_location
+ assert_raise(ArgumentError) { RubyVM::AbstractSyntaxTree.of(backtrace_location) }
+
+ ensure
+ RubyVM.keep_script_lines = keep_script_lines_back
+ end
+
+ def test_of_backtrace_location_under_eval_with_keep_script_lines
+ omit if ParserSupport.prism_enabled?
+ pend if ENV['RUBY_ISEQ_DUMP_DEBUG'] # TODO
+
+ keep_script_lines_back = RubyVM.keep_script_lines
+ RubyVM.keep_script_lines = true
+
+ m = Module.new do
+ eval(<<-END, nil, __FILE__, __LINE__)
+ def self.sample_backtrace_location
+ caller_locations(0).first
+ end
+ END
+ end
+ backtrace_location = m.sample_backtrace_location
+ node = RubyVM::AbstractSyntaxTree.of(backtrace_location)
+ assert_instance_of(RubyVM::AbstractSyntaxTree::Node, node)
+ assert_equal(2, node.first_lineno)
+
+ ensure
+ RubyVM.keep_script_lines = keep_script_lines_back
end
def test_of_c_method
@@ -325,7 +602,7 @@ class TestAst < Test::Unit::TestCase
assert_equal("foo", head)
assert_equal(:EVSTR, body.type)
body, = body.children
- assert_equal(:LIT, body.type)
+ assert_equal(:INTEGER, body.type)
assert_equal([1], body.children)
end
@@ -353,6 +630,30 @@ class TestAst < Test::Unit::TestCase
assert_not_equal(type1, type2)
end
+ def test_rest_arg
+ rest_arg = lambda do |arg_str|
+ node = RubyVM::AbstractSyntaxTree.parse("def a(#{arg_str}) end")
+ node = node.children.last.children.last.children[1].children[-4]
+ end
+
+ assert_equal(nil, rest_arg.call(''))
+ assert_equal(:r, rest_arg.call('*r'))
+ assert_equal(:r, rest_arg.call('a, *r'))
+ assert_equal(:*, rest_arg.call('*'))
+ assert_equal(:*, rest_arg.call('a, *'))
+ end
+
+ def test_block_arg
+ block_arg = lambda do |arg_str|
+ node = RubyVM::AbstractSyntaxTree.parse("def a(#{arg_str}) end")
+ node = node.children.last.children.last.children[1].children[-1]
+ end
+
+ assert_equal(nil, block_arg.call(''))
+ assert_equal(:block, block_arg.call('&block'))
+ assert_equal(:&, block_arg.call('&'))
+ end
+
def test_keyword_rest
kwrest = lambda do |arg_str|
node = RubyVM::AbstractSyntaxTree.parse("def a(#{arg_str}) end")
@@ -361,11 +662,21 @@ class TestAst < Test::Unit::TestCase
end
assert_equal(nil, kwrest.call(''))
- assert_equal([nil], kwrest.call('**'))
+ assert_equal([:**], kwrest.call('**'))
assert_equal(false, kwrest.call('**nil'))
assert_equal([:a], kwrest.call('**a'))
end
+ def test_argument_forwarding
+ forwarding = lambda do |arg_str|
+ node = RubyVM::AbstractSyntaxTree.parse("def a(#{arg_str}) end")
+ node = node.children.last.children.last.children[1]
+ node ? [node.children[-4], node.children[-2]&.children, node.children[-1]] : []
+ end
+
+ assert_equal([:*, [:**], :&], forwarding.call('...'))
+ end
+
def test_ranges_numbered_parameter
helper = Helper.new(__FILE__, src: "1.times {_1}")
helper.validate_range
@@ -398,6 +709,37 @@ class TestAst < Test::Unit::TestCase
assert_equal(:a, args.children[rest])
end
+ def test_return
+ assert_ast_eqaul(<<~STR, <<~EXP)
+ def m(a)
+ return a
+ end
+ STR
+ (SCOPE@1:0-3:3
+ tbl: []
+ args: nil
+ body:
+ (DEFN@1:0-3:3
+ mid: :m
+ body:
+ (SCOPE@1:0-3:3
+ tbl: [:a]
+ args:
+ (ARGS@1:6-1:7
+ pre_num: 1
+ pre_init: nil
+ opt: nil
+ first_post: nil
+ post_num: 0
+ post_init: nil
+ rest: nil
+ kw: nil
+ kwrest: nil
+ block: nil)
+ body: (RETURN@2:2-2:10 (LVAR@2:9-2:10 :a)))))
+ EXP
+ end
+
def test_keep_script_lines_for_parse
node = RubyVM::AbstractSyntaxTree.parse(<<~END, keep_script_lines: true)
1.times do
@@ -438,6 +780,8 @@ dummy
end
def test_keep_script_lines_for_of
+ omit if ParserSupport.prism_enabled?
+
proc = Proc.new { 1 + 2 }
method = self.method(__method__)
@@ -447,4 +791,645 @@ dummy
assert_equal("{ 1 + 2 }", node_proc.source)
assert_equal("def test_keep_script_lines_for_of\n", node_method.source.lines.first)
end
+
+ def test_keep_script_lines_for_of_with_existing_SCRIPT_LINES__that_has__FILE__as_a_key
+ omit if ParserSupport.prism_enabled? || ParserSupport.prism_enabled_in_subprocess?
+
+ # This test confirms that the bug that previously occurred because of
+ # `AbstractSyntaxTree.of`s unnecessary dependence on SCRIPT_LINES__ does not reproduce.
+ # The bug occurred only if SCRIPT_LINES__ included __FILE__ as a key.
+ lines = [
+ "SCRIPT_LINES__ = {__FILE__ => []}",
+ "puts RubyVM::AbstractSyntaxTree.of(->{ 1 + 2 }, keep_script_lines: true).script_lines",
+ "p SCRIPT_LINES__"
+ ]
+ test_stdout = lines + ['{"-e"=>[]}']
+ assert_in_out_err(["-e", lines.join("\n")], "", test_stdout, [])
+ end
+
+ def test_source_with_multibyte_characters
+ ast = RubyVM::AbstractSyntaxTree.parse(%{a("\u00a7");b("\u00a9")}, keep_script_lines: true)
+ a_fcall, b_fcall = ast.children[2].children
+
+ assert_equal(%{a("\u00a7")}, a_fcall.source)
+ assert_equal(%{b("\u00a9")}, b_fcall.source)
+ end
+
+ def test_keep_tokens_for_parse
+ node = RubyVM::AbstractSyntaxTree.parse(<<~END, keep_tokens: true)
+ 1.times do
+ end
+ __END__
+ dummy
+ END
+
+ expected = [
+ [:tINTEGER, "1"],
+ [:".", "."],
+ [:tIDENTIFIER, "times"],
+ [:tSP, " "],
+ [:keyword_do, "do"],
+ [:tIGNORED_NL, "\n"],
+ [:keyword_end, "end"],
+ [:nl, "\n"],
+ ]
+ assert_equal(expected, node.all_tokens.map { [_2, _3]})
+ end
+
+ def test_keep_tokens_unexpected_backslash
+ assert_raise_with_message(SyntaxError, /unexpected backslash/) do
+ RubyVM::AbstractSyntaxTree.parse("\\", keep_tokens: true)
+ end
+ end
+
+ def test_encoding_with_keep_script_lines
+ # Stop a warning "possibly useless use of a literal in void context"
+ verbose_bak, $VERBOSE = $VERBOSE, nil
+
+ enc = Encoding::EUC_JP
+ code = "__ENCODING__".encode(enc)
+
+ assert_equal(enc, eval(code))
+
+ node = RubyVM::AbstractSyntaxTree.parse(code, keep_script_lines: false)
+ assert_equal(enc, node.children[2].children[0])
+
+ node = RubyVM::AbstractSyntaxTree.parse(code, keep_script_lines: true)
+ assert_equal(enc, node.children[2].children[0])
+
+ ensure
+ $VERBOSE = verbose_bak
+ end
+
+ def test_e_option
+ omit if ParserSupport.prism_enabled? || ParserSupport.prism_enabled_in_subprocess?
+
+ assert_in_out_err(["-e", "def foo; end; pp RubyVM::AbstractSyntaxTree.of(method(:foo)).type"],
+ "", [":SCOPE"], [])
+ end
+
+ def test_error_tolerant
+ verbose_bak, $VERBOSE = $VERBOSE, false
+ node = RubyVM::AbstractSyntaxTree.parse(<<~STR, error_tolerant: true)
+ class A
+ def m
+ if;
+ a = 10
+ end
+ end
+ STR
+ assert_nil($!)
+
+ assert_equal(:SCOPE, node.type)
+ ensure
+ $VERBOSE = verbose_bak
+ end
+
+ def test_error_tolerant_end_is_short_for_method_define
+ assert_error_tolerant(<<~STR, <<~EXP)
+ def m
+ m2
+ STR
+ (SCOPE@1:0-2:4
+ tbl: []
+ args: nil
+ body:
+ (DEFN@1:0-2:4
+ mid: :m
+ body:
+ (SCOPE@1:0-2:4
+ tbl: []
+ args:
+ (ARGS@1:5-1:5
+ pre_num: 0
+ pre_init: nil
+ opt: nil
+ first_post: nil
+ post_num: 0
+ post_init: nil
+ rest: nil
+ kw: nil
+ kwrest: nil
+ block: nil)
+ body: (VCALL@2:2-2:4 :m2))))
+ EXP
+ end
+
+ def test_error_tolerant_end_is_short_for_singleton_method_define
+ assert_error_tolerant(<<~STR, <<~EXP)
+ def obj.m
+ m2
+ STR
+ (SCOPE@1:0-2:4
+ tbl: []
+ args: nil
+ body:
+ (DEFS@1:0-2:4 (VCALL@1:4-1:7 :obj) :m
+ (SCOPE@1:0-2:4
+ tbl: []
+ args:
+ (ARGS@1:9-1:9
+ pre_num: 0
+ pre_init: nil
+ opt: nil
+ first_post: nil
+ post_num: 0
+ post_init: nil
+ rest: nil
+ kw: nil
+ kwrest: nil
+ block: nil)
+ body: (VCALL@2:2-2:4 :m2))))
+ EXP
+ end
+
+ def test_error_tolerant_end_is_short_for_begin
+ assert_error_tolerant(<<~STR, <<~EXP)
+ begin
+ a = 1
+ STR
+ (SCOPE@1:0-2:7 tbl: [:a] args: nil body: (LASGN@2:2-2:7 :a (INTEGER@2:6-2:7 1)))
+ EXP
+ end
+
+ def test_error_tolerant_end_is_short_for_if
+ assert_error_tolerant(<<~STR, <<~EXP)
+ if cond
+ a = 1
+ STR
+ (SCOPE@1:0-2:7
+ tbl: [:a]
+ args: nil
+ body:
+ (IF@1:0-2:7 (VCALL@1:3-1:7 :cond) (LASGN@2:2-2:7 :a (INTEGER@2:6-2:7 1))
+ nil))
+ EXP
+
+ assert_error_tolerant(<<~STR, <<~EXP)
+ if cond
+ a = 1
+ else
+ STR
+ (SCOPE@1:0-3:4
+ tbl: [:a]
+ args: nil
+ body:
+ (IF@1:0-3:4 (VCALL@1:3-1:7 :cond) (LASGN@2:2-2:7 :a (INTEGER@2:6-2:7 1))
+ (BEGIN@3:4-3:4 nil)))
+ EXP
+ end
+
+ def test_error_tolerant_end_is_short_for_unless
+ assert_error_tolerant(<<~STR, <<~EXP)
+ unless cond
+ a = 1
+ STR
+ (SCOPE@1:0-2:7
+ tbl: [:a]
+ args: nil
+ body:
+ (UNLESS@1:0-2:7 (VCALL@1:7-1:11 :cond) (LASGN@2:2-2:7 :a (INTEGER@2:6-2:7 1))
+ nil))
+ EXP
+
+ assert_error_tolerant(<<~STR, <<~EXP)
+ unless cond
+ a = 1
+ else
+ STR
+ (SCOPE@1:0-3:4
+ tbl: [:a]
+ args: nil
+ body:
+ (UNLESS@1:0-3:4 (VCALL@1:7-1:11 :cond) (LASGN@2:2-2:7 :a (INTEGER@2:6-2:7 1))
+ (BEGIN@3:4-3:4 nil)))
+ EXP
+ end
+
+ def test_error_tolerant_end_is_short_for_while
+ assert_error_tolerant(<<~STR, <<~EXP)
+ while true
+ m
+ STR
+ (SCOPE@1:0-2:3
+ tbl: []
+ args: nil
+ body: (WHILE@1:0-2:3 (TRUE@1:6-1:10) (VCALL@2:2-2:3 :m) true))
+ EXP
+ end
+
+ def test_error_tolerant_end_is_short_for_until
+ assert_error_tolerant(<<~STR, <<~EXP)
+ until true
+ m
+ STR
+ (SCOPE@1:0-2:3
+ tbl: []
+ args: nil
+ body: (UNTIL@1:0-2:3 (TRUE@1:6-1:10) (VCALL@2:2-2:3 :m) true))
+ EXP
+ end
+
+ def test_error_tolerant_end_is_short_for_case
+ assert_error_tolerant(<<~STR, <<~EXP)
+ case a
+ when 1
+ STR
+ (SCOPE@1:0-2:6
+ tbl: []
+ args: nil
+ body:
+ (CASE@1:0-2:6 (VCALL@1:5-1:6 :a)
+ (WHEN@2:0-2:6 (LIST@2:5-2:6 (INTEGER@2:5-2:6 1) nil) (BEGIN@2:6-2:6 nil)
+ nil)))
+ EXP
+
+
+ assert_error_tolerant(<<~STR, <<~EXP)
+ case
+ when a == 1
+ STR
+ (SCOPE@1:0-2:11
+ tbl: []
+ args: nil
+ body:
+ (CASE2@1:0-2:11 nil
+ (WHEN@2:0-2:11
+ (LIST@2:5-2:11
+ (OPCALL@2:5-2:11 (VCALL@2:5-2:6 :a) :==
+ (LIST@2:10-2:11 (INTEGER@2:10-2:11 1) nil)) nil)
+ (BEGIN@2:11-2:11 nil) nil)))
+ EXP
+
+
+ assert_error_tolerant(<<~STR, <<~EXP)
+ case a
+ in {a: String}
+ STR
+ (SCOPE@1:0-2:14
+ tbl: []
+ args: nil
+ body:
+ (CASE3@1:0-2:14 (VCALL@1:5-1:6 :a)
+ (IN@2:0-2:14
+ (HSHPTN@2:4-2:13
+ const: nil
+ kw:
+ (HASH@2:4-2:13
+ (LIST@2:4-2:13 (SYM@2:4-2:6 :a) (CONST@2:7-2:13 :String) nil))
+ kwrest: nil) (BEGIN@2:14-2:14 nil) nil)))
+ EXP
+ end
+
+ def test_error_tolerant_end_is_short_for_for
+ assert_error_tolerant(<<~STR, <<~EXP)
+ for i in ary
+ m
+ STR
+ (SCOPE@1:0-2:3
+ tbl: [:i]
+ args: nil
+ body:
+ (FOR@1:0-2:3 (VCALL@1:9-1:12 :ary)
+ (SCOPE@1:0-2:3
+ tbl: [nil]
+ args:
+ (ARGS@1:4-1:5
+ pre_num: 1
+ pre_init: (LASGN@1:4-1:5 :i (DVAR@1:4-1:5 nil))
+ opt: nil
+ first_post: nil
+ post_num: 0
+ post_init: nil
+ rest: nil
+ kw: nil
+ kwrest: nil
+ block: nil)
+ body: (VCALL@2:2-2:3 :m))))
+ EXP
+ end
+
+ def test_error_tolerant_end_is_short_for_class
+ assert_error_tolerant(<<~STR, <<~EXP)
+ class C
+ STR
+ (SCOPE@1:0-1:7
+ tbl: []
+ args: nil
+ body:
+ (CLASS@1:0-1:7 (COLON2@1:6-1:7 nil :C) nil
+ (SCOPE@1:0-1:7 tbl: [] args: nil body: (BEGIN@1:7-1:7 nil))))
+ EXP
+ end
+
+ def test_error_tolerant_end_is_short_for_module
+ assert_error_tolerant(<<~STR, <<~EXP)
+ module M
+ STR
+ (SCOPE@1:0-1:8
+ tbl: []
+ args: nil
+ body:
+ (MODULE@1:0-1:8 (COLON2@1:7-1:8 nil :M)
+ (SCOPE@1:0-1:8 tbl: [] args: nil body: (BEGIN@1:8-1:8 nil))))
+ EXP
+ end
+
+ def test_error_tolerant_end_is_short_for_do
+ assert_error_tolerant(<<~STR, <<~EXP)
+ m do
+ a
+ STR
+ (SCOPE@1:0-2:3
+ tbl: []
+ args: nil
+ body:
+ (ITER@1:0-2:3 (FCALL@1:0-1:1 :m nil)
+ (SCOPE@1:2-2:3 tbl: [] args: nil body: (VCALL@2:2-2:3 :a))))
+ EXP
+ end
+
+ def test_error_tolerant_end_is_short_for_do_block
+ assert_error_tolerant(<<~STR, <<~EXP)
+ m 1 do
+ a
+ STR
+ (SCOPE@1:0-2:3
+ tbl: []
+ args: nil
+ body:
+ (ITER@1:0-2:3 (FCALL@1:0-1:3 :m (LIST@1:2-1:3 (INTEGER@1:2-1:3 1) nil))
+ (SCOPE@1:4-2:3 tbl: [] args: nil body: (VCALL@2:2-2:3 :a))))
+ EXP
+ end
+
+ def test_error_tolerant_end_is_short_for_do_LAMBDA
+ assert_error_tolerant(<<~STR, <<~EXP)
+ -> do
+ a
+ STR
+ (SCOPE@1:0-2:3
+ tbl: []
+ args: nil
+ body:
+ (LAMBDA@1:0-2:3
+ (SCOPE@1:2-2:3
+ tbl: []
+ args:
+ (ARGS@1:2-1:2
+ pre_num: 0
+ pre_init: nil
+ opt: nil
+ first_post: nil
+ post_num: 0
+ post_init: nil
+ rest: nil
+ kw: nil
+ kwrest: nil
+ block: nil)
+ body: (VCALL@2:2-2:3 :a))))
+ EXP
+ end
+
+ def test_error_tolerant_treat_end_as_keyword_based_on_indent
+ assert_error_tolerant(<<~STR, <<~EXP)
+ module Z
+ class Foo
+ foo.
+ end
+
+ def bar
+ end
+ end
+ STR
+ (SCOPE@1:0-8:3
+ tbl: []
+ args: nil
+ body:
+ (MODULE@1:0-8:3 (COLON2@1:7-1:8 nil :Z)
+ (SCOPE@1:0-8:3
+ tbl: []
+ args: nil
+ body:
+ (BLOCK@1:8-7:5 (BEGIN@1:8-1:8 nil)
+ (CLASS@2:2-4:5 (COLON2@2:8-2:11 nil :Foo) nil
+ (SCOPE@2:2-4:5
+ tbl: []
+ args: nil
+ body: (BLOCK@2:11-4:5 (BEGIN@2:11-2:11 nil) (ERROR@3:4-4:5))))
+ (DEFN@6:2-7:5
+ mid: :bar
+ body:
+ (SCOPE@6:2-7:5
+ tbl: []
+ args:
+ (ARGS@6:9-6:9
+ pre_num: 0
+ pre_init: nil
+ opt: nil
+ first_post: nil
+ post_num: 0
+ post_init: nil
+ rest: nil
+ kw: nil
+ kwrest: nil
+ block: nil)
+ body: nil))))))
+ EXP
+ end
+
+ def test_error_tolerant_expr_value_can_be_error
+ assert_error_tolerant(<<~STR, <<~EXP)
+ def m
+ if
+ end
+ STR
+ (SCOPE@1:0-3:3
+ tbl: []
+ args: nil
+ body:
+ (DEFN@1:0-3:3
+ mid: :m
+ body:
+ (SCOPE@1:0-3:3
+ tbl: []
+ args:
+ (ARGS@1:5-1:5
+ pre_num: 0
+ pre_init: nil
+ opt: nil
+ first_post: nil
+ post_num: 0
+ post_init: nil
+ rest: nil
+ kw: nil
+ kwrest: nil
+ block: nil)
+ body: (IF@2:2-3:3 (ERROR@3:0-3:3) nil nil))))
+ EXP
+ end
+
+ def test_error_tolerant_unexpected_backslash
+ node = assert_error_tolerant("\\", <<~EXP, keep_tokens: true)
+ (SCOPE@1:0-1:1 tbl: [] args: nil body: (ERROR@1:0-1:1))
+ EXP
+ assert_equal([[0, :backslash, "\\", [1, 0, 1, 1]]], node.children.last.tokens)
+ end
+
+ def test_with_bom
+ assert_error_tolerant("\u{feff}nil", <<~EXP)
+ (SCOPE@1:0-1:3 tbl: [] args: nil body: (NIL@1:0-1:3))
+ EXP
+ end
+
+ def test_unused_block_local_variable
+ assert_warning('') do
+ RubyVM::AbstractSyntaxTree.parse(%{->(; foo) {}})
+ end
+ end
+
+ def test_memory_leak
+ assert_no_memory_leak([], "#{<<~"begin;"}", "\n#{<<~'end;'}", rss: true)
+ begin;
+ 1_000_000.times do
+ eval("")
+ end
+ end;
+ end
+
+ def test_locations
+ begin
+ verbose_bak, $VERBOSE = $VERBOSE, false
+ node = RubyVM::AbstractSyntaxTree.parse("1 + 2")
+ ensure
+ $VERBOSE = verbose_bak
+ end
+ locations = node.locations
+
+ assert_equal(RubyVM::AbstractSyntaxTree::Location, locations[0].class)
+ end
+
+ private
+
+ def assert_error_tolerant(src, expected, keep_tokens: false)
+ assert_ast_eqaul(src, expected, error_tolerant: true, keep_tokens: keep_tokens)
+ end
+
+ def assert_ast_eqaul(src, expected, **options)
+ begin
+ verbose_bak, $VERBOSE = $VERBOSE, false
+ node = RubyVM::AbstractSyntaxTree.parse(src, **options)
+ ensure
+ $VERBOSE = verbose_bak
+ end
+ assert_nil($!)
+ str = ""
+ PP.pp(node, str, 80)
+ assert_equal(expected, str)
+ node
+ end
+
+ class TestLocation < Test::Unit::TestCase
+ def test_lineno_and_column
+ node = ast_parse("1 + 2")
+ assert_locations(node.locations, [[1, 0, 1, 5]])
+ end
+
+ def test_alias_locations
+ node = ast_parse("alias foo bar")
+ assert_locations(node.children[-1].locations, [[1, 0, 1, 13], [1, 0, 1, 5]])
+ end
+
+ def test_and_locations
+ node = ast_parse("1 and 2")
+ assert_locations(node.children[-1].locations, [[1, 0, 1, 7], [1, 2, 1, 5]])
+
+ node = ast_parse("1 && 2")
+ assert_locations(node.children[-1].locations, [[1, 0, 1, 6], [1, 2, 1, 4]])
+ end
+
+ def test_break_locations
+ node = ast_parse("loop { break 1 }")
+ assert_locations(node.children[-1].children[-1].children[-1].locations, [[1, 7, 1, 14], [1, 7, 1, 12]])
+ end
+
+ def test_next_locations
+ node = ast_parse("loop { next 1 }")
+ assert_locations(node.children[-1].children[-1].children[-1].locations, [[1, 7, 1, 13], [1, 7, 1, 11]])
+ end
+
+ def test_or_locations
+ node = ast_parse("1 or 2")
+ assert_locations(node.children[-1].locations, [[1, 0, 1, 6], [1, 2, 1, 4]])
+
+ node = ast_parse("1 || 2")
+ assert_locations(node.children[-1].locations, [[1, 0, 1, 6], [1, 2, 1, 4]])
+ end
+
+ def test_redo_locations
+ node = ast_parse("loop { redo }")
+ assert_locations(node.children[-1].children[-1].children[-1].locations, [[1, 7, 1, 11], [1, 7, 1, 11]])
+ end
+
+ def test_unless_locations
+ node = ast_parse("unless cond then 1 else 2 end")
+ assert_locations(node.children[-1].locations, [[1, 0, 1, 29], [1, 0, 1, 6], [1, 12, 1, 16], [1, 26, 1, 29]])
+
+ node = ast_parse("1 unless 2")
+ assert_locations(node.children[-1].locations, [[1, 0, 1, 10], [1, 2, 1, 8], nil, nil])
+ end
+
+ def test_undef_locations
+ node = ast_parse("undef foo")
+ assert_locations(node.children[-1].locations, [[1, 0, 1, 9], [1, 0, 1, 5]])
+
+ node = ast_parse("undef foo, bar")
+ assert_locations(node.children[-1].locations, [[1, 0, 1, 14], [1, 0, 1, 5]])
+ end
+
+ def test_valias_locations
+ node = ast_parse("alias $foo $bar")
+ assert_locations(node.children[-1].locations, [[1, 0, 1, 15], [1, 0, 1, 5]])
+
+ node = ast_parse("alias $foo $&")
+ assert_locations(node.children[-1].locations, [[1, 0, 1, 13], [1, 0, 1, 5]])
+ end
+
+ def test_when_locations
+ node = ast_parse("case a; when 1 then 2; end")
+ assert_locations(node.children[-1].children[1].locations, [[1, 8, 1, 22], [1, 8, 1, 12], [1, 15, 1, 19]])
+ end
+
+ def test_while_locations
+ node = ast_parse("while cond do 1 end")
+ assert_locations(node.children[-1].locations, [[1, 0, 1, 19], [1, 0, 1, 5], [1, 16, 1, 19]])
+
+ node = ast_parse("1 while 2")
+ assert_locations(node.children[-1].locations, [[1, 0, 1, 9], [1, 2, 1, 7], nil])
+ end
+
+ def test_until_locations
+ node = ast_parse("until cond do 1 end")
+ assert_locations(node.children[-1].locations, [[1, 0, 1, 19], [1, 0, 1, 5], [1, 16, 1, 19]])
+
+ node = ast_parse("1 until 2")
+ assert_locations(node.children[-1].locations, [[1, 0, 1, 9], [1, 2, 1, 7], nil])
+ end
+
+ private
+ def ast_parse(src, **options)
+ begin
+ verbose_bak, $VERBOSE = $VERBOSE, false
+ RubyVM::AbstractSyntaxTree.parse(src, **options)
+ ensure
+ $VERBOSE = verbose_bak
+ end
+ end
+
+ def assert_locations(locations, expected)
+ ary = locations.map {|loc| loc && [loc.first_lineno, loc.first_column, loc.last_lineno, loc.last_column] }
+
+ assert_equal(ary, expected)
+ end
+ end
end
diff --git a/test/ruby/test_autoload.rb b/test/ruby/test_autoload.rb
index 98d513da87..ca3e3d5f7f 100644
--- a/test/ruby/test_autoload.rb
+++ b/test/ruby/test_autoload.rb
@@ -65,6 +65,24 @@ p Foo::Bar
}
end
+ def test_autoload_p_with_static_extensions
+ require 'rbconfig'
+ omit unless RbConfig::CONFIG['EXTSTATIC'] == 'static'
+ begin
+ require 'fcntl.so'
+ rescue LoadError
+ omit('fcntl not included in the build')
+ end
+
+ assert_separately(['--disable-all'], <<~RUBY)
+ autoload :Fcntl, 'fcntl.so'
+
+ assert_equal('fcntl.so', autoload?(:Fcntl))
+ assert(Object.const_defined?(:Fcntl))
+ assert_equal('constant', defined?(Fcntl), '[Bug #19115]')
+ RUBY
+ end
+
def test_autoload_with_unqualified_file_name # [ruby-core:69206]
Object.send(:remove_const, :A) if Object.const_defined?(:A)
@@ -150,6 +168,7 @@ p Foo::Bar
end
def test_nameerror_when_autoload_did_not_define_the_constant
+ verbose_bak, $VERBOSE = $VERBOSE, nil
Tempfile.create(['autoload', '.rb']) {|file|
file.puts ''
file.close
@@ -162,6 +181,8 @@ p Foo::Bar
remove_autoload_constant
end
}
+ ensure
+ $VERBOSE = verbose_bak
end
def test_override_autoload
@@ -253,6 +274,10 @@ p Foo::Bar
end
def test_bug_13526
+ # Skip this on macOS 10.13 because of the following error:
+ # http://rubyci.s3.amazonaws.com/osx1013/ruby-master/log/20231011T014505Z.fail.html.gz
+ require "rbconfig"
+
script = File.join(__dir__, 'bug-13526.rb')
assert_ruby_status([script], '', '[ruby-core:81016] [Bug #13526]')
end
@@ -443,6 +468,23 @@ p Foo::Bar
end
end
+ def test_source_location_after_require
+ bug = "Bug18624"
+ Dir.mktmpdir('autoload') do |tmpdir|
+ path = "#{tmpdir}/test-#{bug}.rb"
+ File.write(path, "C::#{bug} = __FILE__\n")
+ assert_separately(%W[-I #{tmpdir}], "#{<<-"begin;"}\n#{<<-"end;"}")
+ begin;
+ class C; end
+ C.autoload(:Bug18624, #{path.dump})
+ require #{path.dump}
+ assert_equal [#{path.dump}, 1], C.const_source_location(#{bug.dump})
+ assert_equal #{path.dump}, C.const_get(#{bug.dump})
+ assert_equal [#{path.dump}, 1], C.const_source_location(#{bug.dump})
+ end;
+ end
+ end
+
def test_no_memory_leak
assert_no_memory_leak([], '', "#{<<~"begin;"}\n#{<<~'end;'}", 'many autoloads', timeout: 60)
begin;
@@ -456,6 +498,32 @@ p Foo::Bar
end;
end
+ def test_autoload_after_failed_and_removed_from_loaded_features
+ Dir.mktmpdir('autoload') do |tmpdir|
+ autoload_path = File.join(tmpdir, "test-bug-15790.rb")
+ File.write(autoload_path, '')
+
+ assert_separately(%W[-I #{tmpdir}], <<-RUBY)
+ $VERBOSE = nil
+ path = #{File.realpath(autoload_path).inspect}
+ autoload :X, path
+ assert_equal(path, Object.autoload?(:X))
+
+ assert_raise(NameError){X}
+ assert_nil(Object.autoload?(:X))
+ assert_equal(false, Object.const_defined?(:X))
+
+ $LOADED_FEATURES.delete(path)
+ assert_equal(false, Object.const_defined?(:X))
+ assert_nil(Object.autoload?(:X))
+
+ assert_raise(NameError){X}
+ assert_equal(false, Object.const_defined?(:X))
+ assert_nil(Object.autoload?(:X))
+ RUBY
+ end
+ end
+
def add_autoload(path)
(@autoload_paths ||= []) << path
::Object.class_eval {autoload(:AutoloadTest, path)}
@@ -463,7 +531,72 @@ p Foo::Bar
def remove_autoload_constant
$".replace($" - @autoload_paths)
- ::Object.class_eval {remove_const(:AutoloadTest)}
+ ::Object.class_eval {remove_const(:AutoloadTest)} if defined? Object::AutoloadTest
TestAutoload.class_eval {remove_const(:AutoloadTest)} if defined? TestAutoload::AutoloadTest
end
+
+ def test_autoload_module_gc
+ Dir.mktmpdir('autoload') do |tmpdir|
+ autoload_path = File.join(tmpdir, "autoload_module_gc.rb")
+ File.write(autoload_path, "X = 1; Y = 2;")
+
+ x = Module.new
+ x.autoload :X, "./feature.rb"
+
+ 1000.times do
+ y = Module.new
+ y.autoload :Y, "./feature.rb"
+ end
+
+ x = y = nil
+
+ # Ensure the internal data structures are cleaned up correctly / don't crash:
+ GC.start
+ end
+ end
+
+ def test_autoload_parallel_race
+ Dir.mktmpdir('autoload') do |tmpdir|
+ autoload_path = File.join(tmpdir, "autoload_parallel_race.rb")
+ File.write(autoload_path, 'module Foo; end; module Bar; end')
+
+ assert_separately([], <<-RUBY, timeout: 100)
+ autoload_path = #{File.realpath(autoload_path).inspect}
+
+ # This should work with no errors or failures.
+ 1000.times do
+ autoload :Foo, autoload_path
+ autoload :Bar, autoload_path
+
+ t1 = Thread.new {Foo}
+ t2 = Thread.new {Bar}
+
+ t1.join
+ GC.start # force GC.
+ t2.join
+
+ Object.send(:remove_const, :Foo)
+ Object.send(:remove_const, :Bar)
+
+ $LOADED_FEATURES.delete(autoload_path)
+ end
+ RUBY
+ end
+ end
+
+ def test_autoload_parent_namespace
+ Dir.mktmpdir('autoload') do |tmpdir|
+ autoload_path = File.join(tmpdir, "some_const.rb")
+ File.write(autoload_path, 'class SomeConst; end')
+
+ assert_separately(%W[-I #{tmpdir}], <<-RUBY)
+ module SomeNamespace
+ autoload :SomeConst, #{File.realpath(autoload_path).inspect}
+ assert_warning(%r{/some_const\.rb to define SomeNamespace::SomeConst but it didn't}) do
+ assert_not_nil SomeConst
+ end
+ end
+ RUBY
+ end
+ end
end
diff --git a/test/ruby/test_backtrace.rb b/test/ruby/test_backtrace.rb
index aa79db24cb..fca7b62030 100644
--- a/test/ruby/test_backtrace.rb
+++ b/test/ruby/test_backtrace.rb
@@ -154,6 +154,43 @@ class TestBacktrace < Test::Unit::TestCase
assert_equal caller(0), caller(0, nil)
end
+ def test_each_backtrace_location
+ assert_nil(Thread.each_caller_location {})
+
+ assert_raise(LocalJumpError) {Thread.each_caller_location}
+
+ i = 0
+ cl = caller_locations(1, 1)[0]; ecl = Thread.each_caller_location{|x| i+=1; break x if i == 1}
+ assert_equal(cl.to_s, ecl.to_s)
+ assert_kind_of(Thread::Backtrace::Location, ecl)
+
+ i = 0
+ ary = []
+ cllr = caller_locations(1, 2); last = Thread.each_caller_location{|x| ary << x; i+=1; break x if i == 2}
+ assert_equal(cllr.map(&:to_s), ary.map(&:to_s))
+ assert_kind_of(Thread::Backtrace::Location, last)
+
+ i = 0
+ ary = []
+ ->{->{
+ cllr = caller_locations(1, 2); last = Thread.each_caller_location{|x| ary << x; i+=1; break x if i == 2}
+ }.()}.()
+ assert_equal(cllr.map(&:to_s), ary.map(&:to_s))
+ assert_kind_of(Thread::Backtrace::Location, last)
+
+ cllr = caller_locations(1, 2); ary = Thread.to_enum(:each_caller_location).to_a[2..3]
+ assert_equal(cllr.map(&:to_s), ary.map(&:to_s))
+
+ ecl = Thread.to_enum(:each_caller_location)
+ assert_raise(StopIteration) {
+ ecl.next
+ }
+
+ ary = []
+ cl = caller_locations(1, 2); Thread.each_caller_location(1, 2) {|x| ary << x}
+ assert_equal(cl.map(&:to_s), ary.map(&:to_s))
+ end
+
def test_caller_locations_first_label
def self.label
caller_locations.first.label
@@ -186,15 +223,15 @@ class TestBacktrace < Test::Unit::TestCase
@res = caller_locations(2, 1).inspect
end
@line = __LINE__ + 1
- 1.times.map { 1.times.map { foo } }
- assert_equal("[\"#{__FILE__}:#{@line}:in `times'\"]", @res)
+ [1].map.map { [1].map.map { foo } }
+ assert_equal("[\"#{__FILE__}:#{@line}:in 'Array#map'\"]", @res)
end
def test_caller_location_path_cfunc_iseq_no_pc
def self.foo
@res = caller_locations(2, 1)[0].path
end
- 1.times.map { 1.times.map { foo } }
+ [1].map.map { [1].map.map { foo } }
assert_equal(__FILE__, @res)
end
@@ -263,13 +300,13 @@ class TestBacktrace < Test::Unit::TestCase
end
def test_caller_locations_label
- assert_equal("#{__method__}", caller_locations(0, 1)[0].label)
+ assert_equal("TestBacktrace##{__method__}", caller_locations(0, 1)[0].label)
loc, = tap {break caller_locations(0, 1)}
- assert_equal("block in #{__method__}", loc.label)
+ assert_equal("block in TestBacktrace##{__method__}", loc.label)
begin
raise
rescue
- assert_equal("rescue in #{__method__}", caller_locations(0, 1)[0].label)
+ assert_equal("TestBacktrace##{__method__}", caller_locations(0, 1)[0].label)
end
end
@@ -349,17 +386,17 @@ class TestBacktrace < Test::Unit::TestCase
def test_core_backtrace_hash_merge
e = assert_raise(TypeError) do
- {**nil}
+ {**1}
end
assert_not_match(/\Acore#/, e.backtrace_locations[0].base_label)
end
def test_notty_backtrace
- err = ["-:1:in `<main>': unhandled exception"]
+ err = ["-:1:in '<main>': unhandled exception"]
assert_in_out_err([], "raise", [], err)
- err = ["-:2:in `foo': foo! (RuntimeError)",
- "\tfrom -:4:in `<main>'"]
+ err = ["-:2:in 'Object#foo': foo! (RuntimeError)",
+ "\tfrom -:4:in '<main>'"]
assert_in_out_err([], <<-"end;", [], err)
def foo
raise "foo!"
@@ -367,12 +404,11 @@ class TestBacktrace < Test::Unit::TestCase
foo
end;
- err = ["-:7:in `rescue in bar': bar! (RuntimeError)",
- "\tfrom -:4:in `bar'",
- "\tfrom -:9:in `<main>'",
- "-:2:in `foo': foo! (RuntimeError)",
- "\tfrom -:5:in `bar'",
- "\tfrom -:9:in `<main>'"]
+ err = ["-:7:in 'Object#bar': bar! (RuntimeError)",
+ "\tfrom -:9:in '<main>'",
+ "-:2:in 'Object#foo': foo! (RuntimeError)",
+ "\tfrom -:5:in 'Object#bar'",
+ "\tfrom -:9:in '<main>'"]
assert_in_out_err([], <<-"end;", [], err)
def foo
raise "foo!"
@@ -387,7 +423,7 @@ class TestBacktrace < Test::Unit::TestCase
end
def test_caller_to_enum
- err = ["-:3:in `foo': unhandled exception", "\tfrom -:in `each'"]
+ err = ["-:3:in 'Object#foo': unhandled exception", "\tfrom -:in 'Enumerator#each'"]
assert_in_out_err([], <<-"end;", [], err, "[ruby-core:91911]")
def foo
return to_enum(__method__) unless block_given?
@@ -399,4 +435,23 @@ class TestBacktrace < Test::Unit::TestCase
enum.next
end;
end
+
+ def test_no_receiver_for_anonymous_class
+ err = ["-:2:in 'bar': unhandled exception", # Not '#<Class:0xXXX>.bar'
+ "\tfrom -:3:in '<main>'"]
+ assert_in_out_err([], <<-"end;", [], err)
+ foo = Class.new
+ def foo.bar = raise
+ foo.bar
+ end;
+
+ err = ["-:3:in 'baz': unhandled exception", # Not '#<Class:0xXXX>::Bar.baz'
+ "\tfrom -:4:in '<main>'"]
+ assert_in_out_err([], <<-"end;", [], err)
+ foo = Class.new
+ foo::Bar = Class.new
+ def (foo::Bar).baz = raise
+ foo::Bar.baz
+ end;
+ end
end
diff --git a/test/ruby/test_beginendblock.rb b/test/ruby/test_beginendblock.rb
index eb8394864f..3706efab52 100644
--- a/test/ruby/test_beginendblock.rb
+++ b/test/ruby/test_beginendblock.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: false
require 'test/unit'
+EnvUtil.suppress_warning {require 'continuation'}
class TestBeginEndBlock < Test::Unit::TestCase
DIR = File.dirname(File.expand_path(__FILE__))
@@ -14,6 +15,11 @@ class TestBeginEndBlock < Test::Unit::TestCase
assert_in_out_err(["-p", "-eBEGIN{p :begin}", "-eEND{p :end}"], "foo\nbar\n", %w(:begin foo bar :end))
end
+ def test_endblock_variable
+ assert_in_out_err(["-n", "-ea = :ok", "-eEND{p a}"], "foo\n", %w(:ok))
+ assert_in_out_err(["-p", "-ea = :ok", "-eEND{p a}"], "foo\n", %w(foo :ok))
+ end
+
def test_begininmethod
assert_raise_with_message(SyntaxError, /BEGIN is permitted only at toplevel/) do
eval("def foo; BEGIN {}; end")
@@ -40,9 +46,9 @@ class TestBeginEndBlock < Test::Unit::TestCase
end
def test_endblockwarn_in_eval
- assert_in_out_err([], "#{<<~"begin;"}\n#{<<~'end;'}", [], ['(eval):2: warning: END in method; use at_exit'])
+ assert_in_out_err([], "#{<<~"begin;"}\n#{<<~'end;'}", [], ['test.rb:1: warning: END in method; use at_exit'])
begin;
- eval <<-EOE
+ eval <<-EOE, nil, "test.rb", 0
def end2
END {}
end
@@ -62,7 +68,7 @@ class TestBeginEndBlock < Test::Unit::TestCase
bug8501 = '[ruby-core:55365] [Bug #8501]'
args = ['-e', 'o = Object.new; def o.inspect; raise "[Bug #8501]"; end',
'-e', 'at_exit{o.nope}']
- status = assert_in_out_err(args, '', [], /undefined method `nope'/, bug8501)
+ status = assert_in_out_err(args, '', [], /undefined method 'nope'/, bug8501)
assert_not_predicate(status, :success?, bug8501)
end
@@ -126,6 +132,8 @@ class TestBeginEndBlock < Test::Unit::TestCase
end
def test_callcc_at_exit
+ omit 'requires callcc support' unless respond_to?(:callcc)
+
bug9110 = '[ruby-core:58329][Bug #9110]'
assert_ruby_status([], "#{<<~"begin;"}\n#{<<~'end;'}", bug9110)
begin;
diff --git a/test/ruby/test_bignum.rb b/test/ruby/test_bignum.rb
index 3ffe7114b5..1858793952 100644
--- a/test/ruby/test_bignum.rb
+++ b/test/ruby/test_bignum.rb
@@ -203,6 +203,15 @@ class TestBignum < Test::Unit::TestCase
assert_equal(00_02, '00_02'.to_i)
end
+ def test_very_big_str_to_inum
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ digits = [["3", 700], ["0", 2700], ["1", 1], ["0", 26599]]
+ num = digits.inject(+"") {|s,(c,n)|s << c*n}.to_i
+ assert_equal digits.sum {|c,n|n}, num.to_s.size
+ end;
+ end
+
def test_to_s2
assert_raise(ArgumentError) { T31P.to_s(37) }
assert_equal("9" * 32768, (10**32768-1).to_s)
@@ -644,7 +653,7 @@ class TestBignum < Test::Unit::TestCase
thread.raise
thread.join
time = Time.now - time
- skip "too fast cpu" if end_flag
+ omit "too fast cpu" if end_flag
assert_operator(time, :<, 10)
end
@@ -675,7 +684,7 @@ class TestBignum < Test::Unit::TestCase
return
end
end
- skip "cannot create suitable test case"
+ omit "cannot create suitable test case"
ensure
Signal.trap(:INT, oldtrap) if oldtrap
end
@@ -812,5 +821,11 @@ class TestBignum < Test::Unit::TestCase
assert_nil(T1024P.infinite?)
assert_nil((-T1024P).infinite?)
end
+
+ def test_gmp_version
+ if RbConfig::CONFIG.fetch('configure_args').include?("'--with-gmp'")
+ assert_kind_of(String, Integer::GMP_VERSION)
+ end
+ end if ENV['GITHUB_WORKFLOW'] == 'Compilations'
end
end
diff --git a/test/ruby/test_call.rb b/test/ruby/test_call.rb
index 67b3a936d4..ffbda1fdb9 100644
--- a/test/ruby/test_call.rb
+++ b/test/ruby/test_call.rb
@@ -1,8 +1,26 @@
# frozen_string_literal: false
require 'test/unit'
+require '-test-/iter'
class TestCall < Test::Unit::TestCase
- def aaa(a, b=100, *rest)
+ # These dummy method definitions prevent warnings "the block passed to 'a'..."
+ def a(&) = nil
+ def b(&) = nil
+ def c(&) = nil
+ def d(&) = nil
+ def e(&) = nil
+ def f(&) = nil
+ def g(&) = nil
+ def h(&) = nil
+ def i(&) = nil
+ def j(&) = nil
+ def k(&) = nil
+ def l(&) = nil
+ def m(&) = nil
+ def n(&) = nil
+ def o(&) = nil
+
+ def aaa(a, b=100, *rest, &)
res = [a, b]
res += rest if rest
return res
@@ -47,12 +65,19 @@ class TestCall < Test::Unit::TestCase
assert_equal(5, o.y)
o&.z ||= 6
assert_equal(6, o.z)
+ o&.z &&= 7
+ assert_equal(7, o.z)
o = nil
assert_nil(o&.x)
assert_nothing_raised(NoMethodError) {o&.x = raise}
+ assert_nothing_raised(NoMethodError) {o&.x = raise; nil}
assert_nothing_raised(NoMethodError) {o&.x *= raise}
assert_nothing_raised(NoMethodError) {o&.x *= raise; nil}
+ assert_nothing_raised(NoMethodError) {o&.x ||= raise}
+ assert_nothing_raised(NoMethodError) {o&.x ||= raise; nil}
+ assert_nothing_raised(NoMethodError) {o&.x &&= raise}
+ assert_nothing_raised(NoMethodError) {o&.x &&= raise; nil}
end
def test_safe_call_evaluate_arguments_only_method_call_is_made
@@ -92,7 +117,210 @@ class TestCall < Test::Unit::TestCase
}
end
- def test_call_splat_order
+ def test_frozen_splat_and_keywords
+ a = [1, 2].freeze
+ def self.f(*a); a end
+ assert_equal([1, 2, {kw: 3}], f(*a, kw: 3))
+ end
+
+ def test_call_bmethod_proc
+ pr = proc{|sym| sym}
+ define_singleton_method(:a, &pr)
+ ary = [10]
+ assert_equal(10, a(*ary))
+ end
+
+ def test_call_bmethod_proc_restarg
+ pr = proc{|*sym| sym}
+ define_singleton_method(:a, &pr)
+ ary = [10]
+ assert_equal([10], a(*ary))
+ assert_equal([10], a(10))
+ end
+
+ def test_call_op_asgn_keywords
+ h = Class.new do
+ attr_reader :get, :set
+ def v; yield; [*@get, *@set] end
+ def [](*a, **b, &c) @get = [a, b, c]; @set = []; 3 end
+ def []=(*a, **b, &c) @set = [a, b, c] end
+ end.new
+
+ a = []
+ kw = {}
+ b = lambda{}
+
+ # Prevent "assigned but unused variable" warnings
+ _ = [h, a, kw, b]
+
+ message = /keyword arg given in index assignment/
+
+ # +=, without block, non-popped
+ assert_syntax_error(%q{h[**kw] += 1}, message)
+ assert_syntax_error(%q{h[0, **kw] += 1}, message)
+ assert_syntax_error(%q{h[0, *a, **kw] += 1}, message)
+ assert_syntax_error(%q{h[kw: 5] += 1}, message)
+ assert_syntax_error(%q{h[kw: 5, a: 2] += 1}, message)
+ assert_syntax_error(%q{h[kw: 5, a: 2] += 1}, message)
+ assert_syntax_error(%q{h[0, kw: 5, a: 2] += 1}, message)
+ assert_syntax_error(%q{h[0, *a, kw: 5, a: 2, nil: 3] += 1}, message)
+
+ # +=, with block, non-popped
+ assert_syntax_error(%q{h[**kw, &b] += 1}, message)
+ assert_syntax_error(%q{h[0, **kw, &b] += 1}, message)
+ assert_syntax_error(%q{h[0, *a, **kw, &b] += 1}, message)
+ assert_syntax_error(%q{h[kw: 5, &b] += 1}, message)
+ assert_syntax_error(%q{h[kw: 5, a: 2, &b] += 1}, message)
+ assert_syntax_error(%q{h[kw: 5, a: 2, &b] += 1}, message)
+ assert_syntax_error(%q{h[0, kw: 5, a: 2, &b] += 1}, message)
+ assert_syntax_error(%q{h[0, *a, kw: 5, a: 2, b: 3, &b] += 1}, message)
+
+ # +=, without block, popped
+ assert_syntax_error(%q{h[**kw] += 1; nil}, message)
+ assert_syntax_error(%q{h[0, **kw] += 1; nil}, message)
+ assert_syntax_error(%q{h[0, *a, **kw] += 1; nil}, message)
+ assert_syntax_error(%q{h[kw: 5] += 1; nil}, message)
+ assert_syntax_error(%q{h[kw: 5, a: 2] += 1; nil}, message)
+ assert_syntax_error(%q{h[kw: 5, a: 2] += 1; nil}, message)
+ assert_syntax_error(%q{h[0, kw: 5, a: 2] += 1; nil}, message)
+ assert_syntax_error(%q{h[0, *a, kw: 5, a: 2, nil: 3] += 1; nil}, message)
+
+ # +=, with block, popped
+ assert_syntax_error(%q{h[**kw, &b] += 1; nil}, message)
+ assert_syntax_error(%q{h[0, **kw, &b] += 1; nil}, message)
+ assert_syntax_error(%q{h[0, *a, **kw, &b] += 1; nil}, message)
+ assert_syntax_error(%q{h[kw: 5, &b] += 1; nil}, message)
+ assert_syntax_error(%q{h[kw: 5, a: 2, &b] += 1; nil}, message)
+ assert_syntax_error(%q{h[kw: 5, a: 2, &b] += 1; nil}, message)
+ assert_syntax_error(%q{h[0, kw: 5, a: 2, &b] += 1; nil}, message)
+ assert_syntax_error(%q{h[0, *a, kw: 5, a: 2, b: 3, &b] += 1; nil}, message)
+
+ # &&=, without block, non-popped
+ assert_syntax_error(%q{h[**kw] &&= 1}, message)
+ assert_syntax_error(%q{h[0, **kw] &&= 1}, message)
+ assert_syntax_error(%q{h[0, *a, **kw] &&= 1}, message)
+ assert_syntax_error(%q{h[kw: 5] &&= 1}, message)
+ assert_syntax_error(%q{h[kw: 5, a: 2] &&= 1}, message)
+ assert_syntax_error(%q{h[kw: 5, a: 2] &&= 1}, message)
+ assert_syntax_error(%q{h[0, kw: 5, a: 2] &&= 1}, message)
+ assert_syntax_error(%q{h[0, *a, kw: 5, a: 2, nil: 3] &&= 1}, message)
+
+ # &&=, with block, non-popped
+ assert_syntax_error(%q{h[**kw, &b] &&= 1}, message)
+ assert_syntax_error(%q{h[0, **kw, &b] &&= 1}, message)
+ assert_syntax_error(%q{h[0, *a, **kw, &b] &&= 1}, message)
+ assert_syntax_error(%q{h[kw: 5, &b] &&= 1}, message)
+ assert_syntax_error(%q{h[kw: 5, a: 2, &b] &&= 1}, message)
+ assert_syntax_error(%q{h[kw: 5, a: 2, &b] &&= 1}, message)
+ assert_syntax_error(%q{h[0, kw: 5, a: 2, &b] &&= 1}, message)
+ assert_syntax_error(%q{h[0, *a, kw: 5, a: 2, b: 3, &b] &&= 1}, message)
+
+ # &&=, without block, popped
+ assert_syntax_error(%q{h[**kw] &&= 1; nil}, message)
+ assert_syntax_error(%q{h[0, **kw] &&= 1; nil}, message)
+ assert_syntax_error(%q{h[0, *a, **kw] &&= 1; nil}, message)
+ assert_syntax_error(%q{h[kw: 5] &&= 1; nil}, message)
+ assert_syntax_error(%q{h[kw: 5, a: 2] &&= 1; nil}, message)
+ assert_syntax_error(%q{h[kw: 5, a: 2] &&= 1; nil}, message)
+ assert_syntax_error(%q{h[0, kw: 5, a: 2] &&= 1; nil}, message)
+ assert_syntax_error(%q{h[0, *a, kw: 5, a: 2, nil: 3] &&= 1; nil}, message)
+
+ # &&=, with block, popped
+ assert_syntax_error(%q{h[**kw, &b] &&= 1; nil}, message)
+ assert_syntax_error(%q{h[0, **kw, &b] &&= 1; nil}, message)
+ assert_syntax_error(%q{h[0, *a, **kw, &b] &&= 1; nil}, message)
+ assert_syntax_error(%q{h[kw: 5, &b] &&= 1; nil}, message)
+ assert_syntax_error(%q{h[kw: 5, a: 2, &b] &&= 1; nil}, message)
+ assert_syntax_error(%q{h[kw: 5, a: 2, &b] &&= 1; nil}, message)
+ assert_syntax_error(%q{h[0, kw: 5, a: 2, &b] &&= 1; nil}, message)
+ assert_syntax_error(%q{h[0, *a, kw: 5, a: 2, b: 3, &b] &&= 1; nil}, message)
+
+ # ||=, without block, non-popped
+ assert_syntax_error(%q{h[**kw] ||= 1}, message)
+ assert_syntax_error(%q{h[0, **kw] ||= 1}, message)
+ assert_syntax_error(%q{h[0, *a, **kw] ||= 1}, message)
+ assert_syntax_error(%q{h[kw: 5] ||= 1}, message)
+ assert_syntax_error(%q{h[kw: 5, a: 2] ||= 1}, message)
+ assert_syntax_error(%q{h[kw: 5, a: 2] ||= 1}, message)
+ assert_syntax_error(%q{h[0, kw: 5, a: 2] ||= 1}, message)
+ assert_syntax_error(%q{h[0, *a, kw: 5, a: 2, nil: 3] ||= 1}, message)
+
+ # ||=, with block, non-popped
+ assert_syntax_error(%q{h[**kw, &b] ||= 1}, message)
+ assert_syntax_error(%q{h[0, **kw, &b] ||= 1}, message)
+ assert_syntax_error(%q{h[0, *a, **kw, &b] ||= 1}, message)
+ assert_syntax_error(%q{h[kw: 5, &b] ||= 1}, message)
+ assert_syntax_error(%q{h[kw: 5, a: 2, &b] ||= 1}, message)
+ assert_syntax_error(%q{h[kw: 5, a: 2, &b] ||= 1}, message)
+ assert_syntax_error(%q{h[0, kw: 5, a: 2, &b] ||= 1}, message)
+ assert_syntax_error(%q{h[0, *a, kw: 5, a: 2, b: 3, &b] ||= 1}, message)
+
+ # ||=, without block, popped
+ assert_syntax_error(%q{h[**kw] ||= 1; nil}, message)
+ assert_syntax_error(%q{h[0, **kw] ||= 1; nil}, message)
+ assert_syntax_error(%q{h[0, *a, **kw] ||= 1; nil}, message)
+ assert_syntax_error(%q{h[kw: 5] ||= 1; nil}, message)
+ assert_syntax_error(%q{h[kw: 5, a: 2] ||= 1; nil}, message)
+ assert_syntax_error(%q{h[kw: 5, a: 2] ||= 1; nil}, message)
+ assert_syntax_error(%q{h[0, kw: 5, a: 2] ||= 1; nil}, message)
+ assert_syntax_error(%q{h[0, *a, kw: 5, a: 2, nil: 3] ||= 1; nil}, message)
+
+ # ||=, with block, popped
+ assert_syntax_error(%q{h[**kw, &b] ||= 1; nil}, message)
+ assert_syntax_error(%q{h[0, **kw, &b] ||= 1; nil}, message)
+ assert_syntax_error(%q{h[0, *a, **kw, &b] ||= 1; nil}, message)
+ assert_syntax_error(%q{h[kw: 5, &b] ||= 1; nil}, message)
+ assert_syntax_error(%q{h[kw: 5, a: 2, &b] ||= 1; nil}, message)
+ assert_syntax_error(%q{h[kw: 5, a: 2, &b] ||= 1; nil}, message)
+ assert_syntax_error(%q{h[0, kw: 5, a: 2, &b] ||= 1; nil}, message)
+ assert_syntax_error(%q{h[0, *a, kw: 5, a: 2, b: 3, &b] ||= 1; nil}, message)
+
+ end
+
+ def test_kwsplat_block_order_op_asgn
+ o = Object.new
+ ary = []
+ o.define_singleton_method(:to_a) {ary << :to_a; []}
+ o.define_singleton_method(:to_hash) {ary << :to_hash; {}}
+ o.define_singleton_method(:to_proc) {ary << :to_proc; lambda{}}
+
+ def o.[](...) 2 end
+ def o.[]=(...) end
+
+ message = /keyword arg given in index assignment/
+
+ assert_syntax_error(%q{o[kw: 1] += 1}, message)
+ assert_syntax_error(%q{o[**o] += 1}, message)
+ assert_syntax_error(%q{o[**o, &o] += 1}, message)
+ assert_syntax_error(%q{o[*o, **o, &o] += 1}, message)
+ end
+
+ def test_call_op_asgn_keywords_mutable
+ h = Class.new do
+ attr_reader :get, :set
+ def v; yield; [*@get, *@set] end
+ def [](*a, **b)
+ @get = [a.dup, b.dup]
+ a << :splat_modified
+ b[:kw_splat_modified] = true
+ @set = []
+ 3
+ end
+ def []=(*a, **b) @set = [a, b] end
+ end.new
+
+ message = /keyword arg given in index assignment/
+
+ a = []
+ kw = {}
+
+ # Prevent "assigned but unused variable" warnings
+ _ = [h, a, kw]
+
+ assert_syntax_error(%q{h[*a, 2, b: 5, **kw] += 1}, message)
+ end
+
+ def test_call_splat_post_order
bug12860 = '[ruby-core:77701] [Bug# 12860]'
ary = [1, 2]
assert_equal([1, 2, 1], aaa(*ary, ary.shift), bug12860)
@@ -100,7 +328,7 @@ class TestCall < Test::Unit::TestCase
assert_equal([0, 1, 2, 1], aaa(0, *ary, ary.shift), bug12860)
end
- def test_call_block_order
+ def test_call_splat_block_order
bug16504 = '[ruby-core:96769] [Bug# 16504]'
b = proc{}
ary = [1, 2, b]
@@ -108,4 +336,1057 @@ class TestCall < Test::Unit::TestCase
ary = [1, 2, b]
assert_equal([0, 1, 2, b], aaa(0, *ary, &ary.pop), bug16504)
end
+
+ def test_call_splat_kw_order
+ b = {}
+ ary = [1, 2, b]
+ assert_equal([1, 2, b, {a: b}], aaa(*ary, a: ary.pop))
+ ary = [1, 2, b]
+ assert_equal([0, 1, 2, b, {a: b}], aaa(0, *ary, a: ary.pop))
+ end
+
+ def test_call_splat_kw_splat_order
+ b = {}
+ ary = [1, 2, b]
+ assert_equal([1, 2, b], aaa(*ary, **ary.pop))
+ ary = [1, 2, b]
+ assert_equal([0, 1, 2, b], aaa(0, *ary, **ary.pop))
+ end
+
+ def test_call_args_splat_with_nonhash_keyword_splat
+ o = Object.new
+ def o.to_hash; {a: 1} end
+ def self.f(*a, **kw)
+ kw
+ end
+ assert_equal Hash, f(*[], **o).class
+ end
+
+ def test_call_args_splat_with_pos_arg_kw_splat_is_not_mutable
+ o = Object.new
+ def o.foo(a, **h)= h[:splat_modified] = true
+
+ a = []
+ b = {splat_modified: false}
+
+ o.foo(*a, :x, **b)
+
+ assert_equal({splat_modified: false}, b)
+ end
+
+ def test_kwsplat_block_eval_order
+ def self.t(**kw, &b) [kw, b] end
+
+ pr = ->{}
+ h = {a: pr}
+ a = []
+
+ ary = t(**h, &h.delete(:a))
+ assert_equal([{a: pr}, pr], ary)
+
+ h = {a: pr}
+ ary = t(*a, **h, &h.delete(:a))
+ assert_equal([{a: pr}, pr], ary)
+ end
+
+ def test_kwsplat_block_order
+ o = Object.new
+ ary = []
+ o.define_singleton_method(:to_a) {ary << :to_a; []}
+ o.define_singleton_method(:to_hash) {ary << :to_hash; {}}
+ o.define_singleton_method(:to_proc) {ary << :to_proc; lambda{}}
+
+ def self.t(...) end
+
+ t(**o, &o)
+ assert_equal([:to_hash, :to_proc], ary)
+
+ ary.clear
+ t(*o, **o, &o)
+ assert_equal([:to_a, :to_hash, :to_proc], ary)
+ end
+
+ def test_kwsplat_block_order_super
+ def self.t(splat)
+ o = Object.new
+ ary = []
+ o.define_singleton_method(:to_a) {ary << :to_a; []}
+ o.define_singleton_method(:to_hash) {ary << :to_hash; {}}
+ o.define_singleton_method(:to_proc) {ary << :to_proc; lambda{}}
+ if splat
+ super(*o, **o, &o)
+ else
+ super(**o, &o)
+ end
+ ary
+ end
+ extend Module.new{def t(...) end}
+
+ assert_equal([:to_hash, :to_proc], t(false))
+ assert_equal([:to_a, :to_hash, :to_proc], t(true))
+ end
+
+ OVER_STACK_LEN = (ENV['RUBY_OVER_STACK_LEN'] || 150).to_i # Greater than VM_ARGC_STACK_MAX
+ OVER_STACK_ARGV = OVER_STACK_LEN.times.to_a.freeze
+
+ def test_call_cfunc_splat_large_array_bug_4040
+ a = OVER_STACK_ARGV
+
+ assert_equal(a, [].push(*a))
+ assert_equal(a, [].push(a[0], *a[1..]))
+ assert_equal(a, [].push(a[0], a[1], *a[2..]))
+ assert_equal(a, [].push(*a[0..1], *a[2..]))
+ assert_equal(a, [].push(*a[...-1], a[-1]))
+ assert_equal(a, [].push(a[0], *a[1...-1], a[-1]))
+ assert_equal(a, [].push(a[0], a[1], *a[2...-1], a[-1]))
+ assert_equal(a, [].push(*a[0..1], *a[2...-1], a[-1]))
+ assert_equal(a, [].push(*a[...-2], a[-2], a[-1]))
+ assert_equal(a, [].push(a[0], *a[1...-2], a[-2], a[-1]))
+ assert_equal(a, [].push(a[0], a[1], *a[2...-2], a[-2], a[-1]))
+ assert_equal(a, [].push(*a[0..1], *a[2...-2], a[-2], a[-1]))
+
+ kw = {x: 1}
+ a_kw = a + [kw]
+
+ assert_equal(a_kw, [].push(*a, **kw))
+ assert_equal(a_kw, [].push(a[0], *a[1..], **kw))
+ assert_equal(a_kw, [].push(a[0], a[1], *a[2..], **kw))
+ assert_equal(a_kw, [].push(*a[0..1], *a[2..], **kw))
+ assert_equal(a_kw, [].push(*a[...-1], a[-1], **kw))
+ assert_equal(a_kw, [].push(a[0], *a[1...-1], a[-1], **kw))
+ assert_equal(a_kw, [].push(a[0], a[1], *a[2...-1], a[-1], **kw))
+ assert_equal(a_kw, [].push(*a[0..1], *a[2...-1], a[-1], **kw))
+ assert_equal(a_kw, [].push(*a[...-2], a[-2], a[-1], **kw))
+ assert_equal(a_kw, [].push(a[0], *a[1...-2], a[-2], a[-1], **kw))
+ assert_equal(a_kw, [].push(a[0], a[1], *a[2...-2], a[-2], a[-1], **kw))
+ assert_equal(a_kw, [].push(*a[0..1], *a[2...-2], a[-2], a[-1], **kw))
+
+ assert_equal(a_kw, [].push(*a, x: 1))
+ assert_equal(a_kw, [].push(a[0], *a[1..], x: 1))
+ assert_equal(a_kw, [].push(a[0], a[1], *a[2..], x: 1))
+ assert_equal(a_kw, [].push(*a[0..1], *a[2..], x: 1))
+ assert_equal(a_kw, [].push(*a[...-1], a[-1], x: 1))
+ assert_equal(a_kw, [].push(a[0], *a[1...-1], a[-1], x: 1))
+ assert_equal(a_kw, [].push(a[0], a[1], *a[2...-1], a[-1], x: 1))
+ assert_equal(a_kw, [].push(*a[0..1], *a[2...-1], a[-1], x: 1))
+ assert_equal(a_kw, [].push(*a[...-2], a[-2], a[-1], x: 1))
+ assert_equal(a_kw, [].push(a[0], *a[1...-2], a[-2], a[-1], x: 1))
+ assert_equal(a_kw, [].push(a[0], a[1], *a[2...-2], a[-2], a[-1], x: 1))
+ assert_equal(a_kw, [].push(*a[0..1], *a[2...-2], a[-2], a[-1], x: 1))
+
+ a_kw[-1][:y] = 2
+ kw = {y: 2}
+
+ assert_equal(a_kw, [].push(*a, x: 1, **kw))
+ assert_equal(a_kw, [].push(a[0], *a[1..], x: 1, **kw))
+ assert_equal(a_kw, [].push(a[0], a[1], *a[2..], x: 1, **kw))
+ assert_equal(a_kw, [].push(*a[0..1], *a[2..], x: 1, **kw))
+ assert_equal(a_kw, [].push(*a[...-1], a[-1], x: 1, **kw))
+ assert_equal(a_kw, [].push(a[0], *a[1...-1], a[-1], x: 1, **kw))
+ assert_equal(a_kw, [].push(a[0], a[1], *a[2...-1], a[-1], x: 1, **kw))
+ assert_equal(a_kw, [].push(*a[0..1], *a[2...-1], a[-1], x: 1, **kw))
+ assert_equal(a_kw, [].push(*a[...-2], a[-2], a[-1], x: 1, **kw))
+ assert_equal(a_kw, [].push(a[0], *a[1...-2], a[-2], a[-1], x: 1, **kw))
+ assert_equal(a_kw, [].push(a[0], a[1], *a[2...-2], a[-2], a[-1], x: 1, **kw))
+ assert_equal(a_kw, [].push(*a[0..1], *a[2...-2], a[-2], a[-1], x: 1, **kw))
+
+ kw = {}
+
+ assert_equal(a, [].push(*a, **kw))
+ assert_equal(a, [].push(a[0], *a[1..], **kw))
+ assert_equal(a, [].push(a[0], a[1], *a[2..], **kw))
+ assert_equal(a, [].push(*a[0..1], *a[2..], **kw))
+ assert_equal(a, [].push(*a[...-1], a[-1], **kw))
+ assert_equal(a, [].push(a[0], *a[1...-1], a[-1], **kw))
+ assert_equal(a, [].push(a[0], a[1], *a[2...-1], a[-1], **kw))
+ assert_equal(a, [].push(*a[0..1], *a[2...-1], a[-1], **kw))
+ assert_equal(a, [].push(*a[...-2], a[-2], a[-1], **kw))
+ assert_equal(a, [].push(a[0], *a[1...-2], a[-2], a[-1], **kw))
+ assert_equal(a, [].push(a[0], a[1], *a[2...-2], a[-2], a[-1], **kw))
+ assert_equal(a, [].push(*a[0..1], *a[2...-2], a[-2], a[-1], **kw))
+
+ a_kw = a + [Hash.ruby2_keywords_hash({})]
+ assert_equal(a, [].push(*a_kw))
+
+ # Single test with value that would cause SystemStackError.
+ # Not all tests use such a large array to reduce testing time.
+ assert_equal(1380888, [].push(*1380888.times.to_a).size)
+ end
+
+ def test_call_iseq_large_array_splat_fail
+ def self.a; end
+ def self.b(a=1); end
+ def self.c(k: 1); end
+ def self.d(**kw); end
+ def self.e(k: 1, **kw); end
+ def self.f(a=1, k: 1); end
+ def self.g(a=1, **kw); end
+ def self.h(a=1, k: 1, **kw); end
+
+ (:a..:h).each do |meth|
+ assert_raise_with_message(ArgumentError, /wrong number of arguments \(given #{OVER_STACK_LEN}, expected 0(\.\.[12])?\)/) do
+ instance_eval("#{meth}(*OVER_STACK_ARGV)", __FILE__, __LINE__)
+ end
+ end
+ end
+
+ def test_call_iseq_large_array_splat_pass
+ def self.a(*a); a.length end
+ assert_equal OVER_STACK_LEN, a(*OVER_STACK_ARGV)
+
+ def self.b(_, *a); a.length end
+ assert_equal (OVER_STACK_LEN - 1), b(*OVER_STACK_ARGV)
+
+ def self.c(_, *a, _); a.length end
+ assert_equal (OVER_STACK_LEN - 2), c(*OVER_STACK_ARGV)
+
+ def self.d(b=1, *a); a.length end
+ assert_equal (OVER_STACK_LEN - 1), d(*OVER_STACK_ARGV)
+
+ def self.e(b=1, *a, _); a.length end
+ assert_equal (OVER_STACK_LEN - 2), e(*OVER_STACK_ARGV)
+
+ def self.f(b, *a); a.length end
+ assert_equal (OVER_STACK_LEN - 1), f(*OVER_STACK_ARGV)
+
+ def self.g(*a, k: 1); a.length end
+ assert_equal OVER_STACK_LEN, g(*OVER_STACK_ARGV)
+
+ def self.h(*a, **kw); a.length end
+ assert_equal OVER_STACK_LEN, h(*OVER_STACK_ARGV)
+
+ def self.i(*a, k: 1, **kw); a.length end
+ assert_equal OVER_STACK_LEN, i(*OVER_STACK_ARGV)
+
+ def self.j(b=1, *a, k: 1); a.length end
+ assert_equal (OVER_STACK_LEN - 1), j(*OVER_STACK_ARGV)
+
+ def self.k(b=1, *a, **kw); a.length end
+ assert_equal (OVER_STACK_LEN - 1), k(*OVER_STACK_ARGV)
+
+ def self.l(b=1, *a, k: 1, **kw); a.length end
+ assert_equal (OVER_STACK_LEN - 1), l(*OVER_STACK_ARGV)
+
+ def self.m(b=1, *a, _, k: 1); a.length end
+ assert_equal (OVER_STACK_LEN - 2), m(*OVER_STACK_ARGV)
+
+ def self.n(b=1, *a, _, **kw); a.length end
+ assert_equal (OVER_STACK_LEN - 2), n(*OVER_STACK_ARGV)
+
+ def self.o(b=1, *a, _, k: 1, **kw); a.length end
+ assert_equal (OVER_STACK_LEN - 2), o(*OVER_STACK_ARGV)
+ end
+
+ def test_call_iseq_large_array_splat_with_large_number_of_parameters
+ args = OVER_STACK_ARGV.map{|i| "a#{i}"}.join(',')
+ args1 = (OVER_STACK_LEN-1).times.map{|i| "a#{i}"}.join(',')
+
+ singleton_class.class_eval("def a(#{args}); [#{args}] end")
+ assert_equal OVER_STACK_ARGV, a(*OVER_STACK_ARGV)
+
+ singleton_class.class_eval("def b(#{args}, b=0); [#{args}, b] end")
+ assert_equal(OVER_STACK_ARGV + [0], b(*OVER_STACK_ARGV))
+
+ singleton_class.class_eval("def c(#{args}, *b); [#{args}, b] end")
+ assert_equal(OVER_STACK_ARGV + [[]], c(*OVER_STACK_ARGV))
+
+ singleton_class.class_eval("def d(#{args1}, *b); [#{args1}, b] end")
+ assert_equal(OVER_STACK_ARGV[0...-1] + [[OVER_STACK_ARGV.last]], d(*OVER_STACK_ARGV))
+ end if OVER_STACK_LEN < 200
+
+ def test_call_proc_large_array_splat_pass
+ [
+ proc{0} ,
+ proc{|a=1|a},
+ proc{|k: 1|0},
+ proc{|**kw| 0},
+ proc{|k: 1, **kw| 0},
+ proc{|a=1, k: 1| a},
+ proc{|a=1, **kw| a},
+ proc{|a=1, k: 1, **kw| a},
+ ].each do |l|
+ assert_equal 0, l.call(*OVER_STACK_ARGV)
+ end
+
+ assert_equal OVER_STACK_LEN, proc{|*a| a.length}.(*OVER_STACK_ARGV)
+ assert_equal (OVER_STACK_LEN - 1), proc{|_, *a| a.length}.(*OVER_STACK_ARGV)
+ assert_equal (OVER_STACK_LEN - 2), proc{|_, *a, _| a.length}.(*OVER_STACK_ARGV)
+ assert_equal (OVER_STACK_LEN - 1), proc{|b=1, *a| a.length}.(*OVER_STACK_ARGV)
+ assert_equal (OVER_STACK_LEN - 2), proc{|b=1, *a, _| a.length}.(*OVER_STACK_ARGV)
+ assert_equal (OVER_STACK_LEN - 1), proc{|b=1, *a| a.length}.(*OVER_STACK_ARGV)
+ assert_equal OVER_STACK_LEN, proc{|*a, k: 1| a.length}.(*OVER_STACK_ARGV)
+ assert_equal OVER_STACK_LEN, proc{|*a, **kw| a.length}.(*OVER_STACK_ARGV)
+ assert_equal OVER_STACK_LEN, proc{|*a, k: 1, **kw| a.length}.(*OVER_STACK_ARGV)
+ assert_equal (OVER_STACK_LEN - 1), proc{|b=1, *a, k: 1| a.length}.(*OVER_STACK_ARGV)
+ assert_equal (OVER_STACK_LEN - 1), proc{|b=1, *a, **kw| a.length}.(*OVER_STACK_ARGV)
+ assert_equal (OVER_STACK_LEN - 1), proc{|b=1, *a, k: 1, **kw| a.length}.(*OVER_STACK_ARGV)
+ assert_equal (OVER_STACK_LEN - 2), proc{|b=1, *a, _, k: 1| a.length}.(*OVER_STACK_ARGV)
+ assert_equal (OVER_STACK_LEN - 2), proc{|b=1, *a, _, **kw| a.length}.(*OVER_STACK_ARGV)
+ assert_equal (OVER_STACK_LEN - 2), proc{|b=1, *a, _, k: 1, **kw| a.length}.(*OVER_STACK_ARGV)
+ end
+
+ def test_call_proc_large_array_splat_with_large_number_of_parameters
+ args = OVER_STACK_ARGV.map{|i| "a#{i}"}.join(',')
+ args1 = (OVER_STACK_LEN-1).times.map{|i| "a#{i}"}.join(',')
+
+ l = instance_eval("proc{|#{args}| [#{args}]}")
+ assert_equal OVER_STACK_ARGV, l.(*OVER_STACK_ARGV)
+
+ l = instance_eval("proc{|#{args}, b| [#{args}, b]}")
+ assert_equal(OVER_STACK_ARGV + [nil], l.(*OVER_STACK_ARGV))
+
+ l = instance_eval("proc{|#{args1}| [#{args1}]}")
+ assert_equal(OVER_STACK_ARGV[0...-1], l.(*OVER_STACK_ARGV))
+
+ l = instance_eval("proc{|#{args}, *b| [#{args}, b]}")
+ assert_equal(OVER_STACK_ARGV + [[]], l.(*OVER_STACK_ARGV))
+
+ l = instance_eval("proc{|#{args1}, *b| [#{args1}, b]}")
+ assert_equal(OVER_STACK_ARGV[0...-1] + [[OVER_STACK_ARGV.last]], l.(*OVER_STACK_ARGV))
+
+ l = instance_eval("proc{|#{args}, b, *c| [#{args}, b, c]}")
+ assert_equal(OVER_STACK_ARGV + [nil, []], l.(*OVER_STACK_ARGV))
+
+ l = instance_eval("proc{|#{args}, b, *c, d| [#{args}, b, c, d]}")
+ assert_equal(OVER_STACK_ARGV + [nil, [], nil], l.(*OVER_STACK_ARGV))
+ end if OVER_STACK_LEN < 200
+
+ def test_call_lambda_large_array_splat_fail
+ [
+ ->{} ,
+ ->(a=1){},
+ ->(k: 1){},
+ ->(**kw){},
+ ->(k: 1, **kw){},
+ ->(a=1, k: 1){},
+ ->(a=1, **kw){},
+ ->(a=1, k: 1, **kw){},
+ ].each do |l|
+ assert_raise_with_message(ArgumentError, /wrong number of arguments \(given #{OVER_STACK_LEN}, expected 0(\.\.[12])?\)/) do
+ l.call(*OVER_STACK_ARGV)
+ end
+ end
+ end
+
+ def test_call_lambda_large_array_splat_pass
+ assert_equal OVER_STACK_LEN, ->(*a){a.length}.(*OVER_STACK_ARGV)
+ assert_equal (OVER_STACK_LEN - 1), ->(_, *a){a.length}.(*OVER_STACK_ARGV)
+ assert_equal (OVER_STACK_LEN - 2), ->(_, *a, _){a.length}.(*OVER_STACK_ARGV)
+ assert_equal (OVER_STACK_LEN - 1), ->(b=1, *a){a.length}.(*OVER_STACK_ARGV)
+ assert_equal (OVER_STACK_LEN - 2), ->(b=1, *a, _){a.length}.(*OVER_STACK_ARGV)
+ assert_equal (OVER_STACK_LEN - 1), ->(b, *a){a.length}.(*OVER_STACK_ARGV)
+ assert_equal OVER_STACK_LEN, ->(*a, k: 1){a.length}.(*OVER_STACK_ARGV)
+ assert_equal OVER_STACK_LEN, ->(*a, **kw){a.length}.(*OVER_STACK_ARGV)
+ assert_equal OVER_STACK_LEN, ->(*a, k: 1, **kw){a.length}.(*OVER_STACK_ARGV)
+ assert_equal (OVER_STACK_LEN - 1), ->(b=1, *a, k: 1){a.length}.(*OVER_STACK_ARGV)
+ assert_equal (OVER_STACK_LEN - 1), ->(b=1, *a, **kw){a.length}.(*OVER_STACK_ARGV)
+ assert_equal (OVER_STACK_LEN - 1), ->(b=1, *a, k: 1, **kw){a.length}.(*OVER_STACK_ARGV)
+ assert_equal (OVER_STACK_LEN - 2), ->(b=1, *a, _, k: 1){a.length}.(*OVER_STACK_ARGV)
+ assert_equal (OVER_STACK_LEN - 2), ->(b=1, *a, _, **kw){a.length}.(*OVER_STACK_ARGV)
+ assert_equal (OVER_STACK_LEN - 2), ->(b=1, *a, _, k: 1, **kw){a.length}.(*OVER_STACK_ARGV)
+ end
+
+ def test_call_yield_block_large_array_splat_pass
+ def self.a
+ yield(*OVER_STACK_ARGV)
+ end
+
+ [
+ proc{0} ,
+ proc{|a=1|a},
+ proc{|k: 1|0},
+ proc{|**kw| 0},
+ proc{|k: 1, **kw| 0},
+ proc{|a=1, k: 1| a},
+ proc{|a=1, **kw| a},
+ proc{|a=1, k: 1, **kw| a},
+ ].each do |l|
+ assert_equal 0, a(&l)
+ end
+
+ assert_equal OVER_STACK_LEN, a{|*a| a.length}
+ assert_equal (OVER_STACK_LEN - 1), a{|_, *a| a.length}
+ assert_equal (OVER_STACK_LEN - 2), a{|_, *a, _| a.length}
+ assert_equal (OVER_STACK_LEN - 1), a{|b=1, *a| a.length}
+ assert_equal (OVER_STACK_LEN - 2), a{|b=1, *a, _| a.length}
+ assert_equal (OVER_STACK_LEN - 1), a{|b, *a| a.length}
+ assert_equal OVER_STACK_LEN, a{|*a, k: 1| a.length}
+ assert_equal OVER_STACK_LEN, a{|*a, **kw| a.length}
+ assert_equal OVER_STACK_LEN, a{|*a, k: 1, **kw| a.length}
+ assert_equal (OVER_STACK_LEN - 1), a{|b=1, *a, k: 1| a.length}
+ assert_equal (OVER_STACK_LEN - 1), a{|b=1, *a, **kw| a.length}
+ assert_equal (OVER_STACK_LEN - 1), a{|b=1, *a, k: 1, **kw| a.length}
+ assert_equal (OVER_STACK_LEN - 2), a{|b=1, *a, _, k: 1| a.length}
+ assert_equal (OVER_STACK_LEN - 2), a{|b=1, *a, _, **kw| a.length}
+ assert_equal (OVER_STACK_LEN - 2), a{|b=1, *a, _, k: 1, **kw| a.length}
+ end
+
+ def test_call_yield_large_array_splat_with_large_number_of_parameters
+ def self.a
+ yield(*OVER_STACK_ARGV)
+ end
+
+ args = OVER_STACK_ARGV.map{|i| "a#{i}"}.join(',')
+ args1 = (OVER_STACK_LEN-1).times.map{|i| "a#{i}"}.join(',')
+
+ assert_equal OVER_STACK_ARGV, instance_eval("a{|#{args}| [#{args}]}", __FILE__, __LINE__)
+ assert_equal(OVER_STACK_ARGV + [nil], instance_eval("a{|#{args}, b| [#{args}, b]}", __FILE__, __LINE__))
+ assert_equal(OVER_STACK_ARGV[0...-1], instance_eval("a{|#{args1}| [#{args1}]}", __FILE__, __LINE__))
+ assert_equal(OVER_STACK_ARGV + [[]], instance_eval("a{|#{args}, *b| [#{args}, b]}", __FILE__, __LINE__))
+ assert_equal(OVER_STACK_ARGV[0...-1] + [[OVER_STACK_ARGV.last]], instance_eval("a{|#{args1}, *b| [#{args1}, b]}", __FILE__, __LINE__))
+ assert_equal(OVER_STACK_ARGV + [nil, []], instance_eval("a{|#{args}, b, *c| [#{args}, b, c]}", __FILE__, __LINE__))
+ assert_equal(OVER_STACK_ARGV + [nil, [], nil], instance_eval("a{|#{args}, b, *c, d| [#{args}, b, c, d]}", __FILE__, __LINE__))
+ end if OVER_STACK_LEN < 200
+
+ def test_call_yield_lambda_large_array_splat_fail
+ def self.a
+ yield(*OVER_STACK_ARGV)
+ end
+ [
+ ->{} ,
+ ->(a=1){},
+ ->(k: 1){},
+ ->(**kw){},
+ ->(k: 1, **kw){},
+ ->(a=1, k: 1){},
+ ->(a=1, **kw){},
+ ->(a=1, k: 1, **kw){},
+ ].each do |l|
+ assert_raise_with_message(ArgumentError, /wrong number of arguments \(given #{OVER_STACK_LEN}, expected 0(\.\.[12])?\)/) do
+ a(&l)
+ end
+ end
+ end
+
+ def test_call_yield_lambda_large_array_splat_pass
+ def self.a
+ yield(*OVER_STACK_ARGV)
+ end
+
+ assert_equal OVER_STACK_LEN, a(&->(*a){a.length})
+ assert_equal (OVER_STACK_LEN - 1), a(&->(_, *a){a.length})
+ assert_equal (OVER_STACK_LEN - 2), a(&->(_, *a, _){a.length})
+ assert_equal (OVER_STACK_LEN - 1), a(&->(b=1, *a){a.length})
+ assert_equal (OVER_STACK_LEN - 2), a(&->(b=1, *a, _){a.length})
+ assert_equal (OVER_STACK_LEN - 1), a(&->(b, *a){a.length})
+ assert_equal OVER_STACK_LEN, a(&->(*a, k: 1){a.length})
+ assert_equal OVER_STACK_LEN, a(&->(*a, **kw){a.length})
+ assert_equal OVER_STACK_LEN, a(&->(*a, k: 1, **kw){a.length})
+ assert_equal (OVER_STACK_LEN - 1), a(&->(b=1, *a, k: 1){a.length})
+ assert_equal (OVER_STACK_LEN - 1), a(&->(b=1, *a, **kw){a.length})
+ assert_equal (OVER_STACK_LEN - 1), a(&->(b=1, *a, k: 1, **kw){a.length})
+ assert_equal (OVER_STACK_LEN - 2), a(&->(b=1, *a, _, k: 1){a.length})
+ assert_equal (OVER_STACK_LEN - 2), a(&->(b=1, *a, _, **kw){a.length})
+ assert_equal (OVER_STACK_LEN - 2), a(&->(b=1, *a, _, k: 1, **kw){a.length})
+ end
+
+ def test_call_send_iseq_large_array_splat_fail
+ def self.a; end
+ def self.b(a=1); end
+ def self.c(k: 1); end
+ def self.d(**kw); end
+ def self.e(k: 1, **kw); end
+ def self.f(a=1, k: 1); end
+ def self.g(a=1, **kw); end
+ def self.h(a=1, k: 1, **kw); end
+
+ (:a..:h).each do |meth|
+ assert_raise_with_message(ArgumentError, /wrong number of arguments \(given #{OVER_STACK_LEN}, expected 0(\.\.[12])?\)/) do
+ send(meth, *OVER_STACK_ARGV)
+ end
+ end
+ end
+
+ def test_call_send_iseq_large_array_splat_pass
+ def self.a(*a); a.length end
+ assert_equal OVER_STACK_LEN, send(:a, *OVER_STACK_ARGV)
+
+ def self.b(_, *a); a.length end
+ assert_equal (OVER_STACK_LEN - 1), send(:b, *OVER_STACK_ARGV)
+
+ def self.c(_, *a, _); a.length end
+ assert_equal (OVER_STACK_LEN - 2), send(:c, *OVER_STACK_ARGV)
+
+ def self.d(b=1, *a); a.length end
+ assert_equal (OVER_STACK_LEN - 1), send(:d, *OVER_STACK_ARGV)
+
+ def self.e(b=1, *a, _); a.length end
+ assert_equal (OVER_STACK_LEN - 2), send(:e, *OVER_STACK_ARGV)
+
+ def self.f(b, *a); a.length end
+ assert_equal (OVER_STACK_LEN - 1), send(:f, *OVER_STACK_ARGV)
+
+ def self.g(*a, k: 1); a.length end
+ assert_equal OVER_STACK_LEN, send(:g, *OVER_STACK_ARGV)
+
+ def self.h(*a, **kw); a.length end
+ assert_equal OVER_STACK_LEN, send(:h, *OVER_STACK_ARGV)
+
+ def self.i(*a, k: 1, **kw); a.length end
+ assert_equal OVER_STACK_LEN, send(:i, *OVER_STACK_ARGV)
+
+ def self.j(b=1, *a, k: 1); a.length end
+ assert_equal (OVER_STACK_LEN - 1), send(:j, *OVER_STACK_ARGV)
+
+ def self.k(b=1, *a, **kw); a.length end
+ assert_equal (OVER_STACK_LEN - 1), send(:k, *OVER_STACK_ARGV)
+
+ def self.l(b=1, *a, k: 1, **kw); a.length end
+ assert_equal (OVER_STACK_LEN - 1), send(:l, *OVER_STACK_ARGV)
+
+ def self.m(b=1, *a, _, k: 1); a.length end
+ assert_equal (OVER_STACK_LEN - 2), send(:m, *OVER_STACK_ARGV)
+
+ def self.n(b=1, *a, _, **kw); a.length end
+ assert_equal (OVER_STACK_LEN - 2), send(:n, *OVER_STACK_ARGV)
+
+ def self.o(b=1, *a, _, k: 1, **kw); a.length end
+ assert_equal (OVER_STACK_LEN - 2), send(:o, *OVER_STACK_ARGV)
+ end
+
+ def test_call_send_iseq_large_array_splat_with_large_number_of_parameters
+ args = OVER_STACK_ARGV.map{|i| "a#{i}"}.join(',')
+ args1 = (OVER_STACK_LEN-1).times.map{|i| "a#{i}"}.join(',')
+
+ singleton_class.class_eval("def a(#{args}); [#{args}] end")
+ assert_equal OVER_STACK_ARGV, send(:a, *OVER_STACK_ARGV)
+
+ singleton_class.class_eval("def b(#{args}, b=0); [#{args}, b] end")
+ assert_equal(OVER_STACK_ARGV + [0], send(:b, *OVER_STACK_ARGV))
+
+ singleton_class.class_eval("def c(#{args}, *b); [#{args}, b] end")
+ assert_equal(OVER_STACK_ARGV + [[]], send(:c, *OVER_STACK_ARGV))
+
+ singleton_class.class_eval("def d(#{args1}, *b); [#{args1}, b] end")
+ assert_equal(OVER_STACK_ARGV[0...-1] + [[OVER_STACK_ARGV.last]], send(:d, *OVER_STACK_ARGV))
+ end if OVER_STACK_LEN < 200
+
+ def test_call_send_cfunc_large_array_splat_fail
+ assert_raise_with_message(ArgumentError, "wrong number of arguments (given #{OVER_STACK_LEN}, expected 0)") do
+ send(:object_id, *OVER_STACK_ARGV)
+ end
+ end
+
+ def test_call_send_cfunc_large_array_splat_pass
+ assert_equal OVER_STACK_LEN, [].send(:push, *OVER_STACK_ARGV).length
+ end
+
+ def test_call_attr_reader_large_array_splat_fail
+ singleton_class.send(:attr_reader, :a)
+ assert_raise_with_message(ArgumentError, "wrong number of arguments (given #{OVER_STACK_LEN}, expected 0)") do
+ a(*OVER_STACK_ARGV)
+ end
+ assert_raise_with_message(ArgumentError, "wrong number of arguments (given #{OVER_STACK_LEN}, expected 0)") do
+ send(:a, *OVER_STACK_ARGV)
+ end
+ end
+
+ def test_call_attr_writer_large_array_splat_fail
+ singleton_class.send(:attr_writer, :a)
+ singleton_class.send(:alias_method, :a, :a=)
+
+ assert_raise_with_message(ArgumentError, "wrong number of arguments (given #{OVER_STACK_LEN}, expected 1)") do
+ a(*OVER_STACK_ARGV)
+ end
+ assert_raise_with_message(ArgumentError, "wrong number of arguments (given #{OVER_STACK_LEN}, expected 1)") do
+ send(:a, *OVER_STACK_ARGV)
+ end
+ end
+
+ def test_call_struct_aref_large_array_splat_fail
+ s = Struct.new(:a).new
+ assert_raise_with_message(ArgumentError, "wrong number of arguments (given #{OVER_STACK_LEN}, expected 0)") do
+ s.a(*OVER_STACK_ARGV)
+ end
+ assert_raise_with_message(ArgumentError, "wrong number of arguments (given #{OVER_STACK_LEN}, expected 0)") do
+ s.send(:a, *OVER_STACK_ARGV)
+ end
+ end
+
+ def test_call_struct_aset_large_array_splat_fail
+ s = Struct.new(:a) do
+ alias b a=
+ end.new
+ assert_raise_with_message(ArgumentError, "wrong number of arguments (given #{OVER_STACK_LEN}, expected 1)") do
+ s.b(*OVER_STACK_ARGV)
+ end
+ assert_raise_with_message(ArgumentError, "wrong number of arguments (given #{OVER_STACK_LEN}, expected 1)") do
+ s.send(:b, *OVER_STACK_ARGV)
+ end
+ end
+
+ def test_call_alias_large_array_splat
+ c = Class.new do
+ def a; end
+ def c(*a); a.length end
+ attr_accessor :e
+ end
+ sc = Class.new(c) do
+ alias b a
+ alias d c
+ alias f e
+ alias g e=
+ end
+
+ obj = sc.new
+ assert_raise_with_message(ArgumentError, "wrong number of arguments (given #{OVER_STACK_LEN}, expected 0)") do
+ obj.b(*OVER_STACK_ARGV)
+ end
+ assert_raise_with_message(ArgumentError, "wrong number of arguments (given #{OVER_STACK_LEN}, expected 0)") do
+ obj.f(*OVER_STACK_ARGV)
+ end
+ assert_raise_with_message(ArgumentError, "wrong number of arguments (given #{OVER_STACK_LEN}, expected 1)") do
+ obj.g(*OVER_STACK_ARGV)
+ end
+
+ assert_equal OVER_STACK_LEN, obj.d(*OVER_STACK_ARGV)
+ end
+
+ def test_call_zsuper_large_array_splat
+ c = Class.new do
+ private
+ def a; end
+ def c(*a); a.length end
+ attr_reader :e
+ end
+ sc = Class.new(c) do
+ public :a
+ public :c
+ public :e
+ end
+
+ obj = sc.new
+ assert_raise_with_message(ArgumentError, "wrong number of arguments (given #{OVER_STACK_LEN}, expected 0)") do
+ obj.a(*OVER_STACK_ARGV)
+ end
+ assert_raise_with_message(ArgumentError, "wrong number of arguments (given #{OVER_STACK_LEN}, expected 0)") do
+ obj.e(*OVER_STACK_ARGV)
+ end
+
+ assert_equal OVER_STACK_LEN, obj.c(*OVER_STACK_ARGV)
+ end
+
+ class RefinedModuleLargeArrayTest
+ c = self
+ using(Module.new do
+ refine c do
+ def a; end
+ def c(*a) a.length end
+ attr_reader :e
+ end
+ end)
+
+ def b
+ a(*OVER_STACK_ARGV)
+ end
+
+ def d
+ c(*OVER_STACK_ARGV)
+ end
+
+ def f
+ e(*OVER_STACK_ARGV)
+ end
+ end
+
+ def test_call_refined_large_array_splat_fail
+ assert_raise_with_message(ArgumentError, "wrong number of arguments (given #{OVER_STACK_LEN}, expected 0)") do
+ RefinedModuleLargeArrayTest.new.b
+ end
+
+ assert_raise_with_message(ArgumentError, "wrong number of arguments (given #{OVER_STACK_LEN}, expected 0)") do
+ RefinedModuleLargeArrayTest.new.f
+ end
+ end
+
+ def test_call_refined_large_array_splat_pass
+ assert_equal OVER_STACK_LEN, RefinedModuleLargeArrayTest.new.d
+ end
+
+ def test_call_method_missing_iseq_large_array_splat_fail
+ def self.method_missing(_) end
+ assert_raise_with_message(ArgumentError, "wrong number of arguments (given #{OVER_STACK_LEN+1}, expected 1)") do
+ nonexistent_method(*OVER_STACK_ARGV)
+ end
+
+ assert_raise_with_message(ArgumentError, "wrong number of arguments (given #{OVER_STACK_LEN+1}, expected 1)") do
+ send(:nonexistent_method, *OVER_STACK_ARGV)
+ end
+
+ assert_raise_with_message(ArgumentError, "wrong number of arguments (given #{OVER_STACK_LEN+1}, expected 1)") do
+ send("nonexistent_method123", *OVER_STACK_ARGV)
+ end
+ end
+
+ def test_call_method_missing_iseq_large_array_splat_pass
+ def self.method_missing(m, *a)
+ a.length
+ end
+ assert_equal OVER_STACK_LEN, nonexistent_method(*OVER_STACK_ARGV)
+ assert_equal OVER_STACK_LEN, send(:nonexistent_method, *OVER_STACK_ARGV)
+ assert_equal OVER_STACK_LEN, send("nonexistent_method123", *OVER_STACK_ARGV)
+ end
+
+ def test_call_bmethod_large_array_splat_fail
+ define_singleton_method(:a){}
+ define_singleton_method(:b){|a=1|}
+ define_singleton_method(:c){|k: 1|}
+ define_singleton_method(:d){|**kw|}
+ define_singleton_method(:e){|k: 1, **kw|}
+ define_singleton_method(:f){|a=1, k: 1|}
+ define_singleton_method(:g){|a=1, **kw|}
+ define_singleton_method(:h){|a=1, k: 1, **kw|}
+
+ (:a..:h).each do |meth|
+ assert_raise_with_message(ArgumentError, /wrong number of arguments \(given #{OVER_STACK_LEN}, expected 0(\.\.[12])?\)/) do
+ instance_eval("#{meth}(*OVER_STACK_ARGV)", __FILE__, __LINE__)
+ end
+ end
+ end
+
+ def test_call_bmethod_large_array_splat_pass
+ define_singleton_method(:a){|*a| a.length}
+ assert_equal OVER_STACK_LEN, a(*OVER_STACK_ARGV)
+
+ define_singleton_method(:b){|_, *a| a.length}
+ assert_equal (OVER_STACK_LEN - 1), b(*OVER_STACK_ARGV)
+
+ define_singleton_method(:c){|_, *a, _| a.length}
+ assert_equal (OVER_STACK_LEN - 2), c(*OVER_STACK_ARGV)
+
+ define_singleton_method(:d){|b=1, *a| a.length}
+ assert_equal (OVER_STACK_LEN - 1), d(*OVER_STACK_ARGV)
+
+ define_singleton_method(:e){|b=1, *a, _| a.length}
+ assert_equal (OVER_STACK_LEN - 2), e(*OVER_STACK_ARGV)
+
+ define_singleton_method(:f){|b, *a| a.length}
+ assert_equal (OVER_STACK_LEN - 1), f(*OVER_STACK_ARGV)
+
+ define_singleton_method(:g){|*a, k: 1| a.length}
+ assert_equal OVER_STACK_LEN, g(*OVER_STACK_ARGV)
+
+ define_singleton_method(:h){|*a, **kw| a.length}
+ assert_equal OVER_STACK_LEN, h(*OVER_STACK_ARGV)
+
+ define_singleton_method(:i){|*a, k: 1, **kw| a.length}
+ assert_equal OVER_STACK_LEN, i(*OVER_STACK_ARGV)
+
+ define_singleton_method(:j){|b=1, *a, k: 1| a.length}
+ assert_equal (OVER_STACK_LEN - 1), j(*OVER_STACK_ARGV)
+
+ define_singleton_method(:k){|b=1, *a, **kw| a.length}
+ assert_equal (OVER_STACK_LEN - 1), k(*OVER_STACK_ARGV)
+
+ define_singleton_method(:l){|b=1, *a, k: 1, **kw| a.length}
+ assert_equal (OVER_STACK_LEN - 1), l(*OVER_STACK_ARGV)
+
+ define_singleton_method(:m){|b=1, *a, _, k: 1| a.length}
+ assert_equal (OVER_STACK_LEN - 2), m(*OVER_STACK_ARGV)
+
+ define_singleton_method(:n){|b=1, *a, _, **kw| a.length}
+ assert_equal (OVER_STACK_LEN - 2), n(*OVER_STACK_ARGV)
+
+ define_singleton_method(:o){|b=1, *a, _, k: 1, **kw| a.length}
+ assert_equal (OVER_STACK_LEN - 2), o(*OVER_STACK_ARGV)
+ end
+
+ def test_call_method_missing_bmethod_large_array_splat_fail
+ define_singleton_method(:method_missing){|_|}
+ assert_raise_with_message(ArgumentError, "wrong number of arguments (given #{OVER_STACK_LEN+1}, expected 1)") do
+ nonexistent_method(*OVER_STACK_ARGV)
+ end
+
+ assert_raise_with_message(ArgumentError, "wrong number of arguments (given #{OVER_STACK_LEN+1}, expected 1)") do
+ send(:nonexistent_method, *OVER_STACK_ARGV)
+ end
+
+ assert_raise_with_message(ArgumentError, "wrong number of arguments (given #{OVER_STACK_LEN+1}, expected 1)") do
+ send("nonexistent_method123", *OVER_STACK_ARGV)
+ end
+ end
+
+ def test_call_method_missing_bmethod_large_array_splat_pass
+ define_singleton_method(:method_missing){|_, *a| a.length}
+ assert_equal OVER_STACK_LEN, nonexistent_method(*OVER_STACK_ARGV)
+ assert_equal OVER_STACK_LEN, send(:nonexistent_method, *OVER_STACK_ARGV)
+ assert_equal OVER_STACK_LEN, send("nonexistent_method123", *OVER_STACK_ARGV)
+ end
+
+ def test_call_symproc_large_array_splat_fail
+ define_singleton_method(:a){}
+ define_singleton_method(:b){|a=1|}
+ define_singleton_method(:c){|k: 1|}
+ define_singleton_method(:d){|**kw|}
+ define_singleton_method(:e){|k: 1, **kw|}
+ define_singleton_method(:f){|a=1, k: 1|}
+ define_singleton_method(:g){|a=1, **kw|}
+ define_singleton_method(:h){|a=1, k: 1, **kw|}
+
+ (:a..:h).each do |meth|
+ assert_raise_with_message(ArgumentError, /wrong number of arguments \(given #{OVER_STACK_LEN}, expected 0(\.\.[12])?\)/) do
+ instance_eval(":#{meth}.to_proc.(self, *OVER_STACK_ARGV)", __FILE__, __LINE__)
+ end
+ end
+ end
+
+ def test_call_symproc_large_array_splat_pass
+ define_singleton_method(:a){|*a| a.length}
+ assert_equal OVER_STACK_LEN, :a.to_proc.(self, *OVER_STACK_ARGV)
+
+ define_singleton_method(:b){|_, *a| a.length}
+ assert_equal (OVER_STACK_LEN - 1), :b.to_proc.(self, *OVER_STACK_ARGV)
+
+ define_singleton_method(:c){|_, *a, _| a.length}
+ assert_equal (OVER_STACK_LEN - 2), :c.to_proc.(self, *OVER_STACK_ARGV)
+
+ define_singleton_method(:d){|b=1, *a| a.length}
+ assert_equal (OVER_STACK_LEN - 1), :d.to_proc.(self, *OVER_STACK_ARGV)
+
+ define_singleton_method(:e){|b=1, *a, _| a.length}
+ assert_equal (OVER_STACK_LEN - 2), :e.to_proc.(self, *OVER_STACK_ARGV)
+
+ define_singleton_method(:f){|b, *a| a.length}
+ assert_equal (OVER_STACK_LEN - 1), :f.to_proc.(self, *OVER_STACK_ARGV)
+
+ define_singleton_method(:g){|*a, k: 1| a.length}
+ assert_equal OVER_STACK_LEN, :g.to_proc.(self, *OVER_STACK_ARGV)
+
+ define_singleton_method(:h){|*a, **kw| a.length}
+ assert_equal OVER_STACK_LEN, :h.to_proc.(self, *OVER_STACK_ARGV)
+
+ define_singleton_method(:i){|*a, k: 1, **kw| a.length}
+ assert_equal OVER_STACK_LEN, :i.to_proc.(self, *OVER_STACK_ARGV)
+
+ define_singleton_method(:j){|b=1, *a, k: 1| a.length}
+ assert_equal (OVER_STACK_LEN - 1), :j.to_proc.(self, *OVER_STACK_ARGV)
+
+ define_singleton_method(:k){|b=1, *a, **kw| a.length}
+ assert_equal (OVER_STACK_LEN - 1), :k.to_proc.(self, *OVER_STACK_ARGV)
+
+ define_singleton_method(:l){|b=1, *a, k: 1, **kw| a.length}
+ assert_equal (OVER_STACK_LEN - 1), :l.to_proc.(self, *OVER_STACK_ARGV)
+
+ define_singleton_method(:m){|b=1, *a, _, k: 1| a.length}
+ assert_equal (OVER_STACK_LEN - 2), :m.to_proc.(self, *OVER_STACK_ARGV)
+
+ define_singleton_method(:n){|b=1, *a, _, **kw| a.length}
+ assert_equal (OVER_STACK_LEN - 2), :n.to_proc.(self, *OVER_STACK_ARGV)
+
+ define_singleton_method(:o){|b=1, *a, _, k: 1, **kw| a.length}
+ assert_equal (OVER_STACK_LEN - 2), :o.to_proc.(self, *OVER_STACK_ARGV)
+ end
+
+ def test_call_rb_call_iseq_large_array_splat_fail
+ extend Bug::Iter::Yield
+ l = ->(*a){}
+
+ def self.a; end
+ def self.b(a=1) end
+ def self.c(k: 1) end
+ def self.d(**kw) end
+ def self.e(k: 1, **kw) end
+ def self.f(a=1, k: 1) end
+ def self.g(a=1, **kw) end
+ def self.h(a=1, k: 1, **kw) end
+
+ (:a..:h).each do |meth|
+ assert_raise_with_message(ArgumentError, /wrong number of arguments \(given #{OVER_STACK_LEN}, expected 0(\.\.[12])?\)/) do
+ yield_block(meth, *OVER_STACK_ARGV, &l)
+ end
+ end
+ end
+
+ def test_call_rb_call_iseq_large_array_splat_pass
+ extend Bug::Iter::Yield
+ l = ->(*a){a.length}
+
+ def self.a(*a) a.length end
+ assert_equal OVER_STACK_LEN, yield_block(:a, *OVER_STACK_ARGV, &l)
+
+ def self.b(_, *a) a.length end
+ assert_equal (OVER_STACK_LEN - 1), yield_block(:b, *OVER_STACK_ARGV, &l)
+
+ def self.c(_, *a, _) a.length end
+ assert_equal (OVER_STACK_LEN - 2), yield_block(:c, *OVER_STACK_ARGV, &l)
+
+ def self.d(b=1, *a) a.length end
+ assert_equal (OVER_STACK_LEN - 1), yield_block(:d, *OVER_STACK_ARGV, &l)
+
+ def self.e(b=1, *a, _) a.length end
+ assert_equal (OVER_STACK_LEN - 2), yield_block(:e, *OVER_STACK_ARGV, &l)
+
+ def self.f(b, *a) a.length end
+ assert_equal (OVER_STACK_LEN - 1), yield_block(:f, *OVER_STACK_ARGV, &l)
+
+ def self.g(*a, k: 1) a.length end
+ assert_equal OVER_STACK_LEN, yield_block(:g, *OVER_STACK_ARGV, &l)
+
+ def self.h(*a, **kw) a.length end
+ assert_equal OVER_STACK_LEN, yield_block(:h, *OVER_STACK_ARGV, &l)
+
+ def self.i(*a, k: 1, **kw) a.length end
+ assert_equal OVER_STACK_LEN, yield_block(:h, *OVER_STACK_ARGV, &l)
+
+ def self.j(b=1, *a, k: 1) a.length end
+ assert_equal (OVER_STACK_LEN - 1), yield_block(:j, *OVER_STACK_ARGV, &l)
+
+ def self.k(b=1, *a, **kw) a.length end
+ assert_equal (OVER_STACK_LEN - 1), yield_block(:k, *OVER_STACK_ARGV, &l)
+
+ def self.l(b=1, *a, k: 1, **kw) a.length end
+ assert_equal (OVER_STACK_LEN - 1), yield_block(:l, *OVER_STACK_ARGV, &l)
+
+ def self.m(b=1, *a, _, k: 1) a.length end
+ assert_equal (OVER_STACK_LEN - 2), yield_block(:m, *OVER_STACK_ARGV, &l)
+
+ def self.n(b=1, *a, _, **kw) a.length end
+ assert_equal (OVER_STACK_LEN - 2), yield_block(:n, *OVER_STACK_ARGV, &l)
+
+ def self.o(b=1, *a, _, k: 1, **kw) a.length end
+ assert_equal (OVER_STACK_LEN - 2), yield_block(:o, *OVER_STACK_ARGV, &l)
+ end
+
+ def test_call_rb_call_bmethod_large_array_splat_fail
+ extend Bug::Iter::Yield
+ l = ->(*a){}
+
+ define_singleton_method(:a){||}
+ define_singleton_method(:b){|a=1|}
+ define_singleton_method(:c){|k: 1|}
+ define_singleton_method(:d){|**kw|}
+ define_singleton_method(:e){|k: 1, **kw|}
+ define_singleton_method(:f){|a=1, k: 1|}
+ define_singleton_method(:g){|a=1, **kw|}
+ define_singleton_method(:h){|a=1, k: 1, **kw|}
+
+ (:a..:h).each do |meth|
+ assert_raise_with_message(ArgumentError, /wrong number of arguments \(given #{OVER_STACK_LEN}, expected 0(\.\.[12])?\)/) do
+ yield_block(meth, *OVER_STACK_ARGV, &l)
+ end
+ end
+ end
+
+ def test_call_rb_call_bmethod_large_array_splat_pass
+ extend Bug::Iter::Yield
+ l = ->(*a){a.length}
+
+ define_singleton_method(:a){|*a| a.length}
+ assert_equal OVER_STACK_LEN, yield_block(:a, *OVER_STACK_ARGV, &l)
+
+ define_singleton_method(:b){|_, *a| a.length}
+ assert_equal (OVER_STACK_LEN - 1), yield_block(:b, *OVER_STACK_ARGV, &l)
+
+ define_singleton_method(:c){|_, *a, _| a.length}
+ assert_equal (OVER_STACK_LEN - 2), yield_block(:c, *OVER_STACK_ARGV, &l)
+
+ define_singleton_method(:d){|b=1, *a| a.length}
+ assert_equal (OVER_STACK_LEN - 1), yield_block(:d, *OVER_STACK_ARGV, &l)
+
+ define_singleton_method(:e){|b=1, *a, _| a.length}
+ assert_equal (OVER_STACK_LEN - 2), yield_block(:e, *OVER_STACK_ARGV, &l)
+
+ define_singleton_method(:f){|b, *a| a.length}
+ assert_equal (OVER_STACK_LEN - 1), yield_block(:f, *OVER_STACK_ARGV, &l)
+
+ define_singleton_method(:g){|*a, k: 1| a.length}
+ assert_equal OVER_STACK_LEN, yield_block(:g, *OVER_STACK_ARGV, &l)
+
+ define_singleton_method(:h){|*a, **kw| a.length}
+ assert_equal OVER_STACK_LEN, yield_block(:h, *OVER_STACK_ARGV, &l)
+
+ define_singleton_method(:i){|*a, k: 1, **kw| a.length}
+ assert_equal OVER_STACK_LEN, yield_block(:h, *OVER_STACK_ARGV, &l)
+
+ define_singleton_method(:j){|b=1, *a, k: 1| a.length}
+ assert_equal (OVER_STACK_LEN - 1), yield_block(:j, *OVER_STACK_ARGV, &l)
+
+ define_singleton_method(:k){|b=1, *a, **kw| a.length}
+ assert_equal (OVER_STACK_LEN - 1), yield_block(:k, *OVER_STACK_ARGV, &l)
+
+ define_singleton_method(:l){|b=1, *a, k: 1, **kw| a.length}
+ assert_equal (OVER_STACK_LEN - 1), yield_block(:l, *OVER_STACK_ARGV, &l)
+
+ define_singleton_method(:m){|b=1, *a, _, k: 1| a.length}
+ assert_equal (OVER_STACK_LEN - 2), yield_block(:m, *OVER_STACK_ARGV, &l)
+
+ define_singleton_method(:n){|b=1, *a, _, **kw| a.length}
+ assert_equal (OVER_STACK_LEN - 2), yield_block(:n, *OVER_STACK_ARGV, &l)
+
+ define_singleton_method(:o){|b=1, *a, _, k: 1, **kw| a.length}
+ assert_equal (OVER_STACK_LEN - 2), yield_block(:o, *OVER_STACK_ARGV, &l)
+ end
+
+ def test_call_ifunc_iseq_large_array_splat_fail
+ extend Bug::Iter::Yield
+ def self.a(*a)
+ yield(*a)
+ end
+ [
+ ->(){},
+ ->(a=1){},
+ ->(k: 1){},
+ ->(**kw){},
+ ->(k: 1, **kw){},
+ ->(a=1, k: 1){},
+ ->(a=1, **kw){},
+ ->(a=1, k: 1, **kw){},
+ ].each do |l|
+ assert_raise_with_message(ArgumentError, /wrong number of arguments \(given #{OVER_STACK_LEN}, expected 0(\.\.[12])?\)/) do
+ yield_block(:a, *OVER_STACK_ARGV, &l)
+ end
+ end
+ end
+
+ def test_call_ifunc_iseq_large_array_splat_pass
+ extend Bug::Iter::Yield
+ def self.a(*a)
+ yield(*a)
+ end
+
+ l = ->(*a) do a.length end
+ assert_equal OVER_STACK_LEN, yield_block(:a, *OVER_STACK_ARGV, &l)
+
+ l = ->(_, *a) do a.length end
+ assert_equal (OVER_STACK_LEN - 1), yield_block(:a, *OVER_STACK_ARGV, &l)
+
+ l = ->(_, *a, _) do a.length end
+ assert_equal (OVER_STACK_LEN - 2), yield_block(:a, *OVER_STACK_ARGV, &l)
+
+ l = ->(b=1, *a) do a.length end
+ assert_equal (OVER_STACK_LEN - 1), yield_block(:a, *OVER_STACK_ARGV, &l)
+
+ l = ->(b=1, *a, _) do a.length end
+ assert_equal (OVER_STACK_LEN - 2), yield_block(:a, *OVER_STACK_ARGV, &l)
+
+ l = ->(b, *a) do a.length end
+ assert_equal (OVER_STACK_LEN - 1), yield_block(:a, *OVER_STACK_ARGV, &l)
+
+ l = ->(*a, k: 1) do a.length end
+ assert_equal OVER_STACK_LEN, yield_block(:a, *OVER_STACK_ARGV, &l)
+
+ l = ->(*a, **kw) do a.length end
+ assert_equal OVER_STACK_LEN, yield_block(:a, *OVER_STACK_ARGV, &l)
+
+ l = ->(*a, k: 1, **kw) do a.length end
+ assert_equal OVER_STACK_LEN, yield_block(:a, *OVER_STACK_ARGV, &l)
+
+ l = ->(b=1, *a, k: 1) do a.length end
+ assert_equal (OVER_STACK_LEN - 1), yield_block(:a, *OVER_STACK_ARGV, &l)
+
+ l = ->(b=1, *a, **kw) do a.length end
+ assert_equal (OVER_STACK_LEN - 1), yield_block(:a, *OVER_STACK_ARGV, &l)
+
+ l = ->(b=1, *a, k: 1, **kw) do a.length end
+ assert_equal (OVER_STACK_LEN - 1), yield_block(:a, *OVER_STACK_ARGV, &l)
+
+ l = ->(b=1, *a, _, k: 1) do a.length end
+ assert_equal (OVER_STACK_LEN - 2), yield_block(:a, *OVER_STACK_ARGV, &l)
+
+ l = ->(b=1, *a, _, **kw) do a.length end
+ assert_equal (OVER_STACK_LEN - 2), yield_block(:a, *OVER_STACK_ARGV, &l)
+
+ l = ->(b=1, *a, _, k: 1, **kw) do a.length end
+ assert_equal (OVER_STACK_LEN - 2), yield_block(:a, *OVER_STACK_ARGV, &l)
+ end
end
diff --git a/test/ruby/test_case.rb b/test/ruby/test_case.rb
index 4a0f1bf78d..9e8502fb27 100644
--- a/test/ruby/test_case.rb
+++ b/test/ruby/test_case.rb
@@ -68,10 +68,13 @@ class TestCase < Test::Unit::TestCase
assert(false)
end
- assert_raise(NameError) do
- case
- when false, *x, false
+ begin
+ verbose_bak, $VERBOSE = $VERBOSE, nil
+ assert_raise(NameError) do
+ eval("case; when false, *x, false; end")
end
+ ensure
+ $VERBOSE = verbose_bak
end
end
diff --git a/test/ruby/test_class.rb b/test/ruby/test_class.rb
index 368c046261..456362ef21 100644
--- a/test/ruby/test_class.rb
+++ b/test/ruby/test_class.rb
@@ -96,6 +96,13 @@ class TestClass < Test::Unit::TestCase
def test_superclass_of_basicobject
assert_equal(nil, BasicObject.superclass)
+
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ module Mod end
+ BasicObject.include(Mod)
+ assert_equal(nil, BasicObject.superclass)
+ end;
end
def test_module_function
@@ -309,6 +316,7 @@ class TestClass < Test::Unit::TestCase
def test_invalid_return_from_class_definition
assert_syntax_error("class C; return; end", /Invalid return/)
+ assert_syntax_error("class << Object; return; end", /Invalid return/)
end
def test_invalid_yield_from_class_definition
@@ -355,6 +363,17 @@ class TestClass < Test::Unit::TestCase
assert_equal(42, PrivateClass.new.foo)
end
+ def test_private_const_access
+ assert_raise_with_message NameError, /uninitialized/ do
+ begin
+ eval('class ::TestClass::PrivateClass; end')
+ rescue NameError
+ end
+
+ Object.const_get "NOT_AVAILABLE_CONST_NAME_#{__LINE__}"
+ end
+ end
+
StrClone = String.clone
Class.new(StrClone)
@@ -702,9 +721,13 @@ class TestClass < Test::Unit::TestCase
assert_separately([], "#{<<~"begin;"}\n#{<<~"end;"}")
begin;
- Date = (class C\u{1f5ff}; self; end).new
+ module Bug
+ module Class
+ TestClassDefinedInC = (class C\u{1f5ff}; self; end).new
+ end
+ end
assert_raise_with_message(TypeError, /C\u{1f5ff}/) {
- require 'date'
+ require '-test-/class'
}
end;
end
@@ -737,4 +760,85 @@ class TestClass < Test::Unit::TestCase
c = Class.new.freeze
assert_same(c, Module.new.const_set(:Foo, c))
end
+
+ def test_subclasses
+ c = Class.new
+ sc = Class.new(c)
+ ssc = Class.new(sc)
+ [c, sc, ssc].each do |k|
+ k.include Module.new
+ k.new.define_singleton_method(:force_singleton_class){}
+ end
+ assert_equal([sc], c.subclasses)
+ assert_equal([ssc], sc.subclasses)
+ assert_equal([], ssc.subclasses)
+
+ object_subclasses = Object.subclasses
+ assert_include(object_subclasses, c)
+ assert_not_include(object_subclasses, sc)
+ assert_not_include(object_subclasses, ssc)
+ object_subclasses.each do |subclass|
+ assert_equal Object, subclass.superclass, "Expected #{subclass}.superclass to be Object"
+ end
+ end
+
+ def test_attached_object
+ c = Class.new
+ sc = c.singleton_class
+ obj = c.new
+
+ assert_equal(obj, obj.singleton_class.attached_object)
+ assert_equal(c, sc.attached_object)
+
+ assert_raise_with_message(TypeError, /is not a singleton class/) do
+ c.attached_object
+ end
+
+ assert_raise_with_message(TypeError, /'NilClass' is not a singleton class/) do
+ nil.singleton_class.attached_object
+ end
+
+ assert_raise_with_message(TypeError, /'FalseClass' is not a singleton class/) do
+ false.singleton_class.attached_object
+ end
+
+ assert_raise_with_message(TypeError, /'TrueClass' is not a singleton class/) do
+ true.singleton_class.attached_object
+ end
+ end
+
+ def test_subclass_gc
+ c = Class.new
+ 10_000.times do
+ cc = Class.new(c)
+ 100.times { Class.new(cc) }
+ end
+ assert(c.subclasses.size <= 10_000)
+ end
+
+ def test_subclass_gc_stress
+ 10000.times do
+ c = Class.new
+ 100.times { Class.new(c) }
+ assert(c.subclasses.size <= 100)
+ end
+ end
+
+ def test_classext_memory_leak
+ assert_no_memory_leak([], <<-PREP, <<-CODE, rss: true)
+code = proc { Class.new }
+1_000.times(&code)
+PREP
+3_000_000.times(&code)
+CODE
+ end
+
+ def test_instance_freeze_dont_freeze_the_class_bug_19164
+ klass = Class.new
+ klass.prepend(Module.new)
+
+ klass.new.freeze
+ klass.define_method(:bar) {}
+ assert_equal klass, klass.remove_method(:bar), '[Bug #19164]'
+ end
end
diff --git a/test/ruby/test_clone.rb b/test/ruby/test_clone.rb
index 321feb07c7..775c9ed848 100644
--- a/test/ruby/test_clone.rb
+++ b/test/ruby/test_clone.rb
@@ -27,6 +27,59 @@ class TestClone < Test::Unit::TestCase
assert_equal([M003, M002, M001], M003.ancestors)
end
+ def test_frozen_properties_retained_on_clone
+ obj = Object.new.freeze
+ cloned_obj = obj.clone
+
+ assert_predicate(obj, :frozen?)
+ assert_predicate(cloned_obj, :frozen?)
+ end
+
+ def test_ivar_retained_on_clone
+ obj = Object.new
+ obj.instance_variable_set(:@a, 1)
+ cloned_obj = obj.clone
+
+ assert_equal(obj.instance_variable_get(:@a), 1)
+ assert_equal(cloned_obj.instance_variable_get(:@a), 1)
+ end
+
+ def test_ivars_retained_on_extended_obj_clone
+ ivars = { :@a => 1, :@b => 2, :@c => 3, :@d => 4 }
+ obj = Object.new
+ ivars.each do |ivar_name, val|
+ obj.instance_variable_set(ivar_name, val)
+ end
+
+ cloned_obj = obj.clone
+
+ ivars.each do |ivar_name, val|
+ assert_equal(obj.instance_variable_get(ivar_name), val)
+ assert_equal(cloned_obj.instance_variable_get(ivar_name), val)
+ end
+ end
+
+ def test_frozen_properties_and_ivars_retained_on_clone_with_ivar
+ obj = Object.new
+ obj.instance_variable_set(:@a, 1)
+ obj.freeze
+
+ cloned_obj = obj.clone
+
+ assert_predicate(obj, :frozen?)
+ assert_equal(obj.instance_variable_get(:@a), 1)
+
+ assert_predicate(cloned_obj, :frozen?)
+ assert_equal(cloned_obj.instance_variable_get(:@a), 1)
+ end
+
+ def test_proc_obj_id_flag_reset
+ # [Bug #20250]
+ proc = Proc.new { }
+ proc.object_id
+ proc.clone.object_id # Would crash with RUBY_DEBUG=1
+ end
+
def test_user_flags
assert_separately([], <<-EOS)
#
diff --git a/test/ruby/test_comparable.rb b/test/ruby/test_comparable.rb
index b849217b7d..b689469d9e 100644
--- a/test/ruby/test_comparable.rb
+++ b/test/ruby/test_comparable.rb
@@ -85,7 +85,13 @@ class TestComparable < Test::Unit::TestCase
assert_equal(1, @o.clamp(1, 1))
assert_equal(@o, @o.clamp(0, 0))
- assert_raise_with_message(ArgumentError, 'min argument must be smaller than max argument') {
+ assert_equal(@o, @o.clamp(nil, 2))
+ assert_equal(-2, @o.clamp(nil, -2))
+ assert_equal(@o, @o.clamp(-2, nil))
+ assert_equal(2, @o.clamp(2, nil))
+ assert_equal(@o, @o.clamp(nil, nil))
+
+ assert_raise_with_message(ArgumentError, 'min argument must be less than or equal to max argument') {
@o.clamp(2, 1)
}
end
@@ -115,7 +121,7 @@ class TestComparable < Test::Unit::TestCase
assert_raise_with_message(*exc) {@o.clamp(-1...0)}
assert_raise_with_message(*exc) {@o.clamp(...2)}
- assert_raise_with_message(ArgumentError, 'min argument must be smaller than max argument') {
+ assert_raise_with_message(ArgumentError, 'min argument must be less than or equal to max argument') {
@o.clamp(2..1)
}
end
diff --git a/test/ruby/test_compile_prism.rb b/test/ruby/test_compile_prism.rb
new file mode 100644
index 0000000000..66986af827
--- /dev/null
+++ b/test/ruby/test_compile_prism.rb
@@ -0,0 +1,2637 @@
+# frozen_string_literal: true
+
+# This file is organized to match itemization in https://github.com/ruby/prism/issues/1335
+module Prism
+ class TestCompilePrism < Test::Unit::TestCase
+ # Subclass is used for tests which need it
+ class Subclass; end
+ ############################################################################
+ # Literals #
+ ############################################################################
+
+ def test_FalseNode
+ assert_prism_eval("false")
+ end
+
+ def test_FloatNode
+ assert_prism_eval("1.2")
+ assert_prism_eval("1.2e3")
+ assert_prism_eval("+1.2e+3")
+ assert_prism_eval("-1.2e-3")
+ end
+
+ def test_ImaginaryNode
+ assert_prism_eval("1i")
+ assert_prism_eval("+1.0i")
+ assert_prism_eval("1ri")
+ end
+
+ def test_IntegerNode
+ assert_prism_eval("1")
+ assert_prism_eval("+1")
+ assert_prism_eval("-1")
+ assert_prism_eval("0x10")
+ assert_prism_eval("0b10")
+ assert_prism_eval("0o10")
+ assert_prism_eval("010")
+ assert_prism_eval("(0o00)")
+ end
+
+ def test_NilNode
+ assert_prism_eval("nil")
+ end
+
+ def test_RationalNode
+ assert_prism_eval("1.2r")
+ assert_prism_eval("+1.2r")
+ end
+
+ def test_SelfNode
+ assert_prism_eval("self")
+ end
+
+ def test_SourceEncodingNode
+ assert_prism_eval("__ENCODING__")
+ end
+
+ def test_SourceFileNode
+ assert_prism_eval("__FILE__")
+ end
+
+ def test_SourceLineNode
+ assert_prism_eval("__LINE__", raw: true)
+ end
+
+ def test_TrueNode
+ assert_prism_eval("true")
+ end
+
+ ############################################################################
+ # Reads #
+ ############################################################################
+
+ def test_BackReferenceReadNode
+ assert_prism_eval("$+")
+ end
+
+ def test_ClassVariableReadNode
+ assert_prism_eval("class Prism::TestCompilePrism; @@pit = 1; @@pit; end")
+ end
+
+ def test_ConstantPathNode
+ assert_prism_eval("Prism::TestCompilePrism")
+ end
+
+ def test_ConstantReadNode
+ assert_prism_eval("Prism")
+ end
+
+ Z = 1
+
+ def test_DefinedNode
+ assert_prism_eval("defined? nil")
+ assert_prism_eval("defined? self")
+ assert_prism_eval("defined? true")
+ assert_prism_eval("defined? false")
+ assert_prism_eval("defined? 1")
+ assert_prism_eval("defined? 1i")
+ assert_prism_eval("defined? 1.0")
+ assert_prism_eval("defined? 1..2")
+ assert_prism_eval("defined? [A, B, C]")
+ assert_prism_eval("defined? [1, 2, 3]")
+ assert_prism_eval("defined?({ a: 1 })")
+ assert_prism_eval("defined? 'str'")
+ assert_prism_eval('defined?("#{expr}")')
+ assert_prism_eval("defined? :sym")
+ assert_prism_eval("defined? /foo/")
+ assert_prism_eval('defined?(/#{1}/)')
+ assert_prism_eval("defined? -> { 1 + 1 }")
+ assert_prism_eval("defined? a && b")
+ assert_prism_eval("defined? a || b")
+ assert_prism_eval("defined? __ENCODING__")
+ assert_prism_eval("defined? __FILE__")
+ assert_prism_eval("defined? __LINE__")
+
+ assert_prism_eval("defined? %[1,2,3]")
+ assert_prism_eval("defined? %q[1,2,3]")
+ assert_prism_eval("defined? %Q[1,2,3]")
+ assert_prism_eval("defined? %r[1,2,3]")
+ assert_prism_eval("defined? %i[1,2,3]")
+ assert_prism_eval("defined? %I[1,2,3]")
+ assert_prism_eval("defined? %w[1,2,3]")
+ assert_prism_eval("defined? %W[1,2,3]")
+ assert_prism_eval("defined? %s[1,2,3]")
+ assert_prism_eval("defined? %x[1,2,3]")
+
+ assert_prism_eval("defined? [*b]")
+ assert_prism_eval("defined? [[*1..2], 3, *4..5]")
+ assert_prism_eval("defined? [a: [:b, :c]]")
+ assert_prism_eval("defined? 1 in 1")
+
+ assert_prism_eval("defined? @a")
+ assert_prism_eval("defined? $a")
+ assert_prism_eval("defined? @@a")
+ assert_prism_eval("defined? A")
+ assert_prism_eval("defined? ::A")
+ assert_prism_eval("defined? A::B")
+ assert_prism_eval("defined? A::B::C")
+ assert_prism_eval("defined? #{self.class.name}::Z::A")
+ assert_prism_eval("defined? yield")
+ assert_prism_eval("defined? super")
+
+ assert_prism_eval("defined? X = 1")
+ assert_prism_eval("defined? X *= 1")
+ assert_prism_eval("defined? X /= 1")
+ assert_prism_eval("defined? X &= 1")
+ assert_prism_eval("defined? X ||= 1")
+
+ assert_prism_eval("defined? $1")
+ assert_prism_eval("defined? $2")
+ assert_prism_eval("defined? $`")
+ assert_prism_eval("defined? $'")
+ assert_prism_eval("defined? $+")
+
+ assert_prism_eval("defined? $X = 1")
+ assert_prism_eval("defined? $X *= 1")
+ assert_prism_eval("defined? $X /= 1")
+ assert_prism_eval("defined? $X &= 1")
+ assert_prism_eval("defined? $X ||= 1")
+
+ assert_prism_eval("defined? @@X = 1")
+ assert_prism_eval("defined? @@X *= 1")
+ assert_prism_eval("defined? @@X /= 1")
+ assert_prism_eval("defined? @@X &= 1")
+ assert_prism_eval("defined? @@X ||= 1")
+
+ assert_prism_eval("defined? @X = 1")
+ assert_prism_eval("defined? @X *= 1")
+ assert_prism_eval("defined? @X /= 1")
+ assert_prism_eval("defined? @X &= 1")
+ assert_prism_eval("defined? @X ||= 1")
+
+ assert_prism_eval("x = 1; defined? x = 1")
+ assert_prism_eval("x = 1; defined? x *= 1")
+ assert_prism_eval("x = 1; defined? x /= 1")
+ assert_prism_eval("x = 1; defined? x &= 1")
+ assert_prism_eval("x = 1; defined? x ||= 1")
+
+ assert_prism_eval("if defined? A; end")
+
+ assert_prism_eval("defined?(())")
+ assert_prism_eval("defined?(('1'))")
+
+ # method chain starting with self that's truthy
+ assert_prism_eval("defined?(self.itself.itself.itself)")
+
+ # method chain starting with self that's false (exception swallowed)
+ assert_prism_eval("defined?(self.itself.itself.neat)")
+
+ # single self with method, truthy
+ assert_prism_eval("defined?(self.itself)")
+
+ # single self with method, false
+ assert_prism_eval("defined?(self.neat!)")
+
+ # method chain implicit self that's truthy
+ assert_prism_eval("defined?(itself.itself.itself)")
+
+ # method chain implicit self that's false
+ assert_prism_eval("defined?(itself.neat.itself)")
+
+ ## single method implicit self that's truthy
+ assert_prism_eval("defined?(itself)")
+
+ ## single method implicit self that's false
+ assert_prism_eval("defined?(neatneat)")
+
+ assert_prism_eval("defined?(a(itself))")
+ assert_prism_eval("defined?(itself(itself))")
+
+ # Method chain on a constant
+ assert_prism_eval(<<~RUBY)
+ class PrismDefinedNode
+ def m1; end
+ end
+
+ defined?(PrismDefinedNode.new.m1)
+ RUBY
+
+ assert_prism_eval("defined?(next)")
+ assert_prism_eval("defined?(break)")
+ assert_prism_eval("defined?(redo)")
+ assert_prism_eval("defined?(retry)")
+
+ assert_prism_eval(<<~RUBY)
+ class PrismDefinedReturnNode
+ def self.m1; defined?(return) end
+ end
+
+ PrismDefinedReturnNode.m1
+ RUBY
+
+ assert_prism_eval("defined?(begin; 1; end)")
+
+ assert_prism_eval("defined?(defined?(a))")
+ assert_prism_eval('defined?(:"#{1}")')
+ assert_prism_eval("defined?(`echo #{1}`)")
+
+ assert_prism_eval("defined?(PrismTestSubclass.test_call_and_write_node &&= 1)")
+ assert_prism_eval("defined?(PrismTestSubclass.test_call_operator_write_node += 1)")
+ assert_prism_eval("defined?(PrismTestSubclass.test_call_or_write_node ||= 1)")
+ assert_prism_eval("defined?(Prism::CPAWN &&= 1)")
+ assert_prism_eval("defined?(Prism::CPOWN += 1)")
+ assert_prism_eval("defined?(Prism::CPOrWN ||= 1)")
+ assert_prism_eval("defined?(Prism::CPWN = 1)")
+ assert_prism_eval("defined?([0][0] &&= 1)")
+ assert_prism_eval("defined?([0][0] += 1)")
+ assert_prism_eval("defined?([0][0] ||= 1)")
+
+ assert_prism_eval("defined?(case :a; when :a; 1; else; 2; end)")
+ assert_prism_eval("defined?(case [1, 2, 3]; in [1, 2, 3]; 4; end)")
+ assert_prism_eval("defined?(class PrismClassA; end)")
+ assert_prism_eval("defined?(def prism_test_def_node; end)")
+ assert_prism_eval("defined?(for i in [1,2] do; i; end)")
+ assert_prism_eval("defined?(if true; 1; end)")
+ assert_prism_eval("defined?(/(?<foo>bar)/ =~ 'barbar')")
+ assert_prism_eval("defined?(1 => 1)")
+ assert_prism_eval("defined?(module M; end)")
+ assert_prism_eval("defined?(1.2r)")
+ assert_prism_eval("defined?(class << self; end)")
+ assert_prism_eval("defined?(while a != 1; end)")
+ assert_prism_eval("defined?(until a == 1; end)")
+ assert_prism_eval("defined?(unless true; 1; end)")
+ end
+
+ def test_GlobalVariableReadNode
+ assert_prism_eval("$pit = 1; $pit")
+ end
+
+ def test_InstanceVariableReadNode
+ assert_prism_eval("class Prism::TestCompilePrism; @pit = 1; @pit; end")
+ end
+
+ def test_LocalVariableReadNode
+ assert_prism_eval("pit = 1; pit")
+ end
+
+ def test_NumberedReferenceReadNode
+ assert_prism_eval("$1")
+ assert_prism_eval("$99999")
+ end
+
+ ############################################################################
+ # Writes #
+ ############################################################################
+
+ def test_ClassVariableAndWriteNode
+ assert_prism_eval("class Prism::TestCompilePrism; @@pit = 0; @@pit &&= 1; end")
+ end
+
+ def test_ClassVariableOperatorWriteNode
+ assert_prism_eval("class Prism::TestCompilePrism; @@pit = 0; @@pit += 1; end")
+ end
+
+ def test_ClassVariableOrWriteNode
+ assert_prism_eval("class Prism::TestCompilePrism; @@pit = 1; @@pit ||= 0; end")
+ assert_prism_eval("class Prism::TestCompilePrism; @@pit = nil; @@pit ||= 1; end")
+ end
+
+ def test_ClassVariableWriteNode
+ assert_prism_eval("class Prism::TestCompilePrism; @@pit = 1; end")
+ end
+
+ def test_ConstantAndWriteNode
+ assert_prism_eval("Constant = 1; Constant &&= 1")
+ end
+
+ def test_ConstantOperatorWriteNode
+ assert_prism_eval("Constant = 1; Constant += 1")
+ end
+
+ def test_ConstantOrWriteNode
+ assert_prism_eval("Constant = 1; Constant ||= 1")
+ end
+
+ def test_ConstantWriteNode
+ # We don't call assert_prism_eval directly in this case because we
+ # don't want to assign the constant multiple times if we run
+ # with `--repeat-count`
+ # Instead, we eval manually here, and remove the constant to
+ constant_name = "YCT"
+ source = "#{constant_name} = 1"
+ prism_eval = RubyVM::InstructionSequence.compile_prism(source).eval
+ assert_equal prism_eval, 1
+ Object.send(:remove_const, constant_name)
+ end
+
+ def test_ConstantPathWriteNode
+ assert_prism_eval("Prism::CPWN = 1")
+ assert_prism_eval("::CPWN = 1")
+ end
+
+ def test_ConstantPathAndWriteNode
+ assert_prism_eval("Prism::CPAWN = 1; Prism::CPAWN &&= 2")
+ assert_prism_eval("Prism::CPAWN &&= 1")
+ assert_prism_eval("::CPAWN = 1; ::CPAWN &&= 2")
+ end
+
+ def test_ConstantPathOrWriteNode
+ assert_prism_eval("Prism::CPOrWN = nil; Prism::CPOrWN ||= 1")
+ assert_prism_eval("Prism::CPOrWN ||= 1")
+ assert_prism_eval("::CPOrWN = nil; ::CPOrWN ||= 1")
+ end
+
+ def test_ConstantPathOperatorWriteNode
+ assert_prism_eval("Prism::CPOWN = 0; Prism::CPOWN += 1")
+ assert_prism_eval("::CPOWN = 0; ::CPOWN += 1")
+ end
+
+ def test_GlobalVariableAndWriteNode
+ assert_prism_eval("$pit = 0; $pit &&= 1")
+ end
+
+ def test_GlobalVariableOperatorWriteNode
+ assert_prism_eval("$pit = 0; $pit += 1")
+ end
+
+ def test_GlobalVariableOrWriteNode
+ assert_prism_eval("$pit ||= 1")
+ end
+
+ def test_GlobalVariableWriteNode
+ assert_prism_eval("$pit = 1")
+ end
+
+ def test_InstanceVariableAndWriteNode
+ assert_prism_eval("@pit = 0; @pit &&= 1")
+ end
+
+ def test_InstanceVariableOperatorWriteNode
+ assert_prism_eval("@pit = 0; @pit += 1")
+ end
+
+ def test_InstanceVariableOrWriteNode
+ assert_prism_eval("@pit ||= 1")
+ end
+
+ def test_InstanceVariableWriteNode
+ assert_prism_eval("class Prism::TestCompilePrism; @pit = 1; end")
+ end
+
+ def test_LocalVariableAndWriteNode
+ assert_prism_eval("pit = 0; pit &&= 1")
+ end
+
+ def test_LocalVariableOperatorWriteNode
+ assert_prism_eval("pit = 0; pit += 1")
+ end
+
+ def test_LocalVariableOrWriteNode
+ assert_prism_eval("pit ||= 1")
+ end
+
+ def test_LocalVariableWriteNode
+ assert_prism_eval("pit = 1")
+ assert_prism_eval(<<-CODE)
+ a = 0
+ [].each do
+ a = 1
+ end
+ a
+ CODE
+
+ assert_prism_eval(<<-CODE)
+ a = 1
+ d = 1
+ [1].each do
+ b = 2
+ a = 2
+ [2].each do
+ c = 3
+ d = 4
+ a = 2
+ end
+ end
+ [a, d]
+ CODE
+ end
+
+ def test_MatchWriteNode
+ assert_prism_eval("/(?<foo>bar)(?<baz>bar>)/ =~ 'barbar'")
+ assert_prism_eval("/(?<foo>bar)/ =~ 'barbar'")
+ end
+
+ ############################################################################
+ # Multi-writes #
+ ############################################################################
+
+ def test_ClassVariableTargetNode
+ assert_prism_eval("class Prism::TestCompilePrism; @@pit, @@pit1 = 1; end")
+ end
+
+ def test_ConstantTargetNode
+ # We don't call assert_prism_eval directly in this case because we
+ # don't want to assign the constant multiple times if we run
+ # with `--repeat-count`
+ # Instead, we eval manually here, and remove the constant to
+ constant_names = ["YCT", "YCT2"]
+ source = "#{constant_names.join(",")} = 1"
+ prism_eval = RubyVM::InstructionSequence.compile_prism(source).eval
+ assert_equal prism_eval, 1
+ constant_names.map { |name|
+ Object.send(:remove_const, name)
+ }
+ end
+
+ def test_ConstantPathTargetNode
+ assert_separately([], <<~'RUBY')
+ verbose = $VERBOSE
+ # Create some temporary nested constants
+ Object.send(:const_set, "MyFoo", Object)
+ Object.const_get("MyFoo").send(:const_set, "Bar", Object)
+
+ constant_names = ["MyBar", "MyFoo::Bar", "MyFoo::Bar::Baz"]
+ source = "#{constant_names.join(",")} = Object"
+ iseq = RubyVM::InstructionSequence.compile_prism(source)
+ $VERBOSE = nil
+ prism_eval = iseq.eval
+ $VERBOSE = verbose
+ assert_equal prism_eval, Object
+ RUBY
+ end
+
+ def test_GlobalVariableTargetNode
+ assert_prism_eval("$pit, $pit1 = 1")
+ end
+
+ def test_InstanceVariableTargetNode
+ assert_prism_eval("class Prism::TestCompilePrism; @pit, @pit1 = 1; end")
+ end
+
+ def test_LocalVariableTargetNode
+ assert_prism_eval("pit, pit1 = 1")
+ assert_prism_eval(<<-CODE)
+ a = 1
+ [1].each do
+ c = 2
+ a, b = 2
+ end
+ a
+ CODE
+ end
+
+ def test_MultiTargetNode
+ assert_prism_eval("a, (b, c) = [1, 2, 3]")
+ assert_prism_eval("a, (b, c) = [1, 2, 3]; a")
+ assert_prism_eval("a, (b, c) = [1, 2, 3]; b")
+ assert_prism_eval("a, (b, c) = [1, 2, 3]; c")
+ assert_prism_eval("a, (b, c) = [1, [2, 3]]; c")
+ assert_prism_eval("a, (b, *c) = [1, [2, 3]]; c")
+ assert_prism_eval("a, (b, *c) = 1, [2, 3]; c")
+ assert_prism_eval("a, (b, *) = 1, [2, 3]; b")
+ assert_prism_eval("a, (b, *c, d) = 1, [2, 3, 4]; [a, b, c, d]")
+ assert_prism_eval("(a, (b, c, d, e), f, g), h = [1, [2, 3]], 4, 5, [6, 7]; c")
+ end
+
+ def test_MultiWriteNode
+ assert_prism_eval("foo, bar = [1, 2]")
+ assert_prism_eval("foo, = [1, 2]")
+ assert_prism_eval("foo, *, bar = [1, 2]")
+ assert_prism_eval("foo, bar = 1, 2")
+ assert_prism_eval("foo, *, bar = 1, 2")
+ assert_prism_eval("foo, *, bar = 1, 2, 3, 4")
+ assert_prism_eval("a, b, *, d = 1, 2, 3, 4")
+ assert_prism_eval("a, b, *, d = 1, 2")
+ assert_prism_eval("(a, b), *, c = [1, 3], 4, 5")
+ assert_prism_eval("(a, b), *, c = [1, 3], 4, 5; a")
+ assert_prism_eval("(a, b), *, c = [1, 3], 4, 5; b")
+ assert_prism_eval("(a, b), *, c = [1, 3], 4, 5; c")
+ assert_prism_eval("a, *, (c, d) = [1, 3], 4, 5; a")
+ assert_prism_eval("a, *, (c, d) = [1, 3], 4, 5; c")
+ assert_prism_eval("(a, b, c), *, (d, e) = [1, 3], 4, 5, [6, 7]")
+ assert_prism_eval("(a, b, c), *, (d, e) = [1, 3], 4, 5, [6, 7]; b")
+ assert_prism_eval("(a, b, c), *, (d, e) = [1, 3], 4, 5, [6, 7]; d")
+ assert_prism_eval("((a, *, b), *, (c, *, (d, *, e, f, g))), *, ((h, i, *, j), *, (k, l, m, *, n, o, p), q, r) = 1; a")
+ assert_prism_eval("*a = 1; a")
+ assert_prism_eval("_, {}[:foo] = 1")
+ assert_prism_eval("_, {}[:foo], _ = 1")
+ assert_prism_eval("_, {}[:foo], _ = 1")
+ assert_prism_eval("_,{}[:foo], _, {}[:bar] = 1")
+ assert_prism_eval("* = :foo")
+ assert_prism_eval("* = *[]")
+ assert_prism_eval("a, * = :foo")
+
+
+ assert_prism_eval(<<~CODE)
+ class Foo
+ def bar=(x); end
+ def baz=(c); end
+ end
+ foo = Foo.new
+ foo.bar, foo.baz = 1
+ CODE
+ assert_prism_eval(<<~CODE)
+ class Foo
+ def bar=(x); end
+ def baz=(c); end
+ end
+ foo = Foo.new
+ _, foo.bar, foo.baz = 1
+ CODE
+ assert_prism_eval(<<~CODE)
+ class Foo
+ def bar=(x); end
+ def baz=(c); end
+ end
+ foo = Foo.new
+ _, foo.bar, _, foo.baz = 1
+ CODE
+
+ # Test nested writes with method calls
+ assert_prism_eval(<<~RUBY)
+ class Foo
+ attr_accessor :bar
+ end
+
+ a = Foo.new
+
+ (a.bar, a.bar), b = [1], 2
+ RUBY
+ assert_prism_eval(<<~RUBY)
+ h = {}
+ (h[:foo], h[:bar]), a = [1], 2
+ RUBY
+ end
+
+ ############################################################################
+ # String-likes #
+ ############################################################################
+
+ def test_EmbeddedStatementsNode
+ assert_prism_eval('"foo #{to_s} baz"')
+ end
+
+ def test_EmbeddedVariableNode
+ assert_prism_eval('class Prism::TestCompilePrism; @pit = 1; "#@pit"; end')
+ assert_prism_eval('class Prism::TestCompilePrism; @@pit = 1; "#@@pit"; end')
+ assert_prism_eval('$pit = 1; "#$pit"')
+ end
+
+ def test_InterpolatedMatchLastLineNode
+ assert_prism_eval('$pit = ".oo"; if /"#{$pit}"/mix; end')
+ end
+
+ def test_InterpolatedRegularExpressionNode
+ assert_prism_eval('$pit = 1; /1 #$pit 1/')
+ assert_prism_eval('$pit = 1; /#$pit/i')
+ assert_prism_eval('/1 #{1 + 2} 1/')
+ assert_prism_eval('/1 #{"2"} #{1 + 2} 1/')
+ end
+
+ def test_InterpolatedStringNode
+ assert_prism_eval('$pit = 1; "1 #$pit 1"')
+ assert_prism_eval('"1 #{1 + 2} 1"')
+ assert_prism_eval('"Prism" "::" "TestCompilePrism"')
+ assert_prism_eval(<<-'RUBY')
+ # frozen_string_literal: true
+
+ !("a""b""#{1}").frozen?
+ RUBY
+ assert_prism_eval(<<-'RUBY')
+ # frozen_string_literal: true
+
+ !("a""#{1}""b").frozen?
+ RUBY
+
+ # Test encoding of interpolated strings
+ assert_prism_eval(<<~'RUBY')
+ "#{"foo"}s".encoding
+ RUBY
+ assert_prism_eval(<<~'RUBY')
+ a = "foo"
+ b = "#{a}" << "Bar"
+ [a, b, b.encoding]
+ RUBY
+ end
+
+ def test_concatenated_StringNode
+ assert_prism_eval('("a""b").frozen?')
+ assert_prism_eval(<<-CODE)
+ # frozen_string_literal: true
+
+ ("a""b").frozen?
+ CODE
+ end
+
+ def test_InterpolatedSymbolNode
+ assert_prism_eval('$pit = 1; :"1 #$pit 1"')
+ assert_prism_eval(':"1 #{1 + 2} 1"')
+ end
+
+ def test_InterpolatedXStringNode
+ assert_prism_eval(<<~RUBY)
+ def self.`(command) = command * 2
+ `echo \#{1}`
+ RUBY
+
+ assert_prism_eval(<<~RUBY)
+ def self.`(command) = command * 2
+ `echo \#{"100"}`
+ RUBY
+ end
+
+ def test_MatchLastLineNode
+ assert_prism_eval("if /foo/; end")
+ assert_prism_eval("if /foo/i; end")
+ assert_prism_eval("if /foo/x; end")
+ assert_prism_eval("if /foo/m; end")
+ assert_prism_eval("if /foo/im; end")
+ assert_prism_eval("if /foo/mx; end")
+ assert_prism_eval("if /foo/xi; end")
+ assert_prism_eval("if /foo/ixm; end")
+ end
+
+ def test_RegularExpressionNode
+ assert_prism_eval('/pit/')
+ assert_prism_eval('/pit/i')
+ assert_prism_eval('/pit/x')
+ assert_prism_eval('/pit/m')
+ assert_prism_eval('/pit/im')
+ assert_prism_eval('/pit/mx')
+ assert_prism_eval('/pit/xi')
+ assert_prism_eval('/pit/ixm')
+
+ assert_prism_eval('/pit/u')
+ assert_prism_eval('/pit/e')
+ assert_prism_eval('/pit/s')
+ assert_prism_eval('/pit/n')
+
+ assert_prism_eval('/pit/me')
+ assert_prism_eval('/pit/ne')
+
+ assert_prism_eval('2.times.map { /#{1}/o }')
+ assert_prism_eval('2.times.map { foo = 1; /#{foo}/o }')
+ end
+
+ def test_StringNode
+ assert_prism_eval('"pit"')
+ assert_prism_eval('"a".frozen?')
+ end
+
+ def test_StringNode_frozen_string_literal_true
+ [
+ # Test that string literal is frozen
+ <<~RUBY,
+ # frozen_string_literal: true
+ "a".frozen?
+ RUBY
+ # Test that two string literals with the same contents are the same string
+ <<~RUBY,
+ # frozen_string_literal: true
+ "hello".equal?("hello")
+ RUBY
+ ].each do |src|
+ assert_prism_eval(src, raw: true)
+ end
+ end
+
+ def test_StringNode_frozen_string_literal_false
+ [
+ # Test that string literal is frozen
+ <<~RUBY,
+ # frozen_string_literal: false
+ !"a".frozen?
+ RUBY
+ # Test that two string literals with the same contents are the same string
+ <<~RUBY,
+ # frozen_string_literal: false
+ !"hello".equal?("hello")
+ RUBY
+ ].each do |src|
+ assert_prism_eval(src, raw: true)
+ end
+ end
+
+ def test_StringNode_frozen_string_literal_default
+ # Test that string literal is chilled
+ assert_prism_eval('"a".frozen?')
+
+ # Test that two identical chilled string literals aren't the same object
+ assert_prism_eval('!"hello".equal?("hello")')
+ end
+
+ def test_SymbolNode
+ assert_prism_eval(":pit")
+
+ # Test UTF-8 symbol in a US-ASCII file
+ assert_prism_eval(<<~'RUBY', raw: true)
+ # -*- coding: us-ascii -*-
+ :"\u{e9}"
+ RUBY
+
+ # Test ASCII-8BIT symbol in a US-ASCII file
+ assert_prism_eval(<<~'RUBY', raw: true)
+ # -*- coding: us-ascii -*-
+ :"\xff"
+ RUBY
+
+ # Test US-ASCII symbol in a ASCII-8BIT file
+ assert_prism_eval(<<~'RUBY', raw: true)
+ # -*- coding: ascii-8bit -*-
+ :a
+ RUBY
+ end
+
+ def test_XStringNode
+ assert_prism_eval(<<~RUBY)
+ class Prism::TestCompilePrism
+ def self.`(command) = command * 2
+ `pit`
+ end
+ RUBY
+ end
+
+ ############################################################################
+ # Structures #
+ ############################################################################
+
+ def test_ArrayNode
+ assert_prism_eval("[]")
+ assert_prism_eval("[1, 2, 3]")
+ assert_prism_eval("%i[foo bar baz]")
+ assert_prism_eval("%w[foo bar baz]")
+ assert_prism_eval("[*1..2]")
+ assert_prism_eval("[*1..2, 3, 4, *5..6, 7, 8]")
+ assert_prism_eval("[*1..2, 3, 4, *5..6, 7, 8, *9..11]")
+ assert_prism_eval("[0, *1..2, 3, 4, *5..6, 7, 8, *9..11]")
+ assert_prism_eval("[-1, true, 0, *1..2, 3, 4, *5..6, 7, 8, *9..11]")
+ assert_prism_eval("a = [1,2]; [0, *a, 3, 4, *5..6, 7, 8, *9..11]")
+ assert_prism_eval("[[*1..2], 3, *4..5]")
+
+ # Test keyword splat inside of array
+ assert_prism_eval("[**{x: 'hello'}]")
+
+ # Test UTF-8 string array literal in a US-ASCII file
+ assert_prism_eval(<<~'RUBY', raw: true)
+ # -*- coding: us-ascii -*-
+ # frozen_string_literal: true
+ %W"\u{1f44b} \u{1f409}"
+ RUBY
+ end
+
+ def test_AssocNode
+ assert_prism_eval("{ foo: :bar }")
+ end
+
+ def test_AssocSplatNode
+ assert_prism_eval("foo = { a: 1 }; { **foo }")
+ assert_prism_eval("foo = { a: 1 }; bar = foo; { **foo, b: 2, **bar, c: 3 }")
+ assert_prism_eval("foo = { a: 1 }; { b: 2, **foo, c: 3}")
+
+ # Test anonymous AssocSplatNode
+ assert_prism_eval(<<~RUBY)
+ o = Object.new
+ def o.bar(**) = Hash(**)
+
+ o.bar(hello: "world")
+ RUBY
+
+ # Test that AssocSplatNode is evaluated before BlockArgumentNode using
+ # the splatkw instruction
+ assert_prism_eval(<<~RUBY)
+ o = Struct.new(:ary) do
+ def to_hash
+ ary << :to_hash
+ {}
+ end
+
+ def to_proc
+ ary << :to_proc
+ -> {}
+ end
+
+ def t(...); end
+ end.new
+ o.ary = []
+
+ o.t(**o, &o)
+ o.ary
+ RUBY
+ end
+
+ def test_HashNode
+ assert_prism_eval("{}")
+ assert_prism_eval("{ a: :a }")
+ assert_prism_eval("{ a: :a, b: :b }")
+ assert_prism_eval("a = 1; { a: a }")
+ assert_prism_eval("a = 1; { a: }")
+ assert_prism_eval("{ to_s: }")
+ assert_prism_eval("{ Prism: }")
+ assert_prism_eval("[ Prism: [:b, :c]]")
+ assert_prism_eval("{ [] => 1}")
+ end
+
+ def test_ImplicitNode
+ assert_prism_eval("{ to_s: }")
+ end
+
+ def test_RangeNode
+ assert_prism_eval("1..2")
+ assert_prism_eval("1...2")
+ assert_prism_eval("..2")
+ assert_prism_eval("...2")
+ assert_prism_eval("1..")
+ assert_prism_eval("1...")
+ end
+
+ def test_SplatNode
+ assert_prism_eval("*b = []; b")
+ assert_prism_eval("*b = [1, 2, 3]; b")
+ assert_prism_eval("a, *b = [1, 2, 3]; a")
+ assert_prism_eval("a, *b = [1, 2, 3]; b")
+ assert_prism_eval("a, *b, c = [1, 2, 3]; a")
+ assert_prism_eval("a, *b, c = [1, 2, 3]; b")
+ assert_prism_eval("a, *b, c = [1, 2, 3]; c")
+ assert_prism_eval("*b, c = [1, 2, 3]; b")
+ assert_prism_eval("*b, c = [1, 2, 3]; c")
+ assert_prism_eval("a, *, c = [1, 2, 3]; a")
+ assert_prism_eval("a, *, c = [1, 2, 3]; c")
+
+ # Test anonymous splat node
+ assert_prism_eval(<<~RUBY)
+ def self.bar(*) = Array(*)
+
+ bar([1, 2, 3])
+ RUBY
+ end
+
+ ############################################################################
+ # Jumps #
+ ############################################################################
+
+ def test_AndNode
+ assert_prism_eval("true && 1")
+ assert_prism_eval("false && 1")
+ end
+
+ def test_CaseNode
+ assert_prism_eval("case :a; when :a; 1; else; 2; end")
+ assert_prism_eval("case :a; when :b; 1; else; 2; end")
+ assert_prism_eval("case :a; when :a; 1; else; 2; end")
+ assert_prism_eval("case :a; when :a; end")
+ assert_prism_eval("case :a; when :b, :c; end")
+ assert_prism_eval("case; when :a; end")
+ assert_prism_eval("case; when :a, :b; 1; else; 2 end")
+ assert_prism_eval("case :a; when :b; else; end")
+ assert_prism_eval("b = 1; case :a; when b; else; end")
+ assert_prism_eval(<<-CODE)
+ def self.prism_test_case_node
+ case :a
+ when :b
+ else
+ return 2
+ end
+ 1
+ end
+ prism_test_case_node
+ CODE
+
+ # Test splat in when
+ assert_prism_eval(<<~RUBY)
+ ary = [1, 2]
+ case 1
+ when *ary
+ :ok
+ else
+ :ng
+ end
+ RUBY
+
+ # Test splat in when
+ assert_prism_eval(<<~RUBY)
+ ary = [1, 2]
+ case 1
+ when :foo, *ary
+ :ok
+ else
+ :ng
+ end
+ RUBY
+
+ # Test case without predicate
+ assert_prism_eval(<<~RUBY)
+ case
+ when 1 == 2
+ :ng
+ else
+ :ok
+ end
+ RUBY
+
+ # test splat with no predicate
+ assert_prism_eval(<<~RUBY)
+ case
+ when *[true]
+ :ok
+ else
+ :ng
+ end
+ RUBY
+ end
+
+ def test_ElseNode
+ assert_prism_eval("if false; 0; else; 1; end")
+ assert_prism_eval("if true; 0; else; 1; end")
+ assert_prism_eval("true ? 1 : 0")
+ assert_prism_eval("false ? 0 : 1")
+ end
+
+ def test_FlipFlopNode
+ assert_prism_eval("not (1 == 1) .. (2 == 2)")
+ assert_prism_eval("not (1 == 1) ... (2 == 2)")
+ end
+
+ def test_IfNode
+ assert_prism_eval("if true; 1; end")
+ assert_prism_eval("1 if true")
+ assert_prism_eval('a = b = 1; if a..b; end')
+ assert_prism_eval('if "a".."b"; end')
+ assert_prism_eval('if "a"..; end')
+ assert_prism_eval('if .."b"; end')
+ assert_prism_eval('if ..1; end')
+ assert_prism_eval('if 1..; end')
+ assert_prism_eval('if 1..2; end')
+ assert_prism_eval('if true or true; end');
+ end
+
+ def test_OrNode
+ assert_prism_eval("true || 1")
+ assert_prism_eval("false || 1")
+ end
+
+ def test_UnlessNode
+ assert_prism_eval("1 unless true")
+ assert_prism_eval("1 unless false")
+ assert_prism_eval("unless true; 1; end")
+ assert_prism_eval("unless false; 1; end")
+ end
+
+ def test_UntilNode
+ assert_prism_eval("a = 0; until a == 1; a = a + 1; end")
+
+ # Test UntilNode in rescue
+ assert_prism_eval(<<~RUBY)
+ o = Object.new
+ o.instance_variable_set(:@ret, [])
+ def o.foo = @ret << @ret.length
+ def o.bar = @ret.length > 3
+ begin
+ raise
+ rescue
+ o.foo until o.bar
+ end
+ o.instance_variable_get(:@ret)
+ RUBY
+ end
+
+ def test_WhileNode
+ assert_prism_eval("a = 0; while a != 1; a = a + 1; end")
+
+ # Test WhileNode in rescue
+ assert_prism_eval(<<~RUBY)
+ o = Object.new
+ o.instance_variable_set(:@ret, [])
+ def o.foo = @ret << @ret.length
+ def o.bar = @ret.length < 3
+ begin
+ raise
+ rescue
+ o.foo while o.bar
+ end
+ o.instance_variable_get(:@ret)
+ RUBY
+ end
+
+ def test_ForNode
+ assert_prism_eval("for i in [1,2] do; i; end")
+ assert_prism_eval("for @i in [1,2] do; @i; end")
+ assert_prism_eval("for $i in [1,2] do; $i; end")
+
+ assert_prism_eval("for foo, in [1,2,3] do end")
+
+ assert_prism_eval("for i, j in {a: 'b'} do; i; j; end")
+ end
+
+ ############################################################################
+ # Throws #
+ ############################################################################
+
+ def test_BeginNode
+ assert_prism_eval("begin; 1; end")
+ assert_prism_eval("begin; end; 1")
+ end
+
+ def test_BreakNode
+ assert_prism_eval("while true; break; end")
+ assert_prism_eval("while true; break 1; end")
+ assert_prism_eval("while true; break 1, 2; end")
+
+ assert_prism_eval("[].each { break }")
+ assert_prism_eval("[true].map { break }")
+ end
+
+ def test_ensure_in_methods
+ assert_prism_eval(<<-CODE)
+def self.m
+ a = []
+ensure
+ a << 5
+ return a
+end
+m
+ CODE
+ end
+
+ def test_break_runs_ensure
+ assert_prism_eval(<<-CODE)
+a = []
+while true
+ begin
+ break
+ ensure
+ a << 1
+ end
+end
+a
+ CODE
+ end
+
+ def test_EnsureNode
+ assert_prism_eval("begin; 1; ensure; 2; end")
+ assert_prism_eval("begin; 1; begin; 3; ensure; 4; end; ensure; 2; end")
+ assert_prism_eval(<<-CODE)
+ begin
+ a = 2
+ ensure
+ end
+ CODE
+ assert_prism_eval(<<-CODE)
+ begin
+ a = 2
+ ensure
+ a = 3
+ end
+ a
+ CODE
+
+ # Test that ensure block only evaluated once
+ assert_prism_eval(<<~RUBY)
+ res = []
+ begin
+ begin
+ raise
+ ensure
+ res << $!.to_s
+ end
+ rescue
+ res
+ end
+ RUBY
+
+ assert_prism_eval(<<-CODE)
+ a = 1
+ begin
+ a = 2
+ ensure
+ a = 3
+ end
+ a
+ CODE
+ assert_prism_eval(<<-CODE)
+ a = 1
+ begin
+ b = 2
+ ensure
+ c = 3
+ end
+ a + b + c
+ CODE
+ assert_prism_eval(<<~CODE)
+ foo = 1
+ begin
+ ensure
+ begin
+ ensure
+ foo.nil?
+ end
+ end
+ CODE
+ assert_prism_eval(<<~CODE)
+ def test
+ ensure
+ {}.each do |key, value|
+ {}[key] = value
+ end
+ end
+ CODE
+ assert_prism_eval(<<~CODE)
+ def test
+ a = 1
+ ensure
+ {}.each do |key, value|
+ {}[key] = a
+ end
+ end
+ CODE
+ assert_prism_eval(<<-CODE)
+ def self.prism_test_ensure_node
+ begin
+ ensure
+ end
+ return
+ end
+ prism_test_ensure_node
+ CODE
+
+ # Test empty ensure block
+ assert_prism_eval(<<~RUBY)
+ res = []
+
+ begin
+ begin
+ raise
+ ensure
+ end
+ rescue
+ res << "rescue"
+ end
+
+ res
+ RUBY
+ end
+
+ def test_NextNode
+ assert_prism_eval("2.times do |i|; next if i == 1; end")
+
+ assert_prism_eval(<<-CODE)
+ res = []
+ i = 0
+ while i < 5
+ i += 1
+ next if i == 3
+ res << i
+ end
+ res
+ CODE
+
+ assert_prism_eval(<<-CODE)
+ res = []
+ (1..5).each do |i|
+ next if i.even?
+ res << i
+ end
+ res
+ CODE
+
+ assert_prism_eval(<<-CODE)
+ (1..5).map do |i|
+ next i, :even if i.even?
+ i
+ end
+ CODE
+
+ assert_prism_eval(<<-CODE)
+ res = []
+ i = 0
+ begin
+ i += 1
+ next if i == 3
+ res << i
+ end while i < 5
+ res
+ CODE
+
+ assert_prism_eval(<<-CODE)
+ while false
+ begin
+ ensure
+ end
+ next
+ end
+ CODE
+
+ assert_prism_eval(<<~CODE)
+ [].each do
+ begin
+ rescue
+ next
+ end
+ end
+ CODE
+ end
+
+ def test_RedoNode
+ assert_prism_eval(<<-CODE)
+ counter = 0
+
+ 5.times do |i|
+ counter += 1
+ if i == 2 && counter < 3
+ redo
+ end
+ end
+ CODE
+
+ assert_prism_eval(<<-CODE)
+ for i in 1..5
+ if i == 3
+ i = 0
+ redo
+ end
+ end
+ CODE
+
+ assert_prism_eval(<<-CODE)
+ i = 0
+ begin
+ i += 1
+ redo if i == 3
+ end while i < 5
+ CODE
+ end
+
+ def test_RescueNode
+ assert_prism_eval("begin; 1; rescue; 2; end")
+ assert_prism_eval(<<~CODE)
+ begin
+ 1
+ rescue SyntaxError
+ 2
+ end
+ CODE
+ assert_prism_eval(<<~CODE)
+ begin
+ 1
+ raise 'boom'
+ rescue StandardError
+ 2
+ end
+ CODE
+ assert_prism_eval(<<~CODE)
+ begin
+ a = 1
+ rescue StandardError => e
+ end
+ CODE
+ assert_prism_eval(<<~CODE)
+ begin
+ raise StandardError
+ rescue StandardError => e
+ end
+ CODE
+ assert_prism_eval(<<~CODE)
+ begin
+ 1
+ rescue StandardError => e
+ e
+ rescue SyntaxError => f
+ f
+ else
+ 4
+ end
+ CODE
+ assert_prism_eval(<<-CODE)
+ begin
+ a = 2
+ rescue
+ a = 3
+ end
+ a
+ CODE
+ assert_prism_eval(<<-CODE)
+ a = 1
+ begin
+ a = 2
+ rescue
+ a = 3
+ end
+ a
+ CODE
+ assert_prism_eval(<<-CODE)
+ a = 1
+ begin
+ b = 2
+ raise "bang"
+ rescue
+ c = 3
+ end
+ a + b + c
+ CODE
+ assert_prism_eval("begin; rescue; end")
+
+ assert_prism_eval(<<~CODE)
+ begin
+ rescue
+ args.each do |key, value|
+ tmp[key] = 1
+ end
+ end
+ CODE
+ assert_prism_eval(<<~CODE)
+ 10.times do
+ begin
+ rescue
+ break
+ end
+ end
+ CODE
+
+ # Test RescueNode with ElseNode
+ assert_prism_eval(<<~RUBY)
+ calls = []
+ begin
+ begin
+ rescue RuntimeError
+ calls << 1
+ else
+ calls << 2
+ raise RuntimeError
+ end
+ rescue RuntimeError
+ end
+
+ calls
+ RUBY
+ end
+
+ def test_RescueModifierNode
+ assert_prism_eval("1.nil? rescue false")
+ assert_prism_eval("1.nil? rescue 1")
+ assert_prism_eval("raise 'bang' rescue nil")
+ assert_prism_eval("raise 'bang' rescue a = 1; a.nil?")
+ assert_prism_eval("a = 0 rescue (a += 1 && retry if a <= 1)")
+ end
+
+ def test_RetryNode
+ assert_prism_eval(<<~CODE)
+ a = 1
+ begin
+ a
+ raise "boom"
+ rescue
+ a += 1
+ retry unless a > 1
+ ensure
+ a = 3
+ end
+ CODE
+
+ assert_prism_eval(<<~CODE)
+ begin
+ rescue
+ foo = 2
+ retry
+ end
+ CODE
+
+ assert_prism_eval(<<~CODE)
+ begin
+ a = 2
+ rescue
+ retry
+ end
+ CODE
+ end
+
+ def test_ReturnNode
+ assert_prism_eval(<<-CODE)
+ def self.prism_test_return_node
+ return 1
+ end
+ prism_test_return_node
+ CODE
+
+ assert_prism_eval(<<-CODE)
+ def self.prism_test_return_node
+ return 1, 2
+ end
+ prism_test_return_node
+ CODE
+
+ assert_prism_eval(<<-CODE)
+ def self.prism_test_return_node
+ [1].each do |e|
+ return true
+ end
+ end
+ prism_test_return_node
+ CODE
+
+ assert_prism_eval(<<-CODE)
+ def self.prism_test_return_node
+ [1].map do |i|
+ return i if i == 1
+ 2
+ end
+ end
+ prism_test_return_node
+ CODE
+
+ assert_prism_eval(<<-CODE)
+ def self.prism_test_return_node(*args, **kwargs)
+ return *args, *args, **kwargs
+ end
+ prism_test_return_node(1, foo: 0)
+ CODE
+ end
+
+ ############################################################################
+ # Scopes/statements #
+ ############################################################################
+
+ def test_BlockNode
+ assert_prism_eval("[1, 2, 3].each { |num| num }")
+
+ assert_prism_eval("[].tap { _1 }")
+
+ assert_prism_eval("[].each { |a,| }")
+ assert_prism_eval("[[1, 2, 3]].map { |_, _, a| a }")
+ assert_prism_eval("[[1, 2, 3]].map { |_, a| a }")
+
+ assert_prism_eval("[[]].map { |a| a }")
+ assert_prism_eval("[[]].map { |a| a }")
+ assert_prism_eval("[[]].map { |a, &block| a }")
+ assert_prism_eval("[[]].map { |a, &block| a }")
+ assert_prism_eval("[{}].map { |a,| }")
+ assert_prism_eval("[[]].map { |a,b=1| a }")
+ assert_prism_eval("[{}].map { |a,| }")
+ assert_prism_eval("[{}].map { |a| a }")
+
+ # Test blocks with MultiTargetNode
+ assert_prism_eval("[[1, 2]].each.map { |(a), (b)| [a, b] }")
+ end
+
+ def test_ClassNode
+ assert_prism_eval("class PrismClassA; end")
+ assert_prism_eval("class PrismClassA; end; class PrismClassB < PrismClassA; end")
+ assert_prism_eval("class PrismClassA; end; class PrismClassA::PrismClassC; end")
+ assert_prism_eval(<<-HERE
+ class PrismClassA; end
+ class PrismClassA::PrismClassC; end
+ class PrismClassB; end
+ class PrismClassB::PrismClassD < PrismClassA::PrismClassC; end
+ HERE
+ )
+ end
+
+ # Many of these tests are versions of tests at bootstraptest/test_method.rb
+ def test_DefNode
+ assert_prism_eval("def prism_test_def_node; end")
+ assert_prism_eval("a = Object.new; def a.prism_singleton; :ok; end; a.prism_singleton")
+ assert_prism_eval("def self.prism_test_def_node() 1 end; prism_test_def_node()")
+ assert_prism_eval("def self.prism_test_def_node(a,b) [a, b] end; prism_test_def_node(1,2)")
+ assert_prism_eval("def self.prism_test_def_node(a,x=7,y=1) x end; prism_test_def_node(7,1)")
+ assert_prism_eval("def self.prism_test_def_node(a = 1); x = 2; end; prism_test_def_node")
+
+ # rest argument
+ assert_prism_eval("def self.prism_test_def_node(*a) a end; prism_test_def_node().inspect")
+ assert_prism_eval("def self.prism_test_def_node(*a) a end; prism_test_def_node(1).inspect")
+ assert_prism_eval("def self.prism_test_def_node(x,y,*a) a end; prism_test_def_node(7,7,1,2).inspect")
+ assert_prism_eval("def self.prism_test_def_node(x,y=7,*a) a end; prism_test_def_node(7).inspect")
+ assert_prism_eval("def self.prism_test_def_node(x,y,z=7,*a) a end; prism_test_def_node(7,7).inspect")
+ assert_prism_eval("def self.prism_test_def_node(x,y,z=7,zz=7,*a) a end; prism_test_def_node(7,7,7).inspect")
+
+ # keyword arguments
+ assert_prism_eval("def self.prism_test_def_node(a: 1, b: 2, c: 4) a + b + c; end; prism_test_def_node(a: 2)")
+ assert_prism_eval("def self.prism_test_def_node(a: 1, b: 2, c: 4) a + b + c; end; prism_test_def_node(b: 3)")
+ assert_prism_eval(<<-CODE)
+ def self.prism_test_def_node(x = 1, y, a: 8, b: 2, c: 4)
+ a + b + c + x + y
+ end
+ prism_test_def_node(10, b: 3)
+ CODE
+ assert_prism_eval(<<-CODE)
+ def self.prism_test_def_node(a: [])
+ a
+ end
+ prism_test_def_node
+ CODE
+
+ # block arguments
+ assert_prism_eval("def self.prism_test_def_node(&block) block end; prism_test_def_node{}.class")
+ assert_prism_eval("def self.prism_test_def_node(&block) block end; prism_test_def_node().inspect")
+ assert_prism_eval("def self.prism_test_def_node(a,b=7,*c,&block) b end; prism_test_def_node(7,1).inspect")
+ assert_prism_eval("def self.prism_test_def_node(a,b=7,*c,&block) c end; prism_test_def_node(7,7,1).inspect")
+
+ # splat
+ assert_prism_eval("def self.prism_test_def_node(a) a end; prism_test_def_node(*[1])")
+ assert_prism_eval("def self.prism_test_def_node(x,a) a end; prism_test_def_node(7,*[1])")
+ assert_prism_eval("def self.prism_test_def_node(x,y,a) a end; prism_test_def_node(7,7,*[1])")
+ assert_prism_eval("def self.prism_test_def_node(x,y,a,b,c) a end; prism_test_def_node(7,7,*[1,7,7])")
+
+ # recursive call
+ assert_prism_eval("def self.prism_test_def_node(n) n == 0 ? 1 : prism_test_def_node(n-1) end; prism_test_def_node(5)")
+
+ # instance method
+ assert_prism_eval("class PrismTestDefNode; def prism_test_def_node() 1 end end; PrismTestDefNode.new.prism_test_def_node")
+ assert_prism_eval("class PrismTestDefNode; def prism_test_def_node(*a) a end end; PrismTestDefNode.new.prism_test_def_node(1).inspect")
+
+ # block argument
+ assert_prism_eval(<<-CODE)
+ def self.prism_test_def_node(&block) prism_test_def_node2(&block) end
+ def self.prism_test_def_node2() yield 1 end
+ prism_test_def_node2 {|a| a }
+ CODE
+
+ # multi argument
+ assert_prism_eval(<<-CODE)
+ def self.prism_test_def_node(a, (b, *c, d))
+ [a, b, c, d]
+ end
+ prism_test_def_node("a", ["b", "c", "d"])
+ CODE
+ assert_prism_eval(<<-CODE)
+ def self.prism_test_def_node(a, (b, c, *))
+ [a, b, c]
+ end
+ prism_test_def_node("a", ["b", "c"])
+ CODE
+ assert_prism_eval(<<-CODE)
+ def self.prism_test_def_node(a, (*, b, c))
+ [a, b, c]
+ end
+ prism_test_def_node("a", ["b", "c"])
+ CODE
+
+ # recursive multis
+ assert_prism_eval(<<-CODE)
+ def self.prism_test_def_node(a, (b, *c, (d, *e, f)))
+ [a, b, c, d, d, e, f]
+ end
+ prism_test_def_node("a", ["b", "c", ["d", "e", "f"]])
+ CODE
+
+ # Many arguments
+ assert_prism_eval(<<-CODE)
+ def self.prism_test_def_node(a, (b, *c, d), e = 1, *f, g, (h, *i, j), k:, l: 1, **m)
+ [a, b, c, d, e, f, g, h, i, j, k, l, m]
+ end
+ prism_test_def_node(
+ "a",
+ ["b", "c1", "c2", "d"],
+ "e",
+ "f1", "f2",
+ "g",
+ ["h", "i1", "i2", "j"],
+ k: "k",
+ l: "l",
+ m1: "m1",
+ m2: "m2"
+ )
+ CODE
+ end
+
+ def test_pow_parameters
+ assert_prism_eval("def self.m(a, **); end; method(:m).parameters")
+ end
+
+ def test_star_parameters
+ assert_prism_eval("def self.m(a, *, b); end; method(:m).parameters")
+ end
+
+ def test_repeated_block_params
+ assert_prism_eval("def self.x(&blk); blk; end; x { |_, _, _ = 1, *_, _:, _: 2, **_, &_| }.parameters")
+ end
+
+ def test_repeated_proc_params
+ assert_prism_eval("proc {|_, _, _ = 1, *_, _:, _: 2, **_, &_| }.parameters")
+ end
+
+ def test_forward_parameters_block
+ assert_prism_eval("def self.m(&); end; method(:m).parameters")
+ end
+
+ def test_forward_parameters
+ assert_prism_eval("def self.m(...); end; method(:m).parameters")
+ end
+
+ def test_repeated_block_underscore
+ assert_prism_eval("def self.m(_, **_, &_); _; end; method(:m).parameters")
+ end
+
+ def test_repeated_kw_rest_underscore
+ assert_prism_eval("def self.m(_, **_); _; end; method(:m).parameters")
+ end
+
+ def test_repeated_required_keyword_underscore
+ assert_prism_eval("def self.m(_, _, *_, _, _:); _; end; method(:m).parameters")
+ assert_prism_eval("def self.m(_, _, *_, _, _:, _: 2); _; end; method(:m).parameters")
+ end
+
+ def test_repeated_required_post_underscore
+ assert_prism_eval("def self.m(_, _, *_, _); _; end; method(:m).parameters")
+ end
+
+ def test_repeated_splat_underscore
+ assert_prism_eval("def self.m(_, _, _ = 1, _ = 2, *_); end; method(:m).parameters")
+ end
+
+ def test_repeated_optional_underscore
+ assert_prism_eval("def self.m(a, _, _, _ = 1, _ = 2, b); end; method(:m).parameters")
+ end
+
+ def test_repeated_required_underscore
+ assert_prism_eval("def self.m(a, _, _, b); end; method(:m).parameters")
+ end
+
+ def test_locals_in_parameters
+ assert_prism_eval("def self.m(a = b = c = 1); [a, b, c]; end; self.m")
+ end
+
+ def test_trailing_comma_on_block
+ assert_prism_eval("def self.m; yield [:ok]; end; m {|v0,| v0 }")
+ end
+
+ def test_complex_default_params
+ assert_prism_eval("def self.foo(a:, b: '2'.to_i); [a, b]; end; foo(a: 1)")
+ assert_prism_eval("def self.foo(a:, b: 2, c: '3'.to_i); [a, b, c]; end; foo(a: 1)")
+ end
+
+ def test_numbered_params
+ assert_prism_eval("[1, 2, 3].then { _3 }")
+ assert_prism_eval("1.then { one = 1; one + _1 }")
+ end
+
+ def test_rescue_with_ensure
+ assert_prism_eval(<<-CODE)
+begin
+ begin
+ raise "a"
+ rescue
+ raise "b"
+ ensure
+ raise "c"
+ end
+rescue => e
+ e.message
+end
+ CODE
+ end
+
+ def test_required_kwarg_ordering
+ assert_prism_eval("def self.foo(a: 1, b:); [a, b]; end; foo(b: 2)")
+ end
+
+ def test_trailing_keyword_method_params
+ # foo(1, b: 2, c: 3) # argc -> 3
+ assert_prism_eval("def self.foo(a, b:, c:); [a, b, c]; end; foo(1, b: 2, c: 3)")
+ end
+
+ def test_keyword_method_params_only
+ # foo(a: 1, b: 2) # argc -> 2
+ assert_prism_eval("def self.foo(a:, b:); [a, b]; end; foo(a: 1, b: 2)")
+ end
+
+ def test_keyword_method_params_with_splat
+ # foo(a: 1, **b) # argc -> 1
+ assert_prism_eval("def self.foo(a:, b:); [a, b]; end; b = { b: 2 }; foo(a: 1, **b)")
+ end
+
+ def test_positional_and_splat_keyword_method_params
+ # foo(a, **b) # argc -> 2
+ assert_prism_eval("def self.foo(a, b); [a, b]; end; b = { b: 2 }; foo(1, **b)")
+ end
+
+ def test_positional_and_splat_method_params
+ # foo(a, *b, c, *d, e) # argc -> 2
+ assert_prism_eval("def self.foo(a, b, c, d, e); [a, b, c, d, e]; end; b = [2]; d = [4]; foo(1, *b, 3, *d, 5)")
+ end
+
+ def test_positional_with_splat_and_splat_keyword_method_params
+ # foo(a, *b, c, *d, **e) # argc -> 3
+ assert_prism_eval("def self.foo(a, b, c, d, e); [a, b, c, d, e]; end; b = [2]; d = [4]; e = { e: 5 }; foo(1, *b, 3, *d, **e)")
+ end
+
+ def test_positional_with_splat_and_keyword_method_params
+ # foo(a, *b, c, *d, e:) # argc -> 3
+ assert_prism_eval("def self.foo(a, b, c, d, e:); [a, b, c, d, e]; end; b = [2]; d = [4]; foo(1, *b, 3, *d, e: 5)")
+ end
+
+ def test_leading_splat_and_keyword_method_params
+ # foo(*a, b:) # argc -> 2
+ assert_prism_eval("def self.foo(a, b:); [a, b]; end; a = [1]; foo(*a, b: 2)")
+ end
+
+ def test_repeated_method_params
+ assert_prism_eval("def self.foo(_a, _a); _a; end; foo(1, 2)")
+ end
+
+ def test_splat_params_with_no_lefties
+ assert_prism_eval("def self.foo(v, (*)); v; end; foo(1, [2, 3, 4])")
+ end
+
+ def test_method_parameters
+ assert_prism_eval(<<-CODE)
+ def self.prism_test_method_parameters(a, b=1, *c, d:, e: 2, **f, &g)
+ end
+
+ method(:prism_test_method_parameters).parameters
+ CODE
+
+ assert_prism_eval(<<-CODE)
+ def self.prism_test_method_parameters(d:, e: 2, **f, &g)
+ end
+
+ method(:prism_test_method_parameters).parameters
+ CODE
+
+ assert_prism_eval(<<-CODE)
+ def self.prism_test_method_parameters(**f, &g)
+ end
+
+ method(:prism_test_method_parameters).parameters
+ CODE
+
+ assert_prism_eval(<<-CODE)
+ def self.prism_test_method_parameters(&g)
+ end
+
+ method(:prism_test_method_parameters).parameters
+ CODE
+ end
+
+ def test_LambdaNode
+ assert_prism_eval("-> { to_s }.call")
+ end
+
+ def test_LambdaNode_with_multiline_args
+ assert_prism_eval(<<-CODE)
+ -> (a,
+ b) {
+ a + b
+ }.call(1, 2)
+ CODE
+ end
+
+ def test_ModuleNode
+ assert_prism_eval("module M; end")
+ assert_prism_eval("module M::N; end")
+ assert_prism_eval("module ::O; end")
+ end
+
+ def test_ParenthesesNode
+ assert_prism_eval("()")
+ assert_prism_eval("(1)")
+ end
+
+ def test_PreExecutionNode
+ assert_prism_eval("BEGIN { a = 1 }; 2", raw: true)
+ assert_prism_eval("b = 2; BEGIN { a = 1 }; a + b", raw: true)
+ end
+
+ def test_PostExecutionNode
+ assert_prism_eval("END { 1 }")
+ assert_prism_eval("END { @b }; @b = 1")
+ assert_prism_eval("END { @b; 0 }; @b = 1")
+ assert_prism_eval("foo = 1; END { foo.nil? }")
+ assert_prism_eval("foo = 1; END { END { foo.nil? }}")
+ end
+
+ def test_ProgramNode
+ assert_prism_eval("")
+ assert_prism_eval("1")
+ end
+
+ def test_SingletonClassNode
+ assert_prism_eval("class << self; end")
+ end
+
+ def test_StatementsNode
+ assert_prism_eval("1")
+ end
+
+ def test_YieldNode
+ assert_prism_eval("def prism_test_yield_node; yield; end")
+ assert_prism_eval("def prism_test_yield_node; yield 1, 2; end")
+ assert_prism_eval("def prism_test_yield_node; yield **kw if condition; end")
+
+ # Test case where there's a call directly after the yield call
+ assert_prism_eval("def prism_test_yield_node; yield; 1; end")
+ assert_prism_eval("def prism_test_yield_node; yield 1, 2; 1; end")
+ end
+
+ ############################################################################
+ # Calls / arguments #
+ ############################################################################
+
+ def test_ArgumentsNode
+ # assert_prism_eval("[].push 1")
+ end
+
+ def test_BlockArgumentNode
+ assert_prism_eval("1.then(&:to_s)")
+
+ # Test anonymous block forwarding
+ assert_prism_eval(<<~RUBY)
+ o = Object.new
+ def o.foo(&) = yield
+ def o.bar(&) = foo(&)
+
+ o.bar { :ok }
+ RUBY
+ end
+
+ def test_BlockLocalVariableNode
+ assert_prism_eval(<<-CODE
+ pm_var = "outer scope variable"
+
+ 1.times { |;pm_var| pm_var = "inner scope variable"; pm_var }
+ CODE
+ )
+
+ assert_prism_eval(<<-CODE
+ pm_var = "outer scope variable"
+
+ 1.times { |;pm_var| pm_var = "inner scope variable"; pm_var }
+ pm_var
+ CODE
+ )
+ end
+
+ def test_CallNode
+ assert_prism_eval("to_s")
+
+ # with arguments
+ assert_prism_eval("eval '1'")
+
+ # with arguments and popped
+ assert_prism_eval("eval '1'; 1")
+
+ # With different types of calling arguments
+ assert_prism_eval(<<-CODE)
+ def self.prism_test_call_node_double_splat(**); end
+ prism_test_call_node_double_splat(b: 1, **{})
+ CODE
+ assert_prism_eval(<<-CODE)
+ prism_test_call_node_double_splat(:b => 1)
+ CODE
+
+ assert_prism_eval(<<-CODE)
+ def self.prism_test_call_node_splat(*); end
+ prism_test_call_node_splat(*[], 1)
+ CODE
+
+ assert_prism_eval("prism_test_call_node_splat(*[], 1, 2)")
+
+ assert_prism_eval(<<~RUBY)
+ def self.prism_test_call_node_splat_and_double_splat(a, b, **opts); end
+ prism_test_call_node_splat_and_double_splat(*[1], 2, **{})
+ RUBY
+
+ assert_prism_eval(<<-CODE)
+ class Foo
+ def []=(a, b)
+ 1234
+ end
+ end
+
+ def self.foo(i, j)
+ tbl = Foo.new
+ tbl[i] = j
+ end
+ foo(1, 2)
+ CODE
+
+ assert_prism_eval(<<-CODE)
+ class Foo
+ def i=(a)
+ 1234
+ end
+ end
+
+ def self.foo(j)
+ tbl = Foo.new
+ tbl.i = j
+ end
+ foo(1)
+ CODE
+
+ assert_prism_eval(<<-CODE)
+ foo = Object.new
+ def foo.[]=(k,v); 42; end
+ foo.[]=(1,2)
+ CODE
+
+ # With splat inside of []=
+ assert_prism_eval(<<~RUBY)
+ obj = Object.new
+ def obj.[]=(a, b); 10; end
+ obj[*[1]] = 3
+ RUBY
+
+ assert_prism_eval(<<-CODE)
+ def self.prism_opt_var_trail_hash(a = nil, *b, c, **d); end
+ prism_opt_var_trail_hash("a")
+ prism_opt_var_trail_hash("a", c: 1)
+ prism_opt_var_trail_hash("a", "b")
+ prism_opt_var_trail_hash("a", "b", "c")
+ prism_opt_var_trail_hash("a", "b", "c", c: 1)
+ prism_opt_var_trail_hash("a", "b", "c", "c" => 0, c: 1)
+ CODE
+
+ assert_prism_eval(<<-CODE)
+ def self.foo(*args, **kwargs) = [args, kwargs]
+
+ [
+ foo(2 => 3),
+ foo([] => 42),
+ foo(a: 42, b: 61),
+ foo(1, 2, 3, a: 42, "b" => 61),
+ foo(:a => 42, :b => 61),
+ ]
+ CODE
+
+ assert_prism_eval(<<-CODE)
+ class PrivateMethod
+ def initialize
+ self.instance_var
+ end
+ private
+ attr_accessor :instance_var
+ end
+ pm = PrivateMethod.new
+ pm.send(:instance_var)
+ CODE
+
+ # Testing safe navigation operator
+ assert_prism_eval(<<-CODE)
+ def self.test_prism_call_node
+ if [][0]&.first
+ 1
+ end
+ end
+ test_prism_call_node
+ CODE
+ end
+
+ def test_CallAndWriteNode
+ assert_prism_eval(<<-CODE
+ class PrismTestSubclass; end
+ def PrismTestSubclass.test_call_and_write_node; end;
+ PrismTestSubclass.test_call_and_write_node &&= 1
+ CODE
+ )
+
+ assert_prism_eval(<<-CODE
+ def PrismTestSubclass.test_call_and_write_node
+ "str"
+ end
+ def PrismTestSubclass.test_call_and_write_node=(val)
+ val
+ end
+ PrismTestSubclass.test_call_and_write_node &&= 1
+ CODE
+ )
+
+ assert_prism_eval(<<-CODE
+ def self.test_call_and_write_node; end;
+ self.test_call_and_write_node &&= 1
+ CODE
+ )
+
+ assert_prism_eval(<<-CODE
+ def self.test_call_and_write_node
+ "str"
+ end
+ def self.test_call_and_write_node=(val)
+ val
+ end
+ self.test_call_and_write_node &&= 1
+ CODE
+ )
+
+ assert_prism_eval(<<-CODE)
+ def self.test_prism_call_node; end
+ def self.test_prism_call_node=(val)
+ val
+ end
+ self&.test_prism_call_node &&= 1
+ CODE
+
+ assert_prism_eval(<<-CODE)
+ def self.test_prism_call_node
+ 2
+ end
+ def self.test_prism_call_node=(val)
+ val
+ end
+ self&.test_prism_call_node &&= 1
+ CODE
+ end
+
+ def test_CallOrWriteNode
+ assert_prism_eval(<<-CODE
+ class PrismTestSubclass; end
+ def PrismTestSubclass.test_call_or_write_node; end;
+ def PrismTestSubclass.test_call_or_write_node=(val)
+ val
+ end
+ PrismTestSubclass.test_call_or_write_node ||= 1
+ CODE
+ )
+
+ assert_prism_eval(<<-CODE
+ def PrismTestSubclass.test_call_or_write_node
+ "str"
+ end
+ PrismTestSubclass.test_call_or_write_node ||= 1
+ CODE
+ )
+
+ assert_prism_eval(<<-CODE
+ def self.test_call_or_write_node; end;
+ def self.test_call_or_write_node=(val)
+ val
+ end
+ self.test_call_or_write_node ||= 1
+ CODE
+ )
+
+ assert_prism_eval(<<-CODE
+ def self.test_call_or_write_node
+ "str"
+ end
+ self.test_call_or_write_node ||= 1
+ CODE
+ )
+
+ assert_prism_eval(<<-CODE)
+ def self.test_prism_call_node
+ 2
+ end
+ def self.test_prism_call_node=(val)
+ val
+ end
+ self&.test_prism_call_node ||= 1
+ CODE
+
+ assert_prism_eval(<<-CODE)
+ def self.test_prism_call_node; end
+ def self.test_prism_call_node=(val)
+ val
+ end
+ self&.test_prism_call_node ||= 1
+ CODE
+ end
+
+ def test_CallOperatorWriteNode
+ assert_prism_eval(<<-CODE
+ class PrismTestSubclass; end
+ def PrismTestSubclass.test_call_operator_write_node
+ 2
+ end
+ def PrismTestSubclass.test_call_operator_write_node=(val)
+ val
+ end
+ PrismTestSubclass.test_call_operator_write_node += 1
+ CODE
+ )
+ end
+
+ def test_ForwardingArgumentsNode
+ assert_prism_eval(<<-CODE)
+ def prism_test_forwarding_arguments_node(...); end;
+ def prism_test_forwarding_arguments_node1(...)
+ prism_test_forwarding_arguments_node(...)
+ end
+ CODE
+
+ assert_prism_eval(<<-CODE)
+ def prism_test_forwarding_arguments_node(...); end;
+ def prism_test_forwarding_arguments_node1(a, ...)
+ prism_test_forwarding_arguments_node(1,2, 3, ...)
+ end
+ CODE
+
+ assert_prism_eval(<<~RUBY)
+ o = Object.new
+ def o.bar(a, b, c) = [a, b, c]
+ def o.foo(...) = 1.times { bar(...) }
+
+ o.foo(1, 2, 3)
+ RUBY
+ end
+
+ def test_ForwardingSuperNode
+ assert_prism_eval("class Forwarding; def to_s; super; end; end")
+ assert_prism_eval("class Forwarding; def eval(code); super { code }; end; end")
+ assert_prism_eval(<<-CODE)
+ class A
+ def initialize(a, b)
+ end
+ end
+
+ class B < A
+ attr_reader :res
+ def initialize(a, b, *)
+ super
+ @res = [a, b]
+ end
+ end
+
+ B.new(1, 2).res
+ CODE
+ end
+
+ def test_KeywordHashNode
+ assert_prism_eval("[a: [:b, :c]]")
+ end
+
+ def test_SuperNode
+ assert_prism_eval("def to_s; super 1; end")
+ assert_prism_eval("def to_s; super(); end")
+ assert_prism_eval("def to_s; super('a', :b, [1,2,3]); end")
+ assert_prism_eval("def to_s; super(1, 2, 3, &:foo); end")
+ end
+
+ ############################################################################
+ # Methods / parameters #
+ ############################################################################
+
+ def test_AliasGlobalVariableNode
+ assert_prism_eval("alias $prism_foo $prism_bar")
+ end
+
+ def test_AliasMethodNode
+ assert_prism_eval("alias :prism_a :to_s")
+ end
+
+ def test_BlockParameterNode
+ assert_prism_eval("def prism_test_block_parameter_node(&bar) end")
+ assert_prism_eval("->(b, c=1, *d, e, &f){}")
+
+ # Test BlockParameterNode with no name
+ assert_prism_eval("->(&){}")
+ assert_prism_eval("def prism_test_block_parameter_node(&); end")
+ end
+
+ def test_BlockParametersNode
+ assert_prism_eval("Object.tap { || }")
+ assert_prism_eval("[1].map { |num| num }")
+ assert_prism_eval("[1].map { |a; b| b = 2; a + b}")
+
+ # Test block parameters with multiple _
+ assert_prism_eval(<<~RUBY)
+ [[1, 2, 3, 4, 5, 6]].map { |(_, _, _, _, _, _)| _ }
+ RUBY
+ end
+
+ def test_FowardingParameterNode
+ assert_prism_eval("def prism_test_forwarding_parameter_node(...); end")
+ end
+
+ def test_KeywordRestParameterNode
+ assert_prism_eval("def prism_test_keyword_rest_parameter_node(a, **b); end")
+ assert_prism_eval("Object.tap { |**| }")
+
+ # Test that KeywordRestParameterNode creates a copy
+ assert_prism_eval(<<~RUBY)
+ hash = {}
+ o = Object.new
+ def o.foo(**a) = a[:foo] = 1
+
+ o.foo(**hash)
+ hash
+ RUBY
+ end
+
+ def test_NoKeywordsParameterNode
+ assert_prism_eval("def prism_test_no_keywords(**nil); end")
+ assert_prism_eval("def prism_test_no_keywords(a, b = 2, **nil); end")
+ end
+
+ def test_OptionalParameterNode
+ assert_prism_eval("def prism_test_optional_param_node(bar = nil); end")
+ end
+
+ def test_OptionalKeywordParameterNode
+ assert_prism_eval("def prism_test_optional_keyword_param_node(bar: nil); end")
+
+ # Test with optional argument and method call in OptionalKeywordParameterNode
+ assert_prism_eval(<<~RUBY)
+ o = Object.new
+ def o.foo = 1
+ def o.bar(a = nil, b: foo) = b
+ o.bar
+ RUBY
+ end
+
+ def test_ParametersNode
+ assert_prism_eval("def prism_test_parameters_node(bar, baz); end")
+ assert_prism_eval("def prism_test_parameters_node(a, b = 2); end")
+ end
+
+ def test_RequiredParameterNode
+ assert_prism_eval("def prism_test_required_param_node(bar); end")
+ assert_prism_eval("def prism_test_required_param_node(foo, bar); end")
+ end
+
+ def test_RequiredKeywordParameterNode
+ assert_prism_eval("def prism_test_required_param_node(bar:); end")
+ assert_prism_eval("def prism_test_required_param_node(foo:, bar:); end")
+ assert_prism_eval("-> a, b = 1, c:, d:, &e { a }")
+ end
+
+ def test_RestParameterNode
+ assert_prism_eval("def prism_test_rest_parameter_node(*a); end")
+ end
+
+ def test_UndefNode
+ assert_prism_eval("def prism_undef_node_1; end; undef prism_undef_node_1")
+ assert_prism_eval(<<-HERE
+ def prism_undef_node_2
+ end
+ def prism_undef_node_3
+ end
+ undef prism_undef_node_2, prism_undef_node_3
+ HERE
+ )
+ assert_prism_eval(<<-HERE
+ def prism_undef_node_4
+ end
+ undef :'prism_undef_node_#{4}'
+ HERE
+ )
+ end
+
+ ############################################################################
+ # Pattern matching #
+ ############################################################################
+
+ def test_AlternationPatternNode
+ assert_prism_eval("1 in 1 | 2")
+ assert_prism_eval("1 in 2 | 1")
+ assert_prism_eval("1 in 2 | 3 | 4 | 1")
+ assert_prism_eval("1 in 2 | 3")
+ end
+
+ def test_ArrayPatternNode
+ assert_prism_eval("[] => []")
+
+ ["in", "=>"].each do |operator|
+ ["", "Array"].each do |constant|
+ assert_prism_eval("[1, 2, 3] #{operator} #{constant}[1, 2, 3]")
+
+ assert_prism_eval("[1, 2, 3] #{operator} #{constant}[*]")
+ assert_prism_eval("[1, 2, 3] #{operator} #{constant}[1, *]")
+ assert_prism_eval("[1, 2, 3] #{operator} #{constant}[1, 2, *]")
+ assert_prism_eval("[1, 2, 3] #{operator} #{constant}[1, 2, 3, *]")
+
+ assert_prism_eval("[1, 2, 3] #{operator} #{constant}[*foo]")
+ assert_prism_eval("[1, 2, 3] #{operator} #{constant}[1, *foo]")
+ assert_prism_eval("[1, 2, 3] #{operator} #{constant}[1, 2, *foo]")
+ assert_prism_eval("[1, 2, 3] #{operator} #{constant}[1, 2, 3, *foo]")
+
+ assert_prism_eval("[1, 2, 3] #{operator} #{constant}[*, 3]")
+ assert_prism_eval("[1, 2, 3] #{operator} #{constant}[*, 2, 3]")
+ assert_prism_eval("[1, 2, 3] #{operator} #{constant}[*, 1, 2, 3]")
+
+ assert_prism_eval("[1, 2, 3] #{operator} #{constant}[*foo, 3]")
+ assert_prism_eval("[1, 2, 3] #{operator} #{constant}[*foo, 2, 3]")
+ assert_prism_eval("[1, 2, 3] #{operator} #{constant}[*foo, 1, 2, 3]")
+ end
+ end
+
+ assert_prism_eval("begin; Object.new => [1, 2, 3]; rescue NoMatchingPatternError; true; end")
+ assert_prism_eval("begin; [1, 2, 3] => Object[1, 2, 3]; rescue NoMatchingPatternError; true; end")
+ end
+
+ def test_CapturePatternNode
+ assert_prism_eval("[1] => [Integer => foo]")
+ end
+
+ def test_CaseMatchNode
+ assert_prism_eval(<<~RUBY)
+ case [1, 2, 3]
+ in [1, 2, 3]
+ 4
+ end
+ RUBY
+
+ assert_prism_eval(<<~RUBY)
+ case { a: 5, b: 6 }
+ in [1, 2, 3]
+ 4
+ in { a: 5, b: 6 }
+ 7
+ end
+ RUBY
+
+ assert_prism_eval(<<~RUBY)
+ case [1, 2, 3, 4]
+ in [1, 2, 3]
+ 4
+ in { a: 5, b: 6 }
+ 7
+ else
+ end
+ RUBY
+
+ assert_prism_eval(<<~RUBY)
+ case [1, 2, 3, 4]
+ in [1, 2, 3]
+ 4
+ in { a: 5, b: 6 }
+ 7
+ else
+ 8
+ end
+ RUBY
+
+ assert_prism_eval(<<~RUBY)
+ case [1, 2, 3]
+ in [1, 2, 3] unless to_s
+ in [1, 2, 3] if to_s.nil?
+ in [1, 2, 3]
+ true
+ end
+ RUBY
+ end
+
+ def test_FindPatternNode
+ ["in", "=>"].each do |operator|
+ ["", "Array"].each do |constant|
+ assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*, 1, 2, 3, 4, 5, *]")
+
+ assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*, 1, *]")
+ assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*, 3, *]")
+ assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*, 5, *]")
+
+ assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*, 1, 2, *]")
+ assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*, 2, 3, *]")
+ assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*, 3, 4, *]")
+ assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*, 4, 5, *]")
+
+ assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*, 1, 2, 3, *]")
+ assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*, 2, 3, 4, *]")
+ assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*, 3, 4, 5, *]")
+
+ assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*, 1, 2, 3, 4, *]")
+ assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*, 2, 3, 4, 5, *]")
+
+ assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*foo, 3, *]")
+ assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*foo, 3, 4, *]")
+ assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*foo, 3, 4, 5, *]")
+ assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*foo, 1, 2, 3, 4, *]")
+
+ assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*, 3, *foo]")
+ assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*, 3, 4, *foo]")
+ assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*, 3, 4, 5, *foo]")
+ assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*, 1, 2, 3, 4, *foo]")
+
+ assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*foo, 3, *bar]")
+ assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*foo, 3, 4, *bar]")
+ assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*foo, 3, 4, 5, *bar]")
+ assert_prism_eval("[1, 2, 3, 4, 5] #{operator} #{constant}[*foo, 1, 2, 3, 4, *bar]")
+ end
+ end
+
+ assert_prism_eval("[1, [2, [3, [4, [5]]]]] => [*, [*, [*, [*, [*]]]]]")
+ assert_prism_eval("[1, [2, [3, [4, [5]]]]] => [1, [2, [3, [4, [5]]]]]")
+
+ assert_prism_eval("begin; Object.new => [*, 2, *]; rescue NoMatchingPatternError; true; end")
+ assert_prism_eval("begin; [1, 2, 3] => Object[*, 2, *]; rescue NoMatchingPatternError; true; end")
+ end
+
+ def test_HashPatternNode
+ assert_prism_eval("{} => {}")
+
+ [["{ ", " }"], ["Hash[", "]"]].each do |(prefix, suffix)|
+ assert_prism_eval("{} => #{prefix} **nil #{suffix}")
+
+ assert_prism_eval("{ a: 1, b: 2, c: 3 } => #{prefix} a: 1 #{suffix}")
+ assert_prism_eval("{ a: 1, b: 2, c: 3 } => #{prefix} a: 1, b: 2 #{suffix}")
+ assert_prism_eval("{ a: 1, b: 2, c: 3 } => #{prefix} b: 2, c: 3 #{suffix}")
+ assert_prism_eval("{ a: 1, b: 2, c: 3 } => #{prefix} a: 1, b: 2, c: 3 #{suffix}")
+
+ assert_prism_eval("{ a: 1, b: 2, c: 3 } => #{prefix} ** #{suffix}")
+ assert_prism_eval("{ a: 1, b: 2, c: 3 } => #{prefix} a: 1, ** #{suffix}")
+ assert_prism_eval("{ a: 1, b: 2, c: 3 } => #{prefix} a: 1, b: 2, ** #{suffix}")
+ assert_prism_eval("{ a: 1, b: 2, c: 3 } => #{prefix} b: 2, c: 3, ** #{suffix}")
+ assert_prism_eval("{ a: 1, b: 2, c: 3 } => #{prefix} a: 1, b: 2, c: 3, ** #{suffix}")
+
+ assert_prism_eval("{ a: 1, b: 2, c: 3 } => #{prefix} **foo #{suffix}")
+ assert_prism_eval("{ a: 1, b: 2, c: 3 } => #{prefix} a: 1, **foo #{suffix}")
+ assert_prism_eval("{ a: 1, b: 2, c: 3 } => #{prefix} a: 1, b: 2, **foo #{suffix}")
+ assert_prism_eval("{ a: 1, b: 2, c: 3 } => #{prefix} b: 2, c: 3, **foo #{suffix}")
+ assert_prism_eval("{ a: 1, b: 2, c: 3 } => #{prefix} a: 1, b: 2, c: 3, **foo #{suffix}")
+
+ assert_prism_eval("{ a: 1 } => #{prefix} a: 1, **nil #{suffix}")
+ assert_prism_eval("{ a: 1, b: 2, c: 3 } => #{prefix} a: 1, b: 2, c: 3, **nil #{suffix}")
+ end
+
+ assert_prism_eval("{ a: { b: { c: 1 } } } => { a: { b: { c: 1 } } }")
+ end
+
+ def test_MatchPredicateNode
+ assert_prism_eval("1 in 1")
+ assert_prism_eval("1.0 in 1.0")
+ assert_prism_eval("1i in 1i")
+ assert_prism_eval("1r in 1r")
+
+ assert_prism_eval("\"foo\" in \"foo\"")
+ assert_prism_eval("\"foo \#{1}\" in \"foo \#{1}\"")
+
+ assert_prism_eval("false in false")
+ assert_prism_eval("nil in nil")
+ assert_prism_eval("self in self")
+ assert_prism_eval("true in true")
+
+ assert_prism_eval("5 in 0..10")
+ assert_prism_eval("5 in 0...10")
+
+ assert_prism_eval("[\"5\"] in %w[5]")
+
+ assert_prism_eval("Prism in Prism")
+ assert_prism_eval("Prism in ::Prism")
+
+ assert_prism_eval(":prism in :prism")
+ assert_prism_eval("%s[prism\#{1}] in %s[prism\#{1}]")
+ assert_prism_eval("\"foo\" in /.../")
+ assert_prism_eval("\"foo1\" in /...\#{1}/")
+ assert_prism_eval("4 in ->(v) { v.even? }")
+
+ assert_prism_eval("5 in foo")
+
+ assert_prism_eval("1 in 2")
+ end
+
+ def test_MatchRequiredNode
+ assert_prism_eval("1 => 1")
+ assert_prism_eval("1.0 => 1.0")
+ assert_prism_eval("1i => 1i")
+ assert_prism_eval("1r => 1r")
+
+ assert_prism_eval("\"foo\" => \"foo\"")
+ assert_prism_eval("\"foo \#{1}\" => \"foo \#{1}\"")
+
+ assert_prism_eval("false => false")
+ assert_prism_eval("nil => nil")
+ assert_prism_eval("true => true")
+
+ assert_prism_eval("5 => 0..10")
+ assert_prism_eval("5 => 0...10")
+
+ assert_prism_eval("[\"5\"] => %w[5]")
+
+ assert_prism_eval(":prism => :prism")
+ assert_prism_eval("%s[prism\#{1}] => %s[prism\#{1}]")
+ assert_prism_eval("\"foo\" => /.../")
+ assert_prism_eval("\"foo1\" => /...\#{1}/")
+ assert_prism_eval("4 => ->(v) { v.even? }")
+
+ assert_prism_eval("5 => foo")
+ end
+
+ def test_PinnedExpressionNode
+ assert_prism_eval("4 in ^(4)")
+ end
+
+ def test_PinnedVariableNode
+ assert_prism_eval("module Prism; @@prism = 1; 1 in ^@@prism; end")
+ assert_prism_eval("module Prism; @prism = 1; 1 in ^@prism; end")
+ assert_prism_eval("$prism = 1; 1 in ^$prism")
+ assert_prism_eval("prism = 1; 1 in ^prism")
+ end
+
+ ############################################################################
+ # Miscellaneous #
+ ############################################################################
+
+ def test_eval
+ assert_prism_eval("eval('1 + 1')", raw: true)
+ assert_prism_eval("a = 1; eval('a + 1')", raw: true)
+
+ assert_prism_eval(<<~CODE, raw: true)
+ def prism_eval_splat(**bar)
+ eval("bar")
+ end
+ prism_eval_splat(bar: 10)
+ CODE
+
+ assert_prism_eval(<<~CODE, raw: true)
+ def prism_eval_keywords(baz:)
+ eval("baz")
+ end
+ prism_eval_keywords(baz: 10)
+ CODE
+
+ assert_prism_eval(<<~CODE, raw: true)
+ [1].each do |a|
+ [2].each do |b|
+ c = 3
+ eval("a + b + c")
+ end
+ end
+ CODE
+
+ assert_prism_eval(<<~CODE, raw: true)
+ def prism_eval_binding(b)
+ eval("bar", b)
+ end
+
+ bar = :ok
+ prism_eval_binding(binding)
+ CODE
+ end
+
+ def test_ScopeNode
+ assert_separately(%w[], <<~'RUBY')
+ def compare_eval(source)
+ ruby_eval = RubyVM::InstructionSequence.compile("module A; " + source + "; end").eval
+ prism_eval = RubyVM::InstructionSequence.compile_prism("module B; " + source + "; end").eval
+
+ assert_equal ruby_eval, prism_eval
+ end
+
+ def assert_prism_eval(source)
+ $VERBOSE, verbose_bak = nil, $VERBOSE
+
+ begin
+ compare_eval(source)
+
+ # Test "popped" functionality
+ compare_eval("#{source}; 1")
+ ensure
+ $VERBOSE = verbose_bak
+ end
+ end
+
+ assert_prism_eval("a = 1; 1.times do; { a: }; end")
+ assert_prism_eval("a = 1; def foo(a); a; end")
+ RUBY
+ end
+
+ ############################################################################
+ # Errors #
+ ############################################################################
+
+ def test_MissingNode
+ # TODO
+ end
+
+ ############################################################################
+ # Encoding #
+ ############################################################################
+
+ def test_encoding
+ assert_prism_eval('"però"')
+ assert_prism_eval(":però")
+ end
+
+ def test_parse_file
+ assert_nothing_raised do
+ RubyVM::InstructionSequence.compile_file_prism(__FILE__)
+ end
+
+ error = assert_raise Errno::ENOENT do
+ RubyVM::InstructionSequence.compile_file_prism("idontexist.rb")
+ end
+
+ assert_equal "No such file or directory - idontexist.rb", error.message
+
+ assert_raise TypeError do
+ RubyVM::InstructionSequence.compile_file_prism(nil)
+ end
+ end
+
+ private
+
+ def compare_eval(source, raw:, location:)
+ source = raw ? source : "class Prism::TestCompilePrism\n#{source}\nend"
+
+ ruby_eval = RubyVM::InstructionSequence.compile(source).eval
+ prism_eval = RubyVM::InstructionSequence.compile_prism(source).eval
+
+ if ruby_eval.is_a? Proc
+ assert_equal ruby_eval.class, prism_eval.class, "@#{location.path}:#{location.lineno}"
+ else
+ assert_equal ruby_eval, prism_eval, "@#{location.path}:#{location.lineno}"
+ end
+ end
+
+ def assert_prism_eval(source, raw: false)
+ location = caller_locations(1, 1).first
+ $VERBOSE, verbose_bak = nil, $VERBOSE
+
+ begin
+ compare_eval(source, raw:, location:)
+
+ # Test "popped" functionality
+ compare_eval("#{source}; 1", raw:, location:)
+ ensure
+ $VERBOSE = verbose_bak
+ end
+ end
+ end
+end
diff --git a/test/ruby/test_complex.rb b/test/ruby/test_complex.rb
index a3a7546575..c0cfb73235 100644
--- a/test/ruby/test_complex.rb
+++ b/test/ruby/test_complex.rb
@@ -221,10 +221,16 @@ class Complex_Test < Test::Unit::TestCase
assert_equal([1,2], Complex.polar(1,2).polar)
assert_equal(Complex.polar(1.0, Math::PI * 2 / 3), Complex.polar(1, Math::PI * 2 / 3))
- assert_in_out_err([], <<-'end;', ['OK'], [])
- Complex.polar(1, Complex(1, 0))
- puts :OK
- end;
+ one = 1+0i
+ c = Complex.polar(0, one)
+ assert_equal(0, c)
+ assert_predicate(c.real, :real?)
+ c = Complex.polar(one, 0)
+ assert_equal(1, c)
+ assert_predicate(c.real, :real?)
+ c = Complex.polar(one)
+ assert_equal(1, c)
+ assert_predicate(c.real, :real?)
end
def test_uplus
@@ -520,6 +526,71 @@ class Complex_Test < Test::Unit::TestCase
r = c ** Rational(-2,3)
assert_in_delta(0.432, r.real, 0.001)
assert_in_delta(-0.393, r.imag, 0.001)
+ end
+
+ def test_expt_for_special_angle
+ c = Complex(1, 0) ** 100000000000000000000000000000000
+ assert_equal(Complex(1, 0), c)
+
+ c = Complex(-1, 0) ** 10000000000000000000000000000000
+ assert_equal(Complex(1, 0), c)
+
+ c = Complex(-1, 0) ** 10000000000000000000000000000001
+ assert_equal(Complex(-1, 0), c)
+
+ c = Complex(0, 1) ** 100000000000000000000000000000000
+ assert_equal(Complex(1, 0), c)
+
+ c = Complex(0, 1) ** 100000000000000000000000000000001
+ assert_equal(Complex(0, 1), c)
+
+ c = Complex(0, 1) ** 100000000000000000000000000000002
+ assert_equal(Complex(-1, 0), c)
+
+ c = Complex(0, 1) ** 100000000000000000000000000000003
+ assert_equal(Complex(0, -1), c)
+
+ c = Complex(0, -1) ** 100000000000000000000000000000000
+ assert_equal(Complex(1, 0), c)
+
+ c = Complex(0, -1) ** 100000000000000000000000000000001
+ assert_equal(Complex(0, -1), c)
+
+ c = Complex(0, -1) ** 100000000000000000000000000000002
+ assert_equal(Complex(-1, 0), c)
+
+ c = Complex(0, -1) ** 100000000000000000000000000000003
+ assert_equal(Complex(0, 1), c)
+
+ c = Complex(1, 1) ** 1
+ assert_equal(Complex(1, 1), c)
+
+ c = Complex(1, 1) ** 2
+ assert_equal(Complex(0, 2), c)
+
+ c = Complex(1, 1) ** 3
+ assert_equal(Complex(-2, 2), c)
+
+ c = Complex(1, 1) ** 4
+ assert_equal(Complex(-4, 0), c)
+
+ c = Complex(1, 1) ** 5
+ assert_equal(Complex(-4, -4), c)
+
+ c = Complex(1, 1) ** 6
+ assert_equal(Complex(0, -8), c)
+
+ c = Complex(1, 1) ** 7
+ assert_equal(Complex(8, -8), c)
+
+ c = Complex(-2, -2) ** 3
+ assert_equal(Complex(16, -16), c)
+
+ c = Complex(2, -2) ** 3
+ assert_equal(Complex(-16, -16), c)
+
+ c = Complex(-2, 2) ** 3
+ assert_equal(Complex(16, 16), c)
c = Complex(0.0, -888888888888888.0)**8888
assert_not_predicate(c.real, :nan?)
@@ -567,20 +638,24 @@ class Complex_Test < Test::Unit::TestCase
assert_raise_with_message(TypeError, /C\u{1f5ff}/) { Complex(1).coerce(obj) }
end
- class ObjectX
- def +(x) Rational(1) end
+ class ObjectX < Numeric
+ def initialize(real = true, n = 1) @n = n; @real = real; end
+ def +(x) Rational(@n) end
alias - +
alias * +
alias / +
alias quo +
alias ** +
- def coerce(x) [x, Complex(1)] end
+ def coerce(x) [x, Complex(@n)] end
+ def real?; @real; end
end
def test_coerce2
x = ObjectX.new
- %w(+ - * / quo **).each do |op|
- assert_kind_of(Numeric, Complex(1).__send__(op, x))
+ y = ObjectX.new(false)
+ %w(+ - * / quo ** <=>).each do |op|
+ assert_kind_of(Numeric, Complex(1).__send__(op, x), op)
+ assert_kind_of(Numeric, Complex(1).__send__(op, y), op)
end
end
@@ -843,20 +918,42 @@ class Complex_Test < Test::Unit::TestCase
assert_equal(Complex(0), '_5'.to_c)
assert_equal(Complex(5), '5_'.to_c)
assert_equal(Complex(5), '5x'.to_c)
+ assert_equal(Complex(51), '5_1'.to_c)
+ assert_equal(Complex(5), '5__1'.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_equal(Complex(5,31), '5+3_1i'.to_c)
+ assert_equal(Complex(5), '5+3__1i'.to_c)
+ assert_equal(Complex(51), Complex('5_1'))
+ assert_equal(Complex(5,31), Complex('5+3_1i'))
+ assert_equal(Complex(5,31), Complex('5+3_1I'))
+ assert_equal(Complex(5,31), Complex('5+3_1j'))
+ assert_equal(Complex(5,31), Complex('5+3_1J'))
+ assert_equal(Complex(0,31), Complex('3_1i'))
+ assert_equal(Complex(0,31), Complex('3_1I'))
+ assert_equal(Complex(0,31), Complex('3_1j'))
+ assert_equal(Complex(0,31), Complex('3_1J'))
assert_raise(ArgumentError){ Complex('')}
assert_raise(ArgumentError){ Complex('_')}
assert_raise(ArgumentError){ Complex("\f\n\r\t\v5\0")}
assert_raise(ArgumentError){ Complex('_5')}
assert_raise(ArgumentError){ Complex('5_')}
+ assert_raise(ArgumentError){ Complex('5__1')}
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')}
+ assert_raise(ArgumentError){ Complex('5+3__1i')}
+ assert_raise(ArgumentError){ Complex('5+3__1I')}
+ assert_raise(ArgumentError){ Complex('5+3__1j')}
+ assert_raise(ArgumentError){ Complex('5+3__1J')}
+ assert_raise(ArgumentError){ Complex('3__1i')}
+ assert_raise(ArgumentError){ Complex('3__1I')}
+ assert_raise(ArgumentError){ Complex('3__1j')}
+ assert_raise(ArgumentError){ Complex('3__1J')}
assert_equal(Complex(Rational(1,5)), '1/5'.to_c)
assert_equal(Complex(Rational(-1,5)), '-1/5'.to_c)
@@ -883,31 +980,27 @@ class Complex_Test < Test::Unit::TestCase
}
end
- def test_Complex_without_exception
- assert_nothing_raised(ArgumentError){
- assert_equal(nil, Complex('5x', exception: false))
- }
- assert_nothing_raised(ArgumentError){
- assert_equal(nil, Complex(nil, exception: false))
- }
- assert_nothing_raised(ArgumentError){
- assert_equal(nil, Complex(Object.new, exception: false))
- }
- assert_nothing_raised(ArgumentError){
- assert_equal(nil, Complex(1, nil, exception: false))
- }
- assert_nothing_raised(ArgumentError){
- assert_equal(nil, Complex(1, Object.new, exception: false))
- }
+ def assert_complex_with_exception(error, *args, message: "")
+ assert_raise(error, message) do
+ Complex(*args, exception: true)
+ end
+ assert_nothing_raised(error, message) do
+ assert_nil(Complex(*args, exception: false))
+ assert_nil($!)
+ end
+ end
+
+ def test_Complex_with_exception
+ assert_complex_with_exception(ArgumentError, '5x')
+ assert_complex_with_exception(TypeError, nil)
+ assert_complex_with_exception(TypeError, Object.new)
+ assert_complex_with_exception(TypeError, 1, nil)
+ assert_complex_with_exception(TypeError, 1, Object.new)
o = Object.new
def o.to_c; raise; end
- assert_nothing_raised(ArgumentError){
- assert_equal(nil, Complex(o, exception: false))
- }
- assert_nothing_raised(ArgumentError){
- assert_equal(nil, Complex(1, o, exception: false))
- }
+ assert_complex_with_exception(RuntimeError, o)
+ assert_complex_with_exception(TypeError, 1, o)
end
def test_respond
@@ -961,6 +1054,29 @@ class Complex_Test < Test::Unit::TestCase
assert_raise(RangeError){Rational(Complex(3,2))}
end
+ def test_to_r_with_float
+ assert_equal(Rational(3), Complex(3, 0.0).to_r)
+ assert_raise(RangeError){Complex(3, 1.0).to_r}
+ end
+
+ def test_to_r_with_numeric_obj
+ c = Class.new(Numeric)
+
+ num = 0
+ c.define_method(:to_s) { num.to_s }
+ c.define_method(:==) { num == it }
+ c.define_method(:<) { num < it }
+
+ o = c.new
+ assert_equal(Rational(3), Complex(3, o).to_r)
+
+ num = 1
+ assert_raise(RangeError){Complex(3, o).to_r}
+
+ c.define_method(:to_r) { 0r }
+ assert_equal(Rational(3), Complex(3, o).to_r)
+ end
+
def test_to_c
c = nil.to_c
assert_equal([0,0], [c.real, c.imag])
@@ -1135,15 +1251,34 @@ class Complex_Test < Test::Unit::TestCase
end
def test_canonicalize_polar
- obj = Class.new(Numeric) do
- def initialize
- @x = 2
+ error = "not a real"
+ assert_raise_with_message(TypeError, error) do
+ Complex.polar(1i)
+ end
+ assert_raise_with_message(TypeError, error) do
+ Complex.polar(1i, 0)
+ end
+ assert_raise_with_message(TypeError, error) do
+ Complex.polar(0, 1i)
+ end
+ n = Class.new(Numeric) do
+ def initialize(x = 1)
+ @x = x
end
def real?
(@x -= 1) > 0
end
- end.new
- assert_raise(TypeError) do
+ end
+ obj = n.new
+ assert_raise_with_message(TypeError, error) do
+ Complex.polar(obj)
+ end
+ obj = n.new
+ assert_raise_with_message(TypeError, error) do
+ Complex.polar(obj, 0)
+ end
+ obj = n.new
+ assert_raise_with_message(TypeError, error) do
Complex.polar(1, obj)
end
end
diff --git a/test/ruby/test_complex2.rb b/test/ruby/test_complex2.rb
index 594fc3f45a..b89e83efb2 100644
--- a/test/ruby/test_complex2.rb
+++ b/test/ruby/test_complex2.rb
@@ -4,7 +4,7 @@ require 'test/unit'
class Complex_Test2 < Test::Unit::TestCase
def test_kumi
- skip unless defined?(Rational)
+ omit unless defined?(Rational)
assert_equal(Complex(1, 0), +Complex(1, 0))
assert_equal(Complex(-1, 0), -Complex(1, 0))
diff --git a/test/ruby/test_complexrational.rb b/test/ruby/test_complexrational.rb
index bf4e2b1809..31d11fe317 100644
--- a/test/ruby/test_complexrational.rb
+++ b/test/ruby/test_complexrational.rb
@@ -4,7 +4,7 @@ require 'test/unit'
class ComplexRational_Test < Test::Unit::TestCase
def test_rat_srat
- skip unless defined?(Rational)
+ omit unless defined?(Rational)
c = SimpleRat(1,3)
cc = Rational(3,2)
@@ -89,7 +89,7 @@ class ComplexRational_Test < Test::Unit::TestCase
end
def test_comp_srat
- skip unless defined?(Rational)
+ omit unless defined?(Rational)
c = Complex(SimpleRat(2,3),SimpleRat(1,2))
cc = Complex(Rational(3,2),Rational(2,1))
diff --git a/test/ruby/test_continuation.rb b/test/ruby/test_continuation.rb
index 8c62d20840..612dbf28c9 100644
--- a/test/ruby/test_continuation.rb
+++ b/test/ruby/test_continuation.rb
@@ -4,6 +4,10 @@ EnvUtil.suppress_warning {require 'continuation'}
require 'fiber'
class TestContinuation < Test::Unit::TestCase
+ def setup
+ omit 'requires callcc support' unless respond_to?(:callcc)
+ end
+
def test_create
assert_equal(:ok, callcc{:ok})
assert_equal(:ok, callcc{|c| c.call :ok})
diff --git a/test/ruby/test_data.rb b/test/ruby/test_data.rb
new file mode 100644
index 0000000000..bb38f8ec91
--- /dev/null
+++ b/test/ruby/test_data.rb
@@ -0,0 +1,283 @@
+# -*- coding: us-ascii -*-
+# frozen_string_literal: false
+require 'test/unit'
+require 'timeout'
+
+class TestData < Test::Unit::TestCase
+ def test_define
+ klass = Data.define(:foo, :bar)
+ assert_kind_of(Class, klass)
+ assert_equal(%i[foo bar], klass.members)
+
+ assert_raise(NoMethodError) { Data.new(:foo) }
+ assert_raise(TypeError) { Data.define(0) }
+
+ # Because some code is shared with Struct, check we don't share unnecessary functionality
+ assert_raise(TypeError) { Data.define(:foo, keyword_init: true) }
+
+ assert_not_respond_to(Data.define, :define, "Cannot define from defined Data class")
+ end
+
+ def test_define_edge_cases
+ # non-ascii
+ klass = Data.define(:"r\u{e9}sum\u{e9}")
+ o = klass.new(1)
+ assert_equal(1, o.send(:"r\u{e9}sum\u{e9}"))
+
+ # junk string
+ klass = Data.define(:"a\000")
+ o = klass.new(1)
+ assert_equal(1, o.send(:"a\000"))
+
+ # special characters in attribute names
+ klass = Data.define(:a, :b?)
+ x = Object.new
+ o = klass.new("test", x)
+ assert_same(x, o.b?)
+
+ klass = Data.define(:a, :b!)
+ x = Object.new
+ o = klass.new("test", x)
+ assert_same(x, o.b!)
+
+ assert_raise(ArgumentError) { Data.define(:x=) }
+ assert_raise(ArgumentError, /duplicate member/) { Data.define(:x, :x) }
+ end
+
+ def test_define_with_block
+ klass = Data.define(:a, :b) do
+ def c
+ a + b
+ end
+ end
+
+ assert_equal(3, klass.new(1, 2).c)
+ end
+
+ def test_initialize
+ klass = Data.define(:foo, :bar)
+
+ # Regular
+ test = klass.new(1, 2)
+ assert_equal(1, test.foo)
+ assert_equal(2, test.bar)
+ assert_equal(test, klass.new(1, 2))
+ assert_predicate(test, :frozen?)
+
+ # Keywords
+ test_kw = klass.new(foo: 1, bar: 2)
+ assert_equal(1, test_kw.foo)
+ assert_equal(2, test_kw.bar)
+ assert_equal(test_kw, klass.new(foo: 1, bar: 2))
+ assert_equal(test_kw, test)
+
+ # Wrong protocol
+ assert_raise(ArgumentError) { klass.new(1) }
+ assert_raise(ArgumentError) { klass.new(1, 2, 3) }
+ assert_raise(ArgumentError) { klass.new(foo: 1) }
+ assert_raise(ArgumentError) { klass.new(foo: 1, bar: 2, baz: 3) }
+ # Could be converted to foo: 1, bar: 2, but too smart is confusing
+ assert_raise(ArgumentError) { klass.new(1, bar: 2) }
+ end
+
+ def test_initialize_redefine
+ klass = Data.define(:foo, :bar) do
+ attr_reader :passed
+
+ def initialize(*args, **kwargs)
+ @passed = [args, kwargs]
+ super(foo: 1, bar: 2) # so we can experiment with passing wrong numbers of args
+ end
+ end
+
+ assert_equal([[], {foo: 1, bar: 2}], klass.new(foo: 1, bar: 2).passed)
+
+ # Positional arguments are converted to keyword ones
+ assert_equal([[], {foo: 1, bar: 2}], klass.new(1, 2).passed)
+
+ # Missing arguments can be fixed in initialize
+ assert_equal([[], {foo: 1}], klass.new(foo: 1).passed)
+ assert_equal([[], {foo: 42}], klass.new(42).passed)
+
+ # Extra keyword arguments can be dropped in initialize
+ assert_equal([[], {foo: 1, bar: 2, baz: 3}], klass.new(foo: 1, bar: 2, baz: 3).passed)
+ end
+
+ def test_instance_behavior
+ klass = Data.define(:foo, :bar)
+
+ test = klass.new(1, 2)
+ assert_equal(1, test.foo)
+ assert_equal(2, test.bar)
+ assert_equal(%i[foo bar], test.members)
+ assert_equal(1, test.public_send(:foo))
+ assert_equal(0, test.method(:foo).arity)
+ assert_equal([], test.method(:foo).parameters)
+
+ assert_equal({foo: 1, bar: 2}, test.to_h)
+ assert_equal({"foo"=>"1", "bar"=>"2"}, test.to_h { [_1.to_s, _2.to_s] })
+
+ assert_equal([1, 2], test.deconstruct)
+ assert_equal({foo: 1, bar: 2}, test.deconstruct_keys(nil))
+ assert_equal({foo: 1}, test.deconstruct_keys(%i[foo]))
+ assert_equal({foo: 1}, test.deconstruct_keys(%i[foo baz]))
+ assert_equal({}, test.deconstruct_keys(%i[foo bar baz]))
+ assert_raise(TypeError) { test.deconstruct_keys(0) }
+
+ assert_kind_of(Integer, test.hash)
+ end
+
+ def test_hash
+ measure = Data.define(:amount, :unit)
+
+ assert_equal(measure[1, 'km'].hash, measure[1, 'km'].hash)
+ assert_not_equal(measure[1, 'km'].hash, measure[10, 'km'].hash)
+ assert_not_equal(measure[1, 'km'].hash, measure[1, 'm'].hash)
+ assert_not_equal(measure[1, 'km'].hash, measure[1.0, 'km'].hash)
+
+ # Structurally similar data class, but shouldn't be considered
+ # the same hash key
+ measurement = Data.define(:amount, :unit)
+
+ assert_not_equal(measure[1, 'km'].hash, measurement[1, 'km'].hash)
+ end
+
+ def test_inspect
+ klass = Data.define(:a)
+ o = klass.new(1)
+ assert_equal("#<data a=1>", o.inspect)
+
+ Object.const_set(:Foo, klass)
+ assert_equal("#<data Foo a=1>", o.inspect)
+ Object.instance_eval { remove_const(:Foo) }
+
+ klass = Data.define(:@a)
+ o = klass.new(1)
+ assert_equal("#<data :@a=1>", o.inspect)
+ end
+
+ def test_equal
+ klass1 = Data.define(:a)
+ klass2 = Data.define(:a)
+ o1 = klass1.new(1)
+ o2 = klass1.new(1)
+ o3 = klass2.new(1)
+ assert_equal(o1, o2)
+ assert_not_equal(o1, o3)
+ end
+
+ def test_eql
+ klass1 = Data.define(:a)
+ klass2 = Data.define(:a)
+ o1 = klass1.new(1)
+ o2 = klass1.new(1)
+ o3 = klass2.new(1)
+ assert_operator(o1, :eql?, o2)
+ assert_not_operator(o1, :eql?, o3)
+ end
+
+ def test_with
+ klass = Data.define(:foo, :bar)
+ source = klass.new(foo: 1, bar: 2)
+
+ # Simple
+ test = source.with
+ assert_equal(source.object_id, test.object_id)
+
+ # Changes
+ test = source.with(foo: 10)
+
+ assert_equal(1, source.foo)
+ assert_equal(2, source.bar)
+ assert_equal(source, klass.new(foo: 1, bar: 2))
+
+ assert_equal(10, test.foo)
+ assert_equal(2, test.bar)
+ assert_equal(test, klass.new(foo: 10, bar: 2))
+
+ test = source.with(foo: 10, bar: 20)
+
+ assert_equal(1, source.foo)
+ assert_equal(2, source.bar)
+ assert_equal(source, klass.new(foo: 1, bar: 2))
+
+ assert_equal(10, test.foo)
+ assert_equal(20, test.bar)
+ assert_equal(test, klass.new(foo: 10, bar: 20))
+
+ # Keyword splat
+ changes = { foo: 10, bar: 20 }
+ test = source.with(**changes)
+
+ assert_equal(1, source.foo)
+ assert_equal(2, source.bar)
+ assert_equal(source, klass.new(foo: 1, bar: 2))
+
+ assert_equal(10, test.foo)
+ assert_equal(20, test.bar)
+ assert_equal(test, klass.new(foo: 10, bar: 20))
+
+ # Wrong protocol
+ assert_raise_with_message(ArgumentError, "wrong number of arguments (given 1, expected 0)") do
+ source.with(10)
+ end
+ assert_raise_with_message(ArgumentError, "unknown keywords: :baz, :quux") do
+ source.with(foo: 1, bar: 2, baz: 3, quux: 4)
+ end
+ assert_raise_with_message(ArgumentError, "wrong number of arguments (given 1, expected 0)") do
+ source.with(1, bar: 2)
+ end
+ assert_raise_with_message(ArgumentError, "wrong number of arguments (given 2, expected 0)") do
+ source.with(1, 2)
+ end
+ assert_raise_with_message(ArgumentError, "wrong number of arguments (given 1, expected 0)") do
+ source.with({ bar: 2 })
+ end
+ end
+
+ def test_with_initialize
+ oddclass = Data.define(:odd) do
+ def initialize(odd:)
+ raise ArgumentError, "Not odd" unless odd.odd?
+ super(odd: odd)
+ end
+ end
+ assert_raise_with_message(ArgumentError, "Not odd") {
+ oddclass.new(odd: 0)
+ }
+ odd = oddclass.new(odd: 1)
+ assert_raise_with_message(ArgumentError, "Not odd") {
+ odd.with(odd: 2)
+ }
+ end
+
+ def test_memberless
+ klass = Data.define
+
+ test = klass.new
+
+ assert_equal(klass.new, test)
+ assert_not_equal(Data.define.new, test)
+
+ assert_equal('#<data >', test.inspect)
+ assert_equal([], test.members)
+ assert_equal({}, test.to_h)
+ end
+
+ def test_dup
+ klass = Data.define(:foo, :bar)
+ test = klass.new(foo: 1, bar: 2)
+ assert_equal(klass.new(foo: 1, bar: 2), test.dup)
+ assert_predicate(test.dup, :frozen?)
+ end
+
+ Klass = Data.define(:foo, :bar)
+
+ def test_marshal
+ test = Klass.new(foo: 1, bar: 2)
+ loaded = Marshal.load(Marshal.dump(test))
+ assert_equal(test, loaded)
+ assert_not_same(test, loaded)
+ assert_predicate(loaded, :frozen?)
+ end
+end
diff --git a/test/ruby/test_default_gems.rb b/test/ruby/test_default_gems.rb
index 3c4aea1561..b82e304cbd 100644
--- a/test/ruby/test_default_gems.rb
+++ b/test/ruby/test_default_gems.rb
@@ -2,15 +2,28 @@
require 'rubygems'
class TestDefaultGems < Test::Unit::TestCase
+ def self.load(file)
+ code = File.read(file, mode: "r:UTF-8:-", &:read)
+
+ # These regex patterns are from load_gemspec method of rbinstall.rb.
+ # - `git ls-files` is useless under ruby's repository
+ # - `2>/dev/null` works only on Unix-like platforms
+ code.gsub!(/(?:`git[^\`]*`|%x\[git[^\]]*\])\.split\([^\)]*\)/m, '[]')
+ code.gsub!(/IO\.popen\(.*git.*?\)/, '[] || itself')
+
+ eval(code, binding, file)
+ end
def test_validate_gemspec
- skip "git not found" unless system("git", "rev-parse", %i[out err]=>IO::NULL)
srcdir = File.expand_path('../../..', __FILE__)
- Dir.glob("#{srcdir}/{lib,ext}/**/*.gemspec").map do |src|
- assert_nothing_raised do
- raise("invalid spec in #{src}") unless Gem::Specification.load(src)
+ specs = 0
+ Dir.chdir(srcdir) do
+ all_assertions_foreach(nil, *Dir["{lib,ext}/**/*.gemspec"]) do |src|
+ specs += 1
+ assert_kind_of(Gem::Specification, self.class.load(src), "invalid spec in #{src}")
end
end
+ assert_operator specs, :>, 0, "gemspecs not found"
end
end
diff --git a/test/ruby/test_defined.rb b/test/ruby/test_defined.rb
index 3324a09afe..3a8065d959 100644
--- a/test/ruby/test_defined.rb
+++ b/test/ruby/test_defined.rb
@@ -127,6 +127,53 @@ class TestDefined < Test::Unit::TestCase
assert_equal nil, defined?($2)
end
+ def test_defined_assignment
+ assert_equal("assignment", defined?(a = 1))
+ assert_equal("assignment", defined?(a += 1))
+ assert_equal("assignment", defined?(a &&= 1))
+ assert_equal("assignment", eval('defined?(A = 1)'))
+ assert_equal("assignment", eval('defined?(A += 1)'))
+ assert_equal("assignment", eval('defined?(A &&= 1)'))
+ assert_equal("assignment", eval('defined?(A::B = 1)'))
+ assert_equal("assignment", eval('defined?(A::B += 1)'))
+ assert_equal("assignment", eval('defined?(A::B &&= 1)'))
+ end
+
+ def test_defined_splat
+ assert_nil(defined?([*a]))
+ assert_nil(defined?(itself(*a)))
+ assert_equal("expression", defined?([*itself]))
+ assert_equal("method", defined?(itself(*itself)))
+ end
+
+ def test_defined_hash
+ assert_nil(defined?({a: a}))
+ assert_nil(defined?({a => 1}))
+ assert_nil(defined?({a => a}))
+ assert_nil(defined?({**a}))
+ assert_nil(defined?(itself(a: a)))
+ assert_nil(defined?(itself(a => 1)))
+ assert_nil(defined?(itself(a => a)))
+ assert_nil(defined?(itself(**a)))
+ assert_nil(defined?(itself({a: a})))
+ assert_nil(defined?(itself({a => 1})))
+ assert_nil(defined?(itself({a => a})))
+ assert_nil(defined?(itself({**a})))
+
+ assert_equal("expression", defined?({a: itself}))
+ assert_equal("expression", defined?({itself => 1}))
+ assert_equal("expression", defined?({itself => itself}))
+ assert_equal("expression", defined?({**itself}))
+ assert_equal("method", defined?(itself(a: itself)))
+ assert_equal("method", defined?(itself(itself => 1)))
+ assert_equal("method", defined?(itself(itself => itself)))
+ assert_equal("method", defined?(itself(**itself)))
+ assert_equal("method", defined?(itself({a: itself})))
+ assert_equal("method", defined?(itself({itself => 1})))
+ assert_equal("method", defined?(itself({itself => itself})))
+ assert_equal("method", defined?(itself({**itself})))
+ end
+
def test_defined_literal
assert_equal("nil", defined?(nil))
assert_equal("true", defined?(true))
@@ -303,6 +350,20 @@ class TestDefined < Test::Unit::TestCase
assert_equal("super", o.x, bug8367)
end
+ def test_super_in_basic_object
+ BasicObject.class_eval do
+ def a
+ defined?(super)
+ end
+ end
+
+ assert_nil(a)
+ ensure
+ BasicObject.class_eval do
+ undef_method :a if defined?(a)
+ end
+ end
+
def test_super_toplevel
assert_separately([], "assert_nil(defined?(super))")
end
diff --git a/test/ruby/test_dir.rb b/test/ruby/test_dir.rb
index 71bff5f5c3..78371a096b 100644
--- a/test/ruby/test_dir.rb
+++ b/test/ruby/test_dir.rb
@@ -19,11 +19,21 @@ class TestDir < Test::Unit::TestCase
@dirs << File.join(i, "")
end
end
+ @envs = nil
end
def teardown
$VERBOSE = @verbose
FileUtils.remove_entry_secure @root if File.directory?(@root)
+ ENV.update(@envs) if @envs
+ end
+
+ def setup_envs(envs = %w"HOME LOGDIR")
+ @envs ||= {}
+ envs.each do |e, v|
+ @envs[e] = ENV.delete(e)
+ ENV[e] = v if v
+ end
end
def test_seek
@@ -86,33 +96,31 @@ class TestDir < Test::Unit::TestCase
d.close
end
- def test_chdir
+ def test_class_chdir
pwd = Dir.pwd
- env_home = ENV["HOME"]
- env_logdir = ENV["LOGDIR"]
- ENV.delete("HOME")
- ENV.delete("LOGDIR")
+ setup_envs
assert_raise(Errno::ENOENT) { Dir.chdir(@nodir) }
assert_raise(ArgumentError) { Dir.chdir }
ENV["HOME"] = pwd
Dir.chdir do
- assert_warning(/conflicting chdir during another chdir block/) { Dir.chdir(pwd) }
+ conflicting = /conflicting chdir during another chdir block\n^#{Regexp.quote(__FILE__)}:#{__LINE__-1}:/
+ assert_warning(conflicting) { Dir.chdir(pwd) }
- assert_warning(/conflicting chdir during another chdir block/) { Dir.chdir(@root) }
+ assert_warning(conflicting) { Dir.chdir(@root) }
assert_equal(@root, Dir.pwd)
- assert_warning(/conflicting chdir during another chdir block/) { Dir.chdir(pwd) }
+ assert_warning(conflicting) { Dir.chdir(pwd) }
assert_raise(RuntimeError) { Thread.new { Thread.current.report_on_exception = false; Dir.chdir(@root) }.join }
assert_raise(RuntimeError) { Thread.new { Thread.current.report_on_exception = false; Dir.chdir(@root) { } }.join }
- assert_warning(/conflicting chdir during another chdir block/) { Dir.chdir(pwd) }
+ assert_warning(conflicting) { Dir.chdir(pwd) }
- assert_warning(/conflicting chdir during another chdir block/) { Dir.chdir(@root) }
+ assert_warning(conflicting) { Dir.chdir(@root) }
assert_equal(@root, Dir.pwd)
- assert_warning(/conflicting chdir during another chdir block/) { Dir.chdir(pwd) }
+ assert_warning(conflicting) { Dir.chdir(pwd) }
Dir.chdir(@root) do
assert_equal(@root, Dir.pwd)
end
@@ -125,8 +133,73 @@ class TestDir < Test::Unit::TestCase
rescue
abort("cannot return the original directory: #{ pwd }")
end
- ENV["HOME"] = env_home
- ENV["LOGDIR"] = env_logdir
+ end
+
+ def test_instance_chdir
+ pwd = Dir.pwd
+ dir = Dir.new(pwd)
+ root_dir = Dir.new(@root)
+ setup_envs
+
+ ENV["HOME"] = pwd
+ ret = root_dir.chdir do |*a|
+ conflicting = /conflicting chdir during another chdir block\n^#{Regexp.quote(__FILE__)}:#{__LINE__-1}:/
+
+ assert_empty(a)
+
+ assert_warning(conflicting) { dir.chdir }
+ assert_warning(conflicting) { root_dir.chdir }
+
+ assert_equal(@root, Dir.pwd)
+
+ assert_raise(RuntimeError) { Thread.new { Thread.current.report_on_exception = false; dir.chdir }.join }
+ assert_raise(RuntimeError) { Thread.new { Thread.current.report_on_exception = false; dir.chdir{} }.join }
+
+ assert_warning(conflicting) { dir.chdir }
+ assert_equal(pwd, Dir.pwd)
+
+ assert_warning(conflicting) { root_dir.chdir }
+ assert_equal(@root, Dir.pwd)
+
+ assert_warning(conflicting) { dir.chdir }
+
+ root_dir.chdir do
+ assert_equal(@root, Dir.pwd)
+ end
+ assert_equal(pwd, Dir.pwd)
+
+ 42
+ end
+
+ assert_separately(["-", @root], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ root = ARGV.shift
+
+ $dir_warnings = []
+
+ def Warning.warn(message)
+ $dir_warnings << message
+ end
+
+ line2 = line1 = __LINE__; Dir.chdir(root) do
+ line2 = __LINE__; Dir.chdir
+ end
+
+ message = $dir_warnings.shift
+ assert_include(message, "#{__FILE__}:#{line2}:")
+ assert_include(message, "#{__FILE__}:#{line1}:")
+ assert_empty($dir_warnings)
+ end;
+
+ assert_equal(42, ret)
+ ensure
+ begin
+ assert_equal(0, dir.chdir)
+ rescue
+ abort("cannot return the original directory: #{ pwd }")
+ end
+ dir.close
+ root_dir.close
end
def test_chdir_conflict
@@ -152,7 +225,7 @@ class TestDir < Test::Unit::TestCase
end
def test_chroot_nodir
- skip if RUBY_PLATFORM =~ /android/
+ omit if RUBY_PLATFORM =~ /android/
assert_raise(NotImplementedError, Errno::ENOENT, Errno::EPERM
) { Dir.chroot(File.join(@nodir, "")) }
end
@@ -171,11 +244,19 @@ class TestDir < Test::Unit::TestCase
Dir.glob([@root, File.join(@root, "*")]))
assert_equal([@root] + ("a".."z").map {|f| File.join(@root, f) },
Dir.glob([@root, File.join(@root, "*")], sort: false).sort)
+ assert_equal([@root] + ("a".."z").map {|f| File.join(@root, f) },
+ Dir.glob([@root, File.join(@root, "*")], sort: true))
assert_raise_with_message(ArgumentError, /nul-separated/) do
Dir.glob(@root + "\0\0\0" + File.join(@root, "*"))
end
+ assert_raise_with_message(ArgumentError, /expected true or false/) do
+ Dir.glob(@root, sort: 1)
+ end
+ assert_raise_with_message(ArgumentError, /expected true or false/) do
+ Dir.glob(@root, sort: nil)
+ end
- assert_equal(("a".."z").step(2).map {|f| File.join(File.join(@root, f), "") },
+ assert_equal(("a".."z").each_slice(2).map {|f,_| File.join(File.join(@root, f), "") },
Dir.glob(File.join(@root, "*/")))
assert_equal([File.join(@root, '//a')], Dir.glob(@root + '//a'))
@@ -251,6 +332,20 @@ class TestDir < Test::Unit::TestCase
end
end
+ def test_glob_recursive_with_brace
+ Dir.chdir(@root) do
+ bug19042 = '[ruby-core:110220] [Bug #19042]'
+ %w"c/dir_a c/dir_b c/dir_b/dir".each do |d|
+ Dir.mkdir(d)
+ end
+ expected = %w"c/dir_a/file c/dir_b/dir/file"
+ expected.each do |f|
+ File.write(f, "")
+ end
+ assert_equal(expected, Dir.glob("**/{dir_a,dir_b/dir}/file"), bug19042)
+ end
+ end
+
def test_glob_order
Dir.chdir(@root) do
assert_equal(["#{@root}/a", "#{@root}/b"], Dir.glob("#{@root}/[ba]"))
@@ -482,9 +577,9 @@ class TestDir < Test::Unit::TestCase
def test_glob_legacy_short_name
bug10819 = '[ruby-core:67954] [Bug #10819]'
bug11206 = '[ruby-core:69435] [Bug #11206]'
- skip unless /\A\w:/ =~ ENV["ProgramFiles"]
+ omit unless /\A\w:/ =~ ENV["ProgramFiles"]
short = "#$&/PROGRA~1"
- skip unless File.directory?(short)
+ omit unless File.directory?(short)
entries = Dir.glob("#{short}/Common*")
assert_not_empty(entries, bug10819)
long = File.expand_path(short)
@@ -494,13 +589,62 @@ class TestDir < Test::Unit::TestCase
assert_include(Dir.glob(wild, File::FNM_SHORTNAME), long, bug10819)
assert_empty(entries - Dir.glob("#{wild}/Common*", File::FNM_SHORTNAME), bug10819)
end
+
+ def test_home_windows
+ setup_envs(%w[HOME USERPROFILE HOMEDRIVE HOMEPATH])
+
+ ENV['HOME'] = "C:\\ruby\\home"
+ assert_equal("C:/ruby/home", Dir.home)
+
+ ENV['USERPROFILE'] = "C:\\ruby\\userprofile"
+ assert_equal("C:/ruby/home", Dir.home)
+ ENV.delete('HOME')
+ assert_equal("C:/ruby/userprofile", Dir.home)
+
+ ENV['HOMEDRIVE'] = "C:"
+ ENV['HOMEPATH'] = "\\ruby\\homepath"
+ assert_equal("C:/ruby/userprofile", Dir.home)
+ ENV.delete('USERPROFILE')
+ assert_equal("C:/ruby/homepath", Dir.home)
+ end
+
+ def test_home_at_startup_windows
+ env = {'HOME' => "C:\\ruby\\home"}
+ args = [env]
+ assert_separately(args, "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ assert_equal("C:/ruby/home", Dir.home)
+ end;
+
+ env['USERPROFILE'] = "C:\\ruby\\userprofile"
+ assert_separately(args, "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ assert_equal("C:/ruby/home", Dir.home)
+ end;
+
+ env['HOME'] = nil
+ assert_separately(args, "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ assert_equal("C:/ruby/userprofile", Dir.home)
+ end;
+
+ env['HOMEDRIVE'] = "C:"
+ env['HOMEPATH'] = "\\ruby\\homepath"
+ assert_separately(args, "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ assert_equal("C:/ruby/userprofile", Dir.home)
+ end;
+
+ env['USERPROFILE'] = nil
+ assert_separately(args, "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ assert_equal("C:/ruby/homepath", Dir.home)
+ end;
+ end
end
def test_home
- env_home = ENV["HOME"]
- env_logdir = ENV["LOGDIR"]
- ENV.delete("HOME")
- ENV.delete("LOGDIR")
+ setup_envs
ENV["HOME"] = @nodir
assert_nothing_raised(ArgumentError) do
@@ -518,9 +662,16 @@ class TestDir < Test::Unit::TestCase
%W[no:such:user \u{7559 5b88}:\u{756a}].each do |user|
assert_raise_with_message(ArgumentError, /#{user}/) {Dir.home(user)}
end
- ensure
- ENV["HOME"] = env_home
- ENV["LOGDIR"] = env_logdir
+ end
+
+ if Encoding.find("filesystem") == Encoding::UTF_8
+ # On Windows and macOS, file system encoding is always UTF-8.
+ def test_home_utf8
+ setup_envs
+
+ ENV["HOME"] = "/\u{e4}~\u{1f3e0}"
+ assert_equal("/\u{e4}~\u{1f3e0}", Dir.home)
+ end
end
def test_symlinks_not_resolved
@@ -551,6 +702,23 @@ class TestDir < Test::Unit::TestCase
}
end
+ def test_for_fd
+ if Dir.respond_to? :for_fd
+ begin
+ new_dir = Dir.new('..')
+ for_fd_dir = Dir.for_fd(new_dir.fileno)
+ assert_equal(new_dir.chdir{Dir.pwd}, for_fd_dir.chdir{Dir.pwd})
+ ensure
+ new_dir&.close
+ if for_fd_dir
+ assert_raise(Errno::EBADF) { for_fd_dir.close }
+ end
+ end
+ else
+ assert_raise(NotImplementedError) { Dir.for_fd(0) }
+ end
+ end
+
def test_empty?
assert_not_send([Dir, :empty?, @root])
a = File.join(@root, "a")
diff --git a/test/ruby/test_dir_m17n.rb b/test/ruby/test_dir_m17n.rb
index 67bad8a514..cdf8b44ef2 100644
--- a/test/ruby/test_dir_m17n.rb
+++ b/test/ruby/test_dir_m17n.rb
@@ -56,7 +56,7 @@ class TestDir_M17N < Test::Unit::TestCase
return if Bug::File::Fs.fsname(Dir.tmpdir) == "apfs"
with_tmpdir {|d|
assert_separately(%w[-EASCII-8BIT], <<-'EOS', :chdir=>d)
- filename = "\xff".force_encoding("ASCII-8BIT") # invalid byte sequence as UTF-8
+ filename = "\xff".dup.force_encoding("ASCII-8BIT") # invalid byte sequence as UTF-8
File.open(filename, "w") {}
opts = {:encoding => Encoding.default_external} if /mswin|mingw/ =~ RUBY_PLATFORM
ents = Dir.entries(".", **(opts||{}))
@@ -64,7 +64,7 @@ class TestDir_M17N < Test::Unit::TestCase
assert_include(ents, filename)
EOS
assert_separately(%w[-EUTF-8], <<-'EOS', :chdir=>d)
- filename = "\xff".force_encoding("UTF-8") # invalid byte sequence as UTF-8
+ filename = "\xff".dup.force_encoding("UTF-8") # invalid byte sequence as UTF-8
File.open(filename, "w") {}
opts = {:encoding => Encoding.default_external} if /mswin|mingw/ =~ RUBY_PLATFORM
ents = Dir.entries(".", **(opts||{}))
@@ -77,7 +77,7 @@ class TestDir_M17N < Test::Unit::TestCase
def test_filename_as_bytes_extutf8
with_tmpdir {|d|
assert_separately(%w[-EUTF-8], <<-'EOS', :chdir=>d)
- filename = "\xc2\xa1".force_encoding("utf-8")
+ filename = "\xc2\xa1".dup.force_encoding("utf-8")
File.open(filename, "w") {}
opts = {:encoding => Encoding.default_external} if /mswin|mingw/ =~ RUBY_PLATFORM
ents = Dir.entries(".", **(opts||{}))
@@ -85,9 +85,9 @@ class TestDir_M17N < Test::Unit::TestCase
EOS
assert_separately(%w[-EUTF-8], <<-'EOS', :chdir=>d)
if /mswin|mingw|darwin/ =~ RUBY_PLATFORM
- filename = "\x8f\xa2\xc2".force_encoding("euc-jp")
+ filename = "\x8f\xa2\xc2".dup.force_encoding("euc-jp")
else
- filename = "\xc2\xa1".force_encoding("euc-jp")
+ filename = "\xc2\xa1".dup.force_encoding("euc-jp")
end
assert_nothing_raised(Errno::ENOENT) do
open(filename) {}
@@ -96,8 +96,8 @@ class TestDir_M17N < Test::Unit::TestCase
# no meaning test on windows
unless /mswin|mingw|darwin/ =~ RUBY_PLATFORM
assert_separately(%W[-EUTF-8], <<-'EOS', :chdir=>d)
- filename1 = "\xc2\xa1".force_encoding("utf-8")
- filename2 = "\xc2\xa1".force_encoding("euc-jp")
+ filename1 = "\xc2\xa1".dup.force_encoding("utf-8")
+ filename2 = "\xc2\xa1".dup.force_encoding("euc-jp")
filename3 = filename1.encode("euc-jp")
filename4 = filename2.encode("utf-8")
assert_file.stat(filename1)
@@ -121,13 +121,13 @@ class TestDir_M17N < Test::Unit::TestCase
assert_include(ents, filename)
EOS
assert_separately(%w[-EUTF-8:EUC-JP], <<-'EOS', :chdir=>d)
- filename = "\xA4\xA2".force_encoding("euc-jp")
+ filename = "\xA4\xA2".dup.force_encoding("euc-jp")
opts = {:encoding => Encoding.default_external} if /mswin|mingw/ =~ RUBY_PLATFORM
ents = Dir.entries(".", **(opts||{}))
assert_include(ents, filename)
EOS
assert_separately(%w[-EUTF-8:EUC-JP], <<-'EOS', :chdir=>d)
- filename = "\xA4\xA2".force_encoding("euc-jp")
+ filename = "\xA4\xA2".dup.force_encoding("euc-jp")
assert_nothing_raised(Errno::ENOENT) do
open(filename) {}
end
@@ -149,7 +149,7 @@ class TestDir_M17N < Test::Unit::TestCase
EOS
assert_separately(%w[-EUTF-8:EUC-JP], <<-'EOS', :chdir=>d)
filename1 = "\u2661" # WHITE HEART SUIT which is not representable in EUC-JP
- filename2 = "\xA4\xA2".force_encoding("euc-jp") # HIRAGANA LETTER A in EUC-JP
+ filename2 = "\xA4\xA2".dup.force_encoding("euc-jp") # HIRAGANA LETTER A in EUC-JP
opts = {:encoding => Encoding.default_external} if /mswin|mingw/ =~ RUBY_PLATFORM
ents = Dir.entries(".", **(opts||{}))
assert_include(ents, filename1)
@@ -158,7 +158,7 @@ class TestDir_M17N < Test::Unit::TestCase
assert_separately(%w[-EUTF-8:EUC-JP], <<-'EOS', :chdir=>d)
filename1 = "\u2661" # WHITE HEART SUIT which is not representable in EUC-JP
filename2 = "\u3042" # HIRAGANA LETTER A which is representable in EUC-JP
- filename3 = "\xA4\xA2".force_encoding("euc-jp") # HIRAGANA LETTER A in EUC-JP
+ filename3 = "\xA4\xA2".dup.force_encoding("euc-jp") # HIRAGANA LETTER A in EUC-JP
assert_file.stat(filename1)
assert_file.stat(filename2)
assert_file.stat(filename3)
@@ -172,7 +172,7 @@ class TestDir_M17N < Test::Unit::TestCase
return if /cygwin/ =~ RUBY_PLATFORM
with_tmpdir {|d|
assert_separately(%w[-EEUC-JP], <<-'EOS', :chdir=>d)
- filename = "\xA4\xA2".force_encoding("euc-jp")
+ filename = "\xA4\xA2".dup.force_encoding("euc-jp")
File.open(filename, "w") {}
opts = {:encoding => Encoding.default_external} if /mswin|mingw/ =~ RUBY_PLATFORM
ents = Dir.entries(".", **(opts||{}))
@@ -189,7 +189,7 @@ class TestDir_M17N < Test::Unit::TestCase
return if /cygwin/ =~ RUBY_PLATFORM
with_tmpdir {|d|
assert_separately(%w[-EEUC-JP], <<-'EOS', :chdir=>d)
- filename = "\xA4\xA2".force_encoding("euc-jp")
+ filename = "\xA4\xA2".dup.force_encoding("euc-jp")
File.open(filename, "w") {}
ents = Dir.entries(".")
if /darwin/ =~ RUBY_PLATFORM
@@ -200,7 +200,7 @@ class TestDir_M17N < Test::Unit::TestCase
assert_include(ents, filename)
EOS
assert_separately(%w[-EASCII-8BIT], <<-'EOS', :chdir=>d)
- filename = "\xA4\xA2".force_encoding('ASCII-8BIT')
+ filename = "\xA4\xA2".dup.force_encoding('ASCII-8BIT')
ents = Dir.entries(".")
unless ents.include?(filename)
case RUBY_PLATFORM
@@ -231,7 +231,7 @@ class TestDir_M17N < Test::Unit::TestCase
return if /cygwin/ =~ RUBY_PLATFORM
with_tmpdir {|d|
assert_separately(%w[-EEUC-JP], <<-'EOS', :chdir=>d)
- filename = "\xA4\xA2".force_encoding("euc-jp")
+ filename = "\xA4\xA2".dup.force_encoding("euc-jp")
File.open(filename, "w") {}
opts = {:encoding => Encoding.default_external} if /mswin|mingw/ =~ RUBY_PLATFORM
ents = Dir.entries(".", **(opts||{}))
@@ -241,7 +241,7 @@ class TestDir_M17N < Test::Unit::TestCase
assert_include(ents, filename)
EOS
assert_separately(%w[-EEUC-JP:UTF-8], <<-'EOS', :chdir=>d)
- filename = "\u3042"
+ filename = "\u3042".dup
opts = {:encoding => Encoding.default_external} if /mswin|mingw/ =~ RUBY_PLATFORM
ents = Dir.entries(".", **(opts||{}))
if /darwin/ =~ RUBY_PLATFORM
@@ -318,7 +318,7 @@ class TestDir_M17N < Test::Unit::TestCase
def test_glob_warning_opendir
with_enc_path do |dir|
- open("#{dir}/x", "w") {}
+ File.binwrite("#{dir}/x", "")
File.chmod(0300, dir)
next if File.readable?(dir)
assert_warning(/#{dir}/) do
@@ -329,7 +329,7 @@ class TestDir_M17N < Test::Unit::TestCase
def test_glob_warning_match_all
with_enc_path do |dir|
- open("#{dir}/x", "w") {}
+ File.binwrite("#{dir}/x", "")
File.chmod(0000, dir)
next if File.readable?(dir)
assert_warning(/#{dir}/) do
@@ -350,7 +350,7 @@ class TestDir_M17N < Test::Unit::TestCase
end
def test_glob_escape_multibyte
- name = "\x81\\".force_encoding(Encoding::Shift_JIS)
+ name = "\x81\\".dup.force_encoding(Encoding::Shift_JIS)
with_tmpdir do
open(name, "w") {} rescue next
match, = Dir.glob("#{name}*")
@@ -362,9 +362,9 @@ class TestDir_M17N < Test::Unit::TestCase
def test_glob_encoding
with_tmpdir do
list = %W"file_one.ext file_two.ext \u{6587 4ef6}1.txt \u{6587 4ef6}2.txt"
- list.each {|f| open(f, "w") {}}
- a = "file_one*".force_encoding Encoding::IBM437
- b = "file_two*".force_encoding Encoding::EUC_JP
+ list.each {|f| File.binwrite(f, "")}
+ a = "file_one*".dup.force_encoding Encoding::IBM437
+ b = "file_two*".dup.force_encoding Encoding::EUC_JP
assert_equal([a, b].map(&:encoding), Dir[a, b].map(&:encoding))
if Bug::File::Fs.fsname(Dir.pwd) == "apfs"
# High Sierra's APFS cannot use filenames with undefined character
@@ -375,7 +375,7 @@ class TestDir_M17N < Test::Unit::TestCase
Dir.mkdir(dir)
list << dir
bug12081 = '[ruby-core:73868] [Bug #12081]'
- a = "*".force_encoding("us-ascii")
+ a = "*".dup.force_encoding("us-ascii")
result = Dir[a].map {|n|
if n.encoding == Encoding::ASCII_8BIT ||
n.encoding == Encoding::ISO_8859_1 ||
diff --git a/test/ruby/test_dup.rb b/test/ruby/test_dup.rb
new file mode 100644
index 0000000000..75c4fc0339
--- /dev/null
+++ b/test/ruby/test_dup.rb
@@ -0,0 +1,110 @@
+# frozen_string_literal: false
+require 'test/unit'
+
+class TestDup < 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_dup
+ foo = Object.new
+ def foo.test
+ "test"
+ end
+ bar = foo.dup
+ def bar.test2
+ "test2"
+ end
+
+ assert_equal("test2", bar.test2)
+ assert_raise(NoMethodError) { bar.test }
+ assert_equal("test", foo.test)
+
+ assert_raise(NoMethodError) {foo.test2}
+
+ assert_equal([M003, M002, M001], M003.ancestors)
+ end
+
+ def test_frozen_properties_not_retained_on_dup
+ obj = Object.new.freeze
+ duped_obj = obj.dup
+
+ assert_predicate(obj, :frozen?)
+ refute_predicate(duped_obj, :frozen?)
+ end
+
+ def test_ivar_retained_on_dup
+ obj = Object.new
+ obj.instance_variable_set(:@a, 1)
+ duped_obj = obj.dup
+
+ assert_equal(obj.instance_variable_get(:@a), 1)
+ assert_equal(duped_obj.instance_variable_get(:@a), 1)
+ end
+
+ def test_ivars_retained_on_extended_obj_dup
+ ivars = { :@a => 1, :@b => 2, :@c => 3, :@d => 4 }
+ obj = Object.new
+ ivars.each do |ivar_name, val|
+ obj.instance_variable_set(ivar_name, val)
+ end
+
+ duped_obj = obj.dup
+
+ ivars.each do |ivar_name, val|
+ assert_equal(obj.instance_variable_get(ivar_name), val)
+ assert_equal(duped_obj.instance_variable_get(ivar_name), val)
+ end
+ end
+
+ def test_frozen_properties_not_retained_on_dup_with_ivar
+ obj = Object.new
+ obj.instance_variable_set(:@a, 1)
+ obj.freeze
+
+ duped_obj = obj.dup
+
+ assert_predicate(obj, :frozen?)
+ assert_equal(obj.instance_variable_get(:@a), 1)
+
+ refute_predicate(duped_obj, :frozen?)
+ assert_equal(duped_obj.instance_variable_get(:@a), 1)
+ end
+
+ def test_user_flags
+ assert_separately([], <<-EOS)
+ #
+ class Array
+ undef initialize_copy
+ def initialize_copy(*); end
+ end
+ x = [1, 2, 3].dup
+ assert_equal [], x, '[Bug #14847]'
+ EOS
+
+ assert_separately([], <<-EOS)
+ #
+ class Array
+ undef initialize_copy
+ def initialize_copy(*); end
+ end
+ x = [1,2,3,4,5,6,7][1..-2].dup
+ x.push(1,1,1,1,1)
+ assert_equal [1, 1, 1, 1, 1], x, '[Bug #14847]'
+ EOS
+
+ assert_separately([], <<-EOS)
+ #
+ class Hash
+ undef initialize_copy
+ def initialize_copy(*); end
+ end
+ h = {}
+ h.default_proc = proc { raise }
+ h = h.dup
+ assert_equal nil, h[:not_exist], '[Bug #14847]'
+ EOS
+ end
+end
diff --git a/test/ruby/test_econv.rb b/test/ruby/test_econv.rb
index 1aad0de347..1d0641e918 100644
--- a/test/ruby/test_econv.rb
+++ b/test/ruby/test_econv.rb
@@ -931,7 +931,7 @@ class TestEncodingConverter < Test::Unit::TestCase
def test_default_external
Encoding.list.grep(->(enc) {/\AISO-8859-\d+\z/i =~ enc.name}) do |enc|
- assert_separately(%W[--disable=gems -d - #{enc.name}], <<-EOS, ignore_stderr: true)
+ assert_separately(%W[-d - #{enc.name}], <<-EOS, ignore_stderr: true)
Encoding.default_external = ext = ARGV[0]
Encoding.default_internal = int ='utf-8'
assert_nothing_raised do
diff --git a/test/ruby/test_encoding.rb b/test/ruby/test_encoding.rb
index 4a6dd932ed..f2c609a4cd 100644
--- a/test/ruby/test_encoding.rb
+++ b/test/ruby/test_encoding.rb
@@ -55,39 +55,6 @@ class TestEncoding < Test::Unit::TestCase
assert_raise(TypeError, bug5150) {Encoding.find(1)}
end
- def test_replicate
- assert_separately([], "#{<<~'END;'}")
- assert_instance_of(Encoding, Encoding::UTF_8.replicate("UTF-8-ANOTHER#{Time.now.to_f}"))
- assert_instance_of(Encoding, Encoding::ISO_2022_JP.replicate("ISO-2022-JP-ANOTHER#{Time.now.to_f}"))
- bug3127 = '[ruby-dev:40954]'
- assert_raise(TypeError, bug3127) {Encoding::UTF_8.replicate(0)}
- assert_raise_with_message(ArgumentError, /\bNUL\b/, bug3127) {Encoding::UTF_8.replicate("\0")}
- END;
- end
-
- def test_extra_encoding
- assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
- begin;
- 200.times {|i|
- Encoding::UTF_8.replicate("dummy#{i}")
- }
- e = Encoding.list.last
- format = "%d".force_encoding(e)
- assert_equal("0", format % 0)
- assert_equal(e, format.dup.encoding)
- assert_equal(e, (format*1).encoding)
-
- assert_equal(e, (("x"*30).force_encoding(e)*1).encoding)
- GC.start
-
- name = "A" * 64
- Encoding.list.each do |enc|
- assert_raise(ArgumentError) {enc.replicate(name)}
- name.succ!
- end
- end;
- end
-
def test_dummy_p
assert_equal(true, Encoding::ISO_2022_JP.dummy?)
assert_equal(false, Encoding::UTF_8.dummy?)
@@ -139,7 +106,7 @@ class TestEncoding < Test::Unit::TestCase
end
def test_errinfo_after_autoload
- assert_separately(%w[--disable=gems], "#{<<~"begin;"}\n#{<<~'end;'}")
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
bug9038 = '[ruby-core:57949] [Bug #9038]'
begin;
e = assert_raise_with_message(SyntaxError, /unknown regexp option - Q/, bug9038) {
diff --git a/test/ruby/test_enum.rb b/test/ruby/test_enum.rb
index 4674f984ff..237bdc8a4d 100644
--- a/test/ruby/test_enum.rb
+++ b/test/ruby/test_enum.rb
@@ -134,6 +134,12 @@ class TestEnumerable < Test::Unit::TestCase
assert_equal([1, 2, 3, 1, 2], @obj.to_a)
end
+ def test_to_a_keywords
+ @obj.singleton_class.remove_method(:each)
+ def @obj.each(foo:) yield foo end
+ assert_equal([1], @obj.to_a(foo: 1))
+ end
+
def test_to_a_size_symbol
sym = Object.new
class << sym
@@ -228,6 +234,8 @@ class TestEnumerable < Test::Unit::TestCase
assert_equal(24, @obj.inject(2) {|z, x| z * x })
assert_equal(24, assert_warning(/given block not used/) {@obj.inject(2, :*) {|z, x| z * x }})
assert_equal(nil, @empty.inject() {9})
+
+ assert_raise(ArgumentError) {@obj.inject}
end
FIXNUM_MIN = RbConfig::LIMITS['FIXNUM_MIN']
@@ -455,6 +463,17 @@ class TestEnumerable < Test::Unit::TestCase
empty.first
empty.block.call
end;
+
+ bug18475 = '[ruby-dev:107059]'
+ assert_in_out_err([], <<-'end;', [], /unexpected break/, bug18475)
+ e = Enumerator.new do |g|
+ Thread.new do
+ g << 1
+ end.join
+ end
+
+ e.first
+ end;
end
def test_sort
@@ -731,6 +750,9 @@ class TestEnumerable < Test::Unit::TestCase
ary.clear
(1..10).each_slice(11) {|a| ary << a}
assert_equal([[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]], ary)
+
+ assert_equal(1..10, (1..10).each_slice(3) { })
+ assert_equal([], [].each_slice(3) { })
end
def test_each_cons
@@ -750,6 +772,9 @@ class TestEnumerable < Test::Unit::TestCase
ary.clear
(1..5).each_cons(6) {|a| ary << a}
assert_empty(ary)
+
+ assert_equal(1..5, (1..5).each_cons(3) { })
+ assert_equal([], [].each_cons(3) { })
end
def test_zip
@@ -818,6 +843,8 @@ class TestEnumerable < Test::Unit::TestCase
end
def test_callcc
+ omit 'requires callcc support' unless respond_to?(:callcc)
+
assert_raise(RuntimeError) do
c = nil
@obj.sort_by {|x| callcc {|c2| c ||= c2 }; x }
@@ -1309,4 +1336,24 @@ class TestEnumerable < Test::Unit::TestCase
assert_equal([], @obj.filter_map { nil })
assert_instance_of(Enumerator, @obj.filter_map)
end
+
+ def test_ruby_svar
+ klass = Class.new do
+ include Enumerable
+ def each
+ %w(bar baz).each{|e| yield e}
+ end
+ end
+ svars = []
+ klass.new.grep(/(b.)/) { svars << $1 }
+ assert_equal(["ba", "ba"], svars)
+ end
+
+ def test_all_fast
+ data = { "key" => { "key2" => 1 } }
+ kk = vv = nil
+ data.all? { |(k, v)| kk, vv = k, v }
+ assert_equal(kk, "key")
+ assert_equal(vv, { "key2" => 1 })
+ end
end
diff --git a/test/ruby/test_enumerator.rb b/test/ruby/test_enumerator.rb
index c823b79c6d..7599d43463 100644
--- a/test/ruby/test_enumerator.rb
+++ b/test/ruby/test_enumerator.rb
@@ -127,6 +127,17 @@ class TestEnumerator < Test::Unit::TestCase
assert_equal([[1,5],[2,6],[3,7]], @obj.to_enum(:foo, 1, 2, 3).with_index(5).to_a)
end
+ def test_with_index_under_gc_compact_stress
+ omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077
+ EnvUtil.under_gc_compact_stress do
+ assert_equal([[1, 0], [2, 1], [3, 2]], @obj.to_enum(:foo, 1, 2, 3).with_index.to_a)
+ assert_equal([[1, 5], [2, 6], [3, 7]], @obj.to_enum(:foo, 1, 2, 3).with_index(5).to_a)
+
+ s = 1 << (8 * 1.size - 2)
+ assert_equal([[1, s], [2, s + 1], [3, s + 2]], @obj.to_enum(:foo, 1, 2, 3).with_index(s).to_a)
+ end
+ end
+
def test_with_index_large_offset
bug8010 = '[ruby-dev:47131] [Bug #8010]'
s = 1 << (8*1.size-2)
@@ -244,6 +255,26 @@ class TestEnumerator < Test::Unit::TestCase
assert_equal(res, exc.result)
end
+ def test_stopiteration_rescue
+ e = [1].each
+ res = e.each {}
+ e.next
+ exc0 = assert_raise(StopIteration) { e.peek }
+ assert_include(exc0.backtrace.first, "test_enumerator.rb:#{__LINE__-1}:")
+ assert_nil(exc0.cause)
+ assert_equal(res, exc0.result)
+
+ exc1 = assert_raise(StopIteration) { e.next }
+ assert_include(exc1.backtrace.first, "test_enumerator.rb:#{__LINE__-1}:")
+ assert_same(exc0, exc1.cause)
+ assert_equal(res, exc1.result)
+
+ exc2 = assert_raise(StopIteration) { e.next }
+ assert_include(exc2.backtrace.first, "test_enumerator.rb:#{__LINE__-1}:")
+ assert_same(exc0, exc2.cause)
+ assert_equal(res, exc2.result)
+ end
+
def test_next_values
o = Object.new
def o.each
@@ -832,6 +863,21 @@ class TestEnumerator < Test::Unit::TestCase
assert_equal(33, chain.next)
end
+ def test_lazy_chain_under_gc_compact_stress
+ omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077
+ EnvUtil.under_gc_compact_stress do
+ ea = (10..).lazy.select(&:even?).take(10)
+ ed = (20..).lazy.select(&:odd?)
+ chain = (ea + ed).select{|x| x % 3 == 0}
+ assert_equal(12, chain.next)
+ assert_equal(18, chain.next)
+ assert_equal(24, chain.next)
+ assert_equal(21, chain.next)
+ assert_equal(27, chain.next)
+ assert_equal(33, chain.next)
+ end
+ end
+
def test_chain_undef_methods
chain = [1].to_enum + [2].to_enum
meths = (chain.methods & [:feed, :next, :next_values, :peek, :peek_values])
@@ -906,4 +952,95 @@ class TestEnumerator < Test::Unit::TestCase
e.chain.each(&->{})
assert_equal(true, e.is_lambda)
end
+
+ def test_product_new
+ # 0-dimensional
+ e = Enumerator::Product.new
+ assert_instance_of(Enumerator::Product, e)
+ assert_kind_of(Enumerator, e)
+ assert_equal(1, e.size)
+ elts = []
+ e.each { |x| elts << x }
+ assert_equal [[]], elts
+ assert_equal elts, e.to_a
+ heads = []
+ e.each { |x,| heads << x }
+ assert_equal [nil], heads
+
+ # 1-dimensional
+ e = Enumerator::Product.new(1..3)
+ assert_instance_of(Enumerator::Product, e)
+ assert_kind_of(Enumerator, e)
+ assert_equal(3, e.size)
+ elts = []
+ e.each { |x| elts << x }
+ assert_equal [[1], [2], [3]], elts
+ assert_equal elts, e.to_a
+
+ # 2-dimensional
+ e = Enumerator::Product.new(1..3, %w[a b])
+ assert_instance_of(Enumerator::Product, e)
+ assert_kind_of(Enumerator, e)
+ assert_equal(3 * 2, e.size)
+ elts = []
+ e.each { |x| elts << x }
+ assert_equal [[1, "a"], [1, "b"], [2, "a"], [2, "b"], [3, "a"], [3, "b"]], elts
+ assert_equal elts, e.to_a
+ heads = []
+ e.each { |x,| heads << x }
+ assert_equal [1, 1, 2, 2, 3, 3], heads
+
+ # Any enumerable is 0 size
+ assert_equal(0, Enumerator::Product.new([], 1..).size)
+
+ # Reject keyword arguments
+ assert_raise(ArgumentError) {
+ Enumerator::Product.new(1..3, foo: 1, bar: 2)
+ }
+ end
+
+ def test_s_product
+ # without a block
+ e = Enumerator.product(1..3, %w[a b])
+ assert_instance_of(Enumerator::Product, e)
+
+ # with a block
+ elts = []
+ ret = Enumerator.product(1..3) { |x| elts << x }
+ assert_equal(nil, ret)
+ assert_equal [[1], [2], [3]], elts
+ assert_equal elts, Enumerator.product(1..3).to_a
+
+ # an infinite enumerator and a finite enumerable
+ e = Enumerator.product(1.., 'a'..'c')
+ assert_equal(Float::INFINITY, e.size)
+ assert_equal [[1, "a"], [1, "b"], [1, "c"], [2, "a"]], e.take(4)
+
+ # an infinite enumerator and an unknown enumerator
+ e = Enumerator.product(1.., Enumerator.new { |y| y << 'a' << 'b' })
+ assert_equal(Float::INFINITY, e.size)
+ assert_equal [[1, "a"], [1, "b"], [2, "a"], [2, "b"]], e.take(4)
+
+ # an infinite enumerator and an unknown enumerator
+ e = Enumerator.product(1..3, Enumerator.new { |y| y << 'a' << 'b' })
+ assert_equal(nil, e.size)
+ assert_equal [[1, "a"], [1, "b"], [2, "a"], [2, "b"]], e.take(4)
+
+ assert_equal(0, Enumerator.product([], 1..).size)
+
+ # Reject keyword arguments
+ assert_raise(ArgumentError) {
+ Enumerator.product(1..3, foo: 1, bar: 2)
+ }
+ end
+
+ def test_freeze
+ e = 3.times.freeze
+ assert_raise(FrozenError) { e.next }
+ assert_raise(FrozenError) { e.next_values }
+ assert_raise(FrozenError) { e.peek }
+ assert_raise(FrozenError) { e.peek_values }
+ assert_raise(FrozenError) { e.feed 1 }
+ assert_raise(FrozenError) { e.rewind }
+ end
end
diff --git a/test/ruby/test_env.rb b/test/ruby/test_env.rb
index ea0f367334..4b5f18e7bb 100644
--- a/test/ruby/test_env.rb
+++ b/test/ruby/test_env.rb
@@ -69,25 +69,20 @@ class TestEnv < Test::Unit::TestCase
end
def test_clone
- warning = /ENV\.clone is deprecated; use ENV\.to_h instead/
- clone = assert_deprecated_warning(warning) {
+ message = /Cannot clone ENV/
+ assert_raise_with_message(TypeError, message) {
ENV.clone
}
- assert_same(ENV, clone)
-
- clone = assert_deprecated_warning(warning) {
+ assert_raise_with_message(TypeError, message) {
ENV.clone(freeze: false)
}
- assert_same(ENV, clone)
-
- clone = assert_deprecated_warning(warning) {
+ assert_raise_with_message(TypeError, message) {
ENV.clone(freeze: nil)
}
- assert_same(ENV, clone)
-
- assert_raise(TypeError) {
+ assert_raise_with_message(TypeError, message) {
ENV.clone(freeze: true)
}
+
assert_raise(ArgumentError) {
ENV.clone(freeze: 1)
}
@@ -494,16 +489,24 @@ class TestEnv < Test::Unit::TestCase
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.update
+ check(ENV.to_hash.to_a, [%w(foo bar), %w(baz quux), %w(a b)])
+ ENV.update({"foo"=>"zot"}, {"c"=>"d"})
+ check(ENV.to_hash.to_a, [%w(foo zot), %w(baz quux), %w(a b), %w(c d)])
ENV.clear
ENV["foo"] = "bar"
ENV["baz"] = "qux"
ENV.update({"baz"=>"quux","a"=>"b"}) {|k, v1, v2| k + "_" + v1 + "_" + v2 }
check(ENV.to_hash.to_a, [%w(foo bar), %w(baz baz_qux_quux), %w(a b)])
+ ENV.update {|k, v1, v2| k + "_" + v1 + "_" + v2 }
+ check(ENV.to_hash.to_a, [%w(foo bar), %w(baz baz_qux_quux), %w(a b)])
+ ENV.update({"foo"=>"zot"}, {"c"=>"d"}) {|k, v1, v2| k + "_" + v1 + "_" + v2 }
+ check(ENV.to_hash.to_a, [%w(foo foo_bar_zot), %w(baz baz_qux_quux), %w(a b), %w(c d)])
end
def test_huge_value
- if /mswin/ =~ RUBY_PLATFORM || /ucrt/ =~ RbConfig::CONFIG['sitearch']
+ if /mswin|ucrt/ =~ RUBY_PLATFORM
# On Windows >= Vista each environment variable can be max 32768 characters
huge_value = "bar" * 10900
else
@@ -578,6 +581,861 @@ class TestEnv < Test::Unit::TestCase
assert_nil(e1, bug12475)
end
+ def ignore_case_str
+ IGNORE_CASE ? "true" : "false"
+ end
+
+ def str_for_yielding_exception_class(code_str, exception_var: "raised_exception")
+ <<-"end;"
+ #{exception_var} = nil
+ begin
+ #{code_str}
+ rescue Exception => e
+ #{exception_var} = e
+ end
+ Ractor.yield #{exception_var}.class
+ end;
+ end
+
+ def str_for_assert_raise_on_yielded_exception_class(expected_error_class, ractor_var)
+ <<-"end;"
+ error_class = #{ractor_var}.take
+ assert_raise(#{expected_error_class}) do
+ if error_class < Exception
+ raise error_class
+ end
+ end
+ end;
+ end
+
+ def str_to_yield_invalid_envvar_errors(var_name, code_str)
+ <<-"end;"
+ envvars_to_check = [
+ "foo\0bar",
+ "#{'\xa1\xa1'}".dup.force_encoding(Encoding::UTF_16LE),
+ "foo".dup.force_encoding(Encoding::ISO_2022_JP),
+ ]
+ envvars_to_check.each do |#{var_name}|
+ #{str_for_yielding_exception_class(code_str)}
+ end
+ end;
+ end
+
+ def str_to_receive_invalid_envvar_errors(ractor_var)
+ <<-"end;"
+ 3.times do
+ #{str_for_assert_raise_on_yielded_exception_class(ArgumentError, ractor_var)}
+ end
+ end;
+ end
+
+ STR_DEFINITION_FOR_CHECK = %Q{
+ def check(as, bs)
+ if #{IGNORE_CASE ? "true" : "false"}
+ as = as.map {|k, v| [k.upcase, v] }
+ bs = bs.map {|k, v| [k.upcase, v] }
+ end
+ assert_equal(as.sort, bs.sort)
+ end
+ }
+
+ def test_bracket_in_ractor
+ assert_ractor(<<-"end;")
+ r = Ractor.new do
+ Ractor.yield ENV['test']
+ Ractor.yield ENV['TEST']
+ ENV['test'] = 'foo'
+ Ractor.yield ENV['test']
+ Ractor.yield ENV['TEST']
+ ENV['TEST'] = 'bar'
+ Ractor.yield ENV['TEST']
+ Ractor.yield ENV['test']
+ #{str_for_yielding_exception_class("ENV[1]")}
+ #{str_for_yielding_exception_class("ENV[1] = 'foo'")}
+ #{str_for_yielding_exception_class("ENV['test'] = 0")}
+ end
+ assert_nil(r.take)
+ assert_nil(r.take)
+ assert_equal('foo', r.take)
+ if #{ignore_case_str}
+ assert_equal('foo', r.take)
+ else
+ assert_nil(r.take)
+ end
+ assert_equal('bar', r.take)
+ if #{ignore_case_str}
+ assert_equal('bar', r.take)
+ else
+ assert_equal('foo', r.take)
+ end
+ 3.times do
+ #{str_for_assert_raise_on_yielded_exception_class(TypeError, "r")}
+ end
+ end;
+ end
+
+ def test_dup_in_ractor
+ assert_ractor(<<-"end;")
+ r = Ractor.new do
+ #{str_for_yielding_exception_class("ENV.dup")}
+ end
+ #{str_for_assert_raise_on_yielded_exception_class(TypeError, "r")}
+ end;
+ end
+
+ def test_has_value_in_ractor
+ assert_ractor(<<-"end;")
+ r = Ractor.new do
+ val = 'a'
+ val.succ! while ENV.has_value?(val) || ENV.has_value?(val.upcase)
+ ENV['test'] = val[0...-1]
+ Ractor.yield(ENV.has_value?(val))
+ Ractor.yield(ENV.has_value?(val.upcase))
+ ENV['test'] = val
+ Ractor.yield(ENV.has_value?(val))
+ Ractor.yield(ENV.has_value?(val.upcase))
+ ENV['test'] = val.upcase
+ Ractor.yield ENV.has_value?(val)
+ Ractor.yield ENV.has_value?(val.upcase)
+ end
+ assert_equal(false, r.take)
+ assert_equal(false, r.take)
+ assert_equal(true, r.take)
+ assert_equal(false, r.take)
+ assert_equal(false, r.take)
+ assert_equal(true, r.take)
+ end;
+ end
+
+ def test_key_in_ractor
+ assert_ractor(<<-"end;")
+ r = Ractor.new do
+ val = 'a'
+ val.succ! while ENV.has_value?(val) || ENV.has_value?(val.upcase)
+ ENV['test'] = val[0...-1]
+ Ractor.yield ENV.key(val)
+ Ractor.yield ENV.key(val.upcase)
+ ENV['test'] = val
+ Ractor.yield ENV.key(val)
+ Ractor.yield ENV.key(val.upcase)
+ ENV['test'] = val.upcase
+ Ractor.yield ENV.key(val)
+ Ractor.yield ENV.key(val.upcase)
+ end
+ assert_nil(r.take)
+ assert_nil(r.take)
+ if #{ignore_case_str}
+ assert_equal('TEST', r.take.upcase)
+ else
+ assert_equal('test', r.take)
+ end
+ assert_nil(r.take)
+ assert_nil(r.take)
+ if #{ignore_case_str}
+ assert_equal('TEST', r.take.upcase)
+ else
+ assert_equal('test', r.take)
+ end
+ end;
+
+ end
+
+ def test_delete_in_ractor
+ assert_ractor(<<-"end;")
+ r = Ractor.new do
+ #{str_to_yield_invalid_envvar_errors("v", "ENV.delete(v)")}
+ Ractor.yield ENV.delete("TEST")
+ #{str_for_yielding_exception_class("ENV.delete('#{PATH_ENV}')")}
+ Ractor.yield(ENV.delete("TEST"){|name| "NO "+name})
+ end
+ #{str_to_receive_invalid_envvar_errors("r")}
+ assert_nil(r.take)
+ exception_class = r.take
+ assert_equal(NilClass, exception_class)
+ assert_equal("NO TEST", r.take)
+ end;
+ end
+
+ def test_getenv_in_ractor
+ assert_ractor(<<-"end;")
+ r = Ractor.new do
+ #{str_to_yield_invalid_envvar_errors("v", "ENV[v]")}
+ ENV["#{PATH_ENV}"] = ""
+ Ractor.yield ENV["#{PATH_ENV}"]
+ Ractor.yield ENV[""]
+ end
+ #{str_to_receive_invalid_envvar_errors("r")}
+ assert_equal("", r.take)
+ assert_nil(r.take)
+ end;
+ end
+
+ def test_fetch_in_ractor
+ assert_ractor(<<-"end;")
+ r = Ractor.new do
+ ENV["test"] = "foo"
+ Ractor.yield ENV.fetch("test")
+ ENV.delete("test")
+ #{str_for_yielding_exception_class("ENV.fetch('test')", exception_var: "ex")}
+ Ractor.yield ex.receiver.object_id
+ Ractor.yield ex.key
+ Ractor.yield ENV.fetch("test", "foo")
+ Ractor.yield(ENV.fetch("test"){"bar"})
+ #{str_to_yield_invalid_envvar_errors("v", "ENV.fetch(v)")}
+ #{str_for_yielding_exception_class("ENV.fetch('#{PATH_ENV}', 'foo')")}
+ ENV['#{PATH_ENV}'] = ""
+ Ractor.yield ENV.fetch('#{PATH_ENV}')
+ end
+ assert_equal("foo", r.take)
+ #{str_for_assert_raise_on_yielded_exception_class(KeyError, "r")}
+ assert_equal(ENV.object_id, r.take)
+ assert_equal("test", r.take)
+ assert_equal("foo", r.take)
+ assert_equal("bar", r.take)
+ #{str_to_receive_invalid_envvar_errors("r")}
+ exception_class = r.take
+ assert_equal(NilClass, exception_class)
+ assert_equal("", r.take)
+ end;
+ end
+
+ def test_aset_in_ractor
+ assert_ractor(<<-"end;")
+ r = Ractor.new do
+ #{str_for_yielding_exception_class("ENV['test'] = nil")}
+ ENV["test"] = nil
+ Ractor.yield ENV["test"]
+ #{str_to_yield_invalid_envvar_errors("v", "ENV[v] = 'test'")}
+ #{str_to_yield_invalid_envvar_errors("v", "ENV['test'] = v")}
+ end
+ exception_class = r.take
+ assert_equal(NilClass, exception_class)
+ assert_nil(r.take)
+ #{str_to_receive_invalid_envvar_errors("r")}
+ #{str_to_receive_invalid_envvar_errors("r")}
+ end;
+ end
+
+ def test_keys_in_ractor
+ assert_ractor(<<-"end;")
+ r = Ractor.new do
+ a = ENV.keys
+ Ractor.yield a
+ end
+ a = r.take
+ assert_kind_of(Array, a)
+ a.each {|k| assert_kind_of(String, k) }
+ end;
+
+ end
+
+ def test_each_key_in_ractor
+ assert_ractor(<<-"end;")
+ r = Ractor.new do
+ ENV.each_key {|k| Ractor.yield(k)}
+ Ractor.yield "finished"
+ end
+ while((x=r.take) != "finished")
+ assert_kind_of(String, x)
+ end
+ end;
+ end
+
+ def test_values_in_ractor
+ assert_ractor(<<-"end;")
+ r = Ractor.new do
+ a = ENV.values
+ Ractor.yield a
+ end
+ a = r.take
+ assert_kind_of(Array, a)
+ a.each {|k| assert_kind_of(String, k) }
+ end;
+ end
+
+ def test_each_value_in_ractor
+ assert_ractor(<<-"end;")
+ r = Ractor.new do
+ ENV.each_value {|k| Ractor.yield(k)}
+ Ractor.yield "finished"
+ end
+ while((x=r.take) != "finished")
+ assert_kind_of(String, x)
+ end
+ end;
+ end
+
+ def test_each_pair_in_ractor
+ assert_ractor(<<-"end;")
+ r = Ractor.new do
+ ENV.each_pair {|k, v| Ractor.yield([k,v])}
+ Ractor.yield "finished"
+ end
+ while((k,v=r.take) != "finished")
+ assert_kind_of(String, k)
+ assert_kind_of(String, v)
+ end
+ end;
+ end
+
+ def test_reject_bang_in_ractor
+ assert_ractor(<<-"end;")
+ r = Ractor.new do
+ h1 = {}
+ ENV.each_pair {|k, v| h1[k] = v }
+ ENV["test"] = "foo"
+ ENV.reject! {|k, v| #{ignore_case_str} ? k.upcase == "TEST" : k == "test" }
+ h2 = {}
+ ENV.each_pair {|k, v| h2[k] = v }
+ Ractor.yield [h1, h2]
+ Ractor.yield(ENV.reject! {|k, v| #{ignore_case_str} ? k.upcase == "TEST" : k == "test" })
+ end
+ h1, h2 = r.take
+ assert_equal(h1, h2)
+ assert_nil(r.take)
+ end;
+ end
+
+ def test_delete_if_in_ractor
+ assert_ractor(<<-"end;")
+ r = Ractor.new do
+ h1 = {}
+ ENV.each_pair {|k, v| h1[k] = v }
+ ENV["test"] = "foo"
+ ENV.delete_if {|k, v| #{ignore_case_str} ? k.upcase == "TEST" : k == "test" }
+ h2 = {}
+ ENV.each_pair {|k, v| h2[k] = v }
+ Ractor.yield [h1, h2]
+ Ractor.yield (ENV.delete_if {|k, v| #{ignore_case_str} ? k.upcase == "TEST" : k == "test" }).object_id
+ end
+ h1, h2 = r.take
+ assert_equal(h1, h2)
+ assert_equal(ENV.object_id, r.take)
+ end;
+ end
+
+ def test_select_bang_in_ractor
+ assert_ractor(<<-"end;")
+ r = Ractor.new do
+ h1 = {}
+ ENV.each_pair {|k, v| h1[k] = v }
+ ENV["test"] = "foo"
+ ENV.select! {|k, v| #{ignore_case_str} ? k.upcase != "TEST" : k != "test" }
+ h2 = {}
+ ENV.each_pair {|k, v| h2[k] = v }
+ Ractor.yield [h1, h2]
+ Ractor.yield(ENV.select! {|k, v| #{ignore_case_str} ? k.upcase != "TEST" : k != "test" })
+ end
+ h1, h2 = r.take
+ assert_equal(h1, h2)
+ assert_nil(r.take)
+ end;
+ end
+
+ def test_filter_bang_in_ractor
+ assert_ractor(<<-"end;")
+ r = Ractor.new do
+ h1 = {}
+ ENV.each_pair {|k, v| h1[k] = v }
+ ENV["test"] = "foo"
+ ENV.filter! {|k, v| #{ignore_case_str} ? k.upcase != "TEST" : k != "test" }
+ h2 = {}
+ ENV.each_pair {|k, v| h2[k] = v }
+ Ractor.yield [h1, h2]
+ Ractor.yield(ENV.filter! {|k, v| #{ignore_case_str} ? k.upcase != "TEST" : k != "test" })
+ end
+ h1, h2 = r.take
+ assert_equal(h1, h2)
+ assert_nil(r.take)
+ end;
+ end
+
+ def test_keep_if_in_ractor
+ assert_ractor(<<-"end;")
+ r = Ractor.new do
+ h1 = {}
+ ENV.each_pair {|k, v| h1[k] = v }
+ ENV["test"] = "foo"
+ ENV.keep_if {|k, v| #{ignore_case_str} ? k.upcase != "TEST" : k != "test" }
+ h2 = {}
+ ENV.each_pair {|k, v| h2[k] = v }
+ Ractor.yield [h1, h2]
+ Ractor.yield (ENV.keep_if {|k, v| #{ignore_case_str} ? k.upcase != "TEST" : k != "test" }).object_id
+ end
+ h1, h2 = r.take
+ assert_equal(h1, h2)
+ assert_equal(ENV.object_id, r.take)
+ end;
+ end
+
+ def test_values_at_in_ractor
+ assert_ractor(<<-"end;")
+ r = Ractor.new do
+ ENV["test"] = "foo"
+ Ractor.yield ENV.values_at("test", "test")
+ end
+ assert_equal(["foo", "foo"], r.take)
+ end;
+ end
+
+ def test_select_in_ractor
+ assert_ractor(<<-"end;")
+ r = Ractor.new do
+ ENV["test"] = "foo"
+ h = ENV.select {|k| #{ignore_case_str} ? k.upcase == "TEST" : k == "test" }
+ Ractor.yield h.size
+ k = h.keys.first
+ v = h.values.first
+ Ractor.yield [k, v]
+ end
+ assert_equal(1, r.take)
+ k, v = r.take
+ if #{ignore_case_str}
+ assert_equal("TEST", k.upcase)
+ assert_equal("FOO", v.upcase)
+ else
+ assert_equal("test", k)
+ assert_equal("foo", v)
+ end
+ end;
+ end
+
+ def test_filter_in_ractor
+ assert_ractor(<<-"end;")
+ r = Ractor.new do
+ ENV["test"] = "foo"
+ h = ENV.filter {|k| #{ignore_case_str} ? k.upcase == "TEST" : k == "test" }
+ Ractor.yield(h.size)
+ k = h.keys.first
+ v = h.values.first
+ Ractor.yield [k, v]
+ end
+ assert_equal(1, r.take)
+ k, v = r.take
+ if #{ignore_case_str}
+ assert_equal("TEST", k.upcase)
+ assert_equal("FOO", v.upcase)
+ else
+ assert_equal("test", k)
+ assert_equal("foo", v)
+ end
+ end;
+ end
+
+ def test_slice_in_ractor
+ assert_ractor(<<-"end;")
+ r = Ractor.new do
+ ENV.clear
+ ENV["foo"] = "bar"
+ ENV["baz"] = "qux"
+ ENV["bar"] = "rab"
+ Ractor.yield(ENV.slice())
+ Ractor.yield(ENV.slice(""))
+ Ractor.yield(ENV.slice("unknown"))
+ Ractor.yield(ENV.slice("foo", "baz"))
+ end
+ assert_equal({}, r.take)
+ assert_equal({}, r.take)
+ assert_equal({}, r.take)
+ assert_equal({"foo"=>"bar", "baz"=>"qux"}, r.take)
+ end;
+ end
+
+ def test_except_in_ractor
+ assert_ractor(<<-"end;")
+ r = Ractor.new do
+ ENV.clear
+ ENV["foo"] = "bar"
+ ENV["baz"] = "qux"
+ ENV["bar"] = "rab"
+ Ractor.yield ENV.except()
+ Ractor.yield ENV.except("")
+ Ractor.yield ENV.except("unknown")
+ Ractor.yield ENV.except("foo", "baz")
+ end
+ assert_equal({"bar"=>"rab", "baz"=>"qux", "foo"=>"bar"}, r.take)
+ assert_equal({"bar"=>"rab", "baz"=>"qux", "foo"=>"bar"}, r.take)
+ assert_equal({"bar"=>"rab", "baz"=>"qux", "foo"=>"bar"}, r.take)
+ assert_equal({"bar"=>"rab"}, r.take)
+ end;
+ end
+
+ def test_clear_in_ractor
+ assert_ractor(<<-"end;")
+ r = Ractor.new do
+ ENV.clear
+ Ractor.yield ENV.size
+ end
+ assert_equal(0, r.take)
+ end;
+ end
+
+ def test_to_s_in_ractor
+ assert_ractor(<<-"end;")
+ r = Ractor.new do
+ ENV.to_s
+ end
+ assert_equal("ENV", r.take)
+ end;
+ end
+
+ def test_inspect_in_ractor
+ assert_ractor(<<-"end;")
+ r = Ractor.new do
+ ENV.clear
+ ENV["foo"] = "bar"
+ ENV["baz"] = "qux"
+ s = ENV.inspect
+ Ractor.yield s
+ end
+ s = r.take
+ if #{ignore_case_str}
+ 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;
+ end
+
+ def test_to_a_in_ractor
+ assert_ractor(<<-"end;")
+ r = Ractor.new do
+ ENV.clear
+ ENV["foo"] = "bar"
+ ENV["baz"] = "qux"
+ a = ENV.to_a
+ Ractor.yield a
+ end
+ a = r.take
+ assert_equal(2, a.size)
+ if #{ignore_case_str}
+ 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;
+ end
+
+ def test_rehash_in_ractor
+ assert_ractor(<<-"end;")
+ r = Ractor.new do
+ ENV.rehash
+ end
+ assert_nil(r.take)
+ end;
+ end
+
+ def test_size_in_ractor
+ assert_ractor(<<-"end;")
+ r = Ractor.new do
+ s = ENV.size
+ ENV["test"] = "foo"
+ Ractor.yield [s, ENV.size]
+ end
+ s, s2 = r.take
+ assert_equal(s + 1, s2)
+ end;
+ end
+
+ def test_empty_p_in_ractor
+ assert_ractor(<<-"end;")
+ r = Ractor.new do
+ ENV.clear
+ Ractor.yield ENV.empty?
+ ENV["test"] = "foo"
+ Ractor.yield ENV.empty?
+ end
+ assert r.take
+ assert !r.take
+ end;
+ end
+
+ def test_has_key_in_ractor
+ assert_ractor(<<-"end;")
+ r = Ractor.new do
+ Ractor.yield ENV.has_key?("test")
+ ENV["test"] = "foo"
+ Ractor.yield ENV.has_key?("test")
+ #{str_to_yield_invalid_envvar_errors("v", "ENV.has_key?(v)")}
+ end
+ assert !r.take
+ assert r.take
+ #{str_to_receive_invalid_envvar_errors("r")}
+ end;
+ end
+
+ def test_assoc_in_ractor
+ assert_ractor(<<-"end;")
+ r = Ractor.new do
+ Ractor.yield ENV.assoc("test")
+ ENV["test"] = "foo"
+ Ractor.yield ENV.assoc("test")
+ #{str_to_yield_invalid_envvar_errors("v", "ENV.assoc(v)")}
+ end
+ assert_nil(r.take)
+ k, v = r.take
+ if #{ignore_case_str}
+ assert_equal("TEST", k.upcase)
+ assert_equal("FOO", v.upcase)
+ else
+ assert_equal("test", k)
+ assert_equal("foo", v)
+ end
+ #{str_to_receive_invalid_envvar_errors("r")}
+ encoding = /mswin|mingw/ =~ RUBY_PLATFORM ? Encoding::UTF_8 : Encoding.find("locale")
+ assert_equal(encoding, v.encoding)
+ end;
+ end
+
+ def test_has_value2_in_ractor
+ assert_ractor(<<-"end;")
+ r = Ractor.new do
+ ENV.clear
+ Ractor.yield ENV.has_value?("foo")
+ ENV["test"] = "foo"
+ Ractor.yield ENV.has_value?("foo")
+ end
+ assert !r.take
+ assert r.take
+ end;
+ end
+
+ def test_rassoc_in_ractor
+ assert_ractor(<<-"end;")
+ r = Ractor.new do
+ ENV.clear
+ Ractor.yield ENV.rassoc("foo")
+ ENV["foo"] = "bar"
+ ENV["test"] = "foo"
+ ENV["baz"] = "qux"
+ Ractor.yield ENV.rassoc("foo")
+ end
+ assert_nil(r.take)
+ k, v = r.take
+ if #{ignore_case_str}
+ assert_equal("TEST", k.upcase)
+ assert_equal("FOO", v.upcase)
+ else
+ assert_equal("test", k)
+ assert_equal("foo", v)
+ end
+ end;
+ end
+
+ def test_to_hash_in_ractor
+ assert_ractor(<<-"end;")
+ r = Ractor.new do
+ h = {}
+ ENV.each {|k, v| h[k] = v }
+ Ractor.yield [h, ENV.to_hash]
+ end
+ h, h2 = r.take
+ assert_equal(h, h2)
+ end;
+ end
+
+ def test_to_h_in_ractor
+ assert_ractor(<<-"end;")
+ r = Ractor.new do
+ Ractor.yield [ENV.to_hash, ENV.to_h]
+ Ractor.yield [ENV.map {|k, v| ["$\#{k}", v.size]}.to_h, ENV.to_h {|k, v| ["$\#{k}", v.size]}]
+ end
+ a, b = r.take
+ assert_equal(a,b)
+ c, d = r.take
+ assert_equal(c,d)
+ end;
+ end
+
+ def test_reject_in_ractor
+ assert_ractor(<<-"end;")
+ r = Ractor.new do
+ h1 = {}
+ ENV.each_pair {|k, v| h1[k] = v }
+ ENV["test"] = "foo"
+ h2 = ENV.reject {|k, v| #{ignore_case_str} ? k.upcase == "TEST" : k == "test" }
+ Ractor.yield [h1, h2]
+ end
+ h1, h2 = r.take
+ assert_equal(h1, h2)
+ end;
+ end
+
+ def test_shift_in_ractor
+ assert_ractor(<<-"end;")
+ #{STR_DEFINITION_FOR_CHECK}
+ r = Ractor.new do
+ ENV.clear
+ ENV["foo"] = "bar"
+ ENV["baz"] = "qux"
+ a = ENV.shift
+ b = ENV.shift
+ Ractor.yield [a,b]
+ Ractor.yield ENV.shift
+ end
+ a,b = r.take
+ check([a, b], [%w(foo bar), %w(baz qux)])
+ assert_nil(r.take)
+ end;
+ end
+
+ def test_invert_in_ractor
+ assert_ractor(<<-"end;")
+ #{STR_DEFINITION_FOR_CHECK}
+ r = Ractor.new do
+ ENV.clear
+ ENV["foo"] = "bar"
+ ENV["baz"] = "qux"
+ Ractor.yield(ENV.invert)
+ end
+ check(r.take.to_a, [%w(bar foo), %w(qux baz)])
+ end;
+ end
+
+ def test_replace_in_ractor
+ assert_ractor(<<-"end;")
+ #{STR_DEFINITION_FOR_CHECK}
+ r = Ractor.new do
+ ENV["foo"] = "xxx"
+ ENV.replace({"foo"=>"bar", "baz"=>"qux"})
+ Ractor.yield ENV.to_hash
+ ENV.replace({"Foo"=>"Bar", "Baz"=>"Qux"})
+ Ractor.yield ENV.to_hash
+ end
+ check(r.take.to_a, [%w(foo bar), %w(baz qux)])
+ check(r.take.to_a, [%w(Foo Bar), %w(Baz Qux)])
+ end;
+ end
+
+ def test_update_in_ractor
+ assert_ractor(<<-"end;")
+ #{STR_DEFINITION_FOR_CHECK}
+ r = Ractor.new do
+ ENV.clear
+ ENV["foo"] = "bar"
+ ENV["baz"] = "qux"
+ ENV.update({"baz"=>"quux","a"=>"b"})
+ Ractor.yield ENV.to_hash
+ ENV.clear
+ ENV["foo"] = "bar"
+ ENV["baz"] = "qux"
+ ENV.update({"baz"=>"quux","a"=>"b"}) {|k, v1, v2| k + "_" + v1 + "_" + v2 }
+ Ractor.yield ENV.to_hash
+ end
+ check(r.take.to_a, [%w(foo bar), %w(baz quux), %w(a b)])
+ check(r.take.to_a, [%w(foo bar), %w(baz baz_qux_quux), %w(a b)])
+ end;
+ end
+
+ def test_huge_value_in_ractor
+ assert_ractor(<<-"end;")
+ huge_value = "bar" * 40960
+ r = Ractor.new huge_value do |v|
+ ENV["foo"] = "bar"
+ #{str_for_yielding_exception_class("ENV['foo'] = v ")}
+ Ractor.yield ENV["foo"]
+ end
+
+ if /mswin|ucrt/ =~ RUBY_PLATFORM
+ #{str_for_assert_raise_on_yielded_exception_class(Errno::EINVAL, "r")}
+ result = r.take
+ assert_equal("bar", result)
+ else
+ exception_class = r.take
+ assert_equal(NilClass, exception_class)
+ result = r.take
+ assert_equal(huge_value, result)
+ end
+ end;
+ end
+
+ def test_frozen_env_in_ractor
+ assert_ractor(<<-"end;")
+ r = Ractor.new do
+ #{str_for_yielding_exception_class("ENV.freeze")}
+ end
+ #{str_for_assert_raise_on_yielded_exception_class(TypeError, "r")}
+ end;
+ end
+
+ def test_frozen_in_ractor
+ assert_ractor(<<-"end;")
+ r = Ractor.new do
+ ENV["#{PATH_ENV}"] = "/"
+ ENV.each do |k, v|
+ Ractor.yield [k.frozen?]
+ Ractor.yield [v.frozen?]
+ end
+ ENV.each_key do |k|
+ Ractor.yield [k.frozen?]
+ end
+ ENV.each_value do |v|
+ Ractor.yield [v.frozen?]
+ end
+ ENV.each_key do |k|
+ Ractor.yield [ENV[k].frozen?, "[\#{k.dump}]"]
+ Ractor.yield [ENV.fetch(k).frozen?, "fetch(\#{k.dump})"]
+ end
+ Ractor.yield "finished"
+ end
+ while((params=r.take) != "finished")
+ assert(*params)
+ end
+ end;
+ end
+
+ def test_shared_substring_in_ractor
+ assert_ractor(<<-"end;")
+ r = Ractor.new do
+ bug12475 = '[ruby-dev:49655] [Bug #12475]'
+ n = [*"0".."9"].join("")*3
+ e0 = ENV[n0 = "E\#{n}"]
+ e1 = ENV[n1 = "E\#{n}."]
+ ENV[n0] = nil
+ ENV[n1] = nil
+ ENV[n1.chop] = "T\#{n}.".chop
+ ENV[n0], e0 = e0, ENV[n0]
+ ENV[n1], e1 = e1, ENV[n1]
+ Ractor.yield [n, e0, e1, bug12475]
+ end
+ n, e0, e1, bug12475 = r.take
+ assert_equal("T\#{n}", e0, bug12475)
+ assert_nil(e1, bug12475)
+ end;
+ end
+
+ def test_ivar_in_env_should_not_be_access_from_non_main_ractors
+ assert_ractor <<~RUBY
+ ENV.instance_eval{ @a = "hello" }
+ assert_equal "hello", ENV.instance_variable_get(:@a)
+
+ r_get = Ractor.new do
+ ENV.instance_variable_get(:@a)
+ rescue Ractor::IsolationError => e
+ e
+ end
+ assert_equal Ractor::IsolationError, r_get.take.class
+
+ r_get = Ractor.new do
+ ENV.instance_eval{ @a }
+ rescue Ractor::IsolationError => e
+ e
+ end
+
+ assert_equal Ractor::IsolationError, r_get.take.class
+
+ r_set = Ractor.new do
+ ENV.instance_eval{ @b = "hello" }
+ rescue Ractor::IsolationError => e
+ e
+ end
+
+ assert_equal Ractor::IsolationError, r_set.take.class
+ RUBY
+ end
+
if RUBY_PLATFORM =~ /bccwin|mswin|mingw/
def test_memory_leak_aset
bug9977 = '[ruby-dev:48323] [Bug #9977]'
diff --git a/test/ruby/test_eval.rb b/test/ruby/test_eval.rb
index bf551c6845..cf1c2bb2f6 100644
--- a/test/ruby/test_eval.rb
+++ b/test/ruby/test_eval.rb
@@ -219,6 +219,12 @@ class TestEval < Test::Unit::TestCase
end
end
+ def test_instance_exec_cvar
+ [Object.new, [], 7, :sym, true, false, nil].each do |obj|
+ assert_equal(13, obj.instance_exec{@@cvar})
+ end
+ end
+
def test_instance_eval_method
bug2788 = '[ruby-core:28324]'
[Object.new, [], nil, true, false].each do |o|
@@ -253,6 +259,70 @@ class TestEval < Test::Unit::TestCase
assert_equal(2, bar)
end
+ def test_instance_exec_block_basic
+ forall_TYPE do |o|
+ assert_equal nil, o.instance_exec { nil }
+ assert_equal true, o.instance_exec { true }
+ assert_equal false, o.instance_exec { false }
+ assert_equal o, o.instance_exec { self }
+ assert_equal 1, o.instance_exec { 1 }
+ assert_equal :sym, o.instance_exec { :sym }
+
+ assert_equal 11, o.instance_exec { 11 }
+ assert_equal 12, o.instance_exec { @ivar } unless o.frozen?
+ assert_equal 13, o.instance_exec { @@cvar }
+ assert_equal 14, o.instance_exec { $gvar__eval }
+ assert_equal 15, o.instance_exec { Const }
+ assert_equal 16, o.instance_exec { 7 + 9 }
+ assert_equal 17, o.instance_exec { 17.to_i }
+ assert_equal "18", o.instance_exec { "18" }
+ assert_equal "19", o.instance_exec { "1#{9}" }
+
+ 1.times {
+ assert_equal 12, o.instance_exec { @ivar } unless o.frozen?
+ assert_equal 13, o.instance_exec { @@cvar }
+ assert_equal 14, o.instance_exec { $gvar__eval }
+ assert_equal 15, o.instance_exec { Const }
+ }
+ end
+ end
+
+ def test_instance_exec_method_definition
+ klass = Class.new
+ o = klass.new
+
+ o.instance_exec do
+ def foo
+ :foo_result
+ end
+ end
+
+ assert_respond_to o, :foo
+ refute_respond_to klass, :foo
+ refute_respond_to klass.new, :foo
+
+ assert_equal :foo_result, o.foo
+ end
+
+ def test_instance_exec_eval_method_definition
+ klass = Class.new
+ o = klass.new
+
+ o.instance_exec do
+ eval %{
+ def foo
+ :foo_result
+ end
+ }
+ end
+
+ assert_respond_to o, :foo
+ refute_respond_to klass, :foo
+ refute_respond_to klass.new, :foo
+
+ assert_equal :foo_result, o.foo
+ end
+
#
# From ruby/test/ruby/test_eval.rb
#
@@ -418,6 +488,9 @@ class TestEval < Test::Unit::TestCase
end
end
assert_equal(feature6609, feature6609_method)
+ ensure
+ Object.undef_method(:feature6609_block) rescue nil
+ Object.undef_method(:feature6609_method) rescue nil
end
def test_eval_using_integer_as_binding
@@ -462,6 +535,12 @@ class TestEval < Test::Unit::TestCase
assert_equal(fname, eval("__FILE__", nil, fname, 1))
end
+ def test_eval_invalid_block_exit_bug_20597
+ assert_raise(SyntaxError){eval("break if false")}
+ assert_raise(SyntaxError){eval("next if false")}
+ assert_raise(SyntaxError){eval("redo if false")}
+ end
+
def test_eval_location_fstring
o = Object.new
o.instance_eval "def foo() end", "generated code"
@@ -474,8 +553,8 @@ class TestEval < Test::Unit::TestCase
end
def test_eval_location_binding
- assert_equal(['(eval)', 1], eval("[__FILE__, __LINE__]", nil))
- assert_equal(['(eval)', 1], eval("[__FILE__, __LINE__]", binding))
+ assert_equal(["(eval at #{__FILE__}:#{__LINE__})", 1], eval("[__FILE__, __LINE__]", nil))
+ assert_equal(["(eval at #{__FILE__}:#{__LINE__})", 1], eval("[__FILE__, __LINE__]", binding))
assert_equal(['foo', 1], eval("[__FILE__, __LINE__]", nil, 'foo'))
assert_equal(['foo', 1], eval("[__FILE__, __LINE__]", binding, 'foo'))
assert_equal(['foo', 2], eval("[__FILE__, __LINE__]", nil, 'foo', 2))
diff --git a/test/ruby/test_exception.rb b/test/ruby/test_exception.rb
index 67f38c2e91..09df1b5dcb 100644
--- a/test/ruby/test_exception.rb
+++ b/test/ruby/test_exception.rb
@@ -252,6 +252,27 @@ class TestException < Test::Unit::TestCase
}
end
+ def test_catch_throw_in_require_cant_be_rescued
+ bug18562 = '[ruby-core:107403]'
+ Tempfile.create(["dep", ".rb"]) {|t|
+ t.puts("throw :extdep, 42")
+ t.close
+
+ rescue_all = Class.new(Exception)
+ def rescue_all.===(_)
+ raise "should not reach here"
+ end
+
+ v = assert_throw(:extdep, bug18562) do
+ require t.path
+ rescue rescue_all
+ assert(false, "should not reach here")
+ end
+
+ assert_equal(42, v, bug18562)
+ }
+ end
+
def test_throw_false
bug12743 = '[ruby-core:77229] [Bug #12743]'
Thread.start {
@@ -395,7 +416,7 @@ class TestException < Test::Unit::TestCase
assert_in_out_err([], "$@ = 1", [], /\$! not set \(ArgumentError\)$/)
- assert_in_out_err([], <<-INPUT, [], /backtrace must be Array of String \(TypeError\)$/)
+ assert_in_out_err([], <<-INPUT, [], /backtrace must be an Array of String or an Array of Thread::Backtrace::Location \(TypeError\)$/)
begin
raise
rescue
@@ -423,7 +444,7 @@ class TestException < Test::Unit::TestCase
end
def test_thread_signal_location
- skip
+ # pend('TODO: a known bug [Bug #14474]')
_, stderr, _ = EnvUtil.invoke_ruby(%w"--disable-gems -d", <<-RUBY, false, true)
Thread.start do
Thread.current.report_on_exception = false
@@ -457,6 +478,12 @@ end.join
def to_s; ""; end
end
assert_equal(e.inspect, e.new.inspect)
+
+ # https://bugs.ruby-lang.org/issues/18170#note-13
+ assert_equal('#<Exception:"foo\nbar">', Exception.new("foo\nbar").inspect)
+ assert_equal('#<Exception: foo bar>', Exception.new("foo bar").inspect)
+ assert_equal('#<Exception: foo\bar>', Exception.new("foo\\bar").inspect)
+ assert_equal('#<Exception: "foo\nbar">', Exception.new('"foo\nbar"').inspect)
end
def test_to_s
@@ -481,6 +508,16 @@ end.join
assert_raise(TypeError) { e.set_backtrace(1) }
assert_raise(TypeError) { e.set_backtrace([1]) }
+
+ error = assert_raise(TypeError) do
+ e.set_backtrace(caller_locations(1, 1) + ["foo"])
+ end
+ assert_include error.message, "backtrace must be an Array of String or an Array of Thread::Backtrace::Location"
+
+ error = assert_raise(TypeError) do
+ e.set_backtrace(["foo"] + caller_locations(1, 1))
+ end
+ assert_include error.message, "backtrace must be an Array of String or an Array of Thread::Backtrace::Location"
end
def test_exit_success_p
@@ -513,6 +550,14 @@ end.join
assert_equal(Encoding.find("locale"), Errno::EINVAL.new.message.encoding)
end
+ def test_errno_constants
+ assert_equal [:NOERROR], Errno.constants.grep_v(/\AE/)
+ all_assertions_foreach("should be a subclass of SystemCallError", *Errno.constants) do |c|
+ e = Errno.const_get(c)
+ assert_operator e, :<, SystemCallError, proc {e.ancestors.inspect}
+ end
+ end
+
def test_too_many_args_in_eval
bug5720 = '[ruby-core:41520]'
arg_string = (0...140000).to_a.join(", ")
@@ -561,7 +606,7 @@ end.join
end
def test_ensure_after_nomemoryerror
- skip "Forcing NoMemoryError causes problems in some environments"
+ omit "Forcing NoMemoryError causes problems in some environments"
assert_separately([], "$_ = 'a' * 1_000_000_000_000_000_000")
rescue NoMemoryError
assert_raise(NoMemoryError) do
@@ -658,7 +703,7 @@ end.join
def test_machine_stackoverflow
bug9109 = '[ruby-dev:47804] [Bug #9109]'
- assert_separately(%w[--disable-gem], <<-SRC)
+ assert_separately([], <<-SRC)
assert_raise(SystemStackError, #{bug9109.dump}) {
h = {a: ->{h[:a].call}}
h[:a].call
@@ -669,7 +714,7 @@ end.join
def test_machine_stackoverflow_by_define_method
bug9454 = '[ruby-core:60113] [Bug #9454]'
- assert_separately(%w[--disable-gem], <<-SRC)
+ assert_separately([], <<-SRC)
assert_raise(SystemStackError, #{bug9454.dump}) {
define_method(:foo) {self.foo}
self.foo
@@ -774,7 +819,7 @@ end.join
def test_cause_at_end
errs = [
/-: unexpected return\n/,
- /.*undefined local variable or method `n'.*\n/,
+ /.*undefined local variable or method 'n'.*\n/,
]
assert_in_out_err([], <<-'end;', [], errs)
END{n}; END{return}
@@ -786,6 +831,7 @@ end.join
cause = ArgumentError.new("foobar")
e = assert_raise(RuntimeError) {raise msg, cause: cause}
assert_same(cause, e.cause)
+ assert_raise(TypeError) {raise msg, {cause: cause}}
end
def test_cause_with_no_arguments
@@ -970,11 +1016,12 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status|
end
assert_not_nil(e)
assert_include(e.message, "\0")
- assert_in_out_err([], src, [], [], *args, **opts) do |_, err,|
- err.each do |e|
- assert_not_include(e, "\0")
- end
- end
+ # Disabled by [Feature #18367]
+ #assert_in_out_err([], src, [], [], *args, **opts) do |_, err,|
+ # err.each do |e|
+ # assert_not_include(e, "\0")
+ # end
+ #end
e
end
@@ -1008,7 +1055,7 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status|
end
def test_message_of_name_error
- assert_raise_with_message(NameError, /\Aundefined method `foo' for module `#<Module:.*>'$/) do
+ assert_raise_with_message(NameError, /\Aundefined method 'foo' for module '#<Module:.*>'$/) do
Module.new do
module_function :foo
end
@@ -1017,8 +1064,7 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status|
def capture_warning_warn(category: false)
verbose = $VERBOSE
- deprecated = Warning[:deprecated]
- experimental = Warning[:experimental]
+ categories = Warning.categories.to_h {|cat| [cat, Warning[cat]]}
warning = []
::Warning.class_eval do
@@ -1030,22 +1076,20 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status|
warning << [str, category]
end
else
- define_method(:warn) do |str|
+ define_method(:warn) do |str, category: nil|
warning << str
end
end
end
$VERBOSE = true
- Warning[:deprecated] = true
- Warning[:experimental] = true
+ Warning.categories.each {|cat| Warning[cat] = true}
yield
return warning
ensure
$VERBOSE = verbose
- Warning[:deprecated] = deprecated
- Warning[:experimental] = experimental
+ categories.each {|cat, flag| Warning[cat] = flag}
::Warning.class_eval do
remove_method :warn
@@ -1056,7 +1100,7 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status|
def test_warning_warn
warning = capture_warning_warn {$asdfasdsda_test_warning_warn}
- assert_match(/global variable `\$asdfasdsda_test_warning_warn' not initialized/, warning[0])
+ assert_match(/global variable '\$asdfasdsda_test_warning_warn' not initialized/, warning[0])
assert_equal(["a\nz\n"], capture_warning_warn {warn "a\n", "z"})
assert_equal([], capture_warning_warn {warn})
@@ -1064,27 +1108,13 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status|
end
def test_warn_deprecated_backwards_compatibility_category
- warning = capture_warning_warn { Dir.exists?("non-existent") }
-
- assert_match(/deprecated/, warning[0])
- end
-
- def test_warn_deprecated_category
- warning = capture_warning_warn(category: true) { Dir.exists?("non-existent") }
-
- assert_equal :deprecated, warning[0][1]
- end
-
- def test_warn_deprecated_to_remove_backwards_compatibility_category
- warning = capture_warning_warn { Object.new.tainted? }
-
- assert_match(/deprecated/, warning[0])
- end
-
- def test_warn_deprecated_to_remove_category
- warning = capture_warning_warn(category: true) { Object.new.tainted? }
+ (message, category), = capture_warning_warn(category: true) do
+ $; = "www"
+ $; = nil
+ end
- assert_equal :deprecated, warning[0][1]
+ assert_include message, 'deprecated'
+ assert_equal :deprecated, category
end
def test_kernel_warn_uplevel
@@ -1140,7 +1170,7 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status|
end
def test_warning_warn_super
- assert_in_out_err(%[-W0], "#{<<~"{#"}\n#{<<~'};'}", [], /global variable `\$asdfiasdofa_test_warning_warn_super' not initialized/)
+ assert_in_out_err(%[-W0], "#{<<~"{#"}\n#{<<~'};'}", [], /global variable '\$asdfiasdofa_test_warning_warn_super' not initialized/)
{#
module Warning
def warn(message)
@@ -1156,48 +1186,32 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status|
def test_warning_category
assert_raise(TypeError) {Warning[nil]}
assert_raise(ArgumentError) {Warning[:XXXX]}
- assert_include([true, false], Warning[:deprecated])
- assert_include([true, false], Warning[:experimental])
- end
- def test_warning_category_deprecated
- warning = EnvUtil.verbose_warning do
- deprecated = Warning[:deprecated]
- Warning[:deprecated] = true
- Warning.warn "deprecated feature", category: :deprecated
- ensure
- Warning[:deprecated] = deprecated
- end
- assert_equal "deprecated feature", warning
+ all_assertions_foreach("categories", *Warning.categories) do |cat|
+ value = Warning[cat]
+ assert_include([true, false], value)
- warning = EnvUtil.verbose_warning do
- deprecated = Warning[:deprecated]
- Warning[:deprecated] = false
- Warning.warn "deprecated feature", category: :deprecated
+ enabled = EnvUtil.verbose_warning do
+ Warning[cat] = true
+ Warning.warn "#{cat} feature", category: cat
+ end
+ disabled = EnvUtil.verbose_warning do
+ Warning[cat] = false
+ Warning.warn "#{cat} feature", category: cat
+ end
ensure
- Warning[:deprecated] = deprecated
+ Warning[cat] = value
+ assert_equal "#{cat} feature", enabled
+ assert_empty disabled
end
- assert_empty warning
end
- def test_warning_category_experimental
- warning = EnvUtil.verbose_warning do
- experimental = Warning[:experimental]
- Warning[:experimental] = true
- Warning.warn "experimental feature", category: :experimental
- ensure
- Warning[:experimental] = experimental
- end
- assert_equal "experimental feature", warning
-
- warning = EnvUtil.verbose_warning do
- experimental = Warning[:experimental]
- Warning[:experimental] = false
- Warning.warn "experimental feature", category: :experimental
- ensure
- Warning[:experimental] = experimental
- end
- assert_empty warning
+ def test_undef_Warning_warn
+ assert_separately([], "#{<<-"begin;"}\n#{<<-"end;"}")
+ begin;
+ Warning.undef_method(:warn)
+ assert_raise(NoMethodError) { warn "" }
+ end;
end
def test_undefined_backtrace
@@ -1237,7 +1251,7 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status|
begin;
class Bug < RuntimeError
def backtrace
- IO.readlines(IO::NULL)
+ File.readlines(IO::NULL)
end
end
bug = Bug.new '[ruby-core:85939] [Bug #14577]'
@@ -1281,7 +1295,7 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status|
def test_backtrace_in_eval
bug = '[ruby-core:84434] [Bug #14229]'
- assert_in_out_err(['-e', 'eval("raise")'], "", [], /^\(eval\):1:/, bug)
+ assert_in_out_err(['-e', 'eval("raise")'], "", [], /^\(eval at .*\):1:/, bug)
end
def test_full_message
@@ -1383,6 +1397,14 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status|
end;
end
+ def test_marshal_circular_cause
+ dump = "\x04\bo:\x11RuntimeError\b:\tmesgI\"\berr\x06:\x06ET:\abt[\x00:\ncause@\x05"
+ assert_raise_with_message(ArgumentError, /circular cause/, ->{dump.inspect}) do
+ e = Marshal.load(dump)
+ assert_same(e, e.cause)
+ end
+ end
+
def test_super_in_method_missing
assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
begin;
@@ -1394,9 +1416,113 @@ $stderr = $stdout; raise "\x82\xa0"') do |outs, errs, status|
end
bug14670 = '[ruby-dev:50522] [Bug #14670]'
- assert_raise_with_message(NoMethodError, /`foo'/, bug14670) do
+ assert_raise_with_message(NoMethodError, /'foo'/, bug14670) do
Object.new.foo
end
end;
end
+
+ def test_detailed_message
+ e = RuntimeError.new("message")
+ assert_equal("message (RuntimeError)", e.detailed_message)
+ assert_equal("\e[1mmessage (\e[1;4mRuntimeError\e[m\e[1m)\e[m", e.detailed_message(highlight: true))
+
+ e = RuntimeError.new("foo\nbar\nbaz")
+ assert_equal("foo (RuntimeError)\nbar\nbaz", e.detailed_message)
+ assert_equal("\e[1mfoo (\e[1;4mRuntimeError\e[m\e[1m)\e[m\n\e[1mbar\e[m\n\e[1mbaz\e[m", e.detailed_message(highlight: true))
+
+ e = RuntimeError.new("")
+ assert_equal("unhandled exception", e.detailed_message)
+ assert_equal("\e[1;4munhandled exception\e[m", e.detailed_message(highlight: true))
+
+ e = RuntimeError.new
+ assert_equal("RuntimeError (RuntimeError)", e.detailed_message)
+ assert_equal("\e[1mRuntimeError (\e[1;4mRuntimeError\e[m\e[1m)\e[m", e.detailed_message(highlight: true))
+ end
+
+ def test_detailed_message_under_gc_compact_stress
+ omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077
+ EnvUtil.under_gc_compact_stress do
+ e = RuntimeError.new("foo\nbar\nbaz")
+ assert_equal("foo (RuntimeError)\nbar\nbaz", e.detailed_message)
+ assert_equal("\e[1mfoo (\e[1;4mRuntimeError\e[m\e[1m)\e[m\n\e[1mbar\e[m\n\e[1mbaz\e[m", e.detailed_message(highlight: true))
+ end
+ end
+
+ def test_full_message_with_custom_detailed_message
+ e = RuntimeError.new("message")
+ opt_ = nil
+ e.define_singleton_method(:detailed_message) do |**opt|
+ opt_ = opt
+ "BOO!"
+ end
+ assert_match("BOO!", e.full_message.lines.first)
+ assert_equal({ highlight: Exception.to_tty? }, opt_)
+ end
+
+ def test_full_message_with_encoding
+ message = "\u{dc}bersicht"
+ begin
+ begin
+ raise message
+ rescue => e
+ raise "\n#{e.message}"
+ end
+ rescue => e
+ end
+ assert_include(e.full_message, message)
+ end
+
+ def test_syntax_error_detailed_message
+ Dir.mktmpdir do |dir|
+ File.write(File.join(dir, "detail.rb"), "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ class SyntaxError
+ def detailed_message(**)
+ Thread.new {}.join
+ "<#{super}>\n""<#{File.basename(__FILE__)}>"
+ rescue ThreadError => e
+ e.message
+ end
+ end
+ end;
+ pattern = /^<detail\.rb>/
+ assert_in_out_err(%W[-r#{dir}/detail -], "1+", [], pattern)
+
+ File.write(File.join(dir, "main.rb"), "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ 1 +
+ end;
+ assert_in_out_err(%W[-r#{dir}/detail #{dir}/main.rb]) do |stdout, stderr,|
+ assert_empty(stdout)
+ assert_not_empty(stderr.grep(pattern))
+ error, = stderr.grep(/unexpected end-of-input/)
+ assert_not_nil(error)
+ assert_match(/<.*unexpected end-of-input.*>|\^ unexpected end-of-input,/, error)
+ end
+ end
+ end
+
+ def test_syntax_error_path
+ e = assert_raise(SyntaxError) {
+ eval("1+", nil, "test_syntax_error_path.rb")
+ }
+ assert_equal("test_syntax_error_path.rb", e.path)
+
+ Dir.mktmpdir do |dir|
+ lib = File.join(dir, "syntax_error-path.rb")
+ File.write(lib, "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ class SyntaxError
+ def detailed_message(**)
+ STDERR.puts "\n""path=#{path}\n"
+ super
+ end
+ end
+ end;
+ main = File.join(dir, "syntax_error.rb")
+ File.write(main, "1+\n")
+ assert_in_out_err(%W[-r#{lib} #{main}], "", [], [:*, "\n""path=#{main}\n", :*])
+ end
+ end
end
diff --git a/test/ruby/test_fiber.rb b/test/ruby/test_fiber.rb
index 67fef33b85..45e5d12092 100644
--- a/test/ruby/test_fiber.rb
+++ b/test/ruby/test_fiber.rb
@@ -34,7 +34,7 @@ class TestFiber < Test::Unit::TestCase
end
def test_many_fibers
- skip 'This is unstable on GitHub Actions --jit-wait. TODO: debug it' if defined?(RubyVM::JIT) && RubyVM::JIT.enabled?
+ omit 'This is unstable on GitHub Actions --jit-wait. TODO: debug it' if defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled?
max = 1000
assert_equal(max, max.times{
Fiber.new{}
@@ -50,7 +50,7 @@ class TestFiber < Test::Unit::TestCase
end
def test_many_fibers_with_threads
- assert_normal_exit <<-SRC, timeout: (/solaris/i =~ RUBY_PLATFORM ? 300 : 60)
+ assert_normal_exit <<-SRC, timeout: (/solaris/i =~ RUBY_PLATFORM ? 1000 : 60)
max = 1000
@cnt = 0
(1..100).map{|ti|
@@ -82,12 +82,14 @@ class TestFiber < Test::Unit::TestCase
f.resume
f.resume
}
- assert_raise(RuntimeError){
- Fiber.new{
- @c = callcc{|c| @c = c}
- }.resume
- @c.call # cross fiber callcc
- }
+ if respond_to?(:callcc)
+ assert_raise(RuntimeError){
+ Fiber.new{
+ @c = callcc{|c| @c = c}
+ }.resume
+ @c.call # cross fiber callcc
+ }
+ end
assert_raise(RuntimeError){
Fiber.new{
raise
@@ -381,7 +383,7 @@ class TestFiber < Test::Unit::TestCase
def test_fork_from_fiber
- skip 'fork not supported' unless Process.respond_to?(:fork)
+ omit 'fork not supported' unless Process.respond_to?(:fork)
pid = nil
bug5700 = '[ruby-core:41456]'
assert_nothing_raised(bug5700) do
@@ -396,7 +398,7 @@ class TestFiber < Test::Unit::TestCase
Fiber.new {}.transfer
Fiber.new { Fiber.yield }
end
- exit!(0)
+ exit!(true)
end
}.transfer
_, status = Process.waitpid2(xpid)
@@ -405,8 +407,13 @@ class TestFiber < Test::Unit::TestCase
end.resume
end
pid, status = Process.waitpid2(pid)
- assert_equal(0, status.exitstatus, bug5700)
- assert_equal(false, status.signaled?, bug5700)
+ assert_not_predicate(status, :signaled?, bug5700)
+ assert_predicate(status, :success?, bug5700)
+
+ pid = Fiber.new {fork}.resume
+ pid, status = Process.waitpid2(pid)
+ assert_not_predicate(status, :signaled?)
+ assert_predicate(status, :success?)
end
def test_exit_in_fiber
@@ -417,7 +424,7 @@ class TestFiber < Test::Unit::TestCase
end
def test_fatal_in_fiber
- assert_in_out_err(["-r-test-/fatal/rb_fatal", "-e", <<-EOS], "", [], /ok/)
+ assert_in_out_err(["-r-test-/fatal", "-e", <<-EOS], "", [], /ok/)
Fiber.new{
Bug.rb_fatal "ok"
}.resume
diff --git a/test/ruby/test_file.rb b/test/ruby/test_file.rb
index d570b6f6fb..eae9a8e7b0 100644
--- a/test/ruby/test_file.rb
+++ b/test/ruby/test_file.rb
@@ -273,7 +273,7 @@ class TestFile < Test::Unit::TestCase
begin
File.symlink(tst, a)
rescue Errno::EACCES, Errno::EPERM
- skip "need privilege"
+ omit "need privilege"
end
assert_equal(File.join(realdir, tst), File.realpath(a))
File.unlink(a)
@@ -317,7 +317,7 @@ class TestFile < Test::Unit::TestCase
Dir.mktmpdir('rubytest-realpath') {|tmpdir|
Dir.chdir(tmpdir) do
Dir.mkdir('foo')
- skip "cannot run mklink" unless system('mklink /j bar foo > nul')
+ omit "cannot run mklink" unless system('mklink /j bar foo > nul')
assert_equal(File.realpath('foo'), File.realpath('bar'))
end
}
@@ -358,6 +358,19 @@ class TestFile < Test::Unit::TestCase
assert_equal(mod_time_contents, stats.mtime, bug6385)
end
+ def measure_time
+ log = []
+ 30.times do
+ t1 = Process.clock_gettime(Process::CLOCK_REALTIME)
+ yield
+ t2 = Process.clock_gettime(Process::CLOCK_REALTIME)
+ log << (t2 - t1)
+ return (t1 + t2) / 2 if t2 - t1 < 1
+ sleep 1
+ end
+ omit "failed to setup; the machine is stupidly slow #{log.inspect}"
+ end
+
def test_stat
tb = Process.clock_gettime(Process::CLOCK_REALTIME)
Tempfile.create("stat") {|file|
@@ -365,26 +378,39 @@ class TestFile < Test::Unit::TestCase
file.close
path = file.path
- t0 = Process.clock_gettime(Process::CLOCK_REALTIME)
- File.write(path, "foo")
+ measure_time do
+ File.write(path, "foo")
+ end
+
sleep 2
- File.write(path, "bar")
+
+ t1 = measure_time do
+ File.write(path, "bar")
+ end
+
sleep 2
- File.read(path)
- File.chmod(0644, path)
+
+ t2 = measure_time do
+ File.read(path)
+ File.chmod(0644, path)
+ end
+
sleep 2
- File.read(path)
+
+ t3 = measure_time do
+ File.read(path)
+ end
delta = 1
stat = File.stat(path)
- assert_in_delta tb, stat.birthtime.to_f, delta
- assert_in_delta t0+2, stat.mtime.to_f, delta
+ assert_in_delta tb, stat.birthtime.to_f, delta
+ assert_in_delta t1, stat.mtime.to_f, delta
if stat.birthtime != stat.ctime
- assert_in_delta t0+4, stat.ctime.to_f, delta
+ assert_in_delta t2, stat.ctime.to_f, delta
end
if /mswin|mingw/ !~ RUBY_PLATFORM && !Bug::File::Fs.noatime?(path)
# Windows delays updating atime
- assert_in_delta t0+6, stat.atime.to_f, delta
+ assert_in_delta t3, stat.atime.to_f, delta
end
}
rescue NotImplementedError
@@ -460,6 +486,81 @@ class TestFile < Test::Unit::TestCase
end
end
+ def test_initialize
+ Dir.mktmpdir(__method__.to_s) do |tmpdir|
+ path = File.join(tmpdir, "foo")
+
+ assert_raise(Errno::ENOENT) {File.new(path)}
+ f = File.new(path, "w")
+ f.write("FOO\n")
+ f.close
+ f = File.new(path)
+ data = f.read
+ f.close
+ assert_equal("FOO\n", data)
+
+ f = File.new(path, File::WRONLY)
+ f.write("BAR\n")
+ f.close
+ f = File.new(path, File::RDONLY)
+ data = f.read
+ f.close
+ assert_equal("BAR\n", data)
+
+ data = File.open(path) {|file|
+ File.new(file.fileno, mode: File::RDONLY, autoclose: false).read
+ }
+ assert_equal("BAR\n", data)
+
+ data = File.open(path) {|file|
+ File.new(file.fileno, File::RDONLY, autoclose: false).read
+ }
+ assert_equal("BAR\n", data)
+ end
+ end
+
+ def test_file_open_newline_option
+ Dir.mktmpdir(__method__.to_s) do |tmpdir|
+ path = File.join(tmpdir, "foo")
+ test = lambda do |newline|
+ File.open(path, "wt", newline: newline) do |f|
+ f.write "a\n"
+ f.puts "b"
+ end
+ File.binread(path)
+ end
+ assert_equal("a\nb\n", test.(:lf))
+ assert_equal("a\nb\n", test.(:universal))
+ assert_equal("a\r\nb\r\n", test.(:crlf))
+ assert_equal("a\rb\r", test.(:cr))
+
+ test = lambda do |newline|
+ File.open(path, "rt", newline: newline) do |f|
+ f.read
+ end
+ end
+
+ File.binwrite(path, "a\nb\n")
+ assert_equal("a\nb\n", test.(:lf))
+ assert_equal("a\nb\n", test.(:universal))
+ assert_equal("a\nb\n", test.(:crlf))
+ assert_equal("a\nb\n", test.(:cr))
+
+ File.binwrite(path, "a\r\nb\r\n")
+ assert_equal("a\r\nb\r\n", test.(:lf))
+ assert_equal("a\nb\n", test.(:universal))
+ # Work on both Windows and non-Windows
+ assert_include(["a\r\nb\r\n", "a\nb\n"], test.(:crlf))
+ assert_equal("a\r\nb\r\n", test.(:cr))
+
+ File.binwrite(path, "a\rb\r")
+ assert_equal("a\rb\r", test.(:lf))
+ assert_equal("a\nb\n", test.(:universal))
+ assert_equal("a\rb\r", test.(:crlf))
+ assert_equal("a\rb\r", test.(:cr))
+ end
+ end
+
def test_open_nul
Dir.mktmpdir(__method__.to_s) do |tmpdir|
path = File.join(tmpdir, "foo")
@@ -475,17 +576,17 @@ class TestFile < Test::Unit::TestCase
begin
io = File.open(tmpdir, File::RDWR | File::TMPFILE)
rescue Errno::EINVAL
- skip 'O_TMPFILE not supported (EINVAL)'
+ omit 'O_TMPFILE not supported (EINVAL)'
rescue Errno::EISDIR
- skip 'O_TMPFILE not supported (EISDIR)'
+ omit 'O_TMPFILE not supported (EISDIR)'
rescue Errno::EOPNOTSUPP
- skip 'O_TMPFILE not supported (EOPNOTSUPP)'
+ omit 'O_TMPFILE not supported (EOPNOTSUPP)'
end
io.write "foo"
io.flush
assert_equal 3, io.size
- assert_raise(IOError) { io.path }
+ assert_nil io.path
ensure
io&.close
end
@@ -512,4 +613,250 @@ class TestFile < Test::Unit::TestCase
assert_file.absolute_path?("/foo/bar\\baz")
end
end
+
+ class NewlineConvTests < Test::Unit::TestCase
+ TEST_STRING_WITH_CRLF = "line1\r\nline2\r\n".freeze
+ TEST_STRING_WITH_LF = "line1\nline2\n".freeze
+
+ def setup
+ @tmpdir = Dir.mktmpdir(self.class.name)
+ @read_path_with_crlf = File.join(@tmpdir, "read_path_with_crlf")
+ File.binwrite(@read_path_with_crlf, TEST_STRING_WITH_CRLF)
+ @read_path_with_lf = File.join(@tmpdir, "read_path_with_lf")
+ File.binwrite(@read_path_with_lf, TEST_STRING_WITH_LF)
+ @write_path = File.join(@tmpdir, "write_path")
+ File.binwrite(@write_path, '')
+ end
+
+ def teardown
+ FileUtils.rm_rf @tmpdir
+ end
+
+ def windows?
+ /cygwin|mswin|mingw/ =~ RUBY_PLATFORM
+ end
+
+ def open_file_with(method, filename, mode)
+ read_or_write = mode.include?('w') ? :write : :read
+ binary_or_text = mode.include?('b') ? :binary : :text
+
+ f = case method
+ when :ruby_file_open
+ File.open(filename, mode)
+ when :c_rb_file_open
+ Bug::File::NewlineConv.rb_file_open(filename, read_or_write, binary_or_text)
+ when :c_rb_io_fdopen
+ Bug::File::NewlineConv.rb_io_fdopen(filename, read_or_write, binary_or_text)
+ else
+ raise "Don't know how to open with #{method}"
+ end
+
+ begin
+ yield f
+ ensure
+ f.close
+ end
+ end
+
+ def assert_file_contents_has_lf(f)
+ assert_equal TEST_STRING_WITH_LF, f.read
+ end
+
+ def assert_file_contents_has_crlf(f)
+ assert_equal TEST_STRING_WITH_CRLF, f.read
+ end
+
+ def assert_file_contents_has_lf_on_windows(f)
+ if windows?
+ assert_file_contents_has_lf(f)
+ else
+ assert_file_contents_has_crlf(f)
+ end
+ end
+
+ def assert_file_contents_has_crlf_on_windows(f)
+ if windows?
+ assert_file_contents_has_crlf(f)
+ else
+ assert_file_contents_has_lf(f)
+ end
+ end
+
+ def test_ruby_file_open_text_mode_read_crlf
+ open_file_with(:ruby_file_open, @read_path_with_crlf, 'r') { |f| assert_file_contents_has_lf_on_windows(f) }
+ end
+
+ def test_ruby_file_open_bin_mode_read_crlf
+ open_file_with(:ruby_file_open, @read_path_with_crlf, 'rb') { |f| assert_file_contents_has_crlf(f) }
+ end
+
+ def test_ruby_file_open_text_mode_read_lf
+ open_file_with(:ruby_file_open, @read_path_with_lf, 'r') { |f| assert_file_contents_has_lf(f) }
+ end
+
+ def test_ruby_file_open_bin_mode_read_lf
+ open_file_with(:ruby_file_open, @read_path_with_lf, 'rb') { |f| assert_file_contents_has_lf(f) }
+ end
+
+ def test_ruby_file_open_text_mode_read_crlf_with_utf8_encoding
+ open_file_with(:ruby_file_open, @read_path_with_crlf, 'r') do |f|
+ f.set_encoding Encoding::UTF_8, '-'
+ assert_file_contents_has_lf_on_windows(f)
+ end
+ end
+
+ def test_ruby_file_open_bin_mode_read_crlf_with_utf8_encoding
+ open_file_with(:ruby_file_open, @read_path_with_crlf, 'rb') do |f|
+ f.set_encoding Encoding::UTF_8, '-'
+ assert_file_contents_has_crlf(f)
+ end
+ end
+
+ def test_ruby_file_open_text_mode_read_lf_with_utf8_encoding
+ open_file_with(:ruby_file_open, @read_path_with_lf, 'r') do |f|
+ f.set_encoding Encoding::UTF_8, '-'
+ assert_file_contents_has_lf(f)
+ end
+ end
+
+ def test_ruby_file_open_bin_mode_read_lf_with_utf8_encoding
+ open_file_with(:ruby_file_open, @read_path_with_lf, 'rb') do |f|
+ f.set_encoding Encoding::UTF_8, '-'
+ assert_file_contents_has_lf(f)
+ end
+ end
+
+ def test_ruby_file_open_text_mode_write_lf
+ open_file_with(:ruby_file_open, @write_path, 'w') { |f| f.write TEST_STRING_WITH_LF }
+ File.open(@write_path, 'rb') { |f| assert_file_contents_has_crlf_on_windows(f) }
+ end
+
+ def test_ruby_file_open_bin_mode_write_lf
+ open_file_with(:ruby_file_open, @write_path, 'wb') { |f| f.write TEST_STRING_WITH_LF }
+ File.open(@write_path, 'rb') { |f| assert_file_contents_has_lf(f) }
+ end
+
+ def test_ruby_file_open_bin_mode_write_crlf
+ open_file_with(:ruby_file_open, @write_path, 'wb') { |f| f.write TEST_STRING_WITH_CRLF }
+ File.open(@write_path, 'rb') { |f| assert_file_contents_has_crlf(f) }
+ end
+
+ def test_c_rb_file_open_text_mode_read_crlf
+ open_file_with(:c_rb_file_open, @read_path_with_crlf, 'r') { |f| assert_file_contents_has_lf_on_windows(f) }
+ end
+
+ def test_c_rb_file_open_bin_mode_read_crlf
+ open_file_with(:c_rb_file_open, @read_path_with_crlf, 'rb') { |f| assert_file_contents_has_crlf(f) }
+ end
+
+ def test_c_rb_file_open_text_mode_read_lf
+ open_file_with(:c_rb_file_open, @read_path_with_lf, 'r') { |f| assert_file_contents_has_lf(f) }
+ end
+
+ def test_c_rb_file_open_bin_mode_read_lf
+ open_file_with(:c_rb_file_open, @read_path_with_lf, 'rb') { |f| assert_file_contents_has_lf(f) }
+ end
+
+ def test_c_rb_file_open_text_mode_write_lf
+ open_file_with(:c_rb_file_open, @write_path, 'w') { |f| f.write TEST_STRING_WITH_LF }
+ File.open(@write_path, 'rb') { |f| assert_file_contents_has_crlf_on_windows(f) }
+ end
+
+ def test_c_rb_file_open_bin_mode_write_lf
+ open_file_with(:c_rb_file_open, @write_path, 'wb') { |f| f.write TEST_STRING_WITH_LF }
+ File.open(@write_path, 'rb') { |f| assert_file_contents_has_lf(f) }
+ end
+
+ def test_c_rb_file_open_bin_mode_write_crlf
+ open_file_with(:c_rb_file_open, @write_path, 'wb') { |f| f.write TEST_STRING_WITH_CRLF }
+ File.open(@write_path, 'rb') { |f| assert_file_contents_has_crlf(f) }
+ end
+
+ def test_c_rb_file_open_text_mode_read_crlf_with_utf8_encoding
+ open_file_with(:c_rb_file_open, @read_path_with_crlf, 'r') do |f|
+ f.set_encoding Encoding::UTF_8, '-'
+ assert_file_contents_has_lf_on_windows(f)
+ end
+ end
+
+ def test_c_rb_file_open_bin_mode_read_crlf_with_utf8_encoding
+ open_file_with(:c_rb_file_open, @read_path_with_crlf, 'rb') do |f|
+ f.set_encoding Encoding::UTF_8, '-'
+ assert_file_contents_has_crlf(f)
+ end
+ end
+
+ def test_c_rb_file_open_text_mode_read_lf_with_utf8_encoding
+ open_file_with(:c_rb_file_open, @read_path_with_lf, 'r') do |f|
+ f.set_encoding Encoding::UTF_8, '-'
+ assert_file_contents_has_lf(f)
+ end
+ end
+
+ def test_c_rb_file_open_bin_mode_read_lf_with_utf8_encoding
+ open_file_with(:c_rb_file_open, @read_path_with_lf, 'rb') do |f|
+ f.set_encoding Encoding::UTF_8, '-'
+ assert_file_contents_has_lf(f)
+ end
+ end
+
+ def test_c_rb_io_fdopen_text_mode_read_crlf
+ open_file_with(:c_rb_io_fdopen, @read_path_with_crlf, 'r') { |f| assert_file_contents_has_lf_on_windows(f) }
+ end
+
+ def test_c_rb_io_fdopen_bin_mode_read_crlf
+ open_file_with(:c_rb_io_fdopen, @read_path_with_crlf, 'rb') { |f| assert_file_contents_has_crlf(f) }
+ end
+
+ def test_c_rb_io_fdopen_text_mode_read_lf
+ open_file_with(:c_rb_io_fdopen, @read_path_with_lf, 'r') { |f| assert_file_contents_has_lf(f) }
+ end
+
+ def test_c_rb_io_fdopen_bin_mode_read_lf
+ open_file_with(:c_rb_io_fdopen, @read_path_with_lf, 'rb') { |f| assert_file_contents_has_lf(f) }
+ end
+
+ def test_c_rb_io_fdopen_text_mode_write_lf
+ open_file_with(:c_rb_io_fdopen, @write_path, 'w') { |f| f.write TEST_STRING_WITH_LF }
+ File.open(@write_path, 'rb') { |f| assert_file_contents_has_crlf_on_windows(f) }
+ end
+
+ def test_c_rb_io_fdopen_bin_mode_write_lf
+ open_file_with(:c_rb_io_fdopen, @write_path, 'wb') { |f| f.write TEST_STRING_WITH_LF }
+ File.open(@write_path, 'rb') { |f| assert_file_contents_has_lf(f) }
+ end
+
+ def test_c_rb_io_fdopen_bin_mode_write_crlf
+ open_file_with(:c_rb_io_fdopen, @write_path, 'wb') { |f| f.write TEST_STRING_WITH_CRLF }
+ File.open(@write_path, 'rb') { |f| assert_file_contents_has_crlf(f) }
+ end
+
+ def test_c_rb_io_fdopen_text_mode_read_crlf_with_utf8_encoding
+ open_file_with(:c_rb_io_fdopen, @read_path_with_crlf, 'r') do |f|
+ f.set_encoding Encoding::UTF_8, '-'
+ assert_file_contents_has_lf_on_windows(f)
+ end
+ end
+
+ def test_c_rb_io_fdopen_bin_mode_read_crlf_with_utf8_encoding
+ open_file_with(:c_rb_io_fdopen, @read_path_with_crlf, 'rb') do |f|
+ f.set_encoding Encoding::UTF_8, '-'
+ assert_file_contents_has_crlf(f)
+ end
+ end
+
+ def test_c_rb_io_fdopen_text_mode_read_lf_with_utf8_encoding
+ open_file_with(:c_rb_io_fdopen, @read_path_with_lf, 'r') do |f|
+ f.set_encoding Encoding::UTF_8, '-'
+ assert_file_contents_has_lf(f)
+ end
+ end
+
+ def test_c_rb_io_fdopen_bin_mode_read_lf_with_utf8_encoding
+ open_file_with(:c_rb_io_fdopen, @read_path_with_lf, 'rb') do |f|
+ f.set_encoding Encoding::UTF_8, '-'
+ assert_file_contents_has_lf(f)
+ end
+ end
+ end
end
diff --git a/test/ruby/test_file_exhaustive.rb b/test/ruby/test_file_exhaustive.rb
index 70966d83a4..f3068cb189 100644
--- a/test/ruby/test_file_exhaustive.rb
+++ b/test/ruby/test_file_exhaustive.rb
@@ -78,6 +78,19 @@ class TestFileExhaustive < Test::Unit::TestCase
@notownedfile
end
+ def grpownedfile
+ return nil unless POSIX
+ return @grpownedfile if defined? @grpownedfile
+ if group = (Process.groups - [Process.egid]).last
+ grpownedfile = make_tmp_filename("grpownedfile")
+ make_file("grpowned", grpownedfile)
+ File.chown(nil, group, grpownedfile)
+ return @grpownedfile = grpownedfile
+ end
+ rescue
+ @grpownedfile = nil
+ end
+
def suidfile
return @suidfile if defined? @suidfile
if POSIX
@@ -160,9 +173,7 @@ class TestFileExhaustive < Test::Unit::TestCase
end
def chardev
- return @chardev if defined? @chardev
- @chardev = File::NULL == "/dev/null" ? "/dev/null" : nil
- @chardev
+ File::NULL
end
def blockdev
@@ -175,6 +186,12 @@ class TestFileExhaustive < Test::Unit::TestCase
@blockdev
end
+ def root_without_capabilities?
+ return false unless Process.uid == 0
+ return false unless system('command', '-v', 'capsh', out: File::NULL)
+ !system('capsh', '--has-p=CAP_DAC_OVERRIDE', out: File::NULL, err: File::NULL)
+ end
+
def test_path
[regular_file, utf8_file].each do |file|
assert_equal(file, File.open(file) {|f| f.path})
@@ -319,7 +336,7 @@ class TestFileExhaustive < Test::Unit::TestCase
assert_file.not_chardev?(regular_file)
assert_file.not_chardev?(utf8_file)
assert_file.not_chardev?(nofile)
- assert_file.chardev?(chardev) if chardev
+ assert_file.chardev?(chardev)
end
def test_exist_p
@@ -493,6 +510,9 @@ class TestFileExhaustive < Test::Unit::TestCase
def test_grpowned_p ## xxx
assert_file.grpowned?(regular_file)
assert_file.grpowned?(utf8_file)
+ if file = grpownedfile
+ assert_file.grpowned?(file)
+ end
end if POSIX
def io_open(file_name)
@@ -624,7 +644,7 @@ class TestFileExhaustive < Test::Unit::TestCase
end
def test_birthtime
- skip if RUBY_PLATFORM =~ /android/
+ omit if RUBY_PLATFORM =~ /android/
[regular_file, utf8_file].each do |file|
t1 = File.birthtime(file)
t2 = File.open(file) {|f| f.birthtime}
@@ -635,7 +655,7 @@ class TestFileExhaustive < Test::Unit::TestCase
# ignore unsupporting filesystems
rescue Errno::EPERM
# Docker prohibits statx syscall by the default.
- skip("statx(2) is prohibited by seccomp")
+ omit("statx(2) is prohibited by seccomp")
end
assert_raise(Errno::ENOENT) { File.birthtime(nofile) }
end if File.respond_to?(:birthtime)
@@ -757,7 +777,7 @@ class TestFileExhaustive < Test::Unit::TestCase
def test_readlink_junction
base = File.basename(nofile)
err = IO.popen(%W"cmd.exe /c mklink /j #{base} .", chdir: @dir, err: %i[child out], &:read)
- skip err unless $?.success?
+ omit err unless $?.success?
assert_equal(@dir, File.readlink(nofile))
end
@@ -856,9 +876,10 @@ class TestFileExhaustive < Test::Unit::TestCase
bug9934 = '[ruby-core:63114] [Bug #9934]'
require "objspace"
path = File.expand_path("/foo")
- assert_operator(ObjectSpace.memsize_of(path), :<=, path.bytesize + GC::INTERNAL_CONSTANTS[:RVALUE_SIZE], bug9934)
+ assert_operator(ObjectSpace.memsize_of(path), :<=, path.bytesize + GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE], bug9934)
path = File.expand_path("/a"*25)
- assert_equal(path.bytesize+1 + GC::INTERNAL_CONSTANTS[:RVALUE_SIZE], ObjectSpace.memsize_of(path), bug9934)
+ assert_operator(ObjectSpace.memsize_of(path), :<=,
+ (path.bytesize + 1) * 2 + GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE], bug9934)
end
def test_expand_path_encoding
@@ -1103,7 +1124,7 @@ class TestFileExhaustive < Test::Unit::TestCase
def test_expand_path_for_existent_username
user = ENV['USER']
- skip "ENV['USER'] is not set" unless user
+ omit "ENV['USER'] is not set" unless user
assert_equal(ENV['HOME'], File.expand_path("~#{user}"))
end unless DRIVE
@@ -1392,21 +1413,26 @@ class TestFileExhaustive < Test::Unit::TestCase
end
def test_flock_exclusive
+ omit "[Bug #18613]" if /freebsd/ =~ RUBY_PLATFORM
+
+ timeout = EnvUtil.apply_timeout_scale(1).to_s
File.open(regular_file, "r+") do |f|
f.flock(File::LOCK_EX)
- assert_separately(["-rtimeout", "-", regular_file], "#{<<~begin}#{<<~"end;"}")
- begin
+ assert_separately(["-rtimeout", "-", regular_file, timeout], "#{<<-"begin;"}\n#{<<-'end;'}")
+ begin;
+ timeout = ARGV[1].to_f
open(ARGV[0], "r") do |f|
- Timeout.timeout(0.1) do
+ Timeout.timeout(timeout) do
assert(!f.flock(File::LOCK_SH|File::LOCK_NB))
end
end
end;
- assert_separately(["-rtimeout", "-", regular_file], "#{<<~begin}#{<<~"end;"}")
- begin
+ assert_separately(["-rtimeout", "-", regular_file, timeout], "#{<<-"begin;"}\n#{<<-'end;'}")
+ begin;
+ timeout = ARGV[1].to_f
open(ARGV[0], "r") do |f|
assert_raise(Timeout::Error) do
- Timeout.timeout(0.1) do
+ Timeout.timeout(timeout) do
f.flock(File::LOCK_SH)
end
end
@@ -1418,21 +1444,26 @@ class TestFileExhaustive < Test::Unit::TestCase
end
def test_flock_shared
+ omit "[Bug #18613]" if /freebsd/ =~ RUBY_PLATFORM
+
+ timeout = EnvUtil.apply_timeout_scale(1).to_s
File.open(regular_file, "r+") do |f|
f.flock(File::LOCK_SH)
- assert_separately(["-rtimeout", "-", regular_file], "#{<<~begin}#{<<~"end;"}")
- begin
+ assert_separately(["-rtimeout", "-", regular_file, timeout], "#{<<-"begin;"}\n#{<<-'end;'}")
+ begin;
+ timeout = ARGV[1].to_f
open(ARGV[0], "r") do |f|
- Timeout.timeout(0.1) do
+ Timeout.timeout(timeout) do
assert(f.flock(File::LOCK_SH))
end
end
end;
- assert_separately(["-rtimeout", "-", regular_file], "#{<<~begin}#{<<~"end;"}")
- begin
+ assert_separately(["-rtimeout", "-", regular_file, timeout], "#{<<-"begin;"}\n#{<<-'end;'}")
+ begin;
+ timeout = ARGV[1].to_f
open(ARGV[0], "r+") do |f|
assert_raise(Timeout::Error) do
- Timeout.timeout(0.1) do
+ Timeout.timeout(timeout) do
f.flock(File::LOCK_EX)
end
end
@@ -1454,6 +1485,7 @@ class TestFileExhaustive < Test::Unit::TestCase
fn1,
zerofile,
notownedfile,
+ grpownedfile,
suidfile,
sgidfile,
stickyfile,
@@ -1489,6 +1521,43 @@ class TestFileExhaustive < Test::Unit::TestCase
assert_equal(File.executable?(f), test(?x, f), f)
assert_equal(File.executable_real?(f), test(?X, f), f)
assert_equal(File.zero?(f), test(?z, f), f)
+
+ stat = File.stat(f)
+ unless stat.chardev?
+ # null device may be accessed by other processes
+ assert_equal(stat.atime, File.atime(f), f)
+ assert_equal(stat.ctime, File.ctime(f), f)
+ assert_equal(stat.mtime, File.mtime(f), f)
+ end
+ assert_bool_equal(stat.blockdev?, File.blockdev?(f), f)
+ assert_bool_equal(stat.chardev?, File.chardev?(f), f)
+ assert_bool_equal(stat.directory?, File.directory?(f), f)
+ assert_bool_equal(stat.file?, File.file?(f), f)
+ assert_bool_equal(stat.setgid?, File.setgid?(f), f)
+ assert_bool_equal(stat.grpowned?, File.grpowned?(f), f)
+ assert_bool_equal(stat.sticky?, File.sticky?(f), f)
+ assert_bool_equal(File.lstat(f).symlink?, File.symlink?(f), f)
+ assert_bool_equal(stat.owned?, File.owned?(f), f)
+ assert_bool_equal(stat.pipe?, File.pipe?(f), f)
+ assert_bool_equal(stat.readable?, File.readable?(f), f)
+ assert_bool_equal(stat.readable_real?, File.readable_real?(f), f)
+ assert_equal(stat.size?, File.size?(f), f)
+ assert_bool_equal(stat.socket?, File.socket?(f), f)
+ assert_bool_equal(stat.setuid?, File.setuid?(f), f)
+ # It's possible in Linux to be uid 0, but not to have the CAP_DAC_OVERRIDE
+ # capability that allows skipping file permissions checks (e.g. some kinds
+ # of "rootless" container setups). In these cases, stat.writable? will be
+ # true (because it always returns true if Process.uid == 0), but
+ # File.writeable? will be false (because it actually asks the kernel to do
+ # an access check).
+ # Skip these two assertions in that case.
+ unless root_without_capabilities?
+ assert_bool_equal(stat.writable?, File.writable?(f), f)
+ assert_bool_equal(stat.writable_real?, File.writable_real?(f), f)
+ end
+ assert_bool_equal(stat.executable?, File.executable?(f), f)
+ assert_bool_equal(stat.executable_real?, File.executable_real?(f), f)
+ assert_bool_equal(stat.zero?, File.zero?(f), f)
end
assert_equal(false, test(?-, @dir, fn1))
assert_equal(true, test(?-, fn1, fn1))
@@ -1598,7 +1667,7 @@ class TestFileExhaustive < Test::Unit::TestCase
def test_stat_chardev_p
assert_not_predicate(File::Stat.new(@dir), :chardev?)
assert_not_predicate(File::Stat.new(regular_file), :chardev?)
- assert_predicate(File::Stat.new(chardev), :chardev?) if chardev
+ assert_predicate(File::Stat.new(chardev), :chardev?)
end
def test_stat_readable_p
@@ -1689,6 +1758,9 @@ class TestFileExhaustive < Test::Unit::TestCase
def test_stat_grpowned_p ## xxx
assert_predicate(File::Stat.new(regular_file), :grpowned?)
+ if file = grpownedfile
+ assert_predicate(File::Stat.new(file), :grpowned?)
+ end
end if POSIX
def test_stat_suid
@@ -1738,4 +1810,8 @@ class TestFileExhaustive < Test::Unit::TestCase
dir = File.expand_path("/bar")
assert_equal(File.join(dir, "~foo"), File.absolute_path("~foo", dir))
end
+
+ def assert_bool_equal(expected, result, *messages)
+ assert_equal(expected, true & result, *messages)
+ end
end
diff --git a/test/ruby/test_float.rb b/test/ruby/test_float.rb
index 4be2cfeeda..9f522c32bf 100644
--- a/test/ruby/test_float.rb
+++ b/test/ruby/test_float.rb
@@ -141,6 +141,9 @@ class TestFloat < Test::Unit::TestCase
assert_raise(ArgumentError){Float("1__1")}
assert_raise(ArgumentError){Float("1.")}
assert_raise(ArgumentError){Float("1.e+00")}
+ assert_raise(ArgumentError){Float("0x.1")}
+ assert_raise(ArgumentError){Float("0x1.")}
+ assert_raise(ArgumentError){Float("0x1.0")}
assert_raise(ArgumentError){Float("0x1.p+0")}
# add expected behaviour here.
assert_equal(10, Float("1_0"))
@@ -171,6 +174,24 @@ class TestFloat < Test::Unit::TestCase
assert_raise(ArgumentError, n += z + "A") {Float(n)}
assert_raise(ArgumentError, n += z + ".0") {Float(n)}
end
+
+ x = nil
+ 2000.times do
+ x = Float("0x"+"0"*30)
+ break unless x == 0.0
+ end
+ assert_equal(0.0, x, ->{"%a" % x})
+ x = nil
+ 2000.times do
+ begin
+ x = Float("0x1."+"0"*270)
+ rescue ArgumentError => e
+ raise unless /"0x1\.0{270}"/ =~ e.message
+ else
+ break
+ end
+ end
+ assert_nil(x, ->{"%a" % x})
end
def test_divmod
@@ -206,6 +227,12 @@ class TestFloat < Test::Unit::TestCase
assert_equal(-3.5, (-11.5).remainder(-4))
assert_predicate(Float::NAN.remainder(4), :nan?)
assert_predicate(4.remainder(Float::NAN), :nan?)
+
+ ten = Object.new
+ def ten.coerce(other)
+ [other, 10]
+ end
+ assert_equal(4, 14.0.remainder(ten))
end
def test_to_s
@@ -465,6 +492,17 @@ class TestFloat < Test::Unit::TestCase
assert_equal(-1.26, -1.255.round(2))
end
+ def test_round_half_even_with_precision
+ assert_equal(767573.18759, 767573.1875850001.round(5, half: :even))
+ assert_equal(767573.18758, 767573.187585.round(5, half: :even))
+ assert_equal(767573.18758, 767573.1875849998.round(5, half: :even))
+ assert_equal(767573.18758, 767573.187575.round(5, half: :even))
+ assert_equal(-767573.18759, -767573.1875850001.round(5, half: :even))
+ assert_equal(-767573.18758, -767573.187585.round(5, half: :even))
+ assert_equal(-767573.18758, -767573.1875849998.round(5, half: :even))
+ assert_equal(-767573.18758, -767573.187575.round(5, half: :even))
+ end
+
def test_floor_with_precision
assert_equal(+0.0, +0.001.floor(1))
assert_equal(-0.1, -0.001.floor(1))
@@ -492,6 +530,10 @@ class TestFloat < Test::Unit::TestCase
assert_raise(TypeError) {1.0.floor(nil)}
def (prec = Object.new).to_int; 2; end
assert_equal(0.99, 0.998.floor(prec))
+
+ assert_equal(-10000000000, -1.0.floor(-10), "[Bug #20654]")
+ assert_equal(-100000000000000000000, -1.0.floor(-20), "[Bug #20654]")
+ assert_equal(-100000000000000000000000000000000000000000000000000, -1.0.floor(-50), "[Bug #20654]")
end
def test_ceil_with_precision
@@ -519,6 +561,10 @@ class TestFloat < Test::Unit::TestCase
assert_raise(TypeError) {1.0.ceil(nil)}
def (prec = Object.new).to_int; 2; end
assert_equal(0.99, 0.981.ceil(prec))
+
+ assert_equal(10000000000, 1.0.ceil(-10), "[Bug #20654]")
+ assert_equal(100000000000000000000, 1.0.ceil(-20), "[Bug #20654]")
+ assert_equal(100000000000000000000000000000000000000000000000000, 1.0.ceil(-50), "[Bug #20654]")
end
def test_truncate_with_precision
@@ -804,6 +850,14 @@ class TestFloat < Test::Unit::TestCase
o = Object.new
def o.to_f; inf = Float::INFINITY; inf/inf; end
assert_predicate(Float(o), :nan?)
+
+ assert_raise(Encoding::CompatibilityError) {Float("0".encode("utf-16be"))}
+ assert_raise(Encoding::CompatibilityError) {Float("0".encode("utf-16le"))}
+ assert_raise(Encoding::CompatibilityError) {Float("0".encode("utf-32be"))}
+ assert_raise(Encoding::CompatibilityError) {Float("0".encode("utf-32le"))}
+ assert_raise(Encoding::CompatibilityError) {Float("0".encode("iso-2022-jp"))}
+
+ assert_raise_with_message(ArgumentError, /\u{1f4a1}/) {Float("\u{1f4a1}")}
end
def test_invalid_str
diff --git a/test/ruby/test_frozen.rb b/test/ruby/test_frozen.rb
new file mode 100644
index 0000000000..2918a2afd8
--- /dev/null
+++ b/test/ruby/test_frozen.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: false
+require 'test/unit'
+
+class TestFrozen < Test::Unit::TestCase
+ def test_setting_ivar_on_frozen_obj
+ obj = Object.new
+ obj.freeze
+ assert_raise(FrozenError) { obj.instance_variable_set(:@a, 1) }
+ end
+
+ def test_setting_ivar_on_frozen_obj_with_ivars
+ obj = Object.new
+ obj.instance_variable_set(:@a, 1)
+ obj.freeze
+ assert_raise(FrozenError) { obj.instance_variable_set(:@b, 1) }
+ end
+
+ def test_setting_ivar_on_frozen_string
+ str = "str"
+ str.freeze
+ assert_raise(FrozenError) { str.instance_variable_set(:@a, 1) }
+ end
+
+ def test_setting_ivar_on_frozen_string_with_ivars
+ str = "str"
+ str.instance_variable_set(:@a, 1)
+ str.freeze
+ assert_raise(FrozenError) { str.instance_variable_set(:@b, 1) }
+ end
+end
diff --git a/test/ruby/test_gc.rb b/test/ruby/test_gc.rb
index baf9971c48..9a9796dc55 100644
--- a/test/ruby/test_gc.rb
+++ b/test/ruby/test_gc.rb
@@ -40,21 +40,98 @@ class TestGc < Test::Unit::TestCase
end
def test_enable_disable
+ EnvUtil.without_gc do
+ 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)
+ end
+ end
+
+ def test_gc_config_full_mark_by_default
+ omit "unsupoported platform/GC" unless defined?(GC.config)
+
+ config = GC.config
+ assert_not_empty(config)
+ assert_true(config[:rgengc_allow_full_mark])
+ end
+
+ def test_gc_config_invalid_args
+ omit "unsupoported platform/GC" unless defined?(GC.config)
+
+ assert_raise(ArgumentError) { GC.config(0) }
+ end
+
+ def test_gc_config_setting_returns_updated_config_hash
+ omit "unsupoported platform/GC" unless defined?(GC.config)
+
+ old_value = GC.config[:rgengc_allow_full_mark]
+ assert_true(old_value)
+
+ new_value = GC.config(rgengc_allow_full_mark: false)[:rgengc_allow_full_mark]
+ assert_false(new_value)
+ new_value = GC.config(rgengc_allow_full_mark: nil)[:rgengc_allow_full_mark]
+ assert_false(new_value)
+ ensure
+ GC.config(rgengc_allow_full_mark: old_value)
+ GC.start
+ end
+
+ def test_gc_config_setting_returns_nil_for_missing_keys
+ omit "unsupoported platform/GC" unless defined?(GC.config)
+
+ missing_value = GC.config(no_such_key: true)[:no_such_key]
+ assert_nil(missing_value)
+ ensure
+ GC.config(full_mark: true)
+ GC.start
+ end
+
+ def test_gc_config_disable_major
+ omit "unsupoported platform/GC" unless defined?(GC.config)
+
GC.enable
- assert_equal(false, GC.enable)
- assert_equal(false, GC.disable)
- assert_equal(true, GC.disable)
- assert_equal(true, GC.disable)
+ GC.start
+
+ GC.config(rgengc_allow_full_mark: false)
+ major_count = GC.stat[:major_gc_count]
+ minor_count = GC.stat[:minor_gc_count]
+
+ arr = []
+ (GC.stat_heap[0][:heap_eden_slots] * 2).times do
+ arr << Object.new
+ Object.new
+ end
+
+ assert_equal(major_count, GC.stat[:major_gc_count])
+ assert_operator(minor_count, :<=, GC.stat[:minor_gc_count])
assert_nil(GC.start)
- assert_equal(true, GC.enable)
- assert_equal(false, GC.enable)
ensure
- GC.enable
+ GC.config(rgengc_allow_full_mark: true)
+ GC.start
+ end
+
+ def test_gc_config_disable_major_gc_start_always_works
+ omit "unsupoported platform/GC" unless defined?(GC.config)
+
+ GC.config(full_mark: false)
+
+ major_count = GC.stat[:major_gc_count]
+ GC.start
+
+ assert_operator(major_count, :<, GC.stat[:major_gc_count])
+ ensure
+ GC.config(full_mark: true)
+ GC.start
end
def test_start_full_mark
return unless use_rgengc?
- skip 'stress' if GC.stress
+ omit 'stress' if GC.stress
3.times { GC.start } # full mark and next time it should be minor mark
GC.start(full_mark: false)
@@ -65,7 +142,7 @@ class TestGc < Test::Unit::TestCase
end
def test_start_immediate_sweep
- skip 'stress' if GC.stress
+ omit 'stress' if GC.stress
GC.start(immediate_sweep: false)
assert_equal false, GC.latest_gc_info(:immediate_sweep)
@@ -117,7 +194,7 @@ class TestGc < Test::Unit::TestCase
end
def test_stat_single
- skip 'stress' if GC.stress
+ omit 'stress' if GC.stress
stat = GC.stat
assert_equal stat[:count], GC.stat(:count)
@@ -125,29 +202,125 @@ class TestGc < Test::Unit::TestCase
end
def test_stat_constraints
- skip 'stress' if GC.stress
+ omit 'stress' if GC.stress
stat = GC.stat
+ # marking_time + sweeping_time could differ from time by 1 because they're stored in nanoseconds
+ assert_in_delta stat[:time], stat[:marking_time] + stat[:sweeping_time], 1
assert_equal stat[:total_allocated_pages], stat[:heap_allocated_pages] + stat[:total_freed_pages]
- assert_operator stat[:heap_sorted_length], :>=, stat[:heap_eden_pages] + stat[:heap_allocatable_pages], "stat is: " + stat.inspect
assert_equal stat[:heap_available_slots], stat[:heap_live_slots] + stat[:heap_free_slots] + stat[:heap_final_slots]
assert_equal stat[:heap_live_slots], stat[:total_allocated_objects] - stat[:total_freed_objects] - stat[:heap_final_slots]
- assert_equal stat[:heap_allocated_pages], stat[:heap_eden_pages] + stat[:heap_tomb_pages]
+ assert_equal stat[:heap_allocated_pages], stat[:heap_eden_pages]
if use_rgengc?
assert_equal stat[:count], stat[:major_gc_count] + stat[:minor_gc_count]
end
end
+ def test_stat_heap
+ omit 'stress' if GC.stress
+
+ stat_heap = {}
+ stat = {}
+ # Initialize to prevent GC in future calls
+ GC.stat_heap(0, stat_heap)
+ GC.stat(stat)
+
+ GC::INTERNAL_CONSTANTS[:SIZE_POOL_COUNT].times do |i|
+ EnvUtil.without_gc do
+ GC.stat_heap(i, stat_heap)
+ GC.stat(stat)
+ end
+
+ assert_equal (GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE] + GC::INTERNAL_CONSTANTS[:RVALUE_OVERHEAD]) * (2**i), stat_heap[:slot_size]
+ assert_operator stat_heap[:heap_eden_pages], :<=, stat[:heap_eden_pages]
+ assert_operator stat_heap[:heap_eden_slots], :>=, 0
+ assert_operator stat_heap[:total_allocated_pages], :>=, 0
+ assert_operator stat_heap[:force_major_gc_count], :>=, 0
+ assert_operator stat_heap[:force_incremental_marking_finish_count], :>=, 0
+ assert_operator stat_heap[:total_allocated_objects], :>=, 0
+ assert_operator stat_heap[:total_freed_objects], :>=, 0
+ assert_operator stat_heap[:total_freed_objects], :<=, stat_heap[:total_allocated_objects]
+ end
+
+ GC.stat_heap(0, stat_heap)
+ assert_equal stat_heap[:slot_size], GC.stat_heap(0, :slot_size)
+ assert_equal stat_heap[:slot_size], GC.stat_heap(0)[:slot_size]
+
+ assert_raise(ArgumentError) { GC.stat_heap(-1) }
+ assert_raise(ArgumentError) { GC.stat_heap(GC::INTERNAL_CONSTANTS[:SIZE_POOL_COUNT]) }
+ end
+
+ def test_stat_heap_all
+ omit "flaky with RJIT, which allocates objects itself" if defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled?
+ stat_heap_all = {}
+ stat_heap = {}
+ # Initialize to prevent GC in future calls
+ GC.stat_heap(0, stat_heap)
+ GC.stat_heap(nil, stat_heap_all)
+
+ GC::INTERNAL_CONSTANTS[:SIZE_POOL_COUNT].times do |i|
+ GC.stat_heap(nil, stat_heap_all)
+ GC.stat_heap(i, stat_heap)
+
+ # Remove keys that can vary between invocations
+ %i(total_allocated_objects).each do |sym|
+ stat_heap[sym] = stat_heap_all[i][sym] = 0
+ end
+
+ assert_equal stat_heap, stat_heap_all[i]
+ end
+
+ assert_raise(TypeError) { GC.stat_heap(nil, :slot_size) }
+ end
+
+ def test_stat_heap_constraints
+ omit 'stress' if GC.stress
+
+ stat = GC.stat
+ stat_heap = GC.stat_heap
+ 2.times do
+ GC.stat(stat)
+ GC.stat_heap(nil, stat_heap)
+ end
+
+ stat_heap_sum = Hash.new(0)
+ stat_heap.values.each do |hash|
+ hash.each { |k, v| stat_heap_sum[k] += v }
+ end
+
+ assert_equal stat[:heap_eden_pages], stat_heap_sum[:heap_eden_pages]
+ assert_equal stat[:heap_available_slots], stat_heap_sum[:heap_eden_slots]
+ assert_equal stat[:total_allocated_objects], stat_heap_sum[:total_allocated_objects]
+ assert_equal stat[:total_freed_objects], stat_heap_sum[:total_freed_objects]
+ end
+
+ def test_measure_total_time
+ assert_separately([], __FILE__, __LINE__, <<~RUBY)
+ GC.measure_total_time = false
+
+ time_before = GC.stat(:time)
+
+ # Generate some garbage
+ Random.new.bytes(100 * 1024 * 1024)
+ GC.start
+
+ time_after = GC.stat(:time)
+
+ # If time measurement is disabled, the time stat should not change
+ assert_equal time_before, time_after
+ RUBY
+ end
+
def test_latest_gc_info
- skip 'stress' if GC.stress
+ omit 'stress' if GC.stress
- assert_separately %w[--disable-gem], __FILE__, __LINE__, <<-'eom'
- GC.start
- count = GC.stat(:heap_free_slots) + GC.stat(:heap_allocatable_pages) * GC::INTERNAL_CONSTANTS[:HEAP_PAGE_OBJ_LIMIT]
- count.times{ "a" + "b" }
- assert_equal :newobj, GC.latest_gc_info[:gc_by]
- eom
+ assert_separately([], __FILE__, __LINE__, <<-'RUBY')
+ GC.start
+ count = GC.stat(:heap_free_slots) + GC.stat(:heap_allocatable_slots)
+ count.times{ "a" + "b" }
+ assert_equal :newobj, GC.latest_gc_info[:gc_by]
+ RUBY
GC.latest_gc_info(h = {}) # allocate hash and rehearsal
GC.start
@@ -158,6 +331,7 @@ class TestGc < Test::Unit::TestCase
assert_equal :force, h[:major_by] if use_rgengc?
assert_equal :method, h[:gc_by]
assert_equal true, h[:immediate_sweep]
+ assert_equal true, h.key?(:need_major_by)
GC.stress = true
assert_equal :force, GC.latest_gc_info[:major_by]
@@ -175,8 +349,85 @@ class TestGc < Test::Unit::TestCase
assert_raise_with_message(ArgumentError, /\u{30eb 30d3 30fc}/) {GC.latest_gc_info(:"\u{30eb 30d3 30fc}")}
end
+ def test_latest_gc_info_need_major_by
+ return unless use_rgengc?
+ omit 'stress' if GC.stress
+
+ 3.times { GC.start }
+ assert_nil GC.latest_gc_info(:need_major_by)
+
+ # allocate objects until need_major_by is set or major GC happens
+ objects = []
+ while GC.latest_gc_info(:need_major_by).nil?
+ objects.append(100.times.map { '*' })
+ end
+
+ EnvUtil.without_gc do
+ # We need to ensure that no GC gets ran before the call to GC.start since
+ # it would trigger a major GC. Assertions could allocate objects and
+ # trigger a GC so we don't run assertions until we perform the major GC.
+ need_major_by = GC.latest_gc_info(:need_major_by)
+ GC.start(full_mark: false) # should be upgraded to major
+ major_by = GC.latest_gc_info(:major_by)
+
+ assert_not_nil(need_major_by)
+ assert_not_nil(major_by)
+ end
+ end
+
+ def test_latest_gc_info_weak_references_count
+ assert_separately([], __FILE__, __LINE__, <<~RUBY)
+ GC.disable
+ count = 10_000
+ # Some weak references may be created, so allow some margin of error
+ error_tolerance = 100
+
+ # Run full GC to clear out weak references
+ GC.start
+ # Run full GC again to collect stats about weak references
+ GC.start
+
+ before_weak_references_count = GC.latest_gc_info(:weak_references_count)
+ before_retained_weak_references_count = GC.latest_gc_info(:retained_weak_references_count)
+
+ # Create some objects and place it in a WeakMap
+ wmap = ObjectSpace::WeakMap.new
+ ary = Array.new(count)
+ enum = count.times
+ enum.each.with_index do |i|
+ obj = Object.new
+ ary[i] = obj
+ wmap[obj] = nil
+ end
+
+ # Run full GC to collect stats about weak references
+ GC.start
+
+ assert_operator(GC.latest_gc_info(:weak_references_count), :>=, before_weak_references_count + count - error_tolerance)
+ assert_operator(GC.latest_gc_info(:retained_weak_references_count), :>=, before_retained_weak_references_count + count - error_tolerance)
+ assert_operator(GC.latest_gc_info(:retained_weak_references_count), :<=, GC.latest_gc_info(:weak_references_count))
+
+ before_weak_references_count = GC.latest_gc_info(:weak_references_count)
+ before_retained_weak_references_count = GC.latest_gc_info(:retained_weak_references_count)
+
+ ary = nil
+
+ # Free ary, which should empty out the wmap
+ GC.start
+ # Run full GC again to collect stats about weak references
+ GC.start
+
+ # Sometimes the WeakMap has one element, which might be held on by registers.
+ assert_operator(wmap.size, :<=, 1)
+
+ assert_operator(GC.latest_gc_info(:weak_references_count), :<=, before_weak_references_count - count + error_tolerance)
+ assert_operator(GC.latest_gc_info(:retained_weak_references_count), :<=, before_retained_weak_references_count - count + error_tolerance)
+ assert_operator(GC.latest_gc_info(:retained_weak_references_count), :<=, GC.latest_gc_info(:weak_references_count))
+ RUBY
+ end
+
def test_stress_compile_send
- assert_in_out_err(%w[--disable-gems], <<-EOS, [], [], "")
+ assert_in_out_err([], <<-EOS, [], [], "")
GC.stress = true
begin
eval("A::B.c(1, 1, d: 234)")
@@ -186,7 +437,7 @@ class TestGc < Test::Unit::TestCase
end
def test_singleton_method
- assert_in_out_err(%w[--disable-gems], <<-EOS, [], [], "[ruby-dev:42832]")
+ assert_in_out_err([], <<-EOS, [], [], "[ruby-dev:42832]")
GC.stress = true
10.times do
obj = Object.new
@@ -198,7 +449,7 @@ class TestGc < Test::Unit::TestCase
end
def test_singleton_method_added
- assert_in_out_err(%w[--disable-gems], <<-EOS, [], [], "[ruby-dev:44436]")
+ assert_in_out_err([], <<-EOS, [], [], "[ruby-dev:44436]")
class BasicObject
undef singleton_method_added
def singleton_method_added(mid)
@@ -214,19 +465,23 @@ class TestGc < Test::Unit::TestCase
def test_gc_parameter
env = {
- "RUBY_GC_MALLOC_LIMIT" => "60000000",
- "RUBY_GC_HEAP_INIT_SLOTS" => "100000"
+ "RUBY_GC_HEAP_INIT_SLOTS" => "100"
}
- assert_normal_exit("exit", "[ruby-core:39777]", :child_env => env)
+ assert_in_out_err([env, "-W0", "-e", "exit"], "", [], [])
+ assert_in_out_err([env, "-W:deprecated", "-e", "exit"], "", [],
+ /The environment variable RUBY_GC_HEAP_INIT_SLOTS is deprecated; use environment variables RUBY_GC_HEAP_%d_INIT_SLOTS instead/)
- env = {
- "RUBYOPT" => "",
- "RUBY_GC_HEAP_INIT_SLOTS" => "100000"
- }
- assert_in_out_err([env, "-e", "exit"], "", [], [], "[ruby-core:39795]")
- assert_in_out_err([env, "-W0", "-e", "exit"], "", [], [], "[ruby-core:39795]")
- assert_in_out_err([env, "-W1", "-e", "exit"], "", [], [], "[ruby-core:39795]")
- assert_in_out_err([env, "-w", "-e", "exit"], "", [], /RUBY_GC_HEAP_INIT_SLOTS=100000/, "[ruby-core:39795]")
+ env = {}
+ GC.stat_heap.keys.each do |heap|
+ env["RUBY_GC_HEAP_#{heap}_INIT_SLOTS"] = "200000"
+ end
+ assert_normal_exit("exit", "", :child_env => env)
+
+ env = {}
+ GC.stat_heap.keys.each do |heap|
+ env["RUBY_GC_HEAP_#{heap}_INIT_SLOTS"] = "0"
+ end
+ assert_normal_exit("exit", "", :child_env => env)
env = {
"RUBY_GC_HEAP_GROWTH_FACTOR" => "2.0",
@@ -236,16 +491,13 @@ class TestGc < Test::Unit::TestCase
assert_in_out_err([env, "-w", "-e", "exit"], "", [], /RUBY_GC_HEAP_GROWTH_FACTOR=2.0/, "")
assert_in_out_err([env, "-w", "-e", "exit"], "", [], /RUBY_GC_HEAP_GROWTH_MAX_SLOTS=10000/, "[ruby-core:57928]")
- env = {
- "RUBY_GC_HEAP_INIT_SLOTS" => "100000",
- "RUBY_GC_HEAP_FREE_SLOTS" => "10000",
- "RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR" => "0.9",
- }
- assert_normal_exit("exit", "", :child_env => env)
- assert_in_out_err([env, "-w", "-e", "exit"], "", [], /RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR=0\.9/, "")
-
- # always full GC when RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR < 1.0
- assert_in_out_err([env, "-e", "1000_000.times{Object.new}; p(GC.stat[:minor_gc_count] < GC.stat[:major_gc_count])"], "", ['true'], //, "") if use_rgengc?
+ if use_rgengc?
+ env = {
+ "RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR" => "0.4",
+ }
+ # always full GC when RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR < 1.0
+ assert_in_out_err([env, "-e", "GC.start; 1000_000.times{Object.new}; p(GC.stat[:minor_gc_count] < GC.stat[:major_gc_count])"], "", ['true'], //, "")
+ end
env = {
"RUBY_GC_MALLOC_LIMIT" => "60000000",
@@ -268,6 +520,53 @@ class TestGc < Test::Unit::TestCase
assert_in_out_err([env, "-w", "-e", "exit"], "", [], /RUBY_GC_OLDMALLOC_LIMIT_MAX=16000000/, "")
assert_in_out_err([env, "-w", "-e", "exit"], "", [], /RUBY_GC_OLDMALLOC_LIMIT_GROWTH_FACTOR=2.0/, "")
end
+
+ ["0.01", "0.1", "1.0"].each do |i|
+ env = {"RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR" => "0", "RUBY_GC_HEAP_REMEMBERED_WB_UNPROTECTED_OBJECTS_LIMIT_RATIO" => i}
+ assert_separately([env, "-W0"], __FILE__, __LINE__, <<~RUBY)
+ GC.disable
+ GC.start
+ assert_equal((GC.stat[:old_objects] * #{i}).to_i, GC.stat[:remembered_wb_unprotected_objects_limit])
+ RUBY
+ end
+ end
+
+ def test_gc_parameter_init_slots
+ assert_separately([], __FILE__, __LINE__, <<~RUBY, timeout: 60)
+ # Constant from gc.c.
+ GC_HEAP_INIT_SLOTS = 10_000
+
+ gc_count = GC.stat(:count)
+ # Fill up all of the size pools to the init slots
+ GC::INTERNAL_CONSTANTS[:SIZE_POOL_COUNT].times do |i|
+ capa = (GC.stat_heap(i, :slot_size) - GC::INTERNAL_CONSTANTS[:RVALUE_OVERHEAD] - (2 * RbConfig::SIZEOF["void*"])) / RbConfig::SIZEOF["void*"]
+ while GC.stat_heap(i, :heap_eden_slots) < GC_HEAP_INIT_SLOTS
+ Array.new(capa)
+ end
+ end
+
+ assert_equal gc_count, GC.stat(:count)
+ RUBY
+
+ env = {}
+ sizes = GC.stat_heap.keys.reverse.map { 20_000 }
+ GC.stat_heap.keys.each do |heap|
+ env["RUBY_GC_HEAP_#{heap}_INIT_SLOTS"] = sizes[heap].to_s
+ end
+ assert_separately([env, "-W0"], __FILE__, __LINE__, <<~RUBY, timeout: 60)
+ SIZES = #{sizes}
+
+ gc_count = GC.stat(:count)
+ # Fill up all of the size pools to the init slots
+ GC::INTERNAL_CONSTANTS[:SIZE_POOL_COUNT].times do |i|
+ capa = (GC.stat_heap(i, :slot_size) - GC::INTERNAL_CONSTANTS[:RVALUE_OVERHEAD] - (2 * RbConfig::SIZEOF["void*"])) / RbConfig::SIZEOF["void*"]
+ while GC.stat_heap(i, :heap_eden_slots) < SIZES[i]
+ Array.new(capa)
+ end
+ end
+
+ assert_equal gc_count, GC.stat(:count)
+ RUBY
end
def test_profiler_enabled
@@ -280,20 +579,28 @@ class TestGc < Test::Unit::TestCase
end
def test_profiler_clear
- skip "for now"
- assert_separately %w[--disable-gem], __FILE__, __LINE__, <<-'eom', timeout: 30
- GC::Profiler.enable
+ omit "for now"
+ assert_separately([], __FILE__, __LINE__, <<-'RUBY', timeout: 30)
+ GC::Profiler.enable
- GC.start
- assert_equal(1, GC::Profiler.raw_data.size)
- GC::Profiler.clear
- assert_equal(0, GC::Profiler.raw_data.size)
+ GC.start
+ assert_equal(1, GC::Profiler.raw_data.size)
+ GC::Profiler.clear
+ assert_equal(0, GC::Profiler.raw_data.size)
- 200.times{ GC.start }
- assert_equal(200, GC::Profiler.raw_data.size)
- GC::Profiler.clear
- assert_equal(0, GC::Profiler.raw_data.size)
- eom
+ 200.times{ GC.start }
+ assert_equal(200, GC::Profiler.raw_data.size)
+ GC::Profiler.clear
+ assert_equal(0, GC::Profiler.raw_data.size)
+ RUBY
+ end
+
+ def test_profiler_raw_data
+ GC::Profiler.enable
+ GC.start
+ assert GC::Profiler.raw_data
+ ensure
+ GC::Profiler.disable
end
def test_profiler_total_time
@@ -307,33 +614,67 @@ class TestGc < Test::Unit::TestCase
end
def test_finalizing_main_thread
- assert_in_out_err(%w[--disable-gems], <<-EOS, ["\"finalize\""], [], "[ruby-dev:46647]")
+ assert_in_out_err([], <<-EOS, ["\"finalize\""], [], "[ruby-dev:46647]")
ObjectSpace.define_finalizer(Thread.main) { p 'finalize' }
EOS
end
def test_expand_heap
- assert_separately %w[--disable-gem], __FILE__, __LINE__, <<-'eom'
- GC.start
- base_length = GC.stat[:heap_eden_pages]
- (base_length * 500).times{ 'a' }
- GC.start
- base_length = GC.stat[:heap_eden_pages]
- (base_length * 500).times{ 'a' }
- GC.start
- assert_in_epsilon base_length, (v = GC.stat[:heap_eden_pages]), 1/8r,
- "invalid heap expanding (base_length: #{base_length}, GC.stat[:heap_eden_pages]: #{v})"
+ assert_separately([], __FILE__, __LINE__, <<~'RUBY')
+ GC.start
+ base_length = GC.stat[:heap_eden_pages]
+ (base_length * 500).times{ 'a' }
+ GC.start
+ base_length = GC.stat[:heap_eden_pages]
+ (base_length * 500).times{ 'a' }
+ GC.start
+ assert_in_epsilon base_length, (v = GC.stat[:heap_eden_pages]), 1/8r,
+ "invalid heap expanding (base_length: #{base_length}, GC.stat[:heap_eden_pages]: #{v})"
- a = []
- (base_length * 500).times{ a << 'a'; nil }
- GC.start
- assert_operator base_length, :<, GC.stat[:heap_eden_pages] + 1
- eom
+ a = []
+ (base_length * 500).times{ a << 'a'; nil }
+ GC.start
+ assert_operator base_length, :<, GC.stat[:heap_eden_pages] + 1
+ RUBY
+ end
+
+ def test_thrashing_for_young_objects
+ # This test prevents bugs like [Bug #18929]
+
+ assert_separately([], __FILE__, __LINE__, <<-'RUBY', timeout: 60)
+ # Grow the heap
+ @ary = 100_000.times.map { Object.new }
+
+ # Warmup to make sure heap stabilizes
+ 1_000_000.times { Object.new }
+
+ before_stats = GC.stat
+ before_stat_heap = GC.stat_heap
+
+ 1_000_000.times { Object.new }
+
+ # Previous loop may have caused GC to be in an intermediate state,
+ # running a minor GC here will guarantee that GC will be complete
+ GC.start(full_mark: false)
+
+ after_stats = GC.stat
+ after_stat_heap = GC.stat_heap
+
+ # Debugging output to for failures in trunk-repeat50@phosphorus-docker
+ debug_msg = "before_stats: #{before_stats}\nbefore_stat_heap: #{before_stat_heap}\nafter_stats: #{after_stats}\nafter_stat_heap: #{after_stat_heap}"
+
+ # Should not be thrashing in page creation
+ assert_equal before_stats[:heap_allocated_pages], after_stats[:heap_allocated_pages], debug_msg
+ assert_equal 0, after_stats[:heap_empty_pages], debug_msg
+ assert_equal 0, after_stats[:total_freed_pages], debug_msg
+ # Only young objects, so should not trigger major GC
+ assert_equal before_stats[:major_gc_count], after_stats[:major_gc_count], debug_msg
+ RUBY
end
def test_gc_internals
assert_not_nil GC::INTERNAL_CONSTANTS[:HEAP_PAGE_OBJ_LIMIT]
- assert_not_nil GC::INTERNAL_CONSTANTS[:RVALUE_SIZE]
+ assert_not_nil GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE]
end
def test_sweep_in_finalizer
@@ -390,11 +731,11 @@ class TestGc < Test::Unit::TestCase
end
def test_finalizer_passed_object_id
- assert_in_out_err(%w[--disable-gems], <<-EOS, ["true"], [])
+ assert_in_out_err([], <<~RUBY, ["true"], [])
o = Object.new
obj_id = o.object_id
ObjectSpace.define_finalizer(o, ->(id){ p id == obj_id })
- EOS
+ RUBY
end
def test_verify_internal_consistency
@@ -424,13 +765,17 @@ class TestGc < Test::Unit::TestCase
end
def test_gc_disabled_start
- begin
- disabled = GC.disable
+ EnvUtil.without_gc do
c = GC.count
GC.start
assert_equal 1, GC.count - c
- ensure
- GC.enable unless disabled
+ end
+
+ EnvUtil.without_gc do
+ c = GC.count
+ GC.start(immediate_mark: false, immediate_sweep: false)
+ 10_000.times { Object.new }
+ assert_equal 1, GC.count - c
end
end
@@ -479,6 +824,15 @@ class TestGc < Test::Unit::TestCase
obj = nil
end
end;
+
+ assert_normal_exit "#{<<~"begin;"}\n#{<<~'end;'}", '[Bug #20042]'
+ begin;
+ def (f = Object.new).call = nil # missing ID
+ o = Object.new
+ ObjectSpace.define_finalizer(o, f)
+ o = nil
+ GC.start
+ end;
end
def test_object_ids_never_repeat
@@ -494,4 +848,28 @@ class TestGc < Test::Unit::TestCase
Module.new.class_eval( (["# shareable_constant_value: literal"] +
(0..100000).map {|i| "M#{ i } = {}" }).join("\n"))
end
+
+ def test_old_to_young_reference
+ EnvUtil.without_gc do
+ require "objspace"
+
+ old_obj = Object.new
+ 4.times { GC.start }
+
+ assert_include ObjectSpace.dump(old_obj), '"old":true'
+
+ young_obj = Object.new
+ old_obj.instance_variable_set(:@test, young_obj)
+
+ # Not immediately promoted to old generation
+ 3.times do
+ assert_not_include ObjectSpace.dump(young_obj), '"old":true'
+ GC.start
+ end
+
+ # Takes 4 GC to promote to old generation
+ GC.start
+ assert_include ObjectSpace.dump(young_obj), '"old":true'
+ end
+ end
end
diff --git a/test/ruby/test_gc_compact.rb b/test/ruby/test_gc_compact.rb
index 46683d0ed5..c331968b3d 100644
--- a/test/ruby/test_gc_compact.rb
+++ b/test/ruby/test_gc_compact.rb
@@ -1,34 +1,31 @@
# frozen_string_literal: true
require 'test/unit'
-require 'fiddle'
-require 'etc'
-class TestGCCompact < Test::Unit::TestCase
- module SupportsCompact
- def setup
- skip "autocompact not supported on this platform" unless supports_auto_compact?
- super
- end
-
- private
+if RUBY_PLATFORM =~ /s390x/
+ warn "Currently, it is known that the compaction does not work well on s390x; contribution is welcome https://github.com/ruby/ruby/pull/5077"
+ return
+end
+class TestGCCompact < Test::Unit::TestCase
+ module CompactionSupportInspector
def supports_auto_compact?
- return true unless defined?(Etc::SC_PAGE_SIZE)
+ GC::OPTS.include?("GC_COMPACTION_SUPPORTED")
+ end
+ end
- begin
- return GC::INTERNAL_CONSTANTS[:HEAP_PAGE_SIZE] % Etc.sysconf(Etc::SC_PAGE_SIZE) == 0
- rescue NotImplementedError
- rescue ArgumentError
- end
+ module OmitUnlessCompactSupported
+ include CompactionSupportInspector
- true
+ def setup
+ omit "autocompact not supported on this platform" unless supports_auto_compact?
+ super
end
end
- include SupportsCompact
+ include OmitUnlessCompactSupported
class AutoCompact < Test::Unit::TestCase
- include SupportsCompact
+ include OmitUnlessCompactSupported
def test_enable_autocompact
before = GC.auto_compact
@@ -73,7 +70,7 @@ class TestGCCompact < Test::Unit::TestCase
n.times do
break if count < GC.stat(:compact_count)
list2 << Object.new
- end and skip "implicit compaction didn't happen within #{n} objects"
+ end and omit "implicit compaction didn't happen within #{n} objects"
compact_stats = GC.latest_compact_info
refute_predicate compact_stats[:considered], :empty?
refute_predicate compact_stats[:moved], :empty?
@@ -82,13 +79,35 @@ class TestGCCompact < Test::Unit::TestCase
end
end
- def os_page_size
- return true unless defined?(Etc::SC_PAGE_SIZE)
- end
+ class CompactMethodsNotImplemented < Test::Unit::TestCase
+ include CompactionSupportInspector
- def setup
- skip "autocompact not supported on this platform" unless supports_auto_compact?
- super
+ def assert_not_implemented(method, *args)
+ omit "autocompact is supported on this platform" if supports_auto_compact?
+
+ assert_raise(NotImplementedError) { GC.send(method, *args) }
+ refute(GC.respond_to?(method), "GC.#{method} should be defined as rb_f_notimplement")
+ end
+
+ def test_gc_compact_not_implemented
+ assert_not_implemented(:compact)
+ end
+
+ def test_gc_auto_compact_get_not_implemented
+ assert_not_implemented(:auto_compact)
+ end
+
+ def test_gc_auto_compact_set_not_implemented
+ assert_not_implemented(:auto_compact=, true)
+ end
+
+ def test_gc_latest_compact_info_not_implemented
+ assert_not_implemented(:latest_compact_info)
+ end
+
+ def test_gc_verify_compaction_references_not_implemented
+ assert_not_implemented(:verify_compaction_references)
+ end
end
def test_gc_compact_stats
@@ -105,10 +124,6 @@ class TestGCCompact < Test::Unit::TestCase
refute_predicate compact_stats[:moved], :empty?
end
- def memory_location(obj)
- (Fiddle.dlwrap(obj) >> 1)
- end
-
def big_list(level = 10)
if level > 0
big_list(level - 1)
@@ -121,32 +136,17 @@ class TestGCCompact < Test::Unit::TestCase
end
end
- # Find an object that's allocated in a slot that had a previous
- # tenant, and that tenant moved and is still alive
- def find_object_in_recycled_slot(addresses)
- new_object = nil
-
- 100_000.times do
- new_object = Object.new
- if addresses.index memory_location(new_object)
- break
- end
- end
-
- new_object
- end
-
def test_complex_hash_keys
list_of_objects = big_list
hash = list_of_objects.hash
GC.verify_compaction_references(toward: :empty)
assert_equal hash, list_of_objects.hash
- GC.verify_compaction_references(double_heap: false)
+ GC.verify_compaction_references(expand_heap: false)
assert_equal hash, list_of_objects.hash
end
def test_ast_compacts
- assert_separately([], "#{<<~"begin;"}\n#{<<~"end;"}", timeout: 10, signal: :SEGV)
+ assert_separately([], "#{<<~"begin;"}\n#{<<~"end;"}", timeout: 10)
begin;
def walk_ast ast
children = ast.children.grep(RubyVM::AbstractSyntaxTree::Node)
@@ -166,4 +166,290 @@ class TestGCCompact < Test::Unit::TestCase
GC.compact
assert_equal count + 1, GC.stat(:compact_count)
end
+
+ def test_compacting_from_trace_point
+ obj = Object.new
+ def obj.tracee
+ :ret # expected to emit both line and call event from one instruction
+ end
+
+ results = []
+ TracePoint.new(:call, :line) do |tp|
+ results << tp.event
+ GC.verify_compaction_references
+ end.enable(target: obj.method(:tracee)) do
+ obj.tracee
+ end
+
+ assert_equal([:call, :line], results)
+ end
+
+ def test_updating_references_for_heap_allocated_shared_arrays
+ assert_separately(%w[-robjspace], "#{<<~"begin;"}\n#{<<~"end;"}", timeout: 10)
+ begin;
+ ary = []
+ 50.times { |i| ary << i }
+
+ # Pointer in slice should point to buffer of ary
+ slice = ary[10..40]
+
+ # Check that slice is pointing to buffer of ary
+ assert_include(ObjectSpace.dump(slice), '"shared":true')
+
+ # Run compaction to re-embed ary
+ GC.verify_compaction_references(expand_heap: true, toward: :empty)
+
+ # Assert that slice is pointer to updated buffer in ary
+ assert_equal(10, slice[0])
+ # Check that slice is still pointing to buffer of ary
+ assert_include(ObjectSpace.dump(slice), '"shared":true')
+ end;
+ end
+
+ def test_updating_references_for_embed_shared_arrays
+ omit if GC::INTERNAL_CONSTANTS[:SIZE_POOL_COUNT] == 1
+
+ assert_separately(%w[-robjspace], "#{<<~"begin;"}\n#{<<~"end;"}", timeout: 10)
+ begin;
+ ary = Array.new(50)
+ 50.times { |i| ary[i] = i }
+
+ # Ensure ary is embedded
+ assert_include(ObjectSpace.dump(ary), '"embedded":true')
+
+ slice = ary[10..40]
+
+ # Check that slice is pointing to buffer of ary
+ assert_include(ObjectSpace.dump(slice), '"shared":true')
+
+ # Run compaction to re-embed ary
+ GC.verify_compaction_references(expand_heap: true, toward: :empty)
+
+ # Assert that slice is pointer to updated buffer in ary
+ assert_equal(10, slice[0])
+ # Check that slice is still pointing to buffer of ary
+ assert_include(ObjectSpace.dump(slice), '"shared":true')
+ end;
+ end
+
+ def test_updating_references_for_heap_allocated_frozen_shared_arrays
+ assert_separately(%w[-robjspace], "#{<<~"begin;"}\n#{<<~"end;"}", timeout: 10)
+ begin;
+ ary = []
+ 50.times { |i| ary << i }
+ # Frozen arrays can become shared root without RARRAY_SHARED_ROOT_FLAG
+ ary.freeze
+
+ slice = ary[10..40]
+
+ # Check that slice is pointing to buffer of ary
+ assert_include(ObjectSpace.dump(slice), '"shared":true')
+
+ # Run compaction to re-embed ary
+ GC.verify_compaction_references(expand_heap: true, toward: :empty)
+
+ # Assert that slice is pointer to updated buffer in ary
+ assert_equal(10, slice[0])
+ # Check that slice is still pointing to buffer of ary
+ assert_include(ObjectSpace.dump(slice), '"shared":true')
+ end;
+ end
+
+ def test_updating_references_for_embed_frozen_shared_arrays
+ omit if GC::INTERNAL_CONSTANTS[:SIZE_POOL_COUNT] == 1
+
+ assert_separately(%w[-robjspace], "#{<<~"begin;"}\n#{<<~"end;"}", timeout: 10)
+ begin;
+ ary = Array.new(50)
+ 50.times { |i| ary[i] = i }
+ # Frozen arrays can become shared root without RARRAY_SHARED_ROOT_FLAG
+ ary.freeze
+
+ # Ensure ary is embedded
+ assert_include(ObjectSpace.dump(ary), '"embedded":true')
+
+ slice = ary[10..40]
+
+ # Check that slice is pointing to buffer of ary
+ assert_include(ObjectSpace.dump(slice), '"shared":true')
+
+ # Run compaction to re-embed ary
+ GC.verify_compaction_references(expand_heap: true, toward: :empty)
+
+ # Assert that slice is pointer to updated buffer in ary
+ assert_equal(10, slice[0])
+ # Check that slice is still pointing to buffer of ary
+ assert_include(ObjectSpace.dump(slice), '"shared":true')
+ end;
+ end
+
+ def test_moving_arrays_down_size_pools
+ omit if GC::INTERNAL_CONSTANTS[:SIZE_POOL_COUNT] == 1
+
+ assert_separately(%w[-robjspace], "#{<<~"begin;"}\n#{<<~"end;"}", timeout: 10)
+ begin;
+ ARY_COUNT = 50000
+
+ GC.verify_compaction_references(expand_heap: true, toward: :empty)
+
+ Fiber.new {
+ $arys = ARY_COUNT.times.map do
+ ary = "abbbbbbbbbb".chars
+ ary.uniq!
+ end
+ }.resume
+
+ stats = GC.verify_compaction_references(expand_heap: true, toward: :empty)
+ assert_operator(stats.dig(:moved_down, :T_ARRAY) || 0, :>=, ARY_COUNT - 10)
+ refute_empty($arys.keep_if { |o| ObjectSpace.dump(o).include?('"embedded":true') })
+ end;
+ end
+
+ def test_moving_arrays_up_size_pools
+ omit if GC::INTERNAL_CONSTANTS[:SIZE_POOL_COUNT] == 1
+
+ assert_separately(%w[-robjspace], "#{<<~"begin;"}\n#{<<~"end;"}", timeout: 10)
+ begin;
+ ARY_COUNT = 50000
+
+ GC.verify_compaction_references(expand_heap: true, toward: :empty)
+
+ Fiber.new {
+ ary = "hello".chars
+ $arys = ARY_COUNT.times.map do
+ x = []
+ ary.each { |e| x << e }
+ x
+ end
+ }.resume
+
+ stats = GC.verify_compaction_references(expand_heap: true, toward: :empty)
+ assert_operator(stats.dig(:moved_up, :T_ARRAY) || 0, :>=, ARY_COUNT - 10)
+ refute_empty($arys.keep_if { |o| ObjectSpace.dump(o).include?('"embedded":true') })
+ end;
+ end
+
+ def test_moving_objects_between_size_pools
+ omit if GC::INTERNAL_CONSTANTS[:SIZE_POOL_COUNT] == 1
+
+ assert_separately(%w[-robjspace], "#{<<~"begin;"}\n#{<<~"end;"}", timeout: 60)
+ begin;
+ class Foo
+ def add_ivars
+ 10.times do |i|
+ instance_variable_set("@foo" + i.to_s, 0)
+ end
+ end
+ end
+
+ OBJ_COUNT = 50000
+
+ GC.verify_compaction_references(expand_heap: true, toward: :empty)
+
+ Fiber.new {
+ $ary = OBJ_COUNT.times.map { Foo.new }
+ $ary.each(&:add_ivars)
+
+ GC.start
+ Foo.new.add_ivars
+ }.resume
+
+ stats = GC.verify_compaction_references(expand_heap: true, toward: :empty)
+
+ assert_operator(stats.dig(:moved_up, :T_OBJECT) || 0, :>=, OBJ_COUNT - 10)
+ refute_empty($ary.keep_if { |o| ObjectSpace.dump(o).include?('"embedded":true') })
+ end;
+ end
+
+ def test_moving_strings_up_size_pools
+ omit if GC::INTERNAL_CONSTANTS[:SIZE_POOL_COUNT] == 1
+
+ assert_separately(%w[-robjspace], "#{<<~"begin;"}\n#{<<~"end;"}", timeout: 30)
+ begin;
+ STR_COUNT = 50000
+
+ GC.verify_compaction_references(expand_heap: true, toward: :empty)
+
+ Fiber.new {
+ str = "a" * GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE] * 4
+ $ary = STR_COUNT.times.map { +"" << str }
+ }.resume
+
+ stats = GC.verify_compaction_references(expand_heap: true, toward: :empty)
+
+ assert_operator(stats[:moved_up][:T_STRING], :>=, STR_COUNT - 10)
+ refute_empty($ary.keep_if { |o| ObjectSpace.dump(o).include?('"embedded":true') })
+ end;
+ end
+
+ def test_moving_strings_down_size_pools
+ omit if GC::INTERNAL_CONSTANTS[:SIZE_POOL_COUNT] == 1
+
+ assert_separately(%w[-robjspace], "#{<<~"begin;"}\n#{<<~"end;"}", timeout: 30)
+ begin;
+ STR_COUNT = 50000
+
+ GC.verify_compaction_references(expand_heap: true, toward: :empty)
+
+ Fiber.new {
+ $ary = STR_COUNT.times.map { ("a" * GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE] * 4).squeeze! }
+ }.resume
+
+ stats = GC.verify_compaction_references(expand_heap: true, toward: :empty)
+
+ assert_operator(stats[:moved_down][:T_STRING], :>=, STR_COUNT - 10)
+ refute_empty($ary.keep_if { |o| ObjectSpace.dump(o).include?('"embedded":true') })
+ end;
+ end
+
+ def test_moving_hashes_down_size_pools
+ omit if GC::INTERNAL_CONSTANTS[:SIZE_POOL_COUNT] == 1
+ # AR and ST hashes are in the same size pool on 32 bit
+ omit unless RbConfig::SIZEOF["uint64_t"] <= RbConfig::SIZEOF["void*"]
+
+ assert_separately(%w[-robjspace], "#{<<~"begin;"}\n#{<<~"end;"}", timeout: 30)
+ begin;
+ HASH_COUNT = 50000
+
+ GC.verify_compaction_references(expand_heap: true, toward: :empty)
+
+ Fiber.new {
+ base_hash = { a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8 }
+ $ary = HASH_COUNT.times.map { base_hash.dup }
+ $ary.each_with_index { |h, i| h[:i] = 9 }
+ }.resume
+
+ stats = GC.verify_compaction_references(expand_heap: true, toward: :empty)
+
+ assert_operator(stats[:moved_down][:T_HASH], :>=, HASH_COUNT - 10)
+ end;
+ end
+
+ def test_moving_objects_between_size_pools_keeps_shape_frozen_status
+ # [Bug #19536]
+ assert_separately([], "#{<<~"begin;"}\n#{<<~"end;"}")
+ begin;
+ class A
+ def add_ivars
+ @a = @b = @c = @d = 1
+ end
+
+ def set_a
+ @a = 10
+ end
+ end
+
+ a = A.new
+ a.add_ivars
+ a.freeze
+
+ b = A.new
+ b.add_ivars
+ b.set_a # Set the inline cache in set_a
+
+ GC.verify_compaction_references(expand_heap: true, toward: :empty)
+
+ assert_raise(FrozenError) { a.set_a }
+ end;
+ end
end
diff --git a/test/ruby/test_hash.rb b/test/ruby/test_hash.rb
index f79879c20a..f60ba0cffd 100644
--- a/test/ruby/test_hash.rb
+++ b/test/ruby/test_hash.rb
@@ -4,7 +4,6 @@ require 'test/unit'
EnvUtil.suppress_warning {require 'continuation'}
class TestHash < Test::Unit::TestCase
-
def test_hash
x = @cls[1=>2, 2=>4, 3=>6]
y = @cls[1=>2, 2=>4, 3=>6] # y = {1, 2, 2, 4, 3, 6} # 1.9 doesn't support
@@ -85,20 +84,9 @@ class TestHash < Test::Unit::TestCase
self => 'self', true => 'true', nil => 'nil',
'nil' => nil
]
- @verbose = $VERBOSE
end
def teardown
- $VERBOSE = @verbose
- end
-
- def test_bad_initialize_copy
- h = Class.new(Hash) {
- def initialize_copy(h)
- super(Object.new)
- end
- }.new
- assert_raise(TypeError) { h.dup }
end
def test_clear_initialize_copy
@@ -113,35 +101,6 @@ class TestHash < Test::Unit::TestCase
assert_equal(2, h[1])
end
- def test_dup_will_not_rehash
- assert_hash_does_not_rehash(&:dup)
- end
-
- def assert_hash_does_not_rehash
- obj = Object.new
- class << obj
- attr_accessor :hash_calls
- def hash
- @hash_calls += 1
- super
- end
- end
- obj.hash_calls = 0
- hash = {obj => 42}
- assert_equal(1, obj.hash_calls)
- yield hash
- assert_equal(1, obj.hash_calls)
- end
-
- def test_select_reject_will_not_rehash
- assert_hash_does_not_rehash do |hash|
- hash.select { true }
- end
- assert_hash_does_not_rehash do |hash|
- hash.reject { false }
- end
- end
-
def test_s_AREF_from_hash
h = @cls["a" => 100, "b" => 200]
assert_equal(100, h['a'])
@@ -219,6 +178,16 @@ class TestHash < Test::Unit::TestCase
assert_equal('default', h['spurious'])
end
+ def test_st_literal_memory_leak
+ assert_no_memory_leak([], "", "#{<<~"begin;"}\n#{<<~'end;'}", rss: true)
+ begin;
+ 1_000_000.times do
+ # >8 element hashes are ST allocated rather than AR allocated
+ {a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9}
+ end
+ end;
+ end
+
def test_try_convert
assert_equal({1=>2}, Hash.try_convert({1=>2}))
assert_equal(nil, Hash.try_convert("1=>2"))
@@ -294,64 +263,6 @@ class TestHash < Test::Unit::TestCase
assert_equal(256, h[z])
end
- def test_AREF_fstring_key
- # warmup ObjectSpace.count_objects
- ObjectSpace.count_objects
-
- h = {"abc" => 1}
- before = ObjectSpace.count_objects[:T_STRING]
- 5.times{ h["abc"] }
- assert_equal before, ObjectSpace.count_objects[:T_STRING]
- end
-
- def test_ASET_fstring_key
- a, b = {}, {}
- assert_equal 1, a["abc"] = 1
- assert_equal 1, b["abc"] = 1
- assert_same a.keys[0], b.keys[0]
- end
-
- def test_ASET_fstring_non_literal_key
- underscore = "_"
- non_literal_strings = Proc.new{ ["abc#{underscore}def", "abc" * 5, "abc" + "def", "" << "ghi" << "jkl"] }
-
- a, b = {}, {}
- non_literal_strings.call.each do |string|
- assert_equal 1, a[string] = 1
- end
-
- non_literal_strings.call.each do |string|
- assert_equal 1, b[string] = 1
- end
-
- [a.keys, b.keys].transpose.each do |key_a, key_b|
- assert_same key_a, key_b
- end
- end
-
- def test_hash_aset_fstring_identity
- h = {}.compare_by_identity
- h['abc'] = 1
- h['abc'] = 2
- assert_equal 2, h.size, '[ruby-core:78783] [Bug #12855]'
- end
-
- def test_hash_aref_fstring_identity
- h = {}.compare_by_identity
- h['abc'] = 1
- assert_nil h['abc'], '[ruby-core:78783] [Bug #12855]'
- end
-
- def test_NEWHASH_fstring_key
- a = {"ABC" => :t}
- b = {"ABC" => :t}
- assert_same a.keys[0], b.keys[0]
- assert_same "ABC".freeze, a.keys[0]
- var = +'ABC'
- c = { var => :t }
- assert_same "ABC".freeze, c.keys[0]
- end
-
def test_EQUAL # '=='
h1 = @cls[ "a" => 1, "c" => 2 ]
h2 = @cls[ "a" => 1, "c" => 2, 7 => 35 ]
@@ -458,6 +369,10 @@ class TestHash < Test::Unit::TestCase
end
end
assert_equal(base.dup, h)
+
+ h = base.dup
+ assert_same h, h.delete_if {h.assoc(nil); true}
+ assert_empty h
end
def test_keep_if
@@ -828,14 +743,6 @@ class TestHash < Test::Unit::TestCase
assert_predicate(h, :compare_by_identity?)
end
- def test_replace_bug15358
- h1 = {}
- h2 = {a:1,b:2,c:3,d:4,e:5}
- h2.replace(h1)
- GC.start
- assert(true)
- end
-
def test_shift
h = @h.dup
@@ -951,13 +858,6 @@ class TestHash < Test::Unit::TestCase
assert_instance_of(Hash, h)
end
- def test_nil_to_h
- h = nil.to_h
- assert_equal({}, h)
- assert_nil(h.default)
- assert_nil(h.default_proc)
- end
-
def test_to_s
h = @cls[ 1 => 2, "cat" => "dog", 1.5 => :fred ]
assert_equal(h.inspect, h.to_s)
@@ -1004,12 +904,6 @@ class TestHash < Test::Unit::TestCase
assert_equal([], expected - vals)
end
- def test_initialize_wrong_arguments
- assert_raise(ArgumentError) do
- Hash.new(0) { }
- end
- end
-
def test_create
assert_equal({1=>2, 3=>4}, @cls[[[1,2],[3,4]]])
assert_raise(ArgumentError) { @cls[0, 1, 2] }
@@ -1048,14 +942,14 @@ class TestHash < Test::Unit::TestCase
h = @cls.new {|hh, k| :foo }
h[1] = 2
assert_equal([1, 2], h.shift)
- assert_equal(:foo, h.shift)
- assert_equal(:foo, h.shift)
+ assert_nil(h.shift)
+ assert_nil(h.shift)
h = @cls.new(:foo)
h[1] = 2
assert_equal([1, 2], h.shift)
- assert_equal(:foo, h.shift)
- assert_equal(:foo, h.shift)
+ assert_nil(h.shift)
+ assert_nil(h.shift)
h =@cls[1=>2]
h.each { assert_equal([1, 2], h.shift) }
@@ -1066,7 +960,20 @@ class TestHash < Test::Unit::TestCase
def h.default(k = nil)
super.upcase
end
- assert_equal("FOO", h.shift)
+ assert_nil(h.shift)
+ end
+
+ def test_shift_for_empty_hash
+ # [ruby-dev:51159]
+ h = @cls[]
+ 100.times{|n|
+ while h.size < n
+ k = Random.rand 0..1<<30
+ h[k] = 1
+ end
+ 0 while h.shift
+ assert_equal({}, h)
+ }
end
def test_reject_bang2
@@ -1278,15 +1185,6 @@ class TestHash < Test::Unit::TestCase
assert_raise(FrozenError) { h2.replace(42) }
end
- def test_replace_memory_leak
- assert_no_memory_leak([], "#{<<-"begin;"}", "#{<<-'end;'}")
- h = ("aa".."zz").each_with_index.to_h
- 10_000.times {h.dup}
- begin;
- 500_000.times {h.dup.replace(h)}
- end;
- end
-
def test_size2
assert_equal(0, @cls[].size)
end
@@ -1370,6 +1268,15 @@ class TestHash < Test::Unit::TestCase
assert_equal(@cls[a: 10, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10], h)
end
+ def test_update_on_identhash
+ key = +'a'
+ i = @cls[].compare_by_identity
+ i[key] = 0
+ h = @cls[].update(i)
+ key.upcase!
+ assert_equal(0, h.fetch('a'))
+ end
+
def test_merge
h1 = @cls[1=>2, 3=>4]
h2 = {1=>3, 5=>7}
@@ -1392,10 +1299,10 @@ class TestHash < Test::Unit::TestCase
expected[7] = 8
h2 = h.merge(7=>8)
assert_equal(expected, h2)
- assert_equal(true, h2.compare_by_identity?)
+ assert_predicate(h2, :compare_by_identity?)
h2 = h.merge({})
assert_equal(h, h2)
- assert_equal(true, h2.compare_by_identity?)
+ assert_predicate(h2, :compare_by_identity?)
h = @cls[]
h.compare_by_identity
@@ -1403,10 +1310,10 @@ class TestHash < Test::Unit::TestCase
h1.compare_by_identity
h2 = h.merge(7=>8)
assert_equal(h1, h2)
- assert_equal(true, h2.compare_by_identity?)
+ assert_predicate(h2, :compare_by_identity?)
h2 = h.merge({})
assert_equal(h, h2)
- assert_equal(true, h2.compare_by_identity?)
+ assert_predicate(h2, :compare_by_identity?)
end
def test_merge!
@@ -1461,6 +1368,8 @@ class TestHash < Test::Unit::TestCase
end
def test_callcc
+ omit 'requires callcc support' unless respond_to?(:callcc)
+
h = @cls[1=>2]
c = nil
f = false
@@ -1481,6 +1390,8 @@ class TestHash < Test::Unit::TestCase
end
def test_callcc_iter_level
+ omit 'requires callcc support' unless respond_to?(:callcc)
+
bug9105 = '[ruby-dev:47803] [Bug #9105]'
h = @cls[1=>2, 3=>4]
c = nil
@@ -1499,6 +1410,8 @@ class TestHash < Test::Unit::TestCase
end
def test_callcc_escape
+ omit 'requires callcc support' unless respond_to?(:callcc)
+
bug9105 = '[ruby-dev:47803] [Bug #9105]'
assert_nothing_raised(RuntimeError, bug9105) do
h=@cls[]
@@ -1513,6 +1426,8 @@ class TestHash < Test::Unit::TestCase
end
def test_callcc_reenter
+ omit 'requires callcc support' unless respond_to?(:callcc)
+
bug9105 = '[ruby-dev:47803] [Bug #9105]'
assert_nothing_raised(RuntimeError, bug9105) do
h = @cls[1=>2,3=>4]
@@ -1560,6 +1475,16 @@ class TestHash < Test::Unit::TestCase
assert_predicate(h.dup, :compare_by_identity?, bug8703)
end
+ def test_compare_by_identy_memory_leak
+ assert_no_memory_leak([], "", "#{<<~"begin;"}\n#{<<~'end;'}", "[Bug #20145]", rss: true)
+ begin;
+ h = { 1 => 2 }.compare_by_identity
+ 1_000_000.times do
+ h.select { false }
+ end
+ end;
+ end
+
def test_same_key
bug9646 = '[ruby-dev:48047] [Bug #9646] Infinite loop at Hash#each'
h = @cls[a=[], 1]
@@ -1690,115 +1615,6 @@ class TestHash < Test::Unit::TestCase
end
end
- def test_exception_in_rehash_memory_leak
- return unless @cls == Hash
-
- bug9187 = '[ruby-core:58728] [Bug #9187]'
-
- prepare = <<-EOS
- class Foo
- def initialize
- @raise = false
- end
-
- def hash
- raise if @raise
- @raise = true
- return 0
- end
- end
- h = {Foo.new => true}
- EOS
-
- code = <<-EOS
- 10_0000.times do
- h.rehash rescue nil
- end
- GC.start
- EOS
-
- assert_no_memory_leak([], prepare, code, bug9187)
- end
-
- def test_wrapper
- bug9381 = '[ruby-core:59638] [Bug #9381]'
-
- wrapper = Class.new do
- def initialize(obj)
- @obj = obj
- end
-
- def hash
- @obj.hash
- end
-
- def eql?(other)
- @obj.eql?(other)
- end
- end
-
- bad = [
- 5, true, false, nil,
- 0.0, 1.72723e-77,
- :foo, "dsym_#{self.object_id.to_s(16)}_#{Time.now.to_i.to_s(16)}".to_sym,
- "str",
- ].select do |x|
- hash = {x => bug9381}
- hash[wrapper.new(x)] != bug9381
- end
- assert_empty(bad, bug9381)
- end
-
- def assert_hash_random(obj, dump = obj.inspect)
- a = [obj.hash.to_s]
- 3.times {
- assert_in_out_err(["-e", "print (#{dump}).hash"], "") do |r, e|
- a += r
- assert_equal([], e)
- end
- }
- assert_not_equal([obj.hash.to_s], a.uniq)
- assert_operator(a.uniq.size, :>, 2, proc {a.inspect})
- end
-
- def test_string_hash_random
- assert_hash_random('abc')
- end
-
- def test_symbol_hash_random
- assert_hash_random(:-)
- assert_hash_random(:foo)
- assert_hash_random("dsym_#{self.object_id.to_s(16)}_#{Time.now.to_i.to_s(16)}".to_sym)
- end
-
- def test_integer_hash_random
- assert_hash_random(0)
- assert_hash_random(+1)
- assert_hash_random(-1)
- assert_hash_random(+(1<<100))
- assert_hash_random(-(1<<100))
- end
-
- def test_float_hash_random
- assert_hash_random(0.0)
- assert_hash_random(+1.0)
- assert_hash_random(-1.0)
- assert_hash_random(1.72723e-77)
- assert_hash_random(Float::INFINITY, "Float::INFINITY")
- end
-
- def test_label_syntax
- return unless @cls == Hash
-
- feature4935 = '[ruby-core:37553] [Feature #4935]'
- x = 'world'
- hash = assert_nothing_raised(SyntaxError, feature4935) do
- break eval(%q({foo: 1, "foo-bar": 2, "hello-#{x}": 3, 'hello-#{x}': 4, 'bar': {}}))
- end
- assert_equal({:foo => 1, :'foo-bar' => 2, :'hello-world' => 3, :'hello-#{x}' => 4, :bar => {}}, hash, feature4935)
- x = x
- end
-
def test_dig
h = @cls[a: @cls[b: [1, 2, 3]], c: 4]
assert_equal(1, h.dig(:a, :b, 0))
@@ -1818,12 +1634,12 @@ class TestHash < Test::Unit::TestCase
def o.respond_to?(*args)
super
end
- assert_raise(TypeError, bug12030) {{foo: o}.dig(:foo, :foo)}
+ assert_raise(TypeError, bug12030) {@cls[foo: o].dig(:foo, :foo)}
end
def test_cmp
- h1 = {a:1, b:2}
- h2 = {a:1, b:2, c:3}
+ h1 = @cls[a:1, b:2]
+ h2 = @cls[a:1, b:2, c:3]
assert_operator(h1, :<=, h1)
assert_operator(h1, :<=, h2)
@@ -1847,8 +1663,8 @@ class TestHash < Test::Unit::TestCase
end
def test_cmp_samekeys
- h1 = {a:1}
- h2 = {a:2}
+ h1 = @cls[a:1]
+ h2 = @cls[a:2]
assert_operator(h1, :<=, h1)
assert_not_operator(h1, :<=, h2)
@@ -1872,15 +1688,15 @@ class TestHash < Test::Unit::TestCase
end
def test_to_proc
- h = {
+ h = @cls[
1 => 10,
2 => 20,
3 => 30,
- }
+ ]
assert_equal([10, 20, 30], [1, 2, 3].map(&h))
- assert_equal(true, h.to_proc.lambda?)
+ assert_predicate(h.to_proc, :lambda?)
end
def test_transform_keys
@@ -2010,22 +1826,6 @@ class TestHash < Test::Unit::TestCase
assert_equal(@cls[a: 2, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9, j: 10], x)
end
- def test_broken_hash_value
- bug14218 = '[ruby-core:84395] [Bug #14218]'
-
- assert_equal(0, 1_000_000.times.count{a=Object.new.hash; b=Object.new.hash; a < 0 && b < 0 && a + b > 0}, bug14218)
- assert_equal(0, 1_000_000.times.count{a=Object.new.hash; b=Object.new.hash; 0 + a + b != 0 + b + a}, bug14218)
- end
-
- def test_reserved_hash_val
- s = Struct.new(:hash)
- h = {}
- keys = [*0..8]
- keys.each {|i| h[s.new(i)]=true}
- msg = proc {h.inspect}
- assert_equal(keys, h.keys.map(&:hash), msg)
- end
-
def hrec h, n, &b
if n > 0
h.each{hrec(h, n-1, &b)}
@@ -2055,6 +1855,27 @@ class TestHash < Test::Unit::TestCase
# ignore
end
+ # Previously this test would fail because rb_hash inside opt_aref would look
+ # at the current method name
+ def test_hash_recursion_independent_of_mid
+ o = Class.new do
+ def hash(h, k)
+ h[k]
+ end
+
+ def any_other_name(h, k)
+ h[k]
+ end
+ end.new
+
+ rec = []; rec << rec
+
+ h = @cls[]
+ h[rec] = 1
+ assert o.hash(h, rec)
+ assert o.any_other_name(h, rec)
+ end
+
class TestSubHash < TestHash
class SubHash < Hash
end
@@ -2064,6 +1885,341 @@ class TestHash < Test::Unit::TestCase
super
end
end
+end
+
+class TestHashOnly < Test::Unit::TestCase
+ def test_bad_initialize_copy
+ h = Class.new(Hash) {
+ def initialize_copy(h)
+ super(Object.new)
+ end
+ }.new
+ assert_raise(TypeError) { h.dup }
+ end
+
+ def test_dup_will_not_rehash
+ assert_hash_does_not_rehash(&:dup)
+ end
+
+ def assert_hash_does_not_rehash
+ obj = Object.new
+ class << obj
+ attr_accessor :hash_calls
+ def hash
+ @hash_calls += 1
+ super
+ end
+ end
+ obj.hash_calls = 0
+ hash = {obj => 42}
+ assert_equal(1, obj.hash_calls)
+ yield hash
+ assert_equal(1, obj.hash_calls)
+ end
+
+ def test_select_reject_will_not_rehash
+ assert_hash_does_not_rehash do |hash|
+ hash.select { true }
+ end
+ assert_hash_does_not_rehash do |hash|
+ hash.reject { false }
+ end
+ end
+
+ def test_st_literal_memory_leak
+ assert_no_memory_leak([], "", "#{<<~"begin;"}\n#{<<~'end;'}", rss: true)
+ begin;
+ 1_000_000.times do
+ # >8 element hashes are ST allocated rather than AR allocated
+ {a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9}
+ end
+ end;
+ end
+
+ def test_compare_by_id_memory_leak
+ assert_no_memory_leak([], "", <<~RUBY, rss: true)
+ 1_000_000.times do
+ {a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8}.compare_by_identity
+ end
+ RUBY
+ end
+
+ def test_try_convert
+ assert_equal({1=>2}, Hash.try_convert({1=>2}))
+ assert_equal(nil, Hash.try_convert("1=>2"))
+ o = Object.new
+ def o.to_hash; {3=>4} end
+ assert_equal({3=>4}, Hash.try_convert(o))
+ end
+
+ def test_AREF_fstring_key
+ # warmup ObjectSpace.count_objects
+ ObjectSpace.count_objects
+
+ h = {"abc" => 1}
+ before = ObjectSpace.count_objects[:T_STRING]
+ 5.times{ h["abc"] }
+ assert_equal before, ObjectSpace.count_objects[:T_STRING]
+ end
+
+ def test_AREF_fstring_key_default_proc
+ assert_separately(['--disable-frozen-string-literal'], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ h = Hash.new do |h, k|
+ k.frozen?
+ end
+
+ str = "foo"
+ refute str.frozen?
+ refute h[str]
+ refute h["foo"]
+ end;
+ end
+
+ def test_ASET_fstring_key
+ a, b = {}, {}
+ assert_equal 1, a["abc"] = 1
+ assert_equal 1, b["abc"] = 1
+ assert_same a.keys[0], b.keys[0]
+ end
+
+ def test_ASET_fstring_non_literal_key
+ underscore = "_"
+ non_literal_strings = Proc.new{ ["abc#{underscore}def", "abc" * 5, "abc" + "def", "" << "ghi" << "jkl"] }
+
+ a, b = {}, {}
+ non_literal_strings.call.each do |string|
+ assert_equal 1, a[string] = 1
+ end
+
+ non_literal_strings.call.each do |string|
+ assert_equal 1, b[string] = 1
+ end
+
+ [a.keys, b.keys].transpose.each do |key_a, key_b|
+ assert_same key_a, key_b
+ end
+ end
+
+ def test_hash_aset_fstring_identity
+ h = {}.compare_by_identity
+ h['abc'] = 1
+ h['abc'] = 2
+ assert_equal 2, h.size, '[ruby-core:78783] [Bug #12855]'
+ end
+
+ def test_hash_aref_fstring_identity
+ h = {}.compare_by_identity
+ h['abc'] = 1
+ assert_nil h['abc'], '[ruby-core:78783] [Bug #12855]'
+ end
+
+ def test_NEWHASH_fstring_key
+ a = {"ABC" => :t}
+ b = {"ABC" => :t}
+ assert_same a.keys[0], b.keys[0]
+ assert_same "ABC".freeze, a.keys[0]
+ var = +'ABC'
+ c = { var => :t }
+ assert_same "ABC".freeze, c.keys[0]
+ end
+
+ def test_rehash_memory_leak
+ assert_no_memory_leak([], <<~PREP, <<~CODE, rss: true)
+ ar_hash = 1.times.map { |i| [i, i] }.to_h
+ st_hash = 10.times.map { |i| [i, i] }.to_h
+
+ code = proc do
+ ar_hash.rehash
+ st_hash.rehash
+ end
+ 1_000.times(&code)
+ PREP
+ 1_000_000.times(&code)
+ CODE
+ end
+
+ def test_replace_bug15358
+ h1 = {}
+ h2 = {a:1,b:2,c:3,d:4,e:5}
+ h2.replace(h1)
+ GC.start
+ assert(true)
+ end
+
+ def test_replace_st_with_ar
+ # ST hash
+ h1 = { a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7, h: 8, i: 9 }
+ # AR hash
+ h2 = { a: 1, b: 2, c: 3, d: 4, e: 5, f: 6, g: 7 }
+ # Replace ST hash with AR hash
+ h1.replace(h2)
+ assert_equal(h2, h1)
+ end
+
+ def test_nil_to_h
+ h = nil.to_h
+ assert_equal({}, h)
+ assert_nil(h.default)
+ assert_nil(h.default_proc)
+ end
+
+ def test_initialize_wrong_arguments
+ assert_raise(ArgumentError) do
+ Hash.new(0) { }
+ end
+ end
+
+ def test_replace_memory_leak
+ assert_no_memory_leak([], "#{<<-"begin;"}", "#{<<-'end;'}", rss: true)
+ h = ("aa".."zz").each_with_index.to_h
+ 10_000.times {h.dup}
+ begin;
+ 500_000.times {h.dup.replace(h)}
+ end;
+ end
+
+ def hash_iter_recursion(h, level)
+ return if level == 0
+ h.each_key {}
+ h.each_value { hash_iter_recursion(h, level - 1) }
+ end
+
+ def test_iterlevel_in_ivar_bug19589
+ h = { a: nil }
+ hash_iter_recursion(h, 200)
+ assert true
+ end
+
+ def test_exception_in_rehash_memory_leak
+ bug9187 = '[ruby-core:58728] [Bug #9187]'
+
+ prepare = <<-EOS
+ class Foo
+ def initialize
+ @raise = false
+ end
+
+ def hash
+ raise if @raise
+ @raise = true
+ return 0
+ end
+ end
+ h = {Foo.new => true}
+ EOS
+
+ code = <<-EOS
+ 10_0000.times do
+ h.rehash rescue nil
+ end
+ GC.start
+ EOS
+
+ assert_no_memory_leak([], prepare, code, bug9187)
+ end
+
+ def test_memory_size_after_delete
+ require 'objspace'
+ h = {}
+ 1000.times {|i| h[i] = true}
+ big = ObjectSpace.memsize_of(h)
+ 1000.times {|i| h.delete(i)}
+ assert_operator ObjectSpace.memsize_of(h), :<, big/10
+ end
+
+ def test_wrapper
+ bug9381 = '[ruby-core:59638] [Bug #9381]'
+
+ wrapper = Class.new do
+ def initialize(obj)
+ @obj = obj
+ end
+
+ def hash
+ @obj.hash
+ end
+
+ def eql?(other)
+ @obj.eql?(other)
+ end
+ end
+
+ bad = [
+ 5, true, false, nil,
+ 0.0, 1.72723e-77,
+ :foo, "dsym_#{self.object_id.to_s(16)}_#{Time.now.to_i.to_s(16)}".to_sym,
+ "str",
+ ].select do |x|
+ hash = {x => bug9381}
+ hash[wrapper.new(x)] != bug9381
+ end
+ assert_empty(bad, bug9381)
+ end
+
+ def assert_hash_random(obj, dump = obj.inspect)
+ a = [obj.hash.to_s]
+ 3.times {
+ assert_in_out_err(["-e", "print (#{dump}).hash"], "") do |r, e|
+ a += r
+ assert_equal([], e)
+ end
+ }
+ assert_not_equal([obj.hash.to_s], a.uniq)
+ assert_operator(a.uniq.size, :>, 2, proc {a.inspect})
+ end
+
+ def test_string_hash_random
+ assert_hash_random('abc')
+ end
+
+ def test_symbol_hash_random
+ assert_hash_random(:-)
+ assert_hash_random(:foo)
+ assert_hash_random("dsym_#{self.object_id.to_s(16)}_#{Time.now.to_i.to_s(16)}".to_sym)
+ end
+
+ def test_integer_hash_random
+ assert_hash_random(0)
+ assert_hash_random(+1)
+ assert_hash_random(-1)
+ assert_hash_random(+(1<<100))
+ assert_hash_random(-(1<<100))
+ end
+
+ def test_float_hash_random
+ assert_hash_random(0.0)
+ assert_hash_random(+1.0)
+ assert_hash_random(-1.0)
+ assert_hash_random(1.72723e-77)
+ assert_hash_random(Float::INFINITY, "Float::INFINITY")
+ end
+
+ def test_label_syntax
+ feature4935 = '[ruby-core:37553] [Feature #4935]'
+ x = 'world'
+ hash = assert_nothing_raised(SyntaxError, feature4935) do
+ break eval(%q({foo: 1, "foo-bar": 2, "hello-#{x}": 3, 'hello-#{x}': 4, 'bar': {}}))
+ end
+ assert_equal({:foo => 1, :'foo-bar' => 2, :'hello-world' => 3, :'hello-#{x}' => 4, :bar => {}}, hash, feature4935)
+ x = x
+ end
+
+ def test_broken_hash_value
+ bug14218 = '[ruby-core:84395] [Bug #14218]'
+
+ assert_equal(0, 1_000_000.times.count{a=Object.new.hash; b=Object.new.hash; a < 0 && b < 0 && a + b > 0}, bug14218)
+ assert_equal(0, 1_000_000.times.count{a=Object.new.hash; b=Object.new.hash; 0 + a + b != 0 + b + a}, bug14218)
+ end
+
+ def test_reserved_hash_val
+ s = Struct.new(:hash)
+ h = {}
+ keys = [*0..8]
+ keys.each {|i| h[s.new(i)]=true}
+ msg = proc {h.inspect}
+ assert_equal(keys, h.keys.map(&:hash), msg)
+ end
ruby2_keywords def get_flagged_hash(*args)
args.last
@@ -2089,23 +2245,11 @@ class TestHash < Test::Unit::TestCase
assert_raise(TypeError) { Hash.ruby2_keywords_hash(1) }
end
- def test_ar2st
- # insert
- obj = Object.new
- obj.instance_variable_set(:@h, h = {})
- def obj.hash
- 10.times{|i| @h[i] = i}
- 0
+ def ar2st_object
+ class << (obj = Object.new)
+ attr_reader :h
end
- def obj.inspect
- 'test'
- end
- h[obj] = true
- assert_equal '{0=>0, 1=>1, 2=>2, 3=>3, 4=>4, 5=>5, 6=>6, 7=>7, 8=>8, 9=>9, test=>true}', h.inspect
-
- # delete
- obj = Object.new
- obj.instance_variable_set(:@h, h = {})
+ obj.instance_variable_set(:@h, {})
def obj.hash
10.times{|i| @h[i] = i}
0
@@ -2116,6 +2260,21 @@ class TestHash < Test::Unit::TestCase
def obj.eql? other
other.class == Object
end
+ obj
+ end
+
+ def test_ar2st_insert
+ obj = ar2st_object
+ h = obj.h
+
+ h[obj] = true
+ assert_equal '{0=>0, 1=>1, 2=>2, 3=>3, 4=>4, 5=>5, 6=>6, 7=>7, 8=>8, 9=>9, test=>true}', h.inspect
+ end
+
+ def test_ar2st_delete
+ obj = ar2st_object
+ h = obj.h
+
obj2 = Object.new
def obj2.hash
0
@@ -2124,20 +2283,12 @@ class TestHash < Test::Unit::TestCase
h[obj2] = true
h.delete obj
assert_equal '{0=>0, 1=>1, 2=>2, 3=>3, 4=>4, 5=>5, 6=>6, 7=>7, 8=>8, 9=>9}', h.inspect
+ end
+
+ def test_ar2st_lookup
+ obj = ar2st_object
+ h = obj.h
- # lookup
- obj = Object.new
- obj.instance_variable_set(:@h, h = {})
- def obj.hash
- 10.times{|i| @h[i] = i}
- 0
- end
- def obj.inspect
- 'test'
- end
- def obj.eql? other
- other.class == Object
- end
obj2 = Object.new
def obj2.hash
0
@@ -2178,4 +2329,35 @@ class TestHash < Test::Unit::TestCase
end;
end
end
+
+ def test_compare_by_identity_during_iteration
+ h = { 1 => 1 }
+ h.each do
+ assert_raise(RuntimeError, "compare_by_identity during iteration") do
+ h.compare_by_identity
+ end
+ end
+ end
+
+ def test_ar_hash_to_st_hash
+ assert_normal_exit("#{<<~"begin;"}\n#{<<~'end;'}", 'https://bugs.ruby-lang.org/issues/20050#note-5')
+ begin;
+ srand(0)
+ class Foo
+ def to_a
+ []
+ end
+
+ def hash
+ $h.delete($h.keys.sample) if rand < 0.1
+ to_a.hash
+ end
+ end
+
+ 1000.times do
+ $h = {}
+ (0..10).each {|i| $h[Foo.new] ||= {} }
+ end
+ end;
+ end
end
diff --git a/test/ruby/test_inlinecache.rb b/test/ruby/test_inlinecache.rb
index 6c2d86aefd..d48d95d74e 100644
--- a/test/ruby/test_inlinecache.rb
+++ b/test/ruby/test_inlinecache.rb
@@ -3,7 +3,7 @@
require 'test/unit'
-class TestMethod < Test::Unit::TestCase
+class TestMethodInlineCache < Test::Unit::TestCase
def test_alias
m0 = Module.new do
def foo; :M0 end
diff --git a/test/ruby/test_integer.rb b/test/ruby/test_integer.rb
index 9354514df0..c2cad36aa4 100644
--- a/test/ruby/test_integer.rb
+++ b/test/ruby/test_integer.rb
@@ -2,16 +2,9 @@
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
-
FIXNUM_MIN = RbConfig::LIMITS['FIXNUM_MIN']
FIXNUM_MAX = RbConfig::LIMITS['FIXNUM_MAX']
+ LONG_MAX = RbConfig::LIMITS['LONG_MAX']
def test_aref
@@ -96,11 +89,16 @@ class TestInteger < Test::Unit::TestCase
assert_equal(0, 1 << -0x40000001)
assert_equal(0, 1 << -0x80000000)
assert_equal(0, 1 << -0x80000001)
- # assert_equal(bdsize(0x80000000), (1 << 0x80000000).size)
+
+ char_bit = RbConfig::LIMITS["UCHAR_MAX"].bit_length
+ size_max = RbConfig::LIMITS["SIZE_MAX"]
+ size_bit_max = size_max * char_bit
+ assert_raise_with_message(RangeError, /shift width/) {
+ 1 << size_bit_max
+ }
end
def test_rshift
- # assert_equal(bdsize(0x40000001), (1 >> -0x40000001).size)
assert_predicate((1 >> 0x80000000), :zero?)
assert_predicate((1 >> 0xffffffff), :zero?)
assert_predicate((1 >> 0x100000000), :zero?)
@@ -140,20 +138,6 @@ class TestInteger < Test::Unit::TestCase
assert_equal(1234, Integer(1234))
assert_equal(1, Integer(1.234))
- # base argument
- assert_equal(1234, Integer("1234", 10))
- assert_equal(668, Integer("1234", 8))
- assert_equal(4660, Integer("1234", 16))
- assert_equal(49360, Integer("1234", 36))
- # decimal, not octal
- assert_equal(1234, Integer("01234", 10))
- assert_raise(ArgumentError) { Integer("0x123", 10) }
- assert_raise(ArgumentError) { Integer(1234, 10) }
- assert_raise(ArgumentError) { Integer(12.34, 10) }
- assert_raise(ArgumentError) { Integer(Object.new, 1) }
-
- assert_raise(ArgumentError) { Integer(1, 1, 1) }
-
assert_equal(2 ** 50, Integer(2.0 ** 50))
assert_raise(TypeError) { Integer(nil) }
@@ -247,6 +231,39 @@ class TestInteger < Test::Unit::TestCase
end;
end
+ def test_Integer_when_to_str
+ def (obj = Object.new).to_str
+ "0x10"
+ end
+ assert_equal(16, Integer(obj))
+ end
+
+ def test_Integer_with_base
+ assert_equal(1234, Integer("1234", 10))
+ assert_equal(668, Integer("1234", 8))
+ assert_equal(4660, Integer("1234", 16))
+ assert_equal(49360, Integer("1234", 36))
+ # decimal, not octal
+ assert_equal(1234, Integer("01234", 10))
+ assert_raise(ArgumentError) { Integer("0x123", 10) }
+ assert_raise(ArgumentError) { Integer(1234, 10) }
+ assert_raise(ArgumentError) { Integer(12.34, 10) }
+ assert_raise(ArgumentError) { Integer(Object.new, 1) }
+
+ assert_raise(ArgumentError) { Integer(1, 1, 1) }
+
+ def (base = Object.new).to_int
+ 8
+ end
+ assert_equal(8, Integer("10", base))
+
+ assert_raise(TypeError) { Integer("10", "8") }
+ def (base = Object.new).to_int
+ "8"
+ end
+ assert_raise(TypeError) { Integer("10", base) }
+ end
+
def test_int_p
assert_not_predicate(1.0, :integer?)
assert_predicate(1, :integer?)
@@ -265,31 +282,31 @@ class TestInteger < Test::Unit::TestCase
def test_upto
a = []
- 1.upto(3) {|x| a << x }
+ assert_equal(1, 1.upto(3) {|x| a << x })
assert_equal([1, 2, 3], a)
a = []
- 1.upto(0) {|x| a << x }
+ assert_equal(1, 1.upto(0) {|x| a << x })
assert_equal([], a)
y = 2**30 - 1
a = []
- y.upto(y+2) {|x| a << x }
+ assert_equal(y, y.upto(y+2) {|x| a << x })
assert_equal([y, y+1, y+2], a)
end
def test_downto
a = []
- -1.downto(-3) {|x| a << x }
+ assert_equal(-1, -1.downto(-3) {|x| a << x })
assert_equal([-1, -2, -3], a)
a = []
- 1.downto(2) {|x| a << x }
+ assert_equal(1, 1.downto(2) {|x| a << x })
assert_equal([], a)
y = -(2**30)
a = []
- y.downto(y-2) {|x| a << x }
+ assert_equal(y, y.downto(y-2) {|x| a << x })
assert_equal([y, y-1, y-2], a)
end
@@ -299,6 +316,42 @@ class TestInteger < Test::Unit::TestCase
end
end
+ def test_times_bignum_redefine_plus_lt
+ assert_separately([], "#{<<-"begin;"}\n#{<<~"end;"}")
+ begin;
+ called = false
+ Integer.class_eval do
+ alias old_succ succ
+ undef succ
+ define_method(:succ){|x| called = true; x+1}
+ alias old_lt <
+ undef <
+ define_method(:<){|x| called = true}
+ end
+
+ fix = 1
+ fix.times{break 0}
+ fix_called = called
+
+ called = false
+
+ big = 2**65
+ big.times{break 0}
+ big_called = called
+
+ Integer.class_eval do
+ undef succ
+ alias succ old_succ
+ undef <
+ alias < old_lt
+ end
+
+ # Asssert that Fixnum and Bignum behave consistently
+ bug18377 = "[ruby-core:106361]"
+ assert_equal(fix_called, big_called, bug18377)
+ end;
+ end
+
def assert_int_equal(expected, result, mesg = nil)
assert_kind_of(Integer, result, mesg)
assert_equal(expected, result, mesg)
@@ -412,6 +465,10 @@ class TestInteger < Test::Unit::TestCase
assert_int_equal(1111_1111_1111_1111_1111_1111_1111_1111, 1111_1111_1111_1111_1111_1111_1111_1111.floor(1))
assert_int_equal(10**400, (10**400).floor(1))
+
+ assert_int_equal(-10000000000, -1.floor(-10), "[Bug #20654]")
+ assert_int_equal(-100000000000000000000, -1.floor(-20), "[Bug #20654]")
+ assert_int_equal(-100000000000000000000000000000000000000000000000000, -1.floor(-50), "[Bug #20654]")
end
def test_ceil
@@ -440,6 +497,10 @@ class TestInteger < Test::Unit::TestCase
assert_int_equal(1111_1111_1111_1111_1111_1111_1111_1111, 1111_1111_1111_1111_1111_1111_1111_1111.ceil(1))
assert_int_equal(10**400, (10**400).ceil(1))
+
+ assert_int_equal(10000000000, 1.ceil(-10), "[Bug #20654]")
+ assert_int_equal(100000000000000000000, 1.ceil(-20), "[Bug #20654]")
+ assert_int_equal(100000000000000000000000000000000000000000000000000, 1.ceil(-50), "[Bug #20654]")
end
def test_truncate
@@ -651,6 +712,14 @@ class TestInteger < Test::Unit::TestCase
def test_fdiv
assert_equal(1.0, 1.fdiv(1))
assert_equal(0.5, 1.fdiv(2))
+
+ m = 50 << Float::MANT_DIG
+ prev = 1.0
+ (1..100).each do |i|
+ val = (m + i).fdiv(m)
+ assert_operator val, :>=, prev, "1+epsilon*(#{i}/100)"
+ prev = val
+ end
end
def test_obj_fdiv
@@ -679,4 +748,25 @@ class TestInteger < Test::Unit::TestCase
def o.to_int; Object.new; end
assert_raise_with_message(TypeError, /can't convert Object to Integer/) {Integer.try_convert(o)}
end
+
+ def test_ceildiv
+ assert_equal(0, 0.ceildiv(3))
+ assert_equal(1, 1.ceildiv(3))
+ assert_equal(1, 3.ceildiv(3))
+ assert_equal(2, 4.ceildiv(3))
+
+ assert_equal(-1, 4.ceildiv(-3))
+ assert_equal(-1, -4.ceildiv(3))
+ assert_equal(2, -4.ceildiv(-3))
+
+ assert_equal(3, 3.ceildiv(1.2))
+ assert_equal(3, 3.ceildiv(6/5r))
+
+ assert_equal(10, (10**100-11).ceildiv(10**99-1))
+ assert_equal(11, (10**100-9).ceildiv(10**99-1))
+
+ o = Object.new
+ def o.coerce(other); [other, 10]; end
+ assert_equal(124, 1234.ceildiv(o))
+ end
end
diff --git a/test/ruby/test_integer_comb.rb b/test/ruby/test_integer_comb.rb
index 1ad13dd31b..150f45cfd7 100644
--- a/test/ruby/test_integer_comb.rb
+++ b/test/ruby/test_integer_comb.rb
@@ -408,19 +408,32 @@ class TestIntegerComb < Test::Unit::TestCase
end
def test_remainder
+ coerce = EnvUtil.labeled_class("CoerceNum") do
+ def initialize(num)
+ @num = num
+ end
+ def coerce(other)
+ [other, @num]
+ end
+ def inspect
+ "#{self.class.name}(#@num)"
+ end
+ alias to_s inspect
+ end
+
VS.each {|a|
- VS.each {|b|
- if b == 0
+ (VS + VS.map {|b| [coerce.new(b), b]}).each {|b, i = b|
+ if i == 0
assert_raise(ZeroDivisionError) { a.divmod(b) }
else
- r = a.remainder(b)
+ r = assert_nothing_raised(ArgumentError, "#{a}.remainder(#{b})") {a.remainder(b)}
assert_kind_of(Integer, r)
if a < 0
- assert_operator(-b.abs, :<, r, "#{a}.remainder(#{b})")
+ assert_operator(-i.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})")
+ assert_operator(i.abs, :>, r, "#{a}.remainder(#{b})")
else
assert_equal(0, r, "#{a}.remainder(#{b})")
end
diff --git a/test/ruby/test_io.rb b/test/ruby/test_io.rb
index a90140fd0b..1ca05ae362 100644
--- a/test/ruby/test_io.rb
+++ b/test/ruby/test_io.rb
@@ -312,7 +312,7 @@ class TestIO < Test::Unit::TestCase
w.print "a\n\nb\n\n"
w.close
end, proc do |r|
- assert_equal "a\n\nb\n", r.gets(nil, chomp: true)
+ assert_equal("a\n\nb\n\n", r.gets(nil, chomp: true), "[Bug #18770]")
assert_nil r.gets("")
r.close
end)
@@ -476,6 +476,18 @@ class TestIO < Test::Unit::TestCase
}
end
+ def test_copy_stream_append_to_nonempty
+ with_srccontent("foobar") {|src, content|
+ preface = 'preface'
+ File.write('dst', preface)
+ File.open('dst', 'ab') do |dst|
+ ret = IO.copy_stream(src, dst)
+ assert_equal(content.bytesize, ret)
+ assert_equal(preface + content, File.read("dst"))
+ end
+ }
+ end
+
def test_copy_stream_smaller
with_srccontent {|src, content|
@@ -643,8 +655,8 @@ class TestIO < Test::Unit::TestCase
if have_nonblock?
def test_copy_stream_no_busy_wait
- skip "MJIT has busy wait on GC. This sometimes fails with --jit." if defined?(RubyVM::JIT) && RubyVM::JIT.enabled?
- skip "multiple threads already active" if Thread.list.size > 1
+ omit "RJIT has busy wait on GC. This sometimes fails with --jit." if defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled?
+ omit "multiple threads already active" if Thread.list.size > 1
msg = 'r58534 [ruby-core:80969] [Backport #13533]'
IO.pipe do |r,w|
@@ -663,7 +675,7 @@ class TestIO < Test::Unit::TestCase
begin
w2.nonblock = true
rescue Errno::EBADF
- skip "nonblocking IO for pipe is not implemented"
+ omit "nonblocking IO for pipe is not implemented"
end
s = w2.syswrite("a" * 100000)
t = Thread.new { sleep 0.1; r2.read }
@@ -767,7 +779,7 @@ class TestIO < Test::Unit::TestCase
r1.nonblock = true
w2.nonblock = true
rescue Errno::EBADF
- skip "nonblocking IO for pipe is not implemented"
+ omit "nonblocking IO for pipe is not implemented"
end
t1 = Thread.new { w1 << megacontent; w1.close }
t2 = Thread.new { r2.read }
@@ -831,7 +843,7 @@ class TestIO < Test::Unit::TestCase
assert_equal("bcd", r.read)
end)
rescue NotImplementedError
- skip "pread(2) is not implemtented."
+ omit "pread(2) is not implemtented."
end
}
end
@@ -888,6 +900,10 @@ class TestIO < Test::Unit::TestCase
end if defined? UNIXSocket
def test_copy_stream_socket4
+ if RUBY_PLATFORM =~ /mingw|mswin/
+ omit "pread(2) is not implemented."
+ end
+
with_bigsrc {|bigsrc, bigcontent|
File.open(bigsrc) {|f|
assert_equal(0, f.pos)
@@ -904,9 +920,13 @@ class TestIO < Test::Unit::TestCase
}
}
}
- end if defined? UNIXSocket
+ end
def test_copy_stream_socket5
+ if RUBY_PLATFORM =~ /mingw|mswin/
+ omit "pread(2) is not implemented."
+ end
+
with_bigsrc {|bigsrc, bigcontent|
File.open(bigsrc) {|f|
assert_equal(bigcontent[0,100], f.read(100))
@@ -924,9 +944,13 @@ class TestIO < Test::Unit::TestCase
}
}
}
- end if defined? UNIXSocket
+ end
def test_copy_stream_socket6
+ if RUBY_PLATFORM =~ /mingw|mswin/
+ omit "pread(2) is not implemented."
+ end
+
mkcdtmpdir {
megacontent = "abc" * 1234567
File.open("megasrc", "w") {|f| f << megacontent }
@@ -935,7 +959,7 @@ class TestIO < Test::Unit::TestCase
begin
s1.nonblock = true
rescue Errno::EBADF
- skip "nonblocking IO for pipe is not implemented"
+ omit "nonblocking IO for pipe is not implemented"
end
t1 = Thread.new { s2.read }
t2 = Thread.new {
@@ -947,9 +971,13 @@ class TestIO < Test::Unit::TestCase
assert_equal(megacontent, result)
}
}
- end if defined? UNIXSocket
+ end
def test_copy_stream_socket7
+ if RUBY_PLATFORM =~ /mingw|mswin/
+ omit "pread(2) is not implemented."
+ end
+
GC.start
mkcdtmpdir {
megacontent = "abc" * 1234567
@@ -959,7 +987,7 @@ class TestIO < Test::Unit::TestCase
begin
s1.nonblock = true
rescue Errno::EBADF
- skip "nonblocking IO for pipe is not implemented"
+ omit "nonblocking IO for pipe is not implemented"
end
trapping_usr2 do |rd|
nr = 30
@@ -984,7 +1012,7 @@ class TestIO < Test::Unit::TestCase
end
}
}
- end if defined? UNIXSocket and IO.method_defined?("nonblock=")
+ end
def test_copy_stream_strio
src = StringIO.new("abcd")
@@ -1429,6 +1457,16 @@ class TestIO < Test::Unit::TestCase
End
end
+ def test_dup_timeout
+ with_pipe do |r, w|
+ r.timeout = 0.1
+ r2 = r.dup
+ assert_equal(0.1, r2.timeout)
+ ensure
+ r2&.close
+ end
+ end
+
def test_inspect
with_pipe do |r, w|
assert_match(/^#<IO:fd \d+>$/, r.inspect)
@@ -1482,6 +1520,13 @@ class TestIO < Test::Unit::TestCase
end)
end
+ def test_readpartial_zero_size
+ File.open(IO::NULL) do |r|
+ assert_empty(r.readpartial(0, s = "01234567"))
+ assert_empty(s)
+ end
+ end
+
def test_readpartial_buffer_error
with_pipe do |r, w|
s = ""
@@ -1527,6 +1572,13 @@ class TestIO < Test::Unit::TestCase
end)
end
+ def test_read_zero_size
+ File.open(IO::NULL) do |r|
+ assert_empty(r.read(0, s = "01234567"))
+ assert_empty(s)
+ end
+ end
+
def test_read_buffer_error
with_pipe do |r, w|
s = ""
@@ -1564,6 +1616,35 @@ class TestIO < Test::Unit::TestCase
}
end
+ def test_read_nonblock_zero_size
+ File.open(IO::NULL) do |r|
+ assert_empty(r.read_nonblock(0, s = "01234567"))
+ assert_empty(s)
+ end
+ end
+
+ def test_read_nonblock_file
+ make_tempfile do |path|
+ File.open(path, 'r') do |file|
+ file.read_nonblock(4)
+ end
+ end
+ end
+
+ def test_write_nonblock_file
+ make_tempfile do |path|
+ File.open(path, 'w') do |file|
+ file.write_nonblock("Ruby")
+ end
+ end
+ end
+
+ def test_explicit_path
+ io = IO.for_fd(0, path: "Fake Path", autoclose: false)
+ assert_match %r"Fake Path", io.inspect
+ assert_equal "Fake Path", io.path
+ end
+
def test_write_nonblock_simple_no_exceptions
pipe(proc do |w|
w.write_nonblock('1', exception: false)
@@ -1598,7 +1679,7 @@ class TestIO < Test::Unit::TestCase
end if have_nonblock?
def test_read_nonblock_no_exceptions
- skip '[ruby-core:90895] MJIT worker may leave fd open in a forked child' if defined?(RubyVM::JIT) && RubyVM::JIT.enabled? # TODO: consider acquiring GVL from MJIT worker.
+ omit '[ruby-core:90895] RJIT worker may leave fd open in a forked child' if defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled? # TODO: consider acquiring GVL from RJIT worker.
with_pipe {|r, w|
assert_equal :wait_readable, r.read_nonblock(4096, exception: false)
w.puts "HI!"
@@ -1817,6 +1898,110 @@ class TestIO < Test::Unit::TestCase
end)
end
+ def test_readline_bad_param_raises
+ File.open(__FILE__) do |f|
+ assert_raise(TypeError) do
+ f.readline Object.new
+ end
+ end
+
+ File.open(__FILE__) do |f|
+ assert_raise(TypeError) do
+ f.readline 1, 2
+ end
+ end
+ end
+
+ def test_readline_raises
+ File.open(__FILE__) do |f|
+ assert_equal File.read(__FILE__), f.readline(nil)
+ assert_raise(EOFError) do
+ f.readline
+ end
+ end
+ end
+
+ def test_readline_separators
+ File.open(__FILE__) do |f|
+ line = f.readline("def")
+ assert_equal File.read(__FILE__)[/\A.*?def/m], line
+ end
+
+ File.open(__FILE__) do |f|
+ line = f.readline("def", chomp: true)
+ assert_equal File.read(__FILE__)[/\A.*?(?=def)/m], line
+ end
+ end
+
+ def test_readline_separators_limits
+ t = Tempfile.open("readline_limit")
+ str = "#" * 50
+ sep = "def"
+
+ t.write str
+ t.write sep
+ t.write str
+ t.flush
+
+ # over limit
+ File.open(t.path) do |f|
+ line = f.readline sep, str.bytesize
+ assert_equal(str, line)
+ end
+
+ # under limit
+ File.open(t.path) do |f|
+ line = f.readline(sep, str.bytesize + 5)
+ assert_equal(str + sep, line)
+ end
+
+ # under limit + chomp
+ File.open(t.path) do |f|
+ line = f.readline(sep, str.bytesize + 5, chomp: true)
+ assert_equal(str, line)
+ end
+ ensure
+ t&.close!
+ end
+
+ def test_readline_limit_without_separator
+ t = Tempfile.open("readline_limit")
+ str = "#" * 50
+ sep = "\n"
+
+ t.write str
+ t.write sep
+ t.write str
+ t.flush
+
+ # over limit
+ File.open(t.path) do |f|
+ line = f.readline str.bytesize
+ assert_equal(str, line)
+ end
+
+ # under limit
+ File.open(t.path) do |f|
+ line = f.readline(str.bytesize + 5)
+ assert_equal(str + sep, line)
+ end
+
+ # under limit + chomp
+ File.open(t.path) do |f|
+ line = f.readline(str.bytesize + 5, chomp: true)
+ assert_equal(str, line)
+ end
+ ensure
+ t&.close!
+ end
+
+ def test_readline_chomp_true
+ File.open(__FILE__) do |f|
+ line = f.readline(chomp: true)
+ assert_equal File.readlines(__FILE__).first.chomp, line
+ end
+ end
+
def test_set_lineno_readline
pipe(proc do |w|
w.puts "foo"
@@ -1861,6 +2046,20 @@ class TestIO < Test::Unit::TestCase
assert_equal("baz\n", e.next)
assert_raise(StopIteration) { e.next }
end)
+
+ pipe(proc do |w|
+ w.write "foo\n"
+ w.close
+ end, proc do |r|
+ assert_equal(["foo\n"], r.each_line(nil, chomp: true).to_a, "[Bug #18770]")
+ end)
+
+ pipe(proc do |w|
+ w.write "foo\n"
+ w.close
+ end, proc do |r|
+ assert_equal(["fo", "o\n"], r.each_line(nil, 2, chomp: true).to_a, "[Bug #18770]")
+ end)
end
def test_each_byte2
@@ -2166,6 +2365,14 @@ class TestIO < Test::Unit::TestCase
end)
end
+ def test_sysread_with_negative_length
+ make_tempfile {|t|
+ open(t.path) do |f|
+ assert_raise(ArgumentError) { f.sysread(-1) }
+ end
+ }
+ end
+
def test_flag
make_tempfile {|t|
assert_raise(ArgumentError) do
@@ -2244,9 +2451,9 @@ class TestIO < Test::Unit::TestCase
end
def test_autoclose_true_closed_by_finalizer
- # http://ci.rvm.jp/results/trunk-mjit@silicon-docker/1465760
- # http://ci.rvm.jp/results/trunk-mjit@silicon-docker/1469765
- skip 'this randomly fails with MJIT' if defined?(RubyVM::JIT) && RubyVM::JIT.enabled?
+ # http://ci.rvm.jp/results/trunk-rjit@silicon-docker/1465760
+ # http://ci.rvm.jp/results/trunk-rjit@silicon-docker/1469765
+ omit 'this randomly fails with RJIT' if defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled?
feature2250 = '[ruby-core:26222]'
pre = 'ft2250'
@@ -2258,7 +2465,7 @@ class TestIO < Test::Unit::TestCase
t.close
rescue Errno::EBADF
end
- skip "expect IO object was GC'ed but not recycled yet"
+ omit "expect IO object was GC'ed but not recycled yet"
rescue WeakRef::RefError
assert_raise(Errno::EBADF, feature2250) {t.close}
end
@@ -2274,7 +2481,7 @@ class TestIO < Test::Unit::TestCase
begin
w.close
t.close
- skip "expect IO object was GC'ed but not recycled yet"
+ omit "expect IO object was GC'ed but not recycled yet"
rescue WeakRef::RefError
assert_nothing_raised(Errno::EBADF, feature2250) {t.close}
end
@@ -2309,15 +2516,19 @@ class TestIO < Test::Unit::TestCase
end
def test_open_pipe
- open("|" + EnvUtil.rubybin, "r+") do |f|
- f.puts "puts 'foo'"
- f.close_write
- assert_equal("foo\n", f.read)
+ assert_deprecated_warning(/Kernel#open with a leading '\|'/) do # https://bugs.ruby-lang.org/issues/19630
+ open("|" + EnvUtil.rubybin, "r+") do |f|
+ f.puts "puts 'foo'"
+ f.close_write
+ assert_equal("foo\n", f.read)
+ end
end
end
def test_read_command
- assert_equal("foo\n", IO.read("|echo foo"))
+ assert_deprecated_warning(/IO process creation with a leading '\|'/) do # https://bugs.ruby-lang.org/issues/19630
+ assert_equal("foo\n", IO.read("|echo foo"))
+ end
assert_raise(Errno::ENOENT, Errno::EINVAL) do
File.read("|#{EnvUtil.rubybin} -e puts")
end
@@ -2331,7 +2542,9 @@ class TestIO < Test::Unit::TestCase
Class.new(IO).binread("|#{EnvUtil.rubybin} -e puts")
end
assert_raise(Errno::ESPIPE) do
- IO.read("|echo foo", 1, 1)
+ assert_deprecated_warning(/IO process creation with a leading '\|'/) do # https://bugs.ruby-lang.org/issues/19630
+ IO.read("|#{EnvUtil.rubybin} -e 'puts :foo'", 1, 1)
+ end
end
end
@@ -2516,11 +2729,16 @@ class TestIO < Test::Unit::TestCase
def test_foreach
a = []
- IO.foreach("|" + EnvUtil.rubybin + " -e 'puts :foo; puts :bar; puts :baz'") {|x| a << x }
+
+ assert_deprecated_warning(/IO process creation with a leading '\|'/) do # https://bugs.ruby-lang.org/issues/19630
+ IO.foreach("|" + EnvUtil.rubybin + " -e 'puts :foo; puts :bar; puts :baz'") {|x| a << x }
+ end
assert_equal(["foo\n", "bar\n", "baz\n"], a)
a = []
- IO.foreach("|" + EnvUtil.rubybin + " -e 'puts :zot'", :open_args => ["r"]) {|x| a << x }
+ assert_deprecated_warning(/IO process creation with a leading '\|'/) do # https://bugs.ruby-lang.org/issues/19630
+ IO.foreach("|" + EnvUtil.rubybin + " -e 'puts :zot'", :open_args => ["r"]) {|x| a << x }
+ end
assert_equal(["zot\n"], a)
make_tempfile {|t|
@@ -2555,6 +2773,8 @@ class TestIO < Test::Unit::TestCase
bug = '[ruby-dev:31525]'
assert_raise(ArgumentError, bug) {IO.foreach}
+ assert_raise(ArgumentError, "[Bug #18767] [ruby-core:108499]") {IO.foreach(__FILE__, 0){}}
+
a = nil
assert_nothing_raised(ArgumentError, bug) {a = IO.foreach(t.path).to_a}
assert_equal(["foo\n", "bar\n", "baz\n"], a, bug)
@@ -2563,6 +2783,8 @@ class TestIO < Test::Unit::TestCase
assert_raise_with_message(IOError, /not opened for reading/, bug6054) do
IO.foreach(t.path, mode:"w").next
end
+
+ assert_raise(ArgumentError, "[Bug #18771] [ruby-core:108503]") {IO.foreach(t, "\n", 10, true){}}
}
end
@@ -2572,6 +2794,7 @@ class TestIO < Test::Unit::TestCase
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))
+ assert_raise(ArgumentError, "[Bug #18771] [ruby-core:108503]") {IO.readlines(t, "\n", 10, true){}}
}
end
@@ -2637,7 +2860,7 @@ class TestIO < Test::Unit::TestCase
end
def test_puts_parallel
- skip "not portable"
+ omit "not portable"
pipe(proc do |w|
threads = []
100.times do
@@ -2706,6 +2929,15 @@ class TestIO < Test::Unit::TestCase
f.close
assert_equal("FOO\n", File.read(t.path))
+
+ fd = IO.sysopen(t.path)
+ %w[w r+ w+ a+].each do |mode|
+ assert_raise(Errno::EINVAL, "#{mode} [ruby-dev:38571]") {IO.new(fd, mode)}
+ end
+ f = IO.new(fd, "r")
+ data = f.read
+ f.close
+ assert_equal("FOO\n", data)
}
end
@@ -2758,6 +2990,9 @@ class TestIO < Test::Unit::TestCase
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))
+
+ assert_raise(ArgumentError) { File.read(t.path, -1) }
+ assert_raise(ArgumentError) { File.read(t.path, 1, -1) }
}
end
@@ -3064,6 +3299,8 @@ __END__
end
def test_cross_thread_close_stdio
+ omit "[Bug #18613]" if /freebsd/ =~ RUBY_PLATFORM
+
assert_separately([], <<-'end;')
IO.pipe do |r,w|
$stdin.reopen(r)
@@ -3271,7 +3508,7 @@ __END__
begin
f = File.open('/dev/tty')
rescue Errno::ENOENT, Errno::ENXIO => e
- skip e.message
+ omit e.message
else
tiocgwinsz=0x5413
winsize=""
@@ -3397,10 +3634,10 @@ __END__
with_pipe do |r,w|
# Linux 2.6.15 and earlier returned EINVAL instead of ESPIPE
assert_raise(Errno::ESPIPE, Errno::EINVAL) {
- r.advise(:willneed) or skip "fadvise(2) is not implemented"
+ r.advise(:willneed) or omit "fadvise(2) is not implemented"
}
assert_raise(Errno::ESPIPE, Errno::EINVAL) {
- w.advise(:willneed) or skip "fadvise(2) is not implemented"
+ w.advise(:willneed) or omit "fadvise(2) is not implemented"
}
end
end if /linux/ =~ RUBY_PLATFORM
@@ -3540,14 +3777,14 @@ __END__
f.write('1')
pos = f.tell
rescue Errno::ENOSPC
- skip "non-sparse file system"
+ omit "non-sparse file system"
rescue SystemCallError
else
assert_equal(0x1_0000_0000, pos, msg)
end
end;
rescue Timeout::Error
- skip "Timeout because of slow file writing"
+ omit "Timeout because of slow file writing"
end
}
end if /mswin|mingw/ =~ RUBY_PLATFORM
@@ -3639,8 +3876,10 @@ __END__
end
def test_open_fifo_does_not_block_other_threads
- mkcdtmpdir {
+ mkcdtmpdir do
File.mkfifo("fifo")
+ rescue NotImplementedError
+ else
assert_separately([], <<-'EOS')
t1 = Thread.new {
open("fifo", "r") {|r|
@@ -3655,8 +3894,32 @@ __END__
t1_value, _ = assert_join_threads([t1, t2])
assert_equal("foo", t1_value)
EOS
- }
- end if /mswin|mingw|bccwin|cygwin/ !~ RUBY_PLATFORM
+ end
+ end
+
+ def test_open_fifo_restart_at_signal_intterupt
+ mkcdtmpdir do
+ File.mkfifo("fifo")
+ rescue NotImplementedError
+ else
+ wait = EnvUtil.apply_timeout_scale(0.1)
+ data = "writing to fifo"
+
+ # Do not use assert_separately, because reading from stdin
+ # prevents to reproduce [Bug #20708]
+ assert_in_out_err(["-e", "#{<<~"begin;"}\n#{<<~'end;'}"], [], [data])
+ wait, data = #{wait}, #{data.dump}
+ ;
+ begin;
+ trap(:USR1) {}
+ Thread.new do
+ sleep wait; Process.kill(:USR1, $$)
+ sleep wait; File.write("fifo", data)
+ end
+ puts File.read("fifo")
+ end;
+ end
+ end if Signal.list[:USR1] # Pointless on platforms without signal
def test_open_flag
make_tempfile do |t|
@@ -3701,7 +3964,7 @@ __END__
end
def test_race_gets_and_close
- opt = { signal: :ABRT, timeout: 200 }
+ opt = { signal: :ABRT, timeout: 10 }
assert_separately([], "#{<<-"begin;"}\n#{<<-"end;"}", **opt)
bug13076 = '[ruby-core:78845] [Bug #13076]'
begin;
@@ -3732,6 +3995,8 @@ __END__
end
def test_race_closed_stream
+ omit "[Bug #18613]" if /freebsd/ =~ RUBY_PLATFORM
+
assert_separately([], "#{<<-"begin;"}\n#{<<-"end;"}")
begin;
bug13158 = '[ruby-core:79262] [Bug #13158]'
@@ -3826,6 +4091,8 @@ __END__
end
def test_closed_stream_in_rescue
+ omit "[Bug #18613]" if /freebsd/ =~ RUBY_PLATFORM
+
assert_separately([], "#{<<-"begin;"}\n#{<<~"end;"}")
begin;
10.times do
@@ -3847,30 +4114,6 @@ __END__
end
end;
end
-
- def test_write_no_garbage
- skip "multiple threads already active" if Thread.list.size > 1
- res = {}
- ObjectSpace.count_objects(res) # creates strings on first call
- [ 'foo'.b, '*' * 24 ].each do |buf|
- with_pipe do |r, w|
- GC.disable
- begin
- before = ObjectSpace.count_objects(res)[:T_STRING]
- n = w.write(buf)
- s = w.syswrite(buf)
- after = ObjectSpace.count_objects(res)[:T_STRING]
- ensure
- GC.enable
- end
- assert_equal before, after,
- "no strings left over after write [ruby-core:78898] [Bug #13085]: #{ before } strings before write -> #{ after } strings after write"
- assert_not_predicate buf, :frozen?, 'no inadvertent freeze'
- assert_equal buf.bytesize, n, 'IO#write wrote expected size'
- assert_equal s, n, 'IO#syswrite wrote expected size'
- end
- end
- end
end
def test_pread
@@ -3883,7 +4126,7 @@ __END__
assert_raise(EOFError) { f.pread(1, f.size) }
end
}
- end if IO.method_defined?(:pread)
+ end
def test_pwrite
make_tempfile { |t|
@@ -3892,7 +4135,7 @@ __END__
assert_equal("ooo", f.pread(3, 4))
end
}
- end if IO.method_defined?(:pread) and IO.method_defined?(:pwrite)
+ end
def test_select_exceptfds
if Etc.uname[:sysname] == 'SunOS'
@@ -3918,6 +4161,9 @@ __END__
noex = Thread.new do # everything right and never see exceptions :)
until sig_rd.wait_readable(0)
IO.pipe do |r, w|
+ assert_nil r.timeout
+ assert_nil w.timeout
+
th = Thread.new { r.read(1) }
w.write(dot)
diff --git a/test/ruby/test_io_buffer.rb b/test/ruby/test_io_buffer.rb
new file mode 100644
index 0000000000..7a58ec0c5a
--- /dev/null
+++ b/test/ruby/test_io_buffer.rb
@@ -0,0 +1,575 @@
+# frozen_string_literal: false
+
+require 'tempfile'
+
+class TestIOBuffer < Test::Unit::TestCase
+ experimental = Warning[:experimental]
+ begin
+ Warning[:experimental] = false
+ IO::Buffer.new(0)
+ ensure
+ Warning[:experimental] = experimental
+ end
+
+ def assert_negative(value)
+ assert(value < 0, "Expected #{value} to be negative!")
+ end
+
+ def assert_positive(value)
+ assert(value > 0, "Expected #{value} to be positive!")
+ end
+
+ def test_flags
+ assert_equal 1, IO::Buffer::EXTERNAL
+ assert_equal 2, IO::Buffer::INTERNAL
+ assert_equal 4, IO::Buffer::MAPPED
+
+ assert_equal 32, IO::Buffer::LOCKED
+ assert_equal 64, IO::Buffer::PRIVATE
+
+ assert_equal 128, IO::Buffer::READONLY
+ end
+
+ def test_endian
+ assert_equal 4, IO::Buffer::LITTLE_ENDIAN
+ assert_equal 8, IO::Buffer::BIG_ENDIAN
+ assert_equal 8, IO::Buffer::NETWORK_ENDIAN
+
+ assert_include [IO::Buffer::LITTLE_ENDIAN, IO::Buffer::BIG_ENDIAN], IO::Buffer::HOST_ENDIAN
+ end
+
+ def test_default_size
+ assert_equal IO::Buffer::DEFAULT_SIZE, IO::Buffer.new.size
+ end
+
+ def test_new_internal
+ buffer = IO::Buffer.new(1024, IO::Buffer::INTERNAL)
+ assert_equal 1024, buffer.size
+ refute buffer.external?
+ assert buffer.internal?
+ refute buffer.mapped?
+ end
+
+ def test_new_mapped
+ buffer = IO::Buffer.new(1024, IO::Buffer::MAPPED)
+ assert_equal 1024, buffer.size
+ refute buffer.external?
+ refute buffer.internal?
+ assert buffer.mapped?
+ end
+
+ def test_new_readonly
+ buffer = IO::Buffer.new(128, IO::Buffer::INTERNAL|IO::Buffer::READONLY)
+ assert buffer.readonly?
+
+ assert_raise IO::Buffer::AccessError do
+ buffer.set_string("")
+ end
+
+ assert_raise IO::Buffer::AccessError do
+ buffer.set_string("!", 1)
+ end
+ end
+
+ def test_file_mapped
+ buffer = File.open(__FILE__) {|file| IO::Buffer.map(file, nil, 0, IO::Buffer::READONLY)}
+ contents = buffer.get_string
+
+ assert_include contents, "Hello World"
+ assert_equal Encoding::BINARY, contents.encoding
+ end
+
+ def test_file_mapped_invalid
+ assert_raise TypeError do
+ IO::Buffer.map("foobar")
+ end
+ end
+
+ def test_string_mapped
+ string = "Hello World"
+ buffer = IO::Buffer.for(string)
+ assert buffer.readonly?
+ end
+
+ def test_string_mapped_frozen
+ string = "Hello World".freeze
+ buffer = IO::Buffer.for(string)
+ assert buffer.readonly?
+ end
+
+ def test_string_mapped_mutable
+ string = "Hello World"
+ IO::Buffer.for(string) do |buffer|
+ refute buffer.readonly?
+
+ buffer.set_value(:U8, 0, "h".ord)
+
+ # Buffer releases it's ownership of the string:
+ buffer.free
+
+ assert_equal "hello World", string
+ end
+ end
+
+ def test_string_mapped_buffer_locked
+ string = "Hello World"
+ IO::Buffer.for(string) do |buffer|
+ # Cannot modify string as it's locked by the buffer:
+ assert_raise RuntimeError do
+ string[0] = "h"
+ end
+ end
+ end
+
+ def test_non_string
+ not_string = Object.new
+
+ assert_raise TypeError do
+ IO::Buffer.for(not_string)
+ end
+ end
+
+ def test_string
+ result = IO::Buffer.string(12) do |buffer|
+ buffer.set_string("Hello World!")
+ end
+
+ assert_equal "Hello World!", result
+ end
+
+ def test_string_negative
+ assert_raise ArgumentError do
+ IO::Buffer.string(-1)
+ end
+ end
+
+ def test_resize_mapped
+ buffer = IO::Buffer.new
+
+ buffer.resize(2048)
+ assert_equal 2048, buffer.size
+
+ buffer.resize(4096)
+ assert_equal 4096, buffer.size
+ end
+
+ def test_resize_preserve
+ message = "Hello World"
+ buffer = IO::Buffer.new(1024)
+ buffer.set_string(message)
+ buffer.resize(2048)
+ assert_equal message, buffer.get_string(0, message.bytesize)
+ end
+
+ def test_resize_zero_internal
+ buffer = IO::Buffer.new(1)
+
+ buffer.resize(0)
+ assert_equal 0, buffer.size
+
+ buffer.resize(1)
+ assert_equal 1, buffer.size
+ end
+
+ def test_resize_zero_external
+ buffer = IO::Buffer.for('1')
+
+ assert_raise IO::Buffer::AccessError do
+ buffer.resize(0)
+ end
+ end
+
+ def test_compare_same_size
+ buffer1 = IO::Buffer.new(1)
+ assert_equal buffer1, buffer1
+
+ buffer2 = IO::Buffer.new(1)
+ buffer1.set_value(:U8, 0, 0x10)
+ buffer2.set_value(:U8, 0, 0x20)
+
+ assert_negative buffer1 <=> buffer2
+ assert_positive buffer2 <=> buffer1
+ end
+
+ def test_compare_different_size
+ buffer1 = IO::Buffer.new(3)
+ buffer2 = IO::Buffer.new(5)
+
+ assert_negative buffer1 <=> buffer2
+ assert_positive buffer2 <=> buffer1
+ end
+
+ def test_compare_zero_length
+ buffer1 = IO::Buffer.new(0)
+ buffer2 = IO::Buffer.new(1)
+
+ assert_negative buffer1 <=> buffer2
+ assert_positive buffer2 <=> buffer1
+ end
+
+ def test_slice
+ buffer = IO::Buffer.new(128)
+ slice = buffer.slice(8, 32)
+ slice.set_string("Hello World")
+ assert_equal("Hello World", buffer.get_string(8, 11))
+ end
+
+ def test_slice_arguments
+ buffer = IO::Buffer.for("Hello World")
+
+ slice = buffer.slice
+ assert_equal "Hello World", slice.get_string
+
+ slice = buffer.slice(2)
+ assert_equal("llo World", slice.get_string)
+ end
+
+ def test_slice_bounds_error
+ buffer = IO::Buffer.new(128)
+
+ assert_raise ArgumentError do
+ buffer.slice(128, 10)
+ end
+
+ assert_raise ArgumentError do
+ buffer.slice(-10, 10)
+ end
+ end
+
+ def test_locked
+ buffer = IO::Buffer.new(128, IO::Buffer::INTERNAL|IO::Buffer::LOCKED)
+
+ assert_raise IO::Buffer::LockedError do
+ buffer.resize(256)
+ end
+
+ assert_equal 128, buffer.size
+
+ assert_raise IO::Buffer::LockedError do
+ buffer.free
+ end
+
+ assert_equal 128, buffer.size
+ end
+
+ def test_get_string
+ message = "Hello World 🤓"
+
+ buffer = IO::Buffer.new(128)
+ buffer.set_string(message)
+
+ chunk = buffer.get_string(0, message.bytesize, Encoding::UTF_8)
+ assert_equal message, chunk
+ assert_equal Encoding::UTF_8, chunk.encoding
+
+ chunk = buffer.get_string(0, message.bytesize, Encoding::BINARY)
+ assert_equal Encoding::BINARY, chunk.encoding
+
+ assert_raise_with_message(ArgumentError, /bigger than the buffer size/) do
+ buffer.get_string(0, 129)
+ end
+
+ assert_raise_with_message(ArgumentError, /bigger than the buffer size/) do
+ buffer.get_string(129)
+ end
+
+ assert_raise_with_message(ArgumentError, /Offset can't be negative/) do
+ buffer.get_string(-1)
+ end
+ end
+
+ def test_zero_length_get_string
+ buffer = IO::Buffer.new.slice(0, 0)
+ assert_equal "", buffer.get_string
+
+ buffer = IO::Buffer.new(0)
+ assert_equal "", buffer.get_string
+ end
+
+ # We check that values are correctly round tripped.
+ RANGES = {
+ :U8 => [0, 2**8-1],
+ :S8 => [-2**7, 0, 2**7-1],
+
+ :U16 => [0, 2**16-1],
+ :S16 => [-2**15, 0, 2**15-1],
+ :u16 => [0, 2**16-1],
+ :s16 => [-2**15, 0, 2**15-1],
+
+ :U32 => [0, 2**32-1],
+ :S32 => [-2**31, 0, 2**31-1],
+ :u32 => [0, 2**32-1],
+ :s32 => [-2**31, 0, 2**31-1],
+
+ :U64 => [0, 2**64-1],
+ :S64 => [-2**63, 0, 2**63-1],
+ :u64 => [0, 2**64-1],
+ :s64 => [-2**63, 0, 2**63-1],
+
+ :F32 => [-1.0, 0.0, 0.5, 1.0, 128.0],
+ :F64 => [-1.0, 0.0, 0.5, 1.0, 128.0],
+ }
+
+ def test_get_set_value
+ buffer = IO::Buffer.new(128)
+
+ RANGES.each do |data_type, values|
+ values.each do |value|
+ buffer.set_value(data_type, 0, value)
+ assert_equal value, buffer.get_value(data_type, 0), "Converting #{value} as #{data_type}."
+ end
+ end
+ end
+
+ def test_get_set_values
+ buffer = IO::Buffer.new(128)
+
+ RANGES.each do |data_type, values|
+ format = [data_type] * values.size
+
+ buffer.set_values(format, 0, values)
+ assert_equal values, buffer.get_values(format, 0), "Converting #{values} as #{format}."
+ end
+ end
+
+ def test_zero_length_get_set_values
+ buffer = IO::Buffer.new(0)
+
+ assert_equal [], buffer.get_values([], 0)
+ assert_equal 0, buffer.set_values([], 0, [])
+ end
+
+ def test_values
+ buffer = IO::Buffer.new(128)
+
+ RANGES.each do |data_type, values|
+ format = [data_type] * values.size
+
+ buffer.set_values(format, 0, values)
+ assert_equal values, buffer.values(data_type, 0, values.size), "Reading #{values} as #{format}."
+ end
+ end
+
+ def test_each
+ buffer = IO::Buffer.new(128)
+
+ RANGES.each do |data_type, values|
+ format = [data_type] * values.size
+ data_type_size = IO::Buffer.size_of(data_type)
+ values_with_offsets = values.map.with_index{|value, index| [index * data_type_size, value]}
+
+ buffer.set_values(format, 0, values)
+ assert_equal values_with_offsets, buffer.each(data_type, 0, values.size).to_a, "Reading #{values} as #{data_type}."
+ end
+ end
+
+ def test_zero_length_each
+ buffer = IO::Buffer.new(0)
+
+ assert_equal [], buffer.each(:U8).to_a
+ end
+
+ def test_each_byte
+ string = "The quick brown fox jumped over the lazy dog."
+ buffer = IO::Buffer.for(string)
+
+ assert_equal string.bytes, buffer.each_byte.to_a
+ end
+
+ def test_zero_length_each_byte
+ buffer = IO::Buffer.new(0)
+
+ assert_equal [], buffer.each_byte.to_a
+ end
+
+ def test_clear
+ buffer = IO::Buffer.new(16)
+ buffer.set_string("Hello World!")
+ end
+
+ def test_invalidation
+ input, output = IO.pipe
+
+ # (1) rb_write_internal creates IO::Buffer object,
+ buffer = IO::Buffer.new(128)
+
+ # (2) it is passed to (malicious) scheduler
+ # (3) scheduler starts a thread which call system call with the buffer object
+ thread = Thread.new{buffer.locked{input.read}}
+
+ Thread.pass until thread.stop?
+
+ # (4) scheduler returns
+ # (5) rb_write_internal invalidate the buffer object
+ assert_raise IO::Buffer::LockedError do
+ buffer.free
+ end
+
+ # (6) the system call access the memory area after invalidation
+ output.write("Hello World")
+ output.close
+ thread.join
+
+ input.close
+ end
+
+ def hello_world_tempfile
+ io = Tempfile.new
+ io.write("Hello World")
+ io.seek(0)
+
+ yield io
+ ensure
+ io&.close!
+ end
+
+ def test_read
+ hello_world_tempfile do |io|
+ buffer = IO::Buffer.new(128)
+ buffer.read(io)
+ assert_equal "Hello", buffer.get_string(0, 5)
+ end
+ end
+
+ def test_read_with_with_length
+ hello_world_tempfile do |io|
+ buffer = IO::Buffer.new(128)
+ buffer.read(io, 5)
+ assert_equal "Hello", buffer.get_string(0, 5)
+ end
+ end
+
+ def test_read_with_with_offset
+ hello_world_tempfile do |io|
+ buffer = IO::Buffer.new(128)
+ buffer.read(io, nil, 6)
+ assert_equal "Hello", buffer.get_string(6, 5)
+ end
+ end
+
+ def test_write
+ io = Tempfile.new
+
+ buffer = IO::Buffer.new(128)
+ buffer.set_string("Hello")
+ buffer.write(io)
+
+ io.seek(0)
+ assert_equal "Hello", io.read(5)
+ ensure
+ io.close!
+ end
+
+ def test_pread
+ io = Tempfile.new
+ io.write("Hello World")
+ io.seek(0)
+
+ buffer = IO::Buffer.new(128)
+ buffer.pread(io, 6, 5)
+
+ assert_equal "World", buffer.get_string(0, 5)
+ assert_equal 0, io.tell
+ ensure
+ io.close!
+ end
+
+ def test_pread_offset
+ io = Tempfile.new
+ io.write("Hello World")
+ io.seek(0)
+
+ buffer = IO::Buffer.new(128)
+ buffer.pread(io, 6, 5, 6)
+
+ assert_equal "World", buffer.get_string(6, 5)
+ assert_equal 0, io.tell
+ ensure
+ io.close!
+ end
+
+ def test_pwrite
+ io = Tempfile.new
+
+ buffer = IO::Buffer.new(128)
+ buffer.set_string("World")
+ buffer.pwrite(io, 6, 5)
+
+ assert_equal 0, io.tell
+
+ io.seek(6)
+ assert_equal "World", io.read(5)
+ ensure
+ io.close!
+ end
+
+ def test_pwrite_offset
+ io = Tempfile.new
+
+ buffer = IO::Buffer.new(128)
+ buffer.set_string("Hello World")
+ buffer.pwrite(io, 6, 5, 6)
+
+ assert_equal 0, io.tell
+
+ io.seek(6)
+ assert_equal "World", io.read(5)
+ ensure
+ io.close!
+ end
+
+ def test_operators
+ source = IO::Buffer.for("1234123412")
+ mask = IO::Buffer.for("133\x00")
+
+ assert_equal IO::Buffer.for("123\x00123\x0012"), (source & mask)
+ assert_equal IO::Buffer.for("1334133413"), (source | mask)
+ assert_equal IO::Buffer.for("\x00\x01\x004\x00\x01\x004\x00\x01"), (source ^ mask)
+ assert_equal IO::Buffer.for("\xce\xcd\xcc\xcb\xce\xcd\xcc\xcb\xce\xcd"), ~source
+ end
+
+ def test_inplace_operators
+ source = IO::Buffer.for("1234123412")
+ mask = IO::Buffer.for("133\x00")
+
+ assert_equal IO::Buffer.for("123\x00123\x0012"), source.dup.and!(mask)
+ assert_equal IO::Buffer.for("1334133413"), source.dup.or!(mask)
+ assert_equal IO::Buffer.for("\x00\x01\x004\x00\x01\x004\x00\x01"), source.dup.xor!(mask)
+ assert_equal IO::Buffer.for("\xce\xcd\xcc\xcb\xce\xcd\xcc\xcb\xce\xcd"), source.dup.not!
+ end
+
+ def test_shared
+ message = "Hello World"
+ buffer = IO::Buffer.new(64, IO::Buffer::MAPPED | IO::Buffer::SHARED)
+
+ pid = fork do
+ buffer.set_string(message)
+ end
+
+ Process.wait(pid)
+ string = buffer.get_string(0, message.bytesize)
+ assert_equal message, string
+ rescue NotImplementedError
+ omit "Fork/shared memory is not supported."
+ end
+
+ def test_private
+ Tempfile.create(%w"buffer .txt") do |file|
+ file.write("Hello World")
+
+ buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::PRIVATE)
+ begin
+ assert buffer.private?
+ refute buffer.readonly?
+
+ buffer.set_string("J")
+
+ # It was not changed because the mapping was private:
+ file.seek(0)
+ assert_equal "Hello World", file.read
+ ensure
+ buffer&.free
+ end
+ end
+ end
+end
diff --git a/test/ruby/test_io_m17n.rb b/test/ruby/test_io_m17n.rb
index 27b16a2a36..b01d627d92 100644
--- a/test/ruby/test_io_m17n.rb
+++ b/test/ruby/test_io_m17n.rb
@@ -1142,12 +1142,94 @@ EOT
IO.pipe do |r, w|
assert_nothing_raised(bug5567) do
assert_warning(/Unsupported/, bug5567) {r.set_encoding("fffffffffffxx")}
+ w.puts("foo")
+ assert_equal("foo\n", r.gets)
assert_warning(/Unsupported/, bug5567) {r.set_encoding("fffffffffffxx", "us-ascii")}
+ w.puts("bar")
+ assert_equal("bar\n", r.gets)
assert_warning(/Unsupported/, bug5567) {r.set_encoding("us-ascii", "fffffffffffxx")}
+ w.puts("zot")
+ begin
+ assert_equal("zot\n", r.gets)
+ rescue Encoding::ConverterNotFoundError => e
+ assert_match(/\((\S+) to \1\)/, e.message)
+ end
end
end
end
+ def test_set_encoding_argument_parsing
+ File.open(File::NULL) do |f|
+ f.set_encoding('binary')
+ assert_equal(Encoding::ASCII_8BIT, f.external_encoding)
+ end
+
+ File.open(File::NULL) do |f|
+ f.set_encoding(Encoding.find('binary'))
+ assert_equal(Encoding::ASCII_8BIT, f.external_encoding)
+ end
+
+ File.open(File::NULL) do |f|
+ f.set_encoding('binary:utf-8')
+ assert_equal(nil, f.internal_encoding)
+ assert_equal(Encoding::ASCII_8BIT, f.external_encoding)
+ end
+
+ File.open(File::NULL) do |f|
+ f.set_encoding('binary', 'utf-8')
+ assert_equal(nil, f.internal_encoding)
+ assert_equal(Encoding::ASCII_8BIT, f.external_encoding)
+ end
+
+ File.open(File::NULL) do |f|
+ f.set_encoding(Encoding.find('binary'), Encoding.find('utf-8'))
+ assert_equal(nil, f.internal_encoding)
+ assert_equal(Encoding::ASCII_8BIT, f.external_encoding)
+ end
+
+ File.open(File::NULL) do |f|
+ f.set_encoding('binary', Encoding.find('utf-8'))
+ assert_equal(nil, f.internal_encoding)
+ assert_equal(Encoding::ASCII_8BIT, f.external_encoding)
+ end
+
+ File.open(File::NULL) do |f|
+ f.set_encoding(Encoding.find('binary'), 'utf-8')
+ assert_equal(nil, f.internal_encoding)
+ assert_equal(Encoding::ASCII_8BIT, f.external_encoding)
+ end
+
+ File.open(File::NULL) do |f|
+ f.set_encoding('iso-8859-1:utf-8')
+ assert_equal(Encoding::UTF_8, f.internal_encoding)
+ assert_equal(Encoding::ISO_8859_1, f.external_encoding)
+ end
+
+ File.open(File::NULL) do |f|
+ f.set_encoding('iso-8859-1', 'utf-8')
+ assert_equal(Encoding::UTF_8, f.internal_encoding)
+ assert_equal(Encoding::ISO_8859_1, f.external_encoding)
+ end
+
+ File.open(File::NULL) do |f|
+ f.set_encoding(Encoding.find('iso-8859-1'), Encoding.find('utf-8'))
+ assert_equal(Encoding::UTF_8, f.internal_encoding)
+ assert_equal(Encoding::ISO_8859_1, f.external_encoding)
+ end
+
+ File.open(File::NULL) do |f|
+ f.set_encoding('iso-8859-1', Encoding.find('utf-8'))
+ assert_equal(Encoding::UTF_8, f.internal_encoding)
+ assert_equal(Encoding::ISO_8859_1, f.external_encoding)
+ end
+
+ File.open(File::NULL) do |f|
+ f.set_encoding(Encoding.find('iso-8859-1'), 'utf-8')
+ assert_equal(Encoding::UTF_8, f.internal_encoding)
+ assert_equal(Encoding::ISO_8859_1, f.external_encoding)
+ end
+ end
+
def test_textmode_twice
assert_raise(ArgumentError) {
open(__FILE__, "rt", textmode: true) {|f|
@@ -1314,23 +1396,27 @@ EOT
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)
- }
+ EnvUtil.suppress_warning do # https://bugs.ruby-lang.org/issues/19630
+ 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
end
def test_open_pipe_r_enc2
- open("|#{EnvUtil.rubybin} -e 'putc \"\\u3042\"'", "r:UTF-8") {|f|
- assert_equal(Encoding::UTF_8, f.external_encoding)
- assert_equal(nil, f.internal_encoding)
- s = f.read
- assert_equal(Encoding::UTF_8, s.encoding)
- assert_equal("\u3042", s)
- }
+ EnvUtil.suppress_warning do # https://bugs.ruby-lang.org/issues/19630
+ open("|#{EnvUtil.rubybin} -e 'putc \"\\u3042\"'", "r:UTF-8") {|f|
+ assert_equal(Encoding::UTF_8, f.external_encoding)
+ assert_equal(nil, f.internal_encoding)
+ s = f.read
+ assert_equal(Encoding::UTF_8, s.encoding)
+ assert_equal("\u3042", s)
+ }
+ end
end
def test_s_foreach_enc
diff --git a/test/ruby/test_io_timeout.rb b/test/ruby/test_io_timeout.rb
new file mode 100644
index 0000000000..e017395980
--- /dev/null
+++ b/test/ruby/test_io_timeout.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: false
+
+require 'io/nonblock'
+
+class TestIOTimeout < Test::Unit::TestCase
+ def with_pipe
+ omit "UNIXSocket is not defined!" unless defined?(UNIXSocket)
+
+ begin
+ i, o = UNIXSocket.pair
+
+ yield i, o
+ ensure
+ i.close
+ o.close
+ end
+ end
+
+ def test_timeout_attribute
+ with_pipe do |i, o|
+ assert_nil i.timeout
+
+ i.timeout = 10
+ assert_equal 10, i.timeout
+ assert_nil o.timeout
+
+ o.timeout = 20
+ assert_equal 20, o.timeout
+ assert_equal 10, i.timeout
+ end
+ end
+
+ def test_timeout_read_exception
+ with_pipe do |i, o|
+ i.timeout = 0.0001
+
+ assert_raise(IO::TimeoutError) {i.read}
+ end
+ end
+
+ def test_timeout_gets_exception
+ with_pipe do |i, o|
+ i.timeout = 0.0001
+
+ assert_raise(IO::TimeoutError) {i.gets}
+ end
+ end
+
+ def test_timeout_puts
+ with_pipe do |i, o|
+ i.timeout = 0.0001
+ o.puts("Hello World")
+ o.close
+
+ assert_equal "Hello World", i.gets.chomp
+ end
+ end
+end
diff --git a/test/ruby/test_iseq.rb b/test/ruby/test_iseq.rb
index 0cde1fbb7a..49aa4c5abd 100644
--- a/test/ruby/test_iseq.rb
+++ b/test/ruby/test_iseq.rb
@@ -10,13 +10,16 @@ class TestISeq < Test::Unit::TestCase
end
def compile(src, line = nil, opt = nil)
+ unless line
+ line = caller_locations(1).first.lineno
+ end
EnvUtil.suppress_warning do
ISeq.new(src, __FILE__, __FILE__, line, opt)
end
end
- def lines src
- body = compile(src).to_a[13]
+ def lines src, lines = nil
+ body = compile(src, lines).to_a[13]
body.find_all{|e| e.kind_of? Integer}
end
@@ -25,24 +28,22 @@ class TestISeq < Test::Unit::TestCase
end
def test_to_a_lines
- src = <<-EOS
+ assert_equal [__LINE__+1, __LINE__+2, __LINE__+4], lines(<<-EOS, __LINE__+1)
p __LINE__ # 1
p __LINE__ # 2
# 3
p __LINE__ # 4
EOS
- assert_equal [1, 2, 4], lines(src)
- src = <<-EOS
+ assert_equal [__LINE__+2, __LINE__+4], lines(<<-EOS, __LINE__+1)
# 1
p __LINE__ # 2
# 3
p __LINE__ # 4
# 5
EOS
- assert_equal [2, 4], lines(src)
- src = <<-EOS
+ assert_equal [__LINE__+3, __LINE__+4, __LINE__+7, __LINE__+9], lines(<<~EOS, __LINE__+1)
1 # should be optimized out
2 # should be optimized out
p __LINE__ # 3
@@ -53,10 +54,9 @@ class TestISeq < Test::Unit::TestCase
8 # should be optimized out
9
EOS
- assert_equal [3, 4, 7, 9], lines(src)
end
- def test_unsupport_type
+ def test_unsupported_type
ary = compile("p").to_a
ary[9] = :foobar
assert_raise_with_message(TypeError, /:foobar/) {ISeq.load(ary)}
@@ -86,7 +86,7 @@ class TestISeq < Test::Unit::TestCase
# CDHASH was not built properly when loading from binary and
# was causing opt_case_dispatch to clobber its stack canary
# for its "leaf" instruction attribute.
- iseq = compile(<<~EOF)
+ iseq = compile(<<~EOF, __LINE__+1)
case Class.new(String).new("foo")
when "foo"
42
@@ -95,8 +95,98 @@ class TestISeq < Test::Unit::TestCase
assert_equal(42, ISeq.load_from_binary(iseq.to_binary).eval)
end
+ def test_forwardable
+ iseq = compile(<<~EOF, __LINE__+1)
+ Class.new {
+ def bar(a, b); a + b; end
+ def foo(...); bar(...); end
+ }
+ EOF
+ assert_equal(42, ISeq.load_from_binary(iseq.to_binary).eval.new.foo(40, 2))
+ end
+
+ def test_super_with_block
+ iseq = compile(<<~EOF, __LINE__+1)
+ def (Object.new).touch(*) # :nodoc:
+ foo { super }
+ end
+ 42
+ EOF
+ assert_equal(42, ISeq.load_from_binary(iseq.to_binary).eval)
+ end
+
+ def test_super_with_block_hash_0
+ iseq = compile(<<~EOF, __LINE__+1)
+ # [Bug #18250] `req` specifically cause `Assertion failed: (key != 0), function hash_table_raw_insert`
+ def (Object.new).touch(req, *)
+ foo { super }
+ end
+ 42
+ EOF
+ assert_equal(42, ISeq.load_from_binary(iseq.to_binary).eval)
+ end
+
+ def test_super_with_block_and_kwrest
+ iseq = compile(<<~EOF, __LINE__+1)
+ def (Object.new).touch(**) # :nodoc:
+ foo { super }
+ end
+ 42
+ EOF
+ assert_equal(42, ISeq.load_from_binary(iseq.to_binary).eval)
+ end
+
+ def test_lambda_with_ractor_roundtrip
+ iseq = compile(<<~EOF, __LINE__+1)
+ x = 42
+ y = nil.instance_eval{ lambda { x } }
+ Ractor.make_shareable(y)
+ y.call
+ EOF
+ assert_equal(42, ISeq.load_from_binary(iseq.to_binary).eval)
+ end
+
+ def test_super_with_anonymous_block
+ iseq = compile(<<~EOF, __LINE__+1)
+ def (Object.new).touch(&) # :nodoc:
+ foo { super }
+ end
+ 42
+ EOF
+ assert_equal(42, ISeq.load_from_binary(iseq.to_binary).eval)
+ end
+
+ def test_ractor_unshareable_outer_variable
+ name = "\u{2603 26a1}"
+ y = nil.instance_eval do
+ eval("proc {#{name} = nil; proc {|x| #{name} = x}}").call
+ end
+ assert_raise_with_message(ArgumentError, /\(#{name}\)/) do
+ Ractor.make_shareable(y)
+ end
+ y = nil.instance_eval do
+ eval("proc {#{name} = []; proc {|x| #{name}}}").call
+ end
+ assert_raise_with_message(Ractor::IsolationError, /'#{name}'/) do
+ Ractor.make_shareable(y)
+ end
+ obj = Object.new
+ def obj.foo(*) nil.instance_eval{ ->{super} } end
+ assert_raise_with_message(Ractor::IsolationError, /refer unshareable object \[\] from variable '\*'/) do
+ Ractor.make_shareable(obj.foo)
+ end
+ end
+
+ def test_ractor_shareable_value_frozen_core
+ iseq = RubyVM::InstructionSequence.compile(<<~'RUBY')
+ # shareable_constant_value: literal
+ REGEX = /#{}/ # [Bug #20569]
+ RUBY
+ assert_includes iseq.to_binary, "REGEX".b
+ end
+
def test_disasm_encoding
- src = "\u{3042} = 1; \u{3042}; \u{3043}"
+ src = +"\u{3042} = 1; \u{3042}; \u{3043}"
asm = compile(src).disasm
assert_equal(src.encoding, asm.encoding)
assert_predicate(asm, :valid_encoding?)
@@ -137,16 +227,16 @@ class TestISeq < Test::Unit::TestCase
end
def test_line_trace
- iseq = compile \
- %q{ a = 1
+ iseq = compile(<<~EOF, __LINE__+1)
+ a = 1
b = 2
c = 3
# d = 4
e = 5
# f = 6
g = 7
+ EOF
- }
assert_equal([1, 2, 3, 5, 7], iseq.line_trace_all)
iseq.line_trace_specify(1, true) # line 2
iseq.line_trace_specify(3, true) # line 5
@@ -275,11 +365,24 @@ class TestISeq < Test::Unit::TestCase
end
end
assert_equal([m1, e1.message], [m2, e2.message], feature11951)
- message = e1.message.each_line
- message.with_index(1) do |line, i|
- next if /^ / =~ line
- assert_send([line, :start_with?, __FILE__],
- proc {message.map {|l, j| (i == j ? ">" : " ") + l}.join("")})
+
+ if e1.message.lines[0] == "#{__FILE__}:#{line}: syntax errors found\n"
+ # Prism lays out the error messages in line with the source, so the
+ # following assertions do not make sense in that context.
+ else
+ message = e1.message.each_line
+ message.with_index(1) do |line, i|
+ next if /^ / =~ line
+ assert_send([line, :start_with?, __FILE__],
+ proc {message.map {|l, j| (i == j ? ">" : " ") + l}.join("")})
+ end
+ end
+ end
+
+ # [Bug #19173]
+ def test_compile_error
+ assert_raise SyntaxError do
+ RubyVM::InstructionSequence.compile 'using Module.new; yield'
end
end
@@ -288,7 +391,7 @@ class TestISeq < Test::Unit::TestCase
f.puts "end"
f.close
path = f.path
- assert_in_out_err(%W[- #{path}], "#{<<-"begin;"}\n#{<<-"end;"}", /unexpected `end'/, [], success: true)
+ assert_in_out_err(%W[- #{path}], "#{<<-"begin;"}\n#{<<-"end;"}", /unexpected 'end'/, [], success: true)
begin;
path = ARGV[0]
begin
@@ -318,6 +421,30 @@ class TestISeq < Test::Unit::TestCase
end
end
+ def anon_star(*); end
+
+ def test_anon_rest_param_in_disasm
+ iseq = RubyVM::InstructionSequence.of(method(:anon_star))
+ param_names = iseq.to_a[iseq.to_a.index(:method) + 1]
+ assert_equal [:*], param_names
+ end
+
+ def anon_keyrest(**); end
+
+ def test_anon_keyrest_param_in_disasm
+ iseq = RubyVM::InstructionSequence.of(method(:anon_keyrest))
+ param_names = iseq.to_a[iseq.to_a.index(:method) + 1]
+ assert_equal [:**], param_names
+ end
+
+ def anon_block(&); end
+
+ def test_anon_block_param_in_disasm
+ iseq = RubyVM::InstructionSequence.of(method(:anon_block))
+ param_names = iseq.to_a[iseq.to_a.index(:method) + 1]
+ assert_equal [:&], param_names
+ end
+
def strip_lineno(source)
source.gsub(/^.*?: /, "")
end
@@ -360,7 +487,7 @@ class TestISeq < Test::Unit::TestCase
["<class:C>@1",
["bar@10", ["block in bar@11",
["block (2 levels) in bar@12"]]],
- ["foo@2", ["ensure in foo@2"],
+ ["foo@2", ["ensure in foo@7"],
["rescue in foo@4"]]],
["<class:D>@17"]]
@@ -393,8 +520,9 @@ class TestISeq < Test::Unit::TestCase
[4, :line],
[7, :line],
[9, :return]]],
- [["ensure in foo@2", [[7, :line]]]],
- [["rescue in foo@4", [[5, :line]]]]]],
+ [["ensure in foo@7", [[7, :line]]]],
+ [["rescue in foo@4", [[5, :line],
+ [5, :rescue]]]]]],
[["<class:D>@17", [[17, :class],
[18, :end]]]]], collect_iseq.call(sample_iseq)
end
@@ -443,7 +571,7 @@ class TestISeq < Test::Unit::TestCase
bin = assert_nothing_raised(mesg) do
iseq.to_binary
rescue RuntimeError => e
- skip e.message if /compile with coverage/ =~ e.message
+ omit e.message if /compile with coverage/ =~ e.message
raise
end
10.times do
@@ -454,9 +582,31 @@ class TestISeq < Test::Unit::TestCase
a1 = iseq.to_a
a2 = iseq2.to_a
assert_equal(a1, a2, message(mesg) {diff iseq.disassemble, iseq2.disassemble})
+ if iseq2.script_lines
+ assert_kind_of(Array, iseq2.script_lines)
+ else
+ assert_nil(iseq2.script_lines)
+ end
iseq2
end
+ def test_to_binary_with_hidden_local_variables
+ assert_iseq_to_binary("for _foo in bar; end")
+
+ bin = RubyVM::InstructionSequence.compile(<<-RUBY).to_binary
+ Object.new.instance_eval do
+ a = []
+ def self.bar; [1] end
+ for foo in bar
+ a << (foo * 2)
+ end
+ a
+ end
+ RUBY
+ v = RubyVM::InstructionSequence.load_from_binary(bin).eval
+ assert_equal([2], v)
+ end
+
def test_to_binary_with_objects
assert_iseq_to_binary("[]"+100.times.map{|i|"<</#{i}/"}.join)
assert_iseq_to_binary("@x ||= (1..2)")
@@ -529,6 +679,8 @@ class TestISeq < Test::Unit::TestCase
}
lines
+ ensure
+ Object.send(:remove_const, :A) rescue nil
end
def test_to_binary_line_tracepoint
@@ -625,4 +777,140 @@ class TestISeq < Test::Unit::TestCase
RubyVM::InstructionSequence.compile("", debug_level: 5)
end;
end
+
+ def test_mandatory_only
+ assert_separately [], <<~RUBY
+ at0 = Time.at(0)
+ assert_equal at0, Time.public_send(:at, 0, 0)
+ RUBY
+ end
+
+ def test_mandatory_only_redef
+ assert_separately ['-W0'], <<~RUBY
+ r = Ractor.new{
+ Float(10)
+ module Kernel
+ undef Float
+ def Float(n)
+ :new
+ end
+ end
+ GC.start
+ Float(30)
+ }
+ assert_equal :new, r.take
+ RUBY
+ end
+
+ def test_ever_condition_loop
+ assert_ruby_status([], "BEGIN {exit}; while true && true; end")
+ end
+
+ def test_unreachable_syntax_error
+ mesg = /Invalid break/
+ assert_syntax_error("false and break", mesg)
+ assert_syntax_error("if false and break; end", mesg)
+ end
+
+ def test_unreachable_pattern_matching
+ assert_in_out_err([], "true or 1 in 1")
+ assert_in_out_err([], "true or (case 1; in 1; 1; in 2; 2; end)")
+ end
+
+ def test_unreachable_pattern_matching_in_if_condition
+ assert_in_out_err([], "#{<<~"begin;"}\n#{<<~'end;'}", %w[1])
+ begin;
+ if true or {a: 0} in {a:}
+ p 1
+ else
+ p a
+ end
+ end;
+ end
+
+ def test_unreachable_next_in_block
+ bug20344 = '[ruby-core:117210] [Bug #20344]'
+ assert_nothing_raised(SyntaxError, bug20344) do
+ compile(<<~RUBY)
+ proc do
+ next
+
+ case nil
+ when "a"
+ next
+ when "b"
+ when "c"
+ proc {}
+ end
+
+ next
+ end
+ RUBY
+ end
+ end
+
+ def test_loading_kwargs_memory_leak
+ assert_no_memory_leak([], "#{<<~"begin;"}", "#{<<~'end;'}", rss: true)
+ a = RubyVM::InstructionSequence.compile("foo(bar: :baz)").to_binary
+ begin;
+ 1_000_000.times do
+ RubyVM::InstructionSequence.load_from_binary(a)
+ end
+ end;
+ end
+
+ def test_ibf_bignum
+ iseq = RubyVM::InstructionSequence.compile("0x0"+"_0123_4567_89ab_cdef"*5)
+ expected = iseq.eval
+ result = RubyVM::InstructionSequence.load_from_binary(iseq.to_binary).eval
+ assert_equal expected, result, proc {sprintf("expected: %x, result: %x", expected, result)}
+ end
+
+ def test_compile_prism_with_file
+ Tempfile.create(%w"test_iseq .rb") do |f|
+ f.puts "_name = 'Prism'; puts 'hello'"
+ f.close
+
+ assert_nothing_raised(TypeError) do
+ RubyVM::InstructionSequence.compile_prism(f)
+ end
+ end
+ end
+
+ def block_using_method
+ yield
+ end
+
+ def block_unused_method
+ end
+
+ def test_unused_param
+ a = RubyVM::InstructionSequence.of(method(:block_using_method)).to_a
+
+ assert_equal true, a.dig(11, :use_block)
+
+ b = RubyVM::InstructionSequence.of(method(:block_unused_method)).to_a
+ assert_equal nil, b.dig(11, :use_block)
+ end
+
+ def test_compile_prism_with_invalid_object_type
+ assert_raise(TypeError) do
+ RubyVM::InstructionSequence.compile_prism(Object.new)
+ end
+ end
+
+ def test_load_from_binary_only_accepts_string_param
+ assert_raise(TypeError) do
+ var_0 = 0
+ RubyVM::InstructionSequence.load_from_binary(var_0)
+ end
+ end
+
+ def test_while_in_until_condition
+ assert_in_out_err(["--dump=i", "-e", "until while 1; end; end"]) do |stdout, stderr, status|
+ assert_include(stdout.shift, "== disasm:")
+ assert_include(stdout.pop, "leave")
+ assert_predicate(status, :success?)
+ end
+ end
end
diff --git a/test/ruby/test_iterator.rb b/test/ruby/test_iterator.rb
index 820d5591c1..1bb655d52e 100644
--- a/test/ruby/test_iterator.rb
+++ b/test/ruby/test_iterator.rb
@@ -175,10 +175,13 @@ class TestIterator < Test::Unit::TestCase
end
def test_block_given
+ verbose_bak, $VERBOSE = $VERBOSE, nil
assert(m1{p 'test'})
assert(m2{p 'test'})
assert(!m1())
assert(!m2())
+ ensure
+ $VERBOSE = verbose_bak
end
def m3(var, &block)
@@ -308,7 +311,18 @@ class TestIterator < Test::Unit::TestCase
def test_ljump
assert_raise(LocalJumpError) {get_block{break}.call}
- assert_raise(LocalJumpError) {proc_call2(get_block{break}){}}
+ begin
+ verbose_bak, $VERBOSE = $VERBOSE, nil
+ # See the commit https://github.com/ruby/ruby/commit/7d8a415bc2d08a1b5e9d1ea802493b6eeb99c219
+ # This block is not used but this is intentional.
+ # |
+ # +-----------------------------------------------------+
+ # |
+ # vv
+ assert_raise(LocalJumpError) {proc_call2(get_block{break}){}}
+ ensure
+ $VERBOSE = verbose_bak
+ end
# cannot use assert_nothing_raised due to passing block.
begin
diff --git a/test/ruby/test_jit.rb b/test/ruby/test_jit.rb
deleted file mode 100644
index 60e128b3d9..0000000000
--- a/test/ruby/test_jit.rb
+++ /dev/null
@@ -1,1259 +0,0 @@
-# frozen_string_literal: true
-require 'test/unit'
-require 'tmpdir'
-require_relative '../lib/jit_support'
-
-# Test for --jit option
-class TestJIT < Test::Unit::TestCase
- include JITSupport
-
- IGNORABLE_PATTERNS = [
- /\AJIT recompile: .+\n\z/,
- /\AJIT inline: .+\n\z/,
- /\AJIT cancel: .+\n\z/,
- /\ASuccessful MJIT finish\n\z/,
- ]
- MAX_CACHE_PATTERNS = [
- /\AJIT compaction \([^)]+\): .+\n\z/,
- /\AToo many JIT code, but skipped unloading units for JIT compaction\n\z/,
- /\ANo units can be unloaded -- .+\n\z/,
- ]
-
- # trace_* insns are not compiled for now...
- TEST_PENDING_INSNS = RubyVM::INSTRUCTION_NAMES.select { |n| n.start_with?('trace_') }.map(&:to_sym) + [
- # not supported yet
- :defineclass,
-
- # to be tested
- :invokebuiltin,
-
- # never used
- :opt_invokebuiltin_delegate,
- ].each do |insn|
- if !RubyVM::INSTRUCTION_NAMES.include?(insn.to_s)
- warn "instruction #{insn.inspect} is not defined but included in TestJIT::TEST_PENDING_INSNS"
- end
- end
-
- def self.untested_insns
- @untested_insns ||= (RubyVM::INSTRUCTION_NAMES.map(&:to_sym) - TEST_PENDING_INSNS)
- end
-
- def self.setup
- return if defined?(@setup_hooked)
- @setup_hooked = true
-
- # ci.rvm.jp caches its build environment. Clean up temporary files left by SEGV.
- if ENV['RUBY_DEBUG']&.include?('ci')
- Dir.glob("#{ENV.fetch('TMPDIR', '/tmp')}/_ruby_mjit_p*u*.*").each do |file|
- puts "test/ruby/test_jit.rb: removing #{file}"
- File.unlink(file)
- end
- end
-
- # ruby -w -Itest/lib test/ruby/test_jit.rb
- if $VERBOSE
- at_exit do
- unless TestJIT.untested_insns.empty?
- warn "you may want to add tests for following insns, when you have a chance: #{TestJIT.untested_insns.join(' ')}"
- end
- end
- end
- end
-
- def setup
- unless JITSupport.supported?
- skip 'JIT seems not supported on this platform'
- end
- self.class.setup
- end
-
- def test_compile_insn_nop
- assert_compile_once('nil rescue true', result_inspect: 'nil', insns: %i[nop])
- end
-
- def test_compile_insn_local
- assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '1', insns: %i[setlocal_WC_0 getlocal_WC_0])
- begin;
- foo = 1
- foo
- end;
-
- insns = %i[setlocal getlocal setlocal_WC_0 getlocal_WC_0 setlocal_WC_1 getlocal_WC_1]
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", success_count: 3, stdout: '168', insns: insns)
- begin;
- def foo
- a = 0
- [1, 2].each do |i|
- a += i
- [3, 4].each do |j|
- a *= j
- end
- end
- a
- end
-
- print foo
- end;
- end
-
- def test_compile_insn_blockparam
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '3', success_count: 2, insns: %i[getblockparam setblockparam])
- begin;
- def foo(&b)
- a = b
- b = 2
- a.call + 2
- end
-
- print foo { 1 }
- end;
- end
-
- def test_compile_insn_getblockparamproxy
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '4', success_count: 3, insns: %i[getblockparamproxy])
- begin;
- def bar(&b)
- b.call
- end
-
- def foo(&b)
- bar(&b) * bar(&b)
- end
-
- print foo { 2 }
- end;
- end
-
- def test_compile_insn_getspecial
- assert_compile_once('$1', result_inspect: 'nil', insns: %i[getspecial])
- end
-
- def test_compile_insn_setspecial
- assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: 'true', insns: %i[setspecial])
- begin;
- true if nil.nil?..nil.nil?
- end;
- end
-
- def test_compile_insn_instancevariable
- assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '1', insns: %i[getinstancevariable setinstancevariable])
- begin;
- @foo = 1
- @foo
- end;
-
- # optimized getinstancevariable call
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '33', success_count: 1, min_calls: 2)
- begin;
- class A
- def initialize
- @a = 1
- @b = 2
- end
-
- def three
- @a + @b
- end
- end
-
- a = A.new
- print(a.three) # set ic
- print(a.three) # inlined ic
- end;
- end
-
- def test_compile_insn_classvariable
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '1', success_count: 1, insns: %i[getclassvariable setclassvariable])
- begin;
- class Foo
- def self.foo
- @@foo = 1
- @@foo
- end
- end
-
- print Foo.foo
- end;
- end
-
- def test_compile_insn_constant
- assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '1', insns: %i[getconstant setconstant])
- begin;
- FOO = 1
- FOO
- end;
- end
-
- def test_compile_insn_global
- assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '1', insns: %i[getglobal setglobal])
- begin;
- $foo = 1
- $foo
- end;
- end
-
- def test_compile_insn_putnil
- assert_compile_once('nil', result_inspect: 'nil', insns: %i[putnil])
- end
-
- def test_compile_insn_putself
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: 'hello', success_count: 1, insns: %i[putself])
- begin;
- proc { print "hello" }.call
- end;
- end
-
- def test_compile_insn_putobject
- assert_compile_once('0', result_inspect: '0', insns: %i[putobject_INT2FIX_0_])
- assert_compile_once('1', result_inspect: '1', insns: %i[putobject_INT2FIX_1_])
- assert_compile_once('2', result_inspect: '2', insns: %i[putobject])
- end
-
- def test_compile_insn_definemethod_definesmethod
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: 'helloworld', success_count: 3, insns: %i[definemethod definesmethod])
- begin;
- print 1.times.map {
- def method_definition
- 'hello'
- end
-
- def self.smethod_definition
- 'world'
- end
-
- method_definition + smethod_definition
- }.join
- end;
- end
-
- def test_compile_insn_putspecialobject
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: 'a', success_count: 2, insns: %i[putspecialobject])
- begin;
- print 1.times.map {
- def a
- 'a'
- end
-
- alias :b :a
-
- b
- }.join
- end;
- end
-
- def test_compile_insn_putstring_concatstrings_tostring
- assert_compile_once('"a#{}b" + "c"', result_inspect: '"abc"', insns: %i[putstring concatstrings tostring])
- end
-
- def test_compile_insn_toregexp
- assert_compile_once('/#{true}/ =~ "true"', result_inspect: '0', insns: %i[toregexp])
- end
-
- def test_compile_insn_newarray
- assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '[1, 2, 3]', insns: %i[newarray])
- begin;
- a, b, c = 1, 2, 3
- [a, b, c]
- end;
- end
-
- def test_compile_insn_newarraykwsplat
- assert_compile_once('[**{ x: 1 }]', result_inspect: '[{:x=>1}]', insns: %i[newarraykwsplat])
- end
-
- def test_compile_insn_intern_duparray
- assert_compile_once('[:"#{0}"] + [1,2,3]', result_inspect: '[:"0", 1, 2, 3]', insns: %i[intern duparray])
- end
-
- def test_compile_insn_expandarray
- assert_compile_once('y = [ true, false, nil ]; x, = y; x', result_inspect: 'true', insns: %i[expandarray])
- end
-
- def test_compile_insn_concatarray
- assert_compile_once('["t", "r", *x = "u", "e"].join', result_inspect: '"true"', insns: %i[concatarray])
- end
-
- def test_compile_insn_splatarray
- assert_compile_once('[*(1..2)]', result_inspect: '[1, 2]', insns: %i[splatarray])
- end
-
- def test_compile_insn_newhash
- assert_compile_once('a = 1; { a: a }', result_inspect: '{:a=>1}', insns: %i[newhash])
- end
-
- def test_compile_insn_duphash
- assert_compile_once('{ a: 1 }', result_inspect: '{:a=>1}', insns: %i[duphash])
- end
-
- def test_compile_insn_newrange
- assert_compile_once('a = 1; 0..a', result_inspect: '0..1', insns: %i[newrange])
- end
-
- def test_compile_insn_pop
- assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '1', insns: %i[pop])
- begin;
- a = false
- b = 1
- a || b
- end;
- end
-
- def test_compile_insn_dup
- assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '3', insns: %i[dup])
- begin;
- a = 1
- a&.+(2)
- end;
- end
-
- def test_compile_insn_dupn
- assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: 'true', insns: %i[dupn])
- begin;
- klass = Class.new
- klass::X ||= true
- end;
- end
-
- def test_compile_insn_swap_topn
- assert_compile_once('{}["true"] = true', result_inspect: 'true', insns: %i[swap topn])
- end
-
- def test_compile_insn_reput
- skip "write test"
- end
-
- def test_compile_insn_setn
- assert_compile_once('[nil][0] = 1', result_inspect: '1', insns: %i[setn])
- end
-
- def test_compile_insn_adjuststack
- assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: 'true', insns: %i[adjuststack])
- begin;
- x = [true]
- x[0] ||= nil
- x[0]
- end;
- end
-
- def test_compile_insn_defined
- assert_compile_once('defined?(a)', result_inspect: 'nil', insns: %i[defined])
- end
-
- def test_compile_insn_checkkeyword
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: 'true', success_count: 1, insns: %i[checkkeyword])
- begin;
- def test(x: rand)
- x
- end
- print test(x: true)
- end;
- end
-
- def test_compile_insn_tracecoverage
- skip "write test"
- end
-
- def test_compile_insn_defineclass
- skip "support this in mjit_compile (low priority)"
- end
-
- def test_compile_insn_send
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '1', success_count: 3, insns: %i[send])
- begin;
- print proc { yield_self { 1 } }.call
- end;
- end
-
- def test_compile_insn_opt_str_freeze
- assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '"foo"', insns: %i[opt_str_freeze])
- begin;
- 'foo'.freeze
- end;
- end
-
- def test_compile_insn_opt_nil_p
- assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: 'false', insns: %i[opt_nil_p])
- begin;
- nil.nil?.nil?
- end;
- end
-
- def test_compile_insn_opt_str_uminus
- assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '"bar"', insns: %i[opt_str_uminus])
- begin;
- -'bar'
- end;
- end
-
- def test_compile_insn_opt_newarray_max
- assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '2', insns: %i[opt_newarray_max])
- begin;
- a = 1
- b = 2
- [a, b].max
- end;
- end
-
- def test_compile_insn_opt_newarray_min
- assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '1', insns: %i[opt_newarray_min])
- begin;
- a = 1
- b = 2
- [a, b].min
- end;
- end
-
- def test_compile_insn_opt_send_without_block
- assert_compile_once('print', result_inspect: 'nil', insns: %i[opt_send_without_block])
- end
-
- def test_compile_insn_invokesuper
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '3', success_count: 4, insns: %i[invokesuper])
- begin;
- mod = Module.new {
- def test
- super + 2
- end
- }
- klass = Class.new {
- prepend mod
- def test
- 1
- end
- }
- print klass.new.test
- end;
- end
-
- def test_compile_insn_invokeblock_leave
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '2', success_count: 2, insns: %i[invokeblock leave])
- begin;
- def foo
- yield
- end
- print foo { 2 }
- end;
- end
-
- def test_compile_insn_throw
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '4', success_count: 2, insns: %i[throw])
- begin;
- def test
- proc do
- if 1+1 == 1
- return 3
- else
- return 4
- end
- 5
- end.call
- end
- print test
- end;
- end
-
- def test_compile_insn_jump_branchif
- assert_compile_once("#{<<~"begin;"}\n#{<<~'end;'}", result_inspect: 'nil', insns: %i[jump branchif])
- begin;
- a = false
- 1 + 1 while a
- end;
- end
-
- def test_compile_insn_branchunless
- assert_compile_once("#{<<~"begin;"}\n#{<<~'end;'}", result_inspect: '1', insns: %i[branchunless])
- begin;
- a = true
- if a
- 1
- else
- 2
- end
- end;
- end
-
- def test_compile_insn_branchnil
- assert_compile_once("#{<<~"begin;"}\n#{<<~'end;'}", result_inspect: '3', insns: %i[branchnil])
- begin;
- a = 2
- a&.+(1)
- end;
- end
-
- def test_compile_insn_checktype
- assert_compile_once("#{<<~"begin;"}\n#{<<~'end;'}", result_inspect: '"42"', insns: %i[checktype])
- begin;
- a = '2'
- "4#{a}"
- end;
- end
-
- def test_compile_insn_inlinecache
- assert_compile_once('Struct', result_inspect: 'Struct', insns: %i[opt_getinlinecache opt_setinlinecache])
- end
-
- def test_compile_insn_once
- assert_compile_once('/#{true}/o =~ "true" && $~.to_a', result_inspect: '["true"]', insns: %i[once])
- end
-
- def test_compile_insn_checkmatch_opt_case_dispatch
- assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '"world"', insns: %i[opt_case_dispatch])
- begin;
- case 'hello'
- when 'hello'
- 'world'
- end
- end;
- end
-
- def test_compile_insn_opt_calc
- assert_compile_once('4 + 2 - ((2 * 3 / 2) % 2)', result_inspect: '5', insns: %i[opt_plus opt_minus opt_mult opt_div opt_mod])
- assert_compile_once('4.0 + 2.0 - ((2.0 * 3.0 / 2.0) % 2.0)', result_inspect: '5.0', insns: %i[opt_plus opt_minus opt_mult opt_div opt_mod])
- assert_compile_once('4 + 2', result_inspect: '6')
- end
-
- def test_compile_insn_opt_cmp
- assert_compile_once('(1 == 1) && (1 != 2)', result_inspect: 'true', insns: %i[opt_eq opt_neq])
- end
-
- def test_compile_insn_opt_rel
- assert_compile_once('1 < 2 && 1 <= 1 && 2 > 1 && 1 >= 1', result_inspect: 'true', insns: %i[opt_lt opt_le opt_gt opt_ge])
- end
-
- def test_compile_insn_opt_ltlt
- assert_compile_once('[1] << 2', result_inspect: '[1, 2]', insns: %i[opt_ltlt])
- end
-
- def test_compile_insn_opt_and
- assert_compile_once('1 & 3', result_inspect: '1', insns: %i[opt_and])
- end
-
- def test_compile_insn_opt_or
- assert_compile_once('1 | 3', result_inspect: '3', insns: %i[opt_or])
- end
-
- def test_compile_insn_opt_aref
- # optimized call (optimized JIT) -> send call
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '21', success_count: 2, min_calls: 1, insns: %i[opt_aref])
- begin;
- obj = Object.new
- def obj.[](h)
- h
- end
-
- block = proc { |h| h[1] }
- print block.call({ 1 => 2 })
- print block.call(obj)
- end;
-
- # send call -> optimized call (send JIT) -> optimized call
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '122', success_count: 2, min_calls: 2)
- begin;
- obj = Object.new
- def obj.[](h)
- h
- end
-
- block = proc { |h| h[1] }
- print block.call(obj)
- print block.call({ 1 => 2 })
- print block.call({ 1 => 2 })
- end;
- end
-
- def test_compile_insn_opt_aref_with
- assert_compile_once("{ '1' => 2 }['1']", result_inspect: '2', insns: %i[opt_aref_with])
- end
-
- def test_compile_insn_opt_aset
- assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '5', insns: %i[opt_aset opt_aset_with])
- begin;
- hash = { '1' => 2 }
- (hash['2'] = 2) + (hash[1.to_s] = 3)
- end;
- end
-
- def test_compile_insn_opt_length_size
- assert_compile_once("#{<<~"begin;"}\n#{<<~"end;"}", result_inspect: '4', insns: %i[opt_length opt_size])
- begin;
- array = [1, 2]
- array.length + array.size
- end;
- end
-
- def test_compile_insn_opt_empty_p
- assert_compile_once('[].empty?', result_inspect: 'true', insns: %i[opt_empty_p])
- end
-
- def test_compile_insn_opt_succ
- assert_compile_once('1.succ', result_inspect: '2', insns: %i[opt_succ])
- end
-
- def test_compile_insn_opt_not
- assert_compile_once('!!true', result_inspect: 'true', insns: %i[opt_not])
- end
-
- def test_compile_insn_opt_regexpmatch2
- assert_compile_once("/true/ =~ 'true'", result_inspect: '0', insns: %i[opt_regexpmatch2])
- assert_compile_once("'true' =~ /true/", result_inspect: '0', insns: %i[opt_regexpmatch2])
- end
-
- def test_compile_insn_opt_invokebuiltin_delegate_leave
- iseq = eval(EnvUtil.invoke_ruby(['-e', <<~'EOS'], '', true).first)
- p RubyVM::InstructionSequence.of("\x00".method(:unpack)).to_a
- EOS
- insns = collect_insns(iseq)
- mark_tested_insn(:opt_invokebuiltin_delegate_leave, used_insns: insns)
- assert_eval_with_jit('print "\x00".unpack("c")', stdout: '[0]', success_count: 1)
- end
-
- def test_jit_output
- out, err = eval_with_jit('5.times { puts "MJIT" }', verbose: 1, min_calls: 5)
- assert_equal("MJIT\n" * 5, out)
- assert_match(/^#{JIT_SUCCESS_PREFIX}: block in <main>@-e:1 -> .+_ruby_mjit_p\d+u\d+\.c$/, err)
- assert_match(/^Successful MJIT finish$/, err)
- end
-
- def test_nothing_to_unload_with_jit_wait
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: 'hello', success_count: 11, max_cache: 10, ignorable_patterns: MAX_CACHE_PATTERNS)
- begin;
- def a1() a2() end
- def a2() a3() end
- def a3() a4() end
- def a4() a5() end
- def a5() a6() end
- def a6() a7() end
- def a7() a8() end
- def a8() a9() end
- def a9() a10() end
- def a10() a11() end
- def a11() print('hello') end
- a1
- end;
- end
-
- def test_unload_units_on_fiber
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: 'hello', success_count: 12, max_cache: 10, ignorable_patterns: MAX_CACHE_PATTERNS)
- begin;
- def a1() a2(false); a2(true) end
- def a2(a) a3(a) end
- def a3(a) a4(a) end
- def a4(a) a5(a) end
- def a5(a) a6(a) end
- def a6(a) a7(a) end
- def a7(a) a8(a) end
- def a8(a) a9(a) end
- def a9(a) a10(a) end
- def a10(a)
- if a
- Fiber.new { a11 }.resume
- end
- end
- def a11() print('hello') end
- a1
- end;
- end
-
- def test_unload_units_and_compaction
- Dir.mktmpdir("jit_test_unload_units_") do |dir|
- # MIN_CACHE_SIZE is 10
- out, err = eval_with_jit({"TMPDIR"=>dir}, "#{<<~"begin;"}\n#{<<~'end;'}", verbose: 1, min_calls: 1, max_cache: 10)
- begin;
- i = 0
- while i < 11
- eval(<<-EOS)
- def mjit#{i}
- print #{i}
- end
- mjit#{i}
- EOS
- i += 1
- end
-
- if defined?(fork)
- # test the child does not try to delete files which are deleted by parent,
- # and test possible deadlock on fork during MJIT unload and JIT compaction on child
- Process.waitpid(Process.fork {})
- end
- end;
-
- debug_info = %Q[stdout:\n"""\n#{out}\n"""\n\nstderr:\n"""\n#{err}"""\n]
- assert_equal('012345678910', out, debug_info)
- compactions, errs = err.lines.partition do |l|
- l.match?(/\AJIT compaction \(\d+\.\dms\): Compacted \d+ methods /)
- end
- 10.times do |i|
- assert_match(/\A#{JIT_SUCCESS_PREFIX}: mjit#{i}@\(eval\):/, errs[i], debug_info)
- end
-
- assert_equal("No units can be unloaded -- incremented max-cache-size to 11 for --jit-wait\n", errs[10], debug_info)
- assert_match(/\A#{JIT_SUCCESS_PREFIX}: mjit10@\(eval\):/, errs[11], debug_info)
- # On --jit-wait, when the number of JIT-ed code reaches --jit-max-cache,
- # it should trigger compaction.
- unless RUBY_PLATFORM.match?(/mswin|mingw/) # compaction is not supported on Windows yet
- assert_equal(1, compactions.size, debug_info)
- end
-
- if RUBY_PLATFORM.match?(/mswin/)
- # "Permission Denied" error is preventing to remove so file on AppVeyor/RubyCI.
- skip 'Removing so file is randomly failing on AppVeyor/RubyCI mswin due to Permission Denied.'
- else
- # verify .c files are deleted on unload_units
- assert_send([Dir, :empty?, dir], debug_info)
- end
- end
- end
-
- def test_newarraykwsplat_on_stack
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "[nil, [{:type=>:development}]]\n", success_count: 1, insns: %i[newarraykwsplat])
- begin;
- def arr
- [nil, [:type => :development]]
- end
- p arr
- end;
- end
-
- def test_local_stack_on_exception
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '3', success_count: 2)
- begin;
- def b
- raise
- rescue
- 2
- end
-
- def a
- # Calling #b should be vm_exec, not direct mjit_exec.
- # Otherwise `1` on local variable would be purged.
- 1 + b
- end
-
- print a
- end;
- end
-
- def test_local_stack_with_sp_motion_by_blockargs
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '1', success_count: 2)
- begin;
- def b(base)
- 1
- end
-
- # This method is simple enough to have false in catch_except_p.
- # So local_stack_p would be true in JIT compiler.
- def a
- m = method(:b)
-
- # ci->flag has VM_CALL_ARGS_BLOCKARG and cfp->sp is moved in vm_caller_setup_arg_block.
- # So, for this send insn, JIT-ed code should use cfp->sp instead of local variables for stack.
- Module.module_eval(&m)
- end
-
- print a
- end;
- end
-
- def test_catching_deep_exception
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '1', success_count: 4)
- begin;
- def catch_true(paths, prefixes) # catch_except_p: TRUE
- prefixes.each do |prefix| # catch_except_p: TRUE
- paths.each do |path| # catch_except_p: FALSE
- return path
- end
- end
- end
-
- def wrapper(paths, prefixes)
- catch_true(paths, prefixes)
- end
-
- print wrapper(['1'], ['2'])
- end;
- end
-
- def test_inlined_builtin_methods
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '', success_count: 1, min_calls: 2)
- begin;
- def test
- float = 0.0
- float.abs
- float.-@
- float.zero?
- end
- test
- test
- end;
- end
-
- def test_inlined_c_method
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "aaa", success_count: 2, recompile_count: 1, min_calls: 2)
- begin;
- def test(obj, recursive: nil)
- if recursive
- test(recursive)
- end
- obj.to_s
- end
-
- print(test('a')) # set #to_s cc to String#to_s (expecting C method)
- print(test('a')) # JIT with #to_s cc: String#to_s
- # update #to_s cd->cc to Symbol#to_s, then go through the Symbol#to_s cd->cc
- # after checking receiver class using inlined #to_s cc with String#to_s.
- print(test('a', recursive: :foo))
- end;
- end
-
- def test_inlined_exivar
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "aaa", success_count: 3, recompile_count: 1, min_calls: 2)
- begin;
- class Foo < Hash
- def initialize
- @a = :a
- end
-
- def bar
- @a
- end
- end
-
- print(Foo.new.bar)
- print(Foo.new.bar) # compile #initialize, #bar -> recompile #bar
- print(Foo.new.bar) # compile #bar with exivar
- end;
- end
-
- def test_inlined_undefined_ivar
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "bbb", success_count: 3, min_calls: 3)
- begin;
- class Foo
- def initialize
- @a = :a
- end
-
- def bar
- if @b.nil?
- @b = :b
- end
- end
- end
-
- print(Foo.new.bar)
- print(Foo.new.bar)
- print(Foo.new.bar)
- end;
- end
-
- def test_inlined_setivar_frozen
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "FrozenError\n", success_count: 2, min_calls: 3)
- begin;
- class A
- def a
- @a = 1
- end
- end
-
- a = A.new
- a.a
- a.a
- a.a
- a.freeze
- begin
- a.a
- rescue FrozenError => e
- p e.class
- end
- end;
- end
-
- def test_inlined_getconstant
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '11', success_count: 1, min_calls: 2)
- begin;
- FOO = 1
- def const
- FOO
- end
- print const
- print const
- end;
- end
-
- def test_attr_reader
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "4nil\nnil\n6", success_count: 2, min_calls: 2)
- begin;
- class A
- attr_reader :a, :b
-
- def initialize
- @a = 2
- end
-
- def test
- a
- end
-
- def undefined
- b
- end
- end
-
- a = A.new
- print(a.test * a.test)
- p(a.undefined)
- p(a.undefined)
-
- # redefinition
- def a.test
- 3
- end
-
- print(2 * a.test)
- end;
-
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "true", success_count: 1, min_calls: 2)
- begin;
- class Hoge
- attr_reader :foo
-
- def initialize
- @foo = []
- @bar = nil
- end
- end
-
- class Fuga < Hoge
- def initialize
- @bar = nil
- @foo = []
- end
- end
-
- def test(recv)
- recv.foo.empty?
- end
-
- hoge = Hoge.new
- fuga = Fuga.new
-
- test(hoge) # VM: cc set index=1
- test(hoge) # JIT: compile with index=1
- test(fuga) # JIT -> VM: cc set index=2
- print test(hoge) # JIT: should use index=1, not index=2 in cc
- end;
- end
-
- def test_heap_promotion_of_ivar_in_the_middle_of_jit
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "true\ntrue\n", success_count: 2, min_calls: 2)
- begin;
- class A
- def initialize
- @iv0 = nil
- @iv1 = []
- @iv2 = nil
- end
-
- def test(add)
- @iv0.nil?
- @iv2.nil?
- add_ivar if add
- @iv1.empty?
- end
-
- def add_ivar
- @iv3 = nil
- end
- end
-
- a = A.new
- p a.test(false)
- p a.test(true)
- end;
- end
-
- def test_jump_to_precompiled_branch
- assert_eval_with_jit("#{<<~'begin;'}\n#{<<~'end;'}", stdout: ".0", success_count: 1, min_calls: 1)
- begin;
- def test(foo)
- ".#{foo unless foo == 1}" if true
- end
- print test(0)
- end;
- end
-
- def test_clean_so
- if RUBY_PLATFORM.match?(/mswin/)
- skip 'Removing so file is randomly failing on AppVeyor/RubyCI mswin due to Permission Denied.'
- end
- Dir.mktmpdir("jit_test_clean_so_") do |dir|
- code = "x = 0; 10.times {|i|x+=i}"
- eval_with_jit({"TMPDIR"=>dir}, code)
- assert_send([Dir, :empty?, dir])
- eval_with_jit({"TMPDIR"=>dir}, code, save_temps: true)
- assert_not_send([Dir, :empty?, dir])
- end
- end
-
- def test_clean_objects_on_exec
- if /mswin|mingw/ =~ RUBY_PLATFORM
- # TODO: check call stack and close handle of code which is not on stack, and remove objects on best-effort basis
- skip 'Removing so file being used does not work on Windows'
- end
- Dir.mktmpdir("jit_test_clean_objects_on_exec_") do |dir|
- eval_with_jit({"TMPDIR"=>dir}, "#{<<~"begin;"}\n#{<<~"end;"}", min_calls: 1)
- begin;
- def a; end; a
- exec "true"
- end;
- error_message = "Undeleted files:\n #{Dir.glob("#{dir}/*").join("\n ")}\n"
- assert_send([Dir, :empty?, dir], error_message)
- end
- end
-
- def test_lambda_longjmp
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '5', success_count: 1)
- begin;
- fib = lambda do |x|
- return x if x == 0 || x == 1
- fib.call(x-1) + fib.call(x-2)
- end
- print fib.call(5)
- end;
- end
-
- def test_stack_pointer_with_assignment
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "nil\nnil\n", success_count: 1)
- begin;
- 2.times do
- a, _ = nil
- p a
- end
- end;
- end
-
- def test_frame_omitted_inlining
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "true\ntrue\ntrue\n", success_count: 1, min_calls: 2)
- begin;
- class Integer
- remove_method :zero?
- def zero?
- self == 0
- end
- end
-
- 3.times do
- p 0.zero?
- end
- end;
- end
-
- def test_block_handler_with_possible_frame_omitted_inlining
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "70.0\n70.0\n70.0\n", success_count: 2, min_calls: 2)
- begin;
- def multiply(a, b)
- a *= b
- end
-
- 3.times do
- p multiply(7.0, 10.0)
- end
- end;
- end
-
- def test_builtin_frame_omitted_inlining
- assert_eval_with_jit('0.zero?; 0.zero?; 3.times { p 0.zero? }', stdout: "true\ntrue\ntrue\n", success_count: 1, min_calls: 2)
- end
-
- def test_program_counter_with_regexpmatch
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "aa", success_count: 1)
- begin;
- 2.times do
- break if /a/ =~ "ab" && !$~[0]
- print $~[0]
- end
- end;
- end
-
- def test_pushed_values_with_opt_aset_with
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "{}{}", success_count: 1)
- begin;
- 2.times do
- print(Thread.current["a"] = {})
- end
- end;
- end
-
- def test_pushed_values_with_opt_aref_with
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: "nil\nnil\n", success_count: 1)
- begin;
- 2.times do
- p(Thread.current["a"])
- end
- end;
- end
-
- def test_mjit_pause_wait
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", stdout: '', success_count: 0, min_calls: 1)
- begin;
- RubyVM::JIT.pause
- proc {}.call
- end;
- end
-
- def test_not_cancel_by_tracepoint_class
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", success_count: 1, min_calls: 2)
- begin;
- TracePoint.new(:class) {}.enable
- 2.times {}
- end;
- end
-
- def test_cancel_by_tracepoint
- assert_eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", success_count: 0, min_calls: 2)
- begin;
- TracePoint.new(:line) {}.enable
- 2.times {}
- end;
- end
-
- def test_caller_locations_without_catch_table
- out, _ = eval_with_jit("#{<<~"begin;"}\n#{<<~"end;"}", min_calls: 1)
- begin;
- def b # 2
- caller_locations.first # 3
- end # 4
- # 5
- def a # 6
- print # <-- don't leave PC here # 7
- b # 8
- end
- puts a
- puts a
- end;
- lines = out.lines
- assert_equal("-e:8:in `a'\n", lines[0])
- assert_equal("-e:8:in `a'\n", lines[1])
- end
-
- def test_fork_with_mjit_worker_thread
- Dir.mktmpdir("jit_test_fork_with_mjit_worker_thread_") do |dir|
- # min_calls: 2 to skip fork block
- out, err = eval_with_jit({ "TMPDIR" => dir }, "#{<<~"begin;"}\n#{<<~"end;"}", min_calls: 2, verbose: 1)
- begin;
- def before_fork; end
- def after_fork; end
-
- before_fork; before_fork # the child should not delete this .o file
- pid = Process.fork do # this child should not delete shared .pch file
- sleep 2.0 # to prevent mixing outputs on Solaris
- after_fork; after_fork # this child does not share JIT-ed after_fork with parent
- end
- after_fork; after_fork # this parent does not share JIT-ed after_fork with child
-
- Process.waitpid(pid)
- end;
- success_count = err.scan(/^#{JIT_SUCCESS_PREFIX}:/).size
- debug_info = "stdout:\n```\n#{out}\n```\n\nstderr:\n```\n#{err}```\n"
- assert_equal(3, success_count, debug_info)
-
- # assert no remove error
- assert_equal("Successful MJIT finish\n" * 2, err.gsub(/^#{JIT_SUCCESS_PREFIX}:[^\n]+\n/, ''), debug_info)
-
- # ensure objects are deleted
- assert_send([Dir, :empty?, dir], debug_info)
- end
- end if defined?(fork)
-
- private
-
- # The shortest way to test one proc
- def assert_compile_once(script, result_inspect:, insns: [], uplevel: 1)
- if script.match?(/\A\n.+\n\z/m)
- script = script.gsub(/^/, ' ')
- else
- script = " #{script} "
- end
- assert_eval_with_jit("p proc {#{script}}.call", stdout: "#{result_inspect}\n", success_count: 1, insns: insns, uplevel: uplevel + 1)
- end
-
- # Shorthand for normal test cases
- def assert_eval_with_jit(script, stdout: nil, success_count:, recompile_count: nil, min_calls: 1, max_cache: 1000, insns: [], uplevel: 1, ignorable_patterns: [])
- out, err = eval_with_jit(script, verbose: 1, min_calls: min_calls, max_cache: max_cache)
- success_actual = err.scan(/^#{JIT_SUCCESS_PREFIX}:/).size
- recompile_actual = err.scan(/^#{JIT_RECOMPILE_PREFIX}:/).size
- # Add --jit-verbose=2 logs for cl.exe because compiler's error message is suppressed
- # for cl.exe with --jit-verbose=1. See `start_process` in mjit_worker.c.
- if RUBY_PLATFORM.match?(/mswin/) && success_count != success_actual
- out2, err2 = eval_with_jit(script, verbose: 2, min_calls: min_calls, max_cache: max_cache)
- end
-
- # Make sure that the script has insns expected to be tested
- used_insns = method_insns(script)
- insns.each do |insn|
- mark_tested_insn(insn, used_insns: used_insns, uplevel: uplevel + 3)
- end
-
- suffix = "script:\n#{code_block(script)}\nstderr:\n#{code_block(err)}#{(
- "\nstdout(verbose=2 retry):\n#{code_block(out2)}\nstderr(verbose=2 retry):\n#{code_block(err2)}" if out2 || err2
- )}"
- assert_equal(
- success_count, success_actual,
- "Expected #{success_count} times of JIT success, but succeeded #{success_actual} times.\n\n#{suffix}",
- )
- if recompile_count
- assert_equal(
- recompile_count, recompile_actual,
- "Expected #{success_count} times of JIT recompile, but recompiled #{success_actual} times.\n\n#{suffix}",
- )
- end
- if stdout
- assert_equal(stdout, out, "Expected stdout #{out.inspect} to match #{stdout.inspect} with script:\n#{code_block(script)}")
- end
- err_lines = err.lines.reject! do |l|
- l.chomp.empty? || l.match?(/\A#{JIT_SUCCESS_PREFIX}/) || (IGNORABLE_PATTERNS + ignorable_patterns).any? { |pat| pat.match?(l) }
- end
- unless err_lines.empty?
- warn err_lines.join(''), uplevel: uplevel
- end
- end
-
- def mark_tested_insn(insn, used_insns:, uplevel: 1)
- unless used_insns.include?(insn)
- $stderr.puts
- warn "'#{insn}' insn is not included in the script. Actual insns are: #{used_insns.join(' ')}\n", uplevel: uplevel
- end
- TestJIT.untested_insns.delete(insn)
- end
-
- # Collect block's insns or defined method's insns, which are expected to be JIT-ed.
- # Note that this intentionally excludes insns in script's toplevel because they are not JIT-ed.
- def method_insns(script)
- insns = []
- RubyVM::InstructionSequence.compile(script).to_a.last.each do |(insn, *args)|
- case insn
- when :send
- insns += collect_insns(args.last)
- when :definemethod, :definesmethod
- insns += collect_insns(args[1])
- when :defineclass
- insns += collect_insns(args[1])
- end
- end
- insns.uniq
- end
-
- # Recursively collect insns in iseq_array
- def collect_insns(iseq_array)
- return [] if iseq_array.nil?
-
- insns = iseq_array.last.select { |x| x.is_a?(Array) }.map(&:first)
- iseq_array.last.each do |(insn, *args)|
- case insn
- when :definemethod, :definesmethod, :send
- insns += collect_insns(args.last)
- end
- end
- insns
- end
-end
diff --git a/test/ruby/test_jit_debug.rb b/test/ruby/test_jit_debug.rb
deleted file mode 100644
index 50e52b4c2e..0000000000
--- a/test/ruby/test_jit_debug.rb
+++ /dev/null
@@ -1,17 +0,0 @@
-require_relative 'test_jit'
-
-return unless defined?(TestJIT)
-return if ENV.key?('APPVEYOR')
-return if ENV.key?('RUBYCI_NICKNAME')
-return if ENV['RUBY_DEBUG']&.include?('ci') # ci.rvm.jp
-return if /mswin/ =~ RUBY_PLATFORM
-
-class TestJITDebug < TestJIT
- @@test_suites.delete TestJIT if self.respond_to? :on_parallel_worker?
-
- def setup
- super
- # let `#eval_with_jit` use --jit-debug
- @jit_debug = true
- end
-end
diff --git a/test/ruby/test_keyword.rb b/test/ruby/test_keyword.rb
index 9094259bc2..a214acc232 100644
--- a/test/ruby/test_keyword.rb
+++ b/test/ruby/test_keyword.rb
@@ -182,6 +182,52 @@ class TestKeywordArguments < Test::Unit::TestCase
[:keyrest, :kw], [:block, :b]], method(:f9).parameters)
end
+ def test_keyword_with_anonymous_keyword_splat
+ def self.a(b: 1, **) [b, **] end
+ kw = {b: 2, c: 3}
+ assert_equal([2, {c: 3}], a(**kw))
+ assert_equal({b: 2, c: 3}, kw)
+ end
+
+ def test_keyword_splat_nil
+ # cfunc call
+ assert_equal(nil, p(**nil))
+
+ def self.a0(&); end
+ assert_equal(nil, a0(**nil))
+ assert_equal(nil, :a0.to_proc.call(self, **nil))
+ assert_equal(nil, a0(**nil, &:block))
+
+ def self.o(x=1); x end
+ assert_equal(1, o(**nil))
+ assert_equal(2, o(2, **nil))
+ assert_equal(1, o(*nil, **nil))
+ assert_equal(1, o(**nil, **nil))
+ assert_equal({a: 1}, o(a: 1, **nil))
+ assert_equal({a: 1}, o(**nil, a: 1))
+
+ # symproc call
+ assert_equal(1, :o.to_proc.call(self, **nil))
+
+ def self.s(*a); a end
+ assert_equal([], s(**nil))
+ assert_equal([1], s(1, **nil))
+ assert_equal([], s(*nil, **nil))
+
+ def self.kws(**a); a end
+ assert_equal({}, kws(**nil))
+ assert_equal({}, kws(*nil, **nil))
+
+ def self.skws(*a, **kw); [a, kw] end
+ assert_equal([[], {}], skws(**nil))
+ assert_equal([[1], {}], skws(1, **nil))
+ assert_equal([[], {}], skws(*nil, **nil))
+
+ assert_equal({}, {**nil})
+ assert_equal({a: 1}, {a: 1, **nil})
+ assert_equal({a: 1}, {**nil, a: 1})
+ end
+
def test_lambda
f = ->(str: "foo", num: 424242) { [str, num] }
assert_equal(["foo", 424242], f[])
@@ -190,27 +236,74 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal(["bar", 111111], f[str: "bar", num: 111111])
end
+ def test_unset_hash_flag
+ bug18625 = "[ruby-core: 107847]"
+ singleton_class.class_eval do
+ ruby2_keywords def foo(*args)
+ args
+ end
+
+ def single(arg)
+ arg
+ end
+
+ def splat(*args)
+ args.last
+ end
+
+ def kwargs(**kw)
+ kw
+ end
+ end
+
+ h = { a: 1 }
+ args = foo(**h)
+ marked = args.last
+ assert_equal(true, Hash.ruby2_keywords_hash?(marked))
+
+ after_usage = single(*args)
+ assert_equal(h, after_usage)
+ assert_same(marked, args.last)
+ assert_not_same(marked, after_usage)
+ assert_equal(false, Hash.ruby2_keywords_hash?(after_usage))
+
+ after_usage = splat(*args)
+ assert_equal(h, after_usage)
+ assert_same(marked, args.last)
+ assert_not_same(marked, after_usage, bug18625)
+ assert_equal(false, Hash.ruby2_keywords_hash?(after_usage), bug18625)
+
+ after_usage = kwargs(*args)
+ assert_equal(h, after_usage)
+ assert_same(marked, args.last)
+ assert_not_same(marked, after_usage, bug18625)
+ assert_not_same(marked, after_usage)
+ assert_equal(false, Hash.ruby2_keywords_hash?(after_usage))
+
+ assert_equal(true, Hash.ruby2_keywords_hash?(marked))
+ end
+
+ def assert_equal_not_same(kw, res)
+ assert_instance_of(Hash, res)
+ assert_equal(kw, res)
+ assert_not_same(kw, res)
+ end
+
def test_keyword_splat_new
kw = {}
h = {a: 1}
- def self.assert_equal_not_same(kw, res)
- assert_instance_of(Hash, res)
- assert_equal(kw, res)
- assert_not_same(kw, res)
- end
-
- def self.y(**kw) kw end
- m = method(:y)
- assert_equal(false, y(**{}).frozen?)
- assert_equal_not_same(kw, y(**kw))
- assert_equal_not_same(h, y(**h))
- assert_equal(false, send(:y, **{}).frozen?)
- assert_equal_not_same(kw, send(:y, **kw))
- assert_equal_not_same(h, send(:y, **h))
- assert_equal(false, public_send(:y, **{}).frozen?)
- assert_equal_not_same(kw, public_send(:y, **kw))
- assert_equal_not_same(h, public_send(:y, **h))
+ def self.yo(**kw) kw end
+ m = method(:yo)
+ assert_equal(false, yo(**{}).frozen?)
+ assert_equal_not_same(kw, yo(**kw))
+ assert_equal_not_same(h, yo(**h))
+ assert_equal(false, send(:yo, **{}).frozen?)
+ assert_equal_not_same(kw, send(:yo, **kw))
+ assert_equal_not_same(h, send(:yo, **h))
+ assert_equal(false, public_send(:yo, **{}).frozen?)
+ assert_equal_not_same(kw, public_send(:yo, **kw))
+ assert_equal_not_same(h, public_send(:yo, **h))
assert_equal(false, m.(**{}).frozen?)
assert_equal_not_same(kw, m.(**kw))
assert_equal_not_same(h, m.(**h))
@@ -219,25 +312,25 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal_not_same(h, m.send(:call, **h))
m = method(:send)
- assert_equal(false, m.(:y, **{}).frozen?)
- assert_equal_not_same(kw, m.(:y, **kw))
- assert_equal_not_same(h, m.(:y, **h))
- assert_equal(false, m.send(:call, :y, **{}).frozen?)
- assert_equal_not_same(kw, m.send(:call, :y, **kw))
- assert_equal_not_same(h, m.send(:call, :y, **h))
-
- singleton_class.send(:remove_method, :y)
- define_singleton_method(:y) { |**kw| kw }
- m = method(:y)
- assert_equal(false, y(**{}).frozen?)
- assert_equal_not_same(kw, y(**kw))
- assert_equal_not_same(h, y(**h))
- assert_equal(false, send(:y, **{}).frozen?)
- assert_equal_not_same(kw, send(:y, **kw))
- assert_equal_not_same(h, send(:y, **h))
- assert_equal(false, public_send(:y, **{}).frozen?)
- assert_equal_not_same(kw, public_send(:y, **kw))
- assert_equal_not_same(h, public_send(:y, **h))
+ assert_equal(false, m.(:yo, **{}).frozen?)
+ assert_equal_not_same(kw, m.(:yo, **kw))
+ assert_equal_not_same(h, m.(:yo, **h))
+ assert_equal(false, m.send(:call, :yo, **{}).frozen?)
+ assert_equal_not_same(kw, m.send(:call, :yo, **kw))
+ assert_equal_not_same(h, m.send(:call, :yo, **h))
+
+ singleton_class.send(:remove_method, :yo)
+ define_singleton_method(:yo) { |**kw| kw }
+ m = method(:yo)
+ assert_equal(false, yo(**{}).frozen?)
+ assert_equal_not_same(kw, yo(**kw))
+ assert_equal_not_same(h, yo(**h))
+ assert_equal(false, send(:yo, **{}).frozen?)
+ assert_equal_not_same(kw, send(:yo, **kw))
+ assert_equal_not_same(h, send(:yo, **h))
+ assert_equal(false, public_send(:yo, **{}).frozen?)
+ assert_equal_not_same(kw, public_send(:yo, **kw))
+ assert_equal_not_same(h, public_send(:yo, **h))
assert_equal(false, m.(**{}).frozen?)
assert_equal_not_same(kw, m.(**kw))
assert_equal_not_same(h, m.(**h))
@@ -245,17 +338,17 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal_not_same(kw, m.send(:call, **kw))
assert_equal_not_same(h, m.send(:call, **h))
- y = lambda { |**kw| kw }
- m = y.method(:call)
- assert_equal(false, y.(**{}).frozen?)
- assert_equal_not_same(kw, y.(**kw))
- assert_equal_not_same(h, y.(**h))
- assert_equal(false, y.send(:call, **{}).frozen?)
- assert_equal_not_same(kw, y.send(:call, **kw))
- assert_equal_not_same(h, y.send(:call, **h))
- assert_equal(false, y.public_send(:call, **{}).frozen?)
- assert_equal_not_same(kw, y.public_send(:call, **kw))
- assert_equal_not_same(h, y.public_send(:call, **h))
+ yo = lambda { |**kw| kw }
+ m = yo.method(:call)
+ assert_equal(false, yo.(**{}).frozen?)
+ assert_equal_not_same(kw, yo.(**kw))
+ assert_equal_not_same(h, yo.(**h))
+ assert_equal(false, yo.send(:call, **{}).frozen?)
+ assert_equal_not_same(kw, yo.send(:call, **kw))
+ assert_equal_not_same(h, yo.send(:call, **h))
+ assert_equal(false, yo.public_send(:call, **{}).frozen?)
+ assert_equal_not_same(kw, yo.public_send(:call, **kw))
+ assert_equal_not_same(h, yo.public_send(:call, **h))
assert_equal(false, m.(**{}).frozen?)
assert_equal_not_same(kw, m.(**kw))
assert_equal_not_same(h, m.(**h))
@@ -263,17 +356,17 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal_not_same(kw, m.send(:call, **kw))
assert_equal_not_same(h, m.send(:call, **h))
- y = :y.to_proc
- m = y.method(:call)
- assert_equal(false, y.(self, **{}).frozen?)
- assert_equal_not_same(kw, y.(self, **kw))
- assert_equal_not_same(h, y.(self, **h))
- assert_equal(false, y.send(:call, self, **{}).frozen?)
- assert_equal_not_same(kw, y.send(:call, self, **kw))
- assert_equal_not_same(h, y.send(:call, self, **h))
- assert_equal(false, y.public_send(:call, self, **{}).frozen?)
- assert_equal_not_same(kw, y.public_send(:call, self, **kw))
- assert_equal_not_same(h, y.public_send(:call, self, **h))
+ yo = :yo.to_proc
+ m = yo.method(:call)
+ assert_equal(false, yo.(self, **{}).frozen?)
+ assert_equal_not_same(kw, yo.(self, **kw))
+ assert_equal_not_same(h, yo.(self, **h))
+ assert_equal(false, yo.send(:call, self, **{}).frozen?)
+ assert_equal_not_same(kw, yo.send(:call, self, **kw))
+ assert_equal_not_same(h, yo.send(:call, self, **h))
+ assert_equal(false, yo.public_send(:call, self, **{}).frozen?)
+ assert_equal_not_same(kw, yo.public_send(:call, self, **kw))
+ assert_equal_not_same(h, yo.public_send(:call, self, **h))
assert_equal(false, m.(self, **{}).frozen?)
assert_equal_not_same(kw, m.(self, **kw))
assert_equal_not_same(h, m.(self, **h))
@@ -282,20 +375,20 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal_not_same(h, m.send(:call, self, **h))
c = Class.new do
- def y(**kw) kw end
+ def yo(**kw) kw end
end
o = c.new
- def o.y(**kw) super end
- m = o.method(:y)
- assert_equal(false, o.y(**{}).frozen?)
- assert_equal_not_same(kw, o.y(**kw))
- assert_equal_not_same(h, o.y(**h))
- assert_equal(false, o.send(:y, **{}).frozen?)
- assert_equal_not_same(kw, o.send(:y, **kw))
- assert_equal_not_same(h, o.send(:y, **h))
- assert_equal(false, o.public_send(:y, **{}).frozen?)
- assert_equal_not_same(kw, o.public_send(:y, **kw))
- assert_equal_not_same(h, o.public_send(:y, **h))
+ def o.yo(**kw) super end
+ m = o.method(:yo)
+ assert_equal(false, o.yo(**{}).frozen?)
+ assert_equal_not_same(kw, o.yo(**kw))
+ assert_equal_not_same(h, o.yo(**h))
+ assert_equal(false, o.send(:yo, **{}).frozen?)
+ assert_equal_not_same(kw, o.send(:yo, **kw))
+ assert_equal_not_same(h, o.send(:yo, **h))
+ assert_equal(false, o.public_send(:yo, **{}).frozen?)
+ assert_equal_not_same(kw, o.public_send(:yo, **kw))
+ assert_equal_not_same(h, o.public_send(:yo, **h))
assert_equal(false, m.(**{}).frozen?)
assert_equal_not_same(kw, m.(**kw))
assert_equal_not_same(h, m.(**h))
@@ -303,17 +396,17 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal_not_same(kw, m.send(:call, **kw))
assert_equal_not_same(h, m.send(:call, **h))
- o.singleton_class.send(:remove_method, :y)
- def o.y(**kw) super(**kw) end
- assert_equal(false, o.y(**{}).frozen?)
- assert_equal_not_same(kw, o.y(**kw))
- assert_equal_not_same(h, o.y(**h))
- assert_equal(false, o.send(:y, **{}).frozen?)
- assert_equal_not_same(kw, o.send(:y, **kw))
- assert_equal_not_same(h, o.send(:y, **h))
- assert_equal(false, o.public_send(:y, **{}).frozen?)
- assert_equal_not_same(kw, o.public_send(:y, **kw))
- assert_equal_not_same(h, o.public_send(:y, **h))
+ o.singleton_class.send(:remove_method, :yo)
+ def o.yo(**kw) super(**kw) end
+ assert_equal(false, o.yo(**{}).frozen?)
+ assert_equal_not_same(kw, o.yo(**kw))
+ assert_equal_not_same(h, o.yo(**h))
+ assert_equal(false, o.send(:yo, **{}).frozen?)
+ assert_equal_not_same(kw, o.send(:yo, **kw))
+ assert_equal_not_same(h, o.send(:yo, **h))
+ assert_equal(false, o.public_send(:yo, **{}).frozen?)
+ assert_equal_not_same(kw, o.public_send(:yo, **kw))
+ assert_equal_not_same(h, o.public_send(:yo, **h))
assert_equal(false, m.(**{}).frozen?)
assert_equal_not_same(kw, m.(**kw))
assert_equal_not_same(h, m.(**h))
@@ -325,17 +418,17 @@ class TestKeywordArguments < Test::Unit::TestCase
def method_missing(_, **kw) kw end
end
o = c.new
- def o.y(**kw) super end
- m = o.method(:y)
- assert_equal(false, o.y(**{}).frozen?)
- assert_equal_not_same(kw, o.y(**kw))
- assert_equal_not_same(h, o.y(**h))
- assert_equal(false, o.send(:y, **{}).frozen?)
- assert_equal_not_same(kw, o.send(:y, **kw))
- assert_equal_not_same(h, o.send(:y, **h))
- assert_equal(false, o.public_send(:y, **{}).frozen?)
- assert_equal_not_same(kw, o.public_send(:y, **kw))
- assert_equal_not_same(h, o.public_send(:y, **h))
+ def o.yo(**kw) super end
+ m = o.method(:yo)
+ assert_equal(false, o.yo(**{}).frozen?)
+ assert_equal_not_same(kw, o.yo(**kw))
+ assert_equal_not_same(h, o.yo(**h))
+ assert_equal(false, o.send(:yo, **{}).frozen?)
+ assert_equal_not_same(kw, o.send(:yo, **kw))
+ assert_equal_not_same(h, o.send(:yo, **h))
+ assert_equal(false, o.public_send(:yo, **{}).frozen?)
+ assert_equal_not_same(kw, o.public_send(:yo, **kw))
+ assert_equal_not_same(h, o.public_send(:yo, **h))
assert_equal(false, m.(**{}).frozen?)
assert_equal_not_same(kw, m.(**kw))
assert_equal_not_same(h, m.(**h))
@@ -343,17 +436,17 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal_not_same(kw, m.send(:call, **kw))
assert_equal_not_same(h, m.send(:call, **h))
- o.singleton_class.send(:remove_method, :y)
- def o.y(**kw) super(**kw) end
- assert_equal(false, o.y(**{}).frozen?)
- assert_equal_not_same(kw, o.y(**kw))
- assert_equal_not_same(h, o.y(**h))
- assert_equal(false, o.send(:y, **{}).frozen?)
- assert_equal_not_same(kw, o.send(:y, **kw))
- assert_equal_not_same(h, o.send(:y, **h))
- assert_equal(false, o.public_send(:y, **{}).frozen?)
- assert_equal_not_same(kw, o.public_send(:y, **kw))
- assert_equal_not_same(h, o.public_send(:y, **h))
+ o.singleton_class.send(:remove_method, :yo)
+ def o.yo(**kw) super(**kw) end
+ assert_equal(false, o.yo(**{}).frozen?)
+ assert_equal_not_same(kw, o.yo(**kw))
+ assert_equal_not_same(h, o.yo(**h))
+ assert_equal(false, o.send(:yo, **{}).frozen?)
+ assert_equal_not_same(kw, o.send(:yo, **kw))
+ assert_equal_not_same(h, o.send(:yo, **h))
+ assert_equal(false, o.public_send(:yo, **{}).frozen?)
+ assert_equal_not_same(kw, o.public_send(:yo, **kw))
+ assert_equal_not_same(h, o.public_send(:yo, **h))
assert_equal(false, m.(**{}).frozen?)
assert_equal_not_same(kw, m.(**kw))
assert_equal_not_same(h, m.(**h))
@@ -389,17 +482,41 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal_not_same(h, m.(**h))
assert_equal_not_same(h, m.send(:call, **h))
- singleton_class.send(:remove_method, :y)
+ singleton_class.send(:remove_method, :yo)
def self.method_missing(_, **kw) kw end
- assert_equal(false, y(**{}).frozen?)
- assert_equal_not_same(kw, y(**kw))
- assert_equal_not_same(h, y(**h))
- assert_equal(false, send(:y, **{}).frozen?)
- assert_equal_not_same(kw, send(:y, **kw))
- assert_equal_not_same(h, send(:y, **h))
- assert_equal(false, public_send(:y, **{}).frozen?)
- assert_equal_not_same(kw, public_send(:y, **kw))
- assert_equal_not_same(h, public_send(:y, **h))
+ assert_equal(false, yo(**{}).frozen?)
+ assert_equal_not_same(kw, yo(**kw))
+ assert_equal_not_same(h, yo(**h))
+ assert_equal(false, send(:yo, **{}).frozen?)
+ assert_equal_not_same(kw, send(:yo, **kw))
+ assert_equal_not_same(h, send(:yo, **h))
+ assert_equal(false, public_send(:yo, **{}).frozen?)
+ assert_equal_not_same(kw, public_send(:yo, **kw))
+ assert_equal_not_same(h, public_send(:yo, **h))
+
+ def self.yo(*a, **kw) = kw
+ assert_equal_not_same kw, yo(**kw)
+ assert_equal_not_same kw, yo(**kw, **kw)
+
+ singleton_class.send(:remove_method, :yo)
+ def self.yo(opts) = opts
+ assert_equal_not_same h, yo(*[], **h)
+ a = []
+ assert_equal_not_same h, yo(*a, **h)
+ end
+
+ def test_keyword_splat_to_non_keyword_method
+ h = {a: 1}.freeze
+
+ def self.yo(kw) kw end
+ assert_equal_not_same(h, yo(**h))
+ assert_equal_not_same(h, method(:yo).(**h))
+ assert_equal_not_same(h, :yo.to_proc.(self, **h))
+
+ def self.yoa(*kw) kw[0] end
+ assert_equal_not_same(h, yoa(**h))
+ assert_equal_not_same(h, method(:yoa).(**h))
+ assert_equal_not_same(h, :yoa.to_proc.(self, **h))
end
def test_regular_kwsplat
@@ -2700,6 +2817,51 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_raise(FrozenError) { c.send(:ruby2_keywords, :baz) }
end
+ def test_anon_splat_ruby2_keywords
+ singleton_class.class_exec do
+ def bar(*a, **kw)
+ [a, kw]
+ end
+
+ ruby2_keywords def bar_anon(*)
+ bar(*)
+ end
+ end
+
+ a = [1, 2]
+ kw = {a: 1}
+ assert_equal([[1, 2], {a: 1}], bar_anon(*a, **kw))
+ assert_equal([1, 2], a)
+ assert_equal({a: 1}, kw)
+ end
+
+ def test_anon_splat_ruby2_keywords_bug_20388
+ extend(Module.new{def process(action, ...) 1 end})
+ extend(Module.new do
+ def process(action, *args)
+ args.freeze
+ super
+ end
+ ruby2_keywords :process
+ end)
+
+ assert_equal(1, process(:foo, bar: :baz))
+ end
+
+ def test_ruby2_keywords_bug_20679
+ c = Class.new do
+ def self.get(_, _, h, &block)
+ h[1]
+ end
+
+ ruby2_keywords def get(*args, &block)
+ self.class.get(*args, &block)
+ end
+ end
+
+ assert_equal 2, c.new.get(true, {}, 1 => 2)
+ end
+
def test_top_ruby2_keywords
assert_in_out_err([], <<-INPUT, ["[1, 2, 3]", "{:k=>1}"], [])
def bar(*a, **kw)
@@ -3538,7 +3700,7 @@ class TestKeywordArguments < Test::Unit::TestCase
assert_equal(splat_expect, pr.call(a), bug8463)
pr = proc {|a, **opt| next a, opt}
- assert_equal(splat_expect.values_at(0, -1), pr.call(splat_expect), bug8463)
+ assert_equal([splat_expect, {}], pr.call(splat_expect), bug8463)
end
def req_plus_keyword(x, **h)
@@ -3875,6 +4037,20 @@ class TestKeywordArguments < Test::Unit::TestCase
}, bug8964
end
+ def test_large_kwsplat_to_method_taking_kw_and_kwsplat
+ assert_separately(['-'], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ n = 100000
+ x = Fiber.new do
+ h = {kw: 2}
+ n.times{|i| h[i.to_s.to_sym] = i}
+ def self.f(kw: 1, **kws) kws.size end
+ f(**h)
+ end.resume
+ assert_equal(n, x)
+ end;
+ end
+
def test_dynamic_symbol_keyword
bug10266 = '[ruby-dev:48564] [Bug #10266]'
assert_separately(['-', bug10266], "#{<<~"begin;"}\n#{<<~'end;'}")
@@ -4361,6 +4537,24 @@ class TestKeywordArgumentsSymProcRefinements < Test::Unit::TestCase
assert_equal({one: 1, two: 2}, f.call(one:, two:))
end
+ def m_bug20570(*a, **nil)
+ a
+ end
+
+ def test_splat_arg_with_prohibited_keyword
+ assert_equal([], m_bug20570(*[]))
+ assert_equal([1], m_bug20570(*[1]))
+ assert_equal([1, 2], m_bug20570(*[1, 2]))
+ h = nil
+ assert_equal([], m_bug20570(*[], **h))
+ assert_equal([1], m_bug20570(*[1], **h))
+ assert_equal([1, 2], m_bug20570(*[1, 2], **h))
+
+ assert_equal([], m_bug20570(*[], **nil))
+ assert_equal([1], m_bug20570(*[1], **nil))
+ assert_equal([1, 2], m_bug20570(*[1, 2], **nil))
+ end
+
private def one
1
end
diff --git a/test/ruby/test_lambda.rb b/test/ruby/test_lambda.rb
index 9949fab8c7..7738034240 100644
--- a/test/ruby/test_lambda.rb
+++ b/test/ruby/test_lambda.rb
@@ -177,32 +177,6 @@ class TestLambdaParameters < Test::Unit::TestCase
RUBY
end
- def pass_along(&block)
- lambda(&block)
- end
-
- def pass_along2(&block)
- pass_along(&block)
- end
-
- def test_create_non_lambda_for_proc_one_level
- prev_warning, Warning[:deprecated] = Warning[:deprecated], false
- f = pass_along {}
- refute_predicate(f, :lambda?, '[Bug #15620]')
- assert_nothing_raised(ArgumentError) { f.call(:extra_arg) }
- ensure
- Warning[:deprecated] = prev_warning
- end
-
- def test_create_non_lambda_for_proc_two_levels
- prev_warning, Warning[:deprecated] = Warning[:deprecated], false
- f = pass_along2 {}
- refute_predicate(f, :lambda?, '[Bug #15620]')
- assert_nothing_raised(ArgumentError) { f.call(:extra_arg) }
- ensure
- Warning[:deprecated] = prev_warning
- end
-
def test_instance_exec
bug12568 = '[ruby-core:76300] [Bug #12568]'
assert_nothing_raised(ArgumentError, bug12568) do
diff --git a/test/ruby/test_lazy_enumerator.rb b/test/ruby/test_lazy_enumerator.rb
index 2116d0ee31..4dddbab50c 100644
--- a/test/ruby/test_lazy_enumerator.rb
+++ b/test/ruby/test_lazy_enumerator.rb
@@ -282,6 +282,11 @@ class TestLazyEnumerator < Test::Unit::TestCase
assert_equal(3, a.current)
end
+ def test_zip_map_lambda_bug_19569
+ ary = [1, 2, 3].to_enum.lazy.zip([:a, :b, :c]).map(&:last).to_a
+ assert_equal([:a, :b, :c], ary)
+ end
+
def test_take
a = Step.new(1..10)
assert_equal(1, a.take(5).first)
@@ -295,6 +300,26 @@ class TestLazyEnumerator < Test::Unit::TestCase
assert_equal(nil, a.current)
end
+ def test_take_0_bug_18971
+ def (bomb = Object.new.extend(Enumerable)).each
+ raise
+ end
+ [2..10, bomb].each do |e|
+ assert_equal([], e.lazy.take(0).map(&:itself).to_a)
+ assert_equal([], e.lazy.take(0).select(&:even?).to_a)
+ assert_equal([], e.lazy.take(0).select(&:odd?).to_a)
+ assert_equal([], e.lazy.take(0).reject(&:even?).to_a)
+ assert_equal([], e.lazy.take(0).reject(&:odd?).to_a)
+ assert_equal([], e.lazy.take(0).take(1).to_a)
+ assert_equal([], e.lazy.take(0).take(0).take(1).to_a)
+ assert_equal([], e.lazy.take(0).drop(0).to_a)
+ assert_equal([], e.lazy.take(0).find_all {|_| true}.to_a)
+ assert_equal([], e.lazy.take(0).zip((12..20)).to_a)
+ assert_equal([], e.lazy.take(0).uniq.to_a)
+ assert_equal([], e.lazy.take(0).sort.to_a)
+ end
+ end
+
def test_take_bad_arg
a = Step.new(1..10)
assert_raise(ArgumentError) { a.lazy.take(-1) }
@@ -464,6 +489,10 @@ EOS
assert_equal [1, 2, 3], enum.map { |x| x / 2 }
end
+ def test_lazy_zip_map_yield_arity_bug_20623
+ assert_equal([[1, 2]], [1].lazy.zip([2].lazy).map { |x| x }.force)
+ end
+
def test_lazy_to_enum
lazy = [1, 2, 3].lazy
def lazy.foo(*args)
diff --git a/test/ruby/test_literal.rb b/test/ruby/test_literal.rb
index 3a8ff7857f..1fdc6aa853 100644
--- a/test/ruby/test_literal.rb
+++ b/test/ruby/test_literal.rb
@@ -26,7 +26,7 @@ class TestRubyLiteral < Test::Unit::TestCase
assert_equal '5', 0b101.inspect
assert_instance_of Integer, 0b101
assert_raise(SyntaxError) { eval("0b") }
- assert_equal '123456789012345678901234567890', 123456789012345678901234567890.inspect
+ assert_equal '123456789012345678901234567890', 123456789012345678901234567890.to_s
assert_instance_of Integer, 123456789012345678901234567890
assert_instance_of Float, 1.3
assert_equal '2', eval("0x00+2").inspect
@@ -39,6 +39,8 @@ class TestRubyLiteral < Test::Unit::TestCase
end
def test_string
+ verbose_bak, $VERBOSE = $VERBOSE, nil # prevent syntax warnings
+
assert_instance_of String, ?a
assert_equal "a", ?a
assert_instance_of String, ?A
@@ -94,6 +96,9 @@ class TestRubyLiteral < Test::Unit::TestCase
assert_equal "ab", eval("?a 'b'")
assert_equal "a\nb", eval("<<A 'b'\na\nA")
+
+ ensure
+ $VERBOSE = verbose_bak
end
def test_dstring
@@ -142,6 +147,8 @@ class TestRubyLiteral < Test::Unit::TestCase
end
def test_frozen_string
+ default = eval("'test'").frozen?
+
all_assertions do |a|
a.for("false with indicator") do
str = eval("# -*- frozen-string-literal: false -*-\n""'foo'")
@@ -161,19 +168,19 @@ class TestRubyLiteral < Test::Unit::TestCase
end
a.for("false with preceding garbage") do
str = eval("# x frozen-string-literal: false\n""'foo'")
- assert_not_predicate(str, :frozen?)
+ assert_equal(default, str.frozen?)
end
a.for("true with preceding garbage") do
str = eval("# x frozen-string-literal: true\n""'foo'")
- assert_not_predicate(str, :frozen?)
+ assert_equal(default, str.frozen?)
end
a.for("false with succeeding garbage") do
str = eval("# frozen-string-literal: false x\n""'foo'")
- assert_not_predicate(str, :frozen?)
+ assert_equal(default, str.frozen?)
end
a.for("true with succeeding garbage") do
str = eval("# frozen-string-literal: true x\n""'foo'")
- assert_not_predicate(str, :frozen?)
+ assert_equal(default, str.frozen?)
end
end
end
@@ -184,6 +191,11 @@ class TestRubyLiteral < Test::Unit::TestCase
list.each { |str| assert_predicate str, :frozen? }
end
+ def test_string_in_hash_literal
+ hash = eval("# frozen-string-literal: false\n""{foo: 'foo'}")
+ assert_not_predicate(hash[:foo], :frozen?)
+ end
+
if defined?(RubyVM::InstructionSequence.compile_option) and
RubyVM::InstructionSequence.compile_option.key?(:debug_frozen_string_literal)
def test_debug_frozen_string
@@ -234,8 +246,9 @@ class TestRubyLiteral < Test::Unit::TestCase
def test_dregexp
assert_instance_of Regexp, /re#{'ge'}xp/
assert_equal(/regexp/, /re#{'ge'}xp/)
- bug3903 = '[ruby-core:32682]'
- assert_raise(SyntaxError, bug3903) {eval('/[#{"\x80"}]/')}
+
+ # [ruby-core:32682]
+ eval('/[#{"\x80"}]/')
end
def test_array
@@ -474,6 +487,17 @@ class TestRubyLiteral < Test::Unit::TestCase
assert_nil(h['c'])
assert_equal(nil, h.key('300'))
+ a = []
+ h = EnvUtil.suppress_warning do
+ eval <<~end
+ # This is a syntax that renders warning at very early stage.
+ # eval used to delay warning, to be suppressible by EnvUtil.
+ {"a" => a.push(100).last, "b" => a.push(200).last, "a" => a.push(300).last, "a" => a.push(400).last}
+ end
+ end
+ assert_equal({'a' => 400, 'b' => 200}, h)
+ assert_equal([100, 200, 300, 400], a)
+
assert_all_assertions_foreach(
"duplicated literal key",
':foo',
@@ -485,10 +509,11 @@ class TestRubyLiteral < Test::Unit::TestCase
'1.0i',
'1.72723e-77',
'//',
+ '__LINE__',
+ '__FILE__',
+ '__ENCODING__',
) do |key|
- assert_warning(/key #{Regexp.quote(eval(key).inspect)} is duplicated/) do
- eval("{#{key} => :bar, #{key} => :foo}")
- end
+ assert_warning(/key #{Regexp.quote(eval(key).inspect)} is duplicated/) { eval("{#{key} => :bar, #{key} => :foo}") }
end
end
@@ -571,6 +596,8 @@ class TestRubyLiteral < Test::Unit::TestCase
end
def test_integer
+ verbose_bak, $VERBOSE = $VERBOSE, nil # prevent syntax warnings
+
head = ['', '0x', '0o', '0b', '0d', '-', '+']
chars = ['0', '1', '_', '9', 'f']
head.each {|h|
@@ -600,9 +627,14 @@ class TestRubyLiteral < Test::Unit::TestCase
assert_syntax_error(h, /numeric literal without digits\Z/, "#{bug2407}: #{h.inspect}")
end
end
+
+ ensure
+ $VERBOSE = verbose_bak
end
def test_float
+ verbose_bak, $VERBOSE = $VERBOSE, nil # prevent syntax warnings
+
head = ['', '-', '+']
chars = ['0', '1', '_', '9', 'f', '.']
head.each {|h|
@@ -621,15 +653,27 @@ class TestRubyLiteral < Test::Unit::TestCase
end
begin
r2 = eval(s)
- rescue NameError, SyntaxError
+ rescue ArgumentError
+ # Debug log for a random failure: ArgumentError: SyntaxError#path changed
+ $stderr.puts "TestRubyLiteral#test_float failed: %p" % s
+ raise
+ rescue SyntaxError => e
+ r2 = :err
+ rescue NameError
r2 = :err
end
r2 = :err if Range === r2
- assert_equal(r1, r2, "Float(#{s.inspect}) != eval(#{s.inspect})")
+ s = s.inspect
+ mesg = "Float(#{s}) != eval(#{s})"
+ mesg << ":" << e.message if e
+ assert_equal(r1, r2, mesg)
}
}
}
assert_equal(100.0, 0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100e100)
+
+ ensure
+ $VERBOSE = verbose_bak
end
def test_symbol_list
diff --git a/test/ruby/test_m17n.rb b/test/ruby/test_m17n.rb
index 3f28d55ac1..93366ed02a 100644
--- a/test/ruby/test_m17n.rb
+++ b/test/ruby/test_m17n.rb
@@ -226,38 +226,16 @@ class TestM17N < Test::Unit::TestCase
end
end
- STR_WITHOUT_BOM = "\u3042".freeze
- STR_WITH_BOM = "\uFEFF\u3042".freeze
- bug8940 = '[ruby-core:59757] [Bug #8940]'
- bug9415 = '[ruby-dev:47895] [Bug #9415]'
- %w/UTF-16 UTF-32/.each do |enc|
- %w/BE LE/.each do |endian|
- bom = "\uFEFF".encode("#{enc}#{endian}").force_encoding(enc)
-
- define_method("test_utf_16_32_inspect(#{enc}#{endian})") do
- s = STR_WITHOUT_BOM.encode(enc + endian)
- # When a UTF-16/32 string doesn't have a BOM,
- # inspect as a dummy encoding string.
- assert_equal(s.dup.force_encoding("ISO-2022-JP").inspect,
- s.dup.force_encoding(enc).inspect)
- assert_normal_exit("#{bom.b.dump}.force_encoding('#{enc}').inspect", bug8940)
- end
-
- define_method("test_utf_16_32_codepoints(#{enc}#{endian})") do
- assert_equal([0xFEFF], bom.codepoints, bug9415)
- end
-
- define_method("test_utf_16_32_ord(#{enc}#{endian})") do
- assert_equal(0xFEFF, bom.ord, bug9415)
- end
-
- define_method("test_utf_16_32_inspect(#{enc}#{endian}-BOM)") do
- s = STR_WITH_BOM.encode(enc + endian)
- # When a UTF-16/32 string has a BOM,
- # inspect as a particular encoding string.
- assert_equal(s.inspect,
- s.dup.force_encoding(enc).inspect)
- end
+ def test_utf_dummy_are_like_regular_dummy_encodings
+ [Encoding::UTF_16, Encoding::UTF_32].each do |enc|
+ s = "\u3042".encode("UTF-32BE")
+ assert_equal(s.dup.force_encoding("ISO-2022-JP").inspect, s.dup.force_encoding(enc).inspect)
+ s = "\x00\x00\xFE\xFF"
+ assert_equal(s.dup.force_encoding("ISO-2022-JP").inspect, s.dup.force_encoding(enc).inspect)
+
+ assert_equal [0, 0, 254, 255], "\x00\x00\xFE\xFF".force_encoding(enc).codepoints
+ assert_equal 0, "\x00\x00\xFE\xFF".force_encoding(enc).ord
+ assert_equal 255, "\xFF\xFE\x00\x00".force_encoding(enc).ord
end
end
@@ -299,6 +277,9 @@ class TestM17N < Test::Unit::TestCase
orig_v, $VERBOSE = $VERBOSE, false
orig_int, Encoding.default_internal = Encoding.default_internal, nil
orig_ext = Encoding.default_external
+
+ omit "https://bugs.ruby-lang.org/issues/18338"
+
o = Object.new
Encoding.default_external = Encoding::UTF_16BE
@@ -889,10 +870,22 @@ class TestM17N < Test::Unit::TestCase
assert_raise(Encoding::CompatibilityError) {
"%s%s" % [s("\xc2\xa1"), e("\xc2\xa1")]
}
+
+ assert_equal("\u3042".encode('Windows-31J'), "%c" % "\u3042\u3044".encode('Windows-31J'))
end
def test_sprintf_p
Encoding.list.each do |e|
+ unless e.ascii_compatible?
+ format = e.dummy? ? "%p".force_encoding(e) : "%p".encode(e)
+ assert_raise(Encoding::CompatibilityError) do
+ sprintf(format, nil)
+ end
+ assert_raise(Encoding::CompatibilityError) do
+ format % nil
+ end
+ next
+ end
format = "%p".force_encoding(e)
['', 'a', "\xC2\xA1", "\x00"].each do |s|
s.force_encoding(e)
@@ -1097,7 +1090,23 @@ class TestM17N < Test::Unit::TestCase
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(Encoding::CompatibilityError){s.rindex(a("\xb1\xa3"))}
+
+ a_with_e = /EUC-JP and BINARY \(ASCII-8BIT\)/
+ assert_raise_with_message(Encoding::CompatibilityError, a_with_e) do
+ s.index(a("\xb1\xa3"))
+ end
+ assert_raise_with_message(Encoding::CompatibilityError, a_with_e) do
+ s.rindex(a("\xb1\xa3"))
+ end
+
+ a_with_e = /BINARY \(ASCII-8BIT\) regexp with EUC-JP string/
+ assert_raise_with_message(Encoding::CompatibilityError, a_with_e) do
+ s.index(Regexp.new(a("\xb1\xa3")))
+ end
+ assert_raise_with_message(Encoding::CompatibilityError, a_with_e) do
+ s.rindex(Regexp.new(a("\xb1\xa3")))
+ end
+
bug11488 = '[ruby-core:70592] [Bug #11488]'
each_encoding("abcdef", "def") do |str, substr|
assert_equal(3, str.index(substr), bug11488)
@@ -1331,8 +1340,8 @@ class TestM17N < Test::Unit::TestCase
env_encoding = Encoding.find("locale")
end
ENV.each {|k, v|
- assert_equal(env_encoding, k.encoding, k)
- assert_equal(env_encoding, v.encoding, v)
+ assert_equal(env_encoding, k.encoding, proc {"key(#{k.encoding})=#{k.dump}"})
+ assert_equal(env_encoding, v.encoding, proc {"key(#{k.encoding})=#{k.dump}\n" "value(#{v.encoding})=#{v.dump}"})
}
end
@@ -1430,20 +1439,20 @@ class TestM17N < Test::Unit::TestCase
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('/#{%q"\x80"}/', Encoding::US_ASCII)
+ assert_regexp_usascii_literal('/#{"\x80"}/', Encoding::ASCII_8BIT)
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('/a#{"\x80"}/', Encoding::ASCII_8BIT)
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('/\x80#{"\x80"}/', Encoding::ASCII_8BIT)
assert_regexp_usascii_literal('/\u1234/', Encoding::UTF_8)
assert_regexp_usascii_literal('/\u1234#{ }/', Encoding::UTF_8)
@@ -1712,6 +1721,23 @@ class TestM17N < Test::Unit::TestCase
assert_equal(e("[\"\xB4\xC1\xBB\xFA\"]"), s, bug11787)
end
+ def test_encoding_names_of_default_internal
+ # [Bug #20595] [Bug #20598]
+ [
+ "default_internal.names",
+ "name_list",
+ "aliases.keys"
+ ].each do |method|
+ assert_separately(%w(-W0), <<~RUBY)
+ exp_name = "int" + "ernal"
+ Encoding.default_internal = Encoding::ASCII_8BIT
+ name = Encoding.#{method}.find { |x| x == exp_name }
+ Encoding.default_internal = nil
+ assert_equal exp_name, name, "Encoding.#{method} [Bug #20595] [Bug #20598]"
+ RUBY
+ end
+ end
+
def test_greek_capital_gap
bug12204 = '[ruby-core:74478] [Bug #12204] GREEK CAPITAL RHO and SIGMA'
assert_equal("\u03A3", "\u03A1".succ, bug12204)
diff --git a/test/ruby/test_marshal.rb b/test/ruby/test_marshal.rb
index f7f273af42..bcd8892f23 100644
--- a/test/ruby/test_marshal.rb
+++ b/test/ruby/test_marshal.rb
@@ -1,6 +1,5 @@
# frozen_string_literal: false
require 'test/unit'
-require 'tempfile'
require_relative 'marshaltestlib'
class TestMarshal < Test::Unit::TestCase
@@ -33,7 +32,7 @@ class TestMarshal < Test::Unit::TestCase
end
def test_marshal
- a = [1, 2, 3, [4,5,"foo"], {1=>"bar"}, 2.5, fact(30)]
+ a = [1, 2, 3, 2**32, 2**64, [4,5,"foo"], {1=>"bar"}, 2.5, fact(30)]
assert_equal a, Marshal.load(Marshal.dump(a))
[[1,2,3,4], [81, 2, 118, 3146]].each { |w,x,y,z|
@@ -47,6 +46,26 @@ class TestMarshal < Test::Unit::TestCase
}
end
+ def test_marshal_integers
+ a = []
+ [-2, -1, 0, 1, 2].each do |i|
+ 0.upto(65).map do |exp|
+ a << 2**exp + i
+ end
+ end
+ assert_equal a, Marshal.load(Marshal.dump(a))
+
+ a = [2**32, []]*2
+ assert_equal a, Marshal.load(Marshal.dump(a))
+
+ a = [2**32, 2**32, []]*2
+ assert_equal a, Marshal.load(Marshal.dump(a))
+ end
+
+ def test_marshal_small_bignum_backref
+ assert_equal [2**32, 2**32], Marshal.load("\x04\b[\al+\b\x00\x00\x00\x00\x01\x00@\x06")
+ end
+
StrClone = String.clone
def test_marshal_cloned_class
assert_instance_of(StrClone, Marshal.load(Marshal.dump(StrClone.new("abc"))))
@@ -72,6 +91,14 @@ class TestMarshal < Test::Unit::TestCase
TestMarshal.instance_eval { remove_const :StructInvalidMembers }
end
+ def test_load_range_as_struct
+ assert_raise(TypeError, 'GH-6832') do
+ # Can be obtained with:
+ # $ ruby -e 'Range = Struct.new(:a, :b, :c); p Marshal.dump(Range.new(nil, nil, nil))'
+ Marshal.load("\x04\bS:\nRange\b:\x06a0:\x06b0:\x06c0")
+ end
+ end
+
class C
def initialize(str)
@str = str
@@ -286,11 +313,10 @@ class TestMarshal < Test::Unit::TestCase
assert_equal(c, Marshal.load(Marshal.dump(c)), bug2109)
assert_nothing_raised(ArgumentError, '[ruby-dev:40386]') do
- re = Tempfile.create("marshal_regexp") do |f|
- f.binmode.write("\x04\bI/\x00\x00\x06:\rencoding\"\rUS-ASCII")
- f.rewind
- re2 = Marshal.load(f)
- re2
+ re = IO.pipe do |r, w|
+ w.write("\x04\bI/\x00\x00\x06:\rencoding\"\rUS-ASCII")
+ # Marshal.load would not overread and block
+ Marshal.load(r)
end
assert_equal(//, re)
end
@@ -544,13 +570,19 @@ class TestMarshal < Test::Unit::TestCase
def test_class_ivar
assert_raise(TypeError) {Marshal.load("\x04\x08Ic\x1bTestMarshal::TestClass\x06:\x0e@ivar_bug\"\x08bug")}
assert_raise(TypeError) {Marshal.load("\x04\x08IM\x1bTestMarshal::TestClass\x06:\x0e@ivar_bug\"\x08bug")}
- assert_not_operator(TestClass, :instance_variable_defined?, :@bug)
+ assert_not_operator(TestClass, :instance_variable_defined?, :@ivar_bug)
+
+ assert_raise(TypeError) {Marshal.load("\x04\x08[\x07c\x1bTestMarshal::TestClassI@\x06\x06:\x0e@ivar_bug\"\x08bug")}
+ assert_not_operator(TestClass, :instance_variable_defined?, :@ivar_bug)
end
def test_module_ivar
assert_raise(TypeError) {Marshal.load("\x04\x08Im\x1cTestMarshal::TestModule\x06:\x0e@ivar_bug\"\x08bug")}
assert_raise(TypeError) {Marshal.load("\x04\x08IM\x1cTestMarshal::TestModule\x06:\x0e@ivar_bug\"\x08bug")}
- assert_not_operator(TestModule, :instance_variable_defined?, :@bug)
+ assert_not_operator(TestModule, :instance_variable_defined?, :@ivar_bug)
+
+ assert_raise(TypeError) {Marshal.load("\x04\x08[\x07m\x1cTestMarshal::TestModuleI@\x06\x06:\x0e@ivar_bug\"\x08bug")}
+ assert_not_operator(TestModule, :instance_variable_defined?, :@ivar_bug)
end
class TestForRespondToFalse
@@ -583,6 +615,8 @@ class TestMarshal < Test::Unit::TestCase
def test_continuation
EnvUtil.suppress_warning {require "continuation"}
+ omit 'requires callcc support' unless respond_to?(:callcc)
+
c = Bug9523.new
assert_raise_with_message(RuntimeError, /Marshal\.dump reentered at marshal_dump/) do
Marshal.dump(c)
@@ -858,4 +892,73 @@ class TestMarshal < Test::Unit::TestCase
assert_nil(e2.backtrace_locations) # temporal
end
end
+
+ class TestMarshalFreezeProc < Test::Unit::TestCase
+ include MarshalTestLib
+
+ def encode(o)
+ Marshal.dump(o)
+ end
+
+ def decode(s)
+ Marshal.load(s, :freeze.to_proc)
+ end
+ end
+
+ def _test_hash_compared_by_identity(h)
+ h.compare_by_identity
+ h["a" + "0"] = 1
+ h["a" + "0"] = 2
+ h = Marshal.load(Marshal.dump(h))
+ assert_predicate(h, :compare_by_identity?)
+ a = h.to_a
+ assert_equal([["a0", 1], ["a0", 2]], a.sort)
+ assert_not_same(a[1][0], a[0][0])
+ end
+
+ def test_hash_compared_by_identity
+ _test_hash_compared_by_identity(Hash.new)
+ end
+
+ def test_hash_default_compared_by_identity
+ _test_hash_compared_by_identity(Hash.new(true))
+ end
+
+ class TestMarshalFreeze < Test::Unit::TestCase
+ include MarshalTestLib
+
+ def encode(o)
+ Marshal.dump(o)
+ end
+
+ def decode(s)
+ Marshal.load(s, freeze: true)
+ end
+
+ def test_return_objects_are_frozen
+ source = ["foo", {}, /foo/, 1..2]
+ objects = decode(encode(source))
+ assert_equal source, objects
+ assert_predicate objects, :frozen?
+ objects.each do |obj|
+ assert_predicate obj, :frozen?
+ end
+ end
+
+ def test_proc_returned_object_are_not_frozen
+ source = ["foo", {}, /foo/, 1..2]
+ objects = Marshal.load(encode(source), ->(o) { o.dup }, freeze: true)
+ assert_equal source, objects
+ refute_predicate objects, :frozen?
+ objects.each do |obj|
+ refute_predicate obj, :frozen?
+ end
+ end
+
+ def test_modules_and_classes_are_not_frozen
+ _objects = Marshal.load(encode([Object, Kernel]), freeze: true)
+ refute_predicate Object, :frozen?
+ refute_predicate Kernel, :frozen?
+ end
+ end
end
diff --git a/test/ruby/test_math.rb b/test/ruby/test_math.rb
index 73f44c6ae3..6e67099c6b 100644
--- a/test/ruby/test_math.rb
+++ b/test/ruby/test_math.rb
@@ -5,6 +5,7 @@ class TestMath < Test::Unit::TestCase
def assert_infinity(a, *rest)
rest = ["not infinity: #{a.inspect}"] if rest.empty?
assert_predicate(a, :infinite?, *rest)
+ assert_predicate(a, :positive?, *rest)
end
def assert_nan(a, *rest)
@@ -165,6 +166,9 @@ class TestMath < Test::Unit::TestCase
assert_nothing_raised { assert_nan(Math.log(0.0, 0.0)) }
assert_nothing_raised { assert_nan(Math.log(Float::NAN)) }
assert_nothing_raised { assert_nan(Math.log(1.0, Float::NAN)) }
+ assert_nothing_raised { assert_infinity(-Math.log(0)) }
+ assert_nothing_raised { assert_infinity(-Math.log(0, 2)) }
+ check(307.95368556425274, Math.log(2**1023, 10))
end
def test_log2
@@ -179,6 +183,7 @@ class TestMath < Test::Unit::TestCase
assert_raise_with_message(Math::DomainError, /\blog2\b/) { Math.log2(-1.0) }
assert_raise_with_message(Math::DomainError, /\blog2\b/) { Math.log2(-Float::EPSILON) }
assert_nothing_raised { assert_nan(Math.log2(Float::NAN)) }
+ assert_nothing_raised { assert_infinity(-Math.log2(0)) }
end
def test_log10
@@ -193,6 +198,7 @@ class TestMath < Test::Unit::TestCase
assert_raise_with_message(Math::DomainError, /\blog10\b/) { Math.log10(-1.0) }
assert_raise_with_message(Math::DomainError, /\blog10\b/) { Math.log10(-Float::EPSILON) }
assert_nothing_raised { assert_nan(Math.log10(Float::NAN)) }
+ assert_nothing_raised { assert_infinity(-Math.log10(0)) }
end
def test_sqrt
@@ -277,8 +283,7 @@ class TestMath < Test::Unit::TestCase
assert_raise_with_message(Math::DomainError, /\bgamma\b/) { Math.gamma(-1.0) }
x = Math.gamma(-0.0)
mesg = "Math.gamma(-0.0) should be -INF"
- assert_infinity(x, mesg)
- assert_predicate(x, :negative?, mesg)
+ assert_infinity(-x, mesg)
assert_nan(Math.gamma(Float::NAN))
end
@@ -299,7 +304,6 @@ class TestMath < Test::Unit::TestCase
x, sign = Math.lgamma(-0.0)
mesg = "Math.lgamma(-0.0) should be [INF, -1]"
assert_infinity(x, mesg)
- assert_predicate(x, :positive?, mesg)
assert_equal(-1, sign, mesg)
x, sign = Math.lgamma(Float::NAN)
assert_nan(x)
diff --git a/test/ruby/test_method.rb b/test/ruby/test_method.rb
index daf0ec73ca..a7945082c2 100644
--- a/test/ruby/test_method.rb
+++ b/test/ruby/test_method.rb
@@ -318,6 +318,17 @@ class TestMethod < Test::Unit::TestCase
assert_equal(:foo, o.foo)
end
+ PUBLIC_SINGLETON_TEST = Object.new
+ class << PUBLIC_SINGLETON_TEST
+ private
+ PUBLIC_SINGLETON_TEST.define_singleton_method(:dsm){}
+ def PUBLIC_SINGLETON_TEST.def; end
+ end
+ def test_define_singleton_method_public
+ assert_nil(PUBLIC_SINGLETON_TEST.dsm)
+ assert_nil(PUBLIC_SINGLETON_TEST.def)
+ end
+
def test_define_singleton_method_no_proc
o = Object.new
assert_raise(ArgumentError) {
@@ -439,6 +450,18 @@ class TestMethod < Test::Unit::TestCase
assert_equal(:bar, m.clone.bar)
end
+ def test_clone_under_gc_compact_stress
+ omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077
+ EnvUtil.under_gc_compact_stress do
+ 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
+ end
+
def test_inspect
o = Object.new
def o.foo; end; line_no = __LINE__
@@ -566,9 +589,9 @@ class TestMethod < Test::Unit::TestCase
assert_equal([[:req, :a], [:rest, :b], [:req, :c]], method(:mo5).parameters)
assert_equal([[:req, :a], [:rest, :b], [:req, :c], [:block, :d]], method(:mo6).parameters)
assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:block, :e]], method(:mo7).parameters)
- assert_equal([[:req, :a], [:opt, :b], [:rest], [:req, :d], [:block, :e]], method(:mo8).parameters)
+ assert_equal([[:req, :a], [:opt, :b], [:rest, :*], [:req, :d], [:block, :e]], method(:mo8).parameters)
assert_equal([[:req], [:block, :b]], method(:ma1).parameters)
- assert_equal([[:keyrest]], method(:mk1).parameters)
+ assert_equal([[:keyrest, :**]], method(:mk1).parameters)
assert_equal([[:keyrest, :o]], method(:mk2).parameters)
assert_equal([[:req, :a], [:keyrest, :o]], method(:mk3).parameters)
assert_equal([[:opt, :a], [:keyrest, :o]], method(:mk4).parameters)
@@ -592,9 +615,9 @@ class TestMethod < Test::Unit::TestCase
assert_equal([[:req, :a], [:rest, :b], [:req, :c]], self.class.instance_method(:mo5).parameters)
assert_equal([[:req, :a], [:rest, :b], [:req, :c], [:block, :d]], self.class.instance_method(:mo6).parameters)
assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:block, :e]], self.class.instance_method(:mo7).parameters)
- assert_equal([[:req, :a], [:opt, :b], [:rest], [:req, :d], [:block, :e]], self.class.instance_method(:mo8).parameters)
+ assert_equal([[:req, :a], [:opt, :b], [:rest, :*], [:req, :d], [:block, :e]], self.class.instance_method(:mo8).parameters)
assert_equal([[:req], [:block, :b]], self.class.instance_method(:ma1).parameters)
- assert_equal([[:keyrest]], self.class.instance_method(:mk1).parameters)
+ assert_equal([[:keyrest, :**]], self.class.instance_method(:mk1).parameters)
assert_equal([[:keyrest, :o]], self.class.instance_method(:mk2).parameters)
assert_equal([[:req, :a], [:keyrest, :o]], self.class.instance_method(:mk3).parameters)
assert_equal([[:opt, :a], [:keyrest, :o]], self.class.instance_method(:mk4).parameters)
@@ -619,7 +642,7 @@ class TestMethod < Test::Unit::TestCase
assert_equal([[:req, :a], [:rest, :b], [:req, :c], [:block, :d]], method(:pmo6).parameters)
assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:block, :e]], method(:pmo7).parameters)
assert_equal([[:req], [:block, :b]], method(:pma1).parameters)
- assert_equal([[:keyrest]], method(:pmk1).parameters)
+ assert_equal([[:keyrest, :**]], method(:pmk1).parameters)
assert_equal([[:keyrest, :o]], method(:pmk2).parameters)
assert_equal([[:req, :a], [:keyrest, :o]], method(:pmk3).parameters)
assert_equal([[:opt, :a], [:keyrest, :o]], method(:pmk4).parameters)
@@ -643,7 +666,7 @@ class TestMethod < Test::Unit::TestCase
assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:block, :e]], self.class.instance_method(:pmo7).parameters)
assert_equal([[:req], [:block, :b]], self.class.instance_method(:pma1).parameters)
assert_equal([[:req], [:block, :b]], self.class.instance_method(:pma1).parameters)
- assert_equal([[:keyrest]], self.class.instance_method(:pmk1).parameters)
+ assert_equal([[:keyrest, :**]], self.class.instance_method(:pmk1).parameters)
assert_equal([[:keyrest, :o]], self.class.instance_method(:pmk2).parameters)
assert_equal([[:req, :a], [:keyrest, :o]], self.class.instance_method(:pmk3).parameters)
assert_equal([[:opt, :a], [:keyrest, :o]], self.class.instance_method(:pmk4).parameters)
@@ -760,6 +783,14 @@ class TestMethod < Test::Unit::TestCase
assert_raise(NoMethodError) { (self).mv2 }
assert_nothing_raised { self.mv3 }
+ class << (obj = Object.new)
+ private def [](x) x end
+ def mv1(x) self[x] end
+ def mv2(x) (self)[x] end
+ end
+ assert_nothing_raised { obj.mv1(0) }
+ assert_raise(NoMethodError) { obj.mv2(0) }
+
v = Visibility.new
assert_equal('method', defined?(v.mv1))
@@ -1045,7 +1076,7 @@ class TestMethod < Test::Unit::TestCase
assert_equal(sm, im.clone.bind(o).super_method)
end
- def test_super_method_removed
+ def test_super_method_removed_public
c1 = Class.new {private def foo; end}
c2 = Class.new(c1) {public :foo}
c3 = Class.new(c2) {def foo; end}
@@ -1055,20 +1086,35 @@ class TestMethod < Test::Unit::TestCase
assert_nil(m, Feature9781)
end
+ def test_super_method_removed_regular
+ c1 = Class.new { def foo; end }
+ c2 = Class.new(c1) { def foo; end }
+ assert_equal c1.instance_method(:foo), c2.instance_method(:foo).super_method
+ c1.remove_method :foo
+ assert_equal nil, c2.instance_method(:foo).super_method
+ end
+
def test_prepended_public_zsuper
- mod = EnvUtil.labeled_module("Mod") {private def foo; :ok end}
- mods = [mod]
+ mod = EnvUtil.labeled_module("Mod") {private def foo; [:ok] end}
obj = Object.new.extend(mod)
+
class << obj
public :foo
end
- 2.times do |i|
- mods.unshift(mod = EnvUtil.labeled_module("Mod#{i}") {def foo; end})
- obj.singleton_class.prepend(mod)
- end
+
+ mod1 = EnvUtil.labeled_module("Mod1") {def foo; [:mod1] + super end}
+ obj.singleton_class.prepend(mod1)
+
+ mod2 = EnvUtil.labeled_module("Mod2") {def foo; [:mod2] + super end}
+ obj.singleton_class.prepend(mod2)
+
m = obj.method(:foo)
- assert_equal(mods, mods.map {m.owner.tap {m = m.super_method}})
- assert_nil(m)
+ assert_equal mod2, m.owner
+ assert_equal mod1, m.super_method.owner
+ assert_equal obj.singleton_class, m.super_method.super_method.owner
+ assert_equal nil, m.super_method.super_method.super_method
+
+ assert_equal [:mod2, :mod1, :ok], obj.foo
end
def test_super_method_with_prepended_module
@@ -1181,6 +1227,147 @@ class TestMethod < Test::Unit::TestCase
assert_nil(super_method)
end
+ # Bug 18435
+ def test_instance_methods_owner_consistency
+ a = Module.new { def method1; end }
+
+ b = Class.new do
+ include a
+ protected :method1
+ end
+
+ assert_equal [:method1], b.instance_methods(false)
+ assert_equal b, b.instance_method(:method1).owner
+ end
+
+ def test_zsuper_method_removed
+ a = EnvUtil.labeled_class('A') do
+ private
+ def foo(arg = nil)
+ 1
+ end
+ end
+ line = __LINE__ - 4
+
+ b = EnvUtil.labeled_class('B', a) do
+ public :foo
+ end
+
+ unbound = b.instance_method(:foo)
+
+ assert_equal unbound, b.public_instance_method(:foo)
+ assert_equal "#<UnboundMethod: A#foo(arg=...) #{__FILE__}:#{line}>", unbound.inspect
+ assert_equal [[:opt, :arg]], unbound.parameters
+
+ a.remove_method(:foo)
+
+ assert_equal "#<UnboundMethod: A#foo(arg=...) #{__FILE__}:#{line}>", unbound.inspect
+ assert_equal [[:opt, :arg]], unbound.parameters
+
+ obj = b.new
+ assert_equal 1, unbound.bind_call(obj)
+
+ assert_include b.instance_methods(false), :foo
+ link = 'https://github.com/ruby/ruby/pull/6467#issuecomment-1262159088'
+ assert_raise(NameError, link) { b.instance_method(:foo) }
+ # For #test_method_list below, otherwise we get the same error as just above
+ b.remove_method(:foo)
+ end
+
+ def test_zsuper_method_removed_higher_method
+ a0 = EnvUtil.labeled_class('A0') do
+ def foo(arg1 = nil, arg2 = nil)
+ 0
+ end
+ end
+ line0 = __LINE__ - 4
+ a0_foo = a0.instance_method(:foo)
+
+ a = EnvUtil.labeled_class('A', a0) do
+ private
+ def foo(arg = nil)
+ 1
+ end
+ end
+ line = __LINE__ - 4
+
+ b = EnvUtil.labeled_class('B', a) do
+ public :foo
+ end
+
+ unbound = b.instance_method(:foo)
+
+ assert_equal a0_foo, unbound.super_method
+
+ a.remove_method(:foo)
+
+ assert_equal "#<UnboundMethod: A#foo(arg=...) #{__FILE__}:#{line}>", unbound.inspect
+ assert_equal [[:opt, :arg]], unbound.parameters
+ assert_equal a0_foo, unbound.super_method
+
+ obj = b.new
+ assert_equal 1, unbound.bind_call(obj)
+
+ assert_include b.instance_methods(false), :foo
+ assert_equal "#<UnboundMethod: A0#foo(arg1=..., arg2=...) #{__FILE__}:#{line0}>", b.instance_method(:foo).inspect
+ end
+
+ def test_zsuper_method_redefined_bind_call
+ c0 = EnvUtil.labeled_class('C0') do
+ def foo
+ [:foo]
+ end
+ end
+
+ c1 = EnvUtil.labeled_class('C1', c0) do
+ def foo
+ super + [:bar]
+ end
+ end
+ m1 = c1.instance_method(:foo)
+
+ c2 = EnvUtil.labeled_class('C2', c1) do
+ private :foo
+ end
+
+ assert_equal [:foo], c2.private_instance_methods(false)
+ m2 = c2.instance_method(:foo)
+
+ c1.class_exec do
+ remove_method :foo
+ def foo
+ [:bar2]
+ end
+ end
+
+ m3 = c2.instance_method(:foo)
+ c = c2.new
+ assert_equal [:foo, :bar], m1.bind_call(c)
+ assert_equal c1, m1.owner
+ assert_equal [:foo, :bar], m2.bind_call(c)
+ assert_equal c2, m2.owner
+ assert_equal [:bar2], m3.bind_call(c)
+ assert_equal c2, m3.owner
+ end
+
+ # Bug #18751
+ def method_equality_visbility_alias
+ c = Class.new do
+ class << self
+ alias_method :n, :new
+ private :new
+ end
+ end
+
+ assert_equal c.method(:n), c.method(:new)
+
+ assert_not_equal c.method(:n), Class.method(:new)
+ assert_equal c.method(:n) == Class.instance_method(:new).bind(c)
+
+ assert_not_equal c.method(:new), Class.method(:new)
+ assert_equal c.method(:new), Class.instance_method(:new).bind(c)
+ end
+
def rest_parameter(*rest)
rest
end
@@ -1188,7 +1375,7 @@ class TestMethod < Test::Unit::TestCase
def test_splat_long_array
if File.exist?('/etc/os-release') && File.read('/etc/os-release').include?('openSUSE Leap')
# For RubyCI's openSUSE machine http://rubyci.s3.amazonaws.com/opensuseleap/ruby-trunk/recent.html, which tends to die with NoMemoryError here.
- skip 'do not exhaust memory on RubyCI openSUSE Leap machine'
+ omit 'do not exhaust memory on RubyCI openSUSE Leap machine'
end
n = 10_000_000
assert_equal n , rest_parameter(*(1..n)).size, '[Feature #10440]'
@@ -1256,25 +1443,25 @@ class TestMethod < Test::Unit::TestCase
end
def test_argument_error_location
- body = <<-'END_OF_BODY'
- eval <<-'EOS'
- $line_lambda = __LINE__; $f = lambda do
- _x = 1
- end
- $line_method = __LINE__; def foo
- _x = 1
- end
- begin
- $f.call(1)
- rescue ArgumentError => e
- assert_equal "(eval):#{$line_lambda.to_s}:in `block in <main>'", e.backtrace.first
- end
- begin
- foo(1)
- rescue ArgumentError => e
- assert_equal "(eval):#{$line_method}:in `foo'", e.backtrace.first
- end
- EOS
+ body = <<~'END_OF_BODY'
+ eval <<~'EOS', nil, "main.rb"
+ $line_lambda = __LINE__; $f = lambda do
+ _x = 1
+ end
+ $line_method = __LINE__; def foo
+ _x = 1
+ end
+ begin
+ $f.call(1)
+ rescue ArgumentError => e
+ assert_equal "main.rb:#{$line_lambda}:in 'block in <main>'", e.backtrace.first
+ end
+ begin
+ foo(1)
+ rescue ArgumentError => e
+ assert_equal "main.rb:#{$line_method}:in 'foo'", e.backtrace.first
+ end
+ EOS
END_OF_BODY
assert_separately [], body
@@ -1283,7 +1470,7 @@ class TestMethod < Test::Unit::TestCase
end
def test_zsuper_private_override_instance_method
- assert_separately(%w(--disable-gems), <<-'end;', timeout: 30)
+ assert_separately([], <<-'end;', timeout: 30)
# Bug #16942 [ruby-core:98691]
module M
def x
@@ -1299,12 +1486,12 @@ class TestMethod < Test::Unit::TestCase
::Object.prepend(M2)
m = Object.instance_method(:x)
- assert_equal M, m.owner
+ assert_equal M2, m.owner
end;
end
def test_override_optimized_method_on_class_using_prepend
- assert_separately(%w(--disable-gems), <<-'end;', timeout: 30)
+ assert_separately([], <<-'end;', timeout: 30)
# Bug #17725 [ruby-core:102884]
$VERBOSE = nil
String.prepend(Module.new)
@@ -1390,7 +1577,7 @@ class TestMethod < Test::Unit::TestCase
# use_symbol = Object.instance_methods[0].is_a?(Symbol)
nummodule = nummethod = 0
mods = []
- ObjectSpace.each_object(Module) {|m| mods << m if m.name }
+ ObjectSpace.each_object(Module) {|m| mods << m if String === m.name }
mods = mods.sort_by {|m| m.name }
mods.each {|mod|
nummodule += 1
@@ -1428,4 +1615,113 @@ class TestMethod < Test::Unit::TestCase
def test_invalidating_CC_ASAN
assert_ruby_status(['-e', 'using Module.new'])
end
+
+ def test_kwarg_eval_memory_leak
+ assert_no_memory_leak([], "", <<~RUBY, rss: true, limit: 1.2)
+ obj = Object.new
+ def obj.test(**kwargs) = nil
+
+ 100_000.times do
+ eval("obj.test(foo: 123)")
+ end
+ RUBY
+ end
+
+ def test_super_with_splat
+ c = Class.new {
+ attr_reader :x
+
+ def initialize(*args)
+ @x, _ = args
+ end
+ }
+ b = Class.new(c) { def initialize(...) = super }
+ a = Class.new(b) { def initialize(*args) = super }
+ obj = a.new(1, 2, 3)
+ assert_equal 1, obj.x
+ end
+
+ def test_warn_unused_block
+ assert_in_out_err '-w', <<-'RUBY' do |_out, err, _status|
+ def foo = nil
+ foo{} # warn
+ send(:foo){} # don't warn because it uses send
+ b = Proc.new{}
+ foo(&b) # warn
+ RUBY
+ errstr = err.join("\n")
+ assert_equal 2, err.size, errstr
+
+ assert_match(/-:2: warning/, errstr)
+ assert_match(/-:5: warning/, errstr)
+ end
+
+ assert_in_out_err '-w', <<-'RUBY' do |_out, err, _status|
+ def foo = nil
+ 10.times{foo{}} # warn once
+ RUBY
+ assert_equal 1, err.size
+ end
+
+ assert_in_out_err '-w', <<-'RUBY' do |_out, err, _status|
+ def foo = nil; b = nil
+ foo(&b) # no warning
+ 1.object_id{} # no warning because it is written in C
+
+ class C
+ def initialize
+ end
+ end
+ C.new{} # no warning
+
+ RUBY
+ assert_equal 0, err.size
+ end
+
+ assert_in_out_err '-w', <<-'RUBY' do |_out, err, _status|
+ class C0
+ def f1 = nil
+ def f2 = nil
+ def f3 = nil
+ def f4 = nil
+ def f5 = nil
+ def f6 = nil
+ end
+
+ class C1 < C0
+ def f1 = super # zsuper / use
+ def f2 = super() # super / use
+ def f3(&_) = super(&_) # super / use
+ def f4 = super(&nil) # super / unuse
+ def f5 = super(){} # super / unuse
+ def f6 = super{} # zsuper / unuse
+ end
+
+ C1.new.f1{} # no warning
+ C1.new.f2{} # no warning
+ C1.new.f3{} # no warning
+ C1.new.f4{} # warning
+ C1.new.f5{} # warning
+ C1.new.f6{} # warning
+ RUBY
+ assert_equal 3, err.size, err.join("\n")
+ assert_match(/-:22: warning.+f4/, err.join)
+ assert_match(/-:23: warning.+f5/, err.join)
+ assert_match(/-:24: warning.+f6/, err.join)
+ end
+
+ assert_in_out_err '-w', <<-'RUBY' do |_out, err, _status|
+ class C0
+ def f = yield
+ end
+
+ class C1 < C0
+ def f = nil
+ end
+
+ C1.new.f{} # do not warn on duck typing
+ RUBY
+ assert_equal 0, err.size, err.join("\n")
+ end
+ end
end
diff --git a/test/ruby/test_mixed_unicode_escapes.rb b/test/ruby/test_mixed_unicode_escapes.rb
index f0b4cc691f..a30b5c19f5 100644
--- a/test/ruby/test_mixed_unicode_escapes.rb
+++ b/test/ruby/test_mixed_unicode_escapes.rb
@@ -18,12 +18,12 @@ class TestMixedUnicodeEscape < Test::Unit::TestCase
assert_raise(SyntaxError) { eval %q("\u{1234}é")}
# also should not work for Regexp
- assert_raise(SyntaxError) { eval %q(/#{"\u1234"}#{"é"}/)}
assert_raise(RegexpError) { eval %q(/\u{1234}#{nil}é/)}
assert_raise(RegexpError) { eval %q(/é#{nil}\u1234/)}
# String interpolation turns into an expression and we get
# a different kind of error, but we still can't mix these
+ assert_raise(Encoding::CompatibilityError) { eval %q(/#{"\u1234"}#{"é"}/)}
assert_raise(Encoding::CompatibilityError) { eval %q("\u{1234}#{nil}é")}
assert_raise(Encoding::CompatibilityError) { eval %q("é#{nil}\u1234")}
end
diff --git a/test/ruby/test_module.rb b/test/ruby/test_module.rb
index be23b84c46..370b7351c2 100644
--- a/test/ruby/test_module.rb
+++ b/test/ruby/test_module.rb
@@ -253,6 +253,14 @@ class TestModule < Test::Unit::TestCase
assert_operator(Math, :const_defined?, "PI")
assert_not_operator(Math, :const_defined?, :IP)
assert_not_operator(Math, :const_defined?, "IP")
+
+ # Test invalid symbol name
+ # [Bug #20245]
+ EnvUtil.under_gc_stress do
+ assert_raise(EncodingError) do
+ Math.const_defined?("\xC3")
+ end
+ end
end
def each_bad_constants(m, &b)
@@ -475,6 +483,15 @@ class TestModule < Test::Unit::TestCase
assert_not_include(mod.ancestor_list, BasicObject)
end
+ def test_module_collected_extended_object
+ m1 = labeled_module("m1")
+ m2 = labeled_module("m2")
+ Object.new.extend(m1)
+ GC.start
+ m1.include(m2)
+ assert_equal([m1, m2], m1.ancestors)
+ end
+
def test_dup
OtherSetup.call
@@ -519,6 +536,16 @@ class TestModule < Test::Unit::TestCase
assert_raise(ArgumentError) { Module.new { include } }
end
+ def test_include_before_initialize
+ m = Class.new(Module) do
+ def initialize(...)
+ include Enumerable
+ super
+ end
+ end.new
+ assert_operator(m, :<, Enumerable)
+ end
+
def test_prepend_self
m = Module.new
assert_equal([m], m.ancestors)
@@ -553,6 +580,26 @@ class TestModule < Test::Unit::TestCase
assert_equal(2, a2.b)
end
+ def test_ancestry_of_duped_classes
+ m = Module.new
+ sc = Class.new
+ a = Class.new(sc) do
+ def b; 2 end
+ prepend m
+ end
+
+ a2 = a.dup.new
+
+ assert_kind_of Object, a2
+ assert_kind_of sc, a2
+ refute_kind_of a, a2
+ assert_kind_of m, a2
+
+ assert_kind_of Class, a2.class
+ assert_kind_of sc.singleton_class, a2.class
+ assert_same sc, a2.class.superclass
+ end
+
def test_gc_prepend_chain
assert_separately([], <<-EOS)
10000.times { |i|
@@ -737,6 +784,25 @@ class TestModule < Test::Unit::TestCase
assert_equal([:m1, :m0, :m, :sc, :m1, :m0, :c], sc.new.m)
end
+ def test_protected_include_into_included_module
+ m1 = Module.new do
+ def other_foo(other)
+ other.foo
+ end
+
+ protected
+ def foo
+ :ok
+ end
+ end
+ m2 = Module.new
+ c1 = Class.new { include m2 }
+ c2 = Class.new { include m2 }
+ m2.include(m1)
+
+ assert_equal :ok, c1.new.other_foo(c2.new)
+ end
+
def test_instance_methods
assert_equal([:user, :user2], User.instance_methods(false).sort)
assert_equal([:user, :user2, :mixin].sort, User.instance_methods(true).sort)
@@ -936,6 +1002,15 @@ class TestModule < Test::Unit::TestCase
assert_equal([:bClass1], BClass.public_instance_methods(false))
end
+ def test_undefined_instance_methods
+ assert_equal([], AClass.undefined_instance_methods)
+ assert_equal([], BClass.undefined_instance_methods)
+ c = Class.new(AClass) {undef aClass}
+ assert_equal([:aClass], c.undefined_instance_methods)
+ c = Class.new(c)
+ assert_equal([], c.undefined_instance_methods)
+ end
+
def test_s_public
o = (c = Class.new(AClass)).new
assert_raise(NoMethodError, /private method/) {o.aClass1}
@@ -1014,6 +1089,28 @@ class TestModule < Test::Unit::TestCase
assert_raise(NoMethodError, /protected method/) {o.aClass2}
end
+ def test_visibility_method_return_value
+ no_arg_results = nil
+ c = Module.new do
+ singleton_class.send(:public, :public, :private, :protected, :module_function)
+ def foo; end
+ def bar; end
+ no_arg_results = [public, private, protected, module_function]
+ end
+
+ assert_equal([nil]*4, no_arg_results)
+
+ assert_equal(:foo, c.private(:foo))
+ assert_equal(:foo, c.public(:foo))
+ assert_equal(:foo, c.protected(:foo))
+ assert_equal(:foo, c.module_function(:foo))
+
+ assert_equal([:foo, :bar], c.private(:foo, :bar))
+ assert_equal([:foo, :bar], c.public(:foo, :bar))
+ assert_equal([:foo, :bar], c.protected(:foo, :bar))
+ assert_equal([:foo, :bar], c.module_function(:foo, :bar))
+ end
+
def test_s_constants
c1 = Module.constants
Object.module_eval "WALTER = 99"
@@ -1239,8 +1336,6 @@ class TestModule < Test::Unit::TestCase
end
end
include LangModuleSpecInObject
- module LangModuleTop
- end
puts "ok" if LangModuleSpecInObject::LangModuleTop == LangModuleTop
INPUT
@@ -1382,7 +1477,7 @@ class TestModule < Test::Unit::TestCase
end
%w(object_id __send__ initialize).each do |n|
- assert_in_out_err([], <<-INPUT, [], %r"warning: undefining `#{n}' may cause serious problems$")
+ assert_in_out_err([], <<-INPUT, [], %r"warning: undefining '#{n}' may cause serious problems$")
$VERBOSE = false
Class.new.instance_eval { undef_method(:#{n}) }
INPUT
@@ -1641,6 +1736,47 @@ class TestModule < Test::Unit::TestCase
assert_equal("TestModule::C\u{df}", c.name, '[ruby-core:24600]')
c = Module.new.module_eval("class X\u{df} < Module; self; end")
assert_match(/::X\u{df}:/, c.new.to_s)
+ ensure
+ Object.send(:remove_const, "C\u{df}")
+ end
+
+
+ def test_const_added
+ eval(<<~RUBY)
+ module TestConstAdded
+ @memo = []
+ class << self
+ attr_accessor :memo
+
+ def const_added(sym)
+ memo << sym
+ end
+ end
+ CONST = 1
+ module SubModule
+ end
+
+ class SubClass
+ end
+ end
+ TestConstAdded::OUTSIDE_CONST = 2
+ module TestConstAdded::OutsideSubModule; end
+ class TestConstAdded::OutsideSubClass; end
+ RUBY
+ TestConstAdded.const_set(:CONST_SET, 3)
+ assert_equal [
+ :CONST,
+ :SubModule,
+ :SubClass,
+ :OUTSIDE_CONST,
+ :OutsideSubModule,
+ :OutsideSubClass,
+ :CONST_SET,
+ ], TestConstAdded.memo
+ ensure
+ if self.class.const_defined? :TestConstAdded
+ self.class.send(:remove_const, :TestConstAdded)
+ end
end
def test_method_added
@@ -2224,6 +2360,18 @@ class TestModule < Test::Unit::TestCase
assert_equal(:foo, removed)
end
+ def test_frozen_prepend_remove_method
+ [Module, Class].each do |klass|
+ mod = klass.new do
+ prepend(Module.new)
+ def foo; end
+ end
+ mod.freeze
+ assert_raise(FrozenError, '[Bug #19166]') { mod.send(:remove_method, :foo) }
+ assert_equal([:foo], mod.instance_methods(false))
+ end
+ end
+
def test_prepend_class_ancestors
bug6658 = '[ruby-core:45919]'
m = labeled_module("m")
@@ -2730,6 +2878,7 @@ class TestModule < Test::Unit::TestCase
def test_invalid_attr
%W[
+ foo=
foo?
@foo
@@foo
@@ -3014,6 +3163,19 @@ class TestModule < Test::Unit::TestCase
end;
end
+ def test_define_method_changes_visibility_with_existing_method_bug_19749
+ c = Class.new do
+ def a; end
+ private def b; end
+
+ define_method(:b, instance_method(:b))
+ private
+ define_method(:a, instance_method(:a))
+ end
+ assert_equal([:b], c.public_instance_methods(false))
+ assert_equal([:a], c.private_instance_methods(false))
+ end
+
def test_define_method_with_unbound_method
# Passing an UnboundMethod to define_method succeeds if it is from an ancestor
assert_nothing_raised do
@@ -3034,6 +3196,7 @@ class TestModule < Test::Unit::TestCase
end
def test_redefinition_mismatch
+ omit "Investigating trunk-rjit failure on ci.rvm.jp" if defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled?
m = Module.new
m.module_eval "A = 1", __FILE__, line = __LINE__
e = assert_raise_with_message(TypeError, /is not a module/) {
@@ -3135,6 +3298,62 @@ class TestModule < Test::Unit::TestCase
assert_match(/::Foo$/, mod.name, '[Bug #14895]')
end
+ def test_iclass_memory_leak
+ # [Bug #19550]
+ assert_no_memory_leak([], <<~PREP, <<~CODE, rss: true)
+ code = proc do
+ mod = Module.new
+ Class.new do
+ include mod
+ end
+ end
+ 1_000.times(&code)
+ PREP
+ 3_000_000.times(&code)
+ CODE
+ end
+
+ def test_complemented_method_entry_memory_leak
+ # [Bug #19894] [Bug #19896]
+ assert_no_memory_leak([], <<~PREP, <<~CODE, rss: true)
+ code = proc do
+ $c = Class.new do
+ def foo; end
+ end
+
+ $m = Module.new do
+ refine $c do
+ def foo; end
+ end
+ end
+
+ Class.new do
+ using $m
+
+ def initialize
+ o = $c.new
+ o.method(:foo).unbind
+ end
+ end.new
+ end
+ 1_000.times(&code)
+ PREP
+ 300_000.times(&code)
+ CODE
+ end
+
+ def test_module_clone_memory_leak
+ # [Bug #19901]
+ assert_no_memory_leak([], <<~PREP, <<~CODE, rss: true)
+ code = proc do
+ Module.new.clone
+ end
+ 1_000.times(&code)
+ PREP
+ 1_000_000.times(&code)
+ CODE
+ end
+
private
def assert_top_method_is_private(method)
@@ -3142,7 +3361,7 @@ class TestModule < Test::Unit::TestCase
methods = singleton_class.private_instance_methods(false)
assert_include(methods, :#{method}, ":#{method} should be private")
- assert_raise_with_message(NoMethodError, "private method `#{method}' called for main:Object") {
+ assert_raise_with_message(NoMethodError, /^private method '#{method}' called for /) {
recv = self
recv.#{method}
}
diff --git a/test/ruby/test_nomethod_error.rb b/test/ruby/test_nomethod_error.rb
index 321b7ccab2..6d413e6391 100644
--- a/test/ruby/test_nomethod_error.rb
+++ b/test/ruby/test_nomethod_error.rb
@@ -85,7 +85,7 @@ class TestNoMethodError < Test::Unit::TestCase
bug3237 = '[ruby-core:29948]'
str = "\u2600"
id = :"\u2604"
- msg = "undefined method `#{id}' for \"#{str}\":String"
+ msg = "undefined method '#{id}' for an instance of String"
assert_raise_with_message(NoMethodError, Regexp.compile(Regexp.quote(msg)), bug3237) do
str.__send__(id)
end
diff --git a/test/ruby/test_numeric.rb b/test/ruby/test_numeric.rb
index 0593cb535d..ab492743f6 100644
--- a/test/ruby/test_numeric.rb
+++ b/test/ruby/test_numeric.rb
@@ -324,6 +324,9 @@ class TestNumeric < Test::Unit::TestCase
e = 1.step(10, {by: "1"})
assert_raise(TypeError) {e.next}
assert_raise(TypeError) {e.size}
+ e = 1.step(to: "10")
+ assert_raise(ArgumentError) {e.next}
+ assert_raise(ArgumentError) {e.size}
assert_equal(bignum*2+1, (-bignum).step(bignum, 1).size)
assert_equal(bignum*2, (-bignum).step(bignum-1, 1).size)
diff --git a/test/ruby/test_object.rb b/test/ruby/test_object.rb
index 83208bbcdb..37c09596a2 100644
--- a/test/ruby/test_object.rb
+++ b/test/ruby/test_object.rb
@@ -355,6 +355,41 @@ class TestObject < Test::Unit::TestCase
end
end
+ def test_remove_instance_variable_re_embed
+ require "objspace"
+
+ c = Class.new do
+ def a = @a
+
+ def b = @b
+
+ def c = @c
+ end
+
+ o1 = c.new
+ o2 = c.new
+
+ o1.instance_variable_set(:@foo, 5)
+ o1.instance_variable_set(:@a, 0)
+ o1.instance_variable_set(:@b, 1)
+ o1.instance_variable_set(:@c, 2)
+ refute_includes ObjectSpace.dump(o1), '"embedded":true'
+ o1.remove_instance_variable(:@foo)
+ assert_includes ObjectSpace.dump(o1), '"embedded":true'
+
+ o2.instance_variable_set(:@a, 0)
+ o2.instance_variable_set(:@b, 1)
+ o2.instance_variable_set(:@c, 2)
+ assert_includes ObjectSpace.dump(o2), '"embedded":true'
+
+ assert_equal(0, o1.a)
+ assert_equal(1, o1.b)
+ assert_equal(2, o1.c)
+ assert_equal(0, o2.a)
+ assert_equal(1, o2.b)
+ assert_equal(2, o2.c)
+ end
+
def test_convert_string
o = Object.new
def o.to_s; 1; end
@@ -422,6 +457,18 @@ class TestObject < Test::Unit::TestCase
assert_equal(1+3+5+7+9, n)
end
+ def test_max_shape_variation_with_performance_warnings
+ assert_in_out_err([], <<-INPUT, %w(), /The class Foo reached 8 shape variations, instance variables accesses will be slower and memory usage increased/)
+ $VERBOSE = false
+ Warning[:performance] = true
+
+ class Foo; end
+ 10.times do |i|
+ Foo.new.instance_variable_set(:"@a\#{i}", nil)
+ end
+ INPUT
+ end
+
def test_redefine_method_under_verbose
assert_in_out_err([], <<-INPUT, %w(2), /warning: method redefined; discarding old foo$/)
$VERBOSE = true
@@ -433,12 +480,12 @@ class TestObject < Test::Unit::TestCase
end
def test_redefine_method_which_may_case_serious_problem
- assert_in_out_err([], <<-INPUT, [], %r"warning: redefining `object_id' may cause serious problems$")
+ assert_in_out_err([], <<-INPUT, [], %r"warning: redefining 'object_id' may cause serious problems$")
$VERBOSE = false
def (Object.new).object_id; end
INPUT
- assert_in_out_err([], <<-INPUT, [], %r"warning: redefining `__send__' may cause serious problems$")
+ assert_in_out_err([], <<-INPUT, [], %r"warning: redefining '__send__' may cause serious problems$")
$VERBOSE = false
def (Object.new).__send__; end
INPUT
@@ -481,7 +528,7 @@ class TestObject < Test::Unit::TestCase
assert_raise(NoMethodError, bug2202) {o2.meth2}
%w(object_id __send__ initialize).each do |m|
- assert_in_out_err([], <<-INPUT, %w(:ok), %r"warning: removing `#{m}' may cause serious problems$")
+ assert_in_out_err([], <<-INPUT, %w(:ok), %r"warning: removing '#{m}' may cause serious problems$")
$VERBOSE = false
begin
Class.new.instance_eval { remove_method(:#{m}) }
@@ -853,6 +900,15 @@ class TestObject < Test::Unit::TestCase
x.instance_variable_set(:@bar, 42)
assert_match(/\A#<Object:0x\h+ (?:@foo="value", @bar=42|@bar=42, @foo="value")>\z/, x.inspect)
+ # Bug: [ruby-core:19167]
+ x = Object.new
+ x.instance_variable_set(:@foo, NilClass)
+ assert_match(/\A#<Object:0x\h+ @foo=NilClass>\z/, x.inspect)
+ x.instance_variable_set(:@foo, TrueClass)
+ assert_match(/\A#<Object:0x\h+ @foo=TrueClass>\z/, x.inspect)
+ x.instance_variable_set(:@foo, FalseClass)
+ assert_match(/\A#<Object:0x\h+ @foo=FalseClass>\z/, x.inspect)
+
# #inspect does not call #to_s anymore
feature6130 = '[ruby-core:43238]'
x = Object.new
@@ -925,6 +981,19 @@ class TestObject < Test::Unit::TestCase
end
end
+ def test_singleton_class_freeze
+ x = Object.new
+ xs = x.singleton_class
+ x.freeze
+ assert_predicate(xs, :frozen?)
+
+ y = Object.new
+ ys = y.singleton_class
+ ys.prepend(Module.new)
+ y.freeze
+ assert_predicate(ys, :frozen?, '[Bug #19169]')
+ end
+
def test_redef_method_missing
bug5473 = '[ruby-core:40287]'
['ArgumentError.new("bug5473")', 'ArgumentError, "bug5473"', '"bug5473"'].each do |code|
@@ -993,4 +1062,13 @@ class TestObject < Test::Unit::TestCase
end
EOS
end
+
+ def test_frozen_inspect
+ obj = Object.new
+ obj.instance_variable_set(:@a, "a")
+ ins = obj.inspect
+ obj.freeze
+
+ assert_equal(ins, obj.inspect)
+ end
end
diff --git a/test/ruby/test_objectspace.rb b/test/ruby/test_objectspace.rb
index 24a190b2df..beb66da7e2 100644
--- a/test/ruby/test_objectspace.rb
+++ b/test/ruby/test_objectspace.rb
@@ -65,6 +65,14 @@ End
assert_raise_with_message(TypeError, msg) {ObjectSpace._id2ref(Object.new)}
end
+ def test_id2ref_invalid_symbol_id
+ # RB_STATIC_SYM_P checks for static symbols by checking that the bottom
+ # 8 bits of the object is equal to RUBY_SYMBOL_FLAG, so we need to make
+ # sure that the bottom 8 bits remain unchanged.
+ msg = /is not symbol id value/
+ assert_raise_with_message(RangeError, msg) { ObjectSpace._id2ref(:a.object_id + 256) }
+ end
+
def test_count_objects
h = {}
ObjectSpace.count_objects(h)
@@ -93,6 +101,20 @@ End
ObjectSpace.define_finalizer(a) { p :ok }
!b
END
+
+ assert_in_out_err(["-e", <<~RUBY], "", %w(:ok :ok), [], timeout: 60)
+ a = Object.new
+ ObjectSpace.define_finalizer(a) { p :ok }
+
+ 1_000_000.times do
+ o = Object.new
+ ObjectSpace.define_finalizer(o) { }
+ end
+
+ b = Object.new
+ ObjectSpace.define_finalizer(b) { p :ok }
+ RUBY
+
assert_raise(ArgumentError) { ObjectSpace.define_finalizer([], Object.new) }
code = proc do |priv|
@@ -169,30 +191,29 @@ End
end
def test_finalizer_thread_raise
- GC.disable
- fzer = proc do |id|
- sleep 0.2
- end
- 2.times do
- o = Object.new
- ObjectSpace.define_finalizer(o, fzer)
- end
+ EnvUtil.without_gc do
+ fzer = proc do |id|
+ sleep 0.2
+ end
+ 2.times do
+ o = Object.new
+ ObjectSpace.define_finalizer(o, fzer)
+ end
- my_error = Class.new(RuntimeError)
- begin
- main_th = Thread.current
- Thread.new do
- sleep 0.1
- main_th.raise(my_error)
+ my_error = Class.new(RuntimeError)
+ begin
+ main_th = Thread.current
+ Thread.new do
+ sleep 0.1
+ main_th.raise(my_error)
+ end
+ GC.start
+ puts "After GC"
+ sleep(10)
+ assert(false)
+ rescue my_error
end
- GC.start
- puts "After GC"
- sleep(10)
- assert(false)
- rescue my_error
end
- ensure
- GC.enable
end
def test_each_object
@@ -219,7 +240,7 @@ End
assert_same(new_obj, found[0])
end
- def test_each_object_no_gabage
+ def test_each_object_no_garbage
assert_separately([], <<-End)
GC.disable
eval('begin; 1.times{}; rescue; ensure; end')
diff --git a/test/ruby/test_optimization.rb b/test/ruby/test_optimization.rb
index 2075bf3513..982da661ec 100644
--- a/test/ruby/test_optimization.rb
+++ b/test/ruby/test_optimization.rb
@@ -16,6 +16,18 @@ class TestRubyOptimization < Test::Unit::TestCase
end;
end
+ def assert_performance_warning(klass, method)
+ assert_in_out_err([], "#{<<-"begin;"}\n#{<<~"end;"}", [], ["-:4: warning: Redefining '#{klass}##{method}' disables interpreter and JIT optimizations"])
+ begin;
+ Warning[:performance] = true
+ class #{klass}
+ undef #{method}
+ def #{method}
+ end
+ end
+ end;
+ end
+
def disasm(name)
RubyVM::InstructionSequence.of(method(name)).disasm
end
@@ -23,102 +35,122 @@ class TestRubyOptimization < Test::Unit::TestCase
def test_fixnum_plus
assert_equal 21, 10 + 11
assert_redefine_method('Integer', '+', 'assert_equal 11, 10 + 11')
+ assert_performance_warning('Integer', '+')
end
def test_fixnum_minus
assert_equal 5, 8 - 3
assert_redefine_method('Integer', '-', 'assert_equal 3, 8 - 3')
+ assert_performance_warning('Integer', '-')
end
def test_fixnum_mul
assert_equal 15, 3 * 5
assert_redefine_method('Integer', '*', 'assert_equal 5, 3 * 5')
+ assert_performance_warning('Integer', '*')
end
def test_fixnum_div
assert_equal 3, 15 / 5
assert_redefine_method('Integer', '/', 'assert_equal 5, 15 / 5')
+ assert_performance_warning('Integer', '/')
end
def test_fixnum_mod
assert_equal 1, 8 % 7
assert_redefine_method('Integer', '%', 'assert_equal 7, 8 % 7')
+ assert_performance_warning('Integer', '%')
end
def test_fixnum_lt
assert_equal true, 1 < 2
assert_redefine_method('Integer', '<', 'assert_equal 2, 1 < 2')
+ assert_performance_warning('Integer', '<')
end
def test_fixnum_le
assert_equal true, 1 <= 2
assert_redefine_method('Integer', '<=', 'assert_equal 2, 1 <= 2')
+ assert_performance_warning('Integer', '<=')
end
def test_fixnum_gt
assert_equal false, 1 > 2
assert_redefine_method('Integer', '>', 'assert_equal 2, 1 > 2')
+ assert_performance_warning('Integer', '>')
end
def test_fixnum_ge
assert_equal false, 1 >= 2
assert_redefine_method('Integer', '>=', 'assert_equal 2, 1 >= 2')
+ assert_performance_warning('Integer', '>=')
end
def test_float_plus
assert_equal 4.0, 2.0 + 2.0
assert_redefine_method('Float', '+', 'assert_equal 2.0, 2.0 + 2.0')
+ assert_performance_warning('Float', '+')
end
def test_float_minus
assert_equal 4.0, 2.0 + 2.0
- assert_redefine_method('Float', '+', 'assert_equal 2.0, 2.0 + 2.0')
+ assert_redefine_method('Float', '-', 'assert_equal 2.0, 4.0 - 2.0')
+ assert_performance_warning('Float', '-')
end
def test_float_mul
assert_equal 29.25, 4.5 * 6.5
assert_redefine_method('Float', '*', 'assert_equal 6.5, 4.5 * 6.5')
+ assert_performance_warning('Float', '*')
end
def test_float_div
assert_in_delta 0.63063063063063063, 4.2 / 6.66
assert_redefine_method('Float', '/', 'assert_equal 6.66, 4.2 / 6.66', "[Bug #9238]")
+ assert_performance_warning('Float', '/')
end
def test_float_lt
assert_equal true, 1.1 < 2.2
assert_redefine_method('Float', '<', 'assert_equal 2.2, 1.1 < 2.2')
+ assert_performance_warning('Float', '<')
end
def test_float_le
assert_equal true, 1.1 <= 2.2
assert_redefine_method('Float', '<=', 'assert_equal 2.2, 1.1 <= 2.2')
+ assert_performance_warning('Float', '<=')
end
def test_float_gt
assert_equal false, 1.1 > 2.2
assert_redefine_method('Float', '>', 'assert_equal 2.2, 1.1 > 2.2')
+ assert_performance_warning('Float', '>')
end
def test_float_ge
assert_equal false, 1.1 >= 2.2
assert_redefine_method('Float', '>=', 'assert_equal 2.2, 1.1 >= 2.2')
+ assert_performance_warning('Float', '>=')
end
def test_string_length
assert_equal 6, "string".length
assert_redefine_method('String', 'length', 'assert_nil "string".length')
+ assert_performance_warning('String', 'length')
end
def test_string_size
assert_equal 6, "string".size
assert_redefine_method('String', 'size', 'assert_nil "string".size')
+ assert_performance_warning('String', 'size')
end
def test_string_empty?
assert_equal true, "".empty?
assert_equal false, "string".empty?
assert_redefine_method('String', 'empty?', 'assert_nil "string".empty?')
+ assert_performance_warning('String', 'empty?')
end
def test_string_plus
@@ -127,27 +159,50 @@ class TestRubyOptimization < Test::Unit::TestCase
assert_equal "x", "" + "x"
assert_equal "ab", "a" + "b"
assert_redefine_method('String', '+', 'assert_equal "b", "a" + "b"')
+ assert_performance_warning('String', '+')
end
def test_string_succ
assert_equal 'b', 'a'.succ
assert_equal 'B', 'A'.succ
+ assert_performance_warning('String', 'succ')
end
def test_string_format
assert_equal '2', '%d' % 2
assert_redefine_method('String', '%', 'assert_equal 2, "%d" % 2')
+ assert_performance_warning('String', '%')
end
def test_string_freeze
assert_equal "foo", "foo".freeze
assert_equal "foo".freeze.object_id, "foo".freeze.object_id
assert_redefine_method('String', 'freeze', 'assert_nil "foo".freeze')
+ assert_performance_warning('String', 'freeze')
end
def test_string_uminus
assert_same "foo".freeze, -"foo"
assert_redefine_method('String', '-@', 'assert_nil(-"foo")')
+ assert_performance_warning('String', '-@')
+ end
+
+ def test_array_min
+ assert_equal 1, [1, 2, 4].min
+ assert_redefine_method('Array', 'min', 'assert_nil([1, 2, 4].min)')
+ assert_redefine_method('Array', 'min', 'assert_nil([1 + 0, 2, 4].min)')
+ assert_performance_warning('Array', 'min')
+ end
+
+ def test_array_max
+ assert_equal 4, [1, 2, 4].max
+ assert_redefine_method('Array', 'max', 'assert_nil([1, 2, 4].max)')
+ assert_redefine_method('Array', 'max', 'assert_nil([1 + 0, 2, 4].max)')
+ assert_performance_warning('Array', 'max')
+ end
+
+ def test_array_hash
+ assert_performance_warning('Array', 'hash')
end
def test_trace_optimized_methods
@@ -223,6 +278,8 @@ class TestRubyOptimization < Test::Unit::TestCase
assert_equal :b, (b #{m} "b").to_sym
end
end
+
+ assert_performance_warning('String', '==')
end
def test_string_ltlt
@@ -231,50 +288,59 @@ class TestRubyOptimization < Test::Unit::TestCase
assert_equal "x", "" << "x"
assert_equal "ab", "a" << "b"
assert_redefine_method('String', '<<', 'assert_equal "b", "a" << "b"')
+ assert_performance_warning('String', '<<')
end
def test_fixnum_and
assert_equal 1, 1&3
assert_redefine_method('Integer', '&', 'assert_equal 3, 1&3')
+ assert_performance_warning('Integer', '&')
end
def test_fixnum_or
assert_equal 3, 1|3
assert_redefine_method('Integer', '|', 'assert_equal 1, 3|1')
+ assert_performance_warning('Integer', '|')
end
def test_array_plus
assert_equal [1,2], [1]+[2]
assert_redefine_method('Array', '+', 'assert_equal [2], [1]+[2]')
+ assert_performance_warning('Array', '+')
end
def test_array_minus
assert_equal [2], [1,2] - [1]
assert_redefine_method('Array', '-', 'assert_equal [1], [1,2]-[1]')
+ assert_performance_warning('Array', '-')
end
def test_array_length
assert_equal 0, [].length
assert_equal 3, [1,2,3].length
assert_redefine_method('Array', 'length', 'assert_nil([].length); assert_nil([1,2,3].length)')
+ assert_performance_warning('Array', 'length')
end
def test_array_empty?
assert_equal true, [].empty?
assert_equal false, [1,2,3].empty?
assert_redefine_method('Array', 'empty?', 'assert_nil([].empty?); assert_nil([1,2,3].empty?)')
+ assert_performance_warning('Array', 'empty?')
end
def test_hash_length
assert_equal 0, {}.length
assert_equal 1, {1=>1}.length
assert_redefine_method('Hash', 'length', 'assert_nil({}.length); assert_nil({1=>1}.length)')
+ assert_performance_warning('Hash', 'length')
end
def test_hash_empty?
assert_equal true, {}.empty?
assert_equal false, {1=>1}.empty?
assert_redefine_method('Hash', 'empty?', 'assert_nil({}.empty?); assert_nil({1=>1}.empty?)')
+ assert_performance_warning('Hash', 'empty?')
end
def test_hash_aref_with
@@ -285,6 +351,7 @@ class TestRubyOptimization < Test::Unit::TestCase
h = { "foo" => 1 }
assert_equal "foo", h["foo"]
end;
+ assert_performance_warning('Hash', '[]')
end
def test_hash_aset_with
@@ -296,6 +363,7 @@ class TestRubyOptimization < Test::Unit::TestCase
assert_equal 1, h["foo"] = 1, "assignment always returns value set"
assert_nil h["foo"]
end;
+ assert_performance_warning('Hash', '[]=')
end
class MyObj
@@ -425,6 +493,31 @@ class TestRubyOptimization < Test::Unit::TestCase
message(bug12565) {disasm(:add_one_and_two)})
end
+ def test_c_func_with_sp_offset_under_tailcall
+ tailcall("#{<<-"begin;"}\n#{<<~"end;"}")
+ begin;
+ def calc_one_plus_two
+ 1 + 2.abs
+ end
+
+ def one_plus_two
+ calc_one_plus_two
+ end
+ end;
+ assert_equal(3, one_plus_two)
+ end
+
+ def test_tailcall_and_post_arg
+ tailcall(<<~RUBY)
+ def ret_const = :ok
+
+ def post_arg(_a = 1, _b) = ret_const
+ RUBY
+
+ # YJIT probably uses a fallback on the call to post_arg
+ assert_equal(:ok, post_arg(0))
+ end
+
def test_tailcall_interrupted_by_sigint
bug12576 = 'ruby-core:76327'
script = "#{<<-"begin;"}\n#{<<~'end;'}"
@@ -498,7 +591,7 @@ class TestRubyOptimization < Test::Unit::TestCase
end
def test_tailcall_not_to_grow_stack
- skip 'currently JIT-ed code always creates a new stack frame' if defined?(RubyVM::JIT) && RubyVM::JIT.enabled?
+ omit 'currently JIT-ed code always creates a new stack frame' if defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled?
bug16161 = '[ruby-core:94881]'
tailcall("#{<<-"begin;"}\n#{<<~"end;"}")
@@ -540,7 +633,7 @@ class TestRubyOptimization < Test::Unit::TestCase
begin;
class String
undef freeze
- def freeze
+ def freeze(&)
block_given?
end
end
@@ -602,6 +695,7 @@ class TestRubyOptimization < Test::Unit::TestCase
[ nil, true, false, 0.1, :sym, 'str', 0xffffffffffffffff ].each do |v|
k = v.class.to_s
assert_redefine_method(k, '===', "assert_equal(#{v.inspect} === 0, 0)")
+ assert_performance_warning(k, '===')
end
end
@@ -655,6 +749,98 @@ class TestRubyOptimization < Test::Unit::TestCase
end
end
+ def test_peephole_array_freeze
+ code = "#{<<~'begin;'}\n#{<<~'end;'}"
+ begin;
+ [1].freeze
+ end;
+ iseq = RubyVM::InstructionSequence.compile(code)
+ insn = iseq.disasm
+ assert_match(/opt_ary_freeze/, insn)
+ assert_no_match(/duparray/, insn)
+ assert_no_match(/send/, insn)
+ assert_predicate([1].freeze, :frozen?)
+ assert_in_out_err([], <<~RUBY, [":ok"])
+ class Array
+ prepend Module.new {
+ def freeze
+ :ok
+ end
+ }
+ end
+ p [1].freeze
+ RUBY
+ end
+
+ def test_peephole_array_freeze_empty
+ code = "#{<<~'begin;'}\n#{<<~'end;'}"
+ begin;
+ [].freeze
+ end;
+ iseq = RubyVM::InstructionSequence.compile(code)
+ insn = iseq.disasm
+ assert_match(/opt_ary_freeze/, insn)
+ assert_no_match(/duparray/, insn)
+ assert_no_match(/send/, insn)
+ assert_predicate([].freeze, :frozen?)
+ assert_in_out_err([], <<~RUBY, [":ok"])
+ class Array
+ prepend Module.new {
+ def freeze
+ :ok
+ end
+ }
+ end
+ p [].freeze
+ RUBY
+ end
+
+ def test_peephole_hash_freeze
+ code = "#{<<~'begin;'}\n#{<<~'end;'}"
+ begin;
+ {a:1}.freeze
+ end;
+ iseq = RubyVM::InstructionSequence.compile(code)
+ insn = iseq.disasm
+ assert_match(/opt_hash_freeze/, insn)
+ assert_no_match(/duphash/, insn)
+ assert_no_match(/send/, insn)
+ assert_predicate([1].freeze, :frozen?)
+ assert_in_out_err([], <<~RUBY, [":ok"])
+ class Hash
+ prepend Module.new {
+ def freeze
+ :ok
+ end
+ }
+ end
+ p({a:1}.freeze)
+ RUBY
+ end
+
+ def test_peephole_hash_freeze_empty
+ code = "#{<<~'begin;'}\n#{<<~'end;'}"
+ begin;
+ {}.freeze
+ end;
+ iseq = RubyVM::InstructionSequence.compile(code)
+ insn = iseq.disasm
+ assert_match(/opt_hash_freeze/, insn)
+ assert_no_match(/duphash/, insn)
+ assert_no_match(/send/, insn)
+ assert_predicate([].freeze, :frozen?)
+ assert_in_out_err([], <<~RUBY, [":ok"])
+ class Hash
+ prepend Module.new {
+ def freeze
+ :ok
+ end
+ }
+ end
+ p({}.freeze)
+ RUBY
+ end
+
def test_branch_condition_backquote
bug = '[ruby-core:80740] [Bug #13444] redefined backquote should be called'
class << self
@@ -891,4 +1077,34 @@ class TestRubyOptimization < Test::Unit::TestCase
raise "END"
end;
end
+
+ class Objtostring
+ end
+
+ def test_objtostring
+ assert_raise(NoMethodError){"#{BasicObject.new}"}
+ assert_redefine_method('Symbol', 'to_s', <<-'end')
+ assert_match %r{\A#<Symbol:0x[0-9a-f]+>\z}, "#{:foo}"
+ end
+ assert_redefine_method('NilClass', 'to_s', <<-'end')
+ assert_match %r{\A#<NilClass:0x[0-9a-f]+>\z}, "#{nil}"
+ end
+ assert_redefine_method('TrueClass', 'to_s', <<-'end')
+ assert_match %r{\A#<TrueClass:0x[0-9a-f]+>\z}, "#{true}"
+ end
+ assert_redefine_method('FalseClass', 'to_s', <<-'end')
+ assert_match %r{\A#<FalseClass:0x[0-9a-f]+>\z}, "#{false}"
+ end
+ assert_redefine_method('Integer', 'to_s', <<-'end')
+ (-1..10).each { |i|
+ assert_match %r{\A#<Integer:0x[0-9a-f]+>\z}, "#{i}"
+ }
+ end
+ assert_equal "TestRubyOptimization::Objtostring", "#{Objtostring}"
+ assert_match %r{\A#<Class:0x[0-9a-f]+>\z}, "#{Class.new}"
+ assert_match %r{\A#<Module:0x[0-9a-f]+>\z}, "#{Module.new}"
+ o = Object.new
+ def o.to_s; 1; end
+ assert_match %r{\A#<Object:0x[0-9a-f]+>\z}, "#{o}"
+ end
end
diff --git a/test/ruby/test_pack.rb b/test/ruby/test_pack.rb
index c9ca9c3dfd..ca089f09c3 100644
--- a/test/ruby/test_pack.rb
+++ b/test/ruby/test_pack.rb
@@ -1,25 +1,44 @@
# coding: US-ASCII
# frozen_string_literal: false
require 'test/unit'
+require 'rbconfig'
+require 'rbconfig/sizeof'
class TestPack < Test::Unit::TestCase
+ # Note: the size of intptr_t and uintptr_t should be equal.
+ J_SIZE = RbConfig::SIZEOF['uintptr_t']
+
def test_pack
- $format = "c2x5CCxsdils_l_a6";
+ 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)
+ x = ary.pack(format)
+ ary2 = x.unpack(format)
assert_equal(ary.length, ary2.length)
assert_equal(ary.join(':'), ary2.join(':'))
- assert_match(/def/, $x)
+ assert_match(/def/, x)
- $x = [-1073741825]
- assert_equal($x, $x.pack("q").unpack("q"))
+ x = [-1073741825]
+ assert_equal(x, x.pack("q").unpack("q"))
- $x = [-1]
- assert_equal($x, $x.pack("l").unpack("l"))
+ x = [-1]
+ assert_equal(x, x.pack("l").unpack("l"))
+ end
+
+ def test_ascii_incompatible
+ assert_raise(Encoding::CompatibilityError) do
+ ["foo"].pack("u".encode("UTF-32BE"))
+ end
+
+ assert_raise(Encoding::CompatibilityError) do
+ "foo".unpack("C".encode("UTF-32BE"))
+ end
+
+ assert_raise(Encoding::CompatibilityError) do
+ "foo".unpack1("C".encode("UTF-32BE"))
+ end
end
def test_pack_n
@@ -79,11 +98,11 @@ class TestPack < Test::Unit::TestCase
assert_equal("\x01\x02\x03\x04", [0x01020304].pack("L"+mod))
assert_equal("\x01\x02\x03\x04\x05\x06\x07\x08", [0x0102030405060708].pack("q"+mod))
assert_equal("\x01\x02\x03\x04\x05\x06\x07\x08", [0x0102030405060708].pack("Q"+mod))
- psize = [nil].pack('p').bytesize
- if psize == 4
+ case J_SIZE
+ when 4
assert_equal("\x01\x02\x03\x04", [0x01020304].pack("j"+mod))
assert_equal("\x01\x02\x03\x04", [0x01020304].pack("J"+mod))
- elsif psize == 8
+ when 8
assert_equal("\x01\x02\x03\x04\x05\x06\x07\x08", [0x0102030405060708].pack("j"+mod))
assert_equal("\x01\x02\x03\x04\x05\x06\x07\x08", [0x0102030405060708].pack("J"+mod))
end
@@ -95,10 +114,11 @@ class TestPack < Test::Unit::TestCase
assert_match(/\A\x00*\x01\x02\x03\x04\z/, [0x01020304].pack("I!"+mod))
assert_match(/\A\x00*\x01\x02\x03\x04\z/, [0x01020304].pack("l!"+mod))
assert_match(/\A\x00*\x01\x02\x03\x04\z/, [0x01020304].pack("L!"+mod))
- if psize == 4
+ case J_SIZE
+ when 4
assert_match(/\A\x00*\x01\x02\x03\x04\z/, [0x01020304].pack("j!"+mod))
assert_match(/\A\x00*\x01\x02\x03\x04\z/, [0x01020304].pack("J!"+mod))
- elsif psize == 8
+ when 8
assert_match(/\A\x00*\x01\x02\x03\x04\x05\x06\x07\x08\z/, [0x0102030405060708].pack("j!"+mod))
assert_match(/\A\x00*\x01\x02\x03\x04\x05\x06\x07\x08\z/, [0x0102030405060708].pack("J!"+mod))
end
@@ -127,11 +147,11 @@ class TestPack < Test::Unit::TestCase
assert_equal("\x04\x03\x02\x01", [0x01020304].pack("L"+mod))
assert_equal("\x08\x07\x06\x05\x04\x03\x02\x01", [0x0102030405060708].pack("q"+mod))
assert_equal("\x08\x07\x06\x05\x04\x03\x02\x01", [0x0102030405060708].pack("Q"+mod))
- psize = [nil].pack('p').bytesize
- if psize == 4
+ case J_SIZE
+ when 4
assert_equal("\x04\x03\x02\x01", [0x01020304].pack("j"+mod))
assert_equal("\x04\x03\x02\x01", [0x01020304].pack("J"+mod))
- elsif psize == 8
+ when 8
assert_equal("\x08\x07\x06\x05\x04\x03\x02\x01", [0x0102030405060708].pack("j"+mod))
assert_equal("\x08\x07\x06\x05\x04\x03\x02\x01", [0x0102030405060708].pack("J"+mod))
end
@@ -143,10 +163,11 @@ class TestPack < Test::Unit::TestCase
assert_match(/\A\x04\x03\x02\x01\x00*\z/, [0x01020304].pack("I!"+mod))
assert_match(/\A\x04\x03\x02\x01\x00*\z/, [0x01020304].pack("l!"+mod))
assert_match(/\A\x04\x03\x02\x01\x00*\z/, [0x01020304].pack("L!"+mod))
- if psize == 4
+ case J_SIZE
+ when 4
assert_match(/\A\x04\x03\x02\x01\x00*\z/, [0x01020304].pack("j!"+mod))
assert_match(/\A\x04\x03\x02\x01\x00*\z/, [0x01020304].pack("J!"+mod))
- elsif psize == 8
+ when 8
assert_match(/\A\x08\x07\x06\x05\x04\x03\x02\x01\x00*\z/, [0x0102030405060708].pack("j!"+mod))
assert_match(/\A\x08\x07\x06\x05\x04\x03\x02\x01\x00*\z/, [0x0102030405060708].pack("J!"+mod))
end
@@ -182,8 +203,8 @@ class TestPack < Test::Unit::TestCase
end
def test_integer_endian_explicit
- _integer_big_endian('>')
- _integer_little_endian('<')
+ _integer_big_endian('>')
+ _integer_little_endian('<')
end
def test_pack_U
@@ -428,7 +449,6 @@ class TestPack < Test::Unit::TestCase
assert_operator(4, :<=, [1].pack("L!").bytesize)
end
- require 'rbconfig'
def test_pack_unpack_qQ
s1 = [578437695752307201, -506097522914230529].pack("q*")
s2 = [578437695752307201, 17940646550795321087].pack("Q*")
@@ -451,10 +471,8 @@ class TestPack < Test::Unit::TestCase
end if RbConfig::CONFIG['HAVE_LONG_LONG']
def test_pack_unpack_jJ
- # Note: we assume that the size of intptr_t and uintptr_t equals to the size
- # of real pointer.
- psize = [nil].pack("p").bytesize
- if psize == 4
+ case J_SIZE
+ when 4
s1 = [67305985, -50462977].pack("j*")
s2 = [67305985, 4244504319].pack("J*")
assert_equal(s1, s2)
@@ -468,7 +486,7 @@ class TestPack < Test::Unit::TestCase
assert_equal(4, [1].pack("j").bytesize)
assert_equal(4, [1].pack("J").bytesize)
- elsif psize == 8
+ when 8
s1 = [578437695752307201, -506097522914230529].pack("j*")
s2 = [578437695752307201, 17940646550795321087].pack("J*")
assert_equal(s1, s2)
@@ -638,6 +656,14 @@ EXPECTED
end;
end
+ def test_bug_18343
+ bug18343 = '[ruby-core:106096] [Bug #18343]'
+ assert_separately(%W[- #{bug18343}], <<-'end;')
+ bug = ARGV.shift
+ assert_raise(ArgumentError, bug){[0].pack('c', {})}
+ end;
+ end
+
def test_pack_unpack_m0
assert_equal("", [""].pack("m0"))
assert_equal("AA==", ["\0"].pack("m0"))
@@ -755,58 +781,32 @@ EXPECTED
end
def test_pack_garbage
- verbose = $VERBOSE
- $VERBOSE = false
-
- assert_silent do
+ assert_raise(ArgumentError, %r%unknown pack directive '\*' in '\*U'$%) do
assert_equal "\000", [0].pack("*U")
end
-
- $VERBOSE = true
-
- _, err = capture_output do
- assert_equal "\000", [0].pack("*U")
- end
-
- assert_match %r%unknown pack directive '\*' in '\*U'$%, err
- ensure
- $VERBOSE = verbose
end
def test_unpack_garbage
- verbose = $VERBOSE
- $VERBOSE = false
-
- assert_silent do
+ assert_raise(ArgumentError, %r%unknown unpack directive '\*' in '\*U'$%) do
assert_equal [0], "\000".unpack("*U")
end
-
- $VERBOSE = true
-
- _, err = capture_output do
- assert_equal [0], "\000".unpack("*U")
- end
-
- assert_match %r%unknown unpack directive '\*' in '\*U'$%, err
- ensure
- $VERBOSE = verbose
end
def test_invalid_warning
- assert_warning(/unknown pack directive ',' in ','/) {
+ assert_raise(ArgumentError, /unknown pack directive ',' in ','/) {
[].pack(",")
}
- assert_warning(/\A[ -~]+\Z/) {
+ assert_raise(ArgumentError, /\A[ -~]+\Z/) {
[].pack("\x7f")
}
- assert_warning(/\A(.* in '\u{3042}'\n)+\z/) {
+ assert_raise(ArgumentError, /\A(.* in '\u{3042}'\n)+\z/) {
[].pack("\u{3042}")
}
- assert_warning(/\A.* in '.*U'\Z/) {
+ assert_raise(ArgumentError, /\A.* in '.*U'\Z/) {
assert_equal "\000", [0].pack("\0U")
}
- assert_warning(/\A.* in '.*U'\Z/) {
+ assert_raise(ArgumentError, /\A.* in '.*U'\Z/) {
"\000".unpack("\0U")
}
end
@@ -869,4 +869,71 @@ EXPECTED
assert_equal "hogefuga", "aG9nZWZ1Z2E=".unpack1("m")
assert_equal "01000001", "A".unpack1("B*")
end
+
+ def test_unpack1_offset
+ assert_equal 65, "ZA".unpack1("C", offset: 1)
+ assert_equal "01000001", "YZA".unpack1("B*", offset: 2)
+ assert_nil "abc".unpack1("C", offset: 3)
+ assert_raise_with_message(ArgumentError, /offset can't be negative/) {
+ "a".unpack1("C", offset: -1)
+ }
+ assert_raise_with_message(ArgumentError, /offset outside of string/) {
+ "a".unpack1("C", offset: 2)
+ }
+ assert_nil "a".unpack1("C", offset: 1)
+ end
+
+ def test_unpack_offset
+ assert_equal [65], "ZA".unpack("C", offset: 1)
+ assert_equal ["01000001"], "YZA".unpack("B*", offset: 2)
+ assert_equal [nil, nil, nil], "abc".unpack("CCC", offset: 3)
+ assert_raise_with_message(ArgumentError, /offset can't be negative/) {
+ "a".unpack("C", offset: -1)
+ }
+ assert_raise_with_message(ArgumentError, /offset outside of string/) {
+ "a".unpack("C", offset: 2)
+ }
+ assert_equal [nil], "a".unpack("C", offset: 1)
+ end
+
+ def test_monkey_pack
+ assert_separately([], <<-'end;')
+ $-w = false
+ class Array
+ alias :old_pack :pack
+ def pack _; "oh no"; end
+ end
+
+ v = [2 ** 15].pack('n')
+
+ class Array
+ alias :pack :old_pack
+ end
+
+ assert_equal "oh no", v
+ end;
+ end
+
+ def test_monkey_pack_buffer
+ assert_separately([], <<-'end;')
+ $-w = false
+ class Array
+ alias :old_pack :pack
+ def pack _, buffer:; buffer << " no"; end
+ end
+
+ def test
+ b = +"oh"
+ [2 ** 15].pack('n', buffer: b)
+ end
+
+ v = test
+
+ class Array
+ alias :pack :old_pack
+ end
+
+ assert_equal "oh no", v
+ end;
+ end
end
diff --git a/test/ruby/test_parse.rb b/test/ruby/test_parse.rb
index 625b6eb223..d52e480eb9 100644
--- a/test/ruby/test_parse.rb
+++ b/test/ruby/test_parse.rb
@@ -14,10 +14,11 @@ class TestParse < Test::Unit::TestCase
def test_error_line
assert_syntax_error('------,,', /\n\z/, 'Message to pipe should end with a newline')
+ assert_syntax_error("{hello\n world}", /hello/)
end
def test_else_without_rescue
- assert_syntax_error(<<-END, %r":#{__LINE__+2}: else without rescue"o, [__FILE__, __LINE__+1])
+ assert_syntax_error(<<-END, %r"(:#{__LINE__+2}:|#{__LINE__+2} \|.+?\n.+?\^~.+?;) else without rescue"o, [__FILE__, __LINE__+1])
begin
else
42
@@ -377,10 +378,10 @@ class TestParse < Test::Unit::TestCase
def assert_disallowed_variable(type, noname, invalid)
noname.each do |name|
- assert_syntax_error("proc{a = #{name} }", "`#{noname[0]}' without identifiers is not allowed as #{type} variable name")
+ assert_syntax_error("proc{a = #{name} }", "'#{noname[0]}' without identifiers is not allowed as #{type} variable name")
end
invalid.each do |name|
- assert_syntax_error("proc {a = #{name} }", "`#{name}' is not allowed as #{type} variable name")
+ assert_syntax_error("proc {a = #{name} }", "'#{name}' is not allowed as #{type} variable name")
end
end
@@ -452,10 +453,46 @@ class TestParse < Test::Unit::TestCase
end
def test_define_singleton_error
- assert_syntax_error("#{<<~"begin;"}\n#{<<~'end;'}", /singleton method for literals/) do
- begin;
- def ("foo").foo; end
- end;
+ msg = /singleton method for literals/
+ assert_parse_error(%q[def ("foo").foo; end], msg)
+ assert_parse_error(%q[def (1).foo; end], msg)
+ assert_parse_error(%q[def ((1;1)).foo; end], msg)
+ assert_parse_error(%q[def ((;1)).foo; end], msg)
+ assert_parse_error(%q[def ((1+1;1)).foo; end], msg)
+ assert_parse_error(%q[def ((%s();1)).foo; end], msg)
+ assert_parse_error(%q[def ((%w();1)).foo; end], msg)
+ assert_parse_error(%q[def ("#{42}").foo; end], msg)
+ assert_parse_error(%q[def (:"#{42}").foo; end], msg)
+ assert_parse_error(%q[def ([]).foo; end], msg)
+ assert_parse_error(%q[def ([1]).foo; end], msg)
+ end
+
+ def test_flip_flop
+ all_assertions_foreach(nil,
+ ['(cond1..cond2)', true],
+ ['((cond1..cond2))', true],
+
+ # '(;;;cond1..cond2)', # don't care
+
+ '(1; cond1..cond2)',
+ '(%s(); cond1..cond2)',
+ '(%w(); cond1..cond2)',
+ '(1; (2; (3; 4; cond1..cond2)))',
+ '(1+1; cond1..cond2)',
+ ) do |code, pass|
+ code = code.sub("cond1", "n==4").sub("cond2", "n==5")
+ if pass
+ assert_equal([4,5], eval("(1..9).select {|n| true if #{code}}"))
+ else
+ assert_raise_with_message(ArgumentError, /bad value for range/, code) {
+ verbose_bak, $VERBOSE = $VERBOSE, nil # disable "warning: possibly useless use of a literal in void context"
+ begin
+ eval("[4].each {|n| true if #{code}}")
+ ensure
+ $VERBOSE = verbose_bak
+ end
+ }
+ end
end
end
@@ -463,6 +500,10 @@ class TestParse < Test::Unit::TestCase
t = Object.new
a = []
blk = proc {|x| a << x }
+
+ # Prevent an "assigned but unused variable" warning
+ _ = blk
+
def t.[](_)
yield(:aref)
nil
@@ -472,16 +513,16 @@ class TestParse < Test::Unit::TestCase
end
def t.dummy(_)
end
- eval <<-END, nil, __FILE__, __LINE__+1
+
+ assert_syntax_error("#{<<~"begin;"}\n#{<<~'end;'}", /block arg given in index assignment/)
+ begin;
t[42, &blk] ||= 42
- END
- assert_equal([:aref, :aset], a)
- a.clear
- eval <<-END, nil, __FILE__, __LINE__+1
- t[42, &blk] ||= t.dummy 42 # command_asgn test
- END
- assert_equal([:aref, :aset], a)
- blk
+ end;
+
+ assert_syntax_error("#{<<~"begin;"}\n#{<<~'end;'}", /block arg given in index assignment/)
+ begin;
+ t[42, &blk] ||= t.dummy 42 # command_asgn test
+ end;
end
def test_backquote
@@ -492,7 +533,7 @@ class TestParse < Test::Unit::TestCase
def t.`(x); "foo" + x + "bar"; end
END
end
- a = b = nil
+ a = b = c = nil
assert_nothing_raised do
eval <<-END, nil, __FILE__, __LINE__+1
a = t.` "zzz"
@@ -500,10 +541,12 @@ class TestParse < Test::Unit::TestCase
END
t.instance_eval <<-END, __FILE__, __LINE__+1
b = `zzz`
+ c = %x(ccc)
END
end
assert_equal("foozzzbar", a)
assert_equal("foozzzbar", b)
+ assert_equal("foocccbar", c)
end
def test_carrige_return
@@ -514,34 +557,42 @@ class TestParse < Test::Unit::TestCase
mesg = 'from the backslash through the invalid char'
e = assert_syntax_error('"\xg1"', /hex escape/)
- assert_equal(' ^~'"\n", e.message.lines.last, mesg)
+ assert_match(/(^|\| ) \^~(?!~)/, e.message.lines.last, mesg)
e = assert_syntax_error('"\u{1234"', 'unterminated Unicode escape')
- assert_equal(' ^'"\n", e.message.lines.last, mesg)
+ assert_match(/(^|\| ) \^(?!~)/, e.message.lines.last, mesg)
e = assert_syntax_error('"\u{xxxx}"', 'invalid Unicode escape')
- assert_equal(' ^'"\n", e.message.lines.last, mesg)
+ assert_match(/(^|\| ) \^(?!~)/, e.message.lines.last, mesg)
e = assert_syntax_error('"\u{xxxx', 'Unicode escape')
- assert_pattern_list([
- /.*: invalid Unicode escape\n.*\n/,
- / \^/,
- /\n/,
- /.*: unterminated Unicode escape\n.*\n/,
- / \^/,
- /\n/,
- /.*: unterminated string.*\n.*\n/,
- / \^\n/,
- ], e.message)
+ if e.message.lines.first == "#{__FILE__}:#{__LINE__ - 1}: syntax errors found\n"
+ assert_pattern_list([
+ /\s+\| \^ unterminated string;.+\n/,
+ /\s+\| \^ unterminated Unicode escape\n/,
+ /\s+\| \^ invalid Unicode escape sequence\n/,
+ ], e.message.lines[2..-1].join)
+ else
+ assert_pattern_list([
+ /.*: invalid Unicode escape\n.*\n/,
+ / \^/,
+ /\n/,
+ /.*: unterminated Unicode escape\n.*\n/,
+ / \^/,
+ /\n/,
+ /.*: unterminated string.*\n.*\n/,
+ / \^\n/,
+ ], e.message)
+ end
e = assert_syntax_error('"\M1"', /escape character syntax/)
- assert_equal(' ^~~'"\n", e.message.lines.last, mesg)
+ assert_match(/(^|\| ) \^~~(?!~)/, e.message.lines.last, mesg)
e = assert_syntax_error('"\C1"', /escape character syntax/)
- assert_equal(' ^~~'"\n", e.message.lines.last, mesg)
+ assert_match(/(^|\| ) \^~~(?!~)/, e.message.lines.last, mesg)
src = '"\xD0\u{90'"\n""000000000000000000000000"
- assert_syntax_error(src, /:#{__LINE__}: unterminated/o)
+ assert_syntax_error(src, /(:#{__LINE__}:|> #{__LINE__} \|.+) unterminated/om)
assert_syntax_error('"\u{100000000}"', /invalid Unicode escape/)
assert_equal("", eval('"\u{}"'))
@@ -564,19 +615,23 @@ class TestParse < Test::Unit::TestCase
assert_syntax_error("\"\\C-\\M-\x01\"", 'Invalid escape character syntax')
e = assert_syntax_error('"\c\u0000"', 'Invalid escape character syntax')
- assert_equal(' ^~~~'"\n", e.message.lines.last)
+ assert_match(/(^|\| ) \^~~~(?!~)/, e.message.lines.last)
e = assert_syntax_error('"\c\U0000"', 'Invalid escape character syntax')
- assert_equal(' ^~~~'"\n", e.message.lines.last)
+ assert_match(/(^|\| ) \^~~~(?!~)/, e.message.lines.last)
e = assert_syntax_error('"\C-\u0000"', 'Invalid escape character syntax')
- assert_equal(' ^~~~~'"\n", e.message.lines.last)
+ assert_match(/(^|\| ) \^~~~~(?!~)/, e.message.lines.last)
e = assert_syntax_error('"\C-\U0000"', 'Invalid escape character syntax')
- assert_equal(' ^~~~~'"\n", e.message.lines.last)
+ assert_match(/(^|\| ) \^~~~~(?!~)/, e.message.lines.last)
e = assert_syntax_error('"\M-\u0000"', 'Invalid escape character syntax')
- assert_equal(' ^~~~~'"\n", e.message.lines.last)
+ assert_match(/(^|\| ) \^~~~~(?!~)/, e.message.lines.last)
e = assert_syntax_error('"\M-\U0000"', 'Invalid escape character syntax')
- assert_equal(' ^~~~~'"\n", e.message.lines.last)
+ assert_match(/(^|\| ) \^~~~~(?!~)/, e.message.lines.last)
+
+ e = assert_syntax_error(%["\\C-\u3042"], 'Invalid escape character syntax')
+ assert_match(/(^|\|\s)\s \^(?# \\ ) ~(?# C ) ~(?# - ) ~+(?# U+3042 )($|\s)/x, e.message.lines.last)
+ assert_not_include(e.message, "invalid multibyte char")
end
def test_question
@@ -607,6 +662,8 @@ class TestParse < Test::Unit::TestCase
assert_syntax_error("?\\M-\x01", 'Invalid escape character syntax')
assert_syntax_error("?\\M-\\C-\x01", 'Invalid escape character syntax')
assert_syntax_error("?\\C-\\M-\x01", 'Invalid escape character syntax')
+
+ assert_equal("\xff", eval("# encoding: ascii-8bit\n""?\\\xFF"))
end
def test_percent
@@ -640,6 +697,7 @@ class TestParse < Test::Unit::TestCase
assert_syntax_error(':@@1', /is not allowed/)
assert_syntax_error(':@', /is not allowed/)
assert_syntax_error(':@1', /is not allowed/)
+ assert_syntax_error(':$01234', /is not allowed/)
end
def test_parse_string
@@ -680,6 +738,16 @@ FOO
eval "x = <<""FOO\r\n1\r\nFOO"
end
assert_equal("1\n", x)
+
+ assert_nothing_raised do
+ x = eval "<<' FOO'\n""[Bug #19539]\n"" FOO\n"
+ end
+ assert_equal("[Bug #19539]\n", x)
+
+ assert_nothing_raised do
+ x = eval "<<-' FOO'\n""[Bug #19539]\n"" FOO\n"
+ end
+ assert_equal("[Bug #19539]\n", x)
end
def test_magic_comment
@@ -715,6 +783,54 @@ x = __ENCODING__
END
end
assert_equal(__ENCODING__, x)
+
+ assert_raise(ArgumentError) do
+ EnvUtil.with_default_external(Encoding::US_ASCII) {eval <<-END, nil, __FILE__, __LINE__+1}
+# coding = external
+x = __ENCODING__
+ END
+ end
+
+ assert_raise(ArgumentError) do
+ EnvUtil.with_default_internal(Encoding::US_ASCII) {eval <<-END, nil, __FILE__, __LINE__+1}
+# coding = internal
+x = __ENCODING__
+ END
+ end
+
+ assert_raise(ArgumentError) do
+ eval <<-END, nil, __FILE__, __LINE__+1
+# coding = filesystem
+x = __ENCODING__
+ END
+ end
+
+ assert_raise(ArgumentError) do
+ eval <<-END, nil, __FILE__, __LINE__+1
+# coding = locale
+x = __ENCODING__
+ END
+ end
+
+ e = assert_raise(ArgumentError) do
+ eval <<-END, nil, __FILE__, __LINE__+1
+# coding: foo
+ END
+ end
+
+ message = e.message.gsub(/\033\[.*?m/, "")
+ assert_include(message, "# coding: foo\n")
+ assert_include(message, " ^")
+
+ e = assert_raise(ArgumentError) do
+ eval <<-END, nil, __FILE__, __LINE__+1
+# coding = foo
+ END
+ end
+
+ message = e.message.gsub(/\033\[.*?m/, "")
+ assert_include(message, "# coding = foo\n")
+ assert_include(message, " ^")
end
def test_utf8_bom
@@ -758,7 +874,7 @@ x = __ENCODING__
def test_float
assert_predicate(assert_warning(/out of range/) {eval("1e10000")}, :infinite?)
- assert_syntax_error('1_E', /trailing `_'/)
+ assert_syntax_error('1_E', /trailing '_'/)
assert_syntax_error('1E1E1', /unexpected constant/)
end
@@ -769,7 +885,8 @@ x = __ENCODING__
$test_parse_foobarbazqux = nil
assert_equal(nil, $&)
assert_equal(nil, eval('alias $& $preserve_last_match'))
- assert_syntax_error('a = $#', /as a global variable name\na = \$\#\n \^~$/)
+ assert_syntax_error('a = $#', /as a global variable name/)
+ assert_syntax_error('a = $#', /a = \$\#\n(^|.+?\| ) \^~(?!~)/)
end
def test_invalid_instance_variable
@@ -786,7 +903,7 @@ x = __ENCODING__
def test_invalid_char
bug10117 = '[ruby-core:64243] [Bug #10117]'
- invalid_char = /Invalid char `\\x01'/
+ invalid_char = /Invalid char '\\x01'/
x = 1
assert_in_out_err(%W"-e \x01x", "", [], invalid_char, bug10117)
assert_syntax_error("\x01x", invalid_char, bug10117)
@@ -820,24 +937,9 @@ x = __ENCODING__
assert_syntax_error("$& = 1", /Can't set variable/)
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, nil, __FILE__, __LINE__+1
- o[&proc{|x| r = x }] = 1
- END
- end
- assert_equal([1], r)
- end
-
def test_void_expr_stmts_value
x = 1
useless_use = /useless use/
- unused = /unused/
assert_nil assert_warning(useless_use) {eval("x; nil")}
assert_nil assert_warning(useless_use) {eval("1+1; nil")}
assert_nil assert_warning('') {eval("1.+(1); nil")}
@@ -845,24 +947,27 @@ x = __ENCODING__
assert_nil assert_warning(useless_use) {eval("::TestParse; nil")}
assert_nil assert_warning(useless_use) {eval("x..x; nil")}
assert_nil assert_warning(useless_use) {eval("x...x; nil")}
- assert_nil assert_warning(unused) {eval("self; nil")}
- assert_nil assert_warning(unused) {eval("nil; nil")}
- assert_nil assert_warning(unused) {eval("true; nil")}
- assert_nil assert_warning(unused) {eval("false; nil")}
+ assert_nil assert_warning(useless_use) {eval("self; nil")}
+ assert_nil assert_warning(useless_use) {eval("nil; nil")}
+ assert_nil assert_warning(useless_use) {eval("true; nil")}
+ assert_nil assert_warning(useless_use) {eval("false; nil")}
assert_nil assert_warning(useless_use) {eval("defined?(1); nil")}
+ assert_nil assert_warning(useless_use) {eval("begin; ensure; x; end")}
assert_equal 1, x
assert_syntax_error("1; next; 2", /Invalid next/)
end
def test_assign_in_conditional
- assert_warning(/`= literal' in conditional/) do
+ # multiple assignment
+ assert_warning(/'= literal' in conditional/) do
eval <<-END, nil, __FILE__, __LINE__+1
(x, y = 1, 2) ? 1 : 2
END
end
- assert_warning(/`= literal' in conditional/) do
+ # instance variable assignment
+ assert_warning(/'= literal' in conditional/) do
eval <<-END, nil, __FILE__, __LINE__+1
if @x = true
1
@@ -871,6 +976,71 @@ x = __ENCODING__
end
END
end
+
+ # local variable assignment
+ assert_warning(/'= literal' in conditional/) do
+ eval <<-END, nil, __FILE__, __LINE__+1
+ def m
+ if x = true
+ 1
+ else
+ 2
+ end
+ end
+ END
+ end
+
+ # global variable assignment
+ assert_separately([], <<-RUBY)
+ assert_warning(/'= literal' in conditional/) do
+ eval <<-END, nil, __FILE__, __LINE__+1
+ if $x = true
+ 1
+ else
+ 2
+ end
+ END
+ end
+ RUBY
+
+ # dynamic variable assignment
+ assert_warning(/'= literal' in conditional/) do
+ eval <<-END, nil, __FILE__, __LINE__+1
+ y = 1
+
+ 1.times do
+ if y = true
+ 1
+ else
+ 2
+ end
+ end
+ END
+ end
+
+ # class variable assignment
+ assert_warning(/'= literal' in conditional/) do
+ eval <<-END, nil, __FILE__, __LINE__+1
+ c = Class.new
+ class << c
+ if @@a = 1
+ end
+ end
+ END
+ end
+
+ # constant declaration
+ assert_separately([], <<-RUBY)
+ assert_warning(/'= literal' in conditional/) do
+ eval <<-END, nil, __FILE__, __LINE__+1
+ if Const = true
+ 1
+ else
+ 2
+ end
+ END
+ end
+ RUBY
end
def test_literal_in_conditional
@@ -930,6 +1100,10 @@ x = __ENCODING__
assert_no_warning(/shadowing outer local variable/) {eval("a=1; tap {|a|}")}
end
+ def test_shadowing_private_local_variable
+ assert_equal 1, eval("_ = 1; [[2]].each{ |(_)| }; _")
+ end
+
def test_unused_variable
o = Object.new
assert_warning(/assigned but unused variable/) {o.instance_eval("def foo; a=1; nil; end")}
@@ -943,6 +1117,20 @@ x = __ENCODING__
assert_warning('') {o.instance_eval("def marg2((a)); nil; end")}
end
+ def test_parsing_begin_statement_inside_method_definition
+ assert_equal :bug_20234, eval("def (begin;end).bug_20234; end")
+ NilClass.remove_method(:bug_20234)
+ assert_equal :bug_20234, eval("def (begin;rescue;end).bug_20234; end")
+ NilClass.remove_method(:bug_20234)
+ assert_equal :bug_20234, eval("def (begin;ensure;end).bug_20234; end")
+ NilClass.remove_method(:bug_20234)
+ assert_equal :bug_20234, eval("def (begin;rescue;else;end).bug_20234; end")
+ NilClass.remove_method(:bug_20234)
+
+ assert_raise(SyntaxError) { eval("def (begin;else;end).bug_20234; end") }
+ assert_raise(SyntaxError) { eval("def (begin;ensure;else;end).bug_20234; end") }
+ end
+
def test_named_capture_conflict
a = 1
assert_warning('') {eval("a = 1; /(?<a>)/ =~ ''")}
@@ -950,6 +1138,30 @@ x = __ENCODING__
assert_warning('') {eval("#{a} = 1; /(?<#{a}>)/ =~ ''")}
end
+ def test_named_capture_in_block
+ all_assertions_foreach(nil,
+ '(/(?<a>.*)/)',
+ '(;/(?<a>.*)/)',
+ '(%s();/(?<a>.*)/)',
+ '(%w();/(?<a>.*)/)',
+ '(1; (2; 3; (4; /(?<a>.*)/)))',
+ '(1+1; /(?<a>.*)/)',
+ '/#{""}(?<a>.*)/',
+ ) do |code, pass|
+ token = Random.bytes(4).unpack1("H*")
+ if pass
+ assert_equal(token, eval("#{code} =~ #{token.dump}; a"))
+ else
+ verbose_bak, $VERBOSE = $VERBOSE, nil # disable "warning: possibly useless use of a literal in void context"
+ begin
+ assert_nil(eval("#{code} =~ #{token.dump}; defined?(a)"), code)
+ ensure
+ $VERBOSE = verbose_bak
+ end
+ end
+ end
+ end
+
def test_rescue_in_command_assignment
bug = '[ruby-core:75621] [Bug #12402]'
all_assertions(bug) do |a|
@@ -1037,14 +1249,30 @@ x = __ENCODING__
assert_syntax_error(" 0b\n", /\^/)
end
+ def test_unclosed_unicode_escape_at_eol_bug_19750
+ assert_separately([], "#{<<-"begin;"}\n#{<<~'end;'}")
+ begin;
+ assert_syntax_error("/\\u", /too short escape sequence/)
+ assert_syntax_error("/\\u{", /unterminated regexp meets end of file/)
+ assert_syntax_error("/\\u{\\n", /invalid Unicode list/)
+ assert_syntax_error("/a#\\u{\\n/", /invalid Unicode list/)
+ re = eval("/a#\\u{\n$/x")
+ assert_match(re, 'a')
+ assert_not_match(re, 'a#')
+ re = eval("/a#\\u\n$/x")
+ assert_match(re, 'a')
+ assert_not_match(re, 'a#')
+ end;
+ end
+
def test_error_def_in_argument
assert_separately([], "#{<<-"begin;"}\n#{<<~"end;"}")
begin;
assert_syntax_error("def f r:def d; def f 0end", /unexpected/)
end;
- assert_syntax_error("def\nf(000)end", /^ \^~~/)
- assert_syntax_error("def\nf(&)end", /^ \^/)
+ assert_syntax_error("def\nf(000)end", /(^|\| ) \^~~/)
+ assert_syntax_error("def\nf(&0)end", /(^|\| ) \^/)
end
def test_method_location_in_rescue
@@ -1080,46 +1308,61 @@ x = __ENCODING__
end;
end
- def test_heredoc_interpolation
- var = 1
+ def test_heredoc_interpolation
+ var = 1
- v1 = <<~HEREDOC
- something
- #{"/#{var}"}
- HEREDOC
+ v1 = <<~HEREDOC
+ something
+ #{"/#{var}"}
+ HEREDOC
- v2 = <<~HEREDOC
- something
- #{_other = "/#{var}"}
- HEREDOC
+ v2 = <<~HEREDOC
+ something
+ #{_other = "/#{var}"}
+ HEREDOC
- v3 = <<~HEREDOC
- something
- #{("/#{var}")}
- HEREDOC
+ v3 = <<~HEREDOC
+ something
+ #{("/#{var}")}
+ HEREDOC
- assert_equal "something\n/1\n", v1
- assert_equal "something\n/1\n", v2
- assert_equal "something\n/1\n", v3
- assert_equal v1, v2
- assert_equal v2, v3
- assert_equal v1, v3
- end
+ assert_equal "something\n/1\n", v1
+ assert_equal "something\n/1\n", v2
+ assert_equal "something\n/1\n", v3
+ assert_equal v1, v2
+ assert_equal v2, v3
+ assert_equal v1, v3
+ end
+
+ def test_heredoc_unterminated_interpolation
+ code = <<~'HEREDOC'
+ <<A+1
+ #{
+ HEREDOC
+
+ assert_syntax_error(code, /can't find string "A"/)
+ end
def test_unexpected_token_error
assert_syntax_error('"x"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', /unexpected/)
end
def test_unexpected_token_after_numeric
- assert_syntax_error('0000xyz', /^ \^~~\Z/)
- assert_syntax_error('1.2i1.1', /^ \^~~\Z/)
- assert_syntax_error('1.2.3', /^ \^~\Z/)
+ assert_syntax_error('0000xyz', /(^|\| ) \^~~(?!~)/)
+ assert_syntax_error('1.2i1.1', /(^|\| ) \^~~(?!~)/)
+ assert_syntax_error('1.2.3', /(^|\| ) \^~(?!~)/)
+ assert_syntax_error('1.', /unexpected end-of-input/)
+ assert_syntax_error('1e', /expecting end-of-input/)
end
def test_truncated_source_line
- e = assert_syntax_error("'0123456789012345678901234567890123456789' abcdefghijklmnopqrstuvwxyz0123456789 0123456789012345678901234567890123456789",
+ lineno = __LINE__ + 1
+ e = assert_syntax_error("'0123456789012345678901234567890123456789' abcdefghijklmnopqrstuvwxyz0123456789 123456789012345678901234567890123456789",
/unexpected local variable or method/)
+
line = e.message.lines[1]
+ line.delete_prefix!("> #{lineno} | ") if line.start_with?(">")
+
assert_operator(line, :start_with?, "...")
assert_operator(line, :end_with?, "...\n")
end
@@ -1162,8 +1405,12 @@ x = __ENCODING__
assert_syntax_error("def m\n\C-z""end", /unexpected/)
end
+ def test_unexpected_eof
+ assert_syntax_error('unless', /(^|\| ) \^(?!~)/)
+ end
+
def test_location_of_invalid_token
- assert_syntax_error('class xxx end', /^ \^~~\Z/)
+ assert_syntax_error('class xxx end', /(^|\| ) \^~~(?!~)/)
end
def test_whitespace_warning
@@ -1227,10 +1474,25 @@ x = __ENCODING__
assert_valid_syntax('let () { m(a) do; end }')
end
- def test_void_value_in_command_rhs
+ def test_void_value_in_rhs
w = "void value expression"
- ex = assert_syntax_error("x = return 1", w)
- assert_equal(1, ex.message.scan(w).size, "same #{w.inspect} warning should be just once")
+ [
+ "x = return 1", "x = return, 1", "x = 1, return", "x, y = return",
+ "x = begin return ensure end",
+ "x = begin ensure return end",
+ "x = begin return ensure return end",
+ "x = begin return; rescue; return end",
+ "x = begin return; rescue; return; else return end",
+ ].each do |code|
+ ex = assert_syntax_error(code, w)
+ assert_equal(1, ex.message.scan(w).size, ->{"same #{w.inspect} warning should be just once\n#{w.message}"})
+ end
+ [
+ "x = begin return; rescue; end",
+ "x = begin return; rescue; return; else end",
+ ].each do |code|
+ assert_valid_syntax(code)
+ end
end
def eval_separately(code)
@@ -1294,6 +1556,39 @@ x = __ENCODING__
assert_not_ractor_shareable(obj)
assert_equal obj, a
assert !obj.equal?(a)
+
+ bug_20339 = '[ruby-core:117186] [Bug #20339]'
+ bug_20341 = '[ruby-core:117197] [Bug #20341]'
+ a, b = eval_separately(<<~'end;')
+ # shareable_constant_value: literal
+ foo = 1
+ bar = 2
+ A = { foo => bar }
+ B = [foo, bar]
+ [A, B]
+ end;
+
+ assert_ractor_shareable(a)
+ assert_ractor_shareable(b)
+ assert_equal([1], a.keys, bug_20339)
+ assert_equal([2], a.values, bug_20339)
+ assert_equal(1, b[0], bug_20341)
+ assert_equal(2, b[1], bug_20341)
+ end
+
+ def test_shareable_constant_value_literal_const_refs
+ a = eval_separately("#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ # shareable_constant_value: literal
+ # [Bug #20668]
+ SOME_CONST = {
+ 'Object' => Object,
+ 'String' => String,
+ 'Array' => Array,
+ }
+ SOME_CONST
+ end;
+ assert_ractor_shareable(a)
end
def test_shareable_constant_value_nested
@@ -1315,12 +1610,71 @@ x = __ENCODING__
end
def test_shareable_constant_value_unshareable_literal
- assert_raise_separately(Ractor::IsolationError, /unshareable/,
+ assert_raise_separately(Ractor::IsolationError, /unshareable object to C/,
"#{<<~"begin;"}\n#{<<~'end;'}")
begin;
# shareable_constant_value: literal
C = ["Not " + "shareable"]
end;
+
+ assert_raise_separately(Ractor::IsolationError, /unshareable object to B::C/,
+ "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ # shareable_constant_value: literal
+ B = Class.new
+ B::C = ["Not " + "shareable"]
+ end;
+
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ assert_raise_with_message(Ractor::IsolationError, /unshareable object to ::C/) do
+ # shareable_constant_value: literal
+ ::C = ["Not " + "shareable"]
+ end
+ end;
+
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ assert_raise_with_message(Ractor::IsolationError, /unshareable object to ::B::C/) do
+ # shareable_constant_value: literal
+ ::B = Class.new
+ ::B::C = ["Not " + "shareable"]
+ end
+ end;
+
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ assert_raise_with_message(Ractor::IsolationError, /unshareable object to ::C/) do
+ # shareable_constant_value: literal
+ ::C ||= ["Not " + "shareable"]
+ end
+ end;
+
+ assert_raise_separately(Ractor::IsolationError, /unshareable object to B::C/,
+ "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ # shareable_constant_value: literal
+ B = Class.new
+ B::C ||= ["Not " + "shareable"]
+ end;
+
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ assert_raise_with_message(Ractor::IsolationError, /unshareable object to ::B::C/) do
+ # shareable_constant_value: literal
+ ::B = Class.new
+ ::B::C ||= ["Not " + "shareable"]
+ end
+ end;
+
+ assert_raise_separately(Ractor::IsolationError, /unshareable object to ...::C/,
+ "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ # shareable_constant_value: literal
+ B = Class.new
+ def self.expr; B; end
+ expr::C ||= ["Not " + "shareable"]
+ end;
end
def test_shareable_constant_value_nonliteral
@@ -1349,9 +1703,75 @@ x = __ENCODING__
end;
end
+ def test_if_after_class
+ assert_valid_syntax('module if true; Object end::Kernel; end')
+ assert_valid_syntax('module while true; break Object end::Kernel; end')
+ assert_valid_syntax('class if true; Object end::Kernel; end')
+ assert_valid_syntax('class while true; break Object end::Kernel; end')
+ end
+
+ def test_escaped_space
+ assert_syntax_error('x = \ 42', /escaped space/)
+ end
+
+ def test_label
+ expected = {:foo => 1}
+
+ code = '{"foo": 1}'
+ assert_valid_syntax(code)
+ assert_equal(expected, eval(code))
+
+ code = '{foo: 1}'
+ assert_valid_syntax(code)
+ assert_equal(expected, eval(code))
+
+ class << (obj = Object.new)
+ attr_reader :arg
+ def set(arg)
+ @arg = arg
+ end
+ end
+
+ assert_valid_syntax(code = "#{<<~"do;"}\n#{<<~'end;'}")
+ do;
+ obj.set foo:
+ 1
+ end;
+ assert_equal(expected, eval(code))
+ assert_equal(expected, obj.arg)
+
+ assert_valid_syntax(code = "#{<<~"do;"}\n#{<<~'end;'}")
+ do;
+ obj.set "foo":
+ 1
+ end;
+ assert_equal(expected, eval(code))
+ assert_equal(expected, obj.arg)
+ end
+
+ def test_ungettable_gvar
+ assert_syntax_error('$01234', /not allowed/)
+ assert_syntax_error('"#$01234"', /not allowed/)
+ end
+
=begin
def test_past_scope_variable
assert_warning(/past scope/) {catch {|tag| eval("BEGIN{throw tag}; tap {a = 1}; a")}}
end
=end
+
+ def assert_parse(code)
+ assert_kind_of(RubyVM::AbstractSyntaxTree::Node, RubyVM::AbstractSyntaxTree.parse(code))
+ end
+
+ def assert_parse_error(code, message)
+ assert_raise_with_message(SyntaxError, message) do
+ $VERBOSE, verbose_bak = nil, $VERBOSE
+ begin
+ RubyVM::AbstractSyntaxTree.parse(code)
+ ensure
+ $VERBOSE = verbose_bak
+ end
+ end
+ end
end
diff --git a/test/ruby/test_pattern_matching.rb b/test/ruby/test_pattern_matching.rb
index 277a0dcc51..cfe3bd1e19 100644
--- a/test/ruby/test_pattern_matching.rb
+++ b/test/ruby/test_pattern_matching.rb
@@ -1,9 +1,26 @@
# frozen_string_literal: true
require 'test/unit'
-experimental, Warning[:experimental] = Warning[:experimental], false # suppress "warning: Pattern matching is experimental, and the behavior may change in future versions of Ruby!"
-eval "\n#{<<~'END_of_GUARD'}", binding, __FILE__, __LINE__
class TestPatternMatching < Test::Unit::TestCase
+ class NullFormatter
+ def message_for(corrections)
+ ""
+ end
+ end
+
+ def setup
+ if defined?(DidYouMean.formatter=nil)
+ @original_formatter = DidYouMean.formatter
+ DidYouMean.formatter = NullFormatter.new
+ end
+ end
+
+ def teardown
+ if defined?(DidYouMean.formatter=nil)
+ DidYouMean.formatter = @original_formatter
+ end
+ end
+
class C
class << self
attr_accessor :keys
@@ -92,16 +109,12 @@ class TestPatternMatching < Test::Unit::TestCase
end
assert_block do
- # suppress "warning: Pattern matching is experimental, and the behavior may change in future versions of Ruby!"
- experimental, Warning[:experimental] = Warning[:experimental], false
eval(%q{
case true
in a
a
end
})
- ensure
- Warning[:experimental] = experimental
end
assert_block do
@@ -341,6 +354,14 @@ END
end
assert_block do
+ a = "abc"
+ case 'abc'
+ in /#{a}/o
+ true
+ end
+ end
+
+ assert_block do
case 0
in ->(i) { i == 0 }
true
@@ -447,6 +468,8 @@ END
true
end
end
+
+ assert_valid_syntax("1 in ^(1\n)")
end
def test_array_pattern
@@ -781,6 +804,10 @@ END
true
end
end
+
+ assert_syntax_error(%q{
+ 0 => [a, *a]
+ }, /duplicated variable name/)
end
def test_find_pattern
@@ -849,6 +876,10 @@ END
false
end
end
+
+ assert_syntax_error(%q{
+ 0 => [*a, a, b, *b]
+ }, /duplicated variable name/)
end
def test_hash_pattern
@@ -1138,6 +1169,28 @@ END
end
end
+ bug18890 = assert_warning(/(?:.*:[47]: warning: possibly useless use of a literal in void context\n){2}/) do
+ eval("#{<<~';;;'}")
+ proc do |i|
+ case i
+ in a:
+ 0 # line 4
+ a
+ in "b":
+ 0 # line 7
+ b
+ else
+ false
+ end
+ end
+ ;;;
+ end
+ [{a: 42}, {b: 42}].each do |i|
+ assert_block('newline should be significant after pattern label') do
+ bug18890.call(i)
+ end
+ end
+
assert_syntax_error(%q{
case _
in a:, a:
@@ -1278,7 +1331,7 @@ END
end
assert_block do
- case {}
+ case C.new({})
in {}
C.keys == nil
end
@@ -1531,20 +1584,16 @@ END
assert_equal false, (1 in 2)
end
- def assert_experimental_warning(code)
- w = Warning[:experimental]
-
- Warning[:experimental] = false
- assert_warn('') {eval(code)}
-
- Warning[:experimental] = true
- assert_warn(/is experimental/) {eval(code)}
- ensure
- Warning[:experimental] = w
- end
+ def test_bug18990
+ {a: 0} => a:
+ assert_equal 0, a
+ {a: 0} => a:
+ assert_equal 0, a
- def test_experimental_warning
- assert_experimental_warning("case [0]; in [*, 0, *]; end")
+ {a: 0} in a:
+ assert_equal 0, a
+ {a: 0} in a:
+ assert_equal 0, a
end
################################################################
@@ -1674,5 +1723,3 @@ END
end
end
end
-END_of_GUARD
-Warning[:experimental] = experimental
diff --git a/test/ruby/test_proc.rb b/test/ruby/test_proc.rb
index 16efd13d7c..dd05d09a49 100644
--- a/test/ruby/test_proc.rb
+++ b/test/ruby/test_proc.rb
@@ -207,18 +207,24 @@ class TestProc < Test::Unit::TestCase
end
def test_block_given_method
+ verbose_bak, $VERBOSE = $VERBOSE, nil
m = method(:m_block_given?)
assert(!m.call, "without block")
assert(m.call {}, "with block")
assert(!m.call, "without block second")
+ ensure
+ $VERBOSE = verbose_bak
end
def test_block_given_method_to_proc
+ verbose_bak, $VERBOSE = $VERBOSE, nil
bug8341 = '[Bug #8341]'
m = method(:m_block_given?).to_proc
assert(!m.call, "#{bug8341} without block")
assert(m.call {}, "#{bug8341} with block")
assert(!m.call, "#{bug8341} without block second")
+ ensure
+ $VERBOSE = verbose_bak
end
def test_block_persist_between_calls
@@ -289,7 +295,6 @@ class TestProc < Test::Unit::TestCase
assert_equal(false, l.lambda?)
assert_equal(false, l.curry.lambda?, '[ruby-core:24127]')
assert_equal(false, proc(&l).lambda?)
- assert_equal(false, assert_deprecated_warning {lambda(&l)}.lambda?)
assert_equal(false, Proc.new(&l).lambda?)
l = lambda {}
assert_equal(true, l.lambda?)
@@ -299,47 +304,21 @@ class TestProc < Test::Unit::TestCase
assert_equal(true, Proc.new(&l).lambda?)
end
- def self.helper_test_warn_lamda_with_passed_block &b
- lambda(&b)
- end
-
- def self.def_lambda_warning name, warn
- define_method(name, proc do
- prev = Warning[:deprecated]
- assert_warn warn do
- Warning[:deprecated] = true
- yield
- end
- ensure
- Warning[:deprecated] = prev
- end)
- end
-
- def_lambda_warning 'test_lambda_warning_normal', '' do
- lambda{}
- end
-
- def_lambda_warning 'test_lambda_warning_pass_lambda', '' do
- b = lambda{}
- lambda(&b)
- end
-
- def_lambda_warning 'test_lambda_warning_pass_symbol_proc', '' do
- lambda(&:to_s)
- end
-
- def_lambda_warning 'test_lambda_warning_pass_proc', /deprecated/ do
- b = proc{}
+ def helper_test_warn_lambda_with_passed_block &b
lambda(&b)
end
- def_lambda_warning 'test_lambda_warning_pass_block', /deprecated/ do
- helper_test_warn_lamda_with_passed_block{}
+ def test_lambda_warning_pass_proc
+ assert_raise(ArgumentError) do
+ b = proc{}
+ lambda(&b)
+ end
end
- def_lambda_warning 'test_lambda_warning_pass_block_symbol_proc', '' do
- # Symbol#to_proc returns lambda
- helper_test_warn_lamda_with_passed_block(&:to_s)
+ def test_lambda_warning_pass_block
+ assert_raise(ArgumentError) do
+ helper_test_warn_lambda_with_passed_block{}
+ end
end
def test_curry_ski_fib
@@ -412,6 +391,20 @@ class TestProc < Test::Unit::TestCase
assert_equal(:foo, bc.foo)
end
+ def test_dup_subclass
+ c1 = Class.new(Proc)
+ assert_equal c1, c1.new{}.dup.class, '[Bug #17545]'
+ c1 = Class.new(Proc) {def initialize_dup(*) throw :initialize_dup; end}
+ assert_throw(:initialize_dup) {c1.new{}.dup}
+ end
+
+ def test_clone_subclass
+ c1 = Class.new(Proc)
+ assert_equal c1, c1.new{}.clone.class, '[Bug #17545]'
+ c1 = Class.new(Proc) {def initialize_clone(*) throw :initialize_clone; end}
+ assert_throw(:initialize_clone) {c1.new{}.clone}
+ end
+
def test_binding
b = proc {|x, y, z| proc {}.binding }.call(1, 2, 3)
class << b; attr_accessor :foo; end
@@ -440,6 +433,11 @@ class TestProc < Test::Unit::TestCase
assert_equal(@@line_of_source_location_test, lineno, 'Bug #2427')
end
+ def test_binding_error_unless_ruby_frame
+ define_singleton_method :binding_from_c!, method(:binding).to_proc >> ->(bndg) {bndg}
+ assert_raise(RuntimeError) { binding_from_c! }
+ end
+
def test_proc_lambda
assert_raise(ArgumentError) { proc }
assert_raise(ArgumentError) { assert_warn(/deprecated/) {lambda} }
@@ -847,6 +845,88 @@ class TestProc < Test::Unit::TestCase
assert_equal [[1, 2], Proc, :x], (pr.call(1, 2){|x| x})
end
+ def test_proc_args_single_kw_no_autosplat
+ pr = proc {|c, a: 1| [c, a] }
+ assert_equal [nil, 1], pr.call()
+ assert_equal [1, 1], pr.call(1)
+ assert_equal [[1], 1], pr.call([1])
+ assert_equal [1, 1], pr.call(1,2)
+ assert_equal [[1, 2], 1], pr.call([1,2])
+
+ assert_equal [nil, 3], pr.call(a: 3)
+ assert_equal [1, 3], pr.call(1, a: 3)
+ assert_equal [[1], 3], pr.call([1], a: 3)
+ assert_equal [1, 3], pr.call(1,2, a: 3)
+ assert_equal [[1, 2], 3], pr.call([1,2], a: 3)
+ end
+
+ def test_proc_args_single_kwsplat_no_autosplat
+ pr = proc {|c, **kw| [c, kw] }
+ assert_equal [nil, {}], pr.call()
+ assert_equal [1, {}], pr.call(1)
+ assert_equal [[1], {}], pr.call([1])
+ assert_equal [1, {}], pr.call(1,2)
+ assert_equal [[1, 2], {}], pr.call([1,2])
+
+ assert_equal [nil, {a: 3}], pr.call(a: 3)
+ assert_equal [1, {a: 3}], pr.call(1, a: 3)
+ assert_equal [[1], {a: 3}], pr.call([1], a: 3)
+ assert_equal [1, {a: 3}], pr.call(1,2, a: 3)
+ assert_equal [[1, 2], {a: 3}], pr.call([1,2], a: 3)
+ end
+
+ def test_proc_args_multiple_kw_autosplat
+ pr = proc {|c, b, a: 1| [c, b, a] }
+ assert_equal [1, 2, 1], pr.call([1,2])
+
+ pr = proc {|c=nil, b=nil, a: 1| [c, b, a] }
+ assert_equal [nil, nil, 1], pr.call([])
+ assert_equal [1, nil, 1], pr.call([1])
+ assert_equal [1, 2, 1], pr.call([1,2])
+
+ pr = proc {|c, b=nil, a: 1| [c, b, a] }
+ assert_equal [1, nil, 1], pr.call([1])
+ assert_equal [1, 2, 1], pr.call([1,2])
+
+ pr = proc {|c=nil, b, a: 1| [c, b, a] }
+ assert_equal [nil, 1, 1], pr.call([1])
+ assert_equal [1, 2, 1], pr.call([1,2])
+
+ pr = proc {|c, *b, a: 1| [c, b, a] }
+ assert_equal [1, [], 1], pr.call([1])
+ assert_equal [1, [2], 1], pr.call([1,2])
+
+ pr = proc {|*c, b, a: 1| [c, b, a] }
+ assert_equal [[], 1, 1], pr.call([1])
+ assert_equal [[1], 2, 1], pr.call([1,2])
+ end
+
+ def test_proc_args_multiple_kwsplat_autosplat
+ pr = proc {|c, b, **kw| [c, b, kw] }
+ assert_equal [1, 2, {}], pr.call([1,2])
+
+ pr = proc {|c=nil, b=nil, **kw| [c, b, kw] }
+ assert_equal [nil, nil, {}], pr.call([])
+ assert_equal [1, nil, {}], pr.call([1])
+ assert_equal [1, 2, {}], pr.call([1,2])
+
+ pr = proc {|c, b=nil, **kw| [c, b, kw] }
+ assert_equal [1, nil, {}], pr.call([1])
+ assert_equal [1, 2, {}], pr.call([1,2])
+
+ pr = proc {|c=nil, b, **kw| [c, b, kw] }
+ assert_equal [nil, 1, {}], pr.call([1])
+ assert_equal [1, 2, {}], pr.call([1,2])
+
+ pr = proc {|c, *b, **kw| [c, b, kw] }
+ assert_equal [1, [], {}], pr.call([1])
+ assert_equal [1, [2], {}], pr.call([1,2])
+
+ pr = proc {|*c, b, **kw| [c, b, kw] }
+ assert_equal [[], 1, {}], pr.call([1])
+ assert_equal [[1], 2, {}], pr.call([1,2])
+ end
+
def test_proc_args_only_rest
pr = proc {|*c| c }
assert_equal [], pr.call()
@@ -1229,6 +1309,54 @@ class TestProc < Test::Unit::TestCase
assert_empty(pr.parameters.map{|_,n|n}.compact)
end
+ def test_proc_autosplat_with_multiple_args_with_ruby2_keywords_splat_bug_19759
+ def self.yielder_ab(splat)
+ yield([:a, :b], *splat)
+ end
+
+ res = yielder_ab([[:aa, :bb], Hash.ruby2_keywords_hash({k: :k})]) do |a, b, k:|
+ [a, b, k]
+ end
+ assert_equal([[:a, :b], [:aa, :bb], :k], res)
+
+ def self.yielder(splat)
+ yield(*splat)
+ end
+ res = yielder([ [:a, :b] ]){|a, b, **| [a, b]}
+ assert_equal([:a, :b], res)
+
+ res = yielder([ [:a, :b], Hash.ruby2_keywords_hash({}) ]){|a, b, **| [a, b]}
+ assert_equal([[:a, :b], nil], res)
+
+ res = yielder([ [:a, :b], Hash.ruby2_keywords_hash({c: 1}) ]){|a, b, **| [a, b]}
+ assert_equal([[:a, :b], nil], res)
+
+ res = yielder([ [:a, :b], Hash.ruby2_keywords_hash({}) ]){|a, b, **nil| [a, b]}
+ assert_equal([[:a, :b], nil], res)
+ end
+
+ def test_parameters_lambda
+ assert_equal([], proc {}.parameters(lambda: true))
+ assert_equal([], proc {||}.parameters(lambda: true))
+ assert_equal([[:req, :a]], proc {|a|}.parameters(lambda: true))
+ assert_equal([[:req, :a], [:req, :b]], proc {|a, b|}.parameters(lambda: true))
+ assert_equal([[:opt, :a], [:block, :b]], proc {|a=:a, &b|}.parameters(lambda: true))
+ assert_equal([[:req, :a], [:opt, :b]], proc {|a, b=:b|}.parameters(lambda: true))
+ assert_equal([[:rest, :a]], proc {|*a|}.parameters(lambda: true))
+ assert_equal([[:req, :a], [:rest, :b], [:block, :c]], proc {|a, *b, &c|}.parameters(lambda: true))
+ assert_equal([[:req, :a], [:rest, :b], [:req, :c]], proc {|a, *b, c|}.parameters(lambda: true))
+ assert_equal([[:req, :a], [:rest, :b], [:req, :c], [:block, :d]], proc {|a, *b, c, &d|}.parameters(lambda: true))
+ assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:block, :e]], proc {|a, b=:b, *c, d, &e|}.parameters(lambda: true))
+ assert_equal([[:req], [:block, :b]], proc {|(a), &b|a}.parameters(lambda: true))
+ assert_equal([[:req, :a], [:req, :b], [:opt, :c], [:opt, :d], [:rest, :e], [:req, :f], [:req, :g], [:block, :h]], proc {|a,b,c=:c,d=:d,*e,f,g,&h|}.parameters(lambda: true))
+
+ pr = eval("proc{|"+"(_),"*30+"|}")
+ assert_empty(pr.parameters(lambda: true).map{|_,n|n}.compact)
+
+ assert_equal([[:opt, :a]], lambda {|a|}.parameters(lambda: false))
+ assert_equal([[:opt, :a], [:opt, :b], [:opt, :c], [:opt, :d], [:rest, :e], [:opt, :f], [:opt, :g], [:block, :h]], lambda {|a,b,c=:c,d=:d,*e,f,g,&h|}.parameters(lambda: false))
+ end
+
def pm0() end
def pm1(a) end
def pm2(a, b) end
@@ -1261,7 +1389,7 @@ class TestProc < Test::Unit::TestCase
assert_equal([[:req, :a], [:rest, :b], [:req, :c], [:block, :d]], method(:pmo6).to_proc.parameters)
assert_equal([[:req, :a], [:opt, :b], [:rest, :c], [:req, :d], [:block, :e]], method(:pmo7).to_proc.parameters)
assert_equal([[:req], [:block, :b]], method(:pma1).to_proc.parameters)
- assert_equal([[:keyrest]], method(:pmk1).to_proc.parameters)
+ assert_equal([[:keyrest, :**]], method(:pmk1).to_proc.parameters)
assert_equal([[:keyrest, :o]], method(:pmk2).to_proc.parameters)
assert_equal([[:req, :a], [:keyrest, :o]], method(:pmk3).to_proc.parameters)
assert_equal([[:opt, :a], [:keyrest, :o]], method(:pmk4).to_proc.parameters)
@@ -1597,18 +1725,24 @@ class TestProc < Test::Unit::TestCase
def test_isolate
assert_raise_with_message ArgumentError, /\(a\)/ do
a = :a
- Proc.new{p a}.isolate.call
+ Proc.new{p a}.isolate
end
assert_raise_with_message ArgumentError, /\(a\)/ do
a = :a
1.times{
- Proc.new{p a}.isolate.call
+ Proc.new{p a}.isolate
}
end
assert_raise_with_message ArgumentError, /yield/ do
- Proc.new{yield}.isolate.call
+ Proc.new{yield}.isolate
+ end
+
+
+ name = "\u{2603 26a1}"
+ assert_raise_with_message(ArgumentError, /\(#{name}\)/) do
+ eval("#{name} = :#{name}; Proc.new {p #{name}}").isolate
end
# binding
@@ -1718,4 +1852,3 @@ class TestProcKeywords < Test::Unit::TestCase
assert_raise(ArgumentError) { (f >> g).call(**{})[:a] }
end
end
-
diff --git a/test/ruby/test_process.rb b/test/ruby/test_process.rb
index 07aa58418b..6e8ba484a4 100644
--- a/test/ruby/test_process.rb
+++ b/test/ruby/test_process.rb
@@ -3,7 +3,6 @@
require 'test/unit'
require 'tempfile'
require 'timeout'
-require 'io/wait'
require 'rbconfig'
class TestProcess < Test::Unit::TestCase
@@ -24,12 +23,6 @@ class TestProcess < Test::Unit::TestCase
return /mswin|mingw|bccwin/ =~ RUBY_PLATFORM
end
- def write_file(filename, content)
- File.open(filename, "w") {|f|
- f << content
- }
- end
-
def with_tmpchdir
Dir.mktmpdir {|d|
d = File.realpath(d)
@@ -40,7 +33,7 @@ class TestProcess < Test::Unit::TestCase
end
def run_in_child(str) # should be called in a temporary directory
- write_file("test-script", str)
+ File.write("test-script", str)
Process.wait spawn(RUBY, "test-script")
$?
end
@@ -66,7 +59,7 @@ class TestProcess < Test::Unit::TestCase
def test_rlimit_nofile
return unless rlimit_exist?
with_tmpchdir {
- write_file 's', <<-"End"
+ File.write 's', <<-"End"
# Too small RLIMIT_NOFILE, such as zero, causes problems.
# [OpenBSD] Setting to zero freezes this test.
# [GNU/Linux] EINVAL on poll(). EINVAL on ruby's internal poll() ruby with "[ASYNC BUG] thread_timer: select".
@@ -169,7 +162,7 @@ class TestProcess < Test::Unit::TestCase
end
def test_execopts_pgroup
- skip "system(:pgroup) is not supported" if windows?
+ omit "system(:pgroup) is not supported" if windows?
assert_nothing_raised { system(*TRUECOMMAND, :pgroup=>false) }
io = IO.popen([RUBY, "-e", "print Process.getpgrp"])
@@ -206,58 +199,67 @@ class TestProcess < Test::Unit::TestCase
max = Process.getrlimit(:CORE).last
+ # When running under ASAN, we need to set disable_coredump=0 for this test; by default
+ # the ASAN runtime library sets RLIMIT_CORE to 0, "to avoid dumping a 16T+ core file", and
+ # that inteferes with this test.
+ asan_options = ENV['ASAN_OPTIONS'] || ''
+ asan_options << ':' unless asan_options.empty?
+ env = {
+ 'ASAN_OPTIONS' => "#{asan_options}disable_coredump=0"
+ }
+
n = max
- IO.popen([RUBY, "-e",
- "p Process.getrlimit(:CORE)", :rlimit_core=>n]) {|io|
- assert_equal("[#{n}, #{n}]\n", io.read)
+ IO.popen([env, RUBY, "-e",
+ "puts Process.getrlimit(:CORE)", :rlimit_core=>n]) {|io|
+ assert_equal("#{n}\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)
+ IO.popen([env, RUBY, "-e",
+ "puts Process.getrlimit(:CORE)", :rlimit_core=>n]) {|io|
+ assert_equal("#{n}\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)
+ IO.popen([env, RUBY, "-e",
+ "puts Process.getrlimit(:CORE)", :rlimit_core=>[n]]) {|io|
+ assert_equal("#{n}\n#{n}\n", io.read)
}
m, n = 0, max
- IO.popen([RUBY, "-e",
- "p Process.getrlimit(:CORE)", :rlimit_core=>[m,n]]) {|io|
- assert_equal("[#{m}, #{n}]", io.read.chomp)
+ IO.popen([env, RUBY, "-e",
+ "puts Process.getrlimit(:CORE)", :rlimit_core=>[m,n]]) {|io|
+ assert_equal("#{m}\n#{n}\n", io.read)
}
m, n = 0, 0
- IO.popen([RUBY, "-e",
- "p Process.getrlimit(:CORE)", :rlimit_core=>[m,n]]) {|io|
- assert_equal("[#{m}, #{n}]", io.read.chomp)
+ IO.popen([env, RUBY, "-e",
+ "puts Process.getrlimit(:CORE)", :rlimit_core=>[m,n]]) {|io|
+ assert_equal("#{m}\n#{n}\n", io.read)
}
n = max
- IO.popen([RUBY, "-e",
- "p Process.getrlimit(:CORE), Process.getrlimit(:CPU)",
+ IO.popen([env, RUBY, "-e",
+ "puts Process.getrlimit(:CORE), Process.getrlimit(:CPU)",
:rlimit_core=>n, :rlimit_cpu=>3600]) {|io|
- assert_equal("[#{n}, #{n}]\n[3600, 3600]", io.read.chomp)
+ assert_equal("#{n}\n#{n}\n""3600\n3600\n", io.read)
}
assert_raise(ArgumentError) do
- system(RUBY, '-e', 'exit', 'rlimit_bogus'.to_sym => 123)
+ system(env, RUBY, '-e', 'exit', 'rlimit_bogus'.to_sym => 123)
end
- assert_separately([],"#{<<~"begin;"}\n#{<<~'end;'}", 'rlimit_cpu'.to_sym => 3600)
+ assert_separately([env],"#{<<~"begin;"}\n#{<<~'end;'}", 'rlimit_cpu'.to_sym => 3600)
BUG = "[ruby-core:82033] [Bug #13744]"
begin;
assert_equal([3600,3600], Process.getrlimit(:CPU), BUG)
end;
assert_raise_with_message(ArgumentError, /bogus/) do
- system(RUBY, '-e', 'exit', :rlimit_bogus => 123)
+ system(env, RUBY, '-e', 'exit', :rlimit_bogus => 123)
end
assert_raise_with_message(ArgumentError, /rlimit_cpu/) {
- system(RUBY, '-e', 'exit', "rlimit_cpu\0".to_sym => 3600)
+ system(env, RUBY, '-e', 'exit', "rlimit_cpu\0".to_sym => 3600)
}
end
@@ -273,7 +275,7 @@ class TestProcess < Test::Unit::TestCase
end;
end
- MANDATORY_ENVS = %w[RUBYLIB MJIT_SEARCH_BUILD_DIR]
+ MANDATORY_ENVS = %w[RUBYLIB RJIT_SEARCH_BUILD_DIR]
case RbConfig::CONFIG['target_os']
when /linux/
MANDATORY_ENVS << 'LD_PRELOAD'
@@ -362,7 +364,7 @@ class TestProcess < Test::Unit::TestCase
def test_execopt_env_path
bug8004 = '[ruby-core:53103] [Bug #8004]'
Dir.mktmpdir do |d|
- open("#{d}/tmp_script.cmd", "w") {|f| f.puts ": ;"; f.chmod(0755)}
+ File.write("#{d}/tmp_script.cmd", ": ;\n", perm: 0o755)
assert_not_nil(pid = Process.spawn({"PATH" => d}, "tmp_script.cmd"), bug8004)
wpid, st = Process.waitpid2(pid)
assert_equal([pid, true], [wpid, st.success?], bug8004)
@@ -400,7 +402,7 @@ class TestProcess < Test::Unit::TestCase
def test_execopts_env_popen_string
with_tmpchdir do |d|
- open('test-script', 'w') do |f|
+ File.open('test-script', 'w') do |f|
ENVCOMMAND.each_with_index do |cmd, i|
next if i.zero? or cmd == "-e"
f.puts cmd
@@ -412,16 +414,14 @@ class TestProcess < Test::Unit::TestCase
def test_execopts_preserve_env_on_exec_failure
with_tmpchdir {|d|
- write_file 's', <<-"End"
+ File.write 's', <<-"End"
ENV["mgg"] = nil
prog = "./nonexistent"
begin
Process.exec({"mgg" => "mggoo"}, [prog, prog])
rescue Errno::ENOENT
end
- open('out', 'w') {|f|
- f.print ENV["mgg"].inspect
- }
+ File.write('out', ENV["mgg"].inspect)
End
system(RUBY, 's')
assert_equal(nil.inspect, File.read('out'),
@@ -431,9 +431,7 @@ class TestProcess < Test::Unit::TestCase
def test_execopts_env_single_word
with_tmpchdir {|d|
- open("test_execopts_env_single_word.rb", "w") {|f|
- f.puts "print ENV['hgga']"
- }
+ File.write("test_execopts_env_single_word.rb", "print ENV['hgga']\n")
system({"hgga"=>"ugu"}, RUBY,
:in => 'test_execopts_env_single_word.rb',
:out => 'test_execopts_env_single_word.out')
@@ -511,7 +509,7 @@ class TestProcess < Test::Unit::TestCase
UMASK = [RUBY, '-e', 'printf "%04o\n", File.umask']
def test_execopts_umask
- skip "umask is not supported" if windows?
+ omit "umask is not supported" if windows?
IO.popen([*UMASK, :umask => 0]) {|io|
assert_equal("0000", io.read.chomp)
}
@@ -555,7 +553,7 @@ class TestProcess < Test::Unit::TestCase
assert_equal("a", File.read("out").chomp)
if windows?
# currently telling to child the file modes is not supported.
- open("out", "a") {|f| f.write "0\n"}
+ File.write("out", "0\n", mode: "a")
else
Process.wait Process.spawn(*ECHO["0"], STDOUT=>["out", File::WRONLY|File::CREAT|File::APPEND, 0644])
assert_equal("a\n0\n", File.read("out"))
@@ -666,6 +664,7 @@ class TestProcess < Test::Unit::TestCase
end unless windows? # does not support fifo
def test_execopts_redirect_open_fifo_interrupt_raise
+ pid = nil
with_tmpchdir {|d|
begin
File.mkfifo("fifo")
@@ -683,15 +682,21 @@ class TestProcess < Test::Unit::TestCase
puts "ok"
end
EOS
+ pid = io.pid
assert_equal("start\n", io.gets)
sleep 0.5
Process.kill(:USR1, io.pid)
assert_equal("ok\n", io.read)
}
+ assert_equal(pid, $?.pid)
+ assert_predicate($?, :success?)
}
+ ensure
+ assert_raise(Errno::ESRCH) {Process.kill(:KILL, pid)} if pid
end unless windows? # does not support fifo
def test_execopts_redirect_open_fifo_interrupt_print
+ pid = nil
with_tmpchdir {|d|
begin
File.mkfifo("fifo")
@@ -704,14 +709,25 @@ class TestProcess < Test::Unit::TestCase
puts "start"
system("cat", :in => "fifo")
EOS
+ pid = io.pid
assert_equal("start\n", io.gets)
sleep 0.2 # wait for the child to stop at opening "fifo"
Process.kill(:USR1, io.pid)
assert_equal("trap\n", io.readpartial(8))
+ sleep 0.2 # wait for the child to return to opening "fifo".
+ # On arm64-darwin22, often deadlocks while the child is
+ # opening "fifo". Not sure to where "ok" line being written
+ # at the next has gone.
File.write("fifo", "ok\n")
assert_equal("ok\n", io.read)
}
+ assert_equal(pid, $?.pid)
+ assert_predicate($?, :success?)
}
+ ensure
+ if pid
+ assert_raise(Errno::ESRCH) {Process.kill(:KILL, pid)}
+ end
end unless windows? # does not support fifo
def test_execopts_redirect_pipe
@@ -837,7 +853,7 @@ class TestProcess < Test::Unit::TestCase
STDERR=>"out", STDOUT=>[:child, STDERR])
assert_equal("errout", File.read("out"))
- skip "inheritance of fd other than stdin,stdout and stderr is not supported" if windows?
+ omit "inheritance of fd other than stdin,stdout and stderr is not supported" if windows?
Process.wait spawn(RUBY, "-e", "STDERR.print 'err'; STDOUT.print 'out'",
STDOUT=>"out",
STDERR=>[:child, 3],
@@ -859,7 +875,7 @@ class TestProcess < Test::Unit::TestCase
def test_execopts_exec
with_tmpchdir {|d|
- write_file("s", 'exec "echo aaa", STDOUT=>"foo"')
+ File.write("s", 'exec "echo aaa", STDOUT=>"foo"')
pid = spawn RUBY, 's'
Process.wait pid
assert_equal("aaa\n", File.read("foo"))
@@ -889,7 +905,7 @@ class TestProcess < Test::Unit::TestCase
end
def test_execopts_popen_extra_fd
- skip "inheritance of fd other than stdin,stdout and stderr is not supported" if windows?
+ omit "inheritance of fd other than stdin,stdout and stderr is not supported" if windows?
with_tmpchdir {|d|
with_pipe {|r, w|
IO.popen([RUBY, '-e', 'IO.new(3, "w").puts("a"); puts "b"', 3=>w]) {|io|
@@ -918,7 +934,7 @@ class TestProcess < Test::Unit::TestCase
end
def test_fd_inheritance
- skip "inheritance of fd other than stdin,stdout and stderr is not supported" if windows?
+ omit "inheritance of fd other than stdin,stdout and stderr is not supported" if windows?
with_pipe {|r, w|
system(RUBY, '-e', 'IO.new(ARGV[0].to_i, "w").puts(:ba)', w.fileno.to_s, w=>w)
w.close
@@ -933,7 +949,7 @@ class TestProcess < Test::Unit::TestCase
}
with_pipe {|r, w|
with_tmpchdir {|d|
- write_file("s", <<-"End")
+ File.write("s", <<-"End")
exec(#{RUBY.dump}, '-e',
'IO.new(ARGV[0].to_i, "w").puts("bu") rescue nil',
#{w.fileno.to_s.dump}, :close_others=>false)
@@ -964,7 +980,7 @@ class TestProcess < Test::Unit::TestCase
end
def test_execopts_close_others
- skip "inheritance of fd other than stdin,stdout and stderr is not supported" if windows?
+ omit "inheritance of fd other than stdin,stdout and stderr is not supported" if windows?
with_tmpchdir {|d|
with_pipe {|r, w|
system(RUBY, '-e', 'STDERR.reopen("err", "w"); IO.new(ARGV[0].to_i, "w").puts("ma")', w.fileno.to_s, :close_others=>true)
@@ -987,7 +1003,7 @@ class TestProcess < Test::Unit::TestCase
assert_equal("bi\n", r.read)
}
with_pipe {|r, w|
- write_file("s", <<-"End")
+ File.write("s", <<-"End")
exec(#{RUBY.dump}, '-e',
'STDERR.reopen("err", "w"); IO.new(ARGV[0].to_i, "w").puts("mu")',
#{w.fileno.to_s.dump},
@@ -1058,7 +1074,7 @@ class TestProcess < Test::Unit::TestCase
}
}
rescue NotImplementedError
- skip "IO#close_on_exec= is not supported"
+ omit "IO#close_on_exec= is not supported"
end
end unless windows? # passing non-stdio fds is not supported on Windows
@@ -1113,7 +1129,7 @@ class TestProcess < Test::Unit::TestCase
def test_exec_noshell
with_tmpchdir {|d|
- write_file("s", <<-"End")
+ File.write("s", <<-"End")
str = "echo non existing command name which contains spaces"
STDERR.reopen(STDOUT)
begin
@@ -1129,7 +1145,7 @@ class TestProcess < Test::Unit::TestCase
def test_system_wordsplit
with_tmpchdir {|d|
- write_file("script", <<-'End')
+ File.write("script", <<-'End')
File.open("result", "w") {|t| t << "haha pid=#{$$} ppid=#{Process.ppid}" }
exit 5
End
@@ -1145,7 +1161,7 @@ class TestProcess < Test::Unit::TestCase
def test_spawn_wordsplit
with_tmpchdir {|d|
- write_file("script", <<-'End')
+ File.write("script", <<-'End')
File.open("result", "w") {|t| t << "hihi pid=#{$$} ppid=#{Process.ppid}" }
exit 6
End
@@ -1162,7 +1178,7 @@ class TestProcess < Test::Unit::TestCase
def test_popen_wordsplit
with_tmpchdir {|d|
- write_file("script", <<-'End')
+ File.write("script", <<-'End')
print "fufu pid=#{$$} ppid=#{Process.ppid}"
exit 7
End
@@ -1181,7 +1197,7 @@ class TestProcess < Test::Unit::TestCase
def test_popen_wordsplit_beginning_and_trailing_spaces
with_tmpchdir {|d|
- write_file("script", <<-'End')
+ File.write("script", <<-'End')
print "fufumm pid=#{$$} ppid=#{Process.ppid}"
exit 7
End
@@ -1200,7 +1216,7 @@ class TestProcess < Test::Unit::TestCase
def test_exec_wordsplit
with_tmpchdir {|d|
- write_file("script", <<-'End')
+ File.write("script", <<-'End')
File.open("result", "w") {|t|
if /mswin|bccwin|mingw/ =~ RUBY_PLATFORM
t << "hehe ppid=#{Process.ppid}"
@@ -1210,7 +1226,7 @@ class TestProcess < Test::Unit::TestCase
}
exit 6
End
- write_file("s", <<-"End")
+ File.write("s", <<-"End")
ruby = #{RUBY.dump}
exec "\#{ruby} script"
End
@@ -1231,11 +1247,11 @@ class TestProcess < Test::Unit::TestCase
def test_system_shell
with_tmpchdir {|d|
- write_file("script1", <<-'End')
+ File.write("script1", <<-'End')
File.open("result1", "w") {|t| t << "taka pid=#{$$} ppid=#{Process.ppid}" }
exit 7
End
- write_file("script2", <<-'End')
+ File.write("script2", <<-'End')
File.open("result2", "w") {|t| t << "taki pid=#{$$} ppid=#{Process.ppid}" }
exit 8
End
@@ -1251,7 +1267,7 @@ class TestProcess < Test::Unit::TestCase
if windows?
Dir.mkdir(path = "path with space")
- write_file(bat = path + "/bat test.bat", "@echo %1>out")
+ File.write(bat = path + "/bat test.bat", "@echo %1>out")
system(bat, "foo 'bar'")
assert_equal(%["foo 'bar'"\n], File.read("out"), '[ruby-core:22960]')
system(%[#{bat.dump} "foo 'bar'"])
@@ -1262,11 +1278,11 @@ class TestProcess < Test::Unit::TestCase
def test_spawn_shell
with_tmpchdir {|d|
- write_file("script1", <<-'End')
+ File.write("script1", <<-'End')
File.open("result1", "w") {|t| t << "taku pid=#{$$} ppid=#{Process.ppid}" }
exit 7
End
- write_file("script2", <<-'End')
+ File.write("script2", <<-'End')
File.open("result2", "w") {|t| t << "take pid=#{$$} ppid=#{Process.ppid}" }
exit 8
End
@@ -1283,7 +1299,7 @@ class TestProcess < Test::Unit::TestCase
if windows?
Dir.mkdir(path = "path with space")
- write_file(bat = path + "/bat test.bat", "@echo %1>out")
+ File.write(bat = path + "/bat test.bat", "@echo %1>out")
pid = spawn(bat, "foo 'bar'")
Process.wait pid
status = $?
@@ -1302,11 +1318,11 @@ class TestProcess < Test::Unit::TestCase
def test_popen_shell
with_tmpchdir {|d|
- write_file("script1", <<-'End')
+ File.write("script1", <<-'End')
puts "tako pid=#{$$} ppid=#{Process.ppid}"
exit 7
End
- write_file("script2", <<-'End')
+ File.write("script2", <<-'End')
puts "tika pid=#{$$} ppid=#{Process.ppid}"
exit 8
End
@@ -1321,7 +1337,7 @@ class TestProcess < Test::Unit::TestCase
if windows?
Dir.mkdir(path = "path with space")
- write_file(bat = path + "/bat test.bat", "@echo %1")
+ File.write(bat = path + "/bat test.bat", "@echo %1")
r = IO.popen([bat, "foo 'bar'"]) {|f| f.read}
assert_equal(%["foo 'bar'"\n], r, '[ruby-core:22960]')
r = IO.popen(%[#{bat.dump} "foo 'bar'"]) {|f| f.read}
@@ -1332,15 +1348,15 @@ class TestProcess < Test::Unit::TestCase
def test_exec_shell
with_tmpchdir {|d|
- write_file("script1", <<-'End')
+ File.write("script1", <<-'End')
File.open("result1", "w") {|t| t << "tiki pid=#{$$} ppid=#{Process.ppid}" }
exit 7
End
- write_file("script2", <<-'End')
+ File.write("script2", <<-'End')
File.open("result2", "w") {|t| t << "tiku pid=#{$$} ppid=#{Process.ppid}" }
exit 8
End
- write_file("s", <<-"End")
+ File.write("s", <<-"End")
ruby = #{RUBY.dump}
exec("\#{ruby} script1 || \#{ruby} script2")
End
@@ -1367,7 +1383,7 @@ class TestProcess < Test::Unit::TestCase
assert_equal("1", IO.popen([[RUBY, "qwerty"], "-e", "print 1"]) {|f| f.read })
- write_file("s", <<-"End")
+ File.write("s", <<-"End")
exec([#{RUBY.dump}, "lkjh"], "-e", "exit 5")
End
pid = spawn RUBY, "s"
@@ -1377,7 +1393,7 @@ class TestProcess < Test::Unit::TestCase
end
def with_stdin(filename)
- open(filename) {|f|
+ File.open(filename) {|f|
begin
old = STDIN.dup
begin
@@ -1394,8 +1410,8 @@ class TestProcess < Test::Unit::TestCase
def test_argv0_noarg
with_tmpchdir {|d|
- open("t", "w") {|f| f.print "exit true" }
- open("f", "w") {|f| f.print "exit false" }
+ File.write("t", "exit true")
+ File.write("f", "exit false")
with_stdin("t") { assert_equal(true, system([RUBY, "qaz"])) }
with_stdin("f") { assert_equal(false, system([RUBY, "wsx"])) }
@@ -1425,6 +1441,11 @@ class TestProcess < Test::Unit::TestCase
REPRO
end
+ def test_argv0_frozen
+ assert_predicate Process.argv0, :frozen?
+ assert_predicate $0, :frozen?
+ end
+
def test_status
with_tmpchdir do
s = run_in_child("exit 1")
@@ -1433,8 +1454,15 @@ class TestProcess < Test::Unit::TestCase
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_deprecated_warn(/\buse .*Process::Status/) do
+ assert_equal(s.to_i & 0x55555555, s & 0x55555555)
+ end
+ assert_deprecated_warn(/\buse .*Process::Status/) do
+ assert_equal(s.to_i >> 1, s >> 1)
+ end
+ assert_raise(ArgumentError) do
+ s >> -1
+ end
assert_equal(false, s.stopped?)
assert_equal(nil, s.stopsig)
@@ -1450,7 +1478,7 @@ class TestProcess < Test::Unit::TestCase
expected = Signal.list.include?("QUIT") ? [false, true, false, nil] : [true, false, false, true]
with_tmpchdir do
- write_file("foo", "Process.kill(:KILL, $$); exit(42)")
+ File.write("foo", "Process.kill(:KILL, $$); exit(42)")
system(RUBY, "foo")
s = $?
assert_equal(expected,
@@ -1498,7 +1526,7 @@ class TestProcess < Test::Unit::TestCase
def test_wait_without_arg
with_tmpchdir do
- write_file("foo", "sleep 0.1")
+ File.write("foo", "sleep 0.1")
pid = spawn(RUBY, "foo")
assert_equal(pid, Process.wait)
end
@@ -1506,7 +1534,7 @@ class TestProcess < Test::Unit::TestCase
def test_wait2
with_tmpchdir do
- write_file("foo", "sleep 0.1")
+ File.write("foo", "sleep 0.1")
pid = spawn(RUBY, "foo")
assert_equal([pid, 0], Process.wait2)
end
@@ -1514,7 +1542,7 @@ class TestProcess < Test::Unit::TestCase
def test_waitall
with_tmpchdir do
- write_file("foo", "sleep 0.1")
+ File.write("foo", "sleep 0.1")
ps = (0...3).map { spawn(RUBY, "foo") }.sort
ss = Process.waitall.sort
ps.zip(ss) do |p1, (p2, s)|
@@ -1547,6 +1575,8 @@ class TestProcess < Test::Unit::TestCase
assert_operator(diff, :<, sec,
->{"#{bug11340}: #{diff} seconds to interrupt Process.wait"})
f.puts
+ rescue Errno::EPIPE
+ omit "child process exited already in #{diff} seconds"
end
end
@@ -1554,7 +1584,7 @@ class TestProcess < Test::Unit::TestCase
with_tmpchdir do
s = run_in_child("abort")
assert_not_predicate(s, :success?)
- write_file("test-script", "#{<<~"begin;"}\n#{<<~'end;'}")
+ File.write("test-script", "#{<<~"begin;"}\n#{<<~'end;'}")
begin;
STDERR.reopen(STDOUT)
begin
@@ -1610,7 +1640,7 @@ class TestProcess < Test::Unit::TestCase
else
assert_kind_of(Integer, max)
assert_predicate(max, :positive?)
- skip "not limited to NGROUPS_MAX" if /darwin/ =~ RUBY_PLATFORM
+ omit "not limited to NGROUPS_MAX" if /darwin/ =~ RUBY_PLATFORM
gs = Process.groups
assert_operator(gs.size, :<=, max)
gs[0] ||= 0
@@ -1637,7 +1667,7 @@ class TestProcess < Test::Unit::TestCase
end
def test_setegid
- skip "root can use Process.egid on Android platform" if RUBY_PLATFORM =~ /android/
+ omit "root can use Process.egid on Android platform" if RUBY_PLATFORM =~ /android/
assert_nothing_raised(TypeError) {Process.egid += 0}
rescue NotImplementedError
end
@@ -1695,11 +1725,6 @@ class TestProcess < Test::Unit::TestCase
end
def test_wait_and_sigchild
- if /freebsd|openbsd/ =~ RUBY_PLATFORM
- # this relates #4173
- # When ruby can use 2 cores, signal and wait4 may miss the signal.
- skip "this fails on FreeBSD and OpenBSD on multithreaded environment"
- end
signal_received = []
IO.pipe do |sig_r, sig_w|
Signal.trap(:CHLD) do
@@ -1707,18 +1732,23 @@ class TestProcess < Test::Unit::TestCase
sig_w.write('?')
end
pid = nil
+ th = nil
IO.pipe do |r, w|
pid = fork { r.read(1); exit }
- Thread.start {
+ th = Thread.start {
Thread.current.report_on_exception = false
raise
}
w.puts
end
Process.wait pid
+ begin
+ th.join
+ rescue Exception
+ end
assert_send [sig_r, :wait_readable, 5], 'self-pipe not readable'
end
- if defined?(RubyVM::JIT) && RubyVM::JIT.enabled? # checking -DMJIT_FORCE_ENABLE. It may trigger extra SIGCHLD.
+ if defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled? # checking -DRJIT_FORCE_ENABLE. It may trigger extra SIGCHLD.
assert_equal [true], signal_received.uniq, "[ruby-core:19744]"
else
assert_equal [true], signal_received, "[ruby-core:19744]"
@@ -1732,6 +1762,9 @@ class TestProcess < Test::Unit::TestCase
end
def test_no_curdir
+ if /solaris/i =~ RUBY_PLATFORM
+ omit "Temporary omit to avoid CI failures after commit to use realpath on required files"
+ end
with_tmpchdir {|d|
Dir.mkdir("vd")
status = nil
@@ -1749,16 +1782,16 @@ class TestProcess < Test::Unit::TestCase
def test_fallback_to_sh
feature = '[ruby-core:32745]'
with_tmpchdir do |d|
- open("tmp_script.#{$$}", "w") {|f| f.puts ": ;"; f.chmod(0755)}
+ File.write("tmp_script.#{$$}", ": ;\n", perm: 0o755)
assert_not_nil(pid = Process.spawn("./tmp_script.#{$$}"), feature)
wpid, st = Process.waitpid2(pid)
assert_equal([pid, true], [wpid, st.success?], feature)
- open("tmp_script.#{$$}", "w") {|f| f.puts "echo $#: $@"; f.chmod(0755)}
+ File.write("tmp_script.#{$$}", "echo $#: $@", perm: 0o755)
result = IO.popen(["./tmp_script.#{$$}", "a b", "c"]) {|f| f.read}
assert_equal("2: a b c\n", result, feature)
- open("tmp_script.#{$$}", "w") {|f| f.puts "echo $hghg"; f.chmod(0755)}
+ File.write("tmp_script.#{$$}", "echo $hghg", perm: 0o755)
result = IO.popen([{"hghg" => "mogomogo"}, "./tmp_script.#{$$}", "a b", "c"]) {|f| f.read}
assert_equal("mogomogo\n", result, feature)
@@ -1772,7 +1805,7 @@ class TestProcess < Test::Unit::TestCase
def test_aspawn_too_long_path
if /solaris/i =~ RUBY_PLATFORM && !defined?(Process::RLIMIT_NPROC)
- skip "Too exhaustive test on platforms without Process::RLIMIT_NPROC such as Solaris 10"
+ omit "Too exhaustive test on platforms without Process::RLIMIT_NPROC such as Solaris 10"
end
bug4315 = '[ruby-core:34833] #7904 [ruby-core:52628] #11613'
assert_fail_too_long_path(%w"echo |", bug4315)
@@ -1786,14 +1819,20 @@ class TestProcess < Test::Unit::TestCase
exs << Errno::EINVAL if windows?
exs << Errno::E2BIG if defined?(Errno::E2BIG)
opts = {[STDOUT, STDERR]=>File::NULL}
- opts[:rlimit_nproc] = 128 if defined?(Process::RLIMIT_NPROC)
+ if defined?(Process::RLIMIT_NPROC)
+ opts[:rlimit_nproc] = /openbsd/i =~ RUBY_PLATFORM ? 64 : 128
+ end
EnvUtil.suppress_warning do
assert_raise(*exs, mesg) do
begin
loop do
Process.spawn(cmds.join(sep), opts)
min = [cmds.size, min].max
- cmds *= 100
+ begin
+ cmds *= 100
+ rescue ArgumentError
+ raise NoMemoryError
+ end
end
rescue NoMemoryError
size = cmds.size
@@ -1814,7 +1853,7 @@ class TestProcess < Test::Unit::TestCase
with_tmpchdir do
assert_nothing_raised('[ruby-dev:12261]') do
- EnvUtil.timeout(3) do
+ EnvUtil.timeout(10) do
pid = spawn('yes | ls')
Process.waitpid pid
end
@@ -1873,6 +1912,28 @@ class TestProcess < Test::Unit::TestCase
assert_not_equal(cpid, dpid)
end
+ def test_daemon_detached
+ IO.popen("-", "r+") do |f|
+ if f
+ assert_equal(f.pid, Process.wait(f.pid))
+
+ dpid, ppid, dsid = 3.times.map {Integer(f.gets)}
+
+ message = "daemon #{dpid} should be detached"
+ assert_not_equal($$, ppid, message) # would be 1 almost always
+ assert_raise(Errno::ECHILD, message) {Process.wait(dpid)}
+ assert_kind_of(Integer, Process.kill(0, dpid), message)
+ assert_equal(dpid, dsid)
+
+ break # close f, and let the daemon resume and exit
+ end
+ Process.setsid rescue nil
+ Process.daemon(false, true)
+ puts $$, Process.ppid, Process.getsid
+ $stdin.gets # wait for the above assertions using signals
+ end
+ end
+
if File.directory?("/proc/self/task") && /netbsd[a-z]*[1-6]/ !~ RUBY_PLATFORM
def test_daemon_no_threads
pid, data = IO.popen("-", "r+") do |f|
@@ -1955,7 +2016,7 @@ class TestProcess < Test::Unit::TestCase
end
def test_execopts_uid
- skip "root can use uid option of Kernel#system on Android platform" if RUBY_PLATFORM =~ /android/
+ omit "root can use uid option of Kernel#system on Android platform" if RUBY_PLATFORM =~ /android/
feature6975 = '[ruby-core:47414]'
[30000, [Process.uid, ENV["USER"]]].each do |uid, user|
@@ -1986,8 +2047,8 @@ class TestProcess < Test::Unit::TestCase
end
def test_execopts_gid
- skip "Process.groups not implemented on Windows platform" if windows?
- skip "root can use Process.groups on Android platform" if RUBY_PLATFORM =~ /android/
+ omit "Process.groups not implemented on Windows platform" if windows?
+ omit "root can use Process.groups on Android platform" if RUBY_PLATFORM =~ /android/
feature6975 = '[ruby-core:47414]'
groups = Process.groups.map do |g|
@@ -2113,7 +2174,7 @@ EOS
"c\u{1EE7}a",
].each do |arg|
begin
- arg = arg.encode(Encoding.find("locale"))
+ arg = arg.encode(Encoding.local_charmap)
rescue
else
assert_in_out_err([], "#{<<-"begin;"}\n#{<<-"end;"}", [arg], [], bug12841)
@@ -2131,7 +2192,9 @@ EOS
t3 = Process.clock_gettime(Process::CLOCK_REALTIME, :nanosecond)
assert_operator(t1, :<=, t2)
assert_operator(t2, :<=, t3)
- assert_raise(Errno::EINVAL) { Process.clock_gettime(:foo) }
+ assert_raise_with_message(Errno::EINVAL, /:foo/) do
+ Process.clock_gettime(:foo)
+ end
end
def test_clock_gettime_unit
@@ -2236,7 +2299,9 @@ EOS
rescue Errno::EINVAL
else
assert_kind_of(Integer, r)
- assert_raise(Errno::EINVAL) { Process.clock_getres(:foo) }
+ assert_raise_with_message(Errno::EINVAL, /:foo/) do
+ Process.clock_getres(:foo)
+ end
end
def test_clock_getres_constants
@@ -2323,7 +2388,7 @@ EOS
end
def test_deadlock_by_signal_at_forking
- assert_separately(%W(--disable=gems - #{RUBY}), <<-INPUT, timeout: 100)
+ assert_separately(%W(- #{RUBY}), <<-INPUT, timeout: 100)
ruby = ARGV.shift
GC.start # reduce garbage
GC.disable # avoid triggering CoW after forks
@@ -2508,7 +2573,7 @@ EOS
end
def test_forked_child_handles_signal
- skip "fork not supported" unless Process.respond_to?(:fork)
+ omit "fork not supported" unless Process.respond_to?(:fork)
assert_normal_exit(<<-"end;", '[ruby-core:82883] [Bug #13916]')
require 'timeout'
pid = fork { sleep }
@@ -2542,4 +2607,257 @@ EOS
end
assert_empty(Process.waitall)
end
+
+ def test__fork
+ r, w = IO.pipe
+ pid = Process._fork
+ if pid == 0
+ begin
+ r.close
+ w << "ok: #$$"
+ w.close
+ ensure
+ exit!
+ end
+ else
+ w.close
+ assert_equal("ok: #{pid}", r.read)
+ r.close
+ Process.waitpid(pid)
+ end
+ end if Process.respond_to?(:_fork)
+
+ def test__fork_pid_cache
+ _parent_pid = Process.pid
+ r, w = IO.pipe
+ pid = Process._fork
+ if pid == 0
+ begin
+ r.close
+ w << "ok: #{Process.pid}"
+ w.close
+ ensure
+ exit!
+ end
+ else
+ w.close
+ assert_equal("ok: #{pid}", r.read)
+ r.close
+ Process.waitpid(pid)
+ end
+ end if Process.respond_to?(:_fork)
+
+ def test__fork_hook
+ %w(fork Process.fork).each do |method|
+ feature17795 = '[ruby-core:103400] [Feature #17795]'
+ assert_in_out_err([], <<-"end;", [], [], feature17795, timeout: 60) do |r, e|
+ module ForkHook
+ def _fork
+ p :before
+ ret = super
+ p :after
+ ret
+ end
+ end
+
+ Process.singleton_class.prepend(ForkHook)
+
+ pid = #{ method }
+ p pid
+ Process.waitpid(pid) if pid
+ end;
+ assert_equal([], e)
+ assert_equal(":before", r.shift)
+ assert_equal(":after", r.shift)
+ s = r.map {|s| s.chomp }.sort #=> [pid, ":after", "nil"]
+ assert_match(/^\d+$/, s[0]) # pid
+ assert_equal(":after", s[1])
+ assert_equal("nil", s[2])
+ end
+ end
+ end if Process.respond_to?(:_fork)
+
+ def test__fork_hook_popen
+ feature17795 = '[ruby-core:103400] [Feature #17795]'
+ assert_in_out_err([], <<-"end;", %w(:before :after :after foo bar), [], feature17795, timeout: 60)
+ module ForkHook
+ def _fork
+ p :before
+ ret = super
+ p :after
+ ret
+ end
+ end
+
+ Process.singleton_class.prepend(ForkHook)
+
+ IO.popen("-") {|io|
+ if !io
+ puts "foo"
+ else
+ puts io.read + "bar"
+ end
+ }
+ end;
+ end if Process.respond_to?(:_fork)
+
+ def test__fork_wrong_type_hook
+ feature17795 = '[ruby-core:103400] [Feature #17795]'
+ assert_in_out_err([], <<-"end;", ["OK"], [], feature17795, timeout: 60)
+ module ForkHook
+ def _fork
+ "BOO"
+ end
+ end
+
+ Process.singleton_class.prepend(ForkHook)
+
+ begin
+ fork
+ rescue TypeError
+ puts "OK"
+ end
+ end;
+ end if Process.respond_to?(:_fork)
+
+ def test_warmup_promote_all_objects_to_oldgen
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ require 'objspace'
+ begin;
+ obj = Object.new
+
+ assert_not_include(ObjectSpace.dump(obj), '"old":true')
+ Process.warmup
+ assert_include(ObjectSpace.dump(obj), '"old":true')
+ end;
+ end
+
+ def test_warmup_run_major_gc_and_compact
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ # Run a GC to ensure that we are not in the middle of a GC run
+ GC.start
+
+ major_gc_count = GC.stat(:major_gc_count)
+ compact_count = GC.stat(:compact_count)
+ Process.warmup
+ assert_equal major_gc_count + 1, GC.stat(:major_gc_count)
+ assert_equal compact_count + 1, GC.stat(:compact_count)
+ end;
+ end
+
+ def test_warmup_precompute_string_coderange
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ require 'objspace'
+ begin;
+ obj = "a" * 12
+ obj.force_encoding(Encoding::UTF_16LE)
+ obj.force_encoding(Encoding::BINARY)
+ assert_include(ObjectSpace.dump(obj), '"coderange":"unknown"')
+ Process.warmup
+ assert_include(ObjectSpace.dump(obj), '"coderange":"7bit"')
+ end;
+ end
+
+ def test_warmup_frees_pages
+ assert_separately([{"RUBY_GC_HEAP_FREE_SLOTS_MAX_RATIO" => "1.0"}, "-W0"], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ GC.start
+
+ TIMES = 100_000
+ ary = Array.new(TIMES)
+ TIMES.times do |i|
+ ary[i] = Object.new
+ end
+ ary.clear
+ ary = nil
+
+ # Disable GC so we can make sure GC only runs in Process.warmup
+ GC.disable
+
+ total_slots_before = GC.stat(:heap_available_slots) + GC.stat(:heap_allocatable_slots)
+
+ Process.warmup
+
+ assert_equal(total_slots_before, GC.stat(:heap_available_slots) + GC.stat(:heap_allocatable_slots))
+ assert_equal(0, GC.stat(:heap_empty_pages))
+ assert_operator(GC.stat(:total_freed_pages), :>, 0)
+ end;
+ end
+
+ def test_concurrent_group_and_pid_wait
+ # Use a pair of pipes that will make long_pid exit when this test exits, to avoid
+ # leaking temp processes.
+ long_rpipe, long_wpipe = IO.pipe
+ short_rpipe, short_wpipe = IO.pipe
+ # This process should run forever
+ long_pid = fork do
+ [short_rpipe, short_wpipe, long_wpipe].each(&:close)
+ long_rpipe.read
+ end
+ # This process will exit
+ short_pid = fork do
+ [long_rpipe, long_wpipe, short_wpipe].each(&:close)
+ short_rpipe.read
+ end
+ t1, t2, t3 = nil
+ EnvUtil.timeout(5) do
+ t1 = Thread.new do
+ Process.waitpid long_pid
+ end
+ # Wait for us to be blocking in a call to waitpid2
+ Thread.pass until t1.stop?
+ short_wpipe.close # Make short_pid exit
+
+ # The short pid has exited, so -1 should pick that up.
+ assert_equal short_pid, Process.waitpid(-1)
+
+ # Terminate t1 for the next phase of the test.
+ t1.kill
+ t1.join
+
+ t2 = Thread.new do
+ Process.waitpid(-1)
+ rescue Errno::ECHILD
+ nil
+ end
+ Thread.pass until t2.stop?
+ t3 = Thread.new do
+ Process.waitpid long_pid
+ rescue Errno::ECHILD
+ nil
+ end
+ Thread.pass until t3.stop?
+
+ # it's actually nondeterministic which of t2 or t3 will receive the wait (this
+ # nondeterminism comes from the behaviour of the underlying system calls)
+ long_wpipe.close
+ assert_equal [long_pid], [t2, t3].map(&:value).compact
+ end
+ ensure
+ [t1, t2, t3].each { _1&.kill rescue nil }
+ [t1, t2, t3].each { _1&.join rescue nil }
+ [long_rpipe, long_wpipe, short_rpipe, short_wpipe].each { _1&.close rescue nil }
+ end if defined?(fork)
+
+ def test_handle_interrupt_with_fork
+ Thread.handle_interrupt(RuntimeError => :never) do
+ Thread.current.raise(RuntimeError, "Queued error")
+
+ assert_predicate Thread, :pending_interrupt?
+
+ pid = Process.fork do
+ if Thread.pending_interrupt?
+ exit 1
+ end
+ end
+
+ _, status = Process.waitpid2(pid)
+ assert_predicate status, :success?
+
+ assert_predicate Thread, :pending_interrupt?
+ end
+ rescue RuntimeError
+ # Ignore.
+ end if defined?(fork)
end
diff --git a/test/ruby/test_rand.rb b/test/ruby/test_rand.rb
index 13b7329269..a4beffd689 100644
--- a/test/ruby/test_rand.rb
+++ b/test/ruby/test_rand.rb
@@ -317,7 +317,7 @@ class TestRand < Test::Unit::TestCase
assert_equal(r1, r2, bug5661)
assert_fork_status(1, '[ruby-core:82100] [Bug #13753]') do
- Random::DEFAULT.rand(4)
+ Random.rand(4)
end
rescue NotImplementedError
end
@@ -336,6 +336,14 @@ class TestRand < Test::Unit::TestCase
}
end
+ def test_seed_leading_zero_guard
+ guard = 1<<32
+ range = 0...(1<<32)
+ all_assertions_foreach(nil, 0, 1, 2) do |i|
+ assert_not_equal(Random.new(i).rand(range), Random.new(i+guard).rand(range))
+ end
+ end
+
def test_marshal
bug3656 = '[ruby-core:31622]'
assert_raise(TypeError, bug3656) {
@@ -395,8 +403,8 @@ class TestRand < Test::Unit::TestCase
assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
begin;
verbose, $VERBOSE = $VERBOSE, nil
- seed = Random::DEFAULT::seed
- rand1 = Random::DEFAULT::rand
+ seed = Random.seed
+ rand1 = Random.rand
$VERBOSE = verbose
rand2 = Random.new(seed).rand
assert_equal(rand1, rand2)
diff --git a/test/ruby/test_random_formatter.rb b/test/ruby/test_random_formatter.rb
new file mode 100644
index 0000000000..f927522d96
--- /dev/null
+++ b/test/ruby/test_random_formatter.rb
@@ -0,0 +1,178 @@
+require 'test/unit'
+require 'random/formatter'
+
+module Random::Formatter
+ module FormatterTest
+ def test_random_bytes
+ assert_equal(16, @it.random_bytes.size)
+ assert_equal(Encoding::ASCII_8BIT, @it.random_bytes.encoding)
+ 65.times do |idx|
+ assert_equal(idx, @it.random_bytes(idx).size)
+ end
+ end
+
+ def test_hex
+ s = @it.hex
+ assert_equal(16 * 2, s.size)
+ assert_match(/\A\h+\z/, s)
+ 33.times do |idx|
+ s = @it.hex(idx)
+ assert_equal(idx * 2, s.size)
+ assert_match(/\A\h*\z/, s)
+ end
+ end
+
+ def test_hex_encoding
+ assert_equal(Encoding::US_ASCII, @it.hex.encoding)
+ end
+
+ def test_base64
+ assert_equal(16, @it.base64.unpack1('m*').size)
+ 17.times do |idx|
+ assert_equal(idx, @it.base64(idx).unpack1('m*').size)
+ end
+ end
+
+ def test_urlsafe_base64
+ safe = /[\n+\/]/
+ 65.times do |idx|
+ assert_not_match(safe, @it.urlsafe_base64(idx))
+ end
+ # base64 can include unsafe byte
+ assert((0..10000).any? {|idx| safe =~ @it.base64(idx)}, "None of base64(0..10000) is url-safe")
+ end
+
+ def test_random_number_float
+ 101.times do
+ v = @it.random_number
+ assert_in_range(0.0...1.0, v)
+ end
+ end
+
+ def test_random_number_float_by_zero
+ 101.times do
+ v = @it.random_number(0)
+ assert_in_range(0.0...1.0, v)
+ end
+ end
+
+ def test_random_number_int
+ 101.times do |idx|
+ next if idx.zero?
+ v = @it.random_number(idx)
+ assert_in_range(0...idx, v)
+ end
+ end
+
+ def test_uuid
+ uuid = @it.uuid
+ assert_equal(36, uuid.size)
+
+ # Check time_hi_and_version and clock_seq_hi_res bits (RFC 4122 4.4)
+ assert_equal('4', uuid[14])
+ assert_include(%w'8 9 a b', uuid[19])
+
+ assert_match(/\A\h{8}-\h{4}-\h{4}-\h{4}-\h{12}\z/, uuid)
+ end
+
+ def assert_uuid_v7(**opts)
+ t1 = current_uuid7_time(**opts)
+ uuid = @it.uuid_v7(**opts)
+ t3 = current_uuid7_time(**opts)
+
+ assert_match(/\A\h{8}-\h{4}-7\h{3}-[89ab]\h{3}-\h{12}\z/, uuid)
+
+ t2 = get_uuid7_time(uuid, **opts)
+ assert_operator(t1, :<=, t2)
+ assert_operator(t2, :<=, t3)
+ end
+
+ def test_uuid_v7
+ assert_uuid_v7
+ 0.upto(12) do |extra_timestamp_bits|
+ assert_uuid_v7 extra_timestamp_bits: extra_timestamp_bits
+ end
+ end
+
+ # It would be nice to simply use Time#floor here. But that is problematic
+ # due to the difference between decimal vs binary fractions.
+ def current_uuid7_time(extra_timestamp_bits: 0)
+ denominator = (1 << extra_timestamp_bits).to_r
+ Process.clock_gettime(Process::CLOCK_REALTIME, :nanosecond)
+ .then {|ns| ((ns / 1_000_000r) * denominator).floor / denominator }
+ .then {|ms| Time.at(ms / 1000r, in: "+00:00") }
+ end
+
+ def get_uuid7_time(uuid, extra_timestamp_bits: 0)
+ denominator = (1 << extra_timestamp_bits) * 1000r
+ extra_chars = extra_timestamp_bits / 4
+ last_char_bits = extra_timestamp_bits % 4
+ extra_chars += 1 if last_char_bits != 0
+ timestamp_re = /\A(\h{8})-(\h{4})-7(\h{#{extra_chars}})/
+ timestamp_chars = uuid.match(timestamp_re).captures.join
+ timestamp = timestamp_chars.to_i(16)
+ timestamp >>= 4 - last_char_bits unless last_char_bits == 0
+ timestamp /= denominator
+ Time.at timestamp, in: "+00:00"
+ end
+
+ def test_alphanumeric
+ 65.times do |n|
+ an = @it.alphanumeric(n)
+ assert_match(/\A[0-9a-zA-Z]*\z/, an)
+ assert_equal(n, an.length)
+ end
+ end
+
+ def test_alphanumeric_chars
+ [
+ [[*"0".."9"], /\A\d*\z/],
+ [[*"a".."t"], /\A[a-t]*\z/],
+ ["一二三四五六七八ä¹å".chars, /\A[一二三四五六七八ä¹å]*\z/],
+ ].each do |chars, pattern|
+ 10.times do |n|
+ an = @it.alphanumeric(n, chars: chars)
+ assert_match(pattern, an)
+ assert_equal(n, an.length)
+ end
+ end
+ end
+
+ def assert_in_range(range, result, mesg = nil)
+ assert(range.cover?(result), build_message(mesg, "Expected #{result} to be in #{range}"))
+ end
+ end
+
+ module NotDefaultTest
+ def test_random_number_not_default
+ msg = "random_number should not be affected by srand"
+ seed = srand(0)
+ x = @it.random_number(1000)
+ 10.times do|i|
+ srand(0)
+ return unless @it.random_number(1000) == x
+ end
+ srand(0)
+ assert_not_equal(x, @it.random_number(1000), msg)
+ ensure
+ srand(seed) if seed
+ end
+ end
+
+ class TestClassMethods < Test::Unit::TestCase
+ include FormatterTest
+
+ def setup
+ @it = Random
+ end
+ end
+
+ class TestInstanceMethods < Test::Unit::TestCase
+ include FormatterTest
+ include NotDefaultTest
+
+ def setup
+ @it = Random.new
+ end
+ end
+end
diff --git a/test/ruby/test_range.rb b/test/ruby/test_range.rb
index 8ac1930be6..e0c1d20bd2 100644
--- a/test/ruby/test_range.rb
+++ b/test/ruby/test_range.rb
@@ -2,7 +2,7 @@
require 'test/unit'
require 'delegate'
require 'timeout'
-require 'bigdecimal'
+require 'date'
require 'rbconfig/sizeof'
class TestRange < Test::Unit::TestCase
@@ -246,67 +246,138 @@ class TestRange < Test::Unit::TestCase
assert_kind_of(String, (0..1).hash.to_s)
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)
+ def test_step_numeric_range
+ # Fixnums, floats and all other numbers (like rationals) should behave exactly the same,
+ # but the behavior is implemented independently in 3 different branches of code,
+ # so we need to test each of them.
+ %i[to_i to_r to_f].each do |type|
+ conv = type.to_proc
- a = []
- (0..).step {|x| a << x; break if a.size == 10 }
- assert_equal([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], a)
+ from = conv.(0)
+ to = conv.(10)
+ step = conv.(2)
- a = []
- (0..10).step(2) {|x| a << x }
- assert_equal([0, 2, 4, 6, 8, 10], a)
+ # finite
+ a = []
+ (from..to).step(step) {|x| a << x }
+ assert_equal([0, 2, 4, 6, 8, 10].map(&conv), a)
- a = []
- (0..).step(2) {|x| a << x; break if a.size == 10 }
- assert_equal([0, 2, 4, 6, 8, 10, 12, 14, 16, 18], a)
+ a = []
+ (from...to).step(step) {|x| a << x }
+ assert_equal([0, 2, 4, 6, 8].map(&conv), a)
- assert_kind_of(Enumerator::ArithmeticSequence, (0..10).step)
- assert_kind_of(Enumerator::ArithmeticSequence, (0..10).step(2))
- assert_kind_of(Enumerator::ArithmeticSequence, (0..10).step(0.5))
- assert_kind_of(Enumerator::ArithmeticSequence, (10..0).step(-1))
- assert_kind_of(Enumerator::ArithmeticSequence, (..10).step(2))
- assert_kind_of(Enumerator::ArithmeticSequence, (1..).step(2))
+ # Note: ArithmeticSequence behavior tested in its own test, but we also put it here
+ # to demonstrate the result is the same
+ assert_kind_of(Enumerator::ArithmeticSequence, (from..to).step(step))
+ assert_equal([0, 2, 4, 6, 8, 10].map(&conv), (from..to).step(step).to_a)
+ assert_kind_of(Enumerator::ArithmeticSequence, (from...to).step(step))
+ assert_equal([0, 2, 4, 6, 8].map(&conv), (from...to).step(step).to_a)
- assert_raise(ArgumentError) { (0..10).step(-1) { } }
- assert_raise(ArgumentError) { (0..10).step(0) }
- assert_raise(ArgumentError) { (0..10).step(0) { } }
- assert_raise(ArgumentError) { (0..).step(-1) { } }
- assert_raise(ArgumentError) { (0..).step(0) }
- assert_raise(ArgumentError) { (0..).step(0) { } }
+ # endless
+ a = []
+ (from..).step(step) {|x| a << x; break if a.size == 5 }
+ assert_equal([0, 2, 4, 6, 8].map(&conv), a)
- 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)
+ assert_kind_of(Enumerator::ArithmeticSequence, (from..).step(step))
+ assert_equal([0, 2, 4, 6, 8].map(&conv), (from..).step(step).take(5))
- a = []
- ("a" .. ).step(2) {|x| a << x; break if a.size == 13 }
- assert_equal(%w(a c e g i k m o q s u w y), a)
+ # beginless
+ assert_raise(ArgumentError) { (..to).step(step) {} }
+ assert_kind_of(Enumerator::ArithmeticSequence, (..to).step(step))
+ # This is inconsistent, but so it is implemented by ArithmeticSequence
+ assert_raise(TypeError) { (..to).step(step).to_a }
- a = []
- ("a" .. "z").step(2**32) {|x| a << x }
- assert_equal(["a"], a)
+ # negative step
- a = []
- (:a .. :z).step(2) {|x| a << x }
- assert_equal(%i(a c e g i k m o q s u w y), a)
+ a = []
+ (from..to).step(-step) {|x| a << x }
+ assert_equal([], a)
- a = []
- (:a .. ).step(2) {|x| a << x; break if a.size == 13 }
- assert_equal(%i(a c e g i k m o q s u w y), a)
+ a = []
+ (from..-to).step(-step) {|x| a << x }
+ assert_equal([0, -2, -4, -6, -8, -10].map(&conv), a)
- a = []
- (:a .. :z).step(2**32) {|x| a << x }
- assert_equal([:a], a)
+ a = []
+ (from...-to).step(-step) {|x| a << x }
+ assert_equal([0, -2, -4, -6, -8].map(&conv), a)
+
+ a = []
+ (from...).step(-step) {|x| a << x; break if a.size == 5 }
+ assert_equal([0, -2, -4, -6, -8].map(&conv), a)
+
+ assert_kind_of(Enumerator::ArithmeticSequence, (from..to).step(-step))
+ assert_equal([], (from..to).step(-step).to_a)
+
+ assert_kind_of(Enumerator::ArithmeticSequence, (from..-to).step(-step))
+ assert_equal([0, -2, -4, -6, -8, -10].map(&conv), (from..-to).step(-step).to_a)
+
+ assert_kind_of(Enumerator::ArithmeticSequence, (from...-to).step(-step))
+ assert_equal([0, -2, -4, -6, -8].map(&conv), (from...-to).step(-step).to_a)
+
+ assert_kind_of(Enumerator::ArithmeticSequence, (from...).step(-step))
+ assert_equal([0, -2, -4, -6, -8].map(&conv), (from...).step(-step).take(5))
+
+ # zero step
+
+ assert_raise(ArgumentError) { (from..to).step(0) {} }
+ assert_raise(ArgumentError) { (from..to).step(0) }
+
+ # default step
+
+ a = []
+ (from..to).step {|x| a << x }
+ assert_equal([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map(&conv), a)
+
+ assert_kind_of(Enumerator::ArithmeticSequence, (from..to).step)
+ assert_equal([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map(&conv), (from..to).step.to_a)
+
+ # default + endless range
+ a = []
+ (from..).step {|x| a << x; break if a.size == 5 }
+ assert_equal([0, 1, 2, 3, 4].map(&conv), a)
+
+ assert_kind_of(Enumerator::ArithmeticSequence, (from..).step)
+ assert_equal([0, 1, 2, 3, 4].map(&conv), (from..).step.take(5))
+
+ # default + beginless range
+ assert_kind_of(Enumerator::ArithmeticSequence, (..to).step)
+ # step is not numeric
+
+ to = conv.(5)
+
+ val = Struct.new(:val)
+
+ a = []
+ assert_raise(TypeError) { (from..to).step(val.new(step)) {|x| a << x } }
+ assert_kind_of(Enumerator, (from..to).step(val.new(step)))
+ assert_raise(TypeError) { (from..to).step(val.new(step)).to_a }
+
+ # step is not numeric, but coercible
+ val = Struct.new(:val) do
+ def coerce(num) = [self.class.new(num), self]
+ def +(other) = self.class.new(val + other.val)
+ def <=>(other) = other.is_a?(self.class) ? val <=> other.val : val <=> other
+ end
+
+ a = []
+ (from..to).step(val.new(step)) {|x| a << x }
+ assert_equal([from, val.new(conv.(2)), val.new(conv.(4))], a)
+
+ assert_kind_of(Enumerator, (from..to).step(val.new(step)))
+ assert_equal([from, val.new(conv.(2)), val.new(conv.(4))], (from..to).step(val.new(step)).to_a)
+ end
+ end
+
+ def test_step_numeric_fixnum_boundary
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) }
assert_raise(ArgumentError) { (2**32-1 .. 2**32+1).step(zero) { } }
+
a = []
(2**32-1 .. ).step(2) {|x| a << x; break if a.size == 2 }
assert_equal([4294967295, 4294967297], a)
@@ -315,58 +386,189 @@ class TestRange < Test::Unit::TestCase
a = []
(max..).step {|x| a << x; break if a.size == 2 }
assert_equal([max, max+1], a)
+
a = []
(max..).step(max) {|x| a << x; break if a.size == 4 }
assert_equal([max, 2*max, 3*max, 4*max], a)
+ end
- o1 = Object.new
- o2 = Object.new
- def o1.<=>(x); -1; end
- def o2.<=>(x); 0; end
- assert_raise(TypeError) { (o1..o2).step(1) { } }
- assert_raise(TypeError) { (o1..).step(1) { } }
+ def test_step_big_float
+ a = []
+ (0x40000000..0x40000002).step(0.5) {|x| a << x }
+ assert_equal([1073741824, 1073741824.5, 1073741825.0, 1073741825.5, 1073741826], a)
+ end
- class << o1; self; end.class_eval do
- define_method(:succ) { o2 }
- end
+ def test_step_non_numeric_range
+ # finite
a = []
- (o1..o2).step(1) {|x| a << x }
- assert_equal([o1, o2], a)
+ ('a'..'aaaa').step('a') { a << _1 }
+ assert_equal(%w[a aa aaa aaaa], a)
+
+ assert_kind_of(Enumerator, ('a'..'aaaa').step('a'))
+ assert_equal(%w[a aa aaa aaaa], ('a'..'aaaa').step('a').to_a)
a = []
- (o1...o2).step(1) {|x| a << x }
- assert_equal([o1], a)
+ ('a'...'aaaa').step('a') { a << _1 }
+ assert_equal(%w[a aa aaa], a)
- assert_nothing_raised("[ruby-dev:34557]") { (0..2).step(0.5) {|x| } }
+ assert_kind_of(Enumerator, ('a'...'aaaa').step('a'))
+ assert_equal(%w[a aa aaa], ('a'...'aaaa').step('a').to_a)
+ # endless
a = []
- (0..2).step(0.5) {|x| a << x }
- assert_equal([0, 0.5, 1.0, 1.5, 2.0], a)
+ ('a'...).step('a') { a << _1; break if a.size == 3 }
+ assert_equal(%w[a aa aaa], a)
+
+ assert_kind_of(Enumerator, ('a'...).step('a'))
+ assert_equal(%w[a aa aaa], ('a'...).step('a').take(3))
+
+ # beginless
+ assert_raise(ArgumentError) { (...'aaa').step('a') {} }
+ assert_raise(ArgumentError) { (...'aaa').step('a') }
+
+ # step is not provided
+ assert_raise(ArgumentError) { (Time.new(2022)...Time.new(2023)).step }
+ # step is incompatible
+ assert_raise(TypeError) { (Time.new(2022)...Time.new(2023)).step('a') {} }
+ assert_raise(TypeError) { (Time.new(2022)...Time.new(2023)).step('a').to_a }
+
+ # step is compatible, but shouldn't convert into numeric domain:
a = []
- (0..).step(0.5) {|x| a << x; break if a.size == 5 }
- assert_equal([0, 0.5, 1.0, 1.5, 2.0], a)
+ (Time.utc(2022, 2, 24)...).step(1) { a << _1; break if a.size == 2 }
+ assert_equal([Time.utc(2022, 2, 24), Time.utc(2022, 2, 24, 0, 0, 1)], a)
a = []
- (0x40000000..0x40000002).step(0.5) {|x| a << x }
- assert_equal([1073741824, 1073741824.5, 1073741825.0, 1073741825.5, 1073741826], a)
+ (Time.utc(2022, 2, 24)...).step(1.0) { a << _1; break if a.size == 2 }
+ assert_equal([Time.utc(2022, 2, 24), Time.utc(2022, 2, 24, 0, 0, 1)], a)
- o = Object.new
- def o.to_int() 1 end
- assert_nothing_raised("[ruby-dev:34558]") { (0..2).step(o) {|x| } }
+ a = []
+ (Time.utc(2022, 2, 24)...).step(1r) { a << _1; break if a.size == 2 }
+ assert_equal([Time.utc(2022, 2, 24), Time.utc(2022, 2, 24, 0, 0, 1)], a)
- o = Object.new
- class << o
- def to_str() "a" end
- def <=>(other) to_str <=> other end
- end
+ # step decreases the value
+ a = []
+ (Time.utc(2022, 2, 24)...).step(-1) { a << _1; break if a.size == 2 }
+ assert_equal([Time.utc(2022, 2, 24), Time.utc(2022, 2, 23, 23, 59, 59)], a)
a = []
- (o.."c").step(1) {|x| a << x}
- assert_equal(["a", "b", "c"], a)
+ (Time.utc(2022, 2, 24)...Time.utc(2022, 2, 23, 23, 59, 57)).step(-1) { a << _1 }
+ assert_equal([Time.utc(2022, 2, 24), Time.utc(2022, 2, 23, 23, 59, 59),
+ Time.utc(2022, 2, 23, 23, 59, 58)], a)
+
a = []
- (o..).step(1) {|x| a << x; break if a.size >= 3}
- assert_equal(["a", "b", "c"], a)
+ (Time.utc(2022, 2, 24)..Time.utc(2022, 2, 23, 23, 59, 57)).step(-1) { a << _1 }
+ assert_equal([Time.utc(2022, 2, 24), Time.utc(2022, 2, 23, 23, 59, 59),
+ Time.utc(2022, 2, 23, 23, 59, 58), Time.utc(2022, 2, 23, 23, 59, 57)], a)
+
+ # step decreases, but the range is forward-directed:
+ a = []
+ (Time.utc(2022, 2, 24)...Time.utc(2022, 2, 24, 01, 01, 03)).step(-1) { a << _1 }
+ assert_equal([], a)
+ end
+
+ def test_step_string_legacy
+ # finite
+ a = []
+ ('a'..'g').step(2) { a << _1 }
+ assert_equal(%w[a c e g], a)
+
+ assert_kind_of(Enumerator, ('a'..'g').step(2))
+ assert_equal(%w[a c e g], ('a'..'g').step(2).to_a)
+
+ a = []
+ ('a'...'g').step(2) { a << _1 }
+ assert_equal(%w[a c e], a)
+
+ assert_kind_of(Enumerator, ('a'...'g').step(2))
+ assert_equal(%w[a c e], ('a'...'g').step(2).to_a)
+
+ # endless
+ a = []
+ ('a'...).step(2) { a << _1; break if a.size == 3 }
+ assert_equal(%w[a c e], a)
+
+ assert_kind_of(Enumerator, ('a'...).step(2))
+ assert_equal(%w[a c e], ('a'...).step(2).take(3))
+
+ # beginless
+ assert_raise(ArgumentError) { (...'g').step(2) {} }
+ assert_raise(ArgumentError) { (...'g').step(2) }
+
+ # step is not provided
+ a = []
+ ('a'..'d').step { a << _1 }
+ assert_equal(%w[a b c d], a)
+
+ assert_kind_of(Enumerator, ('a'..'d').step)
+ assert_equal(%w[a b c d], ('a'..'d').step.to_a)
+
+ a = []
+ ('a'...'d').step { a << _1 }
+ assert_equal(%w[a b c], a)
+
+ assert_kind_of(Enumerator, ('a'...'d').step)
+ assert_equal(%w[a b c], ('a'...'d').step.to_a)
+
+ # endless
+ a = []
+ ('a'...).step { a << _1; break if a.size == 3 }
+ assert_equal(%w[a b c], a)
+
+ assert_kind_of(Enumerator, ('a'...).step)
+ assert_equal(%w[a b c], ('a'...).step.take(3))
+ end
+
+ def test_step_symbol_legacy
+ # finite
+ a = []
+ (:a..:g).step(2) { a << _1 }
+ assert_equal(%i[a c e g], a)
+
+ assert_kind_of(Enumerator, (:a..:g).step(2))
+ assert_equal(%i[a c e g], (:a..:g).step(2).to_a)
+
+ a = []
+ (:a...:g).step(2) { a << _1 }
+ assert_equal(%i[a c e], a)
+
+ assert_kind_of(Enumerator, (:a...:g).step(2))
+ assert_equal(%i[a c e], (:a...:g).step(2).to_a)
+
+ # endless
+ a = []
+ (:a...).step(2) { a << _1; break if a.size == 3 }
+ assert_equal(%i[a c e], a)
+
+ assert_kind_of(Enumerator, (:a...).step(2))
+ assert_equal(%i[a c e], (:a...).step(2).take(3))
+
+ # beginless
+ assert_raise(ArgumentError) { (...:g).step(2) {} }
+ assert_raise(ArgumentError) { (...:g).step(2) }
+
+ # step is not provided
+ a = []
+ (:a..:d).step { a << _1 }
+ assert_equal(%i[a b c d], a)
+
+ assert_kind_of(Enumerator, (:a..:d).step)
+ assert_equal(%i[a b c d], (:a..:d).step.to_a)
+
+ a = []
+ (:a...:d).step { a << _1 }
+ assert_equal(%i[a b c], a)
+
+ assert_kind_of(Enumerator, (:a...:d).step)
+ assert_equal(%i[a b c], (:a...:d).step.to_a)
+
+ # endless
+ a = []
+ (:a...).step { a << _1; break if a.size == 3 }
+ assert_equal(%i[a b c], a)
+
+ assert_kind_of(Enumerator, (:a...).step)
+ assert_equal(%i[a b c], (:a...).step.take(3))
end
def test_step_bug15537
@@ -456,6 +658,171 @@ class TestRange < Test::Unit::TestCase
assert_equal(["a", "b", "c"], a)
end
+ def test_each_with_succ
+ c = Struct.new(:i) do
+ def succ; self.class.new(i+1); end
+ def <=>(other) i <=> other.i;end
+ end.new(0)
+
+ result = []
+ (c..c.succ).each do |d|
+ result << d.i
+ end
+ assert_equal([0, 1], result)
+
+ result = []
+ (c..).each do |d|
+ result << d.i
+ break if d.i >= 4
+ end
+ assert_equal([0, 1, 2, 3, 4], result)
+ end
+
+ def test_reverse_each
+ a = []
+ (1..3).reverse_each {|x| a << x }
+ assert_equal([3, 2, 1], a)
+
+ a = []
+ (1...3).reverse_each {|x| a << x }
+ assert_equal([2, 1], a)
+
+ fmax = RbConfig::LIMITS['FIXNUM_MAX']
+ fmin = RbConfig::LIMITS['FIXNUM_MIN']
+
+ a = []
+ (fmax+1..fmax+3).reverse_each {|x| a << x }
+ assert_equal([fmax+3, fmax+2, fmax+1], a)
+
+ a = []
+ (fmax+1...fmax+3).reverse_each {|x| a << x }
+ assert_equal([fmax+2, fmax+1], a)
+
+ a = []
+ (fmax-1..fmax+1).reverse_each {|x| a << x }
+ assert_equal([fmax+1, fmax, fmax-1], a)
+
+ a = []
+ (fmax-1...fmax+1).reverse_each {|x| a << x }
+ assert_equal([fmax, fmax-1], a)
+
+ a = []
+ (fmin-1..fmin+1).reverse_each{|x| a << x }
+ assert_equal([fmin+1, fmin, fmin-1], a)
+
+ a = []
+ (fmin-1...fmin+1).reverse_each{|x| a << x }
+ assert_equal([fmin, fmin-1], a)
+
+ a = []
+ (fmin-3..fmin-1).reverse_each{|x| a << x }
+ assert_equal([fmin-1, fmin-2, fmin-3], a)
+
+ a = []
+ (fmin-3...fmin-1).reverse_each{|x| a << x }
+ assert_equal([fmin-2, fmin-3], a)
+
+ a = []
+ ("a".."c").reverse_each {|x| a << x }
+ assert_equal(["c", "b", "a"], a)
+ end
+
+ def test_reverse_each_for_beginless_range
+ fmax = RbConfig::LIMITS['FIXNUM_MAX']
+ fmin = RbConfig::LIMITS['FIXNUM_MIN']
+
+ a = []
+ (..3).reverse_each {|x| a << x; break if x <= 0 }
+ assert_equal([3, 2, 1, 0], a)
+
+ a = []
+ (...3).reverse_each {|x| a << x; break if x <= 0 }
+ assert_equal([2, 1, 0], a)
+
+ a = []
+ (..fmax+1).reverse_each {|x| a << x; break if x <= fmax-1 }
+ assert_equal([fmax+1, fmax, fmax-1], a)
+
+ a = []
+ (...fmax+1).reverse_each {|x| a << x; break if x <= fmax-1 }
+ assert_equal([fmax, fmax-1], a)
+
+ a = []
+ (..fmin+1).reverse_each {|x| a << x; break if x <= fmin-1 }
+ assert_equal([fmin+1, fmin, fmin-1], a)
+
+ a = []
+ (...fmin+1).reverse_each {|x| a << x; break if x <= fmin-1 }
+ assert_equal([fmin, fmin-1], a)
+
+ a = []
+ (..fmin-1).reverse_each {|x| a << x; break if x <= fmin-3 }
+ assert_equal([fmin-1, fmin-2, fmin-3], a)
+
+ a = []
+ (...fmin-1).reverse_each {|x| a << x; break if x <= fmin-3 }
+ assert_equal([fmin-2, fmin-3], a)
+ end
+
+ def test_reverse_each_for_endless_range
+ assert_raise(TypeError) { (1..).reverse_each {} }
+
+ enum = nil
+ assert_nothing_raised { enum = (1..).reverse_each }
+ assert_raise(TypeError) { enum.each {} }
+ end
+
+ def test_reverse_each_for_single_point_range
+ fmin = RbConfig::LIMITS['FIXNUM_MIN']
+ fmax = RbConfig::LIMITS['FIXNUM_MAX']
+
+ values = [fmin*2, fmin-1, fmin, 0, fmax, fmax+1, fmax*2]
+
+ values.each do |b|
+ r = b..b
+ a = []
+ r.reverse_each {|x| a << x }
+ assert_equal([b], a, "failed on #{r}")
+
+ r = b...b+1
+ a = []
+ r.reverse_each {|x| a << x }
+ assert_equal([b], a, "failed on #{r}")
+ end
+ end
+
+ def test_reverse_each_for_empty_range
+ fmin = RbConfig::LIMITS['FIXNUM_MIN']
+ fmax = RbConfig::LIMITS['FIXNUM_MAX']
+
+ values = [fmin*2, fmin-1, fmin, 0, fmax, fmax+1, fmax*2]
+
+ values.each do |b|
+ r = b..b-1
+ a = []
+ r.reverse_each {|x| a << x }
+ assert_equal([], a, "failed on #{r}")
+ end
+
+ values.repeated_permutation(2).to_a.product([true, false]).each do |(b, e), excl|
+ next unless b > e || (b == e && excl)
+
+ r = Range.new(b, e, excl)
+ a = []
+ r.reverse_each {|x| a << x }
+ assert_equal([], a, "failed on #{r}")
+ end
+ end
+
+ def test_reverse_each_with_no_block
+ enum = (1..5).reverse_each
+ assert_equal 5, enum.size
+
+ a = []
+ enum.each {|x| a << x }
+ assert_equal [5, 4, 3, 2, 1], a
+ end
+
def test_begin_end
assert_equal(0, (0..1).begin)
assert_equal(1, (0..1).end)
@@ -539,6 +906,10 @@ class TestRange < Test::Unit::TestCase
assert_not_operator(0..10, :===, 11)
assert_operator(5..nil, :===, 11)
assert_not_operator(5..nil, :===, 0)
+ assert_operator(nil..10, :===, 0)
+ assert_operator(nil..nil, :===, 0)
+ assert_operator(nil..nil, :===, Object.new)
+ assert_not_operator(0..10, :===, 0..10)
end
def test_eqq_string
@@ -583,6 +954,28 @@ class TestRange < Test::Unit::TestCase
assert_operator(c.new(0)..c.new(10), :===, c.new(5), bug12003)
end
+ def test_eqq_unbounded_ruby_bug_19864
+ t1 = Date.today
+ t2 = t1 + 1
+ assert_equal(true, (..t1) === t1)
+ assert_equal(false, (..t1) === t2)
+ assert_equal(true, (..t2) === t1)
+ assert_equal(true, (..t2) === t2)
+ assert_equal(false, (...t1) === t1)
+ assert_equal(false, (...t1) === t2)
+ assert_equal(true, (...t2) === t1)
+ assert_equal(false, (...t2) === t2)
+
+ assert_equal(true, (t1..) === t1)
+ assert_equal(true, (t1..) === t2)
+ assert_equal(false, (t2..) === t1)
+ assert_equal(true, (t2..) === t2)
+ assert_equal(true, (t1...) === t1)
+ assert_equal(true, (t1...) === t2)
+ assert_equal(false, (t2...) === t1)
+ assert_equal(true, (t2...) === t2)
+ end
+
def test_eqq_non_iteratable
k = Class.new do
include Comparable
@@ -599,11 +992,16 @@ class TestRange < Test::Unit::TestCase
assert_include("a"..."z", "y")
assert_not_include("a"..."z", "z")
assert_not_include("a".."z", "cc")
- assert_include("a".., "c")
- assert_not_include("a".., "5")
+ assert_raise(TypeError) {("a"..).include?("c")}
+ assert_raise(TypeError) {("a"..).include?("5")}
+
assert_include(0...10, 5)
assert_include(5..., 10)
assert_not_include(5..., 0)
+ assert_raise(TypeError) {(.."z").include?("z")}
+ assert_raise(TypeError) {(..."z").include?("z")}
+ assert_include(..10, 10)
+ assert_not_include(...10, 10)
end
def test_cover
@@ -666,6 +1064,35 @@ class TestRange < Test::Unit::TestCase
assert_not_operator(1..10, :cover?, 3...3)
assert_not_operator('aa'..'zz', :cover?, 'aa'...'zzz')
assert_not_operator(1..10, :cover?, 1...10.1)
+
+ assert_operator(..2, :cover?, 1)
+ assert_operator(..2, :cover?, 2)
+ assert_not_operator(..2, :cover?, 3)
+ assert_not_operator(...2, :cover?, 2)
+ assert_not_operator(..2, :cover?, "2")
+ assert_operator(..2, :cover?, ..2)
+ assert_operator(..2, :cover?, ...2)
+ assert_not_operator(..2, :cover?, .."2")
+ assert_not_operator(...2, :cover?, ..2)
+
+ assert_not_operator(2.., :cover?, 1)
+ assert_operator(2.., :cover?, 2)
+ assert_operator(2..., :cover?, 3)
+ assert_operator(2.., :cover?, 2)
+ assert_not_operator(2.., :cover?, "2")
+ assert_operator(2.., :cover?, 2..)
+ assert_operator(2.., :cover?, 2...)
+ assert_not_operator(2.., :cover?, "2"..)
+ assert_not_operator(2..., :cover?, 2..)
+ assert_operator(2..., :cover?, 3...)
+ assert_not_operator(2..., :cover?, 3..)
+ assert_not_operator(3.., :cover?, 2..)
+
+ assert_operator(nil..., :cover?, Object.new)
+ assert_operator(nil..., :cover?, nil...)
+ assert_operator(nil.., :cover?, nil...)
+ assert_not_operator(nil..., :cover?, nil..)
+ assert_not_operator(nil..., :cover?, 1..)
end
def test_beg_len
@@ -738,18 +1165,38 @@ class TestRange < Test::Unit::TestCase
end
def test_size
- assert_equal 42, (1..42).size
- assert_equal 41, (1...42).size
- assert_equal 6, (1...6.3).size
- assert_equal 5, (1.1...6).size
- assert_equal 42, (1..42).each.size
+ Enumerator.product([:to_i, :to_f, :to_r].repeated_permutation(2), [1, 10], [5, 5.5], [true, false]) do |(m1, m2), beg, ende, exclude_end|
+ r = Range.new(beg.send(m1), ende.send(m2), exclude_end)
+ iterable = true
+ yielded = []
+ begin
+ r.each { yielded << _1 }
+ rescue TypeError
+ iterable = false
+ end
+
+ if iterable
+ assert_equal(yielded.size, r.size, "failed on #{r}")
+ assert_equal(yielded.size, r.each.size, "failed on #{r}")
+ else
+ assert_raise(TypeError, "failed on #{r}") { r.size }
+ assert_raise(TypeError, "failed on #{r}") { r.each.size }
+ end
+ end
+
assert_nil ("a"..."z").size
- assert_equal Float::INFINITY, (1...).size
- assert_equal Float::INFINITY, (1.0...).size
- assert_equal Float::INFINITY, (...1).size
- assert_equal Float::INFINITY, (...1.0).size
- assert_nil ("a"...).size
+ assert_equal Float::INFINITY, (1..).size
+ assert_raise(TypeError) { (1.0..).size }
+ assert_raise(TypeError) { (1r..).size }
+ assert_nil ("a"..).size
+
+ assert_raise(TypeError) { (..1).size }
+ assert_raise(TypeError) { (..1.0).size }
+ assert_raise(TypeError) { (..1r).size }
+ assert_raise(TypeError) { (..'z').size }
+
+ assert_raise(TypeError) { (nil...nil).size }
end
def test_bsearch_typechecks_return_values
@@ -773,9 +1220,6 @@ class TestRange < Test::Unit::TestCase
assert_raise(TypeError) {
(Rational(-1,2)..Rational(9,4)).bsearch
}
- assert_raise(TypeError) {
- (BigDecimal('0.5')..BigDecimal('2.25')).bsearch
- }
end
def test_bsearch_for_fixnum
@@ -949,7 +1393,10 @@ class TestRange < Test::Unit::TestCase
assert_equal(nil, (bignum...bignum+ary.size).bsearch {|i| ary[i - bignum] >= 100 })
assert_equal(bignum + 0, (bignum...bignum+ary.size).bsearch {|i| true })
assert_equal(nil, (bignum...bignum+ary.size).bsearch {|i| false })
+
+ assert_equal(bignum * 2 + 1, (0...).bsearch {|i| i > bignum * 2 })
assert_equal(bignum * 2 + 1, (bignum...).bsearch {|i| i > bignum * 2 })
+ assert_equal(-bignum * 2 + 1, (...0).bsearch {|i| i > -bignum * 2 })
assert_equal(-bignum * 2 + 1, (...-bignum).bsearch {|i| i > -bignum * 2 })
assert_raise(TypeError) { ("a".."z").bsearch {} }
@@ -974,6 +1421,82 @@ class TestRange < Test::Unit::TestCase
end
def test_count
+ assert_equal 42, (1..42).count
+ assert_equal 41, (1...42).count
+ assert_equal 0, (42..1).count
+ assert_equal 0, (42...1).count
+ assert_equal 2**100, (1..2**100).count
+ assert_equal 6, (1...6.3).count
+ assert_equal 4, ('a'..'d').count
+ assert_equal 3, ('a'...'d').count
+
assert_equal(Float::INFINITY, (1..).count)
+ assert_equal(Float::INFINITY, (..1).count)
+ end
+
+ def test_overlap?
+ assert_not_operator(0..2, :overlap?, -2..-1)
+ assert_not_operator(0..2, :overlap?, -2...0)
+ assert_operator(0..2, :overlap?, -1..0)
+ assert_operator(0..2, :overlap?, 1..2)
+ assert_operator(0..2, :overlap?, 2..3)
+ assert_not_operator(0..2, :overlap?, 3..4)
+ assert_not_operator(0...2, :overlap?, 2..3)
+
+ assert_operator(..0, :overlap?, -1..0)
+ assert_operator(...0, :overlap?, -1..0)
+ assert_operator(..0, :overlap?, 0..1)
+ assert_operator(..0, :overlap?, ..1)
+ assert_not_operator(..0, :overlap?, 1..2)
+ assert_not_operator(...0, :overlap?, 0..1)
+
+ assert_not_operator(0.., :overlap?, -2..-1)
+ assert_not_operator(0.., :overlap?, ...0)
+ assert_operator(0.., :overlap?, -1..0)
+ assert_operator(0.., :overlap?, ..0)
+ assert_operator(0.., :overlap?, 0..1)
+ assert_operator(0.., :overlap?, 1..2)
+ assert_operator(0.., :overlap?, 1..)
+
+ assert_not_operator((1..3), :overlap?, ('a'..'d'))
+ assert_not_operator((1..), :overlap?, ('a'..))
+ assert_not_operator((..1), :overlap?, (..'a'))
+
+ assert_raise(TypeError) { (0..).overlap?(1) }
+ assert_raise(TypeError) { (0..).overlap?(nil) }
+
+ assert_operator((1..3), :overlap?, (2..4))
+ assert_operator((1...3), :overlap?, (2..3))
+ assert_operator((2..3), :overlap?, (1..2))
+ assert_operator((..3), :overlap?, (3..))
+ assert_operator((nil..nil), :overlap?, (3..))
+ assert_operator((nil...nil), :overlap?, (nil..))
+ assert_operator((nil..nil), :overlap?, (..3))
+
+ assert_raise(TypeError) { (1..3).overlap?(1) }
+
+ assert_not_operator((1..2), :overlap?, (2...2))
+ assert_not_operator((2...2), :overlap?, (1..2))
+
+ assert_not_operator((4..1), :overlap?, (2..3))
+ assert_not_operator((4..1), :overlap?, (..3))
+ assert_not_operator((4..1), :overlap?, (2..))
+
+ assert_not_operator((1..4), :overlap?, (3..2))
+ assert_not_operator((..4), :overlap?, (3..2))
+ assert_not_operator((1..), :overlap?, (3..2))
+
+ assert_not_operator((4..5), :overlap?, (2..3))
+ assert_not_operator((4..5), :overlap?, (2...4))
+
+ assert_not_operator((1..2), :overlap?, (3..4))
+ assert_not_operator((1...3), :overlap?, (3..4))
+
+ assert_not_operator((4..5), :overlap?, (2..3))
+ assert_not_operator((4..5), :overlap?, (2...4))
+
+ assert_not_operator((1..2), :overlap?, (3..4))
+ assert_not_operator((1...3), :overlap?, (3..4))
+ assert_not_operator((...3), :overlap?, (3..))
end
end
diff --git a/test/ruby/test_rational.rb b/test/ruby/test_rational.rb
index fe9de64c4c..a51ce3dc99 100644
--- a/test/ruby/test_rational.rb
+++ b/test/ruby/test_rational.rb
@@ -823,6 +823,8 @@ class Rational_Test < Test::Unit::TestCase
ng[5, 1, '5/_3']
ng[5, 3, '5/3_']
ng[5, 3, '5/3x']
+
+ ng[5, 1, '5/-3']
end
def test_parse_zero_denominator
diff --git a/test/ruby/test_refinement.rb b/test/ruby/test_refinement.rb
index a623432cf1..913c968d35 100644
--- a/test/ruby/test_refinement.rb
+++ b/test/ruby/test_refinement.rb
@@ -225,7 +225,7 @@ class TestRefinement < Test::Unit::TestCase
end
end
def test_method_should_use_refinements
- skip if Test::Unit::Runner.current_repeat_count > 0
+ omit if Test::Unit::Runner.current_repeat_count > 0
foo = Foo.new
assert_raise(NameError) { foo.method(:z) }
@@ -248,7 +248,7 @@ class TestRefinement < Test::Unit::TestCase
end
end
def test_instance_method_should_use_refinements
- skip if Test::Unit::Runner.current_repeat_count > 0
+ omit if Test::Unit::Runner.current_repeat_count > 0
foo = Foo.new
assert_raise(NameError) { Foo.instance_method(:z) }
@@ -747,130 +747,37 @@ class TestRefinement < Test::Unit::TestCase
end
end
- module IncludeIntoRefinement
- class C
- def bar
- return "C#bar"
- end
-
- def baz
- return "C#baz"
- end
- end
-
- module Mixin
- def foo
- return "Mixin#foo"
- end
-
- def bar
- return super << " Mixin#bar"
- end
-
- def baz
- return super << " Mixin#baz"
- end
- end
-
- module M
- refine C do
- include Mixin
-
- def baz
- return super << " M#baz"
- end
- end
- end
+ def self.suppress_verbose
+ verbose, $VERBOSE = $VERBOSE, nil
+ yield
+ ensure
+ $VERBOSE = verbose
end
- eval <<-EOF, Sandbox::BINDING
- using TestRefinement::IncludeIntoRefinement::M
-
- module TestRefinement::IncludeIntoRefinement::User
- def self.invoke_foo_on(x)
- x.foo
- end
-
- def self.invoke_bar_on(x)
- x.bar
- end
-
- def self.invoke_baz_on(x)
- x.baz
- end
- end
- EOF
-
def test_include_into_refinement
- x = IncludeIntoRefinement::C.new
- assert_equal("Mixin#foo", IncludeIntoRefinement::User.invoke_foo_on(x))
- assert_equal("C#bar Mixin#bar",
- IncludeIntoRefinement::User.invoke_bar_on(x))
- assert_equal("C#baz Mixin#baz M#baz",
- IncludeIntoRefinement::User.invoke_baz_on(x))
- end
-
- module PrependIntoRefinement
- class C
- def bar
- return "C#bar"
- end
-
- def baz
- return "C#baz"
- end
- end
-
- module Mixin
- def foo
- return "Mixin#foo"
- end
-
- def bar
- return super << " Mixin#bar"
- end
-
- def baz
- return super << " Mixin#baz"
- end
- end
-
- module M
- refine C do
- prepend Mixin
+ assert_raise(TypeError) do
+ c = Class.new
+ mixin = Module.new
- def baz
- return super << " M#baz"
+ Module.new do
+ refine c do
+ include mixin
end
end
end
end
- eval <<-EOF, Sandbox::BINDING
- using TestRefinement::PrependIntoRefinement::M
-
- module TestRefinement::PrependIntoRefinement::User
- def self.invoke_foo_on(x)
- x.foo
- end
-
- def self.invoke_bar_on(x)
- x.bar
- end
+ def test_prepend_into_refinement
+ assert_raise(TypeError) do
+ c = Class.new
+ mixin = Module.new
- def self.invoke_baz_on(x)
- x.baz
+ Module.new do
+ refine c do
+ prepend mixin
+ end
end
end
- EOF
-
- def test_prepend_into_refinement
- x = PrependIntoRefinement::C.new
- assert_equal("Mixin#foo", PrependIntoRefinement::User.invoke_foo_on(x))
- assert_equal("C#bar Mixin#bar",
- PrependIntoRefinement::User.invoke_bar_on(x))
- assert_equal("C#baz M#baz Mixin#baz",
- PrependIntoRefinement::User.invoke_baz_on(x))
end
PrependAfterRefine_CODE = <<-EOC
@@ -912,13 +819,13 @@ class TestRefinement < Test::Unit::TestCase
def test_prepend_after_refine_wb_miss
if /\A(arm|mips)/ =~ RUBY_PLATFORM
- skip "too slow cpu"
+ omit "too slow cpu"
end
assert_normal_exit %Q{
GC.stress = true
10.times{
#{PrependAfterRefine_CODE}
- undef PrependAfterRefine
+ Object.send(:remove_const, :PrependAfterRefine)
}
}, timeout: 60
end
@@ -1137,7 +1044,7 @@ class TestRefinement < Test::Unit::TestCase
end
using Test
def t
- 'Refinements are broken!'.chop!
+ 'Refinements are broken!'.dup.chop!
end
t
module Test
@@ -1299,6 +1206,41 @@ class TestRefinement < Test::Unit::TestCase
INPUT
end
+ def test_refined_protected_methods
+ assert_separately([], <<-"end;")
+ bug18806 = '[ruby-core:108705] [Bug #18806]'
+ class C; end
+
+ module R
+ refine C do
+ def refined_call_foo = foo
+ def refined_call_foo_on(other) = other.foo
+
+ protected
+
+ def foo = :foo
+ end
+ end
+
+ class C
+ using R
+
+ def call_foo = foo
+ def call_foo_on(other) = other.foo
+ end
+
+ c = C.new
+ assert_equal :foo, c.call_foo, bug18806
+ assert_equal :foo, c.call_foo_on(c), bug18806
+ assert_equal :foo, c.call_foo_on(C.new), bug18806
+
+ using R
+ assert_equal :foo, c.refined_call_foo, bug18806
+ assert_equal :foo, c.refined_call_foo_on(c), bug18806
+ assert_equal :foo, c.refined_call_foo_on(C.new), bug18806
+ end;
+ end
+
def test_refine_basic_object
assert_separately([], <<-"end;")
bug10106 = '[ruby-core:64166] [Bug #10106]'
@@ -1664,18 +1606,35 @@ class TestRefinement < Test::Unit::TestCase
end
using R
+ def m
+ C.new.m
+ end
+
assert_equal(:foo, C.new.m)
+ assert_equal(:foo, m)
module R
refine C do
+
+ assert_equal(:foo, C.new.m)
+ assert_equal(:foo, m)
+
alias m m
+
+ assert_equal(:foo, C.new.m)
+ assert_equal(:foo, m)
+
def m
:bar
end
+
+ assert_equal(:bar, C.new.m, "[ruby-core:71423] [Bug #11672]")
+ assert_equal(:bar, m, "[Bug #20285]")
end
end
assert_equal(:bar, C.new.m, "[ruby-core:71423] [Bug #11672]")
+ assert_equal(:bar, m, "[Bug #20285]")
end;
end
@@ -1780,6 +1739,8 @@ class TestRefinement < Test::Unit::TestCase
refine Object do
def in_ref_a
end
+
+ RefA.const_set(:REF, self)
end
end
@@ -1787,6 +1748,8 @@ class TestRefinement < Test::Unit::TestCase
refine Object do
def in_ref_b
end
+
+ RefB.const_set(:REF, self)
end
end
@@ -1796,23 +1759,28 @@ class TestRefinement < Test::Unit::TestCase
refine Object do
def in_ref_c
end
+
+ RefC.const_set(:REF, self)
end
end
module Foo
using RefB
USED_MODS = Module.used_modules
+ USED_REFS = Module.used_refinements
end
module Bar
using RefC
USED_MODS = Module.used_modules
+ USED_REFS = Module.used_refinements
end
module Combined
using RefA
using RefB
USED_MODS = Module.used_modules
+ USED_REFS = Module.used_refinements
end
end
@@ -1824,6 +1792,47 @@ class TestRefinement < Test::Unit::TestCase
assert_equal [ref::RefB, ref::RefA], ref::Combined::USED_MODS
end
+ def test_used_refinements
+ ref = VisibleRefinements
+ assert_equal [], Module.used_refinements
+ assert_equal [ref::RefB::REF], ref::Foo::USED_REFS
+ assert_equal [ref::RefC::REF], ref::Bar::USED_REFS
+ assert_equal [ref::RefB::REF, ref::RefA::REF], ref::Combined::USED_REFS
+ end
+
+ def test_refinements
+ int_refinement = nil
+ str_refinement = nil
+ m = Module.new {
+ refine Integer do
+ int_refinement = self
+ end
+
+ refine String do
+ str_refinement = self
+ end
+ }
+ assert_equal([int_refinement, str_refinement], m.refinements)
+ end
+
+ def test_target
+ refinements = Module.new {
+ refine Integer do
+ end
+
+ refine String do
+ end
+ }.refinements
+ assert_equal(Integer, refinements[0].target)
+ assert_warn(/Refinement#refined_class is deprecated and will be removed in Ruby 3.4; use Refinement#target instead/) do
+ assert_equal(Integer, refinements[0].refined_class)
+ end
+ assert_equal(String, refinements[1].target)
+ assert_warn(/Refinement#refined_class is deprecated and will be removed in Ruby 3.4; use Refinement#target instead/) do
+ assert_equal(String, refinements[1].refined_class)
+ end
+ end
+
def test_warn_setconst_in_refinmenet
bug10103 = '[ruby-core:64143] [Bug #10103]'
warnings = [
@@ -1968,10 +1977,10 @@ class TestRefinement < Test::Unit::TestCase
m = Module.new do
r = refine(String) {def test;:ok end}
end
- assert_raise_with_message(ArgumentError, /refinement/, bug) do
+ assert_raise_with_message(TypeError, /refinement/, bug) do
m.module_eval {include r}
end
- assert_raise_with_message(ArgumentError, /refinement/, bug) do
+ assert_raise_with_message(TypeError, /refinement/, bug) do
m.module_eval {prepend r}
end
end
@@ -2537,6 +2546,25 @@ class TestRefinement < Test::Unit::TestCase
assert_equal(:second, klass.new.foo)
end
+ class Bug18180
+ module M
+ refine Array do
+ def min; :min; end
+ def max; :max; end
+ end
+ end
+
+ using M
+
+ def t
+ [[1+0, 2, 4].min, [1, 2, 4].min, [1+0, 2, 4].max, [1, 2, 4].max]
+ end
+ end
+
+ def test_refine_array_min_max
+ assert_equal([:min, :min, :max, :max], Bug18180.new.t)
+ end
+
class Bug17822
module Ext
refine(Bug17822) do
@@ -2571,6 +2599,125 @@ class TestRefinement < Test::Unit::TestCase
assert_equal([refinement], as, "[ruby-core:86949] [Bug #14744]")
end
+ module TestImport
+ class A
+ def foo
+ "original"
+ end
+ end
+
+ module B
+ BAR = "bar"
+
+ def bar
+ "#{foo}:#{BAR}"
+ end
+ end
+
+ module C
+ refine A do
+ import_methods B
+
+ def foo
+ "refined"
+ end
+ end
+ end
+
+ module UsingC
+ using C
+
+ def self.call_bar
+ A.new.bar
+ end
+ end
+ end
+
+ def test_import_methods
+ assert_equal("refined:bar", TestImport::UsingC.call_bar)
+
+ assert_raise(ArgumentError) do
+ Module.new do
+ refine Integer do
+ import_methods Enumerable
+ end
+ end
+ end
+ end
+
+ def test_inherit_singleton_methods_of_module
+ assert_equal([], Refinement.used_modules)
+ end
+
+ def test_inlinecache
+ assert_separately([], <<-"end;")
+ module R
+ refine String do
+ def to_s = :R
+ end
+ end
+
+ 2.times{|i|
+ s = ''.to_s
+ assert_equal '', s if i == 0
+ assert_equal :R, s if i == 1
+ using R if i == 0
+ assert_equal :R, ''.to_s
+ }
+ end;
+ end
+
+ def test_inline_cache_invalidation
+ klass = Class.new do
+ def cached_foo_callsite = foo
+
+ def foo = :v1
+
+ host = self
+ @refinement = Module.new do
+ refine(host) do
+ def foo = :unused
+ end
+ end
+ end
+
+ obj = klass.new
+ obj.cached_foo_callsite # prime cache
+ klass.class_eval do
+ def foo = :v2 # invalidate
+ end
+ assert_equal(:v2, obj.cached_foo_callsite)
+ end
+
+ # [Bug #20302]
+ def test_multiple_refinements_for_same_module
+ assert_in_out_err([], <<-INPUT, %w(:f2 :f1), [])
+ module M1
+ refine(Kernel) do
+ def f1 = :f1
+ end
+ end
+
+ module M2
+ refine(Kernel) do
+ def f2 = :f2
+ end
+ end
+
+ class Foo
+ using M1
+ using M2
+
+ def test
+ p f2
+ p f1
+ end
+ end
+
+ Foo.new.test
+ INPUT
+ end
+
private
def eval_using(mod, s)
diff --git a/test/ruby/test_regexp.rb b/test/ruby/test_regexp.rb
index 7c76f5c150..58b3081035 100644
--- a/test/ruby/test_regexp.rb
+++ b/test/ruby/test_regexp.rb
@@ -40,19 +40,6 @@ class TestRegexp < Test::Unit::TestCase
assert_equal("a".gsub(/a\Z/, ""), "")
end
- def test_yoshidam_net_20041111_1
- s = "[\xC2\xA0-\xC3\xBE]"
- r = assert_deprecated_warning(/ignored/) {Regexp.new(s, nil, "u")}
- assert_match(r, "\xC3\xBE")
- end
-
- def test_yoshidam_net_20041111_2
- assert_raise(RegexpError) do
- s = "[\xFF-\xFF]".force_encoding("utf-8")
- assert_warning(/ignored/) {Regexp.new(s, nil, "u")}
- end
- end
-
def test_ruby_dev_31309
assert_equal('Ruby', 'Ruby'.sub(/[^a-z]/i, '-'))
end
@@ -85,12 +72,141 @@ class TestRegexp < Test::Unit::TestCase
end
end
+ def test_to_s_under_gc_compact_stress
+ omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077
+ EnvUtil.under_gc_compact_stress do
+ str = "abcd\u3042"
+ [:UTF_16BE, :UTF_16LE, :UTF_32BE, :UTF_32LE].each do |es|
+ enc = Encoding.const_get(es)
+ rs = Regexp.new(str.encode(enc)).to_s
+ assert_equal("(?-mix:abcd\u3042)".encode(enc), rs)
+ assert_equal(enc, rs.encoding)
+ end
+ end
+ end
+
def test_to_s_extended_subexp
re = /#\g#{"\n"}/x
re = /#{re}/
assert_warn('', '[ruby-core:82328] [Bug #13798]') {re.to_s}
end
+ def test_extended_comment_invalid_escape_bug_18294
+ assert_separately([], <<-RUBY)
+ re = / C:\\\\[a-z]{5} # e.g. C:\\users /x
+ assert_match(re, 'C:\\users')
+ assert_not_match(re, 'C:\\user')
+
+ re = /
+ foo # \\M-ca
+ bar
+ /x
+ assert_match(re, 'foobar')
+ assert_not_match(re, 'foobaz')
+
+ re = /
+ f[#o]o # \\M-ca
+ bar
+ /x
+ assert_match(re, 'foobar')
+ assert_not_match(re, 'foobaz')
+
+ re = /
+ f[[:alnum:]#]o # \\M-ca
+ bar
+ /x
+ assert_match(re, 'foobar')
+ assert_not_match(re, 'foobaz')
+
+ re = /
+ f(?# \\M-ca)oo # \\M-ca
+ bar
+ /x
+ assert_match(re, 'foobar')
+ assert_not_match(re, 'foobaz')
+
+ re = /f(?# \\M-ca)oobar/
+ assert_match(re, 'foobar')
+ assert_not_match(re, 'foobaz')
+
+ re = /[-(?# fca)]oobar/
+ assert_match(re, 'foobar')
+ assert_not_match(re, 'foobaz')
+
+ re = /f(?# ca\0\\M-ca)oobar/
+ assert_match(re, 'foobar')
+ assert_not_match(re, 'foobaz')
+ RUBY
+
+ assert_raise(SyntaxError) {eval "/\\users/x"}
+ assert_raise(SyntaxError) {eval "/[\\users]/x"}
+ assert_raise(SyntaxError) {eval "/(?<\\users)/x"}
+ assert_raise(SyntaxError) {eval "/# \\users/"}
+ end
+
+ def test_nonextended_section_of_extended_regexp_bug_19379
+ assert_separately([], <<-'RUBY')
+ re = /(?-x:#)/x
+ assert_match(re, '#')
+ assert_not_match(re, '-')
+
+ re = /(?xi:#
+ y)/
+ assert_match(re, 'Y')
+ assert_not_match(re, '-')
+
+ re = /(?mix:#
+ y)/
+ assert_match(re, 'Y')
+ assert_not_match(re, '-')
+
+ re = /(?x-im:#
+ y)/i
+ assert_match(re, 'y')
+ assert_not_match(re, 'Y')
+
+ re = /(?-imx:(?xim:#
+ y))/x
+ assert_match(re, 'y')
+ assert_not_match(re, '-')
+
+ re = /(?x)#
+ y/
+ assert_match(re, 'y')
+ assert_not_match(re, 'Y')
+
+ re = /(?mx-i)#
+ y/i
+ assert_match(re, 'y')
+ assert_not_match(re, 'Y')
+
+ re = /(?-imx:(?xim:#
+ (?-x)y#))/x
+ assert_match(re, 'Y#')
+ assert_not_match(re, '-#')
+
+ re = /(?imx:#
+ (?-xim:#(?im)#(?x)#
+ )#
+ (?x)#
+ y)/
+ assert_match(re, '###Y')
+ assert_not_match(re, '###-')
+
+ re = %r{#c-\w+/comment/[\w-]+}
+ re = %r{https?://[^/]+#{re}}x
+ assert_match(re, 'http://foo#c-x/comment/bar')
+ assert_not_match(re, 'http://foo#cx/comment/bar')
+ RUBY
+ end
+
+ def test_utf8_comment_in_usascii_extended_regexp_bug_19455
+ assert_separately([], <<-RUBY)
+ assert_equal(Encoding::UTF_8, /(?#\u1000)/x.encoding)
+ assert_equal(Encoding::UTF_8, /#\u1000/x.encoding)
+ RUBY
+ end
+
def test_union
assert_equal :ok, begin
Regexp.union(
@@ -208,6 +324,9 @@ class TestRegexp < Test::Unit::TestCase
assert_equal({'a' => '1', 'b' => '2', 'c' => '3'}, /^(?<a>.)(?<b>.)(?<c>.)?/.match('123').named_captures)
assert_equal({'a' => '1', 'b' => '2', 'c' => ''}, /^(?<a>.)(?<b>.)(?<c>.?)/.match('12').named_captures)
+ assert_equal({a: '1', b: '2', c: ''}, /^(?<a>.)(?<b>.)(?<c>.?)/.match('12').named_captures(symbolize_names: true))
+ assert_equal({'a' => '1', 'b' => '2', 'c' => ''}, /^(?<a>.)(?<b>.)(?<c>.?)/.match('12').named_captures(symbolize_names: false))
+
assert_equal({'a' => 'x'}, /(?<a>x)|(?<a>y)/.match('x').named_captures)
assert_equal({'a' => 'y'}, /(?<a>x)|(?<a>y)/.match('y').named_captures)
@@ -265,6 +384,27 @@ class TestRegexp < Test::Unit::TestCase
assert_equal(re, re.match("foo").regexp)
end
+ def test_match_lambda_multithread
+ bug17507 = "[ruby-core:101901]"
+ str = "a-x-foo-bar-baz-z-b"
+
+ worker = lambda do
+ m = /foo-([A-Za-z0-9_\.]+)-baz/.match(str)
+ assert_equal("bar", m[1], bug17507)
+
+ # These two lines are needed to trigger the bug
+ File.exist? "/tmp"
+ str.gsub(/foo-bar-baz/, "foo-abc-baz")
+ end
+
+ def self. threaded_test(worker)
+ 6.times.map {Thread.new {10_000.times {worker.call}}}.each(&:join)
+ end
+
+ # The bug only occurs in a method calling a block/proc/lambda
+ threaded_test(worker)
+ end
+
def test_source
bug5484 = '[ruby-core:40364]'
assert_equal('', //.source)
@@ -330,6 +470,13 @@ class TestRegexp < Test::Unit::TestCase
assert_equal('/\/\xF1\xF2\xF3/i', /\/#{s}/i.inspect)
end
+ def test_inspect_under_gc_compact_stress
+ omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077
+ EnvUtil.under_gc_compact_stress do
+ assert_equal('/(?-mix:\\/)|/', Regexp.union(/\//, "").inspect)
+ end
+ end
+
def test_char_to_option
assert_equal("BAR", "FOOBARBAZ"[/b../i])
assert_equal("bar", "foobarbaz"[/ b . . /x])
@@ -403,6 +550,37 @@ class TestRegexp < Test::Unit::TestCase
assert_equal([2, 3], m.offset(3))
end
+ def test_match_byteoffset_begin_end
+ m = /(?<x>b..)/.match("foobarbaz")
+ assert_equal([3, 6], m.byteoffset("x"))
+ assert_equal(3, m.begin("x"))
+ assert_equal(6, m.end("x"))
+ assert_raise(IndexError) { m.byteoffset("y") }
+ assert_raise(IndexError) { m.byteoffset(2) }
+ assert_raise(IndexError) { m.begin(2) }
+ assert_raise(IndexError) { m.end(2) }
+ assert_raise(IndexError) { m.bytebegin(2) }
+ assert_raise(IndexError) { m.byteend(2) }
+
+ m = /(?<x>q..)?/.match("foobarbaz")
+ assert_equal([nil, nil], m.byteoffset("x"))
+ assert_equal(nil, m.begin("x"))
+ assert_equal(nil, m.end("x"))
+ assert_equal(nil, m.bytebegin("x"))
+ assert_equal(nil, m.byteend("x"))
+
+ m = /\A\u3042(.)(.)?(.)\z/.match("\u3042\u3043\u3044")
+ assert_equal([3, 6], m.byteoffset(1))
+ assert_equal(3, m.bytebegin(1))
+ assert_equal(6, m.byteend(1))
+ assert_equal([nil, nil], m.byteoffset(2))
+ assert_equal(nil, m.bytebegin(2))
+ assert_equal(nil, m.byteend(2))
+ assert_equal([6, 9], m.byteoffset(3))
+ assert_equal(6, m.bytebegin(3))
+ assert_equal(9, m.byteend(3))
+ end
+
def test_match_to_s
m = /(?<x>b..)/.match("foobarbaz")
assert_equal("bar", m.to_s)
@@ -446,6 +624,7 @@ class TestRegexp < Test::Unit::TestCase
assert_nil(m[5])
assert_raise(IndexError) { m[:foo] }
assert_raise(TypeError) { m[nil] }
+ assert_equal(["baz", nil], m[-2, 3])
end
def test_match_values_at
@@ -512,17 +691,73 @@ class TestRegexp < Test::Unit::TestCase
assert_equal('#<MatchData "foobarbaz" 1:"foo" 2:"bar" 3:"baz" 4:nil>', m.inspect)
end
+ def test_match_data_deconstruct
+ m = /foo.+/.match("foobarbaz")
+ assert_equal([], m.deconstruct)
+
+ m = /(foo).+(baz)/.match("foobarbaz")
+ assert_equal(["foo", "baz"], m.deconstruct)
+
+ m = /(...)(...)(...)(...)?/.match("foobarbaz")
+ assert_equal(["foo", "bar", "baz", nil], m.deconstruct)
+ end
+
+ def test_match_data_deconstruct_keys
+ m = /foo.+/.match("foobarbaz")
+ assert_equal({}, m.deconstruct_keys([:a]))
+
+ m = /(?<a>foo).+(?<b>baz)/.match("foobarbaz")
+ assert_equal({a: "foo", b: "baz"}, m.deconstruct_keys(nil))
+ assert_equal({a: "foo", b: "baz"}, m.deconstruct_keys([:a, :b]))
+ assert_equal({b: "baz"}, m.deconstruct_keys([:b]))
+ assert_equal({}, m.deconstruct_keys([:c, :a]))
+ assert_equal({a: "foo"}, m.deconstruct_keys([:a, :c]))
+ assert_equal({}, m.deconstruct_keys([:a, :b, :c]))
+
+ assert_raise(TypeError) {
+ m.deconstruct_keys(0)
+ }
+
+ assert_raise(TypeError) {
+ m.deconstruct_keys(["a", "b"])
+ }
+ end
+
+ def test_match_no_match_no_matchdata
+ EnvUtil.without_gc do
+ h = {}
+ ObjectSpace.count_objects(h)
+ prev_matches = h[:T_MATCH] || 0
+ _md = /[A-Z]/.match('1') # no match
+ ObjectSpace.count_objects(h)
+ new_matches = h[:T_MATCH] || 0
+ assert_equal prev_matches, new_matches, "Bug [#20104]"
+ end
+ end
+
def test_initialize
assert_raise(ArgumentError) { Regexp.new }
assert_equal(/foo/, assert_warning(/ignored/) {Regexp.new(/foo/, Regexp::IGNORECASE)})
+ assert_equal(/foo/, assert_no_warning(/ignored/) {Regexp.new(/foo/)})
+ assert_equal(/foo/, assert_no_warning(/ignored/) {Regexp.new(/foo/, timeout: nil)})
- assert_equal(Encoding.find("US-ASCII"), Regexp.new("b..", nil, "n").encoding)
- assert_equal("bar", "foobarbaz"[Regexp.new("b..", nil, "n")])
- assert_equal(//n, Regexp.new("", nil, "n"))
+ arg_encoding_none = //n.options # ARG_ENCODING_NONE is implementation defined value
- arg_encoding_none = 32 # ARG_ENCODING_NONE is implementation defined value
- assert_equal(arg_encoding_none, Regexp.new("", nil, "n").options)
- assert_equal(arg_encoding_none, Regexp.new("", nil, "N").options)
+ assert_deprecated_warning('') do
+ assert_equal(Encoding.find("US-ASCII"), Regexp.new("b..", Regexp::NOENCODING).encoding)
+ assert_equal("bar", "foobarbaz"[Regexp.new("b..", Regexp::NOENCODING)])
+ assert_equal(//, Regexp.new(""))
+ assert_equal(//, Regexp.new("", timeout: 1))
+ assert_equal(//n, Regexp.new("", Regexp::NOENCODING))
+ assert_equal(//n, Regexp.new("", Regexp::NOENCODING, timeout: 1))
+
+ assert_equal(arg_encoding_none, Regexp.new("", Regexp::NOENCODING).options)
+
+ assert_nil(Regexp.new("").timeout)
+ assert_equal(1.0, Regexp.new("", timeout: 1.0).timeout)
+ assert_nil(Regexp.compile("").timeout)
+ assert_equal(1.0, Regexp.compile("", timeout: 1.0).timeout)
+ end
assert_raise(RegexpError) { Regexp.new(")(") }
assert_raise(RegexpError) { Regexp.new('[\\40000000000') }
@@ -530,6 +765,35 @@ class TestRegexp < Test::Unit::TestCase
assert_raise(RegexpError) { Regexp.new("((?<v>))\\g<0>") }
end
+ def test_initialize_from_regex_memory_corruption
+ assert_ruby_status([], <<-'end;')
+ 10_000.times { Regexp.new(Regexp.new("(?<name>)")) }
+ end;
+ end
+
+ def test_initialize_bool_warning
+ assert_warning(/expected true or false as ignorecase/) do
+ Regexp.new("foo", :i)
+ end
+ end
+
+ def test_initialize_option
+ assert_equal(//i, Regexp.new("", "i"))
+ assert_equal(//m, Regexp.new("", "m"))
+ assert_equal(//x, Regexp.new("", "x"))
+ assert_equal(//imx, Regexp.new("", "imx"))
+ assert_equal(//, Regexp.new("", ""))
+ assert_equal(//imx, Regexp.new("", "mimix"))
+
+ assert_raise(ArgumentError) { Regexp.new("", "e") }
+ assert_raise(ArgumentError) { Regexp.new("", "n") }
+ assert_raise(ArgumentError) { Regexp.new("", "s") }
+ assert_raise(ArgumentError) { Regexp.new("", "u") }
+ assert_raise(ArgumentError) { Regexp.new("", "o") }
+ assert_raise(ArgumentError) { Regexp.new("", "j") }
+ assert_raise(ArgumentError) { Regexp.new("", "xmen") }
+ end
+
def test_match_control_meta_escape
assert_equal(0, /\c\xFF/ =~ "\c\xFF")
assert_equal(0, /\c\M-\xFF/ =~ "\c\M-\xFF")
@@ -638,6 +902,14 @@ class TestRegexp < Test::Unit::TestCase
$_ = nil; assert_nil(~/./)
end
+ def test_match_under_gc_compact_stress
+ omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077
+ EnvUtil.under_gc_compact_stress do
+ m = /(?<foo>.)(?<n>[^aeiou])?(?<bar>.+)/.match("hoge\u3042")
+ assert_equal("h", m.match(:foo))
+ end
+ end
+
def test_match_p
/backref/ =~ 'backref'
# must match here, but not in a separate method, e.g., assert_send,
@@ -1144,25 +1416,109 @@ class TestRegexp < Test::Unit::TestCase
end
def test_unicode_age
- assert_match(/^\p{Age=6.0}$/u, "\u261c")
- assert_match(/^\p{Age=1.1}$/u, "\u261c")
- assert_no_match(/^\P{age=6.0}$/u, "\u261c")
-
- assert_match(/^\p{age=6.0}$/u, "\u31f6")
- assert_match(/^\p{age=3.2}$/u, "\u31f6")
- assert_no_match(/^\p{age=3.1}$/u, "\u31f6")
- assert_no_match(/^\p{age=3.0}$/u, "\u31f6")
- assert_no_match(/^\p{age=1.1}$/u, "\u31f6")
+ assert_unicode_age("\u261c", matches: %w"6.0 1.1", unmatches: [])
+
+ assert_unicode_age("\u31f6", matches: %w"6.0 3.2", unmatches: %w"3.1 3.0 1.1")
+ assert_unicode_age("\u2754", matches: %w"6.0", unmatches: %w"5.0 4.0 3.0 2.0 1.1")
+
+ assert_unicode_age("\u32FF", matches: %w"12.1", unmatches: %w"12.0")
+ end
+
+ def test_unicode_age_14_0
+ @matches = %w"14.0"
+ @unmatches = %w"13.0"
+
+ assert_unicode_age("\u{10570}")
+ assert_unicode_age("\u9FFF")
+ assert_unicode_age("\u{2A6DF}")
+ assert_unicode_age("\u{2B738}")
+ end
+
+ def test_unicode_age_15_0
+ @matches = %w"15.0"
+ @unmatches = %w"14.0"
+
+ assert_unicode_age("\u{0CF3}",
+ "KANNADA SIGN COMBINING ANUSVARA ABOVE RIGHT")
+ assert_unicode_age("\u{0ECE}", "LAO YAMAKKAN")
+ assert_unicode_age("\u{10EFD}".."\u{10EFF}",
+ "ARABIC SMALL LOW WORD SAKTA..ARABIC SMALL LOW WORD MADDA")
+ assert_unicode_age("\u{1123F}".."\u{11241}",
+ "KHOJKI LETTER QA..KHOJKI VOWEL SIGN VOCALIC R")
+ assert_unicode_age("\u{11B00}".."\u{11B09}",
+ "DEVANAGARI HEAD MARK..DEVANAGARI SIGN MINDU")
+ assert_unicode_age("\u{11F00}".."\u{11F10}",
+ "KAWI SIGN CANDRABINDU..KAWI LETTER O")
+ assert_unicode_age("\u{11F12}".."\u{11F3A}",
+ "KAWI LETTER KA..KAWI VOWEL SIGN VOCALIC R")
+ assert_unicode_age("\u{11F3E}".."\u{11F59}",
+ "KAWI VOWEL SIGN E..KAWI DIGIT NINE")
+ assert_unicode_age("\u{1342F}",
+ "EGYPTIAN HIEROGLYPH V011D")
+ assert_unicode_age("\u{13439}".."\u{1343F}",
+ "EGYPTIAN HIEROGLYPH INSERT AT MIDDLE..EGYPTIAN HIEROGLYPH END WALLED ENCLOSURE")
+ assert_unicode_age("\u{13440}".."\u{13455}",
+ "EGYPTIAN HIEROGLYPH MIRROR HORIZONTALLY..EGYPTIAN HIEROGLYPH MODIFIER DAMAGED")
+ assert_unicode_age("\u{1B132}", "HIRAGANA LETTER SMALL KO")
+ assert_unicode_age("\u{1B155}", "KATAKANA LETTER SMALL KO")
+ assert_unicode_age("\u{1D2C0}".."\u{1D2D3}",
+ "KAKTOVIK NUMERAL ZERO..KAKTOVIK NUMERAL NINETEEN")
+ assert_unicode_age("\u{1DF25}".."\u{1DF2A}",
+ "LATIN SMALL LETTER D WITH MID-HEIGHT LEFT HOOK..LATIN SMALL LETTER T WITH MID-HEIGHT LEFT HOOK")
+ assert_unicode_age("\u{1E030}".."\u{1E06D}",
+ "MODIFIER LETTER CYRILLIC SMALL A..MODIFIER LETTER CYRILLIC SMALL STRAIGHT U WITH STROKE")
+ assert_unicode_age("\u{1E08F}",
+ "COMBINING CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I")
+ assert_unicode_age("\u{1E4D0}".."\u{1E4F9}",
+ "NAG MUNDARI LETTER O..NAG MUNDARI DIGIT NINE")
+ assert_unicode_age("\u{1F6DC}", "WIRELESS")
+ assert_unicode_age("\u{1F774}".."\u{1F776}",
+ "LOT OF FORTUNE..LUNAR ECLIPSE")
+ assert_unicode_age("\u{1F77B}".."\u{1F77F}",
+ "HAUMEA..ORCUS")
+ assert_unicode_age("\u{1F7D9}", "NINE POINTED WHITE STAR")
+ assert_unicode_age("\u{1FA75}".."\u{1FA77}",
+ "LIGHT BLUE HEART..PINK HEART")
+ assert_unicode_age("\u{1FA87}".."\u{1FA88}",
+ "MARACAS..FLUTE")
+ assert_unicode_age("\u{1FAAD}".."\u{1FAAF}",
+ "FOLDING HAND FAN..KHANDA")
+ assert_unicode_age("\u{1FABB}".."\u{1FABD}",
+ "HYACINTH..WING")
+ assert_unicode_age("\u{1FABF}", "GOOSE")
+ assert_unicode_age("\u{1FACE}".."\u{1FACF}",
+ "MOOSE..DONKEY")
+ assert_unicode_age("\u{1FADA}".."\u{1FADB}",
+ "GINGER ROOT..PEA POD")
+ assert_unicode_age("\u{1FAE8}", "SHAKING FACE")
+ assert_unicode_age("\u{1FAF7}".."\u{1FAF8}",
+ "LEFTWARDS PUSHING HAND..RIGHTWARDS PUSHING HAND")
+ assert_unicode_age("\u{2B739}",
+ "CJK UNIFIED IDEOGRAPH-2B739")
+ assert_unicode_age("\u{31350}".."\u{323AF}",
+ "CJK UNIFIED IDEOGRAPH-31350..CJK UNIFIED IDEOGRAPH-323AF")
+ end
+
+ UnicodeAgeRegexps = Hash.new do |h, age|
+ h[age] = [/\A\p{age=#{age}}+\z/u, /\A\P{age=#{age}}+\z/u].freeze
+ end
+
+ def assert_unicode_age(char, mesg = nil, matches: @matches, unmatches: @unmatches)
+ if Range === char
+ char = char.to_a.join("")
+ end
- assert_match(/^\p{age=6.0}$/u, "\u2754")
- assert_no_match(/^\p{age=5.0}$/u, "\u2754")
- assert_no_match(/^\p{age=4.0}$/u, "\u2754")
- assert_no_match(/^\p{age=3.0}$/u, "\u2754")
- assert_no_match(/^\p{age=2.0}$/u, "\u2754")
- assert_no_match(/^\p{age=1.1}$/u, "\u2754")
+ matches.each do |age|
+ pos, neg = UnicodeAgeRegexps[age]
+ assert_match(pos, char, mesg)
+ assert_not_match(neg, char, mesg)
+ end
- assert_no_match(/^\p{age=12.0}$/u, "\u32FF")
- assert_match(/^\p{age=12.1}$/u, "\u32FF")
+ unmatches.each do |age|
+ pos, neg = UnicodeAgeRegexps[age]
+ assert_not_match(pos, char, mesg)
+ assert_match(neg, char, mesg)
+ end
end
MatchData_A = eval("class MatchData_\u{3042} < MatchData; self; end")
@@ -1367,6 +1723,9 @@ class TestRegexp < Test::Unit::TestCase
assert_equal(0, /(?~(a)c)/ =~ "abb")
assert_nil($1)
+
+ assert_equal(0, /(?~(a))/ =~ "")
+ assert_nil($1)
end
def test_backref_overrun
@@ -1375,6 +1734,21 @@ class TestRegexp < Test::Unit::TestCase
end
end
+ def test_bug18631
+ assert_kind_of MatchData, /(?<x>a)(?<x>aa)\k<x>/.match("aaaaa")
+ assert_kind_of MatchData, /(?<x>a)(?<x>aa)\k<x>/.match("aaaa")
+ assert_kind_of MatchData, /(?<x>a)(?<x>aa)\k<x>/.match("aaaab")
+ end
+
+ def test_invalid_group
+ assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
+ begin;
+ assert_raise_with_message(RegexpError, /invalid conditional pattern/) do
+ Regexp.new("((?(1)x|x|)x)+")
+ end
+ end;
+ end
+
# This assertion is for porting x2() tests in testpy.py of Onigmo.
def assert_match_at(re, str, positions, msg = nil)
re = Regexp.new(re) unless re.is_a?(Regexp)
@@ -1404,4 +1778,333 @@ class TestRegexp < Test::Unit::TestCase
}
assert_empty(errs, msg)
end
+
+ def test_s_timeout
+ assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
+ timeout = #{ EnvUtil.apply_timeout_scale(0.2).inspect }
+ begin;
+ Regexp.timeout = timeout
+ assert_in_delta(timeout, Regexp.timeout, timeout * 2 * Float::EPSILON)
+
+ t = Time.now
+ assert_raise_with_message(Regexp::TimeoutError, "regexp match timeout") do
+ # A typical ReDoS case
+ /^(a*)*\1$/ =~ "a" * 1000000 + "x"
+ end
+ t = Time.now - t
+
+ assert_operator(timeout, :<=, [timeout * 1.5, 1].max)
+ end;
+ end
+
+ def test_s_timeout_corner_cases
+ assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
+ begin;
+ assert_nil(Regexp.timeout)
+
+ # This is just an implementation detail that users should not depend on:
+ # If Regexp.timeout is set to a value greater than the value that can be
+ # represented in the internal representation of timeout, it uses the
+ # maximum value that can be represented.
+ Regexp.timeout = Float::INFINITY
+ assert_equal(((1<<64)-1) / 1000000000.0, Regexp.timeout)
+
+ Regexp.timeout = 1e300
+ assert_equal(((1<<64)-1) / 1000000000.0, Regexp.timeout)
+
+ assert_raise(ArgumentError) { Regexp.timeout = 0 }
+ assert_raise(ArgumentError) { Regexp.timeout = -1 }
+
+ Regexp.timeout = nil
+ assert_nil(Regexp.timeout)
+ end;
+ end
+
+ def test_s_timeout_memory_leak
+ assert_no_memory_leak([], "#{<<~"begin;"}", "#{<<~"end;"}", "[Bug #20228]", rss: true)
+ Regexp.timeout = 0.001
+ regex = /^(a*)*$/
+ str = "a" * 1000000 + "x"
+
+ code = proc do
+ regex =~ str
+ rescue
+ end
+
+ 10.times(&code)
+ begin;
+ 1_000.times(&code)
+ end;
+ end
+
+ def test_bug_20453
+ re = Regexp.new("^(a*)x$", timeout: 0.001)
+
+ assert_raise(Regexp::TimeoutError) do
+ re =~ "a" * 1000000 + "x"
+ end
+ end
+
+ def per_instance_redos_test(global_timeout, per_instance_timeout, expected_timeout)
+ assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
+ global_timeout = #{ EnvUtil.apply_timeout_scale(global_timeout).inspect }
+ per_instance_timeout = #{ (per_instance_timeout ? EnvUtil.apply_timeout_scale(per_instance_timeout) : nil).inspect }
+ expected_timeout = #{ EnvUtil.apply_timeout_scale(expected_timeout).inspect }
+ begin;
+ Regexp.timeout = global_timeout
+
+ re = Regexp.new("^(a*)\\1b?a*$", timeout: per_instance_timeout)
+ if per_instance_timeout
+ assert_in_delta(per_instance_timeout, re.timeout, per_instance_timeout * 2 * Float::EPSILON)
+ else
+ assert_nil(re.timeout)
+ end
+
+ t = Time.now
+ assert_raise_with_message(Regexp::TimeoutError, "regexp match timeout") do
+ re =~ "a" * 1000000 + "x"
+ end
+ t = Time.now - t
+
+ assert_in_delta(expected_timeout, t, expected_timeout * 3 / 4)
+ end;
+ end
+
+ def test_timeout_shorter_than_global
+ omit "timeout test is too unstable on s390x" if RUBY_PLATFORM =~ /s390x/
+ per_instance_redos_test(10, 0.5, 0.5)
+ end
+
+ def test_timeout_longer_than_global
+ omit "timeout test is too unstable on s390x" if RUBY_PLATFORM =~ /s390x/
+ per_instance_redos_test(0.01, 0.5, 0.5)
+ end
+
+ def test_timeout_nil
+ per_instance_redos_test(0.5, nil, 0.5)
+ end
+
+ def test_timeout_corner_cases
+ assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
+ begin;
+ assert_nil(//.timeout)
+
+ # This is just an implementation detail that users should not depend on:
+ # If Regexp.timeout is set to a value greater than the value that can be
+ # represented in the internal representation of timeout, it uses the
+ # maximum value that can be represented.
+ assert_equal(((1<<64)-1) / 1000000000.0, Regexp.new("foo", timeout: Float::INFINITY).timeout)
+
+ assert_equal(((1<<64)-1) / 1000000000.0, Regexp.new("foo", timeout: 1e300).timeout)
+
+ assert_raise(ArgumentError) { Regexp.new("foo", timeout: 0) }
+ assert_raise(ArgumentError) { Regexp.new("foo", timeout: -1) }
+ end;
+ end
+
+ def test_timeout_memory_leak
+ assert_no_memory_leak([], "#{<<~"begin;"}", "#{<<~'end;'}", "[Bug #20650]", timeout: 100, rss: true)
+ regex = Regexp.new("^#{"(a*)" * 10_000}x$", timeout: 0.000001)
+ str = "a" * 1_000_000 + "x"
+
+ code = proc do
+ regex =~ str
+ rescue
+ end
+
+ 10.times(&code)
+ begin;
+ 1_000.times(&code)
+ end;
+ end
+
+ def test_match_cache_exponential
+ assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
+ timeout = #{ EnvUtil.apply_timeout_scale(10).inspect }
+ begin;
+ Regexp.timeout = timeout
+ assert_nil(/^(a*)*$/ =~ "a" * 1000000 + "x")
+ end;
+ end
+
+ def test_match_cache_square
+ assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
+ timeout = #{ EnvUtil.apply_timeout_scale(10).inspect }
+ begin;
+ Regexp.timeout = timeout
+ assert_nil(/^a*b?a*$/ =~ "a" * 1000000 + "x")
+ end;
+ end
+
+ def test_match_cache_atomic
+ assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
+ timeout = #{ EnvUtil.apply_timeout_scale(10).inspect }
+ begin;
+ Regexp.timeout = timeout
+ assert_nil(/^a*?(?>a*a*)$/ =~ "a" * 1000000 + "x")
+ end;
+ end
+
+ def test_match_cache_atomic_complex
+ assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
+ timeout = #{ EnvUtil.apply_timeout_scale(10).inspect }
+ begin;
+ Regexp.timeout = timeout
+ assert_nil(/a*(?>a*)ab/ =~ "a" * 1000000 + "b")
+ end;
+ end
+
+ def test_match_cache_positive_look_ahead
+ assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}", timeout: 30)
+ timeout = #{ EnvUtil.apply_timeout_scale(10).inspect }
+ begin;
+ Regexp.timeout = timeout
+ assert_nil(/^a*?(?=a*a*)$/ =~ "a" * 1000000 + "x")
+ end;
+ end
+
+ def test_match_cache_positive_look_ahead_complex
+ assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
+ timeout = #{ EnvUtil.apply_timeout_scale(10).inspect }
+ begin;
+ Regexp.timeout = timeout
+ assert_equal(/(?:(?=a*)a)*/ =~ "a" * 1000000, 0)
+ end;
+ end
+
+ def test_match_cache_negative_look_ahead
+ assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
+ timeout = #{ EnvUtil.apply_timeout_scale(10).inspect }
+ begin;
+ Regexp.timeout = timeout
+ assert_nil(/^a*?(?!a*a*)$/ =~ "a" * 1000000 + "x")
+ end;
+ end
+
+ def test_match_cache_positive_look_behind
+ assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
+ timeout = #{ EnvUtil.apply_timeout_scale(10).inspect }
+ begin;
+ Regexp.timeout = timeout
+ assert_nil(/(?<=abc|def)(a|a)*$/ =~ "abc" + "a" * 1000000 + "x")
+ end;
+ end
+
+ def test_match_cache_negative_look_behind
+ assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
+ timeout = #{ EnvUtil.apply_timeout_scale(10).inspect }
+ begin;
+ Regexp.timeout = timeout
+ assert_nil(/(?<!x)(a|a)*$/ =~ "a" * 1000000 + "x")
+ end;
+ end
+
+ def test_match_cache_with_peek_optimization
+ assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
+ timeout = #{ EnvUtil.apply_timeout_scale(10).inspect }
+ begin;
+ Regexp.timeout = timeout
+ assert_nil(/a+z/ =~ "a" * 1000000 + "xz")
+ end;
+ end
+
+ def test_cache_opcodes_initialize
+ str = 'test1-test2-test3-test4-test_5'
+ re = '^([0-9a-zA-Z\-/]*){1,256}$'
+ 100.times do
+ assert !Regexp.new(re).match?(str)
+ end
+ end
+
+ def test_bug_19273 # [Bug #19273]
+ pattern = /(?:(?:-?b)|(?:-?(?:1_?(?:0_?)*)?0))(?::(?:(?:-?b)|(?:-?(?:1_?(?:0_?)*)?0))){0,3}/
+ assert_equal("10:0:0".match(pattern)[0], "10:0:0")
+ end
+
+ def test_bug_19467 # [Bug #19467]
+ assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
+ timeout = #{ EnvUtil.apply_timeout_scale(10).inspect }
+ begin;
+ Regexp.timeout = timeout
+
+ assert_nil(/\A.*a.*z\z/ =~ "a" * 1000000 + "y")
+ end;
+ end
+
+ def test_bug_19476 # [Bug #19476]
+ assert_equal("123456789".match(/(?:x?\dx?){2,10}/)[0], "123456789")
+ assert_equal("123456789".match(/(?:x?\dx?){2,}/)[0], "123456789")
+ end
+
+ def test_encoding_flags_are_preserved_when_initialized_with_another_regexp
+ re = Regexp.new("\u2018hello\u2019".encode("UTF-8"))
+ str = "".encode("US-ASCII")
+
+ assert_nothing_raised do
+ str.match?(re)
+ str.match?(Regexp.new(re))
+ end
+ end
+
+ def test_bug_19537 # [Bug #19537]
+ str = 'aac'
+ re = '^([ab]{1,3})(a?)*$'
+ 100.times do
+ assert !Regexp.new(re).match?(str)
+ end
+ end
+
+ def test_bug_20083 # [Bug #20083]
+ re = /([\s]*ABC)$/i
+ (1..100).each do |n|
+ text = "#{"0" * n}ABC"
+ assert text.match?(re)
+ end
+ end
+
+ def test_bug_20098 # [Bug #20098]
+ assert(/a((.|.)|bc){,4}z/.match? 'abcbcbcbcz')
+ assert(/a(b+?c*){4,5}z/.match? 'abbbccbbbccbcbcz')
+ assert(/a(b+?(.|.)){2,3}z/.match? 'abbbcbbbcbbbcz')
+ assert(/a(b*?(.|.)[bc]){2,5}z/.match? 'abcbbbcbcccbcz')
+ assert(/^(?:.+){2,4}?b|b/.match? "aaaabaa")
+ end
+
+ def test_bug_20207 # [Bug #20207]
+ assert(!'clan'.match?(/(?=.*a)(?!.*n)/))
+ end
+
+ def test_bug_20212 # [Bug #20212]
+ regex = Regexp.new(
+ /\A((?=.*?[a-z])(?!.*--)[a-z\d]+[a-z\d-]*[a-z\d]+).((?=.*?[a-z])(?!.*--)[a-z\d]+[a-z\d-]*[a-z\d]+).((?=.*?[a-z])(?!.*--)[a-z]+[a-z-]*[a-z]+).((?=.*?[a-z])(?!.*--)[a-z]+[a-z-]*[a-z]+)\Z/x
+ )
+ string = "www.google.com"
+ 100.times.each { assert(regex.match?(string)) }
+ end
+
+ def test_bug_20246 # [Bug #20246]
+ assert_equal '1.2.3', '1.2.3'[/(\d+)(\.\g<1>){2}/]
+ assert_equal '1.2.3', '1.2.3'[/((?:\d|foo|bar)+)(\.\g<1>){2}/]
+ end
+
+ def test_linear_time_p
+ assert_send [Regexp, :linear_time?, /a/]
+ assert_send [Regexp, :linear_time?, 'a']
+ assert_send [Regexp, :linear_time?, 'a', Regexp::IGNORECASE]
+ assert_not_send [Regexp, :linear_time?, /(a)\1/]
+ assert_not_send [Regexp, :linear_time?, "(a)\\1"]
+
+ assert_not_send [Regexp, :linear_time?, /(?=(a))/]
+ assert_not_send [Regexp, :linear_time?, /(?!(a))/]
+
+ assert_raise(TypeError) {Regexp.linear_time?(nil)}
+ assert_raise(TypeError) {Regexp.linear_time?(Regexp.allocate)}
+ end
+
+ def test_linear_performance
+ pre = ->(n) {[Regexp.new("a?" * n + "a" * n), "a" * n]}
+ assert_linear_performance([10, 29], pre: pre) do |re, s|
+ re =~ s
+ end
+ end
end
diff --git a/test/ruby/test_require.rb b/test/ruby/test_require.rb
index 401b274ef6..5aadf779fb 100644
--- a/test/ruby/test_require.rb
+++ b/test/ruby/test_require.rb
@@ -6,11 +6,27 @@ require 'tmpdir'
class TestRequire < Test::Unit::TestCase
def test_load_error_path
- filename = "should_not_exist"
- error = assert_raise(LoadError) do
- require filename
- end
- assert_equal filename, error.path
+ Tempfile.create(["should_not_exist", ".rb"]) {|t|
+ filename = t.path
+ t.close
+ File.unlink(filename)
+
+ error = assert_raise(LoadError) do
+ require filename
+ end
+ assert_equal filename, error.path
+
+ # with --disable=gems
+ assert_separately(["-", filename], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ filename = ARGV[0]
+ path = Struct.new(:to_path).new(filename)
+ error = assert_raise(LoadError) do
+ require path
+ end
+ assert_equal filename, error.path
+ end;
+ }
end
def test_require_invalid_shared_object
@@ -52,7 +68,8 @@ class TestRequire < Test::Unit::TestCase
def test_require_nonascii
bug3758 = '[ruby-core:31915]'
["\u{221e}", "\x82\xa0".force_encoding("cp932")].each do |path|
- assert_raise_with_message(LoadError, /#{path}\z/, bug3758) {require path}
+ e = assert_raise(LoadError, bug3758) {require path}
+ assert_operator(e.message, :end_with?, path, bug3758)
end
end
@@ -93,7 +110,7 @@ class TestRequire < Test::Unit::TestCase
begin
require_path = File.join(tmp, dir, 'foo.rb').encode(encoding)
rescue
- skip "cannot convert path encoding to #{encoding}"
+ omit "cannot convert path encoding to #{encoding}"
end
Dir.mkdir(File.dirname(require_path))
open(require_path, "wb") {|f| f.puts '$:.push __FILE__'}
@@ -175,7 +192,7 @@ class TestRequire < Test::Unit::TestCase
t.close
path = File.expand_path(t.path).sub(/\A(\w):/, '//127.0.0.1/\1$')
- skip "local drive #$1: is not shared" unless File.exist?(path)
+ omit "local drive #$1: is not shared" unless File.exist?(path)
args = ['--disable-gems', "-I#{File.dirname(path)}"]
assert_in_out_err(args, "#{<<~"END;"}", [path], [])
begin
@@ -192,7 +209,7 @@ class TestRequire < Test::Unit::TestCase
File.write(req, "p :ok\n")
assert_file.exist?(req)
req[/.rb$/i] = ""
- assert_in_out_err(['--disable-gems'], <<-INPUT, %w(:ok), [])
+ assert_in_out_err([], <<-INPUT, %w(:ok), [])
require "#{req}"
require "#{req}"
INPUT
@@ -210,6 +227,7 @@ class TestRequire < Test::Unit::TestCase
assert_not_nil(bt = e.backtrace, "no backtrace")
assert_not_empty(bt.find_all {|b| b.start_with? __FILE__}, proc {bt.inspect})
end
+ ensure
$LOADED_FEATURES.replace loaded_features
end
@@ -352,6 +370,26 @@ class TestRequire < Test::Unit::TestCase
end
end
+ def test_public_in_wrapped_load
+ Tempfile.create(["test_public_in_wrapped_load", ".rb"]) do |t|
+ t.puts "def foo; end", "public :foo"
+ t.close
+ assert_warning(/main\.public/) do
+ assert load(t.path, true)
+ end
+ end
+ end
+
+ def test_private_in_wrapped_load
+ Tempfile.create(["test_private_in_wrapped_load", ".rb"]) do |t|
+ t.puts "def foo; end", "private :foo"
+ t.close
+ assert_warning(/main\.private/) do
+ assert load(t.path, true)
+ end
+ end
+ end
+
def test_load_scope
bug1982 = '[ruby-core:25039] [Bug #1982]'
Tempfile.create(["test_ruby_test_require", ".rb"]) {|t|
@@ -367,6 +405,38 @@ class TestRequire < Test::Unit::TestCase
}
end
+ def test_load_into_module
+ Tempfile.create(["test_ruby_test_require", ".rb"]) {|t|
+ t.puts "def b; 1 end"
+ t.puts "class Foo"
+ t.puts " def c; 2 end"
+ t.puts "end"
+ t.close
+
+ m = Module.new
+ load(t.path, m)
+ assert_equal([:b], m.private_instance_methods(false))
+ c = Class.new do
+ include m
+ public :b
+ end
+ assert_equal(1, c.new.b)
+ assert_equal(2, m::Foo.new.c)
+ }
+ end
+
+ def test_load_wrap_nil
+ Dir.mktmpdir do |tmp|
+ File.write("#{tmp}/1.rb", "class LoadWrapNil; end\n")
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ path = ""#{tmp.dump}"/1.rb"
+ begin;
+ load path, nil
+ assert_instance_of(Class, LoadWrapNil)
+ end;
+ end
+ end
+
def test_load_ospath
bug = '[ruby-list:49994] path in ospath'
base = "test_load\u{3042 3044 3046 3048 304a}".encode(Encoding::Windows_31J)
@@ -428,7 +498,33 @@ class TestRequire < Test::Unit::TestCase
result = IO.popen([EnvUtil.rubybin, "b/tst.rb"], &:read)
assert_equal("a/lib.rb\n", result, "[ruby-dev:40040]")
rescue NotImplementedError, Errno::EACCES
- skip "File.symlink is not implemented"
+ omit "File.symlink is not implemented"
+ end
+ }
+ }
+ end
+
+ def test_relative_symlink_realpath
+ Dir.mktmpdir {|tmp|
+ Dir.chdir(tmp) {
+ Dir.mkdir "a"
+ File.open("a/a.rb", "w") {|f| f.puts 'require_relative "b"' }
+ File.open("a/b.rb", "w") {|f| f.puts '$t += 1' }
+ Dir.mkdir "b"
+ File.binwrite("c.rb", <<~RUBY)
+ $t = 0
+ $:.unshift(File.expand_path('../b', __FILE__))
+ require "b"
+ require "a"
+ print $t
+ RUBY
+ begin
+ File.symlink("../a/a.rb", "b/a.rb")
+ File.symlink("../a/b.rb", "b/b.rb")
+ result = IO.popen([EnvUtil.rubybin, "c.rb"], &:read)
+ assert_equal("1", result, "bug17885 [ruby-core:104010]")
+ rescue NotImplementedError, Errno::EACCES
+ omit "File.symlink is not implemented"
end
}
}
@@ -504,9 +600,6 @@ class TestRequire < Test::Unit::TestCase
assert_equal(true, (t1_res ^ t2_res), bug5754 + " t1:#{t1_res} t2:#{t2_res}")
assert_equal([:pre, :post], scratch, bug5754)
-
- assert_match(/circular require/, output)
- assert_match(/in #{__method__}'$/o, output)
}
ensure
$VERBOSE = verbose
@@ -531,6 +624,28 @@ class TestRequire < Test::Unit::TestCase
$".replace(features)
end
+ def test_default_loaded_features_encoding
+ Dir.mktmpdir {|tmp|
+ Dir.mkdir("#{tmp}/1")
+ Dir.mkdir("#{tmp}/2")
+ File.write("#{tmp}/1/bug18191-1.rb", "")
+ File.write("#{tmp}/2/bug18191-2.rb", "")
+ assert_separately(%W[-Eutf-8 -I#{tmp}/1 -], "#{<<~"begin;"}\n#{<<~'end;'}")
+ tmp = #{tmp.dump}"/2"
+ begin;
+ $:.unshift(tmp)
+ require "bug18191-1"
+ require "bug18191-2"
+ encs = [Encoding::US_ASCII, Encoding.find("filesystem")]
+ message = -> {
+ require "pp"
+ {filesystem: encs[1], **$".group_by(&:encoding)}.pretty_inspect
+ }
+ assert($".all? {|n| encs.include?(n.encoding)}, message)
+ end;
+ }
+ end
+
def test_require_changed_current_dir
bug7158 = '[ruby-core:47970]'
Dir.mktmpdir {|tmp|
@@ -602,7 +717,7 @@ class TestRequire < Test::Unit::TestCase
Dir.mktmpdir {|tmp|
Dir.chdir(tmp) {
open("foo.rb", "w") {}
- assert_in_out_err([{"RUBYOPT"=>nil}, '--disable-gems'], "#{<<~"begin;"}\n#{<<~"end;"}", %w(:ok), [], bug7158)
+ assert_in_out_err([{"RUBYOPT"=>nil}], "#{<<~"begin;"}\n#{<<~"end;"}", %w(:ok), [], bug7158)
begin;
$:.replace([IO::NULL])
a = Object.new
@@ -630,7 +745,7 @@ class TestRequire < Test::Unit::TestCase
Dir.mktmpdir {|tmp|
Dir.chdir(tmp) {
open("foo.rb", "w") {}
- assert_in_out_err([{"RUBYOPT"=>nil}, '--disable-gems'], "#{<<~"begin;"}\n#{<<~"end;"}", %w(:ok), [], bug7158)
+ assert_in_out_err([{"RUBYOPT"=>nil}], "#{<<~"begin;"}\n#{<<~"end;"}", %w(:ok), [], bug7158)
begin;
$:.replace([IO::NULL])
a = Object.new
@@ -660,7 +775,7 @@ class TestRequire < Test::Unit::TestCase
open("foo.rb", "w") {}
Dir.mkdir("a")
open(File.join("a", "bar.rb"), "w") {}
- assert_in_out_err(['--disable-gems'], "#{<<~"begin;"}\n#{<<~"end;"}", %w(:ok), [], bug7383)
+ assert_in_out_err([], "#{<<~"begin;"}\n#{<<~"end;"}", %w(:ok), [], bug7383)
begin;
$:.replace([IO::NULL])
$:.#{add} "#{tmp}"
@@ -711,8 +826,8 @@ class TestRequire < Test::Unit::TestCase
assert_in_out_err([{"RUBYOPT" => nil}, "-", script.path], "#{<<~"begin;"}\n#{<<~"end;"}", %w(:ok), [], bug7530, timeout: 60)
begin;
PATH = ARGV.shift
- THREADS = 4
- ITERATIONS_PER_THREAD = 1000
+ THREADS = 30
+ ITERATIONS_PER_THREAD = 300
THREADS.times.map {
Thread.new do
@@ -732,7 +847,7 @@ class TestRequire < Test::Unit::TestCase
f.close
File.unlink(f.path)
File.mkfifo(f.path)
- assert_separately(["-", f.path], "#{<<~"begin;"}\n#{<<~"end;"}", timeout: 3)
+ assert_separately(["-", f.path], "#{<<~"begin;"}\n#{<<~"end;"}", timeout: 10)
begin;
th = Thread.current
Thread.start {begin sleep(0.001) end until th.stop?; th.raise(IOError)}
@@ -744,12 +859,14 @@ class TestRequire < Test::Unit::TestCase
end if File.respond_to?(:mkfifo)
def test_loading_fifo_threading_success
+ omit "[Bug #18613]" if /freebsd/=~ RUBY_PLATFORM
+
Tempfile.create(%w'fifo .rb') {|f|
f.close
File.unlink(f.path)
File.mkfifo(f.path)
- assert_separately(["-", f.path], "#{<<~"begin;"}\n#{<<~"end;"}", timeout: 3)
+ assert_separately(["-", f.path], "#{<<~"begin;"}\n#{<<~"end;"}", timeout: 10)
begin;
path = ARGV[0]
th = Thread.current
@@ -770,7 +887,7 @@ class TestRequire < Test::Unit::TestCase
end if File.respond_to?(:mkfifo)
def test_loading_fifo_fd_leak
- skip if RUBY_PLATFORM =~ /android/ # https://rubyci.org/logs/rubyci.s3.amazonaws.com/android29-x86_64/ruby-master/log/20200419T124100Z.fail.html.gz
+ omit if RUBY_PLATFORM =~ /android/ # https://rubyci.org/logs/rubyci.s3.amazonaws.com/android29-x86_64/ruby-master/log/20200419T124100Z.fail.html.gz
Tempfile.create(%w'fifo .rb') {|f|
f.close
@@ -831,7 +948,7 @@ class TestRequire < Test::Unit::TestCase
begin
File.symlink "real", File.join(tmp, "symlink")
rescue NotImplementedError, Errno::EACCES
- skip "File.symlink is not implemented"
+ omit "File.symlink is not implemented"
end
File.write(File.join(tmp, "real/test_symlink_load_path.rb"), "print __FILE__")
result = IO.popen([EnvUtil.rubybin, "-I#{tmp}/symlink", "-e", "require 'test_symlink_load_path.rb'"], &:read)
@@ -879,4 +996,19 @@ class TestRequire < Test::Unit::TestCase
assert_nil($LOAD_PATH.resolve_feature_path("superkalifragilisticoespialidoso"))
end
end
+
+ def test_require_with_public_method_missing
+ # [Bug #19793]
+ assert_separately(["-W0", "-rtempfile"], __FILE__, __LINE__, <<~RUBY, timeout: 60)
+ GC.stress = true
+
+ class Object
+ public :method_missing
+ end
+
+ Tempfile.create(["empty", ".rb"]) do |file|
+ require file.path
+ end
+ RUBY
+ end
end
diff --git a/test/ruby/test_require_lib.rb b/test/ruby/test_require_lib.rb
index 6b2846c8fd..a88279727e 100644
--- a/test/ruby/test_require_lib.rb
+++ b/test/ruby/test_require_lib.rb
@@ -1,25 +1,26 @@
-# frozen_string_literal: false
+# frozen_string_literal: true
require 'test/unit'
class TestRequireLib < Test::Unit::TestCase
- TEST_RATIO = ENV["TEST_REQUIRE_THREAD_RATIO"]&.tap {|s|break s.to_f} || 0.05 # testing all files needs too long time...
+ libdir = __dir__ + '/../../lib'
- Dir.glob(File.expand_path('../../lib/**/*.rb', __dir__)).each do |lib|
- # skip some problems
- next if %r!/lib/(?:bundler|rubygems)\b! =~ lib
- next if %r!/lib/(?:debug|mkmf)\.rb\z! =~ lib
- next if %r!/lib/irb/ext/tracer\.rb\z! =~ lib
- # skip many files that almost use no threads
- next if TEST_RATIO < rand(0.0..1.0)
+ # .rb files at lib
+ scripts = Dir.glob('*.rb', base: libdir).map {|f| f.chomp('.rb')}
+
+ # .rb files in subdirectories of lib without same name script
+ dirs = Dir.glob('*/', base: libdir).map {|d| d.chomp('/')}
+ dirs -= scripts
+ scripts.concat(Dir.glob(dirs.map {|d| d + '/*.rb'}, base: libdir).map {|f| f.chomp('.rb')})
+
+ # skip some problems
+ scripts -= %w[bundler bundled_gems rubygems mkmf]
+
+ scripts.each do |lib|
define_method "test_thread_size:#{lib}" do
- assert_separately(['--disable-gems', '-W0'], "#{<<~"begin;"}\n#{<<~"end;"}")
+ assert_separately(['-W0'], "#{<<~"begin;"}\n#{<<~"end;"}")
begin;
n = Thread.list.size
- begin
- require #{lib.dump}
- rescue Exception
- skip $!
- end
+ require #{lib.dump}
assert_equal n, Thread.list.size
end;
end
diff --git a/test/ruby/test_rubyoptions.rb b/test/ruby/test_rubyoptions.rb
index e26a24e8ad..f82861b8ce 100644
--- a/test/ruby/test_rubyoptions.rb
+++ b/test/ruby/test_rubyoptions.rb
@@ -5,11 +5,27 @@ require 'timeout'
require 'tmpdir'
require 'tempfile'
require_relative '../lib/jit_support'
+require_relative '../lib/parser_support'
class TestRubyOptions < Test::Unit::TestCase
+ def self.rjit_enabled? = defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled?
+ def self.yjit_enabled? = defined?(RubyVM::YJIT) && RubyVM::YJIT.enabled?
+
+ # Here we're defining our own RUBY_DESCRIPTION without "+PRISM". We do this
+ # here so that the various tests that reference RUBY_DESCRIPTION don't have to
+ # worry about it. The flag itself is tested in its own test.
+ RUBY_DESCRIPTION =
+ if ParserSupport.prism_enabled_in_subprocess?
+ ::RUBY_DESCRIPTION
+ else
+ ::RUBY_DESCRIPTION.sub(/\+PRISM /, '')
+ end
+
NO_JIT_DESCRIPTION =
- if defined?(RubyVM::JIT) && RubyVM::JIT.enabled? # checking -DMJIT_FORCE_ENABLE
- RUBY_DESCRIPTION.sub(/\+JIT /, '')
+ if rjit_enabled?
+ RUBY_DESCRIPTION.sub(/\+RJIT /, '')
+ elsif yjit_enabled?
+ RUBY_DESCRIPTION.sub(/\+YJIT( (dev|dev_nodebug|stats))? /, '')
else
RUBY_DESCRIPTION
end
@@ -36,7 +52,7 @@ class TestRubyOptions < Test::Unit::TestCase
def test_usage
assert_in_out_err(%w(-h)) do |r, e|
assert_operator(r.size, :<=, 25)
- longer = r[1..-1].select {|x| x.size > 80}
+ longer = r[1..-1].select {|x| x.size >= 80}
assert_equal([], longer)
assert_equal([], e)
end
@@ -69,7 +85,7 @@ class TestRubyOptions < Test::Unit::TestCase
def test_backtrace_limit
assert_in_out_err(%w(--backtrace-limit), "", [], /missing argument for --backtrace-limit/)
assert_in_out_err(%w(--backtrace-limit= 1), "", [], /missing argument for --backtrace-limit/)
- assert_in_out_err(%w(--backtrace-limit=-1), "", [], /wrong limit for backtrace length/)
+ assert_in_out_err(%w(--backtrace-limit=-2), "", [], /wrong limit for backtrace length/)
code = 'def f(n);n > 0 ? f(n-1) : raise;end;f(5)'
assert_in_out_err(%w(--backtrace-limit=1), code, [],
[/.*unhandled exception\n/, /^\tfrom .*\n/,
@@ -79,44 +95,71 @@ class TestRubyOptions < Test::Unit::TestCase
/^\t \.{3} \d+ levels\.{3}\n/])
assert_kind_of(Integer, Thread::Backtrace.limit)
assert_in_out_err(%w(--backtrace-limit=1), "p Thread::Backtrace.limit", ['1'], [])
+ assert_in_out_err(%w(--backtrace-limit 1), "p Thread::Backtrace.limit", ['1'], [])
+ env = {"RUBYOPT" => "--backtrace-limit=5"}
+ assert_in_out_err([env], "p Thread::Backtrace.limit", ['5'], [])
+ assert_in_out_err([env, "--backtrace-limit=1"], "p Thread::Backtrace.limit", ['1'], [])
+ assert_in_out_err([env, "--backtrace-limit=-1"], "p Thread::Backtrace.limit", ['-1'], [])
+ assert_in_out_err([env, "--backtrace-limit=3", "--backtrace-limit=1"],
+ "p Thread::Backtrace.limit", ['1'], [])
+ assert_in_out_err([{"RUBYOPT" => "--backtrace-limit=5 --backtrace-limit=3"}],
+ "p Thread::Backtrace.limit", ['3'], [])
+ long_max = RbConfig::LIMITS["LONG_MAX"]
+ assert_in_out_err(%W(--backtrace-limit=#{long_max}), "p Thread::Backtrace.limit",
+ ["#{long_max}"], [])
end
def test_warning
- save_rubyopt = ENV['RUBYOPT']
- ENV['RUBYOPT'] = nil
+ save_rubyopt = ENV.delete('RUBYOPT')
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(2), [])
assert_in_out_err(%w(-W -e) + ['p $-W'], "", %w(2), [])
assert_in_out_err(%w(-We) + ['p $-W'], "", %w(2), [])
assert_in_out_err(%w(-w -W0 -e) + ['p $-W'], "", %w(0), [])
- assert_in_out_err(%w(-W:deprecated -e) + ['p Warning[:deprecated]'], "", %w(true), [])
- assert_in_out_err(%w(-W:no-deprecated -e) + ['p Warning[:deprecated]'], "", %w(false), [])
- assert_in_out_err(%w(-W:experimental -e) + ['p Warning[:experimental]'], "", %w(true), [])
- assert_in_out_err(%w(-W:no-experimental -e) + ['p Warning[:experimental]'], "", %w(false), [])
- assert_in_out_err(%w(-W:qux), "", [], /unknown warning category: `qux'/)
- assert_in_out_err(%w(-w -e) + ['p Warning[:deprecated]'], "", %w(true), [])
- assert_in_out_err(%w(-W -e) + ['p Warning[:deprecated]'], "", %w(true), [])
- assert_in_out_err(%w(-We) + ['p Warning[:deprecated]'], "", %w(true), [])
- assert_in_out_err(%w(-e) + ['p Warning[:deprecated]'], "", %w(false), [])
- code = 'puts "#{$VERBOSE}:#{Warning[:deprecated]}:#{Warning[:experimental]}"'
+
+ categories = {deprecated: 1, experimental: 0, performance: 2}
+ assert_equal categories.keys.sort, Warning.categories.sort
+
+ categories.each do |category, level|
+ assert_in_out_err(["-W:#{category}", "-e", "p Warning[:#{category}]"], "", %w(true), [])
+ assert_in_out_err(["-W:no-#{category}", "-e", "p Warning[:#{category}]"], "", %w(false), [])
+ assert_in_out_err(["-e", "p Warning[:#{category}]"], "", level > 0 ? %w(false) : %w(true), [])
+ assert_in_out_err(["-w", "-e", "p Warning[:#{category}]"], "", level > 1 ? %w(false) : %w(true), [])
+ assert_in_out_err(["-W", "-e", "p Warning[:#{category}]"], "", level > 1 ? %w(false) : %w(true), [])
+ assert_in_out_err(["-We", "p Warning[:#{category}]"], "", level > 1 ? %w(false) : %w(true), [])
+ end
+ assert_in_out_err(%w(-W:qux), "", [], /unknown warning category: 'qux'/)
+
+ def categories.expected(lev = 1, **warnings)
+ [
+ (lev > 1).to_s,
+ *map {|category, level| warnings.fetch(category, lev > level).to_s}
+ ].join(':')
+ end
+ code = ['#{$VERBOSE}', *categories.map {|category, | "\#{Warning[:#{category}]}"}].join(':')
+ code = %[puts "#{code}"]
Tempfile.create(["test_ruby_test_rubyoption", ".rb"]) do |t|
t.puts code
t.close
- assert_in_out_err(["-r#{t.path}", '-e', code], "", %w(false:false:true false:false:true), [])
- assert_in_out_err(["-r#{t.path}", '-w', '-e', code], "", %w(true:true:true true:true:true), [])
- assert_in_out_err(["-r#{t.path}", '-W:deprecated', '-e', code], "", %w(false:true:true false:true:true), [])
- assert_in_out_err(["-r#{t.path}", '-W:no-experimental', '-e', code], "", %w(false:false:false false:false:false), [])
+ assert_in_out_err(["-r#{t.path}", '-e', code], "", [categories.expected(1)]*2, [])
+ assert_in_out_err(["-r#{t.path}", '-w', '-e', code], "", [categories.expected(2)]*2, [])
+ categories.each do |category, |
+ assert_in_out_err(["-r#{t.path}", "-W:#{category}", '-e', code], "", [categories.expected(category => 'true')]*2, [])
+ assert_in_out_err(["-r#{t.path}", "-W:no-#{category}", '-e', code], "", [categories.expected(category => 'false')]*2, [])
+ end
end
ensure
ENV['RUBYOPT'] = save_rubyopt
end
def test_debug
- assert_in_out_err(["--disable-gems", "-de", "p $DEBUG"], "", %w(true), [])
+ assert_in_out_err(["-de", "p $DEBUG"], "", %w(true), [])
- assert_in_out_err(["--disable-gems", "--debug", "-e", "p $DEBUG"],
+ assert_in_out_err(["--debug", "-e", "p $DEBUG"],
"", %w(true), [])
+
+ assert_in_out_err(["--debug-", "-e", "p $DEBUG"], "", %w(), /invalid option --debug-/)
end
q = Regexp.method(:quote)
@@ -126,23 +169,25 @@ class TestRubyOptions < Test::Unit::TestCase
/^jruby #{q[RUBY_ENGINE_VERSION]} \(#{q[RUBY_VERSION]}\).*? \[#{
q[RbConfig::CONFIG["host_os"]]}-#{q[RbConfig::CONFIG["host_cpu"]]}\]$/
else
- /^ruby #{q[RUBY_VERSION]}(?:[p ]|dev|rc).*? \[#{q[RUBY_PLATFORM]}\]$/
+ /^ruby #{q[RUBY_VERSION]}(?:[p ]|dev|rc).*? (\+PRISM )?\[#{q[RUBY_PLATFORM]}\]$/
end
private_constant :VERSION_PATTERN
- VERSION_PATTERN_WITH_JIT =
+ VERSION_PATTERN_WITH_RJIT =
case RUBY_ENGINE
when 'ruby'
- /^ruby #{q[RUBY_VERSION]}(?:[p ]|dev|rc).*? \+JIT \[#{q[RUBY_PLATFORM]}\]$/
+ /^ruby #{q[RUBY_VERSION]}(?:[p ]|dev|rc).*? \+RJIT (\+MN )?(\+PRISM )?\[#{q[RUBY_PLATFORM]}\]$/
else
VERSION_PATTERN
end
- private_constant :VERSION_PATTERN_WITH_JIT
+ private_constant :VERSION_PATTERN_WITH_RJIT
def test_verbose
- assert_in_out_err(["-vve", ""]) do |r, e|
+ assert_in_out_err([{'RUBY_YJIT_ENABLE' => nil}, "-vve", ""]) do |r, e|
assert_match(VERSION_PATTERN, r[0])
- if defined?(RubyVM::JIT) && RubyVM::JIT.enabled? && !mjit_force_enabled? # checking -DMJIT_FORCE_ENABLE
+ if self.class.rjit_enabled? && !JITSupport.rjit_force_enabled?
+ assert_equal(NO_JIT_DESCRIPTION, r[0])
+ elsif self.class.yjit_enabled? && !JITSupport.yjit_force_enabled?
assert_equal(NO_JIT_DESCRIPTION, r[0])
else
assert_equal(RUBY_DESCRIPTION, r[0])
@@ -163,13 +208,18 @@ class TestRubyOptions < Test::Unit::TestCase
end
def test_enable
- if JITSupport.supported?
+ if JITSupport.yjit_supported?
assert_in_out_err(%w(--enable all -e) + [""], "", [], [])
assert_in_out_err(%w(--enable-all -e) + [""], "", [], [])
assert_in_out_err(%w(--enable=all -e) + [""], "", [], [])
+ elsif JITSupport.rjit_supported?
+ # Avoid failing tests by RJIT warnings
+ assert_in_out_err(%w(--enable all --disable rjit -e) + [""], "", [], [])
+ assert_in_out_err(%w(--enable-all --disable-rjit -e) + [""], "", [], [])
+ assert_in_out_err(%w(--enable=all --disable=rjit -e) + [""], "", [], [])
end
assert_in_out_err(%w(--enable foobarbazqux -e) + [""], "", [],
- /unknown argument for --enable: `foobarbazqux'/)
+ /unknown argument for --enable: 'foobarbazqux'/)
assert_in_out_err(%w(--enable), "", [], /missing argument for --enable/)
end
@@ -178,16 +228,16 @@ class TestRubyOptions < Test::Unit::TestCase
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'/)
+ /unknown argument for --disable: 'foobarbazqux'/)
assert_in_out_err(%w(--disable), "", [], /missing argument for --disable/)
- assert_in_out_err(%w(--disable-gems -e) + ['p defined? Gem'], "", ["nil"], [])
+ assert_in_out_err(%w(-e) + ['p defined? Gem'], "", ["nil"], [])
assert_in_out_err(%w(--disable-did_you_mean -e) + ['p defined? DidYouMean'], "", ["nil"], [])
- assert_in_out_err(%w(--disable-gems -e) + ['p defined? DidYouMean'], "", ["nil"], [])
+ assert_in_out_err(%w(-e) + ['p defined? DidYouMean'], "", ["nil"], [])
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))
+ assert_equal("\"\u3042\"", r.join('').force_encoding(Encoding::UTF_8))
end
line = '-eputs"\xc2\xa1".encoding'
env = {'RUBYOPT' => nil}
@@ -203,49 +253,72 @@ class TestRubyOptions < Test::Unit::TestCase
end
def test_version
- assert_in_out_err(%w(--version)) do |r, e|
+ env = { 'RUBY_YJIT_ENABLE' => nil } # unset in children
+ assert_in_out_err([env, '--version']) do |r, e|
assert_match(VERSION_PATTERN, r[0])
- if defined?(RubyVM::JIT) && RubyVM::JIT.enabled? # checking -DMJIT_FORCE_ENABLE
+ if ENV['RUBY_YJIT_ENABLE'] == '1'
+ assert_equal(NO_JIT_DESCRIPTION, r[0])
+ elsif self.class.rjit_enabled? || self.class.yjit_enabled? # checking -D(M|Y)JIT_FORCE_ENABLE
assert_equal(EnvUtil.invoke_ruby(['-e', 'print RUBY_DESCRIPTION'], '', true).first, r[0])
else
assert_equal(RUBY_DESCRIPTION, r[0])
end
assert_equal([], e)
end
+ end
- return if RbConfig::CONFIG["MJIT_SUPPORT"] == 'no'
+ def test_rjit_disabled_version
+ return unless JITSupport.rjit_supported?
+ return if JITSupport.yjit_force_enabled?
+ env = { 'RUBY_YJIT_ENABLE' => nil } # unset in children
[
- %w(--version --jit --disable=jit),
- %w(--version --enable=jit --disable=jit),
- %w(--version --enable-jit --disable-jit),
+ %w(--version --rjit --disable=rjit),
+ %w(--version --enable=rjit --disable=rjit),
+ %w(--version --enable-rjit --disable-rjit),
].each do |args|
- assert_in_out_err(args) do |r, e|
+ assert_in_out_err([env] + args) do |r, e|
assert_match(VERSION_PATTERN, r[0])
assert_match(NO_JIT_DESCRIPTION, r[0])
assert_equal([], e)
end
end
+ end
- if JITSupport.supported?
- [
- %w(--version --jit),
- %w(--version --enable=jit),
- %w(--version --enable-jit),
- ].each do |args|
- assert_in_out_err(args) do |r, e|
- assert_match(VERSION_PATTERN_WITH_JIT, r[0])
- if defined?(RubyVM::JIT) && RubyVM::JIT.enabled? # checking -DMJIT_FORCE_ENABLE
- assert_equal(RUBY_DESCRIPTION, r[0])
- else
- assert_equal(EnvUtil.invoke_ruby(['--jit', '-e', 'print RUBY_DESCRIPTION'], '', true).first, r[0])
- end
- assert_equal([], e)
+ def test_rjit_version
+ return unless JITSupport.rjit_supported?
+ return if JITSupport.yjit_force_enabled?
+
+ env = { 'RUBY_YJIT_ENABLE' => nil } # unset in children
+ [
+ %w(--version --rjit),
+ %w(--version --enable=rjit),
+ %w(--version --enable-rjit),
+ ].each do |args|
+ assert_in_out_err([env] + args) do |r, e|
+ assert_match(VERSION_PATTERN_WITH_RJIT, r[0])
+ if JITSupport.rjit_force_enabled?
+ assert_equal(RUBY_DESCRIPTION, r[0])
+ else
+ assert_equal(EnvUtil.invoke_ruby([env, '--rjit', '-e', 'print RUBY_DESCRIPTION'], '', true).first, r[0])
end
+ assert_equal([], e)
end
end
end
+ def test_parser_flag
+ assert_in_out_err(%w(--parser=prism -e) + ["puts :hi"], "", %w(hi), [])
+ assert_in_out_err(%w(--parser=prism --dump=parsetree -e _=:hi), "", /"hi"/, [])
+
+ assert_in_out_err(%w(--parser=parse.y -e) + ["puts :hi"], "", %w(hi), [])
+ assert_norun_with_rflag('--parser=parse.y', '--version', "")
+
+ assert_in_out_err(%w(--parser=notreal -e) + ["puts :hi"], "", [], /unknown parser notreal/)
+
+ assert_in_out_err(%w(--parser=prism --version), "", /\+PRISM/, [])
+ end
+
def test_eval
assert_in_out_err(%w(-e), "", [], /no code specified for -e \(RuntimeError\)/)
end
@@ -289,12 +362,25 @@ class TestRubyOptions < Test::Unit::TestCase
d = Dir.tmpdir
assert_in_out_err(["-C", d, "-e", "puts Dir.pwd"]) do |r, e|
- assert_file.identical?(r.join, d)
+ assert_file.identical?(r.join(''), d)
assert_equal([], e)
end
+
+ Dir.mktmpdir(d) do |base|
+ # "test" in Japanese and N'Ko
+ test = base + "/\u{30c6 30b9 30c8}_\u{7e1 7ca 7dd 7cc 7df 7cd 7eb}"
+ Dir.mkdir(test)
+ assert_in_out_err(["-C", base, "-C", File.basename(test), "-e", "puts Dir.pwd"]) do |r, e|
+ assert_file.identical?(r.join(''), test)
+ assert_equal([], e)
+ end
+ Dir.rmdir(test)
+ end
end
def test_yydebug
+ omit if ParserSupport.prism_enabled_in_subprocess?
+
assert_in_out_err(["-ye", ""]) do |r, e|
assert_not_equal([], r)
assert_equal([], e)
@@ -312,22 +398,32 @@ class TestRubyOptions < Test::Unit::TestCase
assert_in_out_err(%w(--encoding test_ruby_test_rubyoptions_foobarbazqux), "", [],
/unknown encoding name - test_ruby_test_rubyoptions_foobarbazqux \(RuntimeError\)/)
- if /mswin|mingw|aix|android/ =~ RUBY_PLATFORM &&
- (str = "\u3042".force_encoding(Encoding.find("external"))).valid_encoding?
- # This result depends on locale because LANG=C doesn't affect locale
- # on Windows.
- # On AIX, the source encoding of stdin with LANG=C is ISO-8859-1,
- # which allows \u3042.
- out, err = [str], []
- else
- out, err = [], /invalid multibyte char/
- end
- assert_in_out_err(%w(-Eutf-8), "puts '\u3042'", out, err)
- assert_in_out_err(%w(--encoding utf-8), "puts '\u3042'", out, err)
+ assert_in_out_err(%w(-Eutf-8), 'puts Encoding::default_external', ["UTF-8"])
+ assert_in_out_err(%w(-Ecesu-8), 'puts Encoding::default_external', ["CESU-8"])
+ assert_in_out_err(%w(--encoding utf-8), 'puts Encoding::default_external', ["UTF-8"])
+ assert_in_out_err(%w(--encoding cesu-8), 'puts Encoding::default_external', ["CESU-8"])
end
def test_syntax_check
- assert_in_out_err(%w(-c -e a=1+1 -e !a), "", ["Syntax OK"], [])
+ assert_in_out_err(%w(-cw -e a=1+1 -e !a), "", ["Syntax OK"], [])
+ assert_in_out_err(%w(-cw -e break), "", [], [:*, /(-e:1:|~) Invalid break/, :*])
+ assert_in_out_err(%w(-cw -e next), "", [], [:*, /(-e:1:|~) Invalid next/, :*])
+ assert_in_out_err(%w(-cw -e redo), "", [], [:*, /(-e:1:|~) Invalid redo/, :*])
+ assert_in_out_err(%w(-cw -e retry), "", [], [:*, /(-e:1:|~) Invalid retry/, :*])
+ assert_in_out_err(%w(-cw -e yield), "", [], [:*, /(-e:1:|~) Invalid yield/, :*])
+ assert_in_out_err(%w(-cw -e begin -e break -e end), "", [], [:*, /(-e:2:|~) Invalid break/, :*])
+ assert_in_out_err(%w(-cw -e begin -e next -e end), "", [], [:*, /(-e:2:|~) Invalid next/, :*])
+ assert_in_out_err(%w(-cw -e begin -e redo -e end), "", [], [:*, /(-e:2:|~) Invalid redo/, :*])
+ assert_in_out_err(%w(-cw -e begin -e retry -e end), "", [], [:*, /(-e:2:|~) Invalid retry/, :*])
+ assert_in_out_err(%w(-cw -e begin -e yield -e end), "", [], [:*, /(-e:2:|~) Invalid yield/, :*])
+ assert_in_out_err(%w(-cw -e !defined?(break)), "", ["Syntax OK"], [])
+ assert_in_out_err(%w(-cw -e !defined?(next)), "", ["Syntax OK"], [])
+ assert_in_out_err(%w(-cw -e !defined?(redo)), "", ["Syntax OK"], [])
+ assert_in_out_err(%w(-cw -e !defined?(retry)), "", ["Syntax OK"], [])
+ assert_in_out_err(%w(-cw -e !defined?(yield)), "", ["Syntax OK"], [])
+ assert_in_out_err(%w(-n -cw -e break), "", ["Syntax OK"], [])
+ assert_in_out_err(%w(-n -cw -e next), "", ["Syntax OK"], [])
+ assert_in_out_err(%w(-n -cw -e redo), "", ["Syntax OK"], [])
end
def test_invalid_option
@@ -335,9 +431,9 @@ class TestRubyOptions < Test::Unit::TestCase
assert_in_out_err(%W(-\r -e) + [""], "", [], [])
- assert_in_out_err(%W(-\rx), "", [], /invalid option -\\r \(-h will show valid options\) \(RuntimeError\)/)
+ assert_in_out_err(%W(-\rx), "", [], /invalid option -[\r\n] \(-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(-\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
@@ -374,13 +470,12 @@ class TestRubyOptions < Test::Unit::TestCase
ENV['RUBYOPT'] = '-W:no-experimental'
assert_in_out_err(%w(), "p Warning[:experimental]", ["false"])
ENV['RUBYOPT'] = '-W:qux'
- assert_in_out_err(%w(), "", [], /unknown warning category: `qux'/)
+ assert_in_out_err(%w(), "", [], /unknown warning category: 'qux'/)
+
+ ENV['RUBYOPT'] = 'w'
+ assert_in_out_err(%w(), "p $VERBOSE", ["true"])
ensure
- if rubyopt_orig
- ENV['RUBYOPT'] = rubyopt_orig
- else
- ENV.delete('RUBYOPT')
- end
+ ENV['RUBYOPT'] = rubyopt_orig
end
def test_search
@@ -470,6 +565,16 @@ class TestRubyOptions < Test::Unit::TestCase
/invalid name for global variable - -# \(NameError\)/)
end
+ def test_option_missing_argument
+ assert_in_out_err(%w(-0 --enable), "", [], /missing argument for --enable/)
+ assert_in_out_err(%w(-0 --disable), "", [], /missing argument for --disable/)
+ assert_in_out_err(%w(-0 --dump), "", [], /missing argument for --dump/)
+ assert_in_out_err(%w(-0 --encoding), "", [], /missing argument for --encoding/)
+ assert_in_out_err(%w(-0 --external-encoding), "", [], /missing argument for --external-encoding/)
+ assert_in_out_err(%w(-0 --internal-encoding), "", [], /missing argument for --internal-encoding/)
+ assert_in_out_err(%w(-0 --backtrace-limit), "", [], /missing argument for --backtrace-limit/)
+ end
+
def test_assignment_in_conditional
Tempfile.create(["test_ruby_test_rubyoption", ".rb"]) {|t|
t.puts "if a = 1"
@@ -480,7 +585,7 @@ class TestRubyOptions < Test::Unit::TestCase
t.puts " end"
t.puts "end"
t.flush
- warning = ' warning: found `= literal\' in conditional, should be =='
+ warning = ' warning: found \'= literal\' in conditional, should be =='
err = ["#{t.path}:1:#{warning}",
"#{t.path}:4:#{warning}",
]
@@ -497,16 +602,29 @@ class TestRubyOptions < Test::Unit::TestCase
t.puts "if a = {}; end"
t.puts "if a = {1=>2}; end"
t.puts "if a = {3=>a}; end"
+ t.puts "if a = :sym; end"
t.flush
err = ["#{t.path}:1:#{warning}",
"#{t.path}:2:#{warning}",
"#{t.path}:3:#{warning}",
"#{t.path}:5:#{warning}",
"#{t.path}:6:#{warning}",
+ "#{t.path}:8:#{warning}",
]
feature4299 = '[ruby-dev:43083]'
assert_in_out_err(["-w", t.path], "", [], err, feature4299)
assert_in_out_err(["-wr", t.path, "-e", ""], "", [], err, feature4299)
+
+ t.rewind
+ t.truncate(0)
+ t.puts "if a = __LINE__; end"
+ t.puts "if a = __FILE__; end"
+ t.flush
+ err = ["#{t.path}:1:#{warning}",
+ "#{t.path}:2:#{warning}",
+ ]
+ assert_in_out_err(["-w", t.path], "", [], err)
+ assert_in_out_err(["-wr", t.path, "-e", ""], "", [], err)
}
end
@@ -654,7 +772,7 @@ class TestRubyOptions < Test::Unit::TestCase
end
def test_set_program_name
- skip "platform dependent feature" unless defined?(PSCMD) and PSCMD
+ omit "platform dependent feature" unless defined?(PSCMD) and PSCMD
with_tmpchdir do
write_file("test-script", "$0 = 'hello world'; /test-script/ =~ Process.argv0 or $0 = 'Process.argv0 changed!'; sleep 60")
@@ -677,7 +795,7 @@ class TestRubyOptions < Test::Unit::TestCase
end
def test_setproctitle
- skip "platform dependent feature" unless defined?(PSCMD) and PSCMD
+ omit "platform dependent feature" unless defined?(PSCMD) and PSCMD
assert_separately([], "#{<<-"{#"}\n#{<<-'};'}")
{#
@@ -718,7 +836,7 @@ class TestRubyOptions < Test::Unit::TestCase
-e:(?:1:)?\s\[BUG\]\sSegmentation\sfault.*\n
)x,
%r(
- #{ Regexp.quote(NO_JIT_DESCRIPTION) }\n\n
+ #{ Regexp.quote((TestRubyOptions.rjit_enabled? && !JITSupport.rjit_force_enabled?) ? NO_JIT_DESCRIPTION : RUBY_DESCRIPTION) }\n\n
)x,
%r(
(?:--\s(?:.+\n)*\n)?
@@ -729,17 +847,21 @@ class TestRubyOptions < Test::Unit::TestCase
%r(
(?:
--\sRuby\slevel\sbacktrace\sinformation\s----------------------------------------\n
- (?:-e:1:in\s\`(?:block\sin\s)?<main>\'\n)*
- -e:1:in\s\`kill\'\n
+ (?:-e:1:in\s\'(?:block\sin\s)?<main>\'\n)*
+ -e:1:in\s\'kill\'\n
\n
)?
)x,
%r(
+ (?:--\sThreading(?:.+\n)*\n)?
+ )x,
+ %r(
(?:--\sMachine(?:.+\n)*\n)?
)x,
%r(
(?:
--\sC\slevel\sbacktrace\sinformation\s-------------------------------------------\n
+ (?:Un(?:expected|supported|known)\s.*\n)*
(?:(?:.*\s)?\[0x\h+\].*\n|.*:\d+\n)*\n
)?
)x,
@@ -749,26 +871,38 @@ class TestRubyOptions < Test::Unit::TestCase
)?
)x,
]
+
+ KILL_SELF = "Process.kill :SEGV, $$"
end
- def assert_segv(args, message=nil)
- skip if ENV['RUBY_ON_BUG']
+ def assert_segv(args, message=nil, list: SEGVTest::ExpectedStderrList, **opt, &block)
+ pend "macOS 15 beta is not working with this assertion" if macos?(15)
+
+ # We want YJIT to be enabled in the subprocess if it's enabled for us
+ # so that the Ruby description matches.
+ env = Hash === args.first ? args.shift : {}
+ args.unshift("--yjit") if self.class.yjit_enabled?
+ env.update({'RUBY_ON_BUG' => nil})
+ # ASAN registers a segv handler which prints out "AddressSanitizer: DEADLYSIGNAL" when
+ # catching sigsegv; we don't expect that output, so suppress it.
+ env.update({'ASAN_OPTIONS' => 'handle_segv=0'})
+ args.unshift(env)
test_stdin = ""
- opt = SEGVTest::ExecOptions.dup
- list = SEGVTest::ExpectedStderrList
+ tests = [//, list] unless block
- assert_in_out_err(args, test_stdin, //, list, encoding: "ASCII-8BIT", **opt)
+ assert_in_out_err(args, test_stdin, *tests, encoding: "ASCII-8BIT",
+ **SEGVTest::ExecOptions, **opt, &block)
end
def test_segv_test
- assert_segv(["--disable-gems", "-e", "Process.kill :SEGV, $$"])
+ assert_segv(["--disable-gems", "-e", SEGVTest::KILL_SELF])
end
def test_segv_loaded_features
bug7402 = '[ruby-core:49573]'
- status = assert_segv(['-e', 'END {Process.kill :SEGV, $$}',
+ status = assert_segv(['-e', "END {#{SEGVTest::KILL_SELF}}",
'-e', 'class Bogus; def to_str; exit true; end; end',
'-e', '$".clear',
'-e', '$".unshift Bogus.new',
@@ -782,10 +916,66 @@ class TestRubyOptions < Test::Unit::TestCase
Tempfile.create(["test_ruby_test_bug7597", ".rb"]) {|t|
t.write "f" * 100
t.flush
- assert_segv(["--disable-gems", "-e", "$0=ARGV[0]; Process.kill :SEGV, $$", t.path], bug7597)
+ assert_segv(["--disable-gems", "-e", "$0=ARGV[0]; #{SEGVTest::KILL_SELF}", t.path], bug7597)
}
end
+ def assert_crash_report(path, cmd = nil, &block)
+ pend "macOS 15 beta is not working with this assertion" if macos?(15)
+
+ Dir.mktmpdir("ruby_crash_report") do |dir|
+ list = SEGVTest::ExpectedStderrList
+ if cmd
+ FileUtils.mkpath(File.join(dir, File.dirname(cmd)))
+ File.write(File.join(dir, cmd), SEGVTest::KILL_SELF+"\n")
+ c = Regexp.quote(cmd)
+ list = list.map {|re| Regexp.new(re.source.gsub(/^\s*(\(\?:)?\K-e(?=:)/) {c}, re.options)}
+ else
+ cmd = ['-e', SEGVTest::KILL_SELF]
+ end
+ status = assert_segv([{"RUBY_CRASH_REPORT"=>path}, *cmd], list: [], chdir: dir, &block)
+ next if block
+ reports = Dir.glob("*.log", File::FNM_DOTMATCH, base: dir)
+ assert_equal(1, reports.size)
+ assert_pattern_list(list, File.read(File.join(dir, reports.first)))
+ break status, reports.first
+ end
+ end
+
+ def test_crash_report
+ status, report = assert_crash_report("%e.%f.%p.log")
+ assert_equal("#{File.basename(EnvUtil.rubybin)}.-e.#{status.pid}.log", report)
+ end
+
+ def test_crash_report_script
+ status, report = assert_crash_report("%e.%f.%p.log", "bug.rb")
+ assert_equal("#{File.basename(EnvUtil.rubybin)}.bug.rb.#{status.pid}.log", report)
+ end
+
+ def test_crash_report_executable_path
+ omit if EnvUtil.rubybin.size > 245
+ status, report = assert_crash_report("%E.%p.log")
+ path = EnvUtil.rubybin.sub(/\A\w\K:[\/\\]/, '!').tr_s('/', '!')
+ assert_equal("#{path}.#{status.pid}.log", report)
+ end
+
+ def test_crash_report_script_path
+ status, report = assert_crash_report("%F.%p.log", "test/bug.rb")
+ assert_equal("test!bug.rb.#{status.pid}.log", report)
+ end
+
+ def test_crash_report_pipe
+ if File.executable?(echo = "/bin/echo")
+ elsif /mswin|ming/ =~ RUBY_PLATFORM
+ echo = "echo"
+ else
+ omit "/bin/echo not found"
+ end
+ assert_crash_report("| #{echo} %e:%f:%p") do |stdin, stdout, status|
+ assert_equal(["#{File.basename(EnvUtil.rubybin)}:-e:#{status.pid}"], stdin)
+ end
+ end
+
def test_DATA
Tempfile.create(["test_ruby_test_rubyoption", ".rb"]) {|t|
t.puts "puts DATA.read.inspect"
@@ -837,7 +1027,7 @@ class TestRubyOptions < Test::Unit::TestCase
Process.wait pid
}
rescue RuntimeError
- skip $!
+ omit $!
end
}
assert_equal("", result, '[ruby-dev:37798]')
@@ -887,7 +1077,7 @@ class TestRubyOptions < Test::Unit::TestCase
name = c.chr(Encoding::UTF_8)
expected = name.encode("locale") rescue nil
}
- skip "can't make locale name"
+ omit "can't make locale name"
end
name << ".rb"
expected << ".rb"
@@ -968,18 +1158,17 @@ class TestRubyOptions < Test::Unit::TestCase
assert_in_out_err(['-p', '-e', 'sub(/t.*/){"TEST"}'], %[test], %w[TEST], [], bug7157)
end
- def assert_norun_with_rflag(*opt)
+ def assert_norun_with_rflag(*opt, test_stderr: [])
bug10435 = "[ruby-dev:48712] [Bug #10435]: should not run with #{opt} option"
stderr = []
Tempfile.create(%w"bug10435- .rb") do |script|
dir, base = File.split(script.path)
- script.puts "abort ':run'"
- script.close
+ File.write(script, "abort ':run'\n")
opts = ['-C', dir, '-r', "./#{base}", *opt]
- _, e = assert_in_out_err([*opts, '-ep'], "", //)
+ _, e = assert_in_out_err([*opts, '-ep'], "", //, test_stderr)
stderr.concat(e) if e
stderr << "---"
- _, e = assert_in_out_err([*opts, base], "", //)
+ _, e = assert_in_out_err([*opts, base], "", //, test_stderr)
stderr.concat(e) if e
end
assert_not_include(stderr, ":run", bug10435)
@@ -998,6 +1187,19 @@ class TestRubyOptions < Test::Unit::TestCase
def test_dump_parsetree_with_rflag
assert_norun_with_rflag('--dump=parsetree')
assert_norun_with_rflag('--dump=parsetree', '-e', '#frozen-string-literal: true')
+ assert_norun_with_rflag('--dump=parsetree+error_tolerant')
+ assert_norun_with_rflag('--dump=parse+error_tolerant')
+ end
+
+ def test_dump_parsetree_error_tolerant
+ omit if ParserSupport.prism_enabled_in_subprocess?
+
+ assert_in_out_err(['--dump=parse', '-e', 'begin'],
+ "", [], /unexpected end-of-input/, success: false)
+ assert_in_out_err(['--dump=parse', '--dump=+error_tolerant', '-e', 'begin'],
+ "", /^# @/, /unexpected end-of-input/, success: true)
+ assert_in_out_err(['--dump=+error_tolerant', '-e', 'begin p :run'],
+ "", [], /unexpected end-of-input/, success: false)
end
def test_dump_insns_with_rflag
@@ -1033,8 +1235,8 @@ class TestRubyOptions < Test::Unit::TestCase
frozen = [
["--enable-frozen-string-literal", true],
["--disable-frozen-string-literal", false],
- [nil, false],
]
+
debugs = [
["--debug-frozen-string-literal", true],
["--debug=frozen-string-literal", true],
@@ -1056,6 +1258,17 @@ class TestRubyOptions < Test::Unit::TestCase
end
end
+ def test_frozen_string_literal_debug_chilled_strings
+ code = <<~RUBY
+ "foo" << "bar"
+ RUBY
+ warning = ["-:1: warning: literal string will be frozen in the future"]
+ assert_in_out_err(["-W:deprecated"], code, [], warning)
+ assert_in_out_err(["-W:deprecated", "--debug-frozen-string-literal"], code, [], warning)
+ assert_in_out_err(["-W:deprecated", "--disable-frozen-string-literal", "--debug-frozen-string-literal"], code, [], [])
+ assert_in_out_err(["-W:deprecated", "--enable-frozen-string-literal", "--debug-frozen-string-literal"], code, [], ["-:1:in '<main>': can't modify frozen String: \"foo\", created at -:1 (FrozenError)"])
+ end
+
def test___dir__encoding
lang = {"LC_ALL"=>ENV["LC_ALL"]||ENV["LANG"]}
with_tmpchdir do
@@ -1095,21 +1308,13 @@ class TestRubyOptions < Test::Unit::TestCase
end
def test_null_script
- skip "#{IO::NULL} is not a character device" unless File.chardev?(IO::NULL)
+ omit "#{IO::NULL} is not a character device" unless File.chardev?(IO::NULL)
assert_in_out_err([IO::NULL], success: true)
end
- def test_jit_debug
- # mswin uses prebuilt precompiled header. Thus it does not show a pch compilation log to check "-O0 -O1".
- if JITSupport.supported? && !RUBY_PLATFORM.match?(/mswin/)
- env = { 'MJIT_SEARCH_BUILD_DIR' => 'true' }
- assert_in_out_err([env, "--jit-debug=-O0 -O1", "--jit-verbose=2", "" ], "", [], /-O0 -O1/)
- end
- end
-
- private
-
- def mjit_force_enabled?
- "#{RbConfig::CONFIG['CFLAGS']} #{RbConfig::CONFIG['CPPFLAGS']}".match?(/(\A|\s)-D ?MJIT_FORCE_ENABLE\b/)
+ def test_free_at_exit_env_var
+ env = {"RUBY_FREE_AT_EXIT"=>"1"}
+ assert_ruby_status([env, "-e;"])
+ assert_in_out_err([env, "-W"], "", [], /Free at exit is experimental and may be unstable/)
end
end
diff --git a/test/ruby/test_rubyvm.rb b/test/ruby/test_rubyvm.rb
index 67d46e27ad..225cb45f33 100644
--- a/test/ruby/test_rubyvm.rb
+++ b/test/ruby/test_rubyvm.rb
@@ -1,18 +1,73 @@
# frozen_string_literal: false
require 'test/unit'
+require_relative '../lib/parser_support'
class TestRubyVM < Test::Unit::TestCase
def test_stat
assert_kind_of Hash, RubyVM.stat
- assert_kind_of Integer, RubyVM.stat[:global_constant_state]
RubyVM.stat(stat = {})
assert_not_empty stat
- assert_equal stat[:global_constant_state], RubyVM.stat(:global_constant_state)
end
def test_stat_unknown
assert_raise(ArgumentError){ RubyVM.stat(:unknown) }
assert_raise_with_message(ArgumentError, /\u{30eb 30d3 30fc}/) {RubyVM.stat(:"\u{30eb 30d3 30fc}")}
end
+
+ def parse_and_compile
+ script = <<~RUBY
+ _a = 1
+ def foo
+ _b = 2
+ end
+ 1.times{
+ _c = 3
+ }
+ RUBY
+
+ ast = RubyVM::AbstractSyntaxTree.parse(script)
+ iseq = RubyVM::InstructionSequence.compile(script)
+
+ [ast, iseq]
+ end
+
+ def test_keep_script_lines
+ omit if ParserSupport.prism_enabled?
+ pend if ENV['RUBY_ISEQ_DUMP_DEBUG'] # TODO
+
+ prev_conf = RubyVM.keep_script_lines
+
+ # keep
+ RubyVM.keep_script_lines = true
+
+ ast, iseq = *parse_and_compile
+
+ lines = ast.script_lines
+ assert_equal Array, lines.class
+
+ lines = iseq.script_lines
+ assert_equal Array, lines.class
+ iseq.each_child{|child|
+ assert_equal lines, child.script_lines
+ }
+ assert lines.frozen?
+
+ # don't keep
+ RubyVM.keep_script_lines = false
+
+ ast, iseq = *parse_and_compile
+
+ lines = ast.script_lines
+ assert_equal nil, lines
+
+ lines = iseq.script_lines
+ assert_equal nil, lines
+ iseq.each_child{|child|
+ assert_equal lines, child.script_lines
+ }
+
+ ensure
+ RubyVM.keep_script_lines = prev_conf
+ end
end
diff --git a/test/ruby/test_rubyvm_jit.rb b/test/ruby/test_rubyvm_jit.rb
deleted file mode 100644
index 2104ce3d18..0000000000
--- a/test/ruby/test_rubyvm_jit.rb
+++ /dev/null
@@ -1,91 +0,0 @@
-# frozen_string_literal: true
-require 'test/unit'
-require_relative '../lib/jit_support'
-
-return if RbConfig::CONFIG["MJIT_SUPPORT"] == 'no'
-
-class TestRubyVMJIT < Test::Unit::TestCase
- include JITSupport
-
- def setup
- unless JITSupport.supported?
- skip 'JIT seems not supported on this platform'
- end
- end
-
- def test_pause
- out, err = eval_with_jit(<<~'EOS', verbose: 1, min_calls: 1, wait: false)
- i = 0
- while i < 5
- eval("def mjit#{i}; end; mjit#{i}")
- i += 1
- end
- print RubyVM::JIT.pause
- print RubyVM::JIT.pause
- while i < 10
- eval("def mjit#{i}; end; mjit#{i}")
- i += 1
- end
- print RubyVM::JIT.pause # no JIT here
- EOS
- assert_equal('truefalsefalse', out)
- assert_equal(
- 5, err.scan(/#{JITSupport::JIT_SUCCESS_PREFIX}/).size,
- "unexpected stdout:\n```\n#{out}```\n\nstderr:\n```\n#{err}```",
- )
- end
-
- def test_pause_waits_until_compaction
- out, err = eval_with_jit(<<~'EOS', verbose: 1, min_calls: 1, wait: false)
- def a() end; a
- def b() end; b
- RubyVM::JIT.pause
- EOS
- assert_equal(
- 2, err.scan(/#{JITSupport::JIT_SUCCESS_PREFIX}/).size,
- "unexpected stdout:\n```\n#{out}```\n\nstderr:\n```\n#{err}```",
- )
- assert_equal(
- 1, err.scan(/#{JITSupport::JIT_COMPACTION_PREFIX}/).size,
- "unexpected stdout:\n```\n#{out}```\n\nstderr:\n```\n#{err}```",
- ) unless RUBY_PLATFORM.match?(/mswin|mingw/) # compaction is not supported on Windows yet
- end
-
- def test_pause_does_not_hang_on_full_units
- out, _ = eval_with_jit(<<~'EOS', verbose: 1, min_calls: 1, max_cache: 10, wait: false)
- i = 0
- while i < 11
- eval("def mjit#{i}; end; mjit#{i}")
- i += 1
- end
- print RubyVM::JIT.pause
- EOS
- assert_equal('true', out)
- end
-
- def test_pause_wait_false
- out, err = eval_with_jit(<<~'EOS', verbose: 1, min_calls: 1, wait: false)
- i = 0
- while i < 10
- eval("def mjit#{i}; end; mjit#{i}")
- i += 1
- end
- print RubyVM::JIT.pause(wait: false)
- print RubyVM::JIT.pause(wait: false)
- EOS
- assert_equal('truefalse', out)
- assert_equal(true, err.scan(/#{JITSupport::JIT_SUCCESS_PREFIX}/).size < 10)
- end
-
- def test_resume
- out, err = eval_with_jit(<<~'EOS', verbose: 1, min_calls: 1, wait: false)
- print RubyVM::JIT.resume
- print RubyVM::JIT.pause
- print RubyVM::JIT.resume
- print RubyVM::JIT.resume
- print RubyVM::JIT.pause
- EOS
- assert_equal('falsetruetruefalsetrue', out)
- assert_equal(0, err.scan(/#{JITSupport::JIT_SUCCESS_PREFIX}/).size)
- end
-end
diff --git a/test/ruby/test_settracefunc.rb b/test/ruby/test_settracefunc.rb
index 88488aef5c..868015947e 100644
--- a/test/ruby/test_settracefunc.rb
+++ b/test/ruby/test_settracefunc.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: false
require 'test/unit'
+EnvUtil.suppress_warning {require 'continuation'}
class TestSetTraceFunc < Test::Unit::TestCase
def setup
@@ -50,6 +51,49 @@ class TestSetTraceFunc < Test::Unit::TestCase
assert_equal([], events)
end
+ def test_c_return_no_binding
+ binding = :none
+ TracePoint.new(:c_return){|tp|
+ binding = tp.binding
+ }.enable{
+ 1.object_id
+ }
+ assert_nil(binding)
+ end
+
+ def test_c_call_no_binding
+ binding = :none
+ TracePoint.new(:c_call){|tp|
+ binding = tp.binding
+ }.enable{
+ 1.object_id
+ }
+ assert_nil(binding)
+ end
+
+ def test_c_call_removed_method
+ # [Bug #19305]
+ klass = Class.new do
+ attr_writer :bar
+ alias_method :set_bar, :bar=
+ remove_method :bar=
+ end
+
+ obj = klass.new
+ method_id = nil
+ parameters = nil
+
+ TracePoint.new(:c_call) { |tp|
+ method_id = tp.method_id
+ parameters = tp.parameters
+ }.enable {
+ obj.set_bar(1)
+ }
+
+ assert_equal(:bar=, method_id)
+ assert_equal([[:req]], parameters)
+ end
+
def test_call
events = []
name = "#{self.class}\##{__method__}"
@@ -108,6 +152,10 @@ class TestSetTraceFunc < Test::Unit::TestCase
events.shift)
assert_equal(["line", 4, __method__, self.class],
events.shift)
+ assert_equal(["c-call", 4, :const_added, Module],
+ events.shift)
+ assert_equal(["c-return", 4, :const_added, Module],
+ events.shift)
assert_equal(["c-call", 4, :inherited, Class],
events.shift)
assert_equal(["c-return", 4, :inherited, Class],
@@ -184,7 +232,9 @@ class TestSetTraceFunc < Test::Unit::TestCase
events.shift)
assert_equal(["line", 5, :meth_return, self.class],
events.shift)
- assert_equal(["return", 7, :meth_return, self.class],
+ assert_equal(["line", 6, :meth_return, self.class],
+ events.shift)
+ assert_equal(["return", 6, :meth_return, self.class],
events.shift)
assert_equal(["line", 10, :test_return, self.class],
events.shift)
@@ -223,7 +273,7 @@ class TestSetTraceFunc < Test::Unit::TestCase
events.shift)
assert_equal(["line", 6, :meth_return2, self.class],
events.shift)
- assert_equal(["return", 7, :meth_return2, self.class],
+ assert_equal(["return", 6, :meth_return2, self.class],
events.shift)
assert_equal(["line", 9, :test_return2, self.class],
events.shift)
@@ -311,18 +361,18 @@ class TestSetTraceFunc < Test::Unit::TestCase
def test_thread_trace
events = {:set => [], :add => []}
+ name = "#{self.class}\##{__method__}"
prc = Proc.new { |event, file, lineno, mid, binding, klass|
- events[:set] << [event, lineno, mid, klass, :set]
+ events[:set] << [event, lineno, mid, klass, :set] if file == name
}
prc = prc # suppress warning
prc2 = Proc.new { |event, file, lineno, mid, binding, klass|
- events[:add] << [event, lineno, mid, klass, :add]
+ events[:add] << [event, lineno, mid, klass, :add] if file == name
}
prc2 = prc2 # suppress warning
th = Thread.new do
th = Thread.current
- name = "#{self.class}\##{__method__}"
eval <<-EOF.gsub(/^.*?: /, ""), nil, name
1: th.set_trace_func(prc)
2: th.add_trace_func(prc2)
@@ -345,6 +395,8 @@ class TestSetTraceFunc < Test::Unit::TestCase
[["c-return", 2, :add_trace_func, Thread],
["line", 3, __method__, self.class],
+ ["c-call", 3, :const_added, Module],
+ ["c-return", 3, :const_added, Module],
["c-call", 3, :inherited, Class],
["c-return", 3, :inherited, Class],
["class", 3, nil, nil],
@@ -393,7 +445,7 @@ class TestSetTraceFunc < Test::Unit::TestCase
[["c-return", 3, :set_trace_func, Kernel],
["line", 6, __method__, self.class],
["call", 1, :foobar, FooBar],
- ["return", 6, :foobar, FooBar],
+ ["return", 1, :foobar, FooBar],
["line", 7, __method__, self.class],
["c-call", 7, :set_trace_func, Kernel]].each{|e|
assert_equal(e, events.shift)
@@ -404,6 +456,9 @@ class TestSetTraceFunc < Test::Unit::TestCase
bug3921 = '[ruby-dev:42350]'
ok = false
func = lambda{|e, f, l, i, b, k|
+ # In parallel testing, unexpected events like IO operations may be traced,
+ # so we filter out events here.
+ next unless f == __FILE__
set_trace_func(nil)
ok = eval("self", b)
}
@@ -453,9 +508,9 @@ class TestSetTraceFunc < Test::Unit::TestCase
begin
eval <<-EOF.gsub(/^.*?: /, ""), nil, 'xyzzy'
1: trace = TracePoint.trace(*trace_events){|tp| next if !target_thread?
- 2: events << [tp.event, tp.lineno, tp.path, _defined_class.(tp), tp.method_id, tp.self, tp.binding.eval("_local_var"), _get_data.(tp)] if tp.path == 'xyzzy'
+ 2: events << [tp.event, tp.lineno, tp.path, _defined_class.(tp), tp.method_id, tp.self, tp.binding&.eval("_local_var"), _get_data.(tp)] if tp.path == 'xyzzy'
3: }
- 4: 1.times{|;_local_var| _local_var = :inner
+ 4: [1].reverse_each{|;_local_var| _local_var = :inner
5: tap{}
6: }
7: class XYZZY
@@ -482,27 +537,29 @@ class TestSetTraceFunc < Test::Unit::TestCase
answer_events = [
#
[:line, 4, 'xyzzy', self.class, method, self, :outer, :nothing],
- [:c_call, 4, 'xyzzy', Integer, :times, 1, :outer, :nothing],
+ [:c_call, 4, 'xyzzy', Array, :reverse_each, [1], nil, :nothing],
[:line, 4, 'xyzzy', self.class, method, self, nil, :nothing],
[:line, 5, 'xyzzy', self.class, method, self, :inner, :nothing],
- [:c_return, 4, "xyzzy", Integer, :times, 1, :outer, 1],
+ [:c_return, 4, "xyzzy", Array, :reverse_each, [1], nil, [1]],
[:line, 7, 'xyzzy', self.class, method, self, :outer, :nothing],
- [:c_call, 7, "xyzzy", Class, :inherited, Object, :outer, :nothing],
- [:c_return, 7, "xyzzy", Class, :inherited, Object, :outer, nil],
+ [:c_call, 7, "xyzzy", Module, :const_added, TestSetTraceFunc, nil, :nothing],
+ [:c_return, 7, "xyzzy", Module, :const_added, TestSetTraceFunc, nil, nil],
+ [:c_call, 7, "xyzzy", Class, :inherited, Object, nil, :nothing],
+ [:c_return, 7, "xyzzy", Class, :inherited, Object, nil, nil],
[:class, 7, "xyzzy", nil, nil, xyzzy.class, nil, :nothing],
[:line, 8, "xyzzy", nil, nil, xyzzy.class, nil, :nothing],
[:line, 9, "xyzzy", nil, nil, xyzzy.class, :XYZZY_outer, :nothing],
- [:c_call, 9, "xyzzy", Module, :method_added, xyzzy.class, :XYZZY_outer, :nothing],
- [:c_return, 9, "xyzzy", Module, :method_added, xyzzy.class, :XYZZY_outer, nil],
+ [:c_call, 9, "xyzzy", Module, :method_added, xyzzy.class, nil, :nothing],
+ [:c_return, 9, "xyzzy", Module, :method_added, xyzzy.class, nil, nil],
[:line, 13, "xyzzy", nil, nil, xyzzy.class, :XYZZY_outer, :nothing],
- [:c_call, 13, "xyzzy", Module, :method_added, xyzzy.class, :XYZZY_outer, :nothing],
- [:c_return,13, "xyzzy", Module, :method_added, xyzzy.class, :XYZZY_outer, nil],
+ [:c_call, 13, "xyzzy", Module, :method_added, xyzzy.class, nil, :nothing],
+ [:c_return,13, "xyzzy", Module, :method_added, xyzzy.class, nil, nil],
[:end, 17, "xyzzy", nil, nil, xyzzy.class, :XYZZY_outer, :nothing],
[:line, 18, "xyzzy", TestSetTraceFunc, method, self, :outer, :nothing],
- [:c_call, 18, "xyzzy", Class, :new, xyzzy.class, :outer, :nothing],
- [:c_call, 18, "xyzzy", BasicObject, :initialize, xyzzy, :outer, :nothing],
- [:c_return,18, "xyzzy", BasicObject, :initialize, xyzzy, :outer, nil],
- [:c_return,18, "xyzzy", Class, :new, xyzzy.class, :outer, xyzzy],
+ [:c_call, 18, "xyzzy", Class, :new, xyzzy.class, nil, :nothing],
+ [:c_call, 18, "xyzzy", BasicObject, :initialize, xyzzy, nil, :nothing],
+ [:c_return,18, "xyzzy", BasicObject, :initialize, xyzzy, nil, nil],
+ [:c_return,18, "xyzzy", Class, :new, xyzzy.class, nil, xyzzy],
[:line, 19, "xyzzy", TestSetTraceFunc, method, self, :outer, :nothing],
[:call, 9, "xyzzy", xyzzy.class, :foo, xyzzy, nil, :nothing],
[:line, 10, "xyzzy", xyzzy.class, :foo, xyzzy, nil, :nothing],
@@ -513,17 +570,17 @@ class TestSetTraceFunc < Test::Unit::TestCase
[:return, 16, "xyzzy", xyzzy.class, :bar, xyzzy, :XYZZY_bar, xyzzy],
[:return, 12, "xyzzy", xyzzy.class, :foo, xyzzy, :XYZZY_foo, xyzzy],
[:line, 20, "xyzzy", TestSetTraceFunc, method, self, :outer, :nothing],
- [:c_call, 20, "xyzzy", Kernel, :raise, self, :outer, :nothing],
- [:c_call, 20, "xyzzy", Exception, :exception, RuntimeError, :outer, :nothing],
- [:c_call, 20, "xyzzy", Exception, :initialize, raised_exc, :outer, :nothing],
- [:c_return,20, "xyzzy", Exception, :initialize, raised_exc, :outer, raised_exc],
- [:c_return,20, "xyzzy", Exception, :exception, RuntimeError, :outer, raised_exc],
- [:c_return,20, "xyzzy", Kernel, :raise, self, :outer, nil],
- [:c_call, 20, "xyzzy", Exception, :backtrace, raised_exc, :outer, :nothing],
- [:c_return,20, "xyzzy", Exception, :backtrace, raised_exc, :outer, nil],
+ [:c_call, 20, "xyzzy", Kernel, :raise, self, nil, :nothing],
+ [:c_call, 20, "xyzzy", Exception, :exception, RuntimeError, nil, :nothing],
+ [:c_call, 20, "xyzzy", Exception, :initialize, raised_exc, nil, :nothing],
+ [:c_return,20, "xyzzy", Exception, :initialize, raised_exc, nil, raised_exc],
+ [:c_return,20, "xyzzy", Exception, :exception, RuntimeError, nil, raised_exc],
+ [:c_return,20, "xyzzy", Kernel, :raise, self, nil, nil],
+ [:c_call, 20, "xyzzy", Exception, :backtrace, raised_exc, nil, :nothing],
+ [:c_return,20, "xyzzy", Exception, :backtrace, raised_exc, nil, nil],
[:raise, 20, "xyzzy", TestSetTraceFunc, :trace_by_tracepoint, self, :outer, raised_exc],
- [:c_call, 20, "xyzzy", Module, :===, RuntimeError,:outer, :nothing],
- [:c_return,20, "xyzzy", Module, :===, RuntimeError,:outer, true],
+ [:c_call, 20, "xyzzy", Module, :===, RuntimeError, nil, :nothing],
+ [:c_return,20, "xyzzy", Module, :===, RuntimeError, nil, true],
[:line, 21, "xyzzy", TestSetTraceFunc, method, self, :outer, :nothing],
]
@@ -564,6 +621,29 @@ class TestSetTraceFunc < Test::Unit::TestCase
}
end
+ # Bug #18264
+ def test_tracepoint_memory_leak
+ assert_no_memory_leak([], <<-PREP, <<-CODE, rss: true)
+code = proc { TracePoint.new(:line) { } }
+1_000.times(&code)
+PREP
+1_000_000.times(&code)
+CODE
+ end
+
+ def test_tracepoint_bmethod_memory_leak
+ assert_no_memory_leak([], '', "#{<<~"begin;"}\n#{<<~'end;'}", "[Bug #20194]", rss: true)
+ obj = Object.new
+ obj.define_singleton_method(:foo) {}
+ bmethod = obj.method(:foo)
+ tp = TracePoint.new(:return) {}
+ begin;
+ 1_000_000.times do
+ tp.enable(target: bmethod) {}
+ end
+ end;
+ end
+
def trace_by_set_trace_func
events = []
trace = nil
@@ -576,9 +656,9 @@ class TestSetTraceFunc < Test::Unit::TestCase
eval <<-EOF.gsub(/^.*?: /, ""), nil, 'xyzzy'
1: set_trace_func(lambda{|event, file, line, id, binding, klass|
- 2: events << [event, line, file, klass, id, binding.eval('self'), binding.eval("_local_var")] if file == 'xyzzy'
+ 2: events << [event, line, file, klass, id, binding&.eval('self'), binding&.eval("_local_var")] if file == 'xyzzy'
3: })
- 4: 1.times{|;_local_var| _local_var = :inner
+ 4: [1].map{|;_local_var| _local_var = :inner
5: tap{}
6: }
7: class XYZZY
@@ -601,29 +681,31 @@ class TestSetTraceFunc < Test::Unit::TestCase
answer_events = [
#
- [:c_return, 1, "xyzzy", TracePoint, :trace, TracePoint, :outer, trace],
+ [:c_return, 1, "xyzzy", TracePoint, :trace, TracePoint, nil, nil],
[:line, 4, 'xyzzy', self.class, method, self, :outer, :nothing],
- [:c_call, 4, 'xyzzy', Integer, :times, 1, :outer, :nothing],
+ [:c_call, 4, 'xyzzy', Integer, :times, 1, nil, nil],
[:line, 4, 'xyzzy', self.class, method, self, nil, :nothing],
[:line, 5, 'xyzzy', self.class, method, self, :inner, :nothing],
- [:c_return, 4, "xyzzy", Integer, :times, 1, :outer, 1],
+ [:c_return, 4, "xyzzy", Integer, :times, 1, nil, nil],
[:line, 7, 'xyzzy', self.class, method, self, :outer, :nothing],
- [:c_call, 7, "xyzzy", Class, :inherited, Object, :outer, :nothing],
- [:c_return, 7, "xyzzy", Class, :inherited, Object, :outer, nil],
+ [:c_call, 7, "xyzzy", Class, :inherited, Object, nil, nil],
+ [:c_return, 7, "xyzzy", Class, :inherited, Object, nil, nil],
+ [:c_call, 7, "xyzzy", Class, :const_added, Object, nil, nil],
+ [:c_return, 7, "xyzzy", Class, :const_added, Object, nil, nil],
[:class, 7, "xyzzy", nil, nil, xyzzy.class, nil, :nothing],
[:line, 8, "xyzzy", nil, nil, xyzzy.class, nil, :nothing],
[:line, 9, "xyzzy", nil, nil, xyzzy.class, :XYZZY_outer, :nothing],
- [:c_call, 9, "xyzzy", Module, :method_added, xyzzy.class, :XYZZY_outer, :nothing],
- [:c_return, 9, "xyzzy", Module, :method_added, xyzzy.class, :XYZZY_outer, nil],
+ [:c_call, 9, "xyzzy", Module, :method_added, xyzzy.class, nil, nil],
+ [:c_return, 9, "xyzzy", Module, :method_added, xyzzy.class, nil, nil],
[:line, 13, "xyzzy", nil, nil, xyzzy.class, :XYZZY_outer, :nothing],
- [:c_call, 13, "xyzzy", Module, :method_added, xyzzy.class, :XYZZY_outer, :nothing],
- [:c_return,13, "xyzzy", Module, :method_added, xyzzy.class, :XYZZY_outer, nil],
+ [:c_call, 13, "xyzzy", Module, :method_added, xyzzy.class, nil, nil],
+ [:c_return,13, "xyzzy", Module, :method_added, xyzzy.class, nil, nil],
[:end, 17, "xyzzy", nil, nil, xyzzy.class, :XYZZY_outer, :nothing],
[:line, 18, "xyzzy", TestSetTraceFunc, method, self, :outer, :nothing],
- [:c_call, 18, "xyzzy", Class, :new, xyzzy.class, :outer, :nothing],
- [:c_call, 18, "xyzzy", BasicObject, :initialize, xyzzy, :outer, :nothing],
- [:c_return,18, "xyzzy", BasicObject, :initialize, xyzzy, :outer, nil],
- [:c_return,18, "xyzzy", Class, :new, xyzzy.class, :outer, xyzzy],
+ [:c_call, 18, "xyzzy", Class, :new, xyzzy.class, nil, nil],
+ [:c_call, 18, "xyzzy", BasicObject, :initialize, xyzzy, nil, nil],
+ [:c_return,18, "xyzzy", BasicObject, :initialize, xyzzy, nil, nil],
+ [:c_return,18, "xyzzy", Class, :new, xyzzy.class, nil, nil],
[:line, 19, "xyzzy", TestSetTraceFunc, method, self, :outer, :nothing],
[:call, 9, "xyzzy", xyzzy.class, :foo, xyzzy, nil, :nothing],
[:line, 10, "xyzzy", xyzzy.class, :foo, xyzzy, nil, :nothing],
@@ -634,23 +716,29 @@ class TestSetTraceFunc < Test::Unit::TestCase
[:return, 16, "xyzzy", xyzzy.class, :bar, xyzzy, :XYZZY_bar, xyzzy],
[:return, 12, "xyzzy", xyzzy.class, :foo, xyzzy, :XYZZY_foo, xyzzy],
[:line, 20, "xyzzy", TestSetTraceFunc, method, self, :outer, :nothing],
- [:c_call, 20, "xyzzy", Kernel, :raise, self, :outer, :nothing],
- [:c_call, 20, "xyzzy", Exception, :exception, RuntimeError, :outer, :nothing],
- [:c_call, 20, "xyzzy", Exception, :initialize, raised_exc, :outer, :nothing],
- [:c_return,20, "xyzzy", Exception, :initialize, raised_exc, :outer, raised_exc],
- [:c_return,20, "xyzzy", Exception, :exception, RuntimeError, :outer, raised_exc],
- [:c_return,20, "xyzzy", Kernel, :raise, self, :outer, nil],
- [:c_call, 20, "xyzzy", Exception, :backtrace, raised_exc, :outer, :nothing],
- [:c_return,20, "xyzzy", Exception, :backtrace, raised_exc, :outer, nil],
+ [:c_call, 20, "xyzzy", Kernel, :raise, self, nil, nil],
+ [:c_call, 20, "xyzzy", Exception, :exception, RuntimeError, nil, nil],
+ [:c_call, 20, "xyzzy", Exception, :initialize, raised_exc, nil, nil],
+ [:c_return,20, "xyzzy", Exception, :initialize, raised_exc, nil, nil],
+ [:c_return,20, "xyzzy", Exception, :exception, RuntimeError, nil, nil],
+ [:c_return,20, "xyzzy", Kernel, :raise, self, nil, nil],
+ [:c_call, 20, "xyzzy", Exception, :backtrace, raised_exc, nil, nil],
+ [:c_return,20, "xyzzy", Exception, :backtrace, raised_exc, nil, nil],
[:raise, 20, "xyzzy", TestSetTraceFunc, :trace_by_tracepoint, self, :outer, raised_exc],
- [:c_call, 20, "xyzzy", Module, :===, RuntimeError,:outer, :nothing],
- [:c_return,20, "xyzzy", Module, :===, RuntimeError,:outer, true],
+ [:c_call, 20, "xyzzy", Module, :===, RuntimeError, nil, nil],
+ [:c_return,20, "xyzzy", Module, :===, RuntimeError, nil, nil],
[:line, 21, "xyzzy", TestSetTraceFunc, method, self, :outer, :nothing],
- [:c_call, 21, "xyzzy", TracePoint, :disable, trace, :outer, :nothing],
+ [:c_call, 21, "xyzzy", TracePoint, :disable, trace, nil, nil],
]
return events, answer_events
end
+ def test_set_trace_func_curry_argument_error
+ b = lambda {|x, y, z| (x||0) + (y||0) + (z||0) }.curry[1, 2]
+ set_trace_func(proc {})
+ assert_raise(ArgumentError) {b[3, 4]}
+ end
+
def test_set_trace_func
actual_events, expected_events = trace_by_set_trace_func
expected_events.zip(actual_events){|e, a|
@@ -707,25 +795,30 @@ class TestSetTraceFunc < Test::Unit::TestCase
def test_tracepoint_enable
ary = []
args = nil
- trace = TracePoint.new(:call){|tp|
- next if !target_thread?
- ary << tp.method_id
- }
- foo
- trace.enable{|*a|
- args = a
+ begin
+ trace = TracePoint.new(:call){|tp|
+ next if !target_thread?
+ ary << tp.method_id
+ }
foo
- }
- foo
- assert_equal([:foo], ary)
- assert_equal([], args)
+ trace.enable(target_thread: nil){|*a|
+ args = a
+ foo
+ }
+ foo
+ assert_equal([:foo], ary)
+ assert_equal([], args)
+ ensure
+ trace&.disable
+ end
trace = TracePoint.new{}
begin
assert_equal(false, trace.enable)
assert_equal(true, trace.enable)
- trace.enable{}
- assert_equal(true, trace.enable)
+ trace.enable(target_thread: nil){}
+ trace.disable
+ assert_equal(false, trace.enable)
ensure
trace.disable
end
@@ -881,6 +974,55 @@ class TestSetTraceFunc < Test::Unit::TestCase
assert_equal(expected*2, events)
end
+ def test_tracepoint_struct
+ c = Struct.new(:x) do
+ alias y x
+ alias y= x=
+ end
+ obj = c.new
+
+ ar_meth = obj.method(:x)
+ aw_meth = obj.method(:x=)
+ aar_meth = obj.method(:y)
+ aaw_meth = obj.method(:y=)
+ events = []
+ trace = TracePoint.new(:c_call, :c_return){|tp|
+ next if !target_thread?
+ next if tp.path != __FILE__
+ next if tp.method_id == :call
+ case tp.event
+ when :c_call
+ assert_raise(RuntimeError) {tp.return_value}
+ events << [tp.event, tp.method_id, tp.callee_id]
+ when :c_return
+ events << [tp.event, tp.method_id, tp.callee_id, tp.return_value]
+ end
+ }
+ test_proc = proc do
+ obj.x = 1
+ obj.x
+ obj.y = 2
+ obj.y
+ aw_meth.call(1)
+ ar_meth.call
+ aaw_meth.call(2)
+ aar_meth.call
+ end
+ test_proc.call # populate call caches
+ trace.enable(&test_proc)
+ expected = [
+ [:c_call, :x=, :x=],
+ [:c_return, :x=, :x=, 1],
+ [:c_call, :x, :x],
+ [:c_return, :x, :x, 1],
+ [:c_call, :x=, :y=],
+ [:c_return, :x=, :y=, 2],
+ [:c_call, :x, :y],
+ [:c_return, :x, :y, 2],
+ ]
+ assert_equal(expected*2, events)
+ end
+
class XYZZYException < Exception; end
def method_test_tracepoint_raised_exception err
raise err
@@ -920,7 +1062,7 @@ class TestSetTraceFunc < Test::Unit::TestCase
/return/ =~ tp.event ? tp.return_value : nil
]
}.enable{
- 1.times{
+ [1].map{
3
}
method_for_test_tracepoint_block{
@@ -930,10 +1072,10 @@ class TestSetTraceFunc < Test::Unit::TestCase
# pp events
# expected_events =
[[:b_call, :test_tracepoint_block, TestSetTraceFunc, TestSetTraceFunc, nil],
- [:c_call, :times, Integer, Integer, nil],
+ [:c_call, :map, Array, Array, nil],
[:b_call, :test_tracepoint_block, TestSetTraceFunc, TestSetTraceFunc, nil],
[:b_return, :test_tracepoint_block, TestSetTraceFunc, TestSetTraceFunc, 3],
- [:c_return, :times, Integer, Integer, 1],
+ [:c_return, :map, Array, Array, [3]],
[:call, :method_for_test_tracepoint_block, TestSetTraceFunc, TestSetTraceFunc, nil],
[:b_call, :test_tracepoint_block, TestSetTraceFunc, TestSetTraceFunc, nil],
[:b_return, :test_tracepoint_block, TestSetTraceFunc, TestSetTraceFunc, 4],
@@ -957,7 +1099,7 @@ class TestSetTraceFunc < Test::Unit::TestCase
tp.defined_class, #=> nil,
tp.self.class # tp.self return creating/ending thread
]
- }.enable{
+ }.enable(target_thread: nil){
created_thread = Thread.new{thread_self = self}
created_thread.join
}
@@ -987,9 +1129,9 @@ class TestSetTraceFunc < Test::Unit::TestCase
when :line
assert_match(/ in /, str)
when :call, :c_call
- assert_match(/call \`/, str) # #<TracePoint:c_call `inherited' ../trunk/test.rb:11>
+ assert_match(/call \'/, str) # #<TracePoint:c_call 'inherited' ../trunk/test.rb:11>
when :return, :c_return
- assert_match(/return \`/, str) # #<TracePoint:return `m' ../trunk/test.rb:3>
+ assert_match(/return \'/, str) # #<TracePoint:return 'm' ../trunk/test.rb:3>
when /thread/
assert_match(/\#<Thread:/, str) # #<TracePoint:thread_end of #<Thread:0x87076c0>>
else
@@ -1122,15 +1264,17 @@ class TestSetTraceFunc < Test::Unit::TestCase
end
}
assert_normal_exit src % %q{obj.zip({}) {}}, bug7774
- assert_normal_exit src % %q{
- require 'continuation'
- begin
- c = nil
- obj.sort_by {|x| callcc {|c2| c ||= c2 }; x }
- c.call
- rescue RuntimeError
- end
- }, bug7774
+ if respond_to?(:callcc)
+ assert_normal_exit src % %q{
+ require 'continuation'
+ begin
+ c = nil
+ obj.sort_by {|x| callcc {|c2| c ||= c2 }; x }
+ c.call
+ rescue RuntimeError
+ end
+ }, bug7774
+ end
# TracePoint
tp_b = nil
@@ -1232,11 +1376,13 @@ class TestSetTraceFunc < Test::Unit::TestCase
def test_a_call
events = []
+ log = []
TracePoint.new(:a_call){|tp|
next if !target_thread?
events << tp.event
+ log << "| event:#{ tp.event } method_id:#{ tp.method_id } #{ tp.path }:#{ tp.lineno }"
}.enable{
- 1.times{
+ [1].map{
3
}
method_for_test_tracepoint_block{
@@ -1249,16 +1395,18 @@ class TestSetTraceFunc < Test::Unit::TestCase
:b_call,
:call,
:b_call,
- ], events)
+ ], events, "TracePoint log:\n#{ log.join("\n") }\n")
end
def test_a_return
events = []
+ log = []
TracePoint.new(:a_return){|tp|
next if !target_thread?
events << tp.event
+ log << "| event:#{ tp.event } method_id:#{ tp.method_id } #{ tp.path }:#{ tp.lineno }"
}.enable{
- 1.times{
+ [1].map{
3
}
method_for_test_tracepoint_block{
@@ -1271,7 +1419,7 @@ class TestSetTraceFunc < Test::Unit::TestCase
:b_return,
:return,
:b_return
- ], events)
+ ], events, "TracePoint log:\n#{ log.join("\n") }\n")
end
def test_const_missing
@@ -1617,7 +1765,7 @@ class TestSetTraceFunc < Test::Unit::TestCase
Bug10724.new
}
- assert_equal([:call, :return], evs)
+ assert_equal([:call, :call, :return, :return], evs)
end
require 'fiber'
@@ -1849,7 +1997,11 @@ class TestSetTraceFunc < Test::Unit::TestCase
def tp_return_value mid
ary = []
- TracePoint.new(:return, :b_return){|tp| next if !target_thread?; ary << [tp.event, tp.method_id, tp.return_value]}.enable{
+ TracePoint.new(:return, :b_return){|tp|
+ next if !target_thread?
+ next if tp.path != __FILE__
+ ary << [tp.event, tp.method_id, tp.return_value]
+ }.enable{
send mid
}
ary.pop # last b_return event is not required.
@@ -1941,7 +2093,7 @@ class TestSetTraceFunc < Test::Unit::TestCase
end
define_method(:f_break_defined) do
- return :f_break_defined
+ break :f_break_defined
end
define_method(:f_raise_defined) do
@@ -1962,27 +2114,44 @@ class TestSetTraceFunc < Test::Unit::TestCase
tp_return_value(:f_last_defined),
'[Bug #13369]'
- assert_equal [[:b_return, :f_return_defined, nil], # current limitation
+ assert_equal [[:b_return, :f_return_defined, :f_return_defined],
[:return, :f_return_defined, :f_return_defined]],
tp_return_value(:f_return_defined),
'[Bug #13369]'
- assert_equal [[:b_return, :f_break_defined, nil],
+ assert_equal [[:b_return, :f_break_defined, :f_break_defined],
[:return, :f_break_defined, :f_break_defined]],
tp_return_value(:f_break_defined),
'[Bug #13369]'
- assert_equal [[:b_return, :f_raise_defined, nil],
+ assert_equal [[:b_return, :f_raise_defined, f_raise_defined],
[:return, :f_raise_defined, f_raise_defined]],
tp_return_value(:f_raise_defined),
'[Bug #13369]'
- assert_equal [[:b_return, :f_break_in_rescue_defined, nil],
+ assert_equal [[:b_return, :f_break_in_rescue_defined, f_break_in_rescue_defined],
[:return, :f_break_in_rescue_defined, f_break_in_rescue_defined]],
tp_return_value(:f_break_in_rescue_defined),
'[Bug #13369]'
end
+ define_method(:just_yield) do |&block|
+ block.call
+ end
+
+ define_method(:unwind_multiple_bmethods) do
+ just_yield { return :unwind_multiple_bmethods }
+ end
+
+ def test_non_local_return_across_multiple_define_methods
+ assert_equal [[:b_return, :unwind_multiple_bmethods, nil],
+ [:b_return, :just_yield, nil],
+ [:return, :just_yield, nil],
+ [:b_return, :unwind_multiple_bmethods, :unwind_multiple_bmethods],
+ [:return, :unwind_multiple_bmethods, :unwind_multiple_bmethods]],
+ tp_return_value(:unwind_multiple_bmethods)
+ end
+
def f_iter
yield
end
@@ -2041,7 +2210,7 @@ class TestSetTraceFunc < Test::Unit::TestCase
q = Thread::Queue.new
t = Thread.new{
Thread.current.add_trace_func proc{|ev, file, line, *args|
- events << [ev, line]
+ events << [ev, line] if file == __FILE__
} # do not stop trace. They will be stopped at Thread termination.
q.push 1
_x = 1
@@ -2077,9 +2246,9 @@ class TestSetTraceFunc < Test::Unit::TestCase
}
# it is dirty hack. usually we shouldn't use such technique
Thread.pass until t.status == 'sleep'
- # When MJIT thread exists, t.status becomes 'sleep' even if it does not reach m2t_q.pop.
+ # When RJIT thread exists, t.status becomes 'sleep' even if it does not reach m2t_q.pop.
# This sleep forces it to reach m2t_q.pop for --jit-wait.
- sleep 1 if defined?(RubyVM::JIT) && RubyVM::JIT.enabled?
+ sleep 1 if defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled?
t.add_trace_func proc{|ev, file, line, *args|
if file == __FILE__
@@ -2092,17 +2261,16 @@ class TestSetTraceFunc < Test::Unit::TestCase
m2t_q.push 1
t.join
- assert_equal ["c-return", base_line + 31], events[0]
- assert_equal ["line", base_line + 32], events[1]
- assert_equal ["line", base_line + 33], events[2]
- assert_equal ["call", base_line + -6], events[3]
- assert_equal ["return", base_line + -4], events[4]
- assert_equal ["line", base_line + 34], events[5]
- assert_equal ["line", base_line + 35], events[6]
- assert_equal ["c-call", base_line + 35], events[7] # Thread.current
- assert_equal ["c-return", base_line + 35], events[8] # Thread.current
- assert_equal ["c-call", base_line + 35], events[9] # Thread#set_trace_func
- assert_equal nil, events[10]
+ assert_equal ["line", base_line + 32], events[0]
+ assert_equal ["line", base_line + 33], events[1]
+ assert_equal ["call", base_line + -6], events[2]
+ assert_equal ["return", base_line + -4], events[3]
+ assert_equal ["line", base_line + 34], events[4]
+ assert_equal ["line", base_line + 35], events[5]
+ assert_equal ["c-call", base_line + 35], events[6] # Thread.current
+ assert_equal ["c-return", base_line + 35], events[7] # Thread.current
+ assert_equal ["c-call", base_line + 35], events[8] # Thread#set_trace_func
+ assert_equal nil, events[9]
end
def test_lineno_in_optimized_insn
@@ -2139,7 +2307,7 @@ class TestSetTraceFunc < Test::Unit::TestCase
_c = a + b
end
- def check_with_events *trace_events
+ def check_with_events(trace_point_events, expected_events = trace_point_events)
all_events = [[:call, :method_for_enable_target1],
[:line, :method_for_enable_target1],
[:line, :method_for_enable_target1],
@@ -2161,7 +2329,7 @@ class TestSetTraceFunc < Test::Unit::TestCase
[:return, :method_for_enable_target1],
]
events = []
- TracePoint.new(*trace_events) do |tp|
+ TracePoint.new(*trace_point_events) do |tp|
next unless target_thread?
events << [tp.event, tp.method_id]
end.enable(target: method(:method_for_enable_target1)) do
@@ -2169,15 +2337,22 @@ class TestSetTraceFunc < Test::Unit::TestCase
method_for_enable_target2
method_for_enable_target1
end
- assert_equal all_events.find_all{|(ev)| trace_events.include? ev}, events
+
+ assert_equal all_events.keep_if { |(ev)| expected_events.include? ev }, events
end
def test_tracepoint_enable_target
- check_with_events :line
- check_with_events :call, :return
- check_with_events :line, :call, :return
- check_with_events :call, :return, :b_call, :b_return
- check_with_events :line, :call, :return, :b_call, :b_return
+ check_with_events([:line])
+ check_with_events([:call, :return])
+ check_with_events([:line, :call, :return])
+ check_with_events([:call, :return, :b_call, :b_return])
+ check_with_events([:line, :call, :return, :b_call, :b_return])
+
+ # No arguments passed into TracePoint.new enables all ISEQ_TRACE_EVENTS
+ check_with_events([], [:line, :class, :end, :call, :return, :c_call, :c_return, :b_call, :b_return, :rescue])
+
+ # Raise event should be ignored
+ check_with_events([:line, :raise])
end
def test_tracepoint_nested_enabled_with_target
@@ -2202,7 +2377,7 @@ class TestSetTraceFunc < Test::Unit::TestCase
# global TP and targeted TP
ex = assert_raise(ArgumentError) do
tp = TracePoint.new(:line){}
- tp.enable{
+ tp.enable(target_thread: nil){
tp.enable(target: code2){}
}
end
@@ -2316,6 +2491,40 @@ class TestSetTraceFunc < Test::Unit::TestCase
assert_equal [:tp1, 1, 2, :tp2, 3], events
end
+ def test_multiple_enable
+ ary = []
+ trace = TracePoint.new(:call) do |tp|
+ ary << tp.method_id
+ end
+ trace.enable
+ trace.enable
+ foo
+ trace.disable
+ assert_equal(1, ary.count(:foo), '[Bug #19114]')
+ end
+
+ def test_multiple_tracepoints_same_bmethod
+ events = []
+ tp1 = TracePoint.new(:return) do |tp|
+ events << :tp1
+ end
+ tp2 = TracePoint.new(:return) do |tp|
+ events << :tp2
+ end
+
+ obj = Object.new
+ obj.define_singleton_method(:foo) {}
+ bmethod = obj.method(:foo)
+
+ tp1.enable(target: bmethod) do
+ tp2.enable(target: bmethod) do
+ obj.foo
+ end
+ end
+
+ assert_equal([:tp2, :tp1], events, '[Bug #18031]')
+ end
+
def test_script_compiled
events = []
tp = TracePoint.new(:script_compiled){|tp|
@@ -2344,7 +2553,7 @@ class TestSetTraceFunc < Test::Unit::TestCase
}
assert_equal [], events, 'script_compiled event should not be invoked on compile error'
- skip "TODO: test for requires"
+ omit "TODO: test for requires"
events.clear
tp.enable{
@@ -2393,6 +2602,99 @@ class TestSetTraceFunc < Test::Unit::TestCase
assert_equal Array.new(2){th}, events
end
+ def test_return_bmethod_location
+ bug13392 = "[ruby-core:80515] incorrect bmethod return location"
+ actual = nil
+ obj = Object.new
+ expected = __LINE__ + 1
+ obj.define_singleton_method(:t){}
+ tp = TracePoint.new(:return) do
+ next unless target_thread?
+ actual = tp.lineno
+ end
+ tp.enable {obj.t}
+ assert_equal(expected, actual, bug13392)
+ end
+
+ def test_b_tracepoints_going_away
+ # test that call and return TracePoints continue to work
+ # when b_call and b_return TracePoints stop
+ events = []
+ record_events = ->(tp) do
+ next unless target_thread?
+ events << [tp.event, tp.method_id]
+ end
+
+ call_ret_tp = TracePoint.new(:call, :return, &record_events)
+ block_call_ret_tp = TracePoint.new(:b_call, :b_return, &record_events)
+
+ obj = Object.new
+ obj.define_singleton_method(:foo) {} # a bmethod
+
+ foo = obj.method(:foo)
+ call_ret_tp.enable(target: foo) do
+ block_call_ret_tp.enable(target: foo) do
+ obj.foo
+ end
+ obj.foo
+ end
+
+ assert_equal(
+ [
+ [:call, :foo],
+ [:b_call, :foo],
+ [:b_return, :foo],
+ [:return, :foo],
+ [:call, :foo],
+ [:return, :foo],
+ ],
+ events,
+ )
+ end
+
+ def test_target_different_bmethod_same_iseq
+ # make two bmethods that share the same block iseq
+ block = Proc.new {}
+ obj = Object.new
+ obj.define_singleton_method(:one, &block)
+ obj.define_singleton_method(:two, &block)
+
+ events = []
+ record_events = ->(tp) do
+ next unless target_thread?
+ events << [tp.event, tp.method_id]
+ end
+ tp_one = TracePoint.new(:call, :return, &record_events)
+ tp_two = TracePoint.new(:call, :return, &record_events)
+
+ tp_one.enable(target: obj.method(:one)) do
+ obj.one
+ obj.two # not targeted
+ end
+ assert_equal([[:call, :one], [:return, :one]], events)
+ events.clear
+
+ tp_one.enable(target: obj.method(:one)) do
+ obj.one
+ tp_two.enable(target: obj.method(:two)) do
+ obj.two
+ end
+ obj.two
+ obj.one
+ end
+ assert_equal(
+ [
+ [:call, :one],
+ [:return, :one],
+ [:call, :two],
+ [:return, :two],
+ [:call, :one],
+ [:return, :one],
+ ],
+ events
+ )
+ end
+
def test_return_event_with_rescue
obj = Object.new
def obj.example
@@ -2420,6 +2722,20 @@ class TestSetTraceFunc < Test::Unit::TestCase
end
bar
EOS
+
+ assert_normal_exit(<<-EOS, 'Bug #18730')
+ def bar
+ 42
+ end
+ tp_line = TracePoint.new(:line) do |tp0|
+ tp_multi1 = TracePoint.new(:return, :b_return, :line) do |tp|
+ tp0.disable
+ end
+ tp_multi1.enable
+ end
+ tp_line.enable(target: method(:bar))
+ bar
+ EOS
end
def test_stat_exists
@@ -2455,4 +2771,174 @@ class TestSetTraceFunc < Test::Unit::TestCase
}
assert_equal [__LINE__ - 5, __LINE__ - 4, __LINE__ - 3], lines, 'Bug #17868'
end
+
+ def test_allow_reentry
+ event_lines = []
+ _l1 = _l2 = _l3 = _l4 = nil
+ TracePoint.new(:line) do |tp|
+ next unless target_thread?
+
+ event_lines << tp.lineno
+ next if (__LINE__ + 2 .. __LINE__ + 4).cover?(tp.lineno)
+ TracePoint.allow_reentry do
+ _a = 1; _l3 = __LINE__
+ _b = 2; _l4 = __LINE__
+ end
+ end.enable do
+ _c = 3; _l1 = __LINE__
+ _d = 4; _l2 = __LINE__
+ end
+
+ assert_equal [_l1, _l3, _l4, _l2, _l3, _l4], event_lines
+
+ assert_raise RuntimeError do
+ TracePoint.allow_reentry{}
+ end
+ end
+
+ def test_raising_from_b_return_tp_tracing_bmethod
+ assert_normal_exit(<<~RUBY, '[Bug #18060]', timeout: 3)
+ class Foo
+ define_singleton_method(:foo) { return } # a bmethod
+ end
+
+ TracePoint.trace(:b_return) do |tp|
+ raise
+ end
+
+ Foo.foo
+ RUBY
+
+ # Same thing but with a target
+ assert_normal_exit(<<~RUBY, '[Bug #18060]', timeout: 3)
+ class Foo
+ define_singleton_method(:foo) { return } # a bmethod
+ end
+
+ TracePoint.new(:b_return) do |tp|
+ raise
+ end.enable(target: Foo.method(:foo))
+
+ Foo.foo
+ RUBY
+ end
+
+ def helper_cant_rescue
+ begin
+ raise SyntaxError
+ rescue
+ cant_rescue
+ end
+ end
+
+ def test_tp_rescue
+ lines = []
+ TracePoint.new(:line){|tp|
+ next unless target_thread?
+ lines << tp.lineno
+ }.enable{
+ begin
+ helper_cant_rescue
+ rescue SyntaxError
+ end
+ }
+ _call_line = lines.shift
+ _raise_line = lines.shift
+ assert_equal [], lines
+ end
+
+ def helper_can_rescue
+ begin
+ raise __LINE__.to_s
+ rescue SyntaxError
+ :ng
+ rescue
+ :ok
+ end
+ end
+
+ def helper_can_rescue_empty_body
+ begin
+ raise __LINE__.to_s
+ rescue SyntaxError
+ :ng
+ rescue
+ end
+ end
+
+ def test_tp_rescue_event
+ lines = []
+ TracePoint.new(:rescue){|tp|
+ next unless target_thread?
+ lines << [tp.lineno, tp.raised_exception]
+ }.enable{
+ helper_can_rescue
+ }
+
+ line, err, = lines.pop
+ assert_equal [], lines
+ assert err.kind_of?(RuntimeError)
+ assert_equal err.message.to_i + 4, line
+
+ lines = []
+ TracePoint.new(:rescue){|tp|
+ next unless target_thread?
+ lines << [tp.lineno, tp.raised_exception]
+ }.enable{
+ helper_can_rescue_empty_body
+ }
+
+ line, err, = lines.pop
+ assert_equal [], lines
+ assert err.kind_of?(RuntimeError)
+ assert_equal err.message.to_i + 3, line
+ end
+
+ def test_tracepoint_thread_begin
+ target_thread = nil
+
+ trace = TracePoint.new(:thread_begin) do |tp|
+ target_thread = tp.self
+ end
+
+ trace.enable(target_thread: nil) do
+ Thread.new{}.join
+ end
+
+ assert_kind_of(Thread, target_thread)
+ end
+
+ def test_tracepoint_thread_end
+ target_thread = nil
+
+ trace = TracePoint.new(:thread_end) do |tp|
+ target_thread = tp.self
+ end
+
+ trace.enable(target_thread: nil) do
+ Thread.new{}.join
+ end
+
+ assert_kind_of(Thread, target_thread)
+ end
+
+ def test_tracepoint_thread_end_with_exception
+ target_thread = nil
+
+ trace = TracePoint.new(:thread_end) do |tp|
+ target_thread = tp.self
+ end
+
+ trace.enable(target_thread: nil) do
+ thread = Thread.new do
+ Thread.current.report_on_exception = false
+ raise
+ end
+
+ # Ignore the exception raised by the thread:
+ thread.join rescue nil
+ end
+
+ assert_kind_of(Thread, target_thread)
+ end
end
diff --git a/test/ruby/test_shapes.rb b/test/ruby/test_shapes.rb
new file mode 100644
index 0000000000..9b02504384
--- /dev/null
+++ b/test/ruby/test_shapes.rb
@@ -0,0 +1,1040 @@
+# frozen_string_literal: false
+require 'test/unit'
+require 'objspace'
+require 'json'
+
+# These test the functionality of object shapes
+class TestShapes < Test::Unit::TestCase
+ MANY_IVS = 80
+
+ class IVOrder
+ def expected_ivs
+ %w{ @a @b @c @d @e @f @g @h @i @j @k }
+ end
+
+ def set_ivs
+ expected_ivs.each { instance_variable_set(_1, 1) }
+ self
+ end
+ end
+
+ class ShapeOrder
+ def initialize
+ @b = :b # 5 => 6
+ end
+
+ def set_b
+ @b = :b # 5 => 6
+ end
+
+ def set_c
+ @c = :c # 5 => 7
+ end
+ end
+
+ class OrderedAlloc
+ def add_ivars
+ 10.times do |i|
+ instance_variable_set("@foo" + i.to_s, 0)
+ end
+ end
+ end
+
+ class Example
+ def initialize
+ @a = 1
+ end
+ end
+
+ class RemoveAndAdd
+ def add_foo
+ @foo = 1
+ end
+
+ def remove_foo
+ remove_instance_variable(:@foo)
+ end
+
+ def add_bar
+ @bar = 1
+ end
+ end
+
+ class TooComplex
+ attr_reader :hopefully_unique_name, :b
+
+ def initialize
+ @hopefully_unique_name = "a"
+ @b = "b"
+ end
+
+ # Make enough lazily defined accessors to allow us to force
+ # polymorphism
+ class_eval (RubyVM::Shape::SHAPE_MAX_VARIATIONS + 1).times.map {
+ "def a#{_1}_m; @a#{_1} ||= #{_1}; end"
+ }.join(" ; ")
+
+ class_eval "attr_accessor " + (RubyVM::Shape::SHAPE_MAX_VARIATIONS + 1).times.map {
+ ":a#{_1}"
+ }.join(", ")
+
+ def iv_not_defined; @not_defined; end
+
+ def write_iv_method
+ self.a3 = 12345
+ end
+
+ def write_iv
+ @a3 = 12345
+ end
+ end
+
+ # RubyVM::Shape.of returns new instances of shape objects for
+ # each call. This helper method allows us to define equality for
+ # shapes
+ def assert_shape_equal(shape1, shape2)
+ assert_equal(shape1.id, shape2.id)
+ assert_equal(shape1.parent_id, shape2.parent_id)
+ assert_equal(shape1.depth, shape2.depth)
+ assert_equal(shape1.type, shape2.type)
+ end
+
+ def refute_shape_equal(shape1, shape2)
+ refute_equal(shape1.id, shape2.id)
+ end
+
+ def test_iv_order_correct_on_complex_objects
+ (RubyVM::Shape::SHAPE_MAX_VARIATIONS + 1).times {
+ IVOrder.new.instance_variable_set("@a#{_1}", 1)
+ }
+
+ obj = IVOrder.new
+ iv_list = obj.set_ivs.instance_variables
+ assert_equal obj.expected_ivs, iv_list.map(&:to_s)
+ end
+
+ def test_too_complex
+ ensure_complex
+
+ tc = TooComplex.new
+ tc.send("a#{RubyVM::Shape::SHAPE_MAX_VARIATIONS}_m")
+ assert_predicate RubyVM::Shape.of(tc), :too_complex?
+ end
+
+ def test_ordered_alloc_is_not_complex
+ 5.times { OrderedAlloc.new.add_ivars }
+ obj = JSON.parse(ObjectSpace.dump(OrderedAlloc))
+ assert_operator obj["variation_count"], :<, RubyVM::Shape::SHAPE_MAX_VARIATIONS
+ end
+
+ def test_too_many_ivs_on_obj
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ class Hi; end
+
+ RubyVM::Shape.exhaust_shapes(2)
+
+ obj = Hi.new
+ obj.instance_variable_set(:@b, 1)
+ obj.instance_variable_set(:@c, 1)
+ obj.instance_variable_set(:@d, 1)
+
+ assert_predicate RubyVM::Shape.of(obj), :too_complex?
+ end;
+ end
+
+ def test_too_many_ivs_on_class
+ obj = Class.new
+
+ (MANY_IVS + 1).times do
+ obj.instance_variable_set(:"@a#{_1}", 1)
+ end
+
+ assert_false RubyVM::Shape.of(obj).too_complex?
+ end
+
+ def test_removing_when_too_many_ivs_on_class
+ obj = Class.new
+
+ (MANY_IVS + 2).times do
+ obj.instance_variable_set(:"@a#{_1}", 1)
+ end
+ (MANY_IVS + 2).times do
+ obj.remove_instance_variable(:"@a#{_1}")
+ end
+
+ assert_empty obj.instance_variables
+ end
+
+ def test_removing_when_too_many_ivs_on_module
+ obj = Module.new
+
+ (MANY_IVS + 2).times do
+ obj.instance_variable_set(:"@a#{_1}", 1)
+ end
+ (MANY_IVS + 2).times do
+ obj.remove_instance_variable(:"@a#{_1}")
+ end
+
+ assert_empty obj.instance_variables
+ end
+
+ def test_too_complex_geniv
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ class TooComplex < Hash
+ attr_reader :very_unique
+ end
+
+ RubyVM::Shape.exhaust_shapes
+
+ (RubyVM::Shape::SHAPE_MAX_VARIATIONS * 2).times do
+ TooComplex.new.instance_variable_set(:"@unique_#{_1}", 1)
+ end
+
+ tc = TooComplex.new
+ tc.instance_variable_set(:@very_unique, 3)
+ tc.instance_variable_set(:@very_unique2, 4)
+ assert_equal 3, tc.instance_variable_get(:@very_unique)
+ assert_equal 4, tc.instance_variable_get(:@very_unique2)
+
+ assert_equal [:@very_unique, :@very_unique2], tc.instance_variables
+ end;
+ end
+
+ def test_use_all_shapes_then_freeze
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ class Hi; end
+ RubyVM::Shape.exhaust_shapes(3)
+
+ obj = Hi.new
+ i = 0
+ while RubyVM::Shape.shapes_available > 0
+ obj.instance_variable_set(:"@b#{i}", 1)
+ i += 1
+ end
+ obj.freeze
+
+ assert obj.frozen?
+ end;
+ end
+
+ def test_run_out_of_shape_for_object
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ class A
+ def initialize
+ @a = 1
+ end
+ end
+ RubyVM::Shape.exhaust_shapes
+
+ A.new
+ end;
+ end
+
+ def test_run_out_of_shape_for_class_ivar
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ RubyVM::Shape.exhaust_shapes
+
+ c = Class.new
+ c.instance_variable_set(:@a, 1)
+ assert_equal(1, c.instance_variable_get(:@a))
+
+ c.remove_instance_variable(:@a)
+ assert_nil(c.instance_variable_get(:@a))
+
+ assert_raise(NameError) do
+ c.remove_instance_variable(:@a)
+ end
+ end;
+ end
+
+ def test_evacuate_class_ivar_and_compaction
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ count = 20
+
+ c = Class.new
+ count.times do |ivar|
+ c.instance_variable_set("@i#{ivar}", "ivar-#{ivar}")
+ end
+
+ RubyVM::Shape.exhaust_shapes
+
+ GC.auto_compact = true
+ GC.stress = true
+ # Cause evacuation
+ c.instance_variable_set(:@a, o = Object.new)
+ assert_equal(o, c.instance_variable_get(:@a))
+ GC.stress = false
+
+ count.times do |ivar|
+ assert_equal "ivar-#{ivar}", c.instance_variable_get("@i#{ivar}")
+ end
+ end;
+ end
+
+ def test_evacuate_generic_ivar_and_compaction
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ count = 20
+
+ c = Hash.new
+ count.times do |ivar|
+ c.instance_variable_set("@i#{ivar}", "ivar-#{ivar}")
+ end
+
+ RubyVM::Shape.exhaust_shapes
+
+ GC.auto_compact = true
+ GC.stress = true
+
+ # Cause evacuation
+ c.instance_variable_set(:@a, o = Object.new)
+ assert_equal(o, c.instance_variable_get(:@a))
+
+ GC.stress = false
+
+ count.times do |ivar|
+ assert_equal "ivar-#{ivar}", c.instance_variable_get("@i#{ivar}")
+ end
+ end;
+ end
+
+ def test_evacuate_object_ivar_and_compaction
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ count = 20
+
+ c = Object.new
+ count.times do |ivar|
+ c.instance_variable_set("@i#{ivar}", "ivar-#{ivar}")
+ end
+
+ RubyVM::Shape.exhaust_shapes
+
+ GC.auto_compact = true
+ GC.stress = true
+
+ # Cause evacuation
+ c.instance_variable_set(:@a, o = Object.new)
+ assert_equal(o, c.instance_variable_get(:@a))
+
+ GC.stress = false
+
+ count.times do |ivar|
+ assert_equal "ivar-#{ivar}", c.instance_variable_get("@i#{ivar}")
+ end
+ end;
+ end
+
+ def test_gc_stress_during_evacuate_generic_ivar
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ [].instance_variable_set(:@a, 1)
+
+ RubyVM::Shape.exhaust_shapes
+
+ ary = 10.times.map { [] }
+
+ GC.stress = true
+ ary.each do |o|
+ o.instance_variable_set(:@a, 1)
+ o.instance_variable_set(:@b, 1)
+ end
+ end;
+ end
+
+ def test_run_out_of_shape_for_module_ivar
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ RubyVM::Shape.exhaust_shapes
+
+ module Foo
+ @a = 1
+ @b = 2
+ assert_equal 1, @a
+ assert_equal 2, @b
+ end
+ end;
+ end
+
+ def test_run_out_of_shape_for_class_cvar
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ RubyVM::Shape.exhaust_shapes
+
+ c = Class.new
+
+ c.class_variable_set(:@@a, 1)
+ assert_equal(1, c.class_variable_get(:@@a))
+
+ c.class_eval { remove_class_variable(:@@a) }
+ assert_false(c.class_variable_defined?(:@@a))
+
+ assert_raise(NameError) do
+ c.class_eval { remove_class_variable(:@@a) }
+ end
+ end;
+ end
+
+ def test_run_out_of_shape_generic_instance_variable_set
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ class TooComplex < Hash
+ end
+
+ RubyVM::Shape.exhaust_shapes
+
+ tc = TooComplex.new
+ tc.instance_variable_set(:@a, 1)
+ tc.instance_variable_set(:@b, 2)
+
+ tc.remove_instance_variable(:@a)
+ assert_nil(tc.instance_variable_get(:@a))
+
+ assert_raise(NameError) do
+ tc.remove_instance_variable(:@a)
+ end
+ end;
+ end
+
+ def test_run_out_of_shape_generic_ivar_set
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ class Hi < String
+ def initialize
+ 8.times do |i|
+ instance_variable_set("@ivar_#{i}", i)
+ end
+ end
+
+ def transition
+ @hi_transition ||= 1
+ end
+ end
+
+ a = Hi.new
+
+ # Try to run out of shapes
+ RubyVM::Shape.exhaust_shapes
+
+ assert_equal 1, a.transition
+ assert_equal 1, a.transition
+ end;
+ end
+
+ def test_run_out_of_shape_instance_variable_defined
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ class A
+ attr_reader :a, :b, :c, :d
+ def initialize
+ @a = @b = @c = @d = 1
+ end
+ end
+
+ RubyVM::Shape.exhaust_shapes
+
+ a = A.new
+ assert_equal true, a.instance_variable_defined?(:@a)
+ end;
+ end
+
+ def test_run_out_of_shape_instance_variable_defined_on_module
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ RubyVM::Shape.exhaust_shapes
+
+ module A
+ @a = @b = @c = @d = 1
+ end
+
+ assert_equal true, A.instance_variable_defined?(:@a)
+ end;
+ end
+
+ def test_run_out_of_shape_during_remove_instance_variable
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ o = Object.new
+ 10.times { |i| o.instance_variable_set(:"@a#{i}", i) }
+
+ RubyVM::Shape.exhaust_shapes
+
+ o.remove_instance_variable(:@a0)
+ (1...10).each do |i|
+ assert_equal(i, o.instance_variable_get(:"@a#{i}"))
+ end
+ end;
+ end
+
+ def test_run_out_of_shape_remove_instance_variable
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ class A
+ attr_reader :a, :b, :c, :d
+ def initialize
+ @a = @b = @c = @d = 1
+ end
+ end
+
+ a = A.new
+
+ RubyVM::Shape.exhaust_shapes
+
+ a.remove_instance_variable(:@b)
+ assert_nil a.b
+
+ a.remove_instance_variable(:@a)
+ assert_nil a.a
+
+ a.remove_instance_variable(:@c)
+ assert_nil a.c
+
+ assert_equal 1, a.d
+ end;
+ end
+
+ def test_run_out_of_shape_rb_obj_copy_ivar
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ class A
+ def initialize
+ init # Avoid right sizing
+ end
+
+ def init
+ @a = @b = @c = @d = @e = @f = 1
+ end
+ end
+
+ a = A.new
+
+ RubyVM::Shape.exhaust_shapes
+
+ a.dup
+ end;
+ end
+
+ def test_evacuate_generic_ivar_memory_leak
+ assert_no_memory_leak([], "#{<<~'begin;'}", "#{<<~'end;'}", rss: true)
+ o = []
+ o.instance_variable_set(:@a, 1)
+
+ RubyVM::Shape.exhaust_shapes
+
+ ary = 1_000_000.times.map { [] }
+ begin;
+ ary.each do |o|
+ o.instance_variable_set(:@a, 1)
+ o.instance_variable_set(:@b, 1)
+ end
+ ary.clear
+ ary = nil
+ GC.start
+ end;
+ end
+
+ def test_use_all_shapes_module
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ class Hi; end
+
+ RubyVM::Shape.exhaust_shapes(2)
+
+ obj = Module.new
+ 3.times do
+ obj.instance_variable_set(:"@a#{_1}", _1)
+ end
+
+ ivs = 3.times.map do
+ obj.instance_variable_get(:"@a#{_1}")
+ end
+
+ assert_equal [0, 1, 2], ivs
+ end;
+ end
+
+ def test_complex_freeze_after_clone
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ class Hi; end
+
+ RubyVM::Shape.exhaust_shapes(2)
+
+ obj = Object.new
+ i = 0
+ while RubyVM::Shape.shapes_available > 0
+ obj.instance_variable_set(:"@b#{i}", i)
+ i += 1
+ end
+
+ v = obj.clone(freeze: true)
+ assert_predicate v, :frozen?
+ assert_equal 0, v.instance_variable_get(:@b0)
+ end;
+ end
+
+ def test_too_complex_ractor
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ $VERBOSE = nil
+ class TooComplex
+ attr_reader :very_unique
+ end
+
+ RubyVM::Shape::SHAPE_MAX_VARIATIONS.times do
+ TooComplex.new.instance_variable_set(:"@unique_#{_1}", Object.new)
+ end
+
+ tc = TooComplex.new
+ tc.instance_variable_set(:"@very_unique", 3)
+
+ assert_predicate RubyVM::Shape.of(tc), :too_complex?
+ assert_equal 3, tc.very_unique
+ assert_equal 3, Ractor.new(tc) { |x| Ractor.yield(x.very_unique) }.take
+ assert_equal tc.instance_variables.sort, Ractor.new(tc) { |x| Ractor.yield(x.instance_variables) }.take.sort
+ end;
+ end
+
+ def test_too_complex_ractor_shareable
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ $VERBOSE = nil
+ class TooComplex
+ attr_reader :very_unique
+ end
+
+ RubyVM::Shape::SHAPE_MAX_VARIATIONS.times do
+ TooComplex.new.instance_variable_set(:"@unique_#{_1}", Object.new)
+ end
+
+ tc = TooComplex.new
+ tc.instance_variable_set(:"@very_unique", 3)
+
+ assert_predicate RubyVM::Shape.of(tc), :too_complex?
+ assert_equal 3, tc.very_unique
+ assert_equal 3, Ractor.make_shareable(tc).very_unique
+ end;
+ end
+
+ def test_too_complex_obj_ivar_ractor_share
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ $VERBOSE = nil
+
+ RubyVM::Shape.exhaust_shapes
+
+ r = Ractor.new do
+ o = Object.new
+ o.instance_variable_set(:@a, "hello")
+ Ractor.yield(o)
+ end
+
+ o = r.take
+ assert_equal "hello", o.instance_variable_get(:@a)
+ end;
+ end
+
+ def test_too_complex_generic_ivar_ractor_share
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ $VERBOSE = nil
+
+ RubyVM::Shape.exhaust_shapes
+
+ r = Ractor.new do
+ o = []
+ o.instance_variable_set(:@a, "hello")
+ Ractor.yield(o)
+ end
+
+ o = r.take
+ assert_equal "hello", o.instance_variable_get(:@a)
+ end;
+ end
+
+ def test_read_iv_after_complex
+ ensure_complex
+
+ tc = TooComplex.new
+ tc.send("a#{RubyVM::Shape::SHAPE_MAX_VARIATIONS}_m")
+ assert_predicate RubyVM::Shape.of(tc), :too_complex?
+ assert_equal 3, tc.a3_m
+ end
+
+ def test_read_method_after_complex
+ ensure_complex
+
+ tc = TooComplex.new
+ tc.send("a#{RubyVM::Shape::SHAPE_MAX_VARIATIONS}_m")
+ assert_predicate RubyVM::Shape.of(tc), :too_complex?
+ assert_equal 3, tc.a3_m
+ assert_equal 3, tc.a3
+ end
+
+ def test_write_method_after_complex
+ ensure_complex
+
+ tc = TooComplex.new
+ tc.send("a#{RubyVM::Shape::SHAPE_MAX_VARIATIONS}_m")
+ assert_predicate RubyVM::Shape.of(tc), :too_complex?
+ tc.write_iv_method
+ tc.write_iv_method
+ assert_equal 12345, tc.a3_m
+ assert_equal 12345, tc.a3
+ end
+
+ def test_write_iv_after_complex
+ ensure_complex
+
+ tc = TooComplex.new
+ tc.send("a#{RubyVM::Shape::SHAPE_MAX_VARIATIONS}_m")
+ assert_predicate RubyVM::Shape.of(tc), :too_complex?
+ tc.write_iv
+ tc.write_iv
+ assert_equal 12345, tc.a3_m
+ assert_equal 12345, tc.a3
+ end
+
+ def test_iv_read_via_method_after_complex
+ ensure_complex
+
+ tc = TooComplex.new
+ tc.send("a#{RubyVM::Shape::SHAPE_MAX_VARIATIONS}_m")
+ assert_predicate RubyVM::Shape.of(tc), :too_complex?
+ assert_equal 3, tc.a3_m
+ assert_equal 3, tc.instance_variable_get(:@a3)
+ end
+
+ def test_delete_iv_after_complex
+ ensure_complex
+
+ tc = TooComplex.new
+ tc.send("a#{RubyVM::Shape::SHAPE_MAX_VARIATIONS}_m")
+ assert_predicate RubyVM::Shape.of(tc), :too_complex?
+
+ assert_equal 3, tc.a3_m # make sure IV is initialized
+ assert tc.instance_variable_defined?(:@a3)
+ tc.remove_instance_variable(:@a3)
+ assert_nil tc.a3
+ end
+
+ def test_delete_undefined_after_complex
+ ensure_complex
+
+ tc = TooComplex.new
+ tc.send("a#{RubyVM::Shape::SHAPE_MAX_VARIATIONS}_m")
+ assert_predicate RubyVM::Shape.of(tc), :too_complex?
+
+ refute tc.instance_variable_defined?(:@a3)
+ assert_raise(NameError) do
+ tc.remove_instance_variable(:@a3)
+ end
+ assert_nil tc.a3
+ end
+
+ def test_remove_instance_variable
+ ivars_count = 5
+ object = Object.new
+ ivars_count.times do |i|
+ object.instance_variable_set("@ivar_#{i}", i)
+ end
+
+ ivars = ivars_count.times.map do |i|
+ object.instance_variable_get("@ivar_#{i}")
+ end
+ assert_equal [0, 1, 2, 3, 4], ivars
+
+ object.remove_instance_variable(:@ivar_2)
+
+ ivars = ivars_count.times.map do |i|
+ object.instance_variable_get("@ivar_#{i}")
+ end
+ assert_equal [0, 1, nil, 3, 4], ivars
+ end
+
+ def test_remove_instance_variable_when_out_of_shapes
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ ivars_count = 5
+ object = Object.new
+ ivars_count.times do |i|
+ object.instance_variable_set("@ivar_#{i}", i)
+ end
+
+ ivars = ivars_count.times.map do |i|
+ object.instance_variable_get("@ivar_#{i}")
+ end
+ assert_equal [0, 1, 2, 3, 4], ivars
+
+ RubyVM::Shape.exhaust_shapes
+
+ object.remove_instance_variable(:@ivar_2)
+
+ ivars = ivars_count.times.map do |i|
+ object.instance_variable_get("@ivar_#{i}")
+ end
+ assert_equal [0, 1, nil, 3, 4], ivars
+ end;
+ end
+
+ def test_remove_instance_variable_capacity_transition
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ t_object_shape = RubyVM::Shape.find_by_id(RubyVM::Shape::FIRST_T_OBJECT_SHAPE_ID)
+ assert_equal(RubyVM::Shape::SHAPE_T_OBJECT, t_object_shape.type)
+
+ initial_capacity = t_object_shape.capacity
+
+ # a does not transition in capacity
+ a = Class.new.new
+ initial_capacity.times do |i|
+ a.instance_variable_set(:"@ivar#{i + 1}", i)
+ end
+
+ # b transitions in capacity
+ b = Class.new.new
+ (initial_capacity + 1).times do |i|
+ b.instance_variable_set(:"@ivar#{i}", i)
+ end
+
+ assert_operator(RubyVM::Shape.of(a).capacity, :<, RubyVM::Shape.of(b).capacity)
+
+ # b will now have the same tree as a
+ b.remove_instance_variable(:@ivar0)
+
+ a.instance_variable_set(:@foo, 1)
+ a.instance_variable_set(:@bar, 1)
+
+ # Check that there is no heap corruption
+ GC.verify_internal_consistency
+ end;
+ end
+
+ def test_freeze_after_complex
+ ensure_complex
+
+ tc = TooComplex.new
+ tc.send("a#{RubyVM::Shape::SHAPE_MAX_VARIATIONS}_m")
+ assert_predicate RubyVM::Shape.of(tc), :too_complex?
+ tc.freeze
+ assert_raise(FrozenError) { tc.a3_m }
+ # doesn't transition to frozen shape in this case
+ assert_predicate RubyVM::Shape.of(tc), :too_complex?
+ end
+
+ def test_read_undefined_iv_after_complex
+ ensure_complex
+
+ tc = TooComplex.new
+ tc.send("a#{RubyVM::Shape::SHAPE_MAX_VARIATIONS}_m")
+ assert_predicate RubyVM::Shape.of(tc), :too_complex?
+ assert_equal nil, tc.iv_not_defined
+ assert_predicate RubyVM::Shape.of(tc), :too_complex?
+ end
+
+ def test_shape_order
+ bar = ShapeOrder.new # 0 => 1
+ bar.set_c # 1 => 2
+ bar.set_b # 2 => 2
+
+ foo = ShapeOrder.new # 0 => 1
+ shape_id = RubyVM::Shape.of(foo).id
+ foo.set_b # should not transition
+ assert_equal shape_id, RubyVM::Shape.of(foo).id
+ end
+
+ def test_iv_index
+ example = RemoveAndAdd.new
+ initial_shape = RubyVM::Shape.of(example)
+ assert_equal 0, initial_shape.next_iv_index
+
+ example.add_foo # makes a transition
+ add_foo_shape = RubyVM::Shape.of(example)
+ assert_equal([:@foo], example.instance_variables)
+ assert_equal(initial_shape.id, add_foo_shape.parent.id)
+ assert_equal(1, add_foo_shape.next_iv_index)
+
+ example.remove_foo # makes a transition
+ remove_foo_shape = RubyVM::Shape.of(example)
+ assert_equal([], example.instance_variables)
+ assert_shape_equal(initial_shape, remove_foo_shape)
+
+ example.add_bar # makes a transition
+ bar_shape = RubyVM::Shape.of(example)
+ assert_equal([:@bar], example.instance_variables)
+ assert_equal(initial_shape.id, bar_shape.parent_id)
+ assert_equal(1, bar_shape.next_iv_index)
+ end
+
+ def test_remove_then_add_again
+ example = RemoveAndAdd.new
+ _initial_shape = RubyVM::Shape.of(example)
+
+ example.add_foo # makes a transition
+ add_foo_shape = RubyVM::Shape.of(example)
+ example.remove_foo # makes a transition
+ example.add_foo # makes a transition
+ assert_shape_equal(add_foo_shape, RubyVM::Shape.of(example))
+ end
+
+ class TestObject; end
+
+ def test_new_obj_has_t_object_shape
+ obj = TestObject.new
+ shape = RubyVM::Shape.of(obj)
+ assert_equal RubyVM::Shape::SHAPE_T_OBJECT, shape.type
+ assert_nil shape.parent
+ end
+
+ def test_str_has_root_shape
+ assert_shape_equal(RubyVM::Shape.root_shape, RubyVM::Shape.of(""))
+ end
+
+ def test_array_has_root_shape
+ assert_shape_equal(RubyVM::Shape.root_shape, RubyVM::Shape.of([]))
+ end
+
+ def test_true_has_special_const_shape_id
+ assert_equal(RubyVM::Shape::SPECIAL_CONST_SHAPE_ID, RubyVM::Shape.of(true).id)
+ end
+
+ def test_nil_has_special_const_shape_id
+ assert_equal(RubyVM::Shape::SPECIAL_CONST_SHAPE_ID, RubyVM::Shape.of(nil).id)
+ end
+
+ def test_root_shape_transition_to_special_const_on_frozen
+ assert_equal(RubyVM::Shape::SPECIAL_CONST_SHAPE_ID, RubyVM::Shape.of([].freeze).id)
+ end
+
+ def test_basic_shape_transition
+ omit "Failing with RJIT for some reason" if defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled?
+ obj = Example.new
+ shape = RubyVM::Shape.of(obj)
+ refute_equal(RubyVM::Shape.root_shape, shape)
+ assert_equal :@a, shape.edge_name
+ assert_equal RubyVM::Shape::SHAPE_IVAR, shape.type
+
+ shape = shape.parent
+ assert_equal RubyVM::Shape::SHAPE_T_OBJECT, shape.type
+ assert_nil shape.parent
+
+ assert_equal(1, obj.instance_variable_get(:@a))
+ end
+
+ def test_different_objects_make_same_transition
+ obj = []
+ obj2 = ""
+ obj.instance_variable_set(:@a, 1)
+ obj2.instance_variable_set(:@a, 1)
+ assert_shape_equal(RubyVM::Shape.of(obj), RubyVM::Shape.of(obj2))
+ end
+
+ def test_duplicating_objects
+ obj = Example.new
+ obj2 = obj.dup
+ assert_shape_equal(RubyVM::Shape.of(obj), RubyVM::Shape.of(obj2))
+ end
+
+ def test_duplicating_too_complex_objects_memory_leak
+ assert_no_memory_leak([], "#{<<~'begin;'}", "#{<<~'end;'}", "[Bug #20162]", rss: true)
+ RubyVM::Shape.exhaust_shapes
+
+ o = Object.new
+ o.instance_variable_set(:@a, 0)
+ begin;
+ 1_000_000.times do
+ o.dup
+ end
+ end;
+ end
+
+ def test_freezing_and_duplicating_object
+ obj = Object.new.freeze
+ obj2 = obj.dup
+ refute_predicate(obj2, :frozen?)
+ # dup'd objects shouldn't be frozen, and the shape should be the
+ # parent shape of the copied object
+ assert_equal(RubyVM::Shape.of(obj).parent.id, RubyVM::Shape.of(obj2).id)
+ end
+
+ def test_freezing_and_duplicating_object_with_ivars
+ obj = Example.new.freeze
+ obj2 = obj.dup
+ refute_predicate(obj2, :frozen?)
+ refute_shape_equal(RubyVM::Shape.of(obj), RubyVM::Shape.of(obj2))
+ assert_equal(obj2.instance_variable_get(:@a), 1)
+ end
+
+ def test_freezing_and_duplicating_string_with_ivars
+ str = "str"
+ str.instance_variable_set(:@a, 1)
+ str.freeze
+ str2 = str.dup
+ refute_predicate(str2, :frozen?)
+ refute_equal(RubyVM::Shape.of(str).id, RubyVM::Shape.of(str2).id)
+ assert_equal(str2.instance_variable_get(:@a), 1)
+ end
+
+ def test_freezing_and_cloning_objects
+ obj = Object.new.freeze
+ obj2 = obj.clone(freeze: true)
+ assert_predicate(obj2, :frozen?)
+ assert_shape_equal(RubyVM::Shape.of(obj), RubyVM::Shape.of(obj2))
+ end
+
+ def test_cloning_with_freeze_option
+ obj = Object.new
+ obj2 = obj.clone(freeze: true)
+ assert_predicate(obj2, :frozen?)
+ refute_shape_equal(RubyVM::Shape.of(obj), RubyVM::Shape.of(obj2))
+ assert_equal(RubyVM::Shape::SHAPE_FROZEN, RubyVM::Shape.of(obj2).type)
+ assert_shape_equal(RubyVM::Shape.of(obj), RubyVM::Shape.of(obj2).parent)
+ end
+
+ def test_freezing_and_cloning_object_with_ivars
+ obj = Example.new.freeze
+ obj2 = obj.clone(freeze: true)
+ assert_predicate(obj2, :frozen?)
+ assert_shape_equal(RubyVM::Shape.of(obj), RubyVM::Shape.of(obj2))
+ assert_equal(obj2.instance_variable_get(:@a), 1)
+ end
+
+ def test_freezing_and_cloning_string
+ str = ("str" + "str").freeze
+ str2 = str.clone(freeze: true)
+ assert_predicate(str2, :frozen?)
+ assert_shape_equal(RubyVM::Shape.of(str), RubyVM::Shape.of(str2))
+ end
+
+ def test_freezing_and_cloning_string_with_ivars
+ str = "str"
+ str.instance_variable_set(:@a, 1)
+ str.freeze
+ str2 = str.clone(freeze: true)
+ assert_predicate(str2, :frozen?)
+ assert_shape_equal(RubyVM::Shape.of(str), RubyVM::Shape.of(str2))
+ assert_equal(str2.instance_variable_get(:@a), 1)
+ end
+
+ def test_out_of_bounds_shape
+ assert_raise ArgumentError do
+ RubyVM::Shape.find_by_id(RubyVM.stat[:next_shape_id])
+ end
+ assert_raise ArgumentError do
+ RubyVM::Shape.find_by_id(-1)
+ end
+ end
+
+ def ensure_complex
+ RubyVM::Shape::SHAPE_MAX_VARIATIONS.times do
+ tc = TooComplex.new
+ tc.send("a#{_1}_m")
+ end
+ end
+end if defined?(RubyVM::Shape)
diff --git a/test/ruby/test_signal.rb b/test/ruby/test_signal.rb
index a62537d59d..7877a35129 100644
--- a/test/ruby/test_signal.rb
+++ b/test/ruby/test_signal.rb
@@ -291,7 +291,8 @@ class TestSignal < Test::Unit::TestCase
if trap = Signal.list['TRAP']
bug9820 = '[ruby-dev:48592] [Bug #9820]'
- status = assert_in_out_err(['-e', 'Process.kill(:TRAP, $$)'])
+ no_core = "Process.setrlimit(Process::RLIMIT_CORE, 0); " if defined?(Process.setrlimit) && defined?(Process::RLIMIT_CORE)
+ status = assert_in_out_err(['-e', "#{no_core}Process.kill(:TRAP, $$)"])
assert_predicate(status, :signaled?, bug9820)
assert_equal(trap, status.termsig, bug9820)
end
@@ -322,49 +323,6 @@ class TestSignal < Test::Unit::TestCase
end;
end
- def test_sigchld_ignore
- skip 'no SIGCHLD' unless Signal.list['CHLD']
- old = trap(:CHLD, 'IGNORE')
- cmd = [ EnvUtil.rubybin, '--disable=gems', '-e' ]
- assert(system(*cmd, 'exit!(0)'), 'no ECHILD')
- IO.pipe do |r, w|
- pid = spawn(*cmd, "STDIN.read", in: r)
- nb = Process.wait(pid, Process::WNOHANG)
- th = Thread.new(Thread.current) do |parent|
- Thread.pass until parent.stop? # wait for parent to Process.wait
- w.close
- end
- assert_raise(Errno::ECHILD) { Process.wait(pid) }
- th.join
- assert_nil nb
- end
-
- IO.pipe do |r, w|
- pids = 3.times.map { spawn(*cmd, 'exit!', out: w) }
- w.close
- zombies = pids.dup
- assert_nil r.read(1), 'children dead'
-
- Timeout.timeout(10) do
- zombies.delete_if do |pid|
- begin
- Process.kill(0, pid)
- false
- rescue Errno::ESRCH
- true
- end
- end while zombies[0]
- end
- assert_predicate zombies, :empty?, 'zombies leftover'
-
- pids.each do |pid|
- assert_raise(Errno::ECHILD) { Process.waitpid(pid) }
- end
- end
- ensure
- trap(:CHLD, old) if Signal.list['CHLD']
- end
-
def test_sigwait_fd_unused
t = EnvUtil.apply_timeout_scale(0.1)
assert_separately([], <<-End)
diff --git a/test/ruby/test_sleep.rb b/test/ruby/test_sleep.rb
index 61002b8b18..991b73ebd5 100644
--- a/test/ruby/test_sleep.rb
+++ b/test/ruby/test_sleep.rb
@@ -4,14 +4,13 @@ require 'etc'
class TestSleep < Test::Unit::TestCase
def test_sleep_5sec
- GC.disable
- start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
- sleep 5
- slept = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
- bottom = 5.0
- assert_operator(slept, :>=, bottom)
- assert_operator(slept, :<=, 6.0, "[ruby-core:18015]: longer than expected")
- ensure
- GC.enable
+ EnvUtil.without_gc do
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
+ sleep 5
+ slept = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
+ bottom = 5.0
+ assert_operator(slept, :>=, bottom)
+ assert_operator(slept, :<=, 6.0, "[ruby-core:18015]: longer than expected")
+ end
end
end
diff --git a/test/ruby/test_sprintf.rb b/test/ruby/test_sprintf.rb
index 7986e9d141..8cf2c63a20 100644
--- a/test/ruby/test_sprintf.rb
+++ b/test/ruby/test_sprintf.rb
@@ -266,8 +266,8 @@ class TestSprintf < Test::Unit::TestCase
# 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) {sprintf("%\0x hello")}
+ assert_raise(ArgumentError) {sprintf("%\nx hello")}
assert_raise(ArgumentError, "[ruby-core:11573]") {sprintf("%.25555555555555555555555555555555555555s", "hello")}
@@ -279,10 +279,9 @@ class TestSprintf < Test::Unit::TestCase
assert_raise_with_message(ArgumentError, /unnumbered\(1\) mixed with numbered/) { sprintf("%1$*d", 3) }
assert_raise_with_message(ArgumentError, /unnumbered\(1\) mixed with numbered/) { sprintf("%1$.*d", 3) }
- verbose, $VERBOSE = $VERBOSE, nil
- assert_nothing_raised { sprintf("", 1) }
- ensure
- $VERBOSE = verbose
+ assert_warning(/too many arguments/) do
+ sprintf("", 1)
+ end
end
def test_float
@@ -362,11 +361,16 @@ class TestSprintf < Test::Unit::TestCase
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("a", sprintf("%c", "a"))
+ assert_equal("a", 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))
+ assert_raise(ArgumentError) { sprintf("%c", -1) }
+ s = sprintf("%c".encode(Encoding::US_ASCII), 0x80)
+ assert_equal("\x80".b, s)
+ assert_predicate(s, :valid_encoding?)
end
def test_string
@@ -507,6 +511,16 @@ class TestSprintf < Test::Unit::TestCase
end
end
+ def test_coderange
+ format_str = "wrong constant name %s"
+ interpolated_str = "\u3042"
+ assert_predicate format_str, :ascii_only?
+ refute_predicate interpolated_str, :ascii_only?
+
+ str = format_str % interpolated_str
+ refute_predicate str, :ascii_only?
+ end
+
def test_named_default
h = Hash.new('world')
assert_equal("hello world", "hello %{location}" % h)
@@ -528,19 +542,4 @@ class TestSprintf < Test::Unit::TestCase
sprintf("%*s", RbConfig::LIMITS["INT_MIN"], "")
end
end
-
- def test_no_hidden_garbage
- skip unless Thread.list.size == 1
-
- fmt = [4, 2, 2].map { |x| "%0#{x}d" }.join('-') # defeats optimization
- ObjectSpace.count_objects(res = {}) # creates strings on first call
- GC.disable
- before = ObjectSpace.count_objects(res)[:T_STRING]
- val = sprintf(fmt, 1970, 1, 1)
- after = ObjectSpace.count_objects(res)[:T_STRING]
- assert_equal before + 1, after, 'only new string is the created one'
- assert_equal '1970-01-01', val
- ensure
- GC.enable
- end
end
diff --git a/test/ruby/test_stack.rb b/test/ruby/test_stack.rb
index 763aeb6bc2..8a78848322 100644
--- a/test/ruby/test_stack.rb
+++ b/test/ruby/test_stack.rb
@@ -18,7 +18,6 @@ class TestStack < Test::Unit::TestCase
env = {}
env['RUBY_FIBER_VM_STACK_SIZE'] = vm_stack_size.to_s if vm_stack_size
env['RUBY_FIBER_MACHINE_STACK_SIZE'] = machine_stack_size.to_s if machine_stack_size
- env['ASAN_OPTIONS'] = ENV['ASAN_OPTIONS'] if ENV['ASAN_OPTIONS']
stdout, stderr, status = EnvUtil.invoke_ruby([env, '-e', script], '', true, true, timeout: 30)
assert(!status.signaled?, FailDesc[status, nil, stderr])
diff --git a/test/ruby/test_string.rb b/test/ruby/test_string.rb
index 12e4b0fe2a..8658097ae4 100644
--- a/test/ruby/test_string.rb
+++ b/test/ruby/test_string.rb
@@ -9,9 +9,6 @@ class TestString < Test::Unit::TestCase
def initialize(*args)
@cls = String
- @aref_re_nth = true
- @aref_re_silent = false
- @aref_slicebang_silent = true
super
end
@@ -80,10 +77,17 @@ class TestString < Test::Unit::TestCase
assert_equal("mystring", str.__send__(:initialize, "mystring", capacity: 1000))
str = S("mystring")
assert_equal("mystring", str.__send__(:initialize, str, capacity: 1000))
+
+ if @cls == String
+ 100.times {
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".
+ __send__(:initialize, capacity: -1)
+ }
+ end
end
def test_initialize_shared
- String.new(str = "mystring" * 10).__send__(:initialize, capacity: str.bytesize)
+ S(str = "mystring" * 10).__send__(:initialize, capacity: str.bytesize)
assert_equal("mystring", str[0, 8])
end
@@ -97,8 +101,10 @@ class TestString < Test::Unit::TestCase
end
def test_initialize_memory_leak
+ return unless @cls == String
+
assert_no_memory_leak([], <<-PREP, <<-CODE, rss: true)
-code = proc {('x'*100000).__send__(:initialize, '')}
+code = proc {('x'*100_000).__send__(:initialize, '')}
1_000.times(&code)
PREP
100_000.times(&code)
@@ -107,8 +113,10 @@ CODE
# Bug #18154
def test_initialize_nofree_memory_leak
+ return unless @cls == String
+
assert_no_memory_leak([], <<-PREP, <<-CODE, rss: true)
-code = proc {0.to_s.__send__(:initialize, capacity: 10000)}
+code = proc {0.to_s.__send__(:initialize, capacity: 100_000)}
1_000.times(&code)
PREP
100_000.times(&code)
@@ -142,14 +150,12 @@ CODE
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
+ 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])
o = Object.new
def o.to_int; 2; end
@@ -195,24 +201,18 @@ CODE
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
+ assert_raise(IndexError) { s[/xyzzy/] = S("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("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" }
s = S("FooBar")
s[S("Foo")] = S("Bar")
@@ -240,23 +240,23 @@ CODE
assert_equal(-1, S("ABCDEF") <=> S("abcdef"))
- assert_nil("foo" <=> Object.new)
+ assert_nil(S("foo") <=> Object.new)
o = Object.new
def o.to_str; "bar"; end
- assert_equal(1, "foo" <=> o)
+ assert_equal(1, S("foo") <=> o)
class << o;remove_method :to_str;end
def o.<=>(x); nil; end
- assert_nil("foo" <=> o)
+ assert_nil(S("foo") <=> o)
class << o;remove_method :<=>;end
def o.<=>(x); 1; end
- assert_equal(-1, "foo" <=> o)
+ assert_equal(-1, S("foo") <=> o)
class << o;remove_method :<=>;end
def o.<=>(x); 2**100; end
- assert_equal(-1, "foo" <=> o)
+ assert_equal(-1, S("foo") <=> o)
end
def test_EQUAL # '=='
@@ -270,10 +270,10 @@ CODE
o = Object.new
def o.to_str; end
def o.==(x); false; end
- assert_equal(false, "foo" == o)
+ assert_equal(false, S("foo") == o)
class << o;remove_method :==;end
def o.==(x); true; end
- assert_equal(true, "foo" == o)
+ assert_equal(true, S("foo") == o)
end
def test_LSHIFT # '<<'
@@ -297,6 +297,9 @@ CODE
assert_raise(RangeError, bug) {S("a".force_encoding(Encoding::UTF_8)) << -1}
assert_raise(RangeError, bug) {S("a".force_encoding(Encoding::UTF_8)) << 0x81308130}
assert_nothing_raised {S("a".force_encoding(Encoding::GB18030)) << 0x81308130}
+
+ s = "\x95".force_encoding(Encoding::SJIS).tap(&:valid_encoding?)
+ assert_predicate(s << 0x5c, :valid_encoding?)
end
def test_MATCH # '=~'
@@ -583,6 +586,8 @@ CODE
assert_equal("foo", s.chomp!("\n"))
s = "foo\r"
assert_equal("foo", s.chomp!("\n"))
+
+ assert_raise(ArgumentError) {String.new.chomp!("", "")}
ensure
$/ = save
$VERBOSE = verbose
@@ -648,15 +653,36 @@ CODE
result << 0x0300
expected = S("\u0300".encode(Encoding::UTF_16LE))
assert_equal(expected, result, bug7090)
- assert_raise(TypeError) { 'foo' << :foo }
- assert_raise(FrozenError) { 'foo'.freeze.concat('bar') }
+ assert_raise(TypeError) { S('foo') << :foo }
+ assert_raise(FrozenError) { S('foo').freeze.concat('bar') }
end
def test_concat_literals
- s="." * 50
+ s=S("." * 50)
assert_equal(Encoding::UTF_8, "#{s}x".encoding)
end
+ def test_string_interpolations_across_size_pools_get_embedded
+ omit if GC::INTERNAL_CONSTANTS[:SIZE_POOL_COUNT] == 1
+
+ require 'objspace'
+ base_slot_size = GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE]
+ small_obj_size = (base_slot_size / 2)
+ large_obj_size = base_slot_size * 2
+
+ a = "a" * small_obj_size
+ b = "a" * large_obj_size
+
+ res = "#{a}, #{b}"
+ dump_res = ObjectSpace.dump(res)
+ dump_orig = ObjectSpace.dump(a)
+ new_slot_size = Integer(dump_res.match(/"slot_size":(\d+)/)[1])
+ orig_slot_size = Integer(dump_orig.match(/"slot_size":(\d+)/)[1])
+
+ assert_match(/"embedded":true/, dump_res)
+ assert_operator(new_slot_size, :>, orig_slot_size)
+ end
+
def test_count
a = S("hello world")
assert_equal(5, a.count(S("lo")))
@@ -664,18 +690,18 @@ CODE
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_equal(5, "abc\u{3042 3044 3046}".count("^a"))
- assert_equal(1, "abc\u{3042 3044 3046}".count("\u3042"))
- assert_equal(5, "abc\u{3042 3044 3046}".count("^\u3042"))
- assert_equal(2, "abc\u{3042 3044 3046}".count("a-z", "^a"))
- assert_equal(0, "abc\u{3042 3044 3046}".count("a", "\u3042"))
- assert_equal(0, "abc\u{3042 3044 3046}".count("\u3042", "a"))
- assert_equal(0, "abc\u{3042 3044 3046}".count("\u3042", "\u3044"))
- assert_equal(4, "abc\u{3042 3044 3046}".count("^a", "^\u3044"))
- assert_equal(4, "abc\u{3042 3044 3046}".count("^\u3044", "^a"))
- assert_equal(4, "abc\u{3042 3044 3046}".count("^\u3042", "^\u3044"))
+ assert_equal(5, S("abc\u{3042 3044 3046}").count("^a"))
+ assert_equal(1, S("abc\u{3042 3044 3046}").count("\u3042"))
+ assert_equal(5, S("abc\u{3042 3044 3046}").count("^\u3042"))
+ assert_equal(2, S("abc\u{3042 3044 3046}").count("a-z", "^a"))
+ assert_equal(0, S("abc\u{3042 3044 3046}").count("a", "\u3042"))
+ assert_equal(0, S("abc\u{3042 3044 3046}").count("\u3042", "a"))
+ assert_equal(0, S("abc\u{3042 3044 3046}").count("\u3042", "\u3044"))
+ assert_equal(4, S("abc\u{3042 3044 3046}").count("^a", "^\u3044"))
+ assert_equal(4, S("abc\u{3042 3044 3046}").count("^\u3044", "^a"))
+ assert_equal(4, S("abc\u{3042 3044 3046}").count("^\u3042", "^\u3044"))
- assert_raise(ArgumentError) { "foo".count }
+ assert_raise(ArgumentError) { S("foo").count }
end
def crypt_supports_des_crypt?
@@ -717,17 +743,17 @@ CODE
assert_equal(S("hell"), S("hello").delete(S("aeiou"), S("^e")))
assert_equal(S("ho"), S("hello").delete(S("ej-m")))
- assert_equal("a".hash, "a\u0101".delete("\u0101").hash, '[ruby-talk:329267]')
- assert_equal(true, "a\u0101".delete("\u0101").ascii_only?)
- assert_equal(true, "a\u3041".delete("\u3041").ascii_only?)
- assert_equal(false, "a\u3041\u3042".delete("\u3041").ascii_only?)
+ assert_equal(S("a").hash, S("a\u0101").delete("\u0101").hash, '[ruby-talk:329267]')
+ assert_equal(true, S("a\u0101").delete("\u0101").ascii_only?)
+ assert_equal(true, S("a\u3041").delete("\u3041").ascii_only?)
+ assert_equal(false, S("a\u3041\u3042").delete("\u3041").ascii_only?)
- assert_equal("a", "abc\u{3042 3044 3046}".delete("^a"))
- assert_equal("bc\u{3042 3044 3046}", "abc\u{3042 3044 3046}".delete("a"))
- assert_equal("\u3042", "abc\u{3042 3044 3046}".delete("^\u3042"))
+ assert_equal("a", S("abc\u{3042 3044 3046}").delete("^a"))
+ assert_equal("bc\u{3042 3044 3046}", S("abc\u{3042 3044 3046}").delete("a"))
+ assert_equal("\u3042", S("abc\u{3042 3044 3046}").delete("^\u3042"))
bug6160 = '[ruby-dev:45374]'
- assert_equal("", '\\'.delete('\\'), bug6160)
+ assert_equal("", S('\\').delete('\\'), bug6160)
end
def test_delete!
@@ -832,10 +858,10 @@ CODE
assert_equal(Encoding::UTF_8, S('"\\u3042"').encode(Encoding::EUC_JP).undump.encoding)
assert_equal("abc".encode(Encoding::UTF_16LE),
- '"a\x00b\x00c\x00".force_encoding("UTF-16LE")'.undump)
+ S('"a\x00b\x00c\x00".force_encoding("UTF-16LE")').undump)
- assert_equal('\#', '"\\\\#"'.undump)
- assert_equal('\#{', '"\\\\\#{"'.undump)
+ assert_equal('\#', S('"\\\\#"').undump)
+ assert_equal('\#{', S('"\\\\\#{"').undump)
assert_raise(RuntimeError) { S('\u3042').undump }
assert_raise(RuntimeError) { S('"\x82\xA0\u3042"'.force_encoding("SJIS")).undump }
@@ -867,10 +893,22 @@ CODE
assert_raise(RuntimeError) { S('"\\"').undump }
assert_raise(RuntimeError) { S(%("\0")).undump }
assert_raise_with_message(RuntimeError, /invalid/) {
- '"\\u{007F}".xxxxxx'.undump
+ S('"\\u{007F}".xxxxxx').undump
}
end
+ def test_undump_gc_compact_stress
+ omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077
+ a = S("Test") << 1 << 2 << 3 << 9 << 13 << 10
+ EnvUtil.under_gc_compact_stress do
+ assert_equal(a, S('"Test\\x01\\x02\\x03\\t\\r\\n"').undump)
+ end
+
+ EnvUtil.under_gc_compact_stress do
+ assert_equal(S("\u{ABCDE 10ABCD}"), S('"\\u{ABCDE 10ABCD}"').undump)
+ end
+ end
+
def test_dup
for frozen in [ false, true ]
a = S("hello")
@@ -883,6 +921,18 @@ CODE
end
end
+ class StringWithIVSet < String
+ def set_iv
+ @foo = 1
+ end
+ end
+
+ def test_ivar_set_after_frozen_dup
+ str = StringWithIVSet.new.freeze
+ str.dup.set_iv
+ assert_raise(FrozenError) { str.set_iv }
+ end
+
def test_each
verbose, $VERBOSE = $VERBOSE, nil
@@ -1047,9 +1097,9 @@ CODE
g = g.encode(enc)
assert_equal g.chars, g.grapheme_clusters
end
- assert_equal ["a", "b", "c"], "abc".b.grapheme_clusters
+ assert_equal ["a", "b", "c"], S("abc").b.grapheme_clusters
- s = "ABC".b
+ s = S("ABC").b
res = []
assert_same s, s.grapheme_clusters {|x| res << x }
assert_equal(3, res.size)
@@ -1058,6 +1108,22 @@ CODE
assert_equal("C", res[2])
end
+ def test_grapheme_clusters_memory_leak
+ assert_no_memory_leak([], "", "#{<<~"begin;"}\n#{<<~'end;'}", "[Bug #todo]", rss: true)
+ begin;
+ str = "hello world".encode(Encoding::UTF_32LE)
+
+ 10_000.times do
+ str.grapheme_clusters
+ end
+ end;
+ end
+
+ def test_byteslice_grapheme_clusters
+ string = "안녕"
+ assert_equal(["안"], string.byteslice(0,4).grapheme_clusters)
+ end
+
def test_each_line
verbose, $VERBOSE = $VERBOSE, nil
@@ -1095,7 +1161,7 @@ CODE
$/ = save
s = nil
- "foo\nbar".each_line(nil) {|s2| s = s2 }
+ S("foo\nbar").each_line(nil) {|s2| s = s2 }
assert_equal("foo\nbar", s)
assert_equal "hello\n", S("hello\nworld").each_line.next
@@ -1103,7 +1169,7 @@ CODE
bug7646 = "[ruby-dev:46827]"
assert_nothing_raised(bug7646) do
- "\n\u0100".each_line("\n") {}
+ S("\n\u0100").each_line("\n") {}
end
ensure
$/ = save
@@ -1117,14 +1183,19 @@ CODE
assert_equal(S("world"), res[1])
res = []
- S("hello\n\n\nworld").each_line(S(''), chomp: true) {|x| res << x}
- assert_equal(S("hello\n"), res[0])
- assert_equal(S("world"), res[1])
+ S("hello\n\n\nworld\n").each_line(S(''), chomp: true) {|x| res << x}
+ assert_equal(S("hello"), res[0])
+ assert_equal(S("world\n"), res[1])
res = []
- S("hello\r\n\r\nworld").each_line(S(''), chomp: true) {|x| res << x}
- assert_equal(S("hello\r\n"), res[0])
- assert_equal(S("world"), res[1])
+ S("hello\r\n\r\nworld\r\n").each_line(S(''), chomp: true) {|x| res << x}
+ assert_equal(S("hello"), res[0])
+ assert_equal(S("world\r\n"), res[1])
+
+ res = []
+ S("hello\r\n\n\nworld").each_line(S(''), chomp: true) {|x| res << x}
+ assert_equal(S("hello"), res[0])
+ assert_equal(S("world"), res[1])
res = []
S("hello!world").each_line(S('!'), chomp: true) {|x| res << x}
@@ -1137,7 +1208,7 @@ CODE
assert_equal(S("a"), res[0])
s = nil
- "foo\nbar".each_line(nil, chomp: true) {|s2| s = s2 }
+ S("foo\nbar").each_line(nil, chomp: true) {|s2| s = s2 }
assert_equal("foo\nbar", s)
assert_equal "hello", S("hello\nworld").each_line(chomp: true).next
@@ -1180,6 +1251,8 @@ CODE
assert_send([S("hello"), :end_with?, S("llo")])
assert_not_send([S("hello"), :end_with?, S("ll")])
assert_send([S("hello"), :end_with?, S("el"), S("lo")])
+ assert_send([S("hello"), :end_with?, S("")])
+ assert_not_send([S("hello"), :end_with?])
bug5536 = '[ruby-core:40623]'
assert_raise(TypeError, bug5536) {S("str").end_with? :not_convertible_to_string}
@@ -1200,9 +1273,14 @@ CODE
S("hello").gsub(/(hell)(.)/) { |s| $1.upcase + S('-') + $2 })
assert_equal(S("<>h<>e<>l<>l<>o<>"), S("hello").gsub(S(''), S('<\0>')))
- assert_equal("z", "abc".gsub(/./, "a" => "z"), "moved from btest/knownbug")
+ assert_equal("z", S("abc").gsub(/./, "a" => "z"), "moved from btest/knownbug")
+
+ assert_raise(ArgumentError) { S("foo").gsub }
+ end
- assert_raise(ArgumentError) { "foo".gsub }
+ def test_gsub_gc_compact_stress
+ omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077
+ EnvUtil.under_gc_compact_stress { assert_equal(S("h<e>ll<o>"), S("hello").gsub(/([aeiou])/, S('<\1>'))) }
end
def test_gsub_encoding
@@ -1248,24 +1326,33 @@ CODE
assert_nil(a.sub!(S('X'), S('Y')))
end
+ def test_gsub_bang_gc_compact_stress
+ omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077
+ EnvUtil.under_gc_compact_stress do
+ a = S("hello")
+ a.gsub!(/([aeiou])/, S('<\1>'))
+ assert_equal(S("h<e>ll<o>"), a)
+ end
+ 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"))
+ assert_equal('azc', S('abc').sub(/b/, "b" => "z"))
+ assert_equal('ac', S('abc').sub(/b/, {}))
+ assert_equal('a1c', S('abc').sub(/b/, "b" => 1))
+ assert_equal('aBc', S('abc').sub(/b/, Hash.new {|h, k| k.upcase }))
+ assert_equal('a[\&]c', S('abc').sub(/b/, "b" => '[\&]'))
+ assert_equal('aBcabc', S('abcabc').sub(/b/, Hash.new {|h, k| h[k] = k.upcase }))
+ assert_equal('aBcdef', S('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"))
+ assert_equal('azc', S('abc').gsub(/b/, "b" => "z"))
+ assert_equal('ac', S('abc').gsub(/b/, {}))
+ assert_equal('a1c', S('abc').gsub(/b/, "b" => 1))
+ assert_equal('aBc', S('abc').gsub(/b/, Hash.new {|h, k| k.upcase }))
+ assert_equal('a[\&]c', S('abc').gsub(/b/, "b" => '[\&]'))
+ assert_equal('aBcaBc', S('abcabc').gsub(/b/, Hash.new {|h, k| h[k] = k.upcase }))
+ assert_equal('aBcDEf', S('abcdef').gsub(/de|b/, "b" => "B", "de" => "DE"))
end
def test_hash
@@ -1275,6 +1362,9 @@ CODE
assert_not_equal(S("a").hash, S("a\0").hash, bug4104)
bug9172 = '[ruby-core:58658] [Bug #9172]'
assert_not_equal(S("sub-setter").hash, S("discover").hash, bug9172)
+ assert_equal(S("").hash, S("".encode(Encoding::UTF_32BE)).hash)
+ h1, h2 = ["\x80", "\x81"].map {|c| c.b.hash ^ c.hash}
+ assert_not_equal(h1, h2)
end
def test_hex
@@ -1295,45 +1385,54 @@ CODE
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_index(0, S("hello"), ?h)
+ assert_index(1, S("hello"), S("ell"))
+ assert_index(2, S("hello"), /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_index(3, S("hello"), ?l, 3)
+ assert_index(3, S("hello"), S("l"), 3)
+ assert_index(3, S("hello"), /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_index(nil, S("hello"), ?z, 3)
+ assert_index(nil, S("hello"), S("z"), 3)
+ assert_index(nil, S("hello"), /z./, 3)
- assert_nil(S("hello").index(?z))
- assert_nil(S("hello").index(S("z")))
- assert_nil(S("hello").index(/z./))
+ assert_index(nil, S("hello"), ?z)
+ assert_index(nil, S("hello"), S("z"))
+ assert_index(nil, S("hello"), /z./)
- assert_equal(0, S("").index(S("")))
- assert_equal(0, S("").index(//))
- assert_nil(S("").index(S("hello")))
- assert_nil(S("").index(/hello/))
- assert_equal(0, S("hello").index(S("")))
- assert_equal(0, S("hello").index(//))
+ assert_index(0, S(""), S(""))
+ assert_index(0, S(""), //)
+ assert_index(nil, S(""), S("hello"))
+ assert_index(nil, S(""), /hello/)
+ assert_index(0, S("hello"), S(""))
+ assert_index(0, S("hello"), //)
s = S("long") * 1000 << "x"
- assert_nil(s.index(S("y")))
- assert_equal(4 * 1000, s.index(S("x")))
+ assert_index(nil, s, S("y"))
+ assert_index(4 * 1000, s, S("x"))
s << "yx"
- assert_equal(4 * 1000, s.index(S("x")))
- assert_equal(4 * 1000, s.index(S("xyx")))
+ assert_index(4 * 1000, s, S("x"))
+ assert_index(4 * 1000, s, S("xyx"))
o = Object.new
def o.to_str; "bar"; end
- assert_equal(3, "foobarbarbaz".index(o))
- assert_raise(TypeError) { "foo".index(Object.new) }
+ assert_index(3, S("foobarbarbaz"), o)
+ assert_raise(TypeError) { S("foo").index(Object.new) }
- assert_nil("foo".index(//, -100))
- assert_nil($~)
+ assert_index(nil, S("foo"), //, -100)
+ assert_index(nil, S("foo"), //, 4)
+
+ assert_index(2, S("abcdbce"), /b\Kc/)
- assert_equal(2, S("abcdbce").index(/b\Kc/))
+ assert_index(0, S("ã“ã‚“ã«ã¡ã¯"), ?ã“)
+ assert_index(1, S("ã“ã‚“ã«ã¡ã¯"), S("ã‚“ã«ã¡"))
+ assert_index(2, S("ã“ã‚“ã«ã¡ã¯"), /ã«ã¡./)
+
+ assert_index(0, S("ã«ã‚“ã«ã¡ã¯"), ?ã«, 0)
+ assert_index(2, S("ã«ã‚“ã«ã¡ã¯"), ?ã«, 1)
+ assert_index(2, S("ã«ã‚“ã«ã¡ã¯"), ?ã«, 2)
+ assert_index(nil, S("ã«ã‚“ã«ã¡ã¯"), ?ã«, 3)
end
def test_insert
@@ -1440,16 +1539,16 @@ CODE
b = a.replace(S("xyz"))
assert_equal(S("xyz"), b)
- s = "foo" * 100
+ s = S("foo") * 100
s2 = ("bar" * 100).dup
s.replace(s2)
assert_equal(s2, s)
- s2 = ["foo"].pack("p")
+ s2 = [S("foo")].pack("p")
s.replace(s2)
assert_equal(s2, s)
- fs = "".freeze
+ fs = S("").freeze
assert_raise(FrozenError) { fs.replace("a") }
assert_raise(FrozenError) { fs.replace(fs) }
assert_raise(ArgumentError) { fs.replace() }
@@ -1480,34 +1579,57 @@ CODE
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_rindex(3, S("hello"), ?l)
+ assert_rindex(6, S("ell, hello"), S("ell"))
+ assert_rindex(7, S("ell, hello"), /ll./)
+
+ assert_rindex(3, S("hello,lo"), ?l, 3)
+ assert_rindex(3, S("hello,lo"), S("l"), 3)
+ assert_rindex(3, S("hello,lo"), /l./, 3)
- 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_rindex(nil, S("hello"), ?z, 3)
+ assert_rindex(nil, S("hello"), S("z"), 3)
+ assert_rindex(nil, S("hello"), /z./, 3)
- assert_nil(S("hello").rindex(?z, 3))
- assert_nil(S("hello").rindex(S("z"), 3))
- assert_nil(S("hello").rindex(/z./, 3))
+ assert_rindex(nil, S("hello"), ?z)
+ assert_rindex(nil, S("hello"), S("z"))
+ assert_rindex(nil, S("hello"), /z./)
- assert_nil(S("hello").rindex(?z))
- assert_nil(S("hello").rindex(S("z")))
- assert_nil(S("hello").rindex(/z./))
+ assert_rindex(5, S("hello"), S(""))
+ assert_rindex(5, S("hello"), S(""), 5)
+ assert_rindex(4, S("hello"), S(""), 4)
+ assert_rindex(0, S("hello"), S(""), 0)
o = Object.new
def o.to_str; "bar"; end
- assert_equal(6, "foobarbarbaz".rindex(o))
- assert_raise(TypeError) { "foo".rindex(Object.new) }
+ assert_rindex(6, S("foobarbarbaz"), o)
+ assert_raise(TypeError) { S("foo").rindex(Object.new) }
- assert_nil("foo".rindex(//, -100))
- assert_nil($~)
+ assert_rindex(nil, S("foo"), //, -100)
+
+ m = assert_rindex(3, S("foo"), //)
+ assert_equal([3, 3], m.offset(0))
+ assert_rindex(3, S("foo"), //, 4)
+
+ assert_rindex(5, S("abcdbce"), /b\Kc/)
+
+ assert_rindex(2, S("ã“ã‚“ã«ã¡ã¯"), ?ã«)
+ assert_rindex(6, S("ã«ã¡ã¯ã€ã“ã‚“ã«ã¡ã¯"), S("ã«ã¡ã¯"))
+ assert_rindex(6, S("ã«ã¡ã¯ã€ã“ã‚“ã«ã¡ã¯"), /ã«ã¡./)
- assert_equal(3, "foo".rindex(//))
- assert_equal([3, 3], $~.offset(0))
+ assert_rindex(6, S("ã«ã¡ã¯ã€ã“ã‚“ã«ã¡ã¯"), S("ã«ã¡ã¯"), 7)
+ assert_rindex(6, S("ã«ã¡ã¯ã€ã“ã‚“ã«ã¡ã¯"), S("ã«ã¡ã¯"), -2)
+ assert_rindex(6, S("ã«ã¡ã¯ã€ã“ã‚“ã«ã¡ã¯"), S("ã«ã¡ã¯"), 6)
+ assert_rindex(6, S("ã«ã¡ã¯ã€ã“ã‚“ã«ã¡ã¯"), S("ã«ã¡ã¯"), -3)
+ assert_rindex(0, S("ã«ã¡ã¯ã€ã“ã‚“ã«ã¡ã¯"), S("ã«ã¡ã¯"), 5)
+ assert_rindex(0, S("ã«ã¡ã¯ã€ã“ã‚“ã«ã¡ã¯"), S("ã«ã¡ã¯"), -4)
+ assert_rindex(0, S("ã«ã¡ã¯ã€ã“ã‚“ã«ã¡ã¯"), S("ã«ã¡ã¯"), 1)
+ assert_rindex(0, S("ã«ã¡ã¯ã€ã“ã‚“ã«ã¡ã¯"), S("ã«ã¡ã¯"), 0)
- assert_equal(5, S("abcdbce").rindex(/b\Kc/))
+ assert_rindex(0, S("ã“ã‚“ã«ã¡ã¯"), S("ã“ã‚“ã«ã¡ã¯"))
+ assert_rindex(nil, S("ã“ã‚“ã«ã¡"), S("ã“ã‚“ã«ã¡ã¯"))
+ assert_rindex(nil, S("ã“"), S("ã“ã‚“ã«ã¡ã¯"))
+ assert_rindex(nil, S(""), S("ã“ã‚“ã«ã¡ã¯"))
end
def test_rjust
@@ -1546,6 +1668,20 @@ CODE
assert_equal(%w[1 2 3], S("a1 a2 a3").scan(/a\K./))
end
+ def test_scan_gc_compact_stress
+ omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077
+ EnvUtil.under_gc_compact_stress { assert_equal([["1a"], ["2b"], ["3c"]], S("1a2b3c").scan(/(\d.)/)) }
+ end
+
+ def test_scan_segv
+ bug19159 = '[Bug #19159]'
+ assert_nothing_raised(Exception, bug19159) do
+ ObjectSpace.each_object(MatchData).to_a
+ "".scan(//)
+ ObjectSpace.each_object(MatchData).to_a.inspect
+ end
+ end
+
def test_size
assert_equal(0, S("").size)
assert_equal(4, S("1234").size)
@@ -1597,20 +1733,11 @@ CODE
assert_equal(S("FooBa"), a)
a = S("FooBar")
- if @aref_slicebang_silent
- assert_nil( a.slice!(6) )
- assert_nil( a.slice!(6r) )
- else
- assert_raise(IndexError) { a.slice!(6) }
- assert_raise(IndexError) { a.slice!(6r) }
- end
+ assert_nil( a.slice!(6) )
+ assert_nil( a.slice!(6r) )
assert_equal(S("FooBar"), a)
- if @aref_slicebang_silent
- assert_nil( a.slice!(-7) )
- else
- assert_raise(IndexError) { a.slice!(-7) }
- end
+ assert_nil( a.slice!(-7) )
assert_equal(S("FooBar"), a)
a = S("FooBar")
@@ -1622,17 +1749,9 @@ CODE
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")
@@ -1644,17 +1763,9 @@ CODE
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")
@@ -1666,17 +1777,9 @@ CODE
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_nil(a.slice!(/xyzzy/))
assert_equal(S("FooBar"), a)
- if @aref_slicebang_silent
- assert_nil(a.slice!(/plugh/))
- else
- assert_raise(IndexError) {a.slice!(/plugh/)}
- end
+ assert_nil(a.slice!(/plugh/))
assert_equal(S("FooBar"), a)
a=S("FooBar")
@@ -1687,7 +1790,8 @@ CODE
assert_equal(S("Bar"), a.slice!(S("Bar")))
assert_equal(S("Foo"), a)
- assert_raise(ArgumentError) { "foo".slice! }
+ a = S("foo")
+ assert_raise(ArgumentError) { a.slice! }
end
def test_split
@@ -1712,7 +1816,7 @@ CODE
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([], S("").split(//, 1))
ensure
EnvUtil.suppress_warning {$; = fs}
end
@@ -1751,16 +1855,18 @@ CODE
result = []; S("a||b|c|").split(S('|'), -1) {|s| result << s}
assert_equal([S("a"), S(""), S("b"), S("c"), S("")], result)
- result = []; "".split(//, 1) {|s| result << s}
+ result = []; S("").split(//, 1) {|s| result << s}
assert_equal([], result)
- result = []; "aaa,bbb,ccc,ddd".split(/,/) {|s| result << s.gsub(/./, "A")}
+ result = []; S("aaa,bbb,ccc,ddd").split(/,/) {|s| result << s.gsub(/./, "A")}
assert_equal(["AAA"]*4, result)
ensure
EnvUtil.suppress_warning {$; = fs}
end
def test_fs
+ return unless @cls == String
+
assert_raise_with_message(TypeError, /\$;/) {
$; = []
}
@@ -1850,25 +1956,46 @@ CODE
assert_send([S("hello"), :start_with?, S("hel")])
assert_not_send([S("hello"), :start_with?, S("el")])
assert_send([S("hello"), :start_with?, S("el"), S("he")])
+ assert_send([S("\xFF\xFE"), :start_with?, S("\xFF")])
+ assert_send([S("hello\xBE"), :start_with?, S("hello")])
+ assert_not_send([S("\u{c4}"), :start_with?, S("\xC3")])
bug5536 = '[ruby-core:40623]'
assert_raise(TypeError, bug5536) {S("str").start_with? :not_convertible_to_string}
+ end
- assert_equal(true, "hello".start_with?(/hel/))
+ def test_start_with_regexp
+ assert_equal(true, S("hello").start_with?(/hel/))
assert_equal("hel", $&)
- assert_equal(false, "hello".start_with?(/el/))
+ assert_equal(false, S("hello").start_with?(/el/))
assert_nil($&)
end
+ def test_start_with_timeout_memory_leak
+ assert_no_memory_leak([], "#{<<~"begin;"}", "#{<<~'end;'}", "[Bug #20653]", rss: true)
+ regex = Regexp.new("^#{"(a*)" * 10_000}x$", timeout: 0.000001)
+ str = "a" * 1_000_000 + "x"
+
+ code = proc do
+ str.start_with?(regex)
+ rescue
+ end
+
+ 10.times(&code)
+ begin;
+ 1_000.times(&code)
+ end;
+ 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)
assert_equal(S("x"), S("\x00x\x00").strip)
assert_equal("0b0 ".force_encoding("UTF-16BE"),
- "\x00 0b0 ".force_encoding("UTF-16BE").strip)
+ S("\x00 0b0 ").force_encoding("UTF-16BE").strip)
assert_equal("0\x000b0 ".force_encoding("UTF-16BE"),
- "0\x000b0 ".force_encoding("UTF-16BE").strip)
+ S("0\x000b0 ").force_encoding("UTF-16BE").strip)
end
def test_strip!
@@ -1933,17 +2060,17 @@ CODE
o = Object.new
def o.to_str; "bar"; end
- assert_equal("fooBARbaz", "foobarbaz".sub(o, "BAR"))
+ assert_equal("fooBARbaz", S("foobarbaz").sub(o, "BAR"))
- assert_raise(TypeError) { "foo".sub(Object.new, "") }
+ assert_raise(TypeError) { S("foo").sub(Object.new, "") }
- assert_raise(ArgumentError) { "foo".sub }
+ assert_raise(ArgumentError) { S("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 })
+ assert_match(/^foo#<Object:0x.*>baz$/, S("foobarbaz").sub("bar") { o })
assert_equal(S("Abc"), S("abc").sub("a", "A"))
m = nil
@@ -1952,10 +2079,20 @@ CODE
assert_equal(/a/, m.regexp)
bug = '[ruby-core:78686] [Bug #13042] other than regexp has no name references'
assert_raise_with_message(IndexError, /oops/, bug) {
- 'hello'.gsub('hello', '\k<oops>')
+ S('hello').gsub('hello', '\k<oops>')
}
end
+ def test_sub_gc_compact_stress
+ omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077
+ EnvUtil.under_gc_compact_stress do
+ m = /&(?<foo>.*?);/.match(S("aaa &amp; yyy"))
+ assert_equal("amp", m["foo"])
+
+ assert_equal("aaa [amp] yyy", S("aaa &amp; yyy").sub(/&(?<foo>.*?);/, S('[\k<foo>]')))
+ end
+ end
+
def test_sub!
a = S("hello")
b = a.dup
@@ -1999,18 +2136,18 @@ CODE
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)
+ assert_equal("abce", S("abcd").succ)
+ assert_equal("THX1139", S("THX1138").succ)
+ assert_equal("<\<koalb>>", S("<\<koala>>").succ)
+ assert_equal("2000aaa", S("1999zzz").succ)
+ assert_equal("AAAA0000", S("ZZZ9999").succ)
+ assert_equal("**+", S("***").succ)
- assert_equal("!", " ".succ)
- assert_equal("", "".succ)
+ assert_equal("!", S(" ").succ)
+ assert_equal("", S("").succ)
bug = '[ruby-core:83062] [Bug #13952]'
- s = "\xff".b
+ s = S("\xff").b
assert_not_predicate(s, :ascii_only?)
assert_predicate(s.succ, :ascii_only?, bug)
end
@@ -2062,8 +2199,8 @@ CODE
assert_equal(S(""), a.succ!)
assert_equal(S(""), a)
- assert_equal("aaaaaaaaaaaa", "zzzzzzzzzzz".succ!)
- assert_equal("aaaaaaaaaaaaaaaaaaaaaaaa", "zzzzzzzzzzzzzzzzzzzzzzz".succ!)
+ assert_equal("aaaaaaaaaaaa", S("zzzzzzzzzzz").succ!)
+ assert_equal("aaaaaaaaaaaaaaaaaaaaaaaa", S("zzzzzzzzzzzzzzzzzzzzzzz").succ!)
end
def test_sum
@@ -2085,8 +2222,8 @@ CODE
end
def test_sum_2
- assert_equal(0, "".sum)
- assert_equal(294, "abc".sum)
+ assert_equal(0, S("").sum)
+ assert_equal(294, S("abc").sum)
check_sum("abc")
check_sum("\x80")
-3.upto(70) {|bits|
@@ -2133,39 +2270,39 @@ CODE
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) }
+ assert_equal(0, S(" 0").to_i)
+ assert_equal(0, S("+0").to_i)
+ assert_equal(0, S("-0").to_i)
+ assert_equal(0, S("--0").to_i)
+ assert_equal(16, S("0x10").to_i(0))
+ assert_equal(16, S("0X10").to_i(0))
+ assert_equal(2, S("0b10").to_i(0))
+ assert_equal(2, S("0B10").to_i(0))
+ assert_equal(8, S("0o10").to_i(0))
+ assert_equal(8, S("0O10").to_i(0))
+ assert_equal(10, S("0d10").to_i(0))
+ assert_equal(10, S("0D10").to_i(0))
+ assert_equal(8, S("010").to_i(0))
+ assert_raise(ArgumentError) { S("010").to_i(-10) }
2.upto(36) {|radix|
- assert_equal(radix, "10".to_i(radix))
- assert_equal(radix**2, "100".to_i(radix))
+ assert_equal(radix, S("10").to_i(radix))
+ assert_equal(radix**2, S("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))
+ assert_raise(ArgumentError) { S("0").to_i(1) }
+ assert_raise(ArgumentError) { S("0").to_i(37) }
+ assert_equal(0, S("z").to_i(10))
+ assert_equal(12, S("1_2").to_i(10))
+ assert_equal(0x40000000, S("1073741824").to_i(10))
+ assert_equal(0x4000000000000000, S("4611686018427387904").to_i(10))
+ assert_equal(1, S("1__2").to_i(10))
+ assert_equal(1, S("1_z").to_i(10))
bug6192 = '[ruby-core:43566]'
- assert_raise(Encoding::CompatibilityError, bug6192) {"0".encode("utf-16be").to_i}
- assert_raise(Encoding::CompatibilityError, bug6192) {"0".encode("utf-16le").to_i}
- assert_raise(Encoding::CompatibilityError, bug6192) {"0".encode("utf-32be").to_i}
- assert_raise(Encoding::CompatibilityError, bug6192) {"0".encode("utf-32le").to_i}
- assert_raise(Encoding::CompatibilityError, bug6192) {"0".encode("iso-2022-jp").to_i}
+ assert_raise(Encoding::CompatibilityError, bug6192) {S("0".encode("utf-16be")).to_i}
+ assert_raise(Encoding::CompatibilityError, bug6192) {S("0".encode("utf-16le")).to_i}
+ assert_raise(Encoding::CompatibilityError, bug6192) {S("0".encode("utf-32be")).to_i}
+ assert_raise(Encoding::CompatibilityError, bug6192) {S("0".encode("utf-32le")).to_i}
+ assert_raise(Encoding::CompatibilityError, bug6192) {S("0".encode("iso-2022-jp")).to_i}
end
def test_to_s
@@ -2197,13 +2334,13 @@ CODE
assert_equal(S("*e**o"), S("hello").tr(S("^aeiou"), S("*")))
assert_equal(S("hal"), S("ibm").tr(S("b-z"), S("a-z")))
- a = "abc".force_encoding(Encoding::US_ASCII)
+ a = S("abc".force_encoding(Encoding::US_ASCII))
assert_equal(Encoding::US_ASCII, a.tr(S("z"), S("\u0101")).encoding, '[ruby-core:22326]')
- assert_equal("a".hash, "a".tr("a", "\u0101").tr("\u0101", "a").hash, '[ruby-core:22328]')
- assert_equal(true, "\u0101".tr("\u0101", "a").ascii_only?)
- assert_equal(true, "\u3041".tr("\u3041", "a").ascii_only?)
- assert_equal(false, "\u3041\u3042".tr("\u3041", "a").ascii_only?)
+ assert_equal("a".hash, S("a").tr("a", "\u0101").tr("\u0101", "a").hash, '[ruby-core:22328]')
+ assert_equal(true, S("\u0101").tr("\u0101", "a").ascii_only?)
+ assert_equal(true, S("\u3041").tr("\u3041", "a").ascii_only?)
+ assert_equal(false, S("\u3041\u3042").tr("\u3041", "a").ascii_only?)
bug6156 = '[ruby-core:43335]'
bug13950 = '[ruby-core:83056] [Bug #13950]'
@@ -2213,6 +2350,8 @@ CODE
assert_not_predicate(str, :ascii_only?)
assert_not_predicate(star, :ascii_only?)
assert_not_predicate(result, :ascii_only?, bug13950)
+
+ assert_equal(S("XYC"), S("ABC").tr("A-AB", "XY"))
end
def test_tr!
@@ -2234,16 +2373,20 @@ CODE
assert_nil(a.tr!(S("B-Z"), S("A-Z")))
assert_equal(S("ibm"), a)
- a = "abc".force_encoding(Encoding::US_ASCII)
+ a = S("abc".force_encoding(Encoding::US_ASCII))
assert_nil(a.tr!(S("z"), S("\u0101")), '[ruby-core:22326]')
assert_equal(Encoding::US_ASCII, a.encoding, '[ruby-core:22326]')
+
+ assert_equal(S("XYC"), S("ABC").tr!("A-AB", "XY"))
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("*")))
- assert_equal("a".hash, "\u0101\u0101".tr_s("\u0101", "a").hash)
- assert_equal(true, "\u3041\u3041".tr("\u3041", "a").ascii_only?)
+ assert_equal("a".hash, S("\u0101\u0101").tr_s("\u0101", "a").hash)
+ assert_equal(true, S("\u3041\u3041").tr("\u3041", "a").ascii_only?)
+
+ assert_equal(S("XYC"), S("ABC").tr_s("A-AB", "XY"))
end
def test_tr_s!
@@ -2256,6 +2399,8 @@ CODE
a = S("hello")
assert_equal(S("h*o"), a.tr_s!(S("el"), S("*")))
assert_equal(S("h*o"), a)
+
+ assert_equal(S("XYC"), S("ABC").tr_s!("A-AB", "XY"))
end
def test_unpack
@@ -2343,6 +2488,7 @@ CODE
assert_equal(S("HELLO"), S("HELLO").upcase)
assert_equal(S("ABC HELLO 123"), S("abc HELLO 123").upcase)
assert_equal(S("H\0""ELLO"), S("H\0""ello").upcase)
+ assert_equal(S("\u{10574}"), S("\u{1059B}").upcase)
end
def test_upcase!
@@ -2416,6 +2562,8 @@ CODE
class S2 < String
end
def test_str_new4
+ return unless @cls == String
+
s = (0..54).to_a.join # length = 100
s2 = S2.new(s[10,90])
s3 = s2[10,80]
@@ -2424,7 +2572,7 @@ CODE
end
def test_rb_str_new4
- s = "a" * 100
+ s = S("a" * 100)
s2 = s[10,90]
assert_equal("a" * 90, s2)
s3 = s2[10,80]
@@ -2442,11 +2590,11 @@ CODE
end
def test_rb_str_to_str
- assert_equal("ab", "a" + StringLike.new("b"))
+ assert_equal("ab", S("a") + StringLike.new("b"))
end
def test_rb_str_shared_replace
- s = "a" * 100
+ s = S("a" * 100)
s.succ!
assert_equal("a" * 99 + "b", s)
s = ""
@@ -2470,12 +2618,12 @@ CODE
def test_times2
s1 = ''
100.times {|n|
- s2 = "a" * n
+ s2 = S("a") * n
assert_equal(s1, s2)
s1 << 'a'
}
- assert_raise(ArgumentError) { "foo" * (-1) }
+ assert_raise(ArgumentError) { S("foo") * (-1) }
end
def test_respond_to
@@ -2483,41 +2631,41 @@ CODE
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)
+ assert_equal(false, S("") == o)
end
def test_match_method
- assert_equal("bar", "foobarbaz".match(/bar/).to_s)
+ assert_equal("bar", S("foobarbaz").match(/bar/).to_s)
o = Regexp.new('foo')
def o.match(x, y, z); x + y + z; end
- assert_equal("foobarbaz", "foo".match(o, "bar", "baz"))
+ assert_equal("foobarbaz", S("foo").match(o, "bar", "baz"))
x = nil
- "foo".match(o, "bar", "baz") {|y| x = y }
+ S("foo").match(o, "bar", "baz") {|y| x = y }
assert_equal("foobarbaz", x)
- assert_raise(ArgumentError) { "foo".match }
+ assert_raise(ArgumentError) { S("foo").match }
end
def test_match_p_regexp
/backref/ =~ 'backref'
# must match here, but not in a separate method, e.g., assert_send,
# to check if $~ is affected or not.
- assert_equal(true, "".match?(//))
+ assert_equal(true, S("").match?(//))
assert_equal(true, :abc.match?(/.../))
- assert_equal(true, 'abc'.match?(/b/))
- assert_equal(true, 'abc'.match?(/b/, 1))
- assert_equal(true, 'abc'.match?(/../, 1))
- assert_equal(true, 'abc'.match?(/../, -2))
- assert_equal(false, 'abc'.match?(/../, -4))
- assert_equal(false, 'abc'.match?(/../, 4))
- assert_equal(true, "\u3042xx".match?(/../, 1))
- assert_equal(false, "\u3042x".match?(/../, 1))
- assert_equal(true, ''.match?(/\z/))
- assert_equal(true, 'abc'.match?(/\z/))
- assert_equal(true, 'Ruby'.match?(/R.../))
- assert_equal(false, 'Ruby'.match?(/R.../, 1))
- assert_equal(false, 'Ruby'.match?(/P.../))
+ assert_equal(true, S('abc').match?(/b/))
+ assert_equal(true, S('abc').match?(/b/, 1))
+ assert_equal(true, S('abc').match?(/../, 1))
+ assert_equal(true, S('abc').match?(/../, -2))
+ assert_equal(false, S('abc').match?(/../, -4))
+ assert_equal(false, S('abc').match?(/../, 4))
+ assert_equal(true, S("\u3042xx").match?(/../, 1))
+ assert_equal(false, S("\u3042x").match?(/../, 1))
+ assert_equal(true, S('').match?(/\z/))
+ assert_equal(true, S('abc').match?(/\z/))
+ assert_equal(true, S('Ruby').match?(/R.../))
+ assert_equal(false, S('Ruby').match?(/R.../, 1))
+ assert_equal(false, S('Ruby').match?(/P.../))
assert_equal('backref', $&)
end
@@ -2525,21 +2673,21 @@ CODE
/backref/ =~ 'backref'
# must match here, but not in a separate method, e.g., assert_send,
# to check if $~ is affected or not.
- assert_equal(true, "".match?(''))
+ assert_equal(true, S("").match?(''))
assert_equal(true, :abc.match?('...'))
- assert_equal(true, 'abc'.match?('b'))
- assert_equal(true, 'abc'.match?('b', 1))
- assert_equal(true, 'abc'.match?('..', 1))
- assert_equal(true, 'abc'.match?('..', -2))
- assert_equal(false, 'abc'.match?('..', -4))
- assert_equal(false, 'abc'.match?('..', 4))
- assert_equal(true, "\u3042xx".match?('..', 1))
- assert_equal(false, "\u3042x".match?('..', 1))
- assert_equal(true, ''.match?('\z'))
- assert_equal(true, 'abc'.match?('\z'))
- assert_equal(true, 'Ruby'.match?('R...'))
- assert_equal(false, 'Ruby'.match?('R...', 1))
- assert_equal(false, 'Ruby'.match?('P...'))
+ assert_equal(true, S('abc').match?('b'))
+ assert_equal(true, S('abc').match?('b', 1))
+ assert_equal(true, S('abc').match?('..', 1))
+ assert_equal(true, S('abc').match?('..', -2))
+ assert_equal(false, S('abc').match?('..', -4))
+ assert_equal(false, S('abc').match?('..', 4))
+ assert_equal(true, S("\u3042xx").match?('..', 1))
+ assert_equal(false, S("\u3042x").match?('..', 1))
+ assert_equal(true, S('').match?('\z'))
+ assert_equal(true, S('abc').match?('\z'))
+ assert_equal(true, S('Ruby').match?('R...'))
+ assert_equal(false, S('Ruby').match?('R...', 1))
+ assert_equal(false, S('Ruby').match?('P...'))
assert_equal('backref', $&)
end
@@ -2559,18 +2707,23 @@ CODE
def test_inspect_nul
bug8290 = '[ruby-core:54458]'
- s = "\0" + "12"
+ s = S("\0") + "12"
assert_equal '"\u000012"', s.inspect, bug8290
- s = "\0".b + "12"
+ s = S("\0".b) + "12"
assert_equal '"\x0012"', s.inspect, bug8290
end
+ def test_inspect_next_line
+ bug16842 = '[ruby-core:98231]'
+ assert_equal '"\\u0085"', 0x85.chr(Encoding::UTF_8).inspect, bug16842
+ 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) }
+ assert_equal(%w(he l lo), S("hello").partition(/l/))
+ assert_equal(%w(he l lo), S("hello").partition("l"))
+ assert_raise(TypeError) { S("hello").partition(1) }
def (hyphen = Object.new).to_str; "-"; end
- assert_equal(%w(foo - bar), "foo-bar".partition(hyphen), '[ruby-core:23540]')
+ assert_equal(%w(foo - bar), S("foo-bar").partition(hyphen), '[ruby-core:23540]')
bug6206 = '[ruby-dev:45441]'
Encoding.list.each do |enc|
@@ -2580,24 +2733,24 @@ CODE
end
assert_equal(["\u30E6\u30FC\u30B6", "@", "\u30C9\u30E1.\u30A4\u30F3"],
- "\u30E6\u30FC\u30B6@\u30C9\u30E1.\u30A4\u30F3".partition(/[@.]/))
+ S("\u30E6\u30FC\u30B6@\u30C9\u30E1.\u30A4\u30F3").partition(/[@.]/))
bug = '[ruby-core:82911]'
- hello = "hello"
+ hello = S("hello")
hello.partition("hi").map(&:upcase!)
assert_equal("hello", hello, bug)
- assert_equal(["", "", "foo"], "foo".partition(/^=*/))
+ assert_equal(["", "", "foo"], S("foo").partition(/^=*/))
assert_equal([S("ab"), S("c"), S("dbce")], S("abcdbce").partition(/b\Kc/))
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) }
+ assert_equal(%w(hel l o), S("hello").rpartition(/l/))
+ assert_equal(%w(hel l o), S("hello").rpartition("l"))
+ assert_raise(TypeError) { S("hello").rpartition(1) }
def (hyphen = Object.new).to_str; "-"; end
- assert_equal(%w(foo - bar), "foo-bar".rpartition(hyphen), '[ruby-core:23540]')
+ assert_equal(%w(foo - bar), S("foo-bar").rpartition(hyphen), '[ruby-core:23540]')
bug6206 = '[ruby-dev:45441]'
Encoding.list.each do |enc|
@@ -2608,7 +2761,7 @@ CODE
bug8138 = '[ruby-dev:47183]'
assert_equal(["\u30E6\u30FC\u30B6@\u30C9\u30E1", ".", "\u30A4\u30F3"],
- "\u30E6\u30FC\u30B6@\u30C9\u30E1.\u30A4\u30F3".rpartition(/[@.]/), bug8138)
+ S("\u30E6\u30FC\u30B6@\u30C9\u30E1.\u30A4\u30F3").rpartition(/[@.]/), bug8138)
bug = '[ruby-core:82911]'
hello = "hello"
@@ -2618,10 +2771,13 @@ CODE
assert_equal([S("abcdb"), S("c"), S("e")], S("abcdbce").rpartition(/b\Kc/))
end
- def test_setter
+ def test_fs_setter
+ return unless @cls == String
+
assert_raise(TypeError) { $/ = 1 }
name = "\u{5206 884c}"
- assert_separately([], <<-"end;") # do
+ assert_separately([], "#{<<~"do;"}\n#{<<~"end;"}")
+ do;
alias $#{name} $/
assert_raise_with_message(TypeError, /\\$#{name}/) { $#{name} = 1 }
end;
@@ -2654,16 +2810,19 @@ CODE
end
def test_gsub_enumerator
- assert_normal_exit %q{"abc".gsub(/./).next}, "[ruby-dev:34828]"
+ e = S("abc").gsub(/./)
+ assert_equal("a", e.next, "[ruby-dev:34828]")
+ assert_equal("b", e.next)
+ assert_equal("c", e.next)
end
def test_clear_nonasciicompat
- assert_equal("", "\u3042".encode("ISO-2022-JP").clear)
+ assert_equal("", S("\u3042".encode("ISO-2022-JP")).clear)
end
def test_try_convert
- assert_equal(nil, String.try_convert(1))
- assert_equal("foo", String.try_convert("foo"))
+ assert_equal(nil, @cls.try_convert(1))
+ assert_equal("foo", @cls.try_convert("foo"))
end
def test_substr_negative_begin
@@ -2672,55 +2831,55 @@ CODE
=begin
def test_compare_different_encoding_string
- s1 = "\xff".force_encoding("UTF-8")
- s2 = "\xff".force_encoding("ISO-2022-JP")
+ s1 = S("\xff".force_encoding("UTF-8"))
+ s2 = S("\xff".force_encoding("ISO-2022-JP"))
assert_equal([-1, 1], [s1 <=> s2, s2 <=> s1].sort)
end
=end
def test_casecmp
- assert_equal(0, "FoO".casecmp("fOO"))
- assert_equal(1, "FoO".casecmp("BaR"))
- assert_equal(-1, "baR".casecmp("FoO"))
- assert_equal(1, "\u3042B".casecmp("\u3042a"))
- assert_equal(-1, "foo".casecmp("foo\0"))
+ assert_equal(0, S("FoO").casecmp("fOO"))
+ assert_equal(1, S("FoO").casecmp("BaR"))
+ assert_equal(-1, S("baR").casecmp("FoO"))
+ assert_equal(1, S("\u3042B").casecmp("\u3042a"))
+ assert_equal(-1, S("foo").casecmp("foo\0"))
- assert_nil("foo".casecmp(:foo))
- assert_nil("foo".casecmp(Object.new))
+ assert_nil(S("foo").casecmp(:foo))
+ assert_nil(S("foo").casecmp(Object.new))
o = Object.new
def o.to_str; "fOO"; end
- assert_equal(0, "FoO".casecmp(o))
+ assert_equal(0, S("FoO").casecmp(o))
end
def test_casecmp?
- assert_equal(true, 'FoO'.casecmp?('fOO'))
- assert_equal(false, 'FoO'.casecmp?('BaR'))
- assert_equal(false, 'baR'.casecmp?('FoO'))
- assert_equal(true, 'äöü'.casecmp?('ÄÖÜ'))
- assert_equal(false, "foo".casecmp?("foo\0"))
+ assert_equal(true, S('FoO').casecmp?('fOO'))
+ assert_equal(false, S('FoO').casecmp?('BaR'))
+ assert_equal(false, S('baR').casecmp?('FoO'))
+ assert_equal(true, S('äöü').casecmp?('ÄÖÜ'))
+ assert_equal(false, S("foo").casecmp?("foo\0"))
- assert_nil("foo".casecmp?(:foo))
- assert_nil("foo".casecmp?(Object.new))
+ assert_nil(S("foo").casecmp?(:foo))
+ assert_nil(S("foo").casecmp?(Object.new))
o = Object.new
def o.to_str; "fOO"; end
- assert_equal(true, "FoO".casecmp?(o))
+ assert_equal(true, S("FoO").casecmp?(o))
end
def test_upcase2
- assert_equal("\u3042AB", "\u3042aB".upcase)
+ assert_equal("\u3042AB", S("\u3042aB").upcase)
end
def test_downcase2
- assert_equal("\u3042ab", "\u3042aB".downcase)
+ assert_equal("\u3042ab", S("\u3042aB").downcase)
end
def test_rstrip
- assert_equal(" hello", " hello ".rstrip)
- assert_equal("\u3042", "\u3042 ".rstrip)
- assert_equal("\u3042", "\u3042\u0000".rstrip)
- assert_raise(Encoding::CompatibilityError) { "\u3042".encode("ISO-2022-JP").rstrip }
+ assert_equal(" hello", S(" hello ").rstrip)
+ assert_equal("\u3042", S("\u3042 ").rstrip)
+ assert_equal("\u3042", S("\u3042\u0000").rstrip)
+ assert_raise(Encoding::CompatibilityError) { S("\u3042".encode("ISO-2022-JP")).rstrip }
end
def test_rstrip_bang
@@ -2744,13 +2903,18 @@ CODE
assert_equal("\u3042", s5.rstrip!)
assert_equal("\u3042", s5)
- assert_raise(Encoding::CompatibilityError) { "\u3042".encode("ISO-2022-JP").rstrip! }
+ assert_raise(Encoding::CompatibilityError) { S("\u3042".encode("ISO-2022-JP")).rstrip! }
+ assert_raise(Encoding::CompatibilityError) { S("abc \x80 ".force_encoding('UTF-8')).rstrip! }
+ assert_raise(Encoding::CompatibilityError) { S("abc\x80 ".force_encoding('UTF-8')).rstrip! }
+ assert_raise(Encoding::CompatibilityError) { S("abc \x80".force_encoding('UTF-8')).rstrip! }
+ assert_raise(Encoding::CompatibilityError) { S("\x80".force_encoding('UTF-8')).rstrip! }
+ assert_raise(Encoding::CompatibilityError) { S(" \x80 ".force_encoding('UTF-8')).rstrip! }
end
def test_lstrip
- assert_equal("hello ", " hello ".lstrip)
- assert_equal("\u3042", " \u3042".lstrip)
- assert_equal("hello ", "\x00hello ".lstrip)
+ assert_equal("hello ", S(" hello ").lstrip)
+ assert_equal("\u3042", S(" \u3042").lstrip)
+ assert_equal("hello ", S("\x00hello ").lstrip)
end
def test_lstrip_bang
@@ -2776,11 +2940,13 @@ CODE
end
- def test_delete_prefix
- assert_raise(TypeError) { 'hello'.delete_prefix(nil) }
- assert_raise(TypeError) { 'hello'.delete_prefix(1) }
- assert_raise(TypeError) { 'hello'.delete_prefix(/hel/) }
+ def test_delete_prefix_type_error
+ assert_raise(TypeError) { S('hello').delete_prefix(nil) }
+ assert_raise(TypeError) { S('hello').delete_prefix(1) }
+ assert_raise(TypeError) { S('hello').delete_prefix(/hel/) }
+ end
+ def test_delete_prefix
s = S("hello")
assert_equal("lo", s.delete_prefix('hel'))
assert_equal("hello", s)
@@ -2800,8 +2966,9 @@ CODE
s = S("hello")
assert_equal("hello", s.delete_prefix("\u{3053 3093}"))
assert_equal("hello", s)
+ end
- # skip if argument is a broken string
+ def test_delete_prefix_broken_encoding
s = S("\xe3\x81\x82")
assert_equal("\xe3\x81\x82", s.delete_prefix("\xe3"))
assert_equal("\xe3\x81\x82", s)
@@ -2810,23 +2977,31 @@ CODE
assert_equal("\x95\x5c".force_encoding("Shift_JIS"), s.delete_prefix("\x95"))
assert_equal("\x95\x5c".force_encoding("Shift_JIS"), s)
- # clear coderange
+ assert_equal("\xFE", S("\xFF\xFE").delete_prefix("\xFF"))
+ assert_equal("\xBE", S("hello\xBE").delete_prefix("hello"))
+ assert_equal("\xBE", S("\xFFhello\xBE").delete_prefix("\xFFhello"))
+ end
+
+ def test_delete_prefix_clear_coderange
s = S("\u{3053 3093}hello")
assert_not_predicate(s, :ascii_only?)
assert_predicate(s.delete_prefix("\u{3053 3093}"), :ascii_only?)
+ end
- # argument should be converted to String
+ def test_delete_prefix_argument_conversion
klass = Class.new { def to_str; 'a'; end }
s = S("abba")
assert_equal("bba", s.delete_prefix(klass.new))
assert_equal("abba", s)
end
- def test_delete_prefix_bang
- assert_raise(TypeError) { 'hello'.delete_prefix!(nil) }
- assert_raise(TypeError) { 'hello'.delete_prefix!(1) }
- assert_raise(TypeError) { 'hello'.delete_prefix!(/hel/) }
+ def test_delete_prefix_bang_type_error
+ assert_raise(TypeError) { S('hello').delete_prefix!(nil) }
+ assert_raise(TypeError) { S('hello').delete_prefix!(1) }
+ assert_raise(TypeError) { S('hello').delete_prefix!(/hel/) }
+ end
+ def test_delete_prefix_bang
s = S("hello")
assert_equal("lo", s.delete_prefix!('hel'))
assert_equal("lo", s)
@@ -2846,23 +3021,32 @@ CODE
s = S("hello")
assert_equal(nil, s.delete_prefix!("\u{3053 3093}"))
assert_equal("hello", s)
+ end
- # skip if argument is a broken string
+ def test_delete_prefix_bang_broken_encoding
s = S("\xe3\x81\x82")
assert_equal(nil, s.delete_prefix!("\xe3"))
assert_equal("\xe3\x81\x82", s)
- # clear coderange
+ s = S("\xFF\xFE")
+ assert_equal("\xFE", s.delete_prefix!("\xFF"))
+ assert_equal("\xFE", s)
+ end
+
+ def test_delete_prefix_bang_clear_coderange
s = S("\u{3053 3093}hello")
assert_not_predicate(s, :ascii_only?)
assert_predicate(s.delete_prefix!("\u{3053 3093}"), :ascii_only?)
+ end
- # argument should be converted to String
+ def test_delete_prefix_bang_argument_conversion
klass = Class.new { def to_str; 'a'; end }
s = S("abba")
assert_equal("bba", s.delete_prefix!(klass.new))
assert_equal("bba", s)
+ end
+ def test_delete_prefix_bang_frozen_error
s = S("ax").freeze
assert_raise_with_message(FrozenError, /frozen/) {s.delete_prefix!("a")}
@@ -2875,11 +3059,13 @@ CODE
assert_raise_with_message(FrozenError, /frozen/) {s.delete_prefix!(o)}
end
- def test_delete_suffix
- assert_raise(TypeError) { 'hello'.delete_suffix(nil) }
- assert_raise(TypeError) { 'hello'.delete_suffix(1) }
- assert_raise(TypeError) { 'hello'.delete_suffix(/hel/) }
+ def test_delete_suffix_type_error
+ assert_raise(TypeError) { S('hello').delete_suffix(nil) }
+ assert_raise(TypeError) { S('hello').delete_suffix(1) }
+ assert_raise(TypeError) { S('hello').delete_suffix(/hel/) }
+ end
+ def test_delete_suffix
s = S("hello")
assert_equal("hel", s.delete_suffix('lo'))
assert_equal("hello", s)
@@ -2899,23 +3085,28 @@ CODE
s = S("hello")
assert_equal("hello", s.delete_suffix("\u{3061 306f}"))
assert_equal("hello", s)
+ end
- # skip if argument is a broken string
+ def test_delete_suffix_broken_encoding
s = S("\xe3\x81\x82")
assert_equal("\xe3\x81\x82", s.delete_suffix("\x82"))
assert_equal("\xe3\x81\x82", s)
+ end
- # clear coderange
+ def test_delete_suffix_clear_coderange
s = S("hello\u{3053 3093}")
assert_not_predicate(s, :ascii_only?)
assert_predicate(s.delete_suffix("\u{3053 3093}"), :ascii_only?)
+ end
- # argument should be converted to String
+ def test_delete_suffix_argument_conversion
klass = Class.new { def to_str; 'a'; end }
s = S("abba")
assert_equal("abb", s.delete_suffix(klass.new))
assert_equal("abba", s)
+ end
+ def test_delete_suffix_newline
# chomp removes any of "\n", "\r\n", "\r" when "\n" is specified,
# but delete_suffix does not
s = "foo\n"
@@ -2926,11 +3117,13 @@ CODE
assert_equal("foo\r", s.delete_suffix("\n"))
end
- def test_delete_suffix_bang
- assert_raise(TypeError) { 'hello'.delete_suffix!(nil) }
- assert_raise(TypeError) { 'hello'.delete_suffix!(1) }
- assert_raise(TypeError) { 'hello'.delete_suffix!(/hel/) }
+ def test_delete_suffix_bang_type_error
+ assert_raise(TypeError) { S('hello').delete_suffix!(nil) }
+ assert_raise(TypeError) { S('hello').delete_suffix!(1) }
+ assert_raise(TypeError) { S('hello').delete_suffix!(/hel/) }
+ end
+ def test_delete_suffix_bang_frozen_error
s = S("hello").freeze
assert_raise_with_message(FrozenError, /frozen/) {s.delete_suffix!('lo')}
@@ -2941,7 +3134,9 @@ CODE
"x"
end
assert_raise_with_message(FrozenError, /frozen/) {s.delete_suffix!(o)}
+ end
+ def test_delete_suffix_bang
s = S("hello")
assert_equal("hel", s.delete_suffix!('lo'))
assert_equal("hel", s)
@@ -2961,8 +3156,9 @@ CODE
s = S("hello")
assert_equal(nil, s.delete_suffix!("\u{3061 306f}"))
assert_equal("hello", s)
+ end
- # skip if argument is a broken string
+ def test_delete_suffix_bang_broken_encoding
s = S("\xe3\x81\x82")
assert_equal(nil, s.delete_suffix!("\x82"))
assert_equal("\xe3\x81\x82", s)
@@ -2970,18 +3166,22 @@ CODE
s = S("\x95\x5c").force_encoding("Shift_JIS")
assert_equal(nil, s.delete_suffix!("\x5c"))
assert_equal("\x95\x5c".force_encoding("Shift_JIS"), s)
+ end
- # clear coderange
+ def test_delete_suffix_bang_clear_coderange
s = S("hello\u{3053 3093}")
assert_not_predicate(s, :ascii_only?)
assert_predicate(s.delete_suffix!("\u{3053 3093}"), :ascii_only?)
+ end
- # argument should be converted to String
+ def test_delete_suffix_bang_argument_conversion
klass = Class.new { def to_str; 'a'; end }
s = S("abba")
assert_equal("abb", s.delete_suffix!(klass.new))
assert_equal("abb", s)
+ end
+ def test_delete_suffix_bang_newline
# chomp removes any of "\n", "\r\n", "\r" when "\n" is specified,
# but delete_suffix does not
s = "foo\n"
@@ -3018,7 +3218,7 @@ CODE
end
def test_shared_force_encoding
- s = "\u{3066}\u{3059}\u{3068}".gsub(//, '')
+ s = S("\u{3066}\u{3059}\u{3068}").gsub(//, '')
h = {}
h[s] = nil
k = h.keys[0]
@@ -3033,16 +3233,16 @@ CODE
def test_ascii_incomat_inspect
bug4081 = '[ruby-core:33283]'
WIDE_ENCODINGS.each do |e|
- assert_equal('"abc"', "abc".encode(e).inspect)
- assert_equal('"\\u3042\\u3044\\u3046"', "\u3042\u3044\u3046".encode(e).inspect)
- assert_equal('"ab\\"c"', "ab\"c".encode(e).inspect, bug4081)
+ assert_equal('"abc"', S("abc".encode(e)).inspect)
+ assert_equal('"\\u3042\\u3044\\u3046"', S("\u3042\u3044\u3046".encode(e)).inspect)
+ assert_equal('"ab\\"c"', S("ab\"c".encode(e)).inspect, bug4081)
end
begin
verbose, $VERBOSE = $VERBOSE, nil
ext = Encoding.default_external
Encoding.default_external = "us-ascii"
$VERBOSE = verbose
- i = "abc\"\\".force_encoding("utf-8").inspect
+ i = S("abc\"\\".force_encoding("utf-8")).inspect
ensure
$VERBOSE = nil
Encoding.default_external = ext
@@ -3053,11 +3253,11 @@ CODE
def test_dummy_inspect
assert_equal('"\e\x24\x42\x22\x4C\x22\x68\e\x28\x42"',
- "\u{ffe2}\u{2235}".encode("cp50220").inspect)
+ S("\u{ffe2}\u{2235}".encode("cp50220")).inspect)
end
def test_prepend
- assert_equal(S("hello world!"), "!".prepend("hello ", "world"))
+ assert_equal(S("hello world!"), S("!").prepend("hello ", "world"))
b = S("ue")
assert_equal(S("ueueue"), b.prepend(b, b))
@@ -3065,7 +3265,7 @@ CODE
def foo.to_str
"b"
end
- assert_equal(S("ba"), "a".prepend(foo))
+ assert_equal(S("ba"), S("a").prepend(foo))
a = S("world")
b = S("hello ")
@@ -3079,34 +3279,34 @@ CODE
end
def test_byteslice
- assert_equal("h", "hello".byteslice(0))
- assert_equal(nil, "hello".byteslice(5))
- assert_equal("o", "hello".byteslice(-1))
- assert_equal(nil, "hello".byteslice(-6))
-
- assert_equal("", "hello".byteslice(0, 0))
- assert_equal("hello", "hello".byteslice(0, 6))
- assert_equal("hello", "hello".byteslice(0, 6))
- assert_equal("", "hello".byteslice(5, 1))
- assert_equal("o", "hello".byteslice(-1, 6))
- assert_equal(nil, "hello".byteslice(-6, 1))
- assert_equal(nil, "hello".byteslice(0, -1))
-
- assert_equal("h", "hello".byteslice(0..0))
- assert_equal("", "hello".byteslice(5..0))
- assert_equal("o", "hello".byteslice(4..5))
- assert_equal(nil, "hello".byteslice(6..0))
- assert_equal("", "hello".byteslice(-1..0))
- assert_equal("llo", "hello".byteslice(-3..5))
-
- assert_equal(u("\x81"), "\u3042".byteslice(1))
- assert_equal(u("\x81\x82"), "\u3042".byteslice(1, 2))
- assert_equal(u("\x81\x82"), "\u3042".byteslice(1..2))
-
- assert_equal(u("\x82")+("\u3042"*9), ("\u3042"*10).byteslice(2, 28))
+ assert_equal("h", S("hello").byteslice(0))
+ assert_equal(nil, S("hello").byteslice(5))
+ assert_equal("o", S("hello").byteslice(-1))
+ assert_equal(nil, S("hello").byteslice(-6))
+
+ assert_equal("", S("hello").byteslice(0, 0))
+ assert_equal("hello", S("hello").byteslice(0, 6))
+ assert_equal("hello", S("hello").byteslice(0, 6))
+ assert_equal("", S("hello").byteslice(5, 1))
+ assert_equal("o", S("hello").byteslice(-1, 6))
+ assert_equal(nil, S("hello").byteslice(-6, 1))
+ assert_equal(nil, S("hello").byteslice(0, -1))
+
+ assert_equal("h", S("hello").byteslice(0..0))
+ assert_equal("", S("hello").byteslice(5..0))
+ assert_equal("o", S("hello").byteslice(4..5))
+ assert_equal(nil, S("hello").byteslice(6..0))
+ assert_equal("", S("hello").byteslice(-1..0))
+ assert_equal("llo", S("hello").byteslice(-3..5))
+
+ assert_equal(u("\x81"), S("\u3042").byteslice(1))
+ assert_equal(u("\x81\x82"), S("\u3042").byteslice(1, 2))
+ assert_equal(u("\x81\x82"), S("\u3042").byteslice(1..2))
+
+ assert_equal(u("\x82")+("\u3042"*9), S("\u3042"*10).byteslice(2, 28))
bug7954 = '[ruby-dev:47108]'
- assert_equal(false, "\u3042".byteslice(0, 2).valid_encoding?, bug7954)
+ assert_equal(false, S("\u3042").byteslice(0, 2).valid_encoding?, bug7954)
assert_equal(false, ("\u3042"*10).byteslice(0, 20).valid_encoding?, bug7954)
end
@@ -3121,6 +3321,8 @@ CODE
end
def test_eq_tilde_can_be_overridden
+ return unless @cls == String
+
assert_separately([], <<-RUBY)
class String
undef =~
@@ -3138,7 +3340,7 @@ CODE
end
def test_regexp_match_subclass
- s = Bug9581.new("abc")
+ s = Bug9581.new(S("abc"))
r = /abc/
assert_equal(:foo, s =~ r)
assert_equal(:foo, s.send(:=~, r))
@@ -3148,6 +3350,7 @@ CODE
def test_LSHIFT_neary_long_max
return unless @cls == String
+
assert_ruby_status([], <<-'end;', '[ruby-core:61886] [Bug #9709]', timeout: 20)
begin
a = "a" * 0x4000_0000
@@ -3159,6 +3362,8 @@ CODE
# enable only when string size range is smaller than memory space
def test_uplus_minus
+ return unless @cls == String
+
str = "foo"
assert_not_predicate(str, :frozen?)
assert_not_predicate(+str, :frozen?)
@@ -3167,7 +3372,11 @@ CODE
assert_same(str, +str)
assert_not_same(str, -str)
- str = "bar".freeze
+ require 'objspace'
+
+ str = "test_uplus_minus_str".freeze
+ assert_includes ObjectSpace.dump(str), '"fstring":true'
+
assert_predicate(str, :frozen?)
assert_not_predicate(+str, :frozen?)
assert_predicate(-str, :frozen?)
@@ -3175,11 +3384,13 @@ CODE
assert_not_same(str, +str)
assert_same(str, -str)
- bar = %w(b a r).join('')
- assert_same(str, -bar, "uminus deduplicates [Feature #13077]")
+ bar = -%w(test uplus minus str).join('_')
+ assert_same(str, bar, "uminus deduplicates [Feature #13077] str: #{ObjectSpace.dump(str)} bar: #{ObjectSpace.dump(bar)}")
end
def test_uminus_frozen
+ return unless @cls == String
+
# embedded
str1 = ("foobar" * 3).freeze
str2 = ("foobar" * 3).freeze
@@ -3196,40 +3407,373 @@ CODE
end
def test_uminus_no_freeze_not_bare
- str = @cls.new("foo")
+ str = S("foo")
assert_instance_of(@cls, -str)
assert_equal(false, str.frozen?)
- str = @cls.new("foo")
+ str = S("foo")
str.instance_variable_set(:@iv, 1)
assert_instance_of(@cls, -str)
assert_equal(false, str.frozen?)
assert_equal(1, str.instance_variable_get(:@iv))
- str = @cls.new("foo")
+ str = S("foo")
assert_instance_of(@cls, -str)
assert_equal(false, str.frozen?)
end
def test_ord
- assert_equal(97, "a".ord)
- assert_equal(97, "abc".ord)
- assert_equal(0x3042, "\u3042\u3043".ord)
- assert_raise(ArgumentError) { "".ord }
+ assert_equal(97, S("a").ord)
+ assert_equal(97, S("abc").ord)
+ assert_equal(0x3042, S("\u3042\u3043").ord)
+ assert_raise(ArgumentError) { S("").ord }
end
def test_chr
- assert_equal("a", "abcde".chr)
- assert_equal("a", "a".chr)
- assert_equal("\u3042", "\u3042\u3043".chr)
- assert_equal('', ''.chr)
+ assert_equal("a", S("abcde").chr)
+ assert_equal("a", S("a").chr)
+ assert_equal("\u3042", S("\u3042\u3043").chr)
+ assert_equal('', S('').chr)
end
def test_substr_code_range
- data = "\xff" + "a"*200
+ data = S("\xff" + "a"*200)
assert_not_predicate(data, :valid_encoding?)
assert_predicate(data[100..-1], :valid_encoding?)
end
+
+ def test_byteindex
+ assert_byteindex(0, S("hello"), ?h)
+ assert_byteindex(1, S("hello"), S("ell"))
+ assert_byteindex(2, S("hello"), /ll./)
+
+ assert_byteindex(3, S("hello"), ?l, 3)
+ assert_byteindex(3, S("hello"), S("l"), 3)
+ assert_byteindex(3, S("hello"), /l./, 3)
+
+ assert_byteindex(nil, S("hello"), ?z, 3)
+ assert_byteindex(nil, S("hello"), S("z"), 3)
+ assert_byteindex(nil, S("hello"), /z./, 3)
+
+ assert_byteindex(nil, S("hello"), ?z)
+ assert_byteindex(nil, S("hello"), S("z"))
+ assert_byteindex(nil, S("hello"), /z./)
+
+ assert_byteindex(0, S(""), S(""))
+ assert_byteindex(0, S(""), //)
+ assert_byteindex(nil, S(""), S("hello"))
+ assert_byteindex(nil, S(""), /hello/)
+ assert_byteindex(0, S("hello"), S(""))
+ assert_byteindex(0, S("hello"), //)
+
+ s = S("long") * 1000 << "x"
+ assert_byteindex(nil, s, S("y"))
+ assert_byteindex(4 * 1000, s, S("x"))
+ s << "yx"
+ assert_byteindex(4 * 1000, s, S("x"))
+ assert_byteindex(4 * 1000, s, S("xyx"))
+
+ o = Object.new
+ def o.to_str; "bar"; end
+ assert_byteindex(3, S("foobarbarbaz"), o)
+ assert_raise(TypeError) { S("foo").byteindex(Object.new) }
+
+ assert_byteindex(nil, S("foo"), //, -100)
+ assert_byteindex(nil, S("foo"), //, -4)
+
+ assert_byteindex(2, S("abcdbce"), /b\Kc/)
+
+ assert_byteindex(0, S("ã“ã‚“ã«ã¡ã¯"), ?ã“)
+ assert_byteindex(3, S("ã“ã‚“ã«ã¡ã¯"), S("ã‚“ã«ã¡"))
+ assert_byteindex(6, S("ã“ã‚“ã«ã¡ã¯"), /ã«ã¡./)
+
+ assert_byteindex(0, S("ã«ã‚“ã«ã¡ã¯"), ?ã«, 0)
+ assert_raise(IndexError) { S("ã«ã‚“ã«ã¡ã¯").byteindex(?ã«, 1) }
+ assert_raise(IndexError) { S("ã«ã‚“ã«ã¡ã¯").byteindex(?ã«, 5) }
+ assert_byteindex(6, S("ã«ã‚“ã«ã¡ã¯"), ?ã«, 6)
+ assert_byteindex(6, S("ã«ã‚“ã«ã¡ã¯"), S("ã«"), 6)
+ assert_byteindex(6, S("ã«ã‚“ã«ã¡ã¯"), /ã«./, 6)
+ assert_raise(IndexError) { S("ã«ã‚“ã«ã¡ã¯").byteindex(?ã«, 7) }
+
+ s = S("foobarbarbaz")
+ assert !1000.times.any? {s.byteindex("", 100_000_000)}
+ end
+
+ def test_byterindex
+ assert_byterindex(3, S("hello"), ?l)
+ assert_byterindex(6, S("ell, hello"), S("ell"))
+ assert_byterindex(7, S("ell, hello"), /ll./)
+
+ assert_byterindex(3, S("hello,lo"), ?l, 3)
+ assert_byterindex(3, S("hello,lo"), S("l"), 3)
+ assert_byterindex(3, S("hello,lo"), /l./, 3)
+
+ assert_byterindex(nil, S("hello"), ?z, 3)
+ assert_byterindex(nil, S("hello"), S("z"), 3)
+ assert_byterindex(nil, S("hello"), /z./, 3)
+
+ assert_byterindex(nil, S("hello"), ?z)
+ assert_byterindex(nil, S("hello"), S("z"))
+ assert_byterindex(nil, S("hello"), /z./)
+
+ assert_byterindex(5, S("hello"), S(""))
+ assert_byterindex(5, S("hello"), S(""), 5)
+ assert_byterindex(4, S("hello"), S(""), 4)
+ assert_byterindex(0, S("hello"), S(""), 0)
+
+ o = Object.new
+ def o.to_str; "bar"; end
+ assert_byterindex(6, S("foobarbarbaz"), o)
+ assert_raise(TypeError) { S("foo").byterindex(Object.new) }
+
+ assert_byterindex(nil, S("foo"), //, -100)
+
+ m = assert_byterindex(3, S("foo"), //)
+ assert_equal([3, 3], m.offset(0))
+ assert_byterindex(3, S("foo"), //, 4)
+
+ assert_byterindex(5, S("abcdbce"), /b\Kc/)
+
+ assert_byterindex(6, S("ã“ã‚“ã«ã¡ã¯"), ?ã«)
+ assert_byterindex(18, S("ã«ã¡ã¯ã€ã“ã‚“ã«ã¡ã¯"), S("ã«ã¡ã¯"))
+ assert_byterindex(18, S("ã«ã¡ã¯ã€ã“ã‚“ã«ã¡ã¯"), /ã«ã¡./)
+
+ assert_raise(IndexError) { S("ã«ã¡ã¯ã€ã“ã‚“ã«ã¡ã¯").byterindex(S("ã«ã¡ã¯"), 19) }
+ assert_raise(IndexError) { S("ã«ã¡ã¯ã€ã“ã‚“ã«ã¡ã¯").byterindex(S("ã«ã¡ã¯"), -2) }
+ assert_byterindex(18, S("ã«ã¡ã¯ã€ã“ã‚“ã«ã¡ã¯"), S("ã«ã¡ã¯"), 18)
+ assert_byterindex(18, S("ã«ã¡ã¯ã€ã“ã‚“ã«ã¡ã¯"), S("ã«ã¡ã¯"), -3)
+ assert_raise(IndexError) { S("ã«ã¡ã¯ã€ã“ã‚“ã«ã¡ã¯").byterindex(S("ã«ã¡ã¯"), 17) }
+ assert_raise(IndexError) { S("ã«ã¡ã¯ã€ã“ã‚“ã«ã¡ã¯").byterindex(S("ã«ã¡ã¯"), -4) }
+ assert_raise(IndexError) { S("ã«ã¡ã¯ã€ã“ã‚“ã«ã¡ã¯").byterindex(S("ã«ã¡ã¯"), 1) }
+ assert_byterindex(0, S("ã«ã¡ã¯ã€ã“ã‚“ã«ã¡ã¯"), S("ã«ã¡ã¯"), 0)
+
+ assert_byterindex(0, S("ã“ã‚“ã«ã¡ã¯"), S("ã“ã‚“ã«ã¡ã¯"))
+ assert_byterindex(nil, S("ã“ã‚“ã«ã¡"), S("ã“ã‚“ã«ã¡ã¯"))
+ assert_byterindex(nil, S("ã“"), S("ã“ã‚“ã«ã¡ã¯"))
+ assert_byterindex(nil, S(""), S("ã“ã‚“ã«ã¡ã¯"))
+ end
+
+ def test_bytesplice
+ assert_bytesplice_raise(IndexError, S("hello"), -6, 0, "bye")
+ assert_bytesplice_result("byehello", S("hello"), -5, 0, "bye")
+ assert_bytesplice_result("byehello", S("hello"), 0, 0, "bye")
+ assert_bytesplice_result("byeello", S("hello"), 0, 1, "bye")
+ assert_bytesplice_result("bye", S("hello"), 0, 5, "bye")
+ assert_bytesplice_result("bye", S("hello"), 0, 6, "bye")
+
+ assert_bytesplice_raise(IndexError, S("hello"), -5, 0, "bye", -4, 0)
+ assert_bytesplice_result("byehello", S("hello"), 0, 0, "bye", 0, 3)
+ assert_bytesplice_result("yehello", S("hello"), 0, 0, "bye", 1, 3)
+ assert_bytesplice_result("yehello", S("hello"), 0, 0, "bye", 1, 2)
+ assert_bytesplice_result("ehello", S("hello"), 0, 0, "bye", 2, 1)
+ assert_bytesplice_result("hello", S("hello"), 0, 0, "bye", 3, 0)
+ assert_bytesplice_result("hello", s = S("hello"), 0, 5, s, 0, 5)
+ assert_bytesplice_result("elloo", s = S("hello"), 0, 4, s, 1, 4)
+ assert_bytesplice_result("llolo", s = S("hello"), 0, 3, s, 2, 3)
+ assert_bytesplice_result("lollo", s = S("hello"), 0, 2, s, 3, 2)
+ assert_bytesplice_result("oello", s = S("hello"), 0, 1, s, 4, 1)
+ assert_bytesplice_result("hhell", s = S("hello"), 1, 4, s, 0, 4)
+ assert_bytesplice_result("hehel", s = S("hello"), 2, 3, s, 0, 3)
+ assert_bytesplice_result("helhe", s = S("hello"), 3, 2, s, 0, 2)
+ assert_bytesplice_result("hellh", s = S("hello"), 4, 1, s, 0, 1)
+
+ assert_bytesplice_raise(RangeError, S("hello"), -6...-6, "bye")
+ assert_bytesplice_result("byehello", S("hello"), -5...-5, "bye")
+ assert_bytesplice_result("byehello", S("hello"), 0...0, "bye")
+ assert_bytesplice_result("byeello", S("hello"), 0..0, "bye")
+ assert_bytesplice_result("byeello", S("hello"), 0...1, "bye")
+ assert_bytesplice_result("byello", S("hello"), 0..1, "bye")
+ assert_bytesplice_result("bye", S("hello"), 0..-1, "bye")
+ assert_bytesplice_result("bye", S("hello"), 0...5, "bye")
+ assert_bytesplice_result("bye", S("hello"), 0...6, "bye")
+ assert_bytesplice_result("llolo", s = S("hello"), 0..2, s, 2..4)
+
+ assert_bytesplice_raise(RangeError, S("hello"), -5...-5, "bye", -6...-6)
+ assert_bytesplice_result("byehello", S("hello"), -5...-5, "bye", 0..-1)
+ assert_bytesplice_result("byehello", S("hello"), 0...0, "bye", 0..-1)
+ assert_bytesplice_result("bhello", S("hello"), 0...0, "bye", 0..0)
+ assert_bytesplice_result("byhello", S("hello"), 0...0, "bye", 0..1)
+ assert_bytesplice_result("byehello", S("hello"), 0...0, "bye", 0..2)
+ assert_bytesplice_result("yehello", S("hello"), 0...0, "bye", 1..2)
+
+ assert_bytesplice_raise(TypeError, S("hello"), 0, "bye")
+
+ assert_bytesplice_raise(IndexError, S("ã“ã‚“ã«ã¡ã¯"), -16, 0, "bye")
+ assert_bytesplice_result("byeã“ã‚“ã«ã¡ã¯", S("ã“ã‚“ã«ã¡ã¯"), -15, 0, "bye")
+ assert_bytesplice_result("byeã“ã‚“ã«ã¡ã¯", S("ã“ã‚“ã«ã¡ã¯"), 0, 0, "bye")
+ assert_bytesplice_raise(IndexError, S("ã“ã‚“ã«ã¡ã¯"), 1, 0, "bye")
+ assert_bytesplice_raise(IndexError, S("ã“ã‚“ã«ã¡ã¯"), 0, 1, "bye")
+ assert_bytesplice_raise(IndexError, S("ã“ã‚“ã«ã¡ã¯"), 0, 2, "bye")
+ assert_bytesplice_result("byeã‚“ã«ã¡ã¯", S("ã“ã‚“ã«ã¡ã¯"), 0, 3, "bye")
+ assert_bytesplice_result("ã“ã‚“ã«ã¡ã¯bye", S("ã“ã‚“ã«ã¡ã¯"), 15, 0, "bye")
+
+ assert_bytesplice_raise(IndexError, S("ã“ã‚“ã«ã¡ã¯"), 0, 0, "ã•ã‚ˆã†ãªã‚‰", -16, 0)
+ assert_bytesplice_result("ã“ã‚“ã«ã¡ã¯ã•ã‚ˆã†ãªã‚‰", S("ã“ã‚“ã«ã¡ã¯"), 15, 0, "ã•ã‚ˆã†ãªã‚‰", 0, 15)
+ assert_bytesplice_result("ã•ã‚ˆã†ãªã‚‰", S("ã“ã‚“ã«ã¡ã¯"), 0, 15, "ã•ã‚ˆã†ãªã‚‰", 0, 15)
+ assert_bytesplice_result("ã•ã‚“ã«ã¡ã¯", S("ã“ã‚“ã«ã¡ã¯"), 0, 3, "ã•ã‚ˆã†ãªã‚‰", 0, 3)
+ assert_bytesplice_result("ã•ã‚ˆã†ã¡ã¯", S("ã“ã‚“ã«ã¡ã¯"), 0, 9, "ã•ã‚ˆã†ãªã‚‰", 0, 9)
+ assert_bytesplice_result("よã†ãªã¡ã¯", S("ã“ã‚“ã«ã¡ã¯"), 0, 9, "ã•ã‚ˆã†ãªã‚‰", 3, 9)
+ assert_bytesplice_result("よã†ã¡ã¯", S("ã“ã‚“ã«ã¡ã¯"), 0, 9, "ã•ã‚ˆã†ãªã‚‰", 3, 6)
+ assert_bytesplice_result("よã†ãªã‚‰ã¡ã¯", S("ã“ã‚“ã«ã¡ã¯"), 0, 9, "ã•ã‚ˆã†ãªã‚‰", 3, 12)
+ assert_bytesplice_raise(IndexError, S("ã“ã‚“ã«ã¡ã¯"), 0, 15, "ã•ã‚ˆã†ãªã‚‰", -16, 0)
+ assert_bytesplice_raise(IndexError, S("ã“ã‚“ã«ã¡ã¯"), 0, 15, "ã•ã‚ˆã†ãªã‚‰", 1, 0)
+ assert_bytesplice_raise(IndexError, S("ã“ã‚“ã«ã¡ã¯"), 0, 15, "ã•ã‚ˆã†ãªã‚‰", 2, 0)
+ assert_bytesplice_raise(IndexError, S("ã“ã‚“ã«ã¡ã¯"), 0, 15, "ã•ã‚ˆã†ãªã‚‰", 0, 1)
+ assert_bytesplice_raise(IndexError, S("ã“ã‚“ã«ã¡ã¯"), 0, 15, "ã•ã‚ˆã†ãªã‚‰", 0, 2)
+ assert_bytesplice_result("ã«ã¡ã¯ã¡ã¯", s = S("ã“ã‚“ã«ã¡ã¯"), 0, 9, s, 6, 9)
+
+ assert_bytesplice_result("", S(""), 0, 0, "")
+ assert_bytesplice_result("xxx", S(""), 0, 0, "xxx")
+
+ assert_bytesplice_raise(ArgumentError, S("hello"), 0, 5, "bye", 0)
+ assert_bytesplice_raise(ArgumentError, S("hello"), 0, 5, "bye", 0..-1)
+ assert_bytesplice_raise(ArgumentError, S("hello"), 0..-1, "bye", 0, 3)
+ end
+
+ def test_append_bytes_into_binary
+ buf = S("".b)
+ assert_equal Encoding::BINARY, buf.encoding
+
+ buf.append_as_bytes(S("hello"))
+ assert_equal "hello".b, buf
+ assert_equal Encoding::BINARY, buf.encoding
+
+ buf.append_as_bytes(S("ã“ã‚“ã«ã¡ã¯"))
+ assert_equal S("helloã“ã‚“ã«ã¡ã¯".b), buf
+ assert_equal Encoding::BINARY, buf.encoding
+ end
+
+ def test_append_bytes_into_utf8
+ buf = S("")
+ assert_equal Encoding::UTF_8, buf.encoding
+
+ buf.append_as_bytes(S("hello"))
+ assert_equal S("hello"), buf
+ assert_equal Encoding::UTF_8, buf.encoding
+ assert_predicate buf, :ascii_only?
+ assert_predicate buf, :valid_encoding?
+
+ buf.append_as_bytes(S("ã“ã‚“ã«ã¡ã¯"))
+ assert_equal S("helloã“ã‚“ã«ã¡ã¯"), buf
+ assert_equal Encoding::UTF_8, buf.encoding
+ refute_predicate buf, :ascii_only?
+ assert_predicate buf, :valid_encoding?
+
+ buf.append_as_bytes(S("\xE2\x82".b))
+ assert_equal S("helloã“ã‚“ã«ã¡ã¯\xE2\x82"), buf
+ assert_equal Encoding::UTF_8, buf.encoding
+ refute_predicate buf, :valid_encoding?
+
+ buf.append_as_bytes(S("\xAC".b))
+ assert_equal S("helloã“ã‚“ã«ã¡ã¯â‚¬"), buf
+ assert_equal Encoding::UTF_8, buf.encoding
+ assert_predicate buf, :valid_encoding?
+ end
+
+ def test_append_bytes_into_utf32
+ buf = S("abc".encode(Encoding::UTF_32LE))
+ assert_equal Encoding::UTF_32LE, buf.encoding
+
+ buf.append_as_bytes("def")
+ assert_equal Encoding::UTF_32LE, buf.encoding
+ refute_predicate buf, :valid_encoding?
+ end
+
+ def test_chilled_string
+ chilled_string = eval('"chilled"')
+
+ assert_not_predicate chilled_string, :frozen?
+
+ assert_not_predicate chilled_string.dup, :frozen?
+ assert_not_predicate chilled_string.clone, :frozen?
+
+ # @+ treat the original string as frozen
+ assert_not_predicate(+chilled_string, :frozen?)
+ assert_not_same chilled_string, +chilled_string
+
+ # @- treat the original string as mutable
+ assert_predicate(-chilled_string, :frozen?)
+ assert_not_same chilled_string, -chilled_string
+ end
+
+ def test_chilled_string_setivar
+ deprecated = Warning[:deprecated]
+ Warning[:deprecated] = false
+
+ String.class_eval <<~RUBY, __FILE__, __LINE__ + 1
+ def setivar!
+ @ivar = 42
+ @ivar
+ end
+ RUBY
+ chilled_string = eval('"chilled"')
+ begin
+ assert_equal 42, chilled_string.setivar!
+ ensure
+ String.undef_method(:setivar!)
+ end
+ ensure
+ Warning[:deprecated] = deprecated
+ end
+
+ def test_chilled_string_substring
+ deprecated = Warning[:deprecated]
+ Warning[:deprecated] = false
+ chilled_string = eval('"a chilled string."')
+ substring = chilled_string[0..-1]
+ assert_equal("a chilled string.", substring)
+ chilled_string[0..-1] = "This string is defrosted."
+ assert_equal("a chilled string.", substring)
+ ensure
+ Warning[:deprecated] = deprecated
+ end
+
+ private
+
+ def assert_bytesplice_result(expected, s, *args)
+ assert_equal(expected, s.send(:bytesplice, *args))
+ assert_equal(expected, s)
+ end
+
+ def assert_bytesplice_raise(e, s, *args)
+ assert_raise(e) { s.send(:bytesplice, *args) }
+ end
+
+ def assert_index_like(method, expected, string, match, *rest)
+ message = "#{method} with string does not affect $~"
+ /.*/ =~ message
+ md_before = $~
+ assert_equal(expected, string.__send__(method, match, *rest))
+ md_after = $~
+ case match
+ when Regexp
+ if expected
+ assert_not_nil(md_after)
+ assert_not_same(md_before, md_after)
+ else
+ assert_nil(md_after)
+ end
+ else
+ assert_same(md_before, md_after)
+ end
+ md_after
+ end
+
+ def assert_index(expected, string, match, *rest)
+ assert_index_like(:index, expected, string, match, *rest)
+ end
+
+ def assert_rindex(expected, string, match, *rest)
+ assert_index_like(:rindex, expected, string, match, *rest)
+ end
+
+ def assert_byteindex(expected, string, match, *rest)
+ assert_index_like(:byteindex, expected, string, match, *rest)
+ end
+
+ def assert_byterindex(expected, string, match, *rest)
+ assert_index_like(:byterindex, expected, string, match, *rest)
+ end
end
class TestString2 < TestString
diff --git a/test/ruby/test_string_memory.rb b/test/ruby/test_string_memory.rb
new file mode 100644
index 0000000000..a93a3bd54a
--- /dev/null
+++ b/test/ruby/test_string_memory.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: false
+require 'test/unit'
+require 'objspace'
+
+class TestStringMemory < Test::Unit::TestCase
+ def capture_allocations(klass)
+ allocations = []
+
+ EnvUtil.without_gc do
+ GC.start
+ generation = GC.count
+
+ ObjectSpace.trace_object_allocations do
+ yield
+
+ ObjectSpace.each_object(klass) do |instance|
+ allocations << instance if ObjectSpace.allocation_generation(instance) == generation
+ end
+ end
+
+ return allocations.map do |instance|
+ [
+ ObjectSpace.allocation_sourcefile(instance),
+ ObjectSpace.allocation_sourceline(instance),
+ instance.class,
+ instance,
+ ]
+ end.select do |path,|
+ # drop strings not created in this file
+ # (the parallel testing framework may create strings in a separate thread)
+ path == __FILE__
+ end
+ end
+ end
+
+ def test_byteslice_prefix
+ string = ("a" * 100_000).freeze
+
+ allocations = capture_allocations(String) do
+ string.byteslice(0, 50_000)
+ end
+
+ assert_equal 1, allocations.size, "One object allocation is expected, but allocated: #{ allocations.inspect }"
+ end
+
+ def test_byteslice_postfix
+ string = ("a" * 100_000).freeze
+
+ allocations = capture_allocations(String) do
+ string.byteslice(50_000, 100_000)
+ end
+
+ assert_equal 1, allocations.size, "One object allocation is expected, but allocated: #{ allocations.inspect }"
+ end
+
+ def test_byteslice_postfix_twice
+ string = ("a" * 100_000).freeze
+
+ allocations = capture_allocations(String) do
+ string.byteslice(50_000, 100_000).byteslice(25_000, 50_000)
+ end
+
+ assert_equal 2, allocations.size, "Two object allocations are expected, but allocated: #{ allocations.inspect }"
+ end
+end
diff --git a/test/ruby/test_struct.rb b/test/ruby/test_struct.rb
index 19577266c7..3d727adf04 100644
--- a/test/ruby/test_struct.rb
+++ b/test/ruby/test_struct.rb
@@ -41,6 +41,14 @@ module TestStruct
end
end
+ def test_larger_than_largest_pool
+ count = (GC::INTERNAL_CONSTANTS[:RVARGC_MAX_ALLOCATE_SIZE] / RbConfig::SIZEOF["void*"]) + 1
+ list = Array(0..count)
+ klass = @Struct.new(*list.map { |i| :"a_#{i}"})
+ struct = klass.new(*list)
+ assert_equal 0, struct.a_0
+ end
+
def test_small_structs
names = [:a, :b, :c, :d]
1.upto(4) {|n|
@@ -100,8 +108,9 @@ module TestStruct
assert_equal([:utime, :stime, :cutime, :cstime], Process.times.members)
end
- def test_struct_new_with_empty_hash
- assert_equal({:a=>1}, Struct.new(:a, {}).new({:a=>1}).a)
+ def test_struct_new_with_hash
+ assert_raise_with_message(TypeError, /not a symbol/) {Struct.new(:a, {})}
+ assert_raise_with_message(TypeError, /not a symbol/) {Struct.new(:a, {name: "b"})}
end
def test_struct_new_with_keyword_init
@@ -362,9 +371,8 @@ module TestStruct
end
def test_keyword_args_warning
- warning = /warning: Passing only keyword arguments to Struct#initialize will behave differently from Ruby 3\.2\./
- assert_warn(warning) { assert_equal({a: 1}, @Struct.new(:a).new(a: 1).a) }
- assert_warn(warning) { assert_equal({a: 1}, @Struct.new(:a, keyword_init: nil).new(a: 1).a) }
+ assert_warn('') { assert_equal(1, @Struct.new(:a).new(a: 1).a) }
+ assert_warn('') { assert_equal(1, @Struct.new(:a, keyword_init: nil).new(a: 1).a) }
assert_warn('') { assert_equal({a: 1}, @Struct.new(:a).new({a: 1}).a) }
assert_warn('') { assert_equal({a: 1}, @Struct.new(:a, :b).new(1, a: 1).b) }
assert_warn('') { assert_equal(1, @Struct.new(:a, keyword_init: true).new(a: 1).a) }
@@ -489,6 +497,57 @@ module TestStruct
}
end
+ def test_public_send
+ klass = @Struct.new(:a)
+ x = klass.new(1)
+ assert_equal(1, x.public_send("a"))
+ assert_equal(42, x.public_send("a=", 42))
+ assert_equal(42, x.public_send("a"))
+ end
+
+ def test_arity
+ klass = @Struct.new(:a)
+ assert_equal 0, klass.instance_method(:a).arity
+ assert_equal 1, klass.instance_method(:a=).arity
+
+ klass.module_eval do
+ define_method(:b=, instance_method(:a=))
+ alias c= a=
+ end
+
+ assert_equal 1, klass.instance_method(:b=).arity
+ assert_equal 1, klass.instance_method(:c=).arity
+ end
+
+ def test_parameters
+ klass = @Struct.new(:a)
+ assert_equal [], klass.instance_method(:a).parameters
+ # NOTE: :_ may not be a spec.
+ assert_equal [[:req, :_]], klass.instance_method(:a=).parameters
+
+ klass.module_eval do
+ define_method(:b=, instance_method(:a=))
+ alias c= a=
+ end
+
+ assert_equal [[:req, :_]], klass.instance_method(:b=).parameters
+ assert_equal [[:req, :_]], klass.instance_method(:c=).parameters
+ end
+
+ def test_named_structs_are_not_rooted
+ # [Bug #20311]
+ assert_no_memory_leak([], <<~PREP, <<~CODE, rss: true)
+ code = proc do
+ Struct.new("A")
+ Struct.send(:remove_const, :A)
+ end
+
+ 1_000.times(&code)
+ PREP
+ 50_000.times(&code)
+ CODE
+ end
+
class TopStruct < Test::Unit::TestCase
include TestStruct
diff --git a/test/ruby/test_super.rb b/test/ruby/test_super.rb
index d94f4679d3..418f293f66 100644
--- a/test/ruby/test_super.rb
+++ b/test/ruby/test_super.rb
@@ -8,6 +8,7 @@ class TestSuper < Test::Unit::TestCase
def array(*a) a end
def optional(a = 0) a end
def keyword(**a) a end
+ def forward(*a) a end
end
class Single1 < Base
def single(*) super end
@@ -63,6 +64,16 @@ class TestSuper < Test::Unit::TestCase
[x, y]
end
end
+ class Forward < Base
+ def forward(...)
+ w = super()
+ x = super
+ y = super(...)
+ a = 1
+ z = super(a, ...)
+ [w, x, y, z]
+ end
+ end
def test_single1
assert_equal(1, Single1.new.single(1))
@@ -133,6 +144,11 @@ class TestSuper < Test::Unit::TestCase
def test_keyword2
assert_equal([{foo: "changed1"}, {foo: "changed2"}], Keyword2.new.keyword)
end
+ def test_forwardable(...)
+ assert_equal([[],[],[],[1]], Forward.new.forward())
+ assert_equal([[],[1,2],[1,2],[1,1,2]], Forward.new.forward(1,2))
+ assert_equal([[],[:test],[:test],[1,:test]], Forward.new.forward(:test, ...))
+ end
class A
def tt(aa)
@@ -521,6 +537,55 @@ class TestSuper < Test::Unit::TestCase
assert_equal(%w[B A], result, bug9721)
end
+ # [Bug #18329]
+ def test_super_missing_prepended_module
+ a = Module.new do
+ def probe(*methods)
+ prepend(probing_module(methods))
+ end
+
+ def probing_module(methods)
+ Module.new do
+ methods.each do |method|
+ define_method(method) do |*args, **kwargs, &block|
+ super(*args, **kwargs, &block)
+ end
+ end
+ end
+ end
+ end
+
+ b = Class.new do
+ extend a
+
+ probe :danger!, :missing
+
+ def danger!; end
+ end
+
+ o = b.new
+ o.danger!
+ begin
+ original_gc_stress = GC.stress
+ GC.stress = true
+ 2.times { o.missing rescue NoMethodError }
+ ensure
+ GC.stress = original_gc_stress
+ end
+ end
+
+ def test_zsuper_kw_splat_not_mutable
+ extend(Module.new{def a(**k) k[:a] = 1 end})
+ extend(Module.new do
+ def a(**k)
+ before = k.dup
+ super
+ [before, k]
+ end
+ end)
+ assert_equal(*a)
+ end
+
def test_from_eval
bug10263 = '[ruby-core:65122] [Bug #10263a]'
a = Class.new do
@@ -568,6 +633,35 @@ class TestSuper < Test::Unit::TestCase
}
end
+ def test_super_with_included_prepended_module_method_caching_bug_20716
+ a = Module.new do
+ def test(*args)
+ super
+ end
+ end
+
+ b = Module.new do
+ def test(a)
+ a
+ end
+ end
+
+ c = Class.new
+
+ b.prepend(a)
+ c.include(b)
+
+ assert_equal(1, c.new.test(1))
+
+ b.class_eval do
+ def test
+ :test
+ end
+ end
+
+ assert_equal(:test, c.new.test)
+ end
+
class TestFor_super_with_modified_rest_parameter_base
def foo *args
args
diff --git a/test/ruby/test_symbol.rb b/test/ruby/test_symbol.rb
index f7f17b8d67..c50febf5d1 100644
--- a/test/ruby/test_symbol.rb
+++ b/test/ruby/test_symbol.rb
@@ -36,6 +36,19 @@ class TestSymbol < Test::Unit::TestCase
assert_eval_inspected(:"@@1", false)
assert_eval_inspected(:"@", false)
assert_eval_inspected(:"@@", false)
+ assert_eval_inspected(:"[]=")
+ assert_eval_inspected(:"[][]", false)
+ assert_eval_inspected(:"[][]=", false)
+ assert_eval_inspected(:"@=", false)
+ assert_eval_inspected(:"@@=", false)
+ assert_eval_inspected(:"@x=", false)
+ assert_eval_inspected(:"@@x=", false)
+ assert_eval_inspected(:"$$=", false)
+ assert_eval_inspected(:"$==", false)
+ assert_eval_inspected(:"$x=", false)
+ assert_eval_inspected(:"$$$=", false)
+ assert_eval_inspected(:"foo?=", false)
+ assert_eval_inspected(:"foo!=", false)
end
def assert_inspect_evaled(n)
@@ -77,12 +90,15 @@ class TestSymbol < Test::Unit::TestCase
end
def test_inspect_dollar
+ verbose_bak, $VERBOSE = $VERBOSE, nil
# 4) :$- always treats next character literally:
assert_raise(SyntaxError) {eval ':$-'}
assert_raise(SyntaxError) {eval ":$-\n"}
assert_raise(SyntaxError) {eval ":$- "}
assert_raise(SyntaxError) {eval ":$-#"}
assert_raise(SyntaxError) {eval ':$-('}
+ ensure
+ $VERBOSE = verbose_bak
end
def test_inspect_number
@@ -105,6 +121,14 @@ class TestSymbol < Test::Unit::TestCase
end
end
+ def test_inspect_under_gc_compact_stress
+ omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077
+
+ EnvUtil.under_gc_compact_stress do
+ assert_inspect_evaled(':testing')
+ end
+ end
+
def test_name
assert_equal("foo", :foo.name)
assert_same(:foo.name, :foo.name)
diff --git a/test/ruby/test_syntax.rb b/test/ruby/test_syntax.rb
index 8aa169ac0c..5c341a69b7 100644
--- a/test/ruby/test_syntax.rb
+++ b/test/ruby/test_syntax.rb
@@ -13,8 +13,7 @@ class TestSyntax < Test::Unit::TestCase
def assert_syntax_files(test)
srcdir = File.expand_path("../../..", __FILE__)
srcdir = File.join(srcdir, test)
- assert_separately(%W[--disable-gem - #{srcdir}],
- __FILE__, __LINE__, <<-'eom', timeout: Float::INFINITY)
+ assert_separately(%W[- #{srcdir}], __FILE__, __LINE__, <<-'eom', timeout: Float::INFINITY)
dir = ARGV.shift
for script in Dir["#{dir}/**/*.rb"].sort
assert_valid_syntax(IO::read(script), script)
@@ -66,6 +65,134 @@ class TestSyntax < Test::Unit::TestCase
f&.close!
end
+ def test_script_lines_encoding
+ require 'tmpdir'
+ Dir.mktmpdir do |dir|
+ File.write(File.join(dir, "script_lines.rb"), "SCRIPT_LINES__ = {}\n")
+ assert_in_out_err(%w"-r./script_lines -w -Ke", "puts __ENCODING__.name",
+ %w"EUC-JP", /-K is specified/, chdir: dir)
+ end
+ end
+
+ def test_anonymous_block_forwarding
+ assert_syntax_error("def b; c(&); end", /no anonymous block parameter/)
+ assert_syntax_error("def b(&) ->(&) {c(&)} end", /anonymous block parameter is also used/)
+ assert_valid_syntax("def b(&) ->() {c(&)} end")
+ assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
+ begin;
+ def b(&); c(&) end
+ def c(&); yield 1 end
+ a = nil
+ b{|c| a = c}
+ assert_equal(1, a)
+
+ def inner
+ yield
+ end
+
+ def block_only(&)
+ inner(&)
+ end
+ assert_equal(1, block_only{1})
+
+ def pos(arg1, &)
+ inner(&)
+ end
+ assert_equal(2, pos(nil){2})
+
+ def pos_kwrest(arg1, **kw, &)
+ inner(&)
+ end
+ assert_equal(3, pos_kwrest(nil){3})
+
+ def no_kw(arg1, **nil, &)
+ inner(&)
+ end
+ assert_equal(4, no_kw(nil){4})
+
+ def rest_kw(*a, kwarg: 1, &)
+ inner(&)
+ end
+ assert_equal(5, rest_kw{5})
+
+ def kw(kwarg:1, &)
+ inner(&)
+ end
+ assert_equal(6, kw{6})
+
+ def pos_kw_kwrest(arg1, kwarg:1, **kw, &)
+ inner(&)
+ end
+ assert_equal(7, pos_kw_kwrest(nil){7})
+
+ def pos_rkw(arg1, kwarg1:, &)
+ inner(&)
+ end
+ assert_equal(8, pos_rkw(nil, kwarg1: nil){8})
+
+ def all(arg1, arg2, *rest, post1, post2, kw1: 1, kw2: 2, okw1:, okw2:, &)
+ inner(&)
+ end
+ assert_equal(9, all(nil, nil, nil, nil, okw1: nil, okw2: nil){9})
+
+ def all_kwrest(arg1, arg2, *rest, post1, post2, kw1: 1, kw2: 2, okw1:, okw2:, **kw, &)
+ inner(&)
+ end
+ assert_equal(10, all_kwrest(nil, nil, nil, nil, okw1: nil, okw2: nil){10})
+ end;
+ end
+
+ def test_anonymous_rest_forwarding
+ assert_syntax_error("def b; c(*); end", /no anonymous rest parameter/)
+ assert_syntax_error("def b; c(1, *); end", /no anonymous rest parameter/)
+ assert_syntax_error("def b(*) ->(*) {c(*)} end", /anonymous rest parameter is also used/)
+ assert_syntax_error("def b(a, *) ->(*) {c(1, *)} end", /anonymous rest parameter is also used/)
+ assert_syntax_error("def b(*) ->(a, *) {c(*)} end", /anonymous rest parameter is also used/)
+ assert_valid_syntax("def b(*) ->() {c(*)} end")
+ assert_valid_syntax("def b(a, *) ->() {c(1, *)} end")
+ assert_valid_syntax("def b(*) ->(a) {c(*)} end")
+ assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
+ begin;
+ def b(*); c(*) end
+ def c(*a); a end
+ def d(*); b(*, *) end
+ assert_equal([1, 2], b(1, 2))
+ assert_equal([1, 2, 1, 2], d(1, 2))
+ end;
+ end
+
+ def test_anonymous_keyword_rest_forwarding
+ assert_syntax_error("def b; c(**); end", /no anonymous keyword rest parameter/)
+ assert_syntax_error("def b; c(k: 1, **); end", /no anonymous keyword rest parameter/)
+ assert_syntax_error("def b(**) ->(**) {c(**)} end", /anonymous keyword rest parameter is also used/)
+ assert_syntax_error("def b(k:, **) ->(**) {c(k: 1, **)} end", /anonymous keyword rest parameter is also used/)
+ assert_syntax_error("def b(**) ->(k:, **) {c(**)} end", /anonymous keyword rest parameter is also used/)
+ assert_valid_syntax("def b(**) ->() {c(**)} end")
+ assert_valid_syntax("def b(k:, **) ->() {c(k: 1, **)} end")
+ assert_valid_syntax("def b(**) ->(k:) {c(**)} end")
+ assert_separately([], "#{<<-"begin;"}\n#{<<-'end;'}")
+ begin;
+ def b(**); c(**) end
+ def c(**kw); kw end
+ def d(**); b(k: 1, **) end
+ def e(**); b(**, k: 1) end
+ def f(a: nil, **); b(**) end
+ assert_equal({a: 1, k: 3}, b(a: 1, k: 3))
+ assert_equal({a: 1, k: 3}, d(a: 1, k: 3))
+ assert_equal({a: 1, k: 1}, e(a: 1, k: 3))
+ assert_equal({k: 3}, f(a: 1, k: 3))
+ end;
+ end
+
+ def test_argument_forwarding_with_anon_rest_kwrest_and_block
+ assert_syntax_error("def f(*, **, &); g(...); end", /unexpected \.\.\./)
+ assert_syntax_error("def f(...); g(*); end", /no anonymous rest parameter/)
+ assert_syntax_error("def f(...); g(0, *); end", /no anonymous rest parameter/)
+ assert_syntax_error("def f(...); g(**); end", /no anonymous keyword rest parameter/)
+ assert_syntax_error("def f(...); g(x: 1, **); end", /no anonymous keyword rest parameter/)
+ assert_syntax_error("def f(...); g(&); end", /no anonymous block parameter/)
+ end
+
def test_newline_in_block_parameters
bug = '[ruby-dev:45292]'
["", "a", "a, b"].product(["", ";x", [";", "x"]]) do |params|
@@ -81,7 +208,7 @@ class TestSyntax < Test::Unit::TestCase
blocks = [['do end', 'do'], ['{}', 'brace']],
*|
[%w'. dot', %w':: colon'].product(methods, blocks) do |(c, n1), (m, n2), (b, n3)|
- m = m.tr_s('()', ' ').strip if n2 == 'do'
+ m = m.tr_s('()', ' ').strip if n3 == 'do'
name = "test_#{n3}_block_after_blockcall_#{n1}_#{n2}_arg"
code = "#{blockcall}#{c}#{m} #{b}"
define_method(name) {assert_valid_syntax(code, bug6115)}
@@ -107,6 +234,7 @@ class TestSyntax < Test::Unit::TestCase
def test_array_kwsplat_hash
kw = {}
h = {a: 1}
+ a = []
assert_equal([], [**{}])
assert_equal([], [**kw])
assert_equal([h], [**h])
@@ -121,6 +249,20 @@ class TestSyntax < Test::Unit::TestCase
assert_equal([1, kw], [1, kw])
assert_equal([1, h], [1, h])
+ assert_equal([], [*a, **{}])
+ assert_equal([], [*a, **kw])
+ assert_equal([h], [*a, **h])
+ assert_equal([{}], [*a, {}])
+ assert_equal([kw], [*a, kw])
+ assert_equal([h], [*a, h])
+
+ assert_equal([1], [1, *a, **{}])
+ assert_equal([1], [1, *a, **kw])
+ assert_equal([1, h], [1, *a, **h])
+ assert_equal([1, {}], [1, *a, {}])
+ assert_equal([1, kw], [1, *a, kw])
+ assert_equal([1, h], [1, *a, h])
+
assert_equal([], [**kw, **kw])
assert_equal([], [**kw, **{}, **kw])
assert_equal([1], [1, **kw, **{}, **kw])
@@ -188,7 +330,12 @@ class TestSyntax < Test::Unit::TestCase
bug10315 = '[ruby-core:65368] [Bug #10315]'
o = KW2.new
- assert_equal([23, 2], o.kw(**{k1: 22}, **{k1: 23}), bug10315)
+ begin
+ verbose_bak, $VERBOSE = $VERBOSE, nil
+ assert_equal([23, 2], eval("o.kw(**{k1: 22}, **{k1: 23})"), bug10315)
+ ensure
+ $VERBOSE = verbose_bak
+ end
h = {k3: 31}
assert_raise(ArgumentError) {o.kw(**h)}
@@ -200,17 +347,35 @@ class TestSyntax < Test::Unit::TestCase
bug10315 = '[ruby-core:65625] [Bug #10315]'
a = []
def a.add(x) push(x); x; end
- def a.f(k:) k; end
+ b = a.clone
+ def a.f(k:, **) k; end
+ def b.f(k:) k; end
+ a.clear
+ r = nil
+ assert_warn(/duplicated/) {r = eval("b.f(k: b.add(1), k: b.add(2))")}
+ assert_equal(2, r)
+ assert_equal([1, 2], b, bug10315)
+ b.clear
+ r = nil
+ assert_warn(/duplicated/) {r = eval("a.f(k: a.add(1), j: a.add(2), k: a.add(3), k: a.add(4))")}
+ assert_equal(4, r)
+ assert_equal([1, 2, 3, 4], a)
a.clear
r = nil
- assert_warn(/duplicated/) {r = eval("a.f(k: a.add(1), k: a.add(2))")}
+ assert_warn(/duplicated/) {r = eval("b.f(**{k: b.add(1), k: b.add(2)})")}
assert_equal(2, r)
- assert_equal([1, 2], a, bug10315)
+ assert_equal([1, 2], b, bug10315)
+ b.clear
+ r = nil
+ assert_warn(/duplicated/) {r = eval("a.f(**{k: a.add(1), j: a.add(2), k: a.add(3), k: a.add(4)})")}
+ assert_equal(4, r)
+ assert_equal([1, 2, 3, 4], a)
a.clear
r = nil
- assert_warn(/duplicated/) {r = eval("a.f(**{k: a.add(1), k: a.add(2)})")}
+ _z = {}
+ assert_warn(/duplicated/) {r = eval("a.f(k: a.add(1), **_z, k: a.add(2))")}
assert_equal(2, r)
- assert_equal([1, 2], a, bug10315)
+ assert_equal([1, 2], a)
end
def test_keyword_empty_splat
@@ -232,11 +397,11 @@ class TestSyntax < Test::Unit::TestCase
end
def test_keyword_self_reference
- message = /circular argument reference - var/
- assert_syntax_error("def foo(var: defined?(var)) var end", message)
- assert_syntax_error("def foo(var: var) var end", message)
- assert_syntax_error("def foo(var: bar(var)) var end", message)
- assert_syntax_error("def foo(var: bar {var}) var end", message)
+ assert_valid_syntax("def foo(var: defined?(var)) var end")
+ assert_valid_syntax("def foo(var: var) var end")
+ assert_valid_syntax("def foo(var: bar(var)) var end")
+ assert_valid_syntax("def foo(var: bar {var}) var end")
+ assert_valid_syntax("def foo(var: (1 in ^var)); end")
o = Object.new
assert_warn("") do
@@ -262,6 +427,9 @@ class TestSyntax < Test::Unit::TestCase
assert_warn("") do
o.instance_eval("proc {|var: 1| var}")
end
+
+ o = Object.new
+ assert_nil(o.instance_eval("def foo(bar: bar) = bar; foo"))
end
def test_keyword_invalid_name
@@ -295,13 +463,13 @@ class TestSyntax < Test::Unit::TestCase
end
def test_optional_self_reference
- message = /circular argument reference - var/
- assert_syntax_error("def foo(var = defined?(var)) var end", message)
- assert_syntax_error("def foo(var = var) var end", message)
- assert_syntax_error("def foo(var = bar(var)) var end", message)
- assert_syntax_error("def foo(var = bar {var}) var end", message)
- assert_syntax_error("def foo(var = (def bar;end; var)) var end", message)
- assert_syntax_error("def foo(var = (def self.bar;end; var)) var end", message)
+ assert_valid_syntax("def foo(var = defined?(var)) var end")
+ assert_valid_syntax("def foo(var = var) var end")
+ assert_valid_syntax("def foo(var = bar(var)) var end")
+ assert_valid_syntax("def foo(var = bar {var}) var end")
+ assert_valid_syntax("def foo(var = (def bar;end; var)) var end")
+ assert_valid_syntax("def foo(var = (def self.bar;end; var)) var end")
+ assert_valid_syntax("def foo(var = (1 in ^var)); end")
o = Object.new
assert_warn("") do
@@ -327,6 +495,9 @@ class TestSyntax < Test::Unit::TestCase
assert_warn("") do
o.instance_eval("proc {|var = 1| var}")
end
+
+ o = Object.new
+ assert_nil(o.instance_eval("def foo(bar: bar) = bar; foo"))
end
def test_warn_grouped_expression
@@ -344,10 +515,6 @@ class TestSyntax < Test::Unit::TestCase
end
def test_warn_balanced
- warning = <<WARN
-test:1: warning: `%s' after local variable or literal is interpreted as binary operator
-test:1: warning: even though it seems like %s
-WARN
[
[:**, "argument prefix"],
[:*, "argument prefix"],
@@ -361,7 +528,9 @@ WARN
all_assertions do |a|
["puts 1 #{op}0", "puts :a #{op}0", "m = 1; puts m #{op}0"].each do |src|
a.for(src) do
- assert_warning(warning % [op, syn], src) do
+ warning = /'#{Regexp.escape(op)}' after local variable or literal is interpreted as binary operator.+?even though it seems like #{syn}/m
+
+ assert_warning(warning, src) do
assert_valid_syntax(src, "test", verbose: true)
end
end
@@ -512,6 +681,8 @@ WARN
assert_equal(42, obj.foo(42))
assert_equal(42, obj.foo(2, _: 0))
assert_equal(2, obj.foo(x: 2, _: 0))
+ ensure
+ self.class.remove_method(:foo)
end
def test_duplicated_opt_kw
@@ -551,8 +722,8 @@ WARN
end
def test_duplicated_when
- w = 'warning: duplicated `when\' clause with line 3 is ignored'
- assert_warning(/3: #{w}.+4: #{w}.+4: #{w}.+5: #{w}.+5: #{w}/m) {
+ w = ->(line) { "warning: 'when' clause on line #{line} duplicates 'when' clause on line 3 and is ignored" }
+ assert_warning(/#{w[3]}.+#{w[4]}.+#{w[4]}.+#{w[5]}.+#{w[5]}/m) {
eval %q{
case 1
when 1, 1
@@ -561,7 +732,7 @@ WARN
end
}
}
- assert_warning(/#{w}/) {#/3: #{w}.+4: #{w}.+5: #{w}.+5: #{w}/m){
+ assert_warning(/#{w[3]}.+#{w[4]}.+#{w[5]}.+#{w[5]}/m) {
a = a = 1
eval %q{
case 1
@@ -571,10 +742,28 @@ WARN
end
}
}
+ assert_warning(/#{w[3]}/) {
+ eval %q{
+ case 1
+ when __LINE__, __LINE__
+ when 3, 3
+ when 3, 3
+ end
+ }
+ }
+ assert_warning(/#{w[3]}/) {
+ eval %q{
+ case 1
+ when __FILE__, __FILE__
+ when "filename", "filename"
+ when "filename", "filename"
+ end
+ }, binding, "filename"
+ }
end
def test_duplicated_when_check_option
- w = /duplicated `when\' clause with line 3 is ignored/
+ w = /'when' clause on line 4 duplicates 'when' clause on line 3 and is ignored/
assert_in_out_err(%[-wc], "#{<<~"begin;"}\n#{<<~'end;'}", ["Syntax OK"], w)
begin;
case 1
@@ -707,6 +896,16 @@ e"
assert_dedented_heredoc(expect, result)
end
+ def test_dedented_heredoc_with_leading_blank_line
+ # the blank line has six leading spaces
+ result = " \n" \
+ " b\n"
+ expect = " \n" \
+ "b\n"
+ assert_dedented_heredoc(expect, result)
+ end
+
+
def test_dedented_heredoc_with_blank_more_indented_line_escaped
result = " a\n" \
"\\ \\ \\ \\ \\ \\ \n" \
@@ -814,7 +1013,7 @@ eom
end
def test_dedented_heredoc_concatenation
- assert_equal("\n0\n1", eval("<<~0 '1'\n \n0\#{}\n0"))
+ assert_equal(" \n0\n1", eval("<<~0 '1'\n \n0\#{}\n0"))
end
def test_heredoc_mixed_encoding
@@ -853,6 +1052,14 @@ eom
assert_not_match(/end-of-input/, e.message)
end
+ def test_invalid_regexp
+ bug20295 = '[ruby-core:116913] [Bug #20295]'
+
+ assert_syntax_error("/[/=~s", /premature end of char-class/, bug20295)
+ assert_syntax_error("/(?<>)/=~s", /group name is empty/, bug20295)
+ assert_syntax_error("/(?<a>[)/=~s", /premature end of char-class/, bug20295)
+ end
+
def test_lineno_operation_brace_block
expected = __LINE__ + 1
actual = caller_lineno\
@@ -865,7 +1072,7 @@ eom
["p ", ""], # no-pop
["", "p Foo::Bar"], # pop
].each do |p1, p2|
- src = <<-EOM.gsub(/^\s*\n/, '')
+ src = <<~EOM
class Foo
#{"Bar = " + preset if preset}
end
@@ -897,7 +1104,7 @@ eom
["p ", ""], # no-pop
["", "p ::Bar"], # pop
].each do |p1, p2|
- src = <<-EOM.gsub(/^\s*\n/, '')
+ src = <<~EOM
#{"Bar = " + preset if preset}
class Foo
#{p1}::Bar #{op}= 42
@@ -1048,6 +1255,20 @@ eom
assert_syntax_error("a&.x,=0", /multiple assignment destination/)
end
+ def test_safe_call_in_for_variable
+ assert_valid_syntax("for x&.bar in []; end")
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ foo = nil
+ for foo&.bar in [1]; end
+ assert_nil(foo)
+
+ foo = Struct.new(:bar).new
+ for foo&.bar in [1]; end
+ assert_equal(1, foo.bar)
+ end;
+ end
+
def test_no_warning_logop_literal
assert_warning("") do
eval("true||raise;nil")
@@ -1061,19 +1282,25 @@ eom
end
def test_warning_literal_in_condition
- assert_warn(/literal in condition/) do
+ assert_warn(/string literal in condition/) do
eval('1 if ""')
end
- assert_warn(/literal in condition/) do
+ assert_warning(/string literal in condition/) do
+ eval('1 if __FILE__')
+ end
+ assert_warn(/regex literal in condition/) do
eval('1 if //')
end
assert_warning(/literal in condition/) do
eval('1 if 1')
end
assert_warning(/literal in condition/) do
+ eval('1 if __LINE__')
+ end
+ assert_warning(/symbol literal in condition/) do
eval('1 if :foo')
end
- assert_warning(/literal in condition/) do
+ assert_warning(/symbol literal in condition/) do
eval('1 if :"#{"foo".upcase}"')
end
@@ -1143,7 +1370,7 @@ eom
end
def test_parenthesised_statement_argument
- assert_syntax_error("foo(bar rescue nil)", /unexpected `rescue' modifier/)
+ assert_syntax_error("foo(bar rescue nil)", /unexpected 'rescue' modifier/)
assert_valid_syntax("foo (bar rescue nil)")
end
@@ -1165,7 +1392,7 @@ eom
def test_block_after_cmdarg_in_paren
bug11873 = '[ruby-core:72482] [Bug #11873]'
- def bug11873.p(*);end;
+ def bug11873.p(*, &);end;
assert_raise(LocalJumpError, bug11873) do
bug11873.instance_eval do
@@ -1193,6 +1420,25 @@ eom
assert_valid_syntax 'p :foo, {proc do end => proc do end, b: proc do end}', bug13073
end
+ def test_invalid_encoding_symbol
+ assert_syntax_error('{"\xC3": 1}', "invalid symbol")
+ end
+
+ def test_invalid_symbol_in_hash_memory_leak
+ assert_no_memory_leak([], "#{<<-'begin;'}", "#{<<-'end;'}", rss: true)
+ str = '{"\xC3": 1}'.force_encoding("UTF-8")
+ code = proc do
+ eval(str)
+ raise "unreachable"
+ rescue SyntaxError
+ end
+
+ 1_000.times(&code)
+ begin;
+ 1_000_000.times(&code)
+ end;
+ end
+
def test_do_after_local_variable
obj = Object.new
def obj.m; yield; end
@@ -1241,9 +1487,10 @@ eom
"#{return}"
raise((return; "should not raise"))
begin raise; ensure return; end; self
- begin raise; ensure return; end and self
nil&defined?0--begin e=no_method_error(); return; 0;end
return puts('ignored') #=> ignored
+ BEGIN {return}
+ END {return if false}
end;
.split(/\n/).map {|s|[(line+=1), *s.split(/#=> /, 2)]}
failed = proc do |n, s|
@@ -1273,6 +1520,54 @@ eom
end
end
+ def test_eval_return_toplevel
+ feature4840 = '[ruby-core:36785] [Feature #4840]'
+ line = __LINE__+2
+ code = "#{<<~"begin;"}#{<<~'end;'}"
+ begin;
+ eval "return"; raise
+ begin eval "return"; rescue SystemExit; exit false; end
+ begin eval "return"; ensure puts "ensured"; end #=> ensured
+ begin ensure eval "return"; end
+ begin raise; ensure; eval "return"; end
+ begin raise; rescue; eval "return"; end
+ eval "return false"; raise
+ eval "return 1"; raise
+ "#{eval "return"}"
+ raise((eval "return"; "should not raise"))
+ begin raise; ensure eval "return"; end; self
+ begin raise; ensure eval "return"; end and self
+ eval "return puts('ignored')" #=> ignored
+ BEGIN {eval "return"}
+ end;
+ .split(/\n/).map {|s|[(line+=1), *s.split(/#=> /, 2)]}
+ failed = proc do |n, s|
+ RubyVM::InstructionSequence.compile(s, __FILE__, nil, n).disasm
+ end
+ Tempfile.create(%w"test_return_ .rb") do |lib|
+ lib.close
+ args = %W[-W0 -r#{lib.path}]
+ all_assertions_foreach(feature4840, *[:main, :lib].product([:class, :top], code)) do |main, klass, (n, s, *ex)|
+ if klass == :class
+ s = "class X; #{s}; end"
+ if main == :main
+ assert_in_out_err(%[-W0], s, ex, /return/, proc {failed[n, s]}, success: false)
+ else
+ File.write(lib, s)
+ assert_in_out_err(args, "", ex, /return/, proc {failed[n, s]}, success: false)
+ end
+ else
+ if main == :main
+ assert_in_out_err(%[-W0], s, ex, [], proc {failed[n, s]}, success: true)
+ else
+ File.write(lib, s)
+ assert_in_out_err(args, "", ex, [], proc {failed[n, s]}, success: true)
+ end
+ end
+ end
+ end
+ end
+
def test_return_toplevel_with_argument
assert_warn(/argument of top-level return is ignored/) {eval("return 1")}
end
@@ -1281,6 +1576,20 @@ eom
assert_in_out_err(['-e', 'class TestSyntax; proc{ return }.call; end'], "", [], /^-e:1:.*unexpected return \(LocalJumpError\)/)
end
+ def test_return_in_END
+ assert_normal_exit('END {return}')
+ end
+
+ def test_return_in_BEGIN_in_eval
+ # `BEGIN` in `eval` is allowed, even inside a method, and `return`
+ # from that block exits from that method without `LocalJumpError`.
+ obj = Object.new
+ def obj.ok
+ eval("BEGIN {return :ok}")
+ end
+ assert_equal :ok, assert_nothing_raised(LocalJumpError) {obj.ok}
+ end
+
def test_syntax_error_in_rescue
bug12613 = '[ruby-core:76531] [Bug #12613]'
assert_syntax_error("#{<<-"begin;"}\n#{<<-"end;"}", /Invalid retry/, bug12613)
@@ -1299,13 +1608,13 @@ eom
end
def test_syntax_error_at_newline
- expected = "\n ^"
+ expected = /(\n|\| ) \^/
assert_syntax_error("%[abcdef", expected)
assert_syntax_error("%[abcdef\n", expected)
end
def test_invalid_jump
- assert_in_out_err(%w[-e redo], "", [], /^-e:1: /)
+ assert_in_out_err(%w[-e redo], "", [], /^-e:1: |~ Invalid redo/)
end
def test_keyword_not_parens
@@ -1477,8 +1786,8 @@ eom
assert_equal("instance ok", k.new.rescued("ok"))
# Current technical limitation: cannot prepend "private" or something for command endless def
- error = /syntax error, unexpected string literal/
- error2 = /syntax error, unexpected local variable or method/
+ error = /(syntax error,|\^~*) unexpected string literal/
+ error2 = /(syntax error,|\^~*) unexpected local variable or method/
assert_syntax_error('private def foo = puts "Hello"', error)
assert_syntax_error('private def foo() = puts "Hello"', error)
assert_syntax_error('private def foo(x) = puts x', error2)
@@ -1500,6 +1809,33 @@ eom
def test_command_with_cmd_brace_block
assert_valid_syntax('obj.foo (1) {}')
assert_valid_syntax('obj::foo (1) {}')
+ assert_valid_syntax('bar {}')
+ assert_valid_syntax('Bar {}')
+ assert_valid_syntax('bar() {}')
+ assert_valid_syntax('Bar() {}')
+ assert_valid_syntax('Foo::bar {}')
+ assert_valid_syntax('Foo::Bar {}')
+ assert_valid_syntax('Foo::bar() {}')
+ assert_valid_syntax('Foo::Bar() {}')
+ end
+
+ def test_command_newline_in_tlparen_args
+ assert_valid_syntax("p (1\n2\n),(3),(4)")
+ assert_valid_syntax("p (\n),(),()")
+ assert_valid_syntax("a.b (1\n2\n),(3),(4)")
+ assert_valid_syntax("a.b (\n),(),()")
+ end
+
+ def test_command_semicolon_in_tlparen_at_the_first_arg
+ bug19281 = '[ruby-core:111499] [Bug #19281]'
+ assert_valid_syntax('p (1;2),(3),(4)', bug19281)
+ assert_valid_syntax('p (;),(),()', bug19281)
+ assert_valid_syntax('a.b (1;2),(3),(4)', bug19281)
+ assert_valid_syntax('a.b (;),(),()', bug19281)
+ end
+
+ def test_command_do_block_call_with_empty_args_brace_block
+ assert_valid_syntax('cmd 1, 2 do end.m() { blk_body }')
end
def test_numbered_parameter
@@ -1530,7 +1866,7 @@ eom
assert_syntax_error('def x(_4) end', /_4 is reserved for numbered parameter/)
assert_syntax_error('def _5; end', /_5 is reserved for numbered parameter/)
assert_syntax_error('def self._6; end', /_6 is reserved for numbered parameter/)
- assert_raise_with_message(NameError, /undefined local variable or method `_1'/) {
+ assert_raise_with_message(NameError, /undefined local variable or method '_1'/) {
eval('_1')
}
['class C', 'class << C', 'module M', 'def m', 'def o.m'].each do |c|
@@ -1545,6 +1881,61 @@ eom
assert_raise(NameError) {eval("_1")},
]
}
+
+ assert_valid_syntax("proc {def foo(_);end;_1}")
+ assert_valid_syntax("p { [_1 **2] }")
+ assert_valid_syntax("proc {_1;def foo();end;_1}")
+ end
+
+ def test_it
+ assert_valid_syntax('proc {it}')
+ assert_syntax_error('[1,2].then {it+_2}', /'it' is already used/)
+ assert_syntax_error('[1,2].then {_2+it}', /numbered parameter is already used/)
+ assert_equal([1, 2], eval('[1,2].then {it}'))
+ assert_syntax_error('[1,2].then {"#{it}#{_2}"}', /'it' is already used/)
+ assert_syntax_error('[1,2].then {"#{_2}#{it}"}', /numbered parameter is already used/)
+ assert_syntax_error('->{it+_2}.call(1,2)', /'it' is already used/)
+ assert_syntax_error('->{_2+it}.call(1,2)', /numbered parameter is already used/)
+ assert_equal(4, eval('->(a=->{it}){a}.call.call(4)'))
+ assert_equal(5, eval('-> a: ->{it} {a}.call.call(5)'))
+ assert_syntax_error('proc {|| it}', /ordinary parameter is defined/)
+ assert_syntax_error('proc {|;a| it}', /ordinary parameter is defined/)
+ assert_syntax_error("proc {|\n| it}", /ordinary parameter is defined/)
+ assert_syntax_error('proc {|x| it}', /ordinary parameter is defined/)
+ assert_equal([1, 2], eval('1.then {[it, 2.then {_1}]}'))
+ assert_equal([2, 1], eval('1.then {[2.then {_1}, it]}'))
+ assert_syntax_error('->(){it}', /ordinary parameter is defined/)
+ assert_syntax_error('->(x){it}', /ordinary parameter is defined/)
+ assert_syntax_error('->x{it}', /ordinary parameter is defined/)
+ assert_syntax_error('->x:_1{}', /ordinary parameter is defined/)
+ assert_syntax_error('->x=it{}', /ordinary parameter is defined/)
+ assert_valid_syntax('-> {it; -> {_2}}')
+ assert_valid_syntax('-> {-> {it}; _2}')
+ assert_equal([1, nil], eval('proc {that=it; it=nil; [that, it]}.call(1)'))
+ assert_equal(1, eval('proc {it = 1}.call'))
+ assert_warning(/1: warning: assigned but unused variable - it/) {
+ assert_equal(2, eval('a=Object.new; def a.foo; it = 2; end; a.foo'))
+ }
+ assert_equal(3, eval('proc {|it| it}.call(3)'))
+ assert_equal(4, eval('a=Object.new; def a.foo(it); it; end; a.foo(4)'))
+ assert_equal(5, eval('a=Object.new; def a.it; 5; end; a.it'))
+ assert_equal(6, eval('a=Class.new; a.class_eval{ def it; 6; end }; a.new.it'))
+ assert_raise_with_message(NameError, /undefined local variable or method 'it'/) do
+ eval('it')
+ end
+ ['class C', 'class << C', 'module M', 'def m', 'def o.m'].each do |c|
+ assert_valid_syntax("->{#{c};->{it};end;it}\n")
+ assert_valid_syntax("->{it;#{c};->{it};end}\n")
+ end
+ 1.times do
+ [
+ assert_equal(0, it),
+ assert_equal([:a], eval('[:a].map{it}')),
+ assert_raise(NameError) {eval('it')},
+ ]
+ end
+ assert_valid_syntax('proc {def foo(_);end;it}')
+ assert_syntax_error('p { [it **2] }', /unexpected \*\*/)
end
def test_value_expr_in_condition
@@ -1555,6 +1946,11 @@ eom
assert_valid_syntax("tap {a = (break unless true)}")
end
+ def test_value_expr_in_singleton
+ mesg = /void value expression/
+ assert_syntax_error("class << (return); end", mesg)
+ end
+
def test_tautological_condition
assert_valid_syntax("def f() return if false and invalid; nil end")
assert_valid_syntax("def f() return unless true or invalid; nil end")
@@ -1563,6 +1959,15 @@ eom
def test_argument_forwarding
assert_valid_syntax('def foo(...) bar(...) end')
assert_valid_syntax('def foo(...) end')
+ assert_valid_syntax('def foo(a, ...) bar(...) end')
+ assert_valid_syntax("def foo ...\n bar(...)\nend")
+ assert_valid_syntax("def foo a, ...\n bar(...)\nend")
+ assert_valid_syntax("def foo b = 1, ...\n bar(...)\nend")
+ assert_valid_syntax("def foo ...; bar(...); end")
+ assert_valid_syntax("def foo a, ...; bar(...); end")
+ assert_valid_syntax("def foo b = 1, ...; bar(...); end")
+ assert_valid_syntax("(def foo ...\n bar(...)\nend)")
+ assert_valid_syntax("(def foo ...; bar(...); end)")
assert_valid_syntax('def ==(...) end')
assert_valid_syntax('def [](...) end')
assert_valid_syntax('def nil(...) end')
@@ -1583,6 +1988,8 @@ eom
assert_syntax_error('def foo(...) foo[...] = x; end', /unexpected/)
assert_syntax_error('def foo(...) foo(...) { }; end', /both block arg and actual block given/)
assert_syntax_error('def foo(...) defined?(...); end', /unexpected/)
+ assert_syntax_error('def foo(*rest, ...) end', '... after rest argument')
+ assert_syntax_error('def foo(*, ...) end', '... after rest argument')
obj1 = Object.new
def obj1.bar(*args, **kws, &block)
@@ -1592,7 +1999,11 @@ eom
[args, kws]
end
end
+ obj4 = obj1.clone
+ obj5 = obj1.clone
obj1.instance_eval('def foo(...) bar(...) end', __FILE__, __LINE__)
+ obj4.instance_eval("def foo ...\n bar(...)\n""end", __FILE__, __LINE__)
+ obj5.instance_eval("def foo ...; bar(...); end", __FILE__, __LINE__)
klass = Class.new {
def foo(*args, **kws, &block)
@@ -1621,7 +2032,7 @@ eom
end
obj3.instance_eval('def foo(...) bar(...) end', __FILE__, __LINE__)
- [obj1, obj2, obj3].each do |obj|
+ [obj1, obj2, obj3, obj4, obj5].each do |obj|
assert_warning('') {
assert_equal([[1, 2, 3], {k1: 4, k2: 5}], obj.foo(1, 2, 3, k1: 4, k2: 5) {|*x| x})
}
@@ -1754,6 +2165,51 @@ eom
assert_equal [[4, 1, 5, 2], {a: 1}], obj.foo(4, 5, 2, a: 1)
assert_equal [[4, 1, 5, 2, 3], {a: 1}], obj.foo(4, 5, 2, 3, a: 1)
assert_equal [[4, 1, 5, 2, 3], {a: 1}], obj.foo(4, 5, 2, 3, a: 1){|args, kws| [args, kws]}
+
+ obj.singleton_class.send(:remove_method, :foo)
+ obj.instance_eval("def foo a, ...\n bar(a, ...)\n"" end", __FILE__, __LINE__)
+ assert_equal [[4], {}], obj.foo(4)
+ assert_equal [[4, 2], {}], obj.foo(4, 2)
+ assert_equal [[4, 2, 3], {}], obj.foo(4, 2, 3)
+ assert_equal [[4], {a: 1}], obj.foo(4, a: 1)
+ assert_equal [[4, 2], {a: 1}], obj.foo(4, 2, a: 1)
+ assert_equal [[4, 2, 3], {a: 1}], obj.foo(4, 2, 3, a: 1)
+ assert_equal [[4, 2, 3], {a: 1}], obj.foo(4, 2, 3, a: 1){|args, kws| [args, kws]}
+
+ obj.singleton_class.send(:remove_method, :foo)
+ obj.instance_eval("def foo a, ...; bar(a, ...); end", __FILE__, __LINE__)
+ assert_equal [[4], {}], obj.foo(4)
+ assert_equal [[4, 2], {}], obj.foo(4, 2)
+ assert_equal [[4, 2, 3], {}], obj.foo(4, 2, 3)
+ assert_equal [[4], {a: 1}], obj.foo(4, a: 1)
+ assert_equal [[4, 2], {a: 1}], obj.foo(4, 2, a: 1)
+ assert_equal [[4, 2, 3], {a: 1}], obj.foo(4, 2, 3, a: 1)
+ assert_equal [[4, 2, 3], {a: 1}], obj.foo(4, 2, 3, a: 1){|args, kws| [args, kws]}
+
+ exp = eval("-> (a: nil) {a...1}")
+ assert_equal 0...1, exp.call(a: 0)
+ end
+
+ def test_argument_forwarding_with_super
+ assert_valid_syntax('def foo(...) super {}; end')
+ assert_valid_syntax('def foo(...) super() {}; end')
+ assert_syntax_error('def foo(...) super(...) {}; end', /both block arg and actual block/)
+ assert_syntax_error('def foo(...) super(1, ...) {}; end', /both block arg and actual block/)
+ end
+
+ def test_class_module_Object_ancestors
+ assert_separately([], <<-RUBY)
+ m = Module.new
+ m::Bug18832 = 1
+ include m
+ class Bug18832; end
+ RUBY
+ assert_separately([], <<-RUBY)
+ m = Module.new
+ m::Bug18832 = 1
+ include m
+ module Bug18832; end
+ RUBY
end
def test_cdhash
@@ -1805,7 +2261,7 @@ eom
end
end
- def caller_lineno(*)
+ def caller_lineno(*, &)
caller_locations(1, 1)[0].lineno
end
end
diff --git a/test/ruby/test_system.rb b/test/ruby/test_system.rb
index 31c9cd7654..3fcdaa6aad 100644
--- a/test/ruby/test_system.rb
+++ b/test/ruby/test_system.rb
@@ -146,6 +146,19 @@ class TestSystem < Test::Unit::TestCase
end
end
+ def test_system_closed
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ ios = []
+ ObjectSpace.each_object(IO) {|io| ios << io}
+ `echo`
+ ObjectSpace.each_object(IO) do |io|
+ next if ios.include?(io)
+ assert_nothing_raised {io.close}
+ end
+ end;
+ end
+
def test_empty_evstr
assert_equal("", eval('"#{}"', nil, __FILE__, __LINE__), "[ruby-dev:25113]")
end
diff --git a/test/ruby/test_thread.rb b/test/ruby/test_thread.rb
index 19a3529005..6620ccbf33 100644
--- a/test/ruby/test_thread.rb
+++ b/test/ruby/test_thread.rb
@@ -29,13 +29,19 @@ class TestThread < Test::Unit::TestCase
end
def test_inspect
+ m = Thread::Mutex.new
+ m.lock
line = __LINE__+1
- th = Module.new {break module_eval("class C\u{30b9 30ec 30c3 30c9} < Thread; self; end")}.start{}
+ th = Module.new {break module_eval("class C\u{30b9 30ec 30c3 30c9} < Thread; self; end")}.start do
+ m.synchronize {}
+ end
+ Thread.pass until th.stop?
s = th.inspect
assert_include(s, "::C\u{30b9 30ec 30c3 30c9}:")
assert_include(s, " #{__FILE__}:#{line} ")
assert_equal(s, th.to_s)
ensure
+ m.unlock
th.join
end
@@ -235,6 +241,14 @@ class TestThread < Test::Unit::TestCase
t3&.kill&.join
end
+ def test_join_argument_conversion
+ t = Thread.new {}
+ assert_raise(TypeError) {t.join(:foo)}
+
+ limit = Struct.new(:to_f, :count).new(0.05)
+ assert_same(t, t.join(limit))
+ end
+
{ 'FIXNUM_MAX' => RbConfig::LIMITS['FIXNUM_MAX'],
'UINT64_MAX' => RbConfig::LIMITS['UINT64_MAX'],
'INFINITY' => Float::INFINITY
@@ -309,7 +323,7 @@ class TestThread < Test::Unit::TestCase
s += 1
end
Thread.pass until t.stop?
- sleep 1 if defined?(RubyVM::JIT) && RubyVM::JIT.enabled? # t.stop? behaves unexpectedly with --jit-wait
+ sleep 1 if defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled? # t.stop? behaves unexpectedly with --jit-wait
assert_equal(1, s)
t.wakeup
Thread.pass while t.alive?
@@ -381,7 +395,7 @@ class TestThread < Test::Unit::TestCase
end
INPUT
- assert_in_out_err(%w(--disable-gems -d), <<-INPUT, %w(false 2), %r".+")
+ assert_in_out_err(%w(-d), <<-INPUT, %w(false 2), %r".+")
p Thread.abort_on_exception
begin
t = Thread.new { raise }
@@ -492,7 +506,7 @@ class TestThread < Test::Unit::TestCase
def test_ignore_deadlock
if /mswin|mingw/ =~ RUBY_PLATFORM
- skip "can't trap a signal from another process on Windows"
+ omit "can't trap a signal from another process on Windows"
end
assert_in_out_err([], <<-INPUT, %w(false :sig), [], :signal=>:INT, timeout: 1, timeout_error: nil)
p Thread.ignore_deadlock
@@ -723,7 +737,7 @@ class TestThread < Test::Unit::TestCase
end
def test_no_valid_cfp
- skip 'with win32ole, cannot run this testcase because win32ole redefines Thread#initialize' if defined?(WIN32OLE)
+ omit 'with win32ole, cannot run this testcase because win32ole redefines Thread#initialize' if defined?(WIN32OLE)
bug5083 = '[ruby-dev:44208]'
assert_equal([], Thread.new(&Module.method(:nesting)).value, bug5083)
assert_instance_of(Thread, Thread.new(:to_s, &Class.new.method(:undef_method)).join, bug5083)
@@ -958,6 +972,8 @@ _eom
end
def test_thread_timer_and_interrupt
+ omit "[Bug #18613]" if /freebsd/ =~ RUBY_PLATFORM
+
bug5757 = '[ruby-dev:44985]'
pid = nil
cmd = 'Signal.trap(:INT, "DEFAULT"); pipe=IO.pipe; Thread.start {Thread.pass until Thread.main.stop?; puts; STDOUT.flush}; pipe[0].read'
@@ -1060,7 +1076,7 @@ q.pop
puts mth.status
Process.kill(:INT, $$)
}
- sleep 0.1
+ sleep
INPUT
end
@@ -1236,6 +1252,21 @@ q.pop
assert_predicate(status, :success?, bug9751)
end if Process.respond_to?(:fork)
+ def test_fork_value
+ bug18902 = "[Bug #18902]"
+ th = Thread.start { sleep 2 }
+ begin
+ pid = fork do
+ th.value
+ end
+ _, status = Process.wait2(pid)
+ assert_predicate(status, :success?, bug18902)
+ ensure
+ th.kill
+ th.join
+ end
+ end if Process.respond_to?(:fork)
+
def test_fork_while_locked
m = Thread::Mutex.new
thrs = []
@@ -1248,7 +1279,7 @@ q.pop
end if Process.respond_to?(:fork)
def test_fork_while_parent_locked
- skip 'needs fork' unless Process.respond_to?(:fork)
+ omit 'needs fork' unless Process.respond_to?(:fork)
m = Thread::Mutex.new
nr = 1
thrs = []
@@ -1269,7 +1300,7 @@ q.pop
end
def test_fork_while_mutex_locked_by_forker
- skip 'needs fork' unless Process.respond_to?(:fork)
+ omit 'needs fork' unless Process.respond_to?(:fork)
m = Thread::Mutex.new
m.synchronize do
pid = fork do
@@ -1330,6 +1361,61 @@ q.pop
t.join
end
+ def test_yield_across_thread_through_enum
+ bug18649 = '[ruby-core:107980] [Bug #18649]'
+ @log = []
+
+ def self.p(arg)
+ @log << arg
+ end
+
+ def self.synchronize
+ yield
+ end
+
+ def self.execute(task)
+ success = true
+ value = reason = nil
+ end_sync = false
+
+ synchronize do
+ begin
+ p :before
+ value = task.call
+ p :never_reached
+ success = true
+ rescue StandardError => ex
+ ex = ex.class
+ p [:rescue, ex]
+ reason = ex
+ success = false
+ end
+
+ end_sync = true
+ p :end_sync
+ end
+
+ p :should_not_reach_here! unless end_sync
+ [success, value, reason]
+ end
+
+ def self.foo
+ Thread.new do
+ result = execute(-> { yield 42 })
+ p [:result, result]
+ end.join
+ end
+
+ value = to_enum(:foo).first
+ expected = [:before,
+ [:rescue, LocalJumpError],
+ :end_sync,
+ [:result, [false, nil, LocalJumpError]]]
+
+ assert_equal(expected, @log, bug18649)
+ assert_equal(42, value, bug18649)
+ end
+
def test_thread_setname_in_initialize
bug12290 = '[ruby-core:74963] [Bug #12290]'
c = Class.new(Thread) {def initialize() self.name = "foo"; super; end}
@@ -1337,7 +1423,7 @@ q.pop
end
def test_thread_native_thread_id
- skip "don't support native_thread_id" unless Thread.method_defined?(:native_thread_id)
+ omit "don't support native_thread_id" unless Thread.method_defined?(:native_thread_id)
assert_instance_of Integer, Thread.main.native_thread_id
th1 = Thread.start{sleep}
@@ -1348,7 +1434,8 @@ q.pop
Thread.pass until th1.stop?
# After a thread starts (and execute `sleep`), it returns native_thread_id
- assert_instance_of Integer, th1.native_thread_id
+ native_tid = th1.native_thread_id
+ assert_instance_of Integer, native_tid if native_tid # it can be nil
th1.wakeup
Thread.pass while th1.alive?
@@ -1357,11 +1444,43 @@ q.pop
assert_nil th1.native_thread_id
end
+ def test_thread_native_thread_id_across_fork_on_linux
+ begin
+ require '-test-/thread/id'
+ rescue LoadError
+ omit "this test is only for Linux"
+ else
+ extend Bug::ThreadID
+ end
+
+ parent_thread_id = Thread.main.native_thread_id
+ real_parent_thread_id = gettid
+
+ assert_equal real_parent_thread_id, parent_thread_id
+
+ child_lines = nil
+ IO.popen('-') do |pipe|
+ if pipe
+ # parent
+ child_lines = pipe.read.lines
+ else
+ # child
+ puts Thread.main.native_thread_id
+ puts gettid
+ end
+ end
+ child_thread_id = child_lines[0].chomp.to_i
+ real_child_thread_id = child_lines[1].chomp.to_i
+
+ assert_equal real_child_thread_id, child_thread_id
+ refute_equal parent_thread_id, child_thread_id
+ end
+
def test_thread_interrupt_for_killed_thread
opts = { timeout: 5, timeout_error: nil }
- # prevent SIGABRT from slow shutdown with MJIT
- opts[:reprieve] = 3 if defined?(RubyVM::JIT) && RubyVM::JIT.enabled?
+ # prevent SIGABRT from slow shutdown with RJIT
+ opts[:reprieve] = 3 if defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled?
assert_normal_exit(<<-_end, '[Bug #8996]', **opts)
Thread.report_on_exception = false
@@ -1376,9 +1495,14 @@ q.pop
def test_signal_at_join
if /mswin|mingw/ =~ RUBY_PLATFORM
- skip "can't trap a signal from another process on Windows"
+ omit "can't trap a signal from another process on Windows"
# opt = {new_pgroup: true}
end
+
+ if /freebsd/ =~ RUBY_PLATFORM
+ omit "[Bug #18613]"
+ end
+
assert_separately([], "#{<<~"{#"}\n#{<<~'};'}", timeout: 120)
{#
n = 1000
@@ -1425,4 +1549,12 @@ q.pop
end
};
end
+
+ def test_pending_interrupt?
+ t = Thread.handle_interrupt(Exception => :never) { Thread.new { Thread.stop } }
+ t.raise(StandardError)
+ assert_equal(true, t.pending_interrupt?)
+ assert_equal(true, t.pending_interrupt?(Exception))
+ assert_equal(false, t.pending_interrupt?(ArgumentError))
+ end
end
diff --git a/test/ruby/test_thread_cv.rb b/test/ruby/test_thread_cv.rb
index 812c4221bc..eb88b9606c 100644
--- a/test/ruby/test_thread_cv.rb
+++ b/test/ruby/test_thread_cv.rb
@@ -6,12 +6,6 @@ class TestThreadConditionVariable < Test::Unit::TestCase
ConditionVariable = Thread::ConditionVariable
Mutex = Thread::Mutex
- def test_initialized
- assert_raise(TypeError) {
- ConditionVariable.allocate.wait(nil)
- }
- end
-
def test_condvar_signal_and_wait
mutex = Thread::Mutex.new
condvar = Thread::ConditionVariable.new
@@ -89,6 +83,9 @@ class TestThreadConditionVariable < Test::Unit::TestCase
end
assert_equal ["C1", "C1", "C1", "P1", "P2", "C2", "C2", "C2"], result
+ ensure
+ threads.each(&:kill)
+ threads.each(&:join)
end
def test_condvar_wait_deadlock
diff --git a/test/ruby/test_thread_queue.rb b/test/ruby/test_thread_queue.rb
index 3fa0eae2c1..545bf98888 100644
--- a/test/ruby/test_thread_queue.rb
+++ b/test/ruby/test_thread_queue.rb
@@ -8,17 +8,26 @@ class TestThreadQueue < Test::Unit::TestCase
SizedQueue = Thread::SizedQueue
def test_queue_initialized
- assert_raise(TypeError) {
+ assert_raise_with_message(TypeError, /\bQueue.* not initialized/) {
Queue.allocate.push(nil)
}
end
def test_sized_queue_initialized
- assert_raise(TypeError) {
+ assert_raise_with_message(TypeError, /\bSizedQueue.* not initialized/) {
SizedQueue.allocate.push(nil)
}
end
+ def test_freeze
+ assert_raise(TypeError) {
+ Queue.new.freeze
+ }
+ assert_raise(TypeError) {
+ SizedQueue.new(5).freeze
+ }
+ end
+
def test_queue
grind(5, 1000, 15, Queue)
end
@@ -111,6 +120,23 @@ class TestThreadQueue < Test::Unit::TestCase
assert_equal(0, q.num_waiting)
end
+ def test_queue_pop_timeout
+ q = Thread::Queue.new
+ q << 1
+ assert_equal 1, q.pop(timeout: 1)
+
+ t1 = Thread.new { q.pop(timeout: 1) }
+ assert_equal t1, t1.join(2)
+ assert_nil t1.value
+
+ t2 = Thread.new { q.pop(timeout: 0.1) }
+ assert_equal t2, t2.join(1)
+ assert_nil t2.value
+ ensure
+ t1&.kill&.join
+ t2&.kill&.join
+ end
+
def test_queue_pop_non_block
q = Thread::Queue.new
assert_raise_with_message(ThreadError, /empty/) do
@@ -126,6 +152,24 @@ class TestThreadQueue < Test::Unit::TestCase
assert_equal(0, q.num_waiting)
end
+ def test_sized_queue_pop_timeout
+ q = Thread::SizedQueue.new(1)
+
+ q << 1
+ assert_equal 1, q.pop(timeout: 1)
+
+ t1 = Thread.new { q.pop(timeout: 1) }
+ assert_equal t1, t1.join(2)
+ assert_nil t1.value
+
+ t2 = Thread.new { q.pop(timeout: 0.1) }
+ assert_equal t2, t2.join(1)
+ assert_nil t2.value
+ ensure
+ t1&.kill&.join
+ t2&.kill&.join
+ end
+
def test_sized_queue_pop_non_block
q = Thread::SizedQueue.new(1)
assert_raise_with_message(ThreadError, /empty/) do
@@ -133,6 +177,24 @@ class TestThreadQueue < Test::Unit::TestCase
end
end
+ def test_sized_queue_push_timeout
+ q = Thread::SizedQueue.new(1)
+
+ q << 1
+ assert_equal 1, q.size
+
+ t1 = Thread.new { q.push(2, timeout: 1) }
+ assert_equal t1, t1.join(2)
+ assert_nil t1.value
+
+ t2 = Thread.new { q.push(2, timeout: 0.1) }
+ assert_equal t2, t2.join(1)
+ assert_nil t2.value
+ ensure
+ t1&.kill&.join
+ t2&.kill&.join
+ end
+
def test_sized_queue_push_interrupt
q = Thread::SizedQueue.new(1)
q.push(1)
@@ -151,16 +213,18 @@ class TestThreadQueue < Test::Unit::TestCase
end
def test_thr_kill
+ omit "[Bug #18613]" if /freebsd/ =~ RUBY_PLATFORM
+
bug5343 = '[ruby-core:39634]'
Dir.mktmpdir {|d|
- timeout = EnvUtil.apply_timeout_scale(60)
+ timeout = 60
total_count = 250
begin
- assert_normal_exit(<<-"_eom", bug5343, **{:timeout => timeout, :chdir=>d})
+ assert_normal_exit(<<-"_eom", bug5343, timeout: timeout, chdir: d)
+ r, w = IO.pipe
#{total_count}.times do |i|
- open("test_thr_kill_count", "w") {|f| f.puts i }
+ File.open("test_thr_kill_count", "w") {|f| f.puts i }
queue = Thread::Queue.new
- r, w = IO.pipe
th = Thread.start {
queue.push(nil)
r.read 1
@@ -530,9 +594,14 @@ class TestThreadQueue < Test::Unit::TestCase
count_items = rand(3000..5000)
count_producers = rand(10..20)
+ # ensure threads do not start running too soon and complete before we check status
+ mutex = Mutex.new
+ mutex.lock
+
producers = count_producers.times.map do
Thread.new do
- sleep(rand / 100)
+ mutex.lock
+ mutex.unlock
count_items.times{|i| q << [i,"#{i} for #{Thread.current.inspect}"]}
end
end
@@ -550,9 +619,11 @@ class TestThreadQueue < Test::Unit::TestCase
# No dead or finished threads, give up to 10 seconds to start running
t = Time.now
- Thread.pass until Time.now - t > 10 || (consumers + producers).all?{|thr| thr.status =~ /\A(?:run|sleep)\z/}
+ Thread.pass until Time.now - t > 10 || (consumers + producers).all?{|thr| thr.status.to_s =~ /\A(?:run|sleep)\z/}
+
+ assert (consumers + producers).all?{|thr| thr.status.to_s =~ /\A(?:run|sleep)\z/}, 'no threads running'
- assert (consumers + producers).all?{|thr| thr.status =~ /\A(?:run|sleep)\z/}, 'no threads running'
+ mutex.unlock
# just exercising the concurrency of the support methods.
counter = Thread.new do
@@ -580,10 +651,10 @@ class TestThreadQueue < Test::Unit::TestCase
def test_queue_with_trap
if ENV['APPVEYOR'] == 'True' && RUBY_PLATFORM.match?(/mswin/)
- skip 'This test fails too often on AppVeyor vs140'
+ omit 'This test fails too often on AppVeyor vs140'
end
if RUBY_PLATFORM.match?(/mingw/)
- skip 'This test fails too often on MinGW'
+ omit 'This test fails too often on MinGW'
end
assert_in_out_err([], <<-INPUT, %w(INT INT exit), [])
diff --git a/test/ruby/test_time.rb b/test/ruby/test_time.rb
index fc21c74078..99ee84f247 100644
--- a/test/ruby/test_time.rb
+++ b/test/ruby/test_time.rb
@@ -37,8 +37,11 @@ class TestTime < Test::Unit::TestCase
end
def test_new
+ assert_equal(Time.new(2000,1,1,0,0,0), Time.new(2000))
+ assert_equal(Time.new(2000,2,1,0,0,0), Time.new("2000", "Feb"))
assert_equal(Time.utc(2000,2,10), Time.new(2000,2,10, 11,0,0, 3600*11))
assert_equal(Time.utc(2000,2,10), Time.new(2000,2,9, 13,0,0, -3600*11))
+ assert_equal(Time.utc(2000,2,29,23,0,0), Time.new(2000, 3, 1, 0, 0, 0, 3600))
assert_equal(Time.utc(2000,2,10), Time.new(2000,2,10, 11,0,0, "+11:00"))
assert_equal(Rational(1,2), Time.new(2000,2,10, 11,0,5.5, "+11:00").subsec)
bug4090 = '[ruby-dev:42631]'
@@ -46,7 +49,109 @@ class TestTime < Test::Unit::TestCase
t = Time.new(*tm, "-12:00")
assert_equal([2001,2,28,23,59,30,-43200], [t.year, t.month, t.mday, t.hour, t.min, t.sec, t.gmt_offset], bug4090)
assert_raise(ArgumentError) { Time.new(2000,1,1, 0,0,0, "+01:60") }
+ msg = /invalid value for Integer/
+ assert_raise_with_message(ArgumentError, msg) { Time.new(2021, 1, 1, "+09:99") }
+ assert_raise_with_message(ArgumentError, msg) { Time.new(2021, 1, "+09:99") }
+ assert_raise_with_message(ArgumentError, msg) { Time.new(2021, "+09:99") }
+
+ assert_equal([0, 0, 0, 1, 1, 2000, 6, 1, false, "UTC"], Time.new(2000, 1, 1, 0, 0, 0, "-00:00").to_a)
+ assert_equal([0, 0, 0, 2, 1, 2000, 0, 2, false, "UTC"], Time.new(2000, 1, 1, 24, 0, 0, "-00:00").to_a)
+ end
+
+ def test_new_from_string
assert_raise(ArgumentError) { Time.new(2021, 1, 1, "+09:99") }
+
+ t = Time.utc(2020, 12, 24, 15, 56, 17)
+ assert_equal(t, Time.new("2020-12-24T15:56:17Z"))
+ assert_equal(t, Time.new("2020-12-25 00:56:17 +09:00"))
+ assert_equal(t, Time.new("2020-12-25 00:57:47 +09:01:30"))
+ assert_equal(t, Time.new("2020-12-25 00:56:17 +0900"))
+ assert_equal(t, Time.new("2020-12-25 00:57:47 +090130"))
+ assert_equal(t, Time.new("2020-12-25T00:56:17+09:00"))
+ assert_raise_with_message(ArgumentError, /missing sec part/) {
+ Time.new("2020-12-25 00:56 +09:00")
+ }
+ assert_raise_with_message(ArgumentError, /missing min part/) {
+ Time.new("2020-12-25 00 +09:00")
+ }
+
+ assert_equal(Time.new(2021), Time.new("2021"))
+ assert_equal(Time.new(2021, 12, 25, in: "+09:00"), Time.new("2021-12-25+09:00"))
+ assert_equal(Time.new(2021, 12, 25, in: "+09:00"), Time.new("2021-12-25+09:00", in: "-01:00"))
+
+ assert_equal(0.123456r, Time.new("2021-12-25 00:00:00.123456 +09:00").subsec)
+ assert_equal(0.123456789r, Time.new("2021-12-25 00:00:00.123456789876 +09:00").subsec)
+ assert_equal(0.123r, Time.new("2021-12-25 00:00:00.123456789876 +09:00", precision: 3).subsec)
+ assert_equal(0.123456789876r, Time.new("2021-12-25 00:00:00.123456789876 +09:00", precision: nil).subsec)
+ assert_raise_with_message(ArgumentError, "subsecond expected after dot: 00:56:17. ") {
+ Time.new("2020-12-25 00:56:17. +0900")
+ }
+ assert_raise_with_message(ArgumentError, /year must be 4 or more/) {
+ Time.new("021-12-25 00:00:00.123456 +09:00")
+ }
+ assert_raise_with_message(ArgumentError, /fraction min is.*56\./) {
+ Time.new("2020-12-25 00:56. +0900")
+ }
+ assert_raise_with_message(ArgumentError, /fraction hour is.*00\./) {
+ Time.new("2020-12-25 00. +0900")
+ }
+ assert_raise_with_message(ArgumentError, /two digits sec.*:017\b/) {
+ Time.new("2020-12-25 00:56:017 +0900")
+ }
+ assert_raise_with_message(ArgumentError, /two digits sec.*:9\b/) {
+ Time.new("2020-12-25 00:56:9 +0900")
+ }
+ assert_raise_with_message(ArgumentError, /sec out of range/) {
+ Time.new("2020-12-25 00:56:64 +0900")
+ }
+ assert_raise_with_message(ArgumentError, /two digits min.*:056\b/) {
+ Time.new("2020-12-25 00:056:17 +0900")
+ }
+ assert_raise_with_message(ArgumentError, /two digits min.*:5\b/) {
+ Time.new("2020-12-25 00:5:17 +0900")
+ }
+ assert_raise_with_message(ArgumentError, /min out of range/) {
+ Time.new("2020-12-25 00:64:17 +0900")
+ }
+ assert_raise_with_message(ArgumentError, /two digits hour.*\b000\b/) {
+ Time.new("2020-12-25 000:56:17 +0900")
+ }
+ assert_raise_with_message(ArgumentError, /two digits hour.*\b0\b/) {
+ Time.new("2020-12-25 0:56:17 +0900")
+ }
+ assert_raise_with_message(ArgumentError, /hour out of range/) {
+ Time.new("2020-12-25 33:56:17 +0900")
+ }
+ assert_raise_with_message(ArgumentError, /two digits mday.*\b025\b/) {
+ Time.new("2020-12-025 00:56:17 +0900")
+ }
+ assert_raise_with_message(ArgumentError, /two digits mday.*\b5\b/) {
+ Time.new("2020-12-5 00:56:17 +0900")
+ }
+ assert_raise_with_message(ArgumentError, /mday out of range/) {
+ Time.new("2020-12-33 00:56:17 +0900")
+ }
+ assert_raise_with_message(ArgumentError, /two digits mon.*\b012\b/) {
+ Time.new("2020-012-25 00:56:17 +0900")
+ }
+ assert_raise_with_message(ArgumentError, /two digits mon.*\b1\b/) {
+ Time.new("2020-1-25 00:56:17 +0900")
+ }
+ assert_raise_with_message(ArgumentError, /mon out of range/) {
+ Time.new("2020-17-25 00:56:17 +0900")
+ }
+ assert_raise_with_message(ArgumentError, /no time information/) {
+ Time.new("2020-12")
+ }
+ assert_raise_with_message(ArgumentError, /no time information/) {
+ Time.new("2020-12-02")
+ }
+ assert_raise_with_message(ArgumentError, /can't parse/) {
+ Time.new(" 2020-12-02 00:00:00")
+ }
+ assert_raise_with_message(ArgumentError, /can't parse/) {
+ Time.new("2020-12-02 00:00:00 ")
+ }
end
def test_time_add()
@@ -110,7 +215,7 @@ class TestTime < Test::Unit::TestCase
assert_equal(946684800, Time.utc(2000, 1, 1, 0, 0, 0).tv_sec)
# Giveup to try 2nd test because some state is changed.
- skip if Test::Unit::Runner.current_repeat_count > 0
+ omit if Test::Unit::Runner.current_repeat_count > 0
assert_equal(0x7fffffff, Time.utc(2038, 1, 19, 3, 14, 7).tv_sec)
assert_equal(0x80000000, Time.utc(2038, 1, 19, 3, 14, 8).tv_sec)
@@ -240,6 +345,10 @@ class TestTime < Test::Unit::TestCase
assert_equal(1, Time.at(0, 0.001).nsec)
end
+ def test_at_splat
+ assert_equal(Time.at(1, 2), Time.at(*[1, 2]))
+ end
+
def test_at_with_unit
assert_equal(123456789, Time.at(0, 123456789, :nanosecond).nsec)
assert_equal(123456789, Time.at(0, 123456789, :nsec).nsec)
@@ -330,7 +439,7 @@ class TestTime < Test::Unit::TestCase
end
def test_marshal_zone_gc
- assert_separately(%w(--disable-gems), <<-'end;', timeout: 30)
+ assert_separately([], <<-'end;', timeout: 30)
ENV["TZ"] = "JST-9"
s = Marshal.dump(Time.now)
t = Marshal.load(s)
@@ -379,6 +488,11 @@ class TestTime < Test::Unit::TestCase
end
end
+ def test_marshal_broken_month
+ data = "\x04\x08u:\tTime\r\x20\x7c\x1e\xc0\x00\x00\x00\x00"
+ assert_equal(Time.utc(2022, 4, 1), Marshal.load(data))
+ end
+
def test_marshal_distant_past
assert_marshal_roundtrip(Time.utc(1890, 1, 1))
assert_marshal_roundtrip(Time.utc(-4.5e9, 1, 1))
@@ -1168,7 +1282,7 @@ class TestTime < Test::Unit::TestCase
def test_2038
# Giveup to try 2nd test because some state is changed.
- skip if Test::Unit::Runner.current_repeat_count > 0
+ omit if Test::Unit::Runner.current_repeat_count > 0
if no_leap_seconds?
assert_equal(0x80000000, Time.utc(2038, 1, 19, 3, 14, 8).tv_sec)
@@ -1281,22 +1395,6 @@ class TestTime < Test::Unit::TestCase
assert_equal("366", t.strftime("%j"))
end
- def test_strftime_no_hidden_garbage
- skip unless Thread.list.size == 1
-
- fmt = %w(Y m d).map { |x| "%#{x}" }.join('-') # defeats optimization
- t = Time.at(0).getutc
- ObjectSpace.count_objects(res = {}) # creates strings on first call
- GC.disable
- before = ObjectSpace.count_objects(res)[:T_STRING]
- val = t.strftime(fmt)
- after = ObjectSpace.count_objects(res)[:T_STRING]
- assert_equal before + 1, after, 'only new string is the created one'
- assert_equal '1970-01-01', val
- ensure
- GC.enable
- end
-
def test_num_exact_error
bad = EnvUtil.labeled_class("BadValue").new
x = EnvUtil.labeled_class("Inexact") do
@@ -1309,21 +1407,100 @@ class TestTime < Test::Unit::TestCase
def test_memsize
# Time objects are common in some code, try to keep them small
- skip "Time object size test" if /^(?:i.?86|x86_64)-linux/ !~ RUBY_PLATFORM
- skip "GC is in debug" if GC::INTERNAL_CONSTANTS[:DEBUG]
+ omit "Time object size test" if /^(?:i.?86|x86_64)-linux/ !~ RUBY_PLATFORM
+ omit "GC is in debug" if GC::INTERNAL_CONSTANTS[:RVALUE_OVERHEAD] > 0
+ omit "memsize is not accurate due to using malloc_usable_size" if GC::INTERNAL_CONSTANTS[:SIZE_POOL_COUNT] == 1
+ omit "Only run this test on 64-bit" if RbConfig::SIZEOF["void*"] != 8
+
require 'objspace'
t = Time.at(0)
- size = GC::INTERNAL_CONSTANTS[:RVALUE_SIZE]
- case size
- when 20 then expect = 50
- when 24 then expect = 54
- when 40 then expect = 86
- when 48 then expect = 94
- else
- flunk "Unsupported RVALUE_SIZE=#{size}, update test_memsize"
- end
- assert_equal expect, ObjectSpace.memsize_of(t)
+ sizeof_timew =
+ if RbConfig::SIZEOF.key?("uint64_t") && RbConfig::SIZEOF["long"] * 2 <= RbConfig::SIZEOF["uint64_t"]
+ RbConfig::SIZEOF["uint64_t"]
+ else
+ RbConfig::SIZEOF["void*"] # Same size as VALUE
+ end
+ sizeof_vtm = RbConfig::SIZEOF["void*"] * 4 + 8
+ expect = GC::INTERNAL_CONSTANTS[:BASE_SLOT_SIZE] + sizeof_timew + sizeof_vtm
+ assert_operator ObjectSpace.memsize_of(t), :<=, expect
rescue LoadError => e
- skip "failed to load objspace: #{e.message}"
+ omit "failed to load objspace: #{e.message}"
+ end
+
+ def test_deconstruct_keys
+ t = in_timezone('JST-9') { Time.local(2022, 10, 16, 14, 1, 30, 500) }
+ assert_equal(
+ {year: 2022, month: 10, day: 16, wday: 0, yday: 289,
+ hour: 14, min: 1, sec: 30, subsec: 1/2000r, dst: false, zone: 'JST'},
+ t.deconstruct_keys(nil)
+ )
+
+ assert_equal(
+ {year: 2022, month: 10, sec: 30},
+ t.deconstruct_keys(%i[year month sec nonexistent])
+ )
+ end
+
+ def test_parse_zero_bigint
+ assert_equal 0, Time.new("2020-10-28T16:48:07.000Z").nsec, '[Bug #19390]'
+ end
+
+ def test_xmlschema_encode
+ [:xmlschema, :iso8601].each do |method|
+ bug6100 = '[ruby-core:42997]'
+
+ t = Time.utc(2001, 4, 17, 19, 23, 17, 300000)
+ assert_equal("2001-04-17T19:23:17Z", t.__send__(method))
+ assert_equal("2001-04-17T19:23:17.3Z", t.__send__(method, 1))
+ assert_equal("2001-04-17T19:23:17.300000Z", t.__send__(method, 6))
+ assert_equal("2001-04-17T19:23:17.3000000Z", t.__send__(method, 7))
+ assert_equal("2001-04-17T19:23:17.3Z", t.__send__(method, 1.9), bug6100)
+
+ t = Time.utc(2001, 4, 17, 19, 23, 17, 123456)
+ assert_equal("2001-04-17T19:23:17.1234560Z", t.__send__(method, 7))
+ assert_equal("2001-04-17T19:23:17.123456Z", t.__send__(method, 6))
+ assert_equal("2001-04-17T19:23:17.12345Z", t.__send__(method, 5))
+ assert_equal("2001-04-17T19:23:17.1Z", t.__send__(method, 1))
+ assert_equal("2001-04-17T19:23:17.1Z", t.__send__(method, 1.9), bug6100)
+
+ t = Time.at(2.quo(3)).getlocal("+09:00")
+ assert_equal("1970-01-01T09:00:00.666+09:00", t.__send__(method, 3))
+ assert_equal("1970-01-01T09:00:00.6666666666+09:00", t.__send__(method, 10))
+ assert_equal("1970-01-01T09:00:00.66666666666666666666+09:00", t.__send__(method, 20))
+ assert_equal("1970-01-01T09:00:00.6+09:00", t.__send__(method, 1.1), bug6100)
+ assert_equal("1970-01-01T09:00:00.666+09:00", t.__send__(method, 3.2), bug6100)
+
+ t = Time.at(123456789.quo(9999999999)).getlocal("+09:00")
+ assert_equal("1970-01-01T09:00:00.012+09:00", t.__send__(method, 3))
+ assert_equal("1970-01-01T09:00:00.012345678+09:00", t.__send__(method, 9))
+ assert_equal("1970-01-01T09:00:00.0123456789+09:00", t.__send__(method, 10))
+ assert_equal("1970-01-01T09:00:00.0123456789012345678+09:00", t.__send__(method, 19))
+ assert_equal("1970-01-01T09:00:00.01234567890123456789+09:00", t.__send__(method, 20))
+ assert_equal("1970-01-01T09:00:00.012+09:00", t.__send__(method, 3.8), bug6100)
+
+ t = Time.utc(1)
+ assert_equal("0001-01-01T00:00:00Z", t.__send__(method))
+
+ begin
+ Time.at(-1)
+ rescue ArgumentError
+ # ignore
+ else
+ t = Time.utc(1960, 12, 31, 23, 0, 0, 123456)
+ assert_equal("1960-12-31T23:00:00.123456Z", t.__send__(method, 6))
+ end
+
+ t = get_t2000.getlocal("-09:30") # Pacific/Marquesas
+ assert_equal("1999-12-31T14:30:00-09:30", t.__send__(method))
+
+ assert_equal("10000-01-01T00:00:00Z", Time.utc(10000).__send__(method))
+ assert_equal("9999-01-01T00:00:00Z", Time.utc(9999).__send__(method))
+ assert_equal("0001-01-01T00:00:00Z", Time.utc(1).__send__(method)) # 1 AD
+ assert_equal("0000-01-01T00:00:00Z", Time.utc(0).__send__(method)) # 1 BC
+ assert_equal("-0001-01-01T00:00:00Z", Time.utc(-1).__send__(method)) # 2 BC
+ assert_equal("-0004-01-01T00:00:00Z", Time.utc(-4).__send__(method)) # 5 BC
+ assert_equal("-9999-01-01T00:00:00Z", Time.utc(-9999).__send__(method))
+ assert_equal("-10000-01-01T00:00:00Z", Time.utc(-10000).__send__(method))
+ end
end
end
diff --git a/test/ruby/test_time_tz.rb b/test/ruby/test_time_tz.rb
index fdc9e114b5..f66cd9bec2 100644
--- a/test/ruby/test_time_tz.rb
+++ b/test/ruby/test_time_tz.rb
@@ -7,9 +7,9 @@ class TestTimeTZ < Test::Unit::TestCase
has_lisbon_tz = true
force_tz_test = ENV["RUBY_FORCE_TIME_TZ_TEST"] == "yes"
case RUBY_PLATFORM
- when /linux/
+ when /darwin|linux/
force_tz_test = true
- when /darwin|freebsd|openbsd/
+ when /freebsd|openbsd/
has_lisbon_tz = false
force_tz_test = true
end
@@ -95,6 +95,9 @@ class TestTimeTZ < Test::Unit::TestCase
CORRECT_KIRITIMATI_SKIP_1994 = with_tz("Pacific/Kiritimati") {
Time.local(1994, 12, 31, 0, 0, 0).year == 1995
}
+ CORRECT_SINGAPORE_1982 = with_tz("Asia/Singapore") {
+ "2022g" if Time.local(1981, 12, 31, 23, 59, 59).utc_offset == 8*3600
+ }
def time_to_s(t)
t.to_s
@@ -112,7 +115,7 @@ class TestTimeTZ < Test::Unit::TestCase
t = with_tz("America/Los_Angeles") {
Time.local(2000, 1, 1)
}
- skip "force_tz_test is false on this environment" unless t
+ omit "force_tz_test is false on this environment" unless t
z1 = t.zone
z2 = with_tz(tz="Asia/Singapore") {
t.localtime.zone
@@ -140,9 +143,12 @@ class TestTimeTZ < Test::Unit::TestCase
def test_asia_singapore
with_tz(tz="Asia/Singapore") {
- assert_time_constructor(tz, "1981-12-31 23:59:59 +0730", :local, [1981,12,31,23,59,59])
- assert_time_constructor(tz, "1982-01-01 00:30:00 +0800", :local, [1982,1,1,0,0,0])
- assert_time_constructor(tz, "1982-01-01 00:59:59 +0800", :local, [1982,1,1,0,29,59])
+ assert_time_constructor(tz, "1981-12-31 23:29:59 +0730", :local, [1981,12,31,23,29,59])
+ if CORRECT_SINGAPORE_1982
+ assert_time_constructor(tz, "1982-01-01 00:00:00 +0800", :local, [1981,12,31,23,30,00])
+ assert_time_constructor(tz, "1982-01-01 00:00:00 +0800", :local, [1982,1,1,0,0,0])
+ assert_time_constructor(tz, "1982-01-01 00:29:59 +0800", :local, [1982,1,1,0,29,59])
+ end
assert_time_constructor(tz, "1982-01-01 00:30:00 +0800", :local, [1982,1,1,0,30,0])
}
end
@@ -196,7 +202,7 @@ class TestTimeTZ < Test::Unit::TestCase
def test_europe_lisbon
with_tz("Europe/Lisbon") {
- assert_equal("LMT", Time.new(-0x1_0000_0000_0000_0000).zone)
+ assert_include(%w"LMT CET", Time.new(-0x1_0000_0000_0000_0000).zone)
}
end if has_lisbon_tz
@@ -450,9 +456,12 @@ America/Managua Fri Jan 1 06:00:00 1993 UTC = Fri Jan 1 01:00:00 1993 EST isd
America/Managua Wed Jan 1 04:59:59 1997 UTC = Tue Dec 31 23:59:59 1996 EST isdst=0 gmtoff=-18000
America/Managua Wed Jan 1 05:00:00 1997 UTC = Tue Dec 31 23:00:00 1996 CST isdst=0 gmtoff=-21600
Asia/Singapore Sun Aug 8 16:30:00 1965 UTC = Mon Aug 9 00:00:00 1965 SGT isdst=0 gmtoff=27000
-Asia/Singapore Thu Dec 31 16:29:59 1981 UTC = Thu Dec 31 23:59:59 1981 SGT isdst=0 gmtoff=27000
+Asia/Singapore Thu Dec 31 15:59:59 1981 UTC = Thu Dec 31 23:29:59 1981 SGT isdst=0 gmtoff=27000
Asia/Singapore Thu Dec 31 16:30:00 1981 UTC = Fri Jan 1 00:30:00 1982 SGT isdst=0 gmtoff=28800
End
+ gen_zdump_test <<'End' if CORRECT_SINGAPORE_1982
+Asia/Singapore Thu Dec 31 16:00:00 1981 UTC = Fri Jan 1 00:00:00 1982 SGT isdst=0 gmtoff=28800
+End
gen_zdump_test CORRECT_TOKYO_DST_1951 ? <<'End' + (CORRECT_TOKYO_DST_1951 < "2018f" ? <<'2018e' : <<'2018f') : <<'End'
Asia/Tokyo Sat May 5 14:59:59 1951 UTC = Sat May 5 23:59:59 1951 JST isdst=0 gmtoff=32400
Asia/Tokyo Sat May 5 15:00:00 1951 UTC = Sun May 6 01:00:00 1951 JDT isdst=1 gmtoff=36000
@@ -612,6 +621,11 @@ module TestTimeTZ::WithTZ
assert_raise(ArgumentError) {time_class.new(2018, 9, 1, 12, 0, 0, tzarg, in: tzarg)}
end
+ def subtest_hour24(time_class, tz, tzarg, tzname, abbr, utc_offset)
+ t = time_class.new(2000, 1, 1, 24, 0, 0, tzarg)
+ assert_equal([0, 0, 0, 2, 1, 2000], [t.sec, t.min, t.hour, t.mday, t.mon, t.year])
+ end
+
def subtest_now(time_class, tz, tzarg, tzname, abbr, utc_offset)
t = time_class.now(in: tzarg)
assert_equal(tz, t.zone)
@@ -681,6 +695,13 @@ module TestTimeTZ::WithTZ
assert_equal(t.dst?, t2.dst?)
end
+ def subtest_fractional_second(time_class, tz, tzarg, tzname, abbr, utc_offset)
+ t = time_class.new(2024, 1, 1, 23, 59, 59.9r, tzarg)
+ assert_equal(utc_offset[t.dst? ? 1 : 0], t.utc_offset)
+ t = time_class.new(2024, 7, 1, 23, 59, 59.9r, tzarg)
+ assert_equal(utc_offset[t.dst? ? 1 : 0], t.utc_offset)
+ end
+
def test_invalid_zone
make_timezone("INVALID", "INV", 0)
rescue => e
@@ -705,6 +726,7 @@ module TestTimeTZ::WithTZ
"Asia/Tokyo" => ["JST", +9*3600],
"America/Los_Angeles" => ["PST", -8*3600, "PDT", -7*3600],
"Africa/Ndjamena" => ["WAT", +1*3600],
+ "Etc/UTC" => ["UTC", 0],
}
def make_timezone(tzname, abbr, utc_offset, abbr2 = nil, utc_offset2 = nil)
diff --git a/test/ruby/test_transcode.rb b/test/ruby/test_transcode.rb
index c8b0034e06..63d37f4ba4 100644
--- a/test/ruby/test_transcode.rb
+++ b/test/ruby/test_transcode.rb
@@ -10,9 +10,9 @@ class TestTranscode < Test::Unit::TestCase
assert_raise(Encoding::ConverterNotFoundError) { 'abc'.encode!('foo', 'bar') }
assert_raise(Encoding::ConverterNotFoundError) { 'abc'.force_encoding('utf-8').encode('foo') }
assert_raise(Encoding::ConverterNotFoundError) { 'abc'.force_encoding('utf-8').encode!('foo') }
- assert_raise(Encoding::UndefinedConversionError) { "\x80".encode('utf-8','ASCII-8BIT') }
- assert_raise(Encoding::InvalidByteSequenceError) { "\x80".encode('utf-8','US-ASCII') }
- assert_raise(Encoding::UndefinedConversionError) { "\xA5".encode('utf-8','iso-8859-3') }
+ assert_undefined_in("\x80", 'ASCII-8BIT')
+ assert_invalid_in("\x80", 'US-ASCII')
+ assert_undefined_in("\xA5", 'iso-8859-3')
assert_raise(FrozenError) { 'hello'.freeze.encode!('iso-8859-1') }
assert_raise(FrozenError) { '\u3053\u3093\u306b\u3061\u306f'.freeze.encode!('iso-8859-1') } # ã“ã‚“ã«ã¡ã¯
end
@@ -52,16 +52,6 @@ class TestTranscode < Test::Unit::TestCase
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),utf8.dump+raw.dump)
- assert_equal(raw.force_encoding(encoding), utf8.encode(encoding, 'utf-8'))
- end
-
- def check_both_ways2(str1, enc1, str2, enc2)
- assert_equal(str1.force_encoding(enc1), str2.encode(enc1, enc2))
- assert_equal(str2.force_encoding(enc2), str1.encode(enc2, enc1))
- end
-
def test_encoding_of_ascii_originating_from_binary
binary_string = [0x82, 0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20,
0x61, 0x20, 0x76, 0x65, 0x72, 0x79, 0x20, 0x6c, 0x6f,
@@ -188,16 +178,16 @@ class TestTranscode < Test::Unit::TestCase
def test_windows_874
check_both_ways("\u20AC", "\x80", 'windows-874') # €
- assert_raise(Encoding::UndefinedConversionError) { "\x81".encode("utf-8", 'windows-874') }
- assert_raise(Encoding::UndefinedConversionError) { "\x84".encode("utf-8", 'windows-874') }
+ assert_undefined_in("\x81", 'windows-874')
+ assert_undefined_in("\x84", 'windows-874')
check_both_ways("\u2026", "\x85", 'windows-874') # …
- assert_raise(Encoding::UndefinedConversionError) { "\x86".encode("utf-8", 'windows-874') }
- assert_raise(Encoding::UndefinedConversionError) { "\x8F".encode("utf-8", 'windows-874') }
- assert_raise(Encoding::UndefinedConversionError) { "\x90".encode("utf-8", 'windows-874') }
+ assert_undefined_in("\x86", 'windows-874')
+ assert_undefined_in("\x8F", 'windows-874')
+ assert_undefined_in("\x90", 'windows-874')
check_both_ways("\u2018", "\x91", 'windows-874') # ‘
check_both_ways("\u2014", "\x97", 'windows-874') # —
- assert_raise(Encoding::UndefinedConversionError) { "\x98".encode("utf-8", 'windows-874') }
- assert_raise(Encoding::UndefinedConversionError) { "\x9F".encode("utf-8", 'windows-874') }
+ assert_undefined_in("\x98", 'windows-874')
+ assert_undefined_in("\x9F", 'windows-874')
check_both_ways("\u00A0", "\xA0", 'windows-874') # non-breaking space
check_both_ways("\u0E0F", "\xAF", 'windows-874') # à¸
check_both_ways("\u0E10", "\xB0", 'windows-874') # à¸
@@ -206,31 +196,31 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u0E2F", "\xCF", 'windows-874') # ฯ
check_both_ways("\u0E30", "\xD0", 'windows-874') # ะ
check_both_ways("\u0E3A", "\xDA", 'windows-874') # ฺ
- assert_raise(Encoding::UndefinedConversionError) { "\xDB".encode("utf-8", 'windows-874') }
- assert_raise(Encoding::UndefinedConversionError) { "\xDE".encode("utf-8", 'windows-874') }
+ assert_undefined_in("\xDB", 'windows-874')
+ assert_undefined_in("\xDE", 'windows-874')
check_both_ways("\u0E3F", "\xDF", 'windows-874') # ฿
check_both_ways("\u0E40", "\xE0", 'windows-874') # เ
check_both_ways("\u0E4F", "\xEF", 'windows-874') # à¹
check_both_ways("\u0E50", "\xF0", 'windows-874') # à¹
check_both_ways("\u0E5B", "\xFB", 'windows-874') # ๛
- assert_raise(Encoding::UndefinedConversionError) { "\xFC".encode("utf-8", 'windows-874') }
- assert_raise(Encoding::UndefinedConversionError) { "\xFF".encode("utf-8", 'windows-874') }
+ assert_undefined_in("\xFC", 'windows-874')
+ assert_undefined_in("\xFF", 'windows-874')
end
def test_windows_1250
check_both_ways("\u20AC", "\x80", 'windows-1250') # €
- assert_raise(Encoding::UndefinedConversionError) { "\x81".encode("utf-8", 'windows-1250') }
+ assert_undefined_in("\x81", 'windows-1250')
check_both_ways("\u201A", "\x82", 'windows-1250') # ‚
- assert_raise(Encoding::UndefinedConversionError) { "\x83".encode("utf-8", 'windows-1250') }
+ assert_undefined_in("\x83", 'windows-1250')
check_both_ways("\u201E", "\x84", 'windows-1250') # „
check_both_ways("\u2021", "\x87", 'windows-1250') # ‡
- assert_raise(Encoding::UndefinedConversionError) { "\x88".encode("utf-8", 'windows-1250') }
+ assert_undefined_in("\x88", 'windows-1250')
check_both_ways("\u2030", "\x89", 'windows-1250') # ‰
check_both_ways("\u0179", "\x8F", 'windows-1250') # Ź
- assert_raise(Encoding::UndefinedConversionError) { "\x90".encode("utf-8", 'windows-1250') }
+ assert_undefined_in("\x90", 'windows-1250')
check_both_ways("\u2018", "\x91", 'windows-1250') # ‘
check_both_ways("\u2014", "\x97", 'windows-1250') # —
- assert_raise(Encoding::UndefinedConversionError) { "\x98".encode("utf-8", 'windows-1250') }
+ assert_undefined_in("\x98", 'windows-1250')
check_both_ways("\u2122", "\x99", 'windows-1250') # â„¢
check_both_ways("\u00A0", "\xA0", 'windows-1250') # non-breaking space
check_both_ways("\u017B", "\xAF", 'windows-1250') # Å»
@@ -251,7 +241,7 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u20AC", "\x88", 'windows-1251') # €
check_both_ways("\u040F", "\x8F", 'windows-1251') # Ð
check_both_ways("\u0452", "\x90", 'windows-1251') # Ñ’
- assert_raise(Encoding::UndefinedConversionError) { "\x98".encode("utf-8", 'windows-1251') }
+ assert_undefined_in("\x98", 'windows-1251')
check_both_ways("\u045F", "\x9F", 'windows-1251') # ÑŸ
check_both_ways("\u00A0", "\xA0", 'windows-1251') # non-breaking space
check_both_ways("\u0407", "\xAF", 'windows-1251') # Ї
@@ -269,16 +259,16 @@ class TestTranscode < Test::Unit::TestCase
def test_windows_1252
check_both_ways("\u20AC", "\x80", 'windows-1252') # €
- assert_raise(Encoding::UndefinedConversionError) { "\x81".encode("utf-8", 'windows-1252') }
+ assert_undefined_in("\x81", 'windows-1252')
check_both_ways("\u201A", "\x82", 'windows-1252') # ‚
check_both_ways("\u0152", "\x8C", 'windows-1252') # >Å’
- assert_raise(Encoding::UndefinedConversionError) { "\x8D".encode("utf-8", 'windows-1252') }
+ assert_undefined_in("\x8D", 'windows-1252')
check_both_ways("\u017D", "\x8E", 'windows-1252') # Ž
- assert_raise(Encoding::UndefinedConversionError) { "\x8F".encode("utf-8", 'windows-1252') }
- assert_raise(Encoding::UndefinedConversionError) { "\x90".encode("utf-8", 'windows-1252') }
+ assert_undefined_in("\x8F", 'windows-1252')
+ assert_undefined_in("\x90", 'windows-1252')
check_both_ways("\u2018", "\x91", 'windows-1252') #‘
check_both_ways("\u0153", "\x9C", 'windows-1252') # Å“
- assert_raise(Encoding::UndefinedConversionError) { "\x9D".encode("utf-8", 'windows-1252') }
+ assert_undefined_in("\x9D", 'windows-1252')
check_both_ways("\u017E", "\x9E", 'windows-1252') # ž
check_both_ways("\u00A0", "\xA0", 'windows-1252') # non-breaking space
check_both_ways("\u00AF", "\xAF", 'windows-1252') # ¯
@@ -296,24 +286,24 @@ class TestTranscode < Test::Unit::TestCase
def test_windows_1253
check_both_ways("\u20AC", "\x80", 'windows-1253') # €
- assert_raise(Encoding::UndefinedConversionError) { "\x81".encode("utf-8", 'windows-1253') }
+ assert_undefined_in("\x81", 'windows-1253')
check_both_ways("\u201A", "\x82", 'windows-1253') # ‚
check_both_ways("\u2021", "\x87", 'windows-1253') # ‡
- assert_raise(Encoding::UndefinedConversionError) { "\x88".encode("utf-8", 'windows-1253') }
+ assert_undefined_in("\x88", 'windows-1253')
check_both_ways("\u2030", "\x89", 'windows-1253') # ‰
- assert_raise(Encoding::UndefinedConversionError) { "\x8A".encode("utf-8", 'windows-1253') }
+ assert_undefined_in("\x8A", 'windows-1253')
check_both_ways("\u2039", "\x8B", 'windows-1253') # ‹
- assert_raise(Encoding::UndefinedConversionError) { "\x8C".encode("utf-8", 'windows-1253') }
- assert_raise(Encoding::UndefinedConversionError) { "\x8F".encode("utf-8", 'windows-1253') }
- assert_raise(Encoding::UndefinedConversionError) { "\x90".encode("utf-8", 'windows-1253') }
+ assert_undefined_in("\x8C", 'windows-1253')
+ assert_undefined_in("\x8F", 'windows-1253')
+ assert_undefined_in("\x90", 'windows-1253')
check_both_ways("\u2018", "\x91", 'windows-1253') # ‘
check_both_ways("\u2014", "\x97", 'windows-1253') # —
- assert_raise(Encoding::UndefinedConversionError) { "\x98".encode("utf-8", 'windows-1253') }
+ assert_undefined_in("\x98", 'windows-1253')
check_both_ways("\u2122", "\x99", 'windows-1253') # â„¢
- assert_raise(Encoding::UndefinedConversionError) { "\x9A".encode("utf-8", 'windows-1253') }
+ assert_undefined_in("\x9A", 'windows-1253')
check_both_ways("\u203A", "\x9B", 'windows-1253') # ›
- assert_raise(Encoding::UndefinedConversionError) { "\x9C".encode("utf-8", 'windows-1253') }
- assert_raise(Encoding::UndefinedConversionError) { "\x9F".encode("utf-8", 'windows-1253') }
+ assert_undefined_in("\x9C", 'windows-1253')
+ assert_undefined_in("\x9F", 'windows-1253')
check_both_ways("\u00A0", "\xA0", 'windows-1253') # non-breaking space
check_both_ways("\u2015", "\xAF", 'windows-1253') # ―
check_both_ways("\u00B0", "\xB0", 'windows-1253') # °
@@ -322,28 +312,28 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u039F", "\xCF", 'windows-1253') # Ο
check_both_ways("\u03A0", "\xD0", 'windows-1253') # Π
check_both_ways("\u03A1", "\xD1", 'windows-1253') # Ρ
- assert_raise(Encoding::UndefinedConversionError) { "\xD2".encode("utf-8", 'windows-1253') }
+ assert_undefined_in("\xD2", 'windows-1253')
check_both_ways("\u03A3", "\xD3", 'windows-1253') # Σ
check_both_ways("\u03AF", "\xDF", 'windows-1253') # ί
check_both_ways("\u03B0", "\xE0", 'windows-1253') # ΰ
check_both_ways("\u03BF", "\xEF", 'windows-1253') # ο
check_both_ways("\u03C0", "\xF0", 'windows-1253') # π
check_both_ways("\u03CE", "\xFE", 'windows-1253') # ÏŽ
- assert_raise(Encoding::UndefinedConversionError) { "\xFF".encode("utf-8", 'windows-1253') }
+ assert_undefined_in("\xFF", 'windows-1253')
end
def test_windows_1254
check_both_ways("\u20AC", "\x80", 'windows-1254') # €
- assert_raise(Encoding::UndefinedConversionError) { "\x81".encode("utf-8", 'windows-1254') }
+ assert_undefined_in("\x81", 'windows-1254')
check_both_ways("\u201A", "\x82", 'windows-1254') # ‚
check_both_ways("\u0152", "\x8C", 'windows-1254') # Å’
- assert_raise(Encoding::UndefinedConversionError) { "\x8D".encode("utf-8", 'windows-1254') }
- assert_raise(Encoding::UndefinedConversionError) { "\x8F".encode("utf-8", 'windows-1254') }
- assert_raise(Encoding::UndefinedConversionError) { "\x90".encode("utf-8", 'windows-1254') }
+ assert_undefined_in("\x8D", 'windows-1254')
+ assert_undefined_in("\x8F", 'windows-1254')
+ assert_undefined_in("\x90", 'windows-1254')
check_both_ways("\u2018", "\x91", 'windows-1254') # ‘
check_both_ways("\u0153", "\x9C", 'windows-1254') # Å“
- assert_raise(Encoding::UndefinedConversionError) { "\x9D".encode("utf-8", 'windows-1254') }
- assert_raise(Encoding::UndefinedConversionError) { "\x9E".encode("utf-8", 'windows-1254') }
+ assert_undefined_in("\x9D", 'windows-1254')
+ assert_undefined_in("\x9E", 'windows-1254')
check_both_ways("\u0178", "\x9F", 'windows-1254') # Ÿ
check_both_ways("\u00A0", "\xA0", 'windows-1254') # non-breaking space
check_both_ways("\u00AF", "\xAF", 'windows-1254') # ¯
@@ -361,20 +351,20 @@ class TestTranscode < Test::Unit::TestCase
def test_windows_1255
check_both_ways("\u20AC", "\x80", 'windows-1255') # €
- assert_raise(Encoding::UndefinedConversionError) { "\x81".encode("utf-8", 'windows-1255') }
+ assert_undefined_in("\x81", 'windows-1255')
check_both_ways("\u201A", "\x82", 'windows-1255') # ‚
check_both_ways("\u2030", "\x89", 'windows-1255') # ‰
- assert_raise(Encoding::UndefinedConversionError) { "\x8A".encode("utf-8", 'windows-1255') }
+ assert_undefined_in("\x8A", 'windows-1255')
check_both_ways("\u2039", "\x8B", 'windows-1255') # ‹
- assert_raise(Encoding::UndefinedConversionError) { "\x8C".encode("utf-8", 'windows-1255') }
- assert_raise(Encoding::UndefinedConversionError) { "\x8F".encode("utf-8", 'windows-1255') }
- assert_raise(Encoding::UndefinedConversionError) { "\x90".encode("utf-8", 'windows-1255') }
+ assert_undefined_in("\x8C", 'windows-1255')
+ assert_undefined_in("\x8F", 'windows-1255')
+ assert_undefined_in("\x90", 'windows-1255')
check_both_ways("\u2018", "\x91", 'windows-1255') # ‘
check_both_ways("\u2122", "\x99", 'windows-1255') # â„¢
- assert_raise(Encoding::UndefinedConversionError) { "\x9A".encode("utf-8", 'windows-1255') }
+ assert_undefined_in("\x9A", 'windows-1255')
check_both_ways("\u203A", "\x9B", 'windows-1255') # ›
- assert_raise(Encoding::UndefinedConversionError) { "\x9C".encode("utf-8", 'windows-1255') }
- assert_raise(Encoding::UndefinedConversionError) { "\x9F".encode("utf-8", 'windows-1255') }
+ assert_undefined_in("\x9C", 'windows-1255')
+ assert_undefined_in("\x9F", 'windows-1255')
check_both_ways("\u00A0", "\xA0", 'windows-1255') # non-breaking space
check_both_ways("\u00A1", "\xA1", 'windows-1255') # ¡
check_both_ways("\u00D7", "\xAA", 'windows-1255') # ×
@@ -391,17 +381,17 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u05C0", "\xD0", 'windows-1255') # ×€
check_both_ways("\u05F3", "\xD7", 'windows-1255') # ׳
check_both_ways("\u05F4", "\xD8", 'windows-1255') # ×´
- assert_raise(Encoding::UndefinedConversionError) { "\xD9".encode("utf-8", 'windows-1255') }
- assert_raise(Encoding::UndefinedConversionError) { "\xDF".encode("utf-8", 'windows-1255') }
+ assert_undefined_in("\xD9", 'windows-1255')
+ assert_undefined_in("\xDF", 'windows-1255')
check_both_ways("\u05D0", "\xE0", 'windows-1255') # ×
check_both_ways("\u05DF", "\xEF", 'windows-1255') # ן
check_both_ways("\u05E0", "\xF0", 'windows-1255') # × 
check_both_ways("\u05EA", "\xFA", 'windows-1255') # ת
- assert_raise(Encoding::UndefinedConversionError) { "\xFB".encode("utf-8", 'windows-1255') }
- assert_raise(Encoding::UndefinedConversionError) { "\xFC".encode("utf-8", 'windows-1255') }
+ assert_undefined_in("\xFB", 'windows-1255')
+ assert_undefined_in("\xFC", 'windows-1255')
check_both_ways("\u200E", "\xFD", 'windows-1255') # left-to-right mark
check_both_ways("\u200F", "\xFE", 'windows-1255') # right-to-left mark
- assert_raise(Encoding::UndefinedConversionError) { "\xFF".encode("utf-8", 'windows-1255') }
+ assert_undefined_in("\xFF", 'windows-1255')
end
def test_windows_1256
@@ -429,35 +419,35 @@ class TestTranscode < Test::Unit::TestCase
def test_windows_1257
check_both_ways("\u20AC", "\x80", 'windows-1257') # €
- assert_raise(Encoding::UndefinedConversionError) { "\x81".encode("utf-8", 'windows-1257') }
+ assert_undefined_in("\x81", 'windows-1257')
check_both_ways("\u201A", "\x82", 'windows-1257') # ‚
- assert_raise(Encoding::UndefinedConversionError) { "\x83".encode("utf-8", 'windows-1257') }
+ assert_undefined_in("\x83", 'windows-1257')
check_both_ways("\u201E", "\x84", 'windows-1257') # „
check_both_ways("\u2021", "\x87", 'windows-1257') # ‡
- assert_raise(Encoding::UndefinedConversionError) { "\x88".encode("utf-8", 'windows-1257') }
+ assert_undefined_in("\x88", 'windows-1257')
check_both_ways("\u2030", "\x89", 'windows-1257') # ‰
- assert_raise(Encoding::UndefinedConversionError) { "\x8A".encode("utf-8", 'windows-1257') }
+ assert_undefined_in("\x8A", 'windows-1257')
check_both_ways("\u2039", "\x8B", 'windows-1257') # ‹
- assert_raise(Encoding::UndefinedConversionError) { "\x8C".encode("utf-8", 'windows-1257') }
+ assert_undefined_in("\x8C", 'windows-1257')
check_both_ways("\u00A8", "\x8D", 'windows-1257') # ¨
check_both_ways("\u02C7", "\x8E", 'windows-1257') # ˇ
check_both_ways("\u00B8", "\x8F", 'windows-1257') # ¸
- assert_raise(Encoding::UndefinedConversionError) { "\x90".encode("utf-8", 'windows-1257') }
+ assert_undefined_in("\x90", 'windows-1257')
check_both_ways("\u2018", "\x91", 'windows-1257') # ‘
check_both_ways("\u2014", "\x97", 'windows-1257') # —
- assert_raise(Encoding::UndefinedConversionError) { "\x98".encode("utf-8", 'windows-1257') }
+ assert_undefined_in("\x98", 'windows-1257')
check_both_ways("\u2122", "\x99", 'windows-1257') # â„¢
- assert_raise(Encoding::UndefinedConversionError) { "\x9A".encode("utf-8", 'windows-1257') }
+ assert_undefined_in("\x9A", 'windows-1257')
check_both_ways("\u203A", "\x9B", 'windows-1257') # ›
- assert_raise(Encoding::UndefinedConversionError) { "\x9C".encode("utf-8", 'windows-1257') }
+ assert_undefined_in("\x9C", 'windows-1257')
check_both_ways("\u00AF", "\x9D", 'windows-1257') # ¯
check_both_ways("\u02DB", "\x9E", 'windows-1257') # Ë›
- assert_raise(Encoding::UndefinedConversionError) { "\x9F".encode("utf-8", 'windows-1257') }
+ assert_undefined_in("\x9F", 'windows-1257')
check_both_ways("\u00A0", "\xA0", 'windows-1257') # non-breaking space
- assert_raise(Encoding::UndefinedConversionError) { "\xA1".encode("utf-8", 'windows-1257') }
+ assert_undefined_in("\xA1", 'windows-1257')
check_both_ways("\u00A2", "\xA2", 'windows-1257') # ¢
check_both_ways("\u00A4", "\xA4", 'windows-1257') # ¤
- assert_raise(Encoding::UndefinedConversionError) { "\xA5".encode("utf-8", 'windows-1257') }
+ assert_undefined_in("\xA5", 'windows-1257')
check_both_ways("\u00A6", "\xA6", 'windows-1257') # ¦
check_both_ways("\u00C6", "\xAF", 'windows-1257') # Æ
check_both_ways("\u00B0", "\xB0", 'windows-1257') # °
@@ -492,9 +482,9 @@ class TestTranscode < Test::Unit::TestCase
end
def test_IBM720
- assert_raise(Encoding::UndefinedConversionError) { "\x80".encode("utf-8", 'IBM720') }
- assert_raise(Encoding::UndefinedConversionError) { "\x8F".encode("utf-8", 'IBM720') }
- assert_raise(Encoding::UndefinedConversionError) { "\x90".encode("utf-8", 'IBM720') }
+ assert_undefined_in("\x80", 'IBM720')
+ assert_undefined_in("\x8F", 'IBM720')
+ assert_undefined_in("\x90", 'IBM720')
check_both_ways("\u0627", "\x9F", 'IBM720') # ا
check_both_ways("\u0628", "\xA0", 'IBM720') # ب
check_both_ways("\u00BB", "\xAF", 'IBM720') # »
@@ -580,17 +570,17 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u00A4", "\xCF", 'IBM857') # ¤
check_both_ways("\u00BA", "\xD0", 'IBM857') # º
check_both_ways("\u00C8", "\xD4", 'IBM857') # È
- assert_raise(Encoding::UndefinedConversionError) { "\xD5".encode("utf-8", 'IBM857') }
+ assert_undefined_in("\xD5", 'IBM857')
check_both_ways("\u00CD", "\xD6", 'IBM857') # Ã
check_both_ways("\u2580", "\xDF", 'IBM857') # â–€
check_both_ways("\u00D3", "\xE0", 'IBM857') # Ó
check_both_ways("\u00B5", "\xE6", 'IBM857') # µ
- assert_raise(Encoding::UndefinedConversionError) { "\xE7".encode("utf-8", 'IBM857') }
+ assert_undefined_in("\xE7", 'IBM857')
check_both_ways("\u00D7", "\xE8", 'IBM857') # ×
check_both_ways("\u00B4", "\xEF", 'IBM857') # ´
check_both_ways("\u00AD", "\xF0", 'IBM857') # soft hyphen
check_both_ways("\u00B1", "\xF1", 'IBM857') # ±
- assert_raise(Encoding::UndefinedConversionError) { "\xF2".encode("utf-8", 'IBM857') }
+ assert_undefined_in("\xF2", 'IBM857')
check_both_ways("\u00BE", "\xF3", 'IBM857') # ¾
check_both_ways("\u00A0", "\xFF", 'IBM857') # non-breaking space
end
@@ -671,6 +661,25 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u00A0", "\xFF", 'IBM863') # non-breaking space
end
+ def test_IBM864
+ check_both_ways("\u00B0", "\x80", 'IBM864') # °
+ check_both_ways("\u2518", "\x8F", 'IBM864') # ┘
+ check_both_ways("\u03B2", "\x90", 'IBM864') # β
+ check_both_ways("\uFE73", "\x9F", 'IBM864') # ï¹³
+ check_both_ways("\u00A0", "\xA0", 'IBM864') # non-breaking space
+ check_both_ways("\uFEA5", "\xAF", 'IBM864') # ﺥ
+ check_both_ways("\u0660", "\xB0", 'IBM864') # Ù 
+ check_both_ways("\u061F", "\xBF", 'IBM864') # ØŸ
+ check_both_ways("\u00A2", "\xC0", 'IBM864') # ¢
+ check_both_ways("\uFEA9", "\xCF", 'IBM864') # ﺩ
+ check_both_ways("\uFEAB", "\xD0", 'IBM864') # ﺫ
+ check_both_ways("\uFEC9", "\xDF", 'IBM864') # ﻉ
+ check_both_ways("\u0640", "\xE0", 'IBM864') # Ù€
+ check_both_ways("\uFEE1", "\xEF", 'IBM864') # ﻡ
+ check_both_ways("\uFE7D", "\xF0", 'IBM864') # ï¹½
+ check_both_ways("\u25A0", "\xFE", 'IBM864') # â– 
+ end
+
def test_IBM865
check_both_ways("\u00C7", "\x80", 'IBM865') # Ç
check_both_ways("\u00C5", "\x8F", 'IBM865') # Ã…
@@ -710,16 +719,16 @@ class TestTranscode < Test::Unit::TestCase
end
def test_IBM869
- assert_raise(Encoding::UndefinedConversionError) { "\x80".encode("utf-8", 'IBM869') }
- assert_raise(Encoding::UndefinedConversionError) { "\x85".encode("utf-8", 'IBM869') }
+ assert_undefined_in("\x80", 'IBM869')
+ assert_undefined_in("\x85", 'IBM869')
check_both_ways("\u0386", "\x86", 'IBM869') # Ά
- assert_raise(Encoding::UndefinedConversionError) { "\x87".encode("utf-8", 'IBM869') }
+ assert_undefined_in("\x87", 'IBM869')
check_both_ways("\u00B7", "\x88", 'IBM869') # ·
check_both_ways("\u0389", "\x8F", 'IBM869') # Ή
check_both_ways("\u038A", "\x90", 'IBM869') # Ί
check_both_ways("\u038C", "\x92", 'IBM869') # Ό
- assert_raise(Encoding::UndefinedConversionError) { "\x93".encode("utf-8", 'IBM869') }
- assert_raise(Encoding::UndefinedConversionError) { "\x94".encode("utf-8", 'IBM869') }
+ assert_undefined_in("\x93", 'IBM869')
+ assert_undefined_in("\x94", 'IBM869')
check_both_ways("\u038E", "\x95", 'IBM869') # ÎŽ
check_both_ways("\u03AF", "\x9F", 'IBM869') # ί
check_both_ways("\u03CA", "\xA0", 'IBM869') # ÏŠ
@@ -808,7 +817,7 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u03BF", "\xEF", 'macGreek') # ο
check_both_ways("\u03C0", "\xF0", 'macGreek') # π
check_both_ways("\u03B0", "\xFE", 'macGreek') # ΰ
- assert_raise(Encoding::UndefinedConversionError) { "\xFF".encode("utf-8", 'macGreek') }
+ assert_undefined_in("\xFF", 'macGreek')
end
def test_macIceland
@@ -887,7 +896,7 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u00D4", "\xEF", 'macTurkish') # Ô
#check_both_ways("\uF8FF", "\xF0", 'macTurkish') # Apple logo
check_both_ways("\u00D9", "\xF4", 'macTurkish') # Ù
- assert_raise(Encoding::UndefinedConversionError) { "\xF5".encode("utf-8", 'macTurkish') }
+ assert_undefined_in("\xF5", 'macTurkish')
check_both_ways("\u02C6", "\xF6", 'macTurkish') # ˆ
check_both_ways("\u02C7", "\xFF", 'macTurkish') # ˇ
end
@@ -958,11 +967,11 @@ class TestTranscode < Test::Unit::TestCase
end
def test_TIS_620
- assert_raise(Encoding::UndefinedConversionError) { "\x80".encode("utf-8", 'TIS-620') }
- assert_raise(Encoding::UndefinedConversionError) { "\x8F".encode("utf-8", 'TIS-620') }
- assert_raise(Encoding::UndefinedConversionError) { "\x90".encode("utf-8", 'TIS-620') }
- assert_raise(Encoding::UndefinedConversionError) { "\x9F".encode("utf-8", 'TIS-620') }
- assert_raise(Encoding::UndefinedConversionError) { "\xA0".encode("utf-8", 'TIS-620') }
+ assert_undefined_in("\x80", 'TIS-620')
+ assert_undefined_in("\x8F", 'TIS-620')
+ assert_undefined_in("\x90", 'TIS-620')
+ assert_undefined_in("\x9F", 'TIS-620')
+ assert_undefined_in("\xA0", 'TIS-620')
check_both_ways("\u0E01", "\xA1", 'TIS-620') # à¸
check_both_ways("\u0E0F", "\xAF", 'TIS-620') # à¸
check_both_ways("\u0E10", "\xB0", 'TIS-620') # à¸
@@ -971,15 +980,15 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u0E2F", "\xCF", 'TIS-620') # ฯ
check_both_ways("\u0E30", "\xD0", 'TIS-620') # ะ
check_both_ways("\u0E3A", "\xDA", 'TIS-620') # ฺ
- assert_raise(Encoding::UndefinedConversionError) { "\xDB".encode("utf-8", 'TIS-620') }
- assert_raise(Encoding::UndefinedConversionError) { "\xDE".encode("utf-8", 'TIS-620') }
+ assert_undefined_in("\xDB", 'TIS-620')
+ assert_undefined_in("\xDE", 'TIS-620')
check_both_ways("\u0E3F", "\xDF", 'TIS-620') # ฿
check_both_ways("\u0E40", "\xE0", 'TIS-620') # เ
check_both_ways("\u0E4F", "\xEF", 'TIS-620') # à¹
check_both_ways("\u0E50", "\xF0", 'TIS-620') # à¹
check_both_ways("\u0E5B", "\xFB", 'TIS-620') # ๛
- assert_raise(Encoding::UndefinedConversionError) { "\xFC".encode("utf-8", 'TIS-620') }
- assert_raise(Encoding::UndefinedConversionError) { "\xFF".encode("utf-8", 'TIS-620') }
+ assert_undefined_in("\xFC", 'TIS-620')
+ assert_undefined_in("\xFF", 'TIS-620')
end
def test_CP850
@@ -1182,15 +1191,15 @@ class TestTranscode < Test::Unit::TestCase
expected = "\u{3042}\u{3044}\u{20bb7}"
assert_equal(expected, %w/fffe4230443042d8b7df/.pack("H*").encode("UTF-8","UTF-16"))
check_both_ways(expected, %w/feff30423044d842dfb7/.pack("H*"), "UTF-16")
- assert_raise(Encoding::InvalidByteSequenceError){%w/feffdfb7/.pack("H*").encode("UTF-8","UTF-16")}
- assert_raise(Encoding::InvalidByteSequenceError){%w/fffeb7df/.pack("H*").encode("UTF-8","UTF-16")}
+ assert_invalid_in(%w/feffdfb7/.pack("H*"), "UTF-16")
+ assert_invalid_in(%w/fffeb7df/.pack("H*"), "UTF-16")
end
def test_utf_32_bom
expected = "\u{3042}\u{3044}\u{20bb7}"
assert_equal(expected, %w/fffe00004230000044300000b70b0200/.pack("H*").encode("UTF-8","UTF-32"))
check_both_ways(expected, %w/0000feff000030420000304400020bb7/.pack("H*"), "UTF-32")
- assert_raise(Encoding::InvalidByteSequenceError){%w/0000feff00110000/.pack("H*").encode("UTF-8","UTF-32")}
+ assert_invalid_in(%w/0000feff00110000/.pack("H*"), "UTF-32")
end
def check_utf_32_both_ways(utf8, raw)
@@ -1372,24 +1381,24 @@ class TestTranscode < Test::Unit::TestCase
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::UndefinedConversionError) { "\xEF\x40".encode("utf-8", 'shift_jis') }
- assert_raise(Encoding::UndefinedConversionError) { "\xEF\x7E".encode("utf-8", 'shift_jis') }
- assert_raise(Encoding::UndefinedConversionError) { "\xEF\x80".encode("utf-8", 'shift_jis') }
- assert_raise(Encoding::UndefinedConversionError) { "\xEF\x9E".encode("utf-8", 'shift_jis') }
- assert_raise(Encoding::UndefinedConversionError) { "\xEF\x9F".encode("utf-8", 'shift_jis') }
- assert_raise(Encoding::UndefinedConversionError) { "\xEF\xFC".encode("utf-8", 'shift_jis') }
- assert_raise(Encoding::UndefinedConversionError) { "\xF0\x40".encode("utf-8", 'shift_jis') }
- assert_raise(Encoding::UndefinedConversionError) { "\xF0\x7E".encode("utf-8", 'shift_jis') }
- assert_raise(Encoding::UndefinedConversionError) { "\xF0\x80".encode("utf-8", 'shift_jis') }
- assert_raise(Encoding::UndefinedConversionError) { "\xF0\x9E".encode("utf-8", 'shift_jis') }
- assert_raise(Encoding::UndefinedConversionError) { "\xF0\x9F".encode("utf-8", 'shift_jis') }
- assert_raise(Encoding::UndefinedConversionError) { "\xF0\xFC".encode("utf-8", 'shift_jis') }
+ assert_undefined_in("\xEF\x40", 'shift_jis')
+ assert_undefined_in("\xEF\x7E", 'shift_jis')
+ assert_undefined_in("\xEF\x80", 'shift_jis')
+ assert_undefined_in("\xEF\x9E", 'shift_jis')
+ assert_undefined_in("\xEF\x9F", 'shift_jis')
+ assert_undefined_in("\xEF\xFC", 'shift_jis')
+ assert_undefined_in("\xF0\x40", 'shift_jis')
+ assert_undefined_in("\xF0\x7E", 'shift_jis')
+ assert_undefined_in("\xF0\x80", 'shift_jis')
+ assert_undefined_in("\xF0\x9E", 'shift_jis')
+ assert_undefined_in("\xF0\x9F", 'shift_jis')
+ assert_undefined_in("\xF0\xFC", 'shift_jis')
#check_both_ways("\u9ADC", "\xFC\x40", 'shift_jis') # 髜 (IBM extended)
- assert_raise(Encoding::UndefinedConversionError) { "\xFC\x7E".encode("utf-8", 'shift_jis') }
- assert_raise(Encoding::UndefinedConversionError) { "\xFC\x80".encode("utf-8", 'shift_jis') }
- assert_raise(Encoding::UndefinedConversionError) { "\xFC\x9E".encode("utf-8", 'shift_jis') }
- assert_raise(Encoding::UndefinedConversionError) { "\xFC\x9F".encode("utf-8", 'shift_jis') }
- assert_raise(Encoding::UndefinedConversionError) { "\xFC\xFC".encode("utf-8", 'shift_jis') }
+ assert_undefined_in("\xFC\x7E", 'shift_jis')
+ assert_undefined_in("\xFC\x80", 'shift_jis')
+ assert_undefined_in("\xFC\x9E", 'shift_jis')
+ assert_undefined_in("\xFC\x9F", 'shift_jis')
+ assert_undefined_in("\xFC\xFC", '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') # 神林義åš
@@ -1409,34 +1418,34 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u00F7", "\xA1\xE0", 'euc-jp') # ÷
check_both_ways("\u25C7", "\xA1\xFE", 'euc-jp') # â—‡
check_both_ways("\u25C6", "\xA2\xA1", 'euc-jp') # â—†
- assert_raise(Encoding::UndefinedConversionError) { "\xA2\xAF".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::UndefinedConversionError) { "\xA2\xB9".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::UndefinedConversionError) { "\xA2\xC2".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::UndefinedConversionError) { "\xA2\xC9".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::UndefinedConversionError) { "\xA2\xD1".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::UndefinedConversionError) { "\xA2\xDB".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::UndefinedConversionError) { "\xA2\xEB".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::UndefinedConversionError) { "\xA2\xF1".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::UndefinedConversionError) { "\xA2\xFA".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::UndefinedConversionError) { "\xA2\xFD".encode("utf-8", 'euc-jp') }
+ assert_undefined_in("\xA2\xAF", 'euc-jp')
+ assert_undefined_in("\xA2\xB9", 'euc-jp')
+ assert_undefined_in("\xA2\xC2", 'euc-jp')
+ assert_undefined_in("\xA2\xC9", 'euc-jp')
+ assert_undefined_in("\xA2\xD1", 'euc-jp')
+ assert_undefined_in("\xA2\xDB", 'euc-jp')
+ assert_undefined_in("\xA2\xEB", 'euc-jp')
+ assert_undefined_in("\xA2\xF1", 'euc-jp')
+ assert_undefined_in("\xA2\xFA", 'euc-jp')
+ assert_undefined_in("\xA2\xFD", 'euc-jp')
check_both_ways("\u25EF", "\xA2\xFE", 'euc-jp') # â—¯
- assert_raise(Encoding::UndefinedConversionError) { "\xA3\xAF".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::UndefinedConversionError) { "\xA3\xBA".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::UndefinedConversionError) { "\xA3\xC0".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::UndefinedConversionError) { "\xA3\xDB".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::UndefinedConversionError) { "\xA3\xE0".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::UndefinedConversionError) { "\xA3\xFB".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::UndefinedConversionError) { "\xA4\xF4".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::UndefinedConversionError) { "\xA5\xF7".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::UndefinedConversionError) { "\xA6\xB9".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::UndefinedConversionError) { "\xA6\xC0".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::UndefinedConversionError) { "\xA6\xD9".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::UndefinedConversionError) { "\xA7\xC2".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::UndefinedConversionError) { "\xA7\xD0".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::UndefinedConversionError) { "\xA7\xF2".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::UndefinedConversionError) { "\xA8\xC1".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::UndefinedConversionError) { "\xCF\xD4".encode("utf-8", 'euc-jp') }
- assert_raise(Encoding::UndefinedConversionError) { "\xCF\xFE".encode("utf-8", 'euc-jp') }
+ assert_undefined_in("\xA3\xAF", 'euc-jp')
+ assert_undefined_in("\xA3\xBA", 'euc-jp')
+ assert_undefined_in("\xA3\xC0", 'euc-jp')
+ assert_undefined_in("\xA3\xDB", 'euc-jp')
+ assert_undefined_in("\xA3\xE0", 'euc-jp')
+ assert_undefined_in("\xA3\xFB", 'euc-jp')
+ assert_undefined_in("\xA4\xF4", 'euc-jp')
+ assert_undefined_in("\xA5\xF7", 'euc-jp')
+ assert_undefined_in("\xA6\xB9", 'euc-jp')
+ assert_undefined_in("\xA6\xC0", 'euc-jp')
+ assert_undefined_in("\xA6\xD9", 'euc-jp')
+ assert_undefined_in("\xA7\xC2", 'euc-jp')
+ assert_undefined_in("\xA7\xD0", 'euc-jp')
+ assert_undefined_in("\xA7\xF2", 'euc-jp')
+ assert_undefined_in("\xA8\xC1", 'euc-jp')
+ assert_undefined_in("\xCF\xD4", 'euc-jp')
+ assert_undefined_in("\xCF\xFE", 'euc-jp')
check_both_ways("\u6A97", "\xDD\xA1", 'euc-jp') # 檗
check_both_ways("\u6BEF", "\xDD\xDF", 'euc-jp') # 毯
check_both_ways("\u9EBE", "\xDD\xE0", 'euc-jp') # 麾
@@ -1449,7 +1458,7 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u71FC", "\xDF\xFE", 'euc-jp') # 燼
check_both_ways("\u71F9", "\xE0\xA1", 'euc-jp') # 燹
check_both_ways("\u73F1", "\xE0\xFE", 'euc-jp') # ç±
- assert_raise(Encoding::UndefinedConversionError) { "\xF4\xA7".encode("utf-8", 'euc-jp') }
+ assert_undefined_in("\xF4\xA7", 'euc-jp')
#check_both_ways("\u9ADC", "\xFC\xE3", 'euc-jp') # 髜 (IBM extended)
check_both_ways("\u677E\u672C\u884C\u5F18", "\xBE\xBE\xCB\xDC\xB9\xD4\xB9\xB0", 'euc-jp') # æ¾æœ¬è¡Œå¼˜
@@ -1481,7 +1490,7 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u2127", "\xA3\xE0", 'euc-jis-2004') # ℧
check_both_ways("\u30A0", "\xA3\xFB", 'euc-jis-2004') # ã‚ 
check_both_ways("\uFF54", "\xA3\xF4", 'euc-jis-2004') # ï½”
- assert_raise(Encoding::UndefinedConversionError) { "\xA5\xF7".encode("utf-8", 'euc-jis-2004') }
+ assert_undefined_in("\xA5\xF7", 'euc-jis-2004')
check_both_ways("\u2664", "\xA6\xB9", 'euc-jis-2004') # ♤
check_both_ways("\u2663", "\xA6\xC0", 'euc-jis-2004') # ♣
check_both_ways("\u03C2", "\xA6\xD9", 'euc-jis-2004') # Ï‚
@@ -1566,33 +1575,33 @@ class TestTranscode < Test::Unit::TestCase
end
def test_eucjp_sjis_undef
- assert_raise(Encoding::UndefinedConversionError) { "\x8e\xe0".encode("Shift_JIS", "EUC-JP") }
- assert_raise(Encoding::UndefinedConversionError) { "\x8e\xfe".encode("Shift_JIS", "EUC-JP") }
- assert_raise(Encoding::UndefinedConversionError) { "\x8f\xa1\xa1".encode("Shift_JIS", "EUC-JP") }
- assert_raise(Encoding::UndefinedConversionError) { "\x8f\xa1\xfe".encode("Shift_JIS", "EUC-JP") }
- assert_raise(Encoding::UndefinedConversionError) { "\x8f\xfe\xa1".encode("Shift_JIS", "EUC-JP") }
- assert_raise(Encoding::UndefinedConversionError) { "\x8f\xfe\xfe".encode("Shift_JIS", "EUC-JP") }
-
- assert_raise(Encoding::UndefinedConversionError) { "\xf0\x40".encode("EUC-JP", "Shift_JIS") }
- assert_raise(Encoding::UndefinedConversionError) { "\xf0\x7e".encode("EUC-JP", "Shift_JIS") }
- assert_raise(Encoding::UndefinedConversionError) { "\xf0\x80".encode("EUC-JP", "Shift_JIS") }
- assert_raise(Encoding::UndefinedConversionError) { "\xf0\xfc".encode("EUC-JP", "Shift_JIS") }
- assert_raise(Encoding::UndefinedConversionError) { "\xfc\x40".encode("EUC-JP", "Shift_JIS") }
- assert_raise(Encoding::UndefinedConversionError) { "\xfc\x7e".encode("EUC-JP", "Shift_JIS") }
- assert_raise(Encoding::UndefinedConversionError) { "\xfc\x80".encode("EUC-JP", "Shift_JIS") }
- assert_raise(Encoding::UndefinedConversionError) { "\xfc\xfc".encode("EUC-JP", "Shift_JIS") }
+ assert_undefined_conversion("\x8e\xe0", "Shift_JIS", "EUC-JP")
+ assert_undefined_conversion("\x8e\xfe", "Shift_JIS", "EUC-JP")
+ assert_undefined_conversion("\x8f\xa1\xa1", "Shift_JIS", "EUC-JP")
+ assert_undefined_conversion("\x8f\xa1\xfe", "Shift_JIS", "EUC-JP")
+ assert_undefined_conversion("\x8f\xfe\xa1", "Shift_JIS", "EUC-JP")
+ assert_undefined_conversion("\x8f\xfe\xfe", "Shift_JIS", "EUC-JP")
+
+ assert_undefined_conversion("\xf0\x40", "EUC-JP", "Shift_JIS")
+ assert_undefined_conversion("\xf0\x7e", "EUC-JP", "Shift_JIS")
+ assert_undefined_conversion("\xf0\x80", "EUC-JP", "Shift_JIS")
+ assert_undefined_conversion("\xf0\xfc", "EUC-JP", "Shift_JIS")
+ assert_undefined_conversion("\xfc\x40", "EUC-JP", "Shift_JIS")
+ assert_undefined_conversion("\xfc\x7e", "EUC-JP", "Shift_JIS")
+ assert_undefined_conversion("\xfc\x80", "EUC-JP", "Shift_JIS")
+ assert_undefined_conversion("\xfc\xfc", "EUC-JP", "Shift_JIS")
end
def test_iso_2022_jp
- assert_raise(Encoding::InvalidByteSequenceError) { "\x1b(A".encode("utf-8", "iso-2022-jp") }
- assert_raise(Encoding::InvalidByteSequenceError) { "\x1b$(A".encode("utf-8", "iso-2022-jp") }
- assert_raise(Encoding::InvalidByteSequenceError) { "\x1b$C".encode("utf-8", "iso-2022-jp") }
- assert_raise(Encoding::InvalidByteSequenceError) { "\x0e".encode("utf-8", "iso-2022-jp") }
- assert_raise(Encoding::InvalidByteSequenceError) { "\x80".encode("utf-8", "iso-2022-jp") }
- assert_raise(Encoding::InvalidByteSequenceError) { "\x1b$(Dd!\x1b(B".encode("utf-8", "iso-2022-jp") }
- assert_raise(Encoding::UndefinedConversionError) { "\u9299".encode("iso-2022-jp") }
- assert_raise(Encoding::UndefinedConversionError) { "\uff71\uff72\uff73\uff74\uff75".encode("iso-2022-jp") }
- assert_raise(Encoding::InvalidByteSequenceError) { "\x1b(I12345\x1b(B".encode("utf-8", "iso-2022-jp") }
+ assert_invalid_in("\x1b(A", "iso-2022-jp")
+ assert_invalid_in("\x1b$(A", "iso-2022-jp")
+ assert_invalid_in("\x1b$C", "iso-2022-jp")
+ assert_invalid_in("\x0e", "iso-2022-jp")
+ assert_invalid_in("\x80", "iso-2022-jp")
+ assert_invalid_in("\x1b$(Dd!\x1b(B", "iso-2022-jp")
+ assert_undefined_conversion("\u9299", "iso-2022-jp")
+ assert_undefined_conversion("\uff71\uff72\uff73\uff74\uff75", "iso-2022-jp")
+ assert_invalid_in("\x1b(I12345\x1b(B", "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"),
@@ -1625,6 +1634,8 @@ class TestTranscode < Test::Unit::TestCase
assert_equal("\e$B%*!+%,%I%J!+%N!+%P%\\%^!+%Q%]%\"\e(B".force_encoding("cp50220"),
"\xB5\xDE\xB6\xDE\xC4\xDE\xC5\xDE\xC9\xDE\xCA\xDE\xCE\xDE\xCF\xDE\xCA\xDF\xCE\xDF\xB1".
encode("cp50220", "sjis"))
+ assert_equal("\e$B\x21\x23\e(I\x7E\e(B".force_encoding("cp50220"),
+ "\x8E\xA1\x8E\xFE".encode("cp50220", "cp51932"))
end
def test_iso_2022_jp_1
@@ -1655,11 +1666,11 @@ class TestTranscode < Test::Unit::TestCase
assert_equal("\u005C", "\e(J\x5C\e(B".encode("UTF-8", "ISO-2022-JP"))
assert_equal("\u005C", "\x5C".encode("stateless-ISO-2022-JP", "ISO-2022-JP"))
assert_equal("\u005C", "\e(J\x5C\e(B".encode("stateless-ISO-2022-JP", "ISO-2022-JP"))
- assert_raise(Encoding::UndefinedConversionError) { "\u00A5".encode("Shift_JIS") }
- assert_raise(Encoding::UndefinedConversionError) { "\u00A5".encode("Windows-31J") }
- assert_raise(Encoding::UndefinedConversionError) { "\u00A5".encode("EUC-JP") }
- assert_raise(Encoding::UndefinedConversionError) { "\u00A5".encode("eucJP-ms") }
- assert_raise(Encoding::UndefinedConversionError) { "\u00A5".encode("CP51932") }
+ assert_undefined_conversion("\u00A5", "Shift_JIS")
+ assert_undefined_conversion("\u00A5", "Windows-31J")
+ assert_undefined_conversion("\u00A5", "EUC-JP")
+ assert_undefined_conversion("\u00A5", "eucJP-ms")
+ assert_undefined_conversion("\u00A5", "CP51932")
# FULLWIDTH REVERSE SOLIDUS
check_both_ways("\uFF3C", "\x81\x5F", "Shift_JIS")
@@ -1680,21 +1691,21 @@ class TestTranscode < Test::Unit::TestCase
assert_equal("\u007E", "\e(J\x7E\e(B".encode("UTF-8", "ISO-2022-JP"))
assert_equal("\u007E", "\x7E".encode("stateless-ISO-2022-JP", "ISO-2022-JP"))
assert_equal("\u007E", "\e(J\x7E\e(B".encode("stateless-ISO-2022-JP", "ISO-2022-JP"))
- assert_raise(Encoding::UndefinedConversionError) { "\u203E".encode("Shift_JIS") }
- assert_raise(Encoding::UndefinedConversionError) { "\u203E".encode("Windows-31J") }
- assert_raise(Encoding::UndefinedConversionError) { "\u203E".encode("EUC-JP") }
- assert_raise(Encoding::UndefinedConversionError) { "\u203E".encode("eucJP-ms") }
- assert_raise(Encoding::UndefinedConversionError) { "\u203E".encode("CP51932") }
+ assert_undefined_conversion("\u203E", "Shift_JIS")
+ assert_undefined_conversion("\u203E", "Windows-31J")
+ assert_undefined_conversion("\u203E", "EUC-JP")
+ assert_undefined_conversion("\u203E", "eucJP-ms")
+ assert_undefined_conversion("\u203E", "CP51932")
end
def test_gb2312
check_both_ways("\u3000", "\xA1\xA1", 'GB2312') # full-width space
check_both_ways("\u3013", "\xA1\xFE", 'GB2312') # 〓
- assert_raise(Encoding::UndefinedConversionError) { "\xA2\xB0".encode("utf-8", 'GB2312') }
+ assert_undefined_in("\xA2\xB0", 'GB2312')
check_both_ways("\u2488", "\xA2\xB1", 'GB2312') # â’ˆ
- assert_raise(Encoding::UndefinedConversionError) { "\xA2\xE4".encode("utf-8", 'GB2312') }
+ assert_undefined_in("\xA2\xE4", 'GB2312')
check_both_ways("\u3220", "\xA2\xE5", 'GB2312') # ㈠
- assert_raise(Encoding::UndefinedConversionError) { "\xA2\xF0".encode("utf-8", 'GB2312') }
+ assert_undefined_in("\xA2\xF0", 'GB2312')
check_both_ways("\u2160", "\xA2\xF1", 'GB2312') # â… 
check_both_ways("\uFF01", "\xA3\xA1", 'GB2312') # ï¼
check_both_ways("\uFFE3", "\xA3\xFE", 'GB2312') # ï¿£
@@ -1705,9 +1716,9 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u0410", "\xA7\xA1", 'GB2312') # Ð
check_both_ways("\u0430", "\xA7\xD1", 'GB2312') # а
check_both_ways("\u0101", "\xA8\xA1", 'GB2312') # Ä
- assert_raise(Encoding::UndefinedConversionError) { "\xA8\xC4".encode("utf-8", 'GB2312') }
+ assert_undefined_in("\xA8\xC4", 'GB2312')
check_both_ways("\u3105", "\xA8\xC5", 'GB2312') # ã„…
- assert_raise(Encoding::UndefinedConversionError) { "\xA9\xA3".encode("utf-8", 'GB2312') }
+ assert_undefined_in("\xA9\xA3", 'GB2312')
check_both_ways("\u2500", "\xA9\xA4", 'GB2312') # ─
check_both_ways("\u554A", "\xB0\xA1", 'GB2312') # å•Š
check_both_ways("\u5265", "\xB0\xFE", 'GB2312') # 剥
@@ -1721,7 +1732,7 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u7384", "\xD0\xFE", 'GB2312') # 玄
check_both_ways("\u4F4F", "\xD7\xA1", 'GB2312') # ä½
check_both_ways("\u5EA7", "\xD7\xF9", 'GB2312') # 座
- assert_raise(Encoding::UndefinedConversionError) { "\xD7\xFA".encode("utf-8", 'GB2312') }
+ assert_undefined_in("\xD7\xFA", 'GB2312')
check_both_ways("\u647A", "\xDF\xA1", 'GB2312') # 摺
check_both_ways("\u553C", "\xDF\xFE", 'GB2312') # 唼
check_both_ways("\u5537", "\xE0\xA1", 'GB2312') # å”·
@@ -1759,48 +1770,48 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u3000", "\xA1\xA1", 'GBK') # full-width space
check_both_ways("\u3001", "\xA1\xA2", 'GBK') # ã€
check_both_ways("\u3013", "\xA1\xFE", 'GBK') # 〓
- assert_raise(Encoding::UndefinedConversionError) { "\xA2\xA0".encode("utf-8", 'GBK') }
+ assert_undefined_in("\xA2\xA0", 'GBK')
check_both_ways("\u2170", "\xA2\xA1", 'GBK') # â…°
- assert_raise(Encoding::UndefinedConversionError) { "\xA2\xB0".encode("utf-8", 'GBK') }
+ assert_undefined_in("\xA2\xB0", 'GBK')
check_both_ways("\u2488", "\xA2\xB1", 'GBK') # â’ˆ
- assert_raise(Encoding::UndefinedConversionError) { "\xA2\xE4".encode("utf-8", 'GBK') }
+ assert_undefined_in("\xA2\xE4", 'GBK')
check_both_ways("\u3220", "\xA2\xE5", 'GBK') # ㈠
- assert_raise(Encoding::UndefinedConversionError) { "\xA2\xF0".encode("utf-8", 'GBK') }
+ assert_undefined_in("\xA2\xF0", 'GBK')
check_both_ways("\u2160", "\xA2\xF1", 'GBK') # â… 
- assert_raise(Encoding::UndefinedConversionError) { "\xA3\xA0".encode("utf-8", 'GBK') }
+ assert_undefined_in("\xA3\xA0", 'GBK')
check_both_ways("\uFF01", "\xA3\xA1", 'GBK') # ï¼
check_both_ways("\uFFE3", "\xA3\xFE", 'GBK') # ï¿£
- assert_raise(Encoding::UndefinedConversionError) { "\xA4\xA0".encode("utf-8", 'GBK') }
+ assert_undefined_in("\xA4\xA0", 'GBK')
check_both_ways("\u3041", "\xA4\xA1", 'GBK') # ã
- assert_raise(Encoding::UndefinedConversionError) { "\xA5\xA0".encode("utf-8", 'GBK') }
+ assert_undefined_in("\xA5\xA0", 'GBK')
check_both_ways("\u30A1", "\xA5\xA1", 'GBK') # ã‚¡
check_both_ways("\u0391", "\xA6\xA1", 'GBK') # Α
check_both_ways("\u03B1", "\xA6\xC1", 'GBK') # α
- assert_raise(Encoding::UndefinedConversionError) { "\xA6\xED".encode("utf-8", 'GBK') }
+ assert_undefined_in("\xA6\xED", 'GBK')
check_both_ways("\uFE3B", "\xA6\xEE", 'GBK') # ︻
check_both_ways("\u0410", "\xA7\xA1", 'GBK') # Ð
check_both_ways("\u0430", "\xA7\xD1", 'GBK') # а
check_both_ways("\u02CA", "\xA8\x40", 'GBK') # ËŠ
check_both_ways("\u2587", "\xA8\x7E", 'GBK') # â–‡
- assert_raise(Encoding::UndefinedConversionError) { "\xA8\x96".encode("utf-8", 'GBK') }
+ assert_undefined_in("\xA8\x96", 'GBK')
check_both_ways("\u0101", "\xA8\xA1", 'GBK') # Ä
- assert_raise(Encoding::UndefinedConversionError) { "\xA8\xBC".encode("utf-8", 'GBK') }
- assert_raise(Encoding::UndefinedConversionError) { "\xA8\xBF".encode("utf-8", 'GBK') }
- assert_raise(Encoding::UndefinedConversionError) { "\xA8\xC4".encode("utf-8", 'GBK') }
+ assert_undefined_in("\xA8\xBC", 'GBK')
+ assert_undefined_in("\xA8\xBF", 'GBK')
+ assert_undefined_in("\xA8\xC4", 'GBK')
check_both_ways("\u3105", "\xA8\xC5", 'GBK') # ã„…
check_both_ways("\u3021", "\xA9\x40", 'GBK') # 〡
- assert_raise(Encoding::UndefinedConversionError) { "\xA9\x58".encode("utf-8", 'GBK') }
- assert_raise(Encoding::UndefinedConversionError) { "\xA9\x5B".encode("utf-8", 'GBK') }
- assert_raise(Encoding::UndefinedConversionError) { "\xA9\x5D".encode("utf-8", 'GBK') }
+ assert_undefined_in("\xA9\x58", 'GBK')
+ assert_undefined_in("\xA9\x5B", 'GBK')
+ assert_undefined_in("\xA9\x5D", 'GBK')
check_both_ways("\u3007", "\xA9\x96", 'GBK') # 〇
- assert_raise(Encoding::UndefinedConversionError) { "\xA9\xA3".encode("utf-8", 'GBK') }
+ assert_undefined_in("\xA9\xA3", 'GBK')
check_both_ways("\u2500", "\xA9\xA4", 'GBK') # ─
- assert_raise(Encoding::UndefinedConversionError) { "\xA9\xF0".encode("utf-8", 'GBK') }
+ assert_undefined_in("\xA9\xF0", 'GBK')
check_both_ways("\u7588", "\xAF\x40", 'GBK') # ç–ˆ
check_both_ways("\u7607", "\xAF\x7E", 'GBK') # 瘇
check_both_ways("\u7608", "\xAF\x80", 'GBK') # 瘈
check_both_ways("\u7644", "\xAF\xA0", 'GBK') # 癄
- assert_raise(Encoding::UndefinedConversionError) { "\xAF\xA1".encode("utf-8", 'GBK') }
+ assert_undefined_in("\xAF\xA1", 'GBK')
check_both_ways("\u7645", "\xB0\x40", 'GBK') # ç™…
check_both_ways("\u769B", "\xB0\x7E", 'GBK') # çš›
check_both_ways("\u769C", "\xB0\x80", 'GBK') # 皜
@@ -1841,10 +1852,10 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u9F78", "\xFD\x7E", 'GBK') # 齸
check_both_ways("\u9F79", "\xFD\x80", 'GBK') # é½¹
check_both_ways("\uF9F1", "\xFD\xA0", 'GBK') # 隣
- assert_raise(Encoding::UndefinedConversionError) { "\xFD\xA1".encode("utf-8", 'GBK') }
+ assert_undefined_in("\xFD\xA1", 'GBK')
check_both_ways("\uFA0C", "\xFE\x40", 'GBK') # 兀
check_both_ways("\uFA29", "\xFE\x4F", 'GBK') # 﨩
- assert_raise(Encoding::UndefinedConversionError) { "\xFE\x50".encode("utf-8", 'GBK') }
+ assert_undefined_in("\xFE\x50", 'GBK')
check_both_ways("\u9752\u5C71\u5B66\u9662\u5927\u5B66", "\xC7\xE0\xC9\xBD\xD1\xA7\xD4\xBA\xB4\xF3\xD1\xA7", 'GBK') # é’山学院大学
check_both_ways("\u795E\u6797\u7FA9\u535A", "\xC9\xF1\xC1\xD6\xC1\x78\xB2\xA9", 'GBK') # 神林義åš
end
@@ -1880,48 +1891,48 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u3000", "\xA1\xA1", 'GB18030') # full-width space
check_both_ways("\u3001", "\xA1\xA2", 'GB18030') #
check_both_ways("\u3013", "\xA1\xFE", 'GB18030') #
- #assert_raise(Encoding::UndefinedConversionError) { "\xA2\xA0".encode("utf-8", 'GB18030') }
+ #assert_undefined_in("\xA2\xA0", 'GB18030')
check_both_ways("\u2170", "\xA2\xA1", 'GB18030') # â…°
- #assert_raise(Encoding::UndefinedConversionError) { "\xA2\xB0".encode("utf-8", 'GB18030') }
+ #assert_undefined_in("\xA2\xB0", 'GB18030')
check_both_ways("\u2488", "\xA2\xB1", 'GB18030') #
- #assert_raise(Encoding::UndefinedConversionError) { "\xA2\xE4".encode("utf-8", 'GB18030') }
+ #assert_undefined_in("\xA2\xE4", 'GB18030')
check_both_ways("\u3220", "\xA2\xE5", 'GB18030') # ㈠
- #assert_raise(Encoding::UndefinedConversionError) { "\xA2\xF0".encode("utf-8", 'GB18030') }
+ #assert_undefined_in("\xA2\xF0", 'GB18030')
check_both_ways("\u2160", "\xA2\xF1", 'GB18030') # â… 
- #assert_raise(Encoding::UndefinedConversionError) { "\xA3\xA0".encode("utf-8", 'GB18030') }
+ #assert_undefined_in("\xA3\xA0", 'GB18030')
check_both_ways("\uFF01", "\xA3\xA1", 'GB18030') # E
check_both_ways("\uFFE3", "\xA3\xFE", 'GB18030') # E
- #assert_raise(Encoding::UndefinedConversionError) { "\xA4\xA0".encode("utf-8", 'GB18030') }
+ #assert_undefined_in("\xA4\xA0", 'GB18030')
check_both_ways("\u3041", "\xA4\xA1", 'GB18030') #
- #assert_raise(Encoding::UndefinedConversionError) { "\xA5\xA0".encode("utf-8", 'GB18030') }
+ #assert_undefined_in("\xA5\xA0", 'GB18030')
check_both_ways("\u30A1", "\xA5\xA1", 'GB18030') # ã‚¡
check_both_ways("\u0391", "\xA6\xA1", 'GB18030') #
check_both_ways("\u03B1", "\xA6\xC1", 'GB18030') # α
- #assert_raise(Encoding::UndefinedConversionError) { "\xA6\xED".encode("utf-8", 'GB18030') }
+ #assert_undefined_in("\xA6\xED", 'GB18030')
check_both_ways("\uFE3B", "\xA6\xEE", 'GB18030') # E
check_both_ways("\u0410", "\xA7\xA1", 'GB18030') #
check_both_ways("\u0430", "\xA7\xD1", 'GB18030') # а
check_both_ways("\u02CA", "\xA8\x40", 'GB18030') #
check_both_ways("\u2587", "\xA8\x7E", 'GB18030') #
- #assert_raise(Encoding::UndefinedConversionError) { "\xA8\x96".encode("utf-8", 'GB18030') }
+ #assert_undefined_in("\xA8\x96", 'GB18030')
check_both_ways("\u0101", "\xA8\xA1", 'GB18030') #
- #assert_raise(Encoding::UndefinedConversionError) { "\xA8\xBC".encode("utf-8", 'GB18030') }
- #assert_raise(Encoding::UndefinedConversionError) { "\xA8\xBF".encode("utf-8", 'GB18030') }
- #assert_raise(Encoding::UndefinedConversionError) { "\xA8\xC4".encode("utf-8", 'GB18030') }
+ #assert_undefined_in("\xA8\xBC", 'GB18030')
+ #assert_undefined_in("\xA8\xBF", 'GB18030')
+ #assert_undefined_in("\xA8\xC4", 'GB18030')
check_both_ways("\u3105", "\xA8\xC5", 'GB18030') #
check_both_ways("\u3021", "\xA9\x40", 'GB18030') # 〡
- #assert_raise(Encoding::UndefinedConversionError) { "\xA9\x58".encode("utf-8", 'GB18030') }
- #assert_raise(Encoding::UndefinedConversionError) { "\xA9\x5B".encode("utf-8", 'GB18030') }
- #assert_raise(Encoding::UndefinedConversionError) { "\xA9\x5D".encode("utf-8", 'GB18030') }
+ #assert_undefined_in("\xA9\x58", 'GB18030')
+ #assert_undefined_in("\xA9\x5B", 'GB18030')
+ #assert_undefined_in("\xA9\x5D", 'GB18030')
check_both_ways("\u3007", "\xA9\x96", 'GB18030') #
- #assert_raise(Encoding::UndefinedConversionError) { "\xA9\xA3".encode("utf-8", 'GB18030') }
+ #assert_undefined_in("\xA9\xA3", 'GB18030')
check_both_ways("\u2500", "\xA9\xA4", 'GB18030') # ─
- #assert_raise(Encoding::UndefinedConversionError) { "\xA9\xF0".encode("utf-8", 'GB18030') }
+ #assert_undefined_in("\xA9\xF0", 'GB18030')
check_both_ways("\u7588", "\xAF\x40", 'GB18030') #
check_both_ways("\u7607", "\xAF\x7E", 'GB18030') #
check_both_ways("\u7608", "\xAF\x80", 'GB18030') #
check_both_ways("\u7644", "\xAF\xA0", 'GB18030') #
- #assert_raise(Encoding::UndefinedConversionError) { "\xAF\xA1".encode("utf-8", 'GB18030') }
+ #assert_undefined_in("\xAF\xA1", 'GB18030')
check_both_ways("\u7645", "\xB0\x40", 'GB18030') #
check_both_ways("\u769B", "\xB0\x7E", 'GB18030') #
check_both_ways("\u769C", "\xB0\x80", 'GB18030') #
@@ -1962,10 +1973,10 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u9F78", "\xFD\x7E", 'GB18030') # 齸
check_both_ways("\u9F79", "\xFD\x80", 'GB18030') # é½¹
check_both_ways("\uF9F1", "\xFD\xA0", 'GB18030') # E
- #assert_raise(Encoding::UndefinedConversionError) { "\xFD\xA1".encode("utf-8", 'GB18030') }
+ #assert_undefined_in("\xFD\xA1", 'GB18030')
check_both_ways("\uFA0C", "\xFE\x40", 'GB18030') # E
check_both_ways("\uFA29", "\xFE\x4F", 'GB18030') # E
- #assert_raise(Encoding::UndefinedConversionError) { "\xFE\x50".encode("utf-8", 'GB18030') }
+ #assert_undefined_in("\xFE\x50", 'GB18030')
check_both_ways("\u9752\u5C71\u5B66\u9662\u5927\u5B66", "\xC7\xE0\xC9\xBD\xD1\xA7\xD4\xBA\xB4\xF3\xD1\xA7", 'GB18030') # é’山学院大学
check_both_ways("\u795E\u6797\u7FA9\u535A", "\xC9\xF1\xC1\xD6\xC1\x78\xB2\xA9", 'GB18030') # 神林義
@@ -2020,7 +2031,7 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u310F", "\xA3\x7E", 'Big5') # ã„
check_both_ways("\u3110", "\xA3\xA1", 'Big5') # ã„
check_both_ways("\u02CB", "\xA3\xBF", 'Big5') # Ë‹
- assert_raise(Encoding::UndefinedConversionError) { "\xA3\xC0".encode("utf-8", 'Big5') }
+ assert_undefined_in("\xA3\xC0", 'Big5')
check_both_ways("\u6D6C", "\xAF\x40", 'Big5') # 浬
check_both_ways("\u7837", "\xAF\x7E", 'Big5') # ç ·
check_both_ways("\u7825", "\xAF\xA1", 'Big5') # ç ¥
@@ -2039,9 +2050,9 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u77AC", "\xC0\xFE", 'Big5') # 瞬
check_both_ways("\u8B96", "\xC6\x40", 'Big5') # è®–
check_both_ways("\u7C72", "\xC6\x7E", 'Big5') # ç±²
- #assert_raise(Encoding::UndefinedConversionError) { "\xC6\xA1".encode("utf-8", 'Big5') }
- #assert_raise(Encoding::UndefinedConversionError) { "\xC7\x40".encode("utf-8", 'Big5') }
- #assert_raise(Encoding::UndefinedConversionError) { "\xC8\x40".encode("utf-8", 'Big5') }
+ #assert_undefined_in("\xC6\xA1", 'Big5')
+ #assert_undefined_in("\xC7\x40", 'Big5')
+ #assert_undefined_in("\xC8\x40", 'Big5')
check_both_ways("\u4E42", "\xC9\x40", 'Big5') # 乂
check_both_ways("\u6C15", "\xC9\x7E", 'Big5') # æ°•
check_both_ways("\u6C36", "\xC9\xA1", 'Big5') # æ°¶
@@ -2074,7 +2085,7 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u9F0A", "\xF9\x7E", 'Big5') # 鼊
check_both_ways("\u9FA4", "\xF9\xA1", 'Big5') # 龤
check_both_ways("\u9F98", "\xF9\xD5", 'Big5') # 龘
- #assert_raise(Encoding::UndefinedConversionError) { "\xF9\xD6".encode("utf-8", 'Big5') }
+ #assert_undefined_in("\xF9\xD6", 'Big5')
check_both_ways("\u795E\u6797\u7FA9\u535A", "\xAF\xAB\xAA\x4C\xB8\x71\xB3\xD5", 'Big5') # 神林義åš
end
@@ -2087,7 +2098,7 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u310F", "\xA3\x7E", 'Big5-HKSCS') # ã„
check_both_ways("\u3110", "\xA3\xA1", 'Big5-HKSCS') # ã„
check_both_ways("\u02CB", "\xA3\xBF", 'Big5-HKSCS') # Ë‹
- #assert_raise(Encoding::UndefinedConversionError) { "\xA3\xC0".encode("utf-8", 'Big5-HKSCS') }
+ #assert_undefined_in("\xA3\xC0", 'Big5-HKSCS')
check_both_ways("\u6D6C", "\xAF\x40", 'Big5-HKSCS') # 浬
check_both_ways("\u7837", "\xAF\x7E", 'Big5-HKSCS') # ç ·
check_both_ways("\u7825", "\xAF\xA1", 'Big5-HKSCS') # ç ¥
@@ -2106,9 +2117,9 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u77AC", "\xC0\xFE", 'Big5-HKSCS') # 瞬
check_both_ways("\u8B96", "\xC6\x40", 'Big5-HKSCS') # è®–
check_both_ways("\u7C72", "\xC6\x7E", 'Big5-HKSCS') # ç±²
- #assert_raise(Encoding::UndefinedConversionError) { "\xC6\xA1".encode("utf-8", 'Big5-HKSCS') }
- #assert_raise(Encoding::UndefinedConversionError) { "\xC7\x40".encode("utf-8", 'Big5-HKSCS') }
- #assert_raise(Encoding::UndefinedConversionError) { "\xC8\x40".encode("utf-8", 'Big5-HKSCS') }
+ #assert_undefined_in("\xC6\xA1", 'Big5-HKSCS')
+ #assert_undefined_in("\xC7\x40", 'Big5-HKSCS')
+ #assert_undefined_in("\xC8\x40", 'Big5-HKSCS')
check_both_ways("\u4E42", "\xC9\x40", 'Big5-HKSCS') # 乂
check_both_ways("\u6C15", "\xC9\x7E", 'Big5-HKSCS') # æ°•
check_both_ways("\u6C36", "\xC9\xA1", 'Big5-HKSCS') # æ°¶
@@ -2142,7 +2153,7 @@ class TestTranscode < Test::Unit::TestCase
check_both_ways("\u9FA4", "\xF9\xA1", 'Big5-HKSCS') # 龤
check_both_ways("\u9F98", "\xF9\xD5", 'Big5-HKSCS') # 龘
#check_both_ways("\u{23ED7}", "\x8E\x40", 'Big5-HKSCS') # 𣻗
- #assert_raise(Encoding::UndefinedConversionError) { "\xF9\xD6".encode("utf-8", 'Big5-HKSCS') }
+ #assert_undefined_in("\xF9\xD6", 'Big5-HKSCS')
check_both_ways("\u795E\u6797\u7FA9\u535A", "\xAF\xAB\xAA\x4C\xB8\x71\xB3\xD5", 'Big5-HKSCS') # 神林義åš
end
@@ -2232,12 +2243,12 @@ class TestTranscode < Test::Unit::TestCase
assert_equal("U+3042", "\u{3042}".encode("US-ASCII", fallback: fallback))
end
- bug8940 = '[ruby-core:57318] [Bug #8940]'
- %w[UTF-32 UTF-16].each do |enc|
- define_method("test_pseudo_encoding_inspect(#{enc})") do
- assert_normal_exit("'aaa'.encode('#{enc}').inspect", bug8940)
- assert_equal(4, 'aaa'.encode(enc).length, "should count in #{enc} with BOM")
- end
+ def test_pseudo_encoding_inspect
+ s = 'aaa'.encode "UTF-16"
+ assert_equal '"\xFE\xFF\x00\x61\x00\x61\x00\x61"', s.inspect
+
+ s = 'aaa'.encode "UTF-32"
+ assert_equal '"\x00\x00\xFE\xFF\x00\x00\x00\x61\x00\x00\x00\x61\x00\x00\x00\x61"', s.inspect
end
def test_encode_with_invalid_chars
@@ -2275,7 +2286,7 @@ class TestTranscode < Test::Unit::TestCase
result = th.map(&:value)
end
end
- expected = "\xa4\xa2".force_encoding(Encoding::EUC_JP)
+ expected = "\xa4\xa2".dup.force_encoding(Encoding::EUC_JP)
assert_equal([expected]*num, result, bug11277)
end;
end
@@ -2305,5 +2316,37 @@ class TestTranscode < Test::Unit::TestCase
assert_equal("A\rB\r\rC", s.encode(usascii, newline: :cr))
assert_equal("A\r\nB\r\r\nC", s.encode(usascii, crlf_newline: true))
assert_equal("A\r\nB\r\r\nC", s.encode(usascii, newline: :crlf))
+ assert_equal("A\nB\nC", s.encode(usascii, lf_newline: true))
+ assert_equal("A\nB\nC", s.encode(usascii, newline: :lf))
+ end
+
+ private
+
+ def assert_conversion_both_ways_utf8(utf8, raw, encoding)
+ assert_conversion_both_ways(utf8, 'utf-8', raw, encoding)
+ end
+ alias check_both_ways assert_conversion_both_ways_utf8
+
+ def assert_conversion_both_ways(str1, enc1, str2, enc2)
+ message = str1.dump+str2.dump
+ assert_equal(str1.force_encoding(enc1), str2.encode(enc1, enc2), message)
+ assert_equal(str2.force_encoding(enc2), str1.encode(enc2, enc1), message)
+ end
+ alias check_both_ways2 assert_conversion_both_ways
+
+ def assert_undefined_conversion(str, to, from = nil)
+ assert_raise(Encoding::UndefinedConversionError) { str.encode(to, from) }
+ end
+
+ def assert_undefined_in(str, encoding)
+ assert_undefined_conversion(str, 'utf-8', encoding)
+ end
+
+ def assert_invalid_byte_sequence(str, to, from = nil)
+ assert_raise(Encoding::InvalidByteSequenceError) { str.encode(to, from) }
+ end
+
+ def assert_invalid_in(str, encoding)
+ assert_invalid_byte_sequence(str, 'utf-8', encoding)
end
end
diff --git a/test/ruby/test_undef.rb b/test/ruby/test_undef.rb
index e0add7c3ab..074b92be55 100644
--- a/test/ruby/test_undef.rb
+++ b/test/ruby/test_undef.rb
@@ -35,4 +35,20 @@ class TestUndef < Test::Unit::TestCase
end
end
end
+
+ def test_singleton_undef
+ klass = Class.new do
+ def foo
+ :ok
+ end
+ end
+
+ klass.new.foo
+
+ klass.new.instance_eval do
+ undef foo
+ end
+
+ klass.new.foo
+ end
end
diff --git a/test/ruby/test_variable.rb b/test/ruby/test_variable.rb
index f8a7c68fd3..86f2e4bb84 100644
--- a/test/ruby/test_variable.rb
+++ b/test/ruby/test_variable.rb
@@ -33,6 +33,12 @@ class TestVariable < Test::Unit::TestCase
end
end
+ Athena = Gods.clone
+
+ def test_cloned_classes_copy_cvar_cache
+ assert_equal "Cronus", Athena.new.ruler0
+ end
+
def test_setting_class_variable_on_module_through_inheritance
mod = Module.new
mod.class_variable_set(:@@foo, 1)
@@ -43,6 +49,19 @@ class TestVariable < Test::Unit::TestCase
assert_equal(1, c.class_variable_get(:@@foo))
end
+ Zeus = Gods.clone
+
+ def test_cloned_allows_setting_cvar
+ Zeus.class_variable_set(:@@rule, "Athena")
+
+ god = Gods.new.ruler0
+ zeus = Zeus.new.ruler0
+
+ assert_equal "Cronus", god
+ assert_equal "Athena", zeus
+ assert_not_equal god.object_id, zeus.object_id
+ end
+
def test_singleton_class_included_class_variable
c = Class.new
c.extend(Olympians)
@@ -155,6 +174,21 @@ class TestVariable < Test::Unit::TestCase
end
end
+ def test_set_class_variable_on_frozen_object
+ set_cvar = EnvUtil.labeled_class("SetCVar")
+ set_cvar.class_eval "#{<<~"begin;"}\n#{<<~'end;'}"
+ begin;
+ def self.set(val)
+ @@a = val # inline cache
+ end
+ end;
+ set_cvar.set(1) # fill write cache
+ set_cvar.freeze
+ assert_raise(FrozenError, "[Bug #19341]") do
+ set_cvar.set(2) # hit write cache, but should check frozen status
+ end
+ end
+
def test_variable
assert_instance_of(Integer, $$)
@@ -232,6 +266,84 @@ class TestVariable < Test::Unit::TestCase
assert_include(gv, :$12)
end
+ def prepare_klass_for_test_svar_with_ifunc
+ Class.new do
+ include Enumerable
+ def each(&b)
+ @b = b
+ end
+
+ def check1
+ check2.merge({check1: $1})
+ end
+
+ def check2
+ @b.call('foo')
+ {check2: $1}
+ end
+ end
+ end
+
+ def test_svar_with_ifunc
+ c = prepare_klass_for_test_svar_with_ifunc
+
+ expected_check1_result = {
+ check1: nil, check2: nil
+ }.freeze
+
+ obj = c.new
+ result = nil
+ obj.grep(/(f..)/){
+ result = $1
+ }
+ assert_equal nil, result
+ assert_equal nil, $1
+ assert_equal expected_check1_result, obj.check1
+ assert_equal 'foo', result
+ assert_equal 'foo', $1
+
+ # this frame was escaped so try it again
+ $~ = nil
+ obj = c.new
+ result = nil
+ obj.grep(/(f..)/){
+ result = $1
+ }
+ assert_equal nil, result
+ assert_equal nil, $1
+ assert_equal expected_check1_result, obj.check1
+ assert_equal 'foo', result
+ assert_equal 'foo', $1
+
+ # different context
+ result = nil
+ Fiber.new{
+ obj = c.new
+ obj.grep(/(f..)/){
+ result = $1
+ }
+ }.resume # obj is created in antoher Fiber
+ assert_equal nil, result
+ assert_equal expected_check1_result, obj.check1
+ assert_equal 'foo', result
+ assert_equal 'foo', $1
+
+ # different thread context
+ result = nil
+ Thread.new{
+ obj = c.new
+ obj.grep(/(f..)/){
+ result = $1
+ }
+ }.join # obj is created in another Thread
+
+ assert_equal nil, result
+ assert_equal expected_check1_result, obj.check1
+ assert_equal 'foo', result
+ assert_equal 'foo', $1
+ end
+
+
def test_global_variable_0
assert_in_out_err(["-e", "$0='t'*1000;print $0"], "", /\At+\z/, [])
end
@@ -261,6 +373,12 @@ class TestVariable < Test::Unit::TestCase
v.instance_variable_set(:@foo, :bar)
end
+ assert_raise_with_message(FrozenError, msg, "[Bug #19339]") do
+ v.instance_eval do
+ @a = 1
+ end
+ end
+
assert_nil EnvUtil.suppress_warning {v.instance_variable_get(:@foo)}
assert_not_send([v, :instance_variable_defined?, :@foo])
@@ -295,6 +413,18 @@ class TestVariable < Test::Unit::TestCase
assert_equal(%i(v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11), v, bug11674)
end
+ def test_many_instance_variables
+ objects = [Object.new, Hash.new, Module.new]
+ objects.each do |obj|
+ 1000.times do |i|
+ obj.instance_variable_set("@var#{i}", i)
+ end
+ 1000.times do |i|
+ assert_equal(i, obj.instance_variable_get("@var#{i}"))
+ end
+ end
+ end
+
private
def with_kwargs_11(v1:, v2:, v3:, v4:, v5:, v6:, v7:, v8:, v9:, v10:, v11:)
local_variables
diff --git a/test/ruby/test_vm_dump.rb b/test/ruby/test_vm_dump.rb
index 679ce94b91..22afee7a24 100644
--- a/test/ruby/test_vm_dump.rb
+++ b/test/ruby/test_vm_dump.rb
@@ -1,14 +1,17 @@
# frozen_string_literal: true
require 'test/unit'
+return unless /darwin/ =~ RUBY_PLATFORM
+
class TestVMDump < Test::Unit::TestCase
- def assert_darwin_vm_dump_works(args)
- skip if RUBY_PLATFORM !~ /darwin/
- assert_in_out_err(args, "", [], /^\[IMPORTANT\]/)
+ def assert_darwin_vm_dump_works(args, timeout=nil)
+ pend "macOS 15 beta is not working with this assertion" if macos?(15)
+
+ assert_in_out_err(args, "", [], /^\[IMPORTANT\]/, timeout: timeout || 300)
end
def test_darwin_invalid_call
- assert_darwin_vm_dump_works(['-rfiddle', '-eFiddle::Function.new(Fiddle::Pointer.new(1), [], Fiddle::TYPE_VOID).call'])
+ assert_darwin_vm_dump_works(['-r-test-/fatal', '-eBug.invalid_call(1)'])
end
def test_darwin_segv_in_syscall
@@ -16,6 +19,6 @@ class TestVMDump < Test::Unit::TestCase
end
def test_darwin_invalid_access
- assert_darwin_vm_dump_works(['-rfiddle', '-eFiddle.dlunwrap(100).inspect'])
+ assert_darwin_vm_dump_works(['-r-test-/fatal', '-eBug.invalid_access(100)'])
end
end
diff --git a/test/ruby/test_warning.rb b/test/ruby/test_warning.rb
new file mode 100644
index 0000000000..cd220ff00f
--- /dev/null
+++ b/test/ruby/test_warning.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+require 'test/unit'
+
+class TestWarning < Test::Unit::TestCase
+ def test_warn_called_only_when_category_enabled
+ # Assert that warn is called when the category is enabled
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ Warning[:deprecated] = true
+ $warnings = []
+ def Warning.warn(msg, category:)
+ $warnings << [msg, category]
+ end
+ assert_equal(0, $warnings.length)
+ "" << 12
+ assert_equal(1, $warnings.length)
+ end;
+
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ Warning[:deprecated] = false
+ $warnings = []
+ def Warning.warn(msg, category:)
+ $warnings << [msg, category]
+ end
+ assert_equal(0, $warnings.length)
+ "" << 12
+ assert_equal(0, $warnings.length, $warnings.join)
+ end;
+ end
+end
diff --git a/test/ruby/test_weakkeymap.rb b/test/ruby/test_weakkeymap.rb
new file mode 100644
index 0000000000..91c1538076
--- /dev/null
+++ b/test/ruby/test_weakkeymap.rb
@@ -0,0 +1,159 @@
+# frozen_string_literal: false
+require 'test/unit'
+
+class TestWeakKeyMap < Test::Unit::TestCase
+ def setup
+ @wm = ObjectSpace::WeakKeyMap.new
+ end
+
+ def test_map
+ x = Object.new
+ k = "foo"
+ @wm[k] = x
+ assert_same(x, @wm[k])
+ assert_same(x, @wm["FOO".downcase])
+ end
+
+ def test_aset_const
+ x = Object.new
+ assert_raise(ArgumentError) { @wm[true] = x }
+ assert_raise(ArgumentError) { @wm[false] = x }
+ assert_raise(ArgumentError) { @wm[nil] = x }
+ assert_raise(ArgumentError) { @wm[42] = x }
+ assert_raise(ArgumentError) { @wm[2**128] = x }
+ assert_raise(ArgumentError) { @wm[1.23] = x }
+ assert_raise(ArgumentError) { @wm[:foo] = x }
+ assert_raise(ArgumentError) { @wm["foo#{rand}".to_sym] = x }
+ end
+
+ def test_getkey
+ k = "foo"
+ @wm[k] = true
+ assert_same(k, @wm.getkey("FOO".downcase))
+ end
+
+ def test_key?
+ assert_weak_include(:key?, "foo")
+ assert_not_send([@wm, :key?, "bar"])
+ end
+
+ def test_delete
+ k1 = "foo"
+ x1 = Object.new
+ @wm[k1] = x1
+ assert_equal x1, @wm[k1]
+ assert_equal x1, @wm.delete(k1)
+ assert_nil @wm[k1]
+ assert_nil @wm.delete(k1)
+
+ fallback = @wm.delete(k1) do |key|
+ assert_equal k1, key
+ 42
+ end
+ assert_equal 42, fallback
+ end
+
+ def test_clear
+ k = "foo"
+ @wm[k] = true
+ assert @wm[k]
+ assert_same @wm, @wm.clear
+ refute @wm[k]
+ end
+
+ def test_clear_bug_20691
+ assert_normal_exit(<<~RUBY)
+ map = ObjectSpace::WeakKeyMap.new
+
+ 1_000.times do
+ 1_000.times do
+ map[Object.new] = nil
+ end
+
+ map.clear
+ end
+ RUBY
+ end
+
+ def test_inspect
+ x = Object.new
+ k = Object.new
+ @wm[k] = x
+ assert_match(/\A\#<#{@wm.class.name}:[\dxa-f]+ size=\d+>\z/, @wm.inspect)
+
+ 1000.times do |i|
+ @wm[i.to_s] = Object.new
+ @wm.inspect
+ end
+ assert_match(/\A\#<#{@wm.class.name}:[\dxa-f]+ size=\d+>\z/, @wm.inspect)
+ end
+
+ def test_no_hash_method
+ k = BasicObject.new
+ assert_raise NoMethodError do
+ @wm[k] = 42
+ end
+ end
+
+ def test_frozen_object
+ o = Object.new.freeze
+ assert_nothing_raised(FrozenError) {@wm[o] = 'foo'}
+ assert_nothing_raised(FrozenError) {@wm['foo'] = o}
+ end
+
+ def test_inconsistent_hash_key_memory_leak
+ assert_no_memory_leak [], '', <<~RUBY
+ class BadHash
+ def initialize
+ @hash = 0
+ end
+
+ def hash
+ @hash += 1
+ end
+ end
+
+ k = BadHash.new
+ wm = ObjectSpace::WeakKeyMap.new
+
+ 100_000.times do |i|
+ wm[k] = i
+ end
+ RUBY
+ end
+
+ def test_compaction
+ omit "compaction is not supported on this platform" unless GC.respond_to?(:compact)
+
+ assert_separately(%w(-robjspace), <<-'end;')
+ wm = ObjectSpace::WeakKeyMap.new
+ key = Object.new
+ val = Object.new
+ wm[key] = val
+
+ GC.verify_compaction_references(expand_heap: true, toward: :empty)
+
+ assert_equal(val, wm[key])
+ end;
+ end
+
+ def test_gc_compact_stress
+ omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077
+ EnvUtil.under_gc_compact_stress { ObjectSpace::WeakKeyMap.new }
+ end
+
+ private
+
+ def assert_weak_include(m, k, n = 100)
+ if n > 0
+ return assert_weak_include(m, k, n-1)
+ end
+ 1.times do
+ x = Object.new
+ @wm[k] = x
+ assert_send([@wm, m, k])
+ assert_send([@wm, m, "FOO".downcase])
+ x = Object.new
+ end
+ end
+end
diff --git a/test/ruby/test_weakmap.rb b/test/ruby/test_weakmap.rb
index 3b9eef770a..a2904776bc 100644
--- a/test/ruby/test_weakmap.rb
+++ b/test/ruby/test_weakmap.rb
@@ -59,7 +59,7 @@ class TestWeakMap < Test::Unit::TestCase
assert_weak_include(m, k)
end
GC.start
- skip('TODO: failure introduced from r60440')
+ pend('TODO: failure introduced from 837fd5e494731d7d44786f29e7d6e8c27029806f')
assert_not_send([@wm, m, k])
end
alias test_member? test_include?
@@ -73,6 +73,31 @@ class TestWeakMap < Test::Unit::TestCase
@wm.inspect)
end
+ def test_inspect_garbage
+ 1000.times do |i|
+ @wm[i] = Object.new
+ @wm.inspect
+ end
+ assert_match(/\A\#<#{@wm.class.name}:0x[\da-f]+(?::(?: \d+ => \#<(?:Object|collected):0x[\da-f]+>,?)+)?>\z/,
+ @wm.inspect)
+ end
+
+ def test_delete
+ k1 = "foo"
+ x1 = Object.new
+ @wm[k1] = x1
+ assert_equal x1, @wm[k1]
+ assert_equal x1, @wm.delete(k1)
+ assert_nil @wm[k1]
+ assert_nil @wm.delete(k1)
+
+ fallback = @wm.delete(k1) do |key|
+ assert_equal k1, key
+ 42
+ end
+ assert_equal 42, fallback
+ end
+
def test_each
m = __callee__[/test_(.*)/, 1]
x1 = Object.new
@@ -158,4 +183,86 @@ class TestWeakMap < Test::Unit::TestCase
assert_nothing_raised(FrozenError) {@wm[o] = 'foo'}
assert_nothing_raised(FrozenError) {@wm['foo'] = o}
end
+
+ def test_no_memory_leak
+ assert_no_memory_leak([], '', "#{<<~"begin;"}\n#{<<~'end;'}", "[Bug #19398]", rss: true, limit: 1.5, timeout: 60)
+ begin;
+ 1_000_000.times do
+ ObjectSpace::WeakMap.new
+ end
+ end;
+ end
+
+ def test_compaction
+ omit "compaction is not supported on this platform" unless GC.respond_to?(:compact)
+
+ # [Bug #19529]
+ obj = Object.new
+ 100.times do |i|
+ GC.compact
+ @wm[i] = obj
+ end
+
+ assert_separately([], <<-'end;')
+ wm = ObjectSpace::WeakMap.new
+ obj = Object.new
+ 100.times do
+ wm[Object.new] = obj
+ GC.start
+ end
+ GC.compact
+ end;
+
+ assert_separately(%w(-robjspace), <<-'end;')
+ wm = ObjectSpace::WeakMap.new
+ key = Object.new
+ val = Object.new
+ wm[key] = val
+
+ GC.verify_compaction_references(expand_heap: true, toward: :empty)
+
+ assert_equal(val, wm[key])
+ end;
+
+ assert_separately(["-W0"], <<-'end;')
+ wm = ObjectSpace::WeakMap.new
+
+ ary = 10_000.times.map do
+ o = Object.new
+ wm[o] = 1
+ o
+ end
+
+ GC.verify_compaction_references(expand_heap: true, toward: :empty)
+ end;
+ end
+
+ def test_gc_compact_stress
+ omit "compaction doesn't work well on s390x" if RUBY_PLATFORM =~ /s390x/ # https://github.com/ruby/ruby/pull/5077
+ EnvUtil.under_gc_compact_stress { ObjectSpace::WeakMap.new }
+ end
+
+ def test_replaced_values_bug_19531
+ a = "A".dup
+ b = "B".dup
+
+ @wm[1] = a
+ @wm[1] = a
+ @wm[1] = a
+
+ @wm[1] = b
+ assert_equal b, @wm[1]
+
+ a = nil
+ GC.start
+
+ assert_equal b, @wm[1]
+ end
+
+ def test_use_after_free_bug_20688
+ assert_normal_exit(<<~RUBY)
+ weakmap = ObjectSpace::WeakMap.new
+ 10_000.times { weakmap[Object.new] = Object.new }
+ RUBY
+ end
end
diff --git a/test/ruby/test_whileuntil.rb b/test/ruby/test_whileuntil.rb
index 121c44817d..ff6d29ac4a 100644
--- a/test/ruby/test_whileuntil.rb
+++ b/test/ruby/test_whileuntil.rb
@@ -73,6 +73,24 @@ class TestWhileuntil < Test::Unit::TestCase
}
end
+ def test_begin_while
+ i = 0
+ sum = 0
+ begin
+ i += 1
+ sum += i
+ end while i < 10
+ assert_equal([10, 55], [i, sum])
+
+ i = 0
+ sum = 0
+ (
+ i += 1
+ sum += i
+ ) while false
+ assert_equal([0, 0], [i, sum])
+ end
+
def test_until
i = 0
until i>4
diff --git a/test/ruby/test_yjit.rb b/test/ruby/test_yjit.rb
new file mode 100644
index 0000000000..c91d631256
--- /dev/null
+++ b/test/ruby/test_yjit.rb
@@ -0,0 +1,1842 @@
+# frozen_string_literal: true
+#
+# This set of tests can be run with:
+# make test-all TESTS='test/ruby/test_yjit.rb'
+
+require 'test/unit'
+require 'envutil'
+require 'tmpdir'
+require_relative '../lib/jit_support'
+
+return unless JITSupport.yjit_supported?
+
+require 'stringio'
+
+# Tests for YJIT with assertions on compilation and side exits
+# insipired by the RJIT tests in test/ruby/test_rjit.rb
+class TestYJIT < Test::Unit::TestCase
+ running_with_yjit = defined?(RubyVM::YJIT) && RubyVM::YJIT.enabled?
+
+ def test_yjit_in_ruby_description
+ assert_includes(RUBY_DESCRIPTION, '+YJIT')
+ end if running_with_yjit
+
+ # Check that YJIT is in the version string
+ def test_yjit_in_version
+ [
+ %w(--version --yjit),
+ %w(--version --disable-yjit --yjit),
+ %w(--version --disable-yjit --enable-yjit),
+ %w(--version --disable-yjit --enable=yjit),
+ %w(--version --disable=yjit --yjit),
+ %w(--version --disable=yjit --enable-yjit),
+ %w(--version --disable=yjit --enable=yjit),
+ %w(--version --jit),
+ %w(--version --disable-jit --jit),
+ %w(--version --disable-jit --enable-jit),
+ %w(--version --disable-jit --enable=jit),
+ %w(--version --disable=jit --yjit),
+ %w(--version --disable=jit --enable-jit),
+ %w(--version --disable=jit --enable=jit),
+ ].each do |version_args|
+ assert_in_out_err(version_args) do |stdout, stderr|
+ assert_equal(RUBY_DESCRIPTION, stdout.first)
+ assert_equal([], stderr)
+ end
+ end
+ end if running_with_yjit
+
+ def test_command_line_switches
+ assert_in_out_err('--yjit-', '', [], /invalid option --yjit-/)
+ assert_in_out_err('--yjithello', '', [], /invalid option --yjithello/)
+ #assert_in_out_err('--yjit-call-threshold', '', [], /--yjit-call-threshold needs an argument/)
+ #assert_in_out_err('--yjit-call-threshold=', '', [], /--yjit-call-threshold needs an argument/)
+ end
+
+ def test_yjit_enable
+ args = []
+ args << "--disable=yjit" if RubyVM::YJIT.enabled?
+ assert_separately(args, <<~'RUBY')
+ refute_predicate RubyVM::YJIT, :enabled?
+ refute_includes RUBY_DESCRIPTION, "+YJIT"
+
+ RubyVM::YJIT.enable
+
+ assert_predicate RubyVM::YJIT, :enabled?
+ assert_includes RUBY_DESCRIPTION, "+YJIT"
+ RUBY
+ end
+
+ def test_yjit_disable
+ assert_separately(["--yjit", "--yjit-disable"], <<~'RUBY')
+ refute_predicate RubyVM::YJIT, :enabled?
+ refute_includes RUBY_DESCRIPTION, "+YJIT"
+
+ RubyVM::YJIT.enable
+
+ assert_predicate RubyVM::YJIT, :enabled?
+ assert_includes RUBY_DESCRIPTION, "+YJIT"
+ RUBY
+ end
+
+ def test_yjit_enable_stats_false
+ assert_separately(["--yjit-disable", "--yjit-stats"], <<~RUBY, ignore_stderr: true)
+ assert_false RubyVM::YJIT.enabled?
+ assert_nil RubyVM::YJIT.runtime_stats
+
+ RubyVM::YJIT.enable
+
+ assert_true RubyVM::YJIT.enabled?
+ assert_true RubyVM::YJIT.runtime_stats[:all_stats]
+ RUBY
+ end
+
+ def test_yjit_enable_stats_true
+ args = []
+ args << "--disable=yjit" if RubyVM::YJIT.enabled?
+ assert_separately(args, <<~RUBY, ignore_stderr: true)
+ assert_false RubyVM::YJIT.enabled?
+ assert_nil RubyVM::YJIT.runtime_stats
+
+ RubyVM::YJIT.enable(stats: true)
+
+ assert_true RubyVM::YJIT.enabled?
+ assert_true RubyVM::YJIT.runtime_stats[:all_stats]
+ RUBY
+ end
+
+ def test_yjit_enable_stats_quiet
+ assert_in_out_err(['--yjit-disable', '-e', 'RubyVM::YJIT.enable(stats: true)']) do |_stdout, stderr, _status|
+ assert_not_empty stderr
+ end
+ assert_in_out_err(['--yjit-disable', '-e', 'RubyVM::YJIT.enable(stats: :quiet)']) do |_stdout, stderr, _status|
+ assert_empty stderr
+ end
+ end
+
+ def test_yjit_enable_with_call_threshold
+ assert_separately(%w[--yjit-disable --yjit-call-threshold=1], <<~RUBY)
+ def not_compiled = nil
+ def will_compile = nil
+ def compiled_counts = RubyVM::YJIT.runtime_stats&.dig(:compiled_iseq_count)
+
+ not_compiled
+ assert_nil compiled_counts
+ assert_false RubyVM::YJIT.enabled?
+
+ RubyVM::YJIT.enable
+
+ will_compile
+ assert compiled_counts > 0
+ assert_true RubyVM::YJIT.enabled?
+ RUBY
+ end
+
+ def test_yjit_enable_with_monkey_patch
+ assert_separately(%w[--yjit-disable], <<~RUBY)
+ # This lets rb_method_entry_at(rb_mKernel, ...) return NULL
+ Kernel.prepend(Module.new)
+
+ # This must not crash with "undefined optimized method!"
+ RubyVM::YJIT.enable
+ RUBY
+ end
+
+ def test_yjit_stats_and_v_no_error
+ _stdout, stderr, _status = invoke_ruby(%w(-v --yjit-stats), '', true, true)
+ refute_includes(stderr, "NoMethodError")
+ end
+
+ def test_enable_from_env_var
+ yjit_child_env = {'RUBY_YJIT_ENABLE' => '1'}
+ assert_in_out_err([yjit_child_env, '--version'], '') do |stdout, stderr|
+ assert_equal(RUBY_DESCRIPTION, stdout.first)
+ assert_equal([], stderr)
+ end
+ assert_in_out_err([yjit_child_env, '-e puts RUBY_DESCRIPTION'], '', [RUBY_DESCRIPTION])
+ assert_in_out_err([yjit_child_env, '-e p RubyVM::YJIT.enabled?'], '', ['true'])
+ end if running_with_yjit
+
+ def test_compile_setclassvariable
+ script = 'class Foo; def self.foo; @@foo = 1; end; end; Foo.foo'
+ assert_compiles(script, insns: %i[setclassvariable], result: 1)
+ end
+
+ def test_compile_getclassvariable
+ script = 'class Foo; @@foo = 1; def self.foo; @@foo; end; end; Foo.foo'
+ assert_compiles(script, insns: %i[getclassvariable], result: 1)
+ end
+
+ def test_compile_putnil
+ assert_compiles('nil', insns: %i[putnil], result: nil)
+ end
+
+ def test_compile_putobject
+ assert_compiles('true', insns: %i[putobject], result: true)
+ assert_compiles('123', insns: %i[putobject], result: 123)
+ assert_compiles(':foo', insns: %i[putobject], result: :foo)
+ end
+
+ def test_compile_opt_succ
+ assert_compiles('1.succ', insns: %i[opt_succ], result: 2)
+ end
+
+ def test_compile_opt_not
+ assert_compiles('!false', insns: %i[opt_not], result: true)
+ assert_compiles('!nil', insns: %i[opt_not], result: true)
+ assert_compiles('!true', insns: %i[opt_not], result: false)
+ assert_compiles('![]', insns: %i[opt_not], result: false)
+ end
+
+ def test_compile_opt_newarray
+ assert_compiles('[]', insns: %i[newarray], result: [])
+ assert_compiles('[1+1]', insns: %i[newarray opt_plus], result: [2])
+ assert_compiles('[1,1+1,3,4,5,6]', insns: %i[newarray opt_plus], result: [1, 2, 3, 4, 5, 6])
+ end
+
+ def test_compile_opt_duparray
+ assert_compiles('[1]', insns: %i[duparray], result: [1])
+ assert_compiles('[1, 2, 3]', insns: %i[duparray], result: [1, 2, 3])
+ end
+
+ def test_compile_newrange
+ assert_compiles('s = 1; (s..5)', insns: %i[newrange], result: 1..5)
+ assert_compiles('s = 1; e = 5; (s..e)', insns: %i[newrange], result: 1..5)
+ assert_compiles('s = 1; (s...5)', insns: %i[newrange], result: 1...5)
+ assert_compiles('s = 1; (s..)', insns: %i[newrange], result: 1..)
+ assert_compiles('e = 5; (..e)', insns: %i[newrange], result: ..5)
+ end
+
+ def test_compile_duphash
+ assert_compiles('{ two: 2 }', insns: %i[duphash], result: { two: 2 })
+ end
+
+ def test_compile_newhash
+ assert_compiles('{}', insns: %i[newhash], result: {})
+ assert_compiles('{ two: 1 + 1 }', insns: %i[newhash], result: { two: 2 })
+ assert_compiles('{ 1 + 1 => :two }', insns: %i[newhash], result: { 2 => :two })
+ end
+
+ def test_compile_opt_nil_p
+ assert_compiles('nil.nil?', insns: %i[opt_nil_p], result: true)
+ assert_compiles('false.nil?', insns: %i[opt_nil_p], result: false)
+ assert_compiles('true.nil?', insns: %i[opt_nil_p], result: false)
+ assert_compiles('(-"").nil?', insns: %i[opt_nil_p], result: false)
+ assert_compiles('123.nil?', insns: %i[opt_nil_p], result: false)
+ end
+
+ def test_compile_eq_fixnum
+ assert_compiles('123 == 123', insns: %i[opt_eq], result: true)
+ assert_compiles('123 == 456', insns: %i[opt_eq], result: false)
+ end
+
+ def test_compile_eq_string
+ assert_compiles('-"" == -""', insns: %i[opt_eq], result: true)
+ assert_compiles('-"foo" == -"foo"', insns: %i[opt_eq], result: true)
+ assert_compiles('-"foo" == -"bar"', insns: %i[opt_eq], result: false)
+ end
+
+ def test_compile_eq_symbol
+ assert_compiles(':foo == :foo', insns: %i[opt_eq], result: true)
+ assert_compiles(':foo == :bar', insns: %i[opt_eq], result: false)
+ assert_compiles(':foo == "foo".to_sym', insns: %i[opt_eq], result: true)
+ end
+
+ def test_compile_eq_object
+ assert_compiles(<<~RUBY, insns: %i[opt_eq], result: false)
+ def eq(a, b)
+ a == b
+ end
+
+ eq(Object.new, Object.new)
+ RUBY
+
+ assert_compiles(<<~RUBY, insns: %i[opt_eq], result: true)
+ def eq(a, b)
+ a == b
+ end
+
+ obj = Object.new
+ eq(obj, obj)
+ RUBY
+ end
+
+ def test_compile_eq_arbitrary_class
+ assert_compiles(<<~RUBY, insns: %i[opt_eq], result: "yes")
+ def eq(a, b)
+ a == b
+ end
+
+ class Foo
+ def ==(other)
+ "yes"
+ end
+ end
+
+ eq(Foo.new, Foo.new)
+ eq(Foo.new, Foo.new)
+ RUBY
+ end
+
+ def test_compile_opt_lt
+ assert_compiles('1 < 2', insns: %i[opt_lt])
+ assert_compiles('"a" < "b"', insns: %i[opt_lt])
+ end
+
+ def test_compile_opt_le
+ assert_compiles('1 <= 2', insns: %i[opt_le])
+ assert_compiles('"a" <= "b"', insns: %i[opt_le])
+ end
+
+ def test_compile_opt_gt
+ assert_compiles('1 > 2', insns: %i[opt_gt])
+ assert_compiles('"a" > "b"', insns: %i[opt_gt])
+ end
+
+ def test_compile_opt_ge
+ assert_compiles('1 >= 2', insns: %i[opt_ge])
+ assert_compiles('"a" >= "b"', insns: %i[opt_ge])
+ end
+
+ def test_compile_opt_plus
+ assert_compiles('1 + 2', insns: %i[opt_plus])
+ assert_compiles('"a" + "b"', insns: %i[opt_plus])
+ assert_compiles('[:foo] + [:bar]', insns: %i[opt_plus])
+ end
+
+ def test_compile_opt_minus
+ assert_compiles('1 - 2', insns: %i[opt_minus])
+ assert_compiles('[:foo, :bar] - [:bar]', insns: %i[opt_minus])
+ end
+
+ def test_compile_opt_or
+ assert_compiles('1 | 2', insns: %i[opt_or])
+ assert_compiles('[:foo] | [:bar]', insns: %i[opt_or])
+ end
+
+ def test_compile_opt_and
+ assert_compiles('1 & 2', insns: %i[opt_and])
+ assert_compiles('[:foo, :bar] & [:bar]', insns: %i[opt_and])
+ end
+
+ def test_compile_set_and_get_global
+ assert_compiles('$foo = 123; $foo', insns: %i[setglobal], result: 123)
+ end
+
+ def test_compile_putspecialobject
+ assert_compiles('-> {}', insns: %i[putspecialobject])
+ end
+
+ def test_compile_tostring
+ assert_no_exits('"i am a string #{true}"')
+ end
+
+ def test_compile_opt_aset
+ assert_compiles('[1,2,3][2] = 4', insns: %i[opt_aset], frozen_string_literal: false)
+ assert_compiles('{}[:foo] = :bar', insns: %i[opt_aset], frozen_string_literal: false)
+ assert_compiles('[1,2,3][0..-1] = []', insns: %i[opt_aset], frozen_string_literal: false)
+ assert_compiles('"foo"[3] = "d"', insns: %i[opt_aset], frozen_string_literal: false)
+ end
+
+ def test_compile_attr_set
+ assert_no_exits(<<~EORB)
+ class Foo
+ attr_accessor :bar
+ end
+
+ foo = Foo.new
+ foo.bar = 3
+ foo.bar = 3
+ foo.bar = 3
+ foo.bar = 3
+ EORB
+ end
+
+ def test_compile_regexp
+ assert_no_exits('/#{true}/')
+ end
+
+ def test_compile_dynamic_symbol
+ assert_compiles(':"#{"foo"}"', insns: %i[intern])
+ assert_compiles('s = "bar"; :"foo#{s}"', insns: %i[intern])
+ end
+
+ def test_getlocal_with_level
+ assert_compiles(<<~RUBY, insns: %i[getlocal opt_plus], result: [[7]])
+ def foo(foo, bar)
+ [1].map do |x|
+ [1].map do |y|
+ foo + bar
+ end
+ end
+ end
+
+ foo(5, 2)
+ RUBY
+ end
+
+ def test_setlocal_with_level
+ assert_no_exits(<<~RUBY)
+ def sum(arr)
+ sum = 0
+ arr.each do |x|
+ sum += x
+ end
+ sum
+ end
+
+ sum([1,2,3])
+ RUBY
+ end
+
+ def test_string_then_nil
+ assert_compiles(<<~RUBY, insns: %i[opt_nil_p], result: true)
+ def foo(val)
+ val.nil?
+ end
+
+ foo("foo")
+ foo(nil)
+ RUBY
+ end
+
+ def test_nil_then_string
+ assert_compiles(<<~RUBY, insns: %i[opt_nil_p], result: false)
+ def foo(val)
+ val.nil?
+ end
+
+ foo(nil)
+ foo("foo")
+ RUBY
+ end
+
+ def test_string_concat_utf8
+ assert_compiles(<<~RUBY, frozen_string_literal: true, result: true)
+ def str_cat_utf8
+ s = String.new
+ 10.times { s << "✅" }
+ s
+ end
+
+ str_cat_utf8 == "✅" * 10
+ RUBY
+ end
+
+ def test_string_concat_ascii
+ # Constant-get for classes (e.g. String, Encoding) can cause a side-exit in getinlinecache. For now, ignore exits.
+ assert_compiles(<<~RUBY, exits: :any)
+ str_arg = "b".encode(Encoding::ASCII)
+ def str_cat_ascii(arg)
+ s = String.new(encoding: Encoding::ASCII)
+ 10.times { s << arg }
+ s
+ end
+
+ str_cat_ascii(str_arg) == str_arg * 10
+ RUBY
+ end
+
+ def test_opt_length_in_method
+ assert_compiles(<<~RUBY, insns: %i[opt_length], result: 5)
+ def foo(str)
+ str.length
+ end
+
+ foo("hello, ")
+ foo("world")
+ RUBY
+ end
+
+ def test_opt_regexpmatch2
+ assert_compiles(<<~RUBY, insns: %i[opt_regexpmatch2], result: 0)
+ def foo(str)
+ str =~ /foo/
+ end
+
+ foo("foobar")
+ RUBY
+ end
+
+ def test_expandarray
+ assert_compiles(<<~'RUBY', insns: %i[expandarray], result: [1, 2])
+ a, b = [1, 2]
+ RUBY
+ end
+
+ def test_expandarray_nil
+ assert_compiles(<<~'RUBY', insns: %i[expandarray], result: [nil, nil])
+ a, b = nil
+ [a, b]
+ RUBY
+ end
+
+ def test_getspecial_backref
+ assert_compiles("'foo' =~ /(o)./; $&", insns: %i[getspecial], result: "oo")
+ assert_compiles("'foo' =~ /(o)./; $`", insns: %i[getspecial], result: "f")
+ assert_compiles("'foo' =~ /(o)./; $'", insns: %i[getspecial], result: "")
+ assert_compiles("'foo' =~ /(o)./; $+", insns: %i[getspecial], result: "o")
+ assert_compiles("'foo' =~ /(o)./; $1", insns: %i[getspecial], result: "o")
+ assert_compiles("'foo' =~ /(o)./; $2", insns: %i[getspecial], result: nil)
+ end
+
+ def test_compile_getconstant
+ assert_compiles(<<~RUBY, insns: %i[getconstant], result: [], call_threshold: 1)
+ def get_argv(klass)
+ klass::ARGV
+ end
+
+ get_argv(Object)
+ RUBY
+ end
+
+ def test_compile_getconstant_with_sp_offset
+ assert_compiles(<<~RUBY, insns: %i[getconstant], result: 2, call_threshold: 1)
+ class Foo
+ Bar = 1
+ end
+
+ 2.times do
+ s = Foo # this opt_getconstant_path needs warmup, so 2.times is needed
+ Class.new(Foo).const_set(:Bar, s::Bar)
+ end
+ RUBY
+ end
+
+ def test_compile_opt_getconstant_path
+ assert_compiles(<<~RUBY, insns: %i[opt_getconstant_path], result: 123, call_threshold: 2)
+ def get_foo
+ FOO
+ end
+
+ FOO = 123
+
+ get_foo # warm inline cache
+ get_foo
+ RUBY
+ end
+
+ def test_opt_getconstant_path_slowpath
+ assert_compiles(<<~RUBY, exits: { opt_getconstant_path: 1 }, result: [42, 42, 1, 1], call_threshold: 2)
+ class A
+ FOO = 42
+ class << self
+ def foo
+ _foo = nil
+ FOO
+ end
+ end
+ end
+
+ result = []
+
+ result << A.foo
+ result << A.foo
+
+ class << A
+ FOO = 1
+ end
+
+ result << A.foo
+ result << A.foo
+
+ result
+ RUBY
+ end
+
+ def test_opt_getconstant_path_general
+ assert_compiles(<<~RUBY, result: [1, 1])
+ module Base
+ Const = 1
+ end
+
+ class Sub
+ def const
+ _const = nil # make a non-entry block for opt_getconstant_path
+ Const
+ end
+
+ def self.const_missing(n)
+ Base.const_get(n)
+ end
+ end
+
+
+ sub = Sub.new
+ result = []
+ result << sub.const # generate the general case
+ result << sub.const # const_missing does not invalidate the block
+ result
+ RUBY
+ end
+
+ def test_string_interpolation
+ assert_compiles(<<~'RUBY', insns: %i[objtostring anytostring concatstrings], result: "foobar", call_threshold: 2)
+ def make_str(foo, bar)
+ "#{foo}#{bar}"
+ end
+
+ make_str("foo", "bar")
+ make_str("foo", "bar")
+ RUBY
+ end
+
+ def test_string_interpolation_cast
+ assert_compiles(<<~'RUBY', insns: %i[objtostring anytostring concatstrings], result: "123")
+ def make_str(foo, bar)
+ "#{foo}#{bar}"
+ end
+
+ make_str(1, 23)
+ RUBY
+ end
+
+ def test_checkkeyword
+ assert_compiles(<<~'RUBY', insns: %i[checkkeyword], result: [2, 5])
+ def foo(foo: 1+1)
+ foo
+ end
+
+ [foo, foo(foo: 5)]
+ RUBY
+ end
+
+ def test_struct_aref
+ assert_compiles(<<~RUBY)
+ def foo(obj)
+ obj.foo
+ obj.bar
+ end
+
+ Foo = Struct.new(:foo, :bar)
+ foo(Foo.new(123))
+ foo(Foo.new(123))
+ RUBY
+ end
+
+ def test_struct_aset
+ assert_compiles(<<~RUBY)
+ def foo(obj)
+ obj.foo = 123
+ obj.bar = 123
+ end
+
+ Foo = Struct.new(:foo, :bar)
+ foo(Foo.new(123))
+ foo(Foo.new(123))
+ RUBY
+ end
+
+ def test_getblockparam
+ assert_compiles(<<~'RUBY', insns: [:getblockparam])
+ def foo &blk
+ 2.times do
+ blk
+ end
+ end
+
+ foo {}
+ foo {}
+ RUBY
+ end
+
+ def test_getblockparamproxy
+ assert_compiles(<<~'RUBY', insns: [:getblockparamproxy], exits: {})
+ def foo &blk
+ p blk.call
+ p blk.call
+ end
+
+ foo { 1 }
+ foo { 2 }
+ RUBY
+ end
+
+ def test_ifunc_getblockparamproxy
+ assert_compiles(<<~'RUBY', insns: [:getblockparamproxy], exits: {})
+ class Foo
+ include Enumerable
+
+ def each(&block)
+ block.call 1
+ block.call 2
+ block.call 3
+ end
+ end
+
+ foo = Foo.new
+ foo.map { _1 * 2 }
+ foo.map { _1 * 2 }
+ RUBY
+ end
+
+ def test_send_blockarg
+ assert_compiles(<<~'RUBY', insns: [:getblockparamproxy, :send], exits: {})
+ def bar
+ end
+
+ def foo &blk
+ bar(&blk)
+ bar(&blk)
+ end
+
+ foo
+ foo
+
+ foo { }
+ foo { }
+ RUBY
+ end
+
+ def test_send_splat
+ assert_compiles(<<~'RUBY', result: "3#1,2,3/P", exits: {})
+ def internal_method(*args)
+ "#{args.size}##{args.join(",")}"
+ end
+
+ def jit_method
+ send(:internal_method, *[1, 2, 3]) + "/P"
+ end
+
+ jit_method
+ RUBY
+ end
+
+ def test_send_multiarg
+ assert_compiles(<<~'RUBY', result: "3#1,2,3/Q")
+ def internal_method(*args)
+ "#{args.size}##{args.join(",")}"
+ end
+
+ def jit_method
+ send(:internal_method, 1, 2, 3) + "/Q"
+ end
+
+ jit_method
+ RUBY
+ end
+
+ def test_send_kwargs
+ # For now, this side-exits when calls include keyword args
+ assert_compiles(<<~'RUBY', result: "2#a:1,b:2/A")
+ def internal_method(**kw)
+ "#{kw.size}##{kw.keys.map { |k| "#{k}:#{kw[k]}" }.join(",")}"
+ end
+
+ def jit_method
+ send(:internal_method, a: 1, b: 2) + "/A"
+ end
+ jit_method
+ RUBY
+ end
+
+ def test_send_kwargs_in_receiver_only
+ assert_compiles(<<~'RUBY', result: "0/RK", exits: {})
+ def internal_method(**kw)
+ "#{kw.size}"
+ end
+
+ def jit_method
+ send(:internal_method) + "/RK"
+ end
+ jit_method
+ RUBY
+ end
+
+ def test_send_with_underscores
+ assert_compiles(<<~'RUBY', result: "0/RK", exits: {})
+ def internal_method(**kw)
+ "#{kw.size}"
+ end
+
+ def jit_method
+ __send__(:internal_method) + "/RK"
+ end
+ jit_method
+ RUBY
+ end
+
+ def test_send_kwargs_splat
+ # For now, this side-exits when calling with a splat
+ assert_compiles(<<~'RUBY', result: "2#a:1,b:2/B")
+ def internal_method(**kw)
+ "#{kw.size}##{kw.keys.map { |k| "#{k}:#{kw[k]}" }.join(",")}"
+ end
+
+ def jit_method
+ send(:internal_method, **{ a: 1, b: 2 }) + "/B"
+ end
+ jit_method
+ RUBY
+ end
+
+ def test_send_block
+ # Setlocal_wc_0 sometimes side-exits on write barrier
+ assert_compiles(<<~'RUBY', result: "b:n/b:y/b:y/b:n")
+ def internal_method(&b)
+ "b:#{block_given? ? "y" : "n"}"
+ end
+
+ def jit_method
+ b7 = proc { 7 }
+ [
+ send(:internal_method),
+ send(:internal_method, &b7),
+ send(:internal_method) { 7 },
+ send(:internal_method, &nil),
+ ].join("/")
+ end
+ jit_method
+ RUBY
+ end
+
+ def test_send_block_calling
+ assert_compiles(<<~'RUBY', result: "1a2", exits: {})
+ def internal_method
+ out = yield
+ "1" + out + "2"
+ end
+
+ def jit_method
+ __send__(:internal_method) { "a" }
+ end
+ jit_method
+ RUBY
+ end
+
+ def test_send_block_only_receiver
+ assert_compiles(<<~'RUBY', result: "b:n", exits: {})
+ def internal_method(&b)
+ "b:#{block_given? ? "y" : "n"}"
+ end
+
+ def jit_method
+ send(:internal_method)
+ end
+ jit_method
+ RUBY
+ end
+
+ def test_send_block_only_sender
+ assert_compiles(<<~'RUBY', result: "Y/Y/Y/Y", exits: {})
+ def internal_method
+ "Y"
+ end
+
+ def jit_method
+ b7 = proc { 7 }
+ [
+ send(:internal_method),
+ send(:internal_method, &b7),
+ send(:internal_method) { 7 },
+ send(:internal_method, &nil),
+ ].join("/")
+ end
+ jit_method
+ RUBY
+ end
+
+ def test_multisend
+ assert_compiles(<<~'RUBY', result: "77")
+ def internal_method
+ "7"
+ end
+
+ def jit_method
+ send(:send, :internal_method) + send(:send, :send, :internal_method)
+ end
+ jit_method
+ RUBY
+ end
+
+ def test_getivar_opt_plus
+ assert_no_exits(<<~RUBY)
+ class TheClass
+ def initialize
+ @levar = 1
+ end
+
+ def get_sum
+ sum = 0
+ # The type of levar is unknown,
+ # but this still should not exit
+ sum += @levar
+ sum
+ end
+ end
+
+ obj = TheClass.new
+ obj.get_sum
+ RUBY
+ end
+
+ def test_super_iseq
+ assert_compiles(<<~'RUBY', insns: %i[invokesuper opt_plus opt_mult], result: 15)
+ class A
+ def foo
+ 1 + 2
+ end
+ end
+
+ class B < A
+ def foo
+ super * 5
+ end
+ end
+
+ B.new.foo
+ RUBY
+ end
+
+ def test_super_with_alias
+ assert_compiles(<<~'RUBY', insns: %i[invokesuper opt_plus opt_mult], result: 15)
+ class A
+ def foo = 1 + 2
+ end
+
+ module M
+ def foo = super() * 5
+ alias bar foo
+
+ def foo = :bad
+ end
+
+ A.prepend M
+
+ A.new.bar
+ RUBY
+ end
+
+ def test_super_cfunc
+ assert_compiles(<<~'RUBY', insns: %i[invokesuper], result: "Hello")
+ class Gnirts < String
+ def initialize
+ super(-"olleH")
+ end
+
+ def to_s
+ super().reverse
+ end
+ end
+
+ Gnirts.new.to_s
+ RUBY
+ end
+
+ # Tests calling a variadic cfunc with many args
+ def test_build_large_struct
+ assert_compiles(<<~RUBY, insns: %i[opt_send_without_block], call_threshold: 2)
+ ::Foo = Struct.new(:a, :b, :c, :d, :e, :f, :g, :h)
+
+ def build_foo
+ ::Foo.new(:a, :b, :c, :d, :e, :f, :g, :h)
+ end
+
+ build_foo
+ build_foo
+ RUBY
+ end
+
+ def test_fib_recursion
+ assert_compiles(<<~'RUBY', insns: %i[opt_le opt_minus opt_plus opt_send_without_block], result: 34)
+ def fib(n)
+ return n if n <= 1
+ fib(n-1) + fib(n-2)
+ end
+
+ fib(9)
+ RUBY
+ end
+
+ def test_optarg_and_kwarg
+ assert_no_exits(<<~'RUBY')
+ def opt_and_kwarg(a, b=nil, c: nil)
+ end
+
+ 2.times do
+ opt_and_kwarg(1, 2, c: 3)
+ end
+ RUBY
+ end
+
+ def test_cfunc_kwarg
+ assert_no_exits('{}.store(:value, foo: 123)')
+ assert_no_exits('{}.store(:value, foo: 123, bar: 456, baz: 789)')
+ assert_no_exits('{}.merge(foo: 123)')
+ assert_no_exits('{}.merge(foo: 123, bar: 456, baz: 789)')
+ end
+
+ # regression test simplified from URI::Generic#hostname=
+ def test_ctx_different_mappings
+ assert_compiles(<<~'RUBY', frozen_string_literal: true)
+ def foo(v)
+ !(v&.start_with?('[')) && v&.index(':')
+ end
+
+ foo(nil)
+ foo("example.com")
+ RUBY
+ end
+
+ def test_no_excessive_opt_getinlinecache_invalidation
+ assert_compiles(<<~'RUBY', exits: :any, result: :ok)
+ objects = [Object.new, Object.new]
+
+ objects.each do |o|
+ class << o
+ def foo
+ Object
+ end
+ end
+ end
+
+ 9000.times {
+ objects[0].foo
+ objects[1].foo
+ }
+
+ stats = RubyVM::YJIT.runtime_stats
+ return :ok unless stats[:all_stats]
+ return :ok if stats[:invalidation_count] < 10
+
+ :fail
+ RUBY
+ end
+
+ def test_int_equal
+ assert_compiles(<<~'RUBY', exits: :any, result: [true, false, true, false, true, false, true, false])
+ def eq(a, b)
+ a == b
+ end
+
+ def eqq(a, b)
+ a === b
+ end
+
+ big1 = 2 ** 65
+ big2 = big1 + 1
+ [eq(1, 1), eq(1, 2), eq(big1, big1), eq(big1, big2), eqq(1, 1), eqq(1, 2), eqq(big1, big1), eqq(big1, big2)]
+ RUBY
+ end
+
+ def test_opt_case_dispatch
+ assert_compiles(<<~'RUBY', exits: :any, result: [:"1", "2", 3])
+ def case_dispatch(val)
+ case val
+ when 1
+ :"#{val}"
+ when 2
+ "#{val}"
+ else
+ val
+ end
+ end
+
+ [case_dispatch(1), case_dispatch(2), case_dispatch(3)]
+ RUBY
+ end
+
+ def test_code_gc
+ assert_compiles(code_gc_helpers + <<~'RUBY', exits: :any, result: :ok)
+ return :not_paged unless add_pages(100) # prepare freeable pages
+ RubyVM::YJIT.code_gc # first code GC
+ return :not_compiled1 unless compiles { nil } # should be JITable again
+
+ RubyVM::YJIT.code_gc # second code GC
+ return :not_compiled2 unless compiles { nil } # should be JITable again
+
+ code_gc_count = RubyVM::YJIT.runtime_stats[:code_gc_count]
+ return :"code_gc_#{code_gc_count}" if code_gc_count != 2
+
+ :ok
+ RUBY
+ end
+
+ def test_on_stack_code_gc_call
+ assert_compiles(code_gc_helpers + <<~'RUBY', exits: :any, result: :ok)
+ fiber = Fiber.new {
+ # Loop to call the same basic block again after Fiber.yield
+ while true
+ Fiber.yield(nil.to_i)
+ end
+ }
+
+ return :not_paged1 unless add_pages(400) # go to a page without initial ocb code
+ return :broken_resume1 if fiber.resume != 0 # JIT the fiber
+ RubyVM::YJIT.code_gc # first code GC, which should not free the fiber page
+ return :broken_resume2 if fiber.resume != 0 # The code should be still callable
+
+ code_gc_count = RubyVM::YJIT.runtime_stats[:code_gc_count]
+ return :"code_gc_#{code_gc_count}" if code_gc_count != 1
+
+ :ok
+ RUBY
+ end
+
+ def test_on_stack_code_gc_twice
+ assert_compiles(code_gc_helpers + <<~'RUBY', exits: :any, result: :ok)
+ fiber = Fiber.new {
+ # Loop to call the same basic block again after Fiber.yield
+ while Fiber.yield(nil.to_i); end
+ }
+
+ return :not_paged1 unless add_pages(400) # go to a page without initial ocb code
+ return :broken_resume1 if fiber.resume(true) != 0 # JIT the fiber
+ RubyVM::YJIT.code_gc # first code GC, which should not free the fiber page
+
+ return :not_paged2 unless add_pages(300) # add some stuff to be freed
+ # Not calling fiber.resume here to test the case that the YJIT payload loses some
+ # information at the previous code GC. The payload should still be there, and
+ # thus we could know the fiber ISEQ is still on stack on this second code GC.
+ RubyVM::YJIT.code_gc # second code GC, which should still not free the fiber page
+
+ return :not_paged3 unless add_pages(200) # attempt to overwrite the fiber page (it shouldn't)
+ return :broken_resume2 if fiber.resume(true) != 0 # The fiber code should be still fine
+
+ return :broken_resume3 if fiber.resume(false) != nil # terminate the fiber
+ RubyVM::YJIT.code_gc # third code GC, freeing a page that used to be on stack
+
+ return :not_paged4 unless add_pages(100) # check everything still works
+
+ code_gc_count = RubyVM::YJIT.runtime_stats[:code_gc_count]
+ return :"code_gc_#{code_gc_count}" if code_gc_count != 3
+
+ :ok
+ RUBY
+ end
+
+ def test_disable_code_gc_with_many_iseqs
+ assert_compiles(code_gc_helpers + <<~'RUBY', exits: :any, result: :ok, mem_size: 1, code_gc: false)
+ fiber = Fiber.new {
+ # Loop to call the same basic block again after Fiber.yield
+ while true
+ Fiber.yield(nil.to_i)
+ end
+ }
+
+ return :not_paged1 unless add_pages(250) # use some pages
+ return :broken_resume1 if fiber.resume != 0 # leave an on-stack code as well
+
+ add_pages(2000) # use a whole lot of pages to run out of 1MiB
+ return :broken_resume2 if fiber.resume != 0 # on-stack code should be callable
+
+ code_gc_count = RubyVM::YJIT.runtime_stats[:code_gc_count]
+ return :"code_gc_#{code_gc_count}" if code_gc_count != 0
+
+ :ok
+ RUBY
+ end
+
+ def test_code_gc_with_many_iseqs
+ assert_compiles(code_gc_helpers + <<~'RUBY', exits: :any, result: :ok, mem_size: 1, code_gc: true)
+ fiber = Fiber.new {
+ # Loop to call the same basic block again after Fiber.yield
+ while true
+ Fiber.yield(nil.to_i)
+ end
+ }
+
+ return :not_paged1 unless add_pages(250) # use some pages
+ return :broken_resume1 if fiber.resume != 0 # leave an on-stack code as well
+
+ add_pages(2000) # use a whole lot of pages to run out of 1MiB
+ return :broken_resume2 if fiber.resume != 0 # on-stack code should be callable
+
+ code_gc_count = RubyVM::YJIT.runtime_stats[:code_gc_count]
+ return :"code_gc_#{code_gc_count}" if code_gc_count == 0
+
+ :ok
+ RUBY
+ end
+
+ def test_code_gc_with_auto_compact
+ assert_compiles((code_gc_helpers + <<~'RUBY'), exits: :any, result: :ok, mem_size: 1, code_gc: true)
+ # Test ISEQ moves in the middle of code GC
+ GC.auto_compact = true
+
+ fiber = Fiber.new {
+ # Loop to call the same basic block again after Fiber.yield
+ while true
+ Fiber.yield(nil.to_i)
+ end
+ }
+
+ return :not_paged1 unless add_pages(250) # use some pages
+ return :broken_resume1 if fiber.resume != 0 # leave an on-stack code as well
+
+ add_pages(2000) # use a whole lot of pages to run out of 1MiB
+ return :broken_resume2 if fiber.resume != 0 # on-stack code should be callable
+
+ code_gc_count = RubyVM::YJIT.runtime_stats[:code_gc_count]
+ return :"code_gc_#{code_gc_count}" if code_gc_count == 0
+
+ :ok
+ RUBY
+ end
+
+ def test_code_gc_partial_last_page
+ # call_threshold: 2 to avoid JIT-ing code_gc itself. If code_gc were JITed right before
+ # code_gc is called, the last page would be on stack.
+ assert_compiles(<<~'RUBY', exits: :any, result: :ok, call_threshold: 2)
+ # Leave a bunch of off-stack pages
+ i = 0
+ while i < 1000
+ eval("x = proc { 1.to_s }; x.call; x.call")
+ i += 1
+ end
+
+ # On Linux, memory page size != code page size. So the last code page could be partially
+ # mapped. This call tests that assertions and other things work fine under the situation.
+ RubyVM::YJIT.code_gc
+
+ :ok
+ RUBY
+ end
+
+ def test_trace_script_compiled # not ISEQ_TRACE_EVENTS
+ assert_compiles(<<~'RUBY', exits: :any, result: :ok)
+ @eval_counter = 0
+ def eval_script
+ eval('@eval_counter += 1')
+ end
+
+ @trace_counter = 0
+ trace = TracePoint.new(:script_compiled) do |t|
+ @trace_counter += 1
+ end
+
+ eval_script # JIT without TracePoint
+ trace.enable
+ eval_script # call with TracePoint
+ trace.disable
+
+ return :"eval_#{@eval_counter}" if @eval_counter != 2
+ return :"trace_#{@trace_counter}" if @trace_counter != 1
+
+ :ok
+ RUBY
+ end
+
+ def test_trace_b_call # ISEQ_TRACE_EVENTS
+ assert_compiles(<<~'RUBY', exits: :any, result: :ok)
+ @call_counter = 0
+ def block_call
+ 1.times { @call_counter += 1 }
+ end
+
+ @trace_counter = 0
+ trace = TracePoint.new(:b_call) do |t|
+ @trace_counter += 1
+ end
+
+ block_call # JIT without TracePoint
+ trace.enable
+ block_call # call with TracePoint
+ trace.disable
+
+ return :"call_#{@call_counter}" if @call_counter != 2
+ return :"trace_#{@trace_counter}" if @trace_counter != 1
+
+ :ok
+ RUBY
+ end
+
+ def test_send_to_call
+ assert_compiles(<<~'RUBY', result: :ok)
+ ->{ :ok }.send(:call)
+ RUBY
+ end
+
+ def test_invokeblock_many_locals
+ # [Bug #19299]
+ assert_compiles(<<~'RUBY', result: :ok)
+ def foo
+ yield
+ end
+
+ foo do
+ a1=a2=a3=a4=a5=a6=a7=a8=a9=a10=a11=a12=a13=a14=a15=a16=a17=a18=a19=a20=a21=a22=a23=a24=a25=a26=a27=a28=a29=a30 = :ok
+ a30
+ end
+ RUBY
+ end
+
+ def test_bug_19316
+ n = 2 ** 64
+ # foo's extra param and the splats are relevant
+ assert_compiles(<<~'RUBY', result: [[n, -n], [n, -n]], exits: :any)
+ def foo(_, a, b, c)
+ [a & b, ~c]
+ end
+
+ n = 2 ** 64
+ args = [0, -n, n, n-1]
+
+ GC.stress = true
+ [foo(*args), foo(*args)]
+ RUBY
+ end
+
+ def test_gc_compact_cyclic_branch
+ assert_compiles(<<~'RUBY', result: 2)
+ def foo
+ i = 0
+ while i < 2
+ i += 1
+ end
+ i
+ end
+
+ foo
+ GC.compact
+ foo
+ RUBY
+ end
+
+ def test_invalidate_cyclic_branch
+ assert_compiles(<<~'RUBY', result: 2, exits: { opt_plus: 1 })
+ def foo
+ i = 0
+ while i < 2
+ i += 1
+ end
+ i
+ end
+
+ foo
+ class Integer
+ def +(x) = self - -x
+ end
+ foo
+ RUBY
+ end
+
+ def test_tracing_str_uplus
+ assert_compiles(<<~RUBY, frozen_string_literal: true, result: :ok, exits: { putspecialobject: 1, definemethod: 1 })
+ def str_uplus
+ _ = 1
+ _ = 2
+ ret = [+"frfr", __LINE__]
+ _ = 3
+ _ = 4
+
+ ret
+ end
+
+ str_uplus
+ require 'objspace'
+ ObjectSpace.trace_object_allocations_start
+
+ str, expected_line = str_uplus
+ alloc_line = ObjectSpace.allocation_sourceline(str)
+
+ if expected_line == alloc_line
+ :ok
+ else
+ [expected_line, alloc_line]
+ end
+ RUBY
+ end
+
+ def test_str_uplus_subclass
+ assert_compiles(<<~RUBY, frozen_string_literal: true, result: :subclass)
+ class S < String
+ def encoding
+ :subclass
+ end
+ end
+
+ def test(str)
+ (+str).encoding
+ end
+
+ test ""
+ test S.new
+ RUBY
+ end
+
+ def test_return_to_invalidated_block
+ # [Bug #19463]
+ assert_compiles(<<~RUBY, result: [1, 1, :ugokanai], exits: { definesmethod: 1, getlocal_WC_0: 1 })
+ klass = Class.new do
+ def self.lookup(hash, key) = hash[key]
+
+ def self.foo(a, b) = []
+
+ def self.test(hash, key)
+ [lookup(hash, key), key, "".freeze]
+ # 05 opt_send_without_block :lookup
+ # 07 getlocal_WC_0 :hash
+ # 09 opt_str_freeze ""
+ # 12 newarray 3
+ # 14 leave
+ #
+ # YJIT will put instructions (07..14) into a block.
+ # When String#freeze is redefined from within lookup(),
+ # the return address to the block is still on-stack. We rely
+ # on invalidation patching the code at the return address
+ # to service this situation correctly.
+ end
+ end
+
+ # get YJIT to compile test()
+ hash = { 1 => [] }
+ 31.times { klass.test(hash, 1) }
+
+ # inject invalidation into lookup()
+ evil_hash = Hash.new do |_, key|
+ class String
+ undef :freeze
+ def freeze = :ugokanai
+ end
+
+ key
+ end
+ klass.test(evil_hash, 1)
+ RUBY
+ end
+
+ def test_return_to_invalidated_frame
+ assert_compiles(code_gc_helpers + <<~RUBY, exits: :any, result: :ok)
+ def jump
+ [] # something not inlined
+ end
+
+ def entry(code_gc)
+ jit_exception(code_gc)
+ jump # faulty jump after code GC. #jit_exception should not come back.
+ end
+
+ def jit_exception(code_gc)
+ if code_gc
+ tap do
+ RubyVM::YJIT.code_gc
+ break # jit_exec_exception catches TAG_BREAK and re-enters JIT code
+ end
+ end
+ end
+
+ add_pages(100)
+ jump # Compile #jump in a non-first page
+ add_pages(100)
+ entry(false) # Compile #entry and its call to #jump in another page
+ entry(true) # Free #jump but not #entry
+
+ :ok
+ RUBY
+ end
+
+ def test_setivar_on_class
+ # Bug in https://github.com/ruby/ruby/pull/8152
+ assert_compiles(<<~RUBY, result: :ok)
+ class Base
+ def self.or_equal
+ @or_equal ||= Object.new
+ end
+ end
+
+ Base.or_equal # ensure compiled
+
+ class Child < Base
+ end
+
+ 200.times do |iv| # Need to be more than MAX_IVAR
+ Child.instance_variable_set("@_iv_\#{iv}", Object.new)
+ end
+
+ Child.or_equal
+ :ok
+ RUBY
+ end
+
+ def test_nested_send
+ #[Bug #19464]
+ assert_compiles(<<~RUBY, result: [:ok, :ok], exits: { defineclass: 1 })
+ klass = Class.new do
+ class << self
+ alias_method :my_send, :send
+
+ def bar = :ok
+
+ def foo = bar
+ end
+ end
+
+ with_break = -> { break klass.send(:my_send, :foo) }
+ wo_break = -> { klass.send(:my_send, :foo) }
+
+ [with_break[], wo_break[]]
+ RUBY
+ end
+
+ def test_str_concat_encoding_mismatch
+ assert_compiles(<<~'RUBY', result: "incompatible character encodings: BINARY (ASCII-8BIT) and EUC-JP")
+ def bar(a, b)
+ a << b
+ rescue => e
+ e.message
+ end
+
+ def foo(a, b, h)
+ h[nil]
+ bar(a, b) # Ruby call, not set cfp->pc
+ end
+
+ h = Hash.new { nil }
+ foo("\x80".b, "\xA1A1".dup.force_encoding("EUC-JP"), h)
+ foo("\x80".b, "\xA1A1".dup.force_encoding("EUC-JP"), h)
+ RUBY
+ end
+
+ def test_io_reopen_clobbering_singleton_class
+ assert_compiles(<<~RUBY, result: [:ok, :ok], exits: { definesmethod: 1, opt_eq: 2 })
+ def $stderr.to_i = :i
+
+ def test = $stderr.to_i
+
+ [test, test]
+ $stderr.reopen($stderr.dup)
+ [test, test].map { :ok unless _1 == :i }
+ RUBY
+ end
+
+ def test_opt_aref_with
+ assert_compiles(<<~RUBY, insns: %i[opt_aref_with], result: "bar", frozen_string_literal: false)
+ h = {"foo" => "bar"}
+
+ h["foo"]
+ RUBY
+ end
+
+ def test_proc_block_arg
+ assert_compiles(<<~RUBY, result: [:proc, :no_block])
+ def yield_if_given = block_given? ? yield : :no_block
+
+ def call(block_arg = nil) = yield_if_given(&block_arg)
+
+ [call(-> { :proc }), call]
+ RUBY
+ end
+
+ def test_opt_mult_overflow
+ assert_no_exits('0xfff_ffff_ffff_ffff * 0x10')
+ end
+
+ def test_disable_stats
+ assert_in_out_err(%w[--yjit-stats --yjit-disable])
+ end
+
+ def test_odd_calls_to_attr_reader
+ # Use of delegate from ActiveSupport use these kind of calls to getter methods.
+ assert_compiles(<<~RUBY, result: [1, 1, 1], no_send_fallbacks: true)
+ class One
+ attr_reader :one
+ def initialize
+ @one = 1
+ end
+ end
+
+ def calls(obj, empty, &)
+ [obj.one(*empty), obj.one(&), obj.one(*empty, &)]
+ end
+
+ calls(One.new, [])
+ RUBY
+ end
+
+ def test_kwrest
+ assert_compiles(<<~RUBY, result: true, no_send_fallbacks: true)
+ def req_rest(r1:, **kwrest) = [r1, kwrest]
+ def opt_rest(r1: 1.succ, **kwrest) = [r1, kwrest]
+ def kwrest(**kwrest) = kwrest
+
+ def calls
+ [
+ [1, {}] == req_rest(r1: 1),
+ [1, {:r2=>2, :r3=>3}] == req_rest(r1: 1, r2: 2, r3: 3),
+ [1, {:r2=>2, :r3=>3}] == req_rest(r2: 2, r1:1, r3: 3),
+ [1, {:r2=>2, :r3=>3}] == req_rest(r2: 2, r3: 3, r1: 1),
+
+ [2, {}] == opt_rest,
+ [2, { r2: 2, r3: 3 }] == opt_rest(r2: 2, r3: 3),
+ [0, { r2: 2, r3: 3 }] == opt_rest(r1: 0, r3: 3, r2: 2),
+ [0, { r2: 2, r3: 3 }] == opt_rest(r2: 2, r1: 0, r3: 3),
+ [1, { r2: 2, r3: 3 }] == opt_rest(r2: 2, r3: 3, r1: 1),
+
+ {} == kwrest,
+ { r0: 88, r1: 99 } == kwrest(r0: 88, r1: 99),
+ ]
+ end
+
+ calls.all?
+ RUBY
+ end
+
+ def test_send_polymorphic_method_name
+ assert_compiles(<<~'RUBY', result: %i[ok ok], no_send_fallbacks: true)
+ mid = "dynamic_mid_#{rand(100..200)}"
+ mid_dsym = mid.to_sym
+
+ define_method(mid) { :ok }
+
+ define_method(:send_site) { send(_1) }
+
+ [send_site(mid), send_site(mid_dsym)]
+ RUBY
+ end
+
+ def test_kw_splat_nil
+ assert_compiles(<<~'RUBY', result: %i[ok ok], no_send_fallbacks: true)
+ def id(x) = x
+ def kw_fw(arg, **) = id(arg, **)
+ def use = [kw_fw(:ok), :ok.itself(**nil)]
+
+ use
+ RUBY
+ end
+
+ def test_empty_splat
+ assert_compiles(<<~'RUBY', result: :ok, no_send_fallbacks: true)
+ def foo = :ok
+ def use(empty) = foo(*empty)
+
+ use([])
+ RUBY
+ end
+
+ def test_byteslice_sp_invalidation
+ assert_compiles(<<~'RUBY', result: 'ok', no_send_fallbacks: true)
+ "okng".itself.byteslice(0, 2)
+ RUBY
+ end
+
+ def test_leaf_builtin
+ assert_compiles(code_gc_helpers + <<~'RUBY', exits: :any, result: 1)
+ before = RubyVM::YJIT.runtime_stats[:num_send_iseq_leaf]
+ return 1 if before.nil?
+
+ def entry = self.class
+ entry
+
+ after = RubyVM::YJIT.runtime_stats[:num_send_iseq_leaf]
+ after - before
+ RUBY
+ end
+
+ def test_runtime_stats_types
+ assert_compiles(<<~'RUBY', exits: :any, result: true)
+ def test = :ok
+ 3.times { test }
+
+ stats = RubyVM::YJIT.runtime_stats
+ return true unless stats[:all_stats]
+
+ [
+ stats[:object_shape_count].is_a?(Integer),
+ stats[:ratio_in_yjit].is_a?(Float),
+ ].all?
+ RUBY
+ end
+
+ def test_runtime_stats_key_arg
+ assert_compiles(<<~'RUBY', exits: :any, result: true)
+ def test = :ok
+ 3.times { test }
+
+ # Collect single stat.
+ stat = RubyVM::YJIT.runtime_stats(:ratio_in_yjit)
+
+ # Ensure this invocation had stats.
+ return true unless RubyVM::YJIT.runtime_stats[:all_stats]
+
+ stat > 0.0
+ RUBY
+ end
+
+ def test_runtime_stats_arg_error
+ assert_compiles(<<~'RUBY', exits: :any, result: true)
+ begin
+ RubyVM::YJIT.runtime_stats(Object.new)
+ :no_error
+ rescue TypeError => e
+ e.message == "non-symbol given"
+ end
+ RUBY
+ end
+
+ def test_runtime_stats_unknown_key
+ assert_compiles(<<~'RUBY', exits: :any, result: true)
+ def test = :ok
+ 3.times { test }
+
+ RubyVM::YJIT.runtime_stats(:some_key_unlikely_to_exist).nil?
+ RUBY
+ end
+
+ private
+
+ def code_gc_helpers
+ <<~'RUBY'
+ def compiles(&block)
+ failures = RubyVM::YJIT.runtime_stats[:compilation_failure]
+ block.call
+ failures == RubyVM::YJIT.runtime_stats[:compilation_failure]
+ end
+
+ def add_pages(num_jits)
+ pages = RubyVM::YJIT.runtime_stats[:live_page_count]
+ num_jits.times { return false unless eval('compiles { nil.to_i }') }
+ pages.nil? || pages < RubyVM::YJIT.runtime_stats[:live_page_count]
+ end
+ RUBY
+ end
+
+ def assert_no_exits(script)
+ assert_compiles(script)
+ end
+
+ ANY = Object.new
+ def assert_compiles(
+ test_script, insns: [],
+ call_threshold: 1,
+ stdout: nil,
+ exits: {},
+ result: ANY,
+ frozen_string_literal: nil,
+ mem_size: nil,
+ code_gc: false,
+ no_send_fallbacks: false
+ )
+ reset_stats = <<~RUBY
+ RubyVM::YJIT.runtime_stats
+ RubyVM::YJIT.reset_stats!
+ RUBY
+
+ write_results = <<~RUBY
+ stats = RubyVM::YJIT.runtime_stats
+
+ def collect_insns(iseq)
+ insns = RubyVM::YJIT.insns_compiled(iseq)
+ iseq.each_child { |c| insns.concat collect_insns(c) }
+ insns
+ end
+
+ iseq = RubyVM::InstructionSequence.of(_test_proc)
+ IO.open(3).write Marshal.dump({
+ result: #{result == ANY ? "nil" : "result"},
+ stats: stats,
+ insns: collect_insns(iseq),
+ disasm: iseq.disasm
+ })
+ RUBY
+
+ script = <<~RUBY
+ #{"# frozen_string_literal: " + frozen_string_literal.to_s unless frozen_string_literal.nil?}
+ _test_proc = -> {
+ #{test_script}
+ }
+ #{reset_stats}
+ result = _test_proc.call
+ #{write_results}
+ RUBY
+
+ status, out, err, stats = eval_with_jit(script, call_threshold:, mem_size:, code_gc:)
+
+ assert status.success?, "exited with status #{status.to_i}, stderr:\n#{err}"
+
+ assert_equal stdout.chomp, out.chomp if stdout
+
+ unless ANY.equal?(result)
+ assert_equal result, stats[:result]
+ end
+
+ runtime_stats = stats[:stats]
+ insns_compiled = stats[:insns]
+ disasm = stats[:disasm]
+
+ # Check that exit counts are as expected
+ # Full stats are only available when --enable-yjit=dev
+ if runtime_stats[:all_stats]
+ recorded_exits = runtime_stats.select { |k, v| k.to_s.start_with?("exit_") }
+ recorded_exits = recorded_exits.reject { |k, v| v == 0 }
+
+ recorded_exits.transform_keys! { |k| k.to_s.gsub("exit_", "").to_sym }
+ # Exits can be specified as a hash of stat-name symbol to integer for exact exits.
+ # or stat-name symbol to range if the number of side exits might vary (e.g. write
+ # barriers, cache misses.)
+ if exits != :any &&
+ exits != recorded_exits &&
+ (exits.keys != recorded_exits.keys || !exits.all? { |k, v| v === recorded_exits[k] }) # triple-equal checks range membership or integer equality
+ stats_reasons = StringIO.new
+ ::RubyVM::YJIT.send(:_print_stats_reasons, runtime_stats, stats_reasons)
+ stats_reasons = stats_reasons.string
+ flunk <<~EOM
+ Expected #{exits.empty? ? "no" : exits.inspect} exits, but got:
+ #{recorded_exits.inspect}
+ Reasons:
+ #{stats_reasons}
+ EOM
+ end
+ end
+
+ if no_send_fallbacks
+ assert_equal(0, runtime_stats[:num_send_dynamic], "Expected no use of fallback implementation")
+ end
+
+ # Only available when --enable-yjit=dev
+ if runtime_stats[:all_stats]
+ missed_insns = insns.dup
+
+ insns_compiled.each do |op|
+ if missed_insns.include?(op)
+ # This instruction was compiled
+ missed_insns.delete(op)
+ end
+ end
+
+ unless missed_insns.empty?
+ flunk "Expected to compile instructions #{missed_insns.join(", ")} but didn't.\niseq:\n#{disasm}"
+ end
+ end
+ end
+
+ def script_shell_encode(s)
+ # We can't pass utf-8-encoded characters directly in a shell arg. But we can use Ruby \u constants.
+ s.chars.map { |c| c.ascii_only? ? c : "\\u%x" % c.codepoints[0] }.join
+ end
+
+ def eval_with_jit(script, call_threshold: 1, timeout: 1000, mem_size: nil, code_gc: false)
+ args = [
+ "--disable-gems",
+ "--yjit-call-threshold=#{call_threshold}",
+ "--yjit-stats=quiet"
+ ]
+ args << "--yjit-exec-mem-size=#{mem_size}" if mem_size
+ args << "--yjit-code-gc" if code_gc
+ args << "-e" << script_shell_encode(script)
+ stats_r, stats_w = IO.pipe
+ # Separate thread so we don't deadlock when
+ # the child ruby blocks writing the stats to fd 3
+ stats = ''
+ stats_reader = Thread.new do
+ stats = stats_r.read
+ stats_r.close
+ end
+ out, err, status = invoke_ruby(args, '', true, true, timeout: timeout, ios: { 3 => stats_w })
+ stats_w.close
+ stats_reader.join(timeout)
+ stats = Marshal.load(stats) if !stats.empty?
+ [status, out, err, stats]
+ ensure
+ stats_reader&.kill
+ stats_reader&.join(timeout)
+ stats_r&.close
+ stats_w&.close
+ end
+
+ # A wrapper of EnvUtil.invoke_ruby that uses RbConfig.ruby instead of EnvUtil.ruby
+ # that might use a wrong Ruby depending on your environment.
+ def invoke_ruby(*args, **kwargs)
+ EnvUtil.invoke_ruby(*args, rubybin: RbConfig.ruby, **kwargs)
+ end
+end
diff --git a/test/ruby/test_yjit_exit_locations.rb b/test/ruby/test_yjit_exit_locations.rb
new file mode 100644
index 0000000000..816ab457ce
--- /dev/null
+++ b/test/ruby/test_yjit_exit_locations.rb
@@ -0,0 +1,96 @@
+# frozen_string_literal: true
+#
+# This set of tests can be run with:
+# make test-all TESTS='test/ruby/test_yjit_exit_locations.rb'
+
+require 'test/unit'
+require 'envutil'
+require 'tmpdir'
+require_relative '../lib/jit_support'
+
+return unless JITSupport.yjit_supported?
+
+# Tests for YJIT with assertions on tracing exits
+# insipired by the RJIT tests in test/ruby/test_yjit.rb
+class TestYJITExitLocations < Test::Unit::TestCase
+ def test_yjit_trace_exits_and_v_no_error
+ _stdout, stderr, _status = EnvUtil.invoke_ruby(%w(-v --yjit-trace-exits), '', true, true)
+ refute_includes(stderr, "NoMethodError")
+ end
+
+ def test_trace_exits_expandarray_splat
+ assert_exit_locations('*arr = []')
+ end
+
+ private
+
+ def assert_exit_locations(test_script)
+ write_results = <<~RUBY
+ IO.open(3).write Marshal.dump({
+ enabled: RubyVM::YJIT.trace_exit_locations_enabled?,
+ exit_locations: RubyVM::YJIT.exit_locations
+ })
+ RUBY
+
+ script = <<~RUBY
+ _test_proc = -> {
+ #{test_script}
+ }
+ result = _test_proc.call
+ #{write_results}
+ RUBY
+
+ run_script = eval_with_jit(script)
+ # If stats are disabled when configuring, --yjit-exit-locations
+ # can't be true. We don't want to check if exit_locations hash
+ # is not empty because that could indicate a bug in the exit
+ # locations collection.
+ return unless run_script[:enabled]
+ exit_locations = run_script[:exit_locations]
+
+ assert exit_locations.key?(:raw)
+ assert exit_locations.key?(:frames)
+ assert exit_locations.key?(:lines)
+ assert exit_locations.key?(:samples)
+ assert exit_locations.key?(:missed_samples)
+ assert exit_locations.key?(:gc_samples)
+
+ assert_equal 0, exit_locations[:missed_samples]
+ assert_equal 0, exit_locations[:gc_samples]
+
+ assert_not_empty exit_locations[:raw]
+ assert_not_empty exit_locations[:frames]
+ assert_not_empty exit_locations[:lines]
+
+ exit_locations[:frames].each do |frame_id, frame|
+ assert frame.key?(:name)
+ assert frame.key?(:file)
+ assert frame.key?(:samples)
+ assert frame.key?(:total_samples)
+ assert frame.key?(:edges)
+ end
+ end
+
+ def eval_with_jit(script)
+ args = [
+ "--disable-gems",
+ "--yjit-call-threshold=1",
+ "--yjit-trace-exits"
+ ]
+ args << "-e" << script_shell_encode(script)
+ stats_r, stats_w = IO.pipe
+ _out, _err, _status = EnvUtil.invoke_ruby(args,
+ '', true, true, timeout: 1000, ios: { 3 => stats_w }
+ )
+ stats_w.close
+ stats = stats_r.read
+ stats = Marshal.load(stats) if !stats.empty?
+ stats_r.close
+ stats
+ end
+
+ def script_shell_encode(s)
+ # We can't pass utf-8-encoded characters directly in a shell arg. But we can use Ruby \u constants.
+ s.chars.map { |c| c.ascii_only? ? c : "\\u%x" % c.codepoints[0] }.join
+ end
+end
diff --git a/test/rubygems/alternate_cert.pem b/test/rubygems/alternate_cert.pem
index 54a34441b1..55303190f5 100644
--- a/test/rubygems/alternate_cert.pem
+++ b/test/rubygems/alternate_cert.pem
@@ -1,19 +1,19 @@
-----BEGIN CERTIFICATE-----
-MIIDFjCCAf6gAwIBAgIBBDANBgkqhkiG9w0BAQUFADAtMRIwEAYDVQQDDAlhbHRl
+MIIDFjCCAf6gAwIBAgIBBDANBgkqhkiG9w0BAQsFADAtMRIwEAYDVQQDDAlhbHRl
cm5hdGUxFzAVBgoJkiaJk/IsZAEZFgdleGFtcGxlMCAXDTEyMDEwMTAwMDAwMFoY
Dzk5OTkxMjMxMjM1OTU5WjAtMRIwEAYDVQQDDAlhbHRlcm5hdGUxFzAVBgoJkiaJ
k/IsZAEZFgdleGFtcGxlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
-vZQipBa1xH3M9OonkrUYhGZeX9UHAcJhe6jJbUr/uHXkh1Tu2ERWNnblm85upqBf
-jyZEnKer7uBcwwkkvmisVgC8uBECymsBxuEIw0rfiKYEnLu0B6SiWFYz3dYPS92b
-BK7Vks2/kNyXUmLLGoZ3id2K0eK5C/AJ0j+p84OqPnVhylsjrZmXfIZrh7lkHhgC
-IrzPefjE3pOloi/tz6fh2ktb0FYKQMfweT3Ba2TMeflG13PEOW80AD5w0THxDutG
-G0zPNCDyDEoT7UU1a3B3RMHYuUxEk1GUEYWq9L6a6SMpZISWTSpCp0Ww1QB55PON
-iCCn+o6vcIy46jI71dATAQIDAQABoz8wPTAcBgNVHREEFTATgRFhbHRlcm5hdGVA
-ZXhhbXBsZTAdBgNVHQ4EFgQUyvn/FwcZnA7AkzPjmoooB4/tKgcwDQYJKoZIhvcN
-AQEFBQADggEBAHilxCg0dmOn3hxPjWMf/tAvG/S25iAIZZPuWo71DSSsn/zPRWDZ
-OkDNL7syJ7S2jjrWWCIyLxhj89ZI7Oyd3elOB2zd4RsDij1y9Gv0ZPqNoTp0Repk
-aPtRRLEwk9j2C37Tv+qA2PnTLp8MA0DVkb1/yuSd03b2K/AZEHT8Jtf3WC3RqGSK
-A1+M8CvPSSgPY7oveFFerpqAzfC4tlgyPZjSqBjZucEIlxBD2lA/3JQ8Ys8+0705
-j2jGMl5r1Y22nl0A0+cHGtPX3irtR8bcEAO+rpEfpHNF2APaYsCT7Frk1CtuAHYB
-mEwqWPQKU5ZJOV4uu69Hw5Po2bfgyjKV+N8=
+pebGm7NOnx+DtWG1xQsJBfTfwNlZvfzY61nlZccrhU6vx0AnYNiDZAG3J/gFQmYZ
+9gJ98rzEwfLMCGq9R/TZM+lAEaLhzYZCu3X4QdhKxr1xZ/SFC+1f8KVuH4tLXORW
+30DwayPhNxnrOvup4pWLiYuXUSZpV9CGMvPSUCW2odhMkBMKqaTTPjxoXJIcgacy
+prkNgIq48cSvqWG/e/HrMRtkqvFbD5ta00uO1mlpajYYw1RRftEwktFo8vQgDBo9
+NT/EqoE72tffaDnLq6rQrVtw4Kr9fy775DjNAWXyiCBjnJgOQSXCGPsM/AEdFrh/
+LKQQv2M/M7WNevnEUgsEIwIDAQABoz8wPTAcBgNVHREEFTATgRFhbHRlcm5hdGVA
+ZXhhbXBsZTAdBgNVHQ4EFgQUYPwS8g98+4Tq/8gcEK1iilkGXH4wDQYJKoZIhvcN
+AQELBQADggEBABSKUFmTk53+yrVFT3TvX5iGgXudNdACQqcnknAg66Q8+wMA8WT1
+M2oZJIH4SWSKUGMYubpYuc53tTtMnR594LPidyNbxo8KXMYoNfEkZCk6hh0eKVdx
+zPJSZ4fOQ4mKFCd7HrycOr4bxuGPTVQERYJ45vZnhvVJDIRMgshnQuivP3VBwXkQ
+gKLTCh2ew2ZJgPi1dfqdNMMSw7k4OQtQVhwbAkHgwL1TUShAO9lHzxFHlQgssfR0
+f6c89eB035Vn9s21StjerTOlC9+v4hOO7QhvbsCcUs2wWiE1BWo1QqnVBCjGKyVE
+fISkJd1Sn5j+Vx/NJ7EfZcOGGQMdxHC+c90=
-----END CERTIFICATE-----
diff --git a/test/rubygems/alternate_cert_32.pem b/test/rubygems/alternate_cert_32.pem
index adeffda24a..e727189470 100644
--- a/test/rubygems/alternate_cert_32.pem
+++ b/test/rubygems/alternate_cert_32.pem
@@ -1,19 +1,19 @@
-----BEGIN CERTIFICATE-----
-MIIDFDCCAfygAwIBAgIBBTANBgkqhkiG9w0BAQUFADAtMRIwEAYDVQQDDAlhbHRl
+MIIDFDCCAfygAwIBAgIBBTANBgkqhkiG9w0BAQsFADAtMRIwEAYDVQQDDAlhbHRl
cm5hdGUxFzAVBgoJkiaJk/IsZAEZFgdleGFtcGxlMB4XDTEyMDEwMTAwMDAwMFoX
DTM4MDExOTAzMTQwN1owLTESMBAGA1UEAwwJYWx0ZXJuYXRlMRcwFQYKCZImiZPy
-LGQBGRYHZXhhbXBsZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL2U
-IqQWtcR9zPTqJ5K1GIRmXl/VBwHCYXuoyW1K/7h15IdU7thEVjZ25ZvObqagX48m
-RJynq+7gXMMJJL5orFYAvLgRAsprAcbhCMNK34imBJy7tAekolhWM93WD0vdmwSu
-1ZLNv5Dcl1JiyxqGd4nditHiuQvwCdI/qfODqj51YcpbI62Zl3yGa4e5ZB4YAiK8
-z3n4xN6TpaIv7c+n4dpLW9BWCkDH8Hk9wWtkzHn5RtdzxDlvNAA+cNEx8Q7rRhtM
-zzQg8gxKE+1FNWtwd0TB2LlMRJNRlBGFqvS+mukjKWSElk0qQqdFsNUAeeTzjYgg
-p/qOr3CMuOoyO9XQEwECAwEAAaM/MD0wHAYDVR0RBBUwE4ERYWx0ZXJuYXRlQGV4
-YW1wbGUwHQYDVR0OBBYEFMr5/xcHGZwOwJMz45qKKAeP7SoHMA0GCSqGSIb3DQEB
-BQUAA4IBAQA1Vs3lcPpqnbsdtFDgrzApZuNgtyCRbbSrshq37dem9wSI4aFjAPLx
-QGgf3c+XZczK9FkR3VUHcK8yZFrCKpv9giZDvzCUOMB/HSBAzNiNbhgUC1S0THir
-xFriDITPoY7mrdJlX41Ssqk6tIKZsYP63UVghy7f9wxqXJvyfJZSB9UeM+0baQVL
-tGTKXmvzLw1Pc/LHTrt7jcZT9UbBsxNNy0Wk9FPPePCUUlegRjInd/sNevywzL/T
-1DL0BefqF6iyWcu86Udo+eli1JDzeUsfHOL7oqJGlWhlZHRDJ1M89n5KwPg8SCx5
-TpemV2Wy0nRTzITnmggexlMibSJ0iOvC
+LGQBGRYHZXhhbXBsZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKXm
+xpuzTp8fg7VhtcULCQX038DZWb382OtZ5WXHK4VOr8dAJ2DYg2QBtyf4BUJmGfYC
+ffK8xMHyzAhqvUf02TPpQBGi4c2GQrt1+EHYSsa9cWf0hQvtX/Clbh+LS1zkVt9A
+8Gsj4TcZ6zr7qeKVi4mLl1EmaVfQhjLz0lAltqHYTJATCqmk0z48aFySHIGnMqa5
+DYCKuPHEr6lhv3vx6zEbZKrxWw+bWtNLjtZpaWo2GMNUUX7RMJLRaPL0IAwaPTU/
+xKqBO9rX32g5y6uq0K1bcOCq/X8u++Q4zQFl8oggY5yYDkElwhj7DPwBHRa4fyyk
+EL9jPzO1jXr5xFILBCMCAwEAAaM/MD0wHAYDVR0RBBUwE4ERYWx0ZXJuYXRlQGV4
+YW1wbGUwHQYDVR0OBBYEFGD8EvIPfPuE6v/IHBCtYopZBlx+MA0GCSqGSIb3DQEB
+CwUAA4IBAQBJeq9kniAdddOY2r9MhRYb8/rzWL1mcCgbIzkwXCTeOyVt0nWZZwAy
+arEy8ofkXt1O3Bm+59+dPORnG5WJeBGVmGDHo9HxDjm4dgTramYqgtxbthmB/pu+
+QhJ5DQg59odomoRRG7dkqacd8GMdcJVYcb3OzV3Fe5v2gtvnVPZ711APtjZ7sZUR
+4XBA+ok95QFeSUYo4WIOCHh16pPtZ9ium5SZ7ChVVNj5rthr+sS+rQKjEdjG510w
+UOkg8rUjEvXPGjM80/DnOvzyRJvbcCWBWWHquft3wqbjTomnQtqHne2SwRFEyfpd
+JLEuY9QtEUCUy7obccN39+nT9jUOyg3B
-----END CERTIFICATE-----
diff --git a/test/rubygems/alternate_key.pem b/test/rubygems/alternate_key.pem
index 14ca734aba..ae587b3425 100644
--- a/test/rubygems/alternate_key.pem
+++ b/test/rubygems/alternate_key.pem
@@ -1,27 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
-MIIEowIBAAKCAQEAvZQipBa1xH3M9OonkrUYhGZeX9UHAcJhe6jJbUr/uHXkh1Tu
-2ERWNnblm85upqBfjyZEnKer7uBcwwkkvmisVgC8uBECymsBxuEIw0rfiKYEnLu0
-B6SiWFYz3dYPS92bBK7Vks2/kNyXUmLLGoZ3id2K0eK5C/AJ0j+p84OqPnVhylsj
-rZmXfIZrh7lkHhgCIrzPefjE3pOloi/tz6fh2ktb0FYKQMfweT3Ba2TMeflG13PE
-OW80AD5w0THxDutGG0zPNCDyDEoT7UU1a3B3RMHYuUxEk1GUEYWq9L6a6SMpZISW
-TSpCp0Ww1QB55PONiCCn+o6vcIy46jI71dATAQIDAQABAoIBAArXgfOoaNTH7QTE
-r2awfKp1wEfywufS2ghcasiZVW6TL3Kd5NrxbYzH1/HFKIbW/SAOrDXZUPfkVOnC
-iBtrmQ+CE0jjkClLXVqmW/3vNkF2XSUphu44+B/dLjItn8pS7h6icQxoP+Bk/TJ0
-+/CUaBm2Vc4TDUolfCpOAcYvbXkM3BL+N/XN2JHX52D2ljXtryrNm/sFnabUVo96
-ghWqln8TqpYTagcs/JkEQ5YxwqFuBLofz3SgzCnf8ub8WTIpYhWzWZ4yHjZSL7AS
-54mkJarKWMUYcL/Qeuy1U9vxLrbC9V7cPzSkzYxPZF7XlYaJcAbItX182ufZ1uNX
-3JlQS5ECgYEA+6fbg+WKy5AazEs8YokPjq1X1P01o95KUWFg+68ALowQXEYcExew
-PG0BKW11WrR6Bnn41++13k8Qsrq7Tl8ynCO6ANhoWAxUksdJDAuEgQqpFuRXwa/D
-d++8WlWD4XYqLwiE+h72alE/Ce/SdfPPsyBeHtXo7fih378WyZn7K9cCgYEAwNnw
-zjndLtj9bxd4awHHWgQ7QpKCmtLMGlg7Teo9aODMO80G3h8NEEG6Ou6LHn88tqgH
-yu0WcjJmhINAzNzmABdw+WuV4C94glwtXctQ0w4byuLOaKSh3ggWUnKf56A2KyPh
-JHPe/+A1DTKAgBvU/i5Vx0kZBkUMiiEVcIOgHOcCgYBNkt6998IjIdbA5uhET4+2
-IYUTqMIiM2GhWG026CkcMBzS9OGumPzAg7F5/b3RKhT7bhnhJolfb+vrzFf0vq+x
-JeouXIc9rP9dB4Vi6yH7TTf2UIkksXOFwybCid3PYEd8nBmxqF25RDY0b/LmXTPH
-OdEJnFLjGGN9vz/dAVRFnQKBgQC8hE8hSO8uHG+haRANim+VTw2exhllvypFlnpi
-b9gX7ae3zXQpLbFXcujZMtZLuZVf+GGlvJ10hFAyuRtfJ5CuBjwplUGtJLpotDKk
-vVsE9YW1joC3SjfxE3a+oc4uXi6VfT1YpOwYtNMnU3bJxGsxDZpMdOhBeL4JSM3s
-br7VgQKBgBDdJHRQOkP41Iq7CjcheTJMeXsQJt+HLHSIpEkxi8v/9bLKPbRVRo7e
-8mmEr9mvjrNLVZMrQpgngRGbFzcdi9iDv+4m0OKU7BGZyWy1gtlUV77FqsL7EEl3
-gdM670c2kkrni5DdpTLpNgF6zRKK7ArZ6kSgmuEYJCGHHlpbkg3f
+MIIEpQIBAAKCAQEApebGm7NOnx+DtWG1xQsJBfTfwNlZvfzY61nlZccrhU6vx0An
+YNiDZAG3J/gFQmYZ9gJ98rzEwfLMCGq9R/TZM+lAEaLhzYZCu3X4QdhKxr1xZ/SF
+C+1f8KVuH4tLXORW30DwayPhNxnrOvup4pWLiYuXUSZpV9CGMvPSUCW2odhMkBMK
+qaTTPjxoXJIcgacyprkNgIq48cSvqWG/e/HrMRtkqvFbD5ta00uO1mlpajYYw1RR
+ftEwktFo8vQgDBo9NT/EqoE72tffaDnLq6rQrVtw4Kr9fy775DjNAWXyiCBjnJgO
+QSXCGPsM/AEdFrh/LKQQv2M/M7WNevnEUgsEIwIDAQABAoIBABB/S16uTPIr2xgN
+WFr4xvPtrtZphrAK1bNJpDMjxCMkePxSV9gcj6xBM2ppEnTQ3GIHS2j49oPm1f08
+SAhAw9ySpElcriGW6Unk6EP78yuiKQXSXeyatUCj4riGTH83QaA/v+iXj8y/6hFa
+d0FN56tM00ZBkJYn6UBl2JMZvPiI9cdRO1KhhK4+NZrKg8jdRwjJe9fxo31xefpr
+jNqyx7O06hzaVfMt5jUi5qSc+/1EWJtXlvCyuJJCjpEay6ePUP5eTi/hQpwfaO82
+nIRXolwg7TPxg8rea6WQM/x6Ec3MWYUflJUdZbKDQQv1pyZR62T7WHNA1p5jHMzq
+MW3kctkCgYEAxhnT8+TZG9sF/fQro0JZnKxnZXjQ9ob7vmvbyBgHf2HzrY716UkX
+vLAHrykgqzZmIlWATayCryr+CzkaXu/xLrS0IMmjF//VlFjlob6OL9n40qrOW221
+ryqNNaKkMmm4c4N9D1rhsNH+vVQoeEDkHet9Pll9ilB2o3ERapMfBzcCgYEA1mO+
+iJLf7y1chmpwMWLFrK4hjPK6670K4UvDCfX6517xHtykZ05lZQ9OQLjjDsyG8Uub
+H6k7KxCTV+zxLQDcUUEh/UbTb6eMhh2HAU+Bym8+lWCIdl8qPouPKz1dc+rImRwC
+JE7LtxbyHXv67sPL5/7GhmdCxThXQvjH7fP1CHUCgYEArbj4pmmJ+2OXXZ1Cp2kI
+LN0Dz3ijx42YNuVfV5m6+Xpst0cnX+05Y776/iCTBZIu/uz8FyGxeOu63Ry2g4rn
+do4BaL9qxyETq4RJ3A2/ozcDfbtMO+F58qLeMqruU0di+enVQiHwyZ9eRaoH020U
+nyhkLMlNzn3BjJMbMtrR2wECgYEAm54tSI9sUv2XQs5x/7cVi6GeIuRyP/mpsx2+
+RjWx2U52MZOxFne2a+PvRlWuIyjc7ruVrya1Fy5h9Zm8+pC8W5KurF1DzrFM9HDs
+dUwUBzA2ulEm3N15GYtN8fIKKsEKuPC2sUos3wqd1j8PR08CbLTnv9mmgufBl5Bj
+91p0y50CgYEAsD/KO1/BTJWVFAXoPgde4Fmt3vQyF7OYkOI0EEIGSVPydo8ebNib
+cozGB1H0vhuvdrysi1Oc+uZ2pL8gpZfdYXbmD9cScXL+pP+GUmKKHTKKGAeQCWpv
+2M3MZEjqOGQrqY50khXUDi77H1sAHMIBQ8yF6mdb+YU+OayRwBZmHiI=
-----END RSA PRIVATE KEY-----
diff --git a/test/rubygems/bad_rake.rb b/test/rubygems/bad_rake.rb
index a08aa7dacc..e15a7d4156 100644
--- a/test/rubygems/bad_rake.rb
+++ b/test/rubygems/bad_rake.rb
@@ -1,2 +1,3 @@
# frozen_string_literal: true
+
exit 1
diff --git a/test/rubygems/bundler_test_gem.rb b/test/rubygems/bundler_test_gem.rb
new file mode 100644
index 0000000000..ca2980e04b
--- /dev/null
+++ b/test/rubygems/bundler_test_gem.rb
@@ -0,0 +1,424 @@
+# frozen_string_literal: true
+
+require_relative "helper"
+
+class TestBundlerGem < Gem::TestCase
+ PROJECT_DIR = File.expand_path("../..", __dir__)
+
+ def test_self_use_gemdeps
+ with_local_bundler_at(Gem.dir) do
+ with_rubygems_gemdeps("-") do
+ FileUtils.mkdir_p "detect/a/b"
+ FileUtils.mkdir_p "detect/a/Isolate"
+
+ FileUtils.touch "detect/Isolate"
+
+ begin
+ Dir.chdir "detect/a/b"
+
+ Gem.use_gemdeps
+
+ assert_equal add_bundler_full_name([]), loaded_spec_names
+ ensure
+ Dir.chdir @tempdir
+ end
+ end
+ end
+ end
+
+ def test_self_find_files_with_gemfile
+ with_local_bundler_at(Gem.dir) do
+ cwd = File.expand_path("test/rubygems", PROJECT_DIR)
+ actual_load_path = $LOAD_PATH.unshift(cwd).dup
+
+ discover_path = File.join "lib", "sff", "discover.rb"
+
+ foo1, _ = %w[1 2].map do |version|
+ spec = quick_gem "sff", version do |s|
+ s.files << discover_path
+ end
+
+ write_file(File.join("gems", spec.full_name, discover_path)) do |fp|
+ fp.puts "# #{spec.full_name}"
+ end
+
+ spec
+ end
+ Gem.refresh
+
+ write_file(File.join(Dir.pwd, "Gemfile")) do |fp|
+ fp.puts "source 'https://rubygems.org'"
+ fp.puts "gem '#{foo1.name}', '#{foo1.version}'"
+ end
+ Gem.use_gemdeps(File.join(Dir.pwd, "Gemfile"))
+
+ expected = [
+ File.expand_path("test/rubygems/sff/discover.rb", PROJECT_DIR),
+ File.join(foo1.full_gem_path, discover_path),
+ ].sort
+
+ assert_equal expected, Gem.find_files("sff/discover").sort
+ assert_equal expected, Gem.find_files("sff/**.rb").sort, "[ruby-core:31730]"
+ assert_equal cwd, actual_load_path.shift
+ end
+ end
+
+ def test_auto_activation_of_specific_gemdeps_file
+ with_local_bundler_at(Gem.dir) do
+ a = util_spec "a", "1", nil, "lib/a.rb"
+ b = util_spec "b", "1", nil, "lib/b.rb"
+ c = util_spec "c", "1", nil, "lib/c.rb"
+
+ install_specs a, b, c
+
+ path = File.join @tempdir, "gem.deps.rb"
+
+ File.open path, "w" do |f|
+ f.puts "gem 'a'"
+ f.puts "gem 'b'"
+ f.puts "gem 'c'"
+ end
+
+ with_rubygems_gemdeps(path) do
+ Gem.use_gemdeps
+
+ assert_equal add_bundler_full_name(%W[a-1 b-1 c-1]), loaded_spec_names
+ end
+ end
+ end
+
+ def test_auto_activation_of_used_gemdeps_file
+ with_local_bundler_at(Gem.dir) do
+ a = util_spec "a", "1", nil, "lib/a.rb"
+ b = util_spec "b", "1", nil, "lib/b.rb"
+ c = util_spec "c", "1", nil, "lib/c.rb"
+
+ install_specs a, b, c
+
+ path = File.join @tempdir, "gem.deps.rb"
+
+ File.open path, "w" do |f|
+ f.puts "gem 'a'"
+ f.puts "gem 'b'"
+ f.puts "gem 'c'"
+ end
+
+ with_rubygems_gemdeps("-") do
+ expected_specs = [a, b, util_spec("bundler", Bundler::VERSION), c].compact.map(&:full_name)
+
+ Gem.use_gemdeps
+
+ assert_equal expected_specs, loaded_spec_names
+ end
+ end
+ end
+
+ def test_looks_for_gemdeps_files_automatically_from_binstubs
+ path = File.join(@tempdir, "gd-tmp")
+
+ with_local_bundler_at(path) do
+ a = util_spec "a", "1" do |s|
+ s.executables = %w[foo]
+ s.bindir = "exe"
+ end
+
+ write_file File.join(@tempdir, "exe", "foo") do |fp|
+ fp.puts "puts Gem.loaded_specs.values.map(&:full_name).sort"
+ end
+
+ b = util_spec "b", "1", nil, "lib/b.rb"
+ c = util_spec "c", "1", nil, "lib/c.rb"
+
+ install_specs a, b, c
+
+ install_gem a, install_dir: path
+ install_gem b, install_dir: path
+ install_gem c, install_dir: path
+
+ ENV["GEM_PATH"] = path
+
+ with_rubygems_gemdeps("-") do
+ new_path = [File.join(path, "bin"), ENV["PATH"]].join(File::PATH_SEPARATOR)
+ new_rubyopt = "-I#{rubygems_path} -I#{bundler_path}"
+
+ path = File.join @tempdir, "gem.deps.rb"
+
+ File.open path, "w" do |f|
+ f.puts "gem 'a'"
+ end
+ out0 = with_path_and_rubyopt(new_path, new_rubyopt) do
+ IO.popen("foo", &:read).split(/\n/)
+ end
+
+ File.open path, "a" do |f|
+ f.puts "gem 'b'"
+ f.puts "gem 'c'"
+ end
+ out = with_path_and_rubyopt(new_path, new_rubyopt) do
+ IO.popen("foo", &:read).split(/\n/)
+ end
+
+ assert_equal ["b-1", "c-1"], out - out0
+ end
+ end
+ end
+
+ def test_looks_for_gemdeps_files_automatically_from_binstubs_in_parent_dir
+ path = File.join(@tempdir, "gd-tmp")
+
+ with_local_bundler_at(path) do
+ pend "IO.popen has issues on JRuby when passed :chdir" if Gem.java_platform?
+
+ a = util_spec "a", "1" do |s|
+ s.executables = %w[foo]
+ s.bindir = "exe"
+ end
+
+ write_file File.join(@tempdir, "exe", "foo") do |fp|
+ fp.puts "puts Gem.loaded_specs.values.map(&:full_name).sort"
+ end
+
+ b = util_spec "b", "1", nil, "lib/b.rb"
+ c = util_spec "c", "1", nil, "lib/c.rb"
+
+ install_specs a, b, c
+
+ install_gem a, install_dir: path
+ install_gem b, install_dir: path
+ install_gem c, install_dir: path
+
+ ENV["GEM_PATH"] = path
+
+ with_rubygems_gemdeps("-") do
+ Dir.mkdir "sub1"
+
+ new_path = [File.join(path, "bin"), ENV["PATH"]].join(File::PATH_SEPARATOR)
+ new_rubyopt = "-I#{rubygems_path} -I#{bundler_path}"
+
+ path = File.join @tempdir, "gem.deps.rb"
+
+ File.open path, "w" do |f|
+ f.puts "gem 'a'"
+ end
+ out0 = with_path_and_rubyopt(new_path, new_rubyopt) do
+ IO.popen("foo", chdir: "sub1", &:read).split(/\n/)
+ end
+
+ File.open path, "a" do |f|
+ f.puts "gem 'b'"
+ f.puts "gem 'c'"
+ end
+ out = with_path_and_rubyopt(new_path, new_rubyopt) do
+ IO.popen("foo", chdir: "sub1", &:read).split(/\n/)
+ end
+
+ Dir.rmdir "sub1"
+
+ assert_equal ["b-1", "c-1"], out - out0
+ end
+ end
+ end
+
+ def test_use_gemdeps
+ with_local_bundler_at(Gem.dir) do
+ gem_deps_file = "gem.deps.rb"
+ spec = util_spec "a", 1
+ install_specs spec
+
+ spec = Gem::Specification.find {|s| s == spec }
+ refute spec.activated?
+
+ File.open gem_deps_file, "w" do |io|
+ io.write 'gem "a"'
+ end
+
+ assert_nil Gem.gemdeps
+
+ Gem.use_gemdeps gem_deps_file
+
+ assert_equal add_bundler_full_name(%W[a-1]), loaded_spec_names
+ refute_nil Gem.gemdeps
+ end
+ end
+
+ def test_use_gemdeps_ENV
+ with_local_bundler_at(Gem.dir) do
+ with_rubygems_gemdeps(nil) do
+ spec = util_spec "a", 1
+
+ refute spec.activated?
+
+ File.open "gem.deps.rb", "w" do |io|
+ io.write 'gem "a"'
+ end
+
+ Gem.use_gemdeps
+
+ refute spec.activated?
+ end
+ end
+ end
+
+ def test_use_gemdeps_argument_missing
+ with_local_bundler_at(Gem.dir) do
+ e = assert_raise ArgumentError do
+ Gem.use_gemdeps "gem.deps.rb"
+ end
+
+ assert_equal "Unable to find gem dependencies file at gem.deps.rb",
+ e.message
+ end
+ end
+
+ def test_use_gemdeps_argument_missing_match_ENV
+ with_local_bundler_at(Gem.dir) do
+ with_rubygems_gemdeps("gem.deps.rb") do
+ e = assert_raise ArgumentError do
+ Gem.use_gemdeps "gem.deps.rb"
+ end
+
+ assert_equal "Unable to find gem dependencies file at gem.deps.rb",
+ e.message
+ end
+ end
+ end
+
+ def test_use_gemdeps_automatic
+ with_local_bundler_at(Gem.dir) do
+ with_rubygems_gemdeps("-") do
+ spec = util_spec "a", 1
+ install_specs spec
+ spec = Gem::Specification.find {|s| s == spec }
+
+ refute spec.activated?
+
+ File.open "Gemfile", "w" do |io|
+ io.write 'gem "a"'
+ end
+
+ Gem.use_gemdeps
+
+ assert_equal add_bundler_full_name(%W[a-1]), loaded_spec_names
+ end
+ end
+ end
+
+ def test_use_gemdeps_automatic_missing
+ with_local_bundler_at(Gem.dir) do
+ with_rubygems_gemdeps("-") do
+ Gem.use_gemdeps
+
+ assert true # count
+ end
+ end
+ end
+
+ def test_use_gemdeps_disabled
+ with_local_bundler_at(Gem.dir) do
+ with_rubygems_gemdeps("") do
+ spec = util_spec "a", 1
+
+ refute spec.activated?
+
+ File.open "gem.deps.rb", "w" do |io|
+ io.write 'gem "a"'
+ end
+
+ Gem.use_gemdeps
+
+ refute spec.activated?
+ end
+ end
+ end
+
+ def test_use_gemdeps_missing_gem
+ with_local_bundler_at(Gem.dir) do
+ with_rubygems_gemdeps("x") do
+ File.open "x", "w" do |io|
+ io.write 'gem "a"'
+ end
+
+ expected = <<-EXPECTED
+Could not find gem 'a' in locally installed gems.
+You may need to `bundle install` to install missing gems
+
+ EXPECTED
+
+ Gem::Deprecate.skip_during do
+ actual_stdout, actual_stderr = capture_output do
+ Gem.use_gemdeps
+ end
+ assert_empty actual_stdout
+ assert_equal(expected, actual_stderr)
+ end
+ end
+ end
+ end
+
+ def test_use_gemdeps_specific
+ with_local_bundler_at(Gem.dir) do
+ with_rubygems_gemdeps("x") do
+ spec = util_spec "a", 1
+ install_specs spec
+
+ spec = Gem::Specification.find {|s| s == spec }
+ refute spec.activated?
+
+ File.open "x", "w" do |io|
+ io.write 'gem "a"'
+ end
+
+ Gem.use_gemdeps
+
+ assert_equal add_bundler_full_name(%W[a-1]), loaded_spec_names
+ end
+ end
+ end
+
+ private
+
+ def add_bundler_full_name(names)
+ names << "bundler-#{Bundler::VERSION}"
+ names.sort!
+ names
+ end
+
+ def with_path_and_rubyopt(path_value, rubyopt_value)
+ path = ENV["PATH"]
+ ENV["PATH"] = path_value
+ rubyopt = ENV["RUBYOPT"]
+ ENV["RUBYOPT"] = rubyopt_value
+
+ yield
+ ensure
+ ENV["PATH"] = path
+ ENV["RUBYOPT"] = rubyopt
+ end
+
+ def with_rubygems_gemdeps(value)
+ rubygems_gemdeps = ENV["RUBYGEMS_GEMDEPS"]
+ ENV["RUBYGEMS_GEMDEPS"] = value
+
+ yield
+ ensure
+ ENV["RUBYGEMS_GEMDEPS"] = rubygems_gemdeps
+ end
+
+ def with_local_bundler_at(path)
+ require "bundler"
+
+ # If bundler gemspec exists, pretend it's installed
+ bundler_gemspec = File.expand_path("../../bundler/bundler.gemspec", __dir__)
+ if File.exist?(bundler_gemspec)
+ target_gemspec_location = "#{path}/specifications/bundler-#{Bundler::VERSION}.gemspec"
+
+ FileUtils.mkdir_p File.dirname(target_gemspec_location)
+
+ File.write target_gemspec_location, Gem::Specification.load(bundler_gemspec).to_ruby_for_cache
+ end
+
+ yield
+ ensure
+ Bundler.reset!
+ end
+end
diff --git a/test/rubygems/child_cert.pem b/test/rubygems/child_cert.pem
index 9293cfc966..26c916cf96 100644
--- a/test/rubygems/child_cert.pem
+++ b/test/rubygems/child_cert.pem
@@ -1,20 +1,19 @@
-----BEGIN CERTIFICATE-----
-MIIDTTCCAjWgAwIBAgIBAjANBgkqhkiG9w0BAQUFADAqMQ8wDQYDVQQDDAZub2Jv
+MIIDLDCCAhSgAwIBAgIBAjANBgkqhkiG9w0BAQsFADAqMQ8wDQYDVQQDDAZub2Jv
ZHkxFzAVBgoJkiaJk/IsZAEZFgdleGFtcGxlMCAXDTEyMDEwMTAwMDAwMFoYDzk5
OTkxMjMxMjM1OTU5WjApMQ4wDAYDVQQDDAVjaGlsZDEXMBUGCgmSJomT8ixkARkW
-B2V4YW1wbGUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDKf7+1q0cR
-MhC/RM6Whpon/5IxuSve3CCxxdN0LcSbUisFMlf28Zj+S545SKFc6gHFcnYLZZsy
-Gm4FWEd4DhNpg/kgoDPuPGwQp2DEOvKnnneB/Shj8V+6oLrjXaZFAu8Q916c5/BL
-z+PlHIIsO/Q865XOK+5z1sZi0xval8QT7u4Usrcy86gevflCbpBAWkNPa/DZDqA9
-nk0vB2XDSHvhavcrYLfDrYAnFz3wiZ70LYQrmdeOqkPpaiw//Qpzqp+vtuF2br6U
-iYWpN+dhdFsIxAwIE5kWZ1kk6OBJ4kHvr+Sh8Oqbf6WFBhW/lQa9wldA0xhNwhGr
-1FDEfC+0g/BvAgMBAAGjfTB7MBgGA1UdEQQRMA+BDWNoaWxkQGV4YW1wbGUwHQYD
-VR0OBBYEFHzVU9N7sklKBPrHElxoZ32Fg64IMB8GA1UdIwQYMBaAFF9DbvaajkUl
-6SLjfTdepNU2AoUbMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgIEMA0G
-CSqGSIb3DQEBBQUAA4IBAQAKRUboW7dwIHuzOp+7Nbx+ltWLUgwMkDLjjXjJE1Tv
-L+NNmAx2iv0WghyoKaUBYW+SgIcenQoMfIA+K8Z6a4dUruJ0TKsUgLW8sx3wx9h8
-NwjjybsUh8mN+7EtQ5HtkLKp4F1eOqb+eTIPpCPYP8GyzUGDcFG0pdzhcHvqOKOd
-sRYzkxyf/f8DE+6P01F1EPTql8pZLLirOfZjUtboUY3gZr2JQ03RzTk3dcjEr4pI
-wvQV8rAkj3GE638iBEByzQb/HHN+c9fLAM7f1IDcHS49jZj1gCiuCAVlf52zUmwd
-NnBgKyVrEVhf02sDgXRpoTmoRfwmcMd2cWGvDmRiijHo
+B2V4YW1wbGUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCHyxiIjR9Z
+m3tznMc8OqAvm5h14DAUin+2eq1HzjQZ1fxkTtP4i05ieppHLTxfJrM9mH5H6sb3
+NSNtX/L7p229tM3on8UPUZRp7qDmFNTpgdRbf03ZJFDp3MTprA85wq++gc7GMI6q
+QHhLuc3gshuy4iFzVfrWE0MRF/aVkEiH91iNUCZ3vZTahDG/jTafyMYnADE+26mj
+fK8yCoTA6qYnYQrMPy3jcr0g3aak5+z5Gn55qIJklaAXV7vAyoNgYIq6MjXs9J0f
+kedZWwJTEfAarZDo2s9wEQi7McPzv4HmNB3H6JfJsAVgaD0WtQcAVr7Ngr24lIx4
+AMY7koGayD+VAgMBAAGjXDBaMBgGA1UdEQQRMA+BDWNoaWxkQGV4YW1wbGUwHQYD
+VR0OBBYEFEVZPH+Sg200JF29GN4RJ13XfpIWMA8GA1UdEwEB/wQFMAMBAf8wDgYD
+VR0PAQH/BAQDAgIEMA0GCSqGSIb3DQEBCwUAA4IBAQABo0B3iS7ykcIBRflUTQtd
+ji60ZVsX+pseEvpFvlurdKR4vrhBu/5LImQxk3wMepEhyzXZbKBanWJjgZcfJBKA
+XqWFAPu80WPunonxUpNdgKMouRBCmzmKwXojzafpZUKTZKEm7q8cbE7u1Eye8Ipv
+uj41TMlIpGvJnjfGKugJh2Gu+5Sfl7P6h8nLvM5dkJW8WsRRMGc7vFEXKCvsZbth
+wclhJXWciI4wsGUENTPpqxWhO2uj80/ob3rUNgIwROKeyBWXPUVKCme4AII5Cqk7
+qwQzNIRwWofBIb7TV2aICnFUHb3NHZEjMacviaMI+Nl5ND+gDAdc8YQmXrSHg1fW
-----END CERTIFICATE-----
diff --git a/test/rubygems/child_cert_32.pem b/test/rubygems/child_cert_32.pem
index 3484803a20..4e2fcf10df 100644
--- a/test/rubygems/child_cert_32.pem
+++ b/test/rubygems/child_cert_32.pem
@@ -1,20 +1,19 @@
-----BEGIN CERTIFICATE-----
-MIIDSzCCAjOgAwIBAgIBAzANBgkqhkiG9w0BAQUFADAqMQ8wDQYDVQQDDAZub2Jv
+MIIDKjCCAhKgAwIBAgIBAzANBgkqhkiG9w0BAQsFADAqMQ8wDQYDVQQDDAZub2Jv
ZHkxFzAVBgoJkiaJk/IsZAEZFgdleGFtcGxlMB4XDTEyMDEwMTAwMDAwMFoXDTM4
MDExOTAzMTQwN1owKTEOMAwGA1UEAwwFY2hpbGQxFzAVBgoJkiaJk/IsZAEZFgdl
-eGFtcGxlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyn+/tatHETIQ
-v0TOloaaJ/+SMbkr3twgscXTdC3Em1IrBTJX9vGY/kueOUihXOoBxXJ2C2WbMhpu
-BVhHeA4TaYP5IKAz7jxsEKdgxDryp553gf0oY/FfuqC6412mRQLvEPdenOfwS8/j
-5RyCLDv0POuVzivuc9bGYtMb2pfEE+7uFLK3MvOoHr35Qm6QQFpDT2vw2Q6gPZ5N
-Lwdlw0h74Wr3K2C3w62AJxc98Ime9C2EK5nXjqpD6WosP/0Kc6qfr7bhdm6+lImF
-qTfnYXRbCMQMCBOZFmdZJOjgSeJB76/kofDqm3+lhQYVv5UGvcJXQNMYTcIRq9RQ
-xHwvtIPwbwIDAQABo30wezAYBgNVHREEETAPgQ1jaGlsZEBleGFtcGxlMB0GA1Ud
-DgQWBBR81VPTe7JJSgT6xxJcaGd9hYOuCDAfBgNVHSMEGDAWgBRfQ272mo5FJeki
-4303XqTVNgKFGzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwICBDANBgkq
-hkiG9w0BAQUFAAOCAQEAhHnhcklUtCnLXVr4aCgdNgeuBMqT/v7cJFWGjy0s0isu
-zsAHZ59caMGonykuZWwxQE2ytzMhz1fC1mRH5kfYy2h2uFHGzaexrK4n2BX0HIE+
-XFyZxDW5kwKrpmXrEeo6JVWftCoINrw3eY3iuQc3pKpLtGdir4MKByM90CcjHxzQ
-RFvI9JzRY5TmY3nXdP3JNi4rNGZULEl+Hdm79LS6yrXthZQ4dqeMqJqXLggdVPf5
-5302z//0QKi+nK3UnTi5hbEOC9xUW2n5Yj2dJnSkD/aQFapobMaww8SbbOJ3IMK0
-hsI7EPoqOCw4egbv9SlvlVOQTPDqpZfSfT4Id0AnpA==
+eGFtcGxlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAh8sYiI0fWZt7
+c5zHPDqgL5uYdeAwFIp/tnqtR840GdX8ZE7T+ItOYnqaRy08XyazPZh+R+rG9zUj
+bV/y+6dtvbTN6J/FD1GUae6g5hTU6YHUW39N2SRQ6dzE6awPOcKvvoHOxjCOqkB4
+S7nN4LIbsuIhc1X61hNDERf2lZBIh/dYjVAmd72U2oQxv402n8jGJwAxPtupo3yv
+MgqEwOqmJ2EKzD8t43K9IN2mpOfs+Rp+eaiCZJWgF1e7wMqDYGCKujI17PSdH5Hn
+WVsCUxHwGq2Q6NrPcBEIuzHD87+B5jQdx+iXybAFYGg9FrUHAFa+zYK9uJSMeADG
+O5KBmsg/lQIDAQABo1wwWjAYBgNVHREEETAPgQ1jaGlsZEBleGFtcGxlMB0GA1Ud
+DgQWBBRFWTx/koNtNCRdvRjeESdd136SFjAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud
+DwEB/wQEAwICBDANBgkqhkiG9w0BAQsFAAOCAQEAR53288aEhg6x3zMHv0Y8ZSqB
++xPTrKzouqmHdaFBvEowIkfK6V29A2LAoIBi5DfsnkbKMGCD4mOlX3ipGoi7x2CZ
+UspOfXQ93CdiG9laS4sr4f5ZUJR1sc083UT1PBwqtnajjVUPxYz9I8g2ZxxawmA/
+bybbft/l4xHDv7RUP56uzm/BoCyiUdEC9gvq+5NYS95+M7v2J/CsvV34d5xnb8cl
+49zOoboN1JoZErPZ2dGnxpHvExOcQhz6CVUIEPri5eqRae+zln3RRd8RJ4gPe1FG
+H2aDHUwX7NKxY5Xq2NT2vUmnhTmNzFT5HC9gjG8Zu+2dPw0tTZNxyuctSAhAgw==
-----END CERTIFICATE-----
diff --git a/test/rubygems/child_key.pem b/test/rubygems/child_key.pem
index c56d0699c8..61fdfb628e 100644
--- a/test/rubygems/child_key.pem
+++ b/test/rubygems/child_key.pem
@@ -1,27 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
-MIIEogIBAAKCAQEAyn+/tatHETIQv0TOloaaJ/+SMbkr3twgscXTdC3Em1IrBTJX
-9vGY/kueOUihXOoBxXJ2C2WbMhpuBVhHeA4TaYP5IKAz7jxsEKdgxDryp553gf0o
-Y/FfuqC6412mRQLvEPdenOfwS8/j5RyCLDv0POuVzivuc9bGYtMb2pfEE+7uFLK3
-MvOoHr35Qm6QQFpDT2vw2Q6gPZ5NLwdlw0h74Wr3K2C3w62AJxc98Ime9C2EK5nX
-jqpD6WosP/0Kc6qfr7bhdm6+lImFqTfnYXRbCMQMCBOZFmdZJOjgSeJB76/kofDq
-m3+lhQYVv5UGvcJXQNMYTcIRq9RQxHwvtIPwbwIDAQABAoIBAEJkNgerG0bRAlqj
-hZQml35LtbPlwTN1OqbudFCf/NjrzL0Mb3jAZ2fghQTFAlrDQkdpKri73HFF5xKL
-igsbmlO6+EAxJjWSy9998SUFKq+4LfiJduelqLw4nG2VM8Fmn9kRMY0CIm/IvjBM
-84TrNz2OA/SvxKNoJG0cSAKYRao+00s+xNIu8lr6CqvXqnFO6gzbxQvJ0J0TnKVf
-AezArZZI3VaPXmC8yo2U6v9r7/2txr12QnDPDk9YMwJ7OR+7qzujAPvtHy44t4en
-AsTetle9AXveIBC7zpl0pp27wN8tKIdh8n+jxPfES9ecn4FjfreWiwzzZSSCitqQ
-p7cQdTkCgYEA9U/y38KUjV05FO7AeeMJYmy/o3WxjcZF8lUtuCsGzogD0JbnNj7R
-BF9TwlNnkeSJsPYKMG17dnoZhgY3J96mWhQbEH9CyXNdgQladE9/qH9gCCW9BXyo
-z3urNc77F/44J+1OoegpWGS8Hdm7OGsESLF1wLet+5cRbVHtU2brqQMCgYEA01JK
-AnATj+vACcAtr1Gu9eGE/6EqAM+H/bfQzGtqkxEmY8QihW//XWH/vOZDVZZYLUoc
-9MkSUHNGwZ7ESAgoZWc1D5xxp3sT2+vV192TS+QBe3TT5AXhAGH9uL+qz7Gz4ihH
-ebt4p49u5SJVY+3vv+nck/YgEiBw4PrfwSdugSUCgYB86U/XpoH0FaMKSKRTrErM
-BmnytuxJL8vQIJVeMPKPWezvWtey5HuUCWJiEgwr2r5OEIqRrD3wzy2N9D5Dm/kC
-5zf8x4BfidHz8apQjWaIiwuAOo8saxSeSe+dP57V0coQcqLWiJv8+ZZccNEHYl7V
-ER/PmPgLoxnpm40IKeEXtwKBgCwUEAfuJMZyYD4obd8R5LK49ar0jPRaVX1gqBbb
-mQFQJHfO43x93gA2fseCKC1kDMR1nxCYGE/bm7irSznTKcns+y5kbXiHvZ6z1IkQ
-WLcNuhlsRv5bE5Gm3ut4X0KvSFw2FqKXrhUVYAY/YRxU9xtKxo2+WvYs+h6TdbSu
-auhZAoGAThhKJW0Rf+LX1zlVaq+GXrj2rkYVSBwChMHbmmp49q6crldfLi15KbI/
-LRoUwjnQLQVNT0j090/rlNVv+pcQLqZ/pDHXQOMwrYuhbbLsda/FqTo3Qb/XnwHX
-qRrjdgGk5OC3gJt8EaHHdq+ty/eF4xQ0fUPMvIj8fwowxGyextI=
+MIIEowIBAAKCAQEAh8sYiI0fWZt7c5zHPDqgL5uYdeAwFIp/tnqtR840GdX8ZE7T
++ItOYnqaRy08XyazPZh+R+rG9zUjbV/y+6dtvbTN6J/FD1GUae6g5hTU6YHUW39N
+2SRQ6dzE6awPOcKvvoHOxjCOqkB4S7nN4LIbsuIhc1X61hNDERf2lZBIh/dYjVAm
+d72U2oQxv402n8jGJwAxPtupo3yvMgqEwOqmJ2EKzD8t43K9IN2mpOfs+Rp+eaiC
+ZJWgF1e7wMqDYGCKujI17PSdH5HnWVsCUxHwGq2Q6NrPcBEIuzHD87+B5jQdx+iX
+ybAFYGg9FrUHAFa+zYK9uJSMeADGO5KBmsg/lQIDAQABAoIBAA9dClPKuakK9xLr
+wjvdeymfvkZZ3L66M7xa0VeOLCVfKTzVEVTtt+ra6bETXGD8kStvIRx0YtntvGof
+wK85sGgV+HTw/Jvg1DyO98vIQBWCL5tBgjaGzhPDe1Dfu2JC1VzltVYFgOKgxCt3
+JGSfahRZUsUIjYZibARXVHnz9szRJFYg3lzBcVeCMWDGlPVydGaV3ttrhs4cFgPk
+1TinEH80K9GfpZvkH5/4O1E2uVFetSLONRQiTs+WXpx9flEXP+mNwdrjECI6xvIP
+x7pMfIo9kI9XniXXTvbGdEIeVrOL5OpW/nBCA3+EsL9S72TBVaMuiPTqUPlxA8up
+v/oS2qkCgYEAu7Kj1t2M+NJtR50wQ2g3efY1qO3dQ41SCnoGEWJd/17riNV3u7Xw
+FwPpnpcQAceoctK095JTtRTFGRN6FPl0VWuEsCS9lnwLzS7mQXiBg5EO7474v2Ki
+JPgncJefmCbtjJwaB78l+ybk9iUkdRv80QCHqdeHA5CegbsnDGkcJSkCgYEAuTUx
+Tfd3zpIEz0qhUf1D4PpgtoTj1zbXIUEFWl1SkLqklTF7k4LXZoWj7i3LraFk+jC2
+769qkLzF0CTHRFr5d00v9tCDOT5Sv2lqJw5UAmouKSuLF7XBp5tAkICkFX7Lo61v
+4iS2HtpK9wzri+L2XnDD3bxcHFHsEaxuD0V6iI0CgYEAp6Nsa4pizxT53z1IDtw0
+uCwrTt5rgVrlzE+hvcMSWvPG/+ZQUwmzDotDC462EDDnhO4mDPvW4WNUign4PmVx
+/pzR3JRj89SEodRieFUNr5lOMq2KAz0vvj8Y0pnJQ5Z5Ed2V7hdN79uUITeZMTM3
+AOAtSochohB3UTz7Kj1ykskCgYBPXZAHTSi2CLSu79g5fkJ8Qk73Z/MK4qFFyss0
+chFTm+ezV0URbVxIvrQE+PLzMNpIrF94Tr9nzr0l+Ny7WhDVIuqO5cOV4DMte0rV
++bneXwnw8ovkWSrnXAxK4BVwcKlrNoNfcUPp7Ll7LLozc8sHpWMJvhHqwOBcont3
+Z9qecQKBgAiiWHPgMKChKDg/JVQGEqILF67c7ZuzBMtUHmGNVn8NNr++NXZ4YIRB
+/TgYNXySTgEuD7tUE6B/iO9Mp1CpJbzRtdk8oqJlgJ4rza50N07k/SGIIWl7hAr8
+No1ibENOfw7aeMKRz3udLT50TFoluykWc/m1nJEaqtSEJLkBRM5c
-----END RSA PRIVATE KEY-----
diff --git a/test/rubygems/data/excon-0.7.7.gemspec.rz b/test/rubygems/data/excon-0.7.7.gemspec.rz
new file mode 100644
index 0000000000..159bd4bb1c
--- /dev/null
+++ b/test/rubygems/data/excon-0.7.7.gemspec.rz
Binary files differ
diff --git a/test/rubygems/data/null-type.gemspec.rz b/test/rubygems/data/null-type.gemspec.rz
deleted file mode 100644
index 2134fcde29..0000000000
--- a/test/rubygems/data/null-type.gemspec.rz
+++ /dev/null
Binary files differ
diff --git a/test/rubygems/data/pry-0.4.7.gemspec.rz b/test/rubygems/data/pry-0.4.7.gemspec.rz
new file mode 100644
index 0000000000..58fc1ed8a0
--- /dev/null
+++ b/test/rubygems/data/pry-0.4.7.gemspec.rz
Binary files differ
diff --git a/test/rubygems/encrypted_private_key.pem b/test/rubygems/encrypted_private_key.pem
index 868f332b7c..2d0022a6c0 100644
--- a/test/rubygems/encrypted_private_key.pem
+++ b/test/rubygems/encrypted_private_key.pem
@@ -1,30 +1,30 @@
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
-DEK-Info: DES-CBC,4E38D58B5A059DB6
+DEK-Info: AES-256-CBC,4851D8D265711252BA5EAD983C957412
-IgWLfnHVnkErKkhysrUMoE0ubkRDtJXZv9KR02jGGFk/kGqWyTqPk08uzhwVNM+l
-eOk0qfPykkJM3KZgqTsD6xfA1D5WqFp5mLoFXVVTn9I3acSZsqOY0FweCipwdVpI
-x+9Fl+v62kIW06dOjyWLE1abed9hHiXesGGsD87/RJSywy4OBxOcrhR1fJLK4ElR
-ya0UzI7rWnmZMChjaZBssfzT1DR79/dARXhon2m5EiIJDjMpc8BKGYlQy5RHCHwA
-cnrhUTTvsggZbQtmLZ/yVx8FSJ273XpYR0pmwbw4j1R+zeXQRK5MroBnCfOGcYa7
-rmpERmDW3VAuxXR20SUAGdo1XOMTDe1uLbaotn6e56pXghIaYROTPS+HsuOkAZGY
-OYWEkUoyog4l4n+h/C1umFfTFGvKNATLgDugONFvTw/PLbjvl+sWMy2QfqH0MlNB
-DIUPxhEVCFD9oB4nfB86WDAmPp1DH9/IBet/21kbQ2eTIzakTdG3XiC+xzAQRu68
-EOCTbasFWGxlCix66gt4xWMLksEg8UhWSpjS3/HsifrKyNMB8sfUFYmZmOYMW4mf
-NuEtpBL3AdHNObN8nQ75HfehukzNpbYVRsLzWrVgtxvXHVpnvoCCpCvQBMHeRZxK
-6m028mhH1m6yYE/uGFiRKLrN7BKAttbUiqnGgVIg/lQQilFWwylxQ6aXqJGmNgxa
-oihzWZRlXivIhhrM7VMnLoKAF/YfmWpP3zahGpBQGfObtPtm44R0ezXPdtsivnyu
-CmFOPGzRNMKZtH/lwVhuIIK3AFIGDsRRP9ySN4YfjQZnTdu2sRlxBnANP9m8W9T2
-p+C4zVkDYAbsuWq2HpHwsdL8gqIiXeptsHLqkNw+ulSSLyeBCgM9fpV3RsNGjwqu
-k8QLb1CYp2VX46CE8UKvOd/nyFnEsD+EAc3WangEwA41m2IaXcbs9Au7xsG9oacZ
-DrxlJVNxlxO9YyP9dNOTfP0fHIiygKQQY2aU3y3oRneu7ogYES5V2mUNH7cYUWVL
-CHPXAoUXJErvDQ/opW2DroA9Eqv9sST6WqBf6LXRcWU0ntfzcFUbEqgmCmB7Cbu2
-8udEn6iWilQahLyDoAShLkU7+Tk78Z1c6RuqjyY4VboZPzxrTYK8YIXzwX+jj9bG
-KIIGS5eghK185+AjlwtzJ7MBdoL323YIik6uOZluhnJHLaxjxUXGa1VqDgsyqGi7
-ISRMTpVTrbR+UtoEi4ZhMjobtFUr7lGkt24VkXwBKdoyryj4RPHGdp7Tf6XDJufQ
-+KKhqt8QrpOTPiMskFN2disOSF5/YZCmtT84nkhU7Hf1lkQ2kfx1zfNk0GqYYXOW
-zHOAczy8gWBRetDMnhRYohDzQGWn//b+2Wr2n1RD8D9kyjMRhpFMYfQGfRcuPGjW
-91k/T0XFcjcjeZPL9s+HITmrh7zg5WxbCfTEp91j3Oy1bns196SY77TE0BzUsqR2
-geJggcUMEfyvHiiCMtijmSSD9nf8tNIxLVL8Jaf1coA6e1CrlHnYAu2f/Q3GIcvU
-EEEmw+cZRwsk4fffYzh5psxxGdXKBv1KcQ/CeBhZL0WJsCp2y5oxwg==
+0CH43Il/Lamd5AIkeYFRdCLJUUiUAEuAlE+DDYJ+Schulv9Lp+Au00VvAH/VVdqP
+jFzEJ7FIwcPac2y4SVSa8uMGdzezVhduMz3yrwWNSUPFAJCLazh4FhGMmK2kYRfx
+IReEBebwr1x+e3VqoREfTuwxQqpA5Ho7dgnrzSf2UeIQrnXfDh1rIn3SCqb/xYDI
+qqQ9bPlDs9iY/W24KM/ZfWOB/Dr6SQXXVDu1JS8EAxB9TK4PRMHZIBlIN+OVzju5
+v7FDysTu7g2BTH9BeHs4lWFpsUdJmrj0GjGoM9DCH/6xdPHQSWKpDptFu+06htBB
+zyr2chX5RMjlPxApqtz59YJaHLNhI/nABIAJdEvAgG3CAiYHB4G+X5kQwIYryJIt
+IeD8oerxNtNOVzunGL/QvYyiLB9EcDEBfPUIlriPCpTFz7r/GCLO2wX3y0u6m631
+rh/tVRPMzWTSd4HjJiBQZU/d2bVvdOKKY12b1ieai/QiaO7HjgrcVAgWLwJB8XKr
+QkXIo6W4uZv+W0YVTVQ5lPfwdNY6eQ1ZWPnqIOoczAZtFbs3zdBobgoIjyQ6cEgq
+fgRsIjJmLVYq39F2oDX7bLdUK5UaPgHWGbNi07cOIn0hqo6YNCw1YaQikUw4qfBb
+golYKoSV73/M6IVWlTjuzP6CRDRHY80epQjA3FR9P7ToT2VgcsG+pKxoYjZxotGm
+/E4PEEl+9lxNN9IXR4XuEzWSGTOiNUZ+iVOJIyNQN5tC8k6yYr08s12b9LVzvG+q
+Ro/bD/3UNaDwfujoSNgwKelZPBZmSkJIUECNDXE2i4hr6WqoJu7ZhpO5f/iU5d+i
+Ea0bbSne50zlYoIMIa7YG01zgI5Y+sV8BWSwwK+FaH5dORjpRUVat/yIw/Qx8VZ+
+f9RIfMnOShf5zvXIX8pF+Cayf8nPk4X8rhwrd+gL2cthHlYa58DkfKpJ4FxxRItJ
+mQ01K29PuQPYBdTXN0A8jurxQgETdM2R0JrLCnDOEleshUJqdsqC69Le5Sn5ucui
+ZWqxHjm+ycF4OAO99oq1T9QDyUCtIkMXPpf982KYVyzEbNw9hEr5/0CZdCaMEL4M
+gecBM9rpYeWy0ndmZ/Y9rBdTT6+en2WnONKQj3nCgL8e59y9S1VG+sgQ2LwQ2nxJ
+Mj2CeFi4B4D+2JdqyDKRFXfGKmzLIWW5Xw7/rrnMc7NtWZjRmUkvAOk3ILC81AmY
+QPCEuqju5q9hasKfIDBnB7/eNscAvf23Aa/P3A0NBTPcTko+M+Pkpc82m4eXx1Aw
+MfpfaIcfgPI4LEo+d8IfT0zcPNDuH9ACCcYa8/4q+PnKCmOsxgZ9wGpRHOQ2QfLR
+qTus6c0l9zab8EWJZBnQvuacUecU64OAryP3QAWZl/NerHsKZ/i9ZIDXtDIscCHl
+Yylu68l+vBZmfD455QN3iPVqSm4valJTGZnk40STtf8qLAuXdVhbyI921yGIz63n
+dcRx9+wd9M3VQqmvbrri8FuavTn9/uMMpKeOeR3AIhci8EJdLxhvz2A3+w9cxIO+
+Imj0syk5TWH0c3menzkYe2cO4P8jqBsb+QRdNcA2+YSTpEsvS7Tqvogl/RWnv7r4
-----END RSA PRIVATE KEY-----
diff --git a/test/rubygems/expired_cert.pem b/test/rubygems/expired_cert.pem
index c76fe4c58f..12b8836607 100644
--- a/test/rubygems/expired_cert.pem
+++ b/test/rubygems/expired_cert.pem
@@ -1,19 +1,19 @@
-----BEGIN CERTIFICATE-----
-MIIDCzCCAfOgAwIBAgIBBjANBgkqhkiG9w0BAQUFADAqMQ8wDQYDVQQDDAZub2Jv
+MIIDCzCCAfOgAwIBAgIBBjANBgkqhkiG9w0BAQsFADAqMQ8wDQYDVQQDDAZub2Jv
ZHkxFzAVBgoJkiaJk/IsZAEZFgdleGFtcGxlMB4XDTcwMDEwMTAwMDAwMFoXDTcw
MDEwMTAwMDAwMFowKjEPMA0GA1UEAwwGbm9ib2R5MRcwFQYKCZImiZPyLGQBGRYH
-ZXhhbXBsZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKdlNYcvFB6x
-gpT8QcnMybVelGLUKyQL/hQPTK9J5FyqB8hEDLt2ruMwKsHU6fu/mgG+sLvHF1nq
-WhZADhn6rwCfNP03025vktOZ6iJfU60vytY/f3gkiGNkP21l0hz0+Ms15f+52gk+
-sFXqwGBbDteI0x57UsHi+KAN67QuPDnthYDtwhXIA5pcdx2wH+NW8F82HEZvm1hc
-pA75BDVk4vPxnpDfvPOKSYn9dWghmUtaPmqyVvs8XkDxHDfY54/D3ziPehP+zQzE
-g8C07Sq/z6vLSOQ3uaYn0nBDuNE6XP3ijJ4Zvs2eJEdOMyS1H3CsnkWiePCrLtKd
-w8d/F+D5bocCAwEAAaM8MDowGQYDVR0RBBIwEIEObm9ib2R5QGV4YW1wbGUwHQYD
-VR0OBBYEFF9DbvaajkUl6SLjfTdepNU2AoUbMA0GCSqGSIb3DQEBBQUAA4IBAQAP
-Z8vKQ1OjQCHx8MJ0gy6WN2CIjh0Uqf3fSfza3nd+K8jlJPkF7znEBZ345iCSmNwn
-EPrz/OrqiId2OHW2OCJv3c9NEb7hgaTswGfdq9LmqMRVeQy57FWh2lRdjVZbquWy
-IvM72hjVLqnMVisWbDxf32YghnmT37SzZKsHSXU0xUx7rVSIShnoMjLWQtIQDoqI
-3isMAeKals2NNJOy0TGKJ9SspIDl/IYm9sEO1HKiuxubrdN9q+wEQdizt59sXkol
-4AYga+5TN+KtsSRclAGjfKYfuRrQ85IbVsRhQIYX1ZOJtMseEhBRnIeySKV4xWsi
-kXAaxX5wIyoM+S1vaKcu
+ZXhhbXBsZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANFC3H6Q26GO
+bllXTiJBeALUbouzzxaGinwZeYYhhXKWEcfA0D8k+22w/JyndeEYc29JxwjFNwxM
+/DyyQplptzbM1Q5BCcLNQaQhmpOryosjWuYWW1JUDGTG3nEg0qRCrtjwVoAU++Ko
+NkQboM0wFQJxkBns0J1sr+O5Ml73YzKKtdVWWvg89osxyb4wRxkEoa9a/b9/aiK7
+WoeQhF00cRKoa/eoIN8usTjzKsYudHUtEQWibD7IxWdY3nMntGf1jyLYi40lVUbL
+FFytWtlZGMVKpMVIOMMCQ+ex+ExGQaJrQF5QEqPq1L/BvXgTZkv5P6CS3YjBdVC2
+/ntfos3gMhsCAwEAAaM8MDowGQYDVR0RBBIwEIEObm9ib2R5QGV4YW1wbGUwHQYD
+VR0OBBYEFLEaVAlnRWACAtfO9B1gSonf51jZMA0GCSqGSIb3DQEBCwUAA4IBAQDI
+x70p19RI73Y9AEfBd0Wmk7KsZQyP55kjTAdaM37crhmClkUQRrk/Y2a0pXOhsrNI
+0YO7t44fJKwMu++1dxh/bllKbuOkca6ApxTb2IfhOejx3IXXWzp+C1F9pmG9q5QW
+0FDt//0SFZJIqDq9N+zFiA2z0MM1L7X/r29uUgAqkU7rsytKavHXru9EGQrrkxwh
+5dM5VI+pnJgk9HYpBDPwiFVd0yFelebqdlv/nnW11tVBMTkMloVYyhei5yZbWKFk
+f0Aj5g94+S107oRMyzq5e6lxQcJBhmKfOXqGaz2wue3/IHnwio9dMArayug9GLEr
+ycy6PubJImhM/dboDIdO
-----END CERTIFICATE-----
diff --git a/test/rubygems/fake_certlib/openssl.rb b/test/rubygems/fake_certlib/openssl.rb
index c7f85140a1..928672c7e5 100644
--- a/test/rubygems/fake_certlib/openssl.rb
+++ b/test/rubygems/fake_certlib/openssl.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
diff --git a/test/rubygems/future_cert.pem b/test/rubygems/future_cert.pem
index 05d3f9ebe3..06e08bb4c6 100644
--- a/test/rubygems/future_cert.pem
+++ b/test/rubygems/future_cert.pem
@@ -1,19 +1,19 @@
-----BEGIN CERTIFICATE-----
-MIIDDzCCAfegAwIBAgIBCDANBgkqhkiG9w0BAQUFADAqMQ8wDQYDVQQDDAZub2Jv
+MIIDDzCCAfegAwIBAgIBCDANBgkqhkiG9w0BAQsFADAqMQ8wDQYDVQQDDAZub2Jv
ZHkxFzAVBgoJkiaJk/IsZAEZFgdleGFtcGxlMCIYDzk5OTkxMjMxMjM1OTU5WhgP
OTk5OTEyMzEyMzU5NTlaMCoxDzANBgNVBAMMBm5vYm9keTEXMBUGCgmSJomT8ixk
-ARkWB2V4YW1wbGUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCnZTWH
-LxQesYKU/EHJzMm1XpRi1CskC/4UD0yvSeRcqgfIRAy7dq7jMCrB1On7v5oBvrC7
-xxdZ6loWQA4Z+q8AnzT9N9Nub5LTmeoiX1OtL8rWP394JIhjZD9tZdIc9PjLNeX/
-udoJPrBV6sBgWw7XiNMee1LB4vigDeu0Ljw57YWA7cIVyAOaXHcdsB/jVvBfNhxG
-b5tYXKQO+QQ1ZOLz8Z6Q37zzikmJ/XVoIZlLWj5qslb7PF5A8Rw32OePw984j3oT
-/s0MxIPAtO0qv8+ry0jkN7mmJ9JwQ7jROlz94oyeGb7NniRHTjMktR9wrJ5Fonjw
-qy7SncPHfxfg+W6HAgMBAAGjPDA6MBkGA1UdEQQSMBCBDm5vYm9keUBleGFtcGxl
-MB0GA1UdDgQWBBRfQ272mo5FJeki4303XqTVNgKFGzANBgkqhkiG9w0BAQUFAAOC
-AQEAM/0YoOjHEs1zdE6oG10XKdDcYn192AYhkMaITrfJUJiVUYehmcC+fa7aV5Hp
-CYasFm5SawiyHwcI92GROaM97gJy7Tjpg8zcpkXg/vUA/8ItzD0UYphs5efZ9B3R
-zOfxQDasTZJgg0uCxw23Bil7Anf5/KipuiU92Cc3fjpI6jWOuezGWqSqC2KGJLM+
-S59/oLqQNR67j7WBH3lHe3qbUehpNPkSrTdcLEbvspZM2udrRN9QYUUwBxD9dMlB
-eC4hADgWEh5uPZO5sM2+qUdyIRa+fDUpcbTEhLQy6NceHuCNLK230DdC2xszrtNY
-yNFy3B5BHgxfZeycaC4pMED0gA==
+ARkWB2V4YW1wbGUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDRQtx+
+kNuhjm5ZV04iQXgC1G6Ls88Whop8GXmGIYVylhHHwNA/JPttsPycp3XhGHNvSccI
+xTcMTPw8skKZabc2zNUOQQnCzUGkIZqTq8qLI1rmFltSVAxkxt5xINKkQq7Y8FaA
+FPviqDZEG6DNMBUCcZAZ7NCdbK/juTJe92MyirXVVlr4PPaLMcm+MEcZBKGvWv2/
+f2oiu1qHkIRdNHESqGv3qCDfLrE48yrGLnR1LREFomw+yMVnWN5zJ7Rn9Y8i2IuN
+JVVGyxRcrVrZWRjFSqTFSDjDAkPnsfhMRkGia0BeUBKj6tS/wb14E2ZL+T+gkt2I
+wXVQtv57X6LN4DIbAgMBAAGjPDA6MBkGA1UdEQQSMBCBDm5vYm9keUBleGFtcGxl
+MB0GA1UdDgQWBBSxGlQJZ0VgAgLXzvQdYEqJ3+dY2TANBgkqhkiG9w0BAQsFAAOC
+AQEAATJNbSaVk8fM1uhqQnlBiQ/0TzchHADy+WmsbIbOiUAc8c29sjpCC4x0o5Gk
+Zn18+BsXUjfyF6zyY4wPABZp9SCDIxvLxP2QVmbCtY2TJeKV95c4mWEnrFcCqYZ/
+je13m5iLnAu1WqVjSbFn1KamTf25pfBd9mqgQVwrdJMGoviJC18LyKJTZs7aV+Bu
+tsF9fVMIP8p1Xu0Es/hBXFRwths41seqT0dYFszhwTCBC9tt85TTixWmEXpdyrov
+vLFULJg4ijn9YZeKMViC6V3zgHUl9ZnMlWdFpVZ6cf7kA/1acW1ESEZnARLQhvMF
+a1gof1D2Mj5k3AtQJ2TtPXytxw==
-----END CERTIFICATE-----
diff --git a/test/rubygems/future_cert_32.pem b/test/rubygems/future_cert_32.pem
index aa74bdffbc..c023110141 100644
--- a/test/rubygems/future_cert_32.pem
+++ b/test/rubygems/future_cert_32.pem
@@ -1,19 +1,19 @@
-----BEGIN CERTIFICATE-----
-MIIDCzCCAfOgAwIBAgIBCTANBgkqhkiG9w0BAQUFADAqMQ8wDQYDVQQDDAZub2Jv
+MIIDCzCCAfOgAwIBAgIBCTANBgkqhkiG9w0BAQsFADAqMQ8wDQYDVQQDDAZub2Jv
ZHkxFzAVBgoJkiaJk/IsZAEZFgdleGFtcGxlMB4XDTM4MDExOTAzMTQwN1oXDTM4
MDExOTAzMTQwN1owKjEPMA0GA1UEAwwGbm9ib2R5MRcwFQYKCZImiZPyLGQBGRYH
-ZXhhbXBsZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKdlNYcvFB6x
-gpT8QcnMybVelGLUKyQL/hQPTK9J5FyqB8hEDLt2ruMwKsHU6fu/mgG+sLvHF1nq
-WhZADhn6rwCfNP03025vktOZ6iJfU60vytY/f3gkiGNkP21l0hz0+Ms15f+52gk+
-sFXqwGBbDteI0x57UsHi+KAN67QuPDnthYDtwhXIA5pcdx2wH+NW8F82HEZvm1hc
-pA75BDVk4vPxnpDfvPOKSYn9dWghmUtaPmqyVvs8XkDxHDfY54/D3ziPehP+zQzE
-g8C07Sq/z6vLSOQ3uaYn0nBDuNE6XP3ijJ4Zvs2eJEdOMyS1H3CsnkWiePCrLtKd
-w8d/F+D5bocCAwEAAaM8MDowGQYDVR0RBBIwEIEObm9ib2R5QGV4YW1wbGUwHQYD
-VR0OBBYEFF9DbvaajkUl6SLjfTdepNU2AoUbMA0GCSqGSIb3DQEBBQUAA4IBAQA6
-lip2nqmXyhz1uBDAxlNAv9nN2JPicWpRIvQ4KLNwmZKnagPWfleZ4TbLqsn723w8
-lD2VqFNX/Vj1XNuEJg8pXME+qxbMgtWxGsXC0z6k2Q3rT81QTdhXJ7nqdoe2i8y1
-423Fft2L6Dcgmx2USJwZsNy53pK9smxI9NipuRtL4W34PHHpaFsC2646daxZ2F8M
-No3R9C4CtSFJDrM0XZoFiAnarbqoGCJs2q0NtcdV8D5m6xGeNShWJMLNbVx4DgsT
-E90gVxVqPaqm5ytAIfdPWVUsyJBoD15jDVH5AZtkBmFRNoz60KPt3HpiRPspKWCd
-tVabH2JRC0wDYRwEEMKB
+ZXhhbXBsZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANFC3H6Q26GO
+bllXTiJBeALUbouzzxaGinwZeYYhhXKWEcfA0D8k+22w/JyndeEYc29JxwjFNwxM
+/DyyQplptzbM1Q5BCcLNQaQhmpOryosjWuYWW1JUDGTG3nEg0qRCrtjwVoAU++Ko
+NkQboM0wFQJxkBns0J1sr+O5Ml73YzKKtdVWWvg89osxyb4wRxkEoa9a/b9/aiK7
+WoeQhF00cRKoa/eoIN8usTjzKsYudHUtEQWibD7IxWdY3nMntGf1jyLYi40lVUbL
+FFytWtlZGMVKpMVIOMMCQ+ex+ExGQaJrQF5QEqPq1L/BvXgTZkv5P6CS3YjBdVC2
+/ntfos3gMhsCAwEAAaM8MDowGQYDVR0RBBIwEIEObm9ib2R5QGV4YW1wbGUwHQYD
+VR0OBBYEFLEaVAlnRWACAtfO9B1gSonf51jZMA0GCSqGSIb3DQEBCwUAA4IBAQB2
+EjAxPVbDwoYehhEJEiMnMWk8GL6oo1uVwGJgCM76Yml69FVyWrre2GcSYiv+9f7K
+AzE9S2uREeJuGcSV0VR0MeXoHXwQpQyBV12gCL1eQH15oxFfTi9XbVLhh5CyTKc1
+J6lYtQVpZPlLRoJN3oBq3J8PN8hWBWuhb2VIrpHXNBXAMOZ+hJM2B+EYifH6tcI5
+YK/Bw5Tes81QU4stQTLKybJzQkct02Rm7bYIM3GX/FGMMEPZE4jhnQ5btSNYVBlY
+HXh6qfZVhZ8qpAy50yrlxROLa5zJSuTQ28QWh95XLzzHiHJ4Q4qZQzhcRGUQLfM3
+X6P8rtGWzXtB++CKKQIG
-----END CERTIFICATE-----
diff --git a/test/rubygems/good_rake.rb b/test/rubygems/good_rake.rb
index 4a05ae4a13..bb0ed9fa80 100644
--- a/test/rubygems/good_rake.rb
+++ b/test/rubygems/good_rake.rb
@@ -1,2 +1,3 @@
# frozen_string_literal: true
+
exit 0
diff --git a/test/rubygems/grandchild_cert.pem b/test/rubygems/grandchild_cert.pem
index dbd14bce80..c1d9887b60 100644
--- a/test/rubygems/grandchild_cert.pem
+++ b/test/rubygems/grandchild_cert.pem
@@ -1,20 +1,19 @@
-----BEGIN CERTIFICATE-----
-MIIDNTCCAh2gAwIBAgIBDDANBgkqhkiG9w0BAQUFADApMQ4wDAYDVQQDDAVjaGls
+MIIDFDCCAfygAwIBAgIBDDANBgkqhkiG9w0BAQsFADApMQ4wDAYDVQQDDAVjaGls
ZDEXMBUGCgmSJomT8ixkARkWB2V4YW1wbGUwIBcNMTIwMTAxMDAwMDAwWhgPOTk5
OTEyMzEyMzU5NTlaMC4xEzARBgNVBAMMCmdyYW5kY2hpbGQxFzAVBgoJkiaJk/Is
-ZAEZFgdleGFtcGxlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkfgy
-EbzcRpXvpNA0s75R8gOVk7ENEPX5uXUElbzHbVEmHkC/NFsWZXV0vxGFfZrrnEkT
-Y2kDaMMkfZX9rriRIvsZpxyqrdX87QfQTZ1ktDoytVnd+gw9A6AXB6PR7uoPymso
-f/lZYJ8BWP9fIU39nogiptFqsgkpOtKSFjJfMILkcMAeBPs2B5HV5l4oLrpJ7Ns/
-0vazCXGakTByAXNKBagJWR43gh+RUQWF6Uh04VQTQ7ENGWI83088SKAPtCCcgKxr
-ROHI025S7o7vEfDEqEn+gtu+4ndaLuRp+2AmF3YK8dEDiLXrrvEvG1r4+gIB/6tS
-MUfkkJtBleZrDoIAgQIDAQABo2EwXzAdBgNVHREEFjAUgRJncmFuZGNoaWxkQGV4
-YW1wbGUwHQYDVR0OBBYEFAnex9R5fpiHNpHxq91rMog/PZA6MB8GA1UdIwQYMBaA
-FHzVU9N7sklKBPrHElxoZ32Fg64IMA0GCSqGSIb3DQEBBQUAA4IBAQCYT10tUm9O
-2xSGVmsbYv5YVrMr1Ucuq6Y+mXuTqqXuidILXZZl3LDwaYj64AhmMUqfITybGbR3
-sbWZrz2TWI2qWo+wcYDq+k0K+ys2PBavXdbjw4nVMf/9xYb2bCHK4bxxIG6rkmCw
-zxYRTx+UivRf7Hw+6ZRtkHDxX/qPfMQK1PbmvK9c2VYXGN3+fRRIJqPnknN26Hv1
-gangMI7oqcaNwCvL16E/CpN8uwdJNB1LcCgjFJP7Ora+LIEJVe4eZvmuOYkYaYH2
-7u6CglItKwNjVZ5jULUfBuJqFkRiOxkVMVjChe9QvNXz/fkhW2sH05CR+TDyh4rD
-ZeON5sdo9TV8
+ZAEZFgdleGFtcGxlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyh7u
+lK+O7leQKBQzSSvhEur49Xu4sQJllkVbrVvkv2jSo68woESgljSS8jCSX0I9IJ5T
+0kHzNRpiuOpfWKZx7E4cKeqW6nmV7D/B+Iy1QnJbMzUdnxp1Y+CMCK0JrLIsFBnx
+ndVmiS/S817W3coqkmZqce4e33/O0qmCChGxGJZuAVQFGYI25SiYWPbysVEjwXoW
+6zO0D1m8QZLYYCeDSRpxKgItBoJK+Up+bm/nsrkFvUf4kAZNLgik5zvflM3/Mjyx
+zxgY2MO07YaULOlr0vZN6Wxnq2F3jkuZY8JbEOpQSDGSgU2wJ1iFH+GLvj7LsBuR
+ScjL0FJ4s1EjqjjP8QIDAQABo0AwPjAdBgNVHREEFjAUgRJncmFuZGNoaWxkQGV4
+YW1wbGUwHQYDVR0OBBYEFEuKocg9sisZIWu12gxzse+7/sHfMA0GCSqGSIb3DQEB
+CwUAA4IBAQAFaz3FUNzDYt/Cb++6U1PXsucAy3pKDj8bUW7slJFleNsSooIA9A5b
+axpnHst1Lt6i/bmvbi8F8q/0iq4PtsZvusmwVhJkCinEUZ9inddSJdxpWSyzOww5
+at8ragidzREd9Fx62flRr3GflzqIufkKN8TDjYrB+n45ijnSxDcwZhu7m/tmP/e2
+FxqODaIO9sVrPAU7YbXb0m3p3Em7RK22d0tqy1dHhcRIR5/yMQB4MSEvQ7ytRD2x
+aHAP7A4rDbkRwG+LQ/4L57RJ1kU3InqpOEQnCgpwu3xw/6Alti9TXS7sGhXL4Aav
+OLsFS/1BLSJx/DSSK58Vg6JFxFh6X2NK
-----END CERTIFICATE-----
diff --git a/test/rubygems/grandchild_cert_32.pem b/test/rubygems/grandchild_cert_32.pem
index 5077a43452..5d1ad45cb7 100644
--- a/test/rubygems/grandchild_cert_32.pem
+++ b/test/rubygems/grandchild_cert_32.pem
@@ -1,20 +1,19 @@
-----BEGIN CERTIFICATE-----
-MIIDMzCCAhugAwIBAgIBDTANBgkqhkiG9w0BAQUFADApMQ4wDAYDVQQDDAVjaGls
+MIIDEjCCAfqgAwIBAgIBDTANBgkqhkiG9w0BAQsFADApMQ4wDAYDVQQDDAVjaGls
ZDEXMBUGCgmSJomT8ixkARkWB2V4YW1wbGUwHhcNMTIwMTAxMDAwMDAwWhcNMzgw
MTE5MDMxNDA3WjAuMRMwEQYDVQQDDApncmFuZGNoaWxkMRcwFQYKCZImiZPyLGQB
-GRYHZXhhbXBsZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJH4MhG8
-3EaV76TQNLO+UfIDlZOxDRD1+bl1BJW8x21RJh5AvzRbFmV1dL8RhX2a65xJE2Np
-A2jDJH2V/a64kSL7Gaccqq3V/O0H0E2dZLQ6MrVZ3foMPQOgFwej0e7qD8prKH/5
-WWCfAVj/XyFN/Z6IIqbRarIJKTrSkhYyXzCC5HDAHgT7NgeR1eZeKC66SezbP9L2
-swlxmpEwcgFzSgWoCVkeN4IfkVEFhelIdOFUE0OxDRliPN9PPEigD7QgnICsa0Th
-yNNuUu6O7xHwxKhJ/oLbvuJ3Wi7kaftgJhd2CvHRA4i1667xLxta+PoCAf+rUjFH
-5JCbQZXmaw6CAIECAwEAAaNhMF8wHQYDVR0RBBYwFIESZ3JhbmRjaGlsZEBleGFt
-cGxlMB0GA1UdDgQWBBQJ3sfUeX6YhzaR8avdazKIPz2QOjAfBgNVHSMEGDAWgBR8
-1VPTe7JJSgT6xxJcaGd9hYOuCDANBgkqhkiG9w0BAQUFAAOCAQEAnIlgmwVS3BGk
-cT9LxE3bbQt1WGeLLxAF5ScqkNgFm3OvIxrKPX94WRa6tjWPEeJ9rl64QMKwJ8h1
-GzNbf0DUH8nMcSJLL1J5HUqdzwysQ96HNz54RuZ3ZF8w7QD4Kv3Vvh4IIsANchSj
-unVYjcDVH9lSsbqTwC+bnUxYZ1Xu530fKZ440BG1ju9vLLZu5JaSOoJWRuHNOlQF
-FbYj5AIjPwMNUidzoE9sUWdRzvARwecismWkPjfM0x1AmxVMs8hA5tS2QoCEvOxt
-Hl3q6k7BaC8BRENkA/XRRIqgTMoTv86OOZIMFVaTiuHyU1XUxNHKv+ybAeAlP+H7
-hM/Hqka4bQ==
+GRYHZXhhbXBsZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMoe7pSv
+ju5XkCgUM0kr4RLq+PV7uLECZZZFW61b5L9o0qOvMKBEoJY0kvIwkl9CPSCeU9JB
+8zUaYrjqX1imcexOHCnqlup5lew/wfiMtUJyWzM1HZ8adWPgjAitCayyLBQZ8Z3V
+Zokv0vNe1t3KKpJmanHuHt9/ztKpggoRsRiWbgFUBRmCNuUomFj28rFRI8F6Fusz
+tA9ZvEGS2GAng0kacSoCLQaCSvlKfm5v57K5Bb1H+JAGTS4IpOc735TN/zI8sc8Y
+GNjDtO2GlCzpa9L2TelsZ6thd45LmWPCWxDqUEgxkoFNsCdYhR/hi74+y7AbkUnI
+y9BSeLNRI6o4z/ECAwEAAaNAMD4wHQYDVR0RBBYwFIESZ3JhbmRjaGlsZEBleGFt
+cGxlMB0GA1UdDgQWBBRLiqHIPbIrGSFrtdoMc7Hvu/7B3zANBgkqhkiG9w0BAQsF
+AAOCAQEAFW6StPxdeONHUmWXUAKXNncP66aaHPAk+rQ84IvuyJKqR3UrrKdCbQLQ
+LpL/lQZDkjGJSXdNHUhoB4MQsDJ8TQs2BdwDqOIvQLsZxTKZaXPfc1diFP+z/5f0
+9wbWezUateJwShDpp1RltCBmFCdibPZQUCpsgAsfqsgIWNpzhqy9dI/Upg3vECVc
+c4g+EsEtiNXSbjd0kWUXCGBAeTMu4paBLVtt81fuffKJfnAKRhzrfFy0PoL3Kt2T
+DkMr4MWfkMOyVlrSkvjPtW1oHVnxfZgqaE91J0Ht9qiHvekti3JDqxqcKaYuIgAL
+w9HK9z5uQA2KrMvqn/jiuD8lBFsnuA==
-----END CERTIFICATE-----
diff --git a/test/rubygems/grandchild_key.pem b/test/rubygems/grandchild_key.pem
index a9b9aef624..63635844b0 100644
--- a/test/rubygems/grandchild_key.pem
+++ b/test/rubygems/grandchild_key.pem
@@ -1,27 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
-MIIEpgIBAAKCAQEAkfgyEbzcRpXvpNA0s75R8gOVk7ENEPX5uXUElbzHbVEmHkC/
-NFsWZXV0vxGFfZrrnEkTY2kDaMMkfZX9rriRIvsZpxyqrdX87QfQTZ1ktDoytVnd
-+gw9A6AXB6PR7uoPymsof/lZYJ8BWP9fIU39nogiptFqsgkpOtKSFjJfMILkcMAe
-BPs2B5HV5l4oLrpJ7Ns/0vazCXGakTByAXNKBagJWR43gh+RUQWF6Uh04VQTQ7EN
-GWI83088SKAPtCCcgKxrROHI025S7o7vEfDEqEn+gtu+4ndaLuRp+2AmF3YK8dED
-iLXrrvEvG1r4+gIB/6tSMUfkkJtBleZrDoIAgQIDAQABAoIBAQCFbg4+vpfQghBM
-ZPI399oqUvJwziA2h9Kdn4TwZ18Y41vnvaHKdxUS63orihWvSmTjOL1bWsv+AJuj
-nO8GvroU8tlxM7glLX2FImZb/GrogGaH9bz+bB995+IFXs9xCE4k5y1fRgxYUSDH
-PLC13ffe6WxbdwSD9/HTTlaxqZvv1+UWxyYD0CSwopww5YdqISkVHq2UsmszK49X
-hn6zzK+DT4YA04Tbv2Go9kCYLmsgrL2/dPJulDtJhX3AckbdkodSlBAmxe7XsKEO
-TEzNDGgPZyZ+MXttBnLt1vk8ZrSJWcFG+E6DMbGUZ7rz6g98bUS1LI6PiqIp5BfS
-sr0cGQl9AoGBAMGj7SCp1GMo8wOJpzzSGJ4PCc/fpG9NcTBqtmoUTuvMk4frkGXJ
-dSS68KB0t0EGStbUFIZuylchC7RSzXs0uOZxkgaGcJT5qXXFP0Djy3/qoQMnJ2Yl
-uhD6UsetPXbozK6MPs3mh9VqSDNbf2AM034nTod3I9sV471HZLwAhQk7AoGBAMD6
-Mmvy8DEa62VDTW6P1f4b6Pi6dOiZhGbNz5Xlh5jHplSMYReQGBVmr9szrV7qytGP
-ZcBhEqTc53u2mEhSmRXQflRxJ7U2m8Xl3DClhxELHNGCJ9jEY52M4ZDJkvGj5v3t
-pbTbE/g3zxmAaYZCOKIzYv5bSSStNpauxdomxuFzAoGBAJFohH97qEZSELJ+YrwU
-VHIUfty/Zt5BvBaMe7CK0XzWIY72gHc+4Z2UV29WVeoZTIenuEX+2ii1YvGlIDI9
-s/8wF2SY/d+Q3wTV+prCtCS5TvFsLHTTLbbkEtdoqvgo9tK3881wKF5FMjSGp867
-svFPmPO2rpEtDdgrzWQzy7LTAoGBAK077Sea3qQ2VjqBQHGQDbofs/QU7f4gUgs3
-lrIpaqBsGZSssDxGzlfn5tYQfgJHI+sbn2wjuGjnJaaZM/s4qtQ6Zi3Hpq22aAAv
-aIsDDUzvfN9WyA5/vi0g2xzu10q0qBgrziWcxUB+WRu7ev9bUxvIpYVQzUhvdiGu
-o05CoSahAoGBAKoCGMGKkub+LnWazPkN2BAS6LblV+JIYWRI+DSGpz0UBk4Br546
-ozZq2GsLCQYWJabJ5RE9Are6rl9AvFQXMaWywOBe3TUz7SmLIxMjWpXKiX5YIFkS
-tOiEEmET4ZYS87flEmldnmeDFLHHbMLOw5S0dJa4PyFRn6j9su8d8mWw
+MIIEpAIBAAKCAQEAyh7ulK+O7leQKBQzSSvhEur49Xu4sQJllkVbrVvkv2jSo68w
+oESgljSS8jCSX0I9IJ5T0kHzNRpiuOpfWKZx7E4cKeqW6nmV7D/B+Iy1QnJbMzUd
+nxp1Y+CMCK0JrLIsFBnxndVmiS/S817W3coqkmZqce4e33/O0qmCChGxGJZuAVQF
+GYI25SiYWPbysVEjwXoW6zO0D1m8QZLYYCeDSRpxKgItBoJK+Up+bm/nsrkFvUf4
+kAZNLgik5zvflM3/MjyxzxgY2MO07YaULOlr0vZN6Wxnq2F3jkuZY8JbEOpQSDGS
+gU2wJ1iFH+GLvj7LsBuRScjL0FJ4s1EjqjjP8QIDAQABAoIBACI/cwQxKiojHqtX
+3ufNXlYfB//Kjr05j36SsonRqhUv3Q88umPRtRc2gda1Wbv35JUwFrpoD96F4cf8
++Jp0G5YjlxyYIinJX9i35fVoXDdN2ru2ypXgvRbnH7tBnMPNLfBbBAiPNhBVUOyJ
+e6V5odSMM4mqBEOxK5mg/MaZgFVOrNf/DEI5oFSny7duEEQAuGJadJHUJOh7al0b
+lByNVNAYNkdZMgvOdoAoyEzg5tvY9ykIwXUKdMwBgSlldolLYXyAjluXOVEj32m4
+p3rEV/vs+RQFTLLWXfyVyWoMIPYaK6nNaYpB8fMHnIjga8MzBgC6Hso3HqymRdg2
+Gttp4PUCgYEA2LQL72tzhUb+a0wo7dWJ4MY0ekyA7JxrqZRTWSNuqKMoAb6IxaXe
+quZcpht/430szpOOz52pEwEEKUsCMuqwHiqmO2ZiZqYJpDQet466GFnhYhmAqV/x
+bOaZLVbhGjiMQCD5YbpAmXjxF8SFbkqSKlSnpjxJKD2tGNX5FFWpN4UCgYEA7sXt
+Xsf0XaPbISe2gYdXMO3exHplayt7C/wqjcxMePwtSwAJD+/JrFvFSiPBKT6Ajl+M
+dcJIb9+WHhjk5GJI7KU4AVpf4feu5o1QnpnSAzCUlXpldYwSUS/7LZALvABm68Iy
+2gHU1Aj5DYB/4nesWVhExKrMZDAICVojS5jCJH0CgYEA10SsIo9cN4ZZ0J7cfb7F
+88sRcHg1DlcowFG/JmqDT/ScFnd/CNCITL8ARGZG+eZsL1333RiiT2WQC7EeoxPu
+FlmJvrIriAriwwKfjPq0tOH8eeYZoKfVfbfpbFfEz7Zi5IWdFk7eQ1cYMOMhJXng
+jzp/PCzhA5+ZJ3XPtDqQGb0CgYEA1AuwPuECUfqHSw1yldt0gj5s/D3aPW+SydT6
+kYziSPti2d1BLwb7Kfch4TKZgyA/mLCgE6AjJj8AmN/wviXOr2IWt5Tj29BTYeoT
+s5XVHQISoiDdY6OuTK14ukDXOvF8dVi0QkkoEdmaG/SHHb67r2ilQaaQ91R0fqGv
+AJ67ox0CgYBxkRfXPCnljxrJN7Fb1fS/DE1yVNWNkLiANOlUnPwzaD+jV0miCwEG
+mR1PoRBG0j4sYTp9RyVCwR1RASNPStDTF/VcSllDqI45IHToKqgfeIlApmnCu291
+km1gAveM0Ayg5mLsIfIHyOlPZRL0iuewDDkwFNtwOiR87o9BurhRow==
-----END RSA PRIVATE KEY-----
diff --git a/test/rubygems/helper.rb b/test/rubygems/helper.rb
index 812142f7d2..3514954103 100644
--- a/test/rubygems/helper.rb
+++ b/test/rubygems/helper.rb
@@ -1,56 +1,27 @@
# frozen_string_literal: true
-require 'rubygems'
-
-# If bundler gemspec exists, add to stubs
-bundler_gemspec = File.expand_path("../../../bundler/bundler.gemspec", __FILE__)
-if File.exist?(bundler_gemspec)
- Gem::Specification.dirs.unshift File.dirname(bundler_gemspec)
- Gem::Specification.class_variable_set :@@stubs, nil
- Gem::Specification.stubs
- Gem::Specification.dirs.shift
-end
+require "rubygems"
begin
- gem 'test-unit', '~> 3.0'
+ gem "test-unit", "~> 3.0"
rescue Gem::LoadError
end
-begin
- require 'simplecov'
- SimpleCov.start do
- add_filter "/test/"
- add_filter "/bundler/"
- add_filter "/lib/rubygems/resolver/molinillo"
- end
-rescue LoadError
-end
-
-if File.exist?(bundler_gemspec)
- require_relative '../../bundler/lib/bundler'
-else
- require 'bundler'
-end
-
-require 'test/unit'
+require "test/unit"
ENV["JARS_SKIP"] = "true" if Gem.java_platform? # avoid unnecessary and noisy `jar-dependencies` post install hook
-require 'rubygems/deprecate'
-
-require 'fileutils'
-require 'pathname'
-require 'pp'
-require 'rubygems/package'
-require 'shellwords'
-require 'tmpdir'
-require 'uri'
-require 'zlib'
-require 'benchmark' # stdlib
-require 'rubygems/mock_gem_ui'
+require "fileutils"
+require "pathname"
+require "pp"
+require "rubygems/package"
+require "shellwords"
+require "tmpdir"
+require "rubygems/vendor/uri/lib/uri"
+require "zlib"
+require_relative "mock_gem_ui"
module Gem
-
##
# Allows setting the gem path searcher.
@@ -98,8 +69,6 @@ end
# your normal set of gems is not affected.
class Gem::TestCase < Test::Unit::TestCase
- extend Gem::Deprecate
-
attr_accessor :fetcher # :nodoc:
attr_accessor :gem_repo # :nodoc:
@@ -129,39 +98,38 @@ class Gem::TestCase < Test::Unit::TestCase
assert File.directory?(path), msg
end
- # https://github.com/seattlerb/minitest/blob/21d9e804b63c619f602f3f4ece6c71b48974707a/lib/minitest/assertions.rb#L188
- def _synchronize
- yield
+ def refute_directory_exists(path, msg = nil)
+ msg = build_message(msg, "Expected path '#{path}' not to be a directory")
+ assert_path_not_exist path
+ refute File.directory?(path), msg
end
- # https://github.com/seattlerb/minitest/blob/21d9e804b63c619f602f3f4ece6c71b48974707a/lib/minitest/assertions.rb#L546
+ # Originally copied from minitest/assertions.rb
def capture_subprocess_io
- _synchronize do
- begin
- require "tempfile"
+ require "tempfile"
- captured_stdout, captured_stderr = Tempfile.new("out"), Tempfile.new("err")
+ captured_stdout = Tempfile.new("out")
+ captured_stderr = Tempfile.new("err")
- orig_stdout, orig_stderr = $stdout.dup, $stderr.dup
- $stdout.reopen captured_stdout
- $stderr.reopen captured_stderr
+ orig_stdout = $stdout.dup
+ orig_stderr = $stderr.dup
+ $stdout.reopen captured_stdout
+ $stderr.reopen captured_stderr
- yield
+ yield
- $stdout.rewind
- $stderr.rewind
+ $stdout.rewind
+ $stderr.rewind
- return captured_stdout.read, captured_stderr.read
- ensure
- $stdout.reopen orig_stdout
- $stderr.reopen orig_stderr
+ [captured_stdout.read, captured_stderr.read]
+ ensure
+ $stdout.reopen orig_stdout
+ $stderr.reopen orig_stderr
- orig_stdout.close
- orig_stderr.close
- captured_stdout.close!
- captured_stderr.close!
- end
- end
+ orig_stdout.close
+ orig_stderr.close
+ captured_stdout.close!
+ captured_stderr.close!
end
##
@@ -169,37 +137,45 @@ class Gem::TestCase < Test::Unit::TestCase
# the original value when the block ends
def enable_shared(value)
- enable_shared = RbConfig::CONFIG['ENABLE_SHARED']
- RbConfig::CONFIG['ENABLE_SHARED'] = value
+ enable_shared = RbConfig::CONFIG["ENABLE_SHARED"]
+ RbConfig::CONFIG["ENABLE_SHARED"] = value
yield
ensure
if enable_shared
- RbConfig::CONFIG['enable_shared'] = enable_shared
+ RbConfig::CONFIG["ENABLE_SHARED"] = enable_shared
else
- RbConfig::CONFIG.delete 'enable_shared'
+ RbConfig::CONFIG.delete "ENABLE_SHARED"
end
end
##
+ # Overrides the Gem.install_extension_in_lib function and restores the
+ # original when the block ends
+ #
+ def extension_in_lib(value = true) # :nodoc:
+ Gem.stub(:install_extension_in_lib, value) { yield }
+ end
+
+ ##
# Sets the vendordir entry in RbConfig::CONFIG to +value+ and restores the
# original value when the block ends
#
def vendordir(value)
- vendordir = RbConfig::CONFIG['vendordir']
+ vendordir = RbConfig::CONFIG["vendordir"]
if value
- RbConfig::CONFIG['vendordir'] = value
+ RbConfig::CONFIG["vendordir"] = value
else
- RbConfig::CONFIG.delete 'vendordir'
+ RbConfig::CONFIG.delete "vendordir"
end
yield
ensure
if vendordir
- RbConfig::CONFIG['vendordir'] = vendordir
+ RbConfig::CONFIG["vendordir"] = vendordir
else
- RbConfig::CONFIG.delete 'vendordir'
+ RbConfig::CONFIG.delete "vendordir"
end
end
@@ -209,21 +185,21 @@ class Gem::TestCase < Test::Unit::TestCase
#
def bindir(value)
with_clean_path_to_ruby do
- bindir = RbConfig::CONFIG['bindir']
+ bindir = RbConfig::CONFIG["bindir"]
if value
- RbConfig::CONFIG['bindir'] = value
+ RbConfig::CONFIG["bindir"] = value
else
- RbConfig::CONFIG.delete 'bindir'
+ RbConfig::CONFIG.delete "bindir"
end
begin
yield
ensure
if bindir
- RbConfig::CONFIG['bindir'] = bindir
+ RbConfig::CONFIG["bindir"] = bindir
else
- RbConfig::CONFIG.delete 'bindir'
+ RbConfig::CONFIG.delete "bindir"
end
end
end
@@ -234,20 +210,20 @@ class Gem::TestCase < Test::Unit::TestCase
# original value when the block ends
#
def exeext(value)
- exeext = RbConfig::CONFIG['EXEEXT']
+ exeext = RbConfig::CONFIG["EXEEXT"]
if value
- RbConfig::CONFIG['EXEEXT'] = value
+ RbConfig::CONFIG["EXEEXT"] = value
else
- RbConfig::CONFIG.delete 'EXEEXT'
+ RbConfig::CONFIG.delete "EXEEXT"
end
yield
ensure
if exeext
- RbConfig::CONFIG['EXEEXT'] = exeext
+ RbConfig::CONFIG["EXEEXT"] = exeext
else
- RbConfig::CONFIG.delete 'EXEEXT'
+ RbConfig::CONFIG.delete "EXEEXT"
end
end
@@ -255,52 +231,37 @@ class Gem::TestCase < Test::Unit::TestCase
output.scan(/^#{Regexp.escape make_command}(?:[[:blank:]].*)?$/)
end
- def parse_make_command_line(line)
- command, *args = line.shellsplit
+ def parse_make_command_line_targets(line)
+ args = line.sub(/^#{Regexp.escape make_command}/, "").shellsplit
targets = []
- macros = {}
args.each do |arg|
case arg
when /\A(\w+)=/
- macros[$1] = $'
else
targets << arg
end
end
- targets << '' if targets.empty?
+ targets << "" if targets.empty?
- {
- :command => command,
- :targets => targets,
- :macros => macros,
- }
+ targets
end
def assert_contains_make_command(target, output, msg = nil)
- if output.match(/\n/)
+ if output.include?("\n")
msg = build_message(msg,
- "Expected output containing make command \"%s\", but was \n\nBEGIN_OF_OUTPUT\n%sEND_OF_OUTPUT" % [
- ('%s %s' % [make_command, target]).rstrip,
- output,
- ]
- )
+ format("Expected output containing make command \"%s\", but was \n\nBEGIN_OF_OUTPUT\n%sEND_OF_OUTPUT", format("%s %s", make_command, target).rstrip, output))
else
msg = build_message(msg,
- 'Expected make command "%s": %s' % [
- ('%s %s' % [make_command, target]).rstrip,
- output,
- ]
- )
+ format('Expected make command "%s", but was "%s"', format("%s %s", make_command, target).rstrip, output))
end
assert scan_make_command_lines(output).any? {|line|
- make = parse_make_command_line(line)
+ targets = parse_make_command_line_targets(line)
- if make[:targets].include?(target)
- yield make, line if block_given?
+ if targets.include?(target)
true
else
false
@@ -319,18 +280,26 @@ class Gem::TestCase < Test::Unit::TestCase
# or <tt>i686-darwin8.10.1</tt> otherwise.
def setup
+ @orig_hooks = {}
@orig_env = ENV.to_hash
- @tmp = File.expand_path("tmp")
- FileUtils.mkdir_p @tmp
+ top_srcdir = __dir__ + "/../.."
+ @tmp = File.expand_path(ENV.fetch("GEM_TEST_TMPDIR", "tmp"), top_srcdir)
- ENV['GEM_VENDOR'] = nil
- ENV['GEMRC'] = nil
- ENV['XDG_CACHE_HOME'] = nil
- ENV['XDG_CONFIG_HOME'] = nil
- ENV['XDG_DATA_HOME'] = nil
- ENV['SOURCE_DATE_EPOCH'] = nil
- ENV['BUNDLER_VERSION'] = nil
+ FileUtils.mkdir_p(@tmp, mode: 0o700) # =rwx
+ @tmp = File.realpath(@tmp)
+
+ @tempdir = Dir.mktmpdir("test_rubygems_", @tmp)
+
+ ENV["GEM_VENDOR"] = nil
+ ENV["GEMRC"] = nil
+ ENV["XDG_CACHE_HOME"] = nil
+ ENV["XDG_CONFIG_HOME"] = nil
+ ENV["XDG_DATA_HOME"] = nil
+ ENV["XDG_STATE_HOME"] = nil
+ ENV["SOURCE_DATE_EPOCH"] = nil
+ ENV["BUNDLER_VERSION"] = nil
+ ENV["RUBYGEMS_PREVENT_UPDATE_SUGGESTION"] = "true"
@current_dir = Dir.pwd
@fetcher = nil
@@ -341,36 +310,35 @@ class Gem::TestCase < Test::Unit::TestCase
# capture output
Gem::DefaultUserInteraction.ui = Gem::MockGemUi.new
- @tempdir = Dir.mktmpdir("test_rubygems_", @tmp)
- @tempdir.tap(&Gem::UNTAINT)
-
- ENV["TMPDIR"] = @tempdir
-
- @orig_SYSTEM_WIDE_CONFIG_FILE = Gem::ConfigFile::SYSTEM_WIDE_CONFIG_FILE
+ @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')
+ File.join(@tempdir, "system-gemrc")
- @gemhome = File.join @tempdir, 'gemhome'
- @userhome = File.join @tempdir, 'userhome'
- ENV["GEM_SPEC_CACHE"] = File.join @tempdir, 'spec_cache'
+ @gemhome = File.join @tempdir, "gemhome"
+ @userhome = File.join @tempdir, "userhome"
+ @statehome = File.join @tempdir, "statehome"
+ ENV["GEM_SPEC_CACHE"] = File.join @tempdir, "spec_cache"
- @orig_ruby = if ENV['RUBY']
- ruby = Gem.ruby
- Gem.ruby = ENV['RUBY']
- ruby
- end
+ @orig_ruby = if ENV["RUBY"]
+ ruby = Gem.ruby
+ Gem.ruby = ENV["RUBY"]
+ ruby
+ end
- @git = ENV['GIT'] || (win_platform? ? 'git.exe' : 'git')
+ @git = ENV["GIT"] || "git#{RbConfig::CONFIG["EXEEXT"]}"
Gem.ensure_gem_subdirectories @gemhome
Gem.ensure_default_gem_subdirectories @gemhome
- @orig_LOAD_PATH = $LOAD_PATH.dup
+ @orig_load_path = $LOAD_PATH.dup
$LOAD_PATH.map! do |s|
- expand_path = File.realpath(s) rescue File.expand_path(s)
+ expand_path = begin
+ File.realpath(s)
+ rescue StandardError
+ File.expand_path(s)
+ end
if expand_path != s
- expand_path.tap(&Gem::UNTAINT)
if s.instance_variable_defined?(:@gem_prelude_index)
expand_path.instance_variable_set(:@gem_prelude_index, expand_path)
end
@@ -382,11 +350,17 @@ class Gem::TestCase < Test::Unit::TestCase
Dir.chdir @tempdir
- ENV['HOME'] = @userhome
+ ENV["HOME"] = @userhome
+ # Remove "RUBY_CODESIGN", which is used by mkmf-generated Makefile to
+ # sign extension bundles on macOS, to avoid trying to find the specified key
+ # from the fake $HOME/Library/Keychains directory.
+ ENV.delete "RUBY_CODESIGN"
Gem.instance_variable_set :@config_file, nil
Gem.instance_variable_set :@user_home, nil
Gem.instance_variable_set :@config_home, nil
Gem.instance_variable_set :@data_home, nil
+ Gem.instance_variable_set :@state_home, @statehome
+ Gem.instance_variable_set :@state_file, nil
Gem.instance_variable_set :@gemdeps, nil
Gem.instance_variable_set :@env_requirements_by_name, nil
Gem.send :remove_instance_variable, :@ruby_version if
@@ -394,11 +368,12 @@ class Gem::TestCase < Test::Unit::TestCase
FileUtils.mkdir_p @userhome
- ENV['GEM_PRIVATE_KEY_PASSPHRASE'] = PRIVATE_KEY_PASSPHRASE
+ ENV["GEM_PRIVATE_KEY_PASSPHRASE"] = PRIVATE_KEY_PASSPHRASE
+ Gem.instance_variable_set(:@default_specifications_dir, File.join(@gemhome, "specifications", "default"))
if Gem.java_platform?
- @orig_default_gem_home = RbConfig::CONFIG['default_gem_home']
- RbConfig::CONFIG['default_gem_home'] = @gemhome
+ @orig_default_gem_home = RbConfig::CONFIG["default_gem_home"]
+ RbConfig::CONFIG["default_gem_home"] = @gemhome
else
Gem.instance_variable_set(:@default_dir, @gemhome)
end
@@ -406,13 +381,20 @@ class Gem::TestCase < Test::Unit::TestCase
@orig_bindir = RbConfig::CONFIG["bindir"]
RbConfig::CONFIG["bindir"] = File.join @gemhome, "bin"
+ @orig_sitelibdir = RbConfig::CONFIG["sitelibdir"]
+ new_sitelibdir = @orig_sitelibdir.sub(RbConfig::CONFIG["prefix"], @gemhome)
+ $LOAD_PATH.insert(Gem.load_path_insert_index, new_sitelibdir)
+ RbConfig::CONFIG["sitelibdir"] = new_sitelibdir
+
+ @orig_mandir = RbConfig::CONFIG["mandir"]
+ RbConfig::CONFIG["mandir"] = File.join @gemhome, "share", "man"
+
Gem::Specification.unresolved_deps.clear
Gem.use_paths(@gemhome)
Gem.loaded_specs.clear
Gem.instance_variable_set(:@activated_gem_paths, 0)
Gem.clear_default_specs
- Bundler.reset!
Gem.configuration.verbose = true
Gem.configuration.update_sources = true
@@ -420,27 +402,26 @@ class Gem::TestCase < Test::Unit::TestCase
Gem::RemoteFetcher.fetcher = Gem::FakeFetcher.new
@gem_repo = "http://gems.example.com/"
- @uri = URI.parse @gem_repo
+ @uri = Gem::URI.parse @gem_repo
Gem.sources.replace [@gem_repo]
Gem.searcher = nil
Gem::SpecFetcher.fetcher = nil
- @orig_arch = RbConfig::CONFIG['arch']
+ @orig_arch = RbConfig::CONFIG["arch"]
- if win_platform?
- util_set_arch 'i386-mswin32'
+ if Gem.win_platform?
+ util_set_arch "i386-mswin32"
else
- util_set_arch 'i686-darwin8.10.1'
+ util_set_arch "i686-darwin8.10.1"
end
- @orig_hooks = {}
%w[post_install_hooks done_installing_hooks post_uninstall_hooks pre_uninstall_hooks pre_install_hooks pre_reset_hooks post_reset_hooks post_build_hooks].each do |name|
@orig_hooks[name] = Gem.send(name).dup
end
@marshal_version = "#{Marshal::MAJOR_VERSION}.#{Marshal::MINOR_VERSION}"
- @orig_LOADED_FEATURES = $LOADED_FEATURES.dup
+ @orig_loaded_features = $LOADED_FEATURES.dup
end
##
@@ -448,18 +429,18 @@ class Gem::TestCase < Test::Unit::TestCase
# tempdir
def teardown
- $LOAD_PATH.replace @orig_LOAD_PATH if @orig_LOAD_PATH
- if @orig_LOADED_FEATURES
- if @orig_LOAD_PATH
- ($LOADED_FEATURES - @orig_LOADED_FEATURES).each do |feat|
+ $LOAD_PATH.replace @orig_load_path if @orig_load_path
+ if @orig_loaded_features
+ if @orig_load_path
+ ($LOADED_FEATURES - @orig_loaded_features).each do |feat|
$LOADED_FEATURES.delete(feat) if feat.start_with?(@tmp)
end
else
- $LOADED_FEATURES.replace @orig_LOADED_FEATURES
+ $LOADED_FEATURES.replace @orig_loaded_features
end
end
- RbConfig::CONFIG['arch'] = @orig_arch
+ RbConfig::CONFIG["arch"] = @orig_arch
if defined? Gem::RemoteFetcher
Gem::RemoteFetcher.fetcher = nil
@@ -467,40 +448,44 @@ class Gem::TestCase < Test::Unit::TestCase
Dir.chdir @current_dir
- FileUtils.rm_rf @tempdir
-
ENV.replace(@orig_env)
Gem::ConfigFile.send :remove_const, :SYSTEM_WIDE_CONFIG_FILE
Gem::ConfigFile.send :const_set, :SYSTEM_WIDE_CONFIG_FILE,
- @orig_SYSTEM_WIDE_CONFIG_FILE
+ @orig_system_wide_config_file
Gem.ruby = @orig_ruby if @orig_ruby
- RbConfig::CONFIG['bindir'] = @orig_bindir
+ RbConfig::CONFIG["mandir"] = @orig_mandir
+ RbConfig::CONFIG["sitelibdir"] = @orig_sitelibdir
+ RbConfig::CONFIG["bindir"] = @orig_bindir
+ Gem.instance_variable_set :@default_specifications_dir, nil
if Gem.java_platform?
- RbConfig::CONFIG['default_gem_home'] = @orig_default_gem_home
+ RbConfig::CONFIG["default_gem_home"] = @orig_default_gem_home
else
Gem.instance_variable_set :@default_dir, nil
end
- Gem::Specification._clear_load_cache
Gem::Specification.unresolved_deps.clear
- Gem::refresh
+ Gem.refresh
@orig_hooks.each do |name, hooks|
Gem.send(name).replace hooks
end
@back_ui.close
+
+ FileUtils.rm_rf @tempdir
+
+ refute_directory_exists @tempdir, "#{@tempdir} used by test #{method_name} is still in use"
end
def credential_setup
- @temp_cred = File.join(@userhome, '.gem', 'credentials')
+ @temp_cred = File.join(@userhome, ".gem", "credentials")
FileUtils.mkdir_p File.dirname(@temp_cred)
- File.write @temp_cred, ':rubygems_api_key: 701229f217cdf23b1344c7b4b54ca97'
- File.chmod 0600, @temp_cred
+ File.write @temp_cred, ":rubygems_api_key: 701229f217cdf23b1344c7b4b54ca97"
+ File.chmod 0o600, @temp_cred
end
def credential_teardown
@@ -548,16 +533,26 @@ class Gem::TestCase < Test::Unit::TestCase
ENV["BUNDLE_GEMFILE"] = File.join(@tempdir, "Gemfile")
end
+ def with_env(overrides, &block)
+ orig_env = ENV.to_h
+ ENV.replace(overrides)
+ begin
+ block.call
+ ensure
+ ENV.replace(orig_env)
+ end
+ end
+
##
# A git_gem is used with a gem dependencies file. The gem created here
# has no files, just a gem specification for the given +name+ and +version+.
#
# Yields the +specification+ to the block, if given
- def git_gem(name = 'a', version = 1)
+ def git_gem(name = "a", version = 1)
have_git?
- directory = File.join 'git', name
+ directory = File.join "git", name
directory = File.expand_path directory
git_spec = Gem::Specification.new name, version do |specification|
@@ -568,25 +563,25 @@ class Gem::TestCase < Test::Unit::TestCase
gemspec = "#{name}.gemspec"
- File.open File.join(directory, gemspec), 'w' do |io|
+ File.open File.join(directory, gemspec), "w" do |io|
io.write git_spec.to_ruby
end
head = nil
Dir.chdir directory do
- unless File.exist? '.git'
- system @git, 'init', '--quiet'
- system @git, 'config', 'user.name', 'RubyGems Tests'
- system @git, 'config', 'user.email', 'rubygems@example'
+ unless File.exist? ".git"
+ system @git, "init", "--quiet"
+ system @git, "config", "user.name", "RubyGems Tests"
+ system @git, "config", "user.email", "rubygems@example"
end
- system @git, 'add', gemspec
- system @git, 'commit', '-a', '-m', 'a non-empty commit message', '--quiet'
- head = Gem::Util.popen(@git, 'rev-parse', 'master').strip
+ system @git, "add", gemspec
+ system @git, "commit", "-a", "-m", "a non-empty commit message", "--quiet"
+ head = Gem::Util.popen(@git, "rev-parse", "HEAD").strip
end
- return name, git_spec.version, directory, head
+ [name, git_spec.version, directory, head]
end
##
@@ -595,13 +590,13 @@ class Gem::TestCase < Test::Unit::TestCase
def have_git?
return if in_path? @git
- pend 'cannot find git executable, use GIT environment variable to set'
+ pend "cannot find git executable, use GIT environment variable to set"
end
def in_path?(executable) # :nodoc:
- return true if %r{\A([A-Z]:|/)} =~ executable and File.exist? executable
+ return true if %r{\A([A-Z]:|/)}.match?(executable) && File.exist?(executable)
- ENV['PATH'].split(File::PATH_SEPARATOR).any? do |directory|
+ ENV["PATH"].split(File::PATH_SEPARATOR).any? do |directory|
File.exist? File.join directory, executable
end
end
@@ -610,7 +605,7 @@ class Gem::TestCase < Test::Unit::TestCase
# Builds and installs the Gem::Specification +spec+
def install_gem(spec, options = {})
- require 'rubygems/installer'
+ require "rubygems/installer"
gem = spec.cache_file
@@ -621,29 +616,29 @@ class Gem::TestCase < Test::Unit::TestCase
end
end
- gem = File.join(@tempdir, File.basename(gem)).tap(&Gem::UNTAINT)
+ gem = File.join(@tempdir, File.basename(gem))
end
- Gem::Installer.at(gem, options.merge({:wrappers => true})).install
+ Gem::Installer.at(gem, options.merge({ wrappers: true })).install
end
##
# Builds and installs the Gem::Specification +spec+ into the user dir
def install_gem_user(spec)
- install_gem spec, :user_install => true
+ install_gem spec, user_install: true
end
##
# Uninstalls the Gem::Specification +spec+
def uninstall_gem(spec)
- require 'rubygems/uninstaller'
+ require "rubygems/uninstaller"
Class.new(Gem::Uninstaller) do
def ask_if_ok(spec)
true
end
- end.new(spec.name, :executables => true, :user_install => true).uninstall
+ end.new(spec.name, executables: true, user_install: true).uninstall
end
##
@@ -660,7 +655,7 @@ class Gem::TestCase < Test::Unit::TestCase
# Reads a Marshal file at +path+
def read_cache(path)
- File.open path.dup.tap(&Gem::UNTAINT), 'rb' do |io|
+ File.open path.dup, "rb" do |io|
Marshal.load io.read
end
end
@@ -680,7 +675,7 @@ class Gem::TestCase < Test::Unit::TestCase
dir = File.dirname path
FileUtils.mkdir_p dir unless File.directory? dir
- File.open path, 'wb' do |io|
+ File.open path, "wb" do |io|
yield io if block_given?
end
@@ -691,10 +686,10 @@ class Gem::TestCase < Test::Unit::TestCase
# Load a YAML string, the psych 3 way
def load_yaml(yaml)
- if YAML.respond_to?(:unsafe_load)
- YAML.unsafe_load(yaml)
+ if Psych.respond_to?(:unsafe_load)
+ Psych.unsafe_load(yaml)
else
- YAML.load(yaml)
+ Psych.load(yaml)
end
end
@@ -702,11 +697,8 @@ class Gem::TestCase < Test::Unit::TestCase
# Load a YAML file, the psych 3 way
def load_yaml_file(file)
- if YAML.respond_to?(:unsafe_load_file)
- YAML.unsafe_load_file(file)
- else
- YAML.load_file(file)
- end
+ require "rubygems/config_file"
+ Gem::ConfigFile.load_with_rubygems_config_hash(File.read(file))
end
def all_spec_names
@@ -723,16 +715,16 @@ class Gem::TestCase < Test::Unit::TestCase
#
# Use this with #write_file to build an installed gem.
- def quick_gem(name, version='2')
- require 'rubygems/specification'
+ def quick_gem(name, version="2")
+ require "rubygems/specification"
spec = Gem::Specification.new do |s|
s.platform = Gem::Platform::RUBY
s.name = name
s.version = version
- s.author = 'A User'
- s.email = 'example@example.com'
- s.homepage = 'http://example.com'
+ s.author = "A User"
+ s.email = "example@example.com"
+ s.homepage = "http://example.com"
s.summary = "this is a summary"
s.description = "This is a test description"
@@ -747,7 +739,7 @@ class Gem::TestCase < Test::Unit::TestCase
Gem::Specification.reset
- return spec
+ spec
end
##
@@ -763,7 +755,7 @@ class Gem::TestCase < Test::Unit::TestCase
next if File.exist? file
FileUtils.mkdir_p File.dirname(file)
- File.open file, 'w' do |fp|
+ File.open file, "w" do |fp|
fp.puts "# #{file}"
end
end
@@ -798,7 +790,7 @@ class Gem::TestCase < Test::Unit::TestCase
def install_specs(*specs)
specs.each do |spec|
- Gem::Installer.for_spec(spec, :force => true).install
+ Gem::Installer.for_spec(spec, force: true).install
end
Gem.searcher = nil
@@ -809,7 +801,7 @@ class Gem::TestCase < Test::Unit::TestCase
def install_default_gems(*specs)
specs.each do |spec|
- installer = Gem::Installer.for_spec(spec, :install_as_default => true)
+ installer = Gem::Installer.for_spec(spec, install_as_default: true)
installer.install
Gem.register_default_spec(spec)
end
@@ -823,19 +815,15 @@ class Gem::TestCase < Test::Unit::TestCase
Gem::Specification.unresolved_deps.values.map(&:to_s).sort
end
- def save_loaded_features
- old_loaded_features = $LOADED_FEATURES.dup
- yield
- ensure
- prefix = File.dirname(__FILE__) + "/"
- new_features = ($LOADED_FEATURES - old_loaded_features)
- old_loaded_features.concat(new_features.select {|f| f.rindex(prefix, 0) })
- $LOADED_FEATURES.replace old_loaded_features
- end
-
- def new_default_spec(name, version, deps = nil, *files)
+ def new_default_spec(name, version, deps = nil, *files, executable: false)
spec = util_spec name, version, deps
+ if executable
+ spec.executables = %w[executable]
+
+ write_file File.join(@tempdir, "bin", "executable")
+ end
+
spec.loaded_from = File.join(@gemhome, "specifications", "default", spec.spec_name)
spec.files = files
@@ -844,10 +832,8 @@ class Gem::TestCase < Test::Unit::TestCase
Gem.instance_variable_set(:@default_gem_load_paths, [*Gem.send(:default_gem_load_paths), lib_dir])
$LOAD_PATH.unshift(lib_dir)
files.each do |file|
- rb_path = File.join(lib_dir, file)
- FileUtils.mkdir_p(File.dirname(rb_path))
- File.open(rb_path, "w") do |rb|
- rb << "# #{file}"
+ write_file File.join(lib_dir, file) do |io|
+ io.write "# #{file}"
end
end
@@ -859,15 +845,15 @@ class Gem::TestCase < Test::Unit::TestCase
# or a +block+ can be given for full customization of the specification.
def util_spec(name, version = 2, deps = nil, *files) # :yields: specification
- raise "deps or block, not both" if deps and block_given?
+ raise "deps or block, not both" if deps && block_given?
spec = Gem::Specification.new do |s|
s.platform = Gem::Platform::RUBY
s.name = name
s.version = version
- s.author = 'A User'
- s.email = 'example@example.com'
- s.homepage = 'http://example.com'
+ s.author = "A User"
+ s.email = "example@example.com"
+ s.homepage = "http://example.com"
s.summary = "this is a summary"
s.description = "This is a test description"
@@ -878,7 +864,7 @@ class Gem::TestCase < Test::Unit::TestCase
if deps
deps.keys.each do |n|
- spec.add_dependency n, (deps[n] || '>= 0')
+ spec.add_dependency n, (deps[n] || ">= 0")
end
end
@@ -892,7 +878,7 @@ class Gem::TestCase < Test::Unit::TestCase
FileUtils.rm spec.spec_file
end
- return spec
+ spec
end
##
@@ -905,7 +891,7 @@ class Gem::TestCase < Test::Unit::TestCase
if deps
block = proc do |s|
deps.keys.each do |n|
- s.add_dependency n, (deps[n] || '>= 0')
+ s.add_dependency n, (deps[n] || ">= 0")
end
end
end
@@ -914,7 +900,7 @@ class Gem::TestCase < Test::Unit::TestCase
util_build_gem spec
- cache_file = File.join @tempdir, 'gems', "#{spec.original_name}.gem"
+ cache_file = File.join @tempdir, "gems", "#{spec.original_name}.gem"
FileUtils.mkdir_p File.dirname cache_file
FileUtils.mv spec.cache_file, cache_file
FileUtils.rm spec.spec_file
@@ -956,11 +942,11 @@ class Gem::TestCase < Test::Unit::TestCase
# TODO: nuke this and fix tests. this should speed up a lot
def util_make_gems(prerelease = false)
- @a1 = quick_gem 'a', '1' do |s|
+ @a1 = quick_gem "a", "1" do |s|
s.files = %w[lib/code.rb]
s.require_paths = %w[lib]
- s.date = Gem::Specification::TODAY - 86400
- s.homepage = 'http://a.example.com'
+ s.date = Gem::Specification::TODAY - 86_400
+ s.homepage = "http://a.example.com"
s.email = %w[example@example.com example2@example.com]
s.authors = %w[Example Example2]
s.description = <<-DESC
@@ -977,40 +963,40 @@ Also, a list:
s.require_paths = %w[lib]
end
- @a2 = quick_gem('a', '2', &init)
- @a3a = quick_gem('a', '3.a', &init)
- @a_evil9 = quick_gem('a_evil', '9', &init)
- @b2 = quick_gem('b', '2', &init)
- @c1_2 = quick_gem('c', '1.2', &init)
- @x = quick_gem('x', '1', &init)
- @dep_x = quick_gem('dep_x', '1') do |s|
+ @a2 = quick_gem("a", "2", &init)
+ @a3a = quick_gem("a", "3.a", &init)
+ @a_evil9 = quick_gem("a_evil", "9", &init)
+ @b2 = quick_gem("b", "2", &init)
+ @c1_2 = quick_gem("c", "1.2", &init)
+ @x = quick_gem("x", "1", &init)
+ @dep_x = quick_gem("dep_x", "1") do |s|
s.files = %w[lib/code.rb]
s.require_paths = %w[lib]
- s.add_dependency 'x', '>= 1'
+ s.add_dependency "x", ">= 1"
end
- @pl1 = quick_gem 'pl', '1' do |s| # l for legacy
+ @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'
+ s.platform = Gem::Platform.new "i386-linux"
+ s.instance_variable_set :@original_platform, "i386-linux"
end
if prerelease
- @a2_pre = quick_gem('a', '2.a', &init)
+ @a2_pre = quick_gem("a", "2.a", &init)
write_file File.join(*%W[gems #{@a2_pre.original_name} lib code.rb])
util_build_gem @a2_pre
end
- write_file File.join(*%W[gems #{@a1.original_name} lib code.rb])
- write_file File.join(*%W[gems #{@a2.original_name} lib code.rb])
- write_file File.join(*%W[gems #{@a3a.original_name} lib code.rb])
+ write_file File.join(*%W[gems #{@a1.original_name} lib code.rb])
+ write_file File.join(*%W[gems #{@a2.original_name} lib code.rb])
+ write_file File.join(*%W[gems #{@a3a.original_name} lib code.rb])
write_file File.join(*%W[gems #{@a_evil9.original_name} lib code.rb])
- write_file File.join(*%W[gems #{@b2.original_name} lib code.rb])
- write_file File.join(*%W[gems #{@c1_2.original_name} lib code.rb])
- write_file File.join(*%W[gems #{@pl1.original_name} lib code.rb])
- write_file File.join(*%W[gems #{@x.original_name} lib code.rb])
- write_file File.join(*%W[gems #{@dep_x.original_name} lib code.rb])
+ write_file File.join(*%W[gems #{@b2.original_name} lib code.rb])
+ write_file File.join(*%W[gems #{@c1_2.original_name} lib code.rb])
+ write_file File.join(*%W[gems #{@pl1.original_name} lib code.rb])
+ write_file File.join(*%W[gems #{@x.original_name} lib code.rb])
+ write_file File.join(*%W[gems #{@dep_x.original_name} lib code.rb])
[@a1, @a2, @a3a, @a_evil9, @b2, @c1_2, @pl1, @x, @dep_x].each do |spec|
util_build_gem spec
@@ -1023,7 +1009,7 @@ Also, a list:
# Set the platform to +arch+
def util_set_arch(arch)
- RbConfig::CONFIG['arch'] = arch
+ RbConfig::CONFIG["arch"] = arch
platform = Gem::Platform.new arch
Gem.instance_variable_set :@platforms, nil
@@ -1070,39 +1056,41 @@ Also, a list:
spec_fetcher.prerelease_specs[@uri] << spec.name_tuple
end
- # HACK for test_download_to_cache
+ # HACK: for test_download_to_cache
unless Gem::RemoteFetcher === @fetcher
v = Gem.marshal_version
- specs = all.map {|spec| spec.name_tuple }
+ specs = all.map(&:name_tuple)
s_zip = util_gzip Marshal.dump Gem::NameTuple.to_basic specs
- latest_specs = latest.map do |spec|
- spec.name_tuple
- end
+ latest_specs = latest.map(&:name_tuple)
l_zip = util_gzip Marshal.dump Gem::NameTuple.to_basic latest_specs
- prerelease_specs = prerelease.map {|spec| spec.name_tuple }
+ prerelease_specs = prerelease.map(&:name_tuple)
p_zip = util_gzip Marshal.dump Gem::NameTuple.to_basic prerelease_specs
@fetcher.data["#{@gem_repo}specs.#{v}.gz"] = s_zip
@fetcher.data["#{@gem_repo}latest_specs.#{v}.gz"] = l_zip
@fetcher.data["#{@gem_repo}prerelease_specs.#{v}.gz"] = p_zip
- v = Gem.marshal_version
-
- all_specs.each do |spec|
- path = "#{@gem_repo}quick/Marshal.#{v}/#{spec.original_name}.gemspec.rz"
- data = Marshal.dump spec
- data_deflate = Zlib::Deflate.deflate data
- @fetcher.data[path] = data_deflate
- end
+ write_marshalled_gemspecs(*all_specs)
end
nil # force errors
end
+ def write_marshalled_gemspecs(*all_specs)
+ v = Gem.marshal_version
+
+ all_specs.each do |spec|
+ path = "#{@gem_repo}quick/Marshal.#{v}/#{spec.original_name}.gemspec.rz"
+ data = Marshal.dump spec
+ data_deflate = Zlib::Deflate.deflate data
+ @fetcher.data[path] = data_deflate
+ end
+ end
+
##
# Deflates +data+
@@ -1110,78 +1098,46 @@ Also, a list:
Zlib::Deflate.deflate data
end
- def util_set_RUBY_VERSION(version, patchlevel = nil, revision = nil, description = nil, engine = "ruby", engine_version = nil)
+ def util_set_RUBY_VERSION(version, patchlevel, revision, description, engine = "ruby", engine_version = nil)
if Gem.instance_variables.include? :@ruby_version
Gem.send :remove_instance_variable, :@ruby_version
end
- @RUBY_VERSION = RUBY_VERSION
- @RUBY_PATCHLEVEL = RUBY_PATCHLEVEL if defined?(RUBY_PATCHLEVEL)
- @RUBY_REVISION = RUBY_REVISION if defined?(RUBY_REVISION)
- @RUBY_DESCRIPTION = RUBY_DESCRIPTION if defined?(RUBY_DESCRIPTION)
- @RUBY_ENGINE = RUBY_ENGINE
- @RUBY_ENGINE_VERSION = RUBY_ENGINE_VERSION if defined?(RUBY_ENGINE_VERSION)
+ @ruby_version = RUBY_VERSION
+ @ruby_patchlevel = RUBY_PATCHLEVEL
+ @ruby_revision = RUBY_REVISION
+ @ruby_description = RUBY_DESCRIPTION
+ @ruby_engine = RUBY_ENGINE
+ @ruby_engine_version = RUBY_ENGINE_VERSION
util_clear_RUBY_VERSION
Object.const_set :RUBY_VERSION, version
- Object.const_set :RUBY_PATCHLEVEL, patchlevel if patchlevel
- Object.const_set :RUBY_REVISION, revision if revision
- Object.const_set :RUBY_DESCRIPTION, description if description
+ Object.const_set :RUBY_PATCHLEVEL, patchlevel
+ Object.const_set :RUBY_REVISION, revision
+ Object.const_set :RUBY_DESCRIPTION, description
Object.const_set :RUBY_ENGINE, engine
- Object.const_set :RUBY_ENGINE_VERSION, engine_version if engine_version
+ Object.const_set :RUBY_ENGINE_VERSION, engine_version
end
def util_restore_RUBY_VERSION
util_clear_RUBY_VERSION
- Object.const_set :RUBY_VERSION, @RUBY_VERSION
- Object.const_set :RUBY_PATCHLEVEL, @RUBY_PATCHLEVEL if
- defined?(@RUBY_PATCHLEVEL)
- Object.const_set :RUBY_REVISION, @RUBY_REVISION if
- defined?(@RUBY_REVISION)
- Object.const_set :RUBY_DESCRIPTION, @RUBY_DESCRIPTION if
- defined?(@RUBY_DESCRIPTION)
- Object.const_set :RUBY_ENGINE, @RUBY_ENGINE
- Object.const_set :RUBY_ENGINE_VERSION, @RUBY_ENGINE_VERSION if
- defined?(@RUBY_ENGINE_VERSION)
+ Object.const_set :RUBY_VERSION, @ruby_version
+ Object.const_set :RUBY_PATCHLEVEL, @ruby_patchlevel
+ Object.const_set :RUBY_REVISION, @ruby_revision
+ Object.const_set :RUBY_DESCRIPTION, @ruby_description
+ Object.const_set :RUBY_ENGINE, @ruby_engine
+ Object.const_set :RUBY_ENGINE_VERSION, @ruby_engine_version
end
def util_clear_RUBY_VERSION
Object.send :remove_const, :RUBY_VERSION
- Object.send :remove_const, :RUBY_PATCHLEVEL if defined?(RUBY_PATCHLEVEL)
- Object.send :remove_const, :RUBY_REVISION if defined?(RUBY_REVISION)
- Object.send :remove_const, :RUBY_DESCRIPTION if defined?(RUBY_DESCRIPTION)
+ Object.send :remove_const, :RUBY_PATCHLEVEL
+ Object.send :remove_const, :RUBY_REVISION
+ Object.send :remove_const, :RUBY_DESCRIPTION
Object.send :remove_const, :RUBY_ENGINE
- Object.send :remove_const, :RUBY_ENGINE_VERSION if defined?(RUBY_ENGINE_VERSION)
- end
-
- ##
- # Is this test being run on a Windows platform?
-
- def self.win_platform?
- Gem.win_platform?
- end
-
- ##
- # Is this test being run on a Windows platform?
-
- def win_platform?
- Gem.win_platform?
- end
-
- ##
- # Is this test being run on a Java platform?
-
- def self.java_platform?
- Gem.java_platform?
- end
-
- ##
- # Is this test being run on a Java platform?
-
- def java_platform?
- Gem.java_platform?
+ Object.send :remove_const, :RUBY_ENGINE_VERSION
end
##
@@ -1189,24 +1145,29 @@ Also, a list:
# Borland) versus Cygwin, Mingw, etc.
def self.vc_windows?
- RUBY_PLATFORM.match('mswin')
+ RUBY_PLATFORM.match("mswin")
end
##
- # Returns whether or not we're on a version of Ruby built with VC++ (or
- # Borland) versus Cygwin, Mingw, etc.
+ # see ::vc_windows?
def vc_windows?
- RUBY_PLATFORM.match('mswin')
+ self.class.vc_windows?
end
##
- # Returns the make command for the current platform. For versions of Ruby
- # built on MS Windows with VC++ or Borland it will return 'nmake'. On all
- # other platforms, including Cygwin, it will return 'make'.
+ # Is this test being run on a version of Ruby built with mingw?
- def self.make_command
- ENV["make"] || ENV["MAKE"] || (vc_windows? ? 'nmake' : 'make')
+ def mingw_windows?
+ RUBY_PLATFORM.match("mingw")
+ end
+
+ ##
+ # Is this test being run on a ruby/ruby repository?
+ #
+
+ def ruby_repo?
+ !ENV["GEM_COMMAND"].nil?
end
##
@@ -1215,14 +1176,14 @@ Also, a list:
# other platforms, including Cygwin, it will return 'make'.
def make_command
- ENV["make"] || ENV["MAKE"] || (vc_windows? ? 'nmake' : 'make')
+ ENV["make"] || ENV["MAKE"] || (vc_windows? ? "nmake" : "make")
end
##
# Returns whether or not the nmake command could be found.
def nmake_found?
- system('nmake /? 1>NUL 2>&1')
+ system("nmake /? 1>NUL 2>&1")
end
# In case we're building docs in a background process, this method waits for
@@ -1234,22 +1195,6 @@ Also, a list:
end
##
- # Allows 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
-
- ##
- # See ::process_based_port
-
- def process_based_port
- self.class.process_based_port
- end
-
- ##
# Allows the proper version of +rake+ to be used for the test.
def build_rake_in(good=true)
@@ -1275,13 +1220,13 @@ Also, a list:
ruby = ENV["RUBY"]
return ruby if ruby
ruby = "ruby"
- rubyexe = "#{ruby}.exe"
+ rubyexe = "#{ruby}#{RbConfig::CONFIG["EXEEXT"]}"
3.times do
- if File.exist? ruby and File.executable? ruby and !File.directory? ruby
+ if File.exist?(ruby) && File.executable?(ruby) && !File.directory?(ruby)
return File.expand_path(ruby)
end
- if File.exist? rubyexe and File.executable? rubyexe
+ if File.exist?(rubyexe) && File.executable?(rubyexe)
return File.expand_path(rubyexe)
end
ruby = File.join("..", ruby)
@@ -1299,7 +1244,11 @@ Also, a list:
end
def rubygems_path
- $LOAD_PATH.find{|p| p == File.dirname($LOADED_FEATURES.find{|f| f.end_with?("/rubygems.rb") }) }
+ $LOAD_PATH.find {|p| p == File.dirname($LOADED_FEATURES.find {|f| f.end_with?("/rubygems.rb") }) }
+ end
+
+ def bundler_path
+ $LOAD_PATH.find {|p| p == File.dirname($LOADED_FEATURES.find {|f| f.end_with?("/bundler.rb") }) }
end
def with_clean_path_to_ruby
@@ -1312,26 +1261,39 @@ Also, a list:
Gem.instance_variable_set :@ruby, orig_ruby
end
- class << self
- # :nodoc:
- ##
- # Return the join path, with escaping backticks, dollars, and
- # double-quotes. Unlike `shellescape`, equal-sign is not escaped.
+ def with_internal_encoding(encoding)
+ int_enc = Encoding.default_internal
+ silence_warnings { Encoding.default_internal = encoding }
- private
+ yield
+ ensure
+ silence_warnings { Encoding.default_internal = int_enc }
+ end
- def escape_path(*path)
- path = File.join(*path)
- if %r{\A[-+:/=@,.\w]+\z} =~ path
- path
- else
- "\"#{path.gsub(/[`$"]/, '\\&')}\""
- end
+ def silence_warnings
+ old_verbose = $VERBOSE
+ $VERBOSE = false
+ yield
+ ensure
+ $VERBOSE = old_verbose
+ end
+
+ # :nodoc:
+ ##
+ # Return the join path, with escaping backticks, dollars, and
+ # double-quotes. Unlike `shellescape`, equal-sign is not escaped.
+
+ def self.escape_path(*path)
+ path = File.join(*path)
+ if %r{\A[-+:/=@,.\w]+\z}.match?(path)
+ path
+ else
+ "\"#{path.gsub(/[`$"]/, '\\&')}\""
end
end
- @@good_rake = "#{rubybin} #{escape_path(__dir__, 'good_rake.rb')}"
- @@bad_rake = "#{rubybin} #{escape_path(__dir__, 'bad_rake.rb')}"
+ @@good_rake = "#{rubybin} #{escape_path(__dir__, "good_rake.rb")}"
+ @@bad_rake = "#{rubybin} #{escape_path(__dir__, "bad_rake.rb")}"
##
# Construct a new Gem::Dependency.
@@ -1414,12 +1376,12 @@ Also, a list:
#
# Yields the +specification+ to the block, if given
- def vendor_gem(name = 'a', version = 1)
- directory = File.join 'vendor', name
+ def vendor_gem(name = "a", version = 1, &block)
+ directory = File.join "vendor", name
FileUtils.mkdir_p directory
- save_gemspec name, version, directory
+ save_gemspec name, version, directory, &block
end
##
@@ -1428,16 +1390,16 @@ Also, a list:
#
# Yields the +specification+ to the block, if given
- def save_gemspec(name = 'a', version = 1, directory = '.')
+ def save_gemspec(name = "a", version = 1, directory = ".")
vendor_spec = Gem::Specification.new name, version do |specification|
yield specification if block_given?
end
- File.open File.join(directory, "#{name}.gemspec"), 'w' do |io|
+ File.open File.join(directory, "#{name}.gemspec"), "w" do |io|
io.write vendor_spec.to_ruby
end
- return name, vendor_spec.version, directory
+ [name, vendor_spec.version, directory]
end
##
@@ -1517,7 +1479,11 @@ Also, a list:
# <tt>test/rubygems/</tt>.
def self.cert_path(cert_name)
- if 32 == (Time.at(2**32) rescue 32)
+ if begin
+ Time.at(2**32)
+ rescue StandardError
+ 32
+ end == 32
cert_file = "#{__dir__}/#{cert_name}_cert_32.pem"
return cert_file if File.exist? cert_file
@@ -1527,14 +1493,14 @@ Also, a list:
end
##
- # Loads an RSA private key named +key_name+ with +passphrase+ in <tt>test/rubygems/</tt>
+ # Loads a private key named +key_name+ with +passphrase+ in <tt>test/rubygems/</tt>
def self.load_key(key_name, passphrase = nil)
key_file = key_path key_name
key = File.read key_file
- OpenSSL::PKey::RSA.new key, passphrase
+ OpenSSL::PKey.read key, passphrase
end
##
@@ -1547,20 +1513,20 @@ Also, a list:
# :stopdoc:
# only available in RubyGems tests
- PRIVATE_KEY_PASSPHRASE = 'Foo bar'.freeze
+ PRIVATE_KEY_PASSPHRASE = "Foo bar"
begin
- PRIVATE_KEY = load_key 'private'
- PRIVATE_KEY_PATH = key_path 'private'
+ PRIVATE_KEY = load_key "private"
+ PRIVATE_KEY_PATH = key_path "private"
# ENCRYPTED_PRIVATE_KEY is PRIVATE_KEY encrypted with PRIVATE_KEY_PASSPHRASE
- ENCRYPTED_PRIVATE_KEY = load_key 'encrypted_private', PRIVATE_KEY_PASSPHRASE
- ENCRYPTED_PRIVATE_KEY_PATH = key_path 'encrypted_private'
+ ENCRYPTED_PRIVATE_KEY = load_key "encrypted_private", PRIVATE_KEY_PASSPHRASE
+ ENCRYPTED_PRIVATE_KEY_PATH = key_path "encrypted_private"
PUBLIC_KEY = PRIVATE_KEY.public_key
- PUBLIC_CERT = load_cert 'public'
- PUBLIC_CERT_PATH = cert_path 'public'
+ PUBLIC_CERT = load_cert "public"
+ PUBLIC_CERT_PATH = cert_path "public"
rescue Errno::ENOENT
PRIVATE_KEY = nil
PUBLIC_KEY = nil
@@ -1575,7 +1541,7 @@ class Object
metaclass = class << self; self; end
- if respond_to? name and not methods.map(&:to_s).include? name.to_s
+ if respond_to?(name) && !methods.map(&:to_s).include?(name.to_s)
metaclass.send :define_method, name do |*args|
super(*args)
end
@@ -1587,7 +1553,7 @@ class Object
if val_or_callable.respond_to? :call
val_or_callable.call(*args, &blk)
else
- blk.call(*block_args) if blk
+ blk&.call(*block_args)
val_or_callable
end
end
@@ -1602,4 +1568,4 @@ class Object
end unless method_defined?(:stub) # lib/resolv/test_dns.rb also has the same method definition
end
-require_relative 'utilities'
+require_relative "utilities"
diff --git a/test/rubygems/installer_test_case.rb b/test/rubygems/installer_test_case.rb
index 824ac53a82..abddcbe848 100644
--- a/test/rubygems/installer_test_case.rb
+++ b/test/rubygems/installer_test_case.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/installer'
+
+require_relative "helper"
+require "rubygems/installer"
class Gem::Installer
##
@@ -110,7 +111,7 @@ class Gem::InstallerTestCase < Gem::TestCase
def setup_base_installer(force = true)
@gem = setup_base_gem
- util_installer @spec, @gemhome, false, force
+ util_installer @spec, @gemhome, force
end
##
@@ -133,7 +134,7 @@ class Gem::InstallerTestCase < Gem::TestCase
# And returns it
def setup_base_spec
- quick_gem 'a' do |spec|
+ quick_gem "a" do |spec|
util_make_exec spec
end
end
@@ -154,7 +155,7 @@ class Gem::InstallerTestCase < Gem::TestCase
# And returns a Gem::Installer for the @user_spec that installs into Gem.user_dir
def setup_base_user_installer
- @user_spec = quick_gem 'b' do |spec|
+ @user_spec = quick_gem "b" do |spec|
util_make_exec spec
end
@@ -162,7 +163,7 @@ class Gem::InstallerTestCase < Gem::TestCase
@user_gem = @user_spec.cache_file
- util_installer @user_spec, Gem.user_dir, :user
+ Gem::Installer.at @user_gem, user_install: true
end
##
@@ -183,23 +184,23 @@ class Gem::InstallerTestCase < Gem::TestCase
# ext/a/mkrf_conf.rb
def util_setup_gem(ui = @ui, force = true)
- @spec.files << File.join('lib', 'code.rb')
- @spec.extensions << File.join('ext', 'a', 'mkrf_conf.rb')
+ @spec.files << File.join("lib", "code.rb")
+ @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')
+ FileUtils.mkdir_p "bin"
+ FileUtils.mkdir_p "lib"
+ FileUtils.mkdir_p File.join("ext", "a")
- File.open File.join('bin', 'executable'), 'w' do |f|
+ File.open File.join("bin", "executable"), "w" do |f|
f.puts "raise 'ran executable'"
end
- File.open File.join('lib', 'code.rb'), 'w' do |f|
- f.puts '1'
+ 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|
+ 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
@@ -214,18 +215,16 @@ class Gem::InstallerTestCase < Gem::TestCase
end
end
- Gem::Installer.at @gem, :force => force
+ Gem::Installer.at @gem, force: force
end
##
- # Creates an installer for +spec+ that will install into +gem_home+. If
- # +user+ is true a user-install will be performed.
+ # Creates an installer for +spec+ that will install into +gem_home+.
- def util_installer(spec, gem_home, user=false, force=true)
+ def util_installer(spec, gem_home, force=true)
Gem::Installer.at(spec.cache_file,
- :install_dir => gem_home,
- :user_install => user,
- :force => force)
+ install_dir: gem_home,
+ force: force)
end
@@symlink_supported = nil
diff --git a/test/rubygems/invalid_issuer_cert.pem b/test/rubygems/invalid_issuer_cert.pem
index ea11756bb0..5cb9d22a87 100644
--- a/test/rubygems/invalid_issuer_cert.pem
+++ b/test/rubygems/invalid_issuer_cert.pem
@@ -1,20 +1,20 @@
-----BEGIN CERTIFICATE-----
-MIIDUTCCAjmgAwIBAgIBCjANBgkqhkiG9w0BAQUFADAqMQ8wDQYDVQQDDAZub2Jv
+MIIDMDCCAhigAwIBAgIBCjANBgkqhkiG9w0BAQsFADAqMQ8wDQYDVQQDDAZub2Jv
ZHkxFzAVBgoJkiaJk/IsZAEZFgdleGFtcGxlMCAXDTEyMDEwMTAwMDAwMFoYDzk5
OTkxMjMxMjM1OTU5WjArMRAwDgYDVQQDDAdpbnZhbGlkMRcwFQYKCZImiZPyLGQB
-GRYHZXhhbXBsZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM0ycOSh
-SOKDGhDlPZ3+JAWwp7KB2ps/VlLhIsZl0uAHzCAGPNI1I46gmla1g7Gh429fYeJ0
-VgeRTxI/rRWNJ0HX2I9jhaJqAkiOqV5Rk6RkJv/0lU1VSu1IBjKRmV6qXiNeBWA8
-duEPNdd6zKX7UoKcYgmG3BMDuEy67AqWUgZOjc9WUnd6i+mwWciMuNqul69vMvB5
-go4c/rgtp1Y3PhLDIrheYP9s+Bza1MNp0FUFlrPnL5gzZTsP/IX2u7kF3CEhKCZX
-ZPX0oZc/pbqIS2OuQ9T6ft6StSwA+9IhAyCeJ9bGyBYK78SyiSfELKyGKbk74SmR
-AqjpN2PJX3o/gk8CAwEAAaN/MH0wGgYDVR0RBBMwEYEPaW52YWxpZEBleGFtcGxl
-MB0GA1UdDgQWBBST34uxqPfsv8w/+cc9gEChWnnZTjAfBgNVHSMEGDAWgBRfQ272
-mo5FJeki4303XqTVNgKFGzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIC
-BDANBgkqhkiG9w0BAQUFAAOCAQEAArzlvf6q7By19O1hSabH9jmnMwxJ7rZT8lr9
-G7gt18nQxgpeY6JczRmZ9wCWpoIE+ohHJ56XVUFsWilVIZ9o7+ASpZlxIErq3pzY
-b8SYoOZtGzz6IpucdnaZixOvqXpQQtAsat1/Y+OLaMiyGwzT2VvDkPHsqBphU2qo
-n/WwaYPTQF/yqMVM63HLm34+UwzHISChoo1ZT22S3jdWSso2KrLuRN+mfYwgGm26
-h0zRmr3SmfP8yCJhfkTcAUSR/XGLN8KOTXpjzMgsFLqTIeIbTd0e7APIh/6nBqpr
-GAudXuQMlPdcYQIT8CBZJ6b36ahb+n+1oc5C9ULaeEwEZtYyLQ==
+GRYHZXhhbXBsZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAPEZZzId
+y0m1jSbcHBwUc0MLpq/+JJdwLpGrjD35CuI7DNP0MiH+mNHblyTqMadB3font26k
+QFIjDZtc1es1Zvt4mNo1lScQsvbVGRFDQK2/xdZ0O0GbK31C7IJ2Boa93F+74f7N
+eD6LKn++SWCxHNCKV83RumQ6diG/WdUZQu8k9xjpRywI2u2EwNDETkbhGamj5zNj
+7a8pcPyifBxzTiZ9FZvWVaCEODvdIrF4NdIteXyYEQwDRLWD/nQ9Z9wbw4KQCtA/
+UUd+rObocjveau1wLiZryumhZRwwIKZU4+aaANYTFb3tbmUKnoR9aLavKvxEnlF0
+5kHo9xcHoS5ftw8CAwEAAaNeMFwwGgYDVR0RBBMwEYEPaW52YWxpZEBleGFtcGxl
+MB0GA1UdDgQWBBR17dM2zZQQPor/k6N4/JXerWXhSDAPBgNVHRMBAf8EBTADAQH/
+MA4GA1UdDwEB/wQEAwICBDANBgkqhkiG9w0BAQsFAAOCAQEALrT6pmN79vdBA80a
+f8C1DnWAYNyXskmskWPVMnTtgrDGQkqz0Uqq7nBdWK75FiBjk3XAOiDonZegvho+
+NZUnotUFyTpkkn95q1qpkMwgTufamQlxsBxkDZLPiWqvZS4guSucVgZeEtEOy0R0
+AKXA1SZmhC7472z+pwXprGj86K4SX7w15LxsQ0wDP5qduKFItNo/CnBEP5w87/Eq
+nxSbUN3dt7Glqt0iIp/I4mZlA4OnvtKfqTitATKOnBvHxIzvm9/6BVItjET8DRXv
+2ZEVvEcnkNNRKwNbqtI3V7AzB3lf3E4nb86gFh/GLI2XRN4LlWZQ4PmyE22B8IaZ
+vpqxaQ==
-----END CERTIFICATE-----
diff --git a/test/rubygems/invalid_issuer_cert_32.pem b/test/rubygems/invalid_issuer_cert_32.pem
index bb73772735..2b71179270 100644
--- a/test/rubygems/invalid_issuer_cert_32.pem
+++ b/test/rubygems/invalid_issuer_cert_32.pem
@@ -1,20 +1,20 @@
-----BEGIN CERTIFICATE-----
-MIIDTzCCAjegAwIBAgIBCzANBgkqhkiG9w0BAQUFADAqMQ8wDQYDVQQDDAZub2Jv
+MIIDLjCCAhagAwIBAgIBCzANBgkqhkiG9w0BAQsFADAqMQ8wDQYDVQQDDAZub2Jv
ZHkxFzAVBgoJkiaJk/IsZAEZFgdleGFtcGxlMB4XDTEyMDEwMTAwMDAwMFoXDTM4
MDExOTAzMTQwN1owKzEQMA4GA1UEAwwHaW52YWxpZDEXMBUGCgmSJomT8ixkARkW
-B2V4YW1wbGUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDNMnDkoUji
-gxoQ5T2d/iQFsKeygdqbP1ZS4SLGZdLgB8wgBjzSNSOOoJpWtYOxoeNvX2HidFYH
-kU8SP60VjSdB19iPY4WiagJIjqleUZOkZCb/9JVNVUrtSAYykZleql4jXgVgPHbh
-DzXXesyl+1KCnGIJhtwTA7hMuuwKllIGTo3PVlJ3eovpsFnIjLjarpevbzLweYKO
-HP64LadWNz4SwyK4XmD/bPgc2tTDadBVBZaz5y+YM2U7D/yF9ru5BdwhISgmV2T1
-9KGXP6W6iEtjrkPU+n7ekrUsAPvSIQMgnifWxsgWCu/EsoknxCyshim5O+EpkQKo
-6TdjyV96P4JPAgMBAAGjfzB9MBoGA1UdEQQTMBGBD2ludmFsaWRAZXhhbXBsZTAd
-BgNVHQ4EFgQUk9+Lsaj37L/MP/nHPYBAoVp52U4wHwYDVR0jBBgwFoAUX0Nu9pqO
-RSXpIuN9N16k1TYChRswDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAgQw
-DQYJKoZIhvcNAQEFBQADggEBAMXxi62wMgtxERL3Snu9wB+qPBY0oaZn0gxcqH8x
-IKbBa+ib63l3UX0vVqzHZlDYxBLTJicU3Cwr7Tm+GHPg/oMkqufxeFZPl/n4uvwY
-iogyY5RMsx6C3WqdhA3x+tg04xMxDnAptRWMT4n19myPEadasLBwOqHeXtpc/v2N
-XnNFlX3q8NB3AQya+Sp4fxL1fp9sCYlyJolS4dNZGOW4qC5I2GQGlduFom5oOyTB
-QyWPs+McRfanWrZgmoViu5x+N7l/xRTJ7WEa9DDqZbPxjCaXrKIyteSIJgqsdqwy
-0N+4pygu9VOdQNfQvI2jkxyDZI6rZ/YEr8sxhOKmzvaW0kc=
+B2V4YW1wbGUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDxGWcyHctJ
+tY0m3BwcFHNDC6av/iSXcC6Rq4w9+QriOwzT9DIh/pjR25ck6jGnQd36J7dupEBS
+Iw2bXNXrNWb7eJjaNZUnELL21RkRQ0Ctv8XWdDtBmyt9QuyCdgaGvdxfu+H+zXg+
+iyp/vklgsRzQilfN0bpkOnYhv1nVGULvJPcY6UcsCNrthMDQxE5G4Rmpo+czY+2v
+KXD8onwcc04mfRWb1lWghDg73SKxeDXSLXl8mBEMA0S1g/50PWfcG8OCkArQP1FH
+fqzm6HI73mrtcC4ma8rpoWUcMCCmVOPmmgDWExW97W5lCp6EfWi2ryr8RJ5RdOZB
+6PcXB6EuX7cPAgMBAAGjXjBcMBoGA1UdEQQTMBGBD2ludmFsaWRAZXhhbXBsZTAd
+BgNVHQ4EFgQUde3TNs2UED6K/5OjePyV3q1l4UgwDwYDVR0TAQH/BAUwAwEB/zAO
+BgNVHQ8BAf8EBAMCAgQwDQYJKoZIhvcNAQELBQADggEBAGolEDY9meTGpP7j3Meb
+pxtLX/JYPiTMqQR+FOOdGJlXg4V9syMBYUMmUj3yEPnpBFmDgDtBaH+OQcFuvf43
+mQYOQoTJD6OpC08fkPdVw56Em+cuUCXtDDYY4gc+nVRKk4+tJqkizHNAazqKkZoQ
+PaHaCfXsrMGPLXxh/kbk14ESU9pL0LShh/bNn68hlAKwN2ctTSlfm81QgbNX83d1
+6kLSckj/9B1ksi6ks/eHkHWeMaiJe8H3vAU6PE6NeU3WRZY1ulSGOPleYfJA99fq
+z9yks8IxwMzubJStq2sQ0n6gu3XS4Qu0sn3ih0TwRyUOSQkWa2Bf5SwUZ3/YJ25S
+Wkw=
-----END CERTIFICATE-----
diff --git a/test/rubygems/invalid_key.pem b/test/rubygems/invalid_key.pem
index 74bedabcda..bc02147403 100644
--- a/test/rubygems/invalid_key.pem
+++ b/test/rubygems/invalid_key.pem
@@ -1,27 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
-MIIEpAIBAAKCAQEAzTJw5KFI4oMaEOU9nf4kBbCnsoHamz9WUuEixmXS4AfMIAY8
-0jUjjqCaVrWDsaHjb19h4nRWB5FPEj+tFY0nQdfYj2OFomoCSI6pXlGTpGQm//SV
-TVVK7UgGMpGZXqpeI14FYDx24Q8113rMpftSgpxiCYbcEwO4TLrsCpZSBk6Nz1ZS
-d3qL6bBZyIy42q6Xr28y8HmCjhz+uC2nVjc+EsMiuF5g/2z4HNrUw2nQVQWWs+cv
-mDNlOw/8hfa7uQXcISEoJldk9fShlz+luohLY65D1Pp+3pK1LAD70iEDIJ4n1sbI
-FgrvxLKJJ8QsrIYpuTvhKZECqOk3Y8lfej+CTwIDAQABAoIBAFo5I4pjoDh4jK2B
-HmapqA0Yb6P9lLFOWBZ5B2FUxDPdOdOa6oNC+i9sTnBxv0YLeIUv20pG/My3B51u
-ghxHxEsfLQlfKRMQqZBdqfrew5w0rTE9yagHKLrMQG1bt6P4JQxH+vUloN+0YGgu
-hm005EKpoDGwKnPx3sdeKQs+rTI37fGLw40ZPSod2B7UkSna4/u/uXa1yFbONlqq
-P4ozsDd1xoCaBJfwie2h93KneSPwyHHumlVgbFAJcQycuD5qproYbea9PppppQ+4
-17M9ccuQpS2j9rZWgk7+KqwLrYqzajmtHoQH4zkBYd0JQ4ywGKg307xDhppMZpq3
-uMqnXgECgYEA9iYB7vX91Q3HsRtUAd0aZ91lDIv9RXBP+PuK3OUrtChdtZx7Mih3
-uTgtfVEnP7bxgnPpwecnF4Ncginuu7TBtxjoztFjuFNzk/8Fz/J3i/H3oB0SdjhL
-uqVa6P4hPak7FnWynZHivuuIe+eKYLvK0TCMbYaz6G81xi0Whtbm498CgYEA1Wja
-PgscP/9YykCC6eRP+ixo6chGzSNJR+WRW9CJYpXEicPlaT5AI3nSZVXXSLvXIbq9
-NoExPu47pDzr9Gd02qYmFWUOolUa21W4s/x4d7lU+wJzS6ZNTFoC8woZagL2kZ5G
-+we5ifbUz7eG+ahZODGMGA9BJVT3PI6zPdKtr5ECgYEAy0ORnypGBXUOrUMa+TsD
-fjfGJTlI2dmoQLw/7K/Wijw3PizNUxs12p74eZ7VYXkKMKbVpwjiMDmK3/YOrbTT
-rwaD4Z3p0iIftFwJCbJ5Y/hZez/mqfdNGgFIdFS/UHL6V060RAhfjTdlCqSmkcEh
-9+M2Y4+z60JCzrcW/hxiqFMCgYEAj9ntwoSatkjZAPwbQq2ze18UGQH3N6/hZaVJ
-JiqbcOijYnm52gcsFL25JLWIOG7lxMarZGIRX+oWKc8m/cf+7KOyaBmGk8XqJI7T
-wf8c9RboQYqVTRj8YcsK0eis2NjGe8HE9tFuL6FCMgHz6bWg7k/3rwAZWaC8RwWp
-rLKmgQECgYBXGjEvogVeYMgnpzjoaa99wvfp6FtbRx1jZ+FOSBoH5uCRDalD5Q16
-0UVnoPcnj0Hi7Hvvl6jTLesRW/LDra5Hqyxs4yuSBagEUFv/PvY0eYGZ5egGZgaa
-PlVmxgk33xYXar8wGHLkstwqZY/OqT89cKvJqeLKMb0G2Re13oPVww==
+MIIEowIBAAKCAQEA8RlnMh3LSbWNJtwcHBRzQwumr/4kl3AukauMPfkK4jsM0/Qy
+If6Y0duXJOoxp0Hd+ie3bqRAUiMNm1zV6zVm+3iY2jWVJxCy9tUZEUNArb/F1nQ7
+QZsrfULsgnYGhr3cX7vh/s14Posqf75JYLEc0IpXzdG6ZDp2Ib9Z1RlC7yT3GOlH
+LAja7YTA0MRORuEZqaPnM2Ptrylw/KJ8HHNOJn0Vm9ZVoIQ4O90isXg10i15fJgR
+DANEtYP+dD1n3BvDgpAK0D9RR36s5uhyO95q7XAuJmvK6aFlHDAgplTj5poA1hMV
+ve1uZQqehH1otq8q/ESeUXTmQej3FwehLl+3DwIDAQABAoIBAAQ1PSEES8XZESzH
+nwakcBCQValGW8LNi+/cmSGEb7qxbNC5jIhzBkgfYjIcPkqc3TAeXQFlhNPfgGog
+7YDh7o60Ck2WAtOVjdy+AmZ+kH9Cf271719+mFHi3E2N8XY3k8Q9+2dJlHAvA0pg
+eq0L2k9kzWcuYmeZF50Q1xNfkf9U0qkb6tbx15NOGFhQMUZ/mMcbYifW/bQnU2YO
+2vgxWFDItk0c82gpi/uo22gu0TjhcBp/ByKMgXV8xrLCW7Lsh1DvJ3LtigD0Zp5s
+XtdXcF4KOo81VeUijDbByIQQJTxBlfmgdcyarAb7kV107wvDh55Xd8m68lZUrkj5
+tc3dRf0CgYEA+crRUXgtdeiHqN5gZRg6MF6S5yxFiAaKgeeKm/x/2xpMmoiyWhFv
+tK1DLxRHEGiFuWc9IGgrWu2udEg8VE4j2EExvtFi/w3lSHxBArjeq7oCabnDk261
+lRCNzYb0HU5UZL3vBsHW8pCdnDfaOxlrT2+cDVN7LHd20DsIZROG7T0CgYEA9xdH
+wSNsHqxcB44A7iNNvHxhU3Vi6QCIpzp8sfjc/fd7Ghe/MIn67gs5XPtT+DvQME0N
+4hNEy2GmbHjVJQXqlf4VSWdFJ1RnKwL+4rnOiWq5sNrxmlXuTvOTRLimpjOsLKCR
+G3dgKXiH7/qU9zjLljKOWgo7gqv3cPrPIL8H0jsCgYEAp99SRTpK8w7O/QJWLhrW
+IGOuvoXWRNCAjUUatjI/ivRlvwVXN4i4VeiLWjx6deCI3k0vm3PmjzllIOjbAp1x
+IYjO8bqumVKxYMGAv1+W5jogHQWnFpI0nnV9lz63GGrn9Lxgw13KI0JlafNvSoCO
+ydfsPFh6UywGQXMq9SLmbtECgYAHWC3N09u23bCumM32Rh5dZ+UMsgSKoHVvYxGp
+yJfpBJ4oHGSWcMOAp9zAosfQLRb3GJM9EQ2ObgygVMchHpfmdXL0h5lKnfujD6e7
+3YICG6YBV8CusbcvqZXLCSIK9qY7fVpS0q2NDgQcYfpjjtCeWkpY6szyCWKFfS8C
+7iqxWQKBgBIwdnksccXP01svXJ0tMhiAKx1jKY/aJBPIpcSqxTFNe2WpgzynRpUg
++MKAO2Ed6Rec3TTefGRNKDPb5OUsYZUMHeNbIJ1Y1S2pORRffrE3TFWBUM0LkOTj
+r4Dl5bcnDRL93Phbx7MAmjMO3TZWbQGfEgDuqk3sS1QzKMJnBLAO
-----END RSA PRIVATE KEY-----
diff --git a/test/rubygems/invalid_signer_cert.pem b/test/rubygems/invalid_signer_cert.pem
index 7f8b5cc727..59364ee51b 100644
--- a/test/rubygems/invalid_signer_cert.pem
+++ b/test/rubygems/invalid_signer_cert.pem
@@ -1,19 +1,19 @@
-----BEGIN CERTIFICATE-----
-MIIDEDCCAfigAwIBAgIBDjANBgkqhkiG9w0BAQUFADArMRAwDgYDVQQDDAdpbnZh
+MIIDEDCCAfigAwIBAgIBDjANBgkqhkiG9w0BAQsFADArMRAwDgYDVQQDDAdpbnZh
bGlkMRcwFQYKCZImiZPyLGQBGRYHZXhhbXBsZTAgFw0xMjAxMDEwMDAwMDBaGA85
OTk5MTIzMTIzNTk1OVowKzEQMA4GA1UEAwwHaW52YWxpZDEXMBUGCgmSJomT8ixk
-ARkWB2V4YW1wbGUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDNMnDk
-oUjigxoQ5T2d/iQFsKeygdqbP1ZS4SLGZdLgB8wgBjzSNSOOoJpWtYOxoeNvX2Hi
-dFYHkU8SP60VjSdB19iPY4WiagJIjqleUZOkZCb/9JVNVUrtSAYykZleql4jXgVg
-PHbhDzXXesyl+1KCnGIJhtwTA7hMuuwKllIGTo3PVlJ3eovpsFnIjLjarpevbzLw
-eYKOHP64LadWNz4SwyK4XmD/bPgc2tTDadBVBZaz5y+YM2U7D/yF9ru5BdwhISgm
-V2T19KGXP6W6iEtjrkPU+n7ekrUsAPvSIQMgnifWxsgWCu/EsoknxCyshim5O+Ep
-kQKo6TdjyV96P4JPAgMBAAGjPTA7MBoGA1UdEQQTMBGBD2ludmFsaWRAZXhhbXBs
-ZTAdBgNVHQ4EFgQUk9+Lsaj37L/MP/nHPYBAoVp52U4wDQYJKoZIhvcNAQEFBQAD
-ggEBAGJurQiRw3Vb2LPUhoL9BHyPy8TY+ZXz7eZyzf72saiATkHTuainb9jvLTzf
-9ZNYNnjxGNwR4QnDhlh8Vb8vHaYfQGGwiLhd5ZbKjkid/41Y9XmNh+oHCrmwGcS6
-vX4QmTTmPQRBZ2Ilckr+wb1fdpLYk0wW/JFMFdAzp1OO3kP23hYElqia6qeJGw4k
-4fe9d56huHHptSJrlMTjHwaqXq6QRjfjF5Za1unCjxQMO2vNQC/dUYRaq/M0kwFN
-6A2xHKukkgA9cyjVpFVpxhE3/iFz8OE1GZg7VVcT+Jzhhxaajubpe+ZtDN5rbln/
-NI4WP/ZM3cnxVrHG84G3AYRpkhc=
+ARkWB2V4YW1wbGUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDxGWcy
+HctJtY0m3BwcFHNDC6av/iSXcC6Rq4w9+QriOwzT9DIh/pjR25ck6jGnQd36J7du
+pEBSIw2bXNXrNWb7eJjaNZUnELL21RkRQ0Ctv8XWdDtBmyt9QuyCdgaGvdxfu+H+
+zXg+iyp/vklgsRzQilfN0bpkOnYhv1nVGULvJPcY6UcsCNrthMDQxE5G4Rmpo+cz
+Y+2vKXD8onwcc04mfRWb1lWghDg73SKxeDXSLXl8mBEMA0S1g/50PWfcG8OCkArQ
+P1FHfqzm6HI73mrtcC4ma8rpoWUcMCCmVOPmmgDWExW97W5lCp6EfWi2ryr8RJ5R
+dOZB6PcXB6EuX7cPAgMBAAGjPTA7MBoGA1UdEQQTMBGBD2ludmFsaWRAZXhhbXBs
+ZTAdBgNVHQ4EFgQUde3TNs2UED6K/5OjePyV3q1l4UgwDQYJKoZIhvcNAQELBQAD
+ggEBACbQA7m+zqdAE1/GrJKcXnC/Ujr1tu6rGpe0uExTwySptgVieUGAOvzlLLrY
+r2b/nGmK4bgHkeDPSVuC3F8NhgESvPTuXFSw+DU+1m+mhHxdpW30uSbbebgqV5Ea
+GpckCZj1SEdsn/1SDauXCmkrs/MBuK49mYXv3jejX0Rp0STu1NxnU13yrKF0MtrL
+fzZ/QF8bOZdg5DwtqMwhDPp72x58KpqAPN9GgdlsTiwOMGy4avds1g5KMGmkK8pK
+6I58NEMCOuN4CxFK4oWD9xuD4j+wtHy/UYxqor4rn+UKYHfr5fWtAyRJ3gD8vMUu
+C+Nl2vB8t4OVwS5FCcn0ZK18bPU=
-----END CERTIFICATE-----
diff --git a/test/rubygems/invalid_signer_cert_32.pem b/test/rubygems/invalid_signer_cert_32.pem
index 657608e503..97feb8fd0a 100644
--- a/test/rubygems/invalid_signer_cert_32.pem
+++ b/test/rubygems/invalid_signer_cert_32.pem
@@ -1,19 +1,19 @@
-----BEGIN CERTIFICATE-----
-MIIDDjCCAfagAwIBAgIBDzANBgkqhkiG9w0BAQUFADArMRAwDgYDVQQDDAdpbnZh
+MIIDDjCCAfagAwIBAgIBDzANBgkqhkiG9w0BAQsFADArMRAwDgYDVQQDDAdpbnZh
bGlkMRcwFQYKCZImiZPyLGQBGRYHZXhhbXBsZTAeFw0xMjAxMDEwMDAwMDBaFw0z
ODAxMTkwMzE0MDdaMCsxEDAOBgNVBAMMB2ludmFsaWQxFzAVBgoJkiaJk/IsZAEZ
-FgdleGFtcGxlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzTJw5KFI
-4oMaEOU9nf4kBbCnsoHamz9WUuEixmXS4AfMIAY80jUjjqCaVrWDsaHjb19h4nRW
-B5FPEj+tFY0nQdfYj2OFomoCSI6pXlGTpGQm//SVTVVK7UgGMpGZXqpeI14FYDx2
-4Q8113rMpftSgpxiCYbcEwO4TLrsCpZSBk6Nz1ZSd3qL6bBZyIy42q6Xr28y8HmC
-jhz+uC2nVjc+EsMiuF5g/2z4HNrUw2nQVQWWs+cvmDNlOw/8hfa7uQXcISEoJldk
-9fShlz+luohLY65D1Pp+3pK1LAD70iEDIJ4n1sbIFgrvxLKJJ8QsrIYpuTvhKZEC
-qOk3Y8lfej+CTwIDAQABoz0wOzAaBgNVHREEEzARgQ9pbnZhbGlkQGV4YW1wbGUw
-HQYDVR0OBBYEFJPfi7Go9+y/zD/5xz2AQKFaedlOMA0GCSqGSIb3DQEBBQUAA4IB
-AQA6WW6YyykIJmVFW8Og1R3d8fbFtQarDMGN+oZrCN3Eb9Twoy36Yr/h0bZgkCEe
-arB+VCD1DfEii5luZowUDr/BlIjIR2cNIMFpmQ8ZLIpVWQz/BYHrbw7CHO5df3mg
-HYTKlEoUMimOEWvCYnSgzKWCgSWU/jBQQ0bcUBk2HHpdT4BnLPe/7rs+TZmwd/Dz
-r80sNXQ6vqTkQS+te2hqyh62r+WeaFx7aqnFjGtwiOqMmYPr80uYOy/rX26mmfwm
-vyf8JlA4uTt795Krsc4Brc+BO0bOPfDDGhRs/2tvyHhOOqBbUxQeeV5ogiAZmA31
-ZrzbFysajMrWZ+1GV8QXOcBi
+FgdleGFtcGxlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8RlnMh3L
+SbWNJtwcHBRzQwumr/4kl3AukauMPfkK4jsM0/QyIf6Y0duXJOoxp0Hd+ie3bqRA
+UiMNm1zV6zVm+3iY2jWVJxCy9tUZEUNArb/F1nQ7QZsrfULsgnYGhr3cX7vh/s14
+Posqf75JYLEc0IpXzdG6ZDp2Ib9Z1RlC7yT3GOlHLAja7YTA0MRORuEZqaPnM2Pt
+rylw/KJ8HHNOJn0Vm9ZVoIQ4O90isXg10i15fJgRDANEtYP+dD1n3BvDgpAK0D9R
+R36s5uhyO95q7XAuJmvK6aFlHDAgplTj5poA1hMVve1uZQqehH1otq8q/ESeUXTm
+Qej3FwehLl+3DwIDAQABoz0wOzAaBgNVHREEEzARgQ9pbnZhbGlkQGV4YW1wbGUw
+HQYDVR0OBBYEFHXt0zbNlBA+iv+To3j8ld6tZeFIMA0GCSqGSIb3DQEBCwUAA4IB
+AQBM/EjV791vKu2KQQAhd03eUXfMlvObwEj9nGtEEnSFH5i16V1m8Y5ZY7Aw+VR5
+/xJ9J2AvFG6EXclDVmkDQpo1fUVhWM/SPKD6HJWuB/eyjA30xSj+UeLmBYjdKzHt
+kK+HeEaGVQaT5j8OPOW6meGriucdBWtwbhTdyZgqvwpuZwbtPpElYXwGgSijKqHI
+GG6RWzeANdG/4AIChrp8CIgFfW4sbmlIZK3BAXuSvZ9A/deYqC2DAadJIoTJ9H6w
+0TgYlyTidaWtCkqRBXc3qrwpc/r3wJwpgan0kJAQ2kGc5W7gYUylpoS56sFq23YX
+Fmm0pRq5UZj9jKZUIwcqAoGo
-----END CERTIFICATE-----
diff --git a/test/rubygems/invalidchild_cert.pem b/test/rubygems/invalidchild_cert.pem
index 936dc650c9..281dcce655 100644
--- a/test/rubygems/invalidchild_cert.pem
+++ b/test/rubygems/invalidchild_cert.pem
@@ -1,20 +1,19 @@
-----BEGIN CERTIFICATE-----
-MIIDOTCCAiGgAwIBAgIBEDANBgkqhkiG9w0BAQUFADApMQ4wDAYDVQQDDAVjaGls
+MIIDGDCCAgCgAwIBAgIBEDANBgkqhkiG9w0BAQsFADApMQ4wDAYDVQQDDAVjaGls
ZDEXMBUGCgmSJomT8ixkARkWB2V4YW1wbGUwIBcNMTIwMTAxMDAwMDAwWhgPOTk5
OTEyMzEyMzU5NTlaMDAxFTATBgNVBAMMDGludmFsaWRjaGlsZDEXMBUGCgmSJomT
-8ixkARkWB2V4YW1wbGUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDl
-rDAlDZwmP6Zxc4sSaOdSRRXJBmbQubxmWpqU8bXrTKCkvg1l/2U6weJIS52zW6Te
-Zok7Uus5jywyeNSJ/MBHb7X5ytAPQsvLu/3WFwaVfHJzimQI4vtmx9+CDgZzipYp
-ett7IF18He8DPiFur1xCn8pp0qOOV8mXL/8TpUgJfmaOJosqgFqorj5niqF52IwJ
-vtur/gwpq2xpCtYaCUB/dFzzefLV37kt58S6jTmZnYf4kIdFKhhyTeGmDRf/wOz+
-kK/H/aKtpsYgzI//bo+bsuWNFceIdWrdCBr63cVs4ql7VN7p2xfn9ckEfwH6wFut
-QLquA/6fRkgUFF8fxUiHAgMBAAGjYzBhMB8GA1UdEQQYMBaBFGludmFsaWRjaGls
-ZEBleGFtcGxlMB0GA1UdDgQWBBSwAwFqdxjicsovAzZ1ZeSAWlnKcDAfBgNVHSME
-GDAWgBR81VPTe7JJSgT6xxJcaGd9hYOuCDANBgkqhkiG9w0BAQUFAAOCAQEAYxom
-7nHgbfqLiMtVwx8D6LM6P3sk3p5HwoHJU0zzFVfPA0iuhhC2vWyPoHJroq6d31DG
-DpPpOeVQxTYyQ6CtD6jGUpE+0MjmRoavFnvqFH5lf4OKO0dQ8xUa9fALo7fmK0v0
-ueDlgsHw3mwoVNX2Xu/+jCTuiK2KGG3J+pxr6JNA1++gQEghFFJjM8rw1/mYrDW0
-CSCyx/LeNyYbt9xzeVgo83XNO5TCfwwh8+df52I6Hj5BDFhhkP8KOai4ejq2CmZ8
-by9ylCUXc/aiz9mzX/NzIAYLuRzkmrI+lxDbUJpG/hV7MCS/TZegjD+SUSu9EI1O
-RVerg89R7kQUWZyJqg==
+8ixkARkWB2V4YW1wbGUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDs
+dqLesclj2/6HnJLw4al4swiDFBA4W0KeOS3DXOa2k5+rNfGacKOQ/AkciUnzqLiC
+9D49x/YLlnlJYeSMG57C7gixhLHHDviCneQwy8TlCpuhUXnfcpmHQO+X/c+lrVB7
+wHTPjl5yZYzLFtPa8QAEtJa83E2GrUd+JEOwTRErOcBucIRP5HbeR2aD7BVP1V+F
+gaUhOZb/n2e53diQF7BZurB45DTWQ2L1R/m8VldQiWoTZluWqnCGeEwtpZJXt9kU
+8y5rQcxI3p8Qx4q0ilLKsE7c/sw2wzEFWoZ4BeURnjxdvPgYeOPk4K3a34pFg7lZ
+u1s9XvjChJVsD8HRnbQtAgMBAAGjQjBAMB8GA1UdEQQYMBaBFGludmFsaWRjaGls
+ZEBleGFtcGxlMB0GA1UdDgQWBBS3tDKiI1oVuEkKtGux8TsEy/8iuDANBgkqhkiG
+9w0BAQsFAAOCAQEAQsgdq4NZBnQRk+eNbwS4go3S+m5cPPWY7kG94kpQ3aC3nwR4
+wnICb/hd+kRCB2azTTBY8PA0SkHxIXWgRFjdEpIAekm3Xtag+lCC1q7jtDTNoHw4
+KOdfeBEF621FHL5vBvJmnRMH8f4sCjVZZE8RJcaWAK7uJJXi6gzUm3xz0UnylZNr
+vA+Z+cM5pFnCfxxqXUyT0MRb47O/wqH4f5SybKpOxO3+vnzpSeN++zgdMVjA/Pl0
+0SB8VKNKXGLQrvY2S3GuRoh7OD1DhRPzUTQ8gwwBAlhw2i3i5t9ib0ujw9MUO3GR
+dqn4Yco98R0+wFpY8feGhr5uJNDuIC10l5LHLQ==
-----END CERTIFICATE-----
diff --git a/test/rubygems/invalidchild_cert_32.pem b/test/rubygems/invalidchild_cert_32.pem
index 07687eb156..87885157f8 100644
--- a/test/rubygems/invalidchild_cert_32.pem
+++ b/test/rubygems/invalidchild_cert_32.pem
@@ -1,20 +1,19 @@
-----BEGIN CERTIFICATE-----
-MIIDNzCCAh+gAwIBAgIBETANBgkqhkiG9w0BAQUFADApMQ4wDAYDVQQDDAVjaGls
+MIIDFjCCAf6gAwIBAgIBETANBgkqhkiG9w0BAQsFADApMQ4wDAYDVQQDDAVjaGls
ZDEXMBUGCgmSJomT8ixkARkWB2V4YW1wbGUwHhcNMTIwMTAxMDAwMDAwWhcNMzgw
MTE5MDMxNDA3WjAwMRUwEwYDVQQDDAxpbnZhbGlkY2hpbGQxFzAVBgoJkiaJk/Is
-ZAEZFgdleGFtcGxlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5aww
-JQ2cJj+mcXOLEmjnUkUVyQZm0Lm8ZlqalPG160ygpL4NZf9lOsHiSEuds1uk3maJ
-O1LrOY8sMnjUifzAR2+1+crQD0LLy7v91hcGlXxyc4pkCOL7Zsffgg4Gc4qWKXrb
-eyBdfB3vAz4hbq9cQp/KadKjjlfJly//E6VICX5mjiaLKoBaqK4+Z4qhediMCb7b
-q/4MKatsaQrWGglAf3Rc83ny1d+5LefEuo05mZ2H+JCHRSoYck3hpg0X/8Ds/pCv
-x/2irabGIMyP/26Pm7LljRXHiHVq3Qga+t3FbOKpe1Te6dsX5/XJBH8B+sBbrUC6
-rgP+n0ZIFBRfH8VIhwIDAQABo2MwYTAfBgNVHREEGDAWgRRpbnZhbGlkY2hpbGRA
-ZXhhbXBsZTAdBgNVHQ4EFgQUsAMBancY4nLKLwM2dWXkgFpZynAwHwYDVR0jBBgw
-FoAUfNVT03uySUoE+scSXGhnfYWDrggwDQYJKoZIhvcNAQEFBQADggEBAGK07MzH
-/TJftVEgrghvEHIna0gadQUbWfrpMWxt/Vj7jsd4LvRaZEOWObMRxhtjMvMA2q3A
-qKXoP1KddPkFGfAVdUsNKTKLsaMvDceZ7aN3SGEWv5IYGXtfjUEVhWj7CmpS05li
-Phw9uPQVUwkkY20G2UGInRzxCYqyeW5KZIaep49KebaXCrjrV5Xy13UxgtpbmNMj
-yKPvyA5u0J8TK4gQmx1Az0gujpT1KSwfMyEDrsbIqYDVMp4kF2yLlsrdmNT9Jhwj
-R+M6AMhNqpLrjsklqE6TX2pCQGo+JFxCDOKQmvv5B7AhH0od46Jlwk//aIAheQQK
-4rhDHEHYLCxGhrw=
+ZAEZFgdleGFtcGxlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7Hai
+3rHJY9v+h5yS8OGpeLMIgxQQOFtCnjktw1zmtpOfqzXxmnCjkPwJHIlJ86i4gvQ+
+Pcf2C5Z5SWHkjBuewu4IsYSxxw74gp3kMMvE5QqboVF533KZh0Dvl/3Ppa1Qe8B0
+z45ecmWMyxbT2vEABLSWvNxNhq1HfiRDsE0RKznAbnCET+R23kdmg+wVT9VfhYGl
+ITmW/59nud3YkBewWbqweOQ01kNi9Uf5vFZXUIlqE2ZblqpwhnhMLaWSV7fZFPMu
+a0HMSN6fEMeKtIpSyrBO3P7MNsMxBVqGeAXlEZ48Xbz4GHjj5OCt2t+KRYO5Wbtb
+PV74woSVbA/B0Z20LQIDAQABo0IwQDAfBgNVHREEGDAWgRRpbnZhbGlkY2hpbGRA
+ZXhhbXBsZTAdBgNVHQ4EFgQUt7QyoiNaFbhJCrRrsfE7BMv/IrgwDQYJKoZIhvcN
+AQELBQADggEBAFPyjOoghY6Iba9+psCWC//rwLtDfZPQ3kO9hFtd4CGvalPtR103
+Oc1Dk5pxHSWDTdeQfOb75mqWuqs4ET7IUyw8yY+bKkOOhY1ldwaJhTyP/fkElnrL
+prsLSpB3AdQceS1Ob2wpMaaGIPDzJlW0LG8cQNeU3SRTTdBjX5zjG6imHKG2yuJd
+76PM0tl8ooslPABlYSPSLpd1PAARqxG2ekfrxZioCLknyhBtcRsl1aMWWBiG4BH9
+xZoJvEHwpOMTxMaAFXSkyMjZAoOzAn9qP6eLbwwzeuckIrZXxYBfGcC29VOPPAN4
+IPX0IUZ7/LlzzOE5iuVS/RIBRcD+qpEzSXs=
-----END CERTIFICATE-----
diff --git a/test/rubygems/invalidchild_key.pem b/test/rubygems/invalidchild_key.pem
index 9706c9566e..1c9997150d 100644
--- a/test/rubygems/invalidchild_key.pem
+++ b/test/rubygems/invalidchild_key.pem
@@ -1,27 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
-MIIEpgIBAAKCAQEA5awwJQ2cJj+mcXOLEmjnUkUVyQZm0Lm8ZlqalPG160ygpL4N
-Zf9lOsHiSEuds1uk3maJO1LrOY8sMnjUifzAR2+1+crQD0LLy7v91hcGlXxyc4pk
-COL7Zsffgg4Gc4qWKXrbeyBdfB3vAz4hbq9cQp/KadKjjlfJly//E6VICX5mjiaL
-KoBaqK4+Z4qhediMCb7bq/4MKatsaQrWGglAf3Rc83ny1d+5LefEuo05mZ2H+JCH
-RSoYck3hpg0X/8Ds/pCvx/2irabGIMyP/26Pm7LljRXHiHVq3Qga+t3FbOKpe1Te
-6dsX5/XJBH8B+sBbrUC6rgP+n0ZIFBRfH8VIhwIDAQABAoIBAQC59hllZwev0Ims
-AqnwVhA2hMmG4zAMgNcS6PmQ78Ukp/7KZTfkBk6orKPTdaZSuzla+hrTdegPyuU2
-WK9+qq/lJ4ZootakBKmOZMC6wBoMn57r/nnQ2DhGmD9YxpJiqyu6mkdsAmCvRm1o
-ar4XKNXC/C6gUHUto9cOG0alWYZiZ/VMe/nhPTChr2Dhd+bavO1yx7/CxB+VQMfQ
-l6ihbv//3KgPJAElbaI7jfOGzX6KlwXSGf70REmZQnPGN4/n46/dLFFuA1HzcA5Z
-37NU1zgN2nIrXld8rsR1mSy6EwU46sW3AkEwv6SUajCjz7PCmmWxRaQErGJjZrUq
-sujNj5RBAoGBAPgdiY+6B7WvmLlCBCwI4PXjgRQ/6A1Ycgvi1LdSQzccSHddogNI
-tWKa0pIrYyH7y7jB/UzstFSnsOXAf4H6Xt70VUrFPq1/dRRw1CtSLA1sFspBAD8v
-aGl9R0XqWOk1t60mfgES9b4LJu46cTm7UMfyC7EbWkqHYWqf15umRgwrAoGBAOz4
-nZGqBVBW/ERDs+Imf9NcwDeuwllQ0S9ZBPHF///SQ4Rscz2Bl8GhjhTHldLNJg9k
-HjP8W2BOPas66K3WM+WC3AiGrdJfs6Ju3r27X4wA0hnNc6bcoRaoSNRaqThSkgCH
-l34l7yrB1gwpa5HlIfYXjHfJ7coX7WRMQK7wmVsVAoGBAJ/Y97z/DuSAgpYn7+Qm
-vDfuIETZfzjJ2H/L3VtVxjQFJrKwQiZ3e1RRhoPhK/bC79bSM8yRWwSHHLKIOB2X
-HfPp2eFX/i9sxBMtNaPLRtJG5s/a3LvYYR5FNdvXRPzKPNFy0Q8EFgofyS8Fu9iD
-02FdkSbDBoKpgZtd61w93TcNAoGBAKtM4SKeRC8aYku6oTtW10pkHvNhmk5UVJMk
-h6V6mx9D0NjWSMvqdVhcv8eXq19yOxQfLJIp16gbhwrTj8WyNVuwp/xl1xtfYQyH
-lu6Sl3QuV7KdSQATN0OYrOUNEIyNa8uEOOfQ5j4DVwb9niwd9dnelgU17HYNq+a4
-FH4hoMotAoGBAJk/9+RPAdxqJsr/oVp9E4wU9ffpZ2Lr0faN7/WqBFPPhhFOMWu2
-zj8fcRaP/9Wv9g2xK/GfCKhrX8FMfq/NMkZsNx6V3W0M8Zbarp9ZvA4Sj0OvsZAO
-J1NQjkvFjMCE0A29jtjY1zRmLzoC+Ds7Ola8IOKvAN8SM1X/CC6bOgGz
+MIIEowIBAAKCAQEA7Hai3rHJY9v+h5yS8OGpeLMIgxQQOFtCnjktw1zmtpOfqzXx
+mnCjkPwJHIlJ86i4gvQ+Pcf2C5Z5SWHkjBuewu4IsYSxxw74gp3kMMvE5QqboVF5
+33KZh0Dvl/3Ppa1Qe8B0z45ecmWMyxbT2vEABLSWvNxNhq1HfiRDsE0RKznAbnCE
+T+R23kdmg+wVT9VfhYGlITmW/59nud3YkBewWbqweOQ01kNi9Uf5vFZXUIlqE2Zb
+lqpwhnhMLaWSV7fZFPMua0HMSN6fEMeKtIpSyrBO3P7MNsMxBVqGeAXlEZ48Xbz4
+GHjj5OCt2t+KRYO5WbtbPV74woSVbA/B0Z20LQIDAQABAoIBAF/yuZ60NDwVWb/s
+LAGbB3mm58bMPtKnUS5DlEqn6SPfXdQKhPj+SJh9dDMEkCHS7d+RPKoz96X3DkrU
+8nhZgr+k95kUd1CGxha1+5BDNqcbeU/pcBLXfO2RT0b0oauf2j8EtkE8Cx3PD+Se
+ZCN8U94U6u9CUyDZMd/A1kh01Qkc08mCJQ0UtPbt5iRFp9nGQaN3ZOXG6taPQVOB
+M91DUUPKny74ptMrqlyRRBylTpUlSjsjo3T5LRNSVXMNubfNG2+sf1Vn/Os/3KAL
+PTqc9LLNaHpR/z/oFC/wUiMdJzHB1vBFUcwHvTmahVfqwaffqLj/zJa12ztMcZ/W
+efRFBb8CgYEA9c6JvqB0gR14Q6Shj7Yg6JM/dO3e8yllvGRsJm0S6IHHlblWeUEA
+OeY099wD0y0oK56XvgfZyd2k+hK/FKf5/otgCyzr1i64sx+hpHE6MZ/s08VLYZvt
++N9fdk7Z5crZImo8vne+7AfBhY1UNk6QjwSUMe8U/zQ6BBGbNhKtgCcCgYEA9kTo
+6xyt836PGSXFSnup3wdjlbpMlXMnvZG2V0Aw3ILdTg2iGGf37UUBzDjnZFxVRPqm
+PqHJwzjd8PZesDFvaZQ1Sn4nRLKZj0aLLOGuaUOoTAP04fQkYltWR+j8w+d4JxX6
+CDNbNtf4EYRVhfNO02WCNyE4xHya7s6u4tnySYsCgYBNlRPay/AZtIB58SNhJZ37
+akZUFKQS4ZUPwi50bmbSZevlsOq/OKnmnGdJd/LpG06bfeHtA7NUyJVCrNoMnfwE
+wF7fCB2jq3l2Z9xv96DjetOX/6SMOVgB/ha2U6rooX6pIxjrEQZ8nvIQwgu7XE66
+JTrVC933srdBA4GWrox+bwKBgQCRZLWuuUvpyfpp+ma0RrZPumkM6OR2B3qa7QAe
+GwO97HUDtADTL+6r4mXhUGcsVWbyRpkHuTUJUPWXYZ0doNIKHzonNLuyT09hy2A3
+qzXxZ8RgvKVDEYS5nPsfkWpJrsq9KLhpRwi/JFqM3PgxESiknfV23uJI/tfpzZRq
+0gm9aQKBgBuxr0xIXZpUuXwOnLIyp0qTPltXPentl71qV3tQvkqlBU+nCKnaa0ur
+7PuEGuFC0jiPiBuRbcO81kq9QTPX6poEYSEFhHphuj9o5/G8MqnC9GzHqVwjc+fI
+JPiixH1Dx9YWsCbnCw72lEdpnxMgk1efnzbV00tl63JgMjkyHBJz
-----END RSA PRIVATE KEY-----
diff --git a/test/rubygems/mock_gem_ui.rb b/test/rubygems/mock_gem_ui.rb
new file mode 100644
index 0000000000..1ece78fde7
--- /dev/null
+++ b/test/rubygems/mock_gem_ui.rb
@@ -0,0 +1,86 @@
+# frozen_string_literal: true
+
+require "rubygems/user_interaction"
+
+##
+# This Gem::StreamUI subclass records input and output to StringIO for
+# retrieval during tests.
+
+class Gem::MockGemUi < Gem::StreamUI
+ ##
+ # Raised when you haven't provided enough input to your MockGemUi
+
+ class InputEOFError < RuntimeError
+ def initialize(question)
+ super "Out of input for MockGemUi on #{question.inspect}"
+ end
+ end
+
+ class TermError < RuntimeError
+ attr_reader :exit_code
+
+ def initialize(exit_code)
+ super
+ @exit_code = exit_code
+ end
+ end
+
+ class SystemExitException < RuntimeError; end
+
+ module TTY
+ attr_accessor :tty
+
+ def tty?
+ @tty = true unless defined?(@tty)
+ @tty
+ end
+
+ def noecho
+ yield self
+ end
+ end
+
+ def initialize(input = "")
+ require "stringio"
+ ins = StringIO.new input
+ outs = StringIO.new
+ errs = StringIO.new
+
+ ins.extend TTY
+ outs.extend TTY
+ errs.extend TTY
+
+ super ins, outs, errs, true
+
+ @terminated = false
+ end
+
+ def ask(question)
+ raise InputEOFError, question if @ins.eof?
+
+ super
+ 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, status if status != 0
+ raise SystemExitException
+ end
+end
diff --git a/test/rubygems/multifactor_auth_utilities.rb b/test/rubygems/multifactor_auth_utilities.rb
new file mode 100644
index 0000000000..1133131a76
--- /dev/null
+++ b/test/rubygems/multifactor_auth_utilities.rb
@@ -0,0 +1,111 @@
+# frozen_string_literal: true
+
+##
+# A MultifactorAuthFetcher is a FakeFetcher that adds paths to data for requests related to
+# multi-factor authentication.
+#
+
+require_relative "utilities"
+require "json"
+
+class Gem::MultifactorAuthFetcher < Gem::FakeFetcher
+ attr_reader :host, :webauthn_url
+
+ # GET /api/v1/webauthn_verification defaults to user does not have any security devices
+ def initialize(host: nil)
+ super()
+ @host = host || Gem.host
+ @path_token = "odow34b93t6aPCdY"
+ @webauthn_url = "#{@host}/webauthn_verification/#{@path_token}"
+ @data["#{@host}/api/v1/webauthn_verification"] = Gem::HTTPResponseFactory.create(
+ body: "You don't have any security devices",
+ code: 422,
+ msg: "Unprocessable Entity"
+ )
+ end
+
+ # given a url, return a response that requires multifactor authentication
+ def respond_with_require_otp(url, success_body)
+ response_fail = "You have enabled multifactor authentication"
+
+ @data[url] = proc do
+ @call_count ||= 0
+ if (@call_count += 1).odd?
+ Gem::HTTPResponseFactory.create(body: response_fail, code: 401, msg: "Unauthorized")
+ else
+ Gem::HTTPResponseFactory.create(body: success_body, code: 200, msg: "OK")
+ end
+ end
+ end
+
+ # GET /api/v1/webauthn_verification returns a webauthn url
+ # GET /api/v1/webauthn_verification/:token/status.json (polling url) returns pending status
+ def respond_with_webauthn_url
+ @data["#{@host}/api/v1/webauthn_verification"] = Gem::HTTPResponseFactory.create(body: @webauthn_url, code: 200, msg: "OK")
+ @data["#{@host}/api/v1/webauthn_verification/#{@path_token}/status.json"] = Gem::HTTPResponseFactory.create(
+ body: { status: "pending", message: "Security device authentication is still pending." }.to_json,
+ code: 200,
+ msg: "OK"
+ )
+ end
+
+ # GET /api/v1/webauthn_verification/:token/status.json returns success status with OTP code
+ def respond_with_webauthn_polling(code)
+ @data["#{@host}/api/v1/webauthn_verification/#{@path_token}/status.json"] = Gem::HTTPResponseFactory.create(
+ body: { status: "success", code: code }.to_json,
+ code: 200,
+ msg: "OK"
+ )
+ end
+
+ # GET /api/v1/webauthn_verification/:token/status.json returns expired status
+ def respond_with_webauthn_polling_failure
+ @data["#{@host}/api/v1/webauthn_verification/#{@path_token}/status.json"] = Gem::HTTPResponseFactory.create(
+ body: {
+ status: "expired",
+ message: "The token in the link you used has either expired or been used already.",
+ }.to_json,
+ code: 200,
+ msg: "OK"
+ )
+ end
+
+ def webauthn_url_with_port(port)
+ "#{@webauthn_url}?port=#{port}"
+ end
+end
+
+##
+# The MockTCPServer for use in tests or to avoid real TCPServer instances to be created
+# when testing code related to the WebAuthn listener.
+#
+# Example:
+#
+# server = Gem::MockTCPServer
+# port = server.addr[1].to_s
+#
+# # this mocks waiting for a request by calling sleep
+# server.accept
+#
+# # this mocks the server closing
+# server.close
+
+class Gem::MockTCPServer
+ attr_reader :port
+
+ def initialize(port = 5678)
+ @port = port
+ end
+
+ def close
+ true
+ end
+
+ def addr
+ ["AF_INET6", @port, "::", "::"]
+ end
+
+ def accept
+ sleep
+ end
+end
diff --git a/test/rubygems/package/tar_test_case.rb b/test/rubygems/package/tar_test_case.rb
index 99f503a23f..e3d812bf3f 100644
--- a/test/rubygems/package/tar_test_case.rb
+++ b/test/rubygems/package/tar_test_case.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
-require_relative '../helper'
-require 'rubygems/package'
+
+require_relative "../helper"
+require "rubygems/package"
##
# A test case for Gem::Package::Tar* classes
@@ -67,7 +68,7 @@ class Gem::Package::TarTestCase < Gem::TestCase
end
def calc_checksum(header)
- sum = header.unpack("C*").inject{|s,a| s + a }
+ sum = header.sum(0)
SP(Z(to_oct(sum, 6)))
end
@@ -90,43 +91,52 @@ class Gem::Package::TarTestCase < Gem::TestCase
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)
+ ASCIIZ(dname, 155), # char prefix[155]; ASCII + (Z unless filled)
]
h = arr.join
- ret = h + "\0" * (512 - h.size)
+ ret = ASCIIZ(h, 512)
assert_equal(512, ret.size)
ret
end
- def tar_dir_header(name, prefix, mode, mtime)
- h = header("5", name, prefix, 0, mode, mtime)
+ def header_with_checksum(type, fname, dname, length, mode, mtime, linkname = "")
+ h = header(type, fname, dname, length, mode, mtime, nil, linkname)
checksum = calc_checksum(h)
- header("5", name, prefix, 0, mode, mtime, checksum)
+ header(type, fname, dname, length, mode, mtime, checksum, linkname)
+ end
+
+ def tar_dir_header(name, prefix, mode, mtime)
+ header_with_checksum("5", name, prefix, 0, mode, mtime)
end
def tar_file_header(fname, dname, mode, length, mtime)
- h = header("0", fname, dname, length, mode, mtime)
- checksum = calc_checksum(h)
- header("0", fname, dname, length, mode, mtime, checksum)
+ header_with_checksum("0", fname, dname, length, mode, mtime)
end
- def tar_symlink_header(fname, prefix, mode, mtime, linkname)
- h = header("2", fname, prefix, 0, mode, mtime, nil, linkname)
- checksum = calc_checksum(h)
- header("2", fname, prefix, 0, mode, mtime, checksum, linkname)
+ def tar_symlink_header(fname, dname, mode, mtime, linkname)
+ header_with_checksum("2", fname, dname, 0, mode, mtime, linkname)
+ end
+
+ def tar_file_contents(content)
+ pad = (512 - (content.size % 512)) % 512
+ content + "\0" * pad
end
def to_oct(n, pad_size)
- "%0#{pad_size}o" % n
+ format("%0#{pad_size}o", n)
end
def util_entry(tar)
- io = TempIO.new tar
+ io = tar.respond_to?(:read) ? tar : TempIO.new(tar)
header = Gem::Package::TarHeader.from io
- Gem::Package::TarReader::Entry.new header, io
+ Gem::Package::TarReader::Entry.open header, io
+ end
+
+ def close_util_entry(entry)
+ entry.instance_variable_get(:@io).close!
end
def util_dir_entry
@@ -136,4 +146,30 @@ class Gem::Package::TarTestCase < Gem::TestCase
def util_symlink_entry
util_entry tar_symlink_header("foo", "bar", 0, Time.now, "link")
end
+
+ def util_tar(&block)
+ tar_io = StringIO.new
+ Gem::Package::TarWriter.new(tar_io, &block)
+ tar_io.rewind
+ tar_io
+ end
+
+ def util_tar_gz(&block)
+ tar_io = util_tar(&block)
+ StringIO.new util_gzip(tar_io.string)
+ end
+
+ def util_gem_data_tar(spec = nil, &block)
+ data_tgz = util_tar_gz(&block)
+ util_tar do |tar|
+ if spec
+ tar.add_file "metadata.gz", 0o444 do |io|
+ io.write util_gzip(spec.to_yaml)
+ end
+ end
+ tar.add_file "data.tar.gz", 0o644 do |io|
+ io.write data_tgz.string
+ end
+ end
+ end
end
diff --git a/test/rubygems/packages/Bluebie-legs-0.6.2.gem b/test/rubygems/packages/Bluebie-legs-0.6.2.gem
new file mode 100644
index 0000000000..60918f3bc5
--- /dev/null
+++ b/test/rubygems/packages/Bluebie-legs-0.6.2.gem
Binary files differ
diff --git a/test/rubygems/plugin/exception/rubygems_plugin.rb b/test/rubygems/plugin/exception/rubygems_plugin.rb
deleted file mode 100644
index 9a6f557b5c..0000000000
--- a/test/rubygems/plugin/exception/rubygems_plugin.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-# frozen_string_literal: true
-TestGem::TEST_PLUGIN_EXCEPTION = :loaded
-raise Exception.new('boom')
diff --git a/test/rubygems/plugin/load/rubygems_plugin.rb b/test/rubygems/plugin/load/rubygems_plugin.rb
index 7cc6bef90b..21fef10bb1 100644
--- a/test/rubygems/plugin/load/rubygems_plugin.rb
+++ b/test/rubygems/plugin/load/rubygems_plugin.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
class TestGem
TEST_PLUGIN_LOAD = :loaded
end
diff --git a/test/rubygems/plugin/scripterror/rubygems_plugin.rb b/test/rubygems/plugin/scripterror/rubygems_plugin.rb
new file mode 100644
index 0000000000..0acd55be12
--- /dev/null
+++ b/test/rubygems/plugin/scripterror/rubygems_plugin.rb
@@ -0,0 +1,4 @@
+# frozen_string_literal: true
+
+TestGem::TEST_PLUGIN_EXCEPTION = :loaded
+raise ScriptError.new("boom")
diff --git a/test/rubygems/plugin/standarderror/rubygems_plugin.rb b/test/rubygems/plugin/standarderror/rubygems_plugin.rb
index 94cf4e8a52..58e4080f05 100644
--- a/test/rubygems/plugin/standarderror/rubygems_plugin.rb
+++ b/test/rubygems/plugin/standarderror/rubygems_plugin.rb
@@ -1,3 +1,4 @@
# frozen_string_literal: true
+
TestGem::TEST_PLUGIN_STANDARDERROR = :loaded
-raise StandardError.new('boom')
+raise StandardError.new("boom")
diff --git a/test/rubygems/private_ec_key.pem b/test/rubygems/private_ec_key.pem
new file mode 100644
index 0000000000..5d855d0dfc
--- /dev/null
+++ b/test/rubygems/private_ec_key.pem
@@ -0,0 +1,9 @@
+-----BEGIN EC PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-256-CBC,4107F98A374CB8EC18F1AA4EA4B6A0DB
+
+BRklFxJGcz7gqQYxek8TZkt8qbPhB0FSR6nyw3SYuio/2tlT9ohs74mlK3EbG9Lt
+Y4OquJbksBFmoB7fIoM4vnuIZ0Eoz2ooxn9tjhBtqJ3mVscYXwZmA3UDUWDMlviQ
+Fu37OpikQv4TFA1jlmUK0LM8xmUCfUeLl0kHD17lFsz2gkO2kwg8mn/YUMOIaDOu
+EnnmxbAwnZBpemQkQfpTt2mYL9gu3CcMt5gokBuGDxY=
+-----END EC PRIVATE KEY-----
diff --git a/test/rubygems/private_key.pem b/test/rubygems/private_key.pem
index c6ed3fc24e..4e6ce13e65 100644
--- a/test/rubygems/private_key.pem
+++ b/test/rubygems/private_key.pem
@@ -1,27 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
-MIIEowIBAAKCAQEAp2U1hy8UHrGClPxByczJtV6UYtQrJAv+FA9Mr0nkXKoHyEQM
-u3au4zAqwdTp+7+aAb6wu8cXWepaFkAOGfqvAJ80/TfTbm+S05nqIl9TrS/K1j9/
-eCSIY2Q/bWXSHPT4yzXl/7naCT6wVerAYFsO14jTHntSweL4oA3rtC48Oe2FgO3C
-FcgDmlx3HbAf41bwXzYcRm+bWFykDvkENWTi8/GekN+884pJif11aCGZS1o+arJW
-+zxeQPEcN9jnj8PfOI96E/7NDMSDwLTtKr/Pq8tI5De5pifScEO40Tpc/eKMnhm+
-zZ4kR04zJLUfcKyeRaJ48Ksu0p3Dx38X4PluhwIDAQABAoIBAAx09qfJtBiYoxwN
-LaQjzjrl/+re2RsEnXLGtLEysYDH0m5vyfbFXTxg4D2uZ38pgf9xPluq9CznyK5x
-M9txEUbdkibp2Z0VRnrisE7Ag0yXCuQos4awSUoEMsgkVJ99B2qv5x7BqN0ZQiwS
-nSBOhms5rmRNTxpIlrHqd0jgS/EPggnqVzNcM4/K8PJFthwEBKDmzOyiRByvz54Y
-shzOnTjGtV2oGNgwpzmCXce1yO7dh2IdKnSnmeFwyU88GxEYnGh5MIFuTiyErP72
-k6iEUfiXy0hxk/iXmKs8UyD1lVnwTNWcZcpV8yw4a06Z6nkSnwQm0SSOVIo/w35V
-jdVdUkECgYEA3GhZ70MD/Q47GFvz6BovwQvxhjFN+nIEbBfi7OTkuXprKdhVhjaR
-nERPZpZjHWrcfgbFcvPY7/GJLTPN/VF1nhOsOZpzfAmCgBujRXrzlAGpU877ZNJA
-QKPgzo+iv/RsQCIdrzF1gwHkqD2v1HRLaqb2+dVumiG4Qp3NXgasT2cCgYEAwm1U
-uRDXgQKGODeLK8eSVpfMjD5umBVu7m4D3ZmipbN6sMBxGMAlsU40eQ7DBFH0AFft
-s2D88JdjlwoOrbXYYpOc6iWD/QkygJfPpA9VQx92hv8KBd82gLHuXYMd0T0G3yZO
-gPPioeRgl2TvgVCfjn6AYr3Ubt3rB5aBlSplE+ECgYEAiXhcf6rg1fkGSs8vddi/
-aDy2y+f8pvRuZa0QUIkDT9xW8qaH0Uo/z6ObknTCJRr9o209wdDtwdp4oMTq+dDQ
-92N1zAfVd8vGpXiXgUKKognXPvqeOegZQzfzg2J7NBaTXfzpXtgOX0PTBkxTWsOe
-NkslR/YjIedeMc6SxM6MsokCgYA3mTYyGevWe5dQOin1IgPp+UzICg5sNSzcx98Z
-HpcRVWrPYqi00DW3J0sAF0WTVbA17O8PbbvHPTOAfKLH8Alp3xZvKr08vcWQWllJ
-bA0Qvc2SOxptpXAbi0ZDvXvoWtA9PeITJCr56qnogTewPhLyl6A1HF3EOne8WsDB
-nDb9YQKBgEyUDWhDBGXUfQN0fWy5ksqCCeHXQzvt6aEUstWvkkbnnarUfLAhBIqC
-2B6omokICmWzvAfDt3UsRbb3QJUBxbbVsZVM7Vr+kY2cQ1Ma093I/2mXDoq3bV+j
-LZM5+Uc7xSfiCi1hbVhGm96DXofudddo86W5mhXp3xhcQP1Fl4JZ
+MIIEpAIBAAKCAQEA0ULcfpDboY5uWVdOIkF4AtRui7PPFoaKfBl5hiGFcpYRx8DQ
+PyT7bbD8nKd14Rhzb0nHCMU3DEz8PLJCmWm3NszVDkEJws1BpCGak6vKiyNa5hZb
+UlQMZMbecSDSpEKu2PBWgBT74qg2RBugzTAVAnGQGezQnWyv47kyXvdjMoq11VZa
++Dz2izHJvjBHGQShr1r9v39qIrtah5CEXTRxEqhr96gg3y6xOPMqxi50dS0RBaJs
+PsjFZ1jecye0Z/WPItiLjSVVRssUXK1a2VkYxUqkxUg4wwJD57H4TEZBomtAXlAS
+o+rUv8G9eBNmS/k/oJLdiMF1ULb+e1+izeAyGwIDAQABAoIBABS+vR8q+ysD9LqU
+piFNPjmBl8fvtmr0QYxV9i8u6YzXhcG4wqxP3UEdl51sGIqNIvx4YuviqTdl9meK
+AII28bvUCJcWKYKPWJ+N2UYkdLrgcWV39+use2IOOQUcDOXN2omVIe4mpmXs6RxN
+ZN6SkrKgUXnQeUnx+Wno9S5m9gWPfrAMTr8iwBquo5JMFqJmAlfq1cIActU7SE6M
+7LJZ8rbVGuGmZAyqJw/I5xvxts6NlTFBm2AyGq74wtbUD4OlFDtOTA57LmtRswmr
+MK+JG5LIJIyc6qKQwmHU8vLstJEcVUyCJDbpjDkApd6GQ2FwXXode+S9C40DZKvi
+hnaGfKECgYEA1ArI5tt3GdNR4CbY4e4yDHEuSdSkMVsRa9a7gdtrrjyNitBMbZNE
+HZNqswijBCPZnXPtBxeytMUmlU7uFc7xx3QQvuBSJ6HOb9j0qtWVL+jl8R9XLogH
+sE/m0yMPs2IowevJoQ95KRZIirLywZ8QgTsySEv9U4hx2CdKpn7IeRECgYEA/KR9
+WI1n6pxDbxcjWMaOdziIcgDBk7v05Qssb1OePiz+y+zfrBVqDjsvsokRLoElSAkR
+TAV+/9hRgAu4cZJpP0FMdFe+sVkr1UfcDqvJdgumBL+xUNxRV/QFvuprLa6XbiQO
+jUclJR6BPdXeVQPDUHuQBgnwXrJdRtMl9Fj8GGsCgYAhZKVo/e0OyyHczCFhy1Jk
+dTqV8//7qdzff8y90aFuqiicUNuIciXLBplKIrURhNfTnRsZ/9hr8ZR29Rw3oQSg
+pZ2xgcBOb4QER0WY1dQN3H7B726abF/Rm3O9kor5dB75EzoIvFgXaWP5O99RMMy3
+nWv4yMbXbeiH4wA1okfOEQKBgQDkaAnyrxUN5GyK2M5aCljurCufddOMrtb+5BUu
+KNjduWw6DVNCjrGtYBEFRipEcvmzoI8EvctNntJAA1ijRQzl5TEr1dBPIiEg17C5
+itG+aVWU4YF7a1QXQkSXj/OJ/1hkeTC2xWVto6CQuPQixB4mey+AZifsVTFDQM4F
+lRWFNQKBgQDQWRXaJgc4Jeur1/I1iMAcihN/o4Lra4baM07FdpFWrePJ4IimXHG+
+buws6BuytnQP56hqIQYLQSWCF192dcnHNbodXz48Ug6rKLSBalxH3pvThYLpkBSk
+7OrfHzO4TTVaCH1mcPjzj9vmRog2tvrF/m6/8UAZQIBGDv2+cHk4rA==
-----END RSA PRIVATE KEY-----
diff --git a/test/rubygems/public_cert.pem b/test/rubygems/public_cert.pem
index 4517de53c6..7481c26b79 100644
--- a/test/rubygems/public_cert.pem
+++ b/test/rubygems/public_cert.pem
@@ -1,20 +1,20 @@
-----BEGIN CERTIFICATE-----
-MIIDLjCCAhagAwIBAgIBADANBgkqhkiG9w0BAQUFADAqMQ8wDQYDVQQDDAZub2Jv
+MIIDLjCCAhagAwIBAgIBADANBgkqhkiG9w0BAQsFADAqMQ8wDQYDVQQDDAZub2Jv
ZHkxFzAVBgoJkiaJk/IsZAEZFgdleGFtcGxlMCAXDTEyMDEwMTAwMDAwMFoYDzk5
OTkxMjMxMjM1OTU5WjAqMQ8wDQYDVQQDDAZub2JvZHkxFzAVBgoJkiaJk/IsZAEZ
-FgdleGFtcGxlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp2U1hy8U
-HrGClPxByczJtV6UYtQrJAv+FA9Mr0nkXKoHyEQMu3au4zAqwdTp+7+aAb6wu8cX
-WepaFkAOGfqvAJ80/TfTbm+S05nqIl9TrS/K1j9/eCSIY2Q/bWXSHPT4yzXl/7na
-CT6wVerAYFsO14jTHntSweL4oA3rtC48Oe2FgO3CFcgDmlx3HbAf41bwXzYcRm+b
-WFykDvkENWTi8/GekN+884pJif11aCGZS1o+arJW+zxeQPEcN9jnj8PfOI96E/7N
-DMSDwLTtKr/Pq8tI5De5pifScEO40Tpc/eKMnhm+zZ4kR04zJLUfcKyeRaJ48Ksu
-0p3Dx38X4PluhwIDAQABo10wWzAZBgNVHREEEjAQgQ5ub2JvZHlAZXhhbXBsZTAd
-BgNVHQ4EFgQUX0Nu9pqORSXpIuN9N16k1TYChRswDwYDVR0TAQH/BAUwAwEB/zAO
-BgNVHQ8BAf8EBAMCAgQwDQYJKoZIhvcNAQEFBQADggEBAJasznHQK7el5CY19uRM
-QZSP2moi65jbESKA5CaSOK0erWfLL7k0W69Rr4RG8CQDXmtlVLzdQlEGkvJEfMLs
-GumlIGDEsLZU/3tQ8lML2fMUKipv/fsyWoe6wUHyfsywYYT4WAxyKUtY6AepwN6Y
-sJ6+qDWUFziSVgDnU2bBdqzIOw+ww1NtRGE3PEam+a/VL7l/a2DYcot5cvcc8RYR
-6gyBXp4fvSGasM3iQp7sWdNV04H8m8+lYBLtsfuucgLDu45uEuvKL1tRcRXvtomp
-rKB5y3B5qT/bcc+3b0tbOU6s7CBIdyzIflJI7GuIbZk6lZ+V8Yem+tWt1ArL3Hqf
-Myk=
+FgdleGFtcGxlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ULcfpDb
+oY5uWVdOIkF4AtRui7PPFoaKfBl5hiGFcpYRx8DQPyT7bbD8nKd14Rhzb0nHCMU3
+DEz8PLJCmWm3NszVDkEJws1BpCGak6vKiyNa5hZbUlQMZMbecSDSpEKu2PBWgBT7
+4qg2RBugzTAVAnGQGezQnWyv47kyXvdjMoq11VZa+Dz2izHJvjBHGQShr1r9v39q
+Irtah5CEXTRxEqhr96gg3y6xOPMqxi50dS0RBaJsPsjFZ1jecye0Z/WPItiLjSVV
+RssUXK1a2VkYxUqkxUg4wwJD57H4TEZBomtAXlASo+rUv8G9eBNmS/k/oJLdiMF1
+ULb+e1+izeAyGwIDAQABo10wWzAZBgNVHREEEjAQgQ5ub2JvZHlAZXhhbXBsZTAd
+BgNVHQ4EFgQUsRpUCWdFYAIC1870HWBKid/nWNkwDwYDVR0TAQH/BAUwAwEB/zAO
+BgNVHQ8BAf8EBAMCAgQwDQYJKoZIhvcNAQELBQADggEBAAYrbeZLQujvqrzAa6NN
+QsiGLSVoF+ZcySQH+rpoqcvbd8zLKz/vH+SoMM6db4OUgD8BKaeBb8dGhzz/lE8m
+YUqW/La4xvf/ffW5yze51Rtr1bPw1Tjrk92nE630Unjf0ZZO0h8shTmq/WlXiEqg
+cXxfbZiPP0KZkhn4ulf+RBbKKQGrLYvaVrCZcowSjLWzcfredYxElOpcgHCrL2pl
+2ZAjCySqAUpYo8HTZwgY/DeeGS3V4fZ06ZDoG20cxi7t8R+AcNbEfaTMzG3oe5qN
+A8+a3Qcf5M4yiJtXRNusMKeoRwLDkYRX9u76iOI5LfKTSqnUyhrUQcSYCTFO4y/V
+P48=
-----END CERTIFICATE-----
diff --git a/test/rubygems/public_cert_32.pem b/test/rubygems/public_cert_32.pem
index 0431b8ba1a..efcf7c0ed7 100644
--- a/test/rubygems/public_cert_32.pem
+++ b/test/rubygems/public_cert_32.pem
@@ -1,19 +1,19 @@
-----BEGIN CERTIFICATE-----
-MIIDLDCCAhSgAwIBAgIBATANBgkqhkiG9w0BAQUFADAqMQ8wDQYDVQQDDAZub2Jv
+MIIDLDCCAhSgAwIBAgIBATANBgkqhkiG9w0BAQsFADAqMQ8wDQYDVQQDDAZub2Jv
ZHkxFzAVBgoJkiaJk/IsZAEZFgdleGFtcGxlMB4XDTEyMDEwMTAwMDAwMFoXDTM4
MDExOTAzMTQwN1owKjEPMA0GA1UEAwwGbm9ib2R5MRcwFQYKCZImiZPyLGQBGRYH
-ZXhhbXBsZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKdlNYcvFB6x
-gpT8QcnMybVelGLUKyQL/hQPTK9J5FyqB8hEDLt2ruMwKsHU6fu/mgG+sLvHF1nq
-WhZADhn6rwCfNP03025vktOZ6iJfU60vytY/f3gkiGNkP21l0hz0+Ms15f+52gk+
-sFXqwGBbDteI0x57UsHi+KAN67QuPDnthYDtwhXIA5pcdx2wH+NW8F82HEZvm1hc
-pA75BDVk4vPxnpDfvPOKSYn9dWghmUtaPmqyVvs8XkDxHDfY54/D3ziPehP+zQzE
-g8C07Sq/z6vLSOQ3uaYn0nBDuNE6XP3ijJ4Zvs2eJEdOMyS1H3CsnkWiePCrLtKd
-w8d/F+D5bocCAwEAAaNdMFswGQYDVR0RBBIwEIEObm9ib2R5QGV4YW1wbGUwHQYD
-VR0OBBYEFF9DbvaajkUl6SLjfTdepNU2AoUbMA8GA1UdEwEB/wQFMAMBAf8wDgYD
-VR0PAQH/BAQDAgIEMA0GCSqGSIb3DQEBBQUAA4IBAQA2+XpC520DwKfqlv5Fn2N5
-sGOgr2Kop7Id2wVWiGDnjDEoTf2Fj+nmmLPltemoCumgY/AacUBAdK1kg47x+7NR
-QMq1pOXR5dZbopw1vs9isQQx2P7jKEH7AgIkqo/6XMQGE3tQtJyNIi1LTGCOKNok
-Fpv8ZVS8aBmXgC0zwtlrtTxCXpkFaNB99nEqo46Fy+D7dkEXE4Oc3JjTON83sHYD
-VsV3DFYzZtR9qe/gCOdgnDHYnf5vU+LGA1gX+8d4Iu/B5ZZtaAowgrsA14oJDuO3
-4g491pjaEYDFZG6mUpvf79uZaBjJdDZeyfwtJ6cN3gTv98DO4DKh/qxnbM/46LM1
+ZXhhbXBsZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANFC3H6Q26GO
+bllXTiJBeALUbouzzxaGinwZeYYhhXKWEcfA0D8k+22w/JyndeEYc29JxwjFNwxM
+/DyyQplptzbM1Q5BCcLNQaQhmpOryosjWuYWW1JUDGTG3nEg0qRCrtjwVoAU++Ko
+NkQboM0wFQJxkBns0J1sr+O5Ml73YzKKtdVWWvg89osxyb4wRxkEoa9a/b9/aiK7
+WoeQhF00cRKoa/eoIN8usTjzKsYudHUtEQWibD7IxWdY3nMntGf1jyLYi40lVUbL
+FFytWtlZGMVKpMVIOMMCQ+ex+ExGQaJrQF5QEqPq1L/BvXgTZkv5P6CS3YjBdVC2
+/ntfos3gMhsCAwEAAaNdMFswGQYDVR0RBBIwEIEObm9ib2R5QGV4YW1wbGUwHQYD
+VR0OBBYEFLEaVAlnRWACAtfO9B1gSonf51jZMA8GA1UdEwEB/wQFMAMBAf8wDgYD
+VR0PAQH/BAQDAgIEMA0GCSqGSIb3DQEBCwUAA4IBAQBqjR8ioUTAmRjZNvRPMGXc
+mx0nklEODMfG5k+X4QI2Hux/4CWuSZKh+LoIxOsqQJdm2rG1FkPr6JYQOj5HCFA7
+3gO/MoSOtqBBOY9uMnGJQUq0NrWvleO3giUhfHRzUh7utXy2u3umuwJLqF54vbuT
+a1yufGSzwBO2BP7iURt9SyVrDWFmHSX976ZFWIandPXgMCJTgO6tONOC6/sABctb
+YQKo2scrAiSsk+kgIMnebavL6gKgQud6xdjJzvUq3DV4s93ent9rpRzYRgnTM8Eo
+UcgFbpFsWR21+gEt6UKv1rO9ZaWBf6RUVdh/sJKa/7vK/shQmnWw0A/LewxKQWV3
-----END CERTIFICATE-----
diff --git a/test/rubygems/public_key.pem b/test/rubygems/public_key.pem
index 7c29dcd614..c233b35e7c 100644
--- a/test/rubygems/public_key.pem
+++ b/test/rubygems/public_key.pem
@@ -1,9 +1,9 @@
-----BEGIN PUBLIC KEY-----
-MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp2U1hy8UHrGClPxByczJ
-tV6UYtQrJAv+FA9Mr0nkXKoHyEQMu3au4zAqwdTp+7+aAb6wu8cXWepaFkAOGfqv
-AJ80/TfTbm+S05nqIl9TrS/K1j9/eCSIY2Q/bWXSHPT4yzXl/7naCT6wVerAYFsO
-14jTHntSweL4oA3rtC48Oe2FgO3CFcgDmlx3HbAf41bwXzYcRm+bWFykDvkENWTi
-8/GekN+884pJif11aCGZS1o+arJW+zxeQPEcN9jnj8PfOI96E/7NDMSDwLTtKr/P
-q8tI5De5pifScEO40Tpc/eKMnhm+zZ4kR04zJLUfcKyeRaJ48Ksu0p3Dx38X4Plu
-hwIDAQAB
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ULcfpDboY5uWVdOIkF4
+AtRui7PPFoaKfBl5hiGFcpYRx8DQPyT7bbD8nKd14Rhzb0nHCMU3DEz8PLJCmWm3
+NszVDkEJws1BpCGak6vKiyNa5hZbUlQMZMbecSDSpEKu2PBWgBT74qg2RBugzTAV
+AnGQGezQnWyv47kyXvdjMoq11VZa+Dz2izHJvjBHGQShr1r9v39qIrtah5CEXTRx
+Eqhr96gg3y6xOPMqxi50dS0RBaJsPsjFZ1jecye0Z/WPItiLjSVVRssUXK1a2VkY
+xUqkxUg4wwJD57H4TEZBomtAXlASo+rUv8G9eBNmS/k/oJLdiMF1ULb+e1+izeAy
+GwIDAQAB
-----END PUBLIC KEY-----
diff --git a/test/rubygems/rubygems/commands/crash_command.rb b/test/rubygems/rubygems/commands/crash_command.rb
index 9155360e76..55df274603 100644
--- a/test/rubygems/rubygems/commands/crash_command.rb
+++ b/test/rubygems/rubygems/commands/crash_command.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
class Gem::Commands::CrashCommand < Gem::Command
raise "crash"
end
diff --git a/test/rubygems/rubygems_plugin.rb b/test/rubygems/rubygems_plugin.rb
index 2dc7836904..949580f904 100644
--- a/test/rubygems/rubygems_plugin.rb
+++ b/test/rubygems/rubygems_plugin.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
-require 'rubygems/command_manager'
+
+require "rubygems/command_manager"
##
# This is an example of exactly what NOT to do.
@@ -12,7 +13,7 @@ end
class Gem::Commands::InterruptCommand < Gem::Command
def initialize
- super('interrupt', 'Raises an Interrupt Exception', {})
+ super("interrupt", "Raises an Interrupt Exception", {})
end
def execute
diff --git a/test/rubygems/simple_gem.rb b/test/rubygems/simple_gem.rb
index 0f2ea48198..3d30bade84 100644
--- a/test/rubygems/simple_gem.rb
+++ b/test/rubygems/simple_gem.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
-SIMPLE_GEM = <<-GEMDATA.freeze
+
+SIMPLE_GEM = <<-GEMDATA
MD5SUM = "989bf34a1cbecd52e0ea66b662b3a405"
if $0 == __FILE__
require 'optparse'
diff --git a/test/rubygems/specifications/bar-0.0.2.gemspec b/test/rubygems/specifications/bar-0.0.2.gemspec
index 37b6ea45da..1f3d0161d2 100644
--- a/test/rubygems/specifications/bar-0.0.2.gemspec
+++ b/test/rubygems/specifications/bar-0.0.2.gemspec
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
Gem::Specification.new do |s|
s.name = "bar"
s.version = "0.0.2"
diff --git a/test/rubygems/specifications/rubyforge-0.0.1.gemspec b/test/rubygems/specifications/rubyforge-0.0.1.gemspec
index c760a42073..0421b675a0 100644
--- a/test/rubygems/specifications/rubyforge-0.0.1.gemspec
+++ b/test/rubygems/specifications/rubyforge-0.0.1.gemspec
@@ -1,12 +1,15 @@
+# frozen_string_literal: true
+
Gem::Specification.new do |s|
- s.name = "rubyforge"
- s.version = "0.0.1"
- s.platform = "ruby"
- s.require_paths = ["lib"]
- s.summary = "A very bar gem"
- s.authors = ["unknown"]
- s.license = 'MIT'
- s.homepage = 'http://example.com'
- s.files = ['README.md']
- s.rubyforge_project = 'abc'
+ s.name = "rubyforge"
+ s.version = "0.0.1"
+ s.platform = "ruby"
+ s.require_paths = ["lib"]
+ s.summary = "A very bar gem"
+ s.authors = ["unknown"]
+ s.license = "MIT"
+ s.homepage = "http://example.com"
+ s.files = ["README.md"]
+ s.rubyforge_project = "abc"
+ s.required_ruby_version = ">= 1.9.3"
end
diff --git a/test/rubygems/test_bundled_ca.rb b/test/rubygems/test_bundled_ca.rb
index fff5904aba..a737185681 100644
--- a/test/rubygems/test_bundled_ca.rb
+++ b/test/rubygems/test_bundled_ca.rb
@@ -1,20 +1,21 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'net/http'
-require 'rubygems/openssl'
+
+require_relative "helper"
+require "rubygems/vendored_net_http"
+require "rubygems/openssl"
unless Gem::HAVE_OPENSSL
- warn 'Skipping bundled certificates tests. openssl not found.'
+ warn "Skipping bundled certificates tests. openssl not found."
end
-require 'rubygems/request'
+require "rubygems/request"
# = Testing Bundled CA
#
# The tested hosts are explained in detail here: https://github.com/rubygems/rubygems/commit/5e16a5428f973667cabfa07e94ff939e7a83ebd9
#
-class TestBundledCA < Gem::TestCase
+class TestGemBundledCA < Gem::TestCase
def bundled_certificate_store
store = OpenSSL::X509::Store.new
@@ -27,34 +28,34 @@ class TestBundledCA < Gem::TestCase
def assert_https(host)
assert true
- http = Net::HTTP.new(host, 443)
+ http = Gem::Net::HTTP.new(host, 443)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
http.cert_store = bundled_certificate_store
- http.get('/')
- rescue Errno::ENOENT, Errno::ETIMEDOUT, SocketError
+ http.get("/")
+ rescue Errno::ENOENT, Errno::ETIMEDOUT, SocketError, Gem::Net::OpenTimeout
pend "#{host} seems offline, I can't tell whether ssl would work."
rescue OpenSSL::SSL::SSLError => e
# Only fail for certificate verification errors
- if e.message =~ /certificate verify failed/
+ if e.message.include?("certificate verify failed")
flunk "#{host} is not verifiable using the included certificates. Error was: #{e.message}"
end
raise
end
def test_accessing_rubygems
- assert_https('rubygems.org')
+ assert_https("rubygems.org")
end
def test_accessing_www_rubygems
- assert_https('www.rubygems.org')
+ assert_https("www.rubygems.org")
end
def test_accessing_staging
- assert_https('staging.rubygems.org')
+ assert_https("staging.rubygems.org")
end
def test_accessing_new_index
- assert_https('index.rubygems.org')
+ assert_https("index.rubygems.org")
end
end if Gem::HAVE_OPENSSL
diff --git a/test/rubygems/test_config.rb b/test/rubygems/test_config.rb
index fff539c816..657624d526 100644
--- a/test/rubygems/test_config.rb
+++ b/test/rubygems/test_config.rb
@@ -1,9 +1,10 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems'
-require 'shellwords'
-class TestConfig < Gem::TestCase
+require_relative "helper"
+require "rubygems"
+require "shellwords"
+
+class TestGemConfig < Gem::TestCase
def test_datadir
util_make_gems
spec = Gem::Specification.find_by_name("a")
@@ -15,13 +16,13 @@ class TestConfig < Gem::TestCase
path = Gem::TestCase.class_variable_get(:@@good_rake)
ruby, rake = path.shellsplit
assert_equal(Gem.ruby, ruby)
- assert_match(/\/good_rake.rb\z/, rake)
+ assert_match(%r{/good_rake.rb\z}, rake)
end
def test_bad_rake_path_is_escaped
path = Gem::TestCase.class_variable_get(:@@bad_rake)
ruby, rake = path.shellsplit
assert_equal(Gem.ruby, ruby)
- assert_match(/\/bad_rake.rb\z/, rake)
+ assert_match(%r{/bad_rake.rb\z}, rake)
end
end
diff --git a/test/rubygems/test_deprecate.rb b/test/rubygems/test_deprecate.rb
index a619eccb37..d15de646a4 100644
--- a/test/rubygems/test_deprecate.rb
+++ b/test/rubygems/test_deprecate.rb
@@ -1,8 +1,9 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/deprecate'
-class TestDeprecate < Gem::TestCase
+require_relative "helper"
+require "rubygems/deprecate"
+
+class TestGemDeprecate < Gem::TestCase
def setup
super
@@ -28,7 +29,7 @@ class TestDeprecate < Gem::TestCase
assert_equal true, Gem::Deprecate.skip
Gem::Deprecate.skip = nil
- assert([true,false].include? Gem::Deprecate.skip)
+ assert([true,false].include?(Gem::Deprecate.skip))
end
def test_skip
@@ -45,6 +46,7 @@ class TestDeprecate < Gem::TestCase
def foo
@message = "foo"
end
+
def bar
@message = "bar"
end
@@ -53,6 +55,7 @@ class TestDeprecate < Gem::TestCase
def foo_arg(msg)
@message = "foo" + msg
end
+
def bar_arg(msg)
@message = "bar" + msg
end
@@ -61,6 +64,7 @@ class TestDeprecate < Gem::TestCase
def foo_kwarg(message:)
@message = "foo" + message
end
+
def bar_kwarg(message:)
@message = "bar" + message
end
@@ -73,6 +77,7 @@ class TestDeprecate < Gem::TestCase
def foo
@message = "foo"
end
+
def bar
@message = "bar"
end
@@ -81,6 +86,7 @@ class TestDeprecate < Gem::TestCase
def foo_arg(msg)
@message = "foo" + msg
end
+
def bar_arg(msg)
@message = "bar" + msg
end
@@ -89,6 +95,7 @@ class TestDeprecate < Gem::TestCase
def foo_kwarg(message:)
@message = "foo" + message
end
+
def bar_kwarg(message:)
@message = "bar" + message
end
@@ -123,7 +130,7 @@ class TestDeprecate < Gem::TestCase
end
def test_rubygems_deprecate_command
- require 'rubygems/command'
+ require "rubygems/command"
foo_command = Class.new(Gem::Command) do
extend Gem::Deprecate
diff --git a/test/rubygems/test_exit.rb b/test/rubygems/test_exit.rb
index 9557fe5d06..396837edad 100644
--- a/test/rubygems/test_exit.rb
+++ b/test/rubygems/test_exit.rb
@@ -1,11 +1,17 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems'
+require_relative "helper"
+require "rubygems"
-class TestExit < Gem::TestCase
+class TestGemExit < Gem::TestCase
def test_exit
system(*ruby_with_rubygems_in_load_path, "-e", "raise Gem::SystemExitException.new(2)")
assert_equal 2, $?.exitstatus
end
+
+ def test_status
+ exc = Gem::SystemExitException.new(42)
+ assert_equal 42, exc.status
+ assert_equal 42, exc.exit_code
+ end
end
diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb
index da6fdc54fa..e8a294d65c 100644
--- a/test/rubygems/test_gem.rb
+++ b/test/rubygems/test_gem.rb
@@ -1,16 +1,17 @@
# coding: US-ASCII
-require_relative 'helper'
-require 'rubygems'
-require 'rubygems/command'
-require 'rubygems/installer'
-require 'pathname'
-require 'tmpdir'
-require 'rbconfig'
+
+require_relative "helper"
+require "rubygems"
+require "rubygems/command"
+require "rubygems/installer"
+require "pathname"
+require "tmpdir"
+require "rbconfig"
class TestGem < Gem::TestCase
PLUGINS_LOADED = [] # rubocop:disable Style/MutableConstant
- PROJECT_DIR = File.expand_path('../../..', __FILE__).tap(&Gem::UNTAINT)
+ PROJECT_DIR = File.expand_path("../..", __dir__)
def setup
super
@@ -25,104 +26,98 @@ class TestGem < Gem::TestCase
end
def test_self_finish_resolve
- save_loaded_features do
- a1 = util_spec "a", "1", "b" => "> 0"
- b1 = util_spec "b", "1", "c" => ">= 1"
- b2 = util_spec "b", "2", "c" => ">= 2"
- c1 = util_spec "c", "1"
- c2 = util_spec "c", "2"
+ a1 = util_spec "a", "1", "b" => "> 0"
+ b1 = util_spec "b", "1", "c" => ">= 1"
+ b2 = util_spec "b", "2", "c" => ">= 2"
+ c1 = util_spec "c", "1"
+ c2 = util_spec "c", "2"
- install_specs c1, c2, b1, b2, a1
+ install_specs c1, c2, b1, b2, a1
- a1.activate
+ a1.activate
- assert_equal %w[a-1], loaded_spec_names
- assert_equal ["b (> 0)"], unresolved_names
+ assert_equal %w[a-1], loaded_spec_names
+ assert_equal ["b (> 0)"], unresolved_names
- Gem.finish_resolve
+ Gem.finish_resolve
- assert_equal %w[a-1 b-2 c-2], loaded_spec_names
- assert_equal [], unresolved_names
- end
+ assert_equal %w[a-1 b-2 c-2], loaded_spec_names
+ assert_equal [], unresolved_names
end
def test_self_finish_resolve_wtf
- save_loaded_features do
- a1 = util_spec "a", "1", "b" => "> 0", "d" => "> 0" # this
- b1 = util_spec "b", "1", { "c" => ">= 1" }, "lib/b.rb" # this
- b2 = util_spec "b", "2", { "c" => ">= 2" }, "lib/b.rb"
- c1 = util_spec "c", "1" # this
- c2 = util_spec "c", "2"
- d1 = util_spec "d", "1", { "c" => "< 2" }, "lib/d.rb"
- d2 = util_spec "d", "2", { "c" => "< 2" }, "lib/d.rb" # this
+ a1 = util_spec "a", "1", "b" => "> 0", "d" => "> 0" # this
+ b1 = util_spec "b", "1", { "c" => ">= 1" }, "lib/b.rb" # this
+ b2 = util_spec "b", "2", { "c" => ">= 2" }, "lib/b.rb"
+ c1 = util_spec "c", "1" # this
+ c2 = util_spec "c", "2"
+ d1 = util_spec "d", "1", { "c" => "< 2" }, "lib/d.rb"
+ d2 = util_spec "d", "2", { "c" => "< 2" }, "lib/d.rb" # this
- install_specs c1, c2, b1, b2, d1, d2, a1
+ install_specs c1, c2, b1, b2, d1, d2, a1
- a1.activate
+ a1.activate
- assert_equal %w[a-1], loaded_spec_names
- assert_equal ["b (> 0)", "d (> 0)"], unresolved_names
+ assert_equal %w[a-1], loaded_spec_names
+ assert_equal ["b (> 0)", "d (> 0)"], unresolved_names
- Gem.finish_resolve
+ Gem.finish_resolve
- assert_equal %w[a-1 b-1 c-1 d-2], loaded_spec_names
- assert_equal [], unresolved_names
- end
+ assert_equal %w[a-1 b-1 c-1 d-2], loaded_spec_names
+ assert_equal [], unresolved_names
end
def test_self_finish_resolve_respects_loaded_specs
- save_loaded_features do
- a1 = util_spec "a", "1", "b" => "> 0"
- b1 = util_spec "b", "1", "c" => ">= 1"
- b2 = util_spec "b", "2", "c" => ">= 2"
- c1 = util_spec "c", "1"
- c2 = util_spec "c", "2"
+ a1 = util_spec "a", "1", "b" => "> 0"
+ b1 = util_spec "b", "1", "c" => ">= 1"
+ b2 = util_spec "b", "2", "c" => ">= 2"
+ c1 = util_spec "c", "1"
+ c2 = util_spec "c", "2"
- install_specs c1, c2, b1, b2, a1
+ install_specs c1, c2, b1, b2, a1
- a1.activate
- c1.activate
+ a1.activate
+ c1.activate
- assert_equal %w[a-1 c-1], loaded_spec_names
- assert_equal ["b (> 0)"], unresolved_names
+ assert_equal %w[a-1 c-1], loaded_spec_names
+ assert_equal ["b (> 0)"], unresolved_names
- Gem.finish_resolve
+ Gem.finish_resolve
- assert_equal %w[a-1 b-1 c-1], loaded_spec_names
- assert_equal [], unresolved_names
- end
+ assert_equal %w[a-1 b-1 c-1], loaded_spec_names
+ assert_equal [], unresolved_names
end
def test_self_install
spec_fetcher do |f|
- f.gem 'a', 1
- f.spec 'a', 2
+ f.gem "a", 1
+ f.spec "a", 2
end
gemhome2 = "#{@gemhome}2"
- installed = Gem.install 'a', '= 1', :install_dir => gemhome2
+ installed = Gem.install "a", "= 1", install_dir: gemhome2
- assert_equal %w[a-1], installed.map {|spec| spec.full_name }
+ assert_equal %w[a-1], installed.map(&:full_name)
- assert_path_exist File.join(gemhome2, 'gems', 'a-1')
+ assert_path_exist File.join(gemhome2, "gems", "a-1")
end
def test_self_install_in_rescue
spec_fetcher do |f|
- f.gem 'a', 1
- f.spec 'a', 2
+ f.gem "a", 1
+ f.spec "a", 2
end
gemhome2 = "#{@gemhome}2"
installed =
begin
- raise 'Error'
+ raise "Error"
rescue StandardError
- Gem.install 'a', '= 1', :install_dir => gemhome2
+ Gem.install "a", "= 1", install_dir: gemhome2
end
- assert_equal %w[a-1], installed.map {|spec| spec.full_name }
+ assert_equal %w[a-1], installed.map(&:full_name)
end
def test_self_install_permissions
@@ -137,8 +132,8 @@ class TestGem < Gem::TestCase
end
def test_self_install_permissions_umask_077
- umask = File.umask(077)
- assert_self_install_permissions
+ umask = File.umask(0o077)
+ assert_self_install_permissions(data_mode: 0o600)
ensure
File.umask(umask)
end
@@ -149,55 +144,55 @@ class TestGem < Gem::TestCase
def test_self_install_permissions_with_format_executable_and_non_standard_ruby_install_name
Gem::Installer.exec_format = nil
- ruby_install_name 'ruby27' do
+ ruby_install_name "ruby27" do
assert_self_install_permissions(format_executable: true)
end
ensure
Gem::Installer.exec_format = nil
end
- def assert_self_install_permissions(format_executable: false)
- mask = win_platform? ? 0700 : 0777
+ def assert_self_install_permissions(format_executable: false, data_mode: 0o640)
+ mask = Gem.win_platform? ? 0o700 : 0o777
options = {
- :dir_mode => 0500,
- :prog_mode => win_platform? ? 0410 : 0510,
- :data_mode => 0640,
- :wrappers => true,
- :format_executable => format_executable,
+ dir_mode: 0o500,
+ prog_mode: Gem.win_platform? ? 0o410 : 0o510,
+ data_mode: data_mode,
+ wrappers: true,
+ format_executable: format_executable,
}
Dir.chdir @tempdir do
- Dir.mkdir 'bin'
- Dir.mkdir 'data'
+ Dir.mkdir "bin"
+ Dir.mkdir "data"
- File.write 'bin/foo', "#!/usr/bin/env ruby\n"
- File.chmod 0755, 'bin/foo'
+ File.write "bin/foo", "#!/usr/bin/env ruby\n"
+ File.chmod 0o755, "bin/foo"
- File.write 'data/foo.txt', "blah\n"
+ File.write "data/foo.txt", "blah\n"
spec_fetcher do |f|
- f.gem 'foo', 1 do |s|
- s.executables = ['foo']
+ f.gem "foo", 1 do |s|
+ s.executables = ["foo"]
s.files = %w[bin/foo data/foo.txt]
end
end
- Gem.install 'foo', Gem::Requirement.default, options
+ Gem.install "foo", Gem::Requirement.default, options
end
prog_mode = (options[:prog_mode] & mask).to_s(8)
dir_mode = (options[:dir_mode] & mask).to_s(8)
data_mode = (options[:data_mode] & mask).to_s(8)
- prog_name = 'foo'
- prog_name = RbConfig::CONFIG['ruby_install_name'].sub('ruby', 'foo') if options[:format_executable]
+ prog_name = "foo"
+ prog_name = RbConfig::CONFIG["ruby_install_name"].sub("ruby", "foo") if options[:format_executable]
expected = {
"bin/#{prog_name}" => prog_mode,
- 'gems/foo-1' => dir_mode,
- 'gems/foo-1/bin' => dir_mode,
- 'gems/foo-1/data' => dir_mode,
- 'gems/foo-1/bin/foo' => prog_mode,
- 'gems/foo-1/data/foo.txt' => data_mode,
+ "gems/foo-1" => dir_mode,
+ "gems/foo-1/bin" => dir_mode,
+ "gems/foo-1/data" => dir_mode,
+ "gems/foo-1/bin/foo" => prog_mode,
+ "gems/foo-1/data/foo.txt" => data_mode,
}
# add Windows script
- expected["bin/#{prog_name}.bat"] = mask.to_s(8) if win_platform?
+ expected["bin/#{prog_name}.bat"] = mask.to_s(8) if Gem.win_platform?
result = {}
Dir.chdir @gemhome do
expected.each_key do |n|
@@ -206,83 +201,79 @@ class TestGem < Gem::TestCase
end
assert_equal(expected, result)
ensure
- File.chmod(0755, *Dir.glob(@gemhome + '/gems/**/').map {|path| path.tap(&Gem::UNTAINT) })
+ File.chmod(0o755, *Dir.glob(@gemhome + "/gems/**/"))
end
def test_require_missing
- save_loaded_features do
- assert_raise ::LoadError do
- require "test_require_missing"
- end
+ assert_raise ::LoadError do
+ require "test_require_missing"
end
end
def test_require_does_not_glob
- save_loaded_features do
- a1 = util_spec "a", "1", nil, "lib/a1.rb"
-
- install_specs a1
+ a1 = util_spec "a", "1", nil, "lib/a1.rb"
- assert_raise ::LoadError do
- require "a*"
- end
+ install_specs a1
- assert_equal [], loaded_spec_names
+ assert_raise ::LoadError do
+ require "a*"
end
+
+ assert_equal [], loaded_spec_names
end
def test_self_bin_path_active
- a1 = util_spec 'a', '1' do |s|
- s.executables = ['exec']
+ a1 = util_spec "a", "1" do |s|
+ s.executables = ["exec"]
end
- util_spec 'a', '2' do |s|
- s.executables = ['exec']
+ util_spec "a", "2" do |s|
+ s.executables = ["exec"]
end
a1.activate
- assert_match 'a-1/bin/exec', Gem.bin_path('a', 'exec', '>= 0')
+ assert_match "a-1/bin/exec", Gem.bin_path("a", "exec", ">= 0")
end
def test_self_bin_path_picking_newest
- a1 = util_spec 'a', '1' do |s|
- s.executables = ['exec']
+ a1 = util_spec "a", "1" do |s|
+ s.executables = ["exec"]
end
- a2 = util_spec 'a', '2' do |s|
- s.executables = ['exec']
+ a2 = util_spec "a", "2" do |s|
+ s.executables = ["exec"]
end
install_specs a1, a2
- assert_match 'a-2/bin/exec', Gem.bin_path('a', 'exec', '>= 0')
+ assert_match "a-2/bin/exec", Gem.bin_path("a", "exec", ">= 0")
end
def test_self_activate_bin_path_no_exec_name
e = assert_raise ArgumentError do
- Gem.activate_bin_path 'a'
+ Gem.activate_bin_path "a"
end
- assert_equal 'you must supply exec_name', e.message
+ assert_equal "you must supply exec_name", e.message
end
def test_activate_bin_path_resolves_eagerly
- a1 = util_spec 'a', '1' do |s|
- s.executables = ['exec']
- s.add_dependency 'b'
+ a1 = util_spec "a", "1" do |s|
+ s.executables = ["exec"]
+ s.add_dependency "b"
end
- b1 = util_spec 'b', '1' do |s|
- s.add_dependency 'c', '2'
+ b1 = util_spec "b", "1" do |s|
+ s.add_dependency "c", "2"
end
- b2 = util_spec 'b', '2' do |s|
- s.add_dependency 'c', '1'
+ b2 = util_spec "b", "2" do |s|
+ s.add_dependency "c", "1"
end
- c1 = util_spec 'c', '1'
- c2 = util_spec 'c', '2'
+ c1 = util_spec "c", "1"
+ c2 = util_spec "c", "2"
install_specs c1, c2, b1, b2, a1
@@ -290,27 +281,27 @@ class TestGem < Gem::TestCase
# If we didn't eagerly resolve, this would activate c-2 and then the
# finish_resolve would cause a conflict
- gem 'c'
+ gem "c"
Gem.finish_resolve
assert_equal %w[a-1 b-2 c-1], loaded_spec_names
end
def test_activate_bin_path_does_not_error_if_a_gem_thats_not_finally_activated_has_orphaned_dependencies
- a1 = util_spec 'a', '1' do |s|
- s.executables = ['exec']
- s.add_dependency 'b'
+ a1 = util_spec "a", "1" do |s|
+ s.executables = ["exec"]
+ s.add_dependency "b"
end
- b1 = util_spec 'b', '1' do |s|
- s.add_dependency 'c', '1'
+ b1 = util_spec "b", "1" do |s|
+ s.add_dependency "c", "1"
end
- b2 = util_spec 'b', '2' do |s|
- s.add_dependency 'c', '2'
+ b2 = util_spec "b", "2" do |s|
+ s.add_dependency "c", "2"
end
- c2 = util_spec 'c', '2'
+ c2 = util_spec "c", "2"
install_specs c2, b1, b2, a1
@@ -322,20 +313,20 @@ class TestGem < Gem::TestCase
end
def test_activate_bin_path_raises_a_meaningful_error_if_a_gem_thats_finally_activated_has_orphaned_dependencies
- a1 = util_spec 'a', '1' do |s|
- s.executables = ['exec']
- s.add_dependency 'b'
+ a1 = util_spec "a", "1" do |s|
+ s.executables = ["exec"]
+ s.add_dependency "b"
end
- b1 = util_spec 'b', '1' do |s|
- s.add_dependency 'c', '1'
+ b1 = util_spec "b", "1" do |s|
+ s.add_dependency "c", "1"
end
- b2 = util_spec 'b', '2' do |s|
- s.add_dependency 'c', '2'
+ b2 = util_spec "b", "2" do |s|
+ s.add_dependency "c", "2"
end
- c1 = util_spec 'c', '1'
+ c1 = util_spec "c", "1"
install_specs c1, b1, b2, a1
@@ -349,8 +340,8 @@ class TestGem < Gem::TestCase
end
def test_activate_bin_path_in_debug_mode
- a1 = util_spec 'a', '1' do |s|
- s.executables = ['exec']
+ a1 = util_spec "a", "1" do |s|
+ s.executables = ["exec"]
end
install_specs a1
@@ -364,54 +355,19 @@ class TestGem < Gem::TestCase
assert status.success?, output
end
- def test_activate_bin_path_gives_proper_error_for_bundler
- bundler = util_spec 'bundler', '2' do |s|
- s.executables = ['bundle']
- end
-
- install_specs bundler
-
- File.open("Gemfile.lock", "w") do |f|
- f.write <<-L.gsub(/ {8}/, "")
- GEM
- remote: https://rubygems.org/
- specs:
-
- PLATFORMS
- ruby
-
- DEPENDENCIES
-
- BUNDLED WITH
- 9999
- L
- end
-
- File.open("Gemfile", "w") {|f| f.puts('source "https://rubygems.org"') }
-
- e = assert_raise Gem::GemNotFoundException do
- load Gem.activate_bin_path("bundler", "bundle", ">= 0.a")
- end
-
- assert_includes e.message, "Could not find 'bundler' (9999) required by your #{File.expand_path("Gemfile.lock")}."
- assert_includes e.message, "To update to the latest version installed on your system, run `bundle update --bundler`."
- assert_includes e.message, "To install the missing version, run `gem install bundler:9999`"
- refute_includes e.message, "can't find gem bundler (>= 0.a) with executable bundle"
- end
-
def test_activate_bin_path_selects_exact_bundler_version_if_present
- bundler_latest = util_spec 'bundler', '2.0.1' do |s|
- s.executables = ['bundle']
+ bundler_latest = util_spec "bundler", "2.0.1" do |s|
+ s.executables = ["bundle"]
end
- bundler_previous = util_spec 'bundler', '2.0.0' do |s|
- s.executables = ['bundle']
+ bundler_previous = util_spec "bundler", "2.0.0" do |s|
+ s.executables = ["bundle"]
end
install_specs bundler_latest, bundler_previous
File.open("Gemfile.lock", "w") do |f|
- f.write <<-L.gsub(/ {8}/, "")
+ f.write <<~L
GEM
remote: https://rubygems.org/
specs:
@@ -434,18 +390,18 @@ class TestGem < Gem::TestCase
end
def test_activate_bin_path_respects_underscore_selection_if_given
- bundler_latest = util_spec 'bundler', '2.0.1' do |s|
- s.executables = ['bundle']
+ bundler_latest = util_spec "bundler", "2.0.1" do |s|
+ s.executables = ["bundle"]
end
- bundler_previous = util_spec 'bundler', '1.17.3' do |s|
- s.executables = ['bundle']
+ bundler_previous = util_spec "bundler", "1.17.3" do |s|
+ s.executables = ["bundle"]
end
install_specs bundler_latest, bundler_previous
File.open("Gemfile.lock", "w") do |f|
- f.write <<-L.gsub(/ {8}/, "")
+ f.write <<~L
GEM
remote: https://rubygems.org/
specs:
@@ -469,7 +425,7 @@ class TestGem < Gem::TestCase
def test_activate_bin_path_gives_proper_error_for_bundler_when_underscore_selection_given
File.open("Gemfile.lock", "w") do |f|
- f.write <<-L.gsub(/ {8}/, "")
+ f.write <<~L
GEM
remote: https://rubygems.org/
specs:
@@ -495,57 +451,57 @@ class TestGem < Gem::TestCase
def test_self_bin_path_no_exec_name
e = assert_raise ArgumentError do
- Gem.bin_path 'a'
+ Gem.bin_path "a"
end
- assert_equal 'you must supply exec_name', e.message
+ assert_equal "you must supply exec_name", e.message
end
def test_self_bin_path_bin_name
install_specs util_exec_gem
- assert_equal @abin_path, Gem.bin_path('a', 'abin')
+ assert_equal @abin_path, Gem.bin_path("a", "abin")
end
def test_self_bin_path_bin_name_version
install_specs util_exec_gem
- assert_equal @abin_path, Gem.bin_path('a', 'abin', '4')
+ assert_equal @abin_path, Gem.bin_path("a", "abin", "4")
end
def test_self_bin_path_nonexistent_binfile
- util_spec 'a', '2' do |s|
- s.executables = ['exec']
+ util_spec "a", "2" do |s|
+ s.executables = ["exec"]
end
assert_raise(Gem::GemNotFoundException) do
- Gem.bin_path('a', 'other', '2')
+ Gem.bin_path("a", "other", "2")
end
end
def test_self_bin_path_no_bin_file
- util_spec 'a', '1'
+ util_spec "a", "1"
assert_raise(ArgumentError) do
- Gem.bin_path('a', nil, '1')
+ Gem.bin_path("a", nil, "1")
end
end
def test_self_bin_path_not_found
assert_raise(Gem::GemNotFoundException) do
- Gem.bin_path('non-existent', 'blah')
+ Gem.bin_path("non-existent", "blah")
end
end
def test_self_bin_path_bin_file_gone_in_latest
install_specs util_exec_gem
- spec = util_spec 'a', '10' do |s|
+ spec = util_spec "a", "10" do |s|
s.executables = []
end
install_specs spec
- assert_equal @abin_path, Gem.bin_path('a', 'abin')
+ assert_equal @abin_path, Gem.bin_path("a", "abin")
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))
+ 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
@@ -560,7 +516,10 @@ class TestGem < Gem::TestCase
Gem.clear_paths
- assert_nil Gem::Specification.send(:class_variable_get, :@@all)
+ with_env("GEM_HOME" => "foo", "GEM_PATH" => "bar") do
+ assert_equal("foo", Gem.dir)
+ assert_equal("bar", Gem.path.first)
+ end
end
def test_self_configuration
@@ -574,21 +533,21 @@ class TestGem < Gem::TestCase
foo = nil
Dir.chdir @tempdir do
- FileUtils.mkdir_p 'data'
- File.open File.join('data', 'foo.txt'), 'w' do |fp|
- fp.puts 'blah'
+ FileUtils.mkdir_p "data"
+ File.open File.join("data", "foo.txt"), "w" do |fp|
+ fp.puts "blah"
end
- foo = util_spec 'foo' do |s|
+ foo = util_spec "foo" do |s|
s.files = %w[data/foo.txt]
end
install_gem foo
end
- gem 'foo'
+ gem "foo"
- expected = File.join @gemhome, 'gems', foo.full_name, 'data', 'foo'
+ expected = File.join @gemhome, "gems", foo.full_name, "data", "foo"
assert_equal expected, Gem::Specification.find_by_name("foo").datadir
end
@@ -600,25 +559,25 @@ class TestGem < Gem::TestCase
end
def test_self_default_exec_format
- ruby_install_name 'ruby' do
- assert_equal '%s', Gem.default_exec_format
+ ruby_install_name "ruby" do
+ assert_equal "%s", Gem.default_exec_format
end
end
def test_self_default_exec_format_18
- ruby_install_name 'ruby18' do
- assert_equal '%s18', Gem.default_exec_format
+ ruby_install_name "ruby18" do
+ assert_equal "%s18", Gem.default_exec_format
end
end
def test_self_default_exec_format_jruby
- ruby_install_name 'jruby' do
- assert_equal 'j%s', Gem.default_exec_format
+ ruby_install_name "jruby" do
+ assert_equal "j%s", Gem.default_exec_format
end
end
def test_default_path
- vendordir(File.join(@tempdir, 'vendor')) do
+ vendordir(File.join(@tempdir, "vendor")) do
FileUtils.rm_rf Gem.user_home
expected = [Gem.default_dir]
@@ -638,7 +597,7 @@ class TestGem < Gem::TestCase
end
def test_default_path_user_home
- vendordir(File.join(@tempdir, 'vendor')) do
+ vendordir(File.join(@tempdir, "vendor")) do
expected = [Gem.user_dir, Gem.default_dir]
assert_equal expected, Gem.default_path
@@ -646,7 +605,7 @@ class TestGem < Gem::TestCase
end
def test_default_path_vendor_dir
- vendordir(File.join(@tempdir, 'vendor')) do
+ vendordir(File.join(@tempdir, "vendor")) do
FileUtils.mkdir_p Gem.vendor_dir
FileUtils.rm_rf Gem.user_home
@@ -661,25 +620,6 @@ class TestGem < Gem::TestCase
assert_equal %w[https://rubygems.org/], Gem.default_sources
end
- def test_self_use_gemdeps
- with_rubygems_gemdeps('-') do
- FileUtils.mkdir_p 'detect/a/b'
- FileUtils.mkdir_p 'detect/a/Isolate'
-
- FileUtils.touch 'detect/Isolate'
-
- begin
- Dir.chdir 'detect/a/b'
-
- Gem.use_gemdeps
-
- assert_equal add_bundler_full_name([]), loaded_spec_names
- ensure
- Dir.chdir @tempdir
- end
- end
- end
-
def test_self_dir
assert_equal @gemhome, Gem.dir
end
@@ -690,25 +630,25 @@ class TestGem < Gem::TestCase
Gem.ensure_gem_subdirectories @gemhome
- assert_path_exist File.join @gemhome, 'build_info'
- assert_path_exist File.join @gemhome, 'cache'
- assert_path_exist File.join @gemhome, 'doc'
- assert_path_exist File.join @gemhome, 'extensions'
- assert_path_exist File.join @gemhome, 'gems'
- assert_path_exist File.join @gemhome, 'specifications'
+ assert_path_exist File.join @gemhome, "build_info"
+ assert_path_exist File.join @gemhome, "cache"
+ assert_path_exist File.join @gemhome, "doc"
+ assert_path_exist File.join @gemhome, "extensions"
+ assert_path_exist File.join @gemhome, "gems"
+ assert_path_exist File.join @gemhome, "specifications"
end
def test_self_ensure_gem_directories_permissions
FileUtils.rm_r @gemhome
Gem.use_paths @gemhome
- Gem.ensure_gem_subdirectories @gemhome, 0750
+ Gem.ensure_gem_subdirectories @gemhome, 0o750
assert_directory_exists File.join(@gemhome, "cache")
- assert_equal 0750, File::Stat.new(@gemhome).mode & 0777
- assert_equal 0750, File::Stat.new(File.join(@gemhome, "cache")).mode & 0777
- end unless win_platform?
+ assert_equal 0o750, File::Stat.new(@gemhome).mode & 0o777
+ assert_equal 0o750, File::Stat.new(File.join(@gemhome, "cache")).mode & 0o777
+ end unless Gem.win_platform?
def test_self_ensure_gem_directories_safe_permissions
FileUtils.rm_r @gemhome
@@ -718,17 +658,21 @@ class TestGem < Gem::TestCase
File.umask 0
Gem.ensure_gem_subdirectories @gemhome
- assert_equal 0, File::Stat.new(@gemhome).mode & 002
- assert_equal 0, File::Stat.new(File.join(@gemhome, "cache")).mode & 002
+ assert_equal 0, File::Stat.new(@gemhome).mode & 0o002
+ assert_equal 0, File::Stat.new(File.join(@gemhome, "cache")).mode & 0o002
ensure
File.umask old_umask
- end unless win_platform?
+ end unless Gem.win_platform?
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
- refute File.exist?(File.join(@tempdir, 'a')),
- "manually remove #{File.join @tempdir, 'a'}, tests are broken"
+ gemdir = File.join @tempdir, "a/b/c/gemdir"
+ begin
+ FileUtils.rm_rf File.join(@tempdir, "a")
+ rescue StandardError
+ nil
+ end
+ refute File.exist?(File.join(@tempdir, "a")),
+ "manually remove #{File.join @tempdir, "a"}, tests are broken"
Gem.use_paths gemdir
Gem.ensure_gem_subdirectories gemdir
@@ -736,53 +680,61 @@ class TestGem < Gem::TestCase
assert_directory_exists util_cache_dir
end
- unless win_platform? || Process.uid.zero? # only for FS that support write protection
+ unless Gem.win_platform? || Process.uid.zero? # 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
+ begin
+ FileUtils.rm_r gemdir
+ rescue StandardError
+ nil
+ end
refute File.exist?(gemdir), "manually remove #{gemdir}, tests are broken"
FileUtils.mkdir_p gemdir
- FileUtils.chmod 0400, gemdir
+ FileUtils.chmod 0o400, gemdir
Gem.use_paths gemdir
Gem.ensure_gem_subdirectories gemdir
refute File.exist?(util_cache_dir)
ensure
- FileUtils.chmod 0600, gemdir
+ FileUtils.chmod 0o600, 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
+ begin
+ FileUtils.rm_r parent
+ rescue StandardError
+ nil
+ end
refute File.exist?(parent), "manually remove #{parent}, tests are broken"
FileUtils.mkdir_p parent
- FileUtils.chmod 0400, parent
+ FileUtils.chmod 0o400, parent
Gem.use_paths(gemdir)
Gem.ensure_gem_subdirectories gemdir
refute File.exist? File.join(gemdir, "gems")
ensure
- FileUtils.chmod 0600, parent
+ FileUtils.chmod 0o600, parent
end
def test_self_ensure_gem_directories_non_existent_paths
- Gem.ensure_gem_subdirectories '/proc/0123456789/bogus' # should not raise
- Gem.ensure_gem_subdirectories 'classpath:/bogus/x' # JRuby embed scenario
+ Gem.ensure_gem_subdirectories "/proc/0123456789/bogus" # should not raise
+ Gem.ensure_gem_subdirectories "classpath:/bogus/x" # JRuby embed scenario
end
end
def test_self_extension_dir_shared
- enable_shared 'yes' do
+ enable_shared "yes" do
assert_equal Gem.ruby_api_version, Gem.extension_api_version
end
end
def test_self_extension_dir_static
- enable_shared 'no' do
+ enable_shared "no" do
assert_equal "#{Gem.ruby_api_version}-static", Gem.extension_api_version
end
end
@@ -791,14 +743,14 @@ class TestGem < Gem::TestCase
cwd = File.expand_path("test/rubygems", PROJECT_DIR)
$LOAD_PATH.unshift cwd
- discover_path = File.join 'lib', 'sff', 'discover.rb'
+ discover_path = File.join "lib", "sff", "discover.rb"
foo1, foo2 = %w[1 2].map do |version|
- spec = quick_gem 'sff', version do |s|
+ spec = quick_gem "sff", version do |s|
s.files << discover_path
end
- write_file(File.join 'gems', spec.full_name, discover_path) do |fp|
+ write_file(File.join("gems", spec.full_name, discover_path)) do |fp|
fp.puts "# #{spec.full_name}"
end
@@ -808,65 +760,29 @@ class TestGem < Gem::TestCase
Gem.refresh
expected = [
- File.expand_path('test/rubygems/sff/discover.rb', PROJECT_DIR),
+ File.expand_path("test/rubygems/sff/discover.rb", PROJECT_DIR),
File.join(foo2.full_gem_path, discover_path),
File.join(foo1.full_gem_path, discover_path),
]
- assert_equal expected, Gem.find_files('sff/discover')
- assert_equal expected, Gem.find_files('sff/**.rb'), '[ruby-core:31730]'
+ assert_equal expected, Gem.find_files("sff/discover")
+ assert_equal expected, Gem.find_files("sff/**.rb"), "[ruby-core:31730]"
ensure
assert_equal cwd, $LOAD_PATH.shift
end
- def test_self_find_files_with_gemfile
- cwd = File.expand_path("test/rubygems", PROJECT_DIR)
- actual_load_path = $LOAD_PATH.unshift(cwd).dup
-
- discover_path = File.join 'lib', 'sff', 'discover.rb'
-
- foo1, _ = %w[1 2].map do |version|
- spec = quick_gem 'sff', version do |s|
- s.files << discover_path
- end
-
- write_file(File.join 'gems', spec.full_name, discover_path) do |fp|
- fp.puts "# #{spec.full_name}"
- end
-
- spec
- end
- Gem.refresh
-
- write_file(File.join Dir.pwd, 'Gemfile') do |fp|
- fp.puts "source 'https://rubygems.org'"
- fp.puts "gem '#{foo1.name}', '#{foo1.version}'"
- end
- Gem.use_gemdeps(File.join Dir.pwd, 'Gemfile')
-
- expected = [
- File.expand_path('test/rubygems/sff/discover.rb', PROJECT_DIR),
- File.join(foo1.full_gem_path, discover_path),
- ].sort
-
- assert_equal expected, Gem.find_files('sff/discover').sort
- assert_equal expected, Gem.find_files('sff/**.rb').sort, '[ruby-core:31730]'
- ensure
- assert_equal cwd, actual_load_path.shift unless Gem.java_platform?
- end
-
def test_self_find_latest_files
cwd = File.expand_path("test/rubygems", PROJECT_DIR)
$LOAD_PATH.unshift cwd
- discover_path = File.join 'lib', 'sff', 'discover.rb'
+ discover_path = File.join "lib", "sff", "discover.rb"
_, foo2 = %w[1 2].map do |version|
- spec = quick_gem 'sff', version do |s|
+ spec = quick_gem "sff", version do |s|
s.files << discover_path
end
- write_file(File.join 'gems', spec.full_name, discover_path) do |fp|
+ write_file(File.join("gems", spec.full_name, discover_path)) do |fp|
fp.puts "# #{spec.full_name}"
end
@@ -876,59 +792,103 @@ class TestGem < Gem::TestCase
Gem.refresh
expected = [
- File.expand_path('test/rubygems/sff/discover.rb', PROJECT_DIR),
+ File.expand_path("test/rubygems/sff/discover.rb", PROJECT_DIR),
File.join(foo2.full_gem_path, discover_path),
]
- assert_equal expected, Gem.find_latest_files('sff/discover')
- assert_equal expected, Gem.find_latest_files('sff/**.rb'), '[ruby-core:31730]'
+ assert_equal expected, Gem.find_latest_files("sff/discover")
+ assert_equal expected, Gem.find_latest_files("sff/**.rb"), "[ruby-core:31730]"
ensure
assert_equal cwd, $LOAD_PATH.shift
end
def test_self_latest_spec_for
gems = spec_fetcher do |fetcher|
- fetcher.spec 'a', 1
- fetcher.spec 'a', '3.a'
- fetcher.spec 'a', 2
+ fetcher.spec "a", 1
+ fetcher.spec "a", "3.a"
+ fetcher.spec "a", 2
end
- spec = Gem.latest_spec_for 'a'
+ spec = Gem.latest_spec_for "a"
+
+ assert_equal gems["a-2"], spec
+ end
- assert_equal gems['a-2'], spec
+ def test_self_latest_spec_for_multiple_sources
+ uri = "https://example.sample.com/"
+ source = Gem::Source.new(uri)
+ source_list = Gem::SourceList.new
+ source_list << Gem::Source.new(@uri)
+ source_list << source
+ Gem.sources.replace source_list
+
+ spec_fetcher(uri) do |fetcher|
+ fetcher.spec "a", 1.1
+ end
+
+ gems = spec_fetcher do |fetcher|
+ fetcher.spec "a", 1
+ fetcher.spec "a", "3.a"
+ fetcher.spec "a", 2
+ end
+ spec = Gem.latest_spec_for "a"
+ assert_equal gems["a-2"], spec
end
def test_self_latest_rubygems_version
spec_fetcher do |fetcher|
- fetcher.spec 'rubygems-update', '1.8.23'
- fetcher.spec 'rubygems-update', '1.8.24'
- fetcher.spec 'rubygems-update', '2.0.0.preview3'
+ fetcher.spec "rubygems-update", "1.8.23"
+ fetcher.spec "rubygems-update", "1.8.24"
+ fetcher.spec "rubygems-update", "2.0.0.preview3"
end
version = Gem.latest_rubygems_version
- assert_equal Gem::Version.new('1.8.24'), version
+ assert_equal Gem::Version.new("1.8.24"), version
end
def test_self_latest_version_for
spec_fetcher do |fetcher|
- fetcher.spec 'a', 1
- fetcher.spec 'a', 2
- fetcher.spec 'a', '3.a'
+ fetcher.spec "a", 1
+ fetcher.spec "a", 2
+ fetcher.spec "a", "3.a"
+ end
+
+ version = Gem.latest_version_for "a"
+
+ assert_equal Gem::Version.new(2), version
+ end
+
+ def test_self_latest_version_for_multiple_sources
+ uri = "https://example.sample.com/"
+ source = Gem::Source.new(uri)
+ source_list = Gem::SourceList.new
+ source_list << Gem::Source.new(@uri)
+ source_list << source
+ Gem.sources.replace source_list
+
+ spec_fetcher(uri) do |fetcher|
+ fetcher.spec "a", 1.1
+ end
+
+ spec_fetcher do |fetcher|
+ fetcher.spec "a", 1
+ fetcher.spec "a", 2
+ fetcher.spec "a", "3.a"
end
- version = Gem.latest_version_for 'a'
+ version = Gem.latest_version_for "a"
assert_equal Gem::Version.new(2), version
end
def test_self_loaded_specs
- foo = util_spec 'foo'
+ foo = util_spec "foo"
install_gem foo
foo.activate
- assert_equal true, Gem.loaded_specs.keys.include?('foo')
+ assert_equal true, Gem.loaded_specs.keys.include?("foo")
end
def test_self_path
@@ -948,7 +908,7 @@ class TestGem < Gem::TestCase
path_count = Gem.path.size
Gem.clear_paths
- ENV['GEM_PATH'] = @additional.join(File::PATH_SEPARATOR)
+ ENV["GEM_PATH"] = @additional.join(File::PATH_SEPARATOR)
assert_equal @additional, Gem.path[0,2]
@@ -960,10 +920,10 @@ class TestGem < Gem::TestCase
def test_self_path_duplicate
Gem.clear_paths
util_ensure_gem_dirs
- dirs = @additional + [@gemhome] + [File.join(@tempdir, 'a')]
+ dirs = @additional + [@gemhome] + [File.join(@tempdir, "a")]
- ENV['GEM_HOME'] = @gemhome
- ENV['GEM_PATH'] = dirs.join File::PATH_SEPARATOR
+ ENV["GEM_HOME"] = @gemhome
+ ENV["GEM_PATH"] = dirs.join File::PATH_SEPARATOR
assert_equal @gemhome, Gem.dir
@@ -975,8 +935,8 @@ class TestGem < Gem::TestCase
Gem.clear_paths
util_ensure_gem_dirs
- ENV['GEM_HOME'] = @gemhome
- ENV['GEM_PATH'] = @additional.join(File::PATH_SEPARATOR)
+ ENV["GEM_HOME"] = @gemhome
+ ENV["GEM_PATH"] = @additional.join(File::PATH_SEPARATOR)
assert_equal @gemhome, Gem.dir
@@ -993,38 +953,38 @@ class TestGem < Gem::TestCase
end
def test_self_prefix_libdir
- orig_libdir = RbConfig::CONFIG['libdir']
- RbConfig::CONFIG['libdir'] = PROJECT_DIR
+ orig_libdir = RbConfig::CONFIG["libdir"]
+ RbConfig::CONFIG["libdir"] = PROJECT_DIR
assert_nil Gem.prefix
ensure
- RbConfig::CONFIG['libdir'] = orig_libdir
+ RbConfig::CONFIG["libdir"] = orig_libdir
end
def test_self_prefix_sitelibdir
- orig_sitelibdir = RbConfig::CONFIG['sitelibdir']
- RbConfig::CONFIG['sitelibdir'] = PROJECT_DIR
+ orig_sitelibdir = RbConfig::CONFIG["sitelibdir"]
+ RbConfig::CONFIG["sitelibdir"] = PROJECT_DIR
assert_nil Gem.prefix
ensure
- RbConfig::CONFIG['sitelibdir'] = orig_sitelibdir
+ RbConfig::CONFIG["sitelibdir"] = orig_sitelibdir
end
def test_self_read_binary
- File.open 'test', 'w' do |io|
+ File.open "test", "w" do |io|
io.write "\xCF\x80"
end
- assert_equal ["\xCF", "\x80"], Gem.read_binary('test').chars.to_a
+ assert_equal ["\xCF", "\x80"], Gem.read_binary("test").chars.to_a
- pend 'chmod not supported' if Gem.win_platform?
+ pend "chmod not supported" if Gem.win_platform?
begin
- File.chmod 0444, 'test'
+ File.chmod 0o444, "test"
- assert_equal ["\xCF", "\x80"], Gem.read_binary('test').chars.to_a
+ assert_equal ["\xCF", "\x80"], Gem.read_binary("test").chars.to_a
ensure
- File.chmod 0644, 'test'
+ File.chmod 0o644, "test"
end
end
@@ -1062,7 +1022,7 @@ class TestGem < Gem::TestCase
Gem.refresh
- Gem::Specification.each{|spec| assert spec.activated? if spec == s }
+ Gem::Specification.each {|spec| assert spec.activated? if spec == s }
Gem.loaded_specs.delete(s)
Gem.refresh
@@ -1085,88 +1045,73 @@ class TestGem < Gem::TestCase
end
def test_self_ruby_api_version
- orig_ruby_version, RbConfig::CONFIG['ruby_version'] = RbConfig::CONFIG['ruby_version'], '1.2.3'
+ orig_ruby_version = RbConfig::CONFIG["ruby_version"]
+ RbConfig::CONFIG["ruby_version"] = "1.2.3"
Gem.instance_variable_set :@ruby_api_version, nil
- assert_equal '1.2.3', Gem.ruby_api_version
+ assert_equal "1.2.3", Gem.ruby_api_version
ensure
Gem.instance_variable_set :@ruby_api_version, nil
- RbConfig::CONFIG['ruby_version'] = orig_ruby_version
+ RbConfig::CONFIG["ruby_version"] = orig_ruby_version
end
def test_self_env_requirement
- ENV["GEM_REQUIREMENT_FOO"] = '>= 1.2.3'
- ENV["GEM_REQUIREMENT_BAR"] = '1.2.3'
- ENV["GEM_REQUIREMENT_BAZ"] = 'abcd'
+ ENV["GEM_REQUIREMENT_FOO"] = ">= 1.2.3"
+ ENV["GEM_REQUIREMENT_BAR"] = "1.2.3"
+ ENV["GEM_REQUIREMENT_BAZ"] = "abcd"
- assert_equal Gem::Requirement.create('>= 1.2.3'), Gem.env_requirement('foo')
- assert_equal Gem::Requirement.create('1.2.3'), Gem.env_requirement('bAr')
- assert_raise(Gem::Requirement::BadRequirementError) { Gem.env_requirement('baz') }
- assert_equal Gem::Requirement.default, Gem.env_requirement('qux')
- end
-
- def test_self_ruby_version_with_patchlevel_less_ancient_rubies
- util_set_RUBY_VERSION '1.8.5'
-
- assert_equal Gem::Version.new('1.8.5'), Gem.ruby_version
- ensure
- util_restore_RUBY_VERSION
- end
-
- def test_self_ruby_version_with_release
- util_set_RUBY_VERSION '1.8.6', 287
-
- assert_equal Gem::Version.new('1.8.6.287'), Gem.ruby_version
- ensure
- util_restore_RUBY_VERSION
+ assert_equal Gem::Requirement.create(">= 1.2.3"), Gem.env_requirement("foo")
+ assert_equal Gem::Requirement.create("1.2.3"), Gem.env_requirement("bAr")
+ assert_raise(Gem::Requirement::BadRequirementError) { Gem.env_requirement("baz") }
+ assert_equal Gem::Requirement.default, Gem.env_requirement("qux")
end
def test_self_ruby_version_with_non_mri_implementations
- util_set_RUBY_VERSION '2.5.0', 0, 60928, 'jruby 9.2.0.0 (2.5.0) 2018-05-24 81156a8 OpenJDK 64-Bit Server VM 25.171-b11 on 1.8.0_171-8u171-b11-0ubuntu0.16.04.1-b11 [linux-x86_64]'
+ util_set_RUBY_VERSION "2.5.0", 0, 60_928, "jruby 9.2.0.0 (2.5.0) 2018-05-24 81156a8 OpenJDK 64-Bit Server VM 25.171-b11 on 1.8.0_171-8u171-b11-0ubuntu0.16.04.1-b11 [linux-x86_64]"
- assert_equal Gem::Version.new('2.5.0'), Gem.ruby_version
+ assert_equal Gem::Version.new("2.5.0"), Gem.ruby_version
ensure
util_restore_RUBY_VERSION
end
def test_self_ruby_version_with_svn_prerelease
- util_set_RUBY_VERSION '2.6.0', -1, 63539, 'ruby 2.6.0preview2 (2018-05-31 trunk 63539) [x86_64-linux]'
+ util_set_RUBY_VERSION "2.6.0", -1, 63_539, "ruby 2.6.0preview2 (2018-05-31 trunk 63539) [x86_64-linux]"
- assert_equal Gem::Version.new('2.6.0.preview2'), Gem.ruby_version
+ assert_equal Gem::Version.new("2.6.0.preview2"), Gem.ruby_version
ensure
util_restore_RUBY_VERSION
end
def test_self_ruby_version_with_git_prerelease
- util_set_RUBY_VERSION '2.7.0', -1, 'b563439274a402e33541f5695b1bfd4ac1085638', 'ruby 2.7.0preview3 (2019-11-23 master b563439274) [x86_64-linux]'
+ util_set_RUBY_VERSION "2.7.0", -1, "b563439274a402e33541f5695b1bfd4ac1085638", "ruby 2.7.0preview3 (2019-11-23 master b563439274) [x86_64-linux]"
- assert_equal Gem::Version.new('2.7.0.preview3'), Gem.ruby_version
+ assert_equal Gem::Version.new("2.7.0.preview3"), Gem.ruby_version
ensure
util_restore_RUBY_VERSION
end
def test_self_ruby_version_with_non_mri_implementations_with_mri_prerelase_compatibility
- util_set_RUBY_VERSION '2.6.0', -1, 63539, 'weirdjruby 9.2.0.0 (2.6.0preview2) 2018-05-24 81156a8 OpenJDK 64-Bit Server VM 25.171-b11 on 1.8.0_171-8u171-b11-0ubuntu0.16.04.1-b11 [linux-x86_64]', 'weirdjruby', '9.2.0.0'
+ util_set_RUBY_VERSION "2.6.0", -1, 63_539, "weirdjruby 9.2.0.0 (2.6.0preview2) 2018-05-24 81156a8 OpenJDK 64-Bit Server VM 25.171-b11 on 1.8.0_171-8u171-b11-0ubuntu0.16.04.1-b11 [linux-x86_64]", "weirdjruby", "9.2.0.0"
- assert_equal Gem::Version.new('2.6.0.preview2'), Gem.ruby_version
+ assert_equal Gem::Version.new("2.6.0.preview2"), Gem.ruby_version
ensure
util_restore_RUBY_VERSION
end
def test_self_ruby_version_with_svn_trunk
- util_set_RUBY_VERSION '1.9.2', -1, 23493, 'ruby 1.9.2dev (2009-05-20 trunk 23493) [x86_64-linux]'
+ util_set_RUBY_VERSION "1.9.2", -1, 23_493, "ruby 1.9.2dev (2009-05-20 trunk 23493) [x86_64-linux]"
- assert_equal Gem::Version.new('1.9.2.dev'), Gem.ruby_version
+ assert_equal Gem::Version.new("1.9.2.dev"), Gem.ruby_version
ensure
util_restore_RUBY_VERSION
end
def test_self_ruby_version_with_git_master
- util_set_RUBY_VERSION '2.7.0', -1, '5de284ec78220e75643f89b454ce999da0c1c195', 'ruby 2.7.0dev (2019-12-23T01:37:30Z master 5de284ec78) [x86_64-linux]'
+ util_set_RUBY_VERSION "2.7.0", -1, "5de284ec78220e75643f89b454ce999da0c1c195", "ruby 2.7.0dev (2019-12-23T01:37:30Z master 5de284ec78) [x86_64-linux]"
- assert_equal Gem::Version.new('2.7.0.dev'), Gem.ruby_version
+ assert_equal Gem::Version.new("2.7.0.dev"), Gem.ruby_version
ensure
util_restore_RUBY_VERSION
end
@@ -1176,7 +1121,7 @@ class TestGem < Gem::TestCase
end
def test_self_paths_eq
- other = File.join @tempdir, 'other'
+ other = File.join @tempdir, "other"
path = [@userhome, other].join File::PATH_SEPARATOR
#
@@ -1189,12 +1134,12 @@ class TestGem < Gem::TestCase
end
def test_self_paths_eq_nonexistent_home
- ENV['GEM_HOME'] = @gemhome
+ ENV["GEM_HOME"] = @gemhome
Gem.clear_paths
- other = File.join @tempdir, 'other'
+ other = File.join @tempdir, "other"
- ENV['HOME'] = other
+ ENV["HOME"] = other
Gem.paths = { "GEM_PATH" => other }
@@ -1273,74 +1218,73 @@ class TestGem < Gem::TestCase
end
def test_try_activate_returns_true_for_activated_specs
- b = util_spec 'b', '1.0' do |spec|
- spec.files << 'lib/b.rb'
+ b = util_spec "b", "1.0" do |spec|
+ spec.files << "lib/b.rb"
end
install_specs b
- assert Gem.try_activate('b'), 'try_activate should return true'
- assert Gem.try_activate('b'), 'try_activate should still return true'
+ assert Gem.try_activate("b"), "try_activate should return true"
+ assert Gem.try_activate("b"), "try_activate should still return true"
end
def test_spec_order_is_consistent
- b1 = util_spec 'b', '1.0'
- b2 = util_spec 'b', '2.0'
- b3 = util_spec 'b', '3.0'
+ b1 = util_spec "b", "1.0"
+ b2 = util_spec "b", "2.0"
+ b3 = util_spec "b", "3.0"
install_specs b1, b2, b3
- specs1 = Gem::Specification.stubs.find_all {|s| s.name == 'b' }
+ specs1 = Gem::Specification.stubs.find_all {|s| s.name == "b" }
Gem::Specification.reset
- specs2 = Gem::Specification.stubs_for('b')
+ specs2 = Gem::Specification.stubs_for("b")
assert_equal specs1.map(&:version), specs2.map(&:version)
end
def test_self_try_activate_missing_dep
- b = util_spec 'b', '1.0'
- a = util_spec 'a', '1.0', 'b' => '>= 1.0'
+ b = util_spec "b", "1.0"
+ a = util_spec "a", "1.0", "b" => ">= 1.0"
install_specs b, a
uninstall_gem b
- a_file = File.join a.gem_dir, 'lib', 'a_file.rb'
+ a_file = File.join a.gem_dir, "lib", "a_file.rb"
write_file a_file do |io|
- io.puts '# a_file.rb'
+ io.puts "# a_file.rb"
end
e = assert_raise Gem::MissingSpecError do
- Gem.try_activate 'a_file'
+ Gem.try_activate "a_file"
end
- assert_match %r{Could not find 'b' }, e.message
- assert_match %r{at: #{a.spec_file}}, e.message
+ assert_include(e.message, "Could not find 'b' ")
+ assert_include(e.message, "at: #{a.spec_file}")
end
def test_self_try_activate_missing_prerelease
- b = util_spec 'b', '1.0rc1'
- a = util_spec 'a', '1.0rc1', 'b' => '1.0rc1'
+ b = util_spec "b", "1.0rc1"
+ a = util_spec "a", "1.0rc1", "b" => "1.0rc1"
install_specs b, a
uninstall_gem b
- a_file = File.join a.gem_dir, 'lib', 'a_file.rb'
+ a_file = File.join a.gem_dir, "lib", "a_file.rb"
write_file a_file do |io|
- io.puts '# a_file.rb'
+ io.puts "# a_file.rb"
end
e = assert_raise Gem::MissingSpecError do
- Gem.try_activate 'a_file'
+ Gem.try_activate "a_file"
end
- assert_match %r{Could not find 'b' \(= 1.0rc1\)}, e.message
+ assert_match(/Could not find 'b' \(= 1.0rc1\)/, e.message)
end
def test_self_try_activate_missing_extensions
- spec = util_spec 'ext', '1' do |s|
+ spec = util_spec "ext", "1" do |s|
s.extensions = %w[ext/extconf.rb]
- s.mark_version
- s.installed_by_version = v('2.2')
+ s.installed_by_version = v("2.2")
end
# write the spec without install to simulate a failed install
@@ -1349,55 +1293,53 @@ class TestGem < Gem::TestCase
end
_, err = capture_output do
- refute Gem.try_activate 'nonexistent'
+ refute Gem.try_activate "nonexistent"
end
- unless Gem.java_platform?
- expected = "Ignoring ext-1 because its extensions are not built. " +
- "Try: gem pristine ext --version 1\n"
+ expected = "Ignoring ext-1 because its extensions are not built. " \
+ "Try: gem pristine ext --version 1\n"
- assert_equal expected, err
- end
+ assert_equal expected, err
end
def test_self_use_paths_with_nils
- orig_home = ENV.delete 'GEM_HOME'
- orig_path = ENV.delete 'GEM_PATH'
+ orig_home = ENV.delete "GEM_HOME"
+ orig_path = ENV.delete "GEM_PATH"
Gem.use_paths nil, nil
assert_equal Gem.default_dir, Gem.paths.home
path = (Gem.default_path + [Gem.paths.home]).uniq
assert_equal path, Gem.paths.path
ensure
- ENV['GEM_HOME'] = orig_home
- ENV['GEM_PATH'] = orig_path
+ ENV["GEM_HOME"] = orig_home
+ ENV["GEM_PATH"] = orig_path
end
def test_setting_paths_does_not_warn_about_unknown_keys
stdout, stderr = capture_output do
- Gem.paths = { 'foo' => [],
- 'bar' => Object.new,
- 'GEM_HOME' => Gem.paths.home,
- 'GEM_PATH' => 'foo' }
+ Gem.paths = { "foo" => [],
+ "bar" => Object.new,
+ "GEM_HOME" => Gem.paths.home,
+ "GEM_PATH" => "foo" }
end
- assert_equal ['foo', Gem.paths.home], Gem.paths.path
- assert_equal '', stderr
- assert_equal '', stdout
+ assert_equal ["foo", Gem.paths.home], Gem.paths.path
+ assert_equal "", stderr
+ assert_equal "", stdout
end
def test_setting_paths_does_not_mutate_parameter_object
- Gem.paths = { 'GEM_HOME' => Gem.paths.home,
- 'GEM_PATH' => 'foo' }.freeze
- assert_equal ['foo', Gem.paths.home], Gem.paths.path
+ Gem.paths = { "GEM_HOME" => Gem.paths.home,
+ "GEM_PATH" => "foo" } .freeze
+ assert_equal ["foo", Gem.paths.home], Gem.paths.path
end
def test_deprecated_paths=
stdout, stderr = capture_output do
- Gem.paths = { 'GEM_HOME' => Gem.paths.home,
- 'GEM_PATH' => [Gem.paths.home, 'foo'] }
+ Gem.paths = { "GEM_HOME" => Gem.paths.home,
+ "GEM_PATH" => [Gem.paths.home, "foo"] }
end
- assert_equal [Gem.paths.home, 'foo'], Gem.paths.path
+ assert_equal [Gem.paths.home, "foo"], Gem.paths.path
assert_match(/Array values in the parameter to `Gem.paths=` are deprecated.\nPlease use a String or nil/m, stderr)
- assert_equal '', stdout
+ assert_equal "", stdout
end
def test_self_use_paths
@@ -1410,8 +1352,8 @@ class TestGem < Gem::TestCase
end
def test_self_user_dir
- parts = [@userhome, '.gem', Gem.ruby_engine]
- parts << RbConfig::CONFIG['ruby_version'] unless RbConfig::CONFIG['ruby_version'].empty?
+ parts = [@userhome, ".gem", Gem.ruby_engine]
+ parts << RbConfig::CONFIG["ruby_version"] unless RbConfig::CONFIG["ruby_version"].empty?
FileUtils.mkdir_p File.join(parts)
@@ -1419,10 +1361,10 @@ class TestGem < Gem::TestCase
end
def test_self_user_home
- if ENV['HOME']
- assert_equal ENV['HOME'], Gem.user_home
+ if ENV["HOME"]
+ assert_equal ENV["HOME"], Gem.user_home
else
- assert true, 'count this test'
+ assert true, "count this test"
end
end
@@ -1438,67 +1380,65 @@ class TestGem < Gem::TestCase
r.gem "b", "= 1"
end
- activated = Gem::Specification.map {|x| x.full_name }
+ activated = Gem::Specification.map(&:full_name)
assert_equal %w[a-1 b-1 c-2], activated.sort
end
def test_self_needs_picks_up_unresolved_deps
- save_loaded_features do
- a = util_spec "a", "1"
- b = util_spec "b", "1", "c" => nil
- c = util_spec "c", "2"
- d = util_spec "d", "1", {'e' => '= 1'}, "lib/d#{$$}.rb"
- e = util_spec "e", "1"
-
- install_specs a, c, b, e, d
+ a = util_spec "a", "1"
+ b = util_spec "b", "1", "c" => nil
+ c = util_spec "c", "2"
+ d = util_spec "d", "1", { "e" => "= 1" }, "lib/d#{$$}.rb"
+ e = util_spec "e", "1"
- Gem.needs do |r|
- r.gem "a"
- r.gem "b", "= 1"
+ install_specs a, c, b, e, d
- require "d#{$$}"
- end
+ Gem.needs do |r|
+ r.gem "a"
+ r.gem "b", "= 1"
- assert_equal %w[a-1 b-1 c-2 d-1 e-1], loaded_spec_names
+ require "d#{$$}"
end
+
+ assert_equal %w[a-1 b-1 c-2 d-1 e-1], loaded_spec_names
end
def test_self_gunzip
- input = "\x1F\x8B\b\0\xED\xA3\x1AQ\0\x03\xCBH" +
+ input = "\x1F\x8B\b\0\xED\xA3\x1AQ\0\x03\xCBH" \
"\xCD\xC9\xC9\a\0\x86\xA6\x106\x05\0\0\0"
output = Gem::Util.gunzip input
- assert_equal 'hello', output
+ assert_equal "hello", output
assert_equal Encoding::BINARY, output.encoding
end
def test_self_gzip
- input = 'hello'
+ input = "hello"
output = Gem::Util.gzip input
zipped = StringIO.new output
- assert_equal 'hello', Zlib::GzipReader.new(zipped).read
+ assert_equal "hello", Zlib::GzipReader.new(zipped).read
assert_equal Encoding::BINARY, output.encoding
end
def test_self_vendor_dir
- vendordir(File.join(@tempdir, 'vendor')) do
+ vendordir(File.join(@tempdir, "vendor")) do
expected =
- File.join RbConfig::CONFIG['vendordir'], 'gems',
- RbConfig::CONFIG['ruby_version']
+ File.join RbConfig::CONFIG["vendordir"], "gems",
+ RbConfig::CONFIG["ruby_version"]
assert_equal expected, Gem.vendor_dir
end
end
def test_self_vendor_dir_ENV_GEM_VENDOR
- ENV['GEM_VENDOR'] = File.join @tempdir, 'vendor', 'gems'
+ ENV["GEM_VENDOR"] = File.join @tempdir, "vendor", "gems"
- assert_equal ENV['GEM_VENDOR'], Gem.vendor_dir
+ assert_equal ENV["GEM_VENDOR"], Gem.vendor_dir
refute Gem.vendor_dir.frozen?
end
@@ -1511,28 +1451,35 @@ class TestGem < Gem::TestCase
def test_load_plugins
plugin_path = File.join "lib", "rubygems_plugin.rb"
+ foo1_plugin_path = nil
+ foo2_plugin_path = nil
Dir.chdir @tempdir do
- FileUtils.mkdir_p 'lib'
+ FileUtils.mkdir_p "lib"
File.open plugin_path, "w" do |fp|
fp.puts "class TestGem; PLUGINS_LOADED << 'plugin'; end"
end
- foo1 = util_spec 'foo', '1' do |s|
+ foo1 = util_spec "foo", "1" do |s|
s.files << plugin_path
end
+ foo1_plugin_path = File.join(foo1.gem_dir, plugin_path)
install_gem foo1
- foo2 = util_spec 'foo', '2' do |s|
+ foo2 = util_spec "foo", "2" do |s|
s.files << plugin_path
end
+ foo2_plugin_path = File.join(foo2.gem_dir, plugin_path)
install_gem foo2
end
Gem::Specification.reset
+ PLUGINS_LOADED.clear
+ $LOADED_FEATURES.delete(foo1_plugin_path)
+ $LOADED_FEATURES.delete(foo2_plugin_path)
- gem 'foo'
+ gem "foo"
Gem.load_plugins
@@ -1540,15 +1487,18 @@ class TestGem < Gem::TestCase
end
def test_load_user_installed_plugins
+ @orig_gem_home = ENV["GEM_HOME"]
+ ENV["GEM_HOME"] = @gemhome
+
plugin_path = File.join "lib", "rubygems_plugin.rb"
Dir.chdir @tempdir do
- FileUtils.mkdir_p 'lib'
+ FileUtils.mkdir_p "lib"
File.open plugin_path, "w" do |fp|
fp.puts "class TestGem; PLUGINS_LOADED << 'plugin'; end"
end
- foo = util_spec 'foo', '1' do |s|
+ foo = util_spec "foo", "1" do |s|
s.files << plugin_path
end
@@ -1557,81 +1507,94 @@ class TestGem < Gem::TestCase
Gem.paths = { "GEM_PATH" => [Gem.dir, Gem.user_dir].join(File::PATH_SEPARATOR) }
- gem 'foo'
+ gem "foo"
Gem.load_plugins
assert_equal %w[plugin], PLUGINS_LOADED
+ ensure
+ ENV["GEM_HOME"] = @orig_gem_home
end
def test_load_env_plugins
- with_plugin('load') { Gem.load_env_plugins }
- assert_equal :loaded, TEST_PLUGIN_LOAD rescue nil
+ with_plugin("load") { Gem.load_env_plugins }
+ begin
+ assert_equal :loaded, TEST_PLUGIN_LOAD
+ rescue StandardError
+ nil
+ end
util_remove_interrupt_command
# Should attempt to cause a StandardError
- with_plugin('standarderror') { Gem.load_env_plugins }
- assert_equal :loaded, TEST_PLUGIN_STANDARDERROR rescue nil
+ with_plugin("standarderror") { Gem.load_env_plugins }
+ begin
+ assert_equal :loaded, TEST_PLUGIN_STANDARDERROR
+ rescue StandardError
+ nil
+ end
util_remove_interrupt_command
# Should attempt to cause an Exception
- with_plugin('exception') { Gem.load_env_plugins }
- assert_equal :loaded, TEST_PLUGIN_EXCEPTION rescue nil
+ with_plugin("scripterror") { Gem.load_env_plugins }
+ begin
+ assert_equal :loaded, TEST_PLUGIN_EXCEPTION
+ rescue StandardError
+ nil
+ end
end
def test_gem_path_ordering
refute_equal Gem.dir, Gem.user_dir
- write_file File.join(@tempdir, 'lib', "g.rb") {|fp| fp.puts "" }
- write_file File.join(@tempdir, 'lib', 'm.rb') {|fp| fp.puts "" }
+ write_file File.join(@tempdir, "lib", "g.rb") {|fp| fp.puts "" }
+ write_file File.join(@tempdir, "lib", "m.rb") {|fp| fp.puts "" }
- g = util_spec 'g', '1', nil, "lib/g.rb"
- m = util_spec 'm', '1', nil, "lib/m.rb"
+ g = util_spec "g", "1", nil, "lib/g.rb"
+ m = util_spec "m", "1", nil, "lib/m.rb"
- install_gem g, :install_dir => Gem.dir
- m0 = install_gem m, :install_dir => Gem.dir
- m1 = install_gem m, :install_dir => Gem.user_dir
+ install_gem g, install_dir: Gem.dir
+ m0 = install_gem m, install_dir: Gem.dir
+ m1 = install_gem m, install_dir: Gem.user_dir
assert_equal m0.gem_dir, File.join(Gem.dir, "gems", "m-1")
assert_equal m1.gem_dir, File.join(Gem.user_dir, "gems", "m-1")
tests = [
- [:dir0, [ Gem.dir, Gem.user_dir], m0],
- [:dir1, [ Gem.user_dir, Gem.dir], m1],
+ [:dir0, [Gem.dir, Gem.user_dir]],
+ [:dir1, [Gem.user_dir, Gem.dir]],
]
- tests.each do |_name, _paths, expected|
- Gem.use_paths _paths.first, _paths
- Gem::Specification.reset
+ tests.each do |name, paths|
+ Gem.use_paths paths.first, paths
Gem.searcher = nil
- assert_equal Gem::Dependency.new('m','1').to_specs,
- Gem::Dependency.new('m','1').to_specs.sort
+ assert_equal Gem::Dependency.new("m","1").to_specs,
+ Gem::Dependency.new("m","1").to_specs.sort
assert_equal \
- [expected.gem_dir],
- Gem::Dependency.new('m','1').to_specs.map(&:gem_dir).sort,
- "Wrong specs for #{_name}"
+ [m0.gem_dir, m1.gem_dir],
+ Gem::Dependency.new("m","1").to_specs.map(&:gem_dir).uniq.sort,
+ "Wrong specs for #{name}"
- spec = Gem::Dependency.new('m','1').to_spec
+ spec = Gem::Dependency.new("m","1").to_spec
assert_equal \
- File.join(_paths.first, "gems", "m-1"),
+ File.join(paths.first, "gems", "m-1"),
spec.gem_dir,
- "Wrong spec before require for #{_name}"
- refute spec.activated?, "dependency already activated for #{_name}"
+ "Wrong spec before require for #{name}"
+ refute spec.activated?, "dependency already activated for #{name}"
gem "m"
- spec = Gem::Dependency.new('m','1').to_spec
- assert spec.activated?, "dependency not activated for #{_name}"
+ spec = Gem::Dependency.new("m","1").to_spec
+ assert spec.activated?, "dependency not activated for #{name}"
assert_equal \
- File.join(_paths.first, "gems", "m-1"),
+ File.join(paths.first, "gems", "m-1"),
spec.gem_dir,
- "Wrong spec after require for #{_name}"
+ "Wrong spec after require for #{name}"
spec.instance_variable_set :@activated, false
Gem.loaded_specs.delete(spec.name)
@@ -1640,181 +1603,26 @@ class TestGem < Gem::TestCase
end
def test_gem_path_ordering_short
- write_file File.join(@tempdir, 'lib', "g.rb") {|fp| fp.puts "" }
- write_file File.join(@tempdir, 'lib', 'm.rb') {|fp| fp.puts "" }
+ write_file File.join(@tempdir, "lib", "g.rb") {|fp| fp.puts "" }
+ write_file File.join(@tempdir, "lib", "m.rb") {|fp| fp.puts "" }
+
+ g = util_spec "g", "1", nil, "lib/g.rb"
+ m = util_spec "m", "1", nil, "lib/m.rb"
- g = util_spec 'g', '1', nil, "lib/g.rb"
- m = util_spec 'm', '1', nil, "lib/m.rb"
+ install_gem g, install_dir: Gem.dir
+ install_gem m, install_dir: Gem.dir
+ install_gem m, install_dir: Gem.user_dir
- install_gem g, :install_dir => Gem.dir
- install_gem m, :install_dir => Gem.dir
- install_gem m, :install_dir => Gem.user_dir
+ Gem.use_paths Gem.dir, [Gem.dir, Gem.user_dir]
- Gem.use_paths Gem.dir, [ Gem.dir, Gem.user_dir]
+ spec = Gem::Dependency.new("m", "1").to_spec
assert_equal \
File.join(Gem.dir, "gems", "m-1"),
- Gem::Dependency.new('m','1').to_spec.gem_dir,
+ spec.gem_dir,
"Wrong spec selected"
end
- def test_auto_activation_of_specific_gemdeps_file
- a = util_spec "a", "1", nil, "lib/a.rb"
- b = util_spec "b", "1", nil, "lib/b.rb"
- c = util_spec "c", "1", nil, "lib/c.rb"
-
- install_specs a, b, c
-
- path = File.join @tempdir, "gem.deps.rb"
-
- File.open path, "w" do |f|
- f.puts "gem 'a'"
- f.puts "gem 'b'"
- f.puts "gem 'c'"
- end
-
- with_rubygems_gemdeps(path) do
- Gem.use_gemdeps
-
- assert_equal add_bundler_full_name(%W[a-1 b-1 c-1]), loaded_spec_names
- end
- end
-
- def test_auto_activation_of_used_gemdeps_file
- a = util_spec "a", "1", nil, "lib/a.rb"
- b = util_spec "b", "1", nil, "lib/b.rb"
- c = util_spec "c", "1", nil, "lib/c.rb"
-
- install_specs a, b, c
-
- path = File.join @tempdir, "gem.deps.rb"
-
- File.open path, "w" do |f|
- f.puts "gem 'a'"
- f.puts "gem 'b'"
- f.puts "gem 'c'"
- end
-
- with_rubygems_gemdeps("-") do
- expected_specs = [a, b, util_spec("bundler", Bundler::VERSION), c].compact.map(&:full_name)
-
- Gem.use_gemdeps
-
- assert_equal expected_specs, loaded_spec_names
- end
- end
-
- BUNDLER_LIB_PATH = File.expand_path $LOAD_PATH.find {|lp| File.file?(File.join(lp, "bundler.rb")) }
- BUNDLER_FULL_NAME = "bundler-#{Bundler::VERSION}".freeze
-
- def add_bundler_full_name(names)
- names << BUNDLER_FULL_NAME
- names.sort!
- names
- end
-
- def test_looks_for_gemdeps_files_automatically_from_binstubs
- pend "Requiring bundler messes things up" if Gem.java_platform?
-
- a = util_spec "a", "1" do |s|
- s.executables = %w[foo]
- s.bindir = "exe"
- end
-
- write_file File.join(@tempdir, 'exe', 'foo') do |fp|
- fp.puts "puts Gem.loaded_specs.values.map(&:full_name).sort"
- end
-
- b = util_spec "b", "1", nil, "lib/b.rb"
- c = util_spec "c", "1", nil, "lib/c.rb"
-
- install_specs a, b, c
-
- path = File.join(@tempdir, "gd-tmp")
- install_gem a, :install_dir => path
- install_gem b, :install_dir => path
- install_gem c, :install_dir => path
-
- ENV['GEM_PATH'] = path
-
- with_rubygems_gemdeps("-") do
- new_PATH = [File.join(path, "bin"), ENV["PATH"]].join(File::PATH_SEPARATOR)
- new_RUBYOPT = "-I#{rubygems_path} -I#{BUNDLER_LIB_PATH}"
-
- path = File.join @tempdir, "gem.deps.rb"
-
- File.open path, "w" do |f|
- f.puts "gem 'a'"
- end
- out0 = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do
- IO.popen("foo", &:read).split(/\n/)
- end
-
- File.open path, "a" do |f|
- f.puts "gem 'b'"
- f.puts "gem 'c'"
- end
- out = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do
- IO.popen("foo", &:read).split(/\n/)
- end
-
- assert_equal ["b-1", "c-1"], out - out0
- end
- end
-
- def test_looks_for_gemdeps_files_automatically_from_binstubs_in_parent_dir
- pend "Requiring bundler messes things up" if Gem.java_platform?
-
- a = util_spec "a", "1" do |s|
- s.executables = %w[foo]
- s.bindir = "exe"
- end
-
- write_file File.join(@tempdir, 'exe', 'foo') do |fp|
- fp.puts "puts Gem.loaded_specs.values.map(&:full_name).sort"
- end
-
- b = util_spec "b", "1", nil, "lib/b.rb"
- c = util_spec "c", "1", nil, "lib/c.rb"
-
- install_specs a, b, c
-
- path = File.join(@tempdir, "gd-tmp")
- install_gem a, :install_dir => path
- install_gem b, :install_dir => path
- install_gem c, :install_dir => path
-
- ENV['GEM_PATH'] = path
-
- with_rubygems_gemdeps("-") do
- Dir.mkdir "sub1"
-
- new_PATH = [File.join(path, "bin"), ENV["PATH"]].join(File::PATH_SEPARATOR)
- new_RUBYOPT = "-I#{rubygems_path} -I#{BUNDLER_LIB_PATH}"
-
- path = File.join @tempdir, "gem.deps.rb"
-
- File.open path, "w" do |f|
- f.puts "gem 'a'"
- end
- out0 = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do
- IO.popen("foo", :chdir => "sub1", &:read).split(/\n/)
- end
-
- File.open path, "a" do |f|
- f.puts "gem 'b'"
- f.puts "gem 'c'"
- end
- out = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do
- IO.popen("foo", :chdir => "sub1", &:read).split(/\n/)
- end
-
- Dir.rmdir "sub1"
-
- assert_equal ["b-1", "c-1"], out - out0
- end
- end
-
def test_register_default_spec
Gem.clear_default_specs
@@ -1855,163 +1663,25 @@ class TestGem < Gem::TestCase
assert_equal old_style, Gem.find_unresolved_default_spec("foo.rb")
end
- def test_use_gemdeps
- gem_deps_file = 'gem.deps.rb'.tap(&Gem::UNTAINT)
- spec = util_spec 'a', 1
- install_specs spec
-
- spec = Gem::Specification.find {|s| s == spec }
- refute spec.activated?
-
- File.open gem_deps_file, 'w' do |io|
- io.write 'gem "a"'
- end
-
- assert_nil Gem.gemdeps
-
- Gem.use_gemdeps gem_deps_file
-
- assert_equal add_bundler_full_name(%W[a-1]), loaded_spec_names
- refute_nil Gem.gemdeps
- end
-
- def test_use_gemdeps_ENV
- with_rubygems_gemdeps(nil) do
- spec = util_spec 'a', 1
-
- refute spec.activated?
-
- File.open 'gem.deps.rb', 'w' do |io|
- io.write 'gem "a"'
- end
-
- Gem.use_gemdeps
-
- refute spec.activated?
- end
- end
-
- def test_use_gemdeps_argument_missing
- e = assert_raise ArgumentError do
- Gem.use_gemdeps 'gem.deps.rb'
- end
-
- assert_equal 'Unable to find gem dependencies file at gem.deps.rb',
- e.message
- end
-
- def test_use_gemdeps_argument_missing_match_ENV
- with_rubygems_gemdeps('gem.deps.rb') do
- e = assert_raise ArgumentError do
- Gem.use_gemdeps 'gem.deps.rb'
- end
-
- assert_equal 'Unable to find gem dependencies file at gem.deps.rb',
- e.message
- end
- end
-
- def test_use_gemdeps_automatic
- with_rubygems_gemdeps('-') do
- spec = util_spec 'a', 1
- install_specs spec
- spec = Gem::Specification.find {|s| s == spec }
-
- refute spec.activated?
-
- File.open 'Gemfile', 'w' do |io|
- io.write 'gem "a"'
- end
-
- Gem.use_gemdeps
-
- assert_equal add_bundler_full_name(%W[a-1]), loaded_spec_names
- end
- end
-
- def test_use_gemdeps_automatic_missing
- with_rubygems_gemdeps('-') do
- Gem.use_gemdeps
-
- assert true # count
- end
- end
-
- def test_use_gemdeps_disabled
- with_rubygems_gemdeps('') do
- spec = util_spec 'a', 1
-
- refute spec.activated?
-
- File.open 'gem.deps.rb', 'w' do |io|
- io.write 'gem "a"'
- end
-
- Gem.use_gemdeps
-
- refute spec.activated?
- end
- end
-
- def test_use_gemdeps_missing_gem
- with_rubygems_gemdeps('x') do
- File.open 'x', 'w' do |io|
- io.write 'gem "a"'
- end
-
- expected = <<-EXPECTED
-Could not find gem 'a' in locally installed gems.
-You may need to `bundle install` to install missing gems
-
- EXPECTED
-
- Gem::Deprecate.skip_during do
- actual_stdout, actual_stderr = capture_output do
- Gem.use_gemdeps
- end
- assert_empty actual_stdout
- assert_equal(expected, actual_stderr)
- end
- end
- end
-
- def test_use_gemdeps_specific
- with_rubygems_gemdeps('x') do
- spec = util_spec 'a', 1
- install_specs spec
-
- spec = Gem::Specification.find {|s| s == spec }
- refute spec.activated?
-
- File.open 'x', 'w' do |io|
- io.write 'gem "a"'
- end
-
- Gem.use_gemdeps
-
- assert_equal add_bundler_full_name(%W[a-1]), loaded_spec_names
- end
- end
-
def test_operating_system_defaults
operating_system_defaults = Gem.operating_system_defaults
- assert operating_system_defaults != nil
+ assert !operating_system_defaults.nil?
assert operating_system_defaults.is_a? Hash
end
def test_platform_defaults
platform_defaults = Gem.platform_defaults
- assert platform_defaults != nil
+ assert !platform_defaults.nil?
assert platform_defaults.is_a? Hash
end
# Ensure that `Gem.source_date_epoch` is consistent even if
# $SOURCE_DATE_EPOCH has not been set.
def test_default_source_date_epoch_doesnt_change
- old_epoch = ENV['SOURCE_DATE_EPOCH']
- ENV['SOURCE_DATE_EPOCH'] = nil
+ old_epoch = ENV["SOURCE_DATE_EPOCH"]
+ ENV["SOURCE_DATE_EPOCH"] = nil
# Unfortunately, there is no real way to test this aside from waiting
# enough for `Time.now.to_i` to change -- which is a whole second.
@@ -2022,21 +1692,47 @@ You may need to `bundle install` to install missing gems
b = Gem.source_date_epoch
assert_equal a, b
ensure
- ENV['SOURCE_DATE_EPOCH'] = old_epoch
+ ENV["SOURCE_DATE_EPOCH"] = old_epoch
+ end
+
+ def test_data_home_default
+ expected = File.join(@userhome, ".local", "share")
+ assert_equal expected, Gem.data_home
+ end
+
+ def test_data_home_from_env
+ ENV["XDG_DATA_HOME"] = expected = "/test/data/home"
+ assert_equal expected, Gem.data_home
end
+ def test_state_home_default
+ Gem.instance_variable_set :@state_home, nil
+ Gem.data_home # memoize @data_home, to demonstrate GH-6418
+ expected = File.join(@userhome, ".local", "state")
+ assert_equal expected, Gem.state_home
+ end
+
+ def test_state_home_from_env
+ Gem.instance_variable_set :@state_home, nil
+ Gem.data_home # memoize @data_home, to demonstrate GH-6418
+ ENV["XDG_STATE_HOME"] = expected = "/test/state/home"
+ assert_equal expected, Gem.state_home
+ end
+
+ private
+
def ruby_install_name(name)
with_clean_path_to_ruby do
- orig_RUBY_INSTALL_NAME = RbConfig::CONFIG['ruby_install_name']
- RbConfig::CONFIG['ruby_install_name'] = name
+ orig_ruby_install_name = RbConfig::CONFIG["ruby_install_name"]
+ RbConfig::CONFIG["ruby_install_name"] = name
begin
yield
ensure
- if orig_RUBY_INSTALL_NAME
- RbConfig::CONFIG['ruby_install_name'] = orig_RUBY_INSTALL_NAME
+ if orig_ruby_install_name
+ RbConfig::CONFIG["ruby_install_name"] = orig_ruby_install_name
else
- RbConfig::CONFIG.delete 'ruby_install_name'
+ RbConfig::CONFIG.delete "ruby_install_name"
end
end
end
@@ -2054,13 +1750,8 @@ You may need to `bundle install` to install missing gems
end
def redefine_method(base, method, new_result)
- if RUBY_VERSION >= "2.5"
- base.alias_method(method, method)
- base.define_method(method) { new_result }
- else
- base.send(:alias_method, method, method)
- base.send(:define_method, method) { new_result }
- end
+ base.alias_method(method, method)
+ base.define_method(method) { new_result }
end
def with_plugin(path)
@@ -2085,18 +1776,18 @@ You may need to `bundle install` to install missing gems
#
# FIXME what does this solve precisely? -ebh
#
- @additional.each do |dir|
+ @additional.each do |_dir|
Gem.ensure_gem_subdirectories @gemhome
end
end
def util_exec_gem
- spec, _ = util_spec 'a', '4' do |s|
- s.executables = ['exec', 'abin']
+ spec, _ = util_spec "a", "4" do |s|
+ s.executables = ["exec", "abin"]
end
- @exec_path = File.join spec.full_gem_path, spec.bindir, 'exec'
- @abin_path = File.join spec.full_gem_path, spec.bindir, 'abin'
+ @exec_path = File.join spec.full_gem_path, spec.bindir, "exec"
+ @abin_path = File.join spec.full_gem_path, spec.bindir, "abin"
spec
end
@@ -2108,22 +1799,4 @@ You may need to `bundle install` to install missing gems
def util_cache_dir
File.join Gem.dir, "cache"
end
-
- def with_path_and_rubyopt(path_value, rubyopt_value)
- path, ENV['PATH'] = ENV['PATH'], path_value
- rubyopt, ENV['RUBYOPT'] = ENV['RUBYOPT'], rubyopt_value
-
- yield
- ensure
- ENV['PATH'] = path
- ENV['RUBYOPT'] = rubyopt
- end
-
- def with_rubygems_gemdeps(value)
- rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], value
-
- yield
- ensure
- ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps
- end
end
diff --git a/test/rubygems/test_gem_available_set.rb b/test/rubygems/test_gem_available_set.rb
index c4164d77f2..7c24d25bcb 100644
--- a/test/rubygems/test_gem_available_set.rb
+++ b/test/rubygems/test_gem_available_set.rb
@@ -1,7 +1,8 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/available_set'
-require 'rubygems/security'
+
+require_relative "helper"
+require "rubygems/available_set"
+require "rubygems/security"
class TestGemAvailableSet < Gem::TestCase
def setup
@@ -11,7 +12,7 @@ class TestGemAvailableSet < Gem::TestCase
end
def test_add_and_empty
- a1, _ = util_gem 'a', '1'
+ a1, _ = util_gem "a", "1"
set = Gem::AvailableSet.new
assert set.empty?
@@ -24,8 +25,8 @@ class TestGemAvailableSet < Gem::TestCase
end
def test_find_all
- a1, a1_gem = util_gem 'a', 1
- a1a, a1a_gem = util_gem 'a', '1.a'
+ a1, a1_gem = util_gem "a", 1
+ a1a, a1a_gem = util_gem "a", "1.a"
a1_source = Gem::Source::SpecificFile.new a1_gem
a1a_source = Gem::Source::SpecificFile.new a1a_gem
@@ -34,26 +35,26 @@ class TestGemAvailableSet < Gem::TestCase
set.add a1, a1_source
set.add a1a, a1a_source
- dep = Gem::Resolver::DependencyRequest.new dep('a'), nil
+ dep = Gem::Resolver::DependencyRequest.new dep("a"), nil
- assert_equal %w[a-1], set.find_all(dep).map {|spec| spec.full_name }
+ assert_equal %w[a-1], set.find_all(dep).map(&:full_name)
- dep = Gem::Resolver::DependencyRequest.new dep('a', '>= 0.a'), nil
+ dep = Gem::Resolver::DependencyRequest.new dep("a", ">= 0.a"), nil
assert_equal %w[a-1 a-1.a],
- set.find_all(dep).map {|spec| spec.full_name }.sort
+ set.find_all(dep).map(&:full_name).sort
end
def test_match_platform
- a1, _ = util_gem 'a', '1' do |g|
+ a1, _ = util_gem "a", "1" do |g|
g.platform = "something-weird-yep"
end
- a1c, _ = util_gem 'a', '2' do |g|
+ a1c, _ = util_gem "a", "2" do |g|
g.platform = Gem::Platform.local
end
- a2, _ = util_gem 'a', '2'
+ a2, _ = util_gem "a", "2"
set = Gem::AvailableSet.new
set.add a1, @source
@@ -66,8 +67,8 @@ class TestGemAvailableSet < Gem::TestCase
end
def test_best
- a1, _ = util_gem 'a', '1'
- a2, _ = util_gem 'a', '2'
+ a1, _ = util_gem "a", "1"
+ a2, _ = util_gem "a", "2"
set = Gem::AvailableSet.new
set.add a1, @source
@@ -79,7 +80,7 @@ class TestGemAvailableSet < Gem::TestCase
end
def test_remove_installed_bang
- a1, _ = util_spec 'a', '1'
+ a1, _ = util_spec "a", "1"
install_specs a1
a1.activate
@@ -95,8 +96,8 @@ class TestGemAvailableSet < Gem::TestCase
end
def test_sorted_normal_versions
- a1, _ = util_gem 'a', '1'
- a2, _ = util_gem 'a', '2'
+ a1, _ = util_gem "a", "1"
+ a2, _ = util_gem "a", "2"
set = Gem::AvailableSet.new
set.add a1, @source
@@ -109,11 +110,11 @@ class TestGemAvailableSet < Gem::TestCase
end
def test_sorted_respect_pre
- a1a, _ = util_gem 'a', '1.a'
- a1, _ = util_gem 'a', '1'
- a2a, _ = util_gem 'a', '2.a'
- a2, _ = util_gem 'a', '2'
- a3a, _ = util_gem 'a', '3.a'
+ a1a, _ = util_gem "a", "1.a"
+ a1, _ = util_gem "a", "1"
+ a2a, _ = util_gem "a", "2.a"
+ a2, _ = util_gem "a", "2"
+ a3a, _ = util_gem "a", "3.a"
set = Gem::AvailableSet.new
set.add a1, @source
@@ -122,7 +123,7 @@ class TestGemAvailableSet < Gem::TestCase
set.add a2a, @source
set.add a2, @source
- g = set.sorted.map {|t| t.spec }
+ g = set.sorted.map(&:spec)
assert_equal [a3a, a2, a2a, a1, a1a], g
end
diff --git a/test/rubygems/test_gem_bundler_version_finder.rb b/test/rubygems/test_gem_bundler_version_finder.rb
index e971e6ae29..b72670b802 100644
--- a/test/rubygems/test_gem_bundler_version_finder.rb
+++ b/test/rubygems/test_gem_bundler_version_finder.rb
@@ -1,12 +1,14 @@
# frozen_string_literal: true
-require_relative 'helper'
+
+require_relative "helper"
+require "rubygems/bundler_version_finder"
class TestGemBundlerVersionFinder < Gem::TestCase
def setup
- super
-
@argv = ARGV.dup
@dollar_0 = $0
+ super
+
without_any_upwards_gemfiles
end
@@ -43,41 +45,44 @@ class TestGemBundlerVersionFinder < Gem::TestCase
assert_equal v("1.1.1.1"), bvf.bundler_version
ARGV.replace %w[update --bundler\ 1.1.1.2 --bundler --bundler 1.1.1.1 gem_name]
assert_equal v("1.1.1.1"), bvf.bundler_version
+ $0 = "/foo/bar/bundler"
+ assert_equal v("1.1.1.1"), bvf.bundler_version
$0 = "other"
assert_nil bvf.bundler_version
end
def test_bundler_version_with_lockfile
- bvf.stub(:lockfile_contents, [nil, ""]) do
+ bvf.stub(:lockfile_contents, "") do
assert_nil bvf.bundler_version
end
- bvf.stub(:lockfile_contents, [nil, "\n\nBUNDLED WITH\n 1.1.1.1\n"]) do
+ bvf.stub(:lockfile_contents, "\n\nBUNDLED WITH\n 1.1.1.1\n") do
assert_equal v("1.1.1.1"), bvf.bundler_version
end
- bvf.stub(:lockfile_contents, [nil, "\n\nBUNDLED WITH\n fjdkslfjdkslfjsldk\n"]) do
+ bvf.stub(:lockfile_contents, "\n\nBUNDLED WITH\n fjdkslfjdkslfjsldk\n") do
assert_nil bvf.bundler_version
end
end
- def test_bundler_version_with_reason
- assert_nil bvf.bundler_version_with_reason
- bvf.stub(:lockfile_contents, [nil, "\n\nBUNDLED WITH\n 1.1.1.1\n"]) do
- assert_equal ["1.1.1.1", "your lockfile"], bvf.bundler_version_with_reason
+ def test_bundler_version
+ assert_nil bvf.bundler_version
+ bvf.stub(:lockfile_contents, "\n\nBUNDLED WITH\n 1.1.1.1\n") do
+ assert_equal "1.1.1.1", bvf.bundler_version.to_s
$0 = "bundle"
ARGV.replace %w[update --bundler]
- assert_nil bvf.bundler_version_with_reason
+ assert_nil bvf.bundler_version
+
ARGV.replace %w[update --bundler=1.1.1.2]
- assert_equal ["1.1.1.2", "`bundle update --bundler`"], bvf.bundler_version_with_reason
+ assert_equal "1.1.1.2", bvf.bundler_version.to_s
ENV["BUNDLER_VERSION"] = "1.1.1.3"
- assert_equal ["1.1.1.3", "`$BUNDLER_VERSION`"], bvf.bundler_version_with_reason
+ assert_equal "1.1.1.3", bvf.bundler_version.to_s
end
end
def test_deleted_directory
- pend "Cannot perform this test on windows" if win_platform?
- pend "Cannot perform this test on Solaris" if /solaris/ =~ RUBY_PLATFORM
+ pend "Cannot perform this test on windows" if Gem.win_platform?
+ pend "Cannot perform this test on Solaris" if RUBY_PLATFORM.include?("solaris")
require "tmpdir"
orig_dir = Dir.pwd
@@ -90,57 +95,35 @@ class TestGemBundlerVersionFinder < Gem::TestCase
Dir.chdir(orig_dir)
end
- assert_nil bvf.bundler_version_with_reason
- end
-
- def test_compatible
- assert bvf.compatible?(util_spec("foo"))
- assert bvf.compatible?(util_spec("bundler", 1.1))
-
- bvf.stub(:bundler_version, v("1.1.1.1")) do
- assert bvf.compatible?(util_spec("foo"))
- assert bvf.compatible?(util_spec("bundler", "1.1.1.1"))
- assert bvf.compatible?(util_spec("bundler", "1.1.1.a"))
- assert bvf.compatible?(util_spec("bundler", "1.999"))
- refute bvf.compatible?(util_spec("bundler", "2.999"))
- end
-
- bvf.stub(:bundler_version, v("2.1.1.1")) do
- assert bvf.compatible?(util_spec("foo"))
- assert bvf.compatible?(util_spec("bundler", "2.1.1.1"))
- assert bvf.compatible?(util_spec("bundler", "2.1.1.a"))
- assert bvf.compatible?(util_spec("bundler", "2.999"))
- refute bvf.compatible?(util_spec("bundler", "1.999"))
- refute bvf.compatible?(util_spec("bundler", "3.0.0"))
- end
+ assert_nil bvf.bundler_version
end
- def test_filter
+ def test_prioritize
versions = %w[1 1.0 1.0.1.1 2 2.a 2.0 2.1.1 3 3.a 3.0 3.1.1]
specs = versions.map {|v| util_spec("bundler", v) }
- assert_equal %w[1 1.0 1.0.1.1 2 2.a 2.0 2.1.1 3 3.a 3.0 3.1.1], util_filter_specs(specs).map(&:version).map(&:to_s)
+ assert_equal %w[1 1.0 1.0.1.1 2 2.a 2.0 2.1.1 3 3.a 3.0 3.1.1], util_prioritize_specs(specs)
bvf.stub(:bundler_version, v("2.1.1.1")) do
- assert_equal %w[2 2.a 2.0 2.1.1], util_filter_specs(specs).map(&:version).map(&:to_s)
+ assert_equal %w[1 1.0 1.0.1.1 2 2.a 2.0 2.1.1 3 3.a 3.0 3.1.1], util_prioritize_specs(specs)
end
bvf.stub(:bundler_version, v("1.1.1.1")) do
- assert_equal %w[1 1.0 1.0.1.1], util_filter_specs(specs).map(&:version).map(&:to_s)
+ assert_equal %w[1 1.0 1.0.1.1 2 2.a 2.0 2.1.1 3 3.a 3.0 3.1.1], util_prioritize_specs(specs)
end
bvf.stub(:bundler_version, v("1")) do
- assert_equal %w[1 1.0 1.0.1.1], util_filter_specs(specs).map(&:version).map(&:to_s)
+ assert_equal %w[1 1.0 1.0.1.1 2 2.a 2.0 2.1.1 3 3.a 3.0 3.1.1], util_prioritize_specs(specs)
end
bvf.stub(:bundler_version, v("2.a")) do
- assert_equal %w[2.a 2 2.0 2.1.1], util_filter_specs(specs).map(&:version).map(&:to_s)
+ assert_equal %w[2.a 1 1.0 1.0.1.1 2 2.0 2.1.1 3 3.a 3.0 3.1.1], util_prioritize_specs(specs)
end
bvf.stub(:bundler_version, v("3")) do
- assert_equal %w[3 3.a 3.0 3.1.1], util_filter_specs(specs).map(&:version).map(&:to_s)
+ assert_equal %w[3 1 1.0 1.0.1.1 2 2.a 2.0 2.1.1 3.a 3.0 3.1.1], util_prioritize_specs(specs)
end
end
- def util_filter_specs(specs)
+ def util_prioritize_specs(specs)
specs = specs.dup
- bvf.filter!(specs)
- specs
+ bvf.prioritize!(specs)
+ specs.map(&:version).map(&:to_s)
end
end
diff --git a/test/rubygems/test_gem_ci_detector.rb b/test/rubygems/test_gem_ci_detector.rb
new file mode 100644
index 0000000000..a28ee49f4b
--- /dev/null
+++ b/test/rubygems/test_gem_ci_detector.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+require_relative "helper"
+require "rubygems"
+
+class TestCiDetector < Gem::TestCase
+ def test_ci?
+ with_env("FOO" => "bar") { assert_equal(false, Gem::CIDetector.ci?) }
+ with_env("CI" => "true") { assert_equal(true, Gem::CIDetector.ci?) }
+ with_env("CONTINUOUS_INTEGRATION" => "1") { assert_equal(true, Gem::CIDetector.ci?) }
+ with_env("RUN_ID" => "0", "TASKCLUSTER_ROOT_URL" => "2") do
+ assert_equal(true, Gem::CIDetector.ci?)
+ end
+ end
+
+ def test_ci_strings
+ with_env("FOO" => "bar") { assert_empty(Gem::CIDetector.ci_strings) }
+ with_env("TRAVIS" => "true") { assert_equal(["travis"], Gem::CIDetector.ci_strings) }
+ with_env("CI" => "true", "CIRCLECI" => "true", "GITHUB_ACTIONS" => "true") do
+ assert_equal(["ci", "circle", "github"], Gem::CIDetector.ci_strings)
+ end
+ with_env("CI" => "true", "CI_NAME" => "MYCI") do
+ assert_equal(["ci", "myci"], Gem::CIDetector.ci_strings)
+ end
+ with_env("GITHUB_ACTIONS" => "true", "CI_NAME" => "github") do
+ assert_equal(["github"], Gem::CIDetector.ci_strings)
+ end
+ with_env("TASKCLUSTER_ROOT_URL" => "https://foo.bar", "DSARI" => "1", "CI_NAME" => "") do
+ assert_equal(["dsari", "taskcluster"], Gem::CIDetector.ci_strings)
+ end
+ end
+end
diff --git a/test/rubygems/test_gem_command.rb b/test/rubygems/test_gem_command.rb
index 43ce6ea39f..3695f9488f 100644
--- a/test/rubygems/test_gem_command.rb
+++ b/test/rubygems/test_gem_command.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/command'
+
+require_relative "helper"
+require "rubygems/command"
class Gem::Command
public :parser
@@ -15,13 +16,13 @@ class TestGemCommand < Gem::TestCase
@common_options = Gem::Command.common_options.dup
Gem::Command.common_options.clear
Gem::Command.common_options << [
- ['-x', '--exe', 'Execute'], lambda do |*a|
+ ["-x", "--exe", "Execute"], lambda do |*_a|
@xopt = true
end
]
- @cmd_name = 'doit'
- @cmd = Gem::Command.new @cmd_name, 'summary'
+ @cmd_name = "doit"
+ @cmd = Gem::Command.new @cmd_name, "summary"
end
def teardown
@@ -31,7 +32,7 @@ class TestGemCommand < Gem::TestCase
def test_self_add_specific_extra_args
added_args = %w[--all]
- @cmd.add_option('--all') {|v,o| }
+ @cmd.add_option("--all") {|v,o| }
Gem::Command.add_specific_extra_args @cmd_name, added_args
@@ -55,7 +56,9 @@ class TestGemCommand < Gem::TestCase
end
def test_self_extra_args
- verbose, $VERBOSE, separator = $VERBOSE, nil, $;
+ verbose = $VERBOSE
+ $VERBOSE = nil
+ separator = $;
extra_args = Gem::Command.extra_args
Gem::Command.extra_args = %w[--all]
@@ -68,7 +71,6 @@ class TestGemCommand < Gem::TestCase
Gem::Command.extra_args = "--awesome=true --verbose"
assert_equal %w[--awesome=true --verbose], Gem::Command.extra_args
-
ensure
Gem::Command.extra_args = extra_args
$; = separator
@@ -86,11 +88,11 @@ class TestGemCommand < Gem::TestCase
end
def test_defaults
- @cmd.add_option('-h', '--help [COMMAND]', 'Get help on COMMAND') do |value, options|
+ @cmd.add_option("-h", "--help [COMMAND]", "Get help on COMMAND") do |value, options|
options[:help] = value
end
- @cmd.defaults = { :help => true }
+ @cmd.defaults = { help: true }
@cmd.when_invoked do |options|
assert options[:help], "Help options should default true"
@@ -100,7 +102,7 @@ class TestGemCommand < Gem::TestCase
@cmd.invoke
end
- assert_match %r{Usage: gem doit}, @ui.output
+ assert_match(/Usage: gem doit/, @ui.output)
end
def test_invoke
@@ -118,8 +120,8 @@ class TestGemCommand < Gem::TestCase
use_ui @ui do
@cmd.when_invoked { true }
- ex = assert_raise OptionParser::InvalidOption do
- @cmd.invoke('-zzz')
+ ex = assert_raise Gem::OptionParser::InvalidOption do
+ @cmd.invoke("-zzz")
end
assert_match(/invalid option:/, ex.message)
@@ -151,12 +153,12 @@ class TestGemCommand < Gem::TestCase
done = false
use_ui @ui do
- @cmd.add_option('-h', '--help [COMMAND]', 'Get help on COMMAND') do |value, options|
+ @cmd.add_option("-h", "--help [COMMAND]", "Get help on COMMAND") do |_value, options|
options[:help] = true
done = true
end
- @cmd.invoke('--help')
+ @cmd.invoke("--help")
assert done
end
@@ -174,7 +176,7 @@ class TestGemCommand < Gem::TestCase
end
def test_invoke_with_options
- @cmd.add_option('-h', '--help [COMMAND]', 'Get help on COMMAND') do |value, options|
+ @cmd.add_option("-h", "--help [COMMAND]", "Get help on COMMAND") do |_value, options|
options[:help] = true
end
@@ -183,48 +185,48 @@ class TestGemCommand < Gem::TestCase
end
use_ui @ui do
- @cmd.invoke '-h'
+ @cmd.invoke "-h"
end
- assert_match %r{Usage: gem doit}, @ui.output
+ assert_match(/Usage: gem doit/, @ui.output)
end
def test_add_option
assert_nothing_raised RuntimeError do
- @cmd.add_option('--force', 'skip validation of the spec') {|v,o| }
+ @cmd.add_option("--force", "skip validation of the spec") {|v,o| }
end
end
def test_add_option_with_empty
assert_raise RuntimeError, "Do not pass an empty string in opts" do
- @cmd.add_option('', 'skip validation of the spec') {|v,o| }
+ @cmd.add_option("", "skip validation of the spec") {|v,o| }
end
end
def test_option_recognition
- @cmd.add_option('-h', '--help [COMMAND]', 'Get help on COMMAND') do |value, options|
+ @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|
+ @cmd.add_option("-f", "--file FILE", "File option") do |_value, options|
options[:help] = true
end
- @cmd.add_option('--silent', 'Silence RubyGems output') do |value, options|
+ @cmd.add_option("--silent", "Silence RubyGems output") do |_value, options|
options[:silent] = 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?(['--silent'])
- refute @cmd.handles?(['-z'])
- refute @cmd.handles?(['-f'])
- refute @cmd.handles?(['--toothpaste'])
-
- args = ['-h', 'command']
+ 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?(["--silent"])
+ refute @cmd.handles?(["-z"])
+ refute @cmd.handles?(["-f"])
+ refute @cmd.handles?(["--toothpaste"])
+
+ args = ["-h", "command"]
@cmd.handles?(args)
- assert_equal ['-h', 'command'], args
+ assert_equal ["-h", "command"], args
end
def test_deprecate_option
@@ -232,15 +234,15 @@ class TestGemCommand < Gem::TestCase
WARNING: The \"--test\" option has been deprecated and will be removed in Rubygems 3.1.
EXPECTED
- testCommand = Class.new(Gem::Command) do
+ test_command = Class.new(Gem::Command) do
def initialize
- super('test', 'Gem::Command instance for testing')
+ super("test", "Gem::Command instance for testing")
- add_option('-t', '--test', 'Test command') do |value, options|
+ add_option("-t", "--test", "Test command") do |_value, options|
options[:test] = true
end
- deprecate_option('--test', version: '3.1')
+ deprecate_option("--test", version: "3.1")
end
def execute
@@ -248,7 +250,7 @@ WARNING: The \"--test\" option has been deprecated and will be removed in Rubyg
end
end
- cmd = testCommand.new
+ cmd = test_command.new
use_ui @ui do
cmd.invoke("--test")
@@ -261,15 +263,15 @@ WARNING: The \"--test\" option has been deprecated and will be removed in Rubyg
WARNING: The \"--test\" option has been deprecated and will be removed in future versions of Rubygems.
EXPECTED
- testCommand = Class.new(Gem::Command) do
+ test_command = Class.new(Gem::Command) do
def initialize
- super('test', 'Gem::Command instance for testing')
+ super("test", "Gem::Command instance for testing")
- add_option('-t', '--test', 'Test command') do |value, options|
+ add_option("-t", "--test", "Test command") do |_value, options|
options[:test] = true
end
- deprecate_option('--test')
+ deprecate_option("--test")
end
def execute
@@ -277,7 +279,7 @@ WARNING: The \"--test\" option has been deprecated and will be removed in futur
end
end
- cmd = testCommand.new
+ cmd = test_command.new
use_ui @ui do
cmd.invoke("--test")
@@ -290,15 +292,15 @@ WARNING: The \"--test\" option has been deprecated and will be removed in futur
WARNING: The \"--test\" option has been deprecated and will be removed in Rubygems 3.1. Whether you set `--test` mode or not, this dummy app always runs in test mode.
EXPECTED
- testCommand = Class.new(Gem::Command) do
+ test_command = Class.new(Gem::Command) do
def initialize
- super('test', 'Gem::Command instance for testing')
+ super("test", "Gem::Command instance for testing")
- add_option('-t', '--test', 'Test command') do |value, options|
+ add_option("-t", "--test", "Test command") do |_value, options|
options[:test] = true
end
- deprecate_option('--test', version: '3.1', extra_msg: 'Whether you set `--test` mode or not, this dummy app always runs in test mode.')
+ deprecate_option("--test", version: "3.1", extra_msg: "Whether you set `--test` mode or not, this dummy app always runs in test mode.")
end
def execute
@@ -306,7 +308,7 @@ WARNING: The \"--test\" option has been deprecated and will be removed in Rubyg
end
end
- cmd = testCommand.new
+ cmd = test_command.new
use_ui @ui do
cmd.invoke("--test")
@@ -319,15 +321,15 @@ WARNING: The \"--test\" option has been deprecated and will be removed in Rubyg
WARNING: The \"--test\" option has been deprecated and will be removed in future versions of Rubygems. Whether you set `--test` mode or not, this dummy app always runs in test mode.
EXPECTED
- testCommand = Class.new(Gem::Command) do
+ test_command = Class.new(Gem::Command) do
def initialize
- super('test', 'Gem::Command instance for testing')
+ super("test", "Gem::Command instance for testing")
- add_option('-t', '--test', 'Test command') do |value, options|
+ add_option("-t", "--test", "Test command") do |_value, options|
options[:test] = true
end
- deprecate_option('--test', extra_msg: 'Whether you set `--test` mode or not, this dummy app always runs in test mode.')
+ deprecate_option("--test", extra_msg: "Whether you set `--test` mode or not, this dummy app always runs in test mode.")
end
def execute
@@ -335,7 +337,7 @@ WARNING: The \"--test\" option has been deprecated and will be removed in futur
end
end
- cmd = testCommand.new
+ cmd = test_command.new
use_ui @ui do
cmd.invoke("--test")
@@ -364,11 +366,11 @@ ERROR: Could not find a valid gem 'nonexistent_with_hint' (>= 0) in any reposit
def test_show_lookup_failure_suggestions_none
spec_fetcher do |fetcher|
- fetcher.spec 'correct', 2
+ fetcher.spec "correct", 2
end
use_ui @ui do
- @cmd.show_lookup_failure 'other', Gem::Requirement.default, [], :remote
+ @cmd.show_lookup_failure "other", Gem::Requirement.default, [], :remote
end
expected = <<-EXPECTED
diff --git a/test/rubygems/test_gem_command_manager.rb b/test/rubygems/test_gem_command_manager.rb
index f6a82908b3..f04ec0cafa 100644
--- a/test/rubygems/test_gem_command_manager.rb
+++ b/test/rubygems/test_gem_command_manager.rb
@@ -1,9 +1,10 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/command_manager'
+
+require_relative "helper"
+require "rubygems/command_manager"
class TestGemCommandManager < Gem::TestCase
- PROJECT_DIR = File.expand_path('../../..', __FILE__).tap(&Gem::UNTAINT)
+ PROJECT_DIR = File.expand_path("../..", __dir__)
def setup
super
@@ -12,37 +13,49 @@ class TestGemCommandManager < Gem::TestCase
end
def test_find_command
- command = @command_manager.find_command 'install'
+ command = @command_manager.find_command "install"
assert_kind_of Gem::Commands::InstallCommand, command
- command = @command_manager.find_command 'ins'
+ command = @command_manager.find_command "ins"
assert_kind_of Gem::Commands::InstallCommand, command
end
def test_find_command_ambiguous
e = assert_raise Gem::CommandLineError do
- @command_manager.find_command 'u'
+ @command_manager.find_command "u"
end
- assert_equal 'Ambiguous command u matches [uninstall, unpack, update]',
+ assert_equal "Ambiguous command u matches [uninstall, unpack, update]",
e.message
end
def test_find_alias_command
- command = @command_manager.find_command 'i'
+ command = @command_manager.find_command "i"
assert_kind_of Gem::Commands::InstallCommand, command
end
+ def test_find_login_alias_command
+ command = @command_manager.find_command "login"
+
+ assert_kind_of Gem::Commands::SigninCommand, command
+ end
+
+ def test_find_logout_alias_comamnd
+ command = @command_manager.find_command "logout"
+
+ assert_kind_of Gem::Commands::SignoutCommand, command
+ end
+
def test_find_command_ambiguous_exact
ins_command = Class.new
Gem::Commands.send :const_set, :InsCommand, ins_command
@command_manager.register_command :ins
- command = @command_manager.find_command 'ins'
+ command = @command_manager.find_command "ins"
assert_kind_of ins_command, command
ensure
@@ -51,24 +64,30 @@ class TestGemCommandManager < Gem::TestCase
def test_find_command_unknown
e = assert_raise Gem::UnknownCommandError do
- @command_manager.find_command 'xyz'
+ @command_manager.find_command "xyz"
end
- assert_equal 'Unknown command xyz', e.message
+ assert_equal "Unknown command xyz", e.message
end
def test_find_command_unknown_suggestions
e = assert_raise Gem::UnknownCommandError do
- @command_manager.find_command 'pish'
+ @command_manager.find_command "pish"
end
- message = 'Unknown command pish'.dup
+ message = "Unknown command pish".dup
- if RUBY_VERSION >= "2.4" && defined?(DidYouMean::SPELL_CHECKERS) && defined?(DidYouMean::Correctable)
+ if defined?(DidYouMean::SPELL_CHECKERS) && defined?(DidYouMean::Correctable)
message << "\nDid you mean? \"push\""
end
- assert_equal message, e.message
+ if e.respond_to?(:detailed_message)
+ actual_message = e.detailed_message(highlight: false).sub(/\A(.*?)(?: \(.+?\))/) { $1 }
+ else
+ actual_message = e.message
+ end
+
+ assert_equal message, actual_message
end
def test_run_interrupt
@@ -82,7 +101,7 @@ class TestGemCommandManager < Gem::TestCase
assert_raise Gem::MockGemUi::TermError do
@command_manager.run %w[interrupt]
end
- assert_equal '', ui.output
+ assert_equal "", ui.output
assert_equal "ERROR: Interrupted\n", ui.error
end
ensure
@@ -99,7 +118,7 @@ class TestGemCommandManager < Gem::TestCase
assert_raise Gem::MockGemUi::TermError do
@command_manager.run %w[crash]
end
- assert_equal '', ui.output
+ assert_equal "", ui.output
err = ui.error.split("\n").first
assert_equal "ERROR: Loading command: crash (RuntimeError)", err
end
@@ -108,6 +127,46 @@ class TestGemCommandManager < Gem::TestCase
@command_manager.unregister_command :crash
end
+ def test_process_args_with_c_flag
+ custom_start_point = File.join @tempdir, "nice_folder"
+ FileUtils.mkdir_p custom_start_point
+
+ execution_path = nil
+ use_ui @ui do
+ @command_manager[:install].when_invoked do
+ execution_path = Dir.pwd
+ true
+ end
+ @command_manager.process_args %W[-C #{custom_start_point} install net-scp-4.0.0.gem --local]
+ end
+
+ assert_equal custom_start_point, execution_path
+ end
+
+ def test_process_args_with_c_flag_without_path
+ use_ui @ui do
+ assert_raise Gem::MockGemUi::TermError do
+ @command_manager.process_args %w[-C install net-scp-4.0.0.gem --local]
+ end
+ end
+
+ assert_match(/install isn't a directory\./i, @ui.error)
+ end
+
+ def test_process_args_with_c_flag_path_not_found
+ custom_start_point = File.join @tempdir, "nice_folder"
+ FileUtils.mkdir_p custom_start_point
+ custom_start_point.tr!("_", "-")
+
+ use_ui @ui do
+ assert_raise Gem::MockGemUi::TermError do
+ @command_manager.process_args %W[-C #{custom_start_point} install net-scp-4.0.0.gem --local]
+ end
+ end
+
+ assert_match(/#{Regexp.quote(custom_start_point)} isn't a directory\./i, @ui.error)
+ end
+
def test_process_args_bad_arg
use_ui @ui do
assert_raise Gem::MockGemUi::TermError do
@@ -118,17 +177,17 @@ class TestGemCommandManager < Gem::TestCase
assert_match(/invalid option: --bad-arg/i, @ui.error)
end
- # HACK move to install command test
+ # HACK: move to install command test
def test_process_args_install
- #capture all install options
+ # capture all install options
use_ui @ui do
check_options = nil
- @command_manager['install'].when_invoked do |options|
+ @command_manager["install"].when_invoked do |options|
check_options = options
true
end
- #check defaults
+ # check defaults
@command_manager.process_args %w[install]
assert_equal %w[ri], check_options[:document].sort
assert_equal false, check_options[:force]
@@ -138,7 +197,7 @@ class TestGemCommandManager < Gem::TestCase
assert_nil check_options[:install_dir]
assert_nil check_options[:bin_dir]
- #check settings
+ # check settings
check_options = nil
@command_manager.process_args %w[
install --force --local --document=ri,rdoc --install-dir .
@@ -148,103 +207,103 @@ class TestGemCommandManager < Gem::TestCase
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 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 remote domain
check_options = nil
@command_manager.process_args %w[install --remote]
assert_equal :remote, check_options[:domain]
- #check both domain
+ # check both domain
check_options = nil
@command_manager.process_args %w[install --both]
assert_equal :both, check_options[:domain]
- #check both domain
+ # check both domain
check_options = nil
@command_manager.process_args %w[install --both]
assert_equal :both, check_options[:domain]
end
end
- # HACK move to uninstall command test
+ # HACK: move to uninstall command test
def test_process_args_uninstall
- #capture all uninstall options
+ # capture all uninstall options
check_options = nil
- @command_manager['uninstall'].when_invoked do |options|
+ @command_manager["uninstall"].when_invoked do |options|
check_options = options
true
end
- #check defaults
+ # check defaults
@command_manager.process_args %w[uninstall]
assert_equal Gem::Requirement.default, check_options[:version]
- #check settings
+ # check settings
check_options = nil
@command_manager.process_args %w[uninstall foobar --version 3.0]
assert_equal "foobar", check_options[:args].first
- assert_equal Gem::Requirement.new('3.0'), check_options[:version]
+ assert_equal Gem::Requirement.new("3.0"), check_options[:version]
end
- # HACK move to check command test
+ # HACK: move to check command test
def test_process_args_check
- #capture all check options
+ # capture all check options
check_options = nil
- @command_manager['check'].when_invoked do |options|
+ @command_manager["check"].when_invoked do |options|
check_options = options
true
end
- #check defaults
+ # check defaults
@command_manager.process_args %w[check]
assert_equal true, check_options[:alien]
- #check settings
+ # check settings
check_options = nil
@command_manager.process_args %w[check foobar --alien]
assert_equal true, check_options[:alien]
end
- # HACK move to build command test
+ # HACK: move to build command test
def test_process_args_build
- #capture all build options
+ # capture all build options
check_options = nil
- @command_manager['build'].when_invoked do |options|
+ @command_manager["build"].when_invoked do |options|
check_options = options
true
end
- #check defaults
+ # check defaults
@command_manager.process_args %w[build]
- #NOTE: Currently no defaults
+ # NOTE: Currently no defaults
- #check settings
+ # check settings
check_options = nil
@command_manager.process_args %w[build foobar.rb]
- assert_equal 'foobar.rb', check_options[:args].first
+ assert_equal "foobar.rb", check_options[:args].first
end
- # HACK move to query command test
+ # HACK: move to query command test
def test_process_args_query
- #capture all query options
+ # capture all query options
check_options = nil
- @command_manager['query'].when_invoked do |options|
+ @command_manager["query"].when_invoked do |options|
check_options = options
true
end
- #check defaults
+ # check defaults
Gem::Deprecate.skip_during do
@command_manager.process_args %w[query]
end
- assert_equal(//, check_options[:name])
+ assert_nil(check_options[:name])
assert_equal :local, check_options[:domain]
assert_equal false, check_options[:details]
- #check settings
+ # check settings
check_options = nil
Gem::Deprecate.skip_during do
@command_manager.process_args %w[query --name foobar --local --details]
@@ -253,14 +312,14 @@ class TestGemCommandManager < Gem::TestCase
assert_equal :local, check_options[:domain]
assert_equal true, check_options[:details]
- #remote domain
+ # remote domain
check_options = nil
Gem::Deprecate.skip_during do
@command_manager.process_args %w[query --remote]
end
assert_equal :remote, check_options[:domain]
- #both (local/remote) domains
+ # both (local/remote) domains
check_options = nil
Gem::Deprecate.skip_during do
@command_manager.process_args %w[query --both]
@@ -268,29 +327,29 @@ class TestGemCommandManager < Gem::TestCase
assert_equal :both, check_options[:domain]
end
- # HACK move to update command test
+ # HACK: move to update command test
def test_process_args_update
- #capture all update options
+ # capture all update options
check_options = nil
- @command_manager['update'].when_invoked do |options|
+ @command_manager["update"].when_invoked do |options|
check_options = options
true
end
- #check defaults
+ # check defaults
@command_manager.process_args %w[update]
- assert_includes check_options[:document], 'ri'
+ assert_includes check_options[:document], "ri"
- #check settings
+ # check settings
check_options = nil
@command_manager.process_args %w[update --force --document=ri --install-dir .]
- assert_includes check_options[:document], 'ri'
+ assert_includes check_options[:document], "ri"
assert_equal true, check_options[:force]
assert_equal Dir.pwd, check_options[:install_dir]
end
def test_deprecated_command
- require 'rubygems/command'
+ require "rubygems/command"
foo_command = Class.new(Gem::Command) do
extend Gem::Deprecate
@@ -309,7 +368,32 @@ class TestGemCommandManager < Gem::TestCase
end
assert_equal "pew pew!\n", @ui.output
- assert_match(/WARNING: foo command is deprecated. It will be removed in Rubygems [0-9]+/, @ui.error)
+ assert_match(/WARNING: foo command is deprecated\. It will be removed in Rubygems [0-9]+/, @ui.error)
+ ensure
+ Gem::Commands.send(:remove_const, :FooCommand)
+ end
+
+ def test_deprecated_command_with_version
+ require "rubygems/command"
+ foo_command = Class.new(Gem::Command) do
+ extend Gem::Deprecate
+
+ rubygems_deprecate_command("9.9.9")
+
+ def execute
+ say "pew pew!"
+ end
+ end
+
+ Gem::Commands.send(:const_set, :FooCommand, foo_command)
+ @command_manager.register_command(:foo, foo_command.new("foo"))
+
+ use_ui @ui do
+ @command_manager.process_args(%w[foo])
+ end
+
+ assert_equal "pew pew!\n", @ui.output
+ assert_match(/WARNING: foo command is deprecated\. It will be removed in Rubygems 9\.9\.9/, @ui.error)
ensure
Gem::Commands.send(:remove_const, :FooCommand)
end
diff --git a/test/rubygems/test_gem_commands_build_command.rb b/test/rubygems/test_gem_commands_build_command.rb
index 1304beb580..d44126d204 100644
--- a/test/rubygems/test_gem_commands_build_command.rb
+++ b/test/rubygems/test_gem_commands_build_command.rb
@@ -1,32 +1,34 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/commands/build_command'
-require 'rubygems/package'
+
+require_relative "helper"
+require "rubygems/commands/build_command"
+require "rubygems/package"
class TestGemCommandsBuildCommand < Gem::TestCase
- CERT_FILE = cert_path 'public3072'
- SIGNING_KEY = key_path 'private3072'
+ CERT_FILE = cert_path "public3072"
+ SIGNING_KEY = key_path "private3072"
- EXPIRED_CERT_FILE = cert_path 'expired'
- PRIVATE_KEY_FILE = key_path 'private'
+ EXPIRED_CERT_FILE = cert_path "expired"
+ PRIVATE_KEY_FILE = key_path "private"
def setup
super
- readme_file = File.join(@tempdir, 'README.md')
+ readme_file = File.join(@tempdir, "README.md")
begin
umask_orig = File.umask(2)
- File.open readme_file, 'w' do |f|
- f.write 'My awesome gem'
+ File.open readme_file, "w" do |f|
+ f.write "My awesome gem"
end
ensure
File.umask(umask_orig)
end
- @gem = util_spec 'some_gem' do |s|
- s.license = 'AGPL-3.0'
- s.files = ['README.md']
+ @gem = util_spec "some_gem" do |s|
+ s.license = "AGPL-3.0-only"
+ s.files = ["README.md"]
+ s.required_ruby_version = "2.3.0"
end
@cmd = Gem::Commands::BuildCommand.new
@@ -41,10 +43,20 @@ class TestGemCommandsBuildCommand < Gem::TestCase
assert_includes Gem.platforms, Gem::Platform.local
end
+ def test_handle_deprecated_options
+ use_ui @ui do
+ @cmd.handle_options %w[-C ./test/dir]
+ end
+
+ assert_equal "WARNING: The \"-C\" option has been deprecated and will be removed in Rubygems 4.0. " \
+ "-C is a global flag now. Use `gem -C PATH build GEMSPEC_FILE [options]` instead\n",
+ @ui.error
+ end
+
def test_options_filename
gemspec_file = File.join(@tempdir, @gem.spec_name)
- File.open gemspec_file, 'w' do |gs|
+ File.open gemspec_file, "w" do |gs|
gs.write @gem.to_ruby
end
@@ -79,7 +91,7 @@ class TestGemCommandsBuildCommand < Gem::TestCase
def test_execute
gemspec_file = File.join(@tempdir, @gem.spec_name)
- File.open gemspec_file, 'w' do |gs|
+ File.open gemspec_file, "w" do |gs|
gs.write @gem.to_ruby
end
@@ -91,7 +103,7 @@ class TestGemCommandsBuildCommand < Gem::TestCase
def test_execute_platform
gemspec_file = File.join(@tempdir, @gem.spec_name)
- File.open gemspec_file, 'w' do |gs|
+ File.open gemspec_file, "w" do |gs|
gs.write @gem.to_ruby
end
@@ -110,15 +122,15 @@ class TestGemCommandsBuildCommand < Gem::TestCase
def test_execute_bad_name
[".", "-", "_"].each do |special_char|
- gem = util_spec 'some_gem_with_bad_name' do |s|
+ gem = util_spec "some_gem_with_bad_name" do |s|
s.name = "#{special_char}bad_gem_name"
- s.license = 'AGPL-3.0'
- s.files = ['README.md']
+ s.license = "AGPL-3.0"
+ s.files = ["README.md"]
end
gemspec_file = File.join(@tempdir, gem.spec_name)
- File.open gemspec_file, 'w' do |gs|
+ File.open gemspec_file, "w" do |gs|
gs.write gem.to_ruby
end
@@ -137,7 +149,7 @@ class TestGemCommandsBuildCommand < Gem::TestCase
def test_execute_strict_without_warnings
gemspec_file = File.join(@tempdir, @gem.spec_name)
- File.open gemspec_file, 'w' do |gs|
+ File.open gemspec_file, "w" do |gs|
gs.write @gem.to_ruby
end
@@ -165,13 +177,14 @@ class TestGemCommandsBuildCommand < Gem::TestCase
end
def test_execute_strict_with_warnings
- bad_gem = util_spec 'some_bad_gem' do |s|
- s.files = ['README.md']
+ bad_gem = util_spec "some_bad_gem" do |s|
+ s.files = ["README.md"]
+ s.required_ruby_version = ">= 1.9.3"
end
gemspec_file = File.join(@tempdir, bad_gem.spec_name)
- File.open gemspec_file, 'w' do |gs|
+ File.open gemspec_file, "w" do |gs|
gs.write bad_gem.to_ruby
end
@@ -187,8 +200,9 @@ class TestGemCommandsBuildCommand < Gem::TestCase
end
error = @ui.error.split "\n"
- assert_equal "WARNING: licenses is empty, but is recommended. Use a license identifier from", error.shift
- assert_equal "http://spdx.org/licenses or 'Nonstandard' for a nonstandard license.", error.shift
+ assert_equal "WARNING: licenses is empty, but is recommended. Use an license identifier from", error.shift
+ assert_equal "https://spdx.org/licenses or 'Nonstandard' for a nonstandard license,", error.shift
+ assert_equal "or set it to nil if you don't want to specify a license.", error.shift
assert_equal "WARNING: See https://guides.rubygems.org/specification-reference/ for help", error.shift
assert_equal [], error
@@ -201,7 +215,7 @@ class TestGemCommandsBuildCommand < Gem::TestCase
gemspec_file = File.join(@tempdir, @gem.spec_name)
- File.open gemspec_file, 'w' do |gs|
+ File.open gemspec_file, "w" do |gs|
gs.write @gem.to_ruby.sub(/11-08/, "11-8")
end
@@ -218,7 +232,7 @@ class TestGemCommandsBuildCommand < Gem::TestCase
assert_equal "", out
assert_match(/invalid date format in specification/, err)
- assert_equal '', @ui.output
+ assert_equal "", @ui.output
assert_equal "ERROR: Error loading gemspec. Aborting.\n", @ui.error
end
@@ -230,22 +244,22 @@ class TestGemCommandsBuildCommand < Gem::TestCase
end
end
- assert_equal '', @ui.output
+ assert_equal "", @ui.output
assert_equal "ERROR: Couldn't find a gemspec file matching 'some_gem' in #{@tempdir}\n", @ui.error
end
def test_execute_outside_dir
- gemspec_dir = File.join @tempdir, 'build_command_gem'
+ gemspec_dir = File.join @tempdir, "build_command_gem"
gemspec_file = File.join gemspec_dir, @gem.spec_name
- readme_file = File.join gemspec_dir, 'README.md'
+ readme_file = File.join gemspec_dir, "README.md"
FileUtils.mkdir_p gemspec_dir
- File.open readme_file, 'w' do |f|
+ File.open readme_file, "w" do |f|
f.write "My awesome gem"
end
- File.open gemspec_file, 'w' do |gs|
+ File.open gemspec_file, "w" do |gs|
gs.write @gem.to_ruby
end
@@ -273,17 +287,17 @@ class TestGemCommandsBuildCommand < Gem::TestCase
end
def test_execute_outside_dir_with_glob_argument
- gemspec_dir = File.join @tempdir, 'build_command_gem'
+ gemspec_dir = File.join @tempdir, "build_command_gem"
gemspec_file = File.join gemspec_dir, @gem.spec_name
- readme_file = File.join gemspec_dir, 'README.md'
+ readme_file = File.join gemspec_dir, "README.md"
FileUtils.mkdir_p gemspec_dir
- File.open readme_file, 'w' do |f|
+ File.open readme_file, "w" do |f|
f.write "My awesome gem"
end
- File.open gemspec_file, 'w' do |gs|
+ File.open gemspec_file, "w" do |gs|
gs.write @gem.to_ruby
end
@@ -311,17 +325,17 @@ class TestGemCommandsBuildCommand < Gem::TestCase
end
def test_execute_outside_dir_no_gemspec_present
- gemspec_dir = File.join @tempdir, 'build_command_gem'
+ gemspec_dir = File.join @tempdir, "build_command_gem"
gemspec_file = File.join @tempdir, @gem.spec_name
- readme_file = File.join gemspec_dir, 'README.md'
+ readme_file = File.join gemspec_dir, "README.md"
FileUtils.mkdir_p gemspec_dir
- File.open readme_file, 'w' do |f|
+ File.open readme_file, "w" do |f|
f.write "My awesome gem"
end
- File.open gemspec_file, 'w' do |gs|
+ File.open gemspec_file, "w" do |gs|
gs.write @gem.to_ruby
end
@@ -342,14 +356,14 @@ class TestGemCommandsBuildCommand < Gem::TestCase
end
def test_execute_outside_dir_without_gem_name
- gemspec_dir = File.join(@tempdir, 'build_command_gem')
+ gemspec_dir = File.join(@tempdir, "build_command_gem")
gemspec_file = File.join(gemspec_dir, @gem.spec_name)
- readme_file = File.join gemspec_dir, 'README.md'
+ readme_file = File.join gemspec_dir, "README.md"
FileUtils.mkdir_p(gemspec_dir)
- File.open readme_file, 'w' do |f|
+ File.open readme_file, "w" do |f|
f.write "My awesome gem"
end
@@ -383,20 +397,20 @@ class TestGemCommandsBuildCommand < Gem::TestCase
end
def test_execute_outside_dir_with_external_gemspec
- gemspec_dir = File.join @tempdir, 'gemspec_dir'
+ gemspec_dir = File.join @tempdir, "gemspec_dir"
gemspec_file = File.join gemspec_dir, @gem.spec_name
- gemcode_dir = File.join @tempdir, 'build_command_gem'
- readme_file = File.join gemcode_dir, 'README.md'
+ gemcode_dir = File.join @tempdir, "build_command_gem"
+ readme_file = File.join gemcode_dir, "README.md"
FileUtils.mkdir_p gemspec_dir
FileUtils.mkdir_p gemcode_dir
- File.open readme_file, 'w' do |f|
+ File.open readme_file, "w" do |f|
f.write "My awesome gem in nested directory"
end
- File.open gemspec_file, 'w' do |gs|
+ File.open gemspec_file, "w" do |gs|
gs.write @gem.to_ruby
end
@@ -424,20 +438,20 @@ class TestGemCommandsBuildCommand < Gem::TestCase
end
def test_execute_outside_dir_with_external_relative_gemspec
- gemspec_dir = File.join @tempdir, 'gemspec_dir'
+ gemspec_dir = File.join @tempdir, "gemspec_dir"
gemspec_file = File.join gemspec_dir, @gem.spec_name
- gemcode_dir = File.join @tempdir, 'build_command_gem'
- readme_file = File.join gemcode_dir, 'README.md'
+ gemcode_dir = File.join @tempdir, "build_command_gem"
+ readme_file = File.join gemcode_dir, "README.md"
FileUtils.mkdir_p gemspec_dir
FileUtils.mkdir_p gemcode_dir
- File.open readme_file, 'w' do |f|
+ File.open readme_file, "w" do |f|
f.write "My awesome gem in nested directory"
end
- File.open gemspec_file, 'w' do |gs|
+ File.open gemspec_file, "w" do |gs|
gs.write @gem.to_ruby
end
@@ -467,7 +481,7 @@ class TestGemCommandsBuildCommand < Gem::TestCase
def test_can_find_gemspecs_without_dot_gemspec
gemspec_file = File.join(@tempdir, @gem.name)
- File.open gemspec_file + ".gemspec", 'w' do |gs|
+ File.open gemspec_file + ".gemspec", "w" do |gs|
gs.write @gem.to_ruby
end
@@ -571,7 +585,7 @@ class TestGemCommandsBuildCommand < Gem::TestCase
@gem.send :remove_instance_variable, :@rubygems_version
- File.open gemspec_file, 'w' do |gs|
+ File.open gemspec_file, "w" do |gs|
gs.write @gem.to_ruby
end
@@ -582,18 +596,18 @@ class TestGemCommandsBuildCommand < Gem::TestCase
end
def test_build_signed_gem
- pend 'openssl is missing' unless Gem::HAVE_OPENSSL && !java_platform?
+ pend "openssl is missing" unless Gem::HAVE_OPENSSL && !Gem.java_platform?
trust_dir = Gem::Security.trust_dir
- spec = util_spec 'some_gem' do |s|
+ spec = util_spec "some_gem" do |s|
s.signing_key = SIGNING_KEY
s.cert_chain = [CERT_FILE]
end
gemspec_file = File.join(@tempdir, spec.spec_name)
- File.open gemspec_file, 'w' do |gs|
+ File.open gemspec_file, "w" do |gs|
gs.write spec.to_ruby
end
@@ -609,7 +623,7 @@ class TestGemCommandsBuildCommand < Gem::TestCase
end
def test_build_signed_gem_with_cert_expiration_length_days
- pend 'openssl is missing' unless Gem::HAVE_OPENSSL && !java_platform?
+ pend "openssl is missing" unless Gem::HAVE_OPENSSL && !Gem.java_platform?
gem_path = File.join Gem.user_home, ".gem"
Dir.mkdir gem_path
@@ -622,14 +636,14 @@ class TestGemCommandsBuildCommand < Gem::TestCase
tmp_private_key_file = File.join gem_path, "gem-private_key.pem"
File.write(tmp_private_key_file, File.read(PRIVATE_KEY_FILE))
- spec = util_spec 'some_gem' do |s|
+ spec = util_spec "some_gem" do |s|
s.signing_key = tmp_private_key_file
s.cert_chain = [tmp_expired_cert_file]
end
gemspec_file = File.join(@tempdir, spec.spec_name)
- File.open gemspec_file, 'w' do |gs|
+ File.open gemspec_file, "w" do |gs|
gs.write spec.to_ruby
end
@@ -653,7 +667,7 @@ class TestGemCommandsBuildCommand < Gem::TestCase
end
def test_build_auto_resign_cert
- pend 'openssl is missing' unless Gem::HAVE_OPENSSL && !java_platform?
+ pend "openssl is missing" unless Gem::HAVE_OPENSSL && !Gem.java_platform?
gem_path = File.join Gem.user_home, ".gem"
Dir.mkdir gem_path
@@ -666,14 +680,14 @@ class TestGemCommandsBuildCommand < Gem::TestCase
tmp_private_key_file = File.join gem_path, "gem-private_key.pem"
File.write(tmp_private_key_file, File.read(PRIVATE_KEY_FILE))
- spec = util_spec 'some_gem' do |s|
+ spec = util_spec "some_gem" do |s|
s.signing_key = tmp_private_key_file
s.cert_chain = [tmp_expired_cert_file]
end
gemspec_file = File.join(@tempdir, spec.spec_name)
- File.open gemspec_file, 'w' do |gs|
+ File.open gemspec_file, "w" do |gs|
gs.write spec.to_ruby
end
@@ -689,7 +703,7 @@ class TestGemCommandsBuildCommand < Gem::TestCase
output = @ui.output.split "\n"
assert_equal "INFO: Your certificate has expired, trying to re-sign it...", output.shift
- assert_equal "INFO: Your cert: #{tmp_expired_cert_file } has been auto re-signed with the key: #{tmp_private_key_file}", output.shift
+ assert_equal "INFO: Your cert: #{tmp_expired_cert_file} has been auto re-signed with the key: #{tmp_private_key_file}", output.shift
assert_match(/INFO: Your expired cert will be located at: .+\Wgem-public_cert\.pem\.expired\.[0-9]+/, output.shift)
end
diff --git a/test/rubygems/test_gem_commands_cert_command.rb b/test/rubygems/test_gem_commands_cert_command.rb
index f722678a19..c173467935 100644
--- a/test/rubygems/test_gem_commands_cert_command.rb
+++ b/test/rubygems/test_gem_commands_cert_command.rb
@@ -1,27 +1,29 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/commands/cert_command'
+
+require_relative "helper"
+require "rubygems/commands/cert_command"
unless Gem::HAVE_OPENSSL
- warn 'Skipping `gem cert` tests. openssl not found.'
+ warn "Skipping `gem cert` tests. openssl not found."
end
if Gem.java_platform?
- warn 'Skipping `gem cert` tests on jruby.'
+ warn "Skipping `gem cert` tests on jruby."
end
class TestGemCommandsCertCommand < Gem::TestCase
- ALTERNATE_CERT = load_cert 'alternate'
- EXPIRED_PUBLIC_CERT = load_cert 'expired'
+ ALTERNATE_CERT = load_cert "alternate"
+ EXPIRED_PUBLIC_CERT = load_cert "expired"
- ALTERNATE_KEY_FILE = key_path 'alternate'
- PRIVATE_KEY_FILE = key_path 'private'
- PUBLIC_KEY_FILE = key_path 'public'
+ ALTERNATE_KEY_FILE = key_path "alternate"
+ PRIVATE_KEY_FILE = key_path "private"
+ PRIVATE_EC_KEY_FILE = key_path "private_ec"
+ PUBLIC_KEY_FILE = key_path "public"
- ALTERNATE_CERT_FILE = cert_path 'alternate'
- CHILD_CERT_FILE = cert_path 'child'
- PUBLIC_CERT_FILE = cert_path 'public'
- EXPIRED_PUBLIC_CERT_FILE = cert_path 'expired'
+ ALTERNATE_CERT_FILE = cert_path "alternate"
+ CHILD_CERT_FILE = cert_path "child"
+ PUBLIC_CERT_FILE = cert_path "public"
+ EXPIRED_PUBLIC_CERT_FILE = cert_path "expired"
def setup
super
@@ -43,9 +45,9 @@ class TestGemCommandsCertCommand < Gem::TestCase
@trust_dir.trust_cert PUBLIC_CERT
@trust_dir.trust_cert ALTERNATE_CERT
- matches = @cmd.certificates_matching ''
+ matches = @cmd.certificates_matching ""
- # HACK OpenSSL::X509::Certificate#== is Object#==, so do this the hard way
+ # HACK: OpenSSL::X509::Certificate#== is Object#==, so do this the hard way
match = matches.next
assert_equal ALTERNATE_CERT.to_pem, match.first.to_pem
assert_equal @trust_dir.cert_path(ALTERNATE_CERT), match.last
@@ -63,7 +65,7 @@ class TestGemCommandsCertCommand < Gem::TestCase
@trust_dir.trust_cert PUBLIC_CERT
@trust_dir.trust_cert ALTERNATE_CERT
- matches = @cmd.certificates_matching 'alternate'
+ matches = @cmd.certificates_matching "alternate"
match = matches.next
assert_equal ALTERNATE_CERT.to_pem, match.first.to_pem
@@ -90,7 +92,7 @@ class TestGemCommandsCertCommand < Gem::TestCase
end
def test_execute_add_twice
- self.class.cert_path 'alternate'
+ self.class.cert_path "alternate"
@cmd.handle_options %W[
--add #{PUBLIC_CERT_FILE}
@@ -111,7 +113,7 @@ Added '/CN=alternate/DC=example'
end
def test_execute_build
- passphrase = 'Foo bar'
+ passphrase = "Foo bar"
@cmd.handle_options %W[--build nobody@example.com]
@@ -127,9 +129,9 @@ Added '/CN=alternate/DC=example'
output.shift
assert_equal "Please repeat the passphrase for your Private Key: ",
output.shift
- assert_equal "Certificate: #{File.join @tempdir, 'gem-public_cert.pem'}",
+ assert_equal "Certificate: #{File.join @tempdir, "gem-public_cert.pem"}",
output.shift
- assert_equal "Private Key: #{File.join @tempdir, 'gem-private_key.pem'}",
+ assert_equal "Private Key: #{File.join @tempdir, "gem-private_key.pem"}",
output.shift
assert_equal "Don't forget to move the key file to somewhere private!",
@@ -138,12 +140,48 @@ Added '/CN=alternate/DC=example'
assert_empty output
assert_empty @build_ui.error
- assert_path_exist File.join(@tempdir, 'gem-private_key.pem')
- assert_path_exist File.join(@tempdir, 'gem-public_cert.pem')
+ assert_path_exist File.join(@tempdir, "gem-private_key.pem")
+ assert_path_exist File.join(@tempdir, "gem-public_cert.pem")
+ end
+
+ def test_execute_build_key_algorithm_ec_key
+ passphrase = "Foo bar"
+
+ @cmd.handle_options %W[--build nobody@example.com --key-algorithm ec]
+
+ @build_ui = Gem::MockGemUi.new "#{passphrase}\n#{passphrase}"
+
+ use_ui @build_ui do
+ @cmd.execute
+ end
+
+ output = @build_ui.output.squeeze("\n").split "\n"
+
+ assert_equal "Passphrase for your Private Key: ",
+ output.shift
+ assert_equal "Please repeat the passphrase for your Private Key: ",
+ output.shift
+ assert_equal "Certificate: #{File.join @tempdir, "gem-public_cert.pem"}",
+ output.shift
+ assert_equal "Private Key: #{File.join @tempdir, "gem-private_key.pem"}",
+ output.shift
+
+ assert_equal "Don't forget to move the key file to somewhere private!",
+ output.shift
+
+ assert_empty output
+ assert_empty @build_ui.error
+
+ assert_path_exist File.join(@tempdir, "gem-private_key.pem")
+
+ cert_path = File.join(@tempdir, "gem-public_cert.pem")
+ assert_path_exist cert_path
+ cert = OpenSSL::X509::Certificate.new(File.read(cert_path))
+ assert cert.public_key.is_a? OpenSSL::PKey::EC
end
def test_execute_build_bad_email_address
- passphrase = 'Foo bar'
+ passphrase = "Foo bar"
email = "nobody@"
@cmd.handle_options %W[--build #{email}]
@@ -151,7 +189,6 @@ Added '/CN=alternate/DC=example'
@build_ui = Gem::MockGemUi.new "#{passphrase}\n#{passphrase}"
use_ui @build_ui do
-
e = assert_raise Gem::CommandLineError do
@cmd.execute
end
@@ -159,13 +196,13 @@ Added '/CN=alternate/DC=example'
assert_equal "Invalid email address #{email}",
e.message
- assert_path_not_exist File.join(@tempdir, 'gem-private_key.pem')
- assert_path_not_exist File.join(@tempdir, 'gem-public_cert.pem')
+ assert_path_not_exist File.join(@tempdir, "gem-private_key.pem")
+ assert_path_not_exist File.join(@tempdir, "gem-public_cert.pem")
end
end
def test_execute_build_expiration_days
- passphrase = 'Foo bar'
+ passphrase = "Foo bar"
@cmd.handle_options %W[
--build nobody@example.com
@@ -184,9 +221,9 @@ Added '/CN=alternate/DC=example'
output.shift
assert_equal "Please repeat the passphrase for your Private Key: ",
output.shift
- assert_equal "Certificate: #{File.join @tempdir, 'gem-public_cert.pem'}",
+ assert_equal "Certificate: #{File.join @tempdir, "gem-public_cert.pem"}",
output.shift
- assert_equal "Private Key: #{File.join @tempdir, 'gem-private_key.pem'}",
+ assert_equal "Private Key: #{File.join @tempdir, "gem-private_key.pem"}",
output.shift
assert_equal "Don't forget to move the key file to somewhere private!",
@@ -195,8 +232,8 @@ Added '/CN=alternate/DC=example'
assert_empty output
assert_empty @build_ui.error
- assert_path_exist File.join(@tempdir, 'gem-private_key.pem')
- assert_path_exist File.join(@tempdir, 'gem-public_cert.pem')
+ assert_path_exist File.join(@tempdir, "gem-private_key.pem")
+ assert_path_exist File.join(@tempdir, "gem-public_cert.pem")
pem = File.read("#{@tempdir}/gem-public_cert.pem")
cert = OpenSSL::X509::Certificate.new(pem)
@@ -206,8 +243,8 @@ Added '/CN=alternate/DC=example'
end
def test_execute_build_bad_passphrase_confirmation
- passphrase = 'Foo bar'
- passphrase_confirmation = 'Fu bar'
+ passphrase = "Foo bar"
+ passphrase_confirmation = "Fu bar"
@cmd.handle_options %W[--build nobody@example.com]
@@ -229,11 +266,10 @@ Added '/CN=alternate/DC=example'
assert_equal "Passphrase and passphrase confirmation don't match",
e.message
-
end
- assert_path_not_exist File.join(@tempdir, 'gem-private_key.pem')
- assert_path_not_exist File.join(@tempdir, 'gem-public_cert.pem')
+ assert_path_not_exist File.join(@tempdir, "gem-private_key.pem")
+ assert_path_not_exist File.join(@tempdir, "gem-public_cert.pem")
end
def test_execute_build_key
@@ -248,14 +284,14 @@ Added '/CN=alternate/DC=example'
output = @ui.output.split "\n"
- assert_equal "Certificate: #{File.join @tempdir, 'gem-public_cert.pem'}",
+ assert_equal "Certificate: #{File.join @tempdir, "gem-public_cert.pem"}",
output.shift
assert_empty output
assert_empty @ui.error
- assert_path_exist File.join(@tempdir, 'gem-public_cert.pem')
- assert_path_not_exist File.join(@tempdir, 'gem-private_key.pem')
+ assert_path_exist File.join(@tempdir, "gem-public_cert.pem")
+ assert_path_not_exist File.join(@tempdir, "gem-private_key.pem")
end
def test_execute_build_encrypted_key
@@ -270,13 +306,35 @@ Added '/CN=alternate/DC=example'
output = @ui.output.split "\n"
- assert_equal "Certificate: #{File.join @tempdir, 'gem-public_cert.pem'}",
+ assert_equal "Certificate: #{File.join @tempdir, "gem-public_cert.pem"}",
+ output.shift
+
+ assert_empty output
+ assert_empty @ui.error
+
+ assert_path_exist File.join(@tempdir, "gem-public_cert.pem")
+ end
+
+ def test_execute_build_ec_key
+ @cmd.handle_options %W[
+ --build nobody@example.com
+ --private-key #{PRIVATE_EC_KEY_FILE}
+ ]
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ output = @ui.output.split "\n"
+
+ assert_equal "Certificate: #{File.join @tempdir, "gem-public_cert.pem"}",
output.shift
assert_empty output
assert_empty @ui.error
- assert_path_exist File.join(@tempdir, 'gem-public_cert.pem')
+ assert_path_exist File.join(@tempdir, "gem-public_cert.pem")
+ assert_path_not_exist File.join(@tempdir, "gem-private_key.pem")
end
def test_execute_certificate
@@ -284,8 +342,8 @@ Added '/CN=alternate/DC=example'
@cmd.handle_options %W[--certificate #{PUBLIC_CERT_FILE}]
end
- assert_equal '', @ui.output
- assert_equal '', @ui.error
+ assert_equal "", @ui.output
+ assert_equal "", @ui.error
assert_equal PUBLIC_CERT.to_pem, @cmd.options[:issuer_cert].to_pem
end
@@ -324,8 +382,8 @@ Added '/CN=alternate/DC=example'
@cmd.send :handle_options, %W[--private-key #{PRIVATE_KEY_FILE}]
end
- assert_equal '', @ui.output
- assert_equal '', @ui.error
+ assert_equal "", @ui.output
+ assert_equal "", @ui.error
assert_equal PRIVATE_KEY.to_pem, @cmd.options[:key].to_pem
end
@@ -335,8 +393,8 @@ Added '/CN=alternate/DC=example'
@cmd.send :handle_options, %W[--private-key #{ENCRYPTED_PRIVATE_KEY_PATH}]
end
- assert_equal '', @ui.output
- assert_equal '', @ui.error
+ assert_equal "", @ui.output
+ assert_equal "", @ui.error
assert_equal ENCRYPTED_PRIVATE_KEY.to_pem, @cmd.options[:key].to_pem
end
@@ -355,7 +413,7 @@ Added '/CN=alternate/DC=example'
end
assert_equal "Removed '/CN=nobody/DC=example'\n", @ui.output
- assert_equal '', @ui.error
+ assert_equal "", @ui.error
assert_path_not_exist cert_path
end
@@ -382,7 +440,7 @@ Removed '/CN=nobody/DC=example'
EXPECTED
assert_equal expected, @ui.output
- assert_equal '', @ui.error
+ assert_equal "", @ui.error
assert_path_not_exist public_path
assert_path_not_exist alternate_path
@@ -410,17 +468,17 @@ Removed '/CN=alternate/DC=example'
EXPECTED
assert_equal expected, @ui.output
- assert_equal '', @ui.error
+ assert_equal "", @ui.error
assert_path_not_exist public_path
assert_path_not_exist alternate_path
end
def test_execute_sign
- path = File.join @tempdir, 'cert.pem'
- Gem::Security.write ALTERNATE_CERT, path, 0600
+ path = File.join @tempdir, "cert.pem"
+ Gem::Security.write ALTERNATE_CERT, path, 0o600
- assert_equal '/CN=alternate/DC=example', ALTERNATE_CERT.issuer.to_s
+ assert_equal "/CN=alternate/DC=example", ALTERNATE_CERT.issuer.to_s
@cmd.handle_options %W[
--private-key #{PRIVATE_KEY_FILE}
@@ -433,23 +491,23 @@ Removed '/CN=alternate/DC=example'
@cmd.execute
end
- assert_equal '', @ui.output
- assert_equal '', @ui.error
+ assert_equal "", @ui.output
+ assert_equal "", @ui.error
cert = OpenSSL::X509::Certificate.new File.read path
- assert_equal '/CN=nobody/DC=example', cert.issuer.to_s
+ assert_equal "/CN=nobody/DC=example", cert.issuer.to_s
- mask = 0100600 & (~File.umask)
+ mask = 0o100600 & (~File.umask)
- assert_equal mask, File.stat(path).mode unless win_platform?
+ assert_equal mask, File.stat(path).mode unless Gem.win_platform?
end
def test_execute_sign_encrypted_key
- path = File.join @tempdir, 'cert.pem'
- Gem::Security.write ALTERNATE_CERT, path, 0600
+ path = File.join @tempdir, "cert.pem"
+ Gem::Security.write ALTERNATE_CERT, path, 0o600
- assert_equal '/CN=alternate/DC=example', ALTERNATE_CERT.issuer.to_s
+ assert_equal "/CN=alternate/DC=example", ALTERNATE_CERT.issuer.to_s
@cmd.handle_options %W[
--private-key #{ENCRYPTED_PRIVATE_KEY_PATH}
@@ -462,31 +520,31 @@ Removed '/CN=alternate/DC=example'
@cmd.execute
end
- assert_equal '', @ui.output
- assert_equal '', @ui.error
+ assert_equal "", @ui.output
+ assert_equal "", @ui.error
cert = OpenSSL::X509::Certificate.new File.read path
- assert_equal '/CN=nobody/DC=example', cert.issuer.to_s
+ assert_equal "/CN=nobody/DC=example", cert.issuer.to_s
- mask = 0100600 & (~File.umask)
+ mask = 0o100600 & (~File.umask)
- assert_equal mask, File.stat(path).mode unless win_platform?
+ assert_equal mask, File.stat(path).mode unless Gem.win_platform?
end
def test_execute_sign_default
- FileUtils.mkdir_p File.join Gem.user_home, '.gem'
+ FileUtils.mkdir_p File.join Gem.user_home, ".gem"
- private_key_path = File.join Gem.user_home, '.gem', 'gem-private_key.pem'
+ private_key_path = File.join Gem.user_home, ".gem", "gem-private_key.pem"
Gem::Security.write PRIVATE_KEY, private_key_path
- public_cert_path = File.join Gem.user_home, '.gem', 'gem-public_cert.pem'
+ public_cert_path = File.join Gem.user_home, ".gem", "gem-public_cert.pem"
Gem::Security.write PUBLIC_CERT, public_cert_path
- path = File.join @tempdir, 'cert.pem'
- Gem::Security.write ALTERNATE_CERT, path, 0600
+ path = File.join @tempdir, "cert.pem"
+ Gem::Security.write ALTERNATE_CERT, path, 0o600
- assert_equal '/CN=alternate/DC=example', ALTERNATE_CERT.issuer.to_s
+ assert_equal "/CN=alternate/DC=example", ALTERNATE_CERT.issuer.to_s
@cmd.handle_options %W[--sign #{path}]
@@ -494,31 +552,31 @@ Removed '/CN=alternate/DC=example'
@cmd.execute
end
- assert_equal '', @ui.output
- assert_equal '', @ui.error
+ assert_equal "", @ui.output
+ assert_equal "", @ui.error
cert = OpenSSL::X509::Certificate.new File.read path
- assert_equal '/CN=nobody/DC=example', cert.issuer.to_s
+ assert_equal "/CN=nobody/DC=example", cert.issuer.to_s
- mask = 0100600 & (~File.umask)
+ mask = 0o100600 & (~File.umask)
- assert_equal mask, File.stat(path).mode unless win_platform?
+ assert_equal mask, File.stat(path).mode unless Gem.win_platform?
end
def test_execute_sign_default_encrypted_key
- FileUtils.mkdir_p File.join(Gem.user_home, '.gem')
+ FileUtils.mkdir_p File.join(Gem.user_home, ".gem")
- private_key_path = File.join Gem.user_home, '.gem', 'gem-private_key.pem'
- Gem::Security.write ENCRYPTED_PRIVATE_KEY, private_key_path, 0600, PRIVATE_KEY_PASSPHRASE
+ private_key_path = File.join Gem.user_home, ".gem", "gem-private_key.pem"
+ Gem::Security.write ENCRYPTED_PRIVATE_KEY, private_key_path, 0o600, PRIVATE_KEY_PASSPHRASE
- public_cert_path = File.join Gem.user_home, '.gem', 'gem-public_cert.pem'
+ public_cert_path = File.join Gem.user_home, ".gem", "gem-public_cert.pem"
Gem::Security.write PUBLIC_CERT, public_cert_path
- path = File.join @tempdir, 'cert.pem'
- Gem::Security.write ALTERNATE_CERT, path, 0600
+ path = File.join @tempdir, "cert.pem"
+ Gem::Security.write ALTERNATE_CERT, path, 0o600
- assert_equal '/CN=alternate/DC=example', ALTERNATE_CERT.issuer.to_s
+ assert_equal "/CN=alternate/DC=example", ALTERNATE_CERT.issuer.to_s
@cmd.handle_options %W[--sign #{path}]
@@ -526,28 +584,28 @@ Removed '/CN=alternate/DC=example'
@cmd.execute
end
- assert_equal '', @ui.output
- assert_equal '', @ui.error
+ assert_equal "", @ui.output
+ assert_equal "", @ui.error
cert = OpenSSL::X509::Certificate.new File.read path
- assert_equal '/CN=nobody/DC=example', cert.issuer.to_s
+ assert_equal "/CN=nobody/DC=example", cert.issuer.to_s
- mask = 0100600 & (~File.umask)
+ mask = 0o100600 & (~File.umask)
- assert_equal mask, File.stat(path).mode unless win_platform?
+ assert_equal mask, File.stat(path).mode unless Gem.win_platform?
end
def test_execute_sign_no_cert
- FileUtils.mkdir_p File.join Gem.user_home, '.gem'
+ FileUtils.mkdir_p File.join Gem.user_home, ".gem"
- private_key_path = File.join Gem.user_home, '.gem', 'gem-private_key.pem'
+ private_key_path = File.join Gem.user_home, ".gem", "gem-private_key.pem"
Gem::Security.write PRIVATE_KEY, private_key_path
- path = File.join @tempdir, 'cert.pem'
- Gem::Security.write ALTERNATE_CERT, path, 0600
+ path = File.join @tempdir, "cert.pem"
+ Gem::Security.write ALTERNATE_CERT, path, 0o600
- assert_equal '/CN=alternate/DC=example', ALTERNATE_CERT.issuer.to_s
+ assert_equal "/CN=alternate/DC=example", ALTERNATE_CERT.issuer.to_s
@cmd.handle_options %W[--sign #{path}]
@@ -557,7 +615,7 @@ Removed '/CN=alternate/DC=example'
end
end
- assert_equal '', @ui.output
+ assert_equal "", @ui.output
expected = <<-EXPECTED
ERROR: --certificate not specified and ~/.gem/gem-public_cert.pem does not exist
@@ -567,15 +625,15 @@ ERROR: --certificate not specified and ~/.gem/gem-public_cert.pem does not exis
end
def test_execute_sign_no_key
- FileUtils.mkdir_p File.join Gem.user_home, '.gem'
+ FileUtils.mkdir_p File.join Gem.user_home, ".gem"
- public_cert_path = File.join Gem.user_home, '.gem', 'gem-public_cert.pem'
+ public_cert_path = File.join Gem.user_home, ".gem", "gem-public_cert.pem"
Gem::Security.write PUBLIC_CERT, public_cert_path
- path = File.join @tempdir, 'cert.pem'
- Gem::Security.write ALTERNATE_CERT, path, 0600
+ path = File.join @tempdir, "cert.pem"
+ Gem::Security.write ALTERNATE_CERT, path, 0o600
- assert_equal '/CN=alternate/DC=example', ALTERNATE_CERT.issuer.to_s
+ assert_equal "/CN=alternate/DC=example", ALTERNATE_CERT.issuer.to_s
@cmd.handle_options %W[--sign #{path}]
@@ -585,7 +643,7 @@ ERROR: --certificate not specified and ~/.gem/gem-public_cert.pem does not exis
end
end
- assert_equal '', @ui.output
+ assert_equal "", @ui.output
expected = <<-EXPECTED
ERROR: --private-key not specified and ~/.gem/gem-private_key.pem does not exist
@@ -598,10 +656,10 @@ ERROR: --private-key not specified and ~/.gem/gem-private_key.pem does not exis
gem_path = File.join Gem.user_home, ".gem"
Dir.mkdir gem_path
- path = File.join @tempdir, 'cert.pem'
- Gem::Security.write EXPIRED_PUBLIC_CERT, path, 0600
+ path = File.join @tempdir, "cert.pem"
+ Gem::Security.write EXPIRED_PUBLIC_CERT, path, 0o600
- assert_equal '/CN=nobody/DC=example', EXPIRED_PUBLIC_CERT.issuer.to_s
+ assert_equal "/CN=nobody/DC=example", EXPIRED_PUBLIC_CERT.issuer.to_s
tmp_expired_cert_file = File.join(Dir.tmpdir, File.basename(EXPIRED_PUBLIC_CERT_FILE))
@cleanup << tmp_expired_cert_file
@@ -619,21 +677,22 @@ ERROR: --private-key not specified and ~/.gem/gem-private_key.pem does not exis
expected_path = File.join(gem_path, "#{File.basename(tmp_expired_cert_file)}.expired")
+ assert_include(@ui.output, "INFO: Your certificate #{tmp_expired_cert_file} has been re-signed\n")
assert_match(
- /INFO: Your certificate #{tmp_expired_cert_file} has been re-signed\nINFO: Your expired certificate will be located at: #{expected_path}\.[0-9]+/,
+ /INFO: Your expired certificate will be located at: #{Regexp.quote(expected_path)}\.[0-9]+/,
@ui.output
)
- assert_equal '', @ui.error
+ assert_equal "", @ui.error
end
def test_execute_re_sign_with_cert_expiration_length_days
gem_path = File.join Gem.user_home, ".gem"
Dir.mkdir gem_path
- path = File.join @tempdir, 'cert.pem'
- Gem::Security.write EXPIRED_PUBLIC_CERT, path, 0600
+ path = File.join @tempdir, "cert.pem"
+ Gem::Security.write EXPIRED_PUBLIC_CERT, path, 0o600
- assert_equal '/CN=nobody/DC=example', EXPIRED_PUBLIC_CERT.issuer.to_s
+ assert_equal "/CN=nobody/DC=example", EXPIRED_PUBLIC_CERT.issuer.to_s
tmp_expired_cert_file = File.join(Dir.tmpdir, File.basename(EXPIRED_PUBLIC_CERT_FILE))
@cleanup << tmp_expired_cert_file
@@ -655,7 +714,7 @@ ERROR: --private-key not specified and ~/.gem/gem-private_key.pem does not exis
cert_days_to_expire = (re_signed_cert.not_after - re_signed_cert.not_before).to_i / (24 * 60 * 60)
assert_equal(28, cert_days_to_expire)
- assert_equal '', @ui.error
+ assert_equal "", @ui.error
end
def test_handle_options
@@ -674,29 +733,29 @@ ERROR: --private-key not specified and ~/.gem/gem-private_key.pem does not exis
]
assert_equal [PUBLIC_CERT.to_pem, ALTERNATE_CERT.to_pem],
- @cmd.options[:add].map {|cert| cert.to_pem }
+ @cmd.options[:add].map(&:to_pem)
assert_equal %w[nobody example], @cmd.options[:remove]
assert_equal %w[nobody@example other@example],
- @cmd.options[:build].map {|name| name.to_s }
+ @cmd.options[:build].map(&:to_s)
- assert_equal ['', 'example'], @cmd.options[:list]
+ assert_equal ["", "example"], @cmd.options[:list]
end
def test_handle_options_add_bad
- nonexistent = File.join @tempdir, 'nonexistent'
- e = assert_raise OptionParser::InvalidArgument do
+ nonexistent = File.join @tempdir, "nonexistent"
+ e = assert_raise Gem::OptionParser::InvalidArgument do
@cmd.handle_options %W[--add #{nonexistent}]
end
assert_equal "invalid argument: --add #{nonexistent}: does not exist",
e.message
- bad = File.join @tempdir, 'bad'
+ bad = File.join @tempdir, "bad"
FileUtils.touch bad
- e = assert_raise OptionParser::InvalidArgument do
+ e = assert_raise Gem::OptionParser::InvalidArgument do
@cmd.handle_options %W[--add #{bad}]
end
@@ -705,51 +764,51 @@ ERROR: --private-key not specified and ~/.gem/gem-private_key.pem does not exis
end
def test_handle_options_certificate
- nonexistent = File.join @tempdir, 'nonexistent'
- e = assert_raise OptionParser::InvalidArgument do
+ nonexistent = File.join @tempdir, "nonexistent"
+ e = assert_raise Gem::OptionParser::InvalidArgument do
@cmd.handle_options %W[--certificate #{nonexistent}]
end
assert_equal "invalid argument: --certificate #{nonexistent}: does not exist",
e.message
- bad = File.join @tempdir, 'bad'
+ bad = File.join @tempdir, "bad"
FileUtils.touch bad
- e = assert_raise OptionParser::InvalidArgument do
+ e = assert_raise Gem::OptionParser::InvalidArgument do
@cmd.handle_options %W[--certificate #{bad}]
end
- assert_equal "invalid argument: " +
+ assert_equal "invalid argument: " \
"--certificate #{bad}: invalid X509 certificate",
e.message
end
def test_handle_options_key_bad
- nonexistent = File.join @tempdir, 'nonexistent'
- e = assert_raise OptionParser::InvalidArgument do
+ nonexistent = File.join @tempdir, "nonexistent"
+ e = assert_raise Gem::OptionParser::InvalidArgument do
@cmd.handle_options %W[--private-key #{nonexistent}]
end
- assert_equal "invalid argument: " +
+ assert_equal "invalid argument: " \
"--private-key #{nonexistent}: does not exist",
e.message
- bad = File.join @tempdir, 'bad'
+ bad = File.join @tempdir, "bad"
FileUtils.touch bad
- e = assert_raise OptionParser::InvalidArgument do
+ e = assert_raise Gem::OptionParser::InvalidArgument do
@cmd.handle_options %W[--private-key #{bad}]
end
- assert_equal "invalid argument: --private-key #{bad}: invalid RSA key",
+ assert_equal "invalid argument: --private-key #{bad}: invalid RSA, DSA, or EC key",
e.message
- e = assert_raise OptionParser::InvalidArgument do
+ e = assert_raise Gem::OptionParser::InvalidArgument do
@cmd.handle_options %W[--private-key #{PUBLIC_KEY_FILE}]
end
- assert_equal "invalid argument: " +
+ assert_equal "invalid argument: " \
"--private-key #{PUBLIC_KEY_FILE}: private key not found",
e.message
end
@@ -791,8 +850,8 @@ ERROR: --private-key not specified and ~/.gem/gem-private_key.pem does not exis
end
def test_handle_options_sign_nonexistent
- nonexistent = File.join @tempdir, 'nonexistent'
- e = assert_raise OptionParser::InvalidArgument do
+ nonexistent = File.join @tempdir, "nonexistent"
+ e = assert_raise Gem::OptionParser::InvalidArgument do
@cmd.handle_options %W[
--private-key #{ALTERNATE_KEY_FILE}
diff --git a/test/rubygems/test_gem_commands_check_command.rb b/test/rubygems/test_gem_commands_check_command.rb
index f280b060c4..65a3093b13 100644
--- a/test/rubygems/test_gem_commands_check_command.rb
+++ b/test/rubygems/test_gem_commands_check_command.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/commands/check_command'
+
+require_relative "helper"
+require "rubygems/commands/check_command"
class TestGemCommandsCheckCommand < Gem::TestCase
def setup
@@ -45,8 +46,8 @@ class TestGemCommandsCheckCommand < Gem::TestCase
end
def test_doctor
- gem 'a'
- b = gem 'b'
+ gem "a"
+ b = gem "b"
FileUtils.rm b.spec_file
diff --git a/test/rubygems/test_gem_commands_cleanup_command.rb b/test/rubygems/test_gem_commands_cleanup_command.rb
index fc98998012..bcb8871b57 100644
--- a/test/rubygems/test_gem_commands_cleanup_command.rb
+++ b/test/rubygems/test_gem_commands_cleanup_command.rb
@@ -1,7 +1,8 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/commands/cleanup_command'
-require 'rubygems/installer'
+
+require_relative "helper"
+require "rubygems/commands/cleanup_command"
+require "rubygems/installer"
class TestGemCommandsCleanupCommand < Gem::TestCase
def setup
@@ -9,8 +10,8 @@ class TestGemCommandsCleanupCommand < Gem::TestCase
@cmd = Gem::Commands::CleanupCommand.new
- @a_1 = util_spec 'a', 1
- @a_2 = util_spec 'a', 2
+ @a_1 = util_spec "a", 1
+ @a_2 = util_spec "a", 2
install_gem @a_1
install_gem @a_2
@@ -66,12 +67,12 @@ class TestGemCommandsCleanupCommand < Gem::TestCase
end
def test_execute_all_dependencies
- @b_1 = util_spec 'b', 1 do |s|
- s.add_dependency 'a', '1'
+ @b_1 = util_spec "b", 1 do |s|
+ s.add_dependency "a", "1"
end
- @b_2 = util_spec 'b', 2 do |s|
- s.add_dependency 'a', '2'
+ @b_2 = util_spec "b", 2 do |s|
+ s.add_dependency "a", "2"
end
install_gem @b_1
@@ -86,12 +87,12 @@ class TestGemCommandsCleanupCommand < Gem::TestCase
end
def test_execute_dev_dependencies
- @b_1 = util_spec 'b', 1 do |s|
- s.add_development_dependency 'a', '1'
+ @b_1 = util_spec "b", 1 do |s|
+ s.add_development_dependency "a", "1"
end
- @c_1 = util_spec 'c', 1 do |s|
- s.add_development_dependency 'a', '2'
+ @c_1 = util_spec "c", 1 do |s|
+ s.add_development_dependency "a", "2"
end
install_gem @b_1
@@ -105,12 +106,12 @@ class TestGemCommandsCleanupCommand < Gem::TestCase
end
def test_execute_without_dev_dependencies
- @b_1 = util_spec 'b', 1 do |s|
- s.add_development_dependency 'a', '1'
+ @b_1 = util_spec "b", 1 do |s|
+ s.add_development_dependency "a", "1"
end
- @c_1 = util_spec 'c', 1 do |s|
- s.add_development_dependency 'a', '2'
+ @c_1 = util_spec "c", 1 do |s|
+ s.add_development_dependency "a", "2"
end
install_gem @b_1
@@ -124,14 +125,14 @@ class TestGemCommandsCleanupCommand < Gem::TestCase
end
def test_execute_all
- gemhome2 = File.join @tempdir, 'gemhome2'
+ gemhome2 = File.join @tempdir, "gemhome2"
Gem.ensure_gem_subdirectories gemhome2
Gem.use_paths @gemhome, gemhome2
- @b_1 = util_spec 'b', 1
- @b_2 = util_spec 'b', 2
+ @b_1 = util_spec "b", 1
+ @b_2 = util_spec "b", 2
install_gem @b_1
install_gem @b_2
@@ -140,15 +141,15 @@ class TestGemCommandsCleanupCommand < Gem::TestCase
@cmd.execute
- assert_equal @gemhome, Gem.dir, 'GEM_HOME'
- assert_equal [@gemhome, gemhome2], Gem.path.sort, 'GEM_PATH'
+ assert_equal @gemhome, Gem.dir, "GEM_HOME"
+ assert_equal [@gemhome, gemhome2], Gem.path.sort, "GEM_PATH"
assert_path_not_exist @a_1.gem_dir
assert_path_not_exist @b_1.gem_dir
end
def test_execute_all_user
- @a_1_1, = util_gem 'a', '1.1'
+ @a_1_1, = util_gem "a", "1.1"
@a_1_1 = install_gem @a_1_1 # pick up user install path
Gem::Specification.dirs = [Gem.dir, Gem.user_dir]
@@ -165,10 +166,10 @@ class TestGemCommandsCleanupCommand < Gem::TestCase
end
def test_execute_all_user_no_sudo
- FileUtils.chmod 0555, @gemhome
+ FileUtils.chmod 0o555, @gemhome
- @a_1_1, = util_gem 'a', '1.1'
- @a_1_1 = install_gem @a_1_1, :user_install => true # pick up user install path
+ @a_1_1, = util_gem "a", "1.1"
+ @a_1_1 = install_gem @a_1_1, user_install: true # pick up user install path
Gem::Specification.dirs = [Gem.dir, Gem.user_dir]
@@ -182,8 +183,8 @@ class TestGemCommandsCleanupCommand < Gem::TestCase
assert_path_exist @a_1.gem_dir
assert_path_exist @a_1_1.gem_dir
ensure
- FileUtils.chmod 0755, @gemhome
- end unless win_platform? || Process.uid.zero?
+ FileUtils.chmod 0o755, @gemhome
+ end unless Gem.win_platform? || Process.uid.zero?
def test_execute_dry_run
@cmd.options[:args] = %w[a]
@@ -195,11 +196,11 @@ class TestGemCommandsCleanupCommand < Gem::TestCase
end
def test_execute_keeps_older_versions_with_deps
- @b_1 = util_spec 'b', 1
- @b_2 = util_spec 'b', 2
+ @b_1 = util_spec "b", 1
+ @b_2 = util_spec "b", 2
- @c = util_spec 'c', 1 do |s|
- s.add_dependency 'b', '1'
+ @c = util_spec "c", 1 do |s|
+ s.add_dependency "b", "1"
end
install_gem @b_1
@@ -216,9 +217,9 @@ class TestGemCommandsCleanupCommand < Gem::TestCase
def test_execute_ignore_default_gem_verbose
Gem.configuration.verbose = :really
- @b_1 = util_spec 'b', 1
+ @b_1 = util_spec "b", 1
@b_default = new_default_spec "b", "2"
- @b_2 = util_spec 'b', 3
+ @b_2 = util_spec "b", 3
install_gem @b_1
install_default_gems @b_default
@@ -230,23 +231,23 @@ class TestGemCommandsCleanupCommand < Gem::TestCase
@cmd.execute
end
- assert_match %r{^Skipped default gems: b-2}, @ui.output
+ assert_match(/^Skipped default gems: b-2/, @ui.output)
assert_empty @ui.error
end
def test_execute_remove_gem_home_only
- c_1, = util_gem 'c', '1'
- c_2, = util_gem 'c', '2'
- d_1, = util_gem 'd', '1'
- d_2, = util_gem 'd', '2'
- e_1, = util_gem 'e', '1'
- e_2, = util_gem 'e', '2'
-
- c_1 = install_gem c_1, :user_install => true # pick up user install path
+ c_1, = util_gem "c", "1"
+ c_2, = util_gem "c", "2"
+ d_1, = util_gem "d", "1"
+ d_2, = util_gem "d", "2"
+ e_1, = util_gem "e", "1"
+ e_2, = util_gem "e", "2"
+
+ c_1 = install_gem c_1, user_install: true # pick up user install path
c_2 = install_gem c_2
d_1 = install_gem d_1
- d_2 = install_gem d_2, :user_install => true # pick up user install path
+ d_2 = install_gem d_2, user_install: true # pick up user install path
e_1 = install_gem e_1
e_2 = install_gem e_2
@@ -263,14 +264,14 @@ class TestGemCommandsCleanupCommand < Gem::TestCase
end
def test_execute_user_install
- c_1, = util_gem 'c', '1.0'
- c_2, = util_gem 'c', '1.1'
+ c_1, = util_gem "c", "1.0"
+ c_2, = util_gem "c", "1.1"
- d_1, = util_gem 'd', '1.0'
- d_2, = util_gem 'd', '1.1'
+ d_1, = util_gem "d", "1.0"
+ d_2, = util_gem "d", "1.1"
- c_1 = install_gem c_1, :user_install => true # pick up user install path
- c_2 = install_gem c_2, :user_install => true # pick up user install path
+ c_1 = install_gem c_1, user_install: true # pick up user install path
+ c_2 = install_gem c_2, user_install: true # pick up user install path
d_1 = install_gem d_1
d_2 = install_gem d_2
diff --git a/test/rubygems/test_gem_commands_contents_command.rb b/test/rubygems/test_gem_commands_contents_command.rb
index d79174717b..d8e6ba3dec 100644
--- a/test/rubygems/test_gem_commands_contents_command.rb
+++ b/test/rubygems/test_gem_commands_contents_command.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/commands/contents_command'
+
+require_relative "helper"
+require "rubygems/commands/contents_command"
class TestGemCommandsContentsCommand < Gem::TestCase
def setup
@@ -20,22 +21,22 @@ class TestGemCommandsContentsCommand < Gem::TestCase
def test_execute
@cmd.options[:args] = %w[foo]
- gem 'foo'
+ gem "foo"
use_ui @ui do
@cmd.execute
end
assert_match %r{lib/foo\.rb}, @ui.output
- assert_match %r{Rakefile}, @ui.output
+ assert_match(/Rakefile/, @ui.output)
assert_equal "", @ui.error
end
def test_execute_all
@cmd.options[:all] = true
- gem 'foo'
- gem 'bar'
+ gem "foo"
+ gem "bar"
use_ui @ui do
@cmd.execute
@@ -43,7 +44,7 @@ class TestGemCommandsContentsCommand < Gem::TestCase
assert_match %r{lib/foo\.rb}, @ui.output
assert_match %r{lib/bar\.rb}, @ui.output
- assert_match %r{Rakefile}, @ui.output
+ assert_match(/Rakefile/, @ui.output)
assert_equal "", @ui.error
end
@@ -56,22 +57,22 @@ class TestGemCommandsContentsCommand < Gem::TestCase
end
end
- assert_match %r{Unable to find gem 'foo' in default gem paths}, @ui.output
- assert_match %r{Directories searched:}, @ui.output
+ assert_match(/Unable to find gem 'foo' in default gem paths/, @ui.output)
+ assert_match(/Directories searched:/, @ui.output)
assert_equal "", @ui.error
end
def test_execute_exact_match
@cmd.options[:args] = %w[foo]
- gem 'foo'
- gem 'bar'
+ gem "foo"
+ gem "bar"
use_ui @ui do
@cmd.execute
end
assert_match %r{lib/foo\.rb}, @ui.output
- assert_match %r{Rakefile}, @ui.output
+ assert_match(/Rakefile/, @ui.output)
assert_equal "", @ui.error
end
@@ -79,14 +80,14 @@ class TestGemCommandsContentsCommand < Gem::TestCase
@cmd.options[:args] = %w[foo]
@cmd.options[:lib_only] = true
- gem 'foo'
+ gem "foo"
use_ui @ui do
@cmd.execute
end
assert_match %r{lib/foo\.rb}, @ui.output
- refute_match %r{Rakefile}, @ui.output
+ refute_match(/Rakefile/, @ui.output)
assert_equal "", @ui.error
end
@@ -106,9 +107,9 @@ class TestGemCommandsContentsCommand < Gem::TestCase
def test_execute_missing_version
@cmd.options[:args] = %w[foo]
- @cmd.options[:version] = Gem::Requirement.new '= 2'
+ @cmd.options[:version] = Gem::Requirement.new "= 2"
- gem 'foo', 1
+ gem "foo", 1
assert_raise Gem::MockGemUi::TermError do
use_ui @ui do
@@ -123,7 +124,7 @@ class TestGemCommandsContentsCommand < Gem::TestCase
def test_execute_missing_multiple
@cmd.options[:args] = %w[foo bar]
- gem 'foo'
+ gem "foo"
use_ui @ui do
@cmd.execute
@@ -138,8 +139,8 @@ class TestGemCommandsContentsCommand < Gem::TestCase
def test_execute_multiple
@cmd.options[:args] = %w[foo bar]
- gem 'foo'
- gem 'bar'
+ gem "foo"
+ gem "bar"
use_ui @ui do
@cmd.execute
@@ -147,7 +148,7 @@ class TestGemCommandsContentsCommand < Gem::TestCase
assert_match %r{lib/foo\.rb}, @ui.output
assert_match %r{lib/bar\.rb}, @ui.output
- assert_match %r{Rakefile}, @ui.output
+ assert_match(/Rakefile/, @ui.output)
assert_equal "", @ui.error
end
@@ -155,13 +156,13 @@ class TestGemCommandsContentsCommand < Gem::TestCase
@cmd.options[:args] = %w[foo]
@cmd.options[:show_install_dir] = true
- gem 'foo'
+ gem "foo"
use_ui @ui do
@cmd.execute
end
- expected = File.join @gemhome, 'gems', 'foo-2'
+ expected = File.join @gemhome, "gems", "foo-2"
assert_equal "#{expected}\n", @ui.output
assert_equal "", @ui.error
@@ -171,14 +172,14 @@ class TestGemCommandsContentsCommand < Gem::TestCase
@cmd.options[:args] = %w[foo]
@cmd.options[:show_install_dir] = true
- gem 'foo', 1
- gem 'foo', 2
+ gem "foo", 1
+ gem "foo", 2
use_ui @ui do
@cmd.execute
end
- expected = File.join @gemhome, 'gems', 'foo-2'
+ expected = File.join @gemhome, "gems", "foo-2"
assert_equal "#{expected}\n", @ui.output
assert_equal "", @ui.error
@@ -187,16 +188,16 @@ class TestGemCommandsContentsCommand < Gem::TestCase
def test_execute_show_install_dir_version
@cmd.options[:args] = %w[foo]
@cmd.options[:show_install_dir] = true
- @cmd.options[:version] = Gem::Requirement.new '= 1'
+ @cmd.options[:version] = Gem::Requirement.new "= 1"
- gem 'foo', 1
- gem 'foo', 2
+ gem "foo", 1
+ gem "foo", 2
use_ui @ui do
@cmd.execute
end
- expected = File.join @gemhome, 'gems', 'foo-1'
+ expected = File.join @gemhome, "gems", "foo-1"
assert_equal "#{expected}\n", @ui.output
assert_equal "", @ui.error
@@ -206,7 +207,7 @@ class TestGemCommandsContentsCommand < Gem::TestCase
@cmd.options[:args] = %w[foo]
@cmd.options[:prefix] = false
- gem 'foo'
+ gem "foo"
use_ui @ui do
@cmd.execute
@@ -236,10 +237,10 @@ lib/foo.rb
end
expected = [
- [RbConfig::CONFIG['bindir'], 'default_command'],
- [RbConfig::CONFIG['rubylibdir'], 'default/gem.rb'],
- [RbConfig::CONFIG['archdir'], 'default_gem.so'],
- ].sort.map{|a|File.join a }.join "\n"
+ [RbConfig::CONFIG["bindir"], "default_command"],
+ [RbConfig::CONFIG["rubylibdir"], "default/gem.rb"],
+ [RbConfig::CONFIG["archdir"], "default_gem.so"],
+ ].sort.map {|a|File.join a }.join "\n"
assert_equal expected, @ui.output.chomp
assert_equal "", @ui.error
@@ -264,7 +265,7 @@ lib/foo.rb
assert @cmd.options[:lib_only]
refute @cmd.options[:prefix]
assert_equal %w[foo], @cmd.options[:specdirs]
- assert_equal Gem::Requirement.new('0.0.2'), @cmd.options[:version]
+ assert_equal Gem::Requirement.new("0.0.2"), @cmd.options[:version]
assert @cmd.options[:show_install_dir]
end
end
diff --git a/test/rubygems/test_gem_commands_dependency_command.rb b/test/rubygems/test_gem_commands_dependency_command.rb
index 13c7c065b5..48fe2f8e8d 100644
--- a/test/rubygems/test_gem_commands_dependency_command.rb
+++ b/test/rubygems/test_gem_commands_dependency_command.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/commands/dependency_command'
+
+require_relative "helper"
+require "rubygems/commands/dependency_command"
class TestGemCommandsDependencyCommand < Gem::TestCase
def setup
@@ -11,9 +12,9 @@ class TestGemCommandsDependencyCommand < Gem::TestCase
end
def test_execute
- quick_gem 'foo' do |gem|
- gem.add_dependency 'bar', '> 1'
- gem.add_dependency 'baz', '> 1'
+ quick_gem "foo" do |gem|
+ gem.add_dependency "bar", "> 1"
+ gem.add_dependency "baz", "> 1"
end
@cmd.options[:args] = %w[foo]
@@ -24,16 +25,16 @@ class TestGemCommandsDependencyCommand < Gem::TestCase
assert_equal "Gem foo-2\n bar (> 1)\n baz (> 1)\n\n",
@stub_ui.output
- assert_equal '', @stub_ui.error
+ assert_equal "", @stub_ui.error
end
def test_execute_no_args
- install_specs util_spec 'x', '2'
+ install_specs util_spec "x", "2"
spec_fetcher do |fetcher|
- fetcher.spec 'a', 1
- fetcher.spec 'a', '2.a'
- fetcher.spec 'dep_x', 1, 'x' => '>= 1'
+ fetcher.spec "a", 1
+ fetcher.spec "a", "2.a"
+ fetcher.spec "dep_x", 1, "x" => ">= 1"
fetcher.legacy_platform
end
@@ -58,7 +59,7 @@ Gem x-2
EOF
assert_equal expected, @stub_ui.output
- assert_equal '', @stub_ui.error
+ assert_equal "", @stub_ui.error
end
def test_execute_no_match
@@ -71,14 +72,14 @@ Gem x-2
end
assert_equal "No gems found matching foo (>= 0)\n", @stub_ui.output
- assert_equal '', @stub_ui.error
+ assert_equal "", @stub_ui.error
end
def test_execute_pipe_format
- spec = util_spec 'foo' do |gem|
- gem.add_dependency 'bar', '> 1'
+ spec = util_spec "foo" do |gem|
+ gem.add_dependency "bar", "> 1"
end
- install_specs util_spec 'bar', 2
+ install_specs util_spec "bar", 2
install_specs spec
@cmd.options[:args] = %w[foo]
@@ -89,15 +90,15 @@ Gem x-2
end
assert_equal "bar --version '> 1'\n", @stub_ui.output
- assert_equal '', @stub_ui.error
+ assert_equal "", @stub_ui.error
end
def test_execute_regexp
spec_fetcher do |fetcher|
- fetcher.spec 'a', 1
- fetcher.spec 'a', '2.a'
- fetcher.spec 'a_evil', 9
- fetcher.spec 'b', 2
+ fetcher.spec "a", 1
+ fetcher.spec "a", "2.a"
+ fetcher.spec "a_evil", 9
+ fetcher.spec "b", 2
end
@cmd.options[:args] = %w[[ab]]
@@ -118,17 +119,17 @@ Gem b-2
EOF
assert_equal expected, @stub_ui.output
- assert_equal '', @stub_ui.error
+ assert_equal "", @stub_ui.error
end
def test_execute_reverse
# FIX: this shouldn't need to write out, but fails if you switch it
- quick_gem 'foo' do |gem|
- gem.add_dependency 'bar', '> 1'
+ quick_gem "foo" do |gem|
+ gem.add_dependency "bar", "> 1"
end
- quick_gem 'baz' do |gem|
- gem.add_dependency 'foo'
+ quick_gem "baz" do |gem|
+ gem.add_dependency "foo"
end
@cmd.options[:args] = %w[foo]
@@ -147,7 +148,7 @@ Gem foo-2
EOF
assert_equal expected, @stub_ui.output
- assert_equal '', @stub_ui.error
+ assert_equal "", @stub_ui.error
end
def test_execute_reverse_remote
@@ -165,15 +166,15 @@ Gem foo-2
ERROR: Only reverse dependencies for local gems are supported.
EOF
- assert_equal '', @stub_ui.output
+ assert_equal "", @stub_ui.output
assert_equal expected, @stub_ui.error
end
def test_execute_remote
- install_specs util_spec 'bar', '2'
+ install_specs util_spec "bar", "2"
spec_fetcher do |fetcher|
- fetcher.spec 'foo', 2, 'bar' => '> 1'
+ fetcher.spec "foo", 2, "bar" => "> 1"
end
@cmd.options[:args] = %w[foo]
@@ -184,7 +185,7 @@ ERROR: Only reverse dependencies for local gems are supported.
end
assert_equal "Gem foo-2\n bar (> 1)\n\n", @stub_ui.output
- assert_equal '', @stub_ui.error
+ assert_equal "", @stub_ui.error
end
def test_execute_remote_version
@@ -192,25 +193,25 @@ ERROR: Only reverse dependencies for local gems are supported.
Gem::RemoteFetcher.fetcher = @fetcher
spec_fetcher do |fetcher|
- fetcher.spec 'a', 1
- fetcher.spec 'a', 2
+ fetcher.spec "a", 1
+ fetcher.spec "a", 2
end
@cmd.options[:args] = %w[a]
@cmd.options[:domain] = :remote
- @cmd.options[:version] = req '= 1'
+ @cmd.options[:version] = req "= 1"
use_ui @stub_ui do
@cmd.execute
end
assert_equal "Gem a-1\n\n", @stub_ui.output
- assert_equal '', @stub_ui.error
+ assert_equal "", @stub_ui.error
end
def test_execute_prerelease
spec_fetcher do |fetcher|
- fetcher.spec 'a', '2.a'
+ fetcher.spec "a", "2.a"
end
@cmd.options[:args] = %w[a]
@@ -222,6 +223,6 @@ ERROR: Only reverse dependencies for local gems are supported.
end
assert_equal "Gem a-2.a\n\n", @stub_ui.output
- assert_equal '', @stub_ui.error
+ assert_equal "", @stub_ui.error
end
end
diff --git a/test/rubygems/test_gem_commands_environment_command.rb b/test/rubygems/test_gem_commands_environment_command.rb
index 2bf80d8d85..48252d84d4 100644
--- a/test/rubygems/test_gem_commands_environment_command.rb
+++ b/test/rubygems/test_gem_commands_environment_command.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/commands/environment_command'
+
+require_relative "helper"
+require "rubygems/commands/environment_command"
class TestGemCommandsEnvironmentCommand < Gem::TestCase
def setup
@@ -11,9 +12,10 @@ class TestGemCommandsEnvironmentCommand < Gem::TestCase
def test_execute
orig_sources = Gem.sources.dup
- orig_path, ENV['PATH'] = ENV['PATH'], %w[/usr/local/bin /usr/bin /bin].join(File::PATH_SEPARATOR)
+ orig_path = ENV["PATH"]
+ ENV["PATH"] = %w[/usr/local/bin /usr/bin /bin].join(File::PATH_SEPARATOR)
Gem.sources.replace %w[http://gems.example.com]
- Gem.configuration['gemcutter_key'] = 'blah'
+ Gem.configuration["gemcutter_key"] = "blah"
@cmd.send :handle_options, %w[]
@@ -21,35 +23,36 @@ class TestGemCommandsEnvironmentCommand < Gem::TestCase
@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:.*#{RbConfig::CONFIG['ruby_install_name']}},
- @ui.output
- assert_match %r{GIT EXECUTABLE: #{@cmd.send(:git_path)}}, @ui.output
- assert_match %r{SYSTEM CONFIGURATION DIRECTORY:}, @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{"gemcutter_key" => "\*\*\*\*"}, @ui.output
- assert_match %r{:verbose => }, @ui.output
- assert_match %r{REMOTE SOURCES:}, @ui.output
-
- assert_match %r{- SHELL PATH:}, @ui.output
+ assert_match(/RUBYGEMS VERSION: (\d\.)+\d/, @ui.output)
+ assert_match(/RUBY VERSION: \d+\.\d+\.\d+ \(.*\) \[.*\]/, @ui.output)
+ assert_match(/INSTALLATION DIRECTORY: #{Regexp.escape @gemhome}/,
+ @ui.output)
+ assert_match(/USER INSTALLATION DIRECTORY: #{Regexp.escape Gem.user_dir}/,
+ @ui.output)
+ assert_match(/RUBYGEMS PREFIX: /, @ui.output)
+ assert_match(/RUBY EXECUTABLE:.*#{RbConfig::CONFIG["ruby_install_name"]}/,
+ @ui.output)
+ assert_match(/GIT EXECUTABLE: #{@cmd.send(:git_path)}/, @ui.output)
+ assert_match(/SYSTEM CONFIGURATION DIRECTORY:/, @ui.output)
+ assert_match(/EXECUTABLE DIRECTORY:/, @ui.output)
+ assert_match(/RUBYGEMS PLATFORMS:/, @ui.output)
+ assert_match(/- #{Gem::Platform.local}/, @ui.output)
+ assert_match(/GEM PATHS:/, @ui.output)
+ assert_match(/- #{Regexp.escape @gemhome}/, @ui.output)
+ assert_match(/GEM CONFIGURATION:/, @ui.output)
+ assert_match(/"gemcutter_key" => "\*\*\*\*"/, @ui.output)
+ assert_match(/:verbose => /, @ui.output)
+ assert_match(/REMOTE SOURCES:/, @ui.output)
+
+ assert_match(/- SHELL PATH:/, @ui.output)
assert_match %r{- /usr/local/bin$}, @ui.output
assert_match %r{- /usr/bin$}, @ui.output
assert_match %r{- /bin$}, @ui.output
assert_empty @ui.error
-
ensure
Gem.sources.replace orig_sources
- ENV['PATH'] = orig_path
+ ENV["PATH"] = orig_path
end
def test_execute_gemdir
@@ -60,7 +63,29 @@ class TestGemCommandsEnvironmentCommand < Gem::TestCase
end
assert_equal "#{@gemhome}\n", @ui.output
- assert_equal '', @ui.error
+ assert_equal "", @ui.error
+ end
+
+ def test_execute_user_gemdir
+ @cmd.send :handle_options, %w[user_gemdir]
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ assert_equal "#{Gem.user_dir}\n", @ui.output
+ assert_equal "", @ui.error
+ end
+
+ def test_execute_user_gemhome
+ @cmd.send :handle_options, %w[user_gemhome]
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ assert_equal "#{Gem.user_dir}\n", @ui.output
+ assert_equal "", @ui.error
end
def test_execute_gempath
@@ -71,13 +96,13 @@ class TestGemCommandsEnvironmentCommand < Gem::TestCase
end
assert_equal "#{@gemhome}\n", @ui.output
- assert_equal '', @ui.error
+ 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
+ ENV["GEM_PATH"] = path
@cmd.send :handle_options, %w[gempath]
@@ -86,7 +111,7 @@ class TestGemCommandsEnvironmentCommand < Gem::TestCase
end
assert_equal "#{Gem.path.join File::PATH_SEPARATOR}\n", @ui.output
- assert_equal '', @ui.error
+ assert_equal "", @ui.error
end
def test_execute_remotesources
@@ -100,8 +125,7 @@ class TestGemCommandsEnvironmentCommand < Gem::TestCase
end
assert_equal "http://gems.example.com\n", @ui.output
- assert_equal '', @ui.error
-
+ assert_equal "", @ui.error
ensure
Gem.sources.replace orig_sources
end
@@ -115,8 +139,8 @@ class TestGemCommandsEnvironmentCommand < Gem::TestCase
end
end
- assert_equal '', @ui.output
- assert_equal '', @ui.error
+ assert_equal "", @ui.output
+ assert_equal "", @ui.error
end
def test_execute_version
@@ -127,7 +151,7 @@ class TestGemCommandsEnvironmentCommand < Gem::TestCase
end
assert_equal "#{Gem::VERSION}\n", @ui.output
- assert_equal '', @ui.error
+ assert_equal "", @ui.error
end
def test_execute_platform
@@ -138,6 +162,6 @@ class TestGemCommandsEnvironmentCommand < Gem::TestCase
end
assert_equal "#{Gem.platforms.join File::PATH_SEPARATOR}\n", @ui.output
- assert_equal '', @ui.error
+ assert_equal "", @ui.error
end
end
diff --git a/test/rubygems/test_gem_commands_exec_command.rb b/test/rubygems/test_gem_commands_exec_command.rb
new file mode 100644
index 0000000000..fd48ce73ca
--- /dev/null
+++ b/test/rubygems/test_gem_commands_exec_command.rb
@@ -0,0 +1,859 @@
+# frozen_string_literal: true
+
+require_relative "helper"
+require "rubygems/commands/exec_command"
+
+class TestGemCommandsExecCommand < Gem::TestCase
+ def setup
+ @orig_args = Gem::Command.build_args
+ @orig_specific_extra_args = Gem::Command.specific_extra_args_hash.dup
+ @orig_extra_args = Gem::Command.extra_args.dup
+
+ super
+ common_installer_setup
+
+ @cmd = Gem::Commands::ExecCommand.new
+
+ @gem_home = Gem.dir
+ @gem_path = Gem.path
+ @test_arch = RbConfig::CONFIG["arch"]
+
+ @installed_specs = []
+ Gem.post_install {|installer| @installed_specs << installer.spec }
+ end
+
+ def teardown
+ super
+
+ common_installer_teardown
+
+ Gem::Command.build_args = @orig_args
+ Gem::Command.specific_extra_args_hash = @orig_specific_extra_args
+ Gem::Command.extra_args = @orig_extra_args
+ Gem.configuration = nil
+ end
+
+ def invoke(*args)
+ @ui.outs.truncate(0)
+ @ui.outs.rewind
+ @ui.errs.truncate(0)
+ @ui.errs.rewind
+ @installed_specs.clear
+
+ @cmd.invoke(*args)
+ ensure
+ Gem::Specification.unresolved_deps.clear
+ Gem.loaded_specs.clear
+ Gem.instance_variable_set(:@activated_gem_paths, 0)
+ Gem.clear_default_specs
+ Gem.use_paths(@gem_home, @gem_path)
+ Gem.refresh
+ end
+
+ def test_error_with_no_arguments
+ e = assert_raise Gem::CommandLineError do
+ @cmd.invoke
+ end
+ assert_equal "Please specify an executable to run (e.g. gem exec COMMAND)",
+ e.message
+ end
+
+ def test_error_with_no_executable
+ e = assert_raise Gem::CommandLineError do
+ @cmd.invoke "--verbose", "--gem", "GEM", "--version", "< 10", "--conservative"
+ end
+ assert_equal "Please specify an executable to run (e.g. gem exec COMMAND)",
+ e.message
+ end
+
+ def test_full_option_parsing
+ @cmd.when_invoked do |options|
+ assert_equal options, {
+ args: ["install", "--no-color", "--help", "--verbose"],
+ executable: "pod",
+ explicit_prerelease: false,
+ gem_name: "cocoapods",
+ prerelease: false,
+ version: Gem::Requirement.new(["> 1", "< 1.3"]),
+ build_args: nil,
+ }
+ end
+ @cmd.invoke "--gem", "cocoapods", "-v", "> 1", "--version", "< 1.3", "--verbose", "--", "pod", "install", "--no-color", "--help", "--verbose"
+ end
+
+ def test_single_arg_parsing
+ @cmd.when_invoked do |options|
+ assert_equal options, {
+ args: [],
+ executable: "rails",
+ gem_name: "rails",
+ version: Gem::Requirement.new([">= 0"]),
+ build_args: nil,
+ }
+ end
+ @cmd.invoke "rails"
+ end
+
+ def test_single_arg_parsing_with_version
+ @cmd.when_invoked do |options|
+ assert_equal options, {
+ args: [],
+ executable: "rails",
+ gem_name: "rails",
+ version: Gem::Requirement.new(["= 7.1"]),
+ build_args: nil,
+ }
+ end
+ @cmd.invoke "rails:7.1"
+ end
+
+ def test_gem_without_executable
+ spec_fetcher do |fetcher|
+ fetcher.gem "a", 2
+ end
+
+ util_clear_gems
+
+ use_ui @ui do
+ e = assert_raise Gem::MockGemUi::TermError, @ui.error do
+ @cmd.invoke "a:2"
+ end
+ assert_equal 1, e.exit_code
+ assert_equal "ERROR: Failed to load executable `a`, are you sure the gem `a` contains it?\n", @ui.error
+ end
+ end
+
+ def test_gem_with_executable
+ spec_fetcher do |fetcher|
+ fetcher.gem "a", 2 do |s|
+ s.executables = %w[a]
+ s.files = %w[bin/a lib/a.rb]
+
+ write_file File.join(*%W[gems #{s.original_name} bin a]) do |f|
+ f << "Gem.ui.say #{s.original_name.dump}"
+ end
+ end
+ end
+
+ util_clear_gems
+
+ use_ui @ui do
+ @cmd.invoke "a:2"
+ assert_equal "a-2\n", @ui.output
+ end
+ end
+
+ def test_gem_with_platforms
+ spec_fetcher do |fetcher|
+ fetcher.download "a", 2 do |s|
+ s.executables = %w[a]
+ s.files = %w[bin/a lib/a.rb]
+
+ write_file File.join(*%W[gems #{s.original_name} bin a]) do |f|
+ f << "Gem.ui.say #{s.original_name.dump}"
+ end
+ end
+
+ fetcher.download "a", 2 do |s|
+ s.executables = %w[a]
+ s.files = %w[bin/a lib/a.rb]
+ s.platform = "x86_64-darwin"
+
+ write_file File.join(*%W[gems #{s.original_name} bin a]) do |f|
+ f << "Gem.ui.say #{s.original_name.dump}"
+ end
+ end
+ end
+
+ use_ui @ui do
+ invoke "a:2"
+ assert_equal "a-2\n", @ui.output
+ end
+
+ use_ui @ui do
+ util_set_arch "x86_64-darwin-18"
+ invoke "a:2"
+ assert_equal "a-2-x86_64-darwin\n", @ui.output
+ end
+ end
+
+ def test_gem_with_platform_dependencies
+ spec_fetcher do |fetcher|
+ fetcher.download "a", 2 do |s|
+ s.executables = %w[a]
+ s.files = %w[bin/a lib/a.rb]
+ s.add_dependency "with_platform"
+
+ write_file File.join(*%W[gems #{s.original_name} bin a]) do |f|
+ f << 'require "with_platform"' << "\n"
+ f << 'Gem.ui.say Gem.loaded_specs.each_value.map(&:original_name).sort.join("\n")'
+ end
+ end
+
+ fetcher.download "with_platform", 2 do |s|
+ s.files = %w[lib/with_platform.rb]
+ s.platform = Gem::Platform.local
+ end
+
+ fetcher.download "with_platform", 2 do |s|
+ s.files = %w[lib/with_platform.rb]
+ end
+ end
+
+ use_ui @ui do
+ util_set_arch "unknown-unknown"
+ invoke "a"
+ assert_equal "a-2\nwith_platform-2\n", @ui.output
+ end
+
+ use_ui @ui do
+ util_set_arch @test_arch
+ invoke "a"
+ assert_empty @ui.error
+ assert_equal "a-2\nwith_platform-2-#{Gem::Platform.local}\n", @ui.output
+ end
+ end
+
+ def test_gem_with_platform_and_platform_dependencies
+ pend "extensions don't quite work on jruby" if Gem.java_platform?
+ pend "terminates on mswin" if vc_windows? && ruby_repo?
+
+ spec_fetcher do |fetcher|
+ fetcher.download "a", 2 do |s|
+ s.executables = %w[a]
+ s.files = %w[bin/a lib/a.rb]
+ s.add_dependency "with_platform"
+ s.platform = Gem::Platform.local.to_s
+
+ write_file File.join(*%W[gems #{s.original_name} bin a]) do |f|
+ f << 'require "with_platform"' << "\n"
+ f << 'Gem.ui.say Gem.loaded_specs.each_value.map(&:original_name).sort.join("\n")'
+ end
+ end
+
+ fetcher.download "a", 2 do |s|
+ s.executables = %w[a]
+ s.files = %w[bin/a lib/a.rb extconf.rb]
+ s.add_dependency "with_platform"
+
+ write_file File.join(*%W[gems #{s.original_name} bin a]) do |f|
+ f << 'require "with_platform"' << "\n"
+ f << 'Gem.ui.say Gem.loaded_specs.each_value.map(&:original_name).sort.join("\n")'
+ end
+
+ s.extensions = %w[extconf.rb]
+ write_file File.join(*%W[gems #{s.original_name} extconf.rb]) do |f|
+ f.write <<-RUBY
+ gem('with_platform', '~> 2.0')
+ require 'with_platform'
+ gem 'sometimes_used'
+ require 'sometimes_used'
+ require "mkmf"
+ create_makefile("#{s.name}")
+ RUBY
+ end
+ end
+
+ fetcher.download "with_platform", 2 do |s|
+ s.files = %w[lib/with_platform.rb]
+ s.platform = Gem::Platform.local.to_s
+ end
+
+ fetcher.download "with_platform", 2 do |s|
+ s.files = %w[lib/with_platform.rb]
+ s.add_dependency "sometimes_used"
+ end
+
+ fetcher.download "sometimes_used", 2 do |s|
+ s.files = %w[lib/sometimes_used.rb]
+ end
+ end
+
+ use_ui @ui do
+ util_set_arch "unknown-unknown"
+ invoke "a"
+ assert_empty @ui.error
+ assert_equal "Building native extensions. This could take a while...\na-2\nsometimes_used-2\nwith_platform-2\n", @ui.output
+ end
+
+ use_ui @ui do
+ util_set_arch @test_arch
+ invoke "a"
+ assert_empty @ui.error
+ assert_equal "a-2-#{Gem::Platform.local}\nwith_platform-2-#{Gem::Platform.local}\n", @ui.output
+ end
+ end
+
+ def test_gem_with_other_executable_name
+ spec_fetcher do |fetcher|
+ fetcher.gem "a", 2 do |s|
+ s.executables = %w[foo]
+ s.files = %w[bin/foo lib/a.rb]
+
+ write_file File.join(*%W[gems #{s.original_name} bin foo]) do |f|
+ f << "Gem.ui.say #{s.original_name.dump}"
+ end
+ end
+ end
+
+ util_clear_gems
+
+ use_ui @ui do
+ @cmd.invoke "a:2"
+ assert_equal "a-2\n", @ui.output
+ end
+ end
+
+ def test_gem_with_executable_error
+ spec_fetcher do |fetcher|
+ fetcher.gem "a", 2 do |s|
+ s.executables = %w[foo]
+ s.files = %w[bin/foo lib/a.rb]
+
+ write_file File.join(*%W[gems #{s.original_name} bin foo]) do |f|
+ f << "raise #{s.original_name.dump}"
+ end
+ end
+ end
+
+ util_clear_gems
+
+ use_ui @ui do
+ e = assert_raise RuntimeError do
+ @cmd.invoke "a:2"
+ end
+ assert_equal "a-2", e.message
+ assert_empty @ui.error
+ end
+ end
+
+ def test_gem_with_multiple_executables_one_match
+ spec_fetcher do |fetcher|
+ fetcher.gem "a", 2 do |s|
+ s.executables = %w[foo a]
+ s.files = %w[bin/foo bin/a lib/a.rb]
+
+ write_file File.join(*%W[gems #{s.original_name} bin foo]) do |f|
+ f << "Gem.ui.say #{s.original_name.dump} + ' ' + File.basename(__FILE__)"
+ end
+
+ write_file File.join(*%W[gems #{s.original_name} bin a]) do |f|
+ f << "Gem.ui.say #{s.original_name.dump} + ' ' + File.basename(__FILE__)"
+ end
+ end
+ end
+
+ util_clear_gems
+
+ use_ui @ui do
+ @cmd.invoke "a:2"
+ assert_equal "a-2 a\n", @ui.output
+ end
+ end
+
+ def test_gem_with_multiple_executables_no_match
+ spec_fetcher do |fetcher|
+ fetcher.gem "a", 2 do |s|
+ s.executables = %w[foo bar]
+ s.files = %w[bin/foo bin/bar lib/a.rb]
+
+ write_file File.join(*%W[gems #{s.original_name} bin foo]) do |f|
+ f << "Gem.ui.say #{s.original_name.dump} + ' ' + File.basename(__FILE__)"
+ end
+
+ write_file File.join(*%W[gems #{s.original_name} bin bar]) do |f|
+ f << "Gem.ui.say #{s.original_name.dump} + ' ' + File.basename(__FILE__)"
+ end
+ end
+ end
+
+ util_clear_gems
+
+ use_ui @ui do
+ @cmd.invoke "a:2"
+ assert_equal "a-2 foo\n", @ui.output
+ end
+ end
+
+ def test_gem_dependency_contains_executable
+ spec_fetcher do |fetcher|
+ fetcher.gem "a", 2 do |s|
+ s.executables = %w[]
+ s.files = %w[lib/a.rb]
+
+ s.add_dependency "b"
+ end
+
+ fetcher.gem "b", 2 do |s|
+ s.executables = %w[a]
+ s.files = %w[bin/a lib/b.rb]
+
+ write_file File.join(*%W[gems #{s.original_name} bin a]) do |f|
+ f << "Gem.ui.say #{s.original_name.dump} + ' ' + File.basename(__FILE__)"
+ end
+ end
+ end
+
+ util_clear_gems
+
+ use_ui @ui do
+ @cmd.invoke "a:2"
+ assert_equal "b-2 a\n", @ui.output
+ end
+ end
+
+ def test_gem_dependency_contains_other_executable
+ spec_fetcher do |fetcher|
+ fetcher.gem "a", 2 do |s|
+ s.executables = %w[]
+ s.files = %w[lib/a.rb]
+
+ s.add_dependency "b"
+ end
+
+ fetcher.gem "b", 2 do |s|
+ s.executables = %w[foo]
+ s.files = %w[bin/foo lib/b.rb]
+
+ write_file File.join(*%W[gems #{s.original_name} bin foo]) do |f|
+ f << "Gem.ui.say #{s.original_name.dump} + ' ' + File.basename(__FILE__)"
+ end
+ end
+ end
+
+ util_clear_gems
+
+ use_ui @ui do
+ e = assert_raise Gem::MockGemUi::TermError do
+ @cmd.invoke "a:2"
+ end
+ assert_equal 1, e.exit_code
+ assert_equal <<~ERR, @ui.error
+ ERROR: Failed to load executable `a`, are you sure the gem `a` contains it?
+ ERR
+ end
+ end
+
+ def test_other_gem_contains_executable
+ spec_fetcher do |fetcher|
+ fetcher.gem "a", 2 do |s|
+ s.executables = %w[]
+ s.files = %w[lib/a.rb]
+ end
+
+ fetcher.gem "b", 2 do |s|
+ s.executables = %w[a]
+ s.files = %w[bin/a lib/b.rb]
+
+ write_file File.join(*%W[gems #{s.original_name} bin foo]) do |f|
+ f << "Gem.ui.say #{s.original_name.dump} + ' ' + File.basename(__FILE__)"
+ end
+ end
+ end
+
+ util_clear_gems
+
+ use_ui @ui do
+ e = assert_raise Gem::MockGemUi::TermError do
+ @cmd.invoke "a:2"
+ end
+ assert_equal 1, e.exit_code
+ assert_equal <<~ERR, @ui.error
+ ERROR: Failed to load executable `a`, are you sure the gem `a` contains it?
+ ERR
+ end
+ end
+
+ def test_missing_gem
+ spec_fetcher do |fetcher|
+ end
+
+ use_ui @ui do
+ e = assert_raise Gem::MockGemUi::TermError do
+ @cmd.invoke "a"
+ end
+ assert_equal 2, e.exit_code
+ assert_equal <<~ERR, @ui.error
+ ERROR: Could not find a valid gem 'a' (>= 0) in any repository
+ ERR
+ end
+ end
+
+ def test_version_mismatch
+ spec_fetcher do |fetcher|
+ fetcher.gem "a", 1
+ end
+
+ util_clear_gems
+
+ use_ui @ui do
+ e = assert_raise Gem::MockGemUi::TermError do
+ @cmd.invoke "a:2"
+ end
+ assert_equal 2, e.exit_code
+ assert_equal <<~ERR, @ui.error
+ ERROR: Could not find a valid gem 'a' (= 2) in any repository
+ ERROR: Possible alternatives: a
+ ERR
+ end
+ end
+
+ def test_pre_argument
+ spec_fetcher do |fetcher|
+ fetcher.gem "a", 1 do |s|
+ s.executables = %w[foo]
+ s.files = %w[bin/foo lib/a.rb]
+
+ write_file File.join(*%W[gems #{s.original_name} bin foo]) do |f|
+ f << "Gem.ui.say #{s.original_name.dump} + ' ' + File.basename(__FILE__)"
+ end
+ end
+ fetcher.gem "a", "1.1.a" do |s|
+ s.executables = %w[foo]
+ s.files = %w[bin/foo lib/a.rb]
+
+ write_file File.join(*%W[gems #{s.original_name} bin foo]) do |f|
+ f << "Gem.ui.say #{s.original_name.dump} + ' ' + File.basename(__FILE__)"
+ end
+ end
+ end
+
+ util_clear_gems
+
+ use_ui @ui do
+ @cmd.invoke "--pre", "a"
+ assert_equal "a-1.1.a foo\n", @ui.output
+ end
+ end
+
+ def test_pre_version_option
+ spec_fetcher do |fetcher|
+ fetcher.download "a", 1 do |s|
+ s.executables = %w[foo]
+ s.files = %w[bin/foo lib/a.rb]
+
+ write_file File.join(*%W[gems #{s.original_name} bin foo]) do |f|
+ f << "Gem.ui.say #{s.original_name.dump} + ' ' + File.basename(__FILE__)"
+ end
+ end
+ fetcher.download "a", "1.1.a" do |s|
+ s.executables = %w[foo]
+ s.files = %w[bin/foo lib/a.rb]
+
+ write_file File.join(*%W[gems #{s.original_name} bin foo]) do |f|
+ f << "Gem.ui.say #{s.original_name.dump} + ' ' + File.basename(__FILE__)"
+ end
+ end
+ end
+
+ use_ui @ui do
+ @cmd.invoke "-v", ">= 0.a", "a"
+ assert_equal "a-1.1.a foo\n", @ui.output
+ end
+ end
+
+ def test_conservative_missing_gem
+ spec_fetcher do |fetcher|
+ fetcher.gem "a", 1 do |s|
+ s.executables = %w[foo]
+ s.files = %w[bin/foo lib/a.rb]
+
+ write_file File.join(*%W[gems #{s.original_name} bin foo]) do |f|
+ f << "Gem.ui.say #{s.original_name.dump} + ' ' + File.basename(__FILE__)"
+ end
+ end
+ end
+
+ util_clear_gems
+
+ use_ui @ui do
+ e = assert_raise Gem::MockGemUi::TermError do
+ @cmd.invoke "--verbose", "--conservative", "a:2"
+ end
+ assert_equal 2, e.exit_code
+ assert_include @ui.output, "a (= 2) not available locally"
+ assert_equal <<~ERROR, @ui.error
+ ERROR: Could not find a valid gem 'a' (= 2) in any repository
+ ERROR: Possible alternatives: a
+ ERROR
+ end
+ end
+
+ def test_conservative
+ spec_fetcher do |fetcher|
+ fetcher.download "a", 1 do |s|
+ s.executables = %w[foo]
+ s.files = %w[bin/foo lib/a.rb]
+
+ write_file File.join(*%W[gems #{s.original_name} bin foo]) do |f|
+ f << "Gem.ui.say #{s.original_name.dump} + ' ' + File.basename(__FILE__)"
+ end
+ end
+ end
+
+ use_ui @ui do
+ invoke "--verbose", "--conservative", "a"
+ assert_include @ui.output, "a (>= 0) not available locally"
+ assert_include @ui.output, "a-1 foo"
+ assert_equal %w[a-1], @installed_specs.map(&:original_name)
+ end
+
+ spec_fetcher do |fetcher|
+ fetcher.gem "a", 1 do |s|
+ s.executables = %w[foo]
+ s.files = %w[bin/foo lib/a.rb]
+
+ write_file File.join(*%W[gems #{s.original_name} bin foo]) do |f|
+ f << "Gem.ui.say #{s.original_name.dump} + ' ' + File.basename(__FILE__)"
+ end
+ end
+
+ fetcher.download "a", 2 do |s|
+ s.executables = %w[foo]
+ s.files = %w[bin/foo lib/a.rb]
+
+ write_file File.join(*%W[gems #{s.original_name} bin foo]) do |f|
+ f << "Gem.ui.say #{s.original_name.dump} + ' ' + File.basename(__FILE__)"
+ end
+ end
+ end
+
+ use_ui @ui do
+ invoke "--verbose", "--conservative", "a"
+ assert_not_include @ui.output, "a (>= 0) not available locally"
+ assert_include @ui.output, "a-1 foo"
+ assert_empty @installed_specs.map(&:original_name)
+ end
+ end
+
+ def test_uses_newest_version
+ spec_fetcher do |fetcher|
+ fetcher.download "a", 1 do |s|
+ s.executables = %w[foo]
+ s.files = %w[bin/foo lib/a.rb]
+
+ write_file File.join(*%W[gems #{s.original_name} bin foo]) do |f|
+ f << "Gem.ui.say #{s.original_name.dump} + ' ' + File.basename(__FILE__)"
+ end
+ end
+ end
+
+ use_ui @ui do
+ invoke "a"
+ assert_include @ui.output, "a-1 foo"
+ end
+
+ spec_fetcher do |fetcher|
+ fetcher.download "a", 1 do |s|
+ s.executables = %w[foo]
+ s.files = %w[bin/foo lib/a.rb]
+
+ write_file File.join(*%W[gems #{s.original_name} bin foo]) do |f|
+ f << "Gem.ui.say #{s.original_name.dump} + ' ' + File.basename(__FILE__)"
+ end
+ end
+
+ fetcher.download "a", 2 do |s|
+ s.executables = %w[foo]
+ s.files = %w[bin/foo lib/a.rb]
+
+ write_file File.join(*%W[gems #{s.original_name} bin foo]) do |f|
+ f << "Gem.ui.say #{s.original_name.dump} + ' ' + File.basename(__FILE__)"
+ end
+ end
+ end
+
+ use_ui @ui do
+ invoke "--verbose", "a:2"
+ refute_predicate @ui, :terminated?
+ assert_empty @ui.error
+ assert_include @ui.output, "a-2 foo"
+ assert_equal %w[a-2], @installed_specs.map(&:original_name)
+ end
+ end
+
+ def test_uses_newest_version_of_dependency
+ spec_fetcher do |fetcher|
+ fetcher.gem "a", 1 do |s|
+ s.executables = %w[]
+ s.files = %w[lib/a.rb]
+ s.add_dependency "b"
+ end
+
+ fetcher.gem "b", 1 do |s|
+ s.executables = %w[a]
+ s.files = %w[bin/a lib/a.rb]
+
+ write_file File.join(*%W[gems #{s.original_name} bin a]) do |f|
+ f << "Gem.ui.say #{s.original_name.dump} + ' ' + File.basename(__FILE__)"
+ end
+ end
+
+ fetcher.download "b", 2 do |s|
+ s.executables = %w[a]
+ s.files = %w[bin/a lib/a.rb]
+
+ write_file File.join(*%W[gems #{s.original_name} bin a]) do |f|
+ f << "Gem.ui.say #{s.original_name.dump} + ' ' + File.basename(__FILE__)"
+ end
+ end
+ end
+
+ use_ui @ui do
+ invoke "a"
+ assert_include @ui.output, "b-2 a"
+ assert_equal %w[b-2], @installed_specs.map(&:original_name)
+ end
+ end
+
+ def test_gem_exec_gem_uninstall
+ spec_fetcher do |fetcher|
+ fetcher.download "a", 2 do |s|
+ s.executables = %w[a]
+ s.files = %w[bin/a lib/a.rb]
+ s.add_dependency "b"
+
+ write_file File.join(*%W[gems #{s.original_name} bin a]) do |f|
+ f << "Gem.ui.say #{s.original_name.dump}"
+ end
+ end
+
+ fetcher.download "b", 2 do |s|
+ s.files = %w[lib/b.rb]
+ end
+ end
+
+ use_ui @ui do
+ invoke "a:2"
+ assert_equal "a-2\n", @ui.output
+
+ invoke "gem", "list", "--local"
+ assert_includes @ui.output, "a (2)\n"
+ assert_includes @ui.output, "b (2)\n"
+
+ begin
+ invoke "gem", "uninstall", "--verbose", "-x", "a"
+ rescue StandardError
+ nil
+ end
+
+ assert_empty @ui.error
+ refute_includes @ui.output, "running gem exec with"
+ assert_includes @ui.output, "Successfully uninstalled a-2\n"
+
+ invoke "--verbose", "gem", "uninstall", "b"
+ assert_includes @ui.output, "Successfully uninstalled b-2\n"
+
+ invoke "gem", "list", "--local"
+ assert_empty @ui.error
+ assert_match(/\A\s*\** LOCAL GEMS \**\s*\z/m, @ui.output)
+
+ invoke "gem", "env", "GEM_HOME"
+ assert_equal "#{@gem_home}\n", @ui.output
+ end
+ end
+
+ def test_only_prerelease_available
+ spec_fetcher do |fetcher|
+ fetcher.download "a", "1.a" do |s|
+ s.executables = %w[a]
+ s.files = %w[lib/a.rb bin/a]
+
+ write_file File.join(*%W[gems #{s.original_name} bin a]) do |f|
+ f << "Gem.ui.say #{s.original_name.dump} + ' ' + File.basename(__FILE__)"
+ end
+ end
+ end
+
+ use_ui @ui do
+ assert_raise Gem::MockGemUi::TermError do
+ invoke "a"
+ end
+ assert_equal "ERROR: Could not find a valid gem 'a' (>= 0) in any repository\n" \
+ "ERROR: Possible alternatives: a\n", @ui.error
+ assert_empty @ui.output
+ assert_empty @installed_specs
+ end
+
+ use_ui @ui do
+ invoke "a:1.a"
+ assert_empty @ui.error
+ assert_equal "a-1.a a\n", @ui.output
+ assert_equal %w[a-1.a], @installed_specs.map(&:full_name)
+ end
+
+ FileUtils.rm_rf Gem.dir
+
+ use_ui @ui do
+ invoke "--version", ">= 1.a", "a"
+ assert_empty @ui.error
+ assert_equal "a-1.a a\n", @ui.output
+ assert_equal %w[a-1.a], @installed_specs.map(&:full_name)
+ end
+
+ FileUtils.rm_rf Gem.dir
+
+ use_ui @ui do
+ invoke "--pre", "a"
+ assert_empty @ui.error
+ assert_equal "a-1.a a\n", @ui.output
+ assert_equal %w[a-1.a], @installed_specs.map(&:full_name)
+ end
+ end
+
+ def test_newer_prerelease_available
+ spec_fetcher do |fetcher|
+ fetcher.download "a", "1" do |s|
+ s.executables = %w[a]
+ s.files = %w[lib/a.rb bin/a]
+
+ write_file File.join(*%W[gems #{s.original_name} bin a]) do |f|
+ f << "Gem.ui.say #{s.original_name.dump} + ' ' + File.basename(__FILE__)"
+ end
+ end
+
+ fetcher.download "a", "1.1.a" do |s|
+ s.executables = %w[a]
+ s.files = %w[lib/a.rb bin/a]
+
+ write_file File.join(*%W[gems #{s.original_name} bin a]) do |f|
+ f << "Gem.ui.say #{s.original_name.dump} + ' ' + File.basename(__FILE__)"
+ end
+ end
+ end
+
+ use_ui @ui do
+ invoke "a"
+ assert_empty @ui.error
+ assert_equal "a-1 a\n", @ui.output
+ assert_equal %w[a-1], @installed_specs.map(&:full_name)
+ end
+
+ FileUtils.rm_rf Gem.dir
+
+ use_ui @ui do
+ invoke "a:1.1.a"
+ assert_empty @ui.error
+ assert_equal "a-1.1.a a\n", @ui.output
+ assert_equal %w[a-1.1.a], @installed_specs.map(&:full_name)
+ end
+
+ FileUtils.rm_rf Gem.dir
+
+ use_ui @ui do
+ invoke "--version", ">= 1.a", "a"
+ assert_empty @ui.error
+ assert_equal "a-1.1.a a\n", @ui.output
+ assert_equal %w[a-1.1.a], @installed_specs.map(&:full_name)
+ end
+
+ FileUtils.rm_rf Gem.dir
+
+ use_ui @ui do
+ invoke "--pre", "a"
+ assert_empty @ui.error
+ assert_equal "a-1.1.a a\n", @ui.output
+ assert_equal %w[a-1.1.a], @installed_specs.map(&:full_name)
+ end
+ end
+end
diff --git a/test/rubygems/test_gem_commands_fetch_command.rb b/test/rubygems/test_gem_commands_fetch_command.rb
index 35ee00f763..bd8f8aa4f9 100644
--- a/test/rubygems/test_gem_commands_fetch_command.rb
+++ b/test/rubygems/test_gem_commands_fetch_command.rb
@@ -1,8 +1,9 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/package'
-require 'rubygems/security'
-require 'rubygems/commands/fetch_command'
+
+require_relative "helper"
+require "rubygems/package"
+require "rubygems/security"
+require "rubygems/commands/fetch_command"
class TestGemCommandsFetchCommand < Gem::TestCase
def setup
@@ -13,89 +14,105 @@ class TestGemCommandsFetchCommand < Gem::TestCase
def test_execute
specs = spec_fetcher do |fetcher|
- fetcher.gem 'a', 2
+ fetcher.gem "a", 2
end
- assert_path_not_exist File.join(@tempdir, 'cache'), 'sanity check'
+ assert_path_not_exist File.join(@tempdir, "cache"), "sanity check"
@cmd.options[:args] = %w[a]
- use_ui @ui do
- Dir.chdir @tempdir do
- @cmd.execute
- end
- end
+ execute_with_exit_code
- a2 = specs['a-2']
+ a2 = specs["a-2"]
assert_path_exist(File.join(@tempdir, a2.file_name),
"#{a2.full_name} not fetched")
- assert_path_not_exist File.join(@tempdir, 'cache'),
- 'gem repository directories must not be created'
+ assert_path_not_exist File.join(@tempdir, "cache"),
+ "gem repository directories must not be created"
end
def test_execute_latest
specs = spec_fetcher do |fetcher|
- fetcher.gem 'a', 1
- fetcher.gem 'a', 2
+ fetcher.gem "a", 1
+ fetcher.gem "a", 2
end
- assert_path_not_exist File.join(@tempdir, 'cache'), 'sanity check'
+ assert_path_not_exist File.join(@tempdir, "cache"), "sanity check"
@cmd.options[:args] = %w[a]
- @cmd.options[:version] = req('>= 0.1')
+ @cmd.options[:version] = req(">= 0.1")
- use_ui @ui do
- Dir.chdir @tempdir do
- @cmd.execute
- end
- end
+ execute_with_exit_code
- a2 = specs['a-2']
+ a2 = specs["a-2"]
assert_path_exist(File.join(@tempdir, a2.file_name),
"#{a2.full_name} not fetched")
- assert_path_not_exist File.join(@tempdir, 'cache'),
- 'gem repository directories must not be created'
+ assert_path_not_exist File.join(@tempdir, "cache"),
+ "gem repository directories must not be created"
end
def test_execute_prerelease
specs = spec_fetcher do |fetcher|
- fetcher.gem 'a', 2
- fetcher.gem 'a', '2.a'
+ fetcher.gem "a", 2
+ fetcher.gem "a", "2.a"
end
@cmd.options[:args] = %w[a]
@cmd.options[:prerelease] = true
- use_ui @ui do
- Dir.chdir @tempdir do
- @cmd.execute
- end
- end
+ execute_with_exit_code
- a2 = specs['a-2']
+ a2 = specs["a-2"]
assert_path_exist(File.join(@tempdir, a2.file_name),
"#{a2.full_name} not fetched")
end
+ def test_execute_platform
+ a2_spec, a2 = util_gem("a", "2")
+
+ a2_universal_darwin_spec, a2_universal_darwin = util_gem("a", "2") do |s|
+ s.platform = "universal-darwin"
+ end
+
+ Gem::RemoteFetcher.fetcher = @fetcher = Gem::FakeFetcher.new
+
+ write_marshalled_gemspecs(a2_spec, a2_universal_darwin_spec)
+
+ @cmd.options[:args] = %w[a]
+
+ @fetcher.data["#{@gem_repo}latest_specs.#{Gem.marshal_version}.gz"] = util_gzip(Marshal.dump([
+ Gem::NameTuple.new(a2_spec.name, a2_spec.version, a2_spec.platform),
+ Gem::NameTuple.new(a2_universal_darwin_spec.name, a2_universal_darwin_spec.version, a2_universal_darwin_spec.platform),
+ ]))
+
+ @fetcher.data["#{@gem_repo}gems/#{a2_spec.file_name}"] = Gem.read_binary(a2)
+ FileUtils.cp a2, a2_spec.cache_file
+
+ @fetcher.data["#{@gem_repo}gems/#{a2_universal_darwin_spec.file_name}"] = Gem.read_binary(a2_universal_darwin)
+ FileUtils.cp a2_universal_darwin, a2_universal_darwin_spec.cache_file
+
+ util_set_arch "arm64-darwin20" do
+ execute_with_exit_code
+ end
+
+ assert_path_exist(File.join(@tempdir, a2_universal_darwin_spec.file_name),
+ "#{a2_universal_darwin_spec.full_name} not fetched")
+ end
+
def test_execute_specific_prerelease
specs = spec_fetcher do |fetcher|
- fetcher.gem 'a', 2
- fetcher.gem 'a', '2.a'
+ fetcher.gem "a", 2
+ fetcher.gem "a", "2.a"
end
@cmd.options[:args] = %w[a]
@cmd.options[:prerelease] = true
@cmd.options[:version] = "2.a"
- use_ui @ui do
- Dir.chdir @tempdir do
- @cmd.execute
- end
- end
+ execute_with_exit_code
- a2_pre = specs['a-2.a']
+ a2_pre = specs["a-2.a"]
assert_path_exist(File.join(@tempdir, a2_pre.file_name),
"#{a2_pre.full_name} not fetched")
@@ -103,22 +120,119 @@ class TestGemCommandsFetchCommand < Gem::TestCase
def test_execute_version
specs = spec_fetcher do |fetcher|
- fetcher.gem 'a', 1
- fetcher.gem 'a', 2
+ fetcher.gem "a", 1
+ fetcher.gem "a", 2
end
@cmd.options[:args] = %w[a]
- @cmd.options[:version] = Gem::Requirement.new '1'
+ @cmd.options[:version] = Gem::Requirement.new "1"
- use_ui @ui do
- Dir.chdir @tempdir do
- @cmd.execute
- end
+ execute_with_exit_code
+
+ a1 = specs["a-1"]
+
+ assert_path_exist(File.join(@tempdir, a1.file_name),
+ "#{a1.full_name} not fetched")
+ end
+
+ def test_execute_version_specified_by_colon
+ specs = spec_fetcher do |fetcher|
+ fetcher.gem "a", 1
end
- a1 = specs['a-1']
+ @cmd.options[:args] = %w[a:1]
+
+ execute_with_exit_code
+
+ a1 = specs["a-1"]
assert_path_exist(File.join(@tempdir, a1.file_name),
"#{a1.full_name} not fetched")
end
+
+ def test_execute_two_version
+ @cmd.options[:args] = %w[a b]
+ @cmd.options[:version] = Gem::Requirement.new "1"
+
+ execute_with_term_error
+
+ msg = "ERROR: Can't use --version with multiple gems. You can specify multiple gems with" \
+ " version requirements using `gem fetch 'my_gem:1.0.0' 'my_other_gem:~>2.0.0'`"
+
+ assert_empty @ui.output
+ assert_equal msg, @ui.error.chomp
+ end
+
+ def test_execute_two_version_specified_by_colon
+ specs = spec_fetcher do |fetcher|
+ fetcher.gem "a", 1
+ fetcher.gem "b", 1
+ end
+
+ @cmd.options[:args] = %w[a:1 b:1]
+
+ execute_with_exit_code
+
+ a1 = specs["a-1"]
+ b1 = specs["b-1"]
+
+ assert_path_exist(File.join(@tempdir, a1.file_name),
+ "#{a1.full_name} not fetched")
+ assert_path_exist(File.join(@tempdir, b1.file_name),
+ "#{b1.full_name} not fetched")
+ end
+
+ def test_execute_version_nonexistent
+ spec_fetcher do |fetcher|
+ fetcher.spec "foo", 1
+ end
+
+ @cmd.options[:args] = %w[foo:2]
+
+ execute_with_term_error
+
+ expected = <<-EXPECTED
+ERROR: Could not find a valid gem 'foo' (2) in any repository
+ERROR: Possible alternatives: foo
+ EXPECTED
+
+ assert_equal expected, @ui.error
+ end
+
+ def test_execute_nonexistent_hint_disabled
+ spec_fetcher do |fetcher|
+ fetcher.spec "foo", 1
+ end
+
+ @cmd.options[:args] = %w[foo:2]
+ @cmd.options[:suggest_alternate] = false
+
+ execute_with_term_error
+
+ expected = <<-EXPECTED
+ERROR: Could not find a valid gem 'foo' (2) in any repository
+ EXPECTED
+
+ assert_equal expected, @ui.error
+ end
+
+ private
+
+ def execute_with_term_error
+ use_ui @ui do
+ assert_raise Gem::MockGemUi::TermError, @ui.error do
+ @cmd.execute
+ end
+ end
+ end
+
+ def execute_with_exit_code
+ use_ui @ui do
+ Dir.chdir @tempdir do
+ assert_raise Gem::MockGemUi::SystemExitException, @ui.error do
+ @cmd.execute
+ end
+ end
+ end
+ end
end
diff --git a/test/rubygems/test_gem_commands_generate_index_command.rb b/test/rubygems/test_gem_commands_generate_index_command.rb
deleted file mode 100644
index 5b7b37a446..0000000000
--- a/test/rubygems/test_gem_commands_generate_index_command.rb
+++ /dev/null
@@ -1,80 +0,0 @@
-# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/indexer'
-require 'rubygems/commands/generate_index_command'
-
-class TestGemCommandsGenerateIndexCommand < Gem::TestCase
- def setup
- super
-
- @cmd = Gem::Commands::GenerateIndexCommand.new
- @cmd.options[:directory] = @gemhome
- end
-
- def test_execute
- use_ui @ui do
- @cmd.execute
- end
-
- specs = File.join @gemhome, "specs.4.8.gz"
-
- assert File.exist?(specs), specs
- end
-
- def test_execute_no_modern
- @cmd.options[:modern] = false
-
- use_ui @ui do
- @cmd.execute
- end
-
- specs = File.join @gemhome, "specs.4.8.gz"
-
- assert File.exist?(specs), specs
- end
-
- def test_handle_options_directory
- return if win_platform?
- refute_equal '/nonexistent', @cmd.options[:directory]
-
- @cmd.handle_options %w[--directory /nonexistent]
-
- assert_equal '/nonexistent', @cmd.options[:directory]
- end
-
- def test_handle_options_directory_windows
- return unless win_platform?
-
- refute_equal '/nonexistent', @cmd.options[:directory]
-
- @cmd.handle_options %w[--directory C:/nonexistent]
-
- assert_equal 'C:/nonexistent', @cmd.options[:directory]
- end
-
- def test_handle_options_update
- @cmd.handle_options %w[--update]
-
- assert @cmd.options[:update]
- end
-
- def test_handle_options_modern
- use_ui @ui do
- @cmd.handle_options %w[--modern]
- end
-
- assert_equal \
- "WARNING: The \"--modern\" option has been deprecated and will be removed in Rubygems 4.0. Modern indexes (specs, latest_specs, and prerelease_specs) are always generated, so this option is not needed.\n",
- @ui.error
- end
-
- def test_handle_options_no_modern
- use_ui @ui do
- @cmd.handle_options %w[--no-modern]
- end
-
- assert_equal \
- "WARNING: The \"--no-modern\" option has been deprecated and will be removed in Rubygems 4.0. The `--no-modern` option is currently ignored. Modern indexes (specs, latest_specs, and prerelease_specs) are always generated.\n",
- @ui.error
- end
-end
diff --git a/test/rubygems/test_gem_commands_help_command.rb b/test/rubygems/test_gem_commands_help_command.rb
index a70dd770e1..359da0a6d0 100644
--- a/test/rubygems/test_gem_commands_help_command.rb
+++ b/test/rubygems/test_gem_commands_help_command.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
require "rubygems"
require_relative "helper"
require "rubygems/commands/help_command"
@@ -11,41 +12,41 @@ class TestGemCommandsHelpCommand < Gem::TestCase
@cmd = Gem::Commands::HelpCommand.new
- load File.expand_path('../rubygems_plugin.rb', __FILE__) unless Gem::Commands.const_defined? :InterruptCommand
+ load File.expand_path("rubygems_plugin.rb", __dir__) unless Gem::Commands.const_defined? :InterruptCommand
end
def test_gem_help_bad
- util_gem 'bad' do |out, err|
- assert_equal('', out)
+ util_gem "bad" do |out, err|
+ assert_equal("", out)
assert_match "Unknown command bad", err
end
end
def test_gem_help_gem_dependencies
- util_gem 'gem_dependencies' do |out, err|
- assert_match 'gem.deps.rb', out
- assert_equal '', err
+ util_gem "gem_dependencies" do |out, err|
+ assert_match "gem.deps.rb", out
+ assert_equal "", err
end
end
def test_gem_help_platforms
- util_gem 'platforms' do |out, err|
+ util_gem "platforms" do |out, err|
assert_match(/x86-freebsd/, out)
- assert_equal '', err
+ assert_equal "", err
end
end
def test_gem_help_build
- util_gem 'build' do |out, err|
+ util_gem "build" do |out, err|
assert_match(/-C PATH *Run as if gem build was started in <PATH>/, out)
- assert_equal '', err
+ assert_equal "", err
end
end
def test_gem_help_commands
mgr = Gem::CommandManager.new
- util_gem 'commands' do |out, err|
+ util_gem "commands" do |out, err|
mgr.command_names.each do |cmd|
unless mgr[cmd].deprecated?
assert_match(/\s+#{cmd}\s+\S+/, out)
@@ -55,7 +56,7 @@ class TestGemCommandsHelpCommand < Gem::TestCase
if Gem::HAVE_OPENSSL
assert_empty err
- refute_match %r{No command found for }, out
+ refute_match(/No command found for /, out)
end
end
end
@@ -63,7 +64,7 @@ class TestGemCommandsHelpCommand < Gem::TestCase
def test_gem_help_commands_omits_deprecated_commands
mgr = Gem::CommandManager.new
- util_gem 'commands' do |out, err|
+ util_gem "commands" do |out, _err|
deprecated_commands = mgr.command_names.select {|cmd| mgr[cmd].deprecated? }
deprecated_commands.each do |cmd|
refute_match(/\A\s+#{cmd}\s+\S+\z/, out)
@@ -75,7 +76,7 @@ class TestGemCommandsHelpCommand < Gem::TestCase
util_gem do |out, err|
assert_match(/Usage:/, out)
assert_match(/gem install/, out)
- assert_equal '', err
+ assert_equal "", err
end
end
diff --git a/test/rubygems/test_gem_commands_info_command.rb b/test/rubygems/test_gem_commands_info_command.rb
index 462075f98c..83e4c8a896 100644
--- a/test/rubygems/test_gem_commands_info_command.rb
+++ b/test/rubygems/test_gem_commands_info_command.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/commands/info_command'
+
+require_relative "helper"
+require "rubygems/commands/info_command"
class TestGemCommandsInfoCommand < Gem::TestCase
def setup
@@ -32,12 +33,38 @@ class TestGemCommandsInfoCommand < Gem::TestCase
@cmd.execute
end
- assert_match %r{#{@gem.name} \(#{@gem.version}\)\n}, @ui.output
- assert_match %r{Authors: #{@gem.authors.join(', ')}\n}, @ui.output
- assert_match %r{Homepage: #{@gem.homepage}\n}, @ui.output
- assert_match %r{License: #{@gem.license}\n}, @ui.output
- assert_match %r{Installed at: #{@gem.base_dir}\n}, @ui.output
- assert_match %r{#{@gem.summary}\n}, @ui.output
+ assert_include(@ui.output, "#{@gem.name} (#{@gem.version})\n")
+ assert_include(@ui.output, "Authors: #{@gem.authors.join(", ")}\n")
+ assert_include(@ui.output, "Homepage: #{@gem.homepage}\n")
+ assert_include(@ui.output, "License: #{@gem.license}\n")
+ assert_include(@ui.output, "Installed at: #{@gem.base_dir}\n")
+ assert_include(@ui.output, "#{@gem.summary}\n")
assert_match "", @ui.error
end
+
+ def test_execute_with_version_flag
+ spec_fetcher do |fetcher|
+ fetcher.spec "coolgem", "1.0"
+ fetcher.spec "coolgem", "2.0"
+ end
+
+ @cmd.handle_options %w[coolgem --remote --version 1.0]
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ expected = <<-EOF
+
+*** REMOTE GEMS ***
+
+coolgem (1.0)
+ Author: A User
+ Homepage: http://example.com
+
+ this is a summary
+ EOF
+
+ assert_equal expected, @ui.output
+ end
end
diff --git a/test/rubygems/test_gem_commands_install_command.rb b/test/rubygems/test_gem_commands_install_command.rb
index 535180983b..1bd96600f3 100644
--- a/test/rubygems/test_gem_commands_install_command.rb
+++ b/test/rubygems/test_gem_commands_install_command.rb
@@ -1,11 +1,14 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/commands/install_command'
-require 'rubygems/request_set'
-require 'rubygems/rdoc'
+
+require_relative "helper"
+require_relative "test_gem_update_suggestion"
+require "rubygems/commands/install_command"
+require "rubygems/request_set"
+require "rubygems/rdoc"
class TestGemCommandsInstallCommand < Gem::TestCase
def setup
+ @orig_args = Gem::Command.build_args
super
common_installer_setup
@@ -13,7 +16,6 @@ class TestGemCommandsInstallCommand < Gem::TestCase
@cmd.options[:document] = []
@gemdeps = "tmp_install_gemdeps"
- @orig_args = Gem::Command.build_args
common_installer_setup
end
@@ -30,8 +32,8 @@ class TestGemCommandsInstallCommand < Gem::TestCase
def test_execute_exclude_prerelease
spec_fetcher do |fetcher|
- fetcher.gem 'a', 2
- fetcher.gem 'a', '2.pre'
+ fetcher.gem "a", 2
+ fetcher.gem "a", "2.pre"
end
@cmd.options[:args] = %w[a]
@@ -42,18 +44,18 @@ class TestGemCommandsInstallCommand < Gem::TestCase
end
end
- assert_equal %w[a-2], @cmd.installed_specs.map {|spec| spec.full_name }
+ assert_equal %w[a-2], @cmd.installed_specs.map(&:full_name)
end
def test_execute_explicit_version_includes_prerelease
specs = spec_fetcher do |fetcher|
- fetcher.gem 'a', 2
- fetcher.gem 'a', '2.a'
+ fetcher.gem "a", 2
+ fetcher.gem "a", "2.a"
end
- a2_pre = specs['a-2.a']
+ a2_pre = specs["a-2.a"]
- @cmd.handle_options [a2_pre.name, '--version', a2_pre.version.to_s,
+ @cmd.handle_options [a2_pre.name, "--version", a2_pre.version.to_s,
"--no-document"]
assert @cmd.options[:prerelease]
assert @cmd.options[:version].satisfied_by?(a2_pre.version)
@@ -64,17 +66,17 @@ class TestGemCommandsInstallCommand < Gem::TestCase
end
end
- assert_equal %w[a-2.a], @cmd.installed_specs.map {|spec| spec.full_name }
+ assert_equal %w[a-2.a], @cmd.installed_specs.map(&:full_name)
end
def test_execute_local
specs = spec_fetcher do |fetcher|
- fetcher.gem 'a', 2
+ fetcher.gem "a", 2
end
@cmd.options[:domain] = :local
- FileUtils.mv specs['a-2'].cache_file, @tempdir
+ FileUtils.mv specs["a-2"].cache_file, @tempdir
@cmd.options[:args] = %w[a]
@@ -90,21 +92,21 @@ class TestGemCommandsInstallCommand < Gem::TestCase
end
end
- assert_equal %w[a-2], @cmd.installed_specs.map {|spec| spec.full_name }
+ assert_equal %w[a-2], @cmd.installed_specs.map(&:full_name)
assert_match "1 gem installed", @ui.output
end
def test_execute_local_dependency_nonexistent
specs = spec_fetcher do |fetcher|
- fetcher.gem 'foo', 2, 'bar' => '0.5'
+ fetcher.gem "foo", 2, "bar" => "0.5"
end
@cmd.options[:domain] = :local
- FileUtils.mv specs['foo-2'].cache_file, @tempdir
+ FileUtils.mv specs["foo-2"].cache_file, @tempdir
- @cmd.options[:args] = ['foo']
+ @cmd.options[:args] = ["foo"]
use_ui @ui do
orig_dir = Dir.pwd
@@ -128,15 +130,15 @@ ERROR: Could not find a valid gem 'bar' (= 0.5) (required by 'foo' (>= 0)) in a
def test_execute_local_dependency_nonexistent_ignore_dependencies
specs = spec_fetcher do |fetcher|
- fetcher.gem 'foo', 2, 'bar' => '0.5'
+ fetcher.gem "foo", 2, "bar" => "0.5"
end
@cmd.options[:domain] = :local
@cmd.options[:ignore_dependencies] = true
- FileUtils.mv specs['foo-2'].cache_file, @tempdir
+ FileUtils.mv specs["foo-2"].cache_file, @tempdir
- @cmd.options[:args] = ['foo']
+ @cmd.options[:args] = ["foo"]
use_ui @ui do
orig_dir = Dir.pwd
@@ -155,16 +157,16 @@ ERROR: Could not find a valid gem 'bar' (= 0.5) (required by 'foo' (>= 0)) in a
def test_execute_local_transitive_prerelease
specs = spec_fetcher do |fetcher|
- fetcher.download 'a', 2, 'b' => "2.a", 'c' => '3'
- fetcher.download 'b', '2.a'
- fetcher.download 'c', '3'
+ fetcher.download "a", 2, "b" => "2.a", "c" => "3"
+ fetcher.download "b", "2.a"
+ fetcher.download "c", "3"
end
@cmd.options[:domain] = :local
- FileUtils.mv specs['a-2'].cache_file, @tempdir
- FileUtils.mv specs['b-2.a'].cache_file, @tempdir
- FileUtils.mv specs['c-3'].cache_file, @tempdir
+ FileUtils.mv specs["a-2"].cache_file, @tempdir
+ FileUtils.mv specs["b-2.a"].cache_file, @tempdir
+ FileUtils.mv specs["c-3"].cache_file, @tempdir
@cmd.options[:args] = %w[a]
@@ -181,40 +183,35 @@ ERROR: Could not find a valid gem 'bar' (= 0.5) (required by 'foo' (>= 0)) in a
end
end
- assert_equal %w[a-2 b-2.a c-3], @cmd.installed_specs.map {|spec| spec.full_name }.sort
+ assert_equal %w[a-2 b-2.a c-3], @cmd.installed_specs.map(&:full_name).sort
assert_match "3 gems installed", @ui.output
end
def test_execute_no_user_install
- pend 'skipped on MS Windows (chmod has no effect)' if win_platform?
- pend 'skipped in root privilege' if Process.uid.zero?
+ pend "skipped on MS Windows (chmod has no effect)" if Gem.win_platform?
+ pend "skipped in root privilege" if Process.uid.zero?
- specs = spec_fetcher do |fetcher|
- fetcher.gem 'a', 2
+ spec_fetcher do |fetcher|
+ fetcher.download "a", 2
end
@cmd.options[:user_install] = false
- FileUtils.mv specs['a-2'].cache_file, @tempdir
-
@cmd.options[:args] = %w[a]
use_ui @ui do
- orig_dir = Dir.pwd
- begin
- FileUtils.chmod 0755, @userhome
- FileUtils.chmod 0555, @gemhome
+ FileUtils.chmod 0o755, @userhome
+ FileUtils.chmod 0o555, @gemhome
- Dir.chdir @tempdir
- assert_raise Gem::FilePermissionError do
- @cmd.execute
- end
- ensure
- Dir.chdir orig_dir
- FileUtils.chmod 0755, @gemhome
+ assert_raise Gem::MockGemUi::SystemExitException, @ui.error do
+ @cmd.execute
end
+ ensure
+ FileUtils.chmod 0o755, @gemhome
end
+
+ assert_equal %w[a-2], @cmd.installed_specs.map(&:full_name).sort
end
def test_execute_local_missing
@@ -231,7 +228,7 @@ ERROR: Could not find a valid gem 'bar' (= 0.5) (required by 'foo' (>= 0)) in a
assert_equal 2, e.exit_code
end
- # HACK no repository was checked
+ # HACK: no repository was checked
assert_match(/ould not find a valid gem 'no_such_gem'/, @ui.error)
end
@@ -250,7 +247,7 @@ ERROR: Could not find a valid gem 'bar' (= 0.5) (required by 'foo' (>= 0)) in a
assert_equal 2, e.exit_code
end
- # HACK no repository was checked
+ # HACK: no repository was checked
assert_match(/ould not find a valid gem 'no_such_gem'/, @ui.error)
end
@@ -277,12 +274,28 @@ ERROR: Could not find a valid gem 'bar' (= 0.5) (required by 'foo' (>= 0)) in a
assert_match(/ould not find a valid gem 'nonexistent'/, @ui.error)
end
+ def test_execute_nonexistent_force
+ spec_fetcher
+
+ @cmd.options[:args] = %w[nonexistent]
+ @cmd.options[:force] = true
+
+ use_ui @ui do
+ e = assert_raise Gem::MockGemUi::TermError do
+ @cmd.execute
+ end
+ assert_equal 2, e.exit_code
+ end
+
+ assert_match(/ould not find a valid gem 'nonexistent'/, @ui.error)
+ end
+
def test_execute_dependency_nonexistent
spec_fetcher do |fetcher|
- fetcher.spec 'foo', 2, 'bar' => '0.5'
+ fetcher.spec "foo", 2, "bar" => "0.5"
end
- @cmd.options[:args] = ['foo']
+ @cmd.options[:args] = ["foo"]
use_ui @ui do
e = assert_raise Gem::MockGemUi::TermError do
@@ -418,25 +431,10 @@ ERROR: Possible alternatives: non_existent_with_hint
assert_equal expected, output
end
- def test_execute_conflicting_install_options
- @cmd.options[:user_install] = true
- @cmd.options[:install_dir] = "whatever"
-
- use_ui @ui do
- assert_raise Gem::MockGemUi::TermError do
- @cmd.execute
- end
- end
-
- expected = "ERROR: Use --install-dir or --user-install but not both\n"
-
- assert_equal expected, @ui.error
- end
-
def test_execute_prerelease_skipped_when_no_flag_set
spec_fetcher do |fetcher|
- fetcher.gem 'a', 1
- fetcher.gem 'a', '3.a'
+ fetcher.gem "a", 1
+ fetcher.gem "a", "3.a"
end
@cmd.options[:prerelease] = false
@@ -448,13 +446,13 @@ ERROR: Possible alternatives: non_existent_with_hint
end
end
- assert_equal %w[a-1], @cmd.installed_specs.map {|spec| spec.full_name }
+ assert_equal %w[a-1], @cmd.installed_specs.map(&:full_name)
end
def test_execute_prerelease_wins_over_previous_ver
spec_fetcher do |fetcher|
- fetcher.download 'a', 1
- fetcher.download 'a', '2.a'
+ fetcher.download "a", 1
+ fetcher.download "a", "2.a"
end
@cmd.options[:prerelease] = true
@@ -466,13 +464,13 @@ ERROR: Possible alternatives: non_existent_with_hint
end
end
- assert_equal %w[a-2.a], @cmd.installed_specs.map {|spec| spec.full_name }
+ assert_equal %w[a-2.a], @cmd.installed_specs.map(&:full_name)
end
def test_execute_with_version_specified_by_colon
spec_fetcher do |fetcher|
- fetcher.download 'a', 1
- fetcher.download 'a', 2
+ fetcher.download "a", 1
+ fetcher.download "a", 2
end
@cmd.options[:args] = %w[a:1]
@@ -483,13 +481,13 @@ ERROR: Possible alternatives: non_existent_with_hint
end
end
- assert_equal %w[a-1], @cmd.installed_specs.map {|spec| spec.full_name }
+ assert_equal %w[a-1], @cmd.installed_specs.map(&:full_name)
end
def test_execute_prerelease_skipped_when_non_pre_available
spec_fetcher do |fetcher|
- fetcher.gem 'a', '2.pre'
- fetcher.gem 'a', 2
+ fetcher.gem "a", "2.pre"
+ fetcher.gem "a", 2
end
@cmd.options[:prerelease] = true
@@ -501,23 +499,23 @@ ERROR: Possible alternatives: non_existent_with_hint
end
end
- assert_equal %w[a-2], @cmd.installed_specs.map {|spec| spec.full_name }
+ assert_equal %w[a-2], @cmd.installed_specs.map(&:full_name)
end
def test_execute_required_ruby_version
- next_ruby = Gem.ruby_version.segments.map.with_index{|n, i| i == 1 ? n + 1 : n }.join(".")
+ next_ruby = Gem.ruby_version.segments.map.with_index {|n, i| i == 1 ? n + 1 : n }.join(".")
local = Gem::Platform.local
spec_fetcher do |fetcher|
- fetcher.download 'a', 2
- fetcher.download 'a', 2 do |s|
+ fetcher.download "a", 2
+ fetcher.download "a", 2 do |s|
s.required_ruby_version = "< #{RUBY_VERSION}.a"
s.platform = local
end
- fetcher.download 'a', 3 do |s|
+ fetcher.download "a", 3 do |s|
s.required_ruby_version = ">= #{next_ruby}"
end
- fetcher.download 'a', 3 do |s|
+ fetcher.download "a", 3 do |s|
s.required_ruby_version = ">= #{next_ruby}"
s.platform = local
end
@@ -531,14 +529,14 @@ ERROR: Possible alternatives: non_existent_with_hint
end
end
- assert_equal %w[a-2], @cmd.installed_specs.map {|spec| spec.full_name }
+ assert_equal %w[a-2], @cmd.installed_specs.map(&:full_name)
end
def test_execute_required_ruby_version_upper_bound
local = Gem::Platform.local
spec_fetcher do |fetcher|
- fetcher.gem 'a', 2.0
- fetcher.gem 'a', 2.0 do |s|
+ fetcher.gem "a", 2.0
+ fetcher.gem "a", 2.0 do |s|
s.required_ruby_version = "< #{RUBY_VERSION}.a"
s.platform = local
end
@@ -552,13 +550,13 @@ ERROR: Possible alternatives: non_existent_with_hint
end
end
- assert_equal %w[a-2.0], @cmd.installed_specs.map {|spec| spec.full_name }
+ assert_equal %w[a-2.0], @cmd.installed_specs.map(&:full_name)
end
def test_execute_required_ruby_version_specific_not_met
spec_fetcher do |fetcher|
- fetcher.gem 'a', '1.0' do |s|
- s.required_ruby_version = '= 1.4.6'
+ fetcher.gem "a", "1.0" do |s|
+ s.required_ruby_version = "= 1.4.6"
end
end
@@ -577,8 +575,8 @@ ERROR: Possible alternatives: non_existent_with_hint
def test_execute_required_ruby_version_specific_prerelease_met
spec_fetcher do |fetcher|
- fetcher.gem 'a', '1.0' do |s|
- s.required_ruby_version = '>= 1.4.6.preview2'
+ fetcher.gem "a", "1.0" do |s|
+ s.required_ruby_version = ">= 1.4.6.preview2"
end
end
@@ -590,14 +588,14 @@ ERROR: Possible alternatives: non_existent_with_hint
end
end
- assert_equal %w[a-1.0], @cmd.installed_specs.map {|spec| spec.full_name }
+ assert_equal %w[a-1.0], @cmd.installed_specs.map(&:full_name)
end
def test_execute_required_ruby_version_specific_prerelease_not_met
- next_ruby_pre = Gem.ruby_version.segments.map.with_index{|n, i| i == 1 ? n + 1 : n }.join(".") + ".a"
+ next_ruby_pre = Gem.ruby_version.segments.map.with_index {|n, i| i == 1 ? n + 1 : n }.join(".") + ".a"
spec_fetcher do |fetcher|
- fetcher.gem 'a', '1.0' do |s|
+ fetcher.gem "a", "1.0" do |s|
s.required_ruby_version = "> #{next_ruby_pre}"
end
end
@@ -617,8 +615,8 @@ ERROR: Possible alternatives: non_existent_with_hint
def test_execute_required_rubygems_version_wrong
spec_fetcher do |fetcher|
- fetcher.gem 'a', '1.0' do |s|
- s.required_rubygems_version = '< 0'
+ fetcher.gem "a", "1.0" do |s|
+ s.required_rubygems_version = "< 0"
end
end
@@ -637,7 +635,7 @@ ERROR: Possible alternatives: non_existent_with_hint
def test_execute_rdoc
specs = spec_fetcher do |fetcher|
- fetcher.gem 'a', 2
+ fetcher.gem "a", 2
end
Gem.done_installing(&Gem::RDoc.method(:generation_hook))
@@ -645,7 +643,7 @@ ERROR: Possible alternatives: non_existent_with_hint
@cmd.options[:document] = %w[rdoc ri]
@cmd.options[:domain] = :local
- a2 = specs['a-2']
+ a2 = specs["a-2"]
FileUtils.mv a2.cache_file, @tempdir
@cmd.options[:args] = %w[a]
@@ -667,22 +665,22 @@ ERROR: Possible alternatives: non_existent_with_hint
wait_for_child_process_to_exit
- assert_path_exist File.join(a2.doc_dir, 'ri')
- assert_path_exist File.join(a2.doc_dir, 'rdoc')
- end
+ assert_path_exist File.join(a2.doc_dir, "ri")
+ assert_path_exist File.join(a2.doc_dir, "rdoc")
+ end if defined?(Gem::RDoc)
def test_execute_rdoc_with_path
specs = spec_fetcher do |fetcher|
- fetcher.gem 'a', 2
+ fetcher.gem "a", 2
end
Gem.done_installing(&Gem::RDoc.method(:generation_hook))
@cmd.options[:document] = %w[rdoc ri]
@cmd.options[:domain] = :local
- @cmd.options[:install_dir] = 'whatever'
+ @cmd.options[:install_dir] = "whatever"
- a2 = specs['a-2']
+ a2 = specs["a-2"]
FileUtils.mv a2.cache_file, @tempdir
@cmd.options[:args] = %w[a]
@@ -704,19 +702,19 @@ ERROR: Possible alternatives: non_existent_with_hint
wait_for_child_process_to_exit
- assert_path_exist 'whatever/doc/a-2', 'documentation not installed'
- end
+ assert_path_exist "whatever/doc/a-2", "documentation not installed"
+ end if defined?(Gem::RDoc)
def test_execute_saves_build_args
specs = spec_fetcher do |fetcher|
- fetcher.gem 'a', 2
+ fetcher.gem "a", 2
end
args = %w[--with-awesome=true --more-awesome=yes]
Gem::Command.build_args = args
- a2 = specs['a-2']
+ a2 = specs["a-2"]
FileUtils.mv a2.cache_file, @tempdir
@cmd.options[:domain] = :local
@@ -746,7 +744,7 @@ ERROR: Possible alternatives: non_existent_with_hint
def test_execute_remote
spec_fetcher do |fetcher|
- fetcher.gem 'a', 2
+ fetcher.gem "a", 2
end
@cmd.options[:args] = %w[a]
@@ -757,7 +755,7 @@ ERROR: Possible alternatives: non_existent_with_hint
end
end
- assert_equal %w[a-2], @cmd.installed_specs.map {|spec| spec.full_name }
+ assert_equal %w[a-2], @cmd.installed_specs.map(&:full_name)
assert_match "1 gem installed", @ui.output
end
@@ -766,7 +764,7 @@ ERROR: Possible alternatives: non_existent_with_hint
FileUtils.touch("a.gem")
spec_fetcher do |fetcher|
- fetcher.gem 'a', 2
+ fetcher.gem "a", 2
end
@cmd.options[:args] = %w[a]
@@ -777,21 +775,54 @@ ERROR: Possible alternatives: non_existent_with_hint
end
end
- assert_equal %w[a-2], @cmd.installed_specs.map {|spec| spec.full_name }
+ assert_equal %w[a-2], @cmd.installed_specs.map(&:full_name)
+
+ assert_match "1 gem installed", @ui.output
+ end
+
+ def test_execute_remote_truncates_existing_gemspecs
+ spec_fetcher do |fetcher|
+ fetcher.gem "a", 1
+ end
+
+ @cmd.options[:domain] = :remote
+
+ @cmd.options[:args] = %w[a]
+
+ use_ui @ui do
+ assert_raise Gem::MockGemUi::SystemExitException, @ui.error do
+ @cmd.execute
+ end
+ end
+ assert_equal %w[a-1], @cmd.installed_specs.map(&:full_name)
assert_match "1 gem installed", @ui.output
+
+ a1_gemspec = File.join(@gemhome, "specifications", "a-1.gemspec")
+
+ initial_a1_gemspec_content = File.read(a1_gemspec)
+ modified_a1_gemspec_content = initial_a1_gemspec_content + "\n # AAAAAAA\n"
+ File.write(a1_gemspec, modified_a1_gemspec_content)
+
+ use_ui @ui do
+ assert_raise Gem::MockGemUi::SystemExitException, @ui.error do
+ @cmd.execute
+ end
+ end
+
+ assert_equal initial_a1_gemspec_content, File.read(a1_gemspec)
end
def test_execute_remote_ignores_files
specs = spec_fetcher do |fetcher|
- fetcher.gem 'a', 1
- fetcher.gem 'a', 2
+ fetcher.gem "a", 1
+ fetcher.gem "a", 2
end
@cmd.options[:domain] = :remote
- a1 = specs['a-1']
- a2 = specs['a-2']
+ a1 = specs["a-1"]
+ a2 = specs["a-2"]
FileUtils.mv a2.cache_file, @tempdir
@@ -800,7 +831,7 @@ ERROR: Possible alternatives: non_existent_with_hint
@cmd.options[:args] = [a2.name]
- gemdir = File.join @gemhome, 'specifications'
+ gemdir = File.join @gemhome, "specifications"
a2_gemspec = File.join(gemdir, "a-2.gemspec")
a1_gemspec = File.join(gemdir, "a-1.gemspec")
@@ -818,7 +849,7 @@ ERROR: Possible alternatives: non_existent_with_hint
end
end
- assert_equal %w[a-1], @cmd.installed_specs.map {|spec| spec.full_name }
+ assert_equal %w[a-1], @cmd.installed_specs.map(&:full_name)
assert_match "1 gem installed", @ui.output
@@ -829,12 +860,12 @@ ERROR: Possible alternatives: non_existent_with_hint
def test_execute_two
specs = spec_fetcher do |fetcher|
- fetcher.gem 'a', 2
- fetcher.gem 'b', 2
+ fetcher.gem "a", 2
+ fetcher.gem "b", 2
end
- FileUtils.mv specs['a-2'].cache_file, @tempdir
- FileUtils.mv specs['b-2'].cache_file, @tempdir
+ FileUtils.mv specs["a-2"].cache_file, @tempdir
+ FileUtils.mv specs["b-2"].cache_file, @tempdir
@cmd.options[:domain] = :local
@@ -852,7 +883,7 @@ ERROR: Possible alternatives: non_existent_with_hint
end
end
- assert_equal %w[a-2 b-2], @cmd.installed_specs.map {|spec| spec.full_name }
+ assert_equal %w[a-2 b-2], @cmd.installed_specs.map(&:full_name)
assert_match "2 gems installed", @ui.output
end
@@ -880,10 +911,10 @@ ERROR: Possible alternatives: non_existent_with_hint
def test_execute_two_version_specified_by_colon
spec_fetcher do |fetcher|
- fetcher.gem 'a', 1
- fetcher.gem 'a', 2
- fetcher.gem 'b', 1
- fetcher.gem 'b', 2
+ fetcher.gem "a", 1
+ fetcher.gem "a", 2
+ fetcher.gem "b", 1
+ fetcher.gem "b", 2
end
@cmd.options[:args] = %w[a:1 b:1]
@@ -894,14 +925,14 @@ ERROR: Possible alternatives: non_existent_with_hint
end
end
- assert_equal %w[a-1 b-1], @cmd.installed_specs.map {|spec| spec.full_name }
+ assert_equal %w[a-1 b-1], @cmd.installed_specs.map(&:full_name)
end
def test_execute_conservative
spec_fetcher do |fetcher|
- fetcher.download 'b', 2
+ fetcher.download "b", 2
- fetcher.gem 'a', 2
+ fetcher.gem "a", 2
end
@cmd.options[:conservative] = true
@@ -920,7 +951,7 @@ ERROR: Possible alternatives: non_existent_with_hint
end
end
- assert_equal %w[b-2], @cmd.installed_specs.map {|spec| spec.full_name }
+ assert_equal %w[b-2], @cmd.installed_specs.map(&:full_name)
assert_equal "", @ui.error
assert_match "1 gem installed", @ui.output
@@ -932,7 +963,7 @@ ERROR: Possible alternatives: non_existent_with_hint
done_installing = true
end
- spec = util_spec 'a', 2
+ spec = util_spec "a", 2
util_build_gem spec
@@ -940,44 +971,44 @@ ERROR: Possible alternatives: non_existent_with_hint
@cmd.options[:ignore_dependencies] = true
- @cmd.install_gem 'a', '>= 0'
+ @cmd.install_gem "a", ">= 0"
- assert_equal %w[a-2], @cmd.installed_specs.map {|s| s.full_name }
+ assert_equal %w[a-2], @cmd.installed_specs.map(&:full_name)
- assert done_installing, 'documentation was not generated'
+ assert done_installing, "documentation was not generated"
end
def test_install_gem_ignore_dependencies_remote
spec_fetcher do |fetcher|
- fetcher.gem 'a', 2
+ fetcher.gem "a", 2
end
@cmd.options[:ignore_dependencies] = true
- @cmd.install_gem 'a', '>= 0'
+ @cmd.install_gem "a", ">= 0"
- assert_equal %w[a-2], @cmd.installed_specs.map {|spec| spec.full_name }
+ assert_equal %w[a-2], @cmd.installed_specs.map(&:full_name)
end
def test_install_gem_ignore_dependencies_remote_platform_local
local = Gem::Platform.local
spec_fetcher do |fetcher|
- fetcher.gem 'a', 3
+ fetcher.gem "a", 3
- fetcher.gem 'a', 3 do |s|
+ fetcher.gem "a", 3 do |s|
s.platform = local
end
end
@cmd.options[:ignore_dependencies] = true
- @cmd.install_gem 'a', '>= 0'
+ @cmd.install_gem "a", ">= 0"
- assert_equal %W[a-3-#{local}], @cmd.installed_specs.map {|spec| spec.full_name }
+ assert_equal %W[a-3-#{local}], @cmd.installed_specs.map(&:full_name)
end
def test_install_gem_ignore_dependencies_specific_file
- spec = util_spec 'a', 2
+ spec = util_spec "a", 2
util_build_gem spec
@@ -987,13 +1018,13 @@ ERROR: Possible alternatives: non_existent_with_hint
@cmd.install_gem File.join(@tempdir, spec.file_name), nil
- assert_equal %w[a-2], @cmd.installed_specs.map {|s| s.full_name }
+ assert_equal %w[a-2], @cmd.installed_specs.map(&:full_name)
end
def test_parses_requirement_from_gemname
spec_fetcher do |fetcher|
- fetcher.gem 'a', 2
- fetcher.gem 'b', 2
+ fetcher.gem "a", 2
+ fetcher.gem "b", 2
end
@cmd.options[:domain] = :local
@@ -1016,7 +1047,7 @@ ERROR: Possible alternatives: non_existent_with_hint
end
assert_equal 2, e.exit_code
- assert_match %r{Could not find a valid gem 'a' \(= 10.0\)}, @ui.error
+ assert_match(/Could not find a valid gem 'a' \(= 10.0\)/, @ui.error)
end
def test_show_errors_on_failure
@@ -1039,12 +1070,12 @@ ERROR: Possible alternatives: non_existent_with_hint
assert_equal 2, e.exit_code
- assert_match 'Unable to download data', @ui.error
+ assert_match "Unable to download data", @ui.error
end
def test_show_source_problems_even_on_success
spec_fetcher do |fetcher|
- fetcher.download 'a', 2
+ fetcher.download "a", 2
end
Gem.sources << "http://nonexistent.example"
@@ -1057,7 +1088,7 @@ ERROR: Possible alternatives: non_existent_with_hint
end
end
- assert_equal %w[a-2], @cmd.installed_specs.map {|spec| spec.full_name }
+ assert_equal %w[a-2], @cmd.installed_specs.map(&:full_name)
assert_match "1 gem installed", @ui.output
@@ -1069,7 +1100,7 @@ ERROR: Possible alternatives: non_existent_with_hint
def test_redact_credentials_from_uri_on_warning
spec_fetcher do |fetcher|
- fetcher.download 'a', 2
+ fetcher.download "a", 2
end
Gem.sources << "http://username:SECURE_TOKEN@nonexistent.example"
@@ -1082,7 +1113,7 @@ ERROR: Possible alternatives: non_existent_with_hint
end
end
- assert_equal %w[a-2], @cmd.installed_specs.map {|spec| spec.full_name }
+ assert_equal %w[a-2], @cmd.installed_specs.map(&:full_name)
assert_match "1 gem installed", @ui.output
@@ -1094,7 +1125,7 @@ ERROR: Possible alternatives: non_existent_with_hint
def test_execute_uses_from_a_gemdeps
spec_fetcher do |fetcher|
- fetcher.gem 'a', 2
+ fetcher.gem "a", 2
end
File.open @gemdeps, "w" do |f|
@@ -1109,7 +1140,7 @@ ERROR: Possible alternatives: non_existent_with_hint
end
end
- assert_equal %w[], @cmd.installed_specs.map {|spec| spec.full_name }
+ assert_equal %w[], @cmd.installed_specs.map(&:full_name)
assert_match "Using a (2)", @ui.output
assert File.exist?("#{@gemdeps}.lock")
@@ -1117,7 +1148,7 @@ ERROR: Possible alternatives: non_existent_with_hint
def test_execute_uses_from_a_gemdeps_with_no_lock
spec_fetcher do |fetcher|
- fetcher.gem 'a', 2
+ fetcher.gem "a", 2
end
File.open @gemdeps, "w" do |f|
@@ -1133,7 +1164,7 @@ ERROR: Possible alternatives: non_existent_with_hint
end
end
- assert_equal %w[], @cmd.installed_specs.map {|spec| spec.full_name }
+ assert_equal %w[], @cmd.installed_specs.map(&:full_name)
assert_match "Using a (2)", @ui.output
assert !File.exist?("#{@gemdeps}.lock")
@@ -1141,8 +1172,8 @@ ERROR: Possible alternatives: non_existent_with_hint
def test_execute_installs_from_a_gemdeps_with_conservative
spec_fetcher do |fetcher|
- fetcher.download 'a', 2
- fetcher.gem 'a', 1
+ fetcher.download "a", 2
+ fetcher.gem "a", 1
end
File.open @gemdeps, "w" do |f|
@@ -1158,14 +1189,14 @@ ERROR: Possible alternatives: non_existent_with_hint
end
end
- assert_equal %w[], @cmd.installed_specs.map {|spec| spec.full_name }
+ assert_equal %w[], @cmd.installed_specs.map(&:full_name)
assert_match "Using a (1)", @ui.output
end
def test_execute_installs_from_a_gemdeps
spec_fetcher do |fetcher|
- fetcher.download 'a', 2
+ fetcher.download "a", 2
end
File.open @gemdeps, "w" do |f|
@@ -1180,15 +1211,15 @@ ERROR: Possible alternatives: non_existent_with_hint
end
end
- assert_equal %w[a-2], @cmd.installed_specs.map {|spec| spec.full_name }
+ assert_equal %w[a-2], @cmd.installed_specs.map(&:full_name)
assert_match "Installing a (2)", @ui.output
end
def test_execute_installs_deps_a_gemdeps
spec_fetcher do |fetcher|
- fetcher.download 'q', '1.0'
- fetcher.download 'r', '2.0', 'q' => nil
+ fetcher.download "q", "1.0"
+ fetcher.download "r", "2.0", "q" => nil
end
File.open @gemdeps, "w" do |f|
@@ -1203,7 +1234,7 @@ ERROR: Possible alternatives: non_existent_with_hint
end
end
- names = @cmd.installed_specs.map {|spec| spec.full_name }
+ names = @cmd.installed_specs.map(&:full_name)
assert_equal %w[q-1.0 r-2.0], names
@@ -1213,9 +1244,9 @@ ERROR: Possible alternatives: non_existent_with_hint
def test_execute_uses_deps_a_gemdeps
spec_fetcher do |fetcher|
- fetcher.download 'r', '2.0', 'q' => nil
+ fetcher.download "r", "2.0", "q" => nil
- fetcher.spec 'q', '1.0'
+ fetcher.spec "q", "1.0"
end
File.open @gemdeps, "w" do |f|
@@ -1230,7 +1261,7 @@ ERROR: Possible alternatives: non_existent_with_hint
end
end
- names = @cmd.installed_specs.map {|spec| spec.full_name }
+ names = @cmd.installed_specs.map(&:full_name)
assert_equal %w[r-2.0], names
@@ -1240,8 +1271,8 @@ ERROR: Possible alternatives: non_existent_with_hint
def test_execute_installs_deps_a_gemdeps_into_a_path
spec_fetcher do |fetcher|
- fetcher.download 'q', '1.0'
- fetcher.download 'r', '2.0', 'q' => nil
+ fetcher.download "q", "1.0"
+ fetcher.download "r", "2.0", "q" => nil
end
File.open @gemdeps, "w" do |f|
@@ -1257,7 +1288,7 @@ ERROR: Possible alternatives: non_existent_with_hint
end
end
- names = @cmd.installed_specs.map {|spec| spec.full_name }
+ names = @cmd.installed_specs.map(&:full_name)
assert_equal %w[q-1.0 r-2.0], names
@@ -1270,11 +1301,11 @@ ERROR: Possible alternatives: non_existent_with_hint
def test_execute_with_gemdeps_path_ignores_system
specs = spec_fetcher do |fetcher|
- fetcher.download 'q', '1.0'
- fetcher.download 'r', '2.0', 'q' => nil
+ fetcher.download "q", "1.0"
+ fetcher.download "r", "2.0", "q" => nil
end
- install_specs specs['q-1.0']
+ install_specs specs["q-1.0"]
File.open @gemdeps, "w" do |f|
f << "gem 'r'"
@@ -1289,7 +1320,7 @@ ERROR: Possible alternatives: non_existent_with_hint
end
end
- names = @cmd.installed_specs.map {|spec| spec.full_name }
+ names = @cmd.installed_specs.map(&:full_name)
assert_equal %w[q-1.0 r-2.0], names
@@ -1302,11 +1333,11 @@ ERROR: Possible alternatives: non_existent_with_hint
def test_execute_uses_deps_a_gemdeps_with_a_path
specs = spec_fetcher do |fetcher|
- fetcher.gem 'q', '1.0'
- fetcher.gem 'r', '2.0', 'q' => nil
+ fetcher.gem "q", "1.0"
+ fetcher.gem "r", "2.0", "q" => nil
end
- i = Gem::Installer.at specs['q-1.0'].cache_file, :install_dir => "gf-path"
+ i = Gem::Installer.at specs["q-1.0"].cache_file, install_dir: "gf-path"
i.install
assert File.file?("gf-path/specifications/q-1.0.gemspec"), "not installed"
@@ -1324,7 +1355,7 @@ ERROR: Possible alternatives: non_existent_with_hint
end
end
- names = @cmd.installed_specs.map {|spec| spec.full_name }
+ names = @cmd.installed_specs.map(&:full_name)
assert_equal %w[r-2.0], names
@@ -1333,39 +1364,39 @@ ERROR: Possible alternatives: non_existent_with_hint
end
def test_handle_options_file
- FileUtils.touch 'Gemfile'
+ FileUtils.touch "Gemfile"
@cmd.handle_options %w[-g Gemfile]
- assert_equal 'Gemfile', @cmd.options[:gemdeps]
+ assert_equal "Gemfile", @cmd.options[:gemdeps]
- FileUtils.rm 'Gemfile'
+ FileUtils.rm "Gemfile"
- FileUtils.touch 'gem.deps.rb'
+ FileUtils.touch "gem.deps.rb"
@cmd.handle_options %w[--file gem.deps.rb]
- assert_equal 'gem.deps.rb', @cmd.options[:gemdeps]
+ assert_equal "gem.deps.rb", @cmd.options[:gemdeps]
- FileUtils.rm 'gem.deps.rb'
+ FileUtils.rm "gem.deps.rb"
- FileUtils.touch 'Isolate'
+ FileUtils.touch "Isolate"
@cmd.handle_options %w[-g]
- assert_equal 'Isolate', @cmd.options[:gemdeps]
+ assert_equal "Isolate", @cmd.options[:gemdeps]
- FileUtils.touch 'Gemfile'
+ FileUtils.touch "Gemfile"
@cmd.handle_options %w[-g]
- assert_equal 'Gemfile', @cmd.options[:gemdeps]
+ assert_equal "Gemfile", @cmd.options[:gemdeps]
- FileUtils.touch 'gem.deps.rb'
+ FileUtils.touch "gem.deps.rb"
@cmd.handle_options %w[-g]
- assert_equal 'gem.deps.rb', @cmd.options[:gemdeps]
+ assert_equal "gem.deps.rb", @cmd.options[:gemdeps]
end
def test_handle_options_suggest
@@ -1393,9 +1424,9 @@ ERROR: Possible alternatives: non_existent_with_hint
def test_explain_platform_local
local = Gem::Platform.local
spec_fetcher do |fetcher|
- fetcher.spec 'a', 2
+ fetcher.spec "a", 2
- fetcher.spec 'a', 2 do |s|
+ fetcher.spec "a", 2 do |s|
s.platform = local
end
end
@@ -1419,9 +1450,9 @@ ERROR: Possible alternatives: non_existent_with_hint
def test_explain_platform_local_ignore_dependencies
local = Gem::Platform.local
spec_fetcher do |fetcher|
- fetcher.spec 'a', 3
+ fetcher.spec "a", 3
- fetcher.spec 'a', 3 do |s|
+ fetcher.spec "a", 3 do |s|
s.platform = local
end
end
@@ -1446,9 +1477,9 @@ ERROR: Possible alternatives: non_existent_with_hint
def test_explain_platform_ruby
local = Gem::Platform.local
spec_fetcher do |fetcher|
- fetcher.spec 'a', 2
+ fetcher.spec "a", 2
- fetcher.spec 'a', 2 do |s|
+ fetcher.spec "a", 2 do |s|
s.platform = local
end
end
@@ -1475,9 +1506,9 @@ ERROR: Possible alternatives: non_existent_with_hint
def test_explain_platform_ruby_ignore_dependencies
local = Gem::Platform.local
spec_fetcher do |fetcher|
- fetcher.spec 'a', 3
+ fetcher.spec "a", 3
- fetcher.spec 'a', 3 do |s|
+ fetcher.spec "a", 3 do |s|
s.platform = local
end
end
@@ -1501,4 +1532,22 @@ ERROR: Possible alternatives: non_existent_with_hint
assert_equal " a-3", out.shift
assert_empty out
end
+
+ def test_suggest_update_if_enabled
+ TestUpdateSuggestion.with_eligible_environment(cmd: @cmd) do
+ spec_fetcher do |fetcher|
+ fetcher.gem "a", 2
+ end
+
+ @cmd.options[:args] = %w[a]
+
+ use_ui @ui do
+ assert_raise Gem::MockGemUi::SystemExitException, @ui.error do
+ @cmd.execute
+ end
+ end
+
+ assert_includes @ui.output, "A new release of RubyGems is available: 1.2.3 → 2.0.0!"
+ end
+ end
end
diff --git a/test/rubygems/test_gem_commands_list_command.rb b/test/rubygems/test_gem_commands_list_command.rb
index d8cffce7a3..0b52b54e77 100644
--- a/test/rubygems/test_gem_commands_list_command.rb
+++ b/test/rubygems/test_gem_commands_list_command.rb
@@ -1,23 +1,24 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/commands/list_command'
+
+require_relative "helper"
+require "rubygems/commands/list_command"
class TestGemCommandsListCommand < Gem::TestCase
def setup
super
@cmd = Gem::Commands::ListCommand.new
+ end
+ def test_execute_installed
spec_fetcher do |fetcher|
- fetcher.spec 'c', 1
+ fetcher.spec "c", 1
end
@fetcher.data["#{@gem_repo}Marshal.#{Gem.marshal_version}"] = proc do
raise Gem::RemoteFetcher::FetchError
end
- end
- def test_execute_installed
@cmd.handle_options %w[c --installed]
assert_raise Gem::MockGemUi::SystemExitException do
@@ -27,6 +28,31 @@ class TestGemCommandsListCommand < Gem::TestCase
end
assert_equal "true\n", @ui.output
- assert_equal '', @ui.error
+ assert_equal "", @ui.error
+ end
+
+ def test_execute_normal_gem_shadowing_default_gem
+ c1_default = new_default_spec "c", 1
+ install_default_gems c1_default
+
+ c1 = util_spec("c", 1) {|s| s.date = "2024-01-01" }
+ install_gem c1
+
+ Gem::Specification.reset
+
+ @cmd.handle_options %w[c]
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ expected = <<-EOF
+
+*** LOCAL GEMS ***
+
+c (1)
+EOF
+
+ assert_equal expected, @ui.output
end
end
diff --git a/test/rubygems/test_gem_commands_lock_command.rb b/test/rubygems/test_gem_commands_lock_command.rb
index f8afca1e29..02a7103f89 100644
--- a/test/rubygems/test_gem_commands_lock_command.rb
+++ b/test/rubygems/test_gem_commands_lock_command.rb
@@ -1,18 +1,19 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/commands/lock_command'
+
+require_relative "helper"
+require "rubygems/commands/lock_command"
class TestGemCommandsLockCommand < Gem::TestCase
def setup
super
- @a1 = quick_gem 'a', '1'
- @b1 = quick_gem 'b', '1' do |s|
- s.add_runtime_dependency 'a'
+ @a1 = quick_gem "a", "1"
+ @b1 = quick_gem "b", "1" do |s|
+ s.add_dependency "a"
end
- @d1 = quick_gem 'd', '1' do |s|
- s.add_runtime_dependency 'z'
+ @d1 = quick_gem "d", "1" do |s|
+ s.add_dependency "z"
end
@cmd = Gem::Commands::LockCommand.new
@@ -32,7 +33,7 @@ gem 'a', '= 1'
EXPECTED
assert_equal expected, @ui.output
- assert_equal '', @ui.error
+ assert_equal "", @ui.error
end
def test_execute_missing_dependency
@@ -49,7 +50,7 @@ gem 'd', '= 1'
EXPECTED
assert_equal expected, @ui.output
- assert_equal '', @ui.error
+ assert_equal "", @ui.error
end
def test_execute_strict
@@ -61,6 +62,6 @@ gem 'd', '= 1'
end
end
- assert_equal 'Could not find gem c-1, try using the full name', e.message
+ assert_equal "Could not find gem c-1, try using the full name", e.message
end
end
diff --git a/test/rubygems/test_gem_commands_mirror.rb b/test/rubygems/test_gem_commands_mirror.rb
index 470f1c30fa..2256a3ab33 100644
--- a/test/rubygems/test_gem_commands_mirror.rb
+++ b/test/rubygems/test_gem_commands_mirror.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/commands/mirror_command'
+
+require_relative "helper"
+require "rubygems/commands/mirror_command"
class TestGemCommandsMirrorCommand < Gem::TestCase
def setup
@@ -14,6 +15,6 @@ class TestGemCommandsMirrorCommand < Gem::TestCase
@cmd.execute
end
- assert_match %r{Install the rubygems-mirror}i, @ui.error
+ assert_match(/Install the rubygems-mirror/i, @ui.error)
end
end
diff --git a/test/rubygems/test_gem_commands_open_command.rb b/test/rubygems/test_gem_commands_open_command.rb
index 2d62149cc4..d9e518048c 100644
--- a/test/rubygems/test_gem_commands_open_command.rb
+++ b/test/rubygems/test_gem_commands_open_command.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/commands/open_command'
+
+require_relative "helper"
+require "rubygems/commands/open_command"
class TestGemCommandsOpenCommand < Gem::TestCase
def setup
@@ -21,20 +22,23 @@ class TestGemCommandsOpenCommand < Gem::TestCase
def test_execute
@cmd.options[:args] = %w[foo]
- @cmd.options[:editor] = "#{Gem.ruby} -eexit --"
+ @cmd.options[:editor] = (ruby_with_rubygems_in_load_path + ["-e", "puts(ARGV,Dir.pwd)", "--"]).join(" ")
- gem 'foo', '1.0.0'
- spec = gem 'foo', '1.0.1'
+ gem "foo", "1.0.0"
+ spec = gem "foo", "1.0.1"
assert_nothing_raised Gem::MockGemUi::TermError do
- Dir.stub(:chdir, spec.full_gem_path) do
+ stdout, stderr = capture_subprocess_io do
use_ui @ui do
@cmd.execute
end
end
+ assert_equal [spec.full_gem_path, spec.full_gem_path], stdout.split("\n")
+ assert_equal "", stderr
end
assert_equal "", @ui.error
+ assert_equal "", @ui.output
end
def test_wrong_version
@@ -49,7 +53,7 @@ class TestGemCommandsOpenCommand < Gem::TestCase
end
end
- assert_match %r{Unable to find gem 'foo'}, @ui.output
+ assert_match(/Unable to find gem 'foo'/, @ui.output)
assert_equal "", @ui.error
end
@@ -62,7 +66,7 @@ class TestGemCommandsOpenCommand < Gem::TestCase
end
end
- assert_match %r{Unable to find gem 'foo'}, @ui.output
+ assert_match(/Unable to find gem 'foo'/, @ui.output)
assert_equal "", @ui.error
end
@@ -91,7 +95,7 @@ class TestGemCommandsOpenCommand < Gem::TestCase
end
end
- assert_match %r{'foo' is a default gem and can't be opened\.} , @ui.output
+ assert_match(/'foo' is a default gem and can't be opened\./, @ui.output)
assert_equal "", @ui.error
end
end
diff --git a/test/rubygems/test_gem_commands_outdated_command.rb b/test/rubygems/test_gem_commands_outdated_command.rb
index dc5c40a782..3e61033af3 100644
--- a/test/rubygems/test_gem_commands_outdated_command.rb
+++ b/test/rubygems/test_gem_commands_outdated_command.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/commands/outdated_command'
+
+require_relative "helper"
+require "rubygems/commands/outdated_command"
class TestGemCommandsOutdatedCommand < Gem::TestCase
def setup
@@ -15,10 +16,10 @@ class TestGemCommandsOutdatedCommand < Gem::TestCase
def test_execute
spec_fetcher do |fetcher|
- fetcher.download 'foo', '1.0'
- fetcher.download 'foo', '2.0'
- fetcher.gem 'foo', '0.1'
- fetcher.gem 'foo', '0.2'
+ fetcher.download "foo", "1.0"
+ fetcher.download "foo", "2.0"
+ fetcher.gem "foo", "0.1"
+ fetcher.gem "foo", "0.2"
end
use_ui @ui do
@@ -31,10 +32,10 @@ class TestGemCommandsOutdatedCommand < Gem::TestCase
def test_execute_with_up_to_date_platform_specific_gem
spec_fetcher do |fetcher|
- fetcher.download 'foo', '2.0'
+ fetcher.download "foo", "2.0"
- fetcher.gem 'foo', '1.0'
- fetcher.gem 'foo', '2.0' do |s|
+ fetcher.gem "foo", "1.0"
+ fetcher.gem "foo", "2.0" do |s|
s.platform = Gem::Platform.local
end
end
diff --git a/test/rubygems/test_gem_commands_owner_command.rb b/test/rubygems/test_gem_commands_owner_command.rb
index 5b06b628c2..eddd8afaf5 100644
--- a/test/rubygems/test_gem_commands_owner_command.rb
+++ b/test/rubygems/test_gem_commands_owner_command.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/commands/owner_command'
+
+require_relative "helper"
+require_relative "multifactor_auth_utilities"
+require "rubygems/commands/owner_command"
class TestGemCommandsOwnerCommand < Gem::TestCase
def setup
@@ -10,7 +12,7 @@ class TestGemCommandsOwnerCommand < Gem::TestCase
ENV["RUBYGEMS_HOST"] = nil
@stub_ui = Gem::MockGemUi.new
- @stub_fetcher = Gem::FakeFetcher.new
+ @stub_fetcher = Gem::MultifactorAuthFetcher.new
Gem::RemoteFetcher.fetcher = @stub_fetcher
Gem.configuration = nil
Gem.configuration.rubygems_api_key = "ed244fbf2b1a52e012da8616c512fa47f9aa5250"
@@ -36,20 +38,20 @@ class TestGemCommandsOwnerCommand < Gem::TestCase
- id: 4
EOF
- @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners.yaml"] = [response, 200, 'OK']
+ @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners.yaml"] = HTTPResponseFactory.create(body: response, code: 200, msg: "OK")
use_ui @stub_ui do
@cmd.show_owners("freewill")
end
- assert_equal Net::HTTP::Get, @stub_fetcher.last_request.class
+ assert_equal Gem::Net::HTTP::Get, @stub_fetcher.last_request.class
assert_equal Gem.configuration.rubygems_api_key, @stub_fetcher.last_request["Authorization"]
- assert_match %r{Owners for gem: freewill}, @stub_ui.output
- assert_match %r{- user1@example.com}, @stub_ui.output
- assert_match %r{- user2@example.com}, @stub_ui.output
- assert_match %r{- user3}, @stub_ui.output
- assert_match %r{- 4}, @stub_ui.output
+ assert_match(/Owners for gem: freewill/, @stub_ui.output)
+ assert_match(/- user1@example.com/, @stub_ui.output)
+ assert_match(/- user2@example.com/, @stub_ui.output)
+ assert_match(/- user3/, @stub_ui.output)
+ assert_match(/- 4/, @stub_ui.output)
end
def test_show_owners_dont_load_objects
@@ -66,7 +68,7 @@ EOF
- id: 4
EOF
- @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners.yaml"] = [response, 200, 'OK']
+ @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners.yaml"] = HTTPResponseFactory.create(body: response, code: 200, msg: "OK")
assert_raise Psych::DisallowedClass do
use_ui @ui do
@@ -80,14 +82,14 @@ EOF
host = "http://rubygems.example"
ENV["RUBYGEMS_HOST"] = host
- @stub_fetcher.data["#{host}/api/v1/gems/freewill/owners.yaml"] = [response, 200, 'OK']
+ @stub_fetcher.data["#{host}/api/v1/gems/freewill/owners.yaml"] = HTTPResponseFactory.create(body: response, code: 200, msg: "OK")
use_ui @stub_ui do
@cmd.show_owners("freewill")
end
- assert_match %r{Owners for gem: freewill}, @stub_ui.output
- assert_match %r{- user1@example.com}, @stub_ui.output
+ assert_match(/Owners for gem: freewill/, @stub_ui.output)
+ assert_match(/- user1@example.com/, @stub_ui.output)
end
def test_show_owners_setting_up_host
@@ -95,19 +97,19 @@ EOF
host = "http://rubygems.example"
@cmd.host = host
- @stub_fetcher.data["#{host}/api/v1/gems/freewill/owners.yaml"] = [response, 200, 'OK']
+ @stub_fetcher.data["#{host}/api/v1/gems/freewill/owners.yaml"] = HTTPResponseFactory.create(body: response, code: 200, msg: "OK")
use_ui @stub_ui do
@cmd.show_owners("freewill")
end
- assert_match %r{Owners for gem: freewill}, @stub_ui.output
- assert_match %r{- user1@example.com}, @stub_ui.output
+ assert_match(/Owners for gem: freewill/, @stub_ui.output)
+ assert_match(/- user1@example.com/, @stub_ui.output)
end
def test_show_owners_denied
response = "You don't have permission to push to this gem"
- @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners.yaml"] = [response, 403, 'Forbidden']
+ @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners.yaml"] = HTTPResponseFactory.create(body: response, code: 403, msg: "Forbidden")
assert_raise Gem::MockGemUi::TermError do
use_ui @stub_ui do
@@ -118,29 +120,52 @@ EOF
assert_match response, @stub_ui.output
end
+ def test_show_owners_permanent_redirect
+ host = "http://rubygems.example"
+ ENV["RUBYGEMS_HOST"] = host
+ path = "/api/v1/gems/freewill/owners.yaml"
+ redirected_uri = "https://rubygems.example#{path}"
+
+ @stub_fetcher.data["#{host}#{path}"] = HTTPResponseFactory.create(
+ body: "",
+ code: "301",
+ msg: "Moved Permanently",
+ headers: { "location" => redirected_uri }
+ )
+
+ assert_raise Gem::MockGemUi::TermError do
+ use_ui @stub_ui do
+ @cmd.show_owners("freewill")
+ end
+ end
+
+ response = "The request has redirected permanently to #{redirected_uri}. Please check your defined push host URL."
+ assert_match response, @stub_ui.output
+ end
+
def test_show_owners_key
response = "- email: user1@example.com\n"
- @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners.yaml"] = [response, 200, 'OK']
- File.open Gem.configuration.credentials_path, 'a' do |f|
- f.write ':other: 701229f217cdf23b1344c7b4b54ca97'
+ @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners.yaml"] = HTTPResponseFactory.create(body: response, code: 200, msg: "OK")
+ File.open Gem.configuration.credentials_path, "a" do |f|
+ f.write ":other: 701229f217cdf23b1344c7b4b54ca97"
end
Gem.configuration.load_api_keys
@cmd.handle_options %w[-k other]
- @cmd.show_owners('freewill')
+ @cmd.show_owners("freewill")
- assert_equal '701229f217cdf23b1344c7b4b54ca97', @stub_fetcher.last_request['Authorization']
+ assert_equal "701229f217cdf23b1344c7b4b54ca97", @stub_fetcher.last_request["Authorization"]
end
def test_add_owners
response = "Owner added successfully."
- @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 200, 'OK']
+ @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = HTTPResponseFactory.create(body: response, code: 200, msg: "OK")
use_ui @stub_ui do
@cmd.add_owners("freewill", ["user-new1@example.com"])
end
- assert_equal Net::HTTP::Post, @stub_fetcher.last_request.class
+ assert_equal Gem::Net::HTTP::Post, @stub_fetcher.last_request.class
assert_equal Gem.configuration.rubygems_api_key, @stub_fetcher.last_request["Authorization"]
assert_equal "email=user-new1%40example.com", @stub_fetcher.last_request.body
@@ -149,7 +174,7 @@ EOF
def test_add_owners_denied
response = "You don't have permission to push to this gem"
- @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 403, 'Forbidden']
+ @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = HTTPResponseFactory.create(body: response, code: 403, msg: "Forbidden")
use_ui @stub_ui do
@cmd.add_owners("freewill", ["user-new1@example.com"])
@@ -158,12 +183,33 @@ EOF
assert_match response, @stub_ui.output
end
+ def test_add_owners_permanent_redirect
+ host = "http://rubygems.example"
+ ENV["RUBYGEMS_HOST"] = host
+ path = "/api/v1/gems/freewill/owners"
+ redirected_uri = "https://rubygems.example#{path}"
+
+ @stub_fetcher.data["#{host}#{path}"] = HTTPResponseFactory.create(
+ body: "",
+ code: "308",
+ msg: "Permanent Redirect",
+ headers: { "location" => redirected_uri }
+ )
+
+ use_ui @stub_ui do
+ @cmd.add_owners("freewill", ["user-new1@example.com"])
+ end
+
+ response = "The request has redirected permanently to #{redirected_uri}. Please check your defined push host URL."
+ assert_match response, @stub_ui.output
+ end
+
def test_add_owner_with_host_option_through_execute
host = "http://rubygems.example"
add_owner_response = "Owner added successfully."
show_owners_response = "- email: user1@example.com\n"
- @stub_fetcher.data["#{host}/api/v1/gems/freewill/owners"] = [add_owner_response, 200, 'OK']
- @stub_fetcher.data["#{host}/api/v1/gems/freewill/owners.yaml"] = [show_owners_response, 200, 'OK']
+ @stub_fetcher.data["#{host}/api/v1/gems/freewill/owners"] = HTTPResponseFactory.create(body: add_owner_response, code: 200, msg: "OK")
+ @stub_fetcher.data["#{host}/api/v1/gems/freewill/owners.yaml"] = HTTPResponseFactory.create(body: show_owners_response, code: 200, msg: "OK")
@cmd.handle_options %W[--host #{host} --add user-new1@example.com freewill]
@@ -172,33 +218,33 @@ EOF
end
assert_match add_owner_response, @stub_ui.output
- assert_match %r{Owners for gem: freewill}, @stub_ui.output
- assert_match %r{- user1@example.com}, @stub_ui.output
+ assert_match(/Owners for gem: freewill/, @stub_ui.output)
+ assert_match(/- user1@example.com/, @stub_ui.output)
end
def test_add_owners_key
response = "Owner added successfully."
- @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 200, 'OK']
- File.open Gem.configuration.credentials_path, 'a' do |f|
- f.write ':other: 701229f217cdf23b1344c7b4b54ca97'
+ @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = HTTPResponseFactory.create(body: response, code: 200, msg: "OK")
+ File.open Gem.configuration.credentials_path, "a" do |f|
+ f.write ":other: 701229f217cdf23b1344c7b4b54ca97"
end
Gem.configuration.load_api_keys
@cmd.handle_options %w[-k other]
- @cmd.add_owners('freewill', ['user-new1@example.com'])
+ @cmd.add_owners("freewill", ["user-new1@example.com"])
- assert_equal '701229f217cdf23b1344c7b4b54ca97', @stub_fetcher.last_request['Authorization']
+ assert_equal "701229f217cdf23b1344c7b4b54ca97", @stub_fetcher.last_request["Authorization"]
end
def test_remove_owners
response = "Owner removed successfully."
- @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 200, 'OK']
+ @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = HTTPResponseFactory.create(body: response, code: 200, msg: "OK")
use_ui @stub_ui do
@cmd.remove_owners("freewill", ["user-remove1@example.com"])
end
- assert_equal Net::HTTP::Delete, @stub_fetcher.last_request.class
+ assert_equal Gem::Net::HTTP::Delete, @stub_fetcher.last_request.class
assert_equal Gem.configuration.rubygems_api_key, @stub_fetcher.last_request["Authorization"]
assert_equal "email=user-remove1%40example.com", @stub_fetcher.last_request.body
@@ -207,32 +253,69 @@ EOF
def test_remove_owners_denied
response = "You don't have permission to push to this gem"
- @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 403, 'Forbidden']
+ @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = HTTPResponseFactory.create(body: response, code: 403, msg: "Forbidden")
+
+ use_ui @stub_ui do
+ @cmd.remove_owners("freewill", ["user-remove1@example.com"])
+ end
+
+ assert_match response, @stub_ui.output
+ end
+
+ def test_remove_owners_permanent_redirect
+ host = "http://rubygems.example"
+ ENV["RUBYGEMS_HOST"] = host
+ path = "/api/v1/gems/freewill/owners"
+ redirected_uri = "https://rubygems.example#{path}"
+ @stub_fetcher.data["#{host}#{path}"] = HTTPResponseFactory.create(
+ body: "",
+ code: "308",
+ msg: "Permanent Redirect",
+ headers: { "location" => redirected_uri }
+ )
use_ui @stub_ui do
@cmd.remove_owners("freewill", ["user-remove1@example.com"])
end
+ response = "The request has redirected permanently to #{redirected_uri}. Please check your defined push host URL."
+ assert_match response, @stub_ui.output
+
+ path = "/api/v1/gems/freewill/owners"
+ redirected_uri = "https://rubygems.example#{path}"
+
+ @stub_fetcher.data["#{host}#{path}"] = HTTPResponseFactory.create(
+ body: "",
+ code: "308",
+ msg: "Permanent Redirect",
+ headers: { "location" => redirected_uri }
+ )
+
+ use_ui @stub_ui do
+ @cmd.add_owners("freewill", ["user-new1@example.com"])
+ end
+
+ response = "The request has redirected permanently to #{redirected_uri}. Please check your defined push host URL."
assert_match response, @stub_ui.output
end
def test_remove_owners_key
response = "Owner removed successfully."
- @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 200, 'OK']
- File.open Gem.configuration.credentials_path, 'a' do |f|
- f.write ':other: 701229f217cdf23b1344c7b4b54ca97'
+ @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = HTTPResponseFactory.create(body: response, code: 200, msg: "OK")
+ File.open Gem.configuration.credentials_path, "a" do |f|
+ f.write ":other: 701229f217cdf23b1344c7b4b54ca97"
end
Gem.configuration.load_api_keys
@cmd.handle_options %w[-k other]
- @cmd.remove_owners('freewill', ['user-remove1@example.com'])
+ @cmd.remove_owners("freewill", ["user-remove1@example.com"])
- assert_equal '701229f217cdf23b1344c7b4b54ca97', @stub_fetcher.last_request['Authorization']
+ assert_equal "701229f217cdf23b1344c7b4b54ca97", @stub_fetcher.last_request["Authorization"]
end
def test_remove_owners_missing
- response = 'Owner could not be found.'
- @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 404, 'Not Found']
+ response = "Owner could not be found."
+ @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = HTTPResponseFactory.create(body: response, code: 404, msg: "Not Found")
use_ui @stub_ui do
@cmd.remove_owners("freewill", ["missing@example"])
@@ -242,28 +325,25 @@ EOF
end
def test_otp_verified_success
- response_fail = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry."
response_success = "Owner added successfully."
-
- @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [
- [response_fail, 401, 'Unauthorized'],
- [response_success, 200, 'OK'],
- ]
+ @stub_fetcher.respond_with_require_otp("#{Gem.host}/api/v1/gems/freewill/owners", response_success)
@otp_ui = Gem::MockGemUi.new "111111\n"
use_ui @otp_ui do
@cmd.add_owners("freewill", ["user-new1@example.com"])
end
- assert_match 'You have enabled multi-factor authentication. Please enter OTP code.', @otp_ui.output
- assert_match 'Code: ', @otp_ui.output
+ assert_match "You have enabled multi-factor authentication. Please enter OTP code.", @otp_ui.output
+ assert_match "Code: ", @otp_ui.output
assert_match response_success, @otp_ui.output
- assert_equal '111111', @stub_fetcher.last_request['OTP']
+ assert_equal "111111", @stub_fetcher.last_request["OTP"]
end
def test_otp_verified_failure
response = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry."
- @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [response, 401, 'Unauthorized']
+ @stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = HTTPResponseFactory.create(body: response, code: 401, msg: "Unauthorized")
+ @stub_fetcher.data["#{Gem.host}/api/v1/webauthn_verification"] =
+ HTTPResponseFactory.create(body: "You don't have any security devices", code: 422, msg: "Unprocessable Entity")
@otp_ui = Gem::MockGemUi.new "111111\n"
use_ui @otp_ui do
@@ -271,9 +351,106 @@ EOF
end
assert_match response, @otp_ui.output
- assert_match 'You have enabled multi-factor authentication. Please enter OTP code.', @otp_ui.output
- assert_match 'Code: ', @otp_ui.output
- assert_equal '111111', @stub_fetcher.last_request['OTP']
+ assert_match "You have enabled multi-factor authentication. Please enter OTP code.", @otp_ui.output
+ assert_match "Code: ", @otp_ui.output
+ assert_equal "111111", @stub_fetcher.last_request["OTP"]
+ end
+
+ def test_with_webauthn_enabled_success
+ response_success = "Owner added successfully."
+ server = Gem::MockTCPServer.new
+
+ @stub_fetcher.respond_with_require_otp("#{Gem.host}/api/v1/gems/freewill/owners", response_success)
+ @stub_fetcher.respond_with_webauthn_url
+
+ TCPServer.stub(:new, server) do
+ Gem::GemcutterUtilities::WebauthnListener.stub(:listener_thread, Thread.new { Thread.current[:otp] = "Uvh6T57tkWuUnWYo" }) do
+ use_ui @stub_ui do
+ @cmd.add_owners("freewill", ["user-new1@example.com"])
+ end
+ end
+ end
+
+ assert_match "You have enabled multi-factor authentication. Please visit #{@stub_fetcher.webauthn_url_with_port(server.port)} " \
+ "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, " \
+ "you can re-run the gem signin command with the `--otp [your_code]` option.", @stub_ui.output
+ assert_match "You are verified with a security device. You may close the browser window.", @stub_ui.output
+ assert_equal "Uvh6T57tkWuUnWYo", @stub_fetcher.last_request["OTP"]
+ assert_match response_success, @stub_ui.output
+ end
+
+ def test_with_webauthn_enabled_failure
+ response_success = "Owner added successfully."
+ server = Gem::MockTCPServer.new
+ error = Gem::WebauthnVerificationError.new("Something went wrong")
+
+ @stub_fetcher.respond_with_require_otp("#{Gem.host}/api/v1/gems/freewill/owners", response_success)
+ @stub_fetcher.respond_with_webauthn_url
+
+ TCPServer.stub(:new, server) do
+ Gem::GemcutterUtilities::WebauthnListener.stub(:listener_thread, Thread.new { Thread.current[:error] = error }) do
+ use_ui @stub_ui do
+ @cmd.add_owners("freewill", ["user-new1@example.com"])
+ end
+ end
+ end
+
+ assert_match @stub_fetcher.last_request["Authorization"], Gem.configuration.rubygems_api_key
+ assert_match "You have enabled multi-factor authentication. Please visit #{@stub_fetcher.webauthn_url_with_port(server.port)} " \
+ "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, " \
+ "you can re-run the gem signin command with the `--otp [your_code]` option.", @stub_ui.output
+ assert_match "ERROR: Security device verification failed: Something went wrong", @stub_ui.error
+ refute_match "You are verified with a security device. You may close the browser window.", @stub_ui.output
+ refute_match response_success, @stub_ui.output
+ end
+
+ def test_with_webauthn_enabled_success_with_polling
+ response_success = "Owner added successfully."
+ server = Gem::MockTCPServer.new
+
+ @stub_fetcher.respond_with_require_otp("#{Gem.host}/api/v1/gems/freewill/owners", response_success)
+ @stub_fetcher.respond_with_webauthn_url
+ @stub_fetcher.respond_with_webauthn_polling("Uvh6T57tkWuUnWYo")
+
+ TCPServer.stub(:new, server) do
+ use_ui @stub_ui do
+ @cmd.add_owners("freewill", ["user-new1@example.com"])
+ end
+ end
+
+ assert_match "You have enabled multi-factor authentication. Please visit #{@stub_fetcher.webauthn_url_with_port(server.port)} " \
+ "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, you can re-run the gem signin " \
+ "command with the `--otp [your_code]` option.", @stub_ui.output
+ assert_match "You are verified with a security device. You may close the browser window.", @stub_ui.output
+ assert_equal "Uvh6T57tkWuUnWYo", @stub_fetcher.last_request["OTP"]
+ assert_match response_success, @stub_ui.output
+ end
+
+ def test_with_webauthn_enabled_failure_with_polling
+ response_success = "Owner added successfully."
+ server = Gem::MockTCPServer.new
+
+ @stub_fetcher.respond_with_require_otp(
+ "#{Gem.host}/api/v1/gems/freewill/owners",
+ response_success
+ )
+ @stub_fetcher.respond_with_webauthn_url
+ @stub_fetcher.respond_with_webauthn_polling_failure
+
+ TCPServer.stub(:new, server) do
+ use_ui @stub_ui do
+ @cmd.add_owners("freewill", ["user-new1@example.com"])
+ end
+ end
+
+ assert_match @stub_fetcher.last_request["Authorization"], Gem.configuration.rubygems_api_key
+ assert_match "You have enabled multi-factor authentication. Please visit #{@stub_fetcher.webauthn_url_with_port(server.port)} " \
+ "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, you can re-run the gem signin " \
+ "command with the `--otp [your_code]` option.", @stub_ui.output
+ assert_match "ERROR: Security device verification failed: The token in the link you used has either expired " \
+ "or been used already.", @stub_ui.error
+ refute_match "You are verified with a security device. You may close the browser window.", @stub_ui.output
+ refute_match response_success, @stub_ui.output
end
def test_remove_owners_unathorized_api_key
@@ -281,10 +458,10 @@ EOF
response_success = "Owner removed successfully."
@stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [
- [response_forbidden, 403, 'Forbidden'],
- [response_success, 200, "OK"],
+ HTTPResponseFactory.create(body: response_forbidden, code: 403, msg: "Forbidden"),
+ HTTPResponseFactory.create(body: response_success, code: 200, msg: "OK"),
]
- @stub_fetcher.data["#{Gem.host}/api/v1/api_key"] = ["", 200, "OK"]
+ @stub_fetcher.data["#{Gem.host}/api/v1/api_key"] = HTTPResponseFactory.create(body: "", code: 200, msg: "OK")
@cmd.instance_variable_set :@scope, :remove_owner
@stub_ui = Gem::MockGemUi.new "some@mail.com\npass\n"
@@ -294,7 +471,7 @@ EOF
access_notice = "The existing key doesn't have access of remove_owner on RubyGems.org. Please sign in to update access."
assert_match access_notice, @stub_ui.output
- assert_match "Email:", @stub_ui.output
+ assert_match "Username/email:", @stub_ui.output
assert_match "Password:", @stub_ui.output
assert_match "Added remove_owner scope to the existing API key", @stub_ui.output
assert_match response_success, @stub_ui.output
@@ -305,10 +482,10 @@ EOF
response_success = "Owner added successfully."
@stub_fetcher.data["#{Gem.host}/api/v1/gems/freewill/owners"] = [
- [response_forbidden, 403, 'Forbidden'],
- [response_success, 200, "OK"],
+ HTTPResponseFactory.create(body: response_forbidden, code: 403, msg: "Forbidden"),
+ HTTPResponseFactory.create(body: response_success, code: 200, msg: "OK"),
]
- @stub_fetcher.data["#{Gem.host}/api/v1/api_key"] = ["", 200, "OK"]
+ @stub_fetcher.data["#{Gem.host}/api/v1/api_key"] = HTTPResponseFactory.create(body: "", code: 200, msg: "OK")
@cmd.instance_variable_set :@scope, :add_owner
@stub_ui = Gem::MockGemUi.new "some@mail.com\npass\n"
@@ -318,7 +495,7 @@ EOF
access_notice = "The existing key doesn't have access of add_owner on RubyGems.org. Please sign in to update access."
assert_match access_notice, @stub_ui.output
- assert_match "Email:", @stub_ui.output
+ assert_match "Username/email:", @stub_ui.output
assert_match "Password:", @stub_ui.output
assert_match "Added add_owner scope to the existing API key", @stub_ui.output
assert_match response_success, @stub_ui.output
diff --git a/test/rubygems/test_gem_commands_pristine_command.rb b/test/rubygems/test_gem_commands_pristine_command.rb
index f4000f4657..b8b39133ff 100644
--- a/test/rubygems/test_gem_commands_pristine_command.rb
+++ b/test/rubygems/test_gem_commands_pristine_command.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/commands/pristine_command'
+
+require_relative "helper"
+require "rubygems/commands/pristine_command"
class TestGemCommandsPristineCommand < Gem::TestCase
def setup
@@ -11,29 +12,29 @@ class TestGemCommandsPristineCommand < Gem::TestCase
end
def test_execute
- a = util_spec 'a' do |s|
+ a = util_spec "a" do |s|
s.executables = %w[foo]
s.files = %w[bin/foo lib/a.rb]
end
- write_file File.join(@tempdir, 'lib', 'a.rb') do |fp|
+ write_file File.join(@tempdir, "lib", "a.rb") do |fp|
fp.puts "puts __FILE__"
end
- write_file File.join(@tempdir, 'bin', 'foo') do |fp|
+ write_file File.join(@tempdir, "bin", "foo") do |fp|
fp.puts "#!/usr/bin/ruby"
end
install_gem a
- foo_path = File.join @gemhome, 'gems', a.full_name, 'bin', 'foo'
- a_rb_path = File.join @gemhome, 'gems', a.full_name, 'lib', 'a.rb'
+ foo_path = File.join @gemhome, "gems", a.full_name, "bin", "foo"
+ a_rb_path = File.join @gemhome, "gems", a.full_name, "lib", "a.rb"
write_file foo_path do |io|
- io.puts 'I changed it!'
+ io.puts "I changed it!"
end
write_file a_rb_path do |io|
- io.puts 'I changed it!'
+ io.puts "I changed it!"
end
@cmd.options[:args] = %w[a]
@@ -53,7 +54,7 @@ class TestGemCommandsPristineCommand < Gem::TestCase
end
def test_execute_user_install
- FileUtils.chmod 0555, @gemhome
+ FileUtils.chmod 0o555, @gemhome
a = util_spec "a" do |s|
s.executables = %w[foo]
@@ -95,25 +96,25 @@ class TestGemCommandsPristineCommand < Gem::TestCase
out = @ui.output.split("\n")
assert_equal "Restoring gems to pristine condition...", out.shift
- assert_equal "Restored #{a.full_name}", out.shift
+ assert_equal "Restored #{a.full_name} in #{Gem.user_dir}", out.shift
assert_empty out, out.inspect
ensure
- FileUtils.chmod(0755, @gemhome)
+ FileUtils.chmod(0o755, @gemhome)
end
def test_execute_all
- a = util_spec 'a' do |s|
+ a = util_spec "a" do |s|
s.executables = %w[foo]
end
- write_file File.join(@tempdir, 'bin', 'foo') do |fp|
+ write_file File.join(@tempdir, "bin", "foo") do |fp|
fp.puts "#!/usr/bin/ruby"
end
install_gem a
- gem_bin = File.join @gemhome, 'gems', a.full_name, 'bin', 'foo'
- gem_stub = File.join @gemhome, 'bin', 'foo'
+ gem_bin = File.join @gemhome, "gems", a.full_name, "bin", "foo"
+ gem_stub = File.join @gemhome, "bin", "foo"
FileUtils.rm gem_bin
FileUtils.rm gem_stub
@@ -135,17 +136,17 @@ class TestGemCommandsPristineCommand < Gem::TestCase
end
def test_execute_env_shebang
- a = util_spec 'a' do |s|
+ a = util_spec "a" do |s|
s.executables = %w[foo]
s.files = %w[bin/foo]
end
- write_file File.join(@tempdir, 'bin', 'foo') do |fp|
+ write_file File.join(@tempdir, "bin", "foo") do |fp|
fp.puts "#!/usr/bin/ruby"
end
install_gem a
- gem_exec = File.join @gemhome, 'bin', 'foo'
+ gem_exec = File.join @gemhome, "bin", "foo"
FileUtils.rm gem_exec
@@ -157,19 +158,19 @@ class TestGemCommandsPristineCommand < Gem::TestCase
assert_path_exist gem_exec
- ruby_exec = sprintf Gem.default_exec_format, 'ruby'
+ ruby_exec = format Gem.default_exec_format, "ruby"
- bin_env = win_platform? ? "" : %w[/usr/bin/env /bin/env].find {|f| File.executable?(f) } + " "
+ bin_env = Gem.win_platform? ? "" : %w[/usr/bin/env /bin/env].find {|f| File.executable?(f) } + " "
- assert_match %r{\A#!\s*#{bin_env}#{ruby_exec}}, File.read(gem_exec)
+ assert_match(/\A#!\s*#{bin_env}#{ruby_exec}/, File.read(gem_exec))
end
def test_execute_extensions_explicit
- a = util_spec 'a' do |s|
- s.extensions << 'ext/a/extconf.rb'
+ a = util_spec "a" do |s|
+ s.extensions << "ext/a/extconf.rb"
end
- ext_path = File.join @tempdir, 'ext', 'a', 'extconf.rb'
+ ext_path = File.join @tempdir, "ext", "a", "extconf.rb"
write_file ext_path do |io|
io.write <<-'RUBY'
File.open "Makefile", "w" do |f|
@@ -180,7 +181,7 @@ class TestGemCommandsPristineCommand < Gem::TestCase
RUBY
end
- b = util_spec 'b'
+ b = util_spec "b"
install_gem a
install_gem b
@@ -195,19 +196,67 @@ class TestGemCommandsPristineCommand < Gem::TestCase
out = @ui.output.split "\n"
- assert_equal 'Restoring gems to pristine condition...', out.shift
- assert_equal 'Building native extensions. This could take a while...',
+ assert_equal "Restoring gems to pristine condition...", out.shift
+ assert_equal "Building native extensions. This could take a while...",
out.shift
assert_equal "Restored #{a.full_name}", out.shift
assert_empty out, out.inspect
end
+ def test_execute_extensions_only_missing_extensions
+ a = util_spec "a" do |s|
+ s.extensions << "ext/a/extconf.rb"
+ end
+
+ ext_path = File.join @tempdir, "ext", "a", "extconf.rb"
+ write_file ext_path do |io|
+ io.write <<-'RUBY'
+ File.open "Makefile", "w" do |f|
+ f.puts "clean:\n\techo cleaned\n"
+ f.puts "all:\n\techo built\n"
+ f.puts "install:\n\techo installed\n"
+ end
+ RUBY
+ end
+
+ b = util_spec "b" do |s|
+ s.extensions << "ext/b/extconf.rb"
+ end
+
+ ext_path = File.join @tempdir, "ext", "b", "extconf.rb"
+ write_file ext_path do |io|
+ io.write <<-'RUBY'
+ File.open "Makefile", "w" do |f|
+ f.puts "clean:\n\techo cleaned\n"
+ f.puts "all:\n\techo built\n"
+ f.puts "install:\n\techo installed\n"
+ end
+ RUBY
+ end
+
+ install_gem a
+ install_gem b
+
+ # Remove the extension files for b
+ FileUtils.rm_rf b.gem_build_complete_path
+
+ @cmd.options[:only_missing_extensions] = true
+ @cmd.options[:args] = []
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ refute_includes @ui.output, "Restored #{a.full_name}"
+ assert_includes @ui.output, "Restored #{b.full_name}"
+ end
+
def test_execute_no_extension
- a = util_spec 'a' do |s|
- s.extensions << 'ext/a/extconf.rb'
+ a = util_spec "a" do |s|
+ s.extensions << "ext/a/extconf.rb"
end
- ext_path = File.join @tempdir, 'ext', 'a', 'extconf.rb'
+ ext_path = File.join @tempdir, "ext", "a", "extconf.rb"
write_file ext_path do |io|
io.write "# extconf.rb\nrequire 'mkmf'; create_makefile 'a'"
end
@@ -223,18 +272,18 @@ class TestGemCommandsPristineCommand < Gem::TestCase
out = @ui.output.split "\n"
- assert_equal 'Restoring gems to pristine condition...', out.shift
+ assert_equal "Restoring gems to pristine condition...", out.shift
assert_equal "Skipped #{a.full_name}, it needs to compile an extension",
out.shift
assert_empty out, out.inspect
end
def test_execute_with_extension_with_build_args
- a = util_spec 'a' do |s|
- s.extensions << 'ext/a/extconf.rb'
+ a = util_spec "a" do |s|
+ s.extensions << "ext/a/extconf.rb"
end
- ext_path = File.join @tempdir, 'ext', 'a', 'extconf.rb'
+ ext_path = File.join @tempdir, "ext", "a", "extconf.rb"
write_file ext_path do |io|
io.write <<-'RUBY'
File.open "Makefile", "w" do |f|
@@ -247,7 +296,7 @@ class TestGemCommandsPristineCommand < Gem::TestCase
build_args = %w[--with-awesome=true --sweet]
- install_gem a, :build_args => build_args
+ install_gem a, build_args: build_args
@cmd.options[:args] = %w[a]
@@ -257,7 +306,7 @@ class TestGemCommandsPristineCommand < Gem::TestCase
out = @ui.output.split "\n"
- assert_equal 'Restoring gems to pristine condition...', out.shift
+ assert_equal "Restoring gems to pristine condition...", out.shift
assert_equal "Building native extensions with: '--with-awesome=true --sweet'", out.shift
assert_equal "This could take a while...", out.shift
assert_equal "Restored #{a.full_name}", out.shift
@@ -265,8 +314,8 @@ class TestGemCommandsPristineCommand < Gem::TestCase
end
def test_execute_many
- a = util_spec 'a'
- b = util_spec 'b'
+ a = util_spec "a"
+ b = util_spec "b"
install_gem a
install_gem b
@@ -286,14 +335,14 @@ class TestGemCommandsPristineCommand < Gem::TestCase
end
def test_skip
- a = util_spec 'a'
- b = util_spec 'b'
+ a = util_spec "a"
+ b = util_spec "b"
install_gem a
install_gem b
@cmd.options[:args] = %w[a b]
- @cmd.options[:skip] = 'a'
+ @cmd.options[:skip] = "a"
use_ui @ui do
@cmd.execute
@@ -308,16 +357,16 @@ class TestGemCommandsPristineCommand < Gem::TestCase
end
def test_skip_many_gems
- a = util_spec 'a'
- b = util_spec 'b'
- c = util_spec 'c'
+ a = util_spec "a"
+ b = util_spec "b"
+ c = util_spec "c"
install_gem a
install_gem b
install_gem c
@cmd.options[:args] = %w[a b c]
- @cmd.options[:skip] = ['a', 'c']
+ @cmd.options[:skip] = ["a", "c"]
use_ui @ui do
@cmd.execute
@@ -333,16 +382,19 @@ class TestGemCommandsPristineCommand < Gem::TestCase
end
def test_execute_many_multi_repo
- a = util_spec 'a'
+ a = util_spec "a"
install_gem a
Gem.clear_paths
- gemhome2 = File.join @tempdir, 'gemhome2'
+ gemhome2 = File.join @tempdir, "gemhome2"
Gem.use_paths gemhome2, [gemhome2, @gemhome]
- b = util_spec 'b'
+ b = util_spec "b"
install_gem b
+ assert_path_exist File.join(gemhome2, "gems", "b-2")
+ assert_path_not_exist File.join(@gemhome, "gems", "b-2")
+
@cmd.options[:args] = %w[a b]
use_ui @ui do
@@ -352,25 +404,25 @@ class TestGemCommandsPristineCommand < Gem::TestCase
out = @ui.output.split "\n"
assert_equal "Restoring gems to pristine condition...", out.shift
- assert_equal "Restored #{a.full_name}", out.shift
+ assert_equal "Restored #{a.full_name} in #{@gemhome}", out.shift
assert_equal "Restored #{b.full_name}", out.shift
assert_empty out, out.inspect
- assert_path_exist File.join(@gemhome, "gems", 'a-2')
- assert_path_not_exist File.join(gemhome2, "gems", 'a-2')
- assert_path_exist File.join(gemhome2, "gems", 'b-2')
- assert_path_not_exist File.join(@gemhome, "gems", 'b-2')
+ assert_path_exist File.join(@gemhome, "gems", "a-2")
+ assert_path_not_exist File.join(gemhome2, "gems", "a-2")
+ assert_path_exist File.join(gemhome2, "gems", "b-2")
+ assert_path_not_exist File.join(@gemhome, "gems", "b-2")
end
def test_execute_missing_cache_gem
specs = spec_fetcher do |fetcher|
- fetcher.gem 'a', 1
- fetcher.gem 'a', 2
- fetcher.gem 'a', 3
- fetcher.gem 'a', '3.a'
+ fetcher.gem "a", 1
+ fetcher.gem "a", 2
+ fetcher.gem "a", 3
+ fetcher.gem "a", "3.a"
end
- FileUtils.rm specs['a-2'].cache_file
+ FileUtils.rm specs["a-2"].cache_file
@cmd.options[:args] = %w[a]
@@ -396,22 +448,23 @@ class TestGemCommandsPristineCommand < Gem::TestCase
def test_execute_missing_cache_gem_when_multi_repo
specs = spec_fetcher do |fetcher|
- fetcher.gem 'a', 1
- fetcher.gem 'b', 1
+ fetcher.gem "a", 1
+ fetcher.gem "b", 1
end
- FileUtils.rm_rf File.join(@gemhome, 'gems', 'a-1')
- FileUtils.rm_rf File.join(@gemhome, 'gems', 'b-1')
+ FileUtils.rm_rf File.join(@gemhome, "gems", "a-1")
+ FileUtils.rm_rf File.join(@gemhome, "gems", "b-1")
install_gem specs["a-1"]
- FileUtils.rm File.join(@gemhome, 'cache', 'a-1.gem')
+ FileUtils.rm File.join(@gemhome, "cache", "a-1.gem")
Gem.clear_paths
- gemhome2 = File.join(@tempdir, 'gemhome2')
+ gemhome2 = File.join(@tempdir, "gemhome2")
Gem.use_paths gemhome2, [gemhome2, @gemhome]
install_gem specs["b-1"]
- FileUtils.rm File.join(gemhome2, 'cache', 'b-1.gem')
+ FileUtils.rm File.join(gemhome2, "cache", "b-1.gem")
+ Gem::Specification.reset
@cmd.options[:args] = %w[a b]
@@ -423,8 +476,9 @@ class TestGemCommandsPristineCommand < Gem::TestCase
[
"Restoring gems to pristine condition...",
- "Cached gem for a-1 not found, attempting to fetch...",
- "Restored a-1",
+ "Cached gem for a-1 in #{@gemhome} not found, attempting to fetch...",
+ "Restored a-1 in #{@gemhome}",
+ "Restored b-1 in #{@gemhome}",
"Cached gem for b-1 not found, attempting to fetch...",
"Restored b-1",
].each do |line|
@@ -434,15 +488,15 @@ class TestGemCommandsPristineCommand < Gem::TestCase
assert_empty out, out.inspect
assert_empty @ui.error
- assert_path_exist File.join(@gemhome, "cache", 'a-1.gem')
- assert_path_not_exist File.join(gemhome2, "cache", 'a-2.gem')
- assert_path_exist File.join(@gemhome, "gems", 'a-1')
- assert_path_not_exist File.join(gemhome2, "gems", 'a-1')
+ assert_path_exist File.join(@gemhome, "cache", "a-1.gem")
+ assert_path_not_exist File.join(gemhome2, "cache", "a-2.gem")
+ assert_path_exist File.join(@gemhome, "gems", "a-1")
+ assert_path_not_exist File.join(gemhome2, "gems", "a-1")
- assert_path_exist File.join(gemhome2, "cache", 'b-1.gem')
- assert_path_not_exist File.join(@gemhome, "cache", 'b-2.gem')
- assert_path_exist File.join(gemhome2, "gems", 'b-1')
- assert_path_not_exist File.join(@gemhome, "gems", 'b-1')
+ assert_path_exist File.join(gemhome2, "cache", "b-1.gem")
+ assert_path_not_exist File.join(@gemhome, "cache", "b-2.gem")
+ assert_path_exist File.join(gemhome2, "gems", "b-1")
+ assert_path_exist File.join(@gemhome, "gems", "b-1")
end
def test_execute_no_gem
@@ -454,25 +508,25 @@ class TestGemCommandsPristineCommand < Gem::TestCase
end
end
- assert_match %r{at least one gem name}, e.message
+ assert_match(/at least one gem name/, e.message)
end
def test_execute_only_executables
- a = util_spec 'a' do |s|
+ a = util_spec "a" do |s|
s.executables = %w[foo]
s.files = %w[bin/foo lib/a.rb]
end
- write_file File.join(@tempdir, 'lib', 'a.rb') do |fp|
+ write_file File.join(@tempdir, "lib", "a.rb") do |fp|
fp.puts "puts __FILE__"
end
- write_file File.join(@tempdir, 'bin', 'foo') do |fp|
+ write_file File.join(@tempdir, "bin", "foo") do |fp|
fp.puts "#!/usr/bin/ruby"
end
install_gem a
- gem_lib = File.join @gemhome, 'gems', a.full_name, 'lib', 'a.rb'
- gem_exec = File.join @gemhome, 'bin', 'foo'
+ gem_lib = File.join @gemhome, "gems", a.full_name, "lib", "a.rb"
+ gem_exec = File.join @gemhome, "bin", "foo"
FileUtils.rm gem_exec
FileUtils.rm gem_lib
@@ -488,25 +542,25 @@ class TestGemCommandsPristineCommand < Gem::TestCase
end
def test_execute_only_plugins
- a = util_spec 'a' do |s|
+ a = util_spec "a" do |s|
s.executables = %w[foo]
s.files = %w[bin/foo lib/a.rb lib/rubygems_plugin.rb]
end
- write_file File.join(@tempdir, 'lib', 'a.rb') do |fp|
+ write_file File.join(@tempdir, "lib", "a.rb") do |fp|
fp.puts "puts __FILE__"
end
- write_file File.join(@tempdir, 'lib', 'rubygems_plugin.rb') do |fp|
- fp.puts "puts __FILE__"
+ write_file File.join(@tempdir, "lib", "rubygems_plugin.rb") do |fp|
+ fp.puts "# do nothing"
end
- write_file File.join(@tempdir, 'bin', 'foo') do |fp|
+ write_file File.join(@tempdir, "bin", "foo") do |fp|
fp.puts "#!/usr/bin/ruby"
end
install_gem a
- gem_lib = File.join @gemhome, 'gems', a.full_name, 'lib', 'a.rb'
- gem_plugin = File.join @gemhome, 'plugins', 'a_plugin.rb'
- gem_exec = File.join @gemhome, 'bin', 'foo'
+ gem_lib = File.join @gemhome, "gems", a.full_name, "lib", "a.rb"
+ gem_plugin = File.join @gemhome, "plugins", "a_plugin.rb"
+ gem_exec = File.join @gemhome, "bin", "foo"
FileUtils.rm gem_exec
FileUtils.rm gem_plugin
@@ -524,29 +578,29 @@ class TestGemCommandsPristineCommand < Gem::TestCase
end
def test_execute_bindir
- a = util_spec 'a' do |s|
+ a = util_spec "a" do |s|
s.name = "test_gem"
s.executables = %w[foo]
s.files = %w[bin/foo]
end
- write_file File.join(@tempdir, 'bin', 'foo') do |fp|
+ write_file File.join(@tempdir, "bin", "foo") do |fp|
fp.puts "#!/usr/bin/ruby"
end
- write_file File.join(@tempdir, 'test_bin', 'foo') do |fp|
+ write_file File.join(@tempdir, "test_bin", "foo") do |fp|
fp.puts "#!/usr/bin/ruby"
end
install_gem a
- gem_exec = File.join @gemhome, 'bin', 'foo'
- gem_bindir = File.join @tempdir, 'test_bin', 'foo'
+ gem_exec = File.join @gemhome, "bin", "foo"
+ gem_bindir = File.join @tempdir, "test_bin", "foo"
FileUtils.rm gem_exec
FileUtils.rm gem_bindir
- @cmd.handle_options ["--all", "--only-executables", "--bindir", "#{gem_bindir}"]
+ @cmd.handle_options ["--all", "--only-executables", "--bindir", gem_bindir.to_s]
use_ui @ui do
@cmd.execute
@@ -557,7 +611,7 @@ class TestGemCommandsPristineCommand < Gem::TestCase
end
def test_execute_unknown_gem_at_remote_source
- install_specs util_spec 'a'
+ install_specs util_spec "a"
@cmd.options[:args] = %w[a]
@@ -596,16 +650,16 @@ class TestGemCommandsPristineCommand < Gem::TestCase
end
def test_execute_multi_platform
- a = util_spec 'a' do |s|
- s.extensions << 'ext/a/extconf.rb'
+ a = util_spec "a" do |s|
+ s.extensions << "ext/a/extconf.rb"
end
- b = util_spec 'b' do |s|
- s.extensions << 'ext/a/extconf.rb'
+ b = util_spec "b" do |s|
+ s.extensions << "ext/a/extconf.rb"
s.platform = Gem::Platform.new("java")
end
- ext_path = File.join @tempdir, 'ext', 'a', 'extconf.rb'
+ ext_path = File.join @tempdir, "ext", "a", "extconf.rb"
write_file ext_path do |io|
io.write <<-'RUBY'
File.open "Makefile", "w" do |f|
@@ -631,8 +685,8 @@ class TestGemCommandsPristineCommand < Gem::TestCase
out = @ui.output.split "\n"
- assert_equal 'Restoring gems to pristine condition...', out.shift
- assert_equal 'Building native extensions. This could take a while...',
+ assert_equal "Restoring gems to pristine condition...", out.shift
+ assert_equal "Building native extensions. This could take a while...",
out.shift
assert_equal "Restored #{a.full_name}", out.shift
assert_empty out, out.inspect
diff --git a/test/rubygems/test_gem_commands_push_command.rb b/test/rubygems/test_gem_commands_push_command.rb
index fa3968ffce..a7a18ff4ab 100644
--- a/test/rubygems/test_gem_commands_push_command.rb
+++ b/test/rubygems/test_gem_commands_push_command.rb
@@ -1,6 +1,9 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/commands/push_command'
+
+require_relative "helper"
+require_relative "multifactor_auth_utilities"
+require "rubygems/commands/push_command"
+require "rubygems/config_file"
class TestGemCommandsPushCommand < Gem::TestCase
def setup
@@ -12,7 +15,7 @@ class TestGemCommandsPushCommand < Gem::TestCase
Gem.host = Gem::DEFAULT_HOST
Gem.configuration.disable_default_gem_server = false
- @gems_dir = File.join @tempdir, 'gems'
+ @gems_dir = File.join @tempdir, "gems"
@cache_dir = File.join @gemhome, "cache"
FileUtils.mkdir @gems_dir
@@ -21,10 +24,10 @@ class TestGemCommandsPushCommand < Gem::TestCase
"ed244fbf2b1a52e012da8616c512fa47f9aa5250"
@spec, @path = util_gem "freewill", "1.0.0"
- @host = 'https://rubygems.example'
+ @host = "https://rubygems.example"
@api_key = Gem.configuration.rubygems_api_key
- @fetcher = Gem::FakeFetcher.new
+ @fetcher = Gem::MultifactorAuthFetcher.new
Gem::RemoteFetcher.fetcher = @fetcher
@cmd = Gem::Commands::PushCommand.new
@@ -55,9 +58,9 @@ class TestGemCommandsPushCommand < Gem::TestCase
@cmd.send_gem(@path)
end
- assert_match %r{Pushing gem to #{@host}...}, @ui.output
+ assert_match(/Pushing gem to #{@host}.../, @ui.output)
- assert_equal Net::HTTP::Post, @fetcher.last_request.class
+ assert_equal Gem::Net::HTTP::Post, @fetcher.last_request.class
assert_equal Gem.read_binary(@path), @fetcher.last_request.body
assert_equal File.size(@path), @fetcher.last_request["Content-Length"].to_i
assert_equal "application/octet-stream", @fetcher.last_request["Content-Type"]
@@ -68,32 +71,32 @@ class TestGemCommandsPushCommand < Gem::TestCase
def test_execute
@response = "Successfully registered gem: freewill (1.0.0)"
- @fetcher.data["#{Gem.host}/api/v1/gems"] = [@response, 200, 'OK']
+ @fetcher.data["#{Gem.host}/api/v1/gems"] = HTTPResponseFactory.create(body: @response, code: 200, msg: "OK")
@cmd.options[:args] = [@path]
@cmd.execute
- assert_equal Net::HTTP::Post, @fetcher.last_request.class
+ assert_equal Gem::Net::HTTP::Post, @fetcher.last_request.class
assert_equal Gem.read_binary(@path), @fetcher.last_request.body
assert_equal "application/octet-stream",
@fetcher.last_request["Content-Type"]
end
def test_execute_host
- host = 'https://other.example'
+ host = "https://other.example"
@response = "Successfully registered gem: freewill (1.0.0)"
- @fetcher.data["#{host}/api/v1/gems"] = [@response, 200, 'OK']
+ @fetcher.data["#{host}/api/v1/gems"] = HTTPResponseFactory.create(body: @response, code: 200, msg: "OK")
@fetcher.data["#{Gem.host}/api/v1/gems"] =
- ['fail', 500, 'Internal Server Error']
+ ["fail", 500, "Internal Server Error"]
@cmd.options[:host] = host
@cmd.options[:args] = [@path]
@cmd.execute
- assert_equal Net::HTTP::Post, @fetcher.last_request.class
+ assert_equal Gem::Net::HTTP::Post, @fetcher.last_request.class
assert_equal Gem.read_binary(@path), @fetcher.last_request.body
assert_equal "application/octet-stream",
@fetcher.last_request["Content-Type"]
@@ -101,19 +104,19 @@ class TestGemCommandsPushCommand < Gem::TestCase
def test_execute_allowed_push_host
@spec, @path = util_gem "freebird", "1.0.1" do |spec|
- spec.metadata['allowed_push_host'] = "https://privategemserver.example"
+ spec.metadata["allowed_push_host"] = "https://privategemserver.example"
end
@response = "Successfully registered gem: freewill (1.0.0)"
- @fetcher.data["#{@spec.metadata['allowed_push_host']}/api/v1/gems"] = [@response, 200, 'OK']
+ @fetcher.data["#{@spec.metadata["allowed_push_host"]}/api/v1/gems"] = HTTPResponseFactory.create(body: @response, code: 200, msg: "OK")
@fetcher.data["#{Gem.host}/api/v1/gems"] =
- ['fail', 500, 'Internal Server Error']
+ ["fail", 500, "Internal Server Error"]
@cmd.options[:args] = [@path]
@cmd.execute
- assert_equal Net::HTTP::Post, @fetcher.last_request.class
+ assert_equal Gem::Net::HTTP::Post, @fetcher.last_request.class
assert_equal Gem.read_binary(@path), @fetcher.last_request.body
assert_equal "application/octet-stream",
@fetcher.last_request["Content-Type"]
@@ -136,7 +139,7 @@ class TestGemCommandsPushCommand < Gem::TestCase
ENV["RUBYGEMS_HOST"] = @host
Gem.configuration.disable_default_gem_server = true
@response = "Successfully registered gem: freewill (1.0.0)"
- @fetcher.data["#{@host}/api/v1/gems"] = [@response, 200, 'OK']
+ @fetcher.data["#{@host}/api/v1/gems"] = HTTPResponseFactory.create(body: @response, code: 200, msg: "OK")
send_battery
end
@@ -145,32 +148,32 @@ class TestGemCommandsPushCommand < Gem::TestCase
@host = "http://privategemserver.example"
@spec, @path = util_gem "freebird", "1.0.1" do |spec|
- spec.metadata['default_gem_server'] = @host
+ spec.metadata["default_gem_server"] = @host
end
@api_key = "EYKEY"
keys = {
- :rubygems_api_key => 'KEY',
+ :rubygems_api_key => "KEY",
@host => @api_key,
}
- File.open Gem.configuration.credentials_path, 'w' do |f|
- f.write keys.to_yaml
+ File.open Gem.configuration.credentials_path, "w" do |f|
+ f.write Gem::ConfigFile.dump_with_rubygems_yaml(keys)
end
Gem.configuration.load_api_keys
FileUtils.rm Gem.configuration.credentials_path
@response = "Successfully registered gem: freebird (1.0.1)"
- @fetcher.data["#{@host}/api/v1/gems"] = [@response, 200, 'OK']
+ @fetcher.data["#{@host}/api/v1/gems"] = HTTPResponseFactory.create(body: @response, code: 200, msg: "OK")
send_battery
end
def test_sending_gem
@response = "Successfully registered gem: freewill (1.0.0)"
- @fetcher.data["#{@host}/api/v1/gems"] = [@response, 200, 'OK']
+ @fetcher.data["#{@host}/api/v1/gems"] = HTTPResponseFactory.create(body: @response, code: 200, msg: "OK")
send_battery
end
@@ -179,25 +182,25 @@ class TestGemCommandsPushCommand < Gem::TestCase
@host = "http://privategemserver.example"
@spec, @path = util_gem "freebird", "1.0.1" do |spec|
- spec.metadata['allowed_push_host'] = @host
+ spec.metadata["allowed_push_host"] = @host
end
@api_key = "PRIVKEY"
keys = {
- :rubygems_api_key => 'KEY',
+ :rubygems_api_key => "KEY",
@host => @api_key,
}
- File.open Gem.configuration.credentials_path, 'w' do |f|
- f.write keys.to_yaml
+ File.open Gem.configuration.credentials_path, "w" do |f|
+ f.write Gem::ConfigFile.dump_with_rubygems_yaml(keys)
end
Gem.configuration.load_api_keys
FileUtils.rm Gem.configuration.credentials_path
@response = "Successfully registered gem: freebird (1.0.1)"
- @fetcher.data["#{@host}/api/v1/gems"] = [@response, 200, 'OK']
+ @fetcher.data["#{@host}/api/v1/gems"] = HTTPResponseFactory.create(body: @response, code: 200, msg: "OK")
send_battery
end
@@ -205,14 +208,14 @@ class TestGemCommandsPushCommand < Gem::TestCase
@host = "http://privategemserver.example"
@spec, @path = util_gem "freebird", "1.0.1" do |spec|
- spec.metadata['allowed_push_host'] = @host
+ spec.metadata["allowed_push_host"] = @host
end
@api_key = "PRIVKEY"
ENV["GEM_HOST_API_KEY"] = "PRIVKEY"
@response = "Successfully registered gem: freebird (1.0.1)"
- @fetcher.data["#{@host}/api/v1/gems"] = [@response, 200, 'OK']
+ @fetcher.data["#{@host}/api/v1/gems"] = HTTPResponseFactory.create(body: @response, code: 200, msg: "OK")
send_battery
end
@@ -221,30 +224,30 @@ class TestGemCommandsPushCommand < Gem::TestCase
@host = "http://user:password@privategemserver.example"
@spec, @path = util_gem "freebird", "1.0.1" do |spec|
- spec.metadata['allowed_push_host'] = @sanitized_host
+ spec.metadata["allowed_push_host"] = @sanitized_host
end
@api_key = "DOESNTMATTER"
keys = {
- :rubygems_api_key => @api_key,
+ rubygems_api_key: @api_key,
}
- File.open Gem.configuration.credentials_path, 'w' do |f|
- f.write keys.to_yaml
+ File.open Gem.configuration.credentials_path, "w" do |f|
+ f.write Gem::ConfigFile.dump_with_rubygems_yaml(keys)
end
Gem.configuration.load_api_keys
FileUtils.rm Gem.configuration.credentials_path
@response = "Successfully registered gem: freebird (1.0.1)"
- @fetcher.data["#{@host}/api/v1/gems"] = [@response, 200, 'OK']
+ @fetcher.data["#{@host}/api/v1/gems"] = HTTPResponseFactory.create(body: @response, code: 200, msg: "OK")
send_battery
end
def test_sending_gem_to_disallowed_default_host
@spec, @path = util_gem "freebird", "1.0.1" do |spec|
- spec.metadata['allowed_push_host'] = "https://privategemserver.example"
+ spec.metadata["allowed_push_host"] = "https://privategemserver.example"
end
response = %(ERROR: "#{@host}" is not allowed by the gemspec, which only allows "https://privategemserver.example")
@@ -261,18 +264,18 @@ class TestGemCommandsPushCommand < Gem::TestCase
push_host = "https://privategemserver.example"
@spec, @path = util_gem "freebird", "1.0.1" do |spec|
- spec.metadata['allowed_push_host'] = push_host
+ spec.metadata["allowed_push_host"] = push_host
end
@api_key = "PRIVKEY"
keys = {
- :rubygems_api_key => 'KEY',
+ :rubygems_api_key => "KEY",
@host => @api_key,
}
- File.open Gem.configuration.credentials_path, 'w' do |f|
- f.write keys.to_yaml
+ File.open Gem.configuration.credentials_path, "w" do |f|
+ f.write Gem::ConfigFile.dump_with_rubygems_yaml(keys)
end
Gem.configuration.load_api_keys
@@ -291,8 +294,8 @@ class TestGemCommandsPushCommand < Gem::TestCase
host = "http://privategemserver.example"
@spec, @path = util_gem "freebird", "1.0.1" do |spec|
- spec.metadata.delete('default_gem_server')
- spec.metadata['allowed_push_host'] = host
+ spec.metadata.delete("default_gem_server")
+ spec.metadata["allowed_push_host"] = host
end
api_key = "PRIVKEY"
@@ -301,22 +304,22 @@ class TestGemCommandsPushCommand < Gem::TestCase
host => api_key,
}
- File.open Gem.configuration.credentials_path, 'w' do |f|
- f.write keys.to_yaml
+ File.open Gem.configuration.credentials_path, "w" do |f|
+ f.write Gem::ConfigFile.dump_with_rubygems_yaml(keys)
end
Gem.configuration.load_api_keys
FileUtils.rm Gem.configuration.credentials_path
@response = "Successfully registered gem: freebird (1.0.1)"
- @fetcher.data["#{host}/api/v1/gems"] = [@response, 200, 'OK']
+ @fetcher.data["#{host}/api/v1/gems"] = HTTPResponseFactory.create(body: @response, code: 200, msg: "OK")
# do not set @host
use_ui(@ui) { @cmd.send_gem(@path) }
- assert_match %r{Pushing gem to #{host}...}, @ui.output
+ assert_match(/Pushing gem to #{host}.../, @ui.output)
- assert_equal Net::HTTP::Post, @fetcher.last_request.class
+ assert_equal Gem::Net::HTTP::Post, @fetcher.last_request.class
assert_equal Gem.read_binary(@path), @fetcher.last_request.body
assert_equal File.size(@path), @fetcher.last_request["Content-Length"].to_i
assert_equal "application/octet-stream", @fetcher.last_request["Content-Type"]
@@ -325,6 +328,27 @@ class TestGemCommandsPushCommand < Gem::TestCase
assert_match @response, @ui.output
end
+ def test_sending_gem_to_host_permanent_redirect
+ @host = "http://rubygems.example"
+ redirected_uri = "https://rubygems.example/api/v1/gems"
+ @fetcher.data["#{@host}/api/v1/gems"] = HTTPResponseFactory.create(
+ body: "",
+ code: 308,
+ msg: "Permanent Redirect",
+ headers: { "Location" => redirected_uri }
+ )
+
+ assert_raise Gem::MockGemUi::TermError do
+ use_ui @ui do
+ @cmd.instance_variable_set :@host, @host
+ @cmd.send_gem(@path)
+ end
+ end
+
+ response = "The request has redirected permanently to #{redirected_uri}. Please check your defined push host URL."
+ assert_match response, @ui.output
+ end
+
def test_raises_error_with_no_arguments
def @cmd.sign_in(*); end
assert_raise Gem::CommandLineError do
@@ -334,7 +358,7 @@ class TestGemCommandsPushCommand < Gem::TestCase
def test_sending_gem_denied
response = "You don't have permission to push to this gem"
- @fetcher.data["#{@host}/api/v1/gems"] = [response, 403, 'Forbidden']
+ @fetcher.data["#{@host}/api/v1/gems"] = HTTPResponseFactory.create(body: response, code: 403, msg: "Forbidden")
@cmd.instance_variable_set :@host, @host
assert_raise Gem::MockGemUi::TermError do
@@ -348,9 +372,9 @@ class TestGemCommandsPushCommand < Gem::TestCase
def test_sending_gem_key
@response = "Successfully registered gem: freewill (1.0.0)"
- @fetcher.data["#{@host}/api/v1/gems"] = [@response, 200, "OK"]
- File.open Gem.configuration.credentials_path, 'a' do |f|
- f.write ':other: 701229f217cdf23b1344c7b4b54ca97'
+ @fetcher.data["#{@host}/api/v1/gems"] = HTTPResponseFactory.create(body: @response, code: 200, msg: "OK")
+ File.open Gem.configuration.credentials_path, "a" do |f|
+ f.write ":other: 701229f217cdf23b1344c7b4b54ca97"
end
Gem.configuration.load_api_keys
@@ -363,28 +387,26 @@ class TestGemCommandsPushCommand < Gem::TestCase
end
def test_otp_verified_success
- response_fail = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry."
- response_success = 'Successfully registered gem: freewill (1.0.0)'
+ response_success = "Successfully registered gem: freewill (1.0.0)"
- @fetcher.data["#{Gem.host}/api/v1/gems"] = [
- [response_fail, 401, 'Unauthorized'],
- [response_success, 200, 'OK'],
- ]
+ @fetcher.respond_with_require_otp("#{Gem.host}/api/v1/gems", response_success)
@otp_ui = Gem::MockGemUi.new "111111\n"
use_ui @otp_ui do
@cmd.send_gem(@path)
end
- assert_match 'You have enabled multi-factor authentication. Please enter OTP code.', @otp_ui.output
- assert_match 'Code: ', @otp_ui.output
+ assert_match "You have enabled multi-factor authentication. Please enter OTP code.", @otp_ui.output
+ assert_match "Code: ", @otp_ui.output
assert_match response_success, @otp_ui.output
- assert_equal '111111', @fetcher.last_request['OTP']
+ assert_equal "111111", @fetcher.last_request["OTP"]
end
def test_otp_verified_failure
response = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry."
- @fetcher.data["#{Gem.host}/api/v1/gems"] = [response, 401, 'Unauthorized']
+ @fetcher.data["#{Gem.host}/api/v1/gems"] = HTTPResponseFactory.create(body: response, code: 401, msg: "Unauthorized")
+ @fetcher.data["#{Gem.host}/api/v1/webauthn_verification"] =
+ HTTPResponseFactory.create(body: "You don't have any security devices", code: 422, msg: "Unprocessable Entity")
@otp_ui = Gem::MockGemUi.new "111111\n"
assert_raise Gem::MockGemUi::TermError do
@@ -394,23 +416,125 @@ class TestGemCommandsPushCommand < Gem::TestCase
end
assert_match response, @otp_ui.output
- assert_match 'You have enabled multi-factor authentication. Please enter OTP code.', @otp_ui.output
- assert_match 'Code: ', @otp_ui.output
- assert_equal '111111', @fetcher.last_request['OTP']
+ assert_match "You have enabled multi-factor authentication. Please enter OTP code.", @otp_ui.output
+ assert_match "Code: ", @otp_ui.output
+ assert_equal "111111", @fetcher.last_request["OTP"]
+ end
+
+ def test_with_webauthn_enabled_success
+ response_success = "Successfully registered gem: freewill (1.0.0)"
+ server = Gem::MockTCPServer.new
+
+ @fetcher.respond_with_require_otp("#{Gem.host}/api/v1/gems", response_success)
+ @fetcher.respond_with_webauthn_url
+
+ TCPServer.stub(:new, server) do
+ Gem::GemcutterUtilities::WebauthnListener.stub(:listener_thread, Thread.new { Thread.current[:otp] = "Uvh6T57tkWuUnWYo" }) do
+ use_ui @ui do
+ @cmd.send_gem(@path)
+ end
+ end
+ end
+
+ assert_match "You have enabled multi-factor authentication. Please visit #{@fetcher.webauthn_url_with_port(server.port)} " \
+ "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, " \
+ "you can re-run the gem signin command with the `--otp [your_code]` option.", @ui.output
+ assert_match "You are verified with a security device. You may close the browser window.", @ui.output
+ assert_equal "Uvh6T57tkWuUnWYo", @fetcher.last_request["OTP"]
+ assert_match response_success, @ui.output
+ end
+
+ def test_with_webauthn_enabled_failure
+ response_success = "Successfully registered gem: freewill (1.0.0)"
+ server = Gem::MockTCPServer.new
+ error = Gem::WebauthnVerificationError.new("Something went wrong")
+
+ @fetcher.respond_with_require_otp("#{Gem.host}/api/v1/gems", response_success)
+ @fetcher.respond_with_webauthn_url
+
+ error = assert_raise Gem::MockGemUi::TermError do
+ TCPServer.stub(:new, server) do
+ Gem::GemcutterUtilities::WebauthnListener.stub(:listener_thread, Thread.new { Thread.current[:error] = error }) do
+ use_ui @ui do
+ @cmd.send_gem(@path)
+ end
+ end
+ end
+ end
+ assert_equal 1, error.exit_code
+
+ assert_match @fetcher.last_request["Authorization"], Gem.configuration.rubygems_api_key
+ assert_match "You have enabled multi-factor authentication. Please visit #{@fetcher.webauthn_url_with_port(server.port)} " \
+ "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, " \
+ "you can re-run the gem signin command with the `--otp [your_code]` option.", @ui.output
+ assert_match "ERROR: Security device verification failed: Something went wrong", @ui.error
+ refute_match "You are verified with a security device. You may close the browser window.", @ui.output
+ refute_match response_success, @ui.output
+ end
+
+ def test_with_webauthn_enabled_success_with_polling
+ response_success = "Successfully registered gem: freewill (1.0.0)"
+ server = Gem::MockTCPServer.new
+
+ @fetcher.respond_with_require_otp("#{Gem.host}/api/v1/gems", response_success)
+ @fetcher.respond_with_webauthn_url
+ @fetcher.respond_with_webauthn_polling("Uvh6T57tkWuUnWYo")
+
+ TCPServer.stub(:new, server) do
+ use_ui @ui do
+ @cmd.send_gem(@path)
+ end
+ end
+
+ assert_match "You have enabled multi-factor authentication. Please visit #{@fetcher.webauthn_url_with_port(server.port)} " \
+ "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, " \
+ "you can re-run the gem signin command with the `--otp [your_code]` option.", @ui.output
+ assert_match "You are verified with a security device. You may close the browser window.", @ui.output
+ assert_equal "Uvh6T57tkWuUnWYo", @fetcher.last_request["OTP"]
+ assert_match response_success, @ui.output
+ end
+
+ def test_with_webauthn_enabled_failure_with_polling
+ response_success = "Successfully registered gem: freewill (1.0.0)"
+ server = Gem::MockTCPServer.new
+
+ @fetcher.respond_with_require_otp("#{Gem.host}/api/v1/gems", response_success)
+ @fetcher.respond_with_webauthn_url
+ @fetcher.respond_with_webauthn_polling_failure
+
+ error = assert_raise Gem::MockGemUi::TermError do
+ TCPServer.stub(:new, server) do
+ use_ui @ui do
+ @cmd.send_gem(@path)
+ end
+ end
+ end
+ assert_equal 1, error.exit_code
+
+ assert_match @fetcher.last_request["Authorization"], Gem.configuration.rubygems_api_key
+ assert_match "You have enabled multi-factor authentication. Please visit #{@fetcher.webauthn_url_with_port(server.port)} " \
+ "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, you can re-run the gem signin " \
+ "command with the `--otp [your_code]` option.", @ui.output
+ assert_match "ERROR: Security device verification failed: The token in the link you used has either expired " \
+ "or been used already.", @ui.error
+ refute_match "You are verified with a security device. You may close the browser window.", @ui.output
+ refute_match response_success, @ui.output
end
def test_sending_gem_unathorized_api_key_with_mfa_enabled
response_mfa_enabled = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry."
response_forbidden = "The API key doesn't have access"
- response_success = 'Successfully registered gem: freewill (1.0.0)'
+ response_success = "Successfully registered gem: freewill (1.0.0)"
@fetcher.data["#{@host}/api/v1/gems"] = [
- [response_mfa_enabled, 401, 'Unauthorized'],
- [response_forbidden, 403, 'Forbidden'],
- [response_success, 200, "OK"],
+ HTTPResponseFactory.create(body: response_mfa_enabled, code: 401, msg: "Unauthorized"),
+ HTTPResponseFactory.create(body: response_forbidden, code: 403, msg: "Forbidden"),
+ HTTPResponseFactory.create(body: response_success, code: 200, msg: "OK"),
]
+ @fetcher.data["#{@host}/api/v1/webauthn_verification"] =
+ HTTPResponseFactory.create(body: "You don't have any security devices", code: 422, msg: "Unprocessable Entity")
- @fetcher.data["#{@host}/api/v1/api_key"] = ["", 200, "OK"]
+ @fetcher.data["#{@host}/api/v1/api_key"] = HTTPResponseFactory.create(body: "", code: 200, msg: "OK")
@cmd.instance_variable_set :@host, @host
@cmd.instance_variable_set :@scope, :push_rubygem
@@ -423,27 +547,34 @@ class TestGemCommandsPushCommand < Gem::TestCase
access_notice = "The existing key doesn't have access of push_rubygem on https://rubygems.example. Please sign in to update access."
assert_match mfa_notice, @ui.output
assert_match access_notice, @ui.output
- assert_match "Email:", @ui.output
+ assert_match "Username/email:", @ui.output
assert_match "Password:", @ui.output
assert_match "Added push_rubygem scope to the existing API key", @ui.output
assert_match response_success, @ui.output
- assert_equal '11111', @fetcher.last_request['OTP']
+ assert_equal "11111", @fetcher.last_request["OTP"]
end
def test_sending_gem_with_no_local_creds
Gem.configuration.rubygems_api_key = nil
response_mfa_enabled = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry."
- response_success = 'Successfully registered gem: freewill (1.0.0)'
+ response_success = "Successfully registered gem: freewill (1.0.0)"
+ response_profile = "mfa: disabled\n"
@fetcher.data["#{@host}/api/v1/gems"] = [
- [response_success, 200, "OK"],
+ HTTPResponseFactory.create(body: response_success, code: 200, msg: "OK"),
]
@fetcher.data["#{@host}/api/v1/api_key"] = [
- [response_mfa_enabled, 401, 'Unauthorized'],
- ["", 200, "OK"],
+ HTTPResponseFactory.create(body: response_mfa_enabled, code: 401, msg: "Unauthorized"),
+ HTTPResponseFactory.create(body: "", code: 200, msg: "OK"),
+ ]
+
+ @fetcher.data["#{@host}/api/v1/profile/me.yaml"] = [
+ HTTPResponseFactory.create(body: response_profile, code: 200, msg: "OK"),
]
+ @fetcher.data["#{@host}/api/v1/webauthn_verification"] =
+ HTTPResponseFactory.create(body: "You don't have any security devices", code: 422, msg: "Unprocessable Entity")
@cmd.instance_variable_set :@scope, :push_rubygem
@cmd.options[:args] = [@path]
@@ -457,11 +588,11 @@ class TestGemCommandsPushCommand < Gem::TestCase
mfa_notice = "You have enabled multi-factor authentication. Please enter OTP code."
assert_match mfa_notice, @ui.output
assert_match "Enter your https://rubygems.example credentials.", @ui.output
- assert_match "Email:", @ui.output
+ assert_match "Username/email:", @ui.output
assert_match "Password:", @ui.output
assert_match "Signed in with API key:", @ui.output
assert_match response_success, @ui.output
- assert_equal '11111', @fetcher.last_request['OTP']
+ assert_equal "11111", @fetcher.last_request["OTP"]
end
private
diff --git a/test/rubygems/test_gem_commands_query_command.rb b/test/rubygems/test_gem_commands_query_command.rb
index 0cc88b1685..8e590df124 100644
--- a/test/rubygems/test_gem_commands_query_command.rb
+++ b/test/rubygems/test_gem_commands_query_command.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/commands/query_command'
+
+require_relative "helper"
+require "rubygems/commands/query_command"
module TestGemCommandsQueryCommandSetup
def setup
@@ -22,9 +23,7 @@ class TestGemCommandsQueryCommandWithInstalledGems < Gem::TestCase
include TestGemCommandsQueryCommandSetup
def test_execute
- spec_fetcher do |fetcher|
- fetcher.legacy_platform
- end
+ spec_fetcher(&:legacy_platform)
@cmd.handle_options %w[-r]
@@ -41,13 +40,11 @@ pl (1 i386-linux)
EOF
assert_equal expected, @stub_ui.output
- assert_equal '', @stub_ui.error
+ assert_equal "", @stub_ui.error
end
def test_execute_all
- spec_fetcher do |fetcher|
- fetcher.legacy_platform
- end
+ spec_fetcher(&:legacy_platform)
@cmd.handle_options %w[-r --all]
@@ -64,13 +61,11 @@ pl (1 i386-linux)
EOF
assert_equal expected, @stub_ui.output
- assert_equal '', @stub_ui.error
+ assert_equal "", @stub_ui.error
end
def test_execute_all_prerelease
- spec_fetcher do |fetcher|
- fetcher.legacy_platform
- end
+ spec_fetcher(&:legacy_platform)
@cmd.handle_options %w[-r --all --prerelease]
@@ -87,15 +82,15 @@ pl (1 i386-linux)
EOF
assert_equal expected, @stub_ui.output
- assert_equal '', @stub_ui.error
+ assert_equal "", @stub_ui.error
end
def test_execute_details
spec_fetcher do |fetcher|
- fetcher.spec 'a', 2 do |s|
- s.summary = 'This is a lot of text. ' * 4
- s.authors = ['Abraham Lincoln', 'Hirohito']
- s.homepage = 'http://a.example.com/'
+ fetcher.spec "a", 2 do |s|
+ s.summary = "This is a lot of text. " * 4
+ s.authors = ["Abraham Lincoln", "Hirohito"]
+ s.homepage = "http://a.example.com/"
end
fetcher.legacy_platform
@@ -127,13 +122,13 @@ pl (1)
EOF
assert_equal expected, @stub_ui.output
- assert_equal '', @stub_ui.error
+ assert_equal "", @stub_ui.error
end
def test_execute_details_cleans_text
spec_fetcher do |fetcher|
- fetcher.spec 'a', 2 do |s|
- s.summary = 'This is a lot of text. ' * 4
+ fetcher.spec "a", 2 do |s|
+ s.summary = "This is a lot of text. " * 4
s.authors = ["Abraham Lincoln \x01", "\x02 Hirohito"]
s.homepage = "http://a.example.com/\x03"
end
@@ -167,13 +162,13 @@ pl (1)
EOF
assert_equal expected, @stub_ui.output
- assert_equal '', @stub_ui.error
+ assert_equal "", @stub_ui.error
end
def test_execute_details_truncates_summary
spec_fetcher do |fetcher|
- fetcher.spec 'a', 2 do |s|
- s.summary = 'This is a lot of text. ' * 10_000
+ fetcher.spec "a", 2 do |s|
+ s.summary = "This is a lot of text. " * 10_000
s.authors = ["Abraham Lincoln \x01", "\x02 Hirohito"]
s.homepage = "http://a.example.com/\x03"
end
@@ -207,7 +202,7 @@ pl (1)
EOF
assert_equal expected, @stub_ui.output
- assert_equal '', @stub_ui.error
+ assert_equal "", @stub_ui.error
end
def test_execute_installed
@@ -220,7 +215,7 @@ pl (1)
end
assert_equal "true\n", @stub_ui.output
- assert_equal '', @stub_ui.error
+ assert_equal "", @stub_ui.error
end
def test_execute_installed_inverse
@@ -233,7 +228,7 @@ pl (1)
end
assert_equal "false\n", @stub_ui.output
- assert_equal '', @stub_ui.error
+ assert_equal "", @stub_ui.error
assert_equal 1, e.exit_code
end
@@ -248,7 +243,7 @@ pl (1)
end
assert_equal "true\n", @stub_ui.output
- assert_equal '', @stub_ui.error
+ assert_equal "", @stub_ui.error
end
def test_execute_installed_no_name
@@ -260,7 +255,7 @@ pl (1)
end
end
- assert_equal '', @stub_ui.output
+ assert_equal "", @stub_ui.output
assert_equal "ERROR: You must specify a gem name\n", @stub_ui.error
assert_equal 4, e.exit_code
@@ -276,7 +271,7 @@ pl (1)
end
assert_equal "false\n", @stub_ui.output
- assert_equal '', @stub_ui.error
+ assert_equal "", @stub_ui.error
assert_equal 1, e.exit_code
end
@@ -291,7 +286,7 @@ pl (1)
end
assert_equal "true\n", @stub_ui.output
- assert_equal '', @stub_ui.error
+ assert_equal "", @stub_ui.error
end
def test_execute_installed_version_not_installed
@@ -304,15 +299,13 @@ pl (1)
end
assert_equal "false\n", @stub_ui.output
- assert_equal '', @stub_ui.error
+ assert_equal "", @stub_ui.error
assert_equal 1, e.exit_code
end
def test_execute_local
- spec_fetcher do |fetcher|
- fetcher.legacy_platform
- end
+ spec_fetcher(&:legacy_platform)
@cmd.options[:domain] = :local
@@ -329,13 +322,11 @@ pl (1 i386-linux)
EOF
assert_equal expected, @stub_ui.output
- assert_equal '', @stub_ui.error
+ assert_equal "", @stub_ui.error
end
def test_execute_local_notty
- spec_fetcher do |fetcher|
- fetcher.legacy_platform
- end
+ spec_fetcher(&:legacy_platform)
@cmd.handle_options %w[]
@@ -351,13 +342,11 @@ pl (1 i386-linux)
EOF
assert_equal expected, @stub_ui.output
- assert_equal '', @stub_ui.error
+ assert_equal "", @stub_ui.error
end
def test_execute_local_quiet
- spec_fetcher do |fetcher|
- fetcher.legacy_platform
- end
+ spec_fetcher(&:legacy_platform)
@cmd.options[:domain] = :local
Gem.configuration.verbose = false
@@ -372,13 +361,11 @@ pl (1 i386-linux)
EOF
assert_equal expected, @stub_ui.output
- assert_equal '', @stub_ui.error
+ assert_equal "", @stub_ui.error
end
def test_execute_no_versions
- spec_fetcher do |fetcher|
- fetcher.legacy_platform
- end
+ spec_fetcher(&:legacy_platform)
@cmd.handle_options %w[-r --no-versions]
@@ -395,13 +382,11 @@ pl
EOF
assert_equal expected, @stub_ui.output
- assert_equal '', @stub_ui.error
+ assert_equal "", @stub_ui.error
end
def test_execute_notty
- spec_fetcher do |fetcher|
- fetcher.legacy_platform
- end
+ spec_fetcher(&:legacy_platform)
@cmd.handle_options %w[-r]
@@ -417,7 +402,7 @@ pl (1 i386-linux)
EOF
assert_equal expected, @stub_ui.output
- assert_equal '', @stub_ui.error
+ assert_equal "", @stub_ui.error
end
def test_execute_prerelease
@@ -435,13 +420,11 @@ a (3.a)
EOF
assert_equal expected, @stub_ui.output
- assert_equal '', @stub_ui.error
+ assert_equal "", @stub_ui.error
end
def test_execute_prerelease_local
- spec_fetcher do |fetcher|
- fetcher.legacy_platform
- end
+ spec_fetcher(&:legacy_platform)
@cmd.handle_options %w[-l --prerelease]
@@ -461,9 +444,7 @@ pl (1 i386-linux)
end
def test_execute_no_prerelease_local
- spec_fetcher do |fetcher|
- fetcher.legacy_platform
- end
+ spec_fetcher(&:legacy_platform)
@cmd.handle_options %w[-l --no-prerelease]
@@ -483,9 +464,7 @@ pl (1 i386-linux)
end
def test_execute_remote
- spec_fetcher do |fetcher|
- fetcher.legacy_platform
- end
+ spec_fetcher(&:legacy_platform)
@cmd.options[:domain] = :remote
@@ -502,13 +481,11 @@ pl (1 i386-linux)
EOF
assert_equal expected, @stub_ui.output
- assert_equal '', @stub_ui.error
+ assert_equal "", @stub_ui.error
end
def test_execute_remote_notty
- spec_fetcher do |fetcher|
- fetcher.legacy_platform
- end
+ spec_fetcher(&:legacy_platform)
@cmd.handle_options %w[]
@@ -524,13 +501,11 @@ pl (1 i386-linux)
EOF
assert_equal expected, @stub_ui.output
- assert_equal '', @stub_ui.error
+ assert_equal "", @stub_ui.error
end
def test_execute_remote_quiet
- spec_fetcher do |fetcher|
- fetcher.legacy_platform
- end
+ spec_fetcher(&:legacy_platform)
@cmd.options[:domain] = :remote
Gem.configuration.verbose = false
@@ -545,16 +520,16 @@ pl (1 i386-linux)
EOF
assert_equal expected, @stub_ui.output
- assert_equal '', @stub_ui.error
+ assert_equal "", @stub_ui.error
end
def test_make_entry
- a_2_name = @specs['a-2'].original_name
+ a_2_name = @specs["a-2"].original_name
@stub_fetcher.data.delete \
"#{@gem_repo}quick/Marshal.#{Gem.marshal_version}/#{a_2_name}.gemspec.rz"
- a2 = @specs['a-2']
+ a2 = @specs["a-2"]
entry_tuples = [
[Gem::NameTuple.new(a2.name, a2.version, a2.platform),
Gem.sources.first],
@@ -564,14 +539,12 @@ pl (1 i386-linux)
entry = @cmd.send :make_entry, entry_tuples, platforms
- assert_equal 'a (2)', entry
+ assert_equal "a (2)", entry
end
# Test for multiple args handling!
def test_execute_multiple_args
- spec_fetcher do |fetcher|
- fetcher.legacy_platform
- end
+ spec_fetcher(&:legacy_platform)
@cmd.handle_options %w[a pl]
@@ -579,9 +552,9 @@ pl (1 i386-linux)
@cmd.execute
end
- assert_match %r{^a }, @stub_ui.output
- assert_match %r{^pl }, @stub_ui.output
- assert_equal '', @stub_ui.error
+ assert_match(/^a /, @stub_ui.output)
+ assert_match(/^pl /, @stub_ui.output)
+ assert_equal "", @stub_ui.error
end
def test_show_gems
@@ -592,8 +565,8 @@ pl (1 i386-linux)
@cmd.send :show_gems, /a/i
end
- assert_match %r{^a }, @stub_ui.output
- refute_match %r{^pl }, @stub_ui.output
+ assert_match(/^a /, @stub_ui.output)
+ refute_match(/^pl /, @stub_ui.output)
assert_empty @stub_ui.error
end
@@ -601,9 +574,9 @@ pl (1 i386-linux)
def add_gems_to_fetcher
spec_fetcher do |fetcher|
- fetcher.spec 'a', 1
- fetcher.spec 'a', 2
- fetcher.spec 'a', '3.a'
+ fetcher.spec "a", 1
+ fetcher.spec "a", 2
+ fetcher.spec "a", "3.a"
end
end
end
@@ -613,13 +586,13 @@ class TestGemCommandsQueryCommandWithoutInstalledGems < Gem::TestCase
def test_execute_platform
spec_fetcher do |fetcher|
- fetcher.spec 'a', 1
- fetcher.spec 'a', 1 do |s|
- s.platform = 'x86-linux'
+ fetcher.spec "a", 1
+ fetcher.spec "a", 1 do |s|
+ s.platform = "x86-linux"
end
- fetcher.spec 'a', 2 do |s|
- s.platform = 'universal-darwin'
+ fetcher.spec "a", 2 do |s|
+ s.platform = "universal-darwin"
end
end
@@ -637,13 +610,13 @@ a (2 universal-darwin, 1 ruby x86-linux)
EOF
assert_equal expected, @stub_ui.output
- assert_equal '', @stub_ui.error
+ assert_equal "", @stub_ui.error
end
def test_execute_show_default_gems
- spec_fetcher {|fetcher| fetcher.spec 'a', 2 }
+ spec_fetcher {|fetcher| fetcher.spec "a", 2 }
- a1 = new_default_spec 'a', 1
+ a1 = new_default_spec "a", 1
install_default_gems a1
use_ui @stub_ui do
@@ -661,8 +634,8 @@ EOF
end
def test_execute_show_default_gems_with_platform
- a1 = new_default_spec 'a', 1
- a1.platform = 'java'
+ a1 = new_default_spec "a", 1
+ a1.platform = "java"
install_default_gems a1
use_ui @stub_ui do
@@ -681,10 +654,10 @@ EOF
def test_execute_default_details
spec_fetcher do |fetcher|
- fetcher.spec 'a', 2
+ fetcher.spec "a", 2
end
- a1 = new_default_spec 'a', 1
+ a1 = new_default_spec "a", 1
install_default_gems a1
@cmd.handle_options %w[-l -d]
@@ -711,15 +684,15 @@ a (2, 1)
def test_execute_local_details
spec_fetcher do |fetcher|
- fetcher.spec 'a', 1 do |s|
- s.platform = 'x86-linux'
+ fetcher.spec "a", 1 do |s|
+ s.platform = "x86-linux"
end
- fetcher.spec 'a', 2 do |s|
- s.summary = 'This is a lot of text. ' * 4
- s.authors = ['Abraham Lincoln', 'Hirohito']
- s.homepage = 'http://a.example.com/'
- s.platform = 'universal-darwin'
+ fetcher.spec "a", 2 do |s|
+ s.summary = "This is a lot of text. " * 4
+ s.authors = ["Abraham Lincoln", "Hirohito"]
+ s.homepage = "http://a.example.com/"
+ s.platform = "universal-darwin"
end
fetcher.legacy_platform
@@ -766,9 +739,9 @@ pl (1)
def test_execute_exact_remote
spec_fetcher do |fetcher|
- fetcher.spec 'coolgem-omg', 3
- fetcher.spec 'coolgem', '4.2.1'
- fetcher.spec 'wow_coolgem', 1
+ fetcher.spec "coolgem-omg", 3
+ fetcher.spec "coolgem", "4.2.1"
+ fetcher.spec "wow_coolgem", 1
end
@cmd.handle_options %w[--remote --exact coolgem]
@@ -789,9 +762,9 @@ coolgem (4.2.1)
def test_execute_exact_local
spec_fetcher do |fetcher|
- fetcher.spec 'coolgem-omg', 3
- fetcher.spec 'coolgem', '4.2.1'
- fetcher.spec 'wow_coolgem', 1
+ fetcher.spec "coolgem-omg", 3
+ fetcher.spec "coolgem", "4.2.1"
+ fetcher.spec "wow_coolgem", 1
end
@cmd.handle_options %w[--exact coolgem]
@@ -812,13 +785,13 @@ coolgem (4.2.1)
def test_execute_exact_multiple
spec_fetcher do |fetcher|
- fetcher.spec 'coolgem-omg', 3
- fetcher.spec 'coolgem', '4.2.1'
- fetcher.spec 'wow_coolgem', 1
+ fetcher.spec "coolgem-omg", 3
+ fetcher.spec "coolgem", "4.2.1"
+ fetcher.spec "wow_coolgem", 1
- fetcher.spec 'othergem-omg', 3
- fetcher.spec 'othergem', '1.2.3'
- fetcher.spec 'wow_othergem', 1
+ fetcher.spec "othergem-omg", 3
+ fetcher.spec "othergem", "1.2.3"
+ fetcher.spec "wow_othergem", 1
end
@cmd.handle_options %w[--exact coolgem othergem]
@@ -849,9 +822,9 @@ othergem (1.2.3)
def add_gems_to_fetcher
spec_fetcher do |fetcher|
- fetcher.download 'a', 1
- fetcher.download 'a', 2
- fetcher.download 'a', '3.a'
+ fetcher.download "a", 1
+ fetcher.download "a", 2
+ fetcher.download "a", "3.a"
end
end
end
diff --git a/test/rubygems/test_gem_commands_rebuild_command.rb b/test/rubygems/test_gem_commands_rebuild_command.rb
new file mode 100644
index 0000000000..3b7927c44e
--- /dev/null
+++ b/test/rubygems/test_gem_commands_rebuild_command.rb
@@ -0,0 +1,154 @@
+# frozen_string_literal: true
+
+require_relative "helper"
+require "rubygems/commands/build_command"
+require "rubygems/commands/rebuild_command"
+require "rubygems/package"
+
+class TestGemCommandsRebuildCommand < Gem::TestCase
+ def setup
+ super
+
+ readme_file = File.join(@tempdir, "README.md")
+
+ begin
+ umask_orig = File.umask(2)
+ File.open readme_file, "w" do |f|
+ f.write "My awesome gem"
+ end
+ ensure
+ File.umask(umask_orig)
+ end
+
+ @gem_name = "rebuild_test_gem"
+ @gem_version = "1.0.0"
+ @gem = util_spec @gem_name do |s|
+ s.version = @gem_version
+ s.license = "AGPL-3.0"
+ s.files = ["README.md"]
+ end
+ end
+
+ def util_test_build_gem(gem, args)
+ @ui = Gem::MockGemUi.new
+
+ cmd = Gem::Commands::BuildCommand.new
+
+ cmd.options[:args] = args
+ cmd.options[:build_path] = @tempdir
+ use_ui @ui do
+ cmd.execute
+ end
+ gem_file = "#{@gem_name}-#{@gem_version}.gem"
+ output = @ui.output.split "\n"
+ assert_equal " Successfully built RubyGem", output.shift
+ assert_equal " Name: #{@gem_name}", output.shift
+ assert_equal " Version: #{@gem_version}", output.shift
+ assert_equal " File: #{gem_file}", output.shift
+ assert_equal [], output
+
+ gem_file = File.join(@tempdir, gem_file)
+ assert File.exist?(gem_file)
+
+ spec = Gem::Package.new(gem_file).spec
+
+ assert_equal @gem_name, spec.name
+ assert_equal "this is a summary", spec.summary
+ gem_file
+ end
+
+ def util_test_rebuild_gem(gem, args, original_gem_file, gemspec_file, timestamp)
+ @ui = Gem::MockGemUi.new
+
+ cmd = Gem::Commands::RebuildCommand.new
+
+ cmd.options[:args] = args
+ cmd.options[:original_gem_file] = original_gem_file
+ cmd.options[:build_path] = @tempdir
+ cmd.options[:gemspec_file] = gemspec_file
+ use_ui @ui do
+ cmd.execute
+ end
+ gem_file = "#{@gem_name}-#{@gem_version}.gem"
+ output = @ui.output.split "\n"
+
+ assert_equal " Successfully built RubyGem", output.shift
+ assert_equal " Name: #{@gem_name}", output.shift
+ assert_equal " Version: #{@gem_version}", output.shift
+ assert_equal " File: #{gem_file}", output.shift
+ assert_empty output.shift
+ assert_match(/^Built at: .+ \(#{timestamp}\)/, output.shift)
+ original_line = output.shift
+ original = original_line.split(" ")[-1]
+ assert_match(/^Original build saved to: /, original_line)
+ reproduced_line = output.shift
+ reproduced = reproduced_line.split(" ")[-1]
+ assert_match(/^Reproduced build saved to: /, reproduced_line)
+ assert_equal "Working directory: #{@tempdir}", output.shift
+ assert_equal "", output.shift
+ assert_equal "Hash comparison:", output.shift
+ output.shift # " #{old_hash}\t#{old_file}"
+ output.shift # " #{new_hash}\t#{new_file}"
+ assert_empty output.shift
+ assert_equal "SUCCESS - original and rebuild hashes matched", output.shift
+ assert_equal [], output
+
+ assert File.exist?(original)
+ assert File.exist?(reproduced)
+
+ old_spec = Gem::Package.new(original).spec
+ new_spec = Gem::Package.new(reproduced).spec
+
+ assert_equal @gem_name, old_spec.name
+ assert_equal "this is a summary", old_spec.summary
+
+ assert_equal old_spec.name, new_spec.name
+ assert_equal old_spec.summary, new_spec.summary
+
+ [reproduced, original]
+ end
+
+ def test_build_is_reproducible
+ # Back up SOURCE_DATE_EPOCH to restore later.
+ epoch = ENV["SOURCE_DATE_EPOCH"]
+
+ gemspec_file = File.join(@tempdir, @gem.spec_name)
+
+ # Initial Build
+
+ # Set SOURCE_DATE_EPOCH to 2001-02-03 04:05:06 -0500.
+ ENV["SOURCE_DATE_EPOCH"] = timestamp = Time.new(2001, 2, 3, 4, 5, 6).to_i.to_s
+ File.write(gemspec_file, @gem.to_ruby)
+ gem_file = util_test_build_gem @gem, [gemspec_file]
+
+ build_contents = File.read(gem_file)
+
+ gem_file_dir = File.dirname(gem_file)
+ gem_file_name = File.basename(gem_file)
+ original_gem_file = File.join(gem_file_dir, "original-" + gem_file_name)
+ File.rename(gem_file, original_gem_file)
+
+ # Rebuild
+
+ # Set SOURCE_DATE_EPOCH to a different value, meaning we are
+ # also testing that `gem rebuild` overrides the value.
+ ENV["SOURCE_DATE_EPOCH"] = Time.new(2007, 8, 9, 10, 11, 12).to_s
+
+ rebuild_gem_file, saved_gem_file =
+ util_test_rebuild_gem(@gem, [@gem_name, @gem_version], original_gem_file, gemspec_file, timestamp)
+
+ rebuild_contents = File.read(rebuild_gem_file)
+
+ assert_equal build_contents, rebuild_contents
+ ensure
+ ENV["SOURCE_DATE_EPOCH"] = epoch
+ if rebuild_gem_file
+ File.unlink(rebuild_gem_file)
+ dir = File.dirname(rebuild_gem_file)
+ Dir.rmdir(dir)
+ File.unlink(saved_gem_file)
+ Dir.rmdir(File.dirname(saved_gem_file))
+ Dir.rmdir(File.dirname(dir))
+ end
+ end
+end
diff --git a/test/rubygems/test_gem_commands_search_command.rb b/test/rubygems/test_gem_commands_search_command.rb
index 6397dbd4d4..47aefa0cf7 100644
--- a/test/rubygems/test_gem_commands_search_command.rb
+++ b/test/rubygems/test_gem_commands_search_command.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/commands/search_command'
+
+require_relative "helper"
+require "rubygems/commands/search_command"
class TestGemCommandsSearchCommand < Gem::TestCase
def setup
diff --git a/test/rubygems/test_gem_commands_server_command.rb b/test/rubygems/test_gem_commands_server_command.rb
index 09cec63c15..cabb7cf49d 100644
--- a/test/rubygems/test_gem_commands_server_command.rb
+++ b/test/rubygems/test_gem_commands_server_command.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/commands/server_command'
+
+require_relative "helper"
+require "rubygems/commands/server_command"
class TestGemCommandsServerCommand < Gem::TestCase
def setup
@@ -9,53 +10,11 @@ class TestGemCommandsServerCommand < Gem::TestCase
@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 [], @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
-
- def test_handle_options_gemdir
- @cmd.send :handle_options, %w[--dir a --dir b]
-
- assert_equal [File.expand_path('a'), File.expand_path('b')],
- @cmd.options[:gemdir]
- end
-
- def test_handle_options_port
- @cmd.send :handle_options, %w[-p 0]
- assert_equal 0, @cmd.options[:port]
-
- @cmd.send :handle_options, %w[-p 65535]
- assert_equal 65535, @cmd.options[:port]
-
- begin
- @cmd.send :handle_options, %w[-p discard]
- assert_equal 9, @cmd.options[:port]
- rescue OptionParser::InvalidArgument
- # for container environment on GitHub Actions
- end
-
- e = assert_raise OptionParser::InvalidArgument do
- @cmd.send :handle_options, %w[-p nonexistent]
- end
-
- assert_equal 'invalid argument: -p nonexistent: no such named service',
- e.message
-
- e = assert_raise OptionParser::InvalidArgument do
- @cmd.send :handle_options, %w[-p 65536]
+ def test_execute
+ use_ui @ui do
+ @cmd.execute
end
- assert_equal 'invalid argument: -p 65536: not a port number',
- e.message
+ assert_match(/Install the rubygems-server/i, @ui.error)
end
end
diff --git a/test/rubygems/test_gem_commands_setup_command.rb b/test/rubygems/test_gem_commands_setup_command.rb
index 3aa6bfa2fe..8eedb6c03a 100644
--- a/test/rubygems/test_gem_commands_setup_command.rb
+++ b/test/rubygems/test_gem_commands_setup_command.rb
@@ -1,25 +1,24 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/commands/setup_command'
+require_relative "helper"
+require "rubygems/commands/setup_command"
class TestGemCommandsSetupCommand < Gem::TestCase
- bundler_gemspec = File.expand_path("../../../bundler/lib/bundler/version.rb", __FILE__)
+ bundler_gemspec = File.expand_path("../../bundler/lib/bundler/version.rb", __dir__)
if File.exist?(bundler_gemspec)
BUNDLER_VERS = File.read(bundler_gemspec).match(/VERSION = "(#{Gem::Version::VERSION_PATTERN})"/)[1]
else
- BUNDLER_VERS = "2.0.1".freeze
+ BUNDLER_VERS = "2.0.1"
end
def setup
super
- @install_dir = File.join @tempdir, 'install'
@cmd = Gem::Commands::SetupCommand.new
- @cmd.options[:prefix] = @install_dir
+ @cmd.options[:document] = []
filelist = %w[
- bin/gem
+ exe/gem
lib/rubygems.rb
lib/rubygems/requirement.rb
lib/rubygems/ssl_certs/rubygems.org/foo.pem
@@ -32,23 +31,20 @@ class TestGemCommandsSetupCommand < Gem::TestCase
bundler/lib/bundler/man/gemfile.5
bundler/lib/bundler/man/gemfile.5.ronn
bundler/lib/bundler/templates/.circleci/config.yml
- bundler/lib/bundler/templates/.travis.yml
]
create_dummy_files(filelist)
- gemspec = Gem::Specification.new
- gemspec.author = "Us"
- gemspec.name = "bundler"
- gemspec.version = BUNDLER_VERS
- gemspec.bindir = "exe"
- gemspec.executables = ["bundle", "bundler"]
+ gemspec = util_spec "bundler", BUNDLER_VERS do |s|
+ s.bindir = "exe"
+ s.executables = ["bundle", "bundler"]
+ end
- File.open 'bundler/bundler.gemspec', 'w' do |io|
+ File.open "bundler/bundler.gemspec", "w" do |io|
io.puts gemspec.to_ruby
end
- File.open(File.join(Gem.default_specifications_dir, "bundler-1.15.4.gemspec"), 'w') do |io|
+ File.open(File.join(Gem.default_specifications_dir, "bundler-1.15.4.gemspec"), "w") do |io|
gemspec.version = "1.15.4"
io.puts gemspec.to_ruby
end
@@ -56,31 +52,29 @@ class TestGemCommandsSetupCommand < Gem::TestCase
spec_fetcher do |fetcher|
fetcher.download "bundler", "1.15.4"
- fetcher.gem "bundler", BUNDLER_VERS
+ fetcher.gem "bundler", bundler_version
fetcher.gem "bundler-audit", "1.0.0"
end
end
def test_execute_regenerate_binstubs
- gem_bin_path = gem_install 'a'
+ gem_bin_path = gem_install "a"
write_file gem_bin_path do |io|
- io.puts 'I changed it!'
+ io.puts "I changed it!"
end
- @cmd.options[:document] = []
@cmd.execute
- assert_match %r{\A#!}, File.read(gem_bin_path)
+ assert_match(/\A#!/, File.read(gem_bin_path))
end
def test_execute_no_regenerate_binstubs
- gem_bin_path = gem_install 'a'
+ gem_bin_path = gem_install "a"
write_file gem_bin_path do |io|
- io.puts 'I changed it!'
+ io.puts "I changed it!"
end
- @cmd.options[:document] = []
@cmd.options[:regenerate_binstubs] = false
@cmd.execute
@@ -88,24 +82,22 @@ class TestGemCommandsSetupCommand < Gem::TestCase
end
def test_execute_regenerate_plugins
- gem_plugin_path = gem_install_with_plugin 'a'
+ gem_plugin_path = gem_install_with_plugin "a"
write_file gem_plugin_path do |io|
- io.puts 'I changed it!'
+ io.puts "I changed it!"
end
- @cmd.options[:document] = []
@cmd.execute
- assert_match %r{\Arequire}, File.read(gem_plugin_path)
+ assert_match(/\Arequire/, File.read(gem_plugin_path))
end
def test_execute_no_regenerate_plugins
- gem_plugin_path = gem_install_with_plugin 'a'
+ gem_plugin_path = gem_install_with_plugin "a"
write_file gem_plugin_path do |io|
- io.puts 'I changed it!'
+ io.puts "I changed it!"
end
- @cmd.options[:document] = []
@cmd.options[:regenerate_plugins] = false
@cmd.execute
@@ -113,20 +105,17 @@ class TestGemCommandsSetupCommand < Gem::TestCase
end
def test_execute_regenerate_plugins_creates_plugins_dir_if_not_there
- gem_plugin_path = gem_install_with_plugin 'a'
+ gem_plugin_path = gem_install_with_plugin "a"
# Simulate gem installed with an older rubygems without a plugins layout
FileUtils.rm_rf Gem.plugindir
- @cmd.options[:document] = []
@cmd.execute
- assert_match %r{\Arequire}, File.read(gem_plugin_path)
+ assert_match(/\Arequire/, File.read(gem_plugin_path))
end
def test_execute_informs_about_installed_executables
- @cmd.options[:document] = []
-
use_ui @ui do
@cmd.execute
end
@@ -140,53 +129,80 @@ class TestGemCommandsSetupCommand < Gem::TestCase
end
def test_env_shebang_flag
- gem_bin_path = gem_install 'a'
+ gem_bin_path = gem_install "a"
write_file gem_bin_path do |io|
- io.puts 'I changed it!'
+ io.puts "I changed it!"
end
- @cmd.options[:document] = []
@cmd.options[:env_shebang] = true
@cmd.execute
- ruby_exec = sprintf Gem.default_exec_format, 'ruby'
+ ruby_exec = format Gem.default_exec_format, "ruby"
- bin_env = win_platform? ? "" : %w[/usr/bin/env /bin/env].find {|f| File.executable?(f) } + " "
- assert_match %r{\A#!\s*#{bin_env}#{ruby_exec}}, File.read(default_gem_bin_path)
- assert_match %r{\A#!\s*#{bin_env}#{ruby_exec}}, File.read(default_bundle_bin_path)
- assert_match %r{\A#!\s*#{bin_env}#{ruby_exec}}, File.read(default_bundler_bin_path)
- assert_match %r{\A#!\s*#{bin_env}#{ruby_exec}}, File.read(gem_bin_path)
+ bin_env = Gem.win_platform? ? "" : %w[/usr/bin/env /bin/env].find {|f| File.executable?(f) } + " "
+ assert_match(/\A#!\s*#{bin_env}#{ruby_exec}/, File.read(default_gem_bin_path))
+ assert_match(/\A#!\s*#{bin_env}#{ruby_exec}/, File.read(default_bundle_bin_path))
+ assert_match(/\A#!\s*#{bin_env}#{ruby_exec}/, File.read(default_bundler_bin_path))
+ assert_match(/\A#!\s*#{bin_env}#{ruby_exec}/, File.read(gem_bin_path))
+ end
+
+ def test_destdir_flag_does_not_try_to_write_to_the_default_gem_home
+ FileUtils.chmod "-w", File.join(@gemhome, "plugins")
+
+ destdir = File.join(@tempdir, "foo")
+
+ @cmd.options[:destdir] = destdir
+ @cmd.execute
+
+ bundler_spec.executables.each do |e|
+ assert_path_exist prepend_destdir(destdir, File.join(@gemhome, "gems", bundler_spec.full_name, bundler_spec.bindir, e))
+ end
+ end
+
+ def test_destdir_flag_regenerates_binstubs
+ # install to destdir
+ destdir = File.join(@tempdir, "foo")
+ gem_bin_path = gem_install "destdir-only-gem", install_dir: destdir
+
+ # change binstub manually
+ write_file gem_bin_path do |io|
+ io.puts "I changed it!"
+ end
+
+ @cmd.options[:destdir] = destdir
+ @cmd.options[:prefix] = "/"
+ @cmd.execute
+
+ assert_match(/\A#!/, File.read(gem_bin_path))
end
def test_files_in
assert_equal %w[rubygems.rb rubygems/requirement.rb rubygems/ssl_certs/rubygems.org/foo.pem],
- @cmd.files_in('lib').sort
+ @cmd.files_in("lib").sort
end
def test_install_lib
@cmd.extend FileUtils
- Dir.mktmpdir 'lib' do |dir|
+ Dir.mktmpdir "lib" do |dir|
@cmd.install_lib dir
- assert_path_exist File.join(dir, 'rubygems.rb')
- assert_path_exist File.join(dir, 'rubygems/ssl_certs/rubygems.org/foo.pem')
+ assert_path_exist File.join(dir, "rubygems.rb")
+ assert_path_exist File.join(dir, "rubygems/ssl_certs/rubygems.org/foo.pem")
- assert_path_exist File.join(dir, 'bundler.rb')
- assert_path_exist File.join(dir, 'bundler/b.rb')
+ assert_path_exist File.join(dir, "bundler.rb")
+ assert_path_exist File.join(dir, "bundler/b.rb")
- assert_path_exist File.join(dir, 'bundler/templates/.circleci/config.yml')
- assert_path_exist File.join(dir, 'bundler/templates/.travis.yml')
+ assert_path_exist File.join(dir, "bundler/templates/.circleci/config.yml")
end
end
def test_install_default_bundler_gem
@cmd.extend FileUtils
- bin_dir = File.join(@gemhome, 'bin')
+ bin_dir = File.join(@gemhome, "bin")
@cmd.install_default_bundler_gem bin_dir
- bundler_spec = Gem::Specification.load("bundler/bundler.gemspec")
default_spec_path = File.join(Gem.default_specifications_dir, "#{bundler_spec.full_name}.gemspec")
spec = Gem::Specification.load(default_spec_path)
@@ -198,72 +214,126 @@ class TestGemCommandsSetupCommand < Gem::TestCase
assert_path_exist File.join bin_dir, e
end
- default_dir = Gem.default_specifications_dir
-
# expect to remove other versions of bundler gemspecs on default specification directory.
- assert_path_not_exist File.join(default_dir, "bundler-1.15.4.gemspec")
- assert_path_exist File.join(default_dir, "bundler-#{BUNDLER_VERS}.gemspec")
+ assert_path_not_exist previous_bundler_specification_path
+ assert_path_exist new_bundler_specification_path
# expect to not remove bundler-* gemspecs.
assert_path_exist File.join(Gem.dir, "specifications", "bundler-audit-1.0.0.gemspec")
# expect to remove normal gem that was same version. because it's promoted default gems.
- assert_path_not_exist File.join(Gem.dir, "specifications", "bundler-#{BUNDLER_VERS}.gemspec")
+ assert_path_not_exist File.join(Gem.dir, "specifications", "bundler-#{bundler_version}.gemspec")
- assert_path_exist "#{Gem.dir}/gems/bundler-#{BUNDLER_VERS}"
+ assert_path_exist "#{Gem.dir}/gems/bundler-#{bundler_version}"
assert_path_exist "#{Gem.dir}/gems/bundler-1.15.4"
assert_path_exist "#{Gem.dir}/gems/bundler-audit-1.0.0"
end
+ def test_install_default_bundler_gem_with_default_gems_not_installed_at_default_dir
+ @cmd.extend FileUtils
+
+ gemhome2 = File.join(@tempdir, "gemhome2")
+ Gem.instance_variable_set(:@default_dir, gemhome2)
+
+ FileUtils.mkdir_p gemhome2
+ bin_dir = File.join(gemhome2, "bin")
+
+ @cmd.install_default_bundler_gem bin_dir
+
+ # expect to remove other versions of bundler gemspecs on default specification directory.
+ assert_path_not_exist previous_bundler_specification_path
+ assert_path_exist new_bundler_specification_path
+ end
+
def test_install_default_bundler_gem_with_force_flag
@cmd.extend FileUtils
- bin_dir = File.join(@gemhome, 'bin')
- bundle_bin = File.join(bin_dir, 'bundle')
+ bin_dir = File.join(@gemhome, "bin")
+ bundle_bin = File.join(bin_dir, "bundle")
write_file bundle_bin do |f|
- f.puts '#!/usr/bin/ruby'
- f.puts ''
+ f.puts "#!/usr/bin/ruby"
+ f.puts ""
f.puts 'echo "hello"'
end
- bindir(bin_dir) do
- @cmd.options[:force] = true
+ @cmd.options[:force] = true
- @cmd.install_default_bundler_gem bin_dir
-
- bundler_spec = Gem::Specification.load("bundler/bundler.gemspec")
- default_spec_path = File.join(Gem.default_specifications_dir, "#{bundler_spec.full_name}.gemspec")
- spec = Gem::Specification.load(default_spec_path)
+ @cmd.install_default_bundler_gem bin_dir
- spec.executables.each do |e|
- if Gem.win_platform?
- assert_path_exist File.join(bin_dir, "#{e}.bat")
- end
+ default_spec_path = File.join(Gem.default_specifications_dir, "#{bundler_spec.full_name}.gemspec")
+ spec = Gem::Specification.load(default_spec_path)
- assert_path_exist File.join bin_dir, e
+ spec.executables.each do |e|
+ if Gem.win_platform?
+ assert_path_exist File.join(bin_dir, "#{e}.bat")
end
+
+ assert_path_exist File.join bin_dir, e
+ end
+ end
+
+ def test_install_default_bundler_gem_with_destdir_flag
+ @cmd.extend FileUtils
+
+ FileUtils.chmod "-w", @gemhome
+
+ destdir = File.join(@tempdir, "foo")
+ bin_dir = File.join(destdir, "bin")
+
+ @cmd.options[:destdir] = destdir
+
+ @cmd.install_default_bundler_gem bin_dir
+
+ # leaves other versions of bundler gemspecs on default specification directory.
+ assert_path_exist previous_bundler_specification_path
+ assert_path_not_exist new_bundler_specification_path
+
+ # installs the updated bundler gemspec to destdir
+ assert_path_not_exist prepend_destdir(destdir, previous_bundler_specification_path)
+ assert_path_exist prepend_destdir(destdir, new_bundler_specification_path)
+
+ bundler_spec.executables.each do |e|
+ assert_path_exist prepend_destdir(destdir, File.join(@gemhome, "gems", bundler_spec.full_name, bundler_spec.bindir, e))
+ end
+ ensure
+ FileUtils.chmod "+w", @gemhome
+ end
+
+ def test_install_default_bundler_gem_with_destdir_and_prefix_flags
+ @cmd.extend FileUtils
+
+ destdir = File.join(@tempdir, "foo")
+ bin_dir = File.join(destdir, "bin")
+
+ @cmd.options[:destdir] = destdir
+ @cmd.options[:prefix] = "/"
+
+ @cmd.install_default_bundler_gem bin_dir
+
+ bundler_spec.executables.each do |e|
+ assert_path_exist File.join destdir, "gems", bundler_spec.full_name, bundler_spec.bindir, e
end
end
def test_remove_old_lib_files
- lib = File.join @install_dir, 'lib'
- lib_rubygems = File.join lib, 'rubygems'
- lib_bundler = File.join lib, 'bundler'
- lib_rubygems_defaults = File.join lib_rubygems, 'defaults'
- lib_bundler_templates = File.join lib_bundler, 'templates'
+ lib = RbConfig::CONFIG["sitelibdir"]
+ lib_rubygems = File.join lib, "rubygems"
+ lib_bundler = File.join lib, "bundler"
+ lib_rubygems_defaults = File.join lib_rubygems, "defaults"
+ lib_bundler_templates = File.join lib_bundler, "templates"
- securerandom_rb = File.join lib, 'securerandom.rb'
+ securerandom_rb = File.join lib, "securerandom.rb"
- engine_defaults_rb = File.join lib_rubygems_defaults, 'jruby.rb'
- os_defaults_rb = File.join lib_rubygems_defaults, 'operating_system.rb'
+ engine_defaults_rb = File.join lib_rubygems_defaults, "jruby.rb"
+ os_defaults_rb = File.join lib_rubygems_defaults, "operating_system.rb"
- old_gauntlet_rubygems_rb = File.join lib, 'gauntlet_rubygems.rb'
+ old_gauntlet_rubygems_rb = File.join lib, "gauntlet_rubygems.rb"
- old_builder_rb = File.join lib_rubygems, 'builder.rb'
- old_format_rb = File.join lib_rubygems, 'format.rb'
- old_bundler_c_rb = File.join lib_bundler, 'c.rb'
- old_bundler_ci = File.join lib_bundler_templates, '.lecacy_ci', 'config.yml'
+ old_builder_rb = File.join lib_rubygems, "builder.rb"
+ old_format_rb = File.join lib_rubygems, "format.rb"
+ old_bundler_c_rb = File.join lib_bundler, "c.rb"
+ old_bundler_ci = File.join lib_bundler_templates, ".lecacy_ci", "config.yml"
files_that_go = [old_gauntlet_rubygems_rb, old_builder_rb, old_format_rb, old_bundler_c_rb, old_bundler_ci]
files_that_stay = [securerandom_rb, engine_defaults_rb, os_defaults_rb]
@@ -278,15 +348,15 @@ class TestGemCommandsSetupCommand < Gem::TestCase
end
def test_remove_old_man_files
- man = File.join @install_dir, 'man'
+ man = File.join RbConfig::CONFIG["mandir"], "man"
- ruby_1 = File.join man, 'man1', 'ruby.1'
- bundle_b_1 = File.join man, 'man1', 'bundle-b.1'
- bundle_b_1_ronn = File.join man, 'man1', 'bundle-b.1.ronn'
- bundle_b_1_txt = File.join man, 'man1', 'bundle-b.1.txt'
- gemfile_5 = File.join man, 'man5', 'gemfile.5'
- gemfile_5_ronn = File.join man, 'man5', 'gemfile.5.ronn'
- gemfile_5_txt = File.join man, 'man5', 'gemfile.5.txt'
+ ruby_1 = File.join man, "man1", "ruby.1"
+ bundle_b_1 = File.join man, "man1", "bundle-b.1"
+ bundle_b_1_ronn = File.join man, "man1", "bundle-b.1.ronn"
+ bundle_b_1_txt = File.join man, "man1", "bundle-b.1.txt"
+ gemfile_5 = File.join man, "man5", "gemfile.5"
+ gemfile_5_ronn = File.join man, "man5", "gemfile.5.ronn"
+ gemfile_5_txt = File.join man, "man5", "gemfile.5.txt"
files_that_go = [bundle_b_1, bundle_b_1_txt, bundle_b_1_ronn, gemfile_5, gemfile_5_txt, gemfile_5_ronn]
files_that_stay = [ruby_1]
@@ -304,9 +374,9 @@ class TestGemCommandsSetupCommand < Gem::TestCase
@default_external = @ui.outs.external_encoding
@ui.outs.set_encoding Encoding::US_ASCII
- @cmd.options[:previous_version] = Gem::Version.new '2.0.2'
+ @cmd.options[:previous_version] = Gem::Version.new "2.0.2"
- File.open 'CHANGELOG.md', 'w' do |io|
+ File.open "CHANGELOG.md", "w" do |io|
io.puts <<-HISTORY_TXT
# #{Gem::VERSION} / 2013-03-26
@@ -353,30 +423,30 @@ class TestGemCommandsSetupCommand < Gem::TestCase
list.each do |file|
FileUtils.mkdir_p File.dirname(file)
- File.open file, 'w' do |io|
+ File.open file, "w" do |io|
io.puts "# #{File.basename(file)}"
end
end
end
- def gem_install(name)
+ def gem_install(name, **options)
gem = util_spec name do |s|
s.executables = [name]
s.files = %W[bin/#{name}]
end
- write_file File.join @tempdir, 'bin', name do |f|
- f.puts '#!/usr/bin/ruby'
+ write_file File.join @tempdir, "bin", name do |f|
+ f.puts "#!/usr/bin/ruby"
end
- install_gem gem
- File.join @gemhome, 'bin', name
+ install_gem gem, **options
+ File.join options[:install_dir] || @gemhome, "bin", name
end
def gem_install_with_plugin(name)
gem = util_spec name do |s|
s.files = %W[lib/rubygems_plugin.rb]
end
- write_file File.join @tempdir, 'lib', 'rubygems_plugin.rb' do |f|
- f.puts "require '#{gem.plugins.first}'"
+ write_file File.join @tempdir, "lib", "rubygems_plugin.rb" do |f|
+ f.puts "# do nothing"
end
install_gem gem
@@ -384,14 +454,34 @@ class TestGemCommandsSetupCommand < Gem::TestCase
end
def default_gem_bin_path
- File.join @install_dir, 'bin', 'gem'
+ File.join RbConfig::CONFIG["bindir"], "gem"
end
def default_bundle_bin_path
- File.join @install_dir, 'bin', 'bundle'
+ File.join RbConfig::CONFIG["bindir"], "bundle"
end
def default_bundler_bin_path
- File.join @install_dir, 'bin', 'bundler'
+ File.join RbConfig::CONFIG["bindir"], "bundler"
+ end
+
+ def previous_bundler_specification_path
+ File.join(Gem.default_specifications_dir, "bundler-1.15.4.gemspec")
+ end
+
+ def new_bundler_specification_path
+ File.join(Gem.default_specifications_dir, "bundler-#{bundler_version}.gemspec")
+ end
+
+ def bundler_spec
+ Gem::Specification.load("bundler/bundler.gemspec")
+ end
+
+ def bundler_version
+ bundler_spec.version
+ end
+
+ def prepend_destdir(destdir, path)
+ File.join(destdir, path.gsub(/^[a-zA-Z]:/, ""))
end
end unless Gem.java_platform?
diff --git a/test/rubygems/test_gem_commands_signin_command.rb b/test/rubygems/test_gem_commands_signin_command.rb
index eaf32886b3..29e5edceb7 100644
--- a/test/rubygems/test_gem_commands_signin_command.rb
+++ b/test/rubygems/test_gem_commands_signin_command.rb
@@ -1,7 +1,8 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/commands/signin_command'
-require 'rubygems/installer'
+
+require_relative "helper"
+require "rubygems/commands/signin_command"
+require "rubygems/installer"
class TestGemCommandsSigninCommand < Gem::TestCase
def setup
@@ -23,18 +24,18 @@ class TestGemCommandsSigninCommand < Gem::TestCase
def test_execute_when_not_already_signed_in
sign_in_ui = util_capture { @cmd.execute }
- assert_match %r{Signed in.}, sign_in_ui.output
+ assert_match(/Signed in./, sign_in_ui.output)
end
def test_execute_when_not_already_signed_in_and_not_preexisting_credentials_folder
FileUtils.rm Gem.configuration.credentials_path
sign_in_ui = util_capture { @cmd.execute }
- assert_match %r{Signed in.}, sign_in_ui.output
+ assert_match(/Signed in./, sign_in_ui.output)
end
def test_execute_when_already_signed_in_with_same_host
- host = 'http://some-gemcutter-compatible-host.org'
+ host = "http://some-gemcutter-compatible-host.org"
util_capture(nil, host) { @cmd.execute }
old_credentials = load_yaml_file Gem.configuration.credentials_path
@@ -46,10 +47,10 @@ class TestGemCommandsSigninCommand < Gem::TestCase
end
def test_execute_when_already_signed_in_with_different_host
- api_key = 'a5fdbb6ba150cbb83aad2bb2fede64cf04045xxxx'
+ api_key = "a5fdbb6ba150cbb83aad2bb2fede64cf04045xxxx"
util_capture(nil, nil, api_key) { @cmd.execute }
- host = 'http://some-gemcutter-compatible-host.org'
+ host = "http://some-gemcutter-compatible-host.org"
util_capture(nil, host, api_key) { @cmd.execute }
credentials = load_yaml_file Gem.configuration.credentials_path
@@ -60,66 +61,243 @@ class TestGemCommandsSigninCommand < Gem::TestCase
end
def test_execute_with_host_supplied
- host = 'http://some-gemcutter-compatible-host.org'
+ host = "http://some-gemcutter-compatible-host.org"
sign_in_ui = util_capture(nil, host) { @cmd.execute }
- assert_match %r{Enter your #{host} credentials.}, sign_in_ui.output
- assert_match %r{Signed in.}, sign_in_ui.output
+ assert_match(/Enter your #{host} credentials./, sign_in_ui.output)
+ assert_match(/Signed in./, sign_in_ui.output)
- api_key = 'a5fdbb6ba150cbb83aad2bb2fede64cf040453903'
+ api_key = "a5fdbb6ba150cbb83aad2bb2fede64cf040453903"
credentials = load_yaml_file Gem.configuration.credentials_path
assert_equal api_key, credentials[host]
end
+ def test_execute_with_host_permanent_redirect
+ host = "http://rubygems.example/"
+ ENV["RUBYGEMS_HOST"] = host
+ path = "/api/v1/api_key"
+ redirected_uri = "http://rubygems.example#{path}"
+ fetcher = Gem::FakeFetcher.new
+ fetcher.data["#{host}#{path}"] = HTTPResponseFactory.create(
+ body: "",
+ code: "308",
+ msg: "Permanent Redirect",
+ headers: { "location" => redirected_uri }
+ )
+ Gem::RemoteFetcher.fetcher = fetcher
+ ui = Gem::MockGemUi.new("you@example.com\nsecret\n\n\n")
+
+ assert_raise Gem::MockGemUi::TermError do
+ use_ui ui do
+ @cmd.execute
+ end
+ end
+
+ response = "The request has redirected permanently to #{redirected_uri}. Please check your defined push host URL."
+ assert_match response, ui.output
+ end
+
def test_execute_with_valid_creds_set_for_default_host
util_capture { @cmd.execute }
- api_key = 'a5fdbb6ba150cbb83aad2bb2fede64cf040453903'
+ api_key = "a5fdbb6ba150cbb83aad2bb2fede64cf040453903"
credentials = load_yaml_file Gem.configuration.credentials_path
assert_equal api_key, credentials[:rubygems_api_key]
end
- def test_excute_with_key_name_and_scope
- email = 'you@example.com'
- password = 'secret'
- api_key = '1234'
+ def test_execute_with_key_name_default_scope
+ email = "you@example.com"
+ password = "secret"
+ api_key = "1234abcd"
+ fetcher = Gem::RemoteFetcher.fetcher
+
+ key_name_ui = Gem::MockGemUi.new "#{email}\n#{password}\ntest-key\n\n"
+ util_capture(key_name_ui, nil, api_key, fetcher) { @cmd.execute }
+
+ user = ENV["USER"] || ENV["USERNAME"]
+
+ assert_match "API Key name [#{Socket.gethostname}-#{user}", key_name_ui.output
+ assert_match "The default access scope is:", key_name_ui.output
+ assert_match "index_rubygems: y", key_name_ui.output
+ assert_match "Do you want to customise scopes? [yN]", key_name_ui.output
+ assert_equal "name=test-key&index_rubygems=true", fetcher.last_request.body
+
+ credentials = load_yaml_file Gem.configuration.credentials_path
+ assert_equal api_key, credentials[:rubygems_api_key]
+ end
+
+ def test_execute_with_key_name_and_custom_scope
+ email = "you@example.com"
+ password = "secret"
+ api_key = "1234abcd"
fetcher = Gem::RemoteFetcher.fetcher
- key_name_ui = Gem::MockGemUi.new "#{email}\n#{password}\ntest-key\n\ny\n\n\n\n\n\n"
+ key_name_ui = Gem::MockGemUi.new "#{email}\n#{password}\ntest-key\ny\n\n\ny\n\n\n\n\n\n\n"
util_capture(key_name_ui, nil, api_key, fetcher) { @cmd.execute }
user = ENV["USER"] || ENV["USERNAME"]
assert_match "API Key name [#{Socket.gethostname}-#{user}", key_name_ui.output
- assert_match "index_rubygems [y/N]", key_name_ui.output
- assert_match "push_rubygem [y/N]", key_name_ui.output
- assert_match "yank_rubygem [y/N]", key_name_ui.output
- assert_match "add_owner [y/N]", key_name_ui.output
- assert_match "remove_owner [y/N]", key_name_ui.output
- assert_match "access_webhooks [y/N]", key_name_ui.output
- assert_match "show_dashboard [y/N]", key_name_ui.output
+ assert_match "The default access scope is:", key_name_ui.output
+ assert_match "Do you want to customise scopes? [yN]", key_name_ui.output
+ assert_match "show_dashboard (exclusive scope, answering yes will not prompt for other scopes) [yN]", key_name_ui.output
+ assert_match "index_rubygems [yN]", key_name_ui.output
+ assert_match "push_rubygem [yN]", key_name_ui.output
+ assert_match "yank_rubygem [yN]", key_name_ui.output
+ assert_match "add_owner [yN]", key_name_ui.output
+ assert_match "remove_owner [yN]", key_name_ui.output
+ assert_match "access_webhooks [yN]", key_name_ui.output
assert_equal "name=test-key&push_rubygem=true", fetcher.last_request.body
credentials = load_yaml_file Gem.configuration.credentials_path
assert_equal api_key, credentials[:rubygems_api_key]
end
+ def test_execute_with_key_name_and_exclusive_scope
+ email = "you@example.com"
+ password = "secret"
+ api_key = "1234abcd"
+ fetcher = Gem::RemoteFetcher.fetcher
+
+ key_name_ui = Gem::MockGemUi.new "#{email}\n#{password}\ntest-key\ny\ny\n"
+ util_capture(key_name_ui, nil, api_key, fetcher) { @cmd.execute }
+
+ user = ENV["USER"] || ENV["USERNAME"]
+
+ assert_match "API Key name [#{Socket.gethostname}-#{user}", key_name_ui.output
+ assert_match "The default access scope is:", key_name_ui.output
+ assert_match "index_rubygems: y", key_name_ui.output
+ assert_match "Do you want to customise scopes? [yN]", key_name_ui.output
+ assert_match "show_dashboard (exclusive scope, answering yes will not prompt for other scopes) [yN]", key_name_ui.output
+ assert_equal "name=test-key&show_dashboard=true", fetcher.last_request.body
+
+ credentials = load_yaml_file Gem.configuration.credentials_path
+ assert_equal api_key, credentials[:rubygems_api_key]
+ end
+
+ def test_execute_with_key_name_custom_scope_and_mfa_level_of_ui_only
+ email = "you@example.com"
+ password = "secret"
+ api_key = "1234abcd"
+ fetcher = Gem::RemoteFetcher.fetcher
+ mfa_level = "ui_only"
+
+ key_name_ui = Gem::MockGemUi.new "#{email}\n#{password}\ntest-key\ny\n\n\ny\n\n\n\n\n\n\ny"
+ util_capture(key_name_ui, nil, api_key, fetcher, mfa_level) { @cmd.execute }
+
+ user = ENV["USER"] || ENV["USERNAME"]
+
+ assert_match "API Key name [#{Socket.gethostname}-#{user}", key_name_ui.output
+ assert_match "The default access scope is:", key_name_ui.output
+ assert_match "Do you want to customise scopes? [yN]", key_name_ui.output
+ assert_match "show_dashboard (exclusive scope, answering yes will not prompt for other scopes) [yN]", key_name_ui.output
+ assert_match "index_rubygems [yN]", key_name_ui.output
+ assert_match "push_rubygem [yN]", key_name_ui.output
+ assert_match "yank_rubygem [yN]", key_name_ui.output
+ assert_match "add_owner [yN]", key_name_ui.output
+ assert_match "remove_owner [yN]", key_name_ui.output
+ assert_match "access_webhooks [yN]", key_name_ui.output
+ assert_match "Would you like to enable MFA for this key? (strongly recommended) [yn]", key_name_ui.output
+ assert_equal "name=test-key&push_rubygem=true&mfa=true", fetcher.last_request.body
+
+ credentials = load_yaml_file Gem.configuration.credentials_path
+ assert_equal api_key, credentials[:rubygems_api_key]
+ end
+
+ def test_execute_with_key_name_custom_scope_and_mfa_level_of_gem_signin
+ email = "you@example.com"
+ password = "secret"
+ api_key = "1234abcd"
+ fetcher = Gem::RemoteFetcher.fetcher
+ mfa_level = "ui_and_gem_signin"
+
+ key_name_ui = Gem::MockGemUi.new "#{email}\n#{password}\ntest-key\ny\n\n\ny\n\n\n\n\n\n\ny"
+ util_capture(key_name_ui, nil, api_key, fetcher, mfa_level) { @cmd.execute }
+
+ user = ENV["USER"] || ENV["USERNAME"]
+
+ assert_match "API Key name [#{Socket.gethostname}-#{user}", key_name_ui.output
+ assert_match "The default access scope is:", key_name_ui.output
+ assert_match "Do you want to customise scopes? [yN]", key_name_ui.output
+ assert_match "show_dashboard (exclusive scope, answering yes will not prompt for other scopes) [yN]", key_name_ui.output
+ assert_match "index_rubygems [yN]", key_name_ui.output
+ assert_match "push_rubygem [yN]", key_name_ui.output
+ assert_match "yank_rubygem [yN]", key_name_ui.output
+ assert_match "add_owner [yN]", key_name_ui.output
+ assert_match "remove_owner [yN]", key_name_ui.output
+ assert_match "access_webhooks [yN]", key_name_ui.output
+ assert_match "Would you like to enable MFA for this key? (strongly recommended) [yn]", key_name_ui.output
+ assert_equal "name=test-key&push_rubygem=true&mfa=true", fetcher.last_request.body
+
+ credentials = load_yaml_file Gem.configuration.credentials_path
+ assert_equal api_key, credentials[:rubygems_api_key]
+ end
+
+ def test_execute_with_warnings
+ email = "you@example.com"
+ password = "secret"
+ api_key = "1234abcd"
+ fetcher = Gem::RemoteFetcher.fetcher
+ mfa_level = "disabled"
+ warning = "/[WARNING/] For protection of your account and gems"
+
+ key_name_ui = Gem::MockGemUi.new "#{email}\n#{password}\ntest-key\n\ny\n\n\n\n\n\ny"
+ util_capture(key_name_ui, nil, api_key, fetcher, mfa_level, warning) { @cmd.execute }
+
+ assert_match warning, key_name_ui.output
+ end
+
+ def test_execute_on_gemserver_without_profile_me_endpoint
+ host = "http://some-gemcutter-compatible-host.org"
+
+ email = "you@example.com"
+ password = "secret"
+ api_key = "1234abcd"
+ fetcher = Gem::RemoteFetcher.fetcher
+
+ key_name_ui = Gem::MockGemUi.new "#{email}\n#{password}\ntest-key\ny\n\n\ny\n\n\n\n\n\n\ny"
+
+ # Set the expected response for the Web-API supplied
+ ENV["RUBYGEMS_HOST"] = host
+ data_key = "#{ENV["RUBYGEMS_HOST"]}/api/v1/api_key"
+ fetcher.data[data_key] = HTTPResponseFactory.create(body: api_key, code: 200, msg: "OK")
+
+ use_ui key_name_ui do
+ @cmd.execute
+ end
+
+ user = ENV["USER"] || ENV["USERNAME"]
+
+ assert_match "API Key name [#{Socket.gethostname}-#{user}", key_name_ui.output
+ assert_match "show_dashboard (exclusive scope, answering yes will not prompt for other scopes) [yN]", key_name_ui.output
+ assert_match "index_rubygems [yN]", key_name_ui.output
+ assert_match "push_rubygem [yN]", key_name_ui.output
+ assert_match "yank_rubygem [yN]", key_name_ui.output
+ assert_match "add_owner [yN]", key_name_ui.output
+ assert_match "remove_owner [yN]", key_name_ui.output
+ assert_match "access_webhooks [yN]", key_name_ui.output
+ assert_equal "name=test-key&push_rubygem=true", fetcher.last_request.body
+ end
+
# Utility method to capture IO/UI within the block passed
- def util_capture(ui_stub = nil, host = nil, api_key = nil, fetcher = Gem::FakeFetcher.new)
- api_key ||= 'a5fdbb6ba150cbb83aad2bb2fede64cf040453903'
- response = [api_key, 200, 'OK']
- email = 'you@example.com'
- password = 'secret'
+ def util_capture(ui_stub = nil, host = nil, api_key = nil, fetcher = Gem::FakeFetcher.new, mfa_level = "disabled", warning = nil)
+ api_key ||= "a5fdbb6ba150cbb83aad2bb2fede64cf040453903"
+ response = HTTPResponseFactory.create(body: api_key, code: 200, msg: "OK")
+ profile_response = HTTPResponseFactory.create(body: "mfa: #{mfa_level}\nwarning: #{warning}", code: 200, msg: "OK")
+ email = "you@example.com"
+ password = "secret"
# Set the expected response for the Web-API supplied
- ENV['RUBYGEMS_HOST'] = host || Gem::DEFAULT_HOST
- data_key = "#{ENV['RUBYGEMS_HOST']}/api/v1/api_key"
+ ENV["RUBYGEMS_HOST"] = host || Gem::DEFAULT_HOST
+ data_key = "#{ENV["RUBYGEMS_HOST"]}/api/v1/api_key"
fetcher.data[data_key] = response
+ profile = "#{ENV["RUBYGEMS_HOST"]}/api/v1/profile/me.yaml"
+ fetcher.data[profile] = profile_response
Gem::RemoteFetcher.fetcher = fetcher
- sign_in_ui = ui_stub || Gem::MockGemUi.new("#{email}\n#{password}\n\n\n\n\n\n\n\n\n")
+ sign_in_ui = ui_stub || Gem::MockGemUi.new("#{email}\n#{password}\n\n\n")
use_ui sign_in_ui do
yield
diff --git a/test/rubygems/test_gem_commands_signout_command.rb b/test/rubygems/test_gem_commands_signout_command.rb
index aa6300b6ab..999a14080f 100644
--- a/test/rubygems/test_gem_commands_signout_command.rb
+++ b/test/rubygems/test_gem_commands_signout_command.rb
@@ -1,8 +1,8 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/commands/signout_command'
-require 'rubygems/installer'
+require_relative "helper"
+require "rubygems/commands/signout_command"
+require "rubygems/installer"
class TestGemCommandsSignoutCommand < Gem::TestCase
def setup
@@ -12,12 +12,12 @@ class TestGemCommandsSignoutCommand < Gem::TestCase
def test_execute_when_user_is_signed_in
FileUtils.mkdir_p File.dirname(Gem.configuration.credentials_path)
- FileUtils::touch Gem.configuration.credentials_path
+ FileUtils.touch Gem.configuration.credentials_path
@sign_out_ui = Gem::MockGemUi.new
use_ui(@sign_out_ui) { @cmd.execute }
- assert_match %r{You have successfully signed out}, @sign_out_ui.output
+ assert_match(/You have successfully signed out/, @sign_out_ui.output)
assert_equal false, File.exist?(Gem.configuration.credentials_path)
end
@@ -25,6 +25,6 @@ class TestGemCommandsSignoutCommand < Gem::TestCase
@sign_out_ui = Gem::MockGemUi.new
use_ui(@sign_out_ui) { @cmd.execute }
- assert_match %r{You are not currently signed in}, @sign_out_ui.error
+ assert_match(/You are not currently signed in/, @sign_out_ui.error)
end
end
diff --git a/test/rubygems/test_gem_commands_sources_command.rb b/test/rubygems/test_gem_commands_sources_command.rb
index 7bca0f3803..5e675e5c84 100644
--- a/test/rubygems/test_gem_commands_sources_command.rb
+++ b/test/rubygems/test_gem_commands_sources_command.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/commands/sources_command'
+
+require_relative "helper"
+require "rubygems/commands/sources_command"
class TestGemCommandsSourcesCommand < Gem::TestCase
def setup
@@ -20,7 +21,7 @@ class TestGemCommandsSourcesCommand < Gem::TestCase
end
def test_initialize_proxy
- assert @cmd.handles?(['--http-proxy', 'http://proxy.example.com'])
+ assert @cmd.handles?(["--http-proxy", "http://proxy.example.com"])
end
def test_execute
@@ -37,12 +38,12 @@ class TestGemCommandsSourcesCommand < Gem::TestCase
EOF
assert_equal expected, @ui.output
- assert_equal '', @ui.error
+ assert_equal "", @ui.error
end
def test_execute_add
spec_fetcher do |fetcher|
- fetcher.spec 'a', 1
+ fetcher.spec "a", 1
end
specs = Gem::Specification.map do |spec|
@@ -70,7 +71,7 @@ class TestGemCommandsSourcesCommand < Gem::TestCase
EOF
assert_equal expected, @ui.output
- assert_equal '', @ui.error
+ assert_equal "", @ui.error
end
def test_execute_add_allow_typo_squatting_source
@@ -161,7 +162,6 @@ class TestGemCommandsSourcesCommand < Gem::TestCase
ui = Gem::MockGemUi.new("n")
use_ui ui do
-
assert_raise Gem::MockGemUi::TermError do
@cmd.execute
end
@@ -182,7 +182,7 @@ class TestGemCommandsSourcesCommand < Gem::TestCase
uri = "http://beta-gems.example.com/specs.#{@marshal_version}.gz"
@fetcher.data[uri] = proc do
- raise Gem::RemoteFetcher::FetchError.new('it died', uri)
+ raise Gem::RemoteFetcher::FetchError.new("it died", uri)
end
@cmd.handle_options %w[--add http://beta-gems.example.com]
@@ -199,7 +199,57 @@ Error fetching http://beta-gems.example.com:
EOF
assert_equal expected, @ui.output
- assert_equal '', @ui.error
+ assert_equal "", @ui.error
+ end
+
+ def test_execute_add_existent_source_invalid_uri
+ spec_fetcher
+
+ uri = "https://u:p@example.com/specs.#{@marshal_version}.gz"
+
+ @cmd.handle_options %w[--add https://u:p@example.com]
+ @fetcher.data[uri] = proc do
+ raise Gem::RemoteFetcher::FetchError.new("it died", uri)
+ end
+
+ use_ui @ui do
+ assert_raise Gem::MockGemUi::TermError do
+ @cmd.execute
+ end
+ end
+
+ expected = <<-EOF
+Error fetching https://u:REDACTED@example.com:
+\tit died (https://u:REDACTED@example.com/specs.#{@marshal_version}.gz)
+ EOF
+
+ assert_equal expected, @ui.output
+ assert_equal "", @ui.error
+ end
+
+ def test_execute_add_existent_source_invalid_uri_with_error_by_chance_including_the_uri_password
+ spec_fetcher
+
+ uri = "https://u:secret@example.com/specs.#{@marshal_version}.gz"
+
+ @cmd.handle_options %w[--add https://u:secret@example.com]
+ @fetcher.data[uri] = proc do
+ raise Gem::RemoteFetcher::FetchError.new("it secretly died", uri)
+ end
+
+ use_ui @ui do
+ assert_raise Gem::MockGemUi::TermError do
+ @cmd.execute
+ end
+ end
+
+ expected = <<-EOF
+Error fetching https://u:REDACTED@example.com:
+\tit secretly died (https://u:REDACTED@example.com/specs.#{@marshal_version}.gz)
+ EOF
+
+ assert_equal expected, @ui.output
+ assert_equal "", @ui.error
end
def test_execute_add_redundant_source
@@ -218,7 +268,7 @@ source #{@gem_repo} already present in the cache
EOF
assert_equal expected, @ui.output
- assert_equal '', @ui.error
+ assert_equal "", @ui.error
end
def test_execute_add_redundant_source_trailing_slash
@@ -238,7 +288,7 @@ source #{@gem_repo} already present in the cache
EOF
assert_equal expected, @ui.output
- assert_equal '', @ui.error
+ assert_equal "", @ui.error
# Re-add pre-existing gem source (w/o slash)
repo_without_slash = "http://gems.example.com"
@@ -255,7 +305,7 @@ http://gems.example.com added to sources
EOF
assert_equal expected, @ui.output
- assert_equal '', @ui.error
+ assert_equal "", @ui.error
# Re-add original gem source (w/ slash)
@cmd.handle_options %W[--add #{repo_with_slash}]
@@ -272,14 +322,14 @@ source http://gems.example.com/ already present in the cache
EOF
assert_equal expected, @ui.output
- assert_equal '', @ui.error
+ assert_equal "", @ui.error
end
def test_execute_add_http_rubygems_org
- http_rubygems_org = 'http://rubygems.org/'
+ http_rubygems_org = "http://rubygems.org/"
spec_fetcher do |fetcher|
- fetcher.spec 'a', 1
+ fetcher.spec "a", 1
end
specs = Gem::Specification.map do |spec|
@@ -344,10 +394,10 @@ source http://gems.example.com/ already present in the cache
end
def test_execute_add_https_rubygems_org
- https_rubygems_org = 'https://rubygems.org/'
+ https_rubygems_org = "https://rubygems.org/"
spec_fetcher do |fetcher|
- fetcher.spec 'a', 1
+ fetcher.spec "a", 1
end
specs = Gem::Specification.map do |spec|
@@ -397,7 +447,7 @@ beta-gems.example.com is not a URI
EOF
assert_equal expected, @ui.output
- assert_equal '', @ui.error
+ assert_equal "", @ui.error
end
def test_execute_clear_all
@@ -412,10 +462,10 @@ beta-gems.example.com is not a URI
EOF
assert_equal expected, @ui.output
- assert_equal '', @ui.error
+ assert_equal "", @ui.error
dir = Gem.spec_cache_dir
- refute File.exist?(dir), 'cache dir removed'
+ refute File.exist?(dir), "cache dir removed"
end
def test_execute_list
@@ -432,7 +482,7 @@ beta-gems.example.com is not a URI
EOF
assert_equal expected, @ui.output
- assert_equal '', @ui.error
+ assert_equal "", @ui.error
end
def test_execute_remove
@@ -445,7 +495,7 @@ beta-gems.example.com is not a URI
expected = "#{@gem_repo} removed from sources\n"
assert_equal expected, @ui.output
- assert_equal '', @ui.error
+ assert_equal "", @ui.error
end
def test_execute_remove_no_network
@@ -464,14 +514,14 @@ beta-gems.example.com is not a URI
expected = "#{@gem_repo} removed from sources\n"
assert_equal expected, @ui.output
- assert_equal '', @ui.error
+ assert_equal "", @ui.error
end
def test_execute_update
@cmd.handle_options %w[--update]
spec_fetcher do |fetcher|
- fetcher.gem 'a', 1
+ fetcher.gem "a", 1
end
use_ui @ui do
@@ -479,6 +529,6 @@ beta-gems.example.com is not a URI
end
assert_equal "source cache successfully updated\n", @ui.output
- assert_equal '', @ui.error
+ assert_equal "", @ui.error
end
end
diff --git a/test/rubygems/test_gem_commands_specification_command.rb b/test/rubygems/test_gem_commands_specification_command.rb
index c8cb7df32e..454d6ea1c6 100644
--- a/test/rubygems/test_gem_commands_specification_command.rb
+++ b/test/rubygems/test_gem_commands_specification_command.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/commands/specification_command'
+
+require_relative "helper"
+require "rubygems/commands/specification_command"
class TestGemCommandsSpecificationCommand < Gem::TestCase
def setup
@@ -10,7 +11,7 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase
end
def test_execute
- foo = util_spec 'foo'
+ foo = util_spec "foo"
install_specs foo
@@ -20,14 +21,14 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase
@cmd.execute
end
- assert_match %r{Gem::Specification}, @ui.output
- assert_match %r{name: foo}, @ui.output
- assert_equal '', @ui.error
+ assert_match(/Gem::Specification/, @ui.output)
+ assert_match(/name: foo/, @ui.output)
+ assert_equal "", @ui.error
end
def test_execute_all
- install_specs util_spec 'foo', '0.0.1'
- install_specs util_spec 'foo', '0.0.2'
+ install_specs util_spec "foo", "0.0.1"
+ install_specs util_spec "foo", "0.0.2"
@cmd.options[:args] = %w[foo]
@cmd.options[:all] = true
@@ -36,16 +37,16 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase
@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
+ assert_match(/Gem::Specification/, @ui.output)
+ assert_match(/name: foo/, @ui.output)
+ assert_match(/version: 0.0.1/, @ui.output)
+ assert_match(/version: 0.0.2/, @ui.output)
+ assert_equal "", @ui.error
end
def test_execute_all_conflicts_with_version
- util_spec 'foo', '0.0.1'
- util_spec 'foo', '0.0.2'
+ util_spec "foo", "0.0.1"
+ util_spec "foo", "0.0.2"
@cmd.options[:args] = %w[foo]
@cmd.options[:all] = true
@@ -57,7 +58,7 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase
end
end
- assert_equal '', @ui.output
+ assert_equal "", @ui.output
assert_equal "ERROR: Specify --all or -v, not both\n", @ui.error
end
@@ -70,7 +71,7 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase
end
end
- assert_equal '', @ui.output
+ assert_equal "", @ui.output
assert_equal "ERROR: No gem matching 'foo (>= 0)' found\n", @ui.error
end
@@ -84,13 +85,13 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase
end
end
- assert_equal '', @ui.output
+ assert_equal "", @ui.output
assert_equal "ERROR: No gem matching 'foo (= 1.3.2)' found\n", @ui.error
end
def test_execute_exact_match
- install_specs util_spec 'foo'
- install_specs util_spec 'foo_bar'
+ install_specs util_spec "foo"
+ install_specs util_spec "foo_bar"
@cmd.options[:args] = %w[foo]
@@ -98,13 +99,13 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase
@cmd.execute
end
- assert_match %r{Gem::Specification}, @ui.output
- assert_match %r{name: foo}, @ui.output
- assert_equal '', @ui.error
+ assert_match(/Gem::Specification/, @ui.output)
+ assert_match(/name: foo/, @ui.output)
+ assert_equal "", @ui.error
end
def test_execute_field
- foo = util_spec 'foo', '2'
+ foo = util_spec "foo", "2"
install_specs foo
@@ -118,7 +119,7 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase
end
def test_execute_file
- foo = util_spec 'foo' do |s|
+ foo = util_spec "foo" do |s|
s.files = %w[lib/code.rb]
end
@@ -130,13 +131,13 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase
@cmd.execute
end
- assert_match %r{Gem::Specification}, @ui.output
- assert_match %r{name: foo}, @ui.output
- assert_equal '', @ui.error
+ assert_match(/Gem::Specification/, @ui.output)
+ assert_match(/name: foo/, @ui.output)
+ assert_equal "", @ui.error
end
def test_execute_marshal
- foo = util_spec 'foo', '2'
+ foo = util_spec "foo", "2"
install_specs foo
@@ -148,12 +149,12 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase
end
assert_equal foo, Marshal.load(@ui.output)
- assert_equal '', @ui.error
+ assert_equal "", @ui.error
end
def test_execute_remote
spec_fetcher do |fetcher|
- fetcher.spec 'foo', 1
+ fetcher.spec "foo", 1
end
@cmd.options[:args] = %w[foo]
@@ -164,13 +165,13 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase
end
assert_match %r{\A--- !ruby/object:Gem::Specification}, @ui.output
- assert_match %r{name: foo}, @ui.output
+ assert_match(/name: foo/, @ui.output)
end
def test_execute_remote_with_version
spec_fetcher do |fetcher|
- fetcher.spec 'foo', "1"
- fetcher.spec 'foo', "2"
+ fetcher.spec "foo", "1"
+ fetcher.spec "foo", "2"
end
@cmd.options[:args] = %w[foo]
@@ -190,9 +191,9 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase
original_platforms = Gem.platforms.dup
spec_fetcher do |fetcher|
- fetcher.spec 'foo', "1"
- fetcher.spec 'foo', "1" do |s|
- s.platform = 'x86_64-linux'
+ fetcher.spec "foo", "1"
+ fetcher.spec "foo", "1" do |s|
+ s.platform = "x86_64-linux"
end
end
@@ -216,8 +217,8 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase
def test_execute_remote_without_prerelease
spec_fetcher do |fetcher|
- fetcher.spec 'foo', '2.0.0'
- fetcher.spec 'foo', '2.0.1.pre'
+ fetcher.spec "foo", "2.0.0"
+ fetcher.spec "foo", "2.0.1.pre"
end
@cmd.options[:args] = %w[foo]
@@ -228,7 +229,7 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase
end
assert_match %r{\A--- !ruby/object:Gem::Specification}, @ui.output
- assert_match %r{name: foo}, @ui.output
+ assert_match(/name: foo/, @ui.output)
spec = load_yaml @ui.output
@@ -237,8 +238,8 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase
def test_execute_remote_with_prerelease
spec_fetcher do |fetcher|
- fetcher.spec 'foo', '2.0.0'
- fetcher.spec 'foo', '2.0.1.pre'
+ fetcher.spec "foo", "2.0.0"
+ fetcher.spec "foo", "2.0.1.pre"
end
@cmd.options[:args] = %w[foo]
@@ -250,7 +251,7 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase
end
assert_match %r{\A--- !ruby/object:Gem::Specification}, @ui.output
- assert_match %r{name: foo}, @ui.output
+ assert_match(/name: foo/, @ui.output)
spec = load_yaml @ui.output
@@ -258,7 +259,7 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase
end
def test_execute_ruby
- foo = util_spec 'foo'
+ foo = util_spec "foo"
install_specs foo
@@ -269,8 +270,8 @@ class TestGemCommandsSpecificationCommand < Gem::TestCase
@cmd.execute
end
- assert_match %r{Gem::Specification.new}, @ui.output
- assert_match %r{s.name = "foo"}, @ui.output
- assert_equal '', @ui.error
+ assert_match(/Gem::Specification.new/, @ui.output)
+ assert_match(/s.name = "foo"/, @ui.output)
+ assert_equal "", @ui.error
end
end
diff --git a/test/rubygems/test_gem_commands_stale_command.rb b/test/rubygems/test_gem_commands_stale_command.rb
index 83bd3e5def..ea7493b418 100644
--- a/test/rubygems/test_gem_commands_stale_command.rb
+++ b/test/rubygems/test_gem_commands_stale_command.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/commands/stale_command'
+
+require_relative "helper"
+require "rubygems/commands/stale_command"
class TestGemCommandsStaleCommand < Gem::TestCase
def setup
@@ -11,12 +12,12 @@ class TestGemCommandsStaleCommand < Gem::TestCase
def test_execute_sorts
files = %w[lib/foo_bar.rb Rakefile]
- foo_bar = util_spec 'foo_bar' do |gem|
+ foo_bar = util_spec "foo_bar" do |gem|
gem.files = files
end
install_specs foo_bar
- bar_baz = util_spec 'bar_baz' do |gem|
+ bar_baz = util_spec "bar_baz" do |gem|
gem.files = files
end
install_specs bar_baz
@@ -24,11 +25,11 @@ class TestGemCommandsStaleCommand < Gem::TestCase
files.each do |file|
filename = File.join(bar_baz.full_gem_path, file)
FileUtils.mkdir_p File.dirname filename
- FileUtils.touch(filename, :mtime => Time.now)
+ FileUtils.touch(filename, mtime: Time.now)
filename = File.join(foo_bar.full_gem_path, file)
FileUtils.mkdir_p File.dirname filename
- FileUtils.touch(filename, :mtime => Time.now - 86400)
+ FileUtils.touch(filename, mtime: Time.now - 86_400)
end
use_ui @stub_ui do
diff --git a/test/rubygems/test_gem_commands_uninstall_command.rb b/test/rubygems/test_gem_commands_uninstall_command.rb
index 55f1049266..32553d1730 100644
--- a/test/rubygems/test_gem_commands_uninstall_command.rb
+++ b/test/rubygems/test_gem_commands_uninstall_command.rb
@@ -1,12 +1,13 @@
# frozen_string_literal: true
-require_relative 'installer_test_case'
-require 'rubygems/commands/uninstall_command'
+
+require_relative "installer_test_case"
+require "rubygems/commands/uninstall_command"
class TestGemCommandsUninstallCommand < Gem::InstallerTestCase
def setup
super
@cmd = Gem::Commands::UninstallCommand.new
- @executable = File.join(@gemhome, 'bin', 'executable')
+ @executable = File.join(@gemhome, "bin", "executable")
end
def test_execute_all_named
@@ -14,20 +15,15 @@ class TestGemCommandsUninstallCommand < Gem::InstallerTestCase
util_make_gems
- default = new_default_spec 'default', '1'
+ default = new_default_spec "default", "1"
install_default_gems default
gemhome2 = "#{@gemhome}2"
- a_4, = util_gem 'a', 4
- install_gem a_4, :install_dir => gemhome2
-
- Gem::Specification.dirs = [@gemhome, gemhome2]
+ a_4, = util_gem "a", 4
+ install_gem a_4, install_dir: gemhome2
- assert_includes Gem::Specification.all_names, 'a-1'
- assert_includes Gem::Specification.all_names, 'a-4'
- assert_includes Gem::Specification.all_names, 'b-2'
- assert_includes Gem::Specification.all_names, 'default-1'
+ assert_gems_presence "a-1", "a-4", "b-2", "default-1", dirs: [@gemhome, gemhome2]
@cmd.options[:all] = true
@cmd.options[:args] = %w[a]
@@ -36,15 +32,15 @@ class TestGemCommandsUninstallCommand < Gem::InstallerTestCase
@cmd.execute
end
- assert_equal %w[a_evil-9 b-2 c-1.2 default-1 dep_x-1 pl-1-x86-linux x-1],
+ assert_equal %w[a-4 a_evil-9 b-2 c-1.2 default-1 dep_x-1 pl-1-x86-linux x-1],
Gem::Specification.all_names.sort
end
def test_execute_all_named_default_single
- z_1 = new_default_spec 'z', '1'
+ z_1 = new_default_spec "z", "1"
install_default_gems z_1
- assert_includes Gem::Specification.all_names, 'z-1'
+ assert_includes Gem::Specification.all_names, "z-1"
@cmd.options[:all] = true
@cmd.options[:args] = %w[z]
@@ -57,18 +53,18 @@ class TestGemCommandsUninstallCommand < Gem::InstallerTestCase
output = @ui.output.split "\n"
- assert_equal 'Gem z-1 cannot be uninstalled because it is a default gem', output.shift
+ assert_equal "Gem z-1 cannot be uninstalled because it is a default gem", output.shift
end
def test_execute_all_named_default_multiple
- z_1 = new_default_spec 'z', '1'
+ z_1 = new_default_spec "z", "1"
install_default_gems z_1
- z_2, = util_gem 'z', 2
+ z_2, = util_gem "z", 2
install_gem z_2
- assert_includes Gem::Specification.all_names, 'z-1'
- assert_includes Gem::Specification.all_names, 'z-2'
+ assert_includes Gem::Specification.all_names, "z-1"
+ assert_includes Gem::Specification.all_names, "z-2"
@cmd.options[:all] = true
@cmd.options[:args] = %w[z]
@@ -81,15 +77,70 @@ class TestGemCommandsUninstallCommand < Gem::InstallerTestCase
output = @ui.output.split "\n"
- assert_equal 'Gem z-1 cannot be uninstalled because it is a default gem', output.shift
- assert_equal 'Successfully uninstalled z-2', output.shift
+ assert_equal "Gem z-1 cannot be uninstalled because it is a default gem", output.shift
+ assert_equal "Successfully uninstalled z-2", output.shift
+ end
+
+ def test_execute_does_not_remove_default_gem_executables
+ z_1_default = new_default_spec "z", "1", executable: true
+ install_default_gems z_1_default
+
+ z_1, = util_gem "z", "1" do |spec|
+ util_make_exec spec
+ end
+ install_gem z_1, force: true
+
+ Gem::Specification.reset
+
+ @cmd.options[:all] = true
+ @cmd.options[:force] = true
+ @cmd.options[:executables] = true
+ @cmd.options[:args] = %w[z]
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ assert File.exist? File.join(@gemhome, "bin", "executable")
+ assert File.exist? File.join(@gemhome, "gems", "z-1", "bin", "executable")
+
+ output = @ui.output.split "\n"
+
+ refute_includes output, "Removing executable"
+ assert_equal "Successfully uninstalled z-1", output.shift
+ assert_equal "There was both a regular copy and a default copy of z-1. The regular copy was successfully uninstalled, but the default copy was left around because default gems can't be removed.", output.shift
+ end
+
+ def test_execute_does_not_error_on_shadowed_default_gems
+ z_1_default = new_default_spec "z", "1"
+ install_default_gems z_1_default
+
+ z_1 = util_spec "z", "1" do |spec|
+ spec.date = "2024-01-01"
+ end
+ install_gem z_1
+
+ Gem::Specification.reset
+
+ @cmd.options[:args] = %w[z:1]
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ output = @ui.output.split "\n"
+ assert_equal "Successfully uninstalled z-1", output.shift
+ assert_equal "There was both a regular copy and a default copy of z-1. The regular copy was successfully uninstalled, but the default copy was left around because default gems can't be removed.", output.shift
+
+ error = @ui.error.split "\n"
+ assert_empty error
end
def test_execute_dependency_order
initial_install
- c = quick_gem 'c' do |spec|
- spec.add_dependency 'a'
+ c = quick_gem "c" do |spec|
+ spec.add_dependency "a"
end
util_build_gem c
@@ -110,15 +161,15 @@ class TestGemCommandsUninstallCommand < Gem::InstallerTestCase
output = ui.output.split "\n"
- assert_equal 'Successfully uninstalled c-2', output.shift
+ assert_equal "Successfully uninstalled c-2", output.shift
assert_equal "Removing executable", output.shift
- assert_equal 'Successfully uninstalled a-2', output.shift
+ assert_equal "Successfully uninstalled a-2", output.shift
end
def test_execute_removes_executable
initial_install
- if win_platform?
+ if Gem.win_platform?
assert File.exist?(@executable)
else
assert File.symlink?(@executable)
@@ -149,12 +200,12 @@ class TestGemCommandsUninstallCommand < Gem::InstallerTestCase
FileUtils.rm_f @executable # Wish this didn't happen in #setup
- Gem::Installer.exec_format = 'foo-%s-bar'
+ Gem::Installer.exec_format = "foo-%s-bar"
installer.format_executable = true
installer.install
- formatted_executable = File.join @gemhome, 'bin', 'foo-executable-bar'
+ formatted_executable = File.join @gemhome, "bin", "foo-executable-bar"
assert_equal true, File.exist?(formatted_executable)
@cmd.options[:executables] = true
@@ -162,7 +213,7 @@ class TestGemCommandsUninstallCommand < Gem::InstallerTestCase
@cmd.execute
assert_equal false, File.exist?(formatted_executable)
- rescue
+ rescue StandardError
Gem::Installer.exec_format = nil
end
@@ -197,19 +248,19 @@ class TestGemCommandsUninstallCommand < Gem::InstallerTestCase
util_make_gems
- assert_equal 3, Gem::Specification.find_all_by_name('a').length
+ assert_equal 3, Gem::Specification.find_all_by_name("a").length
- @cmd.options[:version] = '1'
+ @cmd.options[:version] = "1"
@cmd.options[:force] = true
- @cmd.options[:args] = ['a']
+ @cmd.options[:args] = ["a"]
use_ui ui do
@cmd.execute
end
- assert_equal 2, Gem::Specification.find_all_by_name('a').length
+ assert_equal 2, Gem::Specification.find_all_by_name("a").length
- assert File.exist? File.join(@gemhome, 'bin', 'executable')
+ assert File.exist? File.join(@gemhome, "bin", "executable")
end
def test_execute_with_version_specified_as_colon
@@ -219,18 +270,38 @@ class TestGemCommandsUninstallCommand < Gem::InstallerTestCase
util_make_gems
- assert_equal 3, Gem::Specification.find_all_by_name('a').length
+ assert_equal 3, Gem::Specification.find_all_by_name("a").length
@cmd.options[:force] = true
- @cmd.options[:args] = ['a:1']
+ @cmd.options[:args] = ["a:1"]
use_ui ui do
@cmd.execute
end
- assert_equal 2, Gem::Specification.find_all_by_name('a').length
+ assert_equal 2, Gem::Specification.find_all_by_name("a").length
- assert File.exist? File.join(@gemhome, 'bin', 'executable')
+ assert File.exist? File.join(@gemhome, "bin", "executable")
+ end
+
+ def test_execute_with_multiple_version_specified_as_colon
+ initial_install
+
+ ui = Gem::MockGemUi.new "y\n"
+
+ util_make_gems
+
+ assert_equal 3, Gem::Specification.find_all_by_name("a").length
+
+ @cmd.options[:force] = true
+ @cmd.options[:args] = ["a:1", "a:2"]
+
+ use_ui ui do
+ @cmd.execute
+ end
+
+ assert_equal 1, Gem::Specification.find_all_by_name("a").length
+ assert_equal Gem::Version.new("3.a"), Gem::Specification.find_by_name("a").version
end
def test_uninstall_selection
@@ -238,22 +309,22 @@ class TestGemCommandsUninstallCommand < Gem::InstallerTestCase
util_make_gems
- list = Gem::Specification.find_all_by_name 'a'
+ list = Gem::Specification.find_all_by_name "a"
- @cmd.options[:args] = ['a']
+ @cmd.options[:args] = ["a"]
use_ui ui do
@cmd.execute
end
- updated_list = Gem::Specification.find_all_by_name('a')
+ updated_list = Gem::Specification.find_all_by_name("a")
assert_equal list.length - 1, updated_list.length
- assert_match ' 1. a-1', ui.output
- assert_match ' 2. a-2', ui.output
- assert_match ' 3. a-3.a', ui.output
- assert_match ' 4. All versions', ui.output
- assert_match 'uninstalled a-1', ui.output
+ assert_match " 1. a-1", ui.output
+ assert_match " 2. a-2", ui.output
+ assert_match " 3. a-3.a", ui.output
+ assert_match " 4. All versions", ui.output
+ assert_match "uninstalled a-1", ui.output
end
def test_uninstall_selection_multiple_gems
@@ -261,31 +332,31 @@ class TestGemCommandsUninstallCommand < Gem::InstallerTestCase
util_make_gems
- a_list = Gem::Specification.find_all_by_name('a')
- b_list = Gem::Specification.find_all_by_name('b')
+ a_list = Gem::Specification.find_all_by_name("a")
+ b_list = Gem::Specification.find_all_by_name("b")
list = a_list + b_list
- @cmd.options[:args] = ['a', 'b']
+ @cmd.options[:args] = ["a", "b"]
use_ui ui do
@cmd.execute
end
- updated_a_list = Gem::Specification.find_all_by_name('a')
- updated_b_list = Gem::Specification.find_all_by_name('b')
+ updated_a_list = Gem::Specification.find_all_by_name("a")
+ updated_b_list = Gem::Specification.find_all_by_name("b")
updated_list = updated_a_list + updated_b_list
assert_equal list.length - 2, updated_list.length
out = ui.output.split("\n")
- assert_match 'uninstalled b-2', out.shift
- assert_match '', out.shift
- assert_match 'Select gem to uninstall:', out.shift
- assert_match ' 1. a-1', out.shift
- assert_match ' 2. a-2', out.shift
- assert_match ' 3. a-3.a', out.shift
- assert_match ' 4. All versions', out.shift
- assert_match 'uninstalled a-1', out.shift
+ assert_match "uninstalled b-2", out.shift
+ assert_match "", out.shift
+ assert_match "Select gem to uninstall:", out.shift
+ assert_match " 1. a-1", out.shift
+ assert_match " 2. a-2", out.shift
+ assert_match " 3. a-3.a", out.shift
+ assert_match " 4. All versions", out.shift
+ assert_match "uninstalled a-1", out.shift
assert_empty out
end
@@ -294,22 +365,22 @@ class TestGemCommandsUninstallCommand < Gem::InstallerTestCase
ui = Gem::MockGemUi.new "y\n"
- a_1, = util_gem 'a', 1
+ a_1, = util_gem "a", 1
install_gem a_1
- a_3a, = util_gem 'a', '3.a'
+ a_3a, = util_gem "a", "3.a"
install_gem a_3a
- assert_equal 3, Gem::Specification.find_all_by_name('a').length
+ assert_equal 3, Gem::Specification.find_all_by_name("a").length
@cmd.options[:force] = true
- @cmd.options[:args] = ['a']
+ @cmd.options[:args] = ["a"]
use_ui ui do
@cmd.execute
end
- assert_empty Gem::Specification.find_all_by_name('a')
+ assert_empty Gem::Specification.find_all_by_name("a")
assert_match "Removing executable", ui.output
refute File.exist? @executable
end
@@ -321,36 +392,32 @@ class TestGemCommandsUninstallCommand < Gem::InstallerTestCase
util_make_gems
- assert Gem::Specification.find_all_by_name('dep_x').length > 0
- assert Gem::Specification.find_all_by_name('x').length > 0
+ assert Gem::Specification.find_all_by_name("dep_x").length > 0
+ assert Gem::Specification.find_all_by_name("x").length > 0
@cmd.options[:force] = true
- @cmd.options[:args] = ['x']
+ @cmd.options[:args] = ["x"]
use_ui ui do
@cmd.execute
end
- assert Gem::Specification.find_all_by_name('dep_x').length > 0
- assert Gem::Specification.find_all_by_name('x').length.zero?
+ assert Gem::Specification.find_all_by_name("dep_x").length > 0
+ assert Gem::Specification.find_all_by_name("x").length.zero?
end
def test_execute_all
util_make_gems
- default = new_default_spec 'default', '1'
+ default = new_default_spec "default", "1"
install_default_gems default
gemhome2 = "#{@gemhome}2"
- a_4, = util_gem 'a', 4
+ a_4, = util_gem "a", 4
install_gem a_4
- Gem::Specification.dirs = [@gemhome, gemhome2]
-
- assert_includes Gem::Specification.all_names, 'a-1'
- assert_includes Gem::Specification.all_names, 'a-4'
- assert_includes Gem::Specification.all_names, 'default-1'
+ assert_gems_presence "a-1", "a-4", "default-1", dirs: [@gemhome, gemhome2]
@cmd.options[:all] = true
@cmd.options[:args] = []
@@ -368,14 +435,12 @@ class TestGemCommandsUninstallCommand < Gem::InstallerTestCase
gemhome2 = "#{@gemhome}2"
- a_4, = util_gem 'a', 4
- install_gem a_4 , :install_dir => gemhome2
+ a_4, = util_gem "a", 4
+ install_gem a_4, install_dir: gemhome2
- Gem::Specification.dirs = [@gemhome, gemhome2]
+ assert_gems_presence "a-4", dirs: [@gemhome, gemhome2]
- assert_includes Gem::Specification.all_names, 'a-4'
-
- @cmd.options[:args] = ['a:4']
+ @cmd.options[:args] = ["a:4"]
e = assert_raise Gem::InstallError do
use_ui ui do
@@ -386,6 +451,26 @@ class TestGemCommandsUninstallCommand < Gem::InstallerTestCase
assert_includes e.message, "a is not installed in GEM_HOME"
end
+ def test_execute_outside_gem_home_when_install_dir_given
+ gemhome2 = "#{@gemhome}2"
+
+ a_4, = util_gem "a", 4
+ install_gem a_4, install_dir: gemhome2
+
+ assert_gems_presence "a-4", dirs: [@gemhome, gemhome2]
+
+ Gem::Specification.dirs = [@gemhome]
+
+ @cmd.options[:install_dir] = gemhome2
+ @cmd.options[:args] = ["a:4"]
+
+ @cmd.execute
+
+ Gem::Specification.dirs = [gemhome2]
+
+ refute_includes Gem::Specification.all_names.sort, "a-4"
+ end
+
def test_handle_options
@cmd.handle_options %w[]
@@ -397,7 +482,7 @@ class TestGemCommandsUninstallCommand < Gem::InstallerTestCase
end
def test_handle_options_vendor
- vendordir(File.join(@tempdir, 'vendor')) do
+ vendordir(File.join(@tempdir, "vendor")) do
use_ui @ui do
@cmd.handle_options %w[--vendor]
end
@@ -436,11 +521,11 @@ WARNING: Use your OS package manager to uninstall vendor gems
def test_handle_options_vendor_missing
vendordir(nil) do
- e = assert_raise OptionParser::InvalidOption do
+ e = assert_raise Gem::OptionParser::InvalidOption do
@cmd.handle_options %w[--vendor]
end
- assert_equal 'invalid option: --vendor your platform is not supported',
+ assert_equal "invalid option: --vendor your platform is not supported",
e.message
refute @cmd.options[:vendor]
@@ -449,7 +534,7 @@ WARNING: Use your OS package manager to uninstall vendor gems
end
def test_execute_with_gem_not_installed
- @cmd.options[:args] = ['d']
+ @cmd.options[:args] = ["d"]
use_ui ui do
@cmd.execute
@@ -486,7 +571,7 @@ WARNING: Use your OS package manager to uninstall vendor gems
end
assert_empty @ui.output
- assert_match %r{Error: unable to successfully uninstall '#{@spec.name}'}, @ui.error
+ assert_match(/Error: unable to successfully uninstall '#{@spec.name}'/, @ui.error)
end
private
@@ -501,4 +586,12 @@ WARNING: Use your OS package manager to uninstall vendor gems
end
end
end
+
+ def assert_gems_presence(*gems, dirs:)
+ Gem::Specification.dirs = dirs
+
+ gems.each do |full_name|
+ assert_includes Gem::Specification.all_names, full_name
+ end
+ end
end
diff --git a/test/rubygems/test_gem_commands_unpack_command.rb b/test/rubygems/test_gem_commands_unpack_command.rb
index 55369f1eeb..61cf8a611a 100644
--- a/test/rubygems/test_gem_commands_unpack_command.rb
+++ b/test/rubygems/test_gem_commands_unpack_command.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/commands/unpack_command'
+
+require_relative "helper"
+require "rubygems/commands/unpack_command"
class TestGemCommandsUnpackCommand < Gem::TestCase
def setup
@@ -15,30 +16,30 @@ class TestGemCommandsUnpackCommand < Gem::TestCase
util_make_gems
assert_equal(
- @cmd.find_in_cache(File.basename @a1.cache_file),
+ @cmd.find_in_cache(File.basename(@a1.cache_file)),
@a1.cache_file,
- 'found a-1.gem in the cache'
+ "found a-1.gem in the cache"
)
end
def test_get_path
specs = spec_fetcher do |fetcher|
- fetcher.gem 'a', 1
+ fetcher.gem "a", 1
end
- dep = Gem::Dependency.new 'a', 1
+ dep = Gem::Dependency.new "a", 1
assert_equal(
@cmd.get_path(dep),
- specs['a-1'].cache_file,
- 'fetches a-1 and returns the cache path'
+ specs["a-1"].cache_file,
+ "fetches a-1 and returns the cache path"
)
- FileUtils.rm specs['a-1'].cache_file
+ FileUtils.rm specs["a-1"].cache_file
assert_equal(
@cmd.get_path(dep),
- specs['a-1'].cache_file,
- 'when removed from cache, refetches a-1'
+ specs["a-1"].cache_file,
+ "when removed from cache, refetches a-1"
)
end
@@ -53,18 +54,18 @@ class TestGemCommandsUnpackCommand < Gem::TestCase
end
end
- assert File.exist?(File.join(@tempdir, 'a-3.a')), 'a should be unpacked'
- assert File.exist?(File.join(@tempdir, 'b-2')), 'b should be unpacked'
+ assert File.exist?(File.join(@tempdir, "a-3.a")), "a should be unpacked"
+ assert File.exist?(File.join(@tempdir, "b-2")), "b should be unpacked"
end
def test_execute_gem_path
spec_fetcher do |fetcher|
- fetcher.gem 'a', '3.a'
+ fetcher.gem "a", "3.a"
end
Gem.clear_paths
- gemhome2 = File.join @tempdir, 'gemhome2'
+ gemhome2 = File.join @tempdir, "gemhome2"
Gem.use_paths gemhome2, [gemhome2, @gemhome]
@@ -76,7 +77,7 @@ class TestGemCommandsUnpackCommand < Gem::TestCase
end
end
- assert File.exist?(File.join(@tempdir, 'a-3.a'))
+ assert File.exist?(File.join(@tempdir, "a-3.a"))
end
def test_execute_gem_path_missing
@@ -84,7 +85,7 @@ class TestGemCommandsUnpackCommand < Gem::TestCase
Gem.clear_paths
- gemhome2 = File.join @tempdir, 'gemhome2'
+ gemhome2 = File.join @tempdir, "gemhome2"
Gem.use_paths gemhome2, [gemhome2, @gemhome]
@@ -96,13 +97,13 @@ class TestGemCommandsUnpackCommand < Gem::TestCase
end
end
- assert_equal '', @ui.output
+ assert_equal "", @ui.output
end
def test_execute_remote
spec_fetcher do |fetcher|
- fetcher.download 'a', 1
- fetcher.download 'a', 2
+ fetcher.download "a", 1
+ fetcher.download "a", 2
end
Gem.configuration.verbose = :really
@@ -114,7 +115,7 @@ class TestGemCommandsUnpackCommand < Gem::TestCase
end
end
- assert File.exist?(File.join(@tempdir, 'a-2')), 'a should be unpacked'
+ assert File.exist?(File.join(@tempdir, "a-2")), "a should be unpacked"
end
def test_execute_spec
@@ -129,15 +130,15 @@ class TestGemCommandsUnpackCommand < Gem::TestCase
end
end
- assert File.exist?(File.join(@tempdir, 'a-3.a.gemspec'))
- assert File.exist?(File.join(@tempdir, 'b-2.gemspec'))
+ assert File.exist?(File.join(@tempdir, "a-3.a.gemspec"))
+ assert File.exist?(File.join(@tempdir, "b-2.gemspec"))
end
def test_execute_spec_target
util_make_gems
@cmd.options[:args] = %w[a b]
- @cmd.options[:target] = 'specs'
+ @cmd.options[:target] = "specs"
@cmd.options[:spec] = true
use_ui @ui do
@@ -146,16 +147,16 @@ class TestGemCommandsUnpackCommand < Gem::TestCase
end
end
- assert File.exist?(File.join(@tempdir, 'specs/a-3.a.gemspec'))
- assert File.exist?(File.join(@tempdir, 'specs/b-2.gemspec'))
+ assert File.exist?(File.join(@tempdir, "specs/a-3.a.gemspec"))
+ assert File.exist?(File.join(@tempdir, "specs/b-2.gemspec"))
end
def test_execute_sudo
- pend 'Cannot perform this test on windows (chmod)' if win_platform?
+ pend "Cannot perform this test on windows (chmod)" if Gem.win_platform?
util_make_gems
- FileUtils.chmod 0555, @gemhome
+ FileUtils.chmod 0o555, @gemhome
@cmd.options[:args] = %w[b]
@@ -165,15 +166,15 @@ class TestGemCommandsUnpackCommand < Gem::TestCase
end
end
- assert File.exist?(File.join(@tempdir, 'b-2')), 'b should be unpacked'
+ assert File.exist?(File.join(@tempdir, "b-2")), "b should be unpacked"
ensure
- FileUtils.chmod 0755, @gemhome
+ FileUtils.chmod 0o755, @gemhome
end
def test_execute_with_target_option
util_make_gems
- target = 'with_target'
+ target = "with_target"
@cmd.options[:args] = %w[a]
@cmd.options[:target] = target
@@ -183,12 +184,12 @@ class TestGemCommandsUnpackCommand < Gem::TestCase
end
end
- assert File.exist?(File.join(@tempdir, target, 'a-3.a'))
+ assert File.exist?(File.join(@tempdir, target, "a-3.a"))
end
def test_execute_exact_match
- foo_spec = util_spec 'foo'
- foo_bar_spec = util_spec 'foo_bar'
+ foo_spec = util_spec "foo"
+ foo_bar_spec = util_spec "foo_bar"
use_ui @ui do
Dir.chdir @tempdir do
diff --git a/test/rubygems/test_gem_commands_update_command.rb b/test/rubygems/test_gem_commands_update_command.rb
index e9264f6d14..642a62a373 100644
--- a/test/rubygems/test_gem_commands_update_command.rb
+++ b/test/rubygems/test_gem_commands_update_command.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/commands/update_command'
+
+require_relative "helper"
+require "rubygems/commands/update_command"
class TestGemCommandsUpdateCommand < Gem::TestCase
def setup
@@ -12,20 +13,20 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
@cmd.options[:document] = []
@specs = spec_fetcher do |fetcher|
- fetcher.download 'a', 1
- fetcher.download 'a', 2
- fetcher.download 'a', '3.a'
+ fetcher.download "a", 1
+ fetcher.download "a", 2
+ fetcher.download "a", "3.a"
end
- @a1_path = @specs['a-1'].cache_file
- @a2_path = @specs['a-1'].cache_file
- @a3a_path = @specs['a-3.a'].cache_file
+ @a1_path = @specs["a-1"].cache_file
+ @a2_path = @specs["a-1"].cache_file
+ @a3a_path = @specs["a-3.a"].cache_file
end
def test_execute
spec_fetcher do |fetcher|
- fetcher.download 'a', 2
- fetcher.spec 'a', 1
+ fetcher.download "a", 2
+ fetcher.spec "a", 1
end
@cmd.options[:args] = []
@@ -43,11 +44,11 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
def test_execute_multiple
spec_fetcher do |fetcher|
- fetcher.download 'a', 2
- fetcher.download 'ab', 2
+ fetcher.download "a", 2
+ fetcher.download "ab", 2
- fetcher.spec 'a', 1
- fetcher.spec 'ab', 1
+ fetcher.spec "a", 1
+ fetcher.spec "ab", 1
end
@cmd.options[:args] = %w[a]
@@ -65,7 +66,7 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
def test_execute_system
spec_fetcher do |fetcher|
- fetcher.download 'rubygems-update', 9 do |s|
+ fetcher.download "rubygems-update", 9 do |s|
s.files = %w[setup.rb]
end
end
@@ -78,7 +79,6 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
end
out = @ui.output.split "\n"
- assert_equal "Updating rubygems-update", out.shift
assert_equal "Installing RubyGems 9", out.shift
assert_equal "RubyGems system software updated", out.shift
@@ -87,7 +87,7 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
def test_execute_system_at_latest
spec_fetcher do |fetcher|
- fetcher.download 'rubygems-update', Gem::VERSION do |s|
+ fetcher.download "rubygems-update", Gem::VERSION do |s|
s.files = %w[setup.rb]
end
end
@@ -106,17 +106,141 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
assert_empty out
end
+ def test_execute_system_when_latest_does_not_support_your_ruby
+ spec_fetcher do |fetcher|
+ fetcher.download "rubygems-update", 9 do |s|
+ s.files = %w[setup.rb]
+ s.required_ruby_version = "> 9"
+ end
+ end
+
+ @cmd.options[:args] = []
+ @cmd.options[:system] = true
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ out = @ui.output.split "\n"
+ assert_empty out
+
+ err = @ui.error.split "\n"
+ assert_equal "ERROR: Error installing rubygems-update:", err.shift
+ assert_equal "\trubygems-update-9 requires Ruby version > 9. The current ruby version is #{Gem.ruby_version}.", err.shift
+ assert_empty err
+ end
+
+ def test_execute_system_when_latest_does_not_support_your_ruby_but_previous_one_does
+ spec_fetcher do |fetcher|
+ fetcher.download "rubygems-update", 9 do |s|
+ s.files = %w[setup.rb]
+ s.required_ruby_version = "> 9"
+ end
+
+ fetcher.download "rubygems-update", 8 do |s|
+ s.files = %w[setup.rb]
+ end
+ end
+
+ @cmd.options[:args] = []
+ @cmd.options[:system] = true
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ err = @ui.error.split "\n"
+ assert_empty err
+
+ out = @ui.output.split "\n"
+ assert_equal "Installing RubyGems 8", out.shift
+ assert_equal "RubyGems system software updated", out.shift
+ assert_empty out
+ end
+
def test_execute_system_multiple
spec_fetcher do |fetcher|
- fetcher.download 'rubygems-update', 8 do |s|
+ fetcher.download "rubygems-update", 8 do |s|
+ s.files = %w[setup.rb]
+ end
+
+ fetcher.download "rubygems-update", 9 do |s|
+ s.files = %w[setup.rb]
+ end
+ end
+
+ @cmd.options[:args] = []
+ @cmd.options[:system] = true
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ out = @ui.output.split "\n"
+ assert_equal "Installing RubyGems 9", out.shift
+ assert_equal "RubyGems system software updated", out.shift
+
+ assert_empty out
+ end
+
+ def test_execute_system_update_installed
+ spec_fetcher do |fetcher|
+ fetcher.download "rubygems-update", 8 do |s|
s.files = %w[setup.rb]
end
+ end
+
+ @cmd.options[:args] = []
+ @cmd.options[:system] = true
- fetcher.download 'rubygems-update', 9 do |s|
+ @cmd.execute
+
+ spec_fetcher do |fetcher|
+ fetcher.download "rubygems-update", 9 do |s|
s.files = %w[setup.rb]
end
end
+ @cmd = Gem::Commands::UpdateCommand.new
+ @cmd.options[:args] = []
+ @cmd.options[:system] = true
+
+ use_ui @ui do
+ @cmd.execute
+ end
+
+ out = @ui.output.split "\n"
+ assert_equal "Installing RubyGems 9", out.shift
+ assert_equal "RubyGems system software updated", out.shift
+
+ assert_empty out
+ end
+
+ def test_execute_system_update_installed_in_non_default_gem_path
+ rubygems_update_spec = Gem::Specification.new do |s|
+ s.name = "rubygems-update"
+ s.version = "9"
+ s.author = "A User"
+ s.email = "example@example.com"
+ s.homepage = "http://example.com"
+ s.summary = "this is a summary"
+ s.description = "This is a test description"
+
+ write_file File.join(@tempdir, "setup.rb")
+
+ s.files += %w[setup.rb]
+ end
+
+ util_setup_spec_fetcher rubygems_update_spec
+
+ rubygems_update_package = Gem::Package.build rubygems_update_spec
+
+ gemhome2 = "#{@gemhome}2"
+
+ Gem::Installer.at(rubygems_update_package, install_dir: gemhome2).install
+
+ Gem.use_paths @gemhome, [gemhome2, @gemhome]
+
@cmd.options[:args] = []
@cmd.options[:system] = true
@@ -125,7 +249,6 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
end
out = @ui.output.split "\n"
- assert_equal "Updating rubygems-update", out.shift
assert_equal "Installing RubyGems 9", out.shift
assert_equal "RubyGems system software updated", out.shift
@@ -134,11 +257,11 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
def test_execute_system_specific
spec_fetcher do |fetcher|
- fetcher.download 'rubygems-update', 8 do |s|
+ fetcher.download "rubygems-update", 8 do |s|
s.files = %w[setup.rb]
end
- fetcher.download 'rubygems-update', 9 do |s|
+ fetcher.download "rubygems-update", 9 do |s|
s.files = %w[setup.rb]
end
end
@@ -151,7 +274,6 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
end
out = @ui.output.split "\n"
- assert_equal "Updating rubygems-update", out.shift
assert_equal "Installing RubyGems 8", out.shift
assert_equal "RubyGems system software updated", out.shift
@@ -160,7 +282,7 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
def test_execute_system_specific_older_than_minimum_supported_rubygems
spec_fetcher do |fetcher|
- fetcher.download 'rubygems-update', "2.5.1" do |s|
+ fetcher.download "rubygems-update", "2.5.1" do |s|
s.files = %w[setup.rb]
end
end
@@ -189,7 +311,7 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
def test_execute_system_specific_older_than_3_2_removes_plugins_dir
spec_fetcher do |fetcher|
- fetcher.download 'rubygems-update', 3.1 do |s|
+ fetcher.download "rubygems-update", 3.1 do |s|
s.files = %w[setup.rb]
end
end
@@ -207,7 +329,7 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
@cmd.options[:system] = "3.1"
FileUtils.mkdir_p Gem.plugindir
- write_file File.join(Gem.plugindir, 'a_plugin.rb')
+ write_file File.join(Gem.plugindir, "a_plugin.rb")
@cmd.execute
@@ -216,7 +338,7 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
def test_execute_system_specific_newer_than_or_equal_to_3_2_leaves_plugins_dir_alone
spec_fetcher do |fetcher|
- fetcher.download 'rubygems-update', "3.2.a" do |s|
+ fetcher.download "rubygems-update", "3.2.a" do |s|
s.files = %w[setup.rb]
end
end
@@ -234,7 +356,7 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
@cmd.options[:system] = "3.2.a"
FileUtils.mkdir_p Gem.plugindir
- plugin_file = File.join(Gem.plugindir, 'a_plugin.rb')
+ plugin_file = File.join(Gem.plugindir, "a_plugin.rb")
write_file plugin_file
@cmd.execute
@@ -245,11 +367,11 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
def test_execute_system_specifically_to_latest_version
spec_fetcher do |fetcher|
- fetcher.download 'rubygems-update', 8 do |s|
+ fetcher.download "rubygems-update", 8 do |s|
s.files = %w[setup.rb]
end
- fetcher.download 'rubygems-update', 9 do |s|
+ fetcher.download "rubygems-update", 9 do |s|
s.files = %w[setup.rb]
end
end
@@ -262,7 +384,6 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
end
out = @ui.output.split "\n"
- assert_equal "Updating rubygems-update", out.shift
assert_equal "Installing RubyGems 9", out.shift
assert_equal "RubyGems system software updated", out.shift
@@ -310,12 +431,12 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
@cmd.options[:system] = true
@cmd.options[:silent] = true
- assert_equal true, @cmd.update_rubygems_arguments.include?('--silent')
+ assert_equal true, @cmd.update_rubygems_arguments.include?("--silent")
end
def test_execute_system_silent
spec_fetcher do |fetcher|
- fetcher.download 'rubygems-update', 9 do |s|
+ fetcher.download "rubygems-update", 9 do |s|
s.files = %w[setup.rb]
end
end
@@ -339,12 +460,12 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
def test_execute_dependencies
spec_fetcher do |fetcher|
- fetcher.download 'a', 2, 'b' => 2, 'c' => 2
- fetcher.download 'b', 2
- fetcher.download 'c', 2
+ fetcher.download "a", 2, "b" => 2, "c" => 2
+ fetcher.download "b", 2
+ fetcher.download "c", 2
- fetcher.spec 'a', 1, 'c' => '1.2'
- fetcher.spec 'c', '1.2'
+ fetcher.spec "a", 1, "c" => "1.2"
+ fetcher.spec "c", "1.2"
end
Gem::Specification.reset
@@ -366,8 +487,8 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
def test_execute_rdoc
spec_fetcher do |fetcher|
- fetcher.download 'a', 2
- fetcher.spec 'a', 1
+ fetcher.download "a", 2
+ fetcher.spec "a", 1
end
Gem.done_installing(&Gem::RDoc.method(:generation_hook))
@@ -382,16 +503,16 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
wait_for_child_process_to_exit
- a2 = @specs['a-2']
+ a2 = @specs["a-2"]
- assert_path_exist File.join(a2.doc_dir, 'rdoc')
- end
+ assert_path_exist File.join(a2.doc_dir, "rdoc")
+ end if defined?(Gem::RDoc)
def test_execute_named
spec_fetcher do |fetcher|
- fetcher.download 'a', 2
+ fetcher.download "a", 2
- fetcher.spec 'a', 1
+ fetcher.spec "a", 1
end
@cmd.options[:args] = %w[a]
@@ -410,10 +531,10 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
def test_execute_named_some_up_to_date
spec_fetcher do |fetcher|
- fetcher.download 'a', 2
- fetcher.spec 'a', 1
+ fetcher.download "a", 2
+ fetcher.spec "a", 1
- fetcher.spec 'b', 2
+ fetcher.spec "b", 2
end
@cmd.options[:args] = %w[a b]
@@ -433,7 +554,7 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
def test_execute_named_up_to_date
spec_fetcher do |fetcher|
- fetcher.spec 'a', 2
+ fetcher.spec "a", 2
end
@cmd.options[:args] = %w[a]
@@ -445,15 +566,16 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
out = @ui.output.split "\n"
assert_equal "Updating installed gems", out.shift
assert_equal "Nothing to update", out.shift
+ assert_equal "Gems already up-to-date: a", out.shift
assert_empty out
end
def test_execute_named_up_to_date_prerelease
spec_fetcher do |fetcher|
- fetcher.download 'a', '3.a'
+ fetcher.download "a", "3.a"
- fetcher.gem 'a', 2
+ fetcher.gem "a", 2
end
@cmd.options[:args] = %w[a]
@@ -473,7 +595,7 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
def test_execute_up_to_date
spec_fetcher do |fetcher|
- fetcher.gem 'a', 2
+ fetcher.gem "a", 2
end
@cmd.options[:args] = []
@@ -515,73 +637,73 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
def test_fetch_remote_gems
specs = spec_fetcher do |fetcher|
- fetcher.gem 'a', 1
- fetcher.gem 'a', 2
+ fetcher.gem "a", 1
+ fetcher.gem "a", 2
end
expected = [
- [Gem::NameTuple.new('a', v(2), Gem::Platform::RUBY),
+ [Gem::NameTuple.new("a", v(2), Gem::Platform::RUBY),
Gem::Source.new(@gem_repo)],
]
- assert_equal expected, @cmd.fetch_remote_gems(specs['a-1'])
+ assert_equal expected, @cmd.fetch_remote_gems(specs["a-1"])
end
def test_fetch_remote_gems_error
Gem.sources.replace %w[http://nonexistent.example]
assert_raise Gem::RemoteFetcher::FetchError do
- @cmd.fetch_remote_gems @specs['a-1']
+ @cmd.fetch_remote_gems @specs["a-1"]
end
end
def test_fetch_remote_gems_mismatch
- platform = Gem::Platform.new 'x86-freebsd9'
+ platform = Gem::Platform.new "x86-freebsd9"
specs = spec_fetcher do |fetcher|
- fetcher.spec 'a', 1
- fetcher.spec 'a', 2
+ fetcher.spec "a", 1
+ fetcher.spec "a", 2
- fetcher.spec 'a', 2 do |s|
+ fetcher.spec "a", 2 do |s|
s.platform = platform
end
end
expected = [
- [Gem::NameTuple.new('a', v(2), Gem::Platform::RUBY),
+ [Gem::NameTuple.new("a", v(2), Gem::Platform::RUBY),
Gem::Source.new(@gem_repo)],
]
- assert_equal expected, @cmd.fetch_remote_gems(specs['a-1'])
+ assert_equal expected, @cmd.fetch_remote_gems(specs["a-1"])
end
def test_fetch_remote_gems_prerelease
specs = spec_fetcher do |fetcher|
- fetcher.gem 'a', 1
- fetcher.gem 'a', 2
- fetcher.gem 'a', '3.a'
+ fetcher.gem "a", 1
+ fetcher.gem "a", 2
+ fetcher.gem "a", "3.a"
end
@cmd.options[:prerelease] = true
expected = [
- [Gem::NameTuple.new('a', v(2), Gem::Platform::RUBY),
+ [Gem::NameTuple.new("a", v(2), Gem::Platform::RUBY),
Gem::Source.new(@gem_repo)],
- [Gem::NameTuple.new('a', v('3.a'), Gem::Platform::RUBY),
+ [Gem::NameTuple.new("a", v("3.a"), Gem::Platform::RUBY),
Gem::Source.new(@gem_repo)],
]
- assert_equal expected, @cmd.fetch_remote_gems(specs['a-1'])
+ assert_equal expected, @cmd.fetch_remote_gems(specs["a-1"])
end
def test_handle_options_system
@cmd.handle_options %w[--system]
expected = {
- :args => [],
- :document => %w[ri],
- :force => false,
- :system => true,
+ args: [],
+ document: %w[ri],
+ force: false,
+ system: true,
}
assert_equal expected, @cmd.options
@@ -597,10 +719,10 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
@cmd.handle_options %w[--system 1.3.7]
expected = {
- :args => [],
- :document => %w[ri],
- :force => false,
- :system => "1.3.7",
+ args: [],
+ document: %w[ri],
+ force: false,
+ system: "1.3.7",
}
assert_equal expected, @cmd.options
@@ -608,11 +730,11 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
def test_update_gem_prerelease
spec_fetcher do |fetcher|
- fetcher.spec 'a', '1.a'
- fetcher.gem 'a', '1.b'
+ fetcher.spec "a", "1.a"
+ fetcher.gem "a", "1.b"
end
- @cmd.update_gem 'a', Gem::Requirement.new('= 1.b')
+ @cmd.update_gem "a", Gem::Requirement.new("= 1.b")
refute_empty @cmd.updated
@@ -621,15 +743,15 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
def test_update_gem_unresolved_dependency
spec_fetcher do |fetcher|
- fetcher.spec 'a', 1
- fetcher.gem 'a', 2 do |s|
- s.add_dependency 'b', '>= 2'
+ fetcher.spec "a", 1
+ fetcher.gem "a", 2 do |s|
+ s.add_dependency "b", ">= 2"
end
- fetcher.spec 'b', 1
+ fetcher.spec "b", 1
end
- @cmd.update_gem 'a'
+ @cmd.update_gem "a"
assert_empty @cmd.updated
end
@@ -639,18 +761,18 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
arguments = @cmd.update_rubygems_arguments
- assert_equal '--prefix', arguments.shift
+ assert_equal "--prefix", arguments.shift
assert_equal Gem.prefix, arguments.shift
- assert_equal '--no-document', arguments.shift
- assert_equal '--previous-version', arguments.shift
+ assert_equal "--no-document", arguments.shift
+ assert_equal "--previous-version", arguments.shift
assert_equal Gem::VERSION, arguments.shift
assert_empty arguments
end
def test_explain
spec_fetcher do |fetcher|
- fetcher.download 'a', 2
- fetcher.spec 'a', 1
+ fetcher.download "a", 2
+ fetcher.spec "a", 1
end
@cmd.options[:explain] = true
@@ -670,13 +792,13 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
def test_explain_platform_local
local = Gem::Platform.local
spec_fetcher do |fetcher|
- fetcher.download 'a', 2
+ fetcher.download "a", 2
- fetcher.download 'a', 2 do |s|
+ fetcher.download "a", 2 do |s|
s.platform = local
end
- fetcher.spec 'a', 1
+ fetcher.spec "a", 1
end
@cmd.options[:explain] = true
@@ -696,13 +818,13 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
def test_explain_platform_ruby
local = Gem::Platform.local
spec_fetcher do |fetcher|
- fetcher.download 'a', 2
+ fetcher.download "a", 2
- fetcher.download 'a', 2 do |s|
+ fetcher.download "a", 2 do |s|
s.platform = local
end
- fetcher.spec 'a', 1
+ fetcher.spec "a", 1
end
# equivalent to --platform=ruby
@@ -721,4 +843,24 @@ class TestGemCommandsUpdateCommand < Gem::TestCase
assert_equal " a-2", out.shift
assert_empty out
end
+
+ def test_execute_named_not_installed_and_no_update
+ spec_fetcher do |fetcher|
+ fetcher.spec "a", 2
+ end
+
+ @cmd.options[:args] = %w[a b]
+
+ 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_equal "Gems already up-to-date: a", out.shift
+ assert_equal "Gems not currently installed: b", out.shift
+
+ assert_empty out
+ end
end
diff --git a/test/rubygems/test_gem_commands_which_command.rb b/test/rubygems/test_gem_commands_which_command.rb
index a398dc5708..cbd5b5ef14 100644
--- a/test/rubygems/test_gem_commands_which_command.rb
+++ b/test/rubygems/test_gem_commands_which_command.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/commands/which_command'
+
+require_relative "helper"
+require "rubygems/commands/which_command"
class TestGemCommandsWhichCommand < Gem::TestCase
def setup
@@ -19,7 +20,7 @@ class TestGemCommandsWhichCommand < Gem::TestCase
end
assert_equal "#{@foo_bar.full_gem_path}/lib/foo_bar.rb\n", @ui.output
- assert_equal '', @ui.error
+ assert_equal "", @ui.error
end
def test_execute_directory
@@ -31,9 +32,9 @@ class TestGemCommandsWhichCommand < Gem::TestCase
end
end
- assert_equal '', @ui.output
- assert_match %r{Can.t find Ruby library file or shared library directory\n},
- @ui.error
+ assert_equal "", @ui.output
+ assert_match(/Can.t find Ruby library file or shared library directory\n/,
+ @ui.error)
end
def test_execute_one_missing
@@ -50,8 +51,8 @@ class TestGemCommandsWhichCommand < Gem::TestCase
end
assert_equal "#{@foo_bar.full_gem_path}/lib/foo_bar.rb\n", @ui.output
- assert_match %r{Can.t find Ruby library file or shared library missinglib\n},
- @ui.error
+ assert_match(/Can.t find Ruby library file or shared library missinglib\n/,
+ @ui.error)
end
def test_execute_missing
@@ -63,14 +64,14 @@ class TestGemCommandsWhichCommand < Gem::TestCase
end
end
- assert_equal '', @ui.output
- assert_match %r{Can.t find Ruby library file or shared library missinglib\n},
- @ui.error
+ assert_equal "", @ui.output
+ assert_match(/Can.t find Ruby library file or shared library missinglib\n/,
+ @ui.error)
end
def util_foo_bar
files = %w[lib/foo_bar.rb lib/directory/baz.rb Rakefile]
- @foo_bar = util_spec 'foo_bar' do |gem|
+ @foo_bar = util_spec "foo_bar" do |gem|
gem.files = files
end
install_specs @foo_bar
diff --git a/test/rubygems/test_gem_commands_yank_command.rb b/test/rubygems/test_gem_commands_yank_command.rb
index 3b0956e1c4..eb78e3a542 100644
--- a/test/rubygems/test_gem_commands_yank_command.rb
+++ b/test/rubygems/test_gem_commands_yank_command.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/commands/yank_command'
+
+require_relative "helper"
+require_relative "multifactor_auth_utilities"
+require "rubygems/commands/yank_command"
class TestGemCommandsYankCommand < Gem::TestCase
def setup
@@ -9,12 +11,13 @@ class TestGemCommandsYankCommand < Gem::TestCase
credential_setup
@cmd = Gem::Commands::YankCommand.new
- @cmd.options[:host] = 'http://example'
+ @cmd.options[:host] = "http://example"
- @fetcher = Gem::RemoteFetcher.fetcher
+ @fetcher = Gem::MultifactorAuthFetcher.new(host: "http://example")
+ Gem::RemoteFetcher.fetcher = @fetcher
- Gem.configuration.rubygems_api_key = 'key'
- Gem.configuration.api_keys[:KEY] = 'other'
+ Gem.configuration.rubygems_api_key = "key"
+ Gem.configuration.api_keys[:KEY] = "other"
end
def teardown
@@ -30,109 +33,225 @@ class TestGemCommandsYankCommand < Gem::TestCase
assert_equal :KEY, @cmd.options[:key]
assert_equal "HOST", @cmd.options[:host]
assert_nil @cmd.options[:platform]
- assert_equal req('= 1.0'), @cmd.options[:version]
+ assert_equal req("= 1.0"), @cmd.options[:version]
end
def test_handle_options_missing_argument
%w[-v --version -p --platform].each do |option|
- assert_raise OptionParser::MissingArgument do
+ assert_raise Gem::OptionParser::MissingArgument do
@cmd.handle_options %W[a #{option}]
end
end
end
def test_execute
- yank_uri = 'http://example/api/v1/gems/yank'
- @fetcher.data[yank_uri] = ['Successfully yanked', 200, 'OK']
+ yank_uri = "http://example/api/v1/gems/yank"
+ @fetcher.data[yank_uri] = HTTPResponseFactory.create(body: "Successfully yanked", code: 200, msg: "OK")
@cmd.options[:args] = %w[a]
@cmd.options[:added_platform] = true
- @cmd.options[:version] = req('= 1.0')
+ @cmd.options[:version] = req("= 1.0")
use_ui @ui do
@cmd.execute
end
assert_match %r{Yanking gem from http://example}, @ui.output
- assert_match %r{Successfully yanked}, @ui.output
+ assert_match(/Successfully yanked/, @ui.output)
platform = Gem.platforms[1]
- body = @fetcher.last_request.body.split('&').sort
+ body = @fetcher.last_request.body.split("&").sort
assert_equal %W[gem_name=a platform=#{platform} version=1.0], body
- assert_equal 'key', @fetcher.last_request['Authorization']
+ assert_equal "key", @fetcher.last_request["Authorization"]
assert_equal [yank_uri], @fetcher.paths
end
def test_execute_with_otp_success
- response_fail = 'You have enabled multifactor authentication but your request doesn\'t have the correct OTP code. Please check it and retry.'
- yank_uri = 'http://example/api/v1/gems/yank'
+ response_fail = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry."
+ yank_uri = "http://example/api/v1/gems/yank"
@fetcher.data[yank_uri] = [
- [response_fail, 401, 'Unauthorized'],
- ['Successfully yanked', 200, 'OK'],
+ HTTPResponseFactory.create(body: response_fail, code: 401, msg: "Unauthorized"),
+ HTTPResponseFactory.create(body: "Successfully yanked", code: 200, msg: "OK"),
]
@cmd.options[:args] = %w[a]
@cmd.options[:added_platform] = true
- @cmd.options[:version] = req('= 1.0')
+ @cmd.options[:version] = req("= 1.0")
@otp_ui = Gem::MockGemUi.new "111111\n"
use_ui @otp_ui do
@cmd.execute
end
- assert_match 'You have enabled multi-factor authentication. Please enter OTP code.', @otp_ui.output
- assert_match 'Code: ', @otp_ui.output
+ assert_match "You have enabled multi-factor authentication. Please enter OTP code.", @otp_ui.output
+ assert_match "Code: ", @otp_ui.output
assert_match %r{Yanking gem from http://example}, @otp_ui.output
- assert_match %r{Successfully yanked}, @otp_ui.output
- assert_equal '111111', @fetcher.last_request['OTP']
+ assert_match(/Successfully yanked/, @otp_ui.output)
+ assert_equal "111111", @fetcher.last_request["OTP"]
end
def test_execute_with_otp_failure
- response = 'You have enabled multifactor authentication but your request doesn\'t have the correct OTP code. Please check it and retry.'
- yank_uri = 'http://example/api/v1/gems/yank'
- @fetcher.data[yank_uri] = [response, 401, 'Unauthorized']
+ response = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry."
+ yank_uri = "http://example/api/v1/gems/yank"
+ @fetcher.data[yank_uri] = HTTPResponseFactory.create(body: response, code: 401, msg: "Unauthorized")
@cmd.options[:args] = %w[a]
@cmd.options[:added_platform] = true
- @cmd.options[:version] = req('= 1.0')
+ @cmd.options[:version] = req("= 1.0")
@otp_ui = Gem::MockGemUi.new "111111\n"
use_ui @otp_ui do
@cmd.execute
end
- assert_match 'You have enabled multi-factor authentication. Please enter OTP code.', @otp_ui.output
+ assert_match "You have enabled multi-factor authentication. Please enter OTP code.", @otp_ui.output
assert_match response, @otp_ui.output
- assert_match 'Code: ', @otp_ui.output
- assert_equal '111111', @fetcher.last_request['OTP']
+ assert_match "Code: ", @otp_ui.output
+ assert_equal "111111", @fetcher.last_request["OTP"]
+ end
+
+ def test_with_webauthn_enabled_success
+ server = Gem::MockTCPServer.new
+
+ @fetcher.respond_with_require_otp("http://example/api/v1/gems/yank", "Successfully yanked")
+ @fetcher.respond_with_webauthn_url
+
+ @cmd.options[:args] = %w[a]
+ @cmd.options[:added_platform] = true
+ @cmd.options[:version] = req("= 1.0")
+
+ TCPServer.stub(:new, server) do
+ Gem::GemcutterUtilities::WebauthnListener.stub(:listener_thread, Thread.new { Thread.current[:otp] = "Uvh6T57tkWuUnWYo" }) do
+ use_ui @ui do
+ @cmd.execute
+ end
+ end
+ end
+
+ assert_match %r{Yanking gem from http://example}, @ui.output
+ assert_match "You have enabled multi-factor authentication. Please visit #{@fetcher.webauthn_url_with_port(server.port)} " \
+ "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, " \
+ "you can re-run the gem signin command with the `--otp [your_code]` option.", @ui.output
+ assert_match "You are verified with a security device. You may close the browser window.", @ui.output
+ assert_equal "Uvh6T57tkWuUnWYo", @fetcher.last_request["OTP"]
+ assert_match "Successfully yanked", @ui.output
+ end
+
+ def test_with_webauthn_enabled_failure
+ server = Gem::MockTCPServer.new
+ error = Gem::WebauthnVerificationError.new("Something went wrong")
+
+ @fetcher.respond_with_require_otp("http://example/api/v1/gems/yank", "Successfully yanked")
+ @fetcher.respond_with_webauthn_url
+
+ @cmd.options[:args] = %w[a]
+ @cmd.options[:added_platform] = true
+ @cmd.options[:version] = req("= 1.0")
+
+ error = assert_raise Gem::MockGemUi::TermError do
+ TCPServer.stub(:new, server) do
+ Gem::GemcutterUtilities::WebauthnListener.stub(:listener_thread, Thread.new { Thread.current[:error] = error }) do
+ use_ui @ui do
+ @cmd.execute
+ end
+ end
+ end
+ end
+ assert_equal 1, error.exit_code
+
+ assert_match @fetcher.last_request["Authorization"], Gem.configuration.rubygems_api_key
+ assert_match %r{Yanking gem from http://example}, @ui.output
+ assert_match "You have enabled multi-factor authentication. Please visit #{@fetcher.webauthn_url_with_port(server.port)} " \
+ "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, " \
+ "you can re-run the gem signin command with the `--otp [your_code]` option.", @ui.output
+ assert_match "ERROR: Security device verification failed: Something went wrong", @ui.error
+ refute_match "You are verified with a security device. You may close the browser window.", @ui.output
+ refute_match "Successfully yanked", @ui.output
+ end
+
+ def test_with_webauthn_enabled_success_with_polling
+ server = Gem::MockTCPServer.new
+
+ @fetcher.respond_with_require_otp("http://example/api/v1/gems/yank", "Successfully yanked")
+ @fetcher.respond_with_webauthn_url
+ @fetcher.respond_with_webauthn_polling("Uvh6T57tkWuUnWYo")
+
+ @cmd.options[:args] = %w[a]
+ @cmd.options[:added_platform] = true
+ @cmd.options[:version] = req("= 1.0")
+
+ TCPServer.stub(:new, server) do
+ use_ui @ui do
+ @cmd.execute
+ end
+ end
+
+ assert_match %r{Yanking gem from http://example}, @ui.output
+ assert_match "You have enabled multi-factor authentication. Please visit #{@fetcher.webauthn_url_with_port(server.port)} " \
+ "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, " \
+ "you can re-run the gem signin command with the `--otp [your_code]` option.", @ui.output
+ assert_match "You are verified with a security device. You may close the browser window.", @ui.output
+ assert_equal "Uvh6T57tkWuUnWYo", @fetcher.last_request["OTP"]
+ assert_match "Successfully yanked", @ui.output
+ end
+
+ def test_with_webauthn_enabled_failure_with_polling
+ server = Gem::MockTCPServer.new
+
+ @fetcher.respond_with_require_otp("http://example/api/v1/gems/yank", "Successfully yanked")
+ @fetcher.respond_with_webauthn_url
+ @fetcher.respond_with_webauthn_polling_failure
+
+ @cmd.options[:args] = %w[a]
+ @cmd.options[:added_platform] = true
+ @cmd.options[:version] = req("= 1.0")
+
+ error = assert_raise Gem::MockGemUi::TermError do
+ TCPServer.stub(:new, server) do
+ use_ui @ui do
+ @cmd.execute
+ end
+ end
+ end
+ assert_equal 1, error.exit_code
+
+ assert_match @fetcher.last_request["Authorization"], Gem.configuration.rubygems_api_key
+ assert_match %r{Yanking gem from http://example}, @ui.output
+ assert_match "You have enabled multi-factor authentication. Please visit #{@fetcher.webauthn_url_with_port(server.port)} " \
+ "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, " \
+ "you can re-run the gem signin command with the `--otp [your_code]` option.", @ui.output
+ assert_match "ERROR: Security device verification failed: The token in the link you used has either expired " \
+ "or been used already.", @ui.error
+ refute_match "You are verified with a security device. You may close the browser window.", @ui.output
+ refute_match "Successfully yanked", @ui.output
end
def test_execute_key
- yank_uri = 'http://example/api/v1/gems/yank'
- @fetcher.data[yank_uri] = ['Successfully yanked', 200, 'OK']
+ yank_uri = "http://example/api/v1/gems/yank"
+ @fetcher.data[yank_uri] = HTTPResponseFactory.create(body: "Successfully yanked", code: 200, msg: "OK")
@cmd.options[:args] = %w[a]
- @cmd.options[:version] = req('= 1.0')
+ @cmd.options[:version] = req("= 1.0")
@cmd.options[:key] = :KEY
use_ui @ui do
@cmd.execute
end
- body = @fetcher.last_request.body.split('&').sort
+ body = @fetcher.last_request.body.split("&").sort
assert_equal %w[gem_name=a version=1.0], body
- assert_equal 'other', @fetcher.last_request['Authorization']
+ assert_equal "other", @fetcher.last_request["Authorization"]
end
def test_execute_host
- host = 'https://other.example'
+ host = "https://other.example"
yank_uri = "#{host}/api/v1/gems/yank"
- @fetcher.data[yank_uri] = ['Successfully yanked', 200, 'OK']
+ @fetcher.data[yank_uri] = HTTPResponseFactory.create(body: "Successfully yanked", code: 200, msg: "OK")
@cmd.options[:args] = %w[a]
- @cmd.options[:version] = req('= 1.0')
+ @cmd.options[:version] = req("= 1.0")
@cmd.options[:host] = host
use_ui @ui do
@@ -140,28 +259,28 @@ class TestGemCommandsYankCommand < Gem::TestCase
end
assert_match %r{Yanking gem from https://other.example}, @ui.output
- assert_match %r{Successfully yanked}, @ui.output
+ assert_match(/Successfully yanked/, @ui.output)
- body = @fetcher.last_request.body.split('&').sort
+ body = @fetcher.last_request.body.split("&").sort
assert_equal %w[gem_name=a version=1.0], body
- assert_equal 'key', @fetcher.last_request['Authorization']
+ assert_equal "key", @fetcher.last_request["Authorization"]
assert_equal [yank_uri], @fetcher.paths
end
def test_yank_gem_unathorized_api_key
response_forbidden = "The API key doesn't have access"
- response_success = 'Successfully yanked'
- host = 'http://example'
+ response_success = "Successfully yanked"
+ host = "http://example"
@fetcher.data["#{host}/api/v1/gems/yank"] = [
- [response_forbidden, 403, 'Forbidden'],
- [response_success, 200, "OK"],
+ HTTPResponseFactory.create(body: response_forbidden, code: 403, msg: "Forbidden"),
+ HTTPResponseFactory.create(body: response_success, code: 200, msg: "OK"),
]
- @fetcher.data["#{host}/api/v1/api_key"] = ["", 200, "OK"]
+ @fetcher.data["#{host}/api/v1/api_key"] = HTTPResponseFactory.create(body: "", code: 200, msg: "OK")
@cmd.options[:args] = %w[a]
@cmd.options[:added_platform] = true
- @cmd.options[:version] = req('= 1.0')
+ @cmd.options[:version] = req("= 1.0")
@cmd.instance_variable_set :@host, host
@cmd.instance_variable_set :@scope, :yank_rubygem
@@ -172,7 +291,7 @@ class TestGemCommandsYankCommand < Gem::TestCase
access_notice = "The existing key doesn't have access of yank_rubygem on http://example. Please sign in to update access."
assert_match access_notice, @ui.output
- assert_match "Email:", @ui.output
+ assert_match "Username/email:", @ui.output
assert_match "Password:", @ui.output
assert_match "Added yank_rubygem scope to the existing API key", @ui.output
assert_match response_success, @ui.output
diff --git a/test/rubygems/test_gem_config_file.rb b/test/rubygems/test_gem_config_file.rb
index 32375e6936..4230eda4d3 100644
--- a/test/rubygems/test_gem_config_file.rb
+++ b/test/rubygems/test_gem_config_file.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/config_file'
+
+require_relative "helper"
+require "rubygems/config_file"
class TestGemConfigFile < Gem::TestCase
def setup
@@ -8,15 +9,15 @@ class TestGemConfigFile < Gem::TestCase
credential_setup
- @temp_conf = File.join @tempdir, '.gemrc'
+ @temp_conf = File.join @tempdir, ".gemrc"
@cfg_args = %W[--config-file #{@temp_conf}]
Gem::ConfigFile::OPERATING_SYSTEM_DEFAULTS.clear
Gem::ConfigFile::PLATFORM_DEFAULTS.clear
- @env_gemrc = ENV['GEMRC']
- ENV['GEMRC'] = ''
+ @env_gemrc = ENV["GEMRC"]
+ ENV["GEMRC"] = ""
util_config_file
end
@@ -25,7 +26,7 @@ class TestGemConfigFile < Gem::TestCase
Gem::ConfigFile::OPERATING_SYSTEM_DEFAULTS.clear
Gem::ConfigFile::PLATFORM_DEFAULTS.clear
- ENV['GEMRC'] = @env_gemrc
+ ENV["GEMRC"] = @env_gemrc
credential_teardown
@@ -35,7 +36,7 @@ class TestGemConfigFile < Gem::TestCase
def test_initialize
assert_equal @temp_conf, @cfg.config_file_name
- assert_equal false, @cfg.backtrace
+ assert_equal true, @cfg.backtrace
assert_equal true, @cfg.update_sources
assert_equal Gem::ConfigFile::DEFAULT_BULK_THRESHOLD, @cfg.bulk_threshold
assert_equal true, @cfg.verbose
@@ -43,7 +44,7 @@ class TestGemConfigFile < Gem::TestCase
assert_equal 365, @cfg.cert_expiration_length_days
assert_equal false, @cfg.ipv4_fallback_enabled
- File.open @temp_conf, 'w' do |fp|
+ File.open @temp_conf, "w" do |fp|
fp.puts ":backtrace: true"
fp.puts ":update_sources: false"
fp.puts ":bulk_threshold: 10"
@@ -57,6 +58,7 @@ class TestGemConfigFile < Gem::TestCase
fp.puts ":ssl_verify_mode: 0"
fp.puts ":ssl_ca_cert: /etc/ssl/certs"
fp.puts ":cert_expiration_length_days: 28"
+ fp.puts ":install_extension_in_lib: true"
fp.puts ":ipv4_fallback_enabled: true"
end
@@ -66,17 +68,18 @@ class TestGemConfigFile < Gem::TestCase
assert_equal false, @cfg.verbose
assert_equal false, @cfg.update_sources
assert_equal %w[http://more-gems.example.com], @cfg.sources
- assert_equal '--wrappers', @cfg[:install]
- assert_equal(['/usr/ruby/1.8/lib/ruby/gems/1.8', '/var/ruby/1.8/gem_home'],
+ assert_equal "--wrappers", @cfg[:install]
+ assert_equal(["/usr/ruby/1.8/lib/ruby/gems/1.8", "/var/ruby/1.8/gem_home"],
@cfg.path)
assert_equal 0, @cfg.ssl_verify_mode
- assert_equal '/etc/ssl/certs', @cfg.ssl_ca_cert
+ assert_equal "/etc/ssl/certs", @cfg.ssl_ca_cert
assert_equal 28, @cfg.cert_expiration_length_days
+ assert_equal true, @cfg.install_extension_in_lib
assert_equal true, @cfg.ipv4_fallback_enabled
end
def test_initialize_ipv4_fallback_enabled_env
- ENV['IPV4_FALLBACK_ENABLED'] = 'true'
+ ENV["IPV4_FALLBACK_ENABLED"] = "true"
util_config_file %W[--config-file #{@temp_conf}]
assert_equal true, @cfg.ipv4_fallback_enabled
@@ -102,37 +105,37 @@ class TestGemConfigFile < Gem::TestCase
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::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]
+ 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'
+ Gem::ConfigFile::PLATFORM_DEFAULTS["install"] = "--no-env-shebang"
- File.open Gem::ConfigFile::SYSTEM_WIDE_CONFIG_FILE, 'w' do |fp|
+ 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]
+ 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|
+ 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|
+ File.open @temp_conf, "w" do |fp|
fp.puts ":backtrace: true"
end
@@ -143,28 +146,28 @@ class TestGemConfigFile < Gem::TestCase
end
def test_initialize_environment_variable_override
- File.open Gem::ConfigFile::SYSTEM_WIDE_CONFIG_FILE, 'w' do |fp|
- fp.puts ':backtrace: false'
- fp.puts ':verbose: false'
- fp.puts ':bulk_threshold: 2048'
+ File.open Gem::ConfigFile::SYSTEM_WIDE_CONFIG_FILE, "w" do |fp|
+ fp.puts ":backtrace: false"
+ fp.puts ":verbose: false"
+ fp.puts ":bulk_threshold: 2048"
end
- conf1 = File.join @tempdir, 'gemrc1'
- File.open conf1, 'w' do |fp|
- fp.puts ':backtrace: true'
+ conf1 = File.join @tempdir, "gemrc1"
+ File.open conf1, "w" do |fp|
+ fp.puts ":backtrace: true"
end
- conf2 = File.join @tempdir, 'gemrc2'
- File.open conf2, 'w' do |fp|
- fp.puts ':verbose: true'
+ conf2 = File.join @tempdir, "gemrc2"
+ File.open conf2, "w" do |fp|
+ fp.puts ":verbose: true"
end
- conf3 = File.join @tempdir, 'gemrc3'
- File.open conf3, 'w' do |fp|
- fp.puts ':verbose: :loud'
+ conf3 = File.join @tempdir, "gemrc3"
+ File.open conf3, "w" do |fp|
+ fp.puts ":verbose: :loud"
end
ps = File::PATH_SEPARATOR
- ENV['GEMRC'] = conf1 + ps + conf2 + ps + conf3
+ ENV["GEMRC"] = conf1 + ps + conf2 + ps + conf3
util_config_file
@@ -174,7 +177,7 @@ class TestGemConfigFile < Gem::TestCase
end
def test_set_config_file_name_from_environment_variable
- ENV['GEMRC'] = "/tmp/.gemrc"
+ ENV["GEMRC"] = "/tmp/.gemrc"
cfg = Gem::ConfigFile.new([])
assert_equal cfg.config_file_name, "/tmp/.gemrc"
end
@@ -182,24 +185,24 @@ class TestGemConfigFile < Gem::TestCase
def test_api_keys
assert_nil @cfg.instance_variable_get :@api_keys
- temp_cred = File.join Gem.user_home, '.gem', 'credentials'
+ temp_cred = File.join Gem.user_home, ".gem", "credentials"
FileUtils.mkdir_p File.dirname(temp_cred)
- File.open temp_cred, 'w', 0600 do |fp|
- fp.puts ':rubygems_api_key: 701229f217cdf23b1344c7b4b54ca97'
+ File.open temp_cred, "w", 0o600 do |fp|
+ fp.puts ":rubygems_api_key: 701229f217cdf23b1344c7b4b54ca97"
end
util_config_file
- assert_equal({:rubygems => '701229f217cdf23b1344c7b4b54ca97'},
+ assert_equal({ rubygems: "701229f217cdf23b1344c7b4b54ca97" },
@cfg.api_keys)
end
def test_check_credentials_permissions
- pend 'chmod not supported' if win_platform?
+ pend "chmod not supported" if Gem.win_platform?
- @cfg.rubygems_api_key = 'x'
+ @cfg.rubygems_api_key = "x"
- File.chmod 0644, @cfg.credentials_path
+ File.chmod 0o644, @cfg.credentials_path
use_ui @ui do
assert_raise Gem::MockGemUi::TermError do
@@ -239,6 +242,12 @@ if you believe they were disclosed to a third party.
end
def test_handle_arguments_backtrace
+ File.open @temp_conf, "w" do |fp|
+ fp.puts ":backtrace: false"
+ end
+
+ util_config_file %W[--config-file=#{@temp_conf}]
+
assert_equal false, @cfg.backtrace
args = %w[--backtrace]
@@ -257,7 +266,7 @@ if you believe they were disclosed to a third party.
@cfg.handle_arguments args
end
- assert_match 'NOTE', err
+ assert_match "NOTE", err
assert_equal true, $DEBUG
ensure
@@ -265,7 +274,7 @@ if you believe they were disclosed to a third party.
end
def test_handle_arguments_override
- File.open @temp_conf, 'w' do |fp|
+ File.open @temp_conf, "w" do |fp|
fp.puts ":backtrace: false"
end
@@ -275,6 +284,12 @@ if you believe they were disclosed to a third party.
end
def test_handle_arguments_traceback
+ File.open @temp_conf, "w" do |fp|
+ fp.puts ":backtrace: false"
+ end
+
+ util_config_file %W[--config-file=#{@temp_conf}]
+
assert_equal false, @cfg.backtrace
args = %w[--traceback]
@@ -287,8 +302,8 @@ if you believe they were disclosed to a third party.
def test_handle_arguments_norc
assert_equal @temp_conf, @cfg.config_file_name
- File.open @temp_conf, 'w' do |fp|
- fp.puts ":backtrace: true"
+ File.open @temp_conf, "w" do |fp|
+ fp.puts ":backtrace: false"
fp.puts ":update_sources: false"
fp.puts ":bulk_threshold: 10"
fp.puts ":verbose: false"
@@ -300,7 +315,7 @@ if you believe they were disclosed to a third party.
util_config_file args
- assert_equal false, @cfg.backtrace
+ assert_equal true, @cfg.backtrace
assert_equal true, @cfg.update_sources
assert_equal Gem::ConfigFile::DEFAULT_BULK_THRESHOLD, @cfg.bulk_threshold
assert_equal true, @cfg.verbose
@@ -308,25 +323,30 @@ if you believe they were disclosed to a third party.
end
def test_load_api_keys
- temp_cred = File.join Gem.user_home, '.gem', 'credentials'
+ temp_cred = File.join Gem.user_home, ".gem", "credentials"
FileUtils.mkdir_p File.dirname(temp_cred)
- File.open temp_cred, 'w', 0600 do |fp|
- fp.puts ":rubygems_api_key: 701229f217cdf23b1344c7b4b54ca97"
- fp.puts ":other: a5fdbb6ba150cbb83aad2bb2fede64c"
+ File.open temp_cred, "w", 0o600 do |fp|
+ fp.puts ":rubygems_api_key: rubygems_b9ce70c306b3a2e248679fbbbd66722d408d3c8c4f00566c"
+ fp.puts ":other: rubygems_9636a120106ea8b81fbc792188251738665711d2ece160c5"
+ fp.puts "http://localhost:3000: rubygems_be293ad9dd71550a012b17d848893b41960b811ce9312b47"
end
util_config_file
- assert_equal({:rubygems => '701229f217cdf23b1344c7b4b54ca97',
- :other => 'a5fdbb6ba150cbb83aad2bb2fede64c'}, @cfg.api_keys)
+ assert_equal(
+ { :rubygems => "rubygems_b9ce70c306b3a2e248679fbbbd66722d408d3c8c4f00566c",
+ :other => "rubygems_9636a120106ea8b81fbc792188251738665711d2ece160c5",
+ "http://localhost:3000" => "rubygems_be293ad9dd71550a012b17d848893b41960b811ce9312b47" },
+ @cfg.api_keys
+ )
end
def test_load_api_keys_bad_permission
- pend 'chmod not supported' if win_platform?
+ pend "chmod not supported" if Gem.win_platform?
- @cfg.rubygems_api_key = 'x'
+ @cfg.rubygems_api_key = "x"
- File.chmod 0644, @cfg.credentials_path
+ File.chmod 0o644, @cfg.credentials_path
assert_raise Gem::MockGemUi::TermError do
@cfg.load_api_keys
@@ -346,72 +366,72 @@ if you believe they were disclosed to a third party.
end
def test_rubygems_api_key_equals
- @cfg.rubygems_api_key = 'x'
+ @cfg.rubygems_api_key = "x"
- assert_equal 'x', @cfg.rubygems_api_key
+ assert_equal "x", @cfg.rubygems_api_key
expected = {
- :rubygems_api_key => 'x',
+ rubygems_api_key: "x",
}
assert_equal expected, load_yaml_file(@cfg.credentials_path)
- unless win_platform?
+ unless Gem.win_platform?
stat = File.stat @cfg.credentials_path
- assert_equal 0600, stat.mode & 0600
+ assert_equal 0o600, stat.mode & 0o600
end
end
def test_rubygems_api_key_equals_bad_permission
- pend 'chmod not supported' if win_platform?
+ pend "chmod not supported" if Gem.win_platform?
- @cfg.rubygems_api_key = 'x'
+ @cfg.rubygems_api_key = "x"
- File.chmod 0644, @cfg.credentials_path
+ File.chmod 0o644, @cfg.credentials_path
assert_raise Gem::MockGemUi::TermError do
- @cfg.rubygems_api_key = 'y'
+ @cfg.rubygems_api_key = "y"
end
expected = {
- :rubygems_api_key => 'x',
+ rubygems_api_key: "x",
}
assert_equal expected, load_yaml_file(@cfg.credentials_path)
stat = File.stat @cfg.credentials_path
- assert_equal 0644, stat.mode & 0644
+ assert_equal 0o644, stat.mode & 0o644
end
def test_write
- @cfg.backtrace = true
+ @cfg.backtrace = false
@cfg.update_sources = false
@cfg.bulk_threshold = 10
@cfg.verbose = false
Gem.sources.replace %w[http://more-gems.example.com]
- @cfg[:install] = '--wrappers'
+ @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 true, @cfg.backtrace, "backtrace"
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'
+ "bulk_threshold"
+ assert_equal true, @cfg.update_sources, "update_sources"
+ assert_equal true, @cfg.verbose, "verbose"
- assert_equal '--wrappers', @cfg[:install], 'install'
+ 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|
+ File.open @temp_conf, "w" do |fp|
fp.puts ":backtrace: true"
fp.puts ":bulk_threshold: 10"
fp.puts ":update_sources: false"
@@ -431,34 +451,35 @@ if you believe they were disclosed to a third party.
@cfg.bulk_threshold = 20
@cfg.verbose = :junk
Gem.sources.replace %w[http://even-more-gems.example.com]
- @cfg[:install] = '--wrappers --no-rdoc'
+ @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 10, @cfg.bulk_threshold, 'bulk_threshold'
- assert_equal false, @cfg.update_sources, 'update_sources'
- assert_equal false, @cfg.verbose, 'verbose'
+ assert_equal true, @cfg.backtrace, "backtrace"
+ assert_equal 10, @cfg.bulk_threshold, "bulk_threshold"
+ assert_equal false, @cfg.update_sources, "update_sources"
+ assert_equal false, @cfg.verbose, "verbose"
assert_equal 2, @cfg.ssl_verify_mode
- assert_equal '/nonexistent/ca_cert.pem', @cfg.ssl_ca_cert
- assert_equal '/nonexistent/client_cert.pem', @cfg.ssl_client_cert
+ assert_equal "/nonexistent/ca_cert.pem", @cfg.ssl_ca_cert
+ assert_equal "/nonexistent/client_cert.pem", @cfg.ssl_client_cert
- assert_equal '--wrappers --no-rdoc', @cfg[:install], 'install'
+ assert_equal "--wrappers --no-rdoc", @cfg[:install], "install"
assert_equal %w[http://even-more-gems.example.com], Gem.sources
end
def test_ignore_invalid_config_file
- File.open @temp_conf, 'w' do |fp|
+ File.open @temp_conf, "w" do |fp|
fp.puts "invalid: yaml:"
end
begin
- verbose, $VERBOSE = $VERBOSE, nil
+ verbose = $VERBOSE
+ $VERBOSE = nil
util_config_file
ensure
@@ -466,8 +487,18 @@ if you believe they were disclosed to a third party.
end
end
+ def test_accept_string_key
+ File.open @temp_conf, "w" do |fp|
+ fp.puts "verbose: false"
+ end
+
+ util_config_file
+
+ assert_equal false, @cfg.verbose
+ end
+
def test_load_ssl_verify_mode_from_config
- File.open @temp_conf, 'w' do |fp|
+ File.open @temp_conf, "w" do |fp|
fp.puts ":ssl_verify_mode: 1"
end
util_config_file
@@ -475,30 +506,147 @@ if you believe they were disclosed to a third party.
end
def test_load_ssl_ca_cert_from_config
- File.open @temp_conf, 'w' do |fp|
+ File.open @temp_conf, "w" do |fp|
fp.puts ":ssl_ca_cert: /home/me/certs"
end
util_config_file
- assert_equal('/home/me/certs', @cfg.ssl_ca_cert)
+ assert_equal("/home/me/certs", @cfg.ssl_ca_cert)
end
def test_load_ssl_client_cert_from_config
- File.open @temp_conf, 'w' do |fp|
+ File.open @temp_conf, "w" do |fp|
fp.puts ":ssl_client_cert: /home/me/mine.pem"
end
util_config_file
- assert_equal('/home/me/mine.pem', @cfg.ssl_client_cert)
+ assert_equal("/home/me/mine.pem", @cfg.ssl_client_cert)
end
- def util_config_file(args = @cfg_args)
- @cfg = Gem::ConfigFile.new args
+ def test_load_install_extension_in_lib_from_config
+ File.open @temp_conf, "w" do |fp|
+ fp.puts ":install_extension_in_lib: false"
+ end
+ util_config_file
+ assert_equal(false, @cfg.install_extension_in_lib)
end
def test_disable_default_gem_server
- File.open @temp_conf, 'w' do |fp|
+ File.open @temp_conf, "w" do |fp|
fp.puts ":disable_default_gem_server: true"
end
util_config_file
assert_equal(true, @cfg.disable_default_gem_server)
end
+
+ def test_load_with_rubygems_config_hash
+ yaml = <<~YAML
+ ---
+ :foo: bar
+ bar: 100
+ buzz: true
+ alpha: :bravo
+ charlie: ""
+ delta:
+ YAML
+ actual = Gem::ConfigFile.load_with_rubygems_config_hash(yaml)
+
+ assert_equal "bar", actual[:foo]
+ assert_equal 100, actual["bar"]
+ assert_equal true, actual["buzz"]
+ assert_equal :bravo, actual["alpha"]
+ assert_equal nil, actual["charlie"]
+ assert_equal nil, actual["delta"]
+ end
+
+ def test_dump_with_rubygems_yaml
+ symbol_key_hash = { foo: "bar" }
+
+ actual = Gem::ConfigFile.dump_with_rubygems_yaml(symbol_key_hash)
+
+ assert_equal("---\n:foo: \"bar\"\n", actual)
+ end
+
+ def test_handle_comment
+ yaml = <<~YAML
+ ---
+ :foo: bar # buzz
+ #:notkey: bar
+ YAML
+
+ actual = Gem::ConfigFile.load_with_rubygems_config_hash(yaml)
+ assert_equal("bar", actual[:foo])
+ assert_equal(false, actual.key?("#:notkey"))
+ assert_equal(false, actual.key?(:notkey))
+ assert_equal(1, actual.size)
+ end
+
+ def test_s3_source
+ yaml = <<~YAML
+ ---
+ :sources:
+ - s3://bucket1/
+ - s3://bucket2/
+ - s3://bucket3/path_to_gems_dir/
+ - s3://bucket4/
+ - https://rubygems.org/
+ :s3_source:
+ :bucket1:
+ :provider: env
+ :bucket2:
+ :provider: instance_profile
+ :region: us-west-2
+ :bucket3:
+ :id: AOUEAOEU123123AOEUAO
+ :secret: aodnuhtdao/saeuhto+19283oaehu/asoeu+123h
+ :region: us-east-2
+ :bucket4:
+ :id: AOUEAOEU123123AOEUAO
+ :secret: aodnuhtdao/saeuhto+19283oaehu/asoeu+123h
+ :security_token: AQoDYXdzEJr
+ :region: us-west-1
+ YAML
+
+ File.open @temp_conf, "w" do |fp|
+ fp.puts yaml
+ end
+ util_config_file
+
+ assert_equal(["s3://bucket1/", "s3://bucket2/", "s3://bucket3/path_to_gems_dir/", "s3://bucket4/", "https://rubygems.org/"], @cfg.sources)
+ expected_config = {
+ bucket1: { provider: "env" },
+ bucket2: { provider: "instance_profile", region: "us-west-2" },
+ bucket3: { id: "AOUEAOEU123123AOEUAO", secret: "aodnuhtdao/saeuhto+19283oaehu/asoeu+123h", region: "us-east-2" },
+ bucket4: { id: "AOUEAOEU123123AOEUAO", secret: "aodnuhtdao/saeuhto+19283oaehu/asoeu+123h", security_token: "AQoDYXdzEJr", region: "us-west-1" },
+ }
+ assert_equal(expected_config, @cfg[:s3_source])
+ assert_equal(expected_config[:bucket1], @cfg[:s3_source][:bucket1])
+ assert_equal(expected_config[:bucket2], @cfg[:s3_source][:bucket2])
+ assert_equal(expected_config[:bucket3], @cfg[:s3_source][:bucket3])
+ assert_equal(expected_config[:bucket4], @cfg[:s3_source][:bucket4])
+ end
+
+ def test_s3_source_with_config_without_lookahead
+ yaml = <<~YAML
+ :sources:
+ - s3://bucket1/
+ s3_source:
+ bucket1:
+ provider: env
+ YAML
+
+ File.open @temp_conf, "w" do |fp|
+ fp.puts yaml
+ end
+ util_config_file
+
+ assert_equal(["s3://bucket1/"], @cfg.sources)
+ expected_config = {
+ "bucket1" => { "provider" => "env" },
+ }
+ assert_equal(expected_config, @cfg[:s3_source])
+ assert_equal(expected_config[:bucket1], @cfg[:s3_source][:bucket1])
+ end
+
+ def util_config_file(args = @cfg_args)
+ @cfg = Gem::ConfigFile.new args
+ end
end
diff --git a/test/rubygems/test_gem_console_ui.rb b/test/rubygems/test_gem_console_ui.rb
new file mode 100644
index 0000000000..b8a619625f
--- /dev/null
+++ b/test/rubygems/test_gem_console_ui.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+require_relative "helper"
+require "rubygems/user_interaction"
+
+class TestGemConsoleUI < Gem::TestCase
+ def test_output_can_be_captured_by_test_unit
+ output = capture_output do
+ ui = Gem::ConsoleUI.new
+
+ ui.alert_error "test error"
+ ui.alert_warning "test warning"
+ ui.alert "test alert"
+ end
+
+ assert_equal "INFO: test alert\n", output.first
+ assert_equal "ERROR: test error\n" + "WARNING: test warning\n", output.last
+ end
+end
diff --git a/test/rubygems/test_gem_dependency.rb b/test/rubygems/test_gem_dependency.rb
index 1ca0fc378c..2a989a5551 100644
--- a/test/rubygems/test_gem_dependency.rb
+++ b/test/rubygems/test_gem_dependency.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/dependency'
+
+require_relative "helper"
+require "rubygems/dependency"
class TestGemDependency < Gem::TestCase
def setup
@@ -18,7 +19,7 @@ class TestGemDependency < Gem::TestCase
def test_initialize_type_bad
e = assert_raise ArgumentError do
- Gem::Dependency.new 'monkey' => '1.0'
+ Gem::Dependency.new "monkey" => "1.0"
end
assert_equal 'dependency name must be a String, was {"monkey"=>"1.0"}',
@@ -36,11 +37,11 @@ class TestGemDependency < Gem::TestCase
end
def test_initialize_prerelease
- d = dep 'd', '1.a'
+ d = dep "d", "1.a"
assert d.prerelease?
- d = dep 'd', '= 1.a'
+ d = dep "d", "= 1.a"
assert d.prerelease?
end
@@ -105,8 +106,13 @@ class TestGemDependency < Gem::TestCase
def test_equals_tilde_object
o = Object.new
- def o.name ; 'a' end
- def o.version ; '0' end
+ def o.name
+ "a"
+ end
+
+ def o.version
+ "0"
+ end
assert_match dep("a"), o
end
@@ -133,142 +139,142 @@ class TestGemDependency < Gem::TestCase
end
def test_match_eh_name_tuple
- a_dep = dep 'a'
+ a_dep = dep "a"
- a_tup = Gem::NameTuple.new 'a', 1
- b_tup = Gem::NameTuple.new 'b', 2
- c_tup = Gem::NameTuple.new 'c', '2.a'
+ a_tup = Gem::NameTuple.new "a", 1
+ b_tup = Gem::NameTuple.new "b", 2
+ c_tup = Gem::NameTuple.new "c", "2.a"
assert a_dep.match? a_tup
refute a_dep.match? b_tup
- b_dep = dep 'b', '>= 3'
+ b_dep = dep "b", ">= 3"
refute b_dep.match? b_tup
- c_dep = dep 'c', '>= 1'
+ c_dep = dep "c", ">= 1"
refute c_dep.match? c_tup
- c_dep = dep 'c'
+ c_dep = dep "c"
refute c_dep.match? c_tup
- c_dep = dep 'c', '2.a'
+ c_dep = dep "c", "2.a"
assert c_dep.match? c_tup
end
def test_match_eh_allow_prerelease
- a_dep = dep 'a'
+ a_dep = dep "a"
- a_tup = Gem::NameTuple.new 'a', 1
- b_tup = Gem::NameTuple.new 'b', 2
- c_tup = Gem::NameTuple.new 'c', '2.a'
+ a_tup = Gem::NameTuple.new "a", 1
+ b_tup = Gem::NameTuple.new "b", 2
+ c_tup = Gem::NameTuple.new "c", "2.a"
assert a_dep.match? a_tup, nil, true
refute a_dep.match? b_tup, nil, true
- b_dep = dep 'b', '>= 3'
+ b_dep = dep "b", ">= 3"
refute b_dep.match? b_tup, nil, true
- c_dep = dep 'c', '>= 1'
+ c_dep = dep "c", ">= 1"
assert c_dep.match? c_tup, nil, true
- c_dep = dep 'c'
+ c_dep = dep "c"
assert c_dep.match? c_tup, nil, true
- c_dep = dep 'c', '2.a'
+ c_dep = dep "c", "2.a"
assert c_dep.match? c_tup, nil, true
end
def test_match_eh_specification
- a_dep = dep 'a'
+ a_dep = dep "a"
- a_spec = util_spec 'a', 1
- b_spec = util_spec 'b', 2
- c_spec = util_spec 'c', '2.a'
+ a_spec = util_spec "a", 1
+ b_spec = util_spec "b", 2
+ c_spec = util_spec "c", "2.a"
assert a_dep.match? a_spec
refute a_dep.match? b_spec
- b_dep = dep 'b', '>= 3'
+ b_dep = dep "b", ">= 3"
refute b_dep.match? b_spec
- c_dep = dep 'c', '>= 1'
+ c_dep = dep "c", ">= 1"
refute c_dep.match? c_spec
- c_dep = dep 'c'
+ c_dep = dep "c"
refute c_dep.match? c_spec
- c_dep = dep 'c', '2.a'
+ c_dep = dep "c", "2.a"
assert c_dep.match? c_spec
end
def test_matches_spec_eh
- spec = util_spec 'b', 2
+ spec = util_spec "b", 2
- refute dep('a') .matches_spec?(spec), 'name mismatch'
- assert dep('b') .matches_spec?(spec), 'name match'
- refute dep('b', '= 1') .matches_spec?(spec), 'requirement mismatch'
- assert dep('b', '~> 2').matches_spec?(spec), 'requirement match'
+ refute dep("a") .matches_spec?(spec), "name mismatch"
+ assert dep("b") .matches_spec?(spec), "name match"
+ refute dep("b", "= 1") .matches_spec?(spec), "requirement mismatch"
+ assert dep("b", "~> 2").matches_spec?(spec), "requirement match"
end
def test_matches_spec_eh_prerelease
- spec = util_spec 'b', '2.1.a'
+ spec = util_spec "b", "2.1.a"
- refute dep('a') .matches_spec?(spec), 'name mismatch'
- assert dep('b') .matches_spec?(spec), 'name match'
- refute dep('b', '= 1') .matches_spec?(spec), 'requirement mismatch'
- assert dep('b', '~> 2') .matches_spec?(spec), 'requirement match'
- assert dep('b', '~> 2.a').matches_spec?(spec), 'prerelease requirement'
+ refute dep("a") .matches_spec?(spec), "name mismatch"
+ assert dep("b") .matches_spec?(spec), "name match"
+ refute dep("b", "= 1") .matches_spec?(spec), "requirement mismatch"
+ assert dep("b", "~> 2") .matches_spec?(spec), "requirement match"
+ assert dep("b", "~> 2.a").matches_spec?(spec), "prerelease requirement"
end
def test_merge
- a1 = dep 'a', '~> 1.0'
- a2 = dep 'a', '= 1.0'
+ a1 = dep "a", "~> 1.0"
+ a2 = dep "a", "= 1.0"
a3 = a1.merge a2
- assert_equal dep('a', '~> 1.0', '= 1.0'), a3
+ assert_equal dep("a", "~> 1.0", "= 1.0"), a3
end
def test_merge_default
- a1 = dep 'a'
- a2 = dep 'a', '1'
+ a1 = dep "a"
+ a2 = dep "a", "1"
a3 = a1.merge a2
- assert_equal dep('a', '1'), a3
+ assert_equal dep("a", "1"), a3
end
def test_merge_name_mismatch
- a = dep 'a'
- b = dep 'b'
+ a = dep "a"
+ b = dep "b"
e = assert_raise ArgumentError do
a.merge b
end
- assert_equal 'a (>= 0) and b (>= 0) have different names',
+ assert_equal "a (>= 0) and b (>= 0) have different names",
e.message
end
def test_merge_other_default
- a1 = dep 'a', '1'
- a2 = dep 'a'
+ a1 = dep "a", "1"
+ a2 = dep "a"
a3 = a1.merge a2
- assert_equal dep('a', '1'), a3
+ assert_equal dep("a", "1"), a3
end
def test_prerelease_eh
@@ -294,44 +300,44 @@ class TestGemDependency < Gem::TestCase
end
def test_specific
- refute dep('a', '> 1').specific?
+ refute dep("a", "> 1").specific?
- assert dep('a', '= 1').specific?
+ assert dep("a", "= 1").specific?
end
def test_to_spec
- a_1 = util_spec 'a', '1'
- a_2 = util_spec 'a', '2'
+ a_1 = util_spec "a", "1"
+ a_2 = util_spec "a", "2"
- a_dep = dep 'a', '>= 0'
+ a_dep = dep "a", ">= 0"
install_specs a_1, a_2
assert_equal a_2, a_dep.to_spec
end
def test_to_spec_prerelease
- a_1 = util_spec 'a', '1'
- a_1_1_a = util_spec 'a', '1.1.a'
+ a_1 = util_spec "a", "1"
+ a_1_1_a = util_spec "a", "1.1.a"
- a_dep = dep 'a', '>= 0'
+ a_dep = dep "a", ">= 0"
install_specs a_1, a_1_1_a
assert_equal a_1, a_dep.to_spec
- a_pre_dep = dep 'a', '>= 0'
+ a_pre_dep = dep "a", ">= 0"
a_pre_dep.prerelease = true
assert_equal a_1_1_a, a_pre_dep.to_spec
end
def test_to_specs_suggests_other_versions
- a = util_spec 'a', '1.0'
+ a = util_spec "a", "1.0"
install_specs a
- a_file = File.join a.gem_dir, 'lib', 'a_file.rb'
+ a_file = File.join a.gem_dir, "lib", "a_file.rb"
write_file a_file do |io|
- io.puts '# a_file.rb'
+ io.puts "# a_file.rb"
end
dep = Gem::Dependency.new "a", "= 2.0"
@@ -344,41 +350,39 @@ class TestGemDependency < Gem::TestCase
end
def test_to_specs_respects_bundler_version
- b = util_spec 'bundler', '2.0.0.pre.1'
- b_1 = util_spec 'bundler', '1'
+ b = util_spec "bundler", "2.0.0.pre.1"
+ b_1 = util_spec "bundler", "1"
install_specs b, b_1
- b_file = File.join b.gem_dir, 'lib', 'bundler', 'setup.rb'
+ b_file = File.join b.gem_dir, "lib", "bundler", "setup.rb"
write_file b_file do |io|
- io.puts '# setup.rb'
+ io.puts "# setup.rb"
end
dep = Gem::Dependency.new "bundler", ">= 0.a"
assert_equal [b, b_1], dep.to_specs
- Gem::BundlerVersionFinder.stub(:bundler_version_with_reason, ["3.5", "reason"]) do
- e = assert_raise Gem::MissingSpecVersionError do
- dep.to_specs
- end
+ require "rubygems/bundler_version_finder"
- assert_match "Could not find 'bundler' (3.5) required by reason.\nTo update to the latest version installed on your system, run `bundle update --bundler`.\nTo install the missing version, run `gem install bundler:3.5`\n", e.message
+ Gem::BundlerVersionFinder.stub(:bundler_version, Gem::Version.new("1")) do
+ assert_equal [b_1, b], dep.to_specs
end
- Gem::BundlerVersionFinder.stub(:bundler_version_with_reason, ["2.0.0.pre.1", "reason"]) do
- assert_equal [b], dep.to_specs
+ Gem::BundlerVersionFinder.stub(:bundler_version, Gem::Version.new("2.0.0.pre.1")) do
+ assert_equal [b, b_1], dep.to_specs
end
end
def test_to_specs_indicates_total_gem_set_size
- a = util_spec 'a', '1.0'
+ a = util_spec "a", "1.0"
install_specs a
- a_file = File.join a.gem_dir, 'lib', 'a_file.rb'
+ a_file = File.join a.gem_dir, "lib", "a_file.rb"
write_file a_file do |io|
- io.puts '# a_file.rb'
+ io.puts "# a_file.rb"
end
dep = Gem::Dependency.new "b", "= 2.0"
@@ -390,6 +394,16 @@ class TestGemDependency < Gem::TestCase
assert_match "Could not find 'b' (= 2.0) among 1 total gem(s)", e.message
end
+ def test_to_spec_with_only_prereleases
+ a_2_a_1 = util_spec "a", "2.a1"
+ a_2_a_2 = util_spec "a", "2.a2"
+ install_specs a_2_a_1, a_2_a_2
+
+ a_dep = dep "a", ">= 1"
+
+ assert_equal a_2_a_2, a_dep.to_spec
+ end
+
def test_identity
assert_equal dep("a", "= 1").identity, :released
assert_equal dep("a", "= 1.a").identity, :complete
diff --git a/test/rubygems/test_gem_dependency_installer.rb b/test/rubygems/test_gem_dependency_installer.rb
index 9cbdcefea4..8999723ba1 100644
--- a/test/rubygems/test_gem_dependency_installer.rb
+++ b/test/rubygems/test_gem_dependency_installer.rb
@@ -1,15 +1,16 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/dependency_installer'
-require 'rubygems/security'
+
+require_relative "helper"
+require "rubygems/dependency_installer"
+require "rubygems/security"
class TestGemDependencyInstaller < Gem::TestCase
def setup
super
common_installer_setup
- @gems_dir = File.join @tempdir, 'gems'
- @cache_dir = File.join @gemhome, 'cache'
+ @gems_dir = File.join @tempdir, "gems"
+ @cache_dir = File.join @gemhome, "cache"
FileUtils.mkdir @gems_dir
@@ -25,23 +26,23 @@ class TestGemDependencyInstaller < Gem::TestCase
end
def util_setup_gems
- @a1, @a1_gem = util_gem 'a', '1' do |s|
- s.executables << 'a_bin'
+ @a1, @a1_gem = util_gem "a", "1" do |s|
+ s.executables << "a_bin"
end
- @a1_pre, @a1_pre_gem = util_gem 'a', '1.a'
+ @a1_pre, @a1_pre_gem = util_gem "a", "1.a"
- @b1, @b1_gem = util_gem 'b', '1' do |s|
- s.add_dependency 'a'
- s.add_development_dependency 'aa'
+ @b1, @b1_gem = util_gem "b", "1" do |s|
+ s.add_dependency "a"
+ s.add_development_dependency "aa"
end
- @c1, @c1_gem = util_gem 'c', '1' do |s|
- s.add_development_dependency 'b'
+ @c1, @c1_gem = util_gem "c", "1" do |s|
+ s.add_development_dependency "b"
end
- @d1, @d1_gem = util_gem 'd', '1' do |s|
- s.add_development_dependency 'c'
+ @d1, @d1_gem = util_gem "d", "1" do |s|
+ s.add_development_dependency "c"
end
util_setup_spec_fetcher(@a1, @a1_pre, @b1, @d1)
@@ -55,7 +56,7 @@ class TestGemDependencyInstaller < Gem::TestCase
Dir.chdir @tempdir do
inst = Gem::DependencyInstaller.new
- inst.install 'a'
+ inst.install "a"
end
assert_equal %w[a-1], Gem::Specification.map(&:full_name)
@@ -65,16 +66,16 @@ class TestGemDependencyInstaller < Gem::TestCase
def test_install_prerelease
util_setup_gems
- p1a, gem = util_gem 'a', '10.a'
+ p1a, gem = util_gem "a", "10.a"
util_setup_spec_fetcher(p1a, @a1, @a1_pre)
p1a_data = Gem.read_binary(gem)
- @fetcher.data['http://gems.example.com/gems/a-10.a.gem'] = p1a_data
+ @fetcher.data["http://gems.example.com/gems/a-10.a.gem"] = p1a_data
dep = Gem::Dependency.new "a"
- inst = Gem::DependencyInstaller.new :prerelease => true
+ inst = Gem::DependencyInstaller.new prerelease: true
inst.install dep
assert_equal %w[a-10.a], Gem::Specification.map(&:full_name)
@@ -83,33 +84,33 @@ class TestGemDependencyInstaller < Gem::TestCase
def test_install_prerelease_bug_990
spec_fetcher do |fetcher|
- fetcher.gem 'a', '1.b' do |s|
- s.add_dependency 'b', '~> 1.a'
+ fetcher.gem "a", "1.b" do |s|
+ s.add_dependency "b", "~> 1.a"
end
- fetcher.gem 'b', '1.b' do |s|
- s.add_dependency 'c', '>= 1'
+ fetcher.gem "b", "1.b" do |s|
+ s.add_dependency "c", ">= 1"
end
- fetcher.gem 'c', '1.1.b'
+ fetcher.gem "c", "1.1.b"
end
- dep = Gem::Dependency.new 'a'
+ dep = Gem::Dependency.new "a"
- inst = Gem::DependencyInstaller.new :prerelease => true
+ inst = Gem::DependencyInstaller.new prerelease: true
inst.install dep
assert_equal %w[a-1.b b-1.b c-1.1.b], Gem::Specification.map(&:full_name)
end
def test_install_when_only_prerelease
- p1a, gem = util_gem 'p', '1.a'
+ p1a, gem = util_gem "p", "1.a"
util_setup_spec_fetcher(p1a)
p1a_data = Gem.read_binary(gem)
- @fetcher.data['http://gems.example.com/gems/p-1.a.gem'] = p1a_data
+ @fetcher.data["http://gems.example.com/gems/p-1.a.gem"] = p1a_data
dep = Gem::Dependency.new "p"
inst = Gem::DependencyInstaller.new
@@ -128,10 +129,10 @@ class TestGemDependencyInstaller < Gem::TestCase
p1a_data = Gem.read_binary(@a1_gem)
- @fetcher.data['http://gems.example.com/gems/a-1.gem'] = p1a_data
+ @fetcher.data["http://gems.example.com/gems/a-1.gem"] = p1a_data
dep = Gem::Dependency.new "a"
- inst = Gem::DependencyInstaller.new :prerelease => true
+ inst = Gem::DependencyInstaller.new prerelease: true
inst.install dep
assert_equal %w[a-1], Gem::Specification.map(&:full_name)
@@ -141,8 +142,8 @@ class TestGemDependencyInstaller < Gem::TestCase
def test_install_all_dependencies
util_setup_gems
- _, e1_gem = util_gem 'e', '1' do |s|
- s.add_dependency 'b'
+ _, e1_gem = util_gem "e", "1" do |s|
+ s.add_dependency "b"
end
FileUtils.mv @a1_gem, @tempdir
@@ -152,19 +153,19 @@ class TestGemDependencyInstaller < Gem::TestCase
inst = nil
Dir.chdir @tempdir do
- inst = Gem::DependencyInstaller.new :ignore_dependencies => true
- inst.install 'b'
+ inst = Gem::DependencyInstaller.new ignore_dependencies: true
+ inst.install "b"
end
- assert_equal %w[b-1], inst.installed_gems.map {|s| s.full_name },
- 'sanity check'
+ assert_equal %w[b-1], inst.installed_gems.map(&:full_name),
+ "sanity check"
Dir.chdir @tempdir do
inst = Gem::DependencyInstaller.new
- inst.install 'e'
+ inst.install "e"
end
- assert_equal %w[a-1 e-1], inst.installed_gems.map {|s| s.full_name }
+ assert_equal %w[a-1 e-1], inst.installed_gems.map(&:full_name)
end
def test_install_cache_dir
@@ -177,11 +178,11 @@ class TestGemDependencyInstaller < Gem::TestCase
inst = nil
Dir.chdir dir do
- inst = Gem::DependencyInstaller.new :cache_dir => @tempdir
- inst.install 'b'
+ 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_equal %w[a-1 b-1], inst.installed_gems.map(&:full_name)
assert File.exist? File.join(@gemhome, "cache", @a1.file_name)
assert File.exist? File.join(@gemhome, "cache", @b1.file_name)
@@ -190,34 +191,34 @@ class TestGemDependencyInstaller < Gem::TestCase
def test_install_dependencies_satisfied
util_setup_gems
- a2, a2_gem = util_gem 'a', '2'
+ a2, a2_gem = util_gem "a", "2"
- FileUtils.rm_rf File.join(@gemhome, 'gems')
+ FileUtils.rm_rf File.join(@gemhome, "gems")
Gem::Specification.reset
FileUtils.mv @a1_gem, @tempdir
- FileUtils.mv a2_gem, @tempdir # not in index
+ 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', req("= 2")
+ inst.install "a", req("= 2")
end
- assert_equal %w[a-2], inst.installed_gems.map {|s| s.full_name },
- 'sanity check'
+ assert_equal %w[a-2], inst.installed_gems.map(&:full_name),
+ "sanity check"
FileUtils.rm File.join(@tempdir, a2.file_name)
Dir.chdir @tempdir do
inst = Gem::DependencyInstaller.new
- inst.install 'b'
+ inst.install "b"
end
assert_equal %w[a-2 b-1], Gem::Specification.map(&:full_name)
- assert_equal %w[b-1], inst.installed_gems.map {|s| s.full_name }
+ assert_equal %w[b-1], inst.installed_gems.map(&:full_name)
end
# This asserts that if a gem's dependency is satisfied by an
@@ -226,22 +227,22 @@ class TestGemDependencyInstaller < Gem::TestCase
def test_install_doesnt_upgrade_installed_dependencies
util_setup_gems
- a2, a2_gem = util_gem 'a', '2'
- a3, a3_gem = util_gem 'a', '3'
+ a2, a2_gem = util_gem "a", "2"
+ a3, a3_gem = util_gem "a", "3"
util_setup_spec_fetcher @a1, a3, @b1
- FileUtils.rm_rf File.join(@gemhome, 'gems')
+ FileUtils.rm_rf File.join(@gemhome, "gems")
Gem::Specification.reset
FileUtils.mv @a1_gem, @tempdir
- FileUtils.mv a2_gem, @tempdir # not in index
+ FileUtils.mv a2_gem, @tempdir # not in index
FileUtils.mv @b1_gem, @tempdir
FileUtils.mv a3_gem, @tempdir
Dir.chdir @tempdir do
- Gem::DependencyInstaller.new.install 'a', req("= 2")
+ Gem::DependencyInstaller.new.install "a", req("= 2")
end
FileUtils.rm File.join(@tempdir, a2.file_name)
@@ -250,11 +251,11 @@ class TestGemDependencyInstaller < Gem::TestCase
Dir.chdir @tempdir do
inst = Gem::DependencyInstaller.new
- inst.install 'b'
+ inst.install "b"
end
assert_equal %w[a-2 b-1], Gem::Specification.map(&:full_name)
- assert_equal %w[b-1], inst.installed_gems.map {|s| s.full_name }
+ assert_equal %w[b-1], inst.installed_gems.map(&:full_name)
end
def test_install_dependency
@@ -273,19 +274,19 @@ class TestGemDependencyInstaller < Gem::TestCase
FileUtils.mv @b1_gem, @tempdir
Dir.chdir @tempdir do
- inst = Gem::DependencyInstaller.new(:build_docs_in_background => false)
- inst.install 'b'
+ inst = Gem::DependencyInstaller.new(build_docs_in_background: false)
+ inst.install "b"
end
- assert_equal %w[a-1 b-1], inst.installed_gems.map {|s| s.full_name }
+ assert_equal %w[a-1 b-1], inst.installed_gems.map(&:full_name)
- assert done_installing_ran, 'post installs hook was not run'
+ assert done_installing_ran, "post installs hook was not run"
end
def test_install_dependency_development
util_setup_gems
- @aa1, @aa1_gem = util_gem 'aa', '1'
+ @aa1, @aa1_gem = util_gem "aa", "1"
FileUtils.mv @a1_gem, @tempdir
FileUtils.mv @aa1_gem, @tempdir
@@ -293,17 +294,17 @@ class TestGemDependencyInstaller < Gem::TestCase
inst = nil
Dir.chdir @tempdir do
- inst = Gem::DependencyInstaller.new(:development => true)
- inst.install 'b'
+ 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 }
+ assert_equal %w[a-1 aa-1 b-1], inst.installed_gems.map(&:full_name)
end
def test_install_dependency_development_deep
util_setup_gems
- @aa1, @aa1_gem = util_gem 'aa', '1'
+ @aa1, @aa1_gem = util_gem "aa", "1"
FileUtils.mv @a1_gem, @tempdir
FileUtils.mv @aa1_gem, @tempdir
@@ -313,17 +314,17 @@ class TestGemDependencyInstaller < Gem::TestCase
inst = nil
Dir.chdir @tempdir do
- inst = Gem::DependencyInstaller.new(:development => true)
- inst.install 'd'
+ inst = Gem::DependencyInstaller.new(development: true)
+ inst.install "d"
end
- assert_equal %w[a-1 aa-1 b-1 c-1 d-1], inst.installed_gems.map {|s| s.full_name }
+ assert_equal %w[a-1 aa-1 b-1 c-1 d-1], inst.installed_gems.map(&:full_name)
end
def test_install_dependency_development_shallow
util_setup_gems
- @aa1, @aa1_gem = util_gem 'aa', '1'
+ @aa1, @aa1_gem = util_gem "aa", "1"
FileUtils.mv @a1_gem, @tempdir
FileUtils.mv @aa1_gem, @tempdir
@@ -333,11 +334,11 @@ class TestGemDependencyInstaller < Gem::TestCase
inst = nil
Dir.chdir @tempdir do
- inst = Gem::DependencyInstaller.new(:development => true, :dev_shallow => true)
- inst.install 'd'
+ inst = Gem::DependencyInstaller.new(development: true, dev_shallow: true)
+ inst.install "d"
end
- assert_equal %w[c-1 d-1], inst.installed_gems.map {|s| s.full_name }
+ assert_equal %w[c-1 d-1], inst.installed_gems.map(&:full_name)
end
def test_install_dependency_existing
@@ -350,29 +351,29 @@ class TestGemDependencyInstaller < Gem::TestCase
Dir.chdir @tempdir do
inst = Gem::DependencyInstaller.new
- inst.install 'b'
+ inst.install "b"
end
- assert_equal %w[b-1], inst.installed_gems.map {|s| s.full_name }
+ assert_equal %w[b-1], inst.installed_gems.map(&:full_name)
end
def test_install_dependency_existing_extension
- extconf_rb = File.join @gemhome, 'gems', 'e-1', 'extconf.rb'
+ extconf_rb = File.join @gemhome, "gems", "e-1", "extconf.rb"
FileUtils.mkdir_p File.dirname extconf_rb
- File.open extconf_rb, 'w' do |io|
+ File.open extconf_rb, "w" do |io|
io.write <<-EXTCONF_RB
require 'mkmf'
create_makefile 'e'
EXTCONF_RB
end
- e1 = util_spec 'e', '1', nil, 'extconf.rb' do |s|
- s.extensions << 'extconf.rb'
+ e1 = util_spec "e", "1", nil, "extconf.rb" do |s|
+ s.extensions << "extconf.rb"
end
e1_gem = e1.cache_file
- _, f1_gem = util_gem 'f', '1', 'e' => nil
+ _, f1_gem = util_gem "f", "1", "e" => nil
Gem::Installer.at(e1_gem).install
FileUtils.rm_r e1.extension_dir
@@ -385,20 +386,20 @@ class TestGemDependencyInstaller < Gem::TestCase
Dir.chdir @tempdir
begin
inst = Gem::DependencyInstaller.new
- inst.install 'f'
+ inst.install "f"
ensure
Dir.chdir pwd
end
- assert_equal %w[f-1], inst.installed_gems.map {|s| s.full_name }
+ assert_equal %w[f-1], inst.installed_gems.map(&:full_name)
assert_path_exist e1.extension_dir
end
def test_install_dependency_old
- _, e1_gem = util_gem 'e', '1'
- _, f1_gem = util_gem 'f', '1', 'e' => nil
- _, f2_gem = util_gem 'f', '2'
+ _, e1_gem = util_gem "e", "1"
+ _, f1_gem = util_gem "f", "1", "e" => nil
+ _, f2_gem = util_gem "f", "2"
FileUtils.mv e1_gem, @tempdir
FileUtils.mv f1_gem, @tempdir
@@ -407,10 +408,10 @@ class TestGemDependencyInstaller < Gem::TestCase
Dir.chdir @tempdir do
inst = Gem::DependencyInstaller.new
- inst.install 'f'
+ inst.install "f"
end
- assert_equal %w[f-2], inst.installed_gems.map {|s| s.full_name }
+ assert_equal %w[f-2], inst.installed_gems.map(&:full_name)
end
def test_install_local
@@ -420,11 +421,11 @@ class TestGemDependencyInstaller < Gem::TestCase
inst = nil
Dir.chdir @tempdir do
- inst = Gem::DependencyInstaller.new :domain => :local
- inst.install 'a-1.gem'
+ 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 }
+ assert_equal %w[a-1], inst.installed_gems.map(&:full_name)
end
def test_install_local_prerelease
@@ -434,11 +435,11 @@ class TestGemDependencyInstaller < Gem::TestCase
inst = nil
Dir.chdir @tempdir do
- inst = Gem::DependencyInstaller.new :domain => :local
- inst.install 'a-1.a.gem'
+ inst = Gem::DependencyInstaller.new domain: :local
+ inst.install "a-1.a.gem"
end
- assert_equal %w[a-1.a], inst.installed_gems.map {|s| s.full_name }
+ assert_equal %w[a-1.a], inst.installed_gems.map(&:full_name)
end
def test_install_local_dependency
@@ -450,11 +451,11 @@ class TestGemDependencyInstaller < Gem::TestCase
inst = nil
Dir.chdir @tempdir do
- inst = Gem::DependencyInstaller.new :domain => :local
- inst.install 'b-1.gem'
+ 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 }
+ assert_equal %w[a-1 b-1], inst.installed_gems.map(&:full_name)
end
def test_install_local_dependency_installed
@@ -466,13 +467,47 @@ class TestGemDependencyInstaller < Gem::TestCase
inst = nil
Dir.chdir @tempdir do
- Gem::Installer.at('a-1.gem').install
+ Gem::Installer.at("a-1.gem").install
- inst = Gem::DependencyInstaller.new :domain => :local
- inst.install 'b-1.gem'
+ 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 }
+ assert_equal %w[b-1], inst.installed_gems.map(&:full_name)
+ end
+
+ def test_install_local_dependency_no_network_for_target_gem
+ a1, a1_gem = util_gem "a", "1"
+ _, b1_gem = util_gem "b", "1" do |s|
+ s.add_dependency "a"
+ end
+
+ util_setup_spec_fetcher(a1)
+
+ a1_data = Gem.read_binary(a1_gem)
+ @fetcher.data["http://gems.example.com/gems/a-1.gem"] = a1_data
+
+ # compact index is available
+ compact_index_response = Gem::Net::HTTPResponse.new "1.1", 200, "OK"
+ compact_index_response.uri = Gem::URI("http://gems.example.com")
+ @fetcher.data["http://gems.example.com/"] = compact_index_response
+
+ # but private local gem not present there
+ @fetcher.data["http://gems.example.com/info/b"] =
+ proc do
+ raise "should not happen"
+ end
+
+ FileUtils.mv b1_gem, @tempdir
+
+ inst = nil
+
+ Dir.chdir @tempdir do
+ inst = Gem::DependencyInstaller.new
+ inst.install "b-1.gem"
+ end
+
+ assert_equal %w[a-1 b-1], inst.installed_gems.map(&:full_name)
end
def test_install_local_subdir
@@ -481,22 +516,22 @@ class TestGemDependencyInstaller < Gem::TestCase
inst = nil
Dir.chdir @tempdir do
- inst = Gem::DependencyInstaller.new :domain => :local
- inst.install 'gems/a-1.gem'
+ 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 }
+ assert_equal %w[a-1], inst.installed_gems.map(&:full_name)
end
def test_install_minimal_deps
util_setup_gems
- _, e1_gem = util_gem 'e', '1' do |s|
- s.add_dependency 'b'
+ _, e1_gem = util_gem "e", "1" do |s|
+ s.add_dependency "b"
end
- _, b2_gem = util_gem 'b', '2' do |s|
- s.add_dependency 'a'
+ _, b2_gem = util_gem "b", "2" do |s|
+ s.add_dependency "a"
end
FileUtils.mv @a1_gem, @tempdir
@@ -507,30 +542,30 @@ class TestGemDependencyInstaller < Gem::TestCase
inst = nil
Dir.chdir @tempdir do
- inst = Gem::DependencyInstaller.new :ignore_dependencies => true
- inst.install 'b', req('= 1')
+ inst = Gem::DependencyInstaller.new ignore_dependencies: true
+ inst.install "b", req("= 1")
end
- assert_equal %w[b-1], inst.installed_gems.map {|s| s.full_name },
- 'sanity check'
+ assert_equal %w[b-1], inst.installed_gems.map(&:full_name),
+ "sanity check"
Dir.chdir @tempdir do
- inst = Gem::DependencyInstaller.new :minimal_deps => true
- inst.install 'e'
+ inst = Gem::DependencyInstaller.new minimal_deps: true
+ inst.install "e"
end
- assert_equal %w[a-1 e-1], inst.installed_gems.map {|s| s.full_name }
+ assert_equal %w[a-1 e-1], inst.installed_gems.map(&:full_name)
end
def test_install_no_minimal_deps
util_setup_gems
- _, e1_gem = util_gem 'e', '1' do |s|
- s.add_dependency 'b'
+ _, e1_gem = util_gem "e", "1" do |s|
+ s.add_dependency "b"
end
- _, b2_gem = util_gem 'b', '2' do |s|
- s.add_dependency 'a'
+ _, b2_gem = util_gem "b", "2" do |s|
+ s.add_dependency "a"
end
FileUtils.mv @a1_gem, @tempdir
@@ -541,19 +576,19 @@ class TestGemDependencyInstaller < Gem::TestCase
inst = nil
Dir.chdir @tempdir do
- inst = Gem::DependencyInstaller.new :ignore_dependencies => true
- inst.install 'b', req('= 1')
+ inst = Gem::DependencyInstaller.new ignore_dependencies: true
+ inst.install "b", req("= 1")
end
- assert_equal %w[b-1], inst.installed_gems.map {|s| s.full_name },
- 'sanity check'
+ assert_equal %w[b-1], inst.installed_gems.map(&:full_name),
+ "sanity check"
Dir.chdir @tempdir do
- inst = Gem::DependencyInstaller.new :minimal_deps => false
- inst.install 'e'
+ inst = Gem::DependencyInstaller.new minimal_deps: false
+ inst.install "e"
end
- assert_equal %w[a-1 b-2 e-1], inst.installed_gems.map {|s| s.full_name }
+ assert_equal %w[a-1 b-2 e-1], inst.installed_gems.map(&:full_name)
end
def test_install_no_document
@@ -561,12 +596,12 @@ class TestGemDependencyInstaller < Gem::TestCase
done_installing_called = false
- Gem.done_installing do |dep_installer, specs|
+ Gem.done_installing do |dep_installer, _specs|
done_installing_called = true
assert_empty dep_installer.document
end
- inst = Gem::DependencyInstaller.new :domain => :local, :document => []
+ inst = Gem::DependencyInstaller.new domain: :local, document: []
inst.install @a1_gem
@@ -580,14 +615,14 @@ class TestGemDependencyInstaller < Gem::TestCase
inst = nil
Dir.chdir @tempdir do
- inst = Gem::DependencyInstaller.new :env_shebang => true, :wrappers => true, :format_executable => false
- inst.install 'a'
+ inst = Gem::DependencyInstaller.new env_shebang: true, wrappers: true, format_executable: false
+ inst.install "a"
end
env = "/\\S+/env" unless Gem.win_platform?
- assert_match %r{\A#!#{env} #{RbConfig::CONFIG['ruby_install_name']}\n},
- File.read(File.join(@gemhome, 'bin', 'a_bin'))
+ assert_match(/\A#!#{env} #{RbConfig::CONFIG["ruby_install_name"]}\n/,
+ File.read(File.join(@gemhome, "bin", "a_bin")))
end
def test_install_force
@@ -595,15 +630,15 @@ class TestGemDependencyInstaller < Gem::TestCase
FileUtils.mv @b1_gem, @tempdir
si = util_setup_spec_fetcher @b1
- @fetcher.data['http://gems.example.com/gems/yaml'] = si.to_yaml
+ @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'
+ inst = Gem::DependencyInstaller.new force: true
+ inst.install "b"
end
- assert_equal %w[b-1], inst.installed_gems.map {|s| s.full_name }
+ assert_equal %w[b-1], inst.installed_gems.map(&:full_name)
end
def test_install_build_args
@@ -614,9 +649,8 @@ class TestGemDependencyInstaller < Gem::TestCase
build_args = %w[--a --b="c"]
Dir.chdir @tempdir do
- inst = Gem::DependencyInstaller.new(
- :build_args => build_args)
- inst.install 'a'
+ inst = Gem::DependencyInstaller.new(build_args: build_args)
+ inst.install "a"
end
assert_equal build_args.join("\n"), File.read(inst.installed_gems.first.build_info_file).strip
@@ -629,11 +663,11 @@ class TestGemDependencyInstaller < Gem::TestCase
inst = nil
Dir.chdir @tempdir do
- inst = Gem::DependencyInstaller.new :ignore_dependencies => true
- inst.install 'b'
+ inst = Gem::DependencyInstaller.new ignore_dependencies: true
+ inst.install "b"
end
- assert_equal %w[b-1], inst.installed_gems.map {|s| s.full_name }
+ assert_equal %w[b-1], inst.installed_gems.map(&:full_name)
end
def test_install_install_dir
@@ -645,40 +679,40 @@ class TestGemDependencyInstaller < Gem::TestCase
inst = Gem::Installer.at @a1.file_name
inst.install
- gemhome2 = File.join @tempdir, 'gemhome2'
+ gemhome2 = File.join @tempdir, "gemhome2"
Dir.mkdir gemhome2
inst = nil
Dir.chdir @tempdir do
- inst = Gem::DependencyInstaller.new :install_dir => gemhome2
- inst.install 'b'
+ inst = Gem::DependencyInstaller.new install_dir: gemhome2
+ inst.install "b"
end
- assert_equal %w[a-1 b-1], inst.installed_gems.map {|s| s.full_name }
+ assert_equal %w[a-1 b-1], inst.installed_gems.map(&:full_name)
- assert File.exist?(File.join(gemhome2, 'specifications', @a1.spec_name))
- assert File.exist?(File.join(gemhome2, 'cache', @a1.file_name))
+ assert File.exist?(File.join(gemhome2, "specifications", @a1.spec_name))
+ assert File.exist?(File.join(gemhome2, "cache", @a1.file_name))
end
def test_install_domain_both
util_setup_gems
a1_data = nil
- File.open @a1_gem, 'rb' do |fp|
+ File.open @a1_gem, "rb" do |fp|
a1_data = fp.read
end
- @fetcher.data['http://gems.example.com/gems/a-1.gem'] = a1_data
+ @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'
+ 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 }
+ assert_equal %w[a-1 b-1], inst.installed_gems.map(&:full_name)
a1, b1 = inst.installed_gems
assert_equal a1.spec_file, a1.loaded_from
@@ -698,11 +732,11 @@ class TestGemDependencyInstaller < Gem::TestCase
inst = nil
Dir.chdir @tempdir do
- inst = Gem::DependencyInstaller.new :domain => :both
- inst.install 'b'
+ 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 }
+ assert_equal %w[a-1 b-1], inst.installed_gems.map(&:full_name)
end
def test_install_domain_local
@@ -713,31 +747,31 @@ class TestGemDependencyInstaller < Gem::TestCase
Dir.chdir @tempdir do
e = assert_raise Gem::UnsatisfiableDependencyError do
- inst = Gem::DependencyInstaller.new :domain => :local
- inst.install 'b'
+ inst = Gem::DependencyInstaller.new domain: :local
+ inst.install "b"
end
expected = "Unable to resolve dependency: 'b (>= 0)' requires 'a (>= 0)'"
assert_equal expected, e.message
end
- assert_equal [], inst.installed_gems.map {|s| s.full_name }
+ assert_equal [], inst.installed_gems.map(&:full_name)
end
def test_install_domain_remote
util_setup_gems
a1_data = nil
- File.open @a1_gem, 'rb' do |fp|
+ File.open @a1_gem, "rb" do |fp|
a1_data = fp.read
end
- @fetcher.data['http://gems.example.com/gems/a-1.gem'] = a1_data
+ @fetcher.data["http://gems.example.com/gems/a-1.gem"] = a1_data
- inst = Gem::DependencyInstaller.new :domain => :remote
- inst.install 'a'
+ inst = Gem::DependencyInstaller.new domain: :remote
+ inst.install "a"
- assert_equal %w[a-1], inst.installed_gems.map {|s| s.full_name }
+ assert_equal %w[a-1], inst.installed_gems.map(&:full_name)
end
def test_install_dual_repository
@@ -750,23 +784,23 @@ class TestGemDependencyInstaller < Gem::TestCase
gemhome2 = "#{@gemhome}2"
Dir.chdir @tempdir do
- inst = Gem::DependencyInstaller.new :install_dir => gemhome2
- inst.install 'a'
+ inst = Gem::DependencyInstaller.new install_dir: gemhome2
+ inst.install "a"
end
- assert_equal %w[a-1], inst.installed_gems.map {|s| s.full_name },
- 'sanity check'
+ assert_equal %w[a-1], inst.installed_gems.map(&:full_name),
+ "sanity check"
- ENV['GEM_HOME'] = @gemhome
- ENV['GEM_PATH'] = [@gemhome, gemhome2].join File::PATH_SEPARATOR
+ 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'
+ inst.install "b"
end
- assert_equal %w[b-1], inst.installed_gems.map {|s| s.full_name }
+ assert_equal %w[b-1], inst.installed_gems.map(&:full_name)
end
def test_install_reinstall
@@ -777,8 +811,8 @@ class TestGemDependencyInstaller < Gem::TestCase
inst = nil
Dir.chdir @tempdir do
- inst = Gem::DependencyInstaller.new :force => true
- inst.install 'a'
+ inst = Gem::DependencyInstaller.new force: true
+ inst.install "a"
end
assert_equal %w[a-1], Gem::Specification.map(&:full_name)
@@ -789,30 +823,30 @@ class TestGemDependencyInstaller < Gem::TestCase
util_setup_gems
a1_data = nil
- File.open @a1_gem, 'rb' do |fp|
+ File.open @a1_gem, "rb" do |fp|
a1_data = fp.read
end
- @fetcher.data['http://gems.example.com/gems/a-1.gem'] = a1_data
+ @fetcher.data["http://gems.example.com/gems/a-1.gem"] = a1_data
inst = Gem::DependencyInstaller.new
Dir.chdir @tempdir do
- inst.install 'a'
+ inst.install "a"
end
- assert_equal %w[a-1], inst.installed_gems.map {|s| s.full_name }
+ assert_equal %w[a-1], inst.installed_gems.map(&:full_name)
end
def test_install_remote_dep
util_setup_gems
a1_data = nil
- File.open @a1_gem, 'rb' do |fp|
+ File.open @a1_gem, "rb" do |fp|
a1_data = fp.read
end
- @fetcher.data['http://gems.example.com/gems/a-1.gem'] = a1_data
+ @fetcher.data["http://gems.example.com/gems/a-1.gem"] = a1_data
inst = Gem::DependencyInstaller.new
@@ -821,28 +855,28 @@ class TestGemDependencyInstaller < Gem::TestCase
inst.install dep
end
- assert_equal %w[a-1], inst.installed_gems.map {|s| s.full_name }
+ assert_equal %w[a-1], inst.installed_gems.map(&:full_name)
end
def test_install_remote_platform_newer
util_setup_gems
- a2_o, a2_o_gem = util_gem 'a', '2' do |s|
+ a2_o, a2_o_gem = util_gem "a", "2" do |s|
s.platform = Gem::Platform.new %w[cpu other_platform 1]
end
si = util_setup_spec_fetcher @a1, a2_o
- @fetcher.data['http://gems.example.com/gems/yaml'] = si.to_yaml
+ @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|
+ File.open @a1_gem, "rb" do |fp|
a1_data = fp.read
end
- File.open a2_o_gem, 'rb' do |fp|
+ File.open a2_o_gem, "rb" do |fp|
a2_o_data = fp.read
end
@@ -851,103 +885,103 @@ class TestGemDependencyInstaller < Gem::TestCase
@fetcher.data["http://gems.example.com/gems/#{a2_o.file_name}"] =
a2_o_data
- inst = Gem::DependencyInstaller.new :domain => :remote
- inst.install 'a'
+ inst = Gem::DependencyInstaller.new domain: :remote
+ inst.install "a"
- assert_equal %w[a-1], inst.installed_gems.map {|s| s.full_name }
+ assert_equal %w[a-1], inst.installed_gems.map(&:full_name)
end
def test_install_platform_is_ignored_when_a_file_is_specified
- _, a_gem = util_gem 'a', '1' do |s|
+ _, a_gem = util_gem "a", "1" do |s|
s.platform = Gem::Platform.new %w[cpu other_platform 1]
end
- inst = Gem::DependencyInstaller.new :domain => :local
+ inst = Gem::DependencyInstaller.new domain: :local
inst.install a_gem
- assert_equal %w[a-1-cpu-other_platform-1], inst.installed_gems.map {|s| s.full_name }
+ assert_equal %w[a-1-cpu-other_platform-1], inst.installed_gems.map(&:full_name)
end
- require 'rubygems/openssl'
+ require "rubygems/openssl"
if Gem::HAVE_OPENSSL
def test_install_security_policy
util_setup_gems
- data = File.open(@a1_gem, 'rb') {|f| f.read }
- @fetcher.data['http://gems.example.com/gems/a-1.gem'] = data
+ data = File.open(@a1_gem, "rb", &: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
+ data = File.open(@b1_gem, "rb", &:read)
+ @fetcher.data["http://gems.example.com/gems/b-1.gem"] = data
policy = Gem::Security::HighSecurity
- inst = Gem::DependencyInstaller.new :security_policy => policy
+ inst = Gem::DependencyInstaller.new security_policy: policy
e = assert_raise Gem::Security::Exception do
- inst.install 'b'
+ inst.install "b"
end
- assert_equal 'unsigned gems are not allowed by the High Security policy',
+ assert_equal "unsigned gems are not allowed by the High Security policy",
e.message
- assert_equal %w[], inst.installed_gems.map {|s| s.full_name }
+ assert_equal %w[], inst.installed_gems.map(&:full_name)
end
end
# Wrappers don't work on mswin
- unless win_platform?
+ unless Gem.win_platform?
def test_install_no_wrappers
util_setup_gems
- @fetcher.data['http://gems.example.com/gems/a-1.gem'] = read_binary(@a1_gem)
+ @fetcher.data["http://gems.example.com/gems/a-1.gem"] = read_binary(@a1_gem)
- inst = Gem::DependencyInstaller.new :wrappers => false, :format_executable => false
- inst.install 'a'
+ inst = Gem::DependencyInstaller.new wrappers: false, format_executable: false
+ inst.install "a"
- refute_match(%r{This file was generated by RubyGems.},
- File.read(File.join(@gemhome, 'bin', 'a_bin')))
+ refute_match(/This file was generated by RubyGems./,
+ File.read(File.join(@gemhome, "bin", "a_bin")))
end
end
def test_install_version
util_setup_d
- data = File.open(@d2_gem, 'rb') {|f| f.read }
- @fetcher.data['http://gems.example.com/gems/d-2.gem'] = data
+ data = File.open(@d2_gem, "rb", &: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
+ data = File.open(@d1_gem, "rb", &:read)
+ @fetcher.data["http://gems.example.com/gems/d-1.gem"] = data
inst = Gem::DependencyInstaller.new
- inst.install 'd', '= 1'
+ inst.install "d", "= 1"
- assert_equal %w[d-1], inst.installed_gems.map {|s| s.full_name }
+ assert_equal %w[d-1], inst.installed_gems.map(&:full_name)
end
def test_install_version_default
util_setup_d
- data = File.open(@d2_gem, 'rb') {|f| f.read }
- @fetcher.data['http://gems.example.com/gems/d-2.gem'] = data
+ data = File.open(@d2_gem, "rb", &: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
+ data = File.open(@d1_gem, "rb", &:read)
+ @fetcher.data["http://gems.example.com/gems/d-1.gem"] = data
inst = Gem::DependencyInstaller.new
- inst.install 'd'
+ inst.install "d"
- assert_equal %w[d-2], inst.installed_gems.map {|s| s.full_name }
+ assert_equal %w[d-2], inst.installed_gems.map(&:full_name)
end
def test_install_legacy_spec_with_nil_required_ruby_version
- path = File.expand_path "../data/null-required-ruby-version.gemspec.rz", __FILE__
+ path = File.expand_path "data/null-required-ruby-version.gemspec.rz", __dir__
spec = Marshal.load Gem.read_binary(path)
def spec.validate(*args); end
util_build_gem spec
- cache_file = File.join @tempdir, 'gems', "#{spec.original_name}.gem"
+ cache_file = File.join @tempdir, "gems", "#{spec.original_name}.gem"
FileUtils.mkdir_p File.dirname cache_file
FileUtils.mv spec.cache_file, cache_file
@@ -955,9 +989,9 @@ class TestGemDependencyInstaller < Gem::TestCase
data = Gem.read_binary(cache_file)
- @fetcher.data['http://gems.example.com/gems/activesupport-1.0.0.gem'] = data
+ @fetcher.data["http://gems.example.com/gems/activesupport-1.0.0.gem"] = data
- dep = Gem::Dependency.new 'activesupport'
+ dep = Gem::Dependency.new "activesupport"
inst = Gem::DependencyInstaller.new
inst.install dep
@@ -966,13 +1000,13 @@ class TestGemDependencyInstaller < Gem::TestCase
end
def test_install_legacy_spec_with_nil_required_rubygems_version
- path = File.expand_path "../data/null-required-rubygems-version.gemspec.rz", __FILE__
+ path = File.expand_path "data/null-required-rubygems-version.gemspec.rz", __dir__
spec = Marshal.load Gem.read_binary(path)
def spec.validate(*args); end
util_build_gem spec
- cache_file = File.join @tempdir, 'gems', "#{spec.original_name}.gem"
+ cache_file = File.join @tempdir, "gems", "#{spec.original_name}.gem"
FileUtils.mkdir_p File.dirname cache_file
FileUtils.mv spec.cache_file, cache_file
@@ -980,9 +1014,9 @@ class TestGemDependencyInstaller < Gem::TestCase
data = Gem.read_binary(cache_file)
- @fetcher.data['http://gems.example.com/gems/activesupport-1.0.0.gem'] = data
+ @fetcher.data["http://gems.example.com/gems/activesupport-1.0.0.gem"] = data
- dep = Gem::Dependency.new 'activesupport'
+ dep = Gem::Dependency.new "activesupport"
inst = Gem::DependencyInstaller.new
inst.install dep
@@ -994,7 +1028,7 @@ class TestGemDependencyInstaller < Gem::TestCase
util_setup_gems
inst = Gem::DependencyInstaller.new
- dep = Gem::Dependency.new 'b', '>= 0'
+ dep = Gem::Dependency.new "b", ">= 0"
Gem::Specification.reset
@@ -1015,7 +1049,7 @@ class TestGemDependencyInstaller < Gem::TestCase
FileUtils.mv @a1_gem, @tempdir
inst = Gem::DependencyInstaller.new
- dep = Gem::Dependency.new 'a', '>= 0'
+ dep = Gem::Dependency.new "a", ">= 0"
set = nil
Dir.chdir @tempdir do
@@ -1030,12 +1064,12 @@ class TestGemDependencyInstaller < Gem::TestCase
remote, local = gems
- assert_equal 'a-1', local.spec.full_name, 'local spec'
+ assert_equal "a-1", local.spec.full_name, "local spec"
assert_equal File.join(@tempdir, @a1.file_name),
- local.source.download(local.spec), 'local path'
+ local.source.download(local.spec), "local path"
- assert_equal 'a-1', remote.spec.full_name, 'remote spec'
- assert_equal Gem::Source.new(@gem_repo), remote.source, 'remote path'
+ assert_equal "a-1", remote.spec.full_name, "remote spec"
+ assert_equal Gem::Source.new(@gem_repo), remote.source, "remote path"
end
def test_find_gems_with_sources_prerelease
@@ -1043,7 +1077,7 @@ class TestGemDependencyInstaller < Gem::TestCase
installer = Gem::DependencyInstaller.new
- dependency = Gem::Dependency.new('a', Gem::Requirement.default)
+ dependency = Gem::Dependency.new("a", Gem::Requirement.default)
set = Gem::Deprecate.skip_during do
installer.find_gems_with_sources(dependency)
@@ -1051,8 +1085,8 @@ class TestGemDependencyInstaller < Gem::TestCase
releases = set.all_specs
- assert releases.any? {|s| s.name == 'a' and s.version.to_s == '1' }
- refute releases.any? {|s| s.name == 'a' and s.version.to_s == '1.a' }
+ assert releases.any? {|s| s.name == "a" && s.version.to_s == "1" }
+ refute releases.any? {|s| s.name == "a" && s.version.to_s == "1.a" }
dependency.prerelease = true
@@ -1067,15 +1101,15 @@ class TestGemDependencyInstaller < Gem::TestCase
def test_find_gems_with_sources_with_best_only_and_platform
util_setup_gems
- a1_x86_mingw32, = util_gem 'a', '1' do |s|
- s.platform = 'x86-mingw32'
+ a1_x86_mingw32, = util_gem "a", "1" do |s|
+ s.platform = "x86-mingw32"
end
util_setup_spec_fetcher @a1, a1_x86_mingw32
- Gem.platforms << Gem::Platform.new('x86-mingw32')
+ Gem.platforms << Gem::Platform.new("x86-mingw32")
installer = Gem::DependencyInstaller.new
- dependency = Gem::Dependency.new('a', Gem::Requirement.default)
+ dependency = Gem::Dependency.new("a", Gem::Requirement.default)
set = Gem::Deprecate.skip_during do
installer.find_gems_with_sources(dependency, true)
@@ -1091,7 +1125,7 @@ class TestGemDependencyInstaller < Gem::TestCase
installer = Gem::DependencyInstaller.new
- dep = Gem::Dependency.new('a')
+ dep = Gem::Dependency.new("a")
out = Gem::Deprecate.skip_during do
installer.find_gems_with_sources(dep)
@@ -1108,9 +1142,9 @@ class TestGemDependencyInstaller < Gem::TestCase
FileUtils.mv @b1_gem, @tempdir
inst = Gem::DependencyInstaller.new
- request_set = inst.resolve_dependencies 'b', req('>= 0')
+ request_set = inst.resolve_dependencies "b", req(">= 0")
- requests = request_set.sorted_requests.map {|req| req.full_name }
+ requests = request_set.sorted_requests.map(&:full_name)
assert_equal %w[a-1 b-1], requests
end
@@ -1121,10 +1155,10 @@ class TestGemDependencyInstaller < Gem::TestCase
FileUtils.mv @a1_gem, @tempdir
FileUtils.mv @b1_gem, @tempdir
- inst = Gem::DependencyInstaller.new :ignore_dependencies => true
- request_set = inst.resolve_dependencies 'b', req('>= 0')
+ inst = Gem::DependencyInstaller.new ignore_dependencies: true
+ request_set = inst.resolve_dependencies "b", req(">= 0")
- requests = request_set.sorted_requests.map {|req| req.full_name }
+ requests = request_set.sorted_requests.map(&:full_name)
assert request_set.ignore_dependencies
@@ -1134,21 +1168,21 @@ class TestGemDependencyInstaller < Gem::TestCase
def test_resolve_dependencies_local
util_setup_gems
- @a2, @a2_gem = util_gem 'a', '2'
+ @a2, @a2_gem = util_gem "a", "2"
FileUtils.mv @a1_gem, @tempdir
FileUtils.mv @a2_gem, @tempdir
inst = Gem::DependencyInstaller.new
- request_set = inst.resolve_dependencies 'a-1.gem', req('>= 0')
+ request_set = inst.resolve_dependencies "a-1.gem", req(">= 0")
- requests = request_set.sorted_requests.map {|req| req.full_name }
+ requests = request_set.sorted_requests.map(&:full_name)
assert_equal %w[a-1], requests
end
def util_setup_d
- @d1, @d1_gem = util_gem 'd', '1'
- @d2, @d2_gem = util_gem 'd', '2'
+ @d1, @d1_gem = util_gem "d", "1"
+ @d2, @d2_gem = util_gem "d", "2"
util_setup_spec_fetcher(@d1, @d2)
end
diff --git a/test/rubygems/test_gem_dependency_list.rb b/test/rubygems/test_gem_dependency_list.rb
index 15c50de199..590e042315 100644
--- a/test/rubygems/test_gem_dependency_list.rb
+++ b/test/rubygems/test_gem_dependency_list.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/dependency_list'
+
+require_relative "helper"
+require "rubygems/dependency_list"
class TestGemDependencyList < Gem::TestCase
def setup
@@ -9,26 +10,26 @@ class TestGemDependencyList < Gem::TestCase
@deplist = Gem::DependencyList.new
# TODO: switch to util_spec
- @a1 = util_spec 'a', '1'
- @a2 = util_spec 'a', '2'
- @a3 = util_spec 'a', '3'
+ @a1 = util_spec "a", "1"
+ @a2 = util_spec "a", "2"
+ @a3 = util_spec "a", "3"
- @b1 = util_spec 'b', '1' do |s|
- s.add_dependency 'a', '>= 1'
+ @b1 = util_spec "b", "1" do |s|
+ s.add_dependency "a", ">= 1"
end
- @b2 = util_spec 'b', '2' do |s|
- s.add_dependency 'a', '>= 1'
+ @b2 = util_spec "b", "2" do |s|
+ s.add_dependency "a", ">= 1"
end
- @c1 = util_spec 'c', '1' do |s|
- s.add_dependency 'b', '>= 1'
+ @c1 = util_spec "c", "1" do |s|
+ s.add_dependency "b", ">= 1"
end
- @c2 = util_spec 'c', '2'
+ @c2 = util_spec "c", "2"
- @d1 = util_spec 'd', '1' do |s|
- s.add_dependency 'c', '>= 1'
+ @d1 = util_spec "d", "1" do |s|
+ s.add_dependency "c", ">= 1"
end
end
@@ -52,55 +53,55 @@ class TestGemDependencyList < Gem::TestCase
order = @deplist.dependency_order
- assert_equal %w[d-1 c-1 b-1 a-1], order.map {|s| s.full_name }
+ assert_equal %w[d-1 c-1 b-1 a-1], order.map(&:full_name)
end
def test_dependency_order_circle
- @a1.add_dependency 'c', '>= 1'
+ @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 }
+ assert_equal %w[b-1 c-1 a-1], order.map(&:full_name)
end
def test_dependency_order_development
- e1 = util_spec 'e', '1'
- f1 = util_spec 'f', '1'
- g1 = util_spec 'g', '1'
+ e1 = util_spec "e", "1"
+ f1 = util_spec "f", "1"
+ g1 = util_spec "g", "1"
- @a1.add_dependency 'e'
- @a1.add_dependency 'f'
- @a1.add_dependency 'g'
- g1.add_development_dependency 'a'
+ @a1.add_dependency "e"
+ @a1.add_dependency "f"
+ @a1.add_dependency "g"
+ g1.add_development_dependency "a"
deplist = Gem::DependencyList.new true
deplist.add @a1, e1, f1, g1
order = deplist.dependency_order
- assert_equal %w[g-1 a-1 f-1 e-1], order.map {|s| s.full_name },
- 'development on'
+ assert_equal %w[g-1 a-1 f-1 e-1], order.map(&:full_name),
+ "development on"
deplist2 = Gem::DependencyList.new
deplist2.add @a1, e1, f1, g1
order = deplist2.dependency_order
- assert_equal %w[a-1 g-1 f-1 e-1], order.map {|s| s.full_name },
- 'development off'
+ assert_equal %w[a-1 g-1 f-1 e-1], order.map(&:full_name),
+ "development off"
end
def test_dependency_order_diamond
util_diamond
- e1 = util_spec 'e', '1'
+ e1 = util_spec "e", "1"
@deplist.add e1
- @a1.add_dependency 'e', '>= 1'
+ @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'
+ assert_equal %w[d-1 c-2 b-1 a-2 e-1], order.map(&:full_name),
+ "deps of trimmed specs not included"
end
def test_dependency_order_no_dependencies
@@ -108,7 +109,7 @@ class TestGemDependencyList < Gem::TestCase
order = @deplist.dependency_order
- assert_equal %w[c-2 a-1], order.map {|s| s.full_name }
+ assert_equal %w[c-2 a-1], order.map(&:full_name)
end
def test_find_name
@@ -121,15 +122,15 @@ class TestGemDependencyList < Gem::TestCase
end
def test_ok_eh
- assert @deplist.ok?, 'no dependencies'
+ assert @deplist.ok?, "no dependencies"
@deplist.add @b2
- refute @deplist.ok?, 'unsatisfied dependency'
+ refute @deplist.ok?, "unsatisfied dependency"
@deplist.add @a1
- assert @deplist.ok?, 'satisfied dependency'
+ assert @deplist.ok?, "satisfied dependency"
end
def test_why_not_ok_eh
@@ -147,13 +148,13 @@ class TestGemDependencyList < Gem::TestCase
end
def test_why_not_ok_eh_old_dependency
- a = util_spec 'a', '1',
- 'b' => '~> 1.0'
+ a = util_spec "a", "1",
+ "b" => "~> 1.0"
- b0 = util_spec 'b', '1.0',
- 'd' => '>= 0'
+ b0 = util_spec "b", "1.0",
+ "d" => ">= 0"
- b1 = util_spec 'b', '1.1'
+ b1 = util_spec "b", "1.1"
util_clear_gems
@@ -165,25 +166,25 @@ class TestGemDependencyList < Gem::TestCase
end
def test_ok_eh_mismatch
- a1 = util_spec 'a', '1'
- a2 = util_spec 'a', '2'
+ a1 = util_spec "a", "1"
+ a2 = util_spec "a", "2"
- b = util_spec 'b', '1' do |s|
- s.add_dependency 'a', '= 1'
+ b = util_spec "b", "1" do |s|
+ s.add_dependency "a", "= 1"
end
- c = util_spec 'c', '1' do |s|
- s.add_dependency 'a', '= 2'
+ c = util_spec "c", "1" do |s|
+ s.add_dependency "a", "= 2"
end
- d = util_spec 'd', '1' do |s|
- s.add_dependency 'b'
- s.add_dependency 'c'
+ d = util_spec "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'
+ assert @deplist.ok?, "this will break on require"
end
def test_ok_eh_redundant
@@ -256,8 +257,8 @@ class TestGemDependencyList < Gem::TestCase
# d1 -> b1 -> a1
# d1 -> c2 -> a2
def util_diamond
- @c2.add_dependency 'a', '>= 2'
- @d1.add_dependency 'b'
+ @c2.add_dependency "a", ">= 2"
+ @d1.add_dependency "b"
@deplist.add @a1, @a2, @b1, @c2, @d1
end
diff --git a/test/rubygems/test_gem_dependency_resolution_error.rb b/test/rubygems/test_gem_dependency_resolution_error.rb
index 0e4a2fe31a..98a6b6b8fd 100644
--- a/test/rubygems/test_gem_dependency_resolution_error.rb
+++ b/test/rubygems/test_gem_dependency_resolution_error.rb
@@ -1,26 +1,25 @@
# frozen_string_literal: true
-require_relative 'helper'
+
+require_relative "helper"
class TestGemDependencyResolutionError < Gem::TestCase
def setup
super
- @DR = Gem::Resolver
-
- @spec = util_spec 'a', 2
+ @spec = util_spec "a", 2
- @a1_req = @DR::DependencyRequest.new dep('a', '= 1'), nil
- @a2_req = @DR::DependencyRequest.new dep('a', '= 2'), nil
+ @a1_req = Gem::Resolver::DependencyRequest.new dep("a", "= 1"), nil
+ @a2_req = Gem::Resolver::DependencyRequest.new dep("a", "= 2"), nil
- @activated = @DR::ActivationRequest.new @spec, @a2_req
+ @activated = Gem::Resolver::ActivationRequest.new @spec, @a2_req
- @conflict = @DR::Conflict.new @a1_req, @activated
+ @conflict = Gem::Resolver::Conflict.new @a1_req, @activated
@error = Gem::DependencyResolutionError.new @conflict
end
def test_message
- assert_match %r{^conflicting dependencies a \(= 1\) and a \(= 2\)$},
- @error.message
+ assert_match(/^conflicting dependencies a \(= 1\) and a \(= 2\)$/,
+ @error.message)
end
end
diff --git a/test/rubygems/test_gem_doctor.rb b/test/rubygems/test_gem_doctor.rb
index 583c735dd3..1bcdc39022 100644
--- a/test/rubygems/test_gem_doctor.rb
+++ b/test/rubygems/test_gem_doctor.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/doctor'
+
+require_relative "helper"
+require "rubygems/doctor"
class TestGemDoctor < Gem::TestCase
def gem(name)
@@ -15,20 +16,20 @@ class TestGemDoctor < Gem::TestCase
end
def test_doctor
- a = gem 'a'
- b = gem 'b'
- c = gem 'c'
+ a = gem "a"
+ b = gem "b"
+ c = gem "c"
Gem.use_paths @userhome, @gemhome
FileUtils.rm b.spec_file
- File.open c.spec_file, 'w' do |io|
- io.write 'this will raise an exception when evaluated.'
+ File.open c.spec_file, "w" do |io|
+ io.write "this will raise an exception when evaluated."
end
- assert_path_exist File.join(a.gem_dir, 'Rakefile')
- assert_path_exist File.join(a.gem_dir, 'lib', 'a.rb')
+ assert_path_exist File.join(a.gem_dir, "Rakefile")
+ assert_path_exist File.join(a.gem_dir, "lib", "a.rb")
assert_path_exist b.gem_dir
assert_path_not_exist b.spec_file
@@ -44,8 +45,8 @@ class TestGemDoctor < Gem::TestCase
end
end
- assert_path_exist File.join(a.gem_dir, 'Rakefile')
- assert_path_exist File.join(a.gem_dir, 'lib', 'a.rb')
+ assert_path_exist File.join(a.gem_dir, "Rakefile")
+ assert_path_exist File.join(a.gem_dir, "lib", "a.rb")
assert_path_not_exist b.gem_dir
assert_path_not_exist b.spec_file
@@ -68,20 +69,20 @@ Removed directory gems/c-2
end
def test_doctor_dry_run
- a = gem 'a'
- b = gem 'b'
- c = gem 'c'
+ a = gem "a"
+ b = gem "b"
+ c = gem "c"
Gem.use_paths @userhome, @gemhome
FileUtils.rm b.spec_file
- File.open c.spec_file, 'w' do |io|
- io.write 'this will raise an exception when evaluated.'
+ File.open c.spec_file, "w" do |io|
+ io.write "this will raise an exception when evaluated."
end
- assert_path_exist File.join(a.gem_dir, 'Rakefile')
- assert_path_exist File.join(a.gem_dir, 'lib', 'a.rb')
+ assert_path_exist File.join(a.gem_dir, "Rakefile")
+ assert_path_exist File.join(a.gem_dir, "lib", "a.rb")
assert_path_exist b.gem_dir
assert_path_not_exist b.spec_file
@@ -97,8 +98,8 @@ Removed directory gems/c-2
end
end
- assert_path_exist File.join(a.gem_dir, 'Rakefile')
- assert_path_exist File.join(a.gem_dir, 'lib', 'a.rb')
+ assert_path_exist File.join(a.gem_dir, "Rakefile")
+ assert_path_exist File.join(a.gem_dir, "lib", "a.rb")
assert_path_exist b.gem_dir
assert_path_not_exist b.spec_file
@@ -121,7 +122,7 @@ Extra directory gems/c-2
end
def test_doctor_non_gem_home
- other_dir = File.join @tempdir, 'other', 'dir'
+ other_dir = File.join @tempdir, "other", "dir"
FileUtils.mkdir_p other_dir
@@ -147,13 +148,13 @@ This directory does not appear to be a RubyGems repository, skipping
def test_doctor_child_missing
doctor = Gem::Doctor.new @gemhome
- doctor.doctor_child 'missing', ''
+ doctor.doctor_child "missing", ""
assert true # count
end
def test_doctor_badly_named_plugins
- gem 'a'
+ gem "a"
Gem.use_paths @gemhome.to_s
@@ -183,12 +184,12 @@ Removed file plugins/a_badly_named_file.rb
def test_gem_repository_eh
doctor = Gem::Doctor.new @gemhome
- refute doctor.gem_repository?, 'no gems installed'
+ refute doctor.gem_repository?, "no gems installed"
- install_specs util_spec 'a'
+ install_specs util_spec "a"
doctor = Gem::Doctor.new @gemhome
- assert doctor.gem_repository?, 'gems installed'
+ assert doctor.gem_repository?, "gems installed"
end
end
diff --git a/test/rubygems/test_gem_ext_builder.rb b/test/rubygems/test_gem_ext_builder.rb
index 165194510e..34f85e6b75 100644
--- a/test/rubygems/test_gem_ext_builder.rb
+++ b/test/rubygems/test_gem_ext_builder.rb
@@ -1,38 +1,37 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/ext'
-require 'rubygems/installer'
+
+require_relative "helper"
+require "rubygems/ext"
+require "rubygems/installer"
class TestGemExtBuilder < Gem::TestCase
def setup
+ @orig_destdir = ENV["DESTDIR"]
+ @orig_make = ENV["make"]
super
- @ext = File.join @tempdir, 'ext'
- @dest_path = File.join @tempdir, 'prefix'
+ @ext = File.join @tempdir, "ext"
+ @dest_path = File.join @tempdir, "prefix"
FileUtils.mkdir_p @ext
FileUtils.mkdir_p @dest_path
- @orig_DESTDIR = ENV['DESTDIR']
- @orig_make = ENV['make']
-
- @spec = util_spec 'a'
+ @spec = util_spec "a"
- @builder = Gem::Ext::Builder.new @spec, ''
+ @builder = Gem::Ext::Builder.new @spec, ""
end
def teardown
- ENV['DESTDIR'] = @orig_DESTDIR
- ENV['make'] = @orig_make
-
super
+ ENV["DESTDIR"] = @orig_destdir
+ ENV["make"] = @orig_make
end
def test_class_make
- ENV['DESTDIR'] = 'destination'
+ ENV["DESTDIR"] = "destination"
results = []
- File.open File.join(@ext, 'Makefile'), 'w' do |io|
+ File.open File.join(@ext, "Makefile"), "w" do |io|
io.puts <<-MAKEFILE
all:
\t@#{Gem.ruby} -e "puts %Q{all: \#{ENV['DESTDIR']}}"
@@ -49,22 +48,22 @@ install:
results = results.join("\n").b
- assert_match %r{DESTDIR\\=#{ENV['DESTDIR']} clean$}, results
- assert_match %r{DESTDIR\\=#{ENV['DESTDIR']}$}, results
- assert_match %r{DESTDIR\\=#{ENV['DESTDIR']} install$}, results
+ assert_match(/DESTDIR\\=#{ENV["DESTDIR"]} clean$/, results)
+ assert_match(/DESTDIR\\=#{ENV["DESTDIR"]}$/, results)
+ assert_match(/DESTDIR\\=#{ENV["DESTDIR"]} install$/, results)
- if /nmake/ !~ results
- assert_match %r{^clean: destination$}, results
- assert_match %r{^all: destination$}, results
- assert_match %r{^install: destination$}, results
+ unless results.include?("nmake")
+ assert_match(/^clean: destination$/, results)
+ assert_match(/^all: destination$/, results)
+ assert_match(/^install: destination$/, results)
end
end
def test_class_make_no_clean
- ENV['DESTDIR'] = 'destination'
+ ENV["DESTDIR"] = "destination"
results = []
- File.open File.join(@ext, 'Makefile'), 'w' do |io|
+ File.open File.join(@ext, "Makefile"), "w" do |io|
io.puts <<-MAKEFILE
all:
\t@#{Gem.ruby} -e "puts %Q{all: \#{ENV['DESTDIR']}}"
@@ -78,15 +77,17 @@ install:
results = results.join("\n").b
- assert_match %r{DESTDIR\\=#{ENV['DESTDIR']} clean$}, results
- assert_match %r{DESTDIR\\=#{ENV['DESTDIR']}$}, results
- assert_match %r{DESTDIR\\=#{ENV['DESTDIR']} install$}, results
+ assert_match(/DESTDIR\\=#{ENV["DESTDIR"]} clean$/, results)
+ assert_match(/DESTDIR\\=#{ENV["DESTDIR"]}$/, results)
+ assert_match(/DESTDIR\\=#{ENV["DESTDIR"]} install$/, results)
end
def test_custom_make_with_options
- ENV['make'] = 'make V=1'
+ pend "native windows platform only provides nmake" if vc_windows?
+
+ ENV["make"] = "make V=1"
results = []
- File.open File.join(@ext, 'Makefile'), 'w' do |io|
+ File.open File.join(@ext, "Makefile"), "w" do |io|
io.puts <<-MAKEFILE
all:
\t@#{Gem.ruby} -e "puts 'all: OK'"
@@ -100,109 +101,104 @@ install:
end
Gem::Ext::Builder.make @dest_path, results, @ext
results = results.join("\n").b
- assert_match %r{clean: OK}, results
- assert_match %r{all: OK}, results
- assert_match %r{install: OK}, results
+ assert_match(/clean: OK/, results)
+ assert_match(/all: OK/, results)
+ assert_match(/install: OK/, results)
end
def test_build_extensions
- pend if /mswin/ =~ RUBY_PLATFORM && ENV.key?('GITHUB_ACTIONS') # not working from the beginning
- @spec.extensions << 'ext/extconf.rb'
+ pend "terminates on mswin" if vc_windows? && ruby_repo?
- ext_dir = File.join @spec.gem_dir, 'ext'
+ extension_in_lib do
+ @spec.extensions << "ext/extconf.rb"
- FileUtils.mkdir_p ext_dir
+ ext_dir = File.join @spec.gem_dir, "ext"
- extconf_rb = File.join ext_dir, 'extconf.rb'
+ FileUtils.mkdir_p ext_dir
- File.open extconf_rb, 'w' do |f|
- f.write <<-'RUBY'
- require 'mkmf'
+ extconf_rb = File.join ext_dir, "extconf.rb"
- create_makefile 'a'
- RUBY
- end
+ File.open extconf_rb, "w" do |f|
+ f.write <<-'RUBY'
+ require 'mkmf'
- ext_lib_dir = File.join ext_dir, 'lib'
- FileUtils.mkdir ext_lib_dir
- FileUtils.touch File.join ext_lib_dir, 'a.rb'
- FileUtils.mkdir File.join ext_lib_dir, 'a'
- FileUtils.touch File.join ext_lib_dir, 'a', 'b.rb'
+ create_makefile 'a'
+ RUBY
+ end
- use_ui @ui do
- @builder.build_extensions
- end
+ ext_lib_dir = File.join ext_dir, "lib"
+ FileUtils.mkdir ext_lib_dir
+ FileUtils.touch File.join ext_lib_dir, "a.rb"
+ FileUtils.mkdir File.join ext_lib_dir, "a"
+ FileUtils.touch File.join ext_lib_dir, "a", "b.rb"
- assert_path_exist @spec.extension_dir
- assert_path_exist @spec.gem_build_complete_path
- assert_path_exist File.join @spec.extension_dir, 'gem_make.out'
- assert_path_exist File.join @spec.extension_dir, 'a.rb'
- assert_path_exist File.join @spec.gem_dir, 'lib', 'a.rb'
- assert_path_exist File.join @spec.gem_dir, 'lib', 'a', 'b.rb'
+ use_ui @ui do
+ @builder.build_extensions
+ end
+
+ assert_path_exist @spec.extension_dir
+ assert_path_exist @spec.gem_build_complete_path
+ assert_path_exist File.join @spec.extension_dir, "gem_make.out"
+ assert_path_exist File.join @spec.extension_dir, "a.rb"
+ assert_path_exist File.join @spec.gem_dir, "lib", "a.rb"
+ assert_path_exist File.join @spec.gem_dir, "lib", "a", "b.rb"
+ end
end
def test_build_extensions_with_gemhome_with_space
- pend if /mswin/ =~ RUBY_PLATFORM && ENV.key?('GITHUB_ACTIONS') # not working from the beginning
- new_gemhome = File.join @tempdir, 'gem home'
+ pend "terminates on mswin" if vc_windows? && ruby_repo?
+ new_gemhome = File.join @tempdir, "gem home"
File.rename(@gemhome, new_gemhome)
@gemhome = new_gemhome
Gem.use_paths(@gemhome)
- @spec = util_spec 'a'
- @builder = Gem::Ext::Builder.new @spec, ''
+ @spec = util_spec "a"
+ @builder = Gem::Ext::Builder.new @spec, ""
test_build_extensions
end
def test_build_extensions_install_ext_only
- class << Gem
- alias orig_install_extension_in_lib install_extension_in_lib
+ pend "terminates on mswin" if vc_windows? && ruby_repo?
- remove_method :install_extension_in_lib
+ extension_in_lib(false) do
+ @orig_install_extension_in_lib = Gem.configuration.install_extension_in_lib
+ Gem.configuration.install_extension_in_lib = false
- def Gem.install_extension_in_lib
- false
- end
- end
- pend if /mswin/ =~ RUBY_PLATFORM && ENV.key?('GITHUB_ACTIONS') # not working from the beginning
+ @spec.extensions << "ext/extconf.rb"
- @spec.extensions << 'ext/extconf.rb'
+ ext_dir = File.join @spec.gem_dir, "ext"
- ext_dir = File.join @spec.gem_dir, 'ext'
+ FileUtils.mkdir_p ext_dir
- FileUtils.mkdir_p ext_dir
+ extconf_rb = File.join ext_dir, "extconf.rb"
- extconf_rb = File.join ext_dir, 'extconf.rb'
+ File.open extconf_rb, "w" do |f|
+ f.write <<-'RUBY'
+ require 'mkmf'
- File.open extconf_rb, 'w' do |f|
- f.write <<-'RUBY'
- require 'mkmf'
+ create_makefile 'a'
+ RUBY
+ end
- create_makefile 'a'
- RUBY
- end
+ ext_lib_dir = File.join ext_dir, "lib"
+ FileUtils.mkdir ext_lib_dir
+ FileUtils.touch File.join ext_lib_dir, "a.rb"
+ FileUtils.mkdir File.join ext_lib_dir, "a"
+ FileUtils.touch File.join ext_lib_dir, "a", "b.rb"
- ext_lib_dir = File.join ext_dir, 'lib'
- FileUtils.mkdir ext_lib_dir
- FileUtils.touch File.join ext_lib_dir, 'a.rb'
- FileUtils.mkdir File.join ext_lib_dir, 'a'
- FileUtils.touch File.join ext_lib_dir, 'a', 'b.rb'
+ use_ui @ui do
+ @builder.build_extensions
+ end
- use_ui @ui do
- @builder.build_extensions
+ assert_path_exist @spec.extension_dir
+ assert_path_exist @spec.gem_build_complete_path
+ assert_path_exist File.join @spec.extension_dir, "gem_make.out"
+ assert_path_exist File.join @spec.extension_dir, "a.rb"
+ assert_path_not_exist File.join @spec.gem_dir, "lib", "a.rb"
+ assert_path_not_exist File.join @spec.gem_dir, "lib", "a", "b.rb"
end
-
- assert_path_exist @spec.extension_dir
- assert_path_exist @spec.gem_build_complete_path
- assert_path_exist File.join @spec.extension_dir, 'gem_make.out'
- assert_path_exist File.join @spec.extension_dir, 'a.rb'
- assert_path_not_exist File.join @spec.gem_dir, 'lib', 'a.rb'
- assert_path_not_exist File.join @spec.gem_dir, 'lib', 'a', 'b.rb'
ensure
- class << Gem
- remove_method :install_extension_in_lib
-
- alias install_extension_in_lib orig_install_extension_in_lib
- end
+ Gem.configuration.install_extension_in_lib = @orig_install_extension_in_lib
end
def test_build_extensions_none
@@ -210,10 +206,10 @@ install:
@builder.build_extensions
end
- assert_equal '', @ui.output
- assert_equal '', @ui.error
+ assert_equal "", @ui.output
+ assert_equal "", @ui.error
- assert_path_not_exist File.join @spec.extension_dir, 'gem_make.out'
+ assert_path_not_exist File.join @spec.extension_dir, "gem_make.out"
end
def test_build_extensions_rebuild_failure
@@ -234,7 +230,7 @@ install:
def test_build_extensions_extconf_bad
cwd = Dir.pwd
- @spec.extensions << 'extconf.rb'
+ @spec.extensions << "extconf.rb"
FileUtils.mkdir_p @spec.gem_dir
@@ -246,13 +242,13 @@ install:
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
+ assert_equal "", @ui.error
- gem_make_out = File.join @spec.extension_dir, 'gem_make.out'
+ gem_make_out = File.join @spec.extension_dir, "gem_make.out"
cmd_make_out = File.read(gem_make_out)
assert_match %r{#{Regexp.escape Gem.ruby} .* extconf\.rb}, cmd_make_out
- assert_match %r{: No such file}, cmd_make_out
+ assert_match(/: No such file/, cmd_make_out)
assert_path_not_exist @spec.gem_build_complete_path
@@ -261,7 +257,7 @@ install:
def test_build_extensions_unsupported
FileUtils.mkdir_p @spec.gem_dir
- gem_make_out = File.join @spec.extension_dir, 'gem_make.out'
+ gem_make_out = File.join @spec.extension_dir, "gem_make.out"
@spec.extensions << nil
e = assert_raise Gem::Ext::BuildError do
@@ -272,7 +268,7 @@ install:
assert_match(/^\s*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 "", @ui.error
assert_equal "No builder for extension ''\n", File.read(gem_make_out)
@@ -284,14 +280,14 @@ install:
def test_build_extensions_with_build_args
args = ["--aa", "--bb"]
@builder.build_args = args
- @spec.extensions << 'extconf.rb'
+ @spec.extensions << "extconf.rb"
FileUtils.mkdir_p @spec.gem_dir
File.open File.join(@spec.gem_dir, "extconf.rb"), "w" do |f|
f.write <<-'RUBY'
puts "IN EXTCONF"
- extconf_args = File.join File.dirname(__FILE__), 'extconf_args'
+ extconf_args = File.join __dir__, 'extconf_args'
File.open extconf_args, 'w' do |f|
f.puts ARGV.inspect
end
@@ -314,15 +310,85 @@ install:
assert_path_exist @spec.extension_dir
end
+ def test_build_extensions_with_target_rbconfig
+ fake_rbconfig = File.join @tempdir, "fake_rbconfig.rb"
+ File.open fake_rbconfig, "w" do |f|
+ f.write <<~RUBY
+ module RbConfig
+ CONFIG = {}
+ MAKEFILE_CONFIG = {}
+
+ def self.fire_update!(key, value); end
+ def self.expand(val, config = CONFIG); val; end
+ end
+ RUBY
+ RbConfig::CONFIG.each do |k, v|
+ f.puts %(RbConfig::CONFIG[#{k.dump}] = #{v.dump})
+ end
+ RbConfig::MAKEFILE_CONFIG.each do |k, v|
+ f.puts %(RbConfig::MAKEFILE_CONFIG[#{k.dump}] = #{v.dump})
+ end
+ f.puts "RbConfig::CONFIG['host_os'] = 'fake_os'"
+ f.puts "RbConfig::CONFIG['arch'] = 'fake_arch'"
+ f.puts "RbConfig::CONFIG['platform'] = 'fake_platform'"
+ end
+
+ stdout, stderr = capture_subprocess_io do
+ system(Gem.ruby, "-rmkmf", "-e", "exit MakeMakefile::RbConfig::CONFIG['host_os'] == 'fake_os'",
+ "--", "--target-rbconfig=#{fake_rbconfig}")
+ end
+ unless $?.success?
+ assert_include(stderr, "uninitialized constant MakeMakefile::RbConfig")
+ pend "This version of mkmf does not support --target-rbconfig"
+ end
+ assert_empty(stdout)
+
+ @spec.extensions << "extconf.rb"
+ @builder = Gem::Ext::Builder.new @spec, "", Gem::TargetRbConfig.from_path(fake_rbconfig)
+
+ FileUtils.mkdir_p @spec.gem_dir
+ lib_dir = File.join(@spec.gem_dir, "lib")
+
+ FileUtils.mkdir lib_dir
+
+ File.open File.join(@spec.gem_dir, "extconf.rb"), "w" do |f|
+ f.write <<-'RUBY'
+ require 'mkmf'
+
+ extconf_args = File.join __dir__, 'rbconfig_dump'
+ File.open extconf_args, 'w' do |f|
+ ["host_os", "arch"].each do |k|
+ f.puts "#{k}=#{MakeMakefile::RbConfig::CONFIG[k]}"
+ end
+ end
+
+ create_makefile 'a'
+ RUBY
+ end
+
+ use_ui @ui do
+ @builder.build_extensions
+ end
+
+ path = File.join @spec.gem_dir, "rbconfig_dump"
+
+ assert_equal <<~DUMP, File.read(path)
+ host_os=fake_os
+ arch=fake_arch
+ DUMP
+ assert_path_exist @spec.extension_dir
+ assert_equal [], Dir.glob(File.join(lib_dir, "*"))
+ end
+
def test_initialize
- build_info_dir = File.join @gemhome, 'build_info'
+ build_info_dir = File.join @gemhome, "build_info"
FileUtils.mkdir_p build_info_dir
build_info_file = File.join build_info_dir, "#{@spec.full_name}.info"
- File.open build_info_file, 'w' do |io|
- io.puts '--with-foo-dir=/nonexistent'
+ File.open build_info_file, "w" do |io|
+ io.puts "--with-foo-dir=/nonexistent"
end
builder = Gem::Ext::Builder.new @spec
diff --git a/test/rubygems/test_gem_ext_cargo_builder.rb b/test/rubygems/test_gem_ext_cargo_builder.rb
new file mode 100644
index 0000000000..5faf3e2480
--- /dev/null
+++ b/test/rubygems/test_gem_ext_cargo_builder.rb
@@ -0,0 +1,171 @@
+# frozen_string_literal: true
+
+require_relative "helper"
+require "rubygems/ext"
+require "open3"
+
+class TestGemExtCargoBuilder < Gem::TestCase
+ def setup
+ super
+
+ @rust_envs = {
+ "CARGO_HOME" => ENV.fetch("CARGO_HOME", File.join(@orig_env["HOME"], ".cargo")),
+ "RUSTUP_HOME" => ENV.fetch("RUSTUP_HOME", File.join(@orig_env["HOME"], ".rustup")),
+ }
+ end
+
+ def setup_rust_gem(name)
+ @ext = File.join(@tempdir, "ext")
+ @dest_path = File.join(@tempdir, "prefix")
+ @fixture_dir = Pathname.new(File.expand_path("test_gem_ext_cargo_builder/#{name}/", __dir__))
+
+ FileUtils.mkdir_p @dest_path
+ FileUtils.cp_r(@fixture_dir.to_s, @ext)
+ end
+
+ def test_build_cdylib
+ skip_unsupported_platforms!
+ setup_rust_gem "rust_ruby_example"
+
+ output = []
+
+ Dir.chdir @ext do
+ ENV.update(@rust_envs)
+ builder = Gem::Ext::CargoBuilder.new
+ builder.build "Cargo.toml", @dest_path, output
+ end
+
+ output = output.join "\n"
+ bundle = File.join(@dest_path, "rust_ruby_example.#{RbConfig::CONFIG["DLEXT"]}")
+
+ assert_match(/Finished/, output)
+ assert_match(/release/, output)
+ assert_ffi_handle bundle, "Init_rust_ruby_example"
+ rescue StandardError => e
+ pp output if output
+
+ raise(e)
+ end
+
+ def test_rubygems_cfg_passed_to_rustc
+ skip_unsupported_platforms!
+ setup_rust_gem "rust_ruby_example"
+ version_slug = Gem::VERSION.tr(".", "_")
+ output = []
+
+ replace_in_rust_file("src/lib.rs", "rubygems_x_x_x", "rubygems_#{version_slug}")
+
+ Dir.chdir @ext do
+ ENV.update(@rust_envs)
+ builder = Gem::Ext::CargoBuilder.new
+ builder.build "Cargo.toml", @dest_path, output
+ end
+
+ output = output.join "\n"
+ bundle = File.join(@dest_path, "rust_ruby_example.#{RbConfig::CONFIG["DLEXT"]}")
+
+ assert_ffi_handle bundle, "hello_from_rubygems"
+ assert_ffi_handle bundle, "hello_from_rubygems_version"
+ refute_ffi_handle bundle, "should_never_exist"
+ rescue StandardError => e
+ pp output if output
+
+ raise(e)
+ end
+
+ def test_build_fail
+ skip_unsupported_platforms!
+ setup_rust_gem "rust_ruby_example"
+
+ FileUtils.rm(File.join(@ext, "src/lib.rs"))
+
+ error = assert_raise(Gem::InstallError) do
+ Dir.chdir @ext do
+ ENV.update(@rust_envs)
+ builder = Gem::Ext::CargoBuilder.new
+ builder.build "Cargo.toml", @dest_path, []
+ end
+ end
+
+ assert_match(/cargo\s.*\sfailed/, error.message)
+ end
+
+ def test_full_integration
+ skip_unsupported_platforms!
+ setup_rust_gem "rust_ruby_example"
+
+ require "open3"
+
+ Dir.chdir @ext do
+ require "tmpdir"
+
+ env_for_subprocess = @rust_envs.merge("GEM_HOME" => Gem.paths.home)
+ gem = [env_for_subprocess, *ruby_with_rubygems_in_load_path, File.expand_path("../../exe/gem", __dir__)]
+
+ Dir.mktmpdir("rust_ruby_example") do |dir|
+ built_gem = File.expand_path(File.join(dir, "rust_ruby_example.gem"))
+ Open3.capture2e(*gem, "build", "rust_ruby_example.gemspec", "--output", built_gem)
+ Open3.capture2e(*gem, "install", "--verbose", "--local", built_gem, *ARGV)
+
+ stdout_and_stderr_str, status = Open3.capture2e(env_for_subprocess, *ruby_with_rubygems_in_load_path, "-rrust_ruby_example", "-e", "puts 'Result: ' + RustRubyExample.reverse('hello world')")
+ assert status.success?, stdout_and_stderr_str
+ assert_match "Result: #{"hello world".reverse}", stdout_and_stderr_str
+ end
+ end
+ end
+
+ def test_custom_name
+ skip_unsupported_platforms!
+ setup_rust_gem "custom_name"
+
+ Dir.chdir @ext do
+ require "tmpdir"
+
+ env_for_subprocess = @rust_envs.merge("GEM_HOME" => Gem.paths.home)
+ gem = [env_for_subprocess, *ruby_with_rubygems_in_load_path, File.expand_path("../../exe/gem", __dir__)]
+
+ Dir.mktmpdir("custom_name") do |dir|
+ built_gem = File.expand_path(File.join(dir, "custom_name.gem"))
+ Open3.capture2e(*gem, "build", "custom_name.gemspec", "--output", built_gem)
+ Open3.capture2e(*gem, "install", "--verbose", "--local", built_gem, *ARGV)
+ end
+
+ stdout_and_stderr_str, status = Open3.capture2e(env_for_subprocess, *ruby_with_rubygems_in_load_path, "-rcustom_name", "-e", "puts 'Result: ' + CustomName.say_hello")
+
+ assert status.success?, stdout_and_stderr_str
+ assert_match "Result: Hello world!", stdout_and_stderr_str
+ end
+ end
+
+ private
+
+ def skip_unsupported_platforms!
+ pend "jruby not supported" if Gem.java_platform?
+ pend "truffleruby not supported (yet)" if RUBY_ENGINE == "truffleruby"
+ system(@rust_envs, "cargo", "-V", out: IO::NULL, err: [:child, :out])
+ pend "cargo not present" unless $?.success?
+ pend "ruby.h is not provided by ruby repo" if ruby_repo?
+ pend "rust toolchain of mingw is broken" if mingw_windows?
+ end
+
+ def assert_ffi_handle(bundle, name)
+ require "fiddle"
+ dylib_handle = Fiddle.dlopen bundle
+ assert_nothing_raised { dylib_handle[name] }
+ ensure
+ dylib_handle&.close
+ end
+
+ def refute_ffi_handle(bundle, name)
+ require "fiddle"
+ dylib_handle = Fiddle.dlopen bundle
+ assert_raise { dylib_handle[name] }
+ ensure
+ dylib_handle&.close
+ end
+
+ def replace_in_rust_file(name, from, to)
+ content = @fixture_dir.join(name).read.gsub(from, to)
+ File.write(File.join(@ext, name), content)
+ end
+end
diff --git a/test/rubygems/test_gem_ext_cargo_builder/custom_name/.gitignore b/test/rubygems/test_gem_ext_cargo_builder/custom_name/.gitignore
new file mode 100644
index 0000000000..2f7896d1d1
--- /dev/null
+++ b/test/rubygems/test_gem_ext_cargo_builder/custom_name/.gitignore
@@ -0,0 +1 @@
+target/
diff --git a/test/rubygems/test_gem_ext_cargo_builder/custom_name/custom_name.gemspec b/test/rubygems/test_gem_ext_cargo_builder/custom_name/custom_name.gemspec
new file mode 100644
index 0000000000..5f130527dd
--- /dev/null
+++ b/test/rubygems/test_gem_ext_cargo_builder/custom_name/custom_name.gemspec
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+Gem::Specification.new do |s|
+ s.name = "custom_name"
+ s.version = "0.1.0"
+ s.summary = "A Rust extension for Ruby"
+ s.extensions = ["ext/custom_name_lib/Cargo.toml"]
+ s.authors = ["Ian Ker-Seymer"]
+ s.files = ["lib/custom_name.rb", "ext/custom_name_lib/Cargo.toml", "ext/custom_name_lib/Cargo.lock", "ext/custom_name_lib/src/lib.rs"]
+end
diff --git a/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.lock b/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.lock
new file mode 100644
index 0000000000..5ea15859f6
--- /dev/null
+++ b/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.lock
@@ -0,0 +1,249 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "aho-corasick"
+version = "0.7.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "bindgen"
+version = "0.69.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ffcebc3849946a7170a05992aac39da343a90676ab392c51a4280981d6379c2"
+dependencies = [
+ "bitflags",
+ "cexpr",
+ "clang-sys",
+ "lazy_static",
+ "lazycell",
+ "peeking_take_while",
+ "proc-macro2",
+ "quote",
+ "regex",
+ "rustc-hash",
+ "shlex",
+ "syn",
+]
+
+[[package]]
+name = "bitflags"
+version = "2.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42"
+
+[[package]]
+name = "cexpr"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
+dependencies = [
+ "nom",
+]
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "clang-sys"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fa2e27ae6ab525c3d369ded447057bca5438d86dc3a68f6faafb8269ba82ebf3"
+dependencies = [
+ "glob",
+ "libc",
+ "libloading",
+]
+
+[[package]]
+name = "custom-name-ext"
+version = "0.1.0"
+dependencies = [
+ "rb-sys",
+]
+
+[[package]]
+name = "glob"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
+name = "lazycell"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
+
+[[package]]
+name = "libc"
+version = "0.2.138"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
+
+[[package]]
+name = "libloading"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
+dependencies = [
+ "cfg-if",
+ "winapi",
+]
+
+[[package]]
+name = "memchr"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
+
+[[package]]
+name = "minimal-lexical"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
+
+[[package]]
+name = "nom"
+version = "7.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36"
+dependencies = [
+ "memchr",
+ "minimal-lexical",
+]
+
+[[package]]
+name = "peeking_take_while"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.66"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "rb-sys"
+version = "0.9.102"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df4dec4b1d304c3b308a2cd86b1216ea45dd4361f4e9fa056f108332d0a450c1"
+dependencies = [
+ "rb-sys-build",
+]
+
+[[package]]
+name = "rb-sys-build"
+version = "0.9.102"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d71de3e29d174b8fb17b5d4470f27d7aa2605f8a9d05fda0d3aeff30e05a570"
+dependencies = [
+ "bindgen",
+ "lazy_static",
+ "proc-macro2",
+ "quote",
+ "regex",
+ "shell-words",
+ "syn",
+]
+
+[[package]]
+name = "regex"
+version = "1.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.6.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
+
+[[package]]
+name = "rustc-hash"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
+
+[[package]]
+name = "shell-words"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde"
+
+[[package]]
+name = "shlex"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
+
+[[package]]
+name = "syn"
+version = "2.0.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
diff --git a/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.toml b/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.toml
new file mode 100644
index 0000000000..3d78418ed3
--- /dev/null
+++ b/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name = "custom-name-ext"
+version = "0.1.0"
+edition = "2021"
+
+[lib]
+crate-type = ["cdylib"]
+
+[dependencies]
+rb-sys = "0.9.102"
diff --git a/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/src/lib.rs b/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/src/lib.rs
new file mode 100644
index 0000000000..28ba3be564
--- /dev/null
+++ b/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/src/lib.rs
@@ -0,0 +1,27 @@
+extern crate rb_sys;
+
+use rb_sys::{rb_define_module, rb_define_module_function, rb_utf8_str_new, VALUE};
+use std::ffi::CString;
+
+#[no_mangle]
+unsafe extern "C" fn say_hello(_klass: VALUE) -> VALUE {
+ let cstr = CString::new("Hello world!").unwrap();
+
+ rb_utf8_str_new(cstr.as_ptr(), 12)
+}
+
+#[allow(non_snake_case)]
+#[no_mangle]
+pub extern "C" fn Init_custom_name_ext() {
+ let name = CString::new("CustomName").unwrap();
+ let function_name = CString::new("say_hello").unwrap();
+ // bindgen does not properly detect the arity of the ruby callback function, so we have to transmute
+ let callback = unsafe {
+ std::mem::transmute::<unsafe extern "C" fn(VALUE) -> VALUE, unsafe extern "C" fn() -> VALUE>(
+ say_hello,
+ )
+ };
+ let klass = unsafe { rb_define_module(name.as_ptr()) };
+
+ unsafe { rb_define_module_function(klass, function_name.as_ptr(), Some(callback), 0) }
+}
diff --git a/test/rubygems/test_gem_ext_cargo_builder/custom_name/lib/custom_name.rb b/test/rubygems/test_gem_ext_cargo_builder/custom_name/lib/custom_name.rb
new file mode 100644
index 0000000000..9f8d190baf
--- /dev/null
+++ b/test/rubygems/test_gem_ext_cargo_builder/custom_name/lib/custom_name.rb
@@ -0,0 +1,3 @@
+# frozen_string_literal: true
+
+require "custom_name_lib/custom_name_ext"
diff --git a/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/.gitignore b/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/.gitignore
new file mode 100644
index 0000000000..2f7896d1d1
--- /dev/null
+++ b/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/.gitignore
@@ -0,0 +1 @@
+target/
diff --git a/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock b/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock
new file mode 100644
index 0000000000..21e26dd123
--- /dev/null
+++ b/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock
@@ -0,0 +1,249 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "aho-corasick"
+version = "0.7.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "bindgen"
+version = "0.69.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ffcebc3849946a7170a05992aac39da343a90676ab392c51a4280981d6379c2"
+dependencies = [
+ "bitflags",
+ "cexpr",
+ "clang-sys",
+ "lazy_static",
+ "lazycell",
+ "peeking_take_while",
+ "proc-macro2",
+ "quote",
+ "regex",
+ "rustc-hash",
+ "shlex",
+ "syn",
+]
+
+[[package]]
+name = "bitflags"
+version = "2.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "630be753d4e58660abd17930c71b647fe46c27ea6b63cc59e1e3851406972e42"
+
+[[package]]
+name = "cexpr"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
+dependencies = [
+ "nom",
+]
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "clang-sys"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fa2e27ae6ab525c3d369ded447057bca5438d86dc3a68f6faafb8269ba82ebf3"
+dependencies = [
+ "glob",
+ "libc",
+ "libloading",
+]
+
+[[package]]
+name = "glob"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
+name = "lazycell"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
+
+[[package]]
+name = "libc"
+version = "0.2.138"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
+
+[[package]]
+name = "libloading"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
+dependencies = [
+ "cfg-if",
+ "winapi",
+]
+
+[[package]]
+name = "memchr"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
+
+[[package]]
+name = "minimal-lexical"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
+
+[[package]]
+name = "nom"
+version = "7.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36"
+dependencies = [
+ "memchr",
+ "minimal-lexical",
+]
+
+[[package]]
+name = "peeking_take_while"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.66"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "rb-sys"
+version = "0.9.102"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df4dec4b1d304c3b308a2cd86b1216ea45dd4361f4e9fa056f108332d0a450c1"
+dependencies = [
+ "rb-sys-build",
+]
+
+[[package]]
+name = "rb-sys-build"
+version = "0.9.102"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d71de3e29d174b8fb17b5d4470f27d7aa2605f8a9d05fda0d3aeff30e05a570"
+dependencies = [
+ "bindgen",
+ "lazy_static",
+ "proc-macro2",
+ "quote",
+ "regex",
+ "shell-words",
+ "syn",
+]
+
+[[package]]
+name = "regex"
+version = "1.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.6.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
+
+[[package]]
+name = "rust_ruby_example"
+version = "0.1.0"
+dependencies = [
+ "rb-sys",
+]
+
+[[package]]
+name = "rustc-hash"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
+
+[[package]]
+name = "shell-words"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde"
+
+[[package]]
+name = "shlex"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
+
+[[package]]
+name = "syn"
+version = "2.0.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
diff --git a/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.toml b/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.toml
new file mode 100644
index 0000000000..ac2454eda7
--- /dev/null
+++ b/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name = "rust_ruby_example"
+version = "0.1.0"
+edition = "2021"
+
+[lib]
+crate-type = ["cdylib"]
+
+[dependencies]
+rb-sys = "0.9.102"
diff --git a/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/rust_ruby_example.gemspec b/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/rust_ruby_example.gemspec
new file mode 100644
index 0000000000..d3f8b11a8b
--- /dev/null
+++ b/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/rust_ruby_example.gemspec
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+Gem::Specification.new do |s|
+ s.name = "rust_ruby_example"
+ s.version = "0.1.0"
+ s.summary = "A Rust extension for Ruby"
+ s.extensions = ["Cargo.toml"]
+ s.authors = ["Ian Ker-Seymer"]
+ s.files = ["Cargo.toml", "Cargo.lock", "src/lib.rs"]
+end
diff --git a/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/src/lib.rs b/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/src/lib.rs
new file mode 100644
index 0000000000..0626f04e0f
--- /dev/null
+++ b/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/src/lib.rs
@@ -0,0 +1,51 @@
+extern crate rb_sys;
+
+use rb_sys::{
+ rb_define_module, rb_define_module_function, rb_string_value_cstr, rb_utf8_str_new, VALUE,
+};
+use std::ffi::{CStr, CString};
+use std::os::raw::{c_char, c_long};
+
+#[inline]
+unsafe fn cstr_to_string(str: *const c_char) -> String {
+ CStr::from_ptr(str).to_string_lossy().into_owned()
+}
+
+#[no_mangle]
+unsafe extern "C" fn pub_reverse(_klass: VALUE, mut input: VALUE) -> VALUE {
+ let ruby_string = cstr_to_string(rb_string_value_cstr(&mut input));
+ let reversed = ruby_string.to_string().chars().rev().collect::<String>();
+ let reversed_cstring = CString::new(reversed).unwrap();
+ let size = ruby_string.len() as c_long;
+
+ rb_utf8_str_new(reversed_cstring.as_ptr(), size)
+}
+
+#[cfg(rubygems)]
+#[no_mangle]
+pub extern "C" fn hello_from_rubygems() {}
+
+#[cfg(rubygems_0_0_0)]
+#[no_mangle]
+pub extern "C" fn should_never_exist() {}
+
+#[cfg(rubygems_x_x_x)]
+#[no_mangle]
+pub extern "C" fn hello_from_rubygems_version() {}
+
+#[allow(non_snake_case)]
+#[no_mangle]
+pub extern "C" fn Init_rust_ruby_example() {
+ let name = CString::new("RustRubyExample").unwrap();
+ let function_name = CString::new("reverse").unwrap();
+ // bindgen does not properly detect the arity of the ruby callback function, so we have to transmute
+ let callback = unsafe {
+ std::mem::transmute::<
+ unsafe extern "C" fn(VALUE, VALUE) -> VALUE,
+ unsafe extern "C" fn() -> VALUE,
+ >(pub_reverse)
+ };
+ let klass = unsafe { rb_define_module(name.as_ptr()) };
+
+ unsafe { rb_define_module_function(klass, function_name.as_ptr(), Some(callback), 1) }
+}
diff --git a/test/rubygems/test_gem_ext_cargo_builder_link_flag_converter.rb b/test/rubygems/test_gem_ext_cargo_builder_link_flag_converter.rb
new file mode 100644
index 0000000000..a3fef50d54
--- /dev/null
+++ b/test/rubygems/test_gem_ext_cargo_builder_link_flag_converter.rb
@@ -0,0 +1,34 @@
+# frozen_string_literal: true
+
+require_relative "helper"
+require "rubygems/ext"
+require "rubygems/ext/cargo_builder/link_flag_converter"
+
+class TestGemExtCargoBuilderLinkFlagConverter < Gem::TestCase
+ CASES = {
+ test_search_path_basic: ["-L/usr/local/lib", ["-L", "native=/usr/local/lib"]],
+ test_search_path_space: ["-L /usr/local/lib", ["-L", "native=/usr/local/lib"]],
+ test_search_path_space_in_path: ["-L/usr/local/my\ lib", ["-L", "native=/usr/local/my\ lib"]],
+ test_simple_lib: ["-lfoo", ["-l", "foo"]],
+ test_lib_with_nonascii: ["-lws2_32", ["-l", "ws2_32"]],
+ test_simple_lib_space: ["-l foo", ["-l", "foo"]],
+ test_verbose_lib_space: ["--library=foo", ["-l", "foo"]],
+ test_libstatic_with_colon: ["-l:libssp.a", ["-C", "link-args=-l:libssp.a"]],
+ test_libstatic_with_colon_space: ["-l :libssp.a", ["-C", "link-args=-l :libssp.a"]],
+ test_unconventional_lib_with_colon: ["-l:ssp.a", ["-C", "link-args=-l:ssp.a"]],
+ test_dylib_with_colon_space: ["-l :libssp.dylib", ["-C", "link-args=-l :libssp.dylib"]],
+ test_so_with_colon_space: ["-l :libssp.so", ["-C", "link-args=-l :libssp.so"]],
+ test_dll_with_colon_space: ["-l :libssp.dll", ["-C", "link-args=-l :libssp.dll"]],
+ test_framework: ["-F/some/path", ["-l", "framework=/some/path"]],
+ test_framework_space: ["-F /some/path", ["-l", "framework=/some/path"]],
+ test_non_lib_dash_l: ["test_rubygems_20220413-976-lemgf9/prefix", ["-C", "link-args=test_rubygems_20220413-976-lemgf9/prefix"]],
+ }.freeze
+
+ CASES.each do |test_name, (arg, expected)|
+ raise "duplicate test name" if instance_methods.include?(test_name)
+
+ define_method(test_name) do
+ assert_equal(expected, Gem::Ext::CargoBuilder::LinkFlagConverter.convert(arg))
+ end
+ end
+end
diff --git a/test/rubygems/test_gem_ext_cargo_builder_unit.rb b/test/rubygems/test_gem_ext_cargo_builder_unit.rb
new file mode 100644
index 0000000000..89495b84ff
--- /dev/null
+++ b/test/rubygems/test_gem_ext_cargo_builder_unit.rb
@@ -0,0 +1,60 @@
+# frozen_string_literal: true
+
+require_relative "helper"
+require "rubygems/ext"
+
+class TestGemExtCargoBuilderUnit < Gem::TestCase
+ def test_cargo_command_passes_args
+ skip_unsupported_platforms!
+ builder = Gem::Ext::CargoBuilder.new
+ command = builder.cargo_command(Dir.pwd, @tempdir, ["--all-features"])
+
+ assert_includes command, "--all-features"
+ end
+
+ def test_cargo_command_locks_in_release_profile
+ skip_unsupported_platforms!
+ builder = Gem::Ext::CargoBuilder.new
+ builder.profile = :release
+ command = builder.cargo_command(Dir.pwd, @tempdir)
+
+ assert_includes command, "--locked"
+ end
+
+ def test_cargo_command_passes_respects_cargo_env_var
+ skip_unsupported_platforms!
+ old_cargo = ENV["CARGO"]
+ ENV["CARGO"] = "mycargo"
+ builder = Gem::Ext::CargoBuilder.new
+ command = builder.cargo_command(Dir.pwd, @tempdir)
+
+ assert_includes command, "mycargo"
+ ensure
+ ENV["CARGO"] = old_cargo
+ end
+
+ def test_build_env_includes_rbconfig
+ skip_unsupported_platforms!
+ builder = Gem::Ext::CargoBuilder.new
+ env = builder.build_env
+
+ assert_equal env.fetch("RBCONFIG_RUBY_SO_NAME"), RbConfig::CONFIG["RUBY_SO_NAME"]
+ end
+
+ def test_cargo_command_passes_respects_cargo_build_target
+ skip_unsupported_platforms!
+ old_cargo = ENV["CARGO_BUILD_TARGET"]
+ ENV["CARGO_BUILD_TARGET"] = "x86_64-unknown-linux-gnu"
+ builder = Gem::Ext::CargoBuilder.new
+ command = builder.cargo_command(Dir.pwd, @tempdir, ["--locked"])
+
+ assert_includes command, "--target"
+ assert_includes command, "x86_64-unknown-linux-gnu"
+ ensure
+ ENV["CARGO_BUILD_TARGET"] = old_cargo
+ end
+
+ def skip_unsupported_platforms!
+ pend "jruby not supported" if Gem.java_platform?
+ end
+end
diff --git a/test/rubygems/test_gem_ext_cmake_builder.rb b/test/rubygems/test_gem_ext_cmake_builder.rb
index 5ab82c545f..5f886af05f 100644
--- a/test/rubygems/test_gem_ext_cmake_builder.rb
+++ b/test/rubygems/test_gem_ext_cmake_builder.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/ext'
+
+require_relative "helper"
+require "rubygems/ext"
class TestGemExtCmakeBuilder < Gem::TestCase
def setup
@@ -9,22 +10,24 @@ class TestGemExtCmakeBuilder < Gem::TestCase
# Details: https://github.com/rubygems/rubygems/issues/1270#issuecomment-177368340
pend "CmakeBuilder doesn't work on Windows." if Gem.win_platform?
+ require "open3"
+
begin
- _, status = Open3.capture2e('cmake')
- pend 'cmake not present' unless status.success?
+ _, status = Open3.capture2e("cmake")
+ pend "cmake not present" unless status.success?
rescue Errno::ENOENT
- pend 'cmake not present'
+ pend "cmake not present"
end
- @ext = File.join @tempdir, 'ext'
- @dest_path = File.join @tempdir, 'prefix'
+ @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
- File.open File.join(@ext, 'CMakeLists.txt'), 'w' do |cmakelists|
+ File.open File.join(@ext, "CMakeLists.txt"), "w" do |cmakelists|
cmakelists.write <<-EO_CMAKE
cmake_minimum_required(VERSION 2.6)
project(self_build NONE)
@@ -32,7 +35,7 @@ install (FILES test.txt DESTINATION bin)
EO_CMAKE
end
- FileUtils.touch File.join(@ext, 'test.txt')
+ FileUtils.touch File.join(@ext, "test.txt")
output = []
@@ -40,11 +43,11 @@ install (FILES test.txt DESTINATION bin)
output = output.join "\n"
- assert_match %r{^cmake \. -DCMAKE_INSTALL_PREFIX\\=#{Regexp.escape @dest_path}}, output
- assert_match %r{#{Regexp.escape @ext}}, output
- assert_contains_make_command '', output
- assert_contains_make_command 'install', output
- assert_match %r{test\.txt}, output
+ assert_match(/^cmake \. -DCMAKE_INSTALL_PREFIX\\=#{Regexp.escape @dest_path}/, output)
+ assert_match(/#{Regexp.escape @ext}/, output)
+ assert_contains_make_command "", output
+ assert_contains_make_command "install", output
+ assert_match(/test\.txt/, output)
end
def test_self_build_fail
@@ -56,16 +59,16 @@ install (FILES test.txt DESTINATION bin)
output = output.join "\n"
- shell_error_msg = %r{(CMake Error: .*)}
+ shell_error_msg = /(CMake Error: .*)/
- assert_match 'cmake failed', error.message
+ assert_match "cmake failed", error.message
- assert_match %r{^cmake . -DCMAKE_INSTALL_PREFIX\\=#{Regexp.escape @dest_path}}, output
- assert_match %r{#{shell_error_msg}}, output
+ assert_match(/^cmake . -DCMAKE_INSTALL_PREFIX\\=#{Regexp.escape @dest_path}/, output)
+ assert_match(/#{shell_error_msg}/, output)
end
def test_self_build_has_makefile
- File.open File.join(@ext, 'Makefile'), 'w' do |makefile|
+ File.open File.join(@ext, "Makefile"), "w" do |makefile|
makefile.puts "all:\n\t@echo ok\ninstall:\n\t@echo ok"
end
@@ -75,7 +78,7 @@ install (FILES test.txt DESTINATION bin)
output = output.join "\n"
- assert_contains_make_command '', output
- assert_contains_make_command 'install', output
+ assert_contains_make_command "", output
+ assert_contains_make_command "install", output
end
end
diff --git a/test/rubygems/test_gem_ext_configure_builder.rb b/test/rubygems/test_gem_ext_configure_builder.rb
index 76ccfe2dc4..6a2f9883f0 100644
--- a/test/rubygems/test_gem_ext_configure_builder.rb
+++ b/test/rubygems/test_gem_ext_configure_builder.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/ext'
+
+require_relative "helper"
+require "rubygems/ext"
class TestGemExtConfigureBuilder < Gem::TestCase
def setup
@@ -9,8 +10,8 @@ class TestGemExtConfigureBuilder < Gem::TestCase
@makefile_body =
"clean:\n\t@echo ok\nall:\n\t@echo ok\ninstall:\n\t@echo ok"
- @ext = File.join @tempdir, 'ext'
- @dest_path = File.join @tempdir, 'prefix'
+ @ext = File.join @tempdir, "ext"
+ @dest_path = File.join @tempdir, "prefix"
FileUtils.mkdir_p @ext
FileUtils.mkdir_p @dest_path
@@ -19,7 +20,7 @@ class TestGemExtConfigureBuilder < Gem::TestCase
def test_self_build
pend("test_self_build skipped on MS Windows (VC++)") if vc_windows?
- File.open File.join(@ext, './configure'), 'w' do |configure|
+ File.open File.join(@ext, "./configure"), "w" do |configure|
configure.puts "#!/bin/sh\necho \"#{@makefile_body}\" > Makefile"
end
@@ -31,13 +32,13 @@ class TestGemExtConfigureBuilder < Gem::TestCase
assert_equal "sh ./configure --prefix\\=#{@dest_path}", output.shift
assert_equal "", output.shift
assert_match(/^current directory:/, output.shift)
- assert_contains_make_command 'clean', output.shift
+ assert_contains_make_command "clean", output.shift
assert_match(/^ok$/m, output.shift)
assert_match(/^current directory:/, output.shift)
- assert_contains_make_command '', output.shift
+ assert_contains_make_command "", output.shift
assert_match(/^ok$/m, output.shift)
assert_match(/^current directory:/, output.shift)
- assert_contains_make_command 'install', output.shift
+ assert_contains_make_command "install", output.shift
assert_match(/^ok$/m, output.shift)
end
@@ -52,11 +53,11 @@ class TestGemExtConfigureBuilder < Gem::TestCase
shell_error_msg = %r{(\./configure: .*)|((?:[Cc]an't|cannot) open '?\./configure'?(?:: No such file or directory)?)}
sh_prefix_configure = "sh ./configure --prefix\\="
- assert_match 'configure failed', error.message
+ assert_match "configure failed", error.message
assert_match(/^current directory:/, output.shift)
assert_equal "#{sh_prefix_configure}#{@dest_path}", output.shift
- assert_match %r{#{shell_error_msg}}, output.shift
+ assert_match(/#{shell_error_msg}/, output.shift)
assert_equal true, output.empty?
end
@@ -65,15 +66,15 @@ class TestGemExtConfigureBuilder < Gem::TestCase
pend("test_self_build_has_makefile skipped - nmake not found")
end
- File.open File.join(@ext, 'Makefile'), 'w' do |makefile|
+ File.open File.join(@ext, "Makefile"), "w" do |makefile|
makefile.puts @makefile_body
end
output = []
Gem::Ext::ConfigureBuilder.build nil, @dest_path, output, [], nil, @ext
- assert_contains_make_command 'clean', output[1]
- assert_contains_make_command '', output[4]
- assert_contains_make_command 'install', output[7]
+ assert_contains_make_command "clean", output[1]
+ assert_contains_make_command "", output[4]
+ assert_contains_make_command "install", output[7]
end
end
diff --git a/test/rubygems/test_gem_ext_ext_conf_builder.rb b/test/rubygems/test_gem_ext_ext_conf_builder.rb
index 70833f35cf..218c6f3d5e 100644
--- a/test/rubygems/test_gem_ext_ext_conf_builder.rb
+++ b/test/rubygems/test_gem_ext_ext_conf_builder.rb
@@ -1,21 +1,21 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/ext'
+require_relative "helper"
+require "rubygems/ext"
class TestGemExtExtConfBuilder < Gem::TestCase
def setup
super
- @ext = File.join @tempdir, 'ext'
- @dest_path = File.join @tempdir, 'prefix'
+ @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
- if java_platform?
+ if Gem.java_platform?
pend("failing on jruby")
end
@@ -23,73 +23,76 @@ class TestGemExtExtConfBuilder < Gem::TestCase
pend("test_class_build skipped - nmake not found")
end
- File.open File.join(@ext, 'extconf.rb'), 'w' do |extconf|
+ File.open File.join(@ext, "extconf.rb"), "w" do |extconf|
extconf.puts "require 'mkmf'\ncreate_makefile 'foo'"
end
output = []
- result = Gem::Ext::ExtConfBuilder.build 'extconf.rb', @dest_path, output, [], nil, @ext
+ result = Gem::Ext::ExtConfBuilder.build "extconf.rb", @dest_path, output, [], nil, @ext
assert_same result, output
assert_match(/^current directory:/, output[0])
- assert_match(/^#{Gem.ruby}.* extconf.rb/, output[1])
+ assert_match(/^#{Regexp.quote(Gem.ruby)}.* extconf.rb/, output[1])
assert_equal "creating Makefile\n", output[2]
assert_match(/^current directory:/, output[3])
- assert_contains_make_command 'clean', output[4]
- assert_contains_make_command '', output[7]
- assert_contains_make_command 'install', output[10]
- assert_empty Dir.glob(File.join(@ext, 'siteconf*.rb'))
- assert_empty Dir.glob(File.join(@ext, '.gem.*'))
+ assert_contains_make_command "clean", output[4]
+ assert_contains_make_command "", output[7]
+ assert_contains_make_command "install", output[10]
+ assert_empty Dir.glob(File.join(@ext, "siteconf*.rb"))
+ assert_empty Dir.glob(File.join(@ext, ".gem.*"))
end
def test_class_build_rbconfig_make_prog
- if java_platform?
+ if Gem.java_platform?
pend("failing on jruby")
end
configure_args do
-
- File.open File.join(@ext, 'extconf.rb'), 'w' do |extconf|
+ File.open File.join(@ext, "extconf.rb"), "w" do |extconf|
extconf.puts "require 'mkmf'\ncreate_makefile 'foo'"
end
output = []
- Gem::Ext::ExtConfBuilder.build 'extconf.rb', @dest_path, output, [], nil, @ext
+ Gem::Ext::ExtConfBuilder.build "extconf.rb", @dest_path, output, [], nil, @ext
assert_equal "creating Makefile\n", output[2]
- assert_contains_make_command 'clean', output[4]
- assert_contains_make_command '', output[7]
- assert_contains_make_command 'install', output[10]
+ assert_contains_make_command "clean", output[4]
+ assert_contains_make_command "", output[7]
+ assert_contains_make_command "install", output[10]
end
end
def test_class_build_env_make
- env_make = ENV.delete 'MAKE'
- ENV['MAKE'] = 'anothermake'
+ env_make = ENV.delete "make"
+ ENV["make"] = nil
+
+ env_large_make = ENV.delete "MAKE"
+ ENV["MAKE"] = "anothermake"
- if java_platform?
+ if Gem.java_platform?
pend("failing on jruby")
end
- configure_args '' do
- File.open File.join(@ext, 'extconf.rb'), 'w' do |extconf|
+ configure_args "" do
+ File.open File.join(@ext, "extconf.rb"), "w" do |extconf|
extconf.puts "require 'mkmf'\ncreate_makefile 'foo'"
end
output = []
assert_raise Gem::InstallError do
- Gem::Ext::ExtConfBuilder.build 'extconf.rb', @dest_path, output, [], nil, @ext
+ Gem::Ext::ExtConfBuilder.build "extconf.rb", @dest_path, output, [], nil, @ext
end
assert_equal "creating Makefile\n", output[2]
- assert_contains_make_command 'clean', output[4]
+ assert_contains_make_command "clean", output[4]
end
ensure
- ENV['MAKE'] = env_make
+ ENV["MAKE"] = env_large_make
+ ENV["make"] = env_make
end
def test_class_build_extconf_fail
@@ -97,7 +100,7 @@ class TestGemExtExtConfBuilder < Gem::TestCase
pend("test_class_build_extconf_fail skipped - nmake not found")
end
- File.open File.join(@ext, 'extconf.rb'), 'w' do |extconf|
+ 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'"
@@ -106,16 +109,16 @@ class TestGemExtExtConfBuilder < Gem::TestCase
output = []
error = assert_raise Gem::InstallError do
- Gem::Ext::ExtConfBuilder.build 'extconf.rb', @dest_path, output, [], nil, @ext
+ Gem::Ext::ExtConfBuilder.build "extconf.rb", @dest_path, output, [], nil, @ext
end
- assert_equal 'extconf failed, exit code 1', error.message
+ assert_equal "extconf failed, exit code 1", error.message
- assert_match(/^#{Gem.ruby}.* extconf.rb/, output[1])
- assert_match(File.join(@dest_path, 'mkmf.log'), output[4])
+ assert_match(/^#{Regexp.quote(Gem.ruby)}.* extconf.rb/, output[1])
+ assert_match(File.join(@dest_path, "mkmf.log"), output[4])
assert_includes(output, "To see why this extension failed to compile, please check the mkmf.log which can be found here:\n")
- assert_path_exist File.join @dest_path, 'mkmf.log'
+ assert_path_exist File.join @dest_path, "mkmf.log"
end
def test_class_build_extconf_success_without_warning
@@ -123,7 +126,7 @@ class TestGemExtExtConfBuilder < Gem::TestCase
pend("test_class_build_extconf_fail skipped - nmake not found")
end
- File.open File.join(@ext, 'extconf.rb'), 'w' do |extconf|
+ File.open File.join(@ext, "extconf.rb"), "w" do |extconf|
extconf.puts "require 'mkmf'"
extconf.puts "File.open('mkmf.log', 'w'){|f| f.write('a')}"
extconf.puts "create_makefile 'foo'"
@@ -131,11 +134,11 @@ class TestGemExtExtConfBuilder < Gem::TestCase
output = []
- Gem::Ext::ExtConfBuilder.build 'extconf.rb', @dest_path, output, [], nil, @ext
+ Gem::Ext::ExtConfBuilder.build "extconf.rb", @dest_path, output, [], nil, @ext
refute_includes(output, "To see why this extension failed to compile, please check the mkmf.log which can be found here:\n")
- assert_path_exist File.join @dest_path, 'mkmf.log'
+ assert_path_exist File.join @dest_path, "mkmf.log"
end
def test_class_build_unconventional
@@ -143,7 +146,7 @@ class TestGemExtExtConfBuilder < Gem::TestCase
pend("test_class_build skipped - nmake not found")
end
- File.open File.join(@ext, 'extconf.rb'), 'w' do |extconf|
+ File.open File.join(@ext, "extconf.rb"), "w" do |extconf|
extconf.puts <<-'EXTCONF'
include RbConfig
@@ -171,12 +174,12 @@ end
output = []
- Gem::Ext::ExtConfBuilder.build 'extconf.rb', @dest_path, output, [], nil, @ext
+ Gem::Ext::ExtConfBuilder.build "extconf.rb", @dest_path, output, [], nil, @ext
- assert_contains_make_command 'clean', output[4]
- assert_contains_make_command '', output[7]
- assert_contains_make_command 'install', output[10]
- assert_empty Dir.glob(File.join(@ext, 'siteconf*.rb'))
+ assert_contains_make_command "clean", output[4]
+ assert_contains_make_command "", output[7]
+ assert_contains_make_command "install", output[10]
+ assert_empty Dir.glob(File.join(@ext, "siteconf*.rb"))
end
def test_class_make
@@ -185,8 +188,8 @@ end
end
output = []
- makefile_path = File.join(@ext, 'Makefile')
- File.open makefile_path, 'w' do |makefile|
+ makefile_path = File.join(@ext, "Makefile")
+ File.open makefile_path, "w" do |makefile|
makefile.puts "# π"
makefile.puts "RUBYARCHDIR = $(foo)$(target_prefix)"
makefile.puts "RUBYLIBDIR = $(bar)$(target_prefix)"
@@ -197,30 +200,29 @@ end
Gem::Ext::ExtConfBuilder.make @ext, output, @ext
- assert_contains_make_command 'clean', output[1]
- assert_contains_make_command '', output[4]
- assert_contains_make_command 'install', output[7]
+ assert_contains_make_command "clean", output[1]
+ assert_contains_make_command "", output[4]
+ assert_contains_make_command "install", output[7]
end
def test_class_make_no_Makefile
error = assert_raise Gem::InstallError do
- Gem::Ext::ExtConfBuilder.make @ext, ['output'], @ext
+ Gem::Ext::ExtConfBuilder.make @ext, ["output"], @ext
end
- assert_equal 'Makefile not found', error.message
+ assert_equal "Makefile not found", error.message
end
def configure_args(args = nil)
- configure_args = RbConfig::CONFIG['configure_args']
- RbConfig::CONFIG['configure_args'] = args if args
+ configure_args = RbConfig::CONFIG["configure_args"]
+ RbConfig::CONFIG["configure_args"] = args if args
yield
-
ensure
if configure_args
- RbConfig::CONFIG['configure_args'] = configure_args
+ RbConfig::CONFIG["configure_args"] = configure_args
else
- RbConfig::CONFIG.delete 'configure_args'
+ RbConfig::CONFIG.delete "configure_args"
end
end
end
diff --git a/test/rubygems/test_gem_ext_rake_builder.rb b/test/rubygems/test_gem_ext_rake_builder.rb
index 3d8922eed5..bd72c1aa08 100644
--- a/test/rubygems/test_gem_ext_rake_builder.rb
+++ b/test/rubygems/test_gem_ext_rake_builder.rb
@@ -1,30 +1,31 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/ext'
+
+require_relative "helper"
+require "rubygems/ext"
class TestGemExtRakeBuilder < Gem::TestCase
def setup
super
- @ext = File.join @tempdir, 'ext'
- @dest_path = File.join @tempdir, 'prefix'
+ @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
- create_temp_mkrf_file('task :default')
+ create_temp_mkrf_file("task :default")
output = []
build_rake_in do |rake|
- Gem::Ext::RakeBuilder.build 'mkrf_conf.rb', @dest_path, output, [], nil, @ext
+ Gem::Ext::RakeBuilder.build "mkrf_conf.rb", @dest_path, output, [], nil, @ext
output = output.join "\n"
- refute_match %r{^rake failed:}, output
- assert_match %r{^#{Regexp.escape Gem.ruby} mkrf_conf\.rb}, output
- assert_match %r{^#{Regexp.escape rake} RUBYARCHDIR\\=#{Regexp.escape @dest_path} RUBYLIBDIR\\=#{Regexp.escape @dest_path}}, output
+ refute_match(/^rake failed:/, output)
+ assert_match(/^#{Regexp.escape Gem.ruby} mkrf_conf\.rb/, output)
+ assert_match(/^#{Regexp.escape rake} RUBYARCHDIR\\=#{Regexp.escape @dest_path} RUBYLIBDIR\\=#{Regexp.escape @dest_path}/, output)
end
end
@@ -32,46 +33,46 @@ class TestGemExtRakeBuilder < Gem::TestCase
#
# It should not fail with a non-empty args list either
def test_class_build_with_args
- create_temp_mkrf_file('task :default')
+ create_temp_mkrf_file("task :default")
output = []
build_rake_in do |rake|
- non_empty_args_list = ['']
- Gem::Ext::RakeBuilder.build 'mkrf_conf.rb', @dest_path, output, non_empty_args_list, nil, @ext
+ non_empty_args_list = [""]
+ Gem::Ext::RakeBuilder.build "mkrf_conf.rb", @dest_path, output, non_empty_args_list, nil, @ext
output = output.join "\n"
- refute_match %r{^rake failed:}, output
- assert_match %r{^#{Regexp.escape Gem.ruby} mkrf_conf\.rb}, output
- assert_match %r{^#{Regexp.escape rake} RUBYARCHDIR\\=#{Regexp.escape @dest_path} RUBYLIBDIR\\=#{Regexp.escape @dest_path}}, output
+ refute_match(/^rake failed:/, output)
+ assert_match(/^#{Regexp.escape Gem.ruby} mkrf_conf\.rb/, output)
+ assert_match(/^#{Regexp.escape rake} RUBYARCHDIR\\=#{Regexp.escape @dest_path} RUBYLIBDIR\\=#{Regexp.escape @dest_path}/, output)
end
end
def test_class_no_openssl_override
- pend 'openssl is missing' unless Gem::HAVE_OPENSSL
+ pend "openssl is missing" unless Gem::HAVE_OPENSSL
- create_temp_mkrf_file('task :default')
+ create_temp_mkrf_file("task :default")
- rake = util_spec 'rake' do |s|
+ rake = util_spec "rake" do |s|
s.executables = %w[rake]
s.files = %w[bin/rake]
end
output = []
- write_file File.join(@tempdir, 'bin', 'rake') do |fp|
+ write_file File.join(@tempdir, "bin", "rake") do |fp|
fp.puts "#!/usr/bin/ruby"
fp.puts "require 'openssl'; puts OpenSSL"
end
install_gem rake
- Gem::Ext::RakeBuilder.build 'mkrf_conf.rb', @dest_path, output, [''], nil, @ext
+ Gem::Ext::RakeBuilder.build "mkrf_conf.rb", @dest_path, output, [""], nil, @ext
output = output.join "\n"
assert_match "OpenSSL", output
- assert_match %r{^#{Regexp.escape Gem.ruby} mkrf_conf\.rb}, output
+ assert_match(/^#{Regexp.escape Gem.ruby} mkrf_conf\.rb/, output)
end
def test_class_build_no_mkrf_passes_args
@@ -82,8 +83,8 @@ class TestGemExtRakeBuilder < Gem::TestCase
output = output.join "\n"
- refute_match %r{^rake failed:}, output
- assert_match %r{^#{Regexp.escape rake} RUBYARCHDIR\\=#{Regexp.escape @dest_path} RUBYLIBDIR\\=#{Regexp.escape @dest_path} test1 test2}, output
+ refute_match(/^rake failed:/, output)
+ assert_match(/^#{Regexp.escape rake} RUBYARCHDIR\\=#{Regexp.escape @dest_path} RUBYLIBDIR\\=#{Regexp.escape @dest_path} test1 test2/, output)
end
end
@@ -91,17 +92,17 @@ class TestGemExtRakeBuilder < Gem::TestCase
create_temp_mkrf_file("task :default do abort 'fail' end")
output = []
- build_rake_in(false) do |rake|
+ build_rake_in(false) do |_rake|
error = assert_raise Gem::InstallError do
Gem::Ext::RakeBuilder.build "mkrf_conf.rb", @dest_path, output, [], nil, @ext
end
- assert_match %r{^rake failed}, error.message
+ assert_match(/^rake failed/, error.message)
end
end
def create_temp_mkrf_file(rakefile_content)
- File.open File.join(@ext, 'mkrf_conf.rb'), 'w' do |mkrf_conf|
+ 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 "#{rakefile_content}"
diff --git a/test/rubygems/test_gem_gem_runner.rb b/test/rubygems/test_gem_gem_runner.rb
index 6f5361cf2f..c05e74c991 100644
--- a/test/rubygems/test_gem_gem_runner.rb
+++ b/test/rubygems/test_gem_gem_runner.rb
@@ -1,20 +1,26 @@
# frozen_string_literal: true
-require_relative 'helper'
+
+require_relative "helper"
class TestGemGemRunner < Gem::TestCase
def setup
- super
-
- require 'rubygems/command'
+ require "rubygems/command"
@orig_args = Gem::Command.build_args
@orig_specific_extra_args = Gem::Command.specific_extra_args_hash.dup
@orig_extra_args = Gem::Command.extra_args.dup
- require 'rubygems/gem_runner'
+ super
+
+ @orig_gem_home = ENV["GEM_HOME"]
+ ENV["GEM_HOME"] = @gemhome
+
+ require "rubygems/gem_runner"
@runner = Gem::GemRunner.new
end
def teardown
+ ENV["GEM_HOME"] = @orig_gem_home
+
super
Gem::Command.build_args = @orig_args
@@ -25,15 +31,15 @@ class TestGemGemRunner < Gem::TestCase
def test_do_configuration
Gem.clear_paths
- temp_conf = File.join @tempdir, '.gemrc'
+ temp_conf = File.join @tempdir, ".gemrc"
- other_gem_path = File.join @tempdir, 'other_gem_path'
- other_gem_home = File.join @tempdir, 'other_gem_home'
+ 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|
+ File.open temp_conf, "w" do |fp|
fp.puts "gem: --commands"
fp.puts "gemhome: #{other_gem_home}"
fp.puts "gempath:"
diff --git a/test/rubygems/test_gem_gemcutter_utilities.rb b/test/rubygems/test_gem_gemcutter_utilities.rb
index 0bcd1504e9..a3236e6276 100644
--- a/test/rubygems/test_gem_gemcutter_utilities.rb
+++ b/test/rubygems/test_gem_gemcutter_utilities.rb
@@ -1,29 +1,33 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems'
-require 'rubygems/command'
-require 'rubygems/gemcutter_utilities'
+
+require_relative "helper"
+require_relative "multifactor_auth_utilities"
+require "rubygems"
+require "rubygems/command"
+require "rubygems/gemcutter_utilities"
+require "rubygems/config_file"
class TestGemGemcutterUtilities < Gem::TestCase
def setup
super
credential_setup
+ @fetcher = SignInFetcher.new
# below needed for random testing, class property
Gem.configuration.disable_default_gem_server = nil
- ENV['RUBYGEMS_HOST'] = nil
- ENV['GEM_HOST_OTP_CODE'] = nil
+ ENV["RUBYGEMS_HOST"] = nil
+ ENV["GEM_HOST_OTP_CODE"] = nil
Gem.configuration.rubygems_api_key = nil
- @cmd = Gem::Command.new '', 'summary'
+ @cmd = Gem::Command.new "", "summary"
@cmd.extend Gem::GemcutterUtilities
end
def teardown
- ENV['RUBYGEMS_HOST'] = nil
- ENV['GEM_HOST_OTP_CODE'] = nil
+ ENV["RUBYGEMS_HOST"] = nil
+ ENV["GEM_HOST_OTP_CODE"] = nil
Gem.configuration.rubygems_api_key = nil
credential_teardown
@@ -33,38 +37,38 @@ class TestGemGemcutterUtilities < Gem::TestCase
def test_alternate_key_alternate_host
keys = {
- :rubygems_api_key => 'KEY',
+ :rubygems_api_key => "KEY",
"http://rubygems.engineyard.com" => "EYKEY",
}
- File.open Gem.configuration.credentials_path, 'w' do |f|
- f.write keys.to_yaml
+ File.open Gem.configuration.credentials_path, "w" do |f|
+ f.write Gem::ConfigFile.dump_with_rubygems_yaml(keys)
end
ENV["RUBYGEMS_HOST"] = "http://rubygems.engineyard.com"
Gem.configuration.load_api_keys
- assert_equal 'EYKEY', @cmd.api_key
+ assert_equal "EYKEY", @cmd.api_key
end
def test_api_key
- keys = { :rubygems_api_key => 'KEY' }
+ keys = { rubygems_api_key: "KEY" }
- File.open Gem.configuration.credentials_path, 'w' do |f|
- f.write keys.to_yaml
+ File.open Gem.configuration.credentials_path, "w" do |f|
+ f.write Gem::ConfigFile.dump_with_rubygems_yaml(keys)
end
Gem.configuration.load_api_keys
- assert_equal 'KEY', @cmd.api_key
+ assert_equal "KEY", @cmd.api_key
end
def test_api_key_override
- keys = { :rubygems_api_key => 'KEY', :other => 'OTHER' }
+ keys = { rubygems_api_key: "KEY", other: "OTHER" }
- File.open Gem.configuration.credentials_path, 'w' do |f|
- f.write keys.to_yaml
+ File.open Gem.configuration.credentials_path, "w" do |f|
+ f.write Gem::ConfigFile.dump_with_rubygems_yaml(keys)
end
Gem.configuration.load_api_keys
@@ -72,175 +76,237 @@ class TestGemGemcutterUtilities < Gem::TestCase
@cmd.add_key_option
@cmd.handle_options %w[--key other]
- assert_equal 'OTHER', @cmd.api_key
+ assert_equal "OTHER", @cmd.api_key
end
def test_host
- assert_equal 'https://rubygems.org', @cmd.host
+ assert_equal "https://rubygems.org", @cmd.host
end
def test_host_RUBYGEMS_HOST
- ENV['RUBYGEMS_HOST'] = 'https://other.example'
+ ENV["RUBYGEMS_HOST"] = "https://other.example"
- assert_equal 'https://other.example', @cmd.host
+ assert_equal "https://other.example", @cmd.host
end
def test_host_RUBYGEMS_HOST_empty
- ENV['RUBYGEMS_HOST'] = ''
+ ENV["RUBYGEMS_HOST"] = ""
- assert_equal 'https://rubygems.org', @cmd.host
+ assert_equal "https://rubygems.org", @cmd.host
end
def test_sign_in
- api_key = 'a5fdbb6ba150cbb83aad2bb2fede64cf040453903'
- util_sign_in [api_key, 200, 'OK']
+ util_sign_in
- assert_match %r{Enter your RubyGems.org credentials.}, @sign_in_ui.output
+ assert_match(/Enter your RubyGems.org credentials./, @sign_in_ui.output)
assert @fetcher.last_request["authorization"]
- assert_match %r{Signed in.}, @sign_in_ui.output
+ assert_match(/Signed in./, @sign_in_ui.output)
credentials = load_yaml_file Gem.configuration.credentials_path
- assert_equal api_key, credentials[:rubygems_api_key]
+ assert_equal @fetcher.api_key, credentials[:rubygems_api_key]
end
def test_sign_in_with_host
- api_key = 'a5fdbb6ba150cbb83aad2bb2fede64cf040453903'
-
- util_sign_in [api_key, 200, 'OK'], 'http://example.com', ['http://example.com']
+ @fetcher = SignInFetcher.new(host: "http://example.com")
+ util_sign_in
assert_match "Enter your http://example.com credentials.",
@sign_in_ui.output
assert @fetcher.last_request["authorization"]
- assert_match %r{Signed in.}, @sign_in_ui.output
+ assert_match(/Signed in./, @sign_in_ui.output)
credentials = load_yaml_file Gem.configuration.credentials_path
- assert_equal api_key, credentials['http://example.com']
+ assert_equal @fetcher.api_key, credentials["http://example.com"]
end
def test_sign_in_with_host_nil
- api_key = 'a5fdbb6ba150cbb83aad2bb2fede64cf040453903'
-
- util_sign_in [api_key, 200, 'OK'], nil, [nil]
+ @fetcher = SignInFetcher.new(host: nil)
+ util_sign_in(args: [nil])
assert_match "Enter your RubyGems.org credentials.",
@sign_in_ui.output
assert @fetcher.last_request["authorization"]
- assert_match %r{Signed in.}, @sign_in_ui.output
+ assert_match(/Signed in./, @sign_in_ui.output)
credentials = load_yaml_file Gem.configuration.credentials_path
- assert_equal api_key, credentials[:rubygems_api_key]
+ assert_equal @fetcher.api_key, credentials[:rubygems_api_key]
end
def test_sign_in_with_host_ENV
- api_key = 'a5fdbb6ba150cbb83aad2bb2fede64cf040453903'
- util_sign_in [api_key, 200, 'OK'], 'http://example.com'
+ @fetcher = SignInFetcher.new(host: "http://example.com")
+ util_sign_in
assert_match "Enter your http://example.com credentials.",
@sign_in_ui.output
assert @fetcher.last_request["authorization"]
- assert_match %r{Signed in.}, @sign_in_ui.output
+ assert_match(/Signed in./, @sign_in_ui.output)
credentials = load_yaml_file Gem.configuration.credentials_path
- assert_equal api_key, credentials['http://example.com']
+ assert_equal @fetcher.api_key, credentials["http://example.com"]
end
def test_sign_in_skips_with_existing_credentials
- api_key = 'a5fdbb6ba150cbb83aad2bb2fede64cf040453903'
- Gem.configuration.rubygems_api_key = api_key
+ Gem.configuration.rubygems_api_key = @fetcher.api_key
- util_sign_in [api_key, 200, 'OK']
+ util_sign_in
assert_equal "", @sign_in_ui.output
end
def test_sign_in_skips_with_key_override
- api_key = 'a5fdbb6ba150cbb83aad2bb2fede64cf040453903'
- Gem.configuration.api_keys[:KEY] = 'other'
+ Gem.configuration.api_keys[:KEY] = "other"
@cmd.options[:key] = :KEY
- util_sign_in [api_key, 200, 'OK']
+ util_sign_in
assert_equal "", @sign_in_ui.output
end
def test_sign_in_with_other_credentials_doesnt_overwrite_other_keys
- api_key = 'a5fdbb6ba150cbb83aad2bb2fede64cf040453903'
- other_api_key = 'f46dbb18bb6a9c97cdc61b5b85c186a17403cdcbf'
+ other_api_key = "f46dbb18bb6a9c97cdc61b5b85c186a17403cdcbf"
- File.open Gem.configuration.credentials_path, 'w' do |f|
- f.write Hash[:other_api_key, other_api_key].to_yaml
+ config = Hash[:other_api_key, other_api_key]
+
+ File.open Gem.configuration.credentials_path, "w" do |f|
+ f.write Gem::ConfigFile.dump_with_rubygems_yaml(config)
end
- util_sign_in [api_key, 200, 'OK']
+ util_sign_in
- assert_match %r{Enter your RubyGems.org credentials.}, @sign_in_ui.output
- assert_match %r{Signed in.}, @sign_in_ui.output
+ assert_match(/Enter your RubyGems.org credentials./, @sign_in_ui.output)
+ assert_match(/Signed in./, @sign_in_ui.output)
credentials = load_yaml_file Gem.configuration.credentials_path
- assert_equal api_key, credentials[:rubygems_api_key]
+ assert_equal @fetcher.api_key, credentials[:rubygems_api_key]
assert_equal other_api_key, credentials[:other_api_key]
end
def test_sign_in_with_bad_credentials
+ @fetcher.respond_with_forbidden_api_key_response
assert_raise Gem::MockGemUi::TermError do
- util_sign_in ['Access Denied.', 403, 'Forbidden']
+ util_sign_in
end
- assert_match %r{Enter your RubyGems.org credentials.}, @sign_in_ui.output
- assert_match %r{Access Denied.}, @sign_in_ui.output
+ assert_match(/Enter your RubyGems.org credentials./, @sign_in_ui.output)
+ assert_match(/Access Denied./, @sign_in_ui.output)
end
def test_signin_with_env_otp_code
- ENV['GEM_HOST_OTP_CODE'] = '111111'
- api_key = 'a5fdbb6ba150cbb83aad2bb2fede64cf040453903'
+ ENV["GEM_HOST_OTP_CODE"] = "111111"
- util_sign_in [api_key, 200, 'OK']
+ util_sign_in
- assert_match 'Signed in with API key:', @sign_in_ui.output
- assert_equal '111111', @fetcher.last_request['OTP']
+ assert_match "Signed in with API key:", @sign_in_ui.output
+ assert_equal "111111", @fetcher.last_request["OTP"]
end
def test_sign_in_with_correct_otp_code
- api_key = 'a5fdbb6ba150cbb83aad2bb2fede64cf040453903'
- response_fail = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry."
-
- util_sign_in(proc do
- @call_count ||= 0
- (@call_count += 1).odd? ? [response_fail, 401, 'Unauthorized'] : [api_key, 200, 'OK']
- end, nil, [], "111111\n")
-
- assert_match 'You have enabled multi-factor authentication. Please enter OTP code.', @sign_in_ui.output
- assert_match 'Code: ', @sign_in_ui.output
- assert_match 'Signed in with API key:', @sign_in_ui.output
- assert_equal '111111', @fetcher.last_request['OTP']
+ @fetcher.respond_with_require_otp
+ util_sign_in(extra_input: "111111\n")
+
+ assert_match "You have enabled multi-factor authentication. Please enter OTP code.", @sign_in_ui.output
+ assert_match "Code: ", @sign_in_ui.output
+ assert_match "Signed in with API key:", @sign_in_ui.output
+ assert_equal "111111", @fetcher.last_request["OTP"]
end
def test_sign_in_with_incorrect_otp_code
response = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry."
+ @fetcher.respond_with_unauthorized_api_key_response
assert_raise Gem::MockGemUi::TermError do
- util_sign_in [response, 401, 'Unauthorized'], nil, [], "111111\n"
+ util_sign_in(extra_input: "111111\n")
end
- assert_match 'You have enabled multi-factor authentication. Please enter OTP code.', @sign_in_ui.output
- assert_match 'Code: ', @sign_in_ui.output
+ assert_match "You have enabled multi-factor authentication. Please enter OTP code.", @sign_in_ui.output
+ assert_match "Code: ", @sign_in_ui.output
assert_match response, @sign_in_ui.output
- assert_equal '111111', @fetcher.last_request['OTP']
+ assert_equal "111111", @fetcher.last_request["OTP"]
+ end
+
+ def test_sign_in_with_webauthn_enabled
+ server = Gem::MockTCPServer.new
+
+ @fetcher.respond_with_require_otp
+ @fetcher.respond_with_webauthn_url
+ TCPServer.stub(:new, server) do
+ Gem::GemcutterUtilities::WebauthnListener.stub(:listener_thread, Thread.new { Thread.current[:otp] = "Uvh6T57tkWuUnWYo" }) do
+ util_sign_in
+ end
+ end
+
+ assert_match "You have enabled multi-factor authentication. Please visit #{@fetcher.webauthn_url_with_port(server.port)} " \
+ "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, " \
+ "you can re-run the gem signin command with the `--otp [your_code]` option.", @sign_in_ui.output
+ assert_match "You are verified with a security device. You may close the browser window.", @sign_in_ui.output
+ assert_equal "Uvh6T57tkWuUnWYo", @fetcher.last_request["OTP"]
+ end
+
+ def test_sign_in_with_webauthn_enabled_with_error
+ server = Gem::MockTCPServer.new
+ error = Gem::WebauthnVerificationError.new("Something went wrong")
+
+ @fetcher.respond_with_require_otp
+ @fetcher.respond_with_webauthn_url
+ error = assert_raise Gem::MockGemUi::TermError do
+ TCPServer.stub(:new, server) do
+ Gem::GemcutterUtilities::WebauthnListener.stub(:listener_thread, Thread.new { Thread.current[:error] = error }) do
+ util_sign_in
+ end
+ end
+ end
+ assert_equal 1, error.exit_code
+
+ assert_match "You have enabled multi-factor authentication. Please visit #{@fetcher.webauthn_url_with_port(server.port)} " \
+ "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, " \
+ "you can re-run the gem signin command with the `--otp [your_code]` option.", @sign_in_ui.output
+ assert_match "ERROR: Security device verification failed: Something went wrong", @sign_in_ui.error
+ refute_match "You are verified with a security device. You may close the browser window.", @sign_in_ui.output
+ refute_match "Signed in with API key:", @sign_in_ui.output
+ end
+
+ def test_sign_in_with_webauthn_enabled_with_polling
+ server = Gem::MockTCPServer.new
+ @fetcher.respond_with_require_otp
+ @fetcher.respond_with_webauthn_url
+ @fetcher.respond_with_webauthn_polling("Uvh6T57tkWuUnWYo")
+
+ TCPServer.stub(:new, server) do
+ util_sign_in
+ end
+
+ assert_match "You have enabled multi-factor authentication. Please visit #{@fetcher.webauthn_url_with_port(server.port)} " \
+ "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, " \
+ "you can re-run the gem signin command with the `--otp [your_code]` option.", @sign_in_ui.output
+ assert_match "You are verified with a security device. You may close the browser window.", @sign_in_ui.output
+ assert_equal "Uvh6T57tkWuUnWYo", @fetcher.last_request["OTP"]
end
- def util_sign_in(response, host = nil, args = [], extra_input = '')
- email = 'you@example.com'
- password = 'secret'
+ def test_sign_in_with_webauthn_enabled_with_polling_failure
+ server = Gem::MockTCPServer.new
+ @fetcher.respond_with_require_otp
+ @fetcher.respond_with_webauthn_url
+ @fetcher.respond_with_webauthn_polling_failure
- if host
- ENV['RUBYGEMS_HOST'] = host
- else
- host = Gem.host
+ assert_raise Gem::MockGemUi::TermError do
+ TCPServer.stub(:new, server) do
+ util_sign_in
+ end
end
- @fetcher = Gem::FakeFetcher.new
- @fetcher.data["#{host}/api/v1/api_key"] = response
+ assert_match "You have enabled multi-factor authentication. Please visit #{@fetcher.webauthn_url_with_port(server.port)} " \
+ "to authenticate via security device. If you can't verify using WebAuthn but have OTP enabled, " \
+ "you can re-run the gem signin command with the `--otp [your_code]` option.", @sign_in_ui.output
+ assert_match "ERROR: Security device verification failed: " \
+ "The token in the link you used has either expired or been used already.", @sign_in_ui.error
+ end
+
+ def util_sign_in(args: [], extra_input: "")
+ email = "you@example.com"
+ password = "secret"
+
+ ENV["RUBYGEMS_HOST"] = @fetcher.host
Gem::RemoteFetcher.fetcher = @fetcher
- @sign_in_ui = Gem::MockGemUi.new("#{email}\n#{password}\n\n\n\n\n\n\n\n\n" + extra_input)
+ @sign_in_ui = Gem::MockGemUi.new("#{email}\n#{password}\n\n\n" + extra_input)
use_ui @sign_in_ui do
if args.length > 0
@@ -252,13 +318,13 @@ class TestGemGemcutterUtilities < Gem::TestCase
end
def test_verify_api_key
- keys = {:other => 'a5fdbb6ba150cbb83aad2bb2fede64cf040453903'}
- File.open Gem.configuration.credentials_path, 'w' do |f|
- f.write keys.to_yaml
+ keys = { other: "a5fdbb6ba150cbb83aad2bb2fede64cf040453903" }
+ File.open Gem.configuration.credentials_path, "w" do |f|
+ f.write Gem::ConfigFile.dump_with_rubygems_yaml(keys)
end
Gem.configuration.load_api_keys
- assert_equal 'a5fdbb6ba150cbb83aad2bb2fede64cf040453903',
+ assert_equal "a5fdbb6ba150cbb83aad2bb2fede64cf040453903",
@cmd.verify_api_key(:other)
end
@@ -267,4 +333,29 @@ class TestGemGemcutterUtilities < Gem::TestCase
@cmd.verify_api_key :missing
end
end
+
+ class SignInFetcher < Gem::MultifactorAuthFetcher
+ attr_reader :api_key
+
+ def initialize(host: nil)
+ super(host: host)
+ @api_key = "a5fdbb6ba150cbb83aad2bb2fede64cf040453903"
+ @data["#{@host}/api/v1/api_key"] = Gem::HTTPResponseFactory.create(body: @api_key, code: 200, msg: "OK")
+ @data["#{@host}/api/v1/profile/me.yaml"] = Gem::HTTPResponseFactory.create(body: "mfa: disabled\n", code: 200, msg: "OK")
+ end
+
+ def respond_with_require_otp
+ super("#{host}/api/v1/api_key", @api_key)
+ end
+
+ def respond_with_forbidden_api_key_response
+ @data["#{host}/api/v1/api_key"] = Gem::HTTPResponseFactory.create(body: "Access Denied.", code: 403, msg: "Forbidden")
+ end
+
+ def respond_with_unauthorized_api_key_response
+ response = "You have enabled multifactor authentication but your request doesn't have the correct OTP code. Please check it and retry."
+
+ @data["#{host}/api/v1/api_key"] = Gem::HTTPResponseFactory.create(body: response, code: 401, msg: "Unauthorized")
+ end
+ end
end
diff --git a/test/rubygems/test_gem_impossible_dependencies_error.rb b/test/rubygems/test_gem_impossible_dependencies_error.rb
index 971be151df..94c0290ea1 100644
--- a/test/rubygems/test_gem_impossible_dependencies_error.rb
+++ b/test/rubygems/test_gem_impossible_dependencies_error.rb
@@ -1,9 +1,10 @@
# frozen_string_literal: true
-require_relative 'helper'
+
+require_relative "helper"
class TestGemImpossibleDependenciesError < Gem::TestCase
def test_message_conflict
- request = dependency_request dep('net-ssh', '>= 2.0.13'), 'rye', '0.9.8'
+ request = dependency_request dep("net-ssh", ">= 2.0.13"), "rye", "0.9.8"
conflicts = []
@@ -11,9 +12,9 @@ class TestGemImpossibleDependenciesError < Gem::TestCase
# requested-by entries, but they are suitable for testing the message.
# See #485 to construct a correct conflict.
net_ssh_2_2_2 =
- dependency_request dep('net-ssh', '>= 2.6.5'), 'net-ssh', '2.2.2', request
+ dependency_request dep("net-ssh", ">= 2.6.5"), "net-ssh", "2.2.2", request
net_ssh_2_6_5 =
- dependency_request dep('net-ssh', '~> 2.2.2'), 'net-ssh', '2.6.5', request
+ dependency_request dep("net-ssh", "~> 2.2.2"), "net-ssh", "2.6.5", request
conflict1 = Gem::Resolver::Conflict.new \
net_ssh_2_6_5, net_ssh_2_6_5.requester
diff --git a/test/rubygems/test_gem_indexer.rb b/test/rubygems/test_gem_indexer.rb
deleted file mode 100644
index 6653f29adf..0000000000
--- a/test/rubygems/test_gem_indexer.rb
+++ /dev/null
@@ -1,357 +0,0 @@
-# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/indexer'
-
-class TestGemIndexer < Gem::TestCase
- def setup
- super
-
- util_make_gems
-
- @d2_0 = util_spec 'd', '2.0' do |s|
- s.date = Gem::Specification::TODAY - 86400 * 3
- end
- util_build_gem @d2_0
-
- @d2_0_a = util_spec 'd', '2.0.a'
- util_build_gem @d2_0_a
-
- @d2_0_b = util_spec 'd', '2.0.b'
- util_build_gem @d2_0_b
-
- @default = new_default_spec 'default', 2
- install_default_gems @default
-
- @indexerdir = File.join(@tempdir, 'indexer')
-
- gems = File.join(@indexerdir, 'gems')
- FileUtils.mkdir_p gems
- FileUtils.mv Dir[File.join(@gemhome, "cache", '*.gem')], gems
-
- @indexer = Gem::Indexer.new(@indexerdir)
- end
-
- def test_initialize
- assert_equal @indexerdir, @indexer.dest_directory
- assert_match %r{#{Dir.mktmpdir('gem_generate_index').match(/.*-/)}}, @indexer.directory
-
- indexer = Gem::Indexer.new @indexerdir
- assert indexer.build_modern
-
- indexer = Gem::Indexer.new @indexerdir, :build_modern => true
- assert indexer.build_modern
- end
-
- def test_build_indices
- @indexer.make_temp_directories
-
- use_ui @ui do
- @indexer.build_indices
- end
-
- specs_path = File.join @indexer.directory, "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"],
- ["dep_x", Gem::Version.new("1"), "ruby"],
- ["pl", Gem::Version.new("1"), "i386-linux"],
- ["x", Gem::Version.new("1"), "ruby"]]
-
- assert_equal expected, 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 = [["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"],
- ["dep_x", Gem::Version.new("1"), "ruby"],
- ["pl", Gem::Version.new("1"), "i386-linux"],
- ["x", Gem::Version.new("1"), "ruby"]]
-
- assert_equal expected, latest_specs, 'latest_specs'
- end
-
- def test_generate_index
- use_ui @ui do
- @indexer.generate_index
- end
-
- quickdir = File.join @indexerdir, 'quick'
- marshal_quickdir = File.join quickdir, "Marshal.#{@marshal_version}"
-
- assert_directory_exists quickdir
- assert_directory_exists marshal_quickdir
-
- assert_indexed marshal_quickdir, "#{File.basename(@a1.spec_file)}.rz"
- assert_indexed marshal_quickdir, "#{File.basename(@a2.spec_file)}.rz"
-
- refute_indexed marshal_quickdir, File.basename(@c1_2.spec_file)
-
- assert_indexed @indexerdir, "specs.#{@marshal_version}"
- assert_indexed @indexerdir, "specs.#{@marshal_version}.gz"
-
- assert_indexed @indexerdir, "latest_specs.#{@marshal_version}"
- assert_indexed @indexerdir, "latest_specs.#{@marshal_version}.gz"
- end
-
- def test_generate_index_modern
- @indexer.build_modern = true
-
- use_ui @ui do
- @indexer.generate_index
- end
-
- refute_indexed @indexerdir, 'yaml'
- refute_indexed @indexerdir, 'yaml.Z'
- refute_indexed @indexerdir, "Marshal.#{@marshal_version}"
- refute_indexed @indexerdir, "Marshal.#{@marshal_version}.Z"
-
- quickdir = File.join @indexerdir, 'quick'
- marshal_quickdir = File.join quickdir, "Marshal.#{@marshal_version}"
-
- assert_directory_exists quickdir, 'quickdir should be directory'
- assert_directory_exists marshal_quickdir
-
- refute_indexed quickdir, "index"
- refute_indexed quickdir, "index.rz"
-
- refute_indexed quickdir, "latest_index"
- refute_indexed quickdir, "latest_index.rz"
-
- refute_indexed quickdir, "#{File.basename(@a1.spec_file)}.rz"
- refute_indexed quickdir, "#{File.basename(@a2.spec_file)}.rz"
- refute_indexed quickdir, "#{File.basename(@b2.spec_file)}.rz"
- refute_indexed quickdir, "#{File.basename(@c1_2.spec_file)}.rz"
-
- refute_indexed quickdir, "#{@pl1.original_name}.gemspec.rz"
- refute_indexed quickdir, "#{File.basename(@pl1.spec_file)}.rz"
-
- assert_indexed marshal_quickdir, "#{File.basename(@a1.spec_file)}.rz"
- assert_indexed marshal_quickdir, "#{File.basename(@a2.spec_file)}.rz"
-
- refute_indexed quickdir, "#{File.basename(@c1_2.spec_file)}"
- refute_indexed marshal_quickdir, "#{File.basename(@c1_2.spec_file)}"
-
- assert_indexed @indexerdir, "specs.#{@marshal_version}"
- assert_indexed @indexerdir, "specs.#{@marshal_version}.gz"
-
- assert_indexed @indexerdir, "latest_specs.#{@marshal_version}"
- assert_indexed @indexerdir, "latest_specs.#{@marshal_version}.gz"
- end
-
- def test_generate_index_modern_back_to_back
- @indexer.build_modern = true
-
- use_ui @ui do
- @indexer.generate_index
- end
-
- @indexer = Gem::Indexer.new @indexerdir
- @indexer.build_modern = true
-
- use_ui @ui do
- @indexer.generate_index
- end
- quickdir = File.join @indexerdir, 'quick'
- marshal_quickdir = File.join quickdir, "Marshal.#{@marshal_version}"
-
- assert_directory_exists quickdir
- assert_directory_exists marshal_quickdir
-
- assert_indexed marshal_quickdir, "#{File.basename(@a1.spec_file)}.rz"
- assert_indexed marshal_quickdir, "#{File.basename(@a2.spec_file)}.rz"
-
- assert_indexed @indexerdir, "specs.#{@marshal_version}"
- assert_indexed @indexerdir, "specs.#{@marshal_version}.gz"
-
- assert_indexed @indexerdir, "latest_specs.#{@marshal_version}"
- assert_indexed @indexerdir, "latest_specs.#{@marshal_version}.gz"
- end
-
- def test_generate_index_ui
- use_ui @ui do
- @indexer.generate_index
- end
-
- assert_match %r{^\.\.\.\.\.\.\.\.\.\.\.\.$}, @ui.output
- assert_match %r{^Generating Marshal quick index gemspecs for 12 gems$},
- @ui.output
- assert_match %r{^Complete$}, @ui.output
- assert_match %r{^Generating specs index$}, @ui.output
- assert_match %r{^Generating latest specs index$}, @ui.output
- assert_match %r{^Generating prerelease specs index$}, @ui.output
- assert_match %r{^Complete$}, @ui.output
- assert_match %r{^Compressing indices$}, @ui.output
-
- assert_equal '', @ui.error
- end
-
- def test_generate_index_specs
- use_ui @ui do
- @indexer.generate_index
- end
-
- specs_path = File.join @indexerdir, "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'],
- ['dep_x', Gem::Version.new(1), 'ruby'],
- ['pl', Gem::Version.new(1), 'i386-linux'],
- ['x', Gem::Version.new(1), 'ruby'],
- ]
-
- 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'
-
- refute_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 @indexerdir, "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'],
- ['dep_x', Gem::Version.new(1), 'ruby'],
- ['pl', Gem::Version.new(1), 'i386-linux'],
- ['x', Gem::Version.new(1), 'ruby'],
- ]
-
- 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 test_generate_index_prerelease_specs
- use_ui @ui do
- @indexer.generate_index
- end
-
- prerelease_specs_path = File.join @indexerdir, "prerelease_specs.#{@marshal_version}"
-
- prerelease_specs_dump = Gem.read_binary prerelease_specs_path
- prerelease_specs = Marshal.load prerelease_specs_dump
-
- assert_equal [['a', Gem::Version.new('3.a'), 'ruby'],
- ['d', Gem::Version.new('2.0.a'), 'ruby'],
- ['d', Gem::Version.new('2.0.b'), 'ruby']],
- prerelease_specs
- end
-
- ##
- # Emulate the starting state of Gem::Specification in a live environment,
- # where it will carry the list of system gems
- def with_system_gems
- Gem::Specification.reset
-
- sys_gem = util_spec 'systemgem', '1.0'
- util_build_gem sys_gem
- install_default_gems sys_gem
- yield
- util_remove_gem sys_gem
- end
-
- def test_update_index
- use_ui @ui do
- @indexer.generate_index
- end
-
- quickdir = File.join @indexerdir, 'quick'
- marshal_quickdir = File.join quickdir, "Marshal.#{@marshal_version}"
-
- assert_directory_exists quickdir
- assert_directory_exists marshal_quickdir
-
- @d2_1 = util_spec 'd', '2.1'
- util_build_gem @d2_1
- @d2_1_tuple = [@d2_1.name, @d2_1.version, @d2_1.original_platform]
-
- @d2_1_a = util_spec 'd', '2.2.a'
- util_build_gem @d2_1_a
- @d2_1_a_tuple = [@d2_1_a.name, @d2_1_a.version, @d2_1_a.original_platform]
-
- gems = File.join @indexerdir, 'gems'
-
- FileUtils.mv @d2_1.cache_file, gems
- FileUtils.mv @d2_1_a.cache_file, gems
-
- with_system_gems do
- use_ui @ui do
- @indexer.update_index
- end
-
- assert_indexed marshal_quickdir, "#{File.basename(@d2_1.spec_file)}.rz"
-
- specs_index = Marshal.load Gem.read_binary(@indexer.dest_specs_index)
-
- assert_includes specs_index, @d2_1_tuple
- refute_includes specs_index, @d2_1_a_tuple
-
- latest_specs_index = Marshal.load \
- Gem.read_binary(@indexer.dest_latest_specs_index)
-
- assert_includes latest_specs_index, @d2_1_tuple
- assert_includes latest_specs_index,
- [@d2_0.name, @d2_0.version, @d2_0.original_platform]
- refute_includes latest_specs_index, @d2_1_a_tuple
-
- pre_specs_index = Marshal.load \
- Gem.read_binary(@indexer.dest_prerelease_specs_index)
-
- assert_includes pre_specs_index, @d2_1_a_tuple
- refute_includes pre_specs_index, @d2_1_tuple
- end
- 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
- refute File.exist?(file), "#{file} exists"
- end
-end
diff --git a/test/rubygems/test_gem_install_update_options.rb b/test/rubygems/test_gem_install_update_options.rb
index 33cb5c08bf..8fd5d9c543 100644
--- a/test/rubygems/test_gem_install_update_options.rb
+++ b/test/rubygems/test_gem_install_update_options.rb
@@ -1,14 +1,15 @@
# frozen_string_literal: true
-require_relative 'installer_test_case'
-require 'rubygems/install_update_options'
-require 'rubygems/command'
-require 'rubygems/dependency_installer'
+
+require_relative "installer_test_case"
+require "rubygems/install_update_options"
+require "rubygems/command"
+require "rubygems/dependency_installer"
class TestGemInstallUpdateOptions < Gem::InstallerTestCase
def setup
super
- @cmd = Gem::Command.new 'dummy', 'dummy',
+ @cmd = Gem::Command.new "dummy", "dummy",
Gem::DependencyInstaller::DEFAULT_OPTIONS
@cmd.extend Gem::InstallUpdateOptions
@cmd.add_install_update_options
@@ -38,7 +39,7 @@ class TestGemInstallUpdateOptions < Gem::InstallerTestCase
def test_build_root
@cmd.handle_options %w[--build-root build_root]
- assert_equal File.expand_path('build_root'), @cmd.options[:build_root]
+ assert_equal File.expand_path("build_root"), @cmd.options[:build_root]
end
def test_doc
@@ -92,7 +93,7 @@ class TestGemInstallUpdateOptions < Gem::InstallerTestCase
end
def test_security_policy
- pend 'openssl is missing' unless Gem::HAVE_OPENSSL
+ pend "openssl is missing" unless Gem::HAVE_OPENSSL
@cmd.handle_options %w[-P HighSecurity]
@@ -100,18 +101,18 @@ class TestGemInstallUpdateOptions < Gem::InstallerTestCase
end
def test_security_policy_unknown
- pend 'openssl is missing' unless Gem::HAVE_OPENSSL
+ pend "openssl is missing" unless Gem::HAVE_OPENSSL
@cmd.add_install_update_options
- e = assert_raise OptionParser::InvalidArgument do
+ e = assert_raise Gem::OptionParser::InvalidArgument do
@cmd.handle_options %w[-P UnknownSecurity]
end
assert_includes e.message, "UnknownSecurity"
end
def test_user_install_enabled
- @spec = quick_gem 'a' do |spec|
+ @spec = quick_gem "a" do |spec|
util_make_exec spec
end
@@ -124,42 +125,39 @@ class TestGemInstallUpdateOptions < Gem::InstallerTestCase
@installer = Gem::Installer.at @gem, @cmd.options
@installer.install
- assert_path_exist File.join(Gem.user_dir, 'gems')
- assert_path_exist File.join(Gem.user_dir, 'gems', @spec.full_name)
+ assert_path_exist File.join(Gem.user_dir, "gems")
+ assert_path_exist File.join(Gem.user_dir, "gems", @spec.full_name)
end
def test_user_install_disabled_read_only
- @spec = quick_gem 'a' do |spec|
+ pend "skipped on MS Windows (chmod has no effect)" if Gem.win_platform?
+ pend "skipped in root privilege" if Process.uid.zero?
+
+ @spec = quick_gem "a" do |spec|
util_make_exec spec
end
util_build_gem @spec
@gem = @spec.cache_file
- if win_platform?
- pend('test_user_install_disabled_read_only test skipped on MS Windows')
- elsif Process.uid.zero?
- pend('test_user_install_disabled_read_only test skipped in root privilege')
- else
- @cmd.handle_options %w[--no-user-install]
+ @cmd.handle_options %w[--no-user-install]
- refute @cmd.options[:user_install]
+ refute @cmd.options[:user_install]
- FileUtils.chmod 0755, @userhome
- FileUtils.chmod 0000, @gemhome
+ FileUtils.chmod 0o755, @userhome
+ FileUtils.chmod 0o000, @gemhome
- Gem.use_paths @gemhome, @userhome
+ Gem.use_paths @gemhome, @userhome
- assert_raise(Gem::FilePermissionError) do
- Gem::Installer.at(@gem, @cmd.options).install
- end
+ assert_raise(Gem::FilePermissionError) do
+ Gem::Installer.at(@gem, @cmd.options).install
end
ensure
- FileUtils.chmod 0755, @gemhome
+ FileUtils.chmod 0o755, @gemhome
end
def test_vendor
- vendordir(File.join(@tempdir, 'vendor')) do
+ vendordir(File.join(@tempdir, "vendor")) do
@cmd.handle_options %w[--vendor]
assert @cmd.options[:vendor]
@@ -169,11 +167,11 @@ class TestGemInstallUpdateOptions < Gem::InstallerTestCase
def test_vendor_missing
vendordir(nil) do
- e = assert_raise OptionParser::InvalidOption do
+ e = assert_raise Gem::OptionParser::InvalidOption do
@cmd.handle_options %w[--vendor]
end
- assert_equal 'invalid option: --vendor your platform is not supported',
+ assert_equal "invalid option: --vendor your platform is not supported",
e.message
refute @cmd.options[:vendor]
diff --git a/test/rubygems/test_gem_installer.rb b/test/rubygems/test_gem_installer.rb
index 988f14146d..b83a01c73b 100644
--- a/test/rubygems/test_gem_installer.rb
+++ b/test/rubygems/test_gem_installer.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
-require_relative 'installer_test_case'
+
+require_relative "installer_test_case"
class TestGemInstaller < Gem::InstallerTestCase
def setup
@@ -18,11 +19,12 @@ class TestGemInstaller < Gem::InstallerTestCase
end
def test_app_script_text
- installer = setup_base_installer
+ load_relative "no" do
+ installer = setup_base_installer
- util_make_exec @spec, ''
+ util_make_exec @spec, ""
- expected = <<-EOF
+ expected = <<-EOF
#!#{Gem.ruby}
#
# This file was generated by RubyGems.
@@ -52,10 +54,11 @@ else
gem "a", version
load Gem.bin_path("a", "executable", version)
end
- EOF
+ EOF
- wrapper = installer.app_script_text 'executable'
- assert_equal expected, wrapper
+ wrapper = installer.app_script_text "executable"
+ assert_equal expected, wrapper
+ end
end
def test_check_executable_overwrite
@@ -64,12 +67,12 @@ end
installer.generate_bin
@spec = Gem::Specification.new do |s|
- s.files = ['lib/code.rb']
+ s.files = ["lib/code.rb"]
s.name = "a"
s.version = "3"
s.summary = "summary"
s.description = "desc"
- s.require_path = 'lib'
+ s.require_path = "lib"
end
util_make_exec
@@ -77,11 +80,11 @@ end
installer.wrappers = true
installer.generate_bin
- installed_exec = File.join util_inst_bindir, 'executable'
+ installed_exec = File.join util_inst_bindir, "executable"
assert_path_exist installed_exec
wrapper = File.read installed_exec
- assert_match %r{generated by RubyGems}, wrapper
+ assert_match(/generated by RubyGems/, wrapper)
end
def test_check_executable_overwrite_default_bin_dir
@@ -96,9 +99,9 @@ end
installer.generate_bin
end
- conflicted = File.join @gemhome, 'bin', 'executable'
- assert_match %r{\A"executable" from a conflicts with (?:#{Regexp.quote(conflicted)}|installed executable from conflict)\z},
- e.message
+ conflicted = File.join @gemhome, "bin", "executable"
+ assert_match(/\A"executable" from a conflicts with (?:#{Regexp.quote(conflicted)}|installed executable from conflict)\z/,
+ e.message)
end
end
end
@@ -109,15 +112,15 @@ end
installer.generate_bin
@spec = Gem::Specification.new do |s|
- s.files = ['lib/code.rb']
+ s.files = ["lib/code.rb"]
s.name = "a"
s.version = "3"
s.summary = "summary"
s.description = "desc"
- s.require_path = 'lib'
+ s.require_path = "lib"
end
- File.open File.join(util_inst_bindir, 'executable'), 'w' do |io|
+ File.open File.join(util_inst_bindir, "executable"), "w" do |io|
io.write <<-EXEC
#!/usr/local/bin/ruby
#
@@ -128,18 +131,18 @@ gem 'other', version
end
util_make_exec
- Gem::Installer.exec_format = 'foo-%s-bar'
+ Gem::Installer.exec_format = "foo-%s-bar"
installer.gem_dir = @spec.gem_dir
installer.wrappers = true
installer.format_executable = true
installer.generate_bin # should not raise
- installed_exec = File.join util_inst_bindir, 'foo-executable-bar'
+ installed_exec = File.join util_inst_bindir, "foo-executable-bar"
assert_path_exist installed_exec
wrapper = File.read installed_exec
- assert_match %r{generated by RubyGems}, wrapper
+ assert_match(/generated by RubyGems/, wrapper)
ensure
Gem::Installer.exec_format = nil
end
@@ -170,11 +173,11 @@ gem 'other', version
installer.generate_bin
- installed_exec = File.join util_inst_bindir, 'executable'
+ installed_exec = File.join util_inst_bindir, "executable"
assert_path_exist installed_exec
wrapper = File.read installed_exec
- assert_match %r{generated by RubyGems}, wrapper
+ assert_match(/generated by RubyGems/, wrapper)
end
def test_check_executable_overwrite_other_non_gem
@@ -185,11 +188,11 @@ gem 'other', version
installer.generate_bin
- installed_exec = File.join util_inst_bindir, 'executable'
+ installed_exec = File.join util_inst_bindir, "executable"
assert_path_exist installed_exec
wrapper = File.read installed_exec
- assert_match %r{generated by RubyGems}, wrapper
+ assert_match(/generated by RubyGems/, wrapper)
end unless Gem.win_platform?
def test_check_that_user_bin_dir_is_in_path
@@ -201,8 +204,8 @@ gem 'other', version
bin_dir = bin_dir.downcase
end
- orig_PATH, ENV['PATH'] =
- ENV['PATH'], [ENV['PATH'], bin_dir].join(File::PATH_SEPARATOR)
+ orig_path = ENV["PATH"]
+ ENV["PATH"] = [ENV["PATH"], bin_dir].join(File::PATH_SEPARATOR)
use_ui @ui do
installer.check_that_user_bin_dir_is_in_path
@@ -210,9 +213,9 @@ gem 'other', version
assert_empty @ui.error
- return unless win_platform?
+ return unless Gem.win_platform?
- ENV['PATH'] = [orig_PATH, bin_dir.tr(File::SEPARATOR, File::ALT_SEPARATOR)].join(File::PATH_SEPARATOR)
+ ENV["PATH"] = [orig_path, bin_dir.tr(File::SEPARATOR, File::ALT_SEPARATOR)].join(File::PATH_SEPARATOR)
use_ui @ui do
installer.check_that_user_bin_dir_is_in_path
@@ -220,17 +223,17 @@ gem 'other', version
assert_empty @ui.error
ensure
- ENV['PATH'] = orig_PATH
+ ENV["PATH"] = orig_path
end
def test_check_that_user_bin_dir_is_in_path_tilde
- pend "Tilde is PATH is not supported under MS Windows" if win_platform?
+ pend "Tilde is PATH is not supported under MS Windows" if Gem.win_platform?
- orig_PATH, ENV['PATH'] =
- ENV['PATH'], [ENV['PATH'], '~/bin'].join(File::PATH_SEPARATOR)
+ orig_path = ENV["PATH"]
+ ENV["PATH"] = [ENV["PATH"], "~/bin"].join(File::PATH_SEPARATOR)
installer = setup_base_installer
- installer.bin_dir.replace File.join @userhome, 'bin'
+ installer.bin_dir.replace File.join @userhome, "bin"
use_ui @ui do
installer.check_that_user_bin_dir_is_in_path
@@ -238,7 +241,7 @@ gem 'other', version
assert_empty @ui.error
ensure
- ENV['PATH'] = orig_PATH unless win_platform?
+ ENV["PATH"] = orig_path unless Gem.win_platform?
end
def test_check_that_user_bin_dir_is_in_path_not_in_path
@@ -260,22 +263,22 @@ gem 'other', version
def test_ensure_dependency
installer = setup_base_installer
- util_spec 'a'
+ util_spec "a"
- dep = Gem::Dependency.new 'a', '>= 2'
+ dep = Gem::Dependency.new "a", ">= 2"
assert installer.ensure_dependency(@spec, dep)
- dep = Gem::Dependency.new 'b', '> 2'
+ dep = Gem::Dependency.new "b", "> 2"
e = assert_raise Gem::InstallError do
installer.ensure_dependency @spec, dep
end
- assert_equal 'a requires b (> 2)', e.message
+ assert_equal "a requires b (> 2)", e.message
end
def test_ensure_loadable_spec
- a, a_gem = util_gem 'a', 2 do |s|
- s.add_dependency 'garbage ~> 5'
+ a, a_gem = util_gem "a", 2 do |s|
+ s.add_dependency "garbage ~> 5"
end
installer = Gem::Installer.at a_gem
@@ -284,19 +287,19 @@ gem 'other', version
installer.ensure_loadable_spec
end
- assert_equal "The specification for #{a.full_name} is corrupt " +
+ assert_equal "The specification for #{a.full_name} is corrupt " \
"(SyntaxError)", e.message
end
def test_ensure_loadable_spec_security_policy
- pend 'openssl is missing' unless Gem::HAVE_OPENSSL
+ pend "openssl is missing" unless Gem::HAVE_OPENSSL
- _, a_gem = util_gem 'a', 2 do |s|
- s.add_dependency 'garbage ~> 5'
+ _, a_gem = util_gem "a", 2 do |s|
+ s.add_dependency "garbage ~> 5"
end
policy = Gem::Security::HighSecurity
- installer = Gem::Installer.at a_gem, :security_policy => policy
+ installer = Gem::Installer.at a_gem, security_policy: policy
assert_raise Gem::Security::Exception do
installer.ensure_loadable_spec
@@ -308,7 +311,7 @@ gem 'other', version
installer.extract_files
- assert_path_exist File.join @spec.gem_dir, 'bin/executable'
+ assert_path_exist File.join @spec.gem_dir, "bin/executable"
end
def test_generate_bin_bindir
@@ -317,12 +320,12 @@ gem 'other', version
installer.wrappers = true
@spec.executables = %w[executable]
- @spec.bindir = 'bin'
+ @spec.bindir = "bin"
- exec_file = installer.formatted_program_filename 'executable'
+ exec_file = installer.formatted_program_filename "executable"
exec_path = File.join @spec.gem_dir, exec_file
- File.open exec_path, 'w' do |f|
- f.puts '#!/usr/bin/ruby'
+ File.open exec_path, "w" do |f|
+ f.puts "#!/usr/bin/ruby"
end
installer.gem_dir = @spec.gem_dir
@@ -330,27 +333,30 @@ gem 'other', version
installer.generate_bin
assert_directory_exists util_inst_bindir
- installed_exec = File.join(util_inst_bindir, 'executable')
+ installed_exec = File.join(util_inst_bindir, "executable")
assert_path_exist installed_exec
- assert_equal mask, File.stat(installed_exec).mode unless win_platform?
+ assert_equal mask, File.stat(installed_exec).mode unless Gem.win_platform?
wrapper = File.read installed_exec
- assert_match %r{generated by RubyGems}, wrapper
+ assert_match(/generated by RubyGems/, wrapper)
end
def test_generate_bin_bindir_with_user_install_warning
- bin_dir = Gem.win_platform? ? File.expand_path(ENV["WINDIR"]).upcase :
- "/usr/bin"
+ bin_dir = if Gem.win_platform?
+ File.expand_path(ENV["WINDIR"]).upcase
+ else
+ "/usr/bin"
+ end
old_path = ENV["PATH"]
ENV["PATH"] = [ENV["PATH"], bin_dir].compact.join(File::PATH_SEPARATOR)
options = {
- :bin_dir => bin_dir,
- :install_dir => "/non/existent",
+ bin_dir: bin_dir,
+ install_dir: "/non/existent",
}
- inst = Gem::Installer.at '', options
+ inst = Gem::Installer.at "", options
Gem::Installer.path_warning = false
@@ -359,7 +365,6 @@ gem 'other', version
end
assert_equal "", @ui.error
-
ensure
ENV["PATH"] = old_path
end
@@ -373,12 +378,12 @@ gem 'other', version
installer.generate_bin
assert_directory_exists util_inst_bindir
- installed_exec = File.join util_inst_bindir, 'executable'
+ installed_exec = File.join util_inst_bindir, "executable"
assert_path_exist installed_exec
- assert_equal mask, File.stat(installed_exec).mode unless win_platform?
+ assert_equal mask, File.stat(installed_exec).mode unless Gem.win_platform?
wrapper = File.read installed_exec
- assert_match %r{generated by RubyGems}, wrapper
+ assert_match(/generated by RubyGems/, wrapper)
end
def test_generate_bin_script_format
@@ -389,10 +394,10 @@ gem 'other', version
util_make_exec
installer.gem_dir = @spec.gem_dir
- Gem::Installer.exec_format = 'foo-%s-bar'
+ Gem::Installer.exec_format = "foo-%s-bar"
installer.generate_bin
assert_directory_exists util_inst_bindir
- installed_exec = File.join util_inst_bindir, 'foo-executable-bar'
+ installed_exec = File.join util_inst_bindir, "foo-executable-bar"
assert_path_exist installed_exec
ensure
Gem::Installer.exec_format = nil
@@ -405,10 +410,10 @@ gem 'other', version
util_make_exec
installer.gem_dir = @spec.gem_dir
- Gem::Installer.exec_format = 'foo-%s-bar'
+ Gem::Installer.exec_format = "foo-%s-bar"
installer.generate_bin
assert_directory_exists util_inst_bindir
- installed_exec = File.join util_inst_bindir, 'executable'
+ installed_exec = File.join util_inst_bindir, "executable"
assert_path_exist installed_exec
ensure
Gem::Installer.exec_format = nil
@@ -420,24 +425,24 @@ gem 'other', version
installer.wrappers = true
gem_dir = File.join("#{@gemhome}2", "gems", @spec.full_name)
- gem_bindir = File.join gem_dir, 'bin'
+ gem_bindir = File.join gem_dir, "bin"
FileUtils.mkdir_p gem_bindir
- File.open File.join(gem_bindir, 'executable'), 'w' do |f|
+ File.open File.join(gem_bindir, "executable"), "w" do |f|
f.puts "#!/bin/ruby"
end
installer.gem_home = "#{@gemhome}2"
installer.gem_dir = gem_dir
- installer.bin_dir = File.join "#{@gemhome}2", 'bin'
+ installer.bin_dir = File.join "#{@gemhome}2", "bin"
installer.generate_bin
- installed_exec = File.join("#{@gemhome}2", "bin", 'executable')
+ installed_exec = File.join("#{@gemhome}2", "bin", "executable")
assert_path_exist installed_exec
- assert_equal mask, File.stat(installed_exec).mode unless win_platform?
+ assert_equal mask, File.stat(installed_exec).mode unless Gem.win_platform?
wrapper = File.read installed_exec
- assert_match %r{generated by RubyGems}, wrapper
+ assert_match(/generated by RubyGems/, wrapper)
end
def test_generate_bin_script_no_execs
@@ -448,7 +453,7 @@ gem 'other', version
installer.wrappers = true
installer.generate_bin
- assert_path_not_exist util_inst_bindir, 'bin dir was created when not needed'
+ assert_path_not_exist util_inst_bindir, "bin dir was created when not needed"
end
def test_generate_bin_script_no_perms
@@ -459,19 +464,19 @@ gem 'other', version
Dir.mkdir util_inst_bindir
- if win_platform?
- pend('test_generate_bin_script_no_perms skipped on MS Windows')
+ if Gem.win_platform?
+ pend("test_generate_bin_script_no_perms skipped on MS Windows")
elsif Process.uid.zero?
- pend('test_generate_bin_script_no_perms skipped in root privilege')
+ pend("test_generate_bin_script_no_perms skipped in root privilege")
else
- FileUtils.chmod 0000, util_inst_bindir
+ FileUtils.chmod 0o000, util_inst_bindir
assert_raise Gem::FilePermissionError do
installer.generate_bin
end
end
ensure
- FileUtils.chmod 0755, util_inst_bindir unless ($DEBUG or win_platform?)
+ FileUtils.chmod 0o755, util_inst_bindir unless $DEBUG || Gem.win_platform?
end
def test_generate_bin_script_no_shebang
@@ -480,23 +485,23 @@ gem 'other', version
installer.wrappers = true
@spec.executables = %w[executable]
- gem_dir = File.join @gemhome, 'gems', @spec.full_name
- gem_bindir = File.join gem_dir, 'bin'
+ 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, 'executable'), 'w' do |f|
+ File.open File.join(gem_bindir, "executable"), "w" do |f|
f.puts "blah blah blah"
end
installer.generate_bin
- installed_exec = File.join @gemhome, 'bin', 'executable'
+ installed_exec = File.join @gemhome, "bin", "executable"
assert_path_exist installed_exec
- assert_equal mask, File.stat(installed_exec).mode unless win_platform?
+ assert_equal mask, File.stat(installed_exec).mode unless Gem.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
+ assert_match(/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
@@ -505,9 +510,9 @@ gem 'other', version
installer.wrappers = true
util_make_exec
installer.gem_dir = @spec.gem_dir
- installed_exec = File.join(util_inst_bindir, 'executable')
+ installed_exec = File.join(util_inst_bindir, "executable")
- real_exec = File.join @spec.gem_dir, 'bin', 'executable'
+ real_exec = File.join @spec.gem_dir, "bin", "executable"
# fake --no-wrappers for previous install
unless Gem.win_platform?
@@ -518,12 +523,12 @@ gem 'other', version
installer.generate_bin
assert_directory_exists util_inst_bindir
assert_path_exist installed_exec
- assert_equal mask, File.stat(installed_exec).mode unless win_platform?
+ assert_equal mask, File.stat(installed_exec).mode unless Gem.win_platform?
- assert_match %r{generated by RubyGems}, File.read(installed_exec)
+ assert_match(/generated by RubyGems/, File.read(installed_exec))
- refute_match %r{generated by RubyGems}, File.read(real_exec),
- 'real executable overwritten'
+ refute_match(/generated by RubyGems/, File.read(real_exec),
+ "real executable overwritten")
end
def test_generate_bin_symlink
@@ -537,9 +542,9 @@ gem 'other', version
installer.generate_bin
assert_directory_exists util_inst_bindir
- installed_exec = File.join util_inst_bindir, 'executable'
+ installed_exec = File.join util_inst_bindir, "executable"
assert_equal true, File.symlink?(installed_exec)
- assert_equal(File.join(@spec.gem_dir, 'bin', 'executable'),
+ assert_equal(File.join(@spec.gem_dir, "bin", "executable"),
File.readlink(installed_exec))
end
@@ -563,19 +568,19 @@ gem 'other', version
Dir.mkdir util_inst_bindir
- if win_platform?
- pend('test_generate_bin_symlink_no_perms skipped on MS Windows')
+ if Gem.win_platform?
+ pend("test_generate_bin_symlink_no_perms skipped on MS Windows")
elsif Process.uid.zero?
- pend('test_user_install_disabled_read_only test skipped in root privilege')
+ pend("test_user_install_disabled_read_only test skipped in root privilege")
else
- FileUtils.chmod 0000, util_inst_bindir
+ FileUtils.chmod 0o000, util_inst_bindir
assert_raise Gem::FilePermissionError do
installer.generate_bin
end
end
ensure
- FileUtils.chmod 0755, util_inst_bindir unless ($DEBUG or win_platform?)
+ FileUtils.chmod 0o755, util_inst_bindir unless $DEBUG || Gem.win_platform?
end
def test_generate_bin_symlink_update_newer
@@ -588,24 +593,24 @@ gem 'other', version
installer.gem_dir = @spec.gem_dir
installer.generate_bin
- installed_exec = File.join(util_inst_bindir, 'executable')
- assert_equal(File.join(@spec.gem_dir, 'bin', 'executable'),
+ installed_exec = File.join(util_inst_bindir, "executable")
+ assert_equal(File.join(@spec.gem_dir, "bin", "executable"),
File.readlink(installed_exec))
@spec = Gem::Specification.new do |s|
- s.files = ['lib/code.rb']
+ s.files = ["lib/code.rb"]
s.name = "a"
s.version = "3"
s.summary = "summary"
s.description = "desc"
- s.require_path = 'lib'
+ s.require_path = "lib"
end
util_make_exec
installer.gem_dir = @spec.gem_dir
installer.generate_bin
- installed_exec = File.join(util_inst_bindir, 'executable')
- assert_equal(@spec.bin_file('executable'),
+ installed_exec = File.join(util_inst_bindir, "executable")
+ assert_equal(@spec.bin_file("executable"),
File.readlink(installed_exec),
"Ensure symlink moved to latest version")
end
@@ -620,17 +625,17 @@ gem 'other', version
installer.gem_dir = @spec.gem_dir
installer.generate_bin
- installed_exec = File.join(util_inst_bindir, 'executable')
- assert_equal(File.join(@spec.gem_dir, 'bin', 'executable'),
+ installed_exec = File.join(util_inst_bindir, "executable")
+ assert_equal(File.join(@spec.gem_dir, "bin", "executable"),
File.readlink(installed_exec))
spec = Gem::Specification.new do |s|
- s.files = ['lib/code.rb']
+ s.files = ["lib/code.rb"]
s.name = "a"
s.version = "1"
s.summary = "summary"
s.description = "desc"
- s.require_path = 'lib'
+ s.require_path = "lib"
end
util_make_exec
@@ -641,8 +646,8 @@ gem 'other', version
installer.generate_bin
- installed_exec = File.join util_inst_bindir, 'executable'
- expected = File.join @spec.gem_dir, 'bin', 'executable'
+ installed_exec = File.join util_inst_bindir, "executable"
+ expected = File.join @spec.gem_dir, "bin", "executable"
assert_equal(expected,
File.readlink(installed_exec),
"Ensure symlink not moved")
@@ -659,16 +664,16 @@ gem 'other', version
installer.generate_bin
- installed_exec = File.join util_inst_bindir, 'executable'
+ installed_exec = File.join util_inst_bindir, "executable"
assert_path_exist installed_exec
@spec = Gem::Specification.new do |s|
- s.files = ['lib/code.rb']
+ s.files = ["lib/code.rb"]
s.name = "a"
s.version = "3"
s.summary = "summary"
s.description = "desc"
- s.require_path = 'lib'
+ s.require_path = "lib"
end
util_make_exec
@@ -678,8 +683,8 @@ gem 'other', version
installer.generate_bin
- installed_exec = File.join util_inst_bindir, 'executable'
- assert_equal(@spec.bin_file('executable'),
+ installed_exec = File.join util_inst_bindir, "executable"
+ assert_equal(@spec.bin_file("executable"),
File.readlink(installed_exec),
"Ensure symlink moved to latest version")
end
@@ -689,7 +694,7 @@ gem 'other', version
Gem.win_platform = true
old_alt_separator = File::ALT_SEPARATOR
File.__send__(:remove_const, :ALT_SEPARATOR)
- File.const_set(:ALT_SEPARATOR, '\\')
+ File.const_set(:ALT_SEPARATOR, "\\")
installer = setup_base_installer
@@ -702,7 +707,7 @@ gem 'other', version
end
assert_directory_exists util_inst_bindir
- installed_exec = File.join(util_inst_bindir, 'executable')
+ installed_exec = File.join(util_inst_bindir, "executable")
assert_path_exist installed_exec
if symlink_supported?
@@ -724,17 +729,19 @@ gem 'other', version
def test_generate_bin_uses_default_shebang
pend "Symlinks not supported or not enabled" unless symlink_supported?
- installer = setup_base_installer
+ load_relative "no" do
+ installer = setup_base_installer
- installer.wrappers = true
- util_make_exec
+ installer.wrappers = true
+ util_make_exec
- installer.generate_bin
+ installer.generate_bin
- default_shebang = Gem.ruby
- shebang_line = File.open("#{@gemhome}/bin/executable") {|f| f.readlines.first }
- assert_match(/\A#!/, shebang_line)
- assert_match(/#{default_shebang}/, shebang_line)
+ default_shebang = Gem.ruby
+ shebang_line = File.open("#{@gemhome}/bin/executable", &:gets)
+ assert_match(/\A#!/, shebang_line)
+ assert_include(shebang_line, default_shebang)
+ end
end
def test_generate_bin_with_dangling_symlink
@@ -742,8 +749,8 @@ gem 'other', version
installer = Gem::Installer.at(
gem_with_dangling_symlink,
- :user_install => false,
- :force => true
+ user_install: false,
+ force: true
)
build_rake_in do
@@ -752,14 +759,17 @@ gem 'other', version
end
end
- assert_match %r{bin/ascii_binder` is dangling symlink pointing to `bin/asciibinder`}, @ui.error
+ errors = @ui.error.split("\n")
+ assert_equal "WARNING: ascii_binder-0.1.10.1 ships with a dangling symlink named bin/ascii_binder pointing to missing bin/asciibinder file. Ignoring", errors.shift
+ assert_empty errors
+
assert_empty @ui.output
end
def test_generate_plugins
installer = util_setup_installer do |spec|
- write_file File.join(@tempdir, 'lib', 'rubygems_plugin.rb') do |io|
- io.write "puts __FILE__"
+ write_file File.join(@tempdir, "lib", "rubygems_plugin.rb") do |io|
+ io.write "# do nothing"
end
spec.files += %w[lib/rubygems_plugin.rb]
@@ -769,18 +779,18 @@ gem 'other', version
installer.install
end
- plugin_path = File.join Gem.plugindir, 'a_plugin.rb'
+ plugin_path = File.join Gem.plugindir, "a_plugin.rb"
FileUtils.rm plugin_path
installer.generate_plugins
- assert File.exist?(plugin_path), 'plugin not written'
+ assert File.exist?(plugin_path), "plugin not written"
end
def test_generate_plugins_with_install_dir
- spec = quick_gem 'a' do |s|
- write_file File.join(@tempdir, 'lib', 'rubygems_plugin.rb') do |io|
+ spec = quick_gem "a" do |s|
+ write_file File.join(@tempdir, "lib", "rubygems_plugin.rb") do |io|
io.write "puts __FILE__"
end
@@ -789,17 +799,17 @@ gem 'other', version
util_build_gem spec
- plugin_path = File.join "#{@gemhome}2", 'plugins', 'a_plugin.rb'
+ plugin_path = File.join "#{@gemhome}2", "plugins", "a_plugin.rb"
installer = util_installer spec, "#{@gemhome}2"
assert_equal spec, installer.install
- assert File.exist?(plugin_path), 'plugin not written to install_dir'
+ assert File.exist?(plugin_path), "plugin not written to install_dir"
end
def test_generate_plugins_with_user_install
- spec = quick_gem 'a' do |s|
- write_file File.join(@tempdir, 'lib', 'rubygems_plugin.rb') do |io|
+ spec = quick_gem "a" do |s|
+ write_file File.join(@tempdir, "lib", "rubygems_plugin.rb") do |io|
io.write "puts __FILE__"
end
@@ -808,20 +818,20 @@ gem 'other', version
util_build_gem spec
- File.chmod(0555, Gem.plugindir)
- system_path = File.join(Gem.plugindir, 'a_plugin.rb')
- user_path = File.join(Gem.plugindir(Gem.user_dir), 'a_plugin.rb')
- installer = util_installer spec, Gem.dir, :user
+ File.chmod(0o555, Gem.plugindir)
+ system_path = File.join(Gem.plugindir, "a_plugin.rb")
+ user_path = File.join(Gem.plugindir(Gem.user_dir), "a_plugin.rb")
+ installer = Gem::Installer.at spec.cache_file, user_install: true, force: true
assert_equal spec, installer.install
- assert !File.exist?(system_path), 'plugin incorrectly written to system plugins_dir'
- assert File.exist?(user_path), 'plugin not written to user plugins_dir'
+ assert !File.exist?(system_path), "plugin incorrectly written to system plugins_dir"
+ assert File.exist?(user_path), "plugin not written to user plugins_dir"
end
def test_generate_plugins_with_build_root
- spec = quick_gem 'a' do |s|
- write_file File.join(@tempdir, 'lib', 'rubygems_plugin.rb') do |io|
+ spec = quick_gem "a" do |s|
+ write_file File.join(@tempdir, "lib", "rubygems_plugin.rb") do |io|
io.write "puts __FILE__"
end
@@ -830,78 +840,126 @@ gem 'other', version
util_build_gem spec
- File.chmod(0555, Gem.plugindir)
- system_path = File.join(Gem.plugindir, 'a_plugin.rb')
+ File.chmod(0o555, Gem.plugindir)
+ system_path = File.join(Gem.plugindir, "a_plugin.rb")
- build_root = File.join(@tempdir, 'build_root')
- build_root_path = File.join(build_root, Gem.plugindir.gsub(/^[a-zA-Z]:/, ''), 'a_plugin.rb')
+ build_root = File.join(@tempdir, "build_root")
+ build_root_path = File.join(build_root, Gem.plugindir.gsub(/^[a-zA-Z]:/, ""), "a_plugin.rb")
- installer = Gem::Installer.at spec.cache_file, :build_root => build_root
+ installer = Gem::Installer.at spec.cache_file, build_root: build_root
assert_equal spec, installer.install
- assert !File.exist?(system_path), 'plugin written incorrect written to system plugins_dir'
- assert File.exist?(build_root_path), 'plugin not written to build_root'
+ assert !File.exist?(system_path), "plugin written incorrect written to system plugins_dir"
+ assert File.exist?(build_root_path), "plugin not written to build_root"
refute_includes File.read(build_root_path), build_root
end
+ class << self
+ attr_accessor :plugin_loaded
+ attr_accessor :post_install_is_called
+ end
+
+ def test_use_plugin_immediately
+ self.class.plugin_loaded = false
+ self.class.post_install_is_called = false
+ spec_version = nil
+ plugin_path = nil
+ installer = util_setup_installer do |spec|
+ spec_version = spec.version
+ plugin_path = File.join("lib", "rubygems_plugin.rb")
+ write_file File.join(@tempdir, plugin_path) do |io|
+ io.write <<-PLUGIN
+#{self.class}.plugin_loaded = true
+Gem.post_install do
+ #{self.class}.post_install_is_called = true
+end
+ PLUGIN
+ end
+ spec.files += [plugin_path]
+ plugin_path = File.join(spec.gem_dir, plugin_path)
+ end
+ build_rake_in do
+ installer.install
+ end
+ assert self.class.plugin_loaded, "plugin is not loaded"
+ assert self.class.post_install_is_called,
+ "post install hook registered by plugin is not called"
+
+ self.class.plugin_loaded = false
+ $LOADED_FEATURES.delete(plugin_path)
+ installer_new = util_setup_installer do |spec_new|
+ spec_new.version = spec_version.version.succ
+ plugin_path = File.join("lib", "rubygems_plugin.rb")
+ write_file File.join(@tempdir, plugin_path) do |io|
+ io.write "#{self.class}.plugin_loaded = true"
+ end
+ spec_new.files += [plugin_path]
+ end
+ build_rake_in do
+ installer_new.install
+ end
+ assert !self.class.plugin_loaded,
+ "plugin is loaded even when old version is already loaded"
+ end
+
def test_keeps_plugins_up_to_date
# NOTE: version a-2 is already installed by setup hooks
- write_file File.join(@tempdir, 'lib', 'rubygems_plugin.rb') do |io|
- io.write "puts __FILE__"
+ write_file File.join(@tempdir, "lib", "rubygems_plugin.rb") do |io|
+ io.write "# do nothing"
end
build_rake_in do
util_setup_installer do |spec|
- spec.version = '1'
+ spec.version = "1"
spec.files += %w[lib/rubygems_plugin.rb]
end.install
- plugin_path = File.join Gem.plugindir, 'a_plugin.rb'
- refute File.exist?(plugin_path), 'old version installed while newer version without plugin also installed, but plugin written'
+ plugin_path = File.join Gem.plugindir, "a_plugin.rb"
+ refute File.exist?(plugin_path), "old version installed while newer version without plugin also installed, but plugin written"
util_setup_installer do |spec|
- spec.version = '2'
+ spec.version = "2"
spec.files += %w[lib/rubygems_plugin.rb]
end.install
- plugin_path = File.join Gem.plugindir, 'a_plugin.rb'
- assert File.exist?(plugin_path), 'latest version reinstalled, but plugin not written'
- assert_match %r{\Arequire.*a-2/lib/rubygems_plugin\.rb}, File.read(plugin_path), 'written plugin has incorrect content'
+ plugin_path = File.join Gem.plugindir, "a_plugin.rb"
+ assert File.exist?(plugin_path), "latest version reinstalled, but plugin not written"
+ assert_match %r{\Arequire.*a-2/lib/rubygems_plugin\.rb}, File.read(plugin_path), "written plugin has incorrect content"
util_setup_installer do |spec|
- spec.version = '3'
+ spec.version = "3"
spec.files += %w[lib/rubygems_plugin.rb]
end.install
- plugin_path = File.join Gem.plugindir, 'a_plugin.rb'
- assert File.exist?(plugin_path), 'latest version installed, but plugin removed'
- assert_match %r{\Arequire.*a-3/lib/rubygems_plugin\.rb}, File.read(plugin_path), 'written plugin has incorrect content'
+ plugin_path = File.join Gem.plugindir, "a_plugin.rb"
+ assert File.exist?(plugin_path), "latest version installed, but plugin removed"
+ assert_match %r{\Arequire.*a-3/lib/rubygems_plugin\.rb}, File.read(plugin_path), "written plugin has incorrect content"
util_setup_installer do |spec|
- spec.version = '4'
+ spec.version = "4"
end.install
- refute File.exist?(plugin_path), 'new version installed without a plugin while older version with a plugin installed, but plugin not removed'
+ refute File.exist?(plugin_path), "new version installed without a plugin while older version with a plugin installed, but plugin not removed"
end
end
def test_generates_plugins_dir_under_install_dir_if_not_there
Gem.use_paths "#{@gemhome}2" # Set GEM_HOME to an uninitialized repo
- @spec = util_spec 'a'
+ @spec = util_spec "a"
path = Gem::Package.build @spec
- installer = Gem::Installer.at path, :install_dir => "#{@gemhome}3"
+ installer = Gem::Installer.at path, install_dir: "#{@gemhome}3"
assert_equal @spec, installer.install
end
def test_initialize
- spec = util_spec 'a' do |s|
- s.platform = Gem::Platform.new 'mswin32'
+ spec = util_spec "a" do |s|
+ s.platform = Gem::Platform.new "mswin32"
end
gem = File.join @tempdir, spec.file_name
@@ -912,16 +970,16 @@ gem 'other', version
installer = Gem::Installer.at gem
- assert_equal File.join(@gemhome, 'gems', spec.full_name), installer.gem_dir
- assert_equal File.join(@gemhome, 'bin'), installer.bin_dir
+ assert_equal File.join(@gemhome, "gems", spec.full_name), installer.gem_dir
+ assert_equal File.join(@gemhome, "bin"), installer.bin_dir
end
def test_initialize_user_install
@gem = setup_base_gem
- installer = Gem::Installer.at @gem, :user_install => true
+ installer = Gem::Installer.at @gem, user_install: true
- assert_equal File.join(Gem.user_dir, 'gems', @spec.full_name),
+ assert_equal File.join(Gem.user_dir, "gems", @spec.full_name),
installer.gem_dir
assert_equal Gem.bindir(Gem.user_dir), installer.bin_dir
end
@@ -930,39 +988,49 @@ gem 'other', version
@gem = setup_base_gem
installer =
- Gem::Installer.at @gem, :user_install => true, :bin_dir => @tempdir
+ Gem::Installer.at @gem, user_install: true, bin_dir: @tempdir
- assert_equal File.join(Gem.user_dir, 'gems', @spec.full_name),
+ assert_equal File.join(Gem.user_dir, "gems", @spec.full_name),
installer.gem_dir
assert_equal @tempdir, installer.bin_dir
end
+ def test_install_dir_takes_precedence_to_user_install
+ gemhome2 = "#{@gemhome}2"
+
+ @gem = setup_base_gem
+
+ installer =
+ Gem::Installer.at @gem, install_dir: gemhome2, user_install: true
+ installer.install
+
+ assert_path_exist File.join(gemhome2, "gems", @spec.full_name)
+ assert_path_not_exist File.join(Gem.user_dir, "gems", @spec.full_name)
+ end
+
def test_install
installer = util_setup_installer
- gemdir = File.join @gemhome, 'gems', @spec.full_name
- cache_file = File.join @gemhome, 'cache', @spec.file_name
- stub_exe = File.join @gemhome, 'bin', 'executable'
- rakefile = File.join gemdir, 'ext', 'a', 'Rakefile'
- spec_file = File.join @gemhome, 'specifications', @spec.spec_name
+ gemdir = File.join @gemhome, "gems", @spec.full_name
+ cache_file = File.join @gemhome, "cache", @spec.file_name
+ stub_exe = File.join @gemhome, "bin", "executable"
+ rakefile = File.join gemdir, "ext", "a", "Rakefile"
+ spec_file = File.join @gemhome, "specifications", @spec.spec_name
Gem.pre_install do
- assert_path_not_exist cache_file, 'cache file must not exist yet'
- assert_path_not_exist spec_file, 'spec file must not exist yet'
+ assert_path_not_exist cache_file, "cache file must not exist yet"
true
end
Gem.post_build do
- assert_path_exist gemdir, 'gem install dir must exist'
- assert_path_exist rakefile, 'gem executable must exist'
- assert_path_not_exist stub_exe, 'gem executable must not exist'
- assert_path_not_exist spec_file, 'spec file must not exist yet'
+ assert_path_exist gemdir, "gem install dir must exist"
+ assert_path_exist rakefile, "gem executable must exist"
+ assert_path_not_exist stub_exe, "gem executable must not exist"
true
end
Gem.post_install do
- assert_path_exist cache_file, 'cache file must exist'
- assert_path_exist spec_file, 'spec file must exist'
+ assert_path_exist cache_file, "cache file must exist"
end
@newspec = nil
@@ -974,15 +1042,15 @@ gem 'other', version
assert_equal @spec, @newspec
assert_path_exist gemdir
- assert_path_exist stub_exe, 'gem executable must exist'
+ assert_path_exist stub_exe, "gem executable must exist"
- exe = File.join gemdir, 'bin', 'executable'
+ exe = File.join gemdir, "bin", "executable"
assert_path_exist exe
- exe_mode = File.stat(exe).mode & 0111
- assert_equal 0111, exe_mode, "0%o" % exe_mode unless win_platform?
+ exe_mode = File.stat(exe).mode & 0o111
+ assert_equal 0o111, exe_mode, format("0%o", exe_mode) unless Gem.win_platform?
- assert_path_exist File.join gemdir, 'lib', 'code.rb'
+ assert_path_exist File.join gemdir, "lib", "code.rb"
assert_path_exist rakefile
@@ -999,7 +1067,7 @@ gem 'other', version
installer.wrappers = true
- gemdir = File.join @gemhome, 'gems', @spec.full_name
+ gemdir = File.join @gemhome, "gems", @spec.full_name
@newspec = nil
build_rake_in do
@@ -1008,24 +1076,26 @@ gem 'other', version
end
end
- exe = File.join gemdir, 'bin', 'executable'
+ exe = File.join gemdir, "bin", "executable"
e = assert_raise RuntimeError do
instance_eval File.read(exe)
end
assert_match(/ran executable/, e.message)
+
+ assert_path_not_exist(File.join(installer.bin_dir, "executable.lock"))
end
def test_conflicting_binstubs
@gem = setup_base_gem
# build old version that has a bin file
- installer = util_setup_gem do |spec|
- File.open File.join('bin', 'executable'), 'w' do |f|
+ installer = util_setup_gem do |_spec|
+ File.open File.join("bin", "executable"), "w" do |f|
f.puts "require 'code'"
end
- File.open File.join('lib', 'code.rb'), 'w' do |f|
+ File.open File.join("lib", "code.rb"), "w" do |f|
f.puts 'raise "I have an executable"'
end
end
@@ -1037,15 +1107,15 @@ gem 'other', version
end
end
- old_bin_file = File.join installer.bin_dir, 'executable'
+ old_bin_file = File.join installer.bin_dir, "executable"
# build new version that doesn't have a bin file
installer = util_setup_gem do |spec|
- FileUtils.rm File.join('bin', 'executable')
- spec.files.delete File.join('bin', 'executable')
- spec.executables.delete 'executable'
+ FileUtils.rm File.join("bin", "executable")
+ spec.files.delete File.join("bin", "executable")
+ spec.executables.delete "executable"
spec.version = @spec.version.bump
- File.open File.join('lib', 'code.rb'), 'w' do |f|
+ File.open File.join("lib", "code.rb"), "w" do |f|
f.puts 'raise "I do not have an executable"'
end
end
@@ -1062,7 +1132,9 @@ gem 'other', version
# We expect the bin stub to activate the version that actually contains
# the binstub.
- assert_match('I have an executable', e.message)
+ assert_match("I have an executable", e.message)
+
+ assert_path_not_exist(File.join(installer.bin_dir, "executable.lock"))
end
def test_install_creates_binstub_that_understand_version
@@ -1077,7 +1149,7 @@ gem 'other', version
end
end
- exe = File.join @gemhome, 'bin', 'executable'
+ exe = File.join @gemhome, "bin", "executable"
ARGV.unshift "_3.0_"
@@ -1092,20 +1164,22 @@ gem 'other', version
end
assert_includes(e.message, "can't find gem a (= 3.0)")
+
+ assert_path_not_exist(File.join(installer.bin_dir, "executable.lock"))
end
def test_install_creates_binstub_that_prefers_user_installed_gem_to_default
- default_spec = new_default_spec('default', '2', nil, 'exe/executable')
- default_spec.executables = 'executable'
+ default_spec = new_default_spec("default", "2", nil, "exe/executable")
+ default_spec.executables = "executable"
install_default_gems default_spec
- exe = File.join @gemhome, 'bin', 'executable'
+ exe = File.join @gemhome, "bin", "executable"
assert_path_exist exe, "default gem's executable not installed"
installer = util_setup_installer do |spec|
- spec.name = 'default'
- spec.version = '2'
+ spec.name = "default"
+ spec.version = "2"
end
util_clear_gems
@@ -1124,6 +1198,8 @@ gem 'other', version
end
assert_equal(e.message, "ran executable")
+
+ assert_path_not_exist(File.join(installer.bin_dir, "executable.lock"))
end
def test_install_creates_binstub_that_dont_trust_encoding
@@ -1138,7 +1214,7 @@ gem 'other', version
end
end
- exe = File.join @gemhome, 'bin', 'executable'
+ exe = File.join @gemhome, "bin", "executable"
extra_arg = "\xE4pfel".dup.force_encoding("UTF-8")
ARGV.unshift extra_arg
@@ -1154,6 +1230,36 @@ gem 'other', version
end
assert_match(/ran executable/, e.message)
+
+ assert_path_not_exist(File.join(installer.bin_dir, "executable.lock"))
+ end
+
+ def test_install_does_not_leave_lockfile_for_binstub
+ installer = util_setup_installer
+
+ installer.wrappers = true
+
+ File.class_eval do
+ alias_method :original_chmod, :chmod
+ define_method(:chmod) do |mode|
+ original_chmod(mode)
+ raise Gem::Ext::BuildError if path.end_with?("/executable")
+ end
+ end
+
+ assert_raise(Gem::Ext::BuildError) do
+ installer.install
+ end
+
+ assert_path_not_exist(File.join(installer.bin_dir, "executable.lock"))
+ # TODO: remove already copied files at failures.
+ # assert_path_not_exist(File.join(installer.bin_dir, "executable"))
+ ensure
+ File.class_eval do
+ remove_method :chmod
+ alias_method :chmod, :original_chmod
+ remove_method :original_chmod
+ end
end
def test_install_with_no_prior_files
@@ -1165,16 +1271,16 @@ gem 'other', version
end
end
- gemdir = File.join(@gemhome, 'gems', @spec.full_name)
- assert_path_exist File.join gemdir, 'lib', 'code.rb'
+ gemdir = File.join(@gemhome, "gems", @spec.full_name)
+ assert_path_exist File.join gemdir, "lib", "code.rb"
installer = util_setup_installer
# Morph spec to have lib/other.rb instead of code.rb and recreate
- @spec.files = File.join('lib', 'other.rb')
+ @spec.files = File.join("lib", "other.rb")
Dir.chdir @tempdir do
- File.open File.join('lib', 'other.rb'), 'w' do |f|
- f.puts '1'
+ File.open File.join("lib", "other.rb"), "w" do |f|
+ f.puts "1"
end
use_ui ui do
@@ -1182,62 +1288,84 @@ gem 'other', version
Gem::Package.build @spec
end
end
- installer = Gem::Installer.at @gem, :force => true
+ installer = Gem::Installer.at @gem, force: true
build_rake_in do
use_ui @ui do
assert_equal @spec, installer.install
end
end
- assert_path_exist File.join gemdir, 'lib', 'other.rb'
- assert_path_not_exist File.join gemdir, 'lib', 'code.rb',
+ assert_path_exist File.join gemdir, "lib", "other.rb"
+ assert_path_not_exist File.join gemdir, "lib", "code.rb",
"code.rb from prior install of same gem shouldn't remain here"
end
def test_install_force
- _, missing_dep_gem = util_gem 'missing_dep', '1' do |s|
- s.add_dependency 'doesnt_exist', '1'
+ _, missing_dep_gem = util_gem "missing_dep", "1" do |s|
+ s.add_dependency "doesnt_exist", "1"
end
use_ui @ui do
- installer = Gem::Installer.at missing_dep_gem, :force => true
+ installer = Gem::Installer.at missing_dep_gem, force: true
installer.install
end
- gem_dir = File.join(@gemhome, 'gems', 'missing_dep-1')
+ gem_dir = File.join(@gemhome, "gems", "missing_dep-1")
assert_path_exist gem_dir
end
def test_install_build_root
- build_root = File.join(@tempdir, 'build_root')
+ build_root = File.join(@tempdir, "build_root")
@gem = setup_base_gem
- installer = Gem::Installer.at @gem, :build_root => build_root
+ installer = Gem::Installer.at @gem, build_root: build_root
assert_equal @spec, installer.install
end
+ def test_install_build_root_when_gem_home_not_writable_does_not_fallback_to_user_install_inside_build_root
+ build_root = File.join(@tempdir, "build_root")
+
+ orig_gem_home = ENV.delete("GEM_HOME")
+
+ @gem = setup_base_gem
+
+ FileUtils.chmod "-w", @gemhome
+
+ installer = Gem::Installer.at @gem, build_root: build_root
+
+ assert_equal @spec, installer.install
+
+ build_root_path = File.join(build_root, @gemhome.gsub(/^[a-zA-Z]:/, ""))
+ assert File.exist?(build_root_path), "gem not written to build_root"
+ ensure
+ FileUtils.chmod "+w", @gemhome
+ ENV["GEM_HOME"] = orig_gem_home
+ end
+
def test_install_missing_dirs
installer = setup_base_installer
- FileUtils.rm_f File.join(Gem.dir, 'cache')
- FileUtils.rm_f File.join(Gem.dir, 'doc')
- FileUtils.rm_f File.join(Gem.dir, 'specifications')
+ FileUtils.rm_rf File.join(Gem.dir, "doc")
+ FileUtils.rm_rf File.join(Gem.dir, "specifications")
use_ui @ui do
installer.install
end
- assert_directory_exists File.join(Gem.dir, 'cache')
- assert_directory_exists File.join(Gem.dir, 'doc')
- assert_directory_exists File.join(Gem.dir, 'specifications')
+ assert_directory_exists File.join(Gem.dir, "doc")
+ assert_directory_exists File.join(Gem.dir, "specifications")
- assert_path_exist File.join @gemhome, 'cache', @spec.file_name
- assert_path_exist File.join @gemhome, 'specifications', @spec.spec_name
+ assert_path_exist File.join @gemhome, "cache", @spec.file_name
+ assert_path_exist File.join @gemhome, "specifications", @spec.spec_name
end
def test_install_post_build_false
- installer = setup_base_installer
+ @spec = util_spec "a"
+
+ util_build_gem @spec
+
+ installer = util_installer @spec, @gemhome
Gem.post_build do
false
@@ -1253,10 +1381,10 @@ gem 'other', version
assert_equal "post-build hook at #{location} failed for a-2", e.message
end
- spec_file = File.join @gemhome, 'specifications', @spec.spec_name
+ spec_file = File.join @gemhome, "specifications", @spec.spec_name
assert_path_not_exist spec_file
- gem_dir = File.join @gemhome, 'gems', @spec.full_name
+ gem_dir = File.join @gemhome, "gems", @spec.full_name
assert_path_not_exist gem_dir
end
@@ -1271,15 +1399,19 @@ gem 'other', version
installer.install
end
- spec_file = File.join @gemhome, 'specifications', @spec.spec_name
+ spec_file = File.join @gemhome, "specifications", @spec.spec_name
assert_path_exist spec_file
- gem_dir = File.join @gemhome, 'gems', @spec.full_name
+ gem_dir = File.join @gemhome, "gems", @spec.full_name
assert_path_exist gem_dir
end
def test_install_pre_install_false
- installer = setup_base_installer
+ @spec = util_spec "a"
+
+ util_build_gem @spec
+
+ installer = util_installer @spec, @gemhome
Gem.pre_install do
false
@@ -1295,7 +1427,7 @@ gem 'other', version
assert_equal "pre-install hook at #{location} failed for a-2", e.message
end
- spec_file = File.join @gemhome, 'specifications', @spec.spec_name
+ spec_file = File.join @gemhome, "specifications", @spec.spec_name
assert_path_not_exist spec_file
end
@@ -1310,13 +1442,13 @@ gem 'other', version
installer.install
end
- spec_file = File.join @gemhome, 'specifications', @spec.spec_name
+ spec_file = File.join @gemhome, "specifications", @spec.spec_name
assert_path_exist spec_file
end
def test_install_with_message
@spec = setup_base_spec
- @spec.post_install_message = 'I am a shiny gem!'
+ @spec.post_install_message = "I am a shiny gem!"
use_ui @ui do
path = Gem::Package.build @spec
@@ -1325,21 +1457,21 @@ gem 'other', version
installer.install
end
- assert_match %r{I am a shiny gem!}, @ui.output
+ assert_match(/I am a shiny gem!/, @ui.output)
end
def test_install_with_skipped_message
@spec = setup_base_spec
- @spec.post_install_message = 'I am a shiny gem!'
+ @spec.post_install_message = "I am a shiny gem!"
use_ui @ui do
path = Gem::Package.build @spec
- installer = Gem::Installer.at path, :post_install_message => false
+ installer = Gem::Installer.at path, post_install_message: false
installer.install
end
- refute_match %r{I am a shiny gem!}, @ui.output
+ refute_match(/I am a shiny gem!/, @ui.output)
end
def test_install_extension_dir
@@ -1359,11 +1491,11 @@ gem 'other', version
use_ui @ui do
path = Gem::Package.build @spec
- installer = Gem::Installer.at path, :install_dir => gemhome2
+ installer = Gem::Installer.at path, install_dir: gemhome2
installer.install
end
- expected_makefile = File.join gemhome2, 'gems', @spec.full_name, 'Makefile'
+ expected_makefile = File.join gemhome2, "gems", @spec.full_name, "Makefile"
assert_path_exist expected_makefile
end
@@ -1398,7 +1530,7 @@ gem 'other', version
# reinstall the gem, this is also the same as pristine
use_ui @ui do
- installer = Gem::Installer.at path, :force => true
+ installer = Gem::Installer.at path, force: true
installer.install
end
@@ -1424,15 +1556,15 @@ gem 'other', version
use_ui @ui do
path = Gem::Package.build @spec
- installer = Gem::Installer.at path, :user_install => true
+ installer = Gem::Installer.at path, user_install: true
installer.install
end
- expected_makefile = File.join Gem.user_dir, 'gems', @spec.full_name, 'Makefile'
+ expected_makefile = File.join Gem.user_dir, "gems", @spec.full_name, "Makefile"
assert_path_exist expected_makefile
assert_path_exist expected_extension_dir
- assert_path_not_exist File.join expected_extension_dir, 'gem_make.out'
+ assert_path_not_exist File.join expected_extension_dir, "gem_make.out"
end
def test_find_lib_file_after_install
@@ -1462,7 +1594,7 @@ gem 'other', version
end
Dir.mkdir File.join(@tempdir, "lib")
- write_file File.join(@tempdir, 'lib', "b.rb") do |io|
+ write_file File.join(@tempdir, "lib", "b.rb") do |io|
io.write "# b.rb"
end
@@ -1476,14 +1608,14 @@ gem 'other', version
end
expected = File.join @spec.full_require_paths.find {|path|
- File.exist? File.join path, 'b.rb'
- }, 'b.rb'
- assert_equal expected, @spec.matches_for_glob('b.rb').first
+ File.exist? File.join path, "b.rb"
+ }, "b.rb"
+ assert_equal expected, @spec.matches_for_glob("b.rb").first
end
def test_install_extension_and_script
pend "Makefile creation crashes on jruby" if Gem.java_platform?
- pend if /mswin/ =~ RUBY_PLATFORM && ENV.key?('GITHUB_ACTIONS') # not working from the beginning
+ pend "terminates on mswin" if vc_windows? && ruby_repo?
@spec = setup_base_spec
@spec.extensions << "extconf.rb"
@@ -1549,7 +1681,7 @@ gem 'other', version
write_file File.join(@tempdir, file)
end
- so = File.join(@spec.gem_dir, "#{@spec.name}.#{RbConfig::CONFIG["DLEXT"]}")
+ so = File.join(@spec.extension_dir, "#{@spec.name}.#{RbConfig::CONFIG["DLEXT"]}")
assert_path_not_exist so
use_ui @ui do
path = Gem::Package.build @spec
@@ -1558,31 +1690,53 @@ gem 'other', version
installer.install
end
assert_path_exist so
- rescue
- puts '-' * 78
- puts File.read File.join(@gemhome, 'gems', 'a-2', 'Makefile')
- puts '-' * 78
+ end
+ end
- path = File.join(@gemhome, 'gems', 'a-2', 'gem_make.out')
+ def test_install_extension_clean_intermediate_files
+ pend "extensions don't quite work on jruby" if Gem.java_platform?
+ @spec = setup_base_spec
+ @spec.require_paths = ["."]
+ @spec.extensions << "extconf.rb"
- if File.exist?(path)
- puts File.read(path)
- puts '-' * 78
- end
+ File.write File.join(@tempdir, "extconf.rb"), <<-RUBY
+ require "mkmf"
+ CONFIG['CC'] = '$(TOUCH) $@ ||'
+ CONFIG['LDSHARED'] = '$(TOUCH) $@ ||'
+ $ruby = '#{Gem.ruby}'
+ create_makefile("#{@spec.name}")
+ RUBY
- raise
+ # empty depend file for no auto dependencies
+ @spec.files += %W[depend #{@spec.name}.c].each do |file|
+ write_file File.join(@tempdir, file)
end
+
+ shared_object = "#{@spec.name}.#{RbConfig::CONFIG["DLEXT"]}"
+ extension_file = File.join @spec.extension_dir, shared_object
+ intermediate_file = File.join @spec.gem_dir, shared_object
+
+ assert_path_not_exist extension_file, "no before installing"
+ use_ui @ui do
+ path = Gem::Package.build @spec
+
+ installer = Gem::Installer.at path
+ installer.install
+ end
+
+ assert_path_exist extension_file, "installed"
+ assert_path_not_exist intermediate_file
end
def test_installation_satisfies_dependency_eh
installer = setup_base_installer
- util_spec 'a'
+ util_spec "a"
- dep = Gem::Dependency.new 'a', '>= 2'
+ dep = Gem::Dependency.new "a", ">= 2"
assert installer.installation_satisfies_dependency?(dep)
- dep = Gem::Dependency.new 'a', '> 2'
+ dep = Gem::Dependency.new "a", "> 2"
refute installer.installation_satisfies_dependency?(dep)
end
@@ -1591,15 +1745,15 @@ gem 'other', version
installer.options[:development] = true
installer.options[:dev_shallow] = true
- util_spec 'a'
+ util_spec "a"
- dep = Gem::Dependency.new 'a', :development
+ dep = Gem::Dependency.new "a", :development
assert installer.installation_satisfies_dependency?(dep)
end
def test_pre_install_checks_dependencies
installer = setup_base_installer
- @spec.add_dependency 'b', '> 5'
+ @spec.add_dependency "b", "> 5"
installer = util_setup_gem
installer.force = false
@@ -1612,7 +1766,7 @@ gem 'other', version
def test_pre_install_checks_dependencies_ignore
installer = util_setup_installer
- @spec.add_dependency 'b', '> 5'
+ @spec.add_dependency "b", "> 5"
installer.ignore_dependencies = true
build_rake_in do
@@ -1626,22 +1780,22 @@ gem 'other', version
gemhome2 = "#{@gemhome}2"
@gem = setup_base_gem
- @spec.add_dependency 'd'
+ @spec.add_dependency "d"
- quick_gem 'd', 2
+ quick_gem "d", 2
gem = File.join @gemhome, @spec.file_name
FileUtils.mv @gemhome, gemhome2
FileUtils.mkdir @gemhome
- FileUtils.mv File.join(gemhome2, 'cache', @spec.file_name), gem
+ FileUtils.mv File.join(gemhome2, "cache", @spec.file_name), gem
# Don't leak any already activated gems into the installer, require
# that it work everything out on it's own.
Gem::Specification.reset
- installer = Gem::Installer.at gem, :install_dir => gemhome2
+ installer = Gem::Installer.at gem, install_dir: gemhome2
build_rake_in do
use_ui @ui do
@@ -1651,35 +1805,37 @@ gem 'other', version
end
def test_pre_install_checks_malicious_name
- spec = util_spec '../malicious', '1'
+ spec = util_spec "../malicious", "1"
def spec.full_name # so the spec is buildable
"malicious-1"
end
+
def spec.validate(packaging, strict); end
util_build_gem spec
- gem = File.join(@gemhome, 'cache', spec.file_name)
+ gem = File.join(@gemhome, "cache", spec.file_name)
use_ui @ui do
installer = Gem::Installer.at gem
e = assert_raise Gem::InstallError do
installer.pre_install_checks
end
- assert_equal '#<Gem::Specification name=../malicious version=1> has an invalid name', e.message
+ assert_equal "#<Gem::Specification name=../malicious version=1> has an invalid name", e.message
end
end
def test_pre_install_checks_malicious_name_before_eval
- spec = util_spec "malicious\n::Object.const_set(:FROM_EVAL, true)#", '1'
+ spec = util_spec "malicious\n::Object.const_set(:FROM_EVAL, true)#", "1"
def spec.full_name # so the spec is buildable
"malicious-1"
end
+
def spec.validate(*args); end
util_build_gem spec
- gem = File.join(@gemhome, 'cache', spec.file_name)
+ gem = File.join(@gemhome, "cache", spec.file_name)
use_ui @ui do
installer = Gem::Installer.at gem
@@ -1692,16 +1848,17 @@ gem 'other', version
end
def test_pre_install_checks_malicious_require_paths_before_eval
- spec = util_spec "malicious", '1'
+ spec = util_spec "malicious", "1"
def spec.full_name # so the spec is buildable
"malicious-1"
end
+
def spec.validate(*args); end
spec.require_paths = ["malicious\n``"]
util_build_gem spec
- gem = File.join(@gemhome, 'cache', spec.file_name)
+ gem = File.join(@gemhome, "cache", spec.file_name)
use_ui @ui do
installer = Gem::Installer.at gem
@@ -1715,16 +1872,17 @@ gem 'other', version
def test_pre_install_checks_malicious_extensions_before_eval
pend "mswin environment disallow to create file contained the carriage return code." if Gem.win_platform?
- spec = util_spec "malicious", '1'
+ spec = util_spec "malicious", "1"
def spec.full_name # so the spec is buildable
"malicious-1"
end
+
def spec.validate(*args); end
spec.extensions = ["malicious\n``"]
util_build_gem spec
- gem = File.join(@gemhome, 'cache', spec.file_name)
+ gem = File.join(@gemhome, "cache", spec.file_name)
use_ui @ui do
installer = Gem::Installer.at gem
@@ -1736,16 +1894,17 @@ gem 'other', version
end
def test_pre_install_checks_malicious_specification_version_before_eval
- spec = util_spec "malicious", '1'
+ spec = util_spec "malicious", "1"
def spec.full_name # so the spec is buildable
"malicious-1"
end
+
def spec.validate(*args); end
spec.specification_version = "malicious\n``"
util_build_gem spec
- gem = File.join(@gemhome, 'cache', spec.file_name)
+ gem = File.join(@gemhome, "cache", spec.file_name)
use_ui @ui do
installer = Gem::Installer.at gem
@@ -1757,16 +1916,17 @@ gem 'other', version
end
def test_pre_install_checks_malicious_dependencies_before_eval
- spec = util_spec "malicious", '1'
+ spec = util_spec "malicious", "1"
def spec.full_name # so the spec is buildable
"malicious-1"
end
+
def spec.validate(*args); end
- spec.add_dependency "b\nfoo", '> 5'
+ spec.add_dependency "b\nfoo", "> 5"
util_build_gem spec
- gem = File.join(@gemhome, 'cache', spec.file_name)
+ gem = File.join(@gemhome, "cache", spec.file_name)
use_ui @ui do
installer = Gem::Installer.at gem
@@ -1783,9 +1943,9 @@ gem 'other', version
installer = Gem::Installer.at(
gem_with_ill_formated_platform,
- :install_dir => @gem_home,
- :user_install => false,
- :force => true
+ install_dir: @gemhome,
+ user_install: false,
+ force: true
)
use_ui @ui do
@@ -1799,31 +1959,33 @@ gem 'other', version
end
def test_shebang
- installer = setup_base_installer
+ load_relative "no" do
+ installer = setup_base_installer
- util_make_exec @spec, "#!/usr/bin/ruby"
+ util_make_exec @spec, "#!/usr/bin/ruby"
- shebang = installer.shebang 'executable'
+ shebang = installer.shebang "executable"
- assert_equal "#!#{Gem.ruby}", shebang
+ assert_equal "#!#{Gem.ruby}", shebang
+ end
end
def test_process_options
installer = setup_base_installer
assert_nil installer.build_root
- assert_equal File.join(@gemhome, 'bin'), installer.bin_dir
+ assert_equal File.join(@gemhome, "bin"), installer.bin_dir
assert_equal @gemhome, installer.gem_home
end
def test_process_options_build_root
- build_root = File.join @tempdir, 'build_root'
- bin_dir = File.join(build_root, @gemhome.gsub(/^[a-zA-Z]:/, ''), 'bin')
- gem_home = File.join(build_root, @gemhome.gsub(/^[a-zA-Z]:/, ''))
- plugins_dir = File.join(build_root, @gemhome.gsub(/^[a-zA-Z]:/, ''), 'plugins')
+ build_root = File.join @tempdir, "build_root"
+ bin_dir = File.join(build_root, @gemhome.gsub(/^[a-zA-Z]:/, ""), "bin")
+ gem_home = File.join(build_root, @gemhome.gsub(/^[a-zA-Z]:/, ""))
+ plugins_dir = File.join(build_root, @gemhome.gsub(/^[a-zA-Z]:/, ""), "plugins")
@gem = setup_base_gem
- installer = use_ui(@ui) { Gem::Installer.at @gem, :build_root => build_root }
+ installer = use_ui(@ui) { Gem::Installer.at @gem, build_root: build_root }
assert_equal build_root, installer.build_root
assert_equal bin_dir, installer.bin_dir
@@ -1838,136 +2000,273 @@ gem 'other', version
assert_equal " Plugins dir: #{plugins_dir}", errors.shift
end
+ def test_process_options_fallback_to_user_install_when_gem_home_not_writable
+ if Process.uid.zero?
+ pend("skipped in root privilege")
+ return
+ end
+
+ orig_gem_home = ENV.delete("GEM_HOME")
+
+ @gem = setup_base_gem
+
+ FileUtils.chmod 0o000, @gemhome
+
+ installer = use_ui(@ui) { Gem::Installer.at @gem }
+
+ assert_equal Gem.user_dir, installer.gem_home
+ assert_equal "Defaulting to user installation because default installation directory (#{@gemhome}) is not writable.", @ui.output.strip
+ ensure
+ FileUtils.chmod 0o755, @gemhome
+ ENV["GEM_HOME"] = orig_gem_home
+ end
+
+ def test_process_options_does_not_fallback_to_user_install_when_gem_home_not_writable_and_no_user_install
+ if Process.uid.zero?
+ pend("skipped in root privilege")
+ return
+ end
+
+ orig_gem_home = ENV.delete("GEM_HOME")
+
+ @gem = setup_base_gem
+
+ FileUtils.chmod 0o000, @gemhome
+
+ installer = use_ui(@ui) { Gem::Installer.at @gem, user_install: false }
+
+ assert_equal @gemhome, installer.gem_home
+ assert_empty @ui.output.strip
+ ensure
+ FileUtils.chmod 0o755, @gemhome
+ ENV["GEM_HOME"] = orig_gem_home
+ end
+
def test_shebang_arguments
- installer = setup_base_installer
+ load_relative "no" do
+ installer = setup_base_installer
- util_make_exec @spec, "#!/usr/bin/ruby -ws"
+ util_make_exec @spec, "#!/usr/bin/ruby -ws"
+
+ shebang = installer.shebang "executable"
+
+ assert_equal "#!#{Gem.ruby} -ws", shebang
+ end
+ end
+
+ def test_shebang_arguments_with_load_relative
+ load_relative "yes" do
+ installer = setup_base_installer
+
+ util_make_exec @spec, "#!/usr/bin/ruby -ws"
- shebang = installer.shebang 'executable'
+ shebang = installer.shebang "executable"
- assert_equal "#!#{Gem.ruby} -ws", shebang
+ shebang_lines = shebang.split "\n"
+
+ assert_equal "#!/bin/sh", shebang_lines.shift
+ assert_includes shebang_lines, "#!#{Gem.ruby} -ws"
+ end
end
def test_shebang_empty
- installer = setup_base_installer
+ load_relative "no" do
+ installer = setup_base_installer
- util_make_exec @spec, ''
+ util_make_exec @spec, ""
- shebang = installer.shebang 'executable'
- assert_equal "#!#{Gem.ruby}", shebang
+ shebang = installer.shebang "executable"
+ assert_equal "#!#{Gem.ruby}", shebang
+ end
end
def test_shebang_env
- installer = setup_base_installer
+ load_relative "no" do
+ installer = setup_base_installer
- util_make_exec @spec, "#!/usr/bin/env ruby"
+ util_make_exec @spec, "#!/usr/bin/env ruby"
- shebang = installer.shebang 'executable'
+ shebang = installer.shebang "executable"
- assert_equal "#!#{Gem.ruby}", shebang
+ assert_equal "#!#{Gem.ruby}", shebang
+ end
end
def test_shebang_env_arguments
- installer = setup_base_installer
+ load_relative "no" do
+ installer = setup_base_installer
- util_make_exec @spec, "#!/usr/bin/env ruby -ws"
+ util_make_exec @spec, "#!/usr/bin/env ruby -ws"
- shebang = installer.shebang 'executable'
+ shebang = installer.shebang "executable"
- assert_equal "#!#{Gem.ruby} -ws", shebang
+ assert_equal "#!#{Gem.ruby} -ws", shebang
+ end
+ end
+
+ def test_shebang_env_arguments_with_load_relative
+ load_relative "yes" do
+ installer = setup_base_installer
+
+ util_make_exec @spec, "#!/usr/bin/env ruby -ws"
+
+ shebang = installer.shebang "executable"
+
+ shebang_lines = shebang.split "\n"
+
+ assert_equal "#!/bin/sh", shebang_lines.shift
+ assert_includes shebang_lines, "#!#{Gem.ruby} -ws"
+ end
end
def test_shebang_env_shebang
installer = setup_base_installer
- util_make_exec @spec, ''
+ util_make_exec @spec, ""
installer.env_shebang = true
- shebang = installer.shebang 'executable'
+ shebang = installer.shebang "executable"
bin_env = get_bin_env
- assert_equal("#!#{bin_env} #{RbConfig::CONFIG['ruby_install_name']}",
+ assert_equal("#!#{bin_env} #{RbConfig::CONFIG["ruby_install_name"]}",
shebang)
end
def test_shebang_nested
- installer = setup_base_installer
+ load_relative "no" do
+ installer = setup_base_installer
- util_make_exec @spec, "#!/opt/local/ruby/bin/ruby"
+ util_make_exec @spec, "#!/opt/local/ruby/bin/ruby"
- shebang = installer.shebang 'executable'
+ shebang = installer.shebang "executable"
- assert_equal "#!#{Gem.ruby}", shebang
+ assert_equal "#!#{Gem.ruby}", shebang
+ end
end
def test_shebang_nested_arguments
- installer = setup_base_installer
+ load_relative "no" do
+ installer = setup_base_installer
+
+ util_make_exec @spec, "#!/opt/local/ruby/bin/ruby -ws"
+
+ shebang = installer.shebang "executable"
- util_make_exec @spec, "#!/opt/local/ruby/bin/ruby -ws"
+ assert_equal "#!#{Gem.ruby} -ws", shebang
+ end
+ end
+
+ def test_shebang_nested_arguments_with_load_relative
+ load_relative "yes" do
+ installer = setup_base_installer
+
+ util_make_exec @spec, "#!/opt/local/ruby/bin/ruby -ws"
- shebang = installer.shebang 'executable'
+ shebang = installer.shebang "executable"
- assert_equal "#!#{Gem.ruby} -ws", shebang
+ shebang_lines = shebang.split "\n"
+
+ assert_equal "#!/bin/sh", shebang_lines.shift
+ assert_includes shebang_lines, "#!#{Gem.ruby} -ws"
+ end
end
def test_shebang_version
- installer = setup_base_installer
+ load_relative "no" do
+ installer = setup_base_installer
- util_make_exec @spec, "#!/usr/bin/ruby18"
+ util_make_exec @spec, "#!/usr/bin/ruby18"
- shebang = installer.shebang 'executable'
+ shebang = installer.shebang "executable"
- assert_equal "#!#{Gem.ruby}", shebang
+ assert_equal "#!#{Gem.ruby}", shebang
+ end
end
def test_shebang_version_arguments
- installer = setup_base_installer
+ load_relative "no" do
+ installer = setup_base_installer
+
+ util_make_exec @spec, "#!/usr/bin/ruby18 -ws"
+
+ shebang = installer.shebang "executable"
+
+ assert_equal "#!#{Gem.ruby} -ws", shebang
+ end
+ end
- util_make_exec @spec, "#!/usr/bin/ruby18 -ws"
+ def test_shebang_version_arguments_with_load_relative
+ load_relative "yes" do
+ installer = setup_base_installer
- shebang = installer.shebang 'executable'
+ util_make_exec @spec, "#!/usr/bin/ruby18 -ws"
- assert_equal "#!#{Gem.ruby} -ws", shebang
+ shebang = installer.shebang "executable"
+
+ shebang_lines = shebang.split "\n"
+
+ assert_equal "#!/bin/sh", shebang_lines.shift
+ assert_includes shebang_lines, "#!#{Gem.ruby} -ws"
+ end
end
def test_shebang_version_env
- installer = setup_base_installer
+ load_relative "no" do
+ installer = setup_base_installer
- util_make_exec @spec, "#!/usr/bin/env ruby18"
+ util_make_exec @spec, "#!/usr/bin/env ruby18"
- shebang = installer.shebang 'executable'
+ shebang = installer.shebang "executable"
- assert_equal "#!#{Gem.ruby}", shebang
+ assert_equal "#!#{Gem.ruby}", shebang
+ end
end
def test_shebang_version_env_arguments
- installer = setup_base_installer
+ load_relative "no" do
+ installer = setup_base_installer
+
+ util_make_exec @spec, "#!/usr/bin/env ruby18 -ws"
- util_make_exec @spec, "#!/usr/bin/env ruby18 -ws"
+ shebang = installer.shebang "executable"
- shebang = installer.shebang 'executable'
+ assert_equal "#!#{Gem.ruby} -ws", shebang
+ end
+ end
+
+ def test_shebang_version_env_arguments_with_load_relative
+ load_relative "yes" do
+ installer = setup_base_installer
+
+ util_make_exec @spec, "#!/usr/bin/env ruby18 -ws"
- assert_equal "#!#{Gem.ruby} -ws", shebang
+ shebang = installer.shebang "executable"
+
+ shebang_lines = shebang.split "\n"
+
+ assert_equal "#!/bin/sh", shebang_lines.shift
+ assert_includes shebang_lines, "#!#{Gem.ruby} -ws"
+ end
end
def test_shebang_custom
installer = setup_base_installer
conf = Gem::ConfigFile.new []
- conf[:custom_shebang] = 'test'
+ conf[:custom_shebang] = "test"
Gem.configuration = conf
util_make_exec @spec, "#!/usr/bin/ruby"
- shebang = installer.shebang 'executable'
+ shebang = installer.shebang "executable"
assert_equal "#!test", shebang
end
def get_bin_env
- if win_platform?
+ if Gem.win_platform?
""
else
%w[/usr/bin/env /bin/env].find {|f| File.executable?(f) }
@@ -1979,13 +2278,13 @@ gem 'other', version
bin_env = get_bin_env
conf = Gem::ConfigFile.new []
- conf[:custom_shebang] = '1 $env 2 $ruby 3 $exec 4 $name'
+ conf[:custom_shebang] = "1 $env 2 $ruby 3 $exec 4 $name"
Gem.configuration = conf
util_make_exec @spec, "#!/usr/bin/ruby"
- shebang = installer.shebang 'executable'
+ shebang = installer.shebang "executable"
assert_equal "#!1 #{bin_env} 2 #{Gem.ruby} 3 executable 4 a", shebang
end
@@ -1995,13 +2294,13 @@ gem 'other', version
bin_env = get_bin_env
conf = Gem::ConfigFile.new []
- conf[:custom_shebang] = '1 $env 2 $ruby 3 $exec'
+ conf[:custom_shebang] = "1 $env 2 $ruby 3 $exec"
Gem.configuration = conf
util_make_exec @spec, "#!/usr/bin/ruby -ws"
- shebang = installer.shebang 'executable'
+ shebang = installer.shebang "executable"
assert_equal "#!1 #{bin_env} 2 #{Gem.ruby} -ws 3 executable", shebang
end
@@ -2009,14 +2308,14 @@ gem 'other', version
def test_unpack
installer = util_setup_installer
- dest = File.join @gemhome, 'gems', @spec.full_name
+ dest = File.join @gemhome, "gems", @spec.full_name
Gem::Deprecate.skip_during do
installer.unpack dest
end
- assert_path_exist File.join dest, 'lib', 'code.rb'
- assert_path_exist File.join dest, 'bin', 'executable'
+ assert_path_exist File.join dest, "lib", "code.rb"
+ assert_path_exist File.join dest, "bin", "executable"
end
def test_write_build_info_file
@@ -2049,7 +2348,7 @@ gem 'other', version
def test_write_build_info_file_install_dir
@gem = setup_base_gem
- installer = Gem::Installer.at @gem, :install_dir => "#{@gemhome}2"
+ installer = Gem::Installer.at @gem, install_dir: "#{@gemhome}2"
installer.build_args = %w[
--with-libyaml-dir /usr/local/Cellar/libyaml/0.1.4
@@ -2059,12 +2358,12 @@ gem 'other', version
assert_path_not_exist @spec.build_info_file
assert_path_exist \
- File.join("#{@gemhome}2", 'build_info', "#{@spec.full_name}.info")
+ File.join("#{@gemhome}2", "build_info", "#{@spec.full_name}.info")
end
def test_write_cache_file
@gem = setup_base_gem
- cache_file = File.join @gemhome, 'cache', @spec.file_name
+ cache_file = File.join @gemhome, "cache", @spec.file_name
gem = File.join @gemhome, @spec.file_name
FileUtils.mv cache_file, gem
@@ -2115,6 +2414,37 @@ gem 'other', version
assert_equal @spec, eval(File.read(@spec.spec_file))
end
+ def test_leaves_no_empty_cached_spec_when_no_more_disk_space
+ @spec = setup_base_spec
+ FileUtils.rm @spec.spec_file
+ assert_path_not_exist @spec.spec_file
+
+ @spec.files = %w[a.rb b.rb c.rb]
+
+ installer = Gem::Installer.for_spec @spec
+ installer.gem_home = @gemhome
+
+ File.singleton_class.class_eval do
+ alias_method :original_binwrite, :binwrite
+
+ def binwrite(path, data)
+ raise Errno::ENOSPC
+ end
+ end
+
+ assert_raise Errno::ENOSPC do
+ installer.write_spec
+ end
+
+ assert_path_not_exist @spec.spec_file
+ ensure
+ File.singleton_class.class_eval do
+ remove_method :binwrite
+ alias_method :binwrite, :original_binwrite
+ remove_method :original_binwrite
+ end
+ end
+
def test_dir
installer = setup_base_installer
@@ -2122,8 +2452,8 @@ gem 'other', version
end
def test_default_gem_loaded_from
- spec = util_spec 'a'
- installer = Gem::Installer.for_spec spec, :install_as_default => true
+ spec = util_spec "a"
+ installer = Gem::Installer.for_spec spec, install_as_default: true
installer.install
assert_predicate spec, :default_gem?
end
@@ -2131,7 +2461,7 @@ gem 'other', version
def test_default_gem_without_wrappers
installer = setup_base_installer
- FileUtils.rm_f File.join(Gem.dir, 'specifications')
+ FileUtils.rm_rf File.join(Gem.default_dir, "specifications")
installer.wrappers = false
installer.options[:install_as_default] = true
@@ -2141,29 +2471,29 @@ gem 'other', version
installer.install
end
- assert_directory_exists File.join(@spec.gem_dir, 'bin')
- installed_exec = File.join @spec.gem_dir, 'bin', 'executable'
+ assert_directory_exists File.join(@spec.gem_dir, "bin")
+ installed_exec = File.join @spec.gem_dir, "bin", "executable"
assert_path_exist installed_exec
- assert_directory_exists File.join(Gem.default_dir, 'specifications')
- assert_directory_exists File.join(Gem.default_dir, 'specifications', 'default')
+ assert_directory_exists File.join(Gem.default_dir, "specifications")
+ assert_directory_exists File.join(Gem.default_dir, "specifications", "default")
- default_spec = eval File.read File.join(Gem.default_dir, 'specifications', 'default', 'a-2.gemspec')
+ default_spec = eval File.read File.join(Gem.default_dir, "specifications", "default", "a-2.gemspec")
assert_equal Gem::Version.new("2"), default_spec.version
- assert_equal ['bin/executable'], default_spec.files
+ assert_equal ["bin/executable"], default_spec.files
assert_directory_exists util_inst_bindir
- installed_exec = File.join util_inst_bindir, 'executable'
+ installed_exec = File.join util_inst_bindir, "executable"
assert_path_exist installed_exec
wrapper = File.read installed_exec
if symlink_supported?
- refute_match %r{generated by RubyGems}, wrapper
+ refute_match(/generated by RubyGems/, wrapper)
else # when symlink not supported, it warns and fallbacks back to installing wrapper
- assert_match %r{Unable to use symlinks, installing wrapper}, @ui.error
- assert_match %r{generated by RubyGems}, wrapper
+ assert_match(/Unable to use symlinks, installing wrapper/, @ui.error)
+ assert_match(/generated by RubyGems/, wrapper)
end
end
@@ -2180,16 +2510,16 @@ gem 'other', version
assert_directory_exists util_inst_bindir
- installed_exec = File.join util_inst_bindir, 'executable'
+ installed_exec = File.join util_inst_bindir, "executable"
assert_path_exist installed_exec
wrapper = File.read installed_exec
- assert_match %r{generated by RubyGems}, wrapper
+ assert_match(/generated by RubyGems/, wrapper)
end
def test_default_gem_with_exe_as_bindir
- @spec = quick_gem 'c' do |spec|
- util_make_exec spec, '#!/usr/bin/ruby', 'exe'
+ @spec = quick_gem "c" do |spec|
+ util_make_exec spec, "#!/usr/bin/ruby", "exe"
end
util_build_gem @spec
@@ -2205,16 +2535,16 @@ gem 'other', version
installer.install
end
- assert_directory_exists File.join(@spec.gem_dir, 'exe')
- installed_exec = File.join @spec.gem_dir, 'exe', 'executable'
+ assert_directory_exists File.join(@spec.gem_dir, "exe")
+ installed_exec = File.join @spec.gem_dir, "exe", "executable"
assert_path_exist installed_exec
- assert_directory_exists File.join(Gem.default_dir, 'specifications')
- assert_directory_exists File.join(Gem.default_dir, 'specifications', 'default')
+ assert_directory_exists File.join(Gem.default_dir, "specifications")
+ assert_directory_exists File.join(Gem.default_dir, "specifications", "default")
- default_spec = eval File.read File.join(Gem.default_dir, 'specifications', 'default', 'c-2.gemspec')
+ default_spec = eval File.read File.join(Gem.default_dir, "specifications", "default", "c-2.gemspec")
assert_equal Gem::Version.new("2"), default_spec.version
- assert_equal ['exe/executable'], default_spec.files
+ assert_equal ["exe/executable"], default_spec.files
end
def test_default_gem_to_specific_install_dir
@@ -2226,17 +2556,17 @@ gem 'other', version
installer.install
end
- assert_directory_exists File.join("#{@gemhome}2", 'specifications')
- assert_directory_exists File.join("#{@gemhome}2", 'specifications', 'default')
+ assert_directory_exists File.join("#{@gemhome}2", "specifications")
+ assert_directory_exists File.join("#{@gemhome}2", "specifications", "default")
- default_spec = eval File.read File.join("#{@gemhome}2", 'specifications', 'default', 'a-2.gemspec')
+ default_spec = eval File.read File.join("#{@gemhome}2", "specifications", "default", "a-2.gemspec")
assert_equal Gem::Version.new("2"), default_spec.version
- assert_equal ['bin/executable'], default_spec.files
+ assert_equal ["bin/executable"], default_spec.files
end
def test_package_attribute
- gem = quick_gem 'c' do |spec|
- util_make_exec spec, '#!/usr/bin/ruby', 'exe'
+ gem = quick_gem "c" do |spec|
+ util_make_exec spec, "#!/usr/bin/ruby", "exe"
end
installer = util_installer(gem, @gemhome)
@@ -2245,8 +2575,8 @@ gem 'other', version
end
def test_gem_attribute
- gem = quick_gem 'c' do |spec|
- util_make_exec spec, '#!/usr/bin/ruby', 'exe'
+ gem = quick_gem "c" do |spec|
+ util_make_exec spec, "#!/usr/bin/ruby", "exe"
end
installer = util_installer(gem, @gemhome)
@@ -2254,15 +2584,17 @@ gem 'other', version
assert_kind_of(String, installer.gem)
end
+ private
+
def util_execless
- @spec = util_spec 'z'
+ @spec = util_spec "z"
util_build_gem @spec
util_installer @spec, @gemhome
end
def util_conflict_executable(wrappers)
- conflict = quick_gem 'conflict' do |spec|
+ conflict = quick_gem "conflict" do |spec|
util_make_exec spec
end
@@ -2274,6 +2606,16 @@ gem 'other', version
end
def mask
- 0100755
+ 0o100755
+ end
+
+ def load_relative(value)
+ orig_libruby_relative = RbConfig::CONFIG["LIBRUBY_RELATIVE"]
+ RbConfig::CONFIG["LIBRUBY_RELATIVE"] = value
+
+ yield
+ ensure
+ # RbConfig::CONFIG values are strings only, there should not be a nil.
+ RbConfig::CONFIG["LIBRUBY_RELATIVE"] = orig_libruby_relative if orig_libruby_relative
end
end
diff --git a/test/rubygems/test_gem_local_remote_options.rb b/test/rubygems/test_gem_local_remote_options.rb
index 948d1e3981..cea9cde82b 100644
--- a/test/rubygems/test_gem_local_remote_options.rb
+++ b/test/rubygems/test_gem_local_remote_options.rb
@@ -1,13 +1,14 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/local_remote_options'
-require 'rubygems/command'
+
+require_relative "helper"
+require "rubygems/local_remote_options"
+require "rubygems/command"
class TestGemLocalRemoteOptions < Gem::TestCase
def setup
super
- @cmd = Gem::Command.new 'dummy', 'dummy'
+ @cmd = Gem::Command.new "dummy", "dummy"
@cmd.extend Gem::LocalRemoteOptions
end
@@ -33,7 +34,7 @@ class TestGemLocalRemoteOptions < Gem::TestCase
def test_clear_sources_option
@cmd.add_local_remote_options
- s = URI.parse "http://only-gems.example.com/"
+ s = Gem::URI.parse "http://only-gems.example.com/"
@cmd.handle_options %W[--clear-sources --source #{s}]
assert_equal [s.to_s], Gem.sources
@@ -75,10 +76,10 @@ class TestGemLocalRemoteOptions < Gem::TestCase
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'
- s4 = URI.parse 'http://more-gems.example.com/' # Intentional duplicate
+ s1 = Gem::URI.parse "http://more-gems.example.com/"
+ s2 = Gem::URI.parse "http://even-more-gems.example.com/"
+ s3 = Gem::URI.parse "http://other-gems.example.com/some_subdir"
+ s4 = Gem::URI.parse "http://more-gems.example.com/" # Intentional duplicate
original_sources = Gem.sources.dup
@@ -96,7 +97,7 @@ class TestGemLocalRemoteOptions < Gem::TestCase
original_sources = Gem.sources.dup
- source = URI.parse 'http://more-gems.example.com/'
+ source = Gem::URI.parse "http://more-gems.example.com/"
@cmd.handle_options %W[-s #{source}]
original_sources << source
@@ -121,7 +122,7 @@ class TestGemLocalRemoteOptions < Gem::TestCase
def test_source_option_bad
@cmd.add_source_option
- s1 = 'htp://more-gems.example.com'
+ s1 = "htp://more-gems.example.com"
assert_raise ArgumentError do
@cmd.handle_options %W[--source #{s1}]
diff --git a/test/rubygems/test_gem_name_tuple.rb b/test/rubygems/test_gem_name_tuple.rb
index d87db9bc45..bdb8181ce8 100644
--- a/test/rubygems/test_gem_name_tuple.rb
+++ b/test/rubygems/test_gem_name_tuple.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/name_tuple'
+
+require_relative "helper"
+require "rubygems/name_tuple"
class TestGemNameTuple < Gem::TestCase
def test_full_name
@@ -18,14 +19,31 @@ class TestGemNameTuple < Gem::TestCase
end
def test_platform_normalization
- n = Gem::NameTuple.new "a", Gem::Version.new(0), "ruby"
- assert_equal "ruby", n.platform
-
- n = Gem::NameTuple.new "a", Gem::Version.new(0), nil
- assert_equal "ruby", n.platform
-
- n = Gem::NameTuple.new "a", Gem::Version.new(0), ""
- assert_equal "ruby", n.platform
+ a = Gem::NameTuple.new "a", Gem::Version.new(0), "ruby"
+ b = Gem::NameTuple.new "a", Gem::Version.new(0), Gem::Platform::RUBY
+ assert_equal a, b
+ assert_equal a.hash, b.hash
+
+ a = Gem::NameTuple.new "a", Gem::Version.new(0), nil
+ b = Gem::NameTuple.new "a", Gem::Version.new(0), Gem::Platform.new("ruby")
+ assert_equal a, b
+ assert_equal a.hash, b.hash
+
+ a = Gem::NameTuple.new "a", Gem::Version.new(0), ""
+ b = Gem::NameTuple.new "a", Gem::Version.new(0), Gem::Platform.new("ruby")
+ assert_equal a, b
+ assert_equal a.hash, b.hash
+
+ a = Gem::NameTuple.new "a", Gem::Version.new(0), "universal-darwin-23"
+ b = Gem::NameTuple.new "a", Gem::Version.new(0), Gem::Platform.new("universal-darwin-23")
+ assert_equal a, b
+ assert_equal a.hash, b.hash
+
+ # Gem::Platform does normalization so that these are equal (note the missing dash before 21)
+ a = Gem::NameTuple.new "a", Gem::Version.new(0), "universal-darwin-21"
+ b = Gem::NameTuple.new "a", Gem::Version.new(0), Gem::Platform.new("universal-darwin21")
+ assert_equal a, b
+ assert_equal a.hash, b.hash
end
def test_spec_name
@@ -34,8 +52,8 @@ class TestGemNameTuple < Gem::TestCase
end
def test_spaceship
- a = Gem::NameTuple.new 'a', Gem::Version.new(0), Gem::Platform::RUBY
- a_p = Gem::NameTuple.new 'a', Gem::Version.new(0), Gem::Platform.local
+ a = Gem::NameTuple.new "a", Gem::Version.new(0), Gem::Platform::RUBY
+ a_p = Gem::NameTuple.new "a", Gem::Version.new(0), Gem::Platform.local
assert_equal 1, a_p.<=>(a)
end
diff --git a/test/rubygems/test_gem_package.rb b/test/rubygems/test_gem_package.rb
index 3fa2c1911c..2065864107 100644
--- a/test/rubygems/test_gem_package.rb
+++ b/test/rubygems/test_gem_package.rb
@@ -1,14 +1,14 @@
# frozen_string_literal: true
-require_relative 'package/tar_test_case'
-require 'digest'
+require_relative "package/tar_test_case"
+require "rubygems/openssl"
class TestGemPackage < Gem::Package::TarTestCase
def setup
super
- @spec = quick_gem 'a' do |s|
- s.description = 'Ï€'
+ @spec = quick_gem "a" do |s|
+ s.description = "Ï€"
s.files = %w[lib/code.rb]
end
@@ -16,7 +16,7 @@ class TestGemPackage < Gem::Package::TarTestCase
@gem = @spec.cache_file
- @destination = File.join @tempdir, 'extract'
+ @destination = File.join @tempdir, "extract"
FileUtils.mkdir_p @destination
end
@@ -24,11 +24,11 @@ class TestGemPackage < Gem::Package::TarTestCase
def test_class_new_old_format
pend "jruby can't require the simple_gem file" if Gem.java_platform?
require_relative "simple_gem"
- File.open 'old_format.gem', 'wb' do |io|
+ File.open "old_format.gem", "wb" do |io|
io.write SIMPLE_GEM
end
- package = Gem::Package.new 'old_format.gem'
+ package = Gem::Package.new "old_format.gem"
assert package.spec
end
@@ -36,17 +36,17 @@ class TestGemPackage < Gem::Package::TarTestCase
def test_add_checksums
gem_io = StringIO.new
- spec = Gem::Specification.new 'build', '1'
- spec.summary = 'build'
- spec.authors = 'build'
- spec.files = ['lib/code.rb']
+ spec = Gem::Specification.new "build", "1"
+ spec.summary = "build"
+ spec.authors = "build"
+ spec.files = ["lib/code.rb"]
spec.date = Time.at 0
- spec.rubygems_version = Gem::Version.new '0'
+ spec.rubygems_version = Gem::Version.new "0"
- FileUtils.mkdir 'lib'
+ FileUtils.mkdir "lib"
- File.open 'lib/code.rb', 'w' do |io|
- io.write '# lib/code.rb'
+ File.open "lib/code.rb", "w" do |io|
+ io.write "# lib/code.rb"
end
package = Gem::Package.new spec.file_name
@@ -69,11 +69,11 @@ class TestGemPackage < Gem::Package::TarTestCase
reader.each_entry do |entry|
case entry.full_name
- when 'checksums.yaml.gz' then
+ when "checksums.yaml.gz" then
Zlib::GzipReader.wrap entry do |io|
checksums = io.read
end
- when 'data.tar.gz' then
+ when "data.tar.gz" then
tar = entry.read
end
end
@@ -84,17 +84,17 @@ class TestGemPackage < Gem::Package::TarTestCase
io.write spec.to_yaml
end
- metadata_sha256 = Digest::SHA256.hexdigest s.string
- metadata_sha512 = Digest::SHA512.hexdigest s.string
+ metadata_sha256 = OpenSSL::Digest::SHA256.hexdigest s.string
+ metadata_sha512 = OpenSSL::Digest::SHA512.hexdigest s.string
expected = {
- 'SHA512' => {
- 'metadata.gz' => metadata_sha512,
- 'data.tar.gz' => Digest::SHA512.hexdigest(tar),
+ "SHA512" => {
+ "metadata.gz" => metadata_sha512,
+ "data.tar.gz" => OpenSSL::Digest::SHA512.hexdigest(tar),
},
- 'SHA256' => {
- 'metadata.gz' => metadata_sha256,
- 'data.tar.gz' => Digest::SHA256.hexdigest(tar),
+ "SHA256" => {
+ "metadata.gz" => metadata_sha256,
+ "data.tar.gz" => OpenSSL::Digest::SHA256.hexdigest(tar),
},
}
@@ -105,12 +105,12 @@ class TestGemPackage < Gem::Package::TarTestCase
epoch = ENV["SOURCE_DATE_EPOCH"]
ENV["SOURCE_DATE_EPOCH"] = "123456789"
- spec = Gem::Specification.new 'build', '1'
- spec.summary = 'build'
- spec.authors = 'build'
- spec.files = ['lib/code.rb']
+ spec = Gem::Specification.new "build", "1"
+ spec.summary = "build"
+ spec.authors = "build"
+ spec.files = ["lib/code.rb"]
spec.date = Time.at 0
- spec.rubygems_version = Gem::Version.new '0'
+ spec.rubygems_version = Gem::Version.new "0"
package = Gem::Package.new spec.file_name
@@ -123,11 +123,11 @@ class TestGemPackage < Gem::Package::TarTestCase
epoch = ENV["SOURCE_DATE_EPOCH"]
ENV["SOURCE_DATE_EPOCH"] = nil
- spec = Gem::Specification.new 'build', '1'
- spec.summary = 'build'
- spec.authors = 'build'
- spec.files = ['lib/code.rb']
- spec.rubygems_version = Gem::Version.new '0'
+ spec = Gem::Specification.new "build", "1"
+ spec.summary = "build"
+ spec.authors = "build"
+ spec.files = ["lib/code.rb"]
+ spec.rubygems_version = Gem::Version.new "0"
package = Gem::Package.new spec.file_name
@@ -144,17 +144,17 @@ class TestGemPackage < Gem::Package::TarTestCase
spec = Gem::Specification.new
spec.files = %w[lib/code.rb lib/empty]
- FileUtils.mkdir_p 'lib/empty'
+ FileUtils.mkdir_p "lib/empty"
- File.open 'lib/code.rb', 'w' do |io|
- io.write '# lib/code.rb'
+ File.open "lib/code.rb", "w" do |io|
+ io.write "# lib/code.rb"
end
- File.open 'lib/extra.rb', 'w' do |io|
- io.write '# lib/extra.rb'
+ File.open "lib/extra.rb", "w" do |io|
+ io.write "# lib/extra.rb"
end
- package = Gem::Package.new 'bogus.gem'
+ package = Gem::Package.new "bogus.gem"
package.spec = spec
tar = util_tar do |tar_io|
@@ -178,25 +178,25 @@ class TestGemPackage < Gem::Package::TarTestCase
spec = Gem::Specification.new
spec.files = %w[lib/code.rb lib/code_sym.rb lib/code_sym2.rb]
- FileUtils.mkdir_p 'lib'
+ FileUtils.mkdir_p "lib"
- File.open 'lib/code.rb', 'w' do |io|
- io.write '# lib/code.rb'
+ File.open "lib/code.rb", "w" do |io|
+ io.write "# lib/code.rb"
end
# NOTE: 'code.rb' is correct, because it's relative to lib/code_sym.rb
begin
- File.symlink('code.rb', 'lib/code_sym.rb')
- File.symlink('../lib/code.rb', 'lib/code_sym2.rb')
+ File.symlink("code.rb", "lib/code_sym.rb")
+ File.symlink("../lib/code.rb", "lib/code_sym2.rb")
rescue Errno::EACCES => e
- if win_platform?
+ if Gem.win_platform?
pend "symlink - must be admin with no UAC on Windows"
else
raise e
end
end
- package = Gem::Package.new 'bogus.gem'
+ package = Gem::Package.new "bogus.gem"
package.spec = spec
tar = util_tar do |tar_io|
@@ -205,7 +205,8 @@ class TestGemPackage < Gem::Package::TarTestCase
tar.rewind
- files, symlinks = [], []
+ files = []
+ symlinks = []
Gem::Package::TarReader.new tar do |tar_io|
tar_io.each_entry do |entry|
@@ -218,20 +219,20 @@ class TestGemPackage < Gem::Package::TarTestCase
end
assert_equal %w[lib/code.rb], files
- assert_equal [{'lib/code_sym.rb' => 'code.rb'}, {'lib/code_sym2.rb' => '../lib/code.rb'}], symlinks
+ assert_equal [{ "lib/code_sym.rb" => "code.rb" }, { "lib/code_sym2.rb" => "../lib/code.rb" }], symlinks
end
def test_build
- spec = Gem::Specification.new 'build', '1'
- spec.summary = 'build'
- spec.authors = 'build'
- spec.files = ['lib/code.rb']
+ spec = Gem::Specification.new "build", "1"
+ spec.summary = "build"
+ spec.authors = "build"
+ spec.files = ["lib/code.rb"]
spec.rubygems_version = :junk
- FileUtils.mkdir 'lib'
+ FileUtils.mkdir "lib"
- File.open 'lib/code.rb', 'w' do |io|
- io.write '# lib/code.rb'
+ File.open "lib/code.rb", "w" do |io|
+ io.write "# lib/code.rb"
end
package = Gem::Package.new spec.file_name
@@ -252,25 +253,25 @@ class TestGemPackage < Gem::Package::TarTestCase
end
def test_build_auto_signed
- pend 'openssl is missing' unless Gem::HAVE_OPENSSL
+ pend "openssl is missing" unless Gem::HAVE_OPENSSL
- FileUtils.mkdir_p File.join(Gem.user_home, '.gem')
+ FileUtils.mkdir_p File.join(Gem.user_home, ".gem")
- private_key_path = File.join Gem.user_home, '.gem', 'gem-private_key.pem'
+ private_key_path = File.join Gem.user_home, ".gem", "gem-private_key.pem"
Gem::Security.write PRIVATE_KEY, private_key_path
- public_cert_path = File.join Gem.user_home, '.gem', 'gem-public_cert.pem'
+ public_cert_path = File.join Gem.user_home, ".gem", "gem-public_cert.pem"
FileUtils.cp PUBLIC_CERT_PATH, public_cert_path
- spec = Gem::Specification.new 'build', '1'
- spec.summary = 'build'
- spec.authors = 'build'
- spec.files = ['lib/code.rb']
+ spec = Gem::Specification.new "build", "1"
+ spec.summary = "build"
+ spec.authors = "build"
+ spec.files = ["lib/code.rb"]
- FileUtils.mkdir 'lib'
+ FileUtils.mkdir "lib"
- File.open 'lib/code.rb', 'w' do |io|
- io.write '# lib/code.rb'
+ File.open "lib/code.rb", "w" do |io|
+ io.write "# lib/code.rb"
end
package = Gem::Package.new spec.file_name
@@ -286,8 +287,8 @@ class TestGemPackage < Gem::Package::TarTestCase
assert_equal [PUBLIC_CERT.to_pem], reader.spec.cert_chain
- assert_equal %w[metadata.gz metadata.gz.sig
- data.tar.gz data.tar.gz.sig
+ assert_equal %w[metadata.gz metadata.gz.sig
+ data.tar.gz data.tar.gz.sig
checksums.yaml.gz checksums.yaml.gz.sig],
reader.files
@@ -295,25 +296,25 @@ class TestGemPackage < Gem::Package::TarTestCase
end
def test_build_auto_signed_encrypted_key
- pend 'openssl is missing' unless Gem::HAVE_OPENSSL
+ pend "openssl is missing" unless Gem::HAVE_OPENSSL
- FileUtils.mkdir_p File.join(Gem.user_home, '.gem')
+ FileUtils.mkdir_p File.join(Gem.user_home, ".gem")
- private_key_path = File.join Gem.user_home, '.gem', 'gem-private_key.pem'
+ private_key_path = File.join Gem.user_home, ".gem", "gem-private_key.pem"
FileUtils.cp ENCRYPTED_PRIVATE_KEY_PATH, private_key_path
- public_cert_path = File.join Gem.user_home, '.gem', 'gem-public_cert.pem'
+ public_cert_path = File.join Gem.user_home, ".gem", "gem-public_cert.pem"
Gem::Security.write PUBLIC_CERT, public_cert_path
- spec = Gem::Specification.new 'build', '1'
- spec.summary = 'build'
- spec.authors = 'build'
- spec.files = ['lib/code.rb']
+ spec = Gem::Specification.new "build", "1"
+ spec.summary = "build"
+ spec.authors = "build"
+ spec.files = ["lib/code.rb"]
- FileUtils.mkdir 'lib'
+ FileUtils.mkdir "lib"
- File.open 'lib/code.rb', 'w' do |io|
- io.write '# lib/code.rb'
+ File.open "lib/code.rb", "w" do |io|
+ io.write "# lib/code.rb"
end
package = Gem::Package.new spec.file_name
@@ -329,8 +330,8 @@ class TestGemPackage < Gem::Package::TarTestCase
assert_equal [PUBLIC_CERT.to_pem], reader.spec.cert_chain
- assert_equal %w[metadata.gz metadata.gz.sig
- data.tar.gz data.tar.gz.sig
+ assert_equal %w[metadata.gz metadata.gz.sig
+ data.tar.gz data.tar.gz.sig
checksums.yaml.gz checksums.yaml.gz.sig],
reader.files
@@ -338,7 +339,7 @@ class TestGemPackage < Gem::Package::TarTestCase
end
def test_build_invalid
- spec = Gem::Specification.new 'build', '1'
+ spec = Gem::Specification.new "build", "1"
package = Gem::Package.new spec.file_name
package.spec = spec
@@ -347,11 +348,11 @@ class TestGemPackage < Gem::Package::TarTestCase
package.build
end
- assert_equal 'missing value for attribute summary', e.message
+ assert_equal "missing value for attribute summary", e.message
end
def test_build_invalid_arguments
- spec = Gem::Specification.new 'build', '1'
+ spec = Gem::Specification.new "build", "1"
package = Gem::Package.new spec.file_name
package.spec = spec
@@ -364,19 +365,19 @@ class TestGemPackage < Gem::Package::TarTestCase
end
def test_build_signed
- pend 'openssl is missing' unless Gem::HAVE_OPENSSL
+ pend "openssl is missing" unless Gem::HAVE_OPENSSL
- spec = Gem::Specification.new 'build', '1'
- spec.summary = 'build'
- spec.authors = 'build'
- spec.files = ['lib/code.rb']
+ spec = Gem::Specification.new "build", "1"
+ spec.summary = "build"
+ spec.authors = "build"
+ spec.files = ["lib/code.rb"]
spec.cert_chain = [PUBLIC_CERT.to_pem]
spec.signing_key = PRIVATE_KEY
- FileUtils.mkdir 'lib'
+ FileUtils.mkdir "lib"
- File.open 'lib/code.rb', 'w' do |io|
- io.write '# lib/code.rb'
+ File.open "lib/code.rb", "w" do |io|
+ io.write "# lib/code.rb"
end
package = Gem::Package.new spec.file_name
@@ -392,8 +393,8 @@ class TestGemPackage < Gem::Package::TarTestCase
assert_equal spec, reader.spec
- assert_equal %w[metadata.gz metadata.gz.sig
- data.tar.gz data.tar.gz.sig
+ assert_equal %w[metadata.gz metadata.gz.sig
+ data.tar.gz data.tar.gz.sig
checksums.yaml.gz checksums.yaml.gz.sig],
reader.files
@@ -401,19 +402,19 @@ class TestGemPackage < Gem::Package::TarTestCase
end
def test_build_signed_encrypted_key
- pend 'openssl is missing' unless Gem::HAVE_OPENSSL
+ pend "openssl is missing" unless Gem::HAVE_OPENSSL
- spec = Gem::Specification.new 'build', '1'
- spec.summary = 'build'
- spec.authors = 'build'
- spec.files = ['lib/code.rb']
+ spec = Gem::Specification.new "build", "1"
+ spec.summary = "build"
+ spec.authors = "build"
+ spec.files = ["lib/code.rb"]
spec.cert_chain = [PUBLIC_CERT.to_pem]
spec.signing_key = ENCRYPTED_PRIVATE_KEY
- FileUtils.mkdir 'lib'
+ FileUtils.mkdir "lib"
- File.open 'lib/code.rb', 'w' do |io|
- io.write '# lib/code.rb'
+ File.open "lib/code.rb", "w" do |io|
+ io.write "# lib/code.rb"
end
package = Gem::Package.new spec.file_name
@@ -429,8 +430,8 @@ class TestGemPackage < Gem::Package::TarTestCase
assert_equal spec, reader.spec
- assert_equal %w[metadata.gz metadata.gz.sig
- data.tar.gz data.tar.gz.sig
+ assert_equal %w[metadata.gz metadata.gz.sig
+ data.tar.gz data.tar.gz.sig
checksums.yaml.gz checksums.yaml.gz.sig],
reader.files
@@ -441,11 +442,11 @@ class TestGemPackage < Gem::Package::TarTestCase
data_tgz = util_tar_gz {}
gem = util_tar do |tar|
- tar.add_file 'data.tar.gz', 0644 do |io|
+ tar.add_file "data.tar.gz", 0o644 do |io|
io.write data_tgz.string
end
- tar.add_file 'metadata.gz', 0644 do |io|
+ tar.add_file "metadata.gz", 0o644 do |io|
Zlib::GzipWriter.wrap io do |gzio|
gzio.write @spec.to_yaml
end
@@ -475,47 +476,62 @@ class TestGemPackage < Gem::Package::TarTestCase
package.extract_files @destination
- extracted = File.join @destination, 'lib/code.rb'
+ extracted = File.join @destination, "lib/code.rb"
assert_path_exist extracted
- mask = 0100666 & (~File.umask)
+ mask = 0o100666 & (~File.umask)
assert_equal mask.to_s(8), File.stat(extracted).mode.to_s(8) unless
- win_platform?
+ Gem.win_platform?
end
def test_extract_files_empty
data_tgz = util_tar_gz {}
gem = util_tar do |tar|
- tar.add_file 'data.tar.gz', 0644 do |io|
+ tar.add_file "data.tar.gz", 0o644 do |io|
io.write data_tgz.string
end
- tar.add_file 'metadata.gz', 0644 do |io|
+ tar.add_file "metadata.gz", 0o644 do |io|
Zlib::GzipWriter.wrap io do |gzio|
gzio.write @spec.to_yaml
end
end
end
- File.open 'empty.gem', 'wb' do |io|
+ File.open "empty.gem", "wb" do |io|
io.write gem.string
end
- package = Gem::Package.new 'empty.gem'
+ package = Gem::Package.new "empty.gem"
package.extract_files @destination
assert_path_exist @destination
end
+ def test_extract_file_permissions
+ pend "chmod not supported" if Gem.win_platform?
+
+ gem_with_long_permissions = File.expand_path("packages/Bluebie-legs-0.6.2.gem", __dir__)
+
+ package = Gem::Package.new gem_with_long_permissions
+
+ package.extract_files @destination
+
+ filepath = File.join @destination, "README.rdoc"
+ assert_path_exist filepath
+
+ assert_equal 0o104444, File.stat(filepath).mode
+ end
+
def test_extract_tar_gz_absolute
package = Gem::Package.new @gem
tgz_io = util_tar_gz do |tar|
- tar.add_file '/absolute.rb', 0644 do |io|
- io.write 'hi'
+ tar.add_file "/absolute.rb", 0o644 do |io|
+ io.write "hi"
end
end
@@ -523,69 +539,118 @@ class TestGemPackage < Gem::Package::TarTestCase
package.extract_tar_gz tgz_io, @destination
end
- assert_equal("installing into parent path /absolute.rb of " +
+ assert_equal("installing into parent path /absolute.rb of " \
"#{@destination} is not allowed", e.message)
end
def test_extract_tar_gz_symlink_relative_path
package = Gem::Package.new @gem
+ package.verify
tgz_io = util_tar_gz do |tar|
- tar.add_file 'relative.rb', 0644 do |io|
- io.write 'hi'
+ tar.add_file "relative.rb", 0o644 do |io|
+ io.write "hi"
end
- tar.mkdir 'lib', 0755
- tar.add_symlink 'lib/foo.rb', '../relative.rb', 0644
+ tar.mkdir "lib", 0o755
+ tar.add_symlink "lib/foo.rb", "../relative.rb", 0o644
end
begin
package.extract_tar_gz tgz_io, @destination
rescue Errno::EACCES => e
- if win_platform?
+ if Gem.win_platform?
pend "symlink - must be admin with no UAC on Windows"
else
raise e
end
end
- extracted = File.join @destination, 'lib/foo.rb'
+ extracted = File.join @destination, "lib/foo.rb"
assert_path_exist extracted
- assert_equal '../relative.rb',
+ assert_equal "../relative.rb",
File.readlink(extracted)
- assert_equal 'hi',
+ assert_equal "hi",
File.read(extracted)
end
+ def test_extract_symlink_into_symlink_dir
+ package = Gem::Package.new @gem
+ tgz_io = util_tar_gz do |tar|
+ tar.mkdir "lib", 0o755
+ tar.add_symlink "lib/link", "./inside.rb", 0o644
+ tar.add_file "lib/inside.rb", 0o644 do |io|
+ io.write "hi"
+ end
+ end
+
+ destination_subdir = File.join @destination, "subdir"
+ FileUtils.mkdir_p destination_subdir
+
+ destination_linkdir = File.join @destination, "linkdir"
+ File.symlink(destination_subdir, destination_linkdir)
+
+ package.extract_tar_gz tgz_io, destination_linkdir
+
+ extracted = File.join destination_subdir, "lib/link"
+ assert_path_exist extracted
+ assert_equal "./inside.rb",
+ File.readlink(extracted)
+ assert_equal "hi",
+ File.read(extracted)
+ end
+
+ def test_extract_tar_gz_symlink_broken_relative_path
+ package = Gem::Package.new @gem
+ package.verify
+
+ tgz_io = util_tar_gz do |tar|
+ tar.mkdir "lib", 0o755
+ tar.add_symlink "lib/foo.rb", "../broken.rb", 0o644
+ end
+
+ ui = Gem::MockGemUi.new
+
+ use_ui ui do
+ package.extract_tar_gz tgz_io, @destination
+ end
+
+ assert_equal "WARNING: a-2 ships with a dangling symlink named lib/foo.rb pointing to missing ../broken.rb file. Ignoring\n", ui.error
+
+ extracted = File.join @destination, "lib/foo.rb"
+ assert_path_not_exist extracted
+ end
+
def test_extract_symlink_parent
package = Gem::Package.new @gem
tgz_io = util_tar_gz do |tar|
- tar.mkdir 'lib', 0755
- tar.add_symlink 'lib/link', '../..', 0644
- tar.add_file 'lib/link/outside.txt', 0644 do |io|
- io.write 'hi'
+ tar.mkdir "lib", 0o755
+ tar.add_symlink "lib/link", "../..", 0o644
+ tar.add_file "lib/link/outside.txt", 0o644 do |io|
+ io.write "hi"
end
end
# Extract into a subdirectory of @destination; if this test fails it writes
# a file outside destination_subdir, but we want the file to remain inside
# @destination so it will be cleaned up.
- destination_subdir = File.join @destination, 'subdir'
+ destination_subdir = File.join @destination, "subdir"
FileUtils.mkdir_p destination_subdir
- e = assert_raise(Gem::Package::PathError, Errno::EACCES) do
+ expected_exceptions = Gem.win_platform? ? [Gem::Package::SymlinkError, Errno::EACCES] : [Gem::Package::SymlinkError]
+
+ e = assert_raise(*expected_exceptions) do
package.extract_tar_gz tgz_io, destination_subdir
end
- if Gem::Package::PathError === e
- assert_equal("installing into parent path lib/link/outside.txt of " +
- "#{destination_subdir} is not allowed", e.message)
- elsif win_platform?
- pend "symlink - must be admin with no UAC on Windows"
- else
- raise e
- end
+ pend "symlink - must be admin with no UAC on Windows" if Errno::EACCES === e
+
+ assert_equal("installing symlink 'lib/link' pointing to parent path #{@destination} of " \
+ "#{destination_subdir} is not allowed", e.message)
+
+ assert_path_not_exist File.join(@destination, "outside.txt")
+ assert_path_not_exist File.join(destination_subdir, "lib/link")
end
def test_extract_symlink_parent_doesnt_delete_user_dir
@@ -594,53 +659,53 @@ class TestGemPackage < Gem::Package::TarTestCase
# Extract into a subdirectory of @destination; if this test fails it writes
# a file outside destination_subdir, but we want the file to remain inside
# @destination so it will be cleaned up.
- destination_subdir = File.join @destination, 'subdir'
+ destination_subdir = File.join @destination, "subdir"
FileUtils.mkdir_p destination_subdir
- destination_user_dir = File.join @destination, 'user'
- destination_user_subdir = File.join destination_user_dir, 'dir'
+ destination_user_dir = File.join @destination, "user"
+ destination_user_subdir = File.join destination_user_dir, "dir"
FileUtils.mkdir_p destination_user_subdir
pend "TMPDIR seems too long to add it as symlink into tar" if destination_user_dir.size > 90
tgz_io = util_tar_gz do |tar|
- tar.add_symlink 'link', destination_user_dir, 16877
- tar.add_symlink 'link/dir', '.', 16877
+ tar.add_symlink "link", destination_user_dir, 16_877
+ tar.add_symlink "link/dir", ".", 16_877
end
- e = assert_raise(Gem::Package::PathError, Errno::EACCES) do
+ expected_exceptions = Gem.win_platform? ? [Gem::Package::SymlinkError, Errno::EACCES] : [Gem::Package::SymlinkError]
+
+ e = assert_raise(*expected_exceptions) do
package.extract_tar_gz tgz_io, destination_subdir
end
- assert_path_exist destination_user_subdir
+ pend "symlink - must be admin with no UAC on Windows" if Errno::EACCES === e
- if Gem::Package::PathError === e
- assert_equal("installing into parent path #{destination_user_subdir} of " +
- "#{destination_subdir} is not allowed", e.message)
- elsif win_platform?
- pend "symlink - must be admin with no UAC on Windows"
- else
- raise e
- end
+ assert_equal("installing symlink 'link' pointing to parent path #{destination_user_dir} of " \
+ "#{destination_subdir} is not allowed", e.message)
+
+ assert_path_exist destination_user_subdir
+ assert_path_not_exist File.join(destination_subdir, "link/dir")
+ assert_path_not_exist File.join(destination_subdir, "link")
end
def test_extract_tar_gz_directory
package = Gem::Package.new @gem
tgz_io = util_tar_gz do |tar|
- tar.mkdir 'lib', 0755
- tar.add_file 'lib/foo.rb', 0644 do |io|
- io.write 'hi'
+ tar.mkdir "lib", 0o755
+ tar.add_file "lib/foo.rb", 0o644 do |io|
+ io.write "hi"
end
- tar.mkdir 'lib/foo', 0755
+ tar.mkdir "lib/foo", 0o755
end
package.extract_tar_gz tgz_io, @destination
- extracted = File.join @destination, 'lib/foo.rb'
+ extracted = File.join @destination, "lib/foo.rb"
assert_path_exist extracted
- extracted = File.join @destination, 'lib/foo'
+ extracted = File.join @destination, "lib/foo"
assert_path_exist extracted
end
@@ -648,14 +713,14 @@ class TestGemPackage < Gem::Package::TarTestCase
package = Gem::Package.new @gem
tgz_io = util_tar_gz do |tar|
- tar.add_file './dot_slash.rb', 0644 do |io|
- io.write 'hi'
+ tar.add_file "./dot_slash.rb", 0o644 do |io|
+ io.write "hi"
end
end
package.extract_tar_gz tgz_io, @destination
- extracted = File.join @destination, 'dot_slash.rb'
+ extracted = File.join @destination, "dot_slash.rb"
assert_path_exist extracted
end
@@ -663,14 +728,14 @@ class TestGemPackage < Gem::Package::TarTestCase
package = Gem::Package.new @gem
tgz_io = util_tar_gz do |tar|
- tar.add_file '.dot_file.rb', 0644 do |io|
- io.write 'hi'
+ tar.add_file ".dot_file.rb", 0o644 do |io|
+ io.write "hi"
end
end
package.extract_tar_gz tgz_io, @destination
- extracted = File.join @destination, '.dot_file.rb'
+ extracted = File.join @destination, ".dot_file.rb"
assert_path_exist extracted
end
@@ -679,14 +744,14 @@ class TestGemPackage < Gem::Package::TarTestCase
package = Gem::Package.new @gem
tgz_io = util_tar_gz do |tar|
- tar.add_file 'foo/file.rb', 0644 do |io|
- io.write 'hi'
+ tar.add_file "foo/file.rb", 0o644 do |io|
+ io.write "hi"
end
end
package.extract_tar_gz tgz_io, @destination.upcase
- extracted = File.join @destination, 'foo/file.rb'
+ extracted = File.join @destination, "foo/file.rb"
assert_path_exist extracted
end
end
@@ -694,66 +759,60 @@ class TestGemPackage < Gem::Package::TarTestCase
def test_install_location
package = Gem::Package.new @gem
- file = 'file.rb'.dup
- file.taint if RUBY_VERSION < '2.7'
+ file = "file.rb".dup
destination = package.install_location file, @destination
- assert_equal File.join(@destination, 'file.rb'), destination
- refute destination.tainted? if RUBY_VERSION < '2.7'
+ assert_equal File.join(@destination, "file.rb"), destination
end
def test_install_location_absolute
package = Gem::Package.new @gem
e = assert_raise Gem::Package::PathError do
- package.install_location '/absolute.rb', @destination
+ package.install_location "/absolute.rb", @destination
end
- assert_equal("installing into parent path /absolute.rb of " +
+ assert_equal("installing into parent path /absolute.rb of " \
"#{@destination} is not allowed", e.message)
end
def test_install_location_dots
package = Gem::Package.new @gem
- file = 'file.rb'
+ file = "file.rb"
- destination = File.join @destination, 'foo', '..', 'bar'
+ destination = File.join @destination, "foo", "..", "bar"
- FileUtils.mkdir_p File.join @destination, 'foo'
+ FileUtils.mkdir_p File.join @destination, "foo"
FileUtils.mkdir_p File.expand_path destination
destination = package.install_location file, destination
# this test only fails on ruby missing File.realpath
- assert_equal File.join(@destination, 'bar', 'file.rb'), destination
+ assert_equal File.join(@destination, "bar", "file.rb"), destination
end
def test_install_location_extra_slash
package = Gem::Package.new @gem
- file = 'foo//file.rb'.dup
- file.taint if RUBY_VERSION < '2.7'
-
- destination = @destination.sub '/', '//'
+ file = "foo//file.rb".dup
- destination = package.install_location file, destination
+ destination = package.install_location file, @destination
- assert_equal File.join(@destination, 'foo', 'file.rb'), destination
- refute destination.tainted? if RUBY_VERSION < '2.7'
+ assert_equal File.join(@destination, "foo", "file.rb"), destination
end
def test_install_location_relative
package = Gem::Package.new @gem
e = assert_raise Gem::Package::PathError do
- package.install_location '../relative.rb', @destination
+ package.install_location "../relative.rb", @destination
end
parent = File.expand_path File.join @destination, "../relative.rb"
- assert_equal("installing into parent path #{parent} of " +
+ assert_equal("installing into parent path #{parent} of " \
"#{@destination} is not allowed", e.message)
end
@@ -768,15 +827,17 @@ class TestGemPackage < Gem::Package::TarTestCase
parent = File.expand_path File.join @destination, filename
- assert_equal("installing into parent path #{parent} of " +
+ assert_equal("installing into parent path #{parent} of " \
"#{@destination} is not allowed", e.message)
end
def test_load_spec
entry = StringIO.new Gem::Util.gzip @spec.to_yaml
- def entry.full_name() 'metadata.gz' end
+ def entry.full_name
+ "metadata.gz"
+ end
- package = Gem::Package.new 'nonexistent.gem'
+ package = Gem::Package.new "nonexistent.gem"
spec = package.load_spec entry
@@ -795,8 +856,8 @@ class TestGemPackage < Gem::Package::TarTestCase
def test_verify_checksum_bad
data_tgz = util_tar_gz do |tar|
- tar.add_file 'lib/code.rb', 0444 do |io|
- io.write '# lib/code.rb'
+ tar.add_file "lib/code.rb", 0o444 do |io|
+ io.write "# lib/code.rb"
end
end
@@ -805,45 +866,45 @@ class TestGemPackage < Gem::Package::TarTestCase
gem = util_tar do |tar|
metadata_gz = Gem::Util.gzip @spec.to_yaml
- tar.add_file 'metadata.gz', 0444 do |io|
+ tar.add_file "metadata.gz", 0o444 do |io|
io.write metadata_gz
end
- tar.add_file 'data.tar.gz', 0444 do |io|
+ tar.add_file "data.tar.gz", 0o444 do |io|
io.write data_tgz
end
bogus_checksums = {
- 'SHA1' => {
- 'data.tar.gz' => 'bogus',
- 'metadata.gz' => 'bogus',
+ "SHA1" => {
+ "data.tar.gz" => "bogus",
+ "metadata.gz" => "bogus",
},
}
- tar.add_file 'checksums.yaml.gz', 0444 do |io|
+ tar.add_file "checksums.yaml.gz", 0o444 do |io|
Zlib::GzipWriter.wrap io do |gz_io|
- gz_io.write YAML.dump bogus_checksums
+ gz_io.write Psych.dump bogus_checksums
end
end
end
- File.open 'mismatch.gem', 'wb' do |io|
+ File.open "mismatch.gem", "wb" do |io|
io.write gem.string
end
- package = Gem::Package.new 'mismatch.gem'
+ package = Gem::Package.new "mismatch.gem"
e = assert_raise Gem::Package::FormatError do
package.verify
end
- assert_equal 'SHA1 checksum mismatch for data.tar.gz in mismatch.gem',
+ assert_equal "SHA1 checksum mismatch for data.tar.gz in mismatch.gem",
e.message
end
def test_verify_checksum_missing
data_tgz = util_tar_gz do |tar|
- tar.add_file 'lib/code.rb', 0444 do |io|
- io.write '# lib/code.rb'
+ tar.add_file "lib/code.rb", 0o444 do |io|
+ io.write "# lib/code.rb"
end
end
@@ -852,45 +913,45 @@ class TestGemPackage < Gem::Package::TarTestCase
gem = util_tar do |tar|
metadata_gz = Gem::Util.gzip @spec.to_yaml
- tar.add_file 'metadata.gz', 0444 do |io|
+ tar.add_file "metadata.gz", 0o444 do |io|
io.write metadata_gz
end
- digest = Digest::SHA1.new
+ digest = OpenSSL::Digest::SHA1.new
digest << metadata_gz
checksums = {
- 'SHA1' => {
- 'metadata.gz' => digest.hexdigest,
+ "SHA1" => {
+ "metadata.gz" => digest.hexdigest,
},
}
- tar.add_file 'checksums.yaml.gz', 0444 do |io|
+ tar.add_file "checksums.yaml.gz", 0o444 do |io|
Zlib::GzipWriter.wrap io do |gz_io|
- gz_io.write YAML.dump checksums
+ gz_io.write Psych.dump checksums
end
end
- tar.add_file 'data.tar.gz', 0444 do |io|
+ tar.add_file "data.tar.gz", 0o444 do |io|
io.write data_tgz
end
end
- File.open 'data_checksum_missing.gem', 'wb' do |io|
+ File.open "data_checksum_missing.gem", "wb" do |io|
io.write gem.string
end
- package = Gem::Package.new 'data_checksum_missing.gem'
+ package = Gem::Package.new "data_checksum_missing.gem"
assert package.verify
end
def test_verify_corrupt
pend "jruby strips the null byte and does not think it's corrupt" if Gem.java_platform?
- tf = Tempfile.open 'corrupt' do |io|
- data = Gem::Util.gzip 'a' * 10
+ tf = Tempfile.open "corrupt" do |io|
+ data = Gem::Util.gzip "a" * 10
io.write \
- tar_file_header('metadata.gz', "\000x", 0644, data.length, Time.now)
+ tar_file_header("metadata.gz", "\000x", 0o644, data.length, Time.now)
io.write data
io.rewind
@@ -907,43 +968,132 @@ class TestGemPackage < Gem::Package::TarTestCase
tf.close!
end
+ def test_verify_corrupt_tar_metadata_entry
+ gem = tar_file_header("metadata.gz", "", 0, 999, Time.now)
+
+ File.open "corrupt.gem", "wb" do |io|
+ io.write gem
+ end
+
+ package = Gem::Package.new "corrupt.gem"
+
+ e = nil
+ out_err = capture_output do
+ e = assert_raise Gem::Package::FormatError do
+ package.verify
+ end
+ end
+
+ assert_match(/(EOFError|end of file reached) in corrupt.gem/i, e.message)
+ assert_equal(["", "Exception while verifying corrupt.gem\n"], out_err)
+ end
+
+ def test_verify_corrupt_tar_checksums_entry
+ gem = tar_file_header("checksums.yaml.gz", "", 0, 100, Time.now)
+
+ File.open "corrupt.gem", "wb" do |io|
+ io.write gem
+ end
+
+ package = Gem::Package.new "corrupt.gem"
+
+ e = assert_raise Gem::Package::FormatError do
+ package.verify
+ end
+
+ assert_equal "not in gzip format in corrupt.gem", e.message
+ end
+
+ def test_verify_corrupt_tar_data_entry
+ gem = tar_file_header("data.tar.gz", "", 0, 100, Time.now)
+
+ File.open "corrupt.gem", "wb" do |io|
+ io.write gem
+ end
+
+ package = Gem::Package.new "corrupt.gem"
+
+ e = nil
+ out_err = capture_output do
+ e = assert_raise Gem::Package::FormatError do
+ package.verify
+ end
+ end
+
+ assert_match(/(EOFError|end of file reached) in corrupt.gem/i, e.message)
+ assert_equal(["", "Exception while verifying corrupt.gem\n"], out_err)
+ end
+
+ def test_corrupt_data_tar_gz
+ data_tgz = util_gzip tar_file_header("lib/code.rb", "", 0, 100, Time.now)
+ metadata_gz = util_gzip @spec.to_yaml
+
+ gem = util_tar do |tar|
+ tar.add_file "data.tar.gz", 0o444 do |io|
+ io.write data_tgz
+ end
+
+ tar.add_file "metadata.gz", 0o644 do |io|
+ io.write metadata_gz
+ end
+ end
+
+ File.open "corrupt.gem", "wb" do |io|
+ io.write gem.string
+ end
+
+ package = Gem::Package.new "corrupt.gem"
+
+ e = assert_raise Gem::Package::FormatError do
+ package.contents
+ end
+
+ assert_match(/(EOFError|end of file reached) in corrupt.gem/i, e.message)
+
+ e = assert_raise Gem::Package::FormatError do
+ package.extract_files @destination
+ end
+
+ assert_match(/(EOFError|end of file reached) in corrupt.gem/i, e.message)
+ end
+
def test_verify_empty
- FileUtils.touch 'empty.gem'
+ FileUtils.touch "empty.gem"
- package = Gem::Package.new 'empty.gem'
+ package = Gem::Package.new "empty.gem"
e = assert_raise Gem::Package::FormatError do
package.verify
end
- assert_equal 'package metadata is missing in empty.gem', e.message
+ assert_equal "package metadata is missing in empty.gem", e.message
end
def test_verify_nonexistent
- package = Gem::Package.new 'nonexistent.gem'
+ package = Gem::Package.new "nonexistent.gem"
e = assert_raise Gem::Package::FormatError do
package.verify
end
- assert_match %r{^No such file or directory}, e.message
- assert_match %r{nonexistent.gem$}, e.message
+ assert_match(/^No such file or directory/, e.message)
+ assert_match(/nonexistent.gem$/, e.message)
end
def test_verify_duplicate_file
- FileUtils.mkdir_p 'lib'
- FileUtils.touch 'lib/code.rb'
+ FileUtils.mkdir_p "lib"
+ FileUtils.touch "lib/code.rb"
build = Gem::Package.new @gem
build.spec = @spec
build.setup_signer
- File.open @gem, 'wb' do |gem_io|
+ File.open @gem, "wb" do |gem_io|
Gem::Package::TarWriter.new gem_io do |gem|
build.add_metadata gem
build.add_contents gem
- gem.add_file_simple 'a.sig', 0444, 0
- gem.add_file_simple 'a.sig', 0444, 0
+ gem.add_file_simple "a.sig", 0o444, 0
+ gem.add_file_simple "a.sig", 0o444, 0
end
end
@@ -957,7 +1107,7 @@ class TestGemPackage < Gem::Package::TarTestCase
end
def test_verify_security_policy
- pend 'openssl is missing' unless Gem::HAVE_OPENSSL
+ pend "openssl is missing" unless Gem::HAVE_OPENSSL
package = Gem::Package.new @gem
package.security_policy = Gem::Security::HighSecurity
@@ -966,21 +1116,21 @@ class TestGemPackage < Gem::Package::TarTestCase
package.verify
end
- assert_equal 'unsigned gems are not allowed by the High Security policy',
+ assert_equal "unsigned gems are not allowed by the High Security policy",
e.message
- refute package.instance_variable_get(:@spec), '@spec must not be loaded'
- assert_empty package.instance_variable_get(:@files), '@files must empty'
+ refute package.instance_variable_get(:@spec), "@spec must not be loaded"
+ assert_empty package.instance_variable_get(:@files), "@files must empty"
end
def test_verify_security_policy_low_security
- pend 'openssl is missing' unless Gem::HAVE_OPENSSL
+ pend "openssl is missing" unless Gem::HAVE_OPENSSL
@spec.cert_chain = [PUBLIC_CERT.to_pem]
@spec.signing_key = PRIVATE_KEY
- FileUtils.mkdir_p 'lib'
- FileUtils.touch 'lib/code.rb'
+ FileUtils.mkdir_p "lib"
+ FileUtils.touch "lib/code.rb"
build = Gem::Package.new @gem
build.spec = @spec
@@ -994,7 +1144,7 @@ class TestGemPackage < Gem::Package::TarTestCase
end
def test_verify_security_policy_checksum_missing
- pend 'openssl is missing' unless Gem::HAVE_OPENSSL
+ pend "openssl is missing" unless Gem::HAVE_OPENSSL
@spec.cert_chain = [PUBLIC_CERT.to_pem]
@spec.signing_key = PRIVATE_KEY
@@ -1003,23 +1153,34 @@ class TestGemPackage < Gem::Package::TarTestCase
build.spec = @spec
build.setup_signer
- FileUtils.mkdir 'lib'
- FileUtils.touch 'lib/code.rb'
+ FileUtils.mkdir "lib"
+ FileUtils.touch "lib/code.rb"
- File.open @gem, 'wb' do |gem_io|
+ File.open @gem, "wb" do |gem_io|
Gem::Package::TarWriter.new gem_io do |gem|
build.add_metadata gem
build.add_contents gem
# write bogus data.tar.gz to foil signature
- bogus_data = Gem::Util.gzip 'hello'
+ bogus_data = Gem::Util.gzip "hello"
fake_signer = Class.new do
- def digest_name; 'SHA512'; end
- def digest_algorithm; Digest(:SHA512).new; end
- def key; 'key'; end
- def sign(*); 'fake_sig'; end
+ def digest_name
+ "SHA512"
+ end
+
+ def digest_algorithm
+ OpenSSL::Digest(:SHA512).new
+ end
+
+ def key
+ "key"
+ end
+
+ def sign(*)
+ "fake_sig"
+ end
end
- gem.add_file_signed 'data2.tar.gz', 0444, fake_signer.new do |io|
+ gem.add_file_signed "data2.tar.gz", 0o444, fake_signer.new do |io|
io.write bogus_data
end
@@ -1036,24 +1197,24 @@ class TestGemPackage < Gem::Package::TarTestCase
package.verify
end
- assert_equal 'invalid signature', e.message
+ assert_equal "invalid signature", e.message
- refute package.instance_variable_get(:@spec), '@spec must not be loaded'
- assert_empty package.instance_variable_get(:@files), '@files must empty'
+ refute package.instance_variable_get(:@spec), "@spec must not be loaded"
+ assert_empty package.instance_variable_get(:@files), "@files must empty"
end
def test_verify_truncate
- File.open 'bad.gem', 'wb' do |io|
+ File.open "bad.gem", "wb" do |io|
io.write File.read(@gem, 1024) # don't care about newlines
end
- package = Gem::Package.new 'bad.gem'
+ package = Gem::Package.new "bad.gem"
e = assert_raise Gem::Package::FormatError do
package.verify
end
- assert_equal 'package content (data.tar.gz) is missing in bad.gem',
+ assert_equal "package content (data.tar.gz) is missing in bad.gem",
e.message
end
@@ -1061,7 +1222,9 @@ class TestGemPackage < Gem::Package::TarTestCase
def test_verify_entry
entry = Object.new
- def entry.full_name() raise ArgumentError, 'whatever' end
+ def entry.full_name
+ raise ArgumentError, "whatever"
+ end
package = Gem::Package.new @gem
@@ -1088,11 +1251,15 @@ class TestGemPackage < Gem::Package::TarTestCase
$good_name = vm
entry = Object.new
- def entry.full_name() $good_name end
+ def entry.full_name
+ $good_name
+ end
package = Gem::Package.new(@gem)
package.instance_variable_set(:@files, [])
- def package.load_spec(entry) $spec_loaded = true end
+ def package.load_spec(entry)
+ $spec_loaded = true
+ end
package.verify_entry(entry)
@@ -1105,11 +1272,15 @@ class TestGemPackage < Gem::Package::TarTestCase
$bad_name = vm
entry = Object.new
- def entry.full_name() $bad_name end
+ def entry.full_name
+ $bad_name
+ end
package = Gem::Package.new(@gem)
package.instance_variable_set(:@files, [])
- def package.load_spec(entry) $spec_loaded = true end
+ def package.load_spec(entry)
+ $spec_loaded = true
+ end
package.verify_entry(entry)
@@ -1151,29 +1322,4 @@ class TestGemPackage < Gem::Package::TarTestCase
assert_equal %w[lib/code.rb], package.contents
end
-
- def util_tar
- tar_io = StringIO.new
-
- Gem::Package::TarWriter.new tar_io do |tar|
- yield tar
- end
-
- tar_io.rewind
-
- tar_io
- end
-
- def util_tar_gz(&block)
- tar_io = util_tar(&block)
-
- tgz_io = StringIO.new
-
- # can't wrap TarWriter because it seeks
- Zlib::GzipWriter.wrap tgz_io do |io|
- io.write tar_io.string
- end
-
- StringIO.new tgz_io.string
- end
end
diff --git a/test/rubygems/test_gem_package_old.rb b/test/rubygems/test_gem_package_old.rb
index 945340a96a..7582dbedd4 100644
--- a/test/rubygems/test_gem_package_old.rb
+++ b/test/rubygems/test_gem_package_old.rb
@@ -1,19 +1,20 @@
# frozen_string_literal: true
-require_relative 'helper'
+
+require_relative "helper"
unless Gem.java_platform? # jruby can't require the simple_gem file
- require 'rubygems/simple_gem'
+ require "rubygems/simple_gem"
class TestGemPackageOld < Gem::TestCase
def setup
super
- File.open 'old_format.gem', 'wb' do |io|
+ File.open "old_format.gem", "wb" do |io|
io.write SIMPLE_GEM
end
- @package = Gem::Package::Old.new 'old_format.gem'
- @destination = File.join @tempdir, 'extract'
+ @package = Gem::Package::Old.new "old_format.gem"
+ @destination = File.join @tempdir, "extract"
FileUtils.mkdir_p @destination
end
@@ -23,7 +24,7 @@ unless Gem.java_platform? # jruby can't require the simple_gem file
end
def test_contents_security_policy
- pend 'openssl is missing' unless Gem::HAVE_OPENSSL
+ pend "openssl is missing" unless Gem::HAVE_OPENSSL
@package.security_policy = Gem::Security::AlmostNoSecurity
@@ -35,16 +36,16 @@ unless Gem.java_platform? # jruby can't require the simple_gem file
def test_extract_files
@package.extract_files @destination
- extracted = File.join @destination, 'lib/foo.rb'
+ extracted = File.join @destination, "lib/foo.rb"
assert_path_exist extracted
- mask = 0100644 & (~File.umask)
+ mask = 0o100644 & (~File.umask)
- assert_equal mask, File.stat(extracted).mode unless win_platform?
+ assert_equal mask, File.stat(extracted).mode unless Gem.win_platform?
end
def test_extract_files_security_policy
- pend 'openssl is missing' unless Gem::HAVE_OPENSSL
+ pend "openssl is missing" unless Gem::HAVE_OPENSSL
@package.security_policy = Gem::Security::AlmostNoSecurity
@@ -54,11 +55,11 @@ unless Gem.java_platform? # jruby can't require the simple_gem file
end
def test_spec
- assert_equal 'testing', @package.spec.name
+ assert_equal "testing", @package.spec.name
end
def test_spec_security_policy
- pend 'openssl is missing' unless Gem::HAVE_OPENSSL
+ pend "openssl is missing" unless Gem::HAVE_OPENSSL
@package.security_policy = Gem::Security::AlmostNoSecurity
@@ -68,7 +69,7 @@ unless Gem.java_platform? # jruby can't require the simple_gem file
end
def test_verify
- pend 'openssl is missing' unless Gem::HAVE_OPENSSL
+ pend "openssl is missing" unless Gem::HAVE_OPENSSL
assert @package.verify
@@ -82,8 +83,8 @@ unless Gem.java_platform? # jruby can't require the simple_gem file
@package.verify
end
- assert_equal 'old format gems do not contain signatures ' +
- 'and cannot be verified',
+ assert_equal "old format gems do not contain signatures " \
+ "and cannot be verified",
e.message
end
end
diff --git a/test/rubygems/test_gem_package_tar_header.rb b/test/rubygems/test_gem_package_tar_header.rb
index 0e72a72d6a..a3f95bb770 100644
--- a/test/rubygems/test_gem_package_tar_header.rb
+++ b/test/rubygems/test_gem_package_tar_header.rb
@@ -1,25 +1,26 @@
# frozen_string_literal: true
-require_relative 'package/tar_test_case'
-require 'rubygems/package'
+
+require_relative "package/tar_test_case"
+require "rubygems/package"
class TestGemPackageTarHeader < Gem::Package::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',
+ name: "x",
+ mode: 0o644,
+ uid: 1000,
+ gid: 10_000,
+ size: 100,
+ mtime: 12_345,
+ typeflag: "0",
+ linkname: "link",
+ uname: "user",
+ gname: "group",
+ devmajor: 1,
+ devminor: 2,
+ prefix: "y",
}
@tar_header = Gem::Package::TarHeader.new header
@@ -36,66 +37,91 @@ class TestGemPackageTarHeader < Gem::Package::TarTestCase
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'
-
- refute_empty @tar_header, 'empty'
+ assert_equal "", @tar_header.checksum, "checksum"
+ assert_equal 1, @tar_header.devmajor, "devmajor"
+ assert_equal 2, @tar_header.devminor, "devminor"
+ assert_equal 10_000, @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 0o644, @tar_header.mode, "mode"
+ assert_equal 12_345, @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"
+
+ refute_empty @tar_header, "empty"
end
def test_initialize_bad
assert_raise ArgumentError do
- Gem::Package::TarHeader.new :name => '', :size => '', :mode => ''
+ Gem::Package::TarHeader.new name: "", size: "", mode: ""
end
assert_raise ArgumentError do
- Gem::Package::TarHeader.new :name => '', :size => '', :prefix => ''
+ Gem::Package::TarHeader.new name: "", size: "", prefix: ""
end
assert_raise ArgumentError do
- Gem::Package::TarHeader.new :name => '', :prefix => '', :mode => ''
+ Gem::Package::TarHeader.new name: "", prefix: "", mode: ""
end
assert_raise ArgumentError do
- Gem::Package::TarHeader.new :prefix => '', :size => '', :mode => ''
+ Gem::Package::TarHeader.new prefix: "", size: "", mode: ""
end
end
def test_initialize_typeflag
header = {
- :mode => '',
- :name => '',
- :prefix => '',
- :size => '',
- :typeflag => '',
+ mode: "",
+ name: "",
+ prefix: "",
+ size: "",
+ typeflag: "",
}
tar_header = Gem::Package::TarHeader.new header
- assert_equal '0', tar_header.typeflag
+ assert_equal "0", tar_header.typeflag
end
def test_empty_eh
refute_empty @tar_header
- @tar_header = Gem::Package::TarHeader.new :name => 'x', :prefix => '',
- :mode => 0, :size => 0,
- :empty => true
+ @tar_header = Gem::Package::TarHeader.new name: "x", prefix: "",
+ mode: 0, size: 0,
+ empty: true
+
+ assert_empty @tar_header
+ end
+
+ def test_empty
+ @tar_header = Gem::Package::TarHeader.from(StringIO.new(Gem::Package::TarHeader::EMPTY_HEADER))
assert_empty @tar_header
+ assert_equal Gem::Package::TarHeader.new(
+ checksum: 0,
+ devmajor: 0,
+ devminor: 0,
+ empty: true,
+ gid: 0,
+ gname: "",
+ linkname: "",
+ magic: "",
+ mode: 0,
+ mtime: 0,
+ name: "",
+ prefix: "",
+ size: 0,
+ typeflag: "0",
+ uid: 0,
+ uname: "",
+ version: 0,
+ ), @tar_header
end
def test_equals2
@@ -135,11 +161,11 @@ group\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
end
def test_update_checksum
- assert_equal '', @tar_header.checksum
+ assert_equal "", @tar_header.checksum
@tar_header.update_checksum
- assert_equal '012467', @tar_header.checksum
+ assert_equal "012467", @tar_header.checksum
end
def test_from_bad_octal
@@ -159,13 +185,14 @@ group\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
assert_raise ArgumentError do
Gem::Package::TarHeader.from io
end
+ ensure
io.close!
end
end
def test_big_uid_gid
stream = StringIO.new(
- <<-EOF.dup.force_encoding('binary').split("\n").join
+ <<-EOF.dup.force_encoding("binary").split("\n").join
GeoIP2-City_20190528/
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
@@ -194,19 +221,19 @@ tjmather\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
tar_header = Gem::Package::TarHeader.from stream
- assert_equal 1991400094, tar_header.uid
- assert_equal 1991400094, tar_header.gid
+ assert_equal 1_991_400_094, tar_header.uid
+ assert_equal 1_991_400_094, tar_header.gid
- assert_equal 'GeoIP2-City_20190528/', tar_header.name
- assert_equal 0755, tar_header.mode
+ assert_equal "GeoIP2-City_20190528/", tar_header.name
+ assert_equal 0o755, tar_header.mode
assert_equal 0, tar_header.size
- assert_equal 1559064640, tar_header.mtime
+ assert_equal 1_559_064_640, tar_header.mtime
assert_equal 6932, tar_header.checksum
end
def test_spaces_in_headers
stream = StringIO.new(
- <<-EOF.dup.force_encoding('binary').split("\n").join
+ <<-EOF.dup.force_encoding("binary").split("\n").join
Access_Points_09202018.csv
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
diff --git a/test/rubygems/test_gem_package_tar_reader.rb b/test/rubygems/test_gem_package_tar_reader.rb
index 277b552f1b..b2f7cc2d5c 100644
--- a/test/rubygems/test_gem_package_tar_reader.rb
+++ b/test/rubygems/test_gem_package_tar_reader.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
-require_relative 'package/tar_test_case'
-require 'rubygems/package'
+
+require_relative "package/tar_test_case"
+require "rubygems/package"
class TestGemPackageTarReader < Gem::Package::TarTestCase
def test_each_entry
@@ -24,12 +25,27 @@ class TestGemPackageTarReader < Gem::Package::TarTestCase
io.close!
end
+ def test_each_with_not_a_tar
+ text = "Hello, world!!?\n" * 256 # 4 KiB
+ io = TempIO.new text
+
+ Gem::Package::TarReader.new io do |tar|
+ assert_raise Gem::Package::TarInvalidError do
+ tar.each do
+ flunk "TarInvalidError was expected to occur, but an entry was found"
+ end
+ end
+ end
+ ensure
+ io.close!
+ end
+
def test_rewind
- content = ('a'..'z').to_a.join(" ")
+ content = ("a".."z").to_a.join(" ")
str =
- tar_file_header("lib/foo", "", 010644, content.size, Time.now) +
- content + "\0" * (512 - content.size)
+ tar_file_header("lib/foo", "", 0o10644, content.size, Time.now) +
+ content + "\0" * (512 - content.size)
str << "\0" * 1024
io = TempIO.new(str)
@@ -56,12 +72,14 @@ class TestGemPackageTarReader < Gem::Package::TarTestCase
io = TempIO.new tar
Gem::Package::TarReader.new io do |tar_reader|
- tar_reader.seek 'baz/bar' do |entry|
+ retval = tar_reader.seek "baz/bar" do |entry|
assert_kind_of Gem::Package::TarReader::Entry, entry
- assert_equal 'baz/bar', entry.full_name
+ assert_equal "baz/bar", entry.full_name
+ entry.read
end
+ assert_equal "", retval
assert_equal 0, io.pos
end
ensure
@@ -75,8 +93,8 @@ class TestGemPackageTarReader < Gem::Package::TarTestCase
io = TempIO.new tar
Gem::Package::TarReader.new io do |tar_reader|
- tar_reader.seek 'nonexistent' do |entry|
- flunk 'entry missing but entry-found block was run'
+ tar_reader.seek "nonexistent" do |_entry|
+ flunk "entry missing but entry-found block was run"
end
assert_equal 0, io.pos
@@ -84,4 +102,49 @@ class TestGemPackageTarReader < Gem::Package::TarTestCase
ensure
io.close!
end
+
+ def test_read_in_gem_data
+ gem_tar = util_gem_data_tar do |tar|
+ tar.add_file "lib/code.rb", 0o444 do |io|
+ io.write "# lib/code.rb"
+ end
+ end
+
+ count = 0
+ Gem::Package::TarReader.new(gem_tar).each do |entry|
+ next unless entry.full_name == "data.tar.gz"
+
+ Zlib::GzipReader.wrap entry do |gzio|
+ Gem::Package::TarReader.new(gzio).each do |contents_entry|
+ assert_equal "# lib/code.rb", contents_entry.read
+ count += 1
+ end
+ end
+ end
+
+ assert_equal 1, count, "should have found one file"
+ end
+
+ def test_seek_in_gem_data
+ gem_tar = util_gem_data_tar do |tar|
+ tar.add_file "lib/code.rb", 0o444 do |io|
+ io.write "# lib/code.rb"
+ end
+ tar.add_file "lib/foo.rb", 0o444 do |io|
+ io.write "# lib/foo.rb"
+ end
+ end
+
+ count = 0
+ Gem::Package::TarReader.new(gem_tar).seek("data.tar.gz") do |entry|
+ Zlib::GzipReader.wrap entry do |gzio|
+ Gem::Package::TarReader.new(gzio).seek("lib/foo.rb") do |contents_entry|
+ assert_equal "# lib/foo.rb", contents_entry.read
+ count += 1
+ end
+ end
+ end
+
+ assert_equal 1, count, "should have found one file"
+ end
end
diff --git a/test/rubygems/test_gem_package_tar_reader_entry.rb b/test/rubygems/test_gem_package_tar_reader_entry.rb
index 1be5870146..67ab7922b5 100644
--- a/test/rubygems/test_gem_package_tar_reader_entry.rb
+++ b/test/rubygems/test_gem_package_tar_reader_entry.rb
@@ -1,17 +1,17 @@
# frozen_string_literal: true
-require_relative 'package/tar_test_case'
-require 'rubygems/package'
+
+require_relative "package/tar_test_case"
+require "rubygems/package"
class TestGemPackageTarReaderEntry < Gem::Package::TarTestCase
def setup
super
- @contents = ('a'..'z').to_a.join * 100
+ @contents = ("a".."z").to_a.join * 100
@tar = String.new
@tar << tar_file_header("lib/foo", "", 0, @contents.size, Time.now)
- @tar << @contents
- @tar << "\0" * (512 - (@tar.size % 512))
+ @tar << tar_file_contents(@contents)
@entry = util_entry @tar
end
@@ -21,8 +21,39 @@ class TestGemPackageTarReaderEntry < Gem::Package::TarTestCase
super
end
- def close_util_entry(entry)
- entry.instance_variable_get(:@io).close!
+ def test_open
+ io = TempIO.new @tar
+ header = Gem::Package::TarHeader.from io
+ retval = Gem::Package::TarReader::Entry.open header, io, &:getc
+ assert_equal "a", retval
+ assert_equal @tar.size, io.pos, "should have read to end of entry"
+ ensure
+ io&.close!
+ end
+
+ def test_open_closes_entry
+ io = TempIO.new @tar
+ header = Gem::Package::TarHeader.from io
+ entry = nil
+ Gem::Package::TarReader::Entry.open header, io do |e|
+ entry = e
+ end
+ assert entry.closed?
+ assert_raise(IOError) { entry.getc }
+ ensure
+ io&.close!
+ end
+
+ def test_open_returns_entry
+ io = TempIO.new @tar
+ header = Gem::Package::TarHeader.from io
+ entry = Gem::Package::TarReader::Entry.open header, io
+ refute entry.closed?
+ assert_equal "a", entry.getc
+ assert_nil entry.close
+ assert entry.closed?
+ ensure
+ io&.close!
end
def test_bytes_read
@@ -43,19 +74,19 @@ class TestGemPackageTarReaderEntry < Gem::Package::TarTestCase
assert @entry.bytes_read
e = assert_raise(IOError) { @entry.eof? }
- assert_equal 'closed Gem::Package::TarReader::Entry', e.message
+ assert_equal "closed Gem::Package::TarReader::Entry", e.message
e = assert_raise(IOError) { @entry.getc }
- assert_equal 'closed Gem::Package::TarReader::Entry', e.message
+ assert_equal "closed Gem::Package::TarReader::Entry", e.message
e = assert_raise(IOError) { @entry.pos }
- assert_equal 'closed Gem::Package::TarReader::Entry', e.message
+ assert_equal "closed Gem::Package::TarReader::Entry", e.message
e = assert_raise(IOError) { @entry.read }
- assert_equal 'closed Gem::Package::TarReader::Entry', e.message
+ assert_equal "closed Gem::Package::TarReader::Entry", e.message
e = assert_raise(IOError) { @entry.rewind }
- assert_equal 'closed Gem::Package::TarReader::Entry', e.message
+ assert_equal "closed Gem::Package::TarReader::Entry", e.message
end
def test_closed_eh
@@ -71,7 +102,7 @@ class TestGemPackageTarReaderEntry < Gem::Package::TarTestCase
end
def test_full_name
- assert_equal 'lib/foo', @entry.full_name
+ assert_equal "lib/foo", @entry.full_name
end
def test_full_name_null
@@ -82,11 +113,11 @@ class TestGemPackageTarReaderEntry < Gem::Package::TarTestCase
@entry.full_name
end
- assert_equal 'tar is corrupt, name contains null byte', e.message
+ assert_equal "tar is corrupt, name contains null byte", e.message
end
def test_getc
- assert_equal ?a, @entry.getc
+ assert_equal "a", @entry.getc
end
def test_directory_eh
@@ -125,6 +156,18 @@ class TestGemPackageTarReaderEntry < Gem::Package::TarTestCase
assert_equal @contents, @entry.read
end
+ def test_consecutive_read
+ expected = StringIO.new(@contents)
+ assert_equal expected.read, @entry.read
+ assert_equal expected.read, @entry.read
+ end
+
+ def test_consecutive_read_bytes_past_eof
+ expected = StringIO.new(@contents)
+ assert_equal expected.read, @entry.read
+ assert_equal expected.read(1), @entry.read(1)
+ end
+
def test_read_big
assert_equal @contents, @entry.read(@contents.size * 2)
end
@@ -133,13 +176,64 @@ class TestGemPackageTarReaderEntry < Gem::Package::TarTestCase
assert_equal @contents[0...100], @entry.read(100)
end
+ def test_read_remaining
+ @entry.read(100)
+ assert_equal @contents[100..-1], @entry.read
+ end
+
def test_readpartial
+ assert_equal @contents[0...100], @entry.readpartial(100)
+ end
+
+ def test_readpartial_to_eof
+ assert_equal @contents, @entry.readpartial(4096)
+ assert @entry.eof?
+ end
+
+ def test_read_partial_buffer
+ buffer = "".b
+ @entry.readpartial(100, buffer)
+ assert_equal @contents[0...100], buffer
+ end
+
+ def test_readpartial_past_eof
+ @entry.readpartial(@contents.size)
+ assert @entry.eof?
assert_raise(EOFError) do
- @entry.read(@contents.size)
@entry.readpartial(1)
end
end
+ def test_read_corrupted_tar
+ corrupt_tar = String.new
+ corrupt_tar << tar_file_header("lib/foo", "", 0, 100, Time.now)
+ corrupt_tar << tar_file_contents("")
+ corrupt_entry = util_entry corrupt_tar
+
+ assert_equal "", corrupt_entry.read(0)
+ assert_equal "", corrupt_entry.read, "IO.read without len should return empty string (even though it's at an unpexpected EOF)"
+
+ corrupt_entry.rewind
+
+ assert_nil corrupt_entry.read(100), "IO.read with len should return nil as per IO.read docs"
+ ensure
+ close_util_entry(corrupt_entry) if corrupt_entry
+ end
+
+ def test_readpartial_corrupted_tar
+ corrupt_tar = String.new
+ corrupt_tar << tar_file_header("lib/foo", "", 0, 100, Time.now)
+ corrupt_tar << tar_file_contents("")
+
+ corrupt_entry = util_entry corrupt_tar
+
+ assert_raise EOFError do
+ corrupt_entry.readpartial(100)
+ end
+ ensure
+ close_util_entry(corrupt_entry) if corrupt_entry
+ end
+
def test_rewind
char = @entry.getc
@@ -149,4 +243,116 @@ class TestGemPackageTarReaderEntry < Gem::Package::TarTestCase
assert_equal char, @entry.getc
end
+
+ def test_seek
+ @entry.seek(50)
+ assert_equal 50, @entry.pos
+ assert_equal @contents[50..-1], @entry.read, "read remaining after seek"
+ @entry.seek(-50, IO::SEEK_CUR)
+ assert_equal @contents.size - 50, @entry.pos
+ assert_equal @contents[-50..-1], @entry.read, "read after stepping back 50 from the end"
+ @entry.seek(0, IO::SEEK_SET)
+ assert_equal 0, @entry.pos
+ assert_equal @contents, @entry.read, "read from beginning"
+ @entry.seek(-10, IO::SEEK_END)
+ assert_equal @contents.size - 10, @entry.pos
+ assert_equal @contents[-10..-1], @entry.read, "read from end"
+ end
+
+ def test_read_zero
+ expected = StringIO.new("")
+ assert_equal expected.read(0), @entry.read(0)
+ end
+
+ def test_readpartial_zero
+ expected = StringIO.new("")
+ assert_equal expected.readpartial(0), @entry.readpartial(0)
+ end
+
+ def test_zero_byte_file_read
+ zero_entry = util_entry(tar_file_header("foo", "", 0, 0, Time.now))
+ expected = StringIO.new("")
+ assert_equal expected.read, zero_entry.read
+ ensure
+ close_util_entry(zero_entry) if zero_entry
+ end
+
+ def test_zero_byte_file_readpartial
+ zero_entry = util_entry(tar_file_header("foo", "", 0, 0, Time.now))
+ expected = StringIO.new("")
+ assert_equal expected.readpartial(0), zero_entry.readpartial(0)
+ ensure
+ close_util_entry(zero_entry) if zero_entry
+ end
+
+ def test_read_from_gzip_io
+ tgz = util_gzip(@tar)
+
+ Zlib::GzipReader.wrap StringIO.new(tgz) do |gzio|
+ entry = util_entry(gzio)
+ assert_equal @contents, entry.read
+ entry.rewind
+ assert_equal @contents, entry.read, "second read after rewind should read same contents"
+ end
+ end
+
+ def test_read_from_gzip_io_with_non_zero_offset
+ contents2 = ("0".."9").to_a.join * 100
+ @tar << tar_file_header("lib/bar", "", 0, contents2.size, Time.now)
+ @tar << tar_file_contents(contents2)
+
+ tgz = util_gzip(@tar)
+
+ Zlib::GzipReader.wrap StringIO.new(tgz) do |gzio|
+ util_entry(gzio).close # skip the first entry so io.pos is not 0, preventing easy rewind
+ entry = util_entry(gzio)
+
+ assert_equal contents2, entry.read
+ entry.rewind
+ assert_equal contents2, entry.read, "second read after rewind should read same contents"
+ end
+ end
+
+ def test_seek_in_gzip_io_with_non_zero_offset
+ contents2 = ("0".."9").to_a.join * 100
+ @tar << tar_file_header("lib/bar", "", 0, contents2.size, Time.now)
+ @tar << tar_file_contents(contents2)
+
+ tgz = util_gzip(@tar)
+
+ Zlib::GzipReader.wrap StringIO.new(tgz) do |gzio|
+ util_entry(gzio).close # skip the first entry so io.pos is not 0
+ entry = util_entry(gzio)
+
+ entry.seek(50)
+ assert_equal 50, entry.pos
+ assert_equal contents2[50..-1], entry.read, "read remaining after seek"
+ entry.seek(-50, IO::SEEK_CUR)
+ assert_equal contents2.size - 50, entry.pos
+ assert_equal contents2[-50..-1], entry.read, "read after stepping back 50 from the end"
+ entry.seek(0, IO::SEEK_SET)
+ assert_equal 0, entry.pos
+ assert_equal contents2, entry.read, "read from beginning"
+ entry.seek(-10, IO::SEEK_END)
+ assert_equal contents2.size - 10, entry.pos
+ assert_equal contents2[-10..-1], entry.read, "read from end"
+ assert_equal contents2.size, entry.pos
+ end
+ end
+
+ def test_seek_in_gzip_io_corrupted
+ @tar << tar_file_header("lib/bar", "", 0, 100, Time.now)
+ @tar << tar_file_contents("")
+
+ tgz = util_gzip(@tar)
+
+ Zlib::GzipReader.wrap StringIO.new(tgz) do |gzio|
+ util_entry(gzio).close # skip the first entry so io.pos is not 0
+ entry = util_entry(gzio)
+
+ assert_raise EOFError do
+ entry.seek(50)
+ end
+ end
+ end
end
diff --git a/test/rubygems/test_gem_package_tar_writer.rb b/test/rubygems/test_gem_package_tar_writer.rb
index 31a91fa21a..751ceaca81 100644
--- a/test/rubygems/test_gem_package_tar_writer.rb
+++ b/test/rubygems/test_gem_package_tar_writer.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
-require_relative 'package/tar_test_case'
-require 'rubygems/package/tar_writer'
+
+require_relative "package/tar_test_case"
+require "rubygems/package/tar_writer"
class TestGemPackageTarWriter < Gem::Package::TarTestCase
def setup
@@ -11,7 +12,7 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase
# is not set.
Gem.instance_variable_set(:'@default_source_date_epoch', nil)
- @data = 'abcde12345'
+ @data = "abcde12345"
@io = TempIO.new
@tar_writer = Gem::Package::TarWriter.new @io
@epoch = ENV["SOURCE_DATE_EPOCH"]
@@ -27,12 +28,12 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase
end
def test_add_file
- Time.stub :now, Time.at(1458518157) do
- @tar_writer.add_file 'x', 0644 do |f|
- f.write 'a' * 10
+ Time.stub :now, Time.at(1_458_518_157) do
+ @tar_writer.add_file "x", 0o644 do |f|
+ f.write "a" * 10
end
- assert_headers_equal(tar_file_header('x', '', 0644, 10, Time.now),
+ assert_headers_equal(tar_file_header("x", "", 0o644, 10, Time.now),
@io.string[0, 512])
end
assert_equal "aaaaaaaaaa#{"\0" * 502}", @io.string[512, 512]
@@ -41,19 +42,19 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase
def test_add_file_source_date_epoch
ENV["SOURCE_DATE_EPOCH"] = "123456789"
- Time.stub :now, Time.at(1458518157) do
- @tar_writer.mkdir 'foo', 0644
+ Time.stub :now, Time.at(1_458_518_157) do
+ @tar_writer.mkdir "foo", 0o644
- assert_headers_equal tar_dir_header('foo', '', 0644, Time.at(ENV["SOURCE_DATE_EPOCH"].to_i).utc),
+ assert_headers_equal tar_dir_header("foo", "", 0o644, Time.at(ENV["SOURCE_DATE_EPOCH"].to_i).utc),
@io.string[0, 512]
end
end
def test_add_symlink
- Time.stub :now, Time.at(1458518157) do
- @tar_writer.add_symlink 'x', 'y', 0644
+ Time.stub :now, Time.at(1_458_518_157) do
+ @tar_writer.add_symlink "x", "y", 0o644
- assert_headers_equal(tar_symlink_header('x', '', 0644, Time.now, 'y'),
+ assert_headers_equal(tar_symlink_header("x", "", 0o644, Time.now, "y"),
@io.string[0, 512])
end
assert_equal 512, @io.pos
@@ -61,31 +62,31 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase
def test_add_symlink_source_date_epoch
ENV["SOURCE_DATE_EPOCH"] = "123456789"
- Time.stub :now, Time.at(1458518157) do
- @tar_writer.add_symlink 'x', 'y', 0644
+ Time.stub :now, Time.at(1_458_518_157) do
+ @tar_writer.add_symlink "x", "y", 0o644
- assert_headers_equal(tar_symlink_header('x', '', 0644, Time.at(ENV["SOURCE_DATE_EPOCH"].to_i).utc, 'y'),
+ assert_headers_equal(tar_symlink_header("x", "", 0o644, Time.at(ENV["SOURCE_DATE_EPOCH"].to_i).utc, "y"),
@io.string[0, 512])
end
end
def test_add_file_digest
- digest_algorithms = Digest::SHA1.new, Digest::SHA512.new
+ digest_algorithms = OpenSSL::Digest::SHA1.new, OpenSSL::Digest::SHA512.new
- Time.stub :now, Time.at(1458518157) do
- digests = @tar_writer.add_file_digest 'x', 0644, digest_algorithms do |io|
- io.write 'a' * 10
+ Time.stub :now, Time.at(1_458_518_157) do
+ digests = @tar_writer.add_file_digest "x", 0o644, digest_algorithms do |io|
+ io.write "a" * 10
end
- assert_equal '3495ff69d34671d1e15b33a63c1379fdedd3a32a',
- digests['SHA1'].hexdigest
- assert_equal '4714870aff6c97ca09d135834fdb58a6389a50c1' \
- '1fef8ec4afef466fb60a23ac6b7a9c92658f14df' \
- '4993d6b40a4e4d8424196afc347e97640d68de61' \
- 'e1cf14b0',
- digests['SHA512'].hexdigest
+ assert_equal "3495ff69d34671d1e15b33a63c1379fdedd3a32a",
+ digests["SHA1"].hexdigest
+ assert_equal "4714870aff6c97ca09d135834fdb58a6389a50c1" \
+ "1fef8ec4afef466fb60a23ac6b7a9c92658f14df" \
+ "4993d6b40a4e4d8424196afc347e97640d68de61" \
+ "e1cf14b0",
+ digests["SHA512"].hexdigest
- assert_headers_equal(tar_file_header('x', '', 0644, 10, Time.now),
+ assert_headers_equal(tar_file_header("x", "", 0o644, 10, Time.now),
@io.string[0, 512])
end
assert_equal "aaaaaaaaaa#{"\0" * 502}", @io.string[512, 512]
@@ -93,22 +94,22 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase
end
def test_add_file_digest_multiple
- digest_algorithms = [Digest::SHA1.new, Digest::SHA512.new]
+ digest_algorithms = [OpenSSL::Digest::SHA1.new, OpenSSL::Digest::SHA512.new]
- Time.stub :now, Time.at(1458518157) do
- digests = @tar_writer.add_file_digest 'x', 0644, digest_algorithms do |io|
- io.write 'a' * 10
+ Time.stub :now, Time.at(1_458_518_157) do
+ digests = @tar_writer.add_file_digest "x", 0o644, digest_algorithms do |io|
+ io.write "a" * 10
end
- assert_equal '3495ff69d34671d1e15b33a63c1379fdedd3a32a',
- digests['SHA1'].hexdigest
- assert_equal '4714870aff6c97ca09d135834fdb58a6389a50c1' \
- '1fef8ec4afef466fb60a23ac6b7a9c92658f14df' \
- '4993d6b40a4e4d8424196afc347e97640d68de61' \
- 'e1cf14b0',
- digests['SHA512'].hexdigest
+ assert_equal "3495ff69d34671d1e15b33a63c1379fdedd3a32a",
+ digests["SHA1"].hexdigest
+ assert_equal "4714870aff6c97ca09d135834fdb58a6389a50c1" \
+ "1fef8ec4afef466fb60a23ac6b7a9c92658f14df" \
+ "4993d6b40a4e4d8424196afc347e97640d68de61" \
+ "e1cf14b0",
+ digests["SHA512"].hexdigest
- assert_headers_equal(tar_file_header('x', '', 0644, 10, Time.now),
+ assert_headers_equal(tar_file_header("x", "", 0o644, 10, Time.now),
@io.string[0, 512])
end
assert_equal "aaaaaaaaaa#{"\0" * 502}", @io.string[512, 512]
@@ -116,26 +117,26 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase
end
def test_add_file_signer
- pend 'openssl is missing' unless Gem::HAVE_OPENSSL
+ pend "openssl is missing" unless Gem::HAVE_OPENSSL
signer = Gem::Security::Signer.new PRIVATE_KEY, [PUBLIC_CERT]
- Time.stub :now, Time.at(1458518157) do
- @tar_writer.add_file_signed 'x', 0644, signer do |io|
- io.write 'a' * 10
+ Time.stub :now, Time.at(1_458_518_157) do
+ @tar_writer.add_file_signed "x", 0o644, signer do |io|
+ io.write "a" * 10
end
- assert_headers_equal(tar_file_header('x', '', 0644, 10, Time.now),
+ assert_headers_equal(tar_file_header("x", "", 0o644, 10, Time.now),
@io.string[0, 512])
assert_equal "aaaaaaaaaa#{"\0" * 502}", @io.string[512, 512]
digest = signer.digest_algorithm.new
- digest.update 'a' * 10
+ digest.update "a" * 10
signature = signer.sign digest.digest
- assert_headers_equal(tar_file_header('x.sig', '', 0444, signature.length,
+ assert_headers_equal(tar_file_header("x.sig", "", 0o444, signature.length,
Time.now),
@io.string[1024, 512])
assert_equal "#{signature}#{"\0" * (512 - signature.length)}",
@@ -148,12 +149,12 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase
def test_add_file_signer_empty
signer = Gem::Security::Signer.new nil, nil
- Time.stub :now, Time.at(1458518157) do
- @tar_writer.add_file_signed 'x', 0644, signer do |io|
- io.write 'a' * 10
+ Time.stub :now, Time.at(1_458_518_157) do
+ @tar_writer.add_file_signed "x", 0o644, signer do |io|
+ io.write "a" * 10
end
- assert_headers_equal(tar_file_header('x', '', 0644, 10, Time.now),
+ assert_headers_equal(tar_file_header("x", "", 0o644, 10, Time.now),
@io.string[0, 512])
end
assert_equal "aaaaaaaaaa#{"\0" * 502}", @io.string[512, 512]
@@ -162,12 +163,12 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase
end
def test_add_file_simple
- Time.stub :now, Time.at(1458518157) do
- @tar_writer.add_file_simple 'x', 0644, 10 do |io|
+ Time.stub :now, Time.at(1_458_518_157) do
+ @tar_writer.add_file_simple "x", 0o644, 10 do |io|
io.write "a" * 10
end
- assert_headers_equal(tar_file_header('x', '', 0644, 10, Time.now),
+ assert_headers_equal(tar_file_header("x", "", 0o644, 10, Time.now),
@io.string[0, 512])
assert_equal "aaaaaaaaaa#{"\0" * 502}", @io.string[512, 512]
@@ -177,21 +178,21 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase
def test_add_file_simple_source_date_epoch
ENV["SOURCE_DATE_EPOCH"] = "123456789"
- Time.stub :now, Time.at(1458518157) do
- @tar_writer.add_file_simple 'x', 0644, 10 do |io|
+ Time.stub :now, Time.at(1_458_518_157) do
+ @tar_writer.add_file_simple "x", 0o644, 10 do |io|
io.write "a" * 10
end
- assert_headers_equal(tar_file_header('x', '', 0644, 10, Time.at(ENV["SOURCE_DATE_EPOCH"].to_i).utc),
+ assert_headers_equal(tar_file_header("x", "", 0o644, 10, Time.at(ENV["SOURCE_DATE_EPOCH"].to_i).utc),
@io.string[0, 512])
end
end
def test_add_file_simple_padding
- Time.stub :now, Time.at(1458518157) do
- @tar_writer.add_file_simple 'x', 0, 100
+ Time.stub :now, Time.at(1_458_518_157) do
+ @tar_writer.add_file_simple "x", 0, 100
- assert_headers_equal tar_file_header('x', '', 0, 100, Time.now),
+ assert_headers_equal tar_file_header("x", "", 0, 100, Time.now),
@io.string[0, 512]
end
@@ -222,34 +223,34 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase
e = assert_raise IOError do
@tar_writer.close
end
- assert_equal 'closed Gem::Package::TarWriter', e.message
+ 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
+ assert_equal "closed Gem::Package::TarWriter", e.message
e = assert_raise IOError do
- @tar_writer.add_file 'x', 0
+ @tar_writer.add_file "x", 0
end
- assert_equal 'closed Gem::Package::TarWriter', e.message
+ assert_equal "closed Gem::Package::TarWriter", e.message
e = assert_raise IOError do
- @tar_writer.add_file_simple 'x', 0, 0
+ @tar_writer.add_file_simple "x", 0, 0
end
- assert_equal 'closed Gem::Package::TarWriter', e.message
+ assert_equal "closed Gem::Package::TarWriter", e.message
e = assert_raise IOError do
- @tar_writer.mkdir 'x', 0
+ @tar_writer.mkdir "x", 0
end
- assert_equal 'closed Gem::Package::TarWriter', e.message
+ assert_equal "closed Gem::Package::TarWriter", e.message
end
def test_mkdir
- Time.stub :now, Time.at(1458518157) do
- @tar_writer.mkdir 'foo', 0644
+ Time.stub :now, Time.at(1_458_518_157) do
+ @tar_writer.mkdir "foo", 0o644
- assert_headers_equal tar_dir_header('foo', '', 0644, Time.now),
+ assert_headers_equal tar_dir_header("foo", "", 0o644, Time.now),
@io.string[0, 512]
assert_equal 512, @io.pos
@@ -258,43 +259,43 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase
def test_mkdir_source_date_epoch
ENV["SOURCE_DATE_EPOCH"] = "123456789"
- Time.stub :now, Time.at(1458518157) do
- @tar_writer.mkdir 'foo', 0644
+ Time.stub :now, Time.at(1_458_518_157) do
+ @tar_writer.mkdir "foo", 0o644
- assert_headers_equal tar_dir_header('foo', '', 0644, Time.at(ENV["SOURCE_DATE_EPOCH"].to_i).utc),
+ assert_headers_equal tar_dir_header("foo", "", 0o644, Time.at(ENV["SOURCE_DATE_EPOCH"].to_i).utc),
@io.string[0, 512]
end
end
def test_split_name
- assert_equal ['b' * 100, 'a' * 155],
- @tar_writer.split_name("#{'a' * 155}/#{'b' * 100}")
+ 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")
+ assert_equal ["#{"qwer/" * 19}bla", "a" * 151],
+ @tar_writer.split_name("#{"a" * 151}/#{"qwer/" * 19}bla")
names = [
- ([''] + ['123456789'] * 9 + ['1234567890']).join('/'), # 101 bytes (several pieces)
- (['123456789'] * 9 + ['1234567890'] + ['']).join('/'), # 101 bytes (several pieces)
- '/' * 99,
- '/' * 100,
- '/' * 101,
- '/' * 102,
+ ([""] + ["123456789"] * 9 + ["1234567890"]).join("/"), # 101 bytes (several pieces)
+ (["123456789"] * 9 + ["1234567890"] + [""]).join("/"), # 101 bytes (several pieces)
+ "/" * 99,
+ "/" * 100,
+ "/" * 101,
+ "/" * 102,
]
names.each do |name|
newname, prefix = @tar_writer.split_name(name)
- assert(!(newname.empty?), "split_name() returned empty name")
+ assert(!newname.empty?, "split_name() returned empty name")
assert(newname.bytesize <= 100, "split_name() returned name longer than 100 bytes: '#{newname}' for '#{name}'")
assert(prefix.bytesize <= 155, "split_name() returned prefix longer than 155 bytes: '#{prefix}' for '#{name}'")
- newname = [prefix, newname].join('/') unless prefix.empty?
+ newname = [prefix, newname].join("/") unless prefix.empty?
assert_equal name, newname
end
end
def test_split_name_too_long_name
- name = File.join 'a', 'b' * 100
- assert_equal ['b' * 100, 'a'], @tar_writer.split_name(name)
+ name = File.join "a", "b" * 100
+ assert_equal ["b" * 100, "a"], @tar_writer.split_name(name)
- name = File.join 'a', 'b' * 101
+ name = File.join "a", "b" * 101
exception = assert_raise Gem::Package::TooLongFileName do
@tar_writer.split_name name
end
@@ -302,7 +303,7 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase
# note, GNU tar 1.28 is unable to handle this case too,
# tested with "tar --format=ustar -cPf /tmp/foo.tartar -- /aaaaaa....a"
- name = '/' + 'a' * 100
+ name = "/" + "a" * 100
exception = assert_raise Gem::Package::TooLongFileName do
@tar_writer.split_name name
end
@@ -310,10 +311,10 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase
end
def test_split_name_too_long_prefix
- name = File.join 'a' * 155, 'b'
- assert_equal ['b', 'a' * 155], @tar_writer.split_name(name)
+ name = File.join "a" * 155, "b"
+ assert_equal ["b", "a" * 155], @tar_writer.split_name(name)
- name = File.join 'a' * 156, 'b'
+ name = File.join "a" * 156, "b"
exception = assert_raise Gem::Package::TooLongFileName do
@tar_writer.split_name name
end
@@ -321,7 +322,7 @@ class TestGemPackageTarWriter < Gem::Package::TarTestCase
end
def test_split_name_too_long_total
- name = 'a' * 257
+ name = "a" * 257
exception = assert_raise Gem::Package::TooLongFileName do
@tar_writer.split_name name
end
diff --git a/test/rubygems/test_gem_package_task.rb b/test/rubygems/test_gem_package_task.rb
index 0cedfe56eb..6f322ad61e 100644
--- a/test/rubygems/test_gem_package_task.rb
+++ b/test/rubygems/test_gem_package_task.rb
@@ -1,15 +1,12 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems'
+
+require_relative "helper"
+require "rubygems"
begin
- require 'rubygems/package_task'
+ require "rubygems/package_task"
rescue LoadError => e
- raise unless e.path == 'rake/packagetask'
-end
-
-unless defined?(Rake::PackageTask)
- warn 'Skipping Gem::PackageTask tests. rake not found.'
+ raise unless e.path == "rake/packagetask"
end
class TestGemPackageTask < Gem::TestCase
@@ -23,7 +20,7 @@ class TestGemPackageTask < Gem::TestCase
g.authors = %w[author]
g.files = %w[x]
- g.summary = 'summary'
+ g.summary = "summary"
end
Rake.application = Rake::Application.new
@@ -35,12 +32,12 @@ class TestGemPackageTask < Gem::TestCase
assert_equal %w[x y], pkg.package_files
Dir.chdir @tempdir do
- FileUtils.touch 'x'
- FileUtils.touch 'y'
+ FileUtils.touch "x"
+ FileUtils.touch "y"
- Rake.application['package'].invoke
+ Rake.application["package"].invoke
- assert_path_exist 'pkg/pkgr-1.2.3.gem'
+ assert_path_exist "pkg/pkgr-1.2.3.gem"
end
ensure
RakeFileUtils.verbose_flag = original_rake_fileutils_verbosity
@@ -53,7 +50,7 @@ class TestGemPackageTask < Gem::TestCase
g.authors = %w[author]
g.files = %w[x]
- g.summary = 'summary'
+ g.summary = "summary"
end
_, err = capture_output do
@@ -66,10 +63,10 @@ class TestGemPackageTask < Gem::TestCase
assert_equal %w[x y], pkg.package_files
Dir.chdir @tempdir do
- FileUtils.touch 'x'
- FileUtils.touch 'y'
+ FileUtils.touch "x"
+ FileUtils.touch "y"
- Rake.application['package'].invoke
+ Rake.application["package"].invoke
end
end
@@ -104,14 +101,14 @@ class TestGemPackageTask < Gem::TestCase
def test_package_dir_path
gem = Gem::Specification.new do |g|
- g.name = 'nokogiri'
- g.version = '1.5.0'
- g.platform = 'java'
+ g.name = "nokogiri"
+ g.version = "1.5.0"
+ g.platform = "java"
end
pkg = Gem::PackageTask.new gem
pkg.define
- assert_equal 'pkg/nokogiri-1.5.0-java', pkg.package_dir_path
+ assert_equal "pkg/nokogiri-1.5.0-java", pkg.package_dir_path
end
end if defined?(Rake::PackageTask)
diff --git a/test/rubygems/test_gem_path_support.rb b/test/rubygems/test_gem_path_support.rb
index 394cba2b7f..8720bcf858 100644
--- a/test/rubygems/test_gem_path_support.rb
+++ b/test/rubygems/test_gem_path_support.rb
@@ -1,7 +1,8 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems'
-require 'fileutils'
+
+require_relative "helper"
+require "rubygems"
+require "fileutils"
class TestGemPathSupport < Gem::TestCase
def setup
@@ -25,7 +26,7 @@ class TestGemPathSupport < Gem::TestCase
assert_equal File.join(@tempdir, "foo"), ps.home
- expected = ENV["GEM_PATH"].split(File::PATH_SEPARATOR) + [File.join(@tempdir, 'foo')]
+ expected = ENV["GEM_PATH"].split(File::PATH_SEPARATOR) + [File.join(@tempdir, "foo")]
assert_equal expected, ps.path
end
@@ -45,8 +46,8 @@ class TestGemPathSupport < Gem::TestCase
assert_equal ENV["GEM_HOME"], ps.home
expected = [
- File.join(@tempdir, 'foo'),
- File.join(@tempdir, 'bar'),
+ File.join(@tempdir, "foo"),
+ File.join(@tempdir, "bar"),
ENV["GEM_HOME"],
]
@@ -65,8 +66,8 @@ class TestGemPathSupport < Gem::TestCase
assert_equal ENV["GEM_HOME"], ps.home
expected = [
- File.join(@tempdir, 'foo'),
- File.join(@tempdir, 'bar'),
+ File.join(@tempdir, "foo"),
+ File.join(@tempdir, "bar"),
] + Gem.default_path << ENV["GEM_HOME"]
assert_equal expected, ps.path
@@ -83,8 +84,8 @@ class TestGemPathSupport < Gem::TestCase
assert_equal ENV["GEM_HOME"], ps.home
expected = [
- File.join(@tempdir, 'foo'),
- File.join(@tempdir, 'bar'),
+ File.join(@tempdir, "foo"),
+ File.join(@tempdir, "bar"),
] + Gem.default_path << ENV["GEM_HOME"]
assert_equal expected, ps.path
@@ -97,7 +98,7 @@ class TestGemPathSupport < Gem::TestCase
assert_equal File.join(@tempdir, "foo"), ps.home
- expected = [File.join(@tempdir, 'foo'), File.join(@tempdir, 'bar')]
+ expected = [File.join(@tempdir, "foo"), File.join(@tempdir, "bar")]
assert_equal expected, ps.path
end
end
@@ -108,12 +109,12 @@ class TestGemPathSupport < Gem::TestCase
ps = Gem::PathSupport.new ENV
assert_equal Gem.default_spec_cache_dir, ps.spec_cache_dir
- ENV["GEM_SPEC_CACHE"] = 'bar'
+ ENV["GEM_SPEC_CACHE"] = "bar"
ps = Gem::PathSupport.new ENV
assert_equal ENV["GEM_SPEC_CACHE"], ps.spec_cache_dir
- ENV["GEM_SPEC_CACHE"] = File.join @tempdir, 'spec_cache'
+ ENV["GEM_SPEC_CACHE"] = File.join @tempdir, "spec_cache"
ps = Gem::PathSupport.new "GEM_SPEC_CACHE" => "foo"
assert_equal "foo", ps.spec_cache_dir
@@ -126,7 +127,7 @@ class TestGemPathSupport < Gem::TestCase
begin
File.symlink(dir, symlink)
rescue NotImplementedError, SystemCallError
- pend 'symlinks not supported'
+ pend "symlinks not supported"
end
not_existing = "#{@tempdir}/does_not_exist"
path = "#{symlink}#{File::PATH_SEPARATOR}#{not_existing}"
diff --git a/test/rubygems/test_gem_platform.rb b/test/rubygems/test_gem_platform.rb
index 8029035db1..070c8007bc 100644
--- a/test/rubygems/test_gem_platform.rb
+++ b/test/rubygems/test_gem_platform.rb
@@ -1,47 +1,48 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/platform'
-require 'rbconfig'
+
+require_relative "helper"
+require "rubygems/platform"
+require "rbconfig"
class TestGemPlatform < Gem::TestCase
def test_self_local
- util_set_arch 'i686-darwin8.10.1'
+ util_set_arch "i686-darwin8.10.1"
assert_equal Gem::Platform.new(%w[x86 darwin 8]), Gem::Platform.local
end
def test_self_match
Gem::Deprecate.skip_during do
- 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'
+ 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
end
def test_self_match_gem?
- assert Gem::Platform.match_gem?(nil, 'json'), 'nil == ruby'
- assert Gem::Platform.match_gem?(Gem::Platform.local, 'json'), 'exact match'
- assert Gem::Platform.match_gem?(Gem::Platform.local.to_s, 'json'), '=~ match'
- assert Gem::Platform.match_gem?(Gem::Platform::RUBY, 'json'), 'ruby'
+ assert Gem::Platform.match_gem?(nil, "json"), "nil == ruby"
+ assert Gem::Platform.match_gem?(Gem::Platform.local, "json"), "exact match"
+ assert Gem::Platform.match_gem?(Gem::Platform.local.to_s, "json"), "=~ match"
+ assert Gem::Platform.match_gem?(Gem::Platform::RUBY, "json"), "ruby"
end
def test_self_match_spec?
- make_spec = -> platform do
- util_spec 'mygem-for-platform-match_spec', '1' do |s|
+ make_spec = ->(platform) do
+ util_spec "mygem-for-platform-match_spec", "1" do |s|
s.platform = platform
end
end
- assert Gem::Platform.match_spec?(make_spec.call(nil)), 'nil == ruby'
- assert Gem::Platform.match_spec?(make_spec.call(Gem::Platform.local)), 'exact match'
- assert Gem::Platform.match_spec?(make_spec.call(Gem::Platform.local.to_s)), '=~ match'
- assert Gem::Platform.match_spec?(make_spec.call(Gem::Platform::RUBY)), 'ruby'
+ assert Gem::Platform.match_spec?(make_spec.call(nil)), "nil == ruby"
+ assert Gem::Platform.match_spec?(make_spec.call(Gem::Platform.local)), "exact match"
+ assert Gem::Platform.match_spec?(make_spec.call(Gem::Platform.local.to_s)), "=~ match"
+ assert Gem::Platform.match_spec?(make_spec.call(Gem::Platform::RUBY)), "ruby"
end
def test_self_match_spec_with_match_gem_override
- make_spec = -> name, platform do
- util_spec name, '1' do |s|
+ make_spec = ->(name, platform) do
+ util_spec name, "1" do |s|
s.platform = platform
end
end
@@ -50,7 +51,7 @@ class TestGemPlatform < Gem::TestCase
alias_method :original_match_gem?, :match_gem?
def match_gem?(platform, gem_name)
# e.g., sassc and libv8 are such gems, their native extensions do not use the Ruby C API
- if gem_name == 'gem-with-ruby-impl-independent-precompiled-ext'
+ if gem_name == "gem-with-ruby-impl-independent-precompiled-ext"
match_platforms?(platform, [Gem::Platform::RUBY, Gem::Platform.local])
else
match_platforms?(platform, Gem.platforms)
@@ -61,16 +62,16 @@ class TestGemPlatform < Gem::TestCase
platforms = Gem.platforms
Gem.platforms = [Gem::Platform::RUBY]
begin
- assert_equal true, Gem::Platform.match_spec?(make_spec.call('mygem', Gem::Platform::RUBY))
- assert_equal false, Gem::Platform.match_spec?(make_spec.call('mygem', Gem::Platform.local))
+ assert_equal true, Gem::Platform.match_spec?(make_spec.call("mygem", Gem::Platform::RUBY))
+ assert_equal false, Gem::Platform.match_spec?(make_spec.call("mygem", Gem::Platform.local))
- name = 'gem-with-ruby-impl-independent-precompiled-ext'
+ name = "gem-with-ruby-impl-independent-precompiled-ext"
assert_equal true, Gem::Platform.match_spec?(make_spec.call(name, Gem::Platform.local))
ensure
Gem.platforms = platforms
class << Gem::Platform
remove_method :match_gem?
- alias_method :match_gem?, :original_match_gem? # rubocop:disable Lint/DuplicateMethods
+ alias_method :match_gem?, :original_match_gem?
remove_method :original_match_gem?
end
end
@@ -80,135 +81,144 @@ class TestGemPlatform < Gem::TestCase
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('')
+ 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],
- 'universal-dotnet' => ['universal', 'dotnet', nil],
- 'universal-dotnet2.0' => ['universal', 'dotnet', '2.0'],
- 'universal-dotnet4.0' => ['universal', 'dotnet', '4.0'],
- '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'],
- 'universal-macruby' => ['universal', 'macruby', nil],
- '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-freebsd' => ['x86', 'freebsd', nil],
- 'universal-freebsd' => ['universal', 'freebsd', nil],
- '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],
- 'x64-mingw-ucrt' => ['x64', 'mingw', 'ucrt'],
- '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-linux-musl' => ['x86_64', 'linux', 'musl'],
- 'x86_64-openbsd3.9' => ['x86_64', 'openbsd', '3.9'],
- 'x86_64-openbsd4.0' => ['x86_64', 'openbsd', '4.0'],
- 'x86_64-openbsd' => ['x86_64', 'openbsd', nil],
+ "amd64-freebsd6" => ["amd64", "freebsd", "6"],
+ "java" => [nil, "java", nil],
+ "jruby" => [nil, "java", nil],
+ "universal-dotnet" => ["universal", "dotnet", nil],
+ "universal-dotnet2.0" => ["universal", "dotnet", "2.0"],
+ "universal-dotnet4.0" => ["universal", "dotnet", "4.0"],
+ "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"],
+ "universal-macruby" => ["universal", "macruby", nil],
+ "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-freebsd" => ["x86", "freebsd", nil],
+ "universal-freebsd" => ["universal", "freebsd", nil],
+ "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", "gnu"],
+ "i386-linux-gnu" => ["x86", "linux", "gnu"],
+ "i386-mingw32" => ["x86", "mingw32", nil],
+ "x64-mingw-ucrt" => ["x64", "mingw", "ucrt"],
+ "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-linux-gnu" => ["x86_64", "linux", "gnu"],
+ "x86_64-linux-musl" => ["x86_64", "linux", "musl"],
+ "x86_64-linux-uclibc" => ["x86_64", "linux", "uclibc"],
+ "arm-linux-eabi" => ["arm", "linux", "eabi"],
+ "arm-linux-gnueabi" => ["arm", "linux", "gnueabi"],
+ "arm-linux-musleabi" => ["arm", "linux", "musleabi"],
+ "arm-linux-uclibceabi" => ["arm", "linux", "uclibceabi"],
+ "x86_64-openbsd3.9" => ["x86_64", "openbsd", "3.9"],
+ "x86_64-openbsd4.0" => ["x86_64", "openbsd", "4.0"],
+ "x86_64-openbsd" => ["x86_64", "openbsd", nil],
+ "wasm32-wasi" => ["wasm32", "wasi", nil],
+ "wasm32-wasip1" => ["wasm32", "wasi", nil],
+ "wasm32-wasip2" => ["wasm32", "wasi", nil],
}
test_cases.each do |arch, expected|
platform = Gem::Platform.new arch
assert_equal expected, platform.to_a, arch.inspect
+ assert_equal expected, Gem::Platform.new(platform.to_s).to_a, arch.inspect
end
end
def test_initialize_command_line
- expected = ['x86', 'mswin32', nil]
+ expected = ["x86", "mswin32", nil]
- platform = Gem::Platform.new 'i386-mswin32'
+ platform = Gem::Platform.new "i386-mswin32"
- assert_equal expected, platform.to_a, 'i386-mswin32'
+ assert_equal expected, platform.to_a, "i386-mswin32"
- expected = ['x86', 'mswin32', '80']
+ expected = ["x86", "mswin32", "80"]
- platform = Gem::Platform.new 'i386-mswin32-80'
+ platform = Gem::Platform.new "i386-mswin32-80"
- assert_equal expected, platform.to_a, 'i386-mswin32-80'
+ assert_equal expected, platform.to_a, "i386-mswin32-80"
- expected = ['x86', 'solaris', '2.10']
+ expected = ["x86", "solaris", "2.10"]
- platform = Gem::Platform.new 'i386-solaris-2.10'
+ platform = Gem::Platform.new "i386-solaris-2.10"
- assert_equal expected, platform.to_a, 'i386-solaris-2.10'
+ assert_equal expected, platform.to_a, "i386-solaris-2.10"
end
def test_initialize_mswin32_vc6
- orig_RUBY_SO_NAME = RbConfig::CONFIG['RUBY_SO_NAME']
- RbConfig::CONFIG['RUBY_SO_NAME'] = 'msvcrt-ruby18'
+ orig_ruby_so_name = RbConfig::CONFIG["RUBY_SO_NAME"]
+ RbConfig::CONFIG["RUBY_SO_NAME"] = "msvcrt-ruby18"
- expected = ['x86', 'mswin32', nil]
+ expected = ["x86", "mswin32", nil]
- platform = Gem::Platform.new 'i386-mswin32'
+ platform = Gem::Platform.new "i386-mswin32"
- assert_equal expected, platform.to_a, 'i386-mswin32 VC6'
+ assert_equal expected, platform.to_a, "i386-mswin32 VC6"
ensure
- if orig_RUBY_SO_NAME
- RbConfig::CONFIG['RUBY_SO_NAME'] = orig_RUBY_SO_NAME
+ if orig_ruby_so_name
+ RbConfig::CONFIG["RUBY_SO_NAME"] = orig_ruby_so_name
else
- RbConfig::CONFIG.delete 'RUBY_SO_NAME'
+ RbConfig::CONFIG.delete "RUBY_SO_NAME"
end
end
def test_initialize_platform
- platform = Gem::Platform.new 'cpu-my_platform1'
+ platform = Gem::Platform.new "cpu-my_platform1"
- assert_equal 'cpu', platform.cpu
- assert_equal 'my_platform', platform.os
- assert_equal '1', platform.version
+ 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
+ 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?
- assert_equal 'x86-mswin32-60', Gem::Platform.local.to_s
+ if Gem.win_platform?
+ assert_equal "x86-mswin32-60", Gem::Platform.local.to_s
else
- assert_equal 'x86-darwin-8', Gem::Platform.local.to_s
+ assert_equal "x86-darwin-8", Gem::Platform.local.to_s
end
end
@@ -225,136 +235,253 @@ class TestGemPlatform < Gem::TestCase
my = Gem::Platform.new %w[cpu my_platform 1]
other = Gem::Platform.new %w[cpu other_platform 1]
- assert(my === my)
+ assert(my === my) # rubocop:disable Lint/BinaryOperatorWithIdenticalOperands
refute(other === my)
refute(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')
- refute((x86_darwin8 === Gem::Platform.local), 'powerpc =~ universal')
-
- util_set_arch 'i686-darwin8'
- refute((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')
+ 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")
+ refute((x86_darwin8 === Gem::Platform.local), "powerpc =~ universal")
+
+ util_set_arch "i686-darwin8"
+ refute((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_nil_cpu_arch_is_treated_as_universal
- with_nil_arch = Gem::Platform.new [nil, 'mingw32']
- with_uni_arch = Gem::Platform.new ['universal', 'mingw32']
- with_x86_arch = Gem::Platform.new ['x86', 'mingw32']
-
- assert((with_nil_arch === with_uni_arch), 'nil =~ universal')
- assert((with_uni_arch === with_nil_arch), 'universal =~ nil')
- assert((with_nil_arch === with_x86_arch), 'nil =~ x86')
- assert((with_x86_arch === with_nil_arch), 'x86 =~ nil')
+ with_nil_arch = Gem::Platform.new [nil, "mingw32"]
+ with_uni_arch = Gem::Platform.new ["universal", "mingw32"]
+ with_x86_arch = Gem::Platform.new ["x86", "mingw32"]
+
+ assert((with_nil_arch === with_uni_arch), "nil =~ universal")
+ assert((with_uni_arch === with_nil_arch), "universal =~ nil")
+ assert((with_nil_arch === with_x86_arch), "nil =~ x86")
+ assert((with_x86_arch === with_nil_arch), "x86 =~ nil")
+ end
+
+ def test_nil_version_is_treated_as_any_version
+ x86_darwin_8 = Gem::Platform.new "i686-darwin8.0"
+ x86_darwin_nil = Gem::Platform.new "i686-darwin"
+
+ assert((x86_darwin_8 === x86_darwin_nil), "8.0 =~ nil")
+ assert((x86_darwin_nil === x86_darwin_8), "nil =~ 8.0")
+ end
+
+ def test_nil_version_is_stricter_for_linux_os
+ x86_linux = Gem::Platform.new "i686-linux"
+ x86_linux_gnu = Gem::Platform.new "i686-linux-gnu"
+ x86_linux_musl = Gem::Platform.new "i686-linux-musl"
+ x86_linux_uclibc = Gem::Platform.new "i686-linux-uclibc"
+
+ # a naked linux runtime is implicit gnu, as it represents the common glibc-linked runtime
+ assert(x86_linux === x86_linux_gnu, "linux =~ linux-gnu")
+ assert(x86_linux_gnu === x86_linux, "linux-gnu =~ linux")
+
+ # musl and explicit gnu should differ
+ refute(x86_linux_gnu === x86_linux_musl, "linux-gnu =~ linux-musl")
+ refute(x86_linux_musl === x86_linux_gnu, "linux-musl =~ linux-gnu")
+
+ # explicit libc differ
+ refute(x86_linux_uclibc === x86_linux_musl, "linux-uclibc =~ linux-musl")
+ refute(x86_linux_musl === x86_linux_uclibc, "linux-musl =~ linux-uclibc")
+
+ # musl host runtime accepts libc-generic or statically linked gems...
+ assert(x86_linux === x86_linux_musl, "linux =~ linux-musl")
+ # ...but implicit gnu runtime generally does not accept musl-specific gems
+ refute(x86_linux_musl === x86_linux, "linux-musl =~ linux")
+
+ # other libc are not glibc compatible
+ refute(x86_linux === x86_linux_uclibc, "linux =~ linux-uclibc")
+ refute(x86_linux_uclibc === x86_linux, "linux-uclibc =~ linux")
+ end
+
+ def test_eabi_version_is_stricter_for_linux_os
+ arm_linux_eabi = Gem::Platform.new "arm-linux-eabi"
+ arm_linux_gnueabi = Gem::Platform.new "arm-linux-gnueabi"
+ arm_linux_musleabi = Gem::Platform.new "arm-linux-musleabi"
+ arm_linux_uclibceabi = Gem::Platform.new "arm-linux-uclibceabi"
+
+ # a naked linux runtime is implicit gnu, as it represents the common glibc-linked runtime
+ assert(arm_linux_eabi === arm_linux_gnueabi, "linux-eabi =~ linux-gnueabi")
+ assert(arm_linux_gnueabi === arm_linux_eabi, "linux-gnueabi =~ linux-eabi")
+
+ # musl and explicit gnu should differ
+ refute(arm_linux_gnueabi === arm_linux_musleabi, "linux-gnueabi =~ linux-musleabi")
+ refute(arm_linux_musleabi === arm_linux_gnueabi, "linux-musleabi =~ linux-gnueabi")
+
+ # explicit libc differ
+ refute(arm_linux_uclibceabi === arm_linux_musleabi, "linux-uclibceabi =~ linux-musleabi")
+ refute(arm_linux_musleabi === arm_linux_uclibceabi, "linux-musleabi =~ linux-uclibceabi")
+
+ # musl host runtime accepts libc-generic or statically linked gems...
+ assert(arm_linux_eabi === arm_linux_musleabi, "linux-eabi =~ linux-musleabi")
+ # ...but implicit gnu runtime generally does not accept musl-specific gems
+ refute(arm_linux_musleabi === arm_linux_eabi, "linux-musleabi =~ linux-eabi")
+
+ # other libc are not glibc compatible
+ refute(arm_linux_eabi === arm_linux_uclibceabi, "linux-eabi =~ linux-uclibceabi")
+ refute(arm_linux_uclibceabi === arm_linux_eabi, "linux-uclibceabi =~ linux-eabi")
+ end
+
+ def test_eabi_and_nil_version_combination_strictness
+ arm_linux = Gem::Platform.new "arm-linux"
+ arm_linux_eabi = Gem::Platform.new "arm-linux-eabi"
+ arm_linux_eabihf = Gem::Platform.new "arm-linux-eabihf"
+ arm_linux_gnueabi = Gem::Platform.new "arm-linux-gnueabi"
+ arm_linux_gnueabihf = Gem::Platform.new "arm-linux-gnueabihf"
+ arm_linux_musleabi = Gem::Platform.new "arm-linux-musleabi"
+ arm_linux_musleabihf = Gem::Platform.new "arm-linux-musleabihf"
+ arm_linux_uclibceabi = Gem::Platform.new "arm-linux-uclibceabi"
+ arm_linux_uclibceabihf = Gem::Platform.new "arm-linux-uclibceabihf"
+
+ # generic arm host runtime with eabi modifier accepts generic arm gems
+ assert(arm_linux === arm_linux_eabi, "arm-linux =~ arm-linux-eabi")
+ assert(arm_linux === arm_linux_eabihf, "arm-linux =~ arm-linux-eabihf")
+
+ # explicit gnu arm host runtime with eabi modifier accepts generic arm gems
+ assert(arm_linux === arm_linux_gnueabi, "arm-linux =~ arm-linux-gnueabi")
+ assert(arm_linux === arm_linux_gnueabihf, "arm-linux =~ arm-linux-gnueabihf")
+
+ # musl arm host runtime accepts libc-generic or statically linked gems...
+ assert(arm_linux === arm_linux_musleabi, "arm-linux =~ arm-linux-musleabi")
+ assert(arm_linux === arm_linux_musleabihf, "arm-linux =~ arm-linux-musleabihf")
+
+ # other libc arm hosts are not glibc compatible
+ refute(arm_linux === arm_linux_uclibceabi, "arm-linux =~ arm-linux-uclibceabi")
+ refute(arm_linux === arm_linux_uclibceabihf, "arm-linux =~ arm-linux-uclibceabihf")
end
def test_equals3_cpu_arm
- arm = Gem::Platform.new 'arm-linux'
- armv5 = Gem::Platform.new 'armv5-linux'
- armv7 = Gem::Platform.new 'armv7-linux'
-
- util_set_arch 'armv5-linux'
- assert((arm === Gem::Platform.local), 'arm === armv5')
- assert((armv5 === Gem::Platform.local), 'armv5 === armv5')
- refute((armv7 === Gem::Platform.local), 'armv7 === armv5')
- refute((Gem::Platform.local === arm), 'armv5 === arm')
-
- util_set_arch 'armv7-linux'
- assert((arm === Gem::Platform.local), 'arm === armv7')
- refute((armv5 === Gem::Platform.local), 'armv5 === armv7')
- assert((armv7 === Gem::Platform.local), 'armv7 === armv7')
- refute((Gem::Platform.local === arm), 'armv7 === arm')
+ arm = Gem::Platform.new "arm-linux"
+ armv5 = Gem::Platform.new "armv5-linux"
+ armv7 = Gem::Platform.new "armv7-linux"
+ arm64 = Gem::Platform.new "arm64-linux"
+
+ util_set_arch "armv5-linux"
+ assert((arm === Gem::Platform.local), "arm === armv5")
+ assert((armv5 === Gem::Platform.local), "armv5 === armv5")
+ refute((armv7 === Gem::Platform.local), "armv7 === armv5")
+ refute((arm64 === Gem::Platform.local), "arm64 === armv5")
+ refute((Gem::Platform.local === arm), "armv5 === arm")
+
+ util_set_arch "armv7-linux"
+ assert((arm === Gem::Platform.local), "arm === armv7")
+ refute((armv5 === Gem::Platform.local), "armv5 === armv7")
+ assert((armv7 === Gem::Platform.local), "armv7 === armv7")
+ refute((arm64 === Gem::Platform.local), "arm64 === armv7")
+ refute((Gem::Platform.local === arm), "armv7 === arm")
+
+ util_set_arch "arm64-linux"
+ refute((arm === Gem::Platform.local), "arm === arm64")
+ refute((armv5 === Gem::Platform.local), "armv5 === arm64")
+ refute((armv7 === Gem::Platform.local), "armv7 === arm64")
+ assert((arm64 === Gem::Platform.local), "arm64 === arm64")
+ end
+
+ def test_equals3_universal_mingw
+ uni_mingw = Gem::Platform.new "universal-mingw"
+ mingw32 = Gem::Platform.new "x64-mingw32"
+ mingw_ucrt = Gem::Platform.new "x64-mingw-ucrt"
+
+ util_set_arch "x64-mingw32"
+ assert((uni_mingw === Gem::Platform.local), "uni_mingw === mingw32")
+ assert((mingw32 === Gem::Platform.local), "mingw32 === mingw32")
+ refute((mingw_ucrt === Gem::Platform.local), "mingw32 === mingw_ucrt")
+
+ util_set_arch "x64-mingw-ucrt"
+ assert((uni_mingw === Gem::Platform.local), "uni_mingw === mingw32")
+ assert((mingw_ucrt === Gem::Platform.local), "mingw_ucrt === mingw_ucrt")
+ refute((mingw32 === Gem::Platform.local), "mingw32 === mingw_ucrt")
end
def test_equals3_version
- util_set_arch 'i686-darwin8'
+ 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']
+ 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_darwin === Gem::Platform.local), "x86_darwin === x86_darwin8")
+ assert((x86_darwin8 === Gem::Platform.local), "x86_darwin8 === x86_darwin8")
- refute((x86_darwin7 === Gem::Platform.local), 'x86_darwin7 === x86_darwin8')
- refute((x86_darwin9 === Gem::Platform.local), 'x86_darwin9 === x86_darwin8')
+ refute((x86_darwin7 === Gem::Platform.local), "x86_darwin7 === x86_darwin8")
+ refute((x86_darwin9 === Gem::Platform.local), "x86_darwin9 === x86_darwin8")
end
def test_equals_tilde
- util_set_arch 'i386-mswin32'
+ util_set_arch "i386-mswin32"
- assert_local_match 'mswin32'
- assert_local_match 'i386-mswin32'
+ assert_local_match "mswin32"
+ assert_local_match "i386-mswin32"
# oddballs
- assert_local_match 'i386-mswin32-mq5.3'
- assert_local_match 'i386-mswin32-mq6'
- refute_local_match 'win32-1.8.2-VC7'
- refute_local_match 'win32-1.8.4-VC6'
- refute_local_match 'win32-source'
- refute_local_match 'windows'
-
- util_set_arch 'i686-linux'
- assert_local_match 'i486-linux'
- assert_local_match 'i586-linux'
- assert_local_match 'i686-linux'
-
- util_set_arch 'i686-darwin8'
- assert_local_match 'i686-darwin8.4.1'
- assert_local_match 'i686-darwin8.8.2'
-
- util_set_arch 'java'
- assert_local_match 'java'
- assert_local_match 'jruby'
-
- util_set_arch 'universal-dotnet2.0'
- assert_local_match 'universal-dotnet'
- assert_local_match 'universal-dotnet-2.0'
- refute_local_match 'universal-dotnet-4.0'
- assert_local_match 'dotnet'
- assert_local_match 'dotnet-2.0'
- refute_local_match 'dotnet-4.0'
-
- util_set_arch 'universal-dotnet4.0'
- assert_local_match 'universal-dotnet'
- refute_local_match 'universal-dotnet-2.0'
- assert_local_match 'universal-dotnet-4.0'
- assert_local_match 'dotnet'
- refute_local_match 'dotnet-2.0'
- assert_local_match 'dotnet-4.0'
-
- util_set_arch 'universal-macruby-1.0'
- assert_local_match 'universal-macruby'
- assert_local_match 'macruby'
- refute_local_match 'universal-macruby-0.10'
- assert_local_match 'universal-macruby-1.0'
-
- util_set_arch 'powerpc-darwin'
- assert_local_match 'powerpc-darwin'
-
- util_set_arch 'powerpc-darwin7'
- assert_local_match 'powerpc-darwin7.9.0'
-
- util_set_arch 'powerpc-darwin8'
- assert_local_match 'powerpc-darwin8.10.0'
-
- util_set_arch 'sparc-solaris2.8'
- assert_local_match 'sparc-solaris2.8-mq5.3'
+ assert_local_match "i386-mswin32-mq5.3"
+ assert_local_match "i386-mswin32-mq6"
+ refute_local_match "win32-1.8.2-VC7"
+ refute_local_match "win32-1.8.4-VC6"
+ refute_local_match "win32-source"
+ refute_local_match "windows"
+
+ util_set_arch "i686-linux"
+ assert_local_match "i486-linux"
+ assert_local_match "i586-linux"
+ assert_local_match "i686-linux"
+
+ util_set_arch "i686-darwin8"
+ assert_local_match "i686-darwin8.4.1"
+ assert_local_match "i686-darwin8.8.2"
+
+ util_set_arch "java"
+ assert_local_match "java"
+ assert_local_match "jruby"
+
+ util_set_arch "universal-dotnet2.0"
+ assert_local_match "universal-dotnet"
+ assert_local_match "universal-dotnet-2.0"
+ refute_local_match "universal-dotnet-4.0"
+ assert_local_match "dotnet"
+ assert_local_match "dotnet-2.0"
+ refute_local_match "dotnet-4.0"
+
+ util_set_arch "universal-dotnet4.0"
+ assert_local_match "universal-dotnet"
+ refute_local_match "universal-dotnet-2.0"
+ assert_local_match "universal-dotnet-4.0"
+ assert_local_match "dotnet"
+ refute_local_match "dotnet-2.0"
+ assert_local_match "dotnet-4.0"
+
+ util_set_arch "universal-macruby-1.0"
+ assert_local_match "universal-macruby"
+ assert_local_match "macruby"
+ refute_local_match "universal-macruby-0.10"
+ assert_local_match "universal-macruby-1.0"
+
+ util_set_arch "powerpc-darwin"
+ assert_local_match "powerpc-darwin"
+
+ util_set_arch "powerpc-darwin7"
+ assert_local_match "powerpc-darwin7.9.0"
+
+ util_set_arch "powerpc-darwin8"
+ assert_local_match "powerpc-darwin8.10.0"
+
+ util_set_arch "sparc-solaris2.8"
+ assert_local_match "sparc-solaris2.8-mq5.3"
end
def test_inspect
@@ -365,6 +492,15 @@ class TestGemPlatform < Gem::TestCase
assert_equal 1, result.scan(/@version=/).size
end
+ def test_gem_platform_match_with_string_argument
+ util_set_arch "x86_64-linux-musl"
+
+ Gem::Deprecate.skip_during do
+ assert(Gem::Platform.match(Gem::Platform.new("x86_64-linux")), "should match Gem::Platform")
+ assert(Gem::Platform.match("x86_64-linux"), "should match String platform")
+ end
+ end
+
def assert_local_match(name)
assert_match Gem::Platform.local, name
end
diff --git a/test/rubygems/test_gem_rdoc.rb b/test/rubygems/test_gem_rdoc.rb
index 7b8ad07b27..19ccf1e587 100644
--- a/test/rubygems/test_gem_rdoc.rb
+++ b/test/rubygems/test_gem_rdoc.rb
@@ -1,7 +1,8 @@
# frozen_string_literal: true
-require 'rubygems'
-require_relative 'helper'
-require 'rubygems/rdoc'
+
+require "rubygems"
+require_relative "helper"
+require "rubygems/rdoc"
class TestGemRDoc < Gem::TestCase
Gem::RDoc.load_rdoc
@@ -9,13 +10,13 @@ class TestGemRDoc < Gem::TestCase
def setup
super
- @a = util_spec 'a' do |s|
+ @a = util_spec "a" do |s|
s.rdoc_options = %w[--main MyTitle]
s.extra_rdoc_files = %w[README]
end
- write_file File.join(@tempdir, 'lib', 'a.rb')
- write_file File.join(@tempdir, 'README')
+ write_file File.join(@tempdir, "lib", "a.rb")
+ write_file File.join(@tempdir, "README")
install_gem @a
@@ -70,14 +71,14 @@ class TestGemRDoc < Gem::TestCase
def test_rdoc_installed?
refute @hook.rdoc_installed?
- FileUtils.mkdir_p @a.doc_dir 'rdoc'
+ FileUtils.mkdir_p @a.doc_dir "rdoc"
assert @hook.rdoc_installed?
end
def test_remove
- FileUtils.mkdir_p @a.doc_dir 'rdoc'
- FileUtils.mkdir_p @a.doc_dir 'ri'
+ FileUtils.mkdir_p @a.doc_dir "rdoc"
+ FileUtils.mkdir_p @a.doc_dir "ri"
@hook.remove
@@ -88,8 +89,8 @@ class TestGemRDoc < Gem::TestCase
end
def test_remove_unwritable
- pend 'chmod not supported' if Gem.win_platform?
- pend 'skipped in root privilege' if Process.uid.zero?
+ pend "chmod not supported" if Gem.win_platform?
+ pend "skipped in root privilege" if Process.uid.zero?
FileUtils.mkdir_p @a.base_dir
FileUtils.chmod 0, @a.base_dir
@@ -99,13 +100,13 @@ class TestGemRDoc < Gem::TestCase
assert_equal @a.base_dir, e.directory
ensure
- FileUtils.chmod(0755, @a.base_dir) if File.directory?(@a.base_dir)
+ FileUtils.chmod(0o755, @a.base_dir) if File.directory?(@a.base_dir)
end
def test_ri_installed?
refute @hook.ri_installed?
- FileUtils.mkdir_p @a.doc_dir 'ri'
+ FileUtils.mkdir_p @a.doc_dir "ri"
assert @hook.ri_installed?
end
@@ -117,8 +118,8 @@ class TestGemRDoc < Gem::TestCase
end
def test_setup_unwritable
- pend 'chmod not supported' if Gem.win_platform?
- pend 'skipped in root privilege' if Process.uid.zero?
+ pend "chmod not supported" if Gem.win_platform?
+ pend "skipped in root privilege" if Process.uid.zero?
FileUtils.mkdir_p @a.doc_dir
FileUtils.chmod 0, @a.doc_dir
@@ -129,8 +130,8 @@ class TestGemRDoc < Gem::TestCase
assert_equal @a.doc_dir, e.directory
ensure
if File.exist? @a.doc_dir
- FileUtils.chmod 0755, @a.doc_dir
+ FileUtils.chmod 0o755, @a.doc_dir
FileUtils.rm_r @a.doc_dir
end
end
-end
+end if defined?(Gem::RDoc)
diff --git a/test/rubygems/test_gem_remote_fetcher.rb b/test/rubygems/test_gem_remote_fetcher.rb
index 5ce420b91a..ca858cfda5 100644
--- a/test/rubygems/test_gem_remote_fetcher.rb
+++ b/test/rubygems/test_gem_remote_fetcher.rb
@@ -1,128 +1,30 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'webrick'
-require 'webrick/https' if Gem::HAVE_OPENSSL
+require_relative "helper"
-unless Gem::HAVE_OPENSSL
- warn 'Skipping Gem::RemoteFetcher tests. openssl not found.'
-end
-
-require 'rubygems/remote_fetcher'
-require 'rubygems/package'
-
-# = 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.
+require "rubygems/remote_fetcher"
+require "rubygems/package"
class TestGemRemoteFetcher < Gem::TestCase
include Gem::DefaultUserInteraction
- SERVER_DATA = <<-EOY.freeze
---- !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
- description: Rake is a Make-like program implemented in Ruby. Tasks and dependencies are specified in standard Ruby syntax.
- autorequire:
- 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')
-
- # Generated via:
- # x = OpenSSL::PKey::DH.new(2048) # wait a while...
- # x.to_s => pem
- TEST_KEY_DH2048 = OpenSSL::PKey::DH.new <<-_END_OF_PEM_
------BEGIN DH PARAMETERS-----
-MIIBCAKCAQEA3Ze2EHSfYkZLUn557torAmjBgPsqzbodaRaGZtgK1gEU+9nNJaFV
-G1JKhmGUiEDyIW7idsBpe4sX/Wqjnp48Lr8IeI/SlEzLdoGpf05iRYXC8Cm9o8aM
-cfmVgoSEAo9YLBpzoji2jHkO7Q5IPt4zxbTdlmmGFLc/GO9q7LGHhC+rcMcNTGsM
-49AnILNn49pq4Y72jSwdmvq4psHZwwFBbPwLdw6bLUDDCN90jfqvYt18muwUxDiN
-NP0fuvVAIB158VnQ0liHSwcl6+9vE1mL0Jo/qEXQxl0+UdKDjaGfTsn6HIrwTnmJ
-PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
------END DH PARAMETERS-----
- _END_OF_PEM_
-
def setup
- @proxies = %w[https_proxy http_proxy HTTP_PROXY http_proxy_user HTTP_PROXY_USER http_proxy_pass HTTP_PROXY_PASS no_proxy NO_PROXY]
- @old_proxies = @proxies.map {|k| ENV[k] }
- @proxies.each {|k| ENV[k] = nil }
-
super
- start_servers
- self.enable_yaml = true
- self.enable_zip = false
-
- base_server_uri = "http://localhost:#{normal_server_port}"
- @proxy_uri = "http://localhost:#{proxy_server_port}"
-
- @server_uri = base_server_uri + "/yaml"
- @server_z_uri = base_server_uri + "/yaml.Z"
@cache_dir = File.join @gemhome, "cache"
# TODO: why does the remote fetcher need it written to disk?
- @a1, @a1_gem = util_gem 'a', '1' do |s|
- s.executables << 'a_bin'
+ @a1, @a1_gem = util_gem "a", "1" do |s|
+ s.executables << "a_bin"
end
- @a1.loaded_from = File.join(@gemhome, 'specifications', @a1.full_name)
+ @a1.loaded_from = File.join(@gemhome, "specifications", @a1.full_name)
Gem::RemoteFetcher.fetcher = nil
@stub_ui = Gem::MockGemUi.new
@fetcher = Gem::RemoteFetcher.fetcher
end
- def teardown
- @fetcher.close_all
- stop_servers
- super
- Gem.configuration[:http_proxy] = nil
- @proxies.each_with_index {|k, i| ENV[k] = @old_proxies[i] }
- end
-
def test_self_fetcher
fetcher = Gem::RemoteFetcher.fetcher
refute_nil fetcher
@@ -130,7 +32,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
end
def test_self_fetcher_with_proxy
- proxy_uri = 'http://proxy.example.com'
+ proxy_uri = "http://proxy.example.com"
Gem.configuration[:http_proxy] = proxy_uri
Gem::RemoteFetcher.fetcher = nil
@@ -139,6 +41,8 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
refute_nil fetcher
assert_kind_of Gem::RemoteFetcher, fetcher
assert_equal proxy_uri, fetcher.instance_variable_get(:@proxy).to_s
+ ensure
+ Gem.configuration[:http_proxy] = nil
end
def test_fetch_path_bad_uri
@@ -149,39 +53,46 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
@fetcher.fetch_path("gems.example.com/yaml", nil, true)
end
- assert_equal 'uri scheme is invalid: nil', e.message
- end
-
- def test_no_proxy
- use_ui @stub_ui do
- assert_data_from_server @fetcher.fetch_path(@server_uri)
- response = @fetcher.fetch_path(@server_uri, nil, true)
- assert_equal SERVER_DATA.size, response['content-length'].to_i
- end
+ assert_equal "uri scheme is invalid: nil", e.message
end
def test_cache_update_path
- uri = URI 'http://example/file'
- path = File.join @tempdir, 'file'
+ uri = Gem::URI "http://example/file"
+ path = File.join @tempdir, "file"
- fetcher = util_fuck_with_fetcher 'hello'
+ fetcher = util_fuck_with_fetcher "hello"
data = fetcher.cache_update_path uri, path
- assert_equal 'hello', data
+ assert_equal "hello", data
+
+ assert_equal "hello", File.read(path)
+ end
+
+ def test_cache_update_path_with_utf8_internal_encoding
+ with_internal_encoding("UTF-8") do
+ uri = Gem::URI "http://example/file"
+ path = File.join @tempdir, "file"
+ data = String.new("\xC8").force_encoding(Encoding::BINARY)
- assert_equal 'hello', File.read(path)
+ fetcher = util_fuck_with_fetcher data
+
+ written_data = fetcher.cache_update_path uri, path
+
+ assert_equal data, written_data
+ assert_equal data, File.binread(path)
+ end
end
def test_cache_update_path_no_update
- uri = URI 'http://example/file'
- path = File.join @tempdir, 'file'
+ uri = Gem::URI "http://example/file"
+ path = File.join @tempdir, "file"
- fetcher = util_fuck_with_fetcher 'hello'
+ fetcher = util_fuck_with_fetcher "hello"
data = fetcher.cache_update_path uri, path, false
- assert_equal 'hello', data
+ assert_equal "hello", data
assert_path_not_exist path
end
@@ -190,12 +101,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
fetcher = Gem::RemoteFetcher.fetcher
fetcher.instance_variable_set :@test_data, data
- unless blow
- def fetcher.fetch_path(arg, *rest)
- @test_arg = arg
- @test_data
- end
- else
+ if blow
def fetcher.fetch_path(arg, *rest)
# OMG I'm such an ass
class << self; remove_method :fetch_path; end
@@ -204,7 +110,12 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
@test_data
end
- raise Gem::RemoteFetcher::FetchError.new("haha!", '')
+ raise Gem::RemoteFetcher::FetchError.new("haha!", "")
+ end
+ else
+ def fetcher.fetch_path(arg, *rest)
+ @test_arg = arg
+ @test_data
end
end
@@ -213,14 +124,14 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
def test_download
a1_data = nil
- File.open @a1_gem, 'rb' do |fp|
+ File.open @a1_gem, "rb" do |fp|
a1_data = fp.read
end
fetcher = util_fuck_with_fetcher a1_data
a1_cache_gem = @a1.cache_file
- assert_equal a1_cache_gem, fetcher.download(@a1, 'http://gems.example.com')
+ 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)
@@ -228,14 +139,14 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
def test_download_with_auth
a1_data = nil
- File.open @a1_gem, 'rb' do |fp|
+ File.open @a1_gem, "rb" do |fp|
a1_data = fp.read
end
fetcher = util_fuck_with_fetcher a1_data
a1_cache_gem = @a1.cache_file
- assert_equal a1_cache_gem, fetcher.download(@a1, 'http://user:password@gems.example.com')
+ assert_equal a1_cache_gem, fetcher.download(@a1, "http://user:password@gems.example.com")
assert_equal("http://user:password@gems.example.com/gems/a-1.gem",
fetcher.instance_variable_get(:@test_arg).to_s)
assert File.exist?(a1_cache_gem)
@@ -243,14 +154,14 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
def test_download_with_token
a1_data = nil
- File.open @a1_gem, 'rb' do |fp|
+ File.open @a1_gem, "rb" do |fp|
a1_data = fp.read
end
fetcher = util_fuck_with_fetcher a1_data
a1_cache_gem = @a1.cache_file
- assert_equal a1_cache_gem, fetcher.download(@a1, 'http://token@gems.example.com')
+ assert_equal a1_cache_gem, fetcher.download(@a1, "http://token@gems.example.com")
assert_equal("http://token@gems.example.com/gems/a-1.gem",
fetcher.instance_variable_get(:@test_arg).to_s)
assert File.exist?(a1_cache_gem)
@@ -258,14 +169,14 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
def test_download_with_x_oauth_basic
a1_data = nil
- File.open @a1_gem, 'rb' do |fp|
+ File.open @a1_gem, "rb" do |fp|
a1_data = fp.read
end
fetcher = util_fuck_with_fetcher a1_data
a1_cache_gem = @a1.cache_file
- assert_equal a1_cache_gem, fetcher.download(@a1, 'http://token:x-oauth-basic@gems.example.com')
+ assert_equal a1_cache_gem, fetcher.download(@a1, "http://token:x-oauth-basic@gems.example.com")
assert_equal("http://token:x-oauth-basic@gems.example.com/gems/a-1.gem",
fetcher.instance_variable_get(:@test_arg).to_s)
assert File.exist?(a1_cache_gem)
@@ -273,14 +184,14 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
def test_download_with_encoded_auth
a1_data = nil
- File.open @a1_gem, 'rb' do |fp|
+ File.open @a1_gem, "rb" do |fp|
a1_data = fp.read
end
fetcher = util_fuck_with_fetcher a1_data
a1_cache_gem = @a1.cache_file
- assert_equal a1_cache_gem, fetcher.download(@a1, 'http://user:%25pas%25sword@gems.example.com')
+ assert_equal a1_cache_gem, fetcher.download(@a1, "http://user:%25pas%25sword@gems.example.com")
assert_equal("http://user:%25pas%25sword@gems.example.com/gems/a-1.gem",
fetcher.instance_variable_get(:@test_arg).to_s)
assert File.exist?(a1_cache_gem)
@@ -291,10 +202,11 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
inst = Gem::RemoteFetcher.fetcher
- assert_equal @a1.cache_file, inst.download(@a1, 'http://gems.example.com')
+ assert_equal @a1.cache_file, inst.download(@a1, "http://gems.example.com")
end
def test_download_local
+ omit "doesn't work if tempdir has +" if @tempdir.include?("+")
FileUtils.mv @a1_gem, @tempdir
local_path = File.join @tempdir, @a1.file_name
inst = nil
@@ -307,7 +219,8 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
end
def test_download_local_space
- space_path = File.join @tempdir, 'space path'
+ omit "doesn't work if tempdir has +" if @tempdir.include?("+")
+ space_path = File.join @tempdir, "space path"
FileUtils.mkdir space_path
FileUtils.mv @a1_gem, space_path
local_path = File.join space_path, @a1.file_name
@@ -321,17 +234,15 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
end
def test_download_install_dir
- a1_data = File.open @a1_gem, 'rb' do |fp|
- fp.read
- end
+ a1_data = File.open @a1_gem, "rb", &:read
fetcher = util_fuck_with_fetcher a1_data
- install_dir = File.join @tempdir, 'more_gems'
+ install_dir = File.join @tempdir, "more_gems"
a1_cache_gem = File.join install_dir, "cache", @a1.file_name
FileUtils.mkdir_p(File.dirname(a1_cache_gem))
- actual = fetcher.download(@a1, 'http://gems.example.com', install_dir)
+ 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",
@@ -340,14 +251,19 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
assert File.exist?(a1_cache_gem)
end
- unless win_platform? || Process.uid.zero? # File.chmod doesn't work
+ unless Gem.win_platform? || Process.uid.zero? # File.chmod doesn't work
def test_download_local_read_only
+ omit "doesn't work if tempdir has +" if @tempdir.include?("+")
FileUtils.mv @a1_gem, @tempdir
local_path = File.join @tempdir, @a1.file_name
inst = nil
- FileUtils.chmod 0555, @a1.cache_dir
- FileUtils.mkdir_p File.join(Gem.user_dir, "cache") rescue nil
- FileUtils.chmod 0555, File.join(Gem.user_dir, "cache")
+ FileUtils.chmod 0o555, @a1.cache_dir
+ begin
+ FileUtils.mkdir_p File.join(Gem.user_dir, "cache")
+ rescue StandardError
+ nil
+ end
+ FileUtils.chmod 0o555, File.join(Gem.user_dir, "cache")
Dir.chdir @tempdir do
inst = Gem::RemoteFetcher.fetcher
@@ -356,35 +272,37 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
assert_equal(File.join(@tempdir, @a1.file_name),
inst.download(@a1, local_path))
ensure
- FileUtils.chmod 0755, File.join(Gem.user_dir, "cache")
- FileUtils.chmod 0755, @a1.cache_dir
+ if local_path
+ FileUtils.chmod 0o755, File.join(Gem.user_dir, "cache")
+ FileUtils.chmod 0o755, @a1.cache_dir
+ end
end
def test_download_read_only
- FileUtils.chmod 0555, @a1.cache_dir
- FileUtils.chmod 0555, @gemhome
+ FileUtils.chmod 0o555, @a1.cache_dir
+ FileUtils.chmod 0o555, @gemhome
fetcher = util_fuck_with_fetcher File.read(@a1_gem)
- fetcher.download(@a1, 'http://gems.example.com')
+ fetcher.download(@a1, "http://gems.example.com")
a1_cache_gem = File.join Gem.user_dir, "cache", @a1.file_name
assert File.exist? a1_cache_gem
ensure
- FileUtils.chmod 0755, @gemhome
- FileUtils.chmod 0755, @a1.cache_dir
+ FileUtils.chmod 0o755, @gemhome
+ FileUtils.chmod 0o755, @a1.cache_dir
end
end
def test_download_platform_legacy
- original_platform = 'old-platform'
+ original_platform = "old-platform"
- e1, e1_gem = util_gem 'e', '1' do |s|
+ e1, e1_gem = util_gem "e", "1" do |s|
s.platform = Gem::Platform::CURRENT
s.instance_variable_set :@original_platform, original_platform
end
- e1.loaded_from = File.join(@gemhome, 'specifications', e1.full_name)
+ e1.loaded_from = File.join(@gemhome, "specifications", e1.full_name)
e1_data = nil
- File.open e1_gem, 'rb' do |fp|
+ File.open e1_gem, "rb" do |fp|
e1_data = fp.read
end
@@ -392,7 +310,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
e1_cache_gem = e1.cache_file
- assert_equal e1_cache_gem, fetcher.download(e1, 'http://gems.example.com')
+ 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)
@@ -400,6 +318,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
end
def test_download_same_file
+ omit "doesn't work if tempdir has +" if @tempdir.include?("+")
FileUtils.mv @a1_gem, @tempdir
local_path = File.join @tempdir, @a1.file_name
inst = nil
@@ -420,14 +339,14 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
inst = Gem::RemoteFetcher.fetcher
e = assert_raise ArgumentError do
- inst.download @a1, 'ftp://gems.rubyforge.org'
+ inst.download @a1, "ftp://gems.rubyforge.org"
end
- assert_equal 'unsupported URI scheme ftp', e.message
+ assert_equal "unsupported URI scheme ftp", e.message
end
def test_download_to_cache
- @a2, @a2_gem = util_gem 'a', '2'
+ @a2, @a2_gem = util_gem "a", "2"
util_setup_spec_fetcher @a1, @a2
@fetcher.instance_variable_set :@a1, @a1
@@ -443,7 +362,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
end
end
- gem = Gem::RemoteFetcher.fetcher.download_to_cache dep 'a'
+ gem = Gem::RemoteFetcher.fetcher.download_to_cache dep "a"
assert_equal @a2.file_name, File.basename(gem)
end
@@ -453,10 +372,10 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
@fetcher = fetcher
def fetcher.fetch_http(uri, mtime, head = nil)
- Gem::Util.gzip 'foo'
+ Gem::Util.gzip "foo"
end
- assert_equal 'foo', fetcher.fetch_path(@uri + 'foo.gz')
+ assert_equal "foo", fetcher.fetch_path(@uri + "foo.gz")
end
def test_fetch_path_gzip_unmodified
@@ -467,7 +386,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
nil
end
- assert_nil fetcher.fetch_path(@uri + 'foo.gz', Time.at(0))
+ assert_nil fetcher.fetch_path(@uri + "foo.gz", Time.at(0))
end
def test_fetch_path_io_error
@@ -478,7 +397,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
raise EOFError
end
- url = 'http://example.com/uri'
+ url = "http://example.com/uri"
e = assert_raise Gem::RemoteFetcher::FetchError do
fetcher.fetch_path url
@@ -496,7 +415,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
raise SocketError
end
- url = 'http://example.com/uri'
+ url = "http://example.com/uri"
e = assert_raise Gem::RemoteFetcher::FetchError do
fetcher.fetch_path url
@@ -511,17 +430,17 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
@fetcher = fetcher
def fetcher.fetch_http(uri, mtime = nil, head = nil)
- raise Errno::ECONNREFUSED, 'connect(2)'
+ raise Errno::ECONNREFUSED, "connect(2)"
end
- url = 'http://example.com/uri'
+ url = "http://example.com/uri"
e = assert_raise Gem::RemoteFetcher::FetchError do
fetcher.fetch_path url
end
- assert_match %r{ECONNREFUSED:.*connect\(2\) \(#{Regexp.escape url}\)\z},
- e.message
+ assert_match(/ECONNREFUSED:.*connect\(2\) \(#{Regexp.escape url}\)\z/,
+ e.message)
assert_equal url, e.uri
end
@@ -530,17 +449,17 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
@fetcher = fetcher
def fetcher.fetch_http(uri, mtime = nil, head = nil)
- raise Timeout::Error, 'timed out'
+ raise Gem::Timeout::Error, "timed out"
end
- url = 'http://example.com/uri'
+ url = "http://example.com/uri"
e = assert_raise Gem::RemoteFetcher::FetchError do
fetcher.fetch_path url
end
- assert_match %r{Timeout::Error: timed out \(#{Regexp.escape url}\)\z},
- e.message
+ assert_match(/Gem::Timeout::Error: timed out \(#{Regexp.escape url}\)\z/,
+ e.message)
assert_equal url, e.uri
end
@@ -549,17 +468,17 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
@fetcher = fetcher
def fetcher.fetch_http(uri, mtime = nil, head = nil)
- raise SocketError, 'getaddrinfo: nodename nor servname provided'
+ raise SocketError, "getaddrinfo: nodename nor servname provided"
end
- url = 'http://example.com/uri'
+ url = "http://example.com/uri"
e = assert_raise Gem::RemoteFetcher::FetchError do
fetcher.fetch_path url
end
- assert_match %r{SocketError: getaddrinfo: nodename nor servname provided \(#{Regexp.escape url}\)\z},
- e.message
+ assert_match(/SocketError: getaddrinfo: nodename nor servname provided \(#{Regexp.escape url}\)\z/,
+ e.message)
assert_equal url, e.uri
end
@@ -571,7 +490,7 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
raise OpenSSL::SSL::SSLError
end
- url = 'http://example.com/uri'
+ url = "http://example.com/uri"
e = assert_raise Gem::RemoteFetcher::FetchError do
fetcher.fetch_path url
@@ -589,82 +508,48 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
nil
end
- assert_nil fetcher.fetch_path(URI.parse(@gem_repo), Time.at(0))
- end
-
- def test_implicit_no_proxy
- use_ui @stub_ui do
- ENV['http_proxy'] = 'http://fakeurl:12345'
- fetcher = Gem::RemoteFetcher.new :no_proxy
- @fetcher = fetcher
- assert_data_from_server fetcher.fetch_path(@server_uri)
- end
- end
-
- def test_implicit_proxy
- use_ui @stub_ui do
- ENV['http_proxy'] = @proxy_uri
- fetcher = Gem::RemoteFetcher.new nil
- @fetcher = fetcher
- assert_data_from_proxy fetcher.fetch_path(@server_uri)
- end
- end
-
- def test_implicit_upper_case_proxy
- use_ui @stub_ui do
- ENV['HTTP_PROXY'] = @proxy_uri
- fetcher = Gem::RemoteFetcher.new nil
- @fetcher = fetcher
- assert_data_from_proxy fetcher.fetch_path(@server_uri)
- end
- end
-
- def test_implicit_proxy_no_env
- use_ui @stub_ui do
- fetcher = Gem::RemoteFetcher.new nil
- @fetcher = fetcher
- assert_data_from_server fetcher.fetch_path(@server_uri)
- end
+ assert_nil fetcher.fetch_path(Gem::URI.parse(@gem_repo), Time.at(0))
end
def test_fetch_http
fetcher = Gem::RemoteFetcher.new nil
@fetcher = fetcher
- url = 'http://gems.example.com/redirect'
+ url = "http://gems.example.com/redirect"
def fetcher.request(uri, request_class, last_modified = nil)
- url = 'http://gems.example.com/redirect'
- unless defined? @requested
- @requested = true
- res = Net::HTTPMovedPermanently.new nil, 301, nil
- res.add_field 'Location', url
- res
+ url = "http://gems.example.com/redirect"
+ if defined? @requested
+ res = Gem::Net::HTTPOK.new nil, 200, nil
+ def res.body
+ "real_path"
+ end
else
- res = Net::HTTPOK.new nil, 200, nil
- def res.body() 'real_path' end
- res
+ @requested = true
+ res = Gem::Net::HTTPMovedPermanently.new nil, 301, nil
+ res.add_field "Location", url
end
+ res
end
- data = fetcher.fetch_http URI.parse(url)
+ data = fetcher.fetch_http Gem::URI.parse(url)
- assert_equal 'real_path', data
+ assert_equal "real_path", data
end
def test_fetch_http_redirects
fetcher = Gem::RemoteFetcher.new nil
@fetcher = fetcher
- url = 'http://gems.example.com/redirect'
+ url = "http://gems.example.com/redirect"
def fetcher.request(uri, request_class, last_modified = nil)
- url = 'http://gems.example.com/redirect'
- res = Net::HTTPMovedPermanently.new nil, 301, nil
- res.add_field 'Location', url
+ url = "http://gems.example.com/redirect"
+ res = Gem::Net::HTTPMovedPermanently.new nil, 301, nil
+ res.add_field "Location", url
res
end
e = assert_raise Gem::RemoteFetcher::FetchError do
- fetcher.fetch_http URI.parse(url)
+ fetcher.fetch_http Gem::URI.parse(url)
end
assert_equal "too many redirects (#{url})", e.message
@@ -673,266 +558,27 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
def test_fetch_http_redirects_without_location
fetcher = Gem::RemoteFetcher.new nil
@fetcher = fetcher
- url = 'http://gems.example.com/redirect'
+ url = "http://gems.example.com/redirect"
def fetcher.request(uri, request_class, last_modified = nil)
- res = Net::HTTPMovedPermanently.new nil, 301, nil
+ res = Gem::Net::HTTPMovedPermanently.new nil, 301, nil
res
end
e = assert_raise Gem::RemoteFetcher::FetchError do
- fetcher.fetch_http URI.parse(url)
+ fetcher.fetch_http Gem::URI.parse(url)
end
assert_equal "redirecting but no redirect location was given (#{url})", e.message
end
- def test_fetch_http_with_additional_headers
- ENV["http_proxy"] = @proxy_uri
- ENV["no_proxy"] = URI::parse(@server_uri).host
- fetcher = Gem::RemoteFetcher.new nil, nil, {"X-Captain" => "murphy"}
- @fetcher = fetcher
- assert_equal "murphy", fetcher.fetch_path(@server_uri)
- end
-
- def assert_fetch_s3(url, signature, token=nil, region='us-east-1', instance_profile_json=nil)
- fetcher = Gem::RemoteFetcher.new nil
- @fetcher = fetcher
- $fetched_uri = nil
- $instance_profile = instance_profile_json
-
- def fetcher.request(uri, request_class, last_modified = nil)
- $fetched_uri = uri
- res = Net::HTTPOK.new nil, 200, nil
- def res.body() 'success' end
- res
- end
-
- def fetcher.s3_uri_signer(uri)
- require 'json'
- s3_uri_signer = Gem::S3URISigner.new(uri)
- def s3_uri_signer.ec2_metadata_credentials_json
- JSON.parse($instance_profile)
- end
- # Running sign operation to make sure uri.query is not mutated
- s3_uri_signer.sign
- raise "URI query is not empty: #{uri.query}" unless uri.query.nil?
- s3_uri_signer
- end
-
- data = fetcher.fetch_s3 URI.parse(url)
-
- assert_equal "https://my-bucket.s3.#{region}.amazonaws.com/gems/specs.4.8.gz?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=testuser%2F20190624%2F#{region}%2Fs3%2Faws4_request&X-Amz-Date=20190624T050641Z&X-Amz-Expires=86400#{token ? "&X-Amz-Security-Token=" + token : ""}&X-Amz-SignedHeaders=host&X-Amz-Signature=#{signature}", $fetched_uri.to_s
- assert_equal 'success', data
- ensure
- $fetched_uri = nil
- end
-
- def test_fetch_s3_config_creds
- Gem.configuration[:s3_source] = {
- 'my-bucket' => {:id => 'testuser', :secret => 'testpass'},
- }
- url = 's3://my-bucket/gems/specs.4.8.gz'
- Time.stub :now, Time.at(1561353581) do
- assert_fetch_s3 url, '20f974027db2f3cd6193565327a7c73457a138efb1a63ea248d185ce6827d41b'
- end
- ensure
- Gem.configuration[:s3_source] = nil
- end
-
- def test_fetch_s3_config_creds_with_region
- Gem.configuration[:s3_source] = {
- 'my-bucket' => {:id => 'testuser', :secret => 'testpass', :region => 'us-west-2'},
- }
- url = 's3://my-bucket/gems/specs.4.8.gz'
- Time.stub :now, Time.at(1561353581) do
- assert_fetch_s3 url, '4afc3010757f1fd143e769f1d1dabd406476a4fc7c120e9884fd02acbb8f26c9', nil, 'us-west-2'
- end
- ensure
- Gem.configuration[:s3_source] = nil
- end
-
- def test_fetch_s3_config_creds_with_token
- Gem.configuration[:s3_source] = {
- 'my-bucket' => {:id => 'testuser', :secret => 'testpass', :security_token => 'testtoken'},
- }
- url = 's3://my-bucket/gems/specs.4.8.gz'
- Time.stub :now, Time.at(1561353581) do
- assert_fetch_s3 url, '935160a427ef97e7630f799232b8f208c4a4e49aad07d0540572a2ad5fe9f93c', 'testtoken'
- end
- ensure
- Gem.configuration[:s3_source] = nil
- end
-
- def test_fetch_s3_env_creds
- ENV['AWS_ACCESS_KEY_ID'] = 'testuser'
- ENV['AWS_SECRET_ACCESS_KEY'] = 'testpass'
- ENV['AWS_SESSION_TOKEN'] = nil
- Gem.configuration[:s3_source] = {
- 'my-bucket' => {:provider => 'env'},
- }
- url = 's3://my-bucket/gems/specs.4.8.gz'
- Time.stub :now, Time.at(1561353581) do
- assert_fetch_s3 url, '20f974027db2f3cd6193565327a7c73457a138efb1a63ea248d185ce6827d41b'
- end
- ensure
- ENV.each_key {|key| ENV.delete(key) if key.start_with?('AWS') }
- Gem.configuration[:s3_source] = nil
- end
-
- def test_fetch_s3_env_creds_with_region
- ENV['AWS_ACCESS_KEY_ID'] = 'testuser'
- ENV['AWS_SECRET_ACCESS_KEY'] = 'testpass'
- ENV['AWS_SESSION_TOKEN'] = nil
- Gem.configuration[:s3_source] = {
- 'my-bucket' => {:provider => 'env', :region => 'us-west-2'},
- }
- url = 's3://my-bucket/gems/specs.4.8.gz'
- Time.stub :now, Time.at(1561353581) do
- assert_fetch_s3 url, '4afc3010757f1fd143e769f1d1dabd406476a4fc7c120e9884fd02acbb8f26c9', nil, 'us-west-2'
- end
- ensure
- ENV.each_key {|key| ENV.delete(key) if key.start_with?('AWS') }
- Gem.configuration[:s3_source] = nil
- end
-
- def test_fetch_s3_env_creds_with_token
- ENV['AWS_ACCESS_KEY_ID'] = 'testuser'
- ENV['AWS_SECRET_ACCESS_KEY'] = 'testpass'
- ENV['AWS_SESSION_TOKEN'] = 'testtoken'
- Gem.configuration[:s3_source] = {
- 'my-bucket' => {:provider => 'env'},
- }
- url = 's3://my-bucket/gems/specs.4.8.gz'
- Time.stub :now, Time.at(1561353581) do
- assert_fetch_s3 url, '935160a427ef97e7630f799232b8f208c4a4e49aad07d0540572a2ad5fe9f93c', 'testtoken'
- end
- ensure
- ENV.each_key {|key| ENV.delete(key) if key.start_with?('AWS') }
- Gem.configuration[:s3_source] = nil
- end
-
- def test_fetch_s3_url_creds
- url = 's3://testuser:testpass@my-bucket/gems/specs.4.8.gz'
- Time.stub :now, Time.at(1561353581) do
- assert_fetch_s3 url, '20f974027db2f3cd6193565327a7c73457a138efb1a63ea248d185ce6827d41b'
- end
- end
-
- def test_fetch_s3_instance_profile_creds
- Gem.configuration[:s3_source] = {
- 'my-bucket' => {:provider => 'instance_profile'},
- }
-
- url = 's3://my-bucket/gems/specs.4.8.gz'
- Time.stub :now, Time.at(1561353581) do
- assert_fetch_s3 url, '20f974027db2f3cd6193565327a7c73457a138efb1a63ea248d185ce6827d41b', nil, 'us-east-1',
- '{"AccessKeyId": "testuser", "SecretAccessKey": "testpass"}'
- end
- ensure
- Gem.configuration[:s3_source] = nil
- end
-
- def test_fetch_s3_instance_profile_creds_with_region
- Gem.configuration[:s3_source] = {
- 'my-bucket' => {:provider => 'instance_profile', :region => 'us-west-2'},
- }
-
- url = 's3://my-bucket/gems/specs.4.8.gz'
- Time.stub :now, Time.at(1561353581) do
- assert_fetch_s3 url, '4afc3010757f1fd143e769f1d1dabd406476a4fc7c120e9884fd02acbb8f26c9', nil, 'us-west-2',
- '{"AccessKeyId": "testuser", "SecretAccessKey": "testpass"}'
- end
- ensure
- Gem.configuration[:s3_source] = nil
- end
-
- def test_fetch_s3_instance_profile_creds_with_token
- Gem.configuration[:s3_source] = {
- 'my-bucket' => {:provider => 'instance_profile'},
- }
-
- url = 's3://my-bucket/gems/specs.4.8.gz'
- Time.stub :now, Time.at(1561353581) do
- assert_fetch_s3 url, '935160a427ef97e7630f799232b8f208c4a4e49aad07d0540572a2ad5fe9f93c', 'testtoken', 'us-east-1',
- '{"AccessKeyId": "testuser", "SecretAccessKey": "testpass", "Token": "testtoken"}'
- end
- ensure
- Gem.configuration[:s3_source] = nil
- end
-
- def refute_fetch_s3(url, expected_message)
- fetcher = Gem::RemoteFetcher.new nil
- @fetcher = fetcher
-
- e = assert_raise Gem::RemoteFetcher::FetchError do
- fetcher.fetch_s3 URI.parse(url)
- end
-
- assert_match expected_message, e.message
- end
-
- def test_fetch_s3_no_source_key
- url = 's3://my-bucket/gems/specs.4.8.gz'
- refute_fetch_s3 url, 'no s3_source key exists in .gemrc'
- end
-
- def test_fetch_s3_no_host
- Gem.configuration[:s3_source] = {
- 'my-bucket' => {:id => 'testuser', :secret => 'testpass'},
- }
-
- url = 's3://other-bucket/gems/specs.4.8.gz'
- refute_fetch_s3 url, 'no key for host other-bucket in s3_source in .gemrc'
- ensure
- Gem.configuration[:s3_source] = nil
- end
-
- def test_fetch_s3_no_id
- Gem.configuration[:s3_source] = { 'my-bucket' => {:secret => 'testpass'} }
-
- url = 's3://my-bucket/gems/specs.4.8.gz'
- refute_fetch_s3 url, 's3_source for my-bucket missing id or secret'
- ensure
- Gem.configuration[:s3_source] = nil
- end
-
- def test_fetch_s3_no_secret
- Gem.configuration[:s3_source] = { 'my-bucket' => {:id => 'testuser'} }
-
- url = 's3://my-bucket/gems/specs.4.8.gz'
- refute_fetch_s3 url, 's3_source for my-bucket missing id or secret'
- ensure
- Gem.configuration[:s3_source] = nil
- end
-
- def test_observe_no_proxy_env_single_host
- use_ui @stub_ui do
- ENV["http_proxy"] = @proxy_uri
- ENV["no_proxy"] = URI::parse(@server_uri).host
- fetcher = Gem::RemoteFetcher.new nil
- @fetcher = fetcher
- assert_data_from_server fetcher.fetch_path(@server_uri)
- end
- end
-
- def test_observe_no_proxy_env_list
- use_ui @stub_ui do
- ENV["http_proxy"] = @proxy_uri
- ENV["no_proxy"] = "fakeurl.com, #{URI::parse(@server_uri).host}"
- fetcher = Gem::RemoteFetcher.new nil
- @fetcher = fetcher
- assert_data_from_server fetcher.fetch_path(@server_uri)
- end
- end
-
def test_request_block
fetcher = Gem::RemoteFetcher.new nil
@fetcher = fetcher
assert_throws :block_called do
- fetcher.request URI('http://example'), Net::HTTP::Get do |req|
- assert_kind_of Net::HTTPGenericRequest, req
+ fetcher.request Gem::URI("http://example"), Gem::Net::HTTP::Get do |req|
+ assert_kind_of Gem::Net::HTTPGenericRequest, req
throw :block_called
end
end
@@ -940,110 +586,12 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
def test_yaml_error_on_size
use_ui @stub_ui do
- self.enable_yaml = false
fetcher = Gem::RemoteFetcher.new nil
@fetcher = fetcher
assert_error { fetcher.size }
end
end
- def test_ssl_connection
- ssl_server = start_ssl_server
- temp_ca_cert = File.join(__dir__, 'ca_cert.pem')
- with_configured_fetcher(":ssl_ca_cert: #{temp_ca_cert}") do |fetcher|
- fetcher.fetch_path("https://localhost:#{ssl_server.config[:Port]}/yaml")
- end
- end
-
- def test_ssl_client_cert_auth_connection
- ssl_server = start_ssl_server({
- :SSLVerifyClient =>
- OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT})
-
- temp_ca_cert = File.join(__dir__, 'ca_cert.pem')
- temp_client_cert = File.join(__dir__, 'client.pem')
-
- with_configured_fetcher(
- ":ssl_ca_cert: #{temp_ca_cert}\n" +
- ":ssl_client_cert: #{temp_client_cert}\n") do |fetcher|
- fetcher.fetch_path("https://localhost:#{ssl_server.config[:Port]}/yaml")
- end
- end
-
- def test_do_not_allow_invalid_client_cert_auth_connection
- ssl_server = start_ssl_server({
- :SSLVerifyClient =>
- OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT})
-
- temp_ca_cert = File.join(__dir__, 'ca_cert.pem')
- temp_client_cert = File.join(__dir__, 'invalid_client.pem')
-
- with_configured_fetcher(
- ":ssl_ca_cert: #{temp_ca_cert}\n" +
- ":ssl_client_cert: #{temp_client_cert}\n") do |fetcher|
- assert_raise Gem::RemoteFetcher::FetchError do
- fetcher.fetch_path("https://localhost:#{ssl_server.config[:Port]}/yaml")
- end
- end
- end
-
- def test_do_not_allow_insecure_ssl_connection_by_default
- ssl_server = start_ssl_server
- with_configured_fetcher do |fetcher|
- assert_raise Gem::RemoteFetcher::FetchError do
- fetcher.fetch_path("https://localhost:#{ssl_server.config[:Port]}/yaml")
- end
- end
- end
-
- def test_ssl_connection_allow_verify_none
- ssl_server = start_ssl_server
- with_configured_fetcher(":ssl_verify_mode: 0") do |fetcher|
- fetcher.fetch_path("https://localhost:#{ssl_server.config[:Port]}/yaml")
- end
- end
-
- def test_do_not_follow_insecure_redirect
- ssl_server = start_ssl_server
- temp_ca_cert = File.join(__dir__, 'ca_cert.pem')
- expected_error_message =
- "redirecting to non-https resource: #{@server_uri} (https://localhost:#{ssl_server.config[:Port]}/insecure_redirect?to=#{@server_uri})"
-
- with_configured_fetcher(":ssl_ca_cert: #{temp_ca_cert}") do |fetcher|
- err = assert_raise Gem::RemoteFetcher::FetchError do
- fetcher.fetch_path("https://localhost:#{ssl_server.config[:Port]}/insecure_redirect?to=#{@server_uri}")
- end
-
- assert_equal(err.message, expected_error_message)
- end
- end
-
- def test_nil_ca_cert
- ssl_server = start_ssl_server
- temp_ca_cert = nil
-
- with_configured_fetcher(":ssl_ca_cert: #{temp_ca_cert}") do |fetcher|
- assert_raise Gem::RemoteFetcher::FetchError do
- fetcher.fetch_path("https://localhost:#{ssl_server.config[:Port]}")
- end
- end
- end
-
- def with_configured_fetcher(config_str = nil, &block)
- if config_str
- temp_conf = File.join @tempdir, '.gemrc'
- File.open temp_conf, 'w' do |fp|
- fp.puts config_str
- end
- Gem.configuration = Gem::ConfigFile.new %W[--config-file #{temp_conf}]
- end
- fetcher = Gem::RemoteFetcher.new
- yield fetcher
- ensure
- fetcher.close_all
- Gem.configuration = nil
- end
-
def assert_error(exception_class=Exception)
got_exception = false
@@ -1055,157 +603,4 @@ PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
assert got_exception, "Expected exception conforming to #{exception_class}"
end
-
- def assert_data_from_server(data)
- assert_match(/0\.4\.11/, data, "Data is not from server")
- end
-
- def assert_data_from_proxy(data)
- assert_match(/0\.4\.2/, data, "Data is not from proxy")
- end
-
- class NilLog < WEBrick::Log
- def log(level, data) #Do nothing
- end
- end
-
- private
-
- attr_reader :normal_server, :proxy_server
- attr_accessor :enable_zip, :enable_yaml
-
- def start_servers
- @normal_server ||= start_server(SERVER_DATA)
- @proxy_server ||= start_server(PROXY_DATA)
- @enable_yaml = true
- @enable_zip = false
- @ssl_server = nil
- @ssl_server_thread = nil
- end
-
- def stop_servers
- if @normal_server
- @normal_server.kill.join
- @normal_server = nil
- end
- if @proxy_server
- @proxy_server.kill.join
- @proxy_server = nil
- end
- if @ssl_server
- @ssl_server.stop
- @ssl_server = nil
- end
- if @ssl_server_thread
- @ssl_server_thread.kill.join
- @ssl_server_thread = nil
- end
- utils = WEBrick::Utils # TimeoutHandler is since 1.9
- utils::TimeoutHandler.terminate if defined?(utils::TimeoutHandler.terminate)
- end
-
- def normal_server_port
- @normal_server[:server].config[:Port]
- end
-
- def proxy_server_port
- @proxy_server[:server].config[:Port]
- end
-
- def start_ssl_server(config = {})
- pend "starting this test server fails randomly on jruby" if Gem.java_platform?
-
- null_logger = NilLog.new
- server = WEBrick::HTTPServer.new({
- :Port => 0,
- :Logger => null_logger,
- :AccessLog => [],
- :SSLEnable => true,
- :SSLCACertificateFile => File.join(__dir__, 'ca_cert.pem'),
- :SSLCertificate => cert('ssl_cert.pem'),
- :SSLPrivateKey => key('ssl_key.pem'),
- :SSLVerifyClient => nil,
- :SSLCertName => nil,
- }.merge(config))
- server.mount_proc("/yaml") do |req, res|
- res.body = "--- true\n"
- end
- server.mount_proc("/insecure_redirect") do |req, res|
- res.set_redirect(WEBrick::HTTPStatus::MovedPermanently, req.query['to'])
- end
- server.ssl_context.tmp_dh_callback = proc { TEST_KEY_DH2048 }
- t = Thread.new do
- begin
- server.start
- rescue Exception => ex
- puts "ERROR during server thread: #{ex.message}"
- raise
- ensure
- server.shutdown
- end
- end
- while server.status != :Running
- sleep 0.1
- unless t.alive?
- t.join
- raise
- end
- end
- @ssl_server = server
- @ssl_server_thread = t
- server
- end
-
- def start_server(data)
- null_logger = NilLog.new
- s = WEBrick::HTTPServer.new(
- :Port => 0,
- :DocumentRoot => nil,
- :Logger => null_logger,
- :AccessLog => null_logger
- )
- s.mount_proc("/kill") {|req, res| s.shutdown }
- s.mount_proc("/yaml") do |req, res|
- if req["X-Captain"]
- res.body = req["X-Captain"]
- elsif @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
- end
- s.mount_proc("/yaml.Z") do |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
- end
- th = Thread.new do
- begin
- s.start
- rescue Exception => ex
- abort "ERROR during server thread: #{ex.message}"
- ensure
- s.shutdown
- end
- end
- th[:server] = s
- th
- end
-
- def cert(filename)
- OpenSSL::X509::Certificate.new(File.read(File.join(__dir__, filename)))
- end
-
- def key(filename)
- OpenSSL::PKey::RSA.new(File.read(File.join(__dir__, filename)))
- end
-end if Gem::HAVE_OPENSSL
+end
diff --git a/test/rubygems/test_gem_remote_fetcher_local_server.rb b/test/rubygems/test_gem_remote_fetcher_local_server.rb
new file mode 100644
index 0000000000..3d3e8b503b
--- /dev/null
+++ b/test/rubygems/test_gem_remote_fetcher_local_server.rb
@@ -0,0 +1,220 @@
+# frozen_string_literal: true
+
+require_relative "helper"
+
+require "socket"
+
+require "rubygems/remote_fetcher"
+require "rubygems/package"
+
+# = 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 TestGemRemoteFetcherLocalServer < Gem::TestCase
+ 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
+ description: Rake is a Make-like program implemented in Ruby. Tasks and dependencies are specified in standard Ruby syntax.
+ autorequire:
+ 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")
+
+ def setup
+ @proxies = %w[https_proxy http_proxy HTTP_PROXY http_proxy_user HTTP_PROXY_USER http_proxy_pass HTTP_PROXY_PASS no_proxy NO_PROXY]
+ @old_proxies = @proxies.map {|k| ENV[k] }
+ @proxies.each {|k| ENV[k] = nil }
+
+ super
+
+ @normal_server ||= start_server(SERVER_DATA)
+ @proxy_server ||= start_server(PROXY_DATA)
+
+ @server_uri = "http://localhost:#{@normal_server[:server].addr[1]}" + "/yaml"
+ @proxy_uri = "http://localhost:#{@proxy_server[:server].addr[1]}"
+
+ Gem::RemoteFetcher.fetcher = nil
+ @stub_ui = Gem::MockGemUi.new
+ @fetcher = Gem::RemoteFetcher.fetcher
+ end
+
+ def teardown
+ @fetcher&.close_all
+
+ if @normal_server
+ @normal_server.kill.join
+ @normal_server[:server].close
+ @normal_server = nil
+ end
+ if @proxy_server
+ @proxy_server.kill.join
+ @proxy_server[:server].close
+ @proxy_server = nil
+ end
+
+ super
+ Gem.configuration[:http_proxy] = nil
+ @proxies.each_with_index {|k, i| ENV[k] = @old_proxies[i] }
+ end
+
+ def test_no_proxy
+ use_ui @stub_ui do
+ assert_data_from_server @fetcher.fetch_path(@server_uri)
+ response = @fetcher.fetch_path(@server_uri, nil, true)
+ assert_equal SERVER_DATA.size, response["content-length"].to_i
+ end
+ end
+
+ def test_implicit_no_proxy
+ use_ui @stub_ui do
+ ENV["http_proxy"] = "http://fakeurl:12345"
+ fetcher = Gem::RemoteFetcher.new :no_proxy
+ @fetcher = fetcher
+ assert_data_from_server fetcher.fetch_path(@server_uri)
+ end
+ end
+
+ def test_implicit_proxy
+ use_ui @stub_ui do
+ ENV["http_proxy"] = @proxy_uri
+ fetcher = Gem::RemoteFetcher.new nil
+ @fetcher = fetcher
+ assert_data_from_proxy fetcher.fetch_path(@server_uri)
+ end
+ end
+
+ def test_implicit_upper_case_proxy
+ use_ui @stub_ui do
+ ENV["HTTP_PROXY"] = @proxy_uri
+ fetcher = Gem::RemoteFetcher.new nil
+ @fetcher = fetcher
+ assert_data_from_proxy fetcher.fetch_path(@server_uri)
+ end
+ end
+
+ def test_implicit_proxy_no_env
+ use_ui @stub_ui do
+ fetcher = Gem::RemoteFetcher.new nil
+ @fetcher = fetcher
+ assert_data_from_server fetcher.fetch_path(@server_uri)
+ end
+ end
+
+ def test_fetch_http_with_additional_headers
+ ENV["http_proxy"] = @proxy_uri
+ ENV["no_proxy"] = Gem::URI.parse(@server_uri).host
+ fetcher = Gem::RemoteFetcher.new nil, nil, { "X-Captain" => "murphy" }
+ @fetcher = fetcher
+ assert_equal "murphy", fetcher.fetch_path(@server_uri)
+ end
+
+ def test_observe_no_proxy_env_single_host
+ use_ui @stub_ui do
+ ENV["http_proxy"] = @proxy_uri
+ ENV["no_proxy"] = Gem::URI.parse(@server_uri).host
+ fetcher = Gem::RemoteFetcher.new nil
+ @fetcher = fetcher
+ assert_data_from_server fetcher.fetch_path(@server_uri)
+ end
+ end
+
+ def test_observe_no_proxy_env_list
+ use_ui @stub_ui do
+ ENV["http_proxy"] = @proxy_uri
+ ENV["no_proxy"] = "fakeurl.com, #{Gem::URI.parse(@server_uri).host}"
+ fetcher = Gem::RemoteFetcher.new nil
+ @fetcher = fetcher
+ assert_data_from_server fetcher.fetch_path(@server_uri)
+ end
+ end
+
+ private
+
+ attr_reader :normal_server, :proxy_server
+
+ def assert_data_from_server(data)
+ assert_match(/0\.4\.11/, data, "Data is not from server")
+ end
+
+ def assert_data_from_proxy(data)
+ assert_match(/0\.4\.2/, data, "Data is not from proxy")
+ end
+
+ def start_server(data)
+ server = TCPServer.new("localhost", 0)
+ thread = Thread.new do
+ loop do
+ client = server.accept
+ handle_request(client, data)
+ end
+ end
+ thread[:server] = server
+ thread
+ end
+
+ def handle_request(client, data)
+ request_line = client.gets
+ headers = {}
+ while (line = client.gets) && line != "\r\n"
+ key, value = line.split(": ", 2)
+ headers[key] = value.strip
+ end
+
+ if request_line.start_with?("GET /yaml")
+ response = headers["X-Captain"] ? headers["X-Captain"] : data
+ client.print "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: #{response.size}\r\n\r\n#{response}"
+ elsif request_line.start_with?("HEAD /yaml") || request_line.start_with?("GET http://") && request_line.include?("/yaml")
+ client.print "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: #{data.size}\r\n\r\n#{data}"
+ else
+ client.print "HTTP/1.1 404 Not Found\r\nContent-Type: text/html\r\n\r\n<h1>NOT FOUND</h1>"
+ end
+ client.close
+ end
+end
diff --git a/test/rubygems/test_gem_remote_fetcher_local_ssl_server.rb b/test/rubygems/test_gem_remote_fetcher_local_ssl_server.rb
new file mode 100644
index 0000000000..ad5be1a033
--- /dev/null
+++ b/test/rubygems/test_gem_remote_fetcher_local_ssl_server.rb
@@ -0,0 +1,195 @@
+# frozen_string_literal: true
+
+require_relative "helper"
+require "socket"
+require "openssl"
+
+unless Gem::HAVE_OPENSSL
+ warn "Skipping Gem::RemoteFetcher tests. openssl not found."
+end
+
+require "rubygems/remote_fetcher"
+require "rubygems/package"
+
+class TestGemRemoteFetcherLocalSSLServer < Gem::TestCase
+ include Gem::DefaultUserInteraction
+
+ # Generated via:
+ # x = OpenSSL::PKey::DH.new(2048) # wait a while...
+ # x.to_s => pem
+ TEST_KEY_DH2048 = OpenSSL::PKey::DH.new <<-_END_OF_PEM_
+-----BEGIN DH PARAMETERS-----
+MIIBCAKCAQEA3Ze2EHSfYkZLUn557torAmjBgPsqzbodaRaGZtgK1gEU+9nNJaFV
+G1JKhmGUiEDyIW7idsBpe4sX/Wqjnp48Lr8IeI/SlEzLdoGpf05iRYXC8Cm9o8aM
+cfmVgoSEAo9YLBpzoji2jHkO7Q5IPt4zxbTdlmmGFLc/GO9q7LGHhC+rcMcNTGsM
+49AnILNn49pq4Y72jSwdmvq4psHZwwFBbPwLdw6bLUDDCN90jfqvYt18muwUxDiN
+NP0fuvVAIB158VnQ0liHSwcl6+9vE1mL0Jo/qEXQxl0+UdKDjaGfTsn6HIrwTnmJ
+PeIQQkFng2VVot/WAQbv3ePqWq07g1BBcwIBAg==
+-----END DH PARAMETERS-----
+ _END_OF_PEM_
+
+ def setup
+ super
+ @ssl_server_thread = nil
+ @ssl_server = nil
+ end
+
+ def teardown
+ if @ssl_server_thread
+ @ssl_server_thread.kill.join
+ @ssl_server_thread = nil
+ end
+ if @ssl_server
+ @ssl_server.close
+ @ssl_server = nil
+ end
+ super
+ end
+
+ def test_ssl_connection
+ ssl_server = start_ssl_server
+ temp_ca_cert = File.join(__dir__, "ca_cert.pem")
+ with_configured_fetcher(":ssl_ca_cert: #{temp_ca_cert}") do |fetcher|
+ fetcher.fetch_path("https://localhost:#{ssl_server.addr[1]}/yaml")
+ end
+ end
+
+ def test_ssl_client_cert_auth_connection
+ ssl_server = start_ssl_server(
+ { verify_mode: OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT }
+ )
+
+ temp_ca_cert = File.join(__dir__, "ca_cert.pem")
+ temp_client_cert = File.join(__dir__, "client.pem")
+
+ with_configured_fetcher(
+ ":ssl_ca_cert: #{temp_ca_cert}\n" \
+ ":ssl_client_cert: #{temp_client_cert}\n"
+ ) do |fetcher|
+ fetcher.fetch_path("https://localhost:#{ssl_server.addr[1]}/yaml")
+ end
+ end
+
+ def test_do_not_allow_invalid_client_cert_auth_connection
+ ssl_server = start_ssl_server(
+ { verify_mode: OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT }
+ )
+
+ temp_ca_cert = File.join(__dir__, "ca_cert.pem")
+ temp_client_cert = File.join(__dir__, "invalid_client.pem")
+
+ with_configured_fetcher(
+ ":ssl_ca_cert: #{temp_ca_cert}\n" \
+ ":ssl_client_cert: #{temp_client_cert}\n"
+ ) do |fetcher|
+ assert_raise Gem::RemoteFetcher::FetchError do
+ fetcher.fetch_path("https://localhost:#{ssl_server.addr[1]}/yaml")
+ end
+ end
+ end
+
+ def test_do_not_allow_insecure_ssl_connection_by_default
+ ssl_server = start_ssl_server
+ with_configured_fetcher do |fetcher|
+ assert_raise Gem::RemoteFetcher::FetchError do
+ fetcher.fetch_path("https://localhost:#{ssl_server.addr[1]}/yaml")
+ end
+ end
+ end
+
+ def test_ssl_connection_allow_verify_none
+ ssl_server = start_ssl_server
+ with_configured_fetcher(":ssl_verify_mode: 0") do |fetcher|
+ fetcher.fetch_path("https://localhost:#{ssl_server.addr[1]}/yaml")
+ end
+ end
+
+ def test_do_not_follow_insecure_redirect
+ @server_uri = "http://example.com"
+ ssl_server = start_ssl_server
+ temp_ca_cert = File.join(__dir__, "ca_cert.pem")
+ expected_error_message =
+ "redirecting to non-https resource: #{@server_uri} (https://localhost:#{ssl_server.addr[1]}/insecure_redirect?to=#{@server_uri})"
+
+ with_configured_fetcher(":ssl_ca_cert: #{temp_ca_cert}") do |fetcher|
+ err = assert_raise Gem::RemoteFetcher::FetchError do
+ fetcher.fetch_path("https://localhost:#{ssl_server.addr[1]}/insecure_redirect?to=#{@server_uri}")
+ end
+
+ assert_equal(err.message, expected_error_message)
+ end
+ end
+
+ def test_nil_ca_cert
+ ssl_server = start_ssl_server
+ temp_ca_cert = nil
+
+ with_configured_fetcher(":ssl_ca_cert: #{temp_ca_cert}") do |fetcher|
+ assert_raise Gem::RemoteFetcher::FetchError do
+ fetcher.fetch_path("https://localhost:#{ssl_server.addr[1]}")
+ end
+ end
+ end
+
+ private
+
+ def with_configured_fetcher(config_str = nil, &block)
+ if config_str
+ temp_conf = File.join @tempdir, ".gemrc"
+ File.open temp_conf, "w" do |fp|
+ fp.puts config_str
+ end
+ Gem.configuration = Gem::ConfigFile.new %W[--config-file #{temp_conf}]
+ end
+ fetcher = Gem::RemoteFetcher.new
+ yield fetcher
+ sleep 0.5 unless RUBY_PLATFORM.match?(/mswin|mingw/)
+ ensure
+ fetcher.close_all
+ Gem.configuration = nil
+ end
+
+ def start_ssl_server(config = {})
+ server = TCPServer.new(0)
+ ctx = OpenSSL::SSL::SSLContext.new
+ ctx.cert = cert("ssl_cert.pem")
+ ctx.key = key("ssl_key.pem")
+ ctx.ca_file = File.join(__dir__, "ca_cert.pem")
+ ctx.tmp_dh_callback = proc { TEST_KEY_DH2048 }
+ ctx.verify_mode = config[:verify_mode] if config[:verify_mode]
+ @ssl_server = OpenSSL::SSL::SSLServer.new(server, ctx)
+ @ssl_server_thread = Thread.new do
+ loop do
+ ssl_client = @ssl_server.accept
+ Thread.new(ssl_client) do |client|
+ handle_request(client)
+ ensure
+ client.close
+ end
+ rescue OpenSSL::SSL::SSLError
+ # Ignore SSL errors because we're testing them implicitly
+ end
+ end
+ @ssl_server
+ end
+
+ def handle_request(client)
+ request = client.gets
+ if request.start_with?("GET /yaml")
+ client.print "HTTP/1.1 200 OK\r\nContent-Type: text/yaml\r\n\r\n--- true\n"
+ elsif request.start_with?("GET /insecure_redirect")
+ location = request.match(/to=([^ ]+)/)[1]
+ client.print "HTTP/1.1 301 Moved Permanently\r\nLocation: #{location}\r\n\r\n"
+ else
+ client.print "HTTP/1.1 404 Not Found\r\n\r\n"
+ end
+ end
+
+ def cert(filename)
+ OpenSSL::X509::Certificate.new(File.read(File.join(__dir__, filename)))
+ end
+
+ def key(filename)
+ OpenSSL::PKey::RSA.new(File.read(File.join(__dir__, filename)))
+ end
+end if Gem::HAVE_OPENSSL
diff --git a/test/rubygems/test_gem_remote_fetcher_s3.rb b/test/rubygems/test_gem_remote_fetcher_s3.rb
new file mode 100644
index 0000000000..fe7eb7ec01
--- /dev/null
+++ b/test/rubygems/test_gem_remote_fetcher_s3.rb
@@ -0,0 +1,233 @@
+# frozen_string_literal: true
+
+require_relative "helper"
+
+require "rubygems/remote_fetcher"
+require "rubygems/package"
+
+class TestGemRemoteFetcherS3 < Gem::TestCase
+ include Gem::DefaultUserInteraction
+
+ def setup
+ super
+
+ @a1, @a1_gem = util_gem "a", "1" do |s|
+ s.executables << "a_bin"
+ end
+
+ @a1.loaded_from = File.join(@gemhome, "specifications", @a1.full_name)
+ end
+
+ def assert_fetch_s3(url, signature, token=nil, region="us-east-1", instance_profile_json=nil)
+ fetcher = Gem::RemoteFetcher.new nil
+ @fetcher = fetcher
+ $fetched_uri = nil
+ $instance_profile = instance_profile_json
+
+ def fetcher.request(uri, request_class, last_modified = nil)
+ $fetched_uri = uri
+ res = Gem::Net::HTTPOK.new nil, 200, nil
+ def res.body
+ "success"
+ end
+ res
+ end
+
+ def fetcher.s3_uri_signer(uri)
+ require "json"
+ s3_uri_signer = Gem::S3URISigner.new(uri)
+ def s3_uri_signer.ec2_metadata_credentials_json
+ JSON.parse($instance_profile)
+ end
+ # Running sign operation to make sure uri.query is not mutated
+ s3_uri_signer.sign
+ raise "URI query is not empty: #{uri.query}" unless uri.query.nil?
+ s3_uri_signer
+ end
+
+ data = fetcher.fetch_s3 Gem::URI.parse(url)
+
+ assert_equal "https://my-bucket.s3.#{region}.amazonaws.com/gems/specs.4.8.gz?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=testuser%2F20190624%2F#{region}%2Fs3%2Faws4_request&X-Amz-Date=20190624T050641Z&X-Amz-Expires=86400#{token ? "&X-Amz-Security-Token=" + token : ""}&X-Amz-SignedHeaders=host&X-Amz-Signature=#{signature}", $fetched_uri.to_s
+ assert_equal "success", data
+ ensure
+ $fetched_uri = nil
+ end
+
+ def test_fetch_s3_config_creds
+ Gem.configuration[:s3_source] = {
+ "my-bucket" => { id: "testuser", secret: "testpass" },
+ }
+ url = "s3://my-bucket/gems/specs.4.8.gz"
+ Time.stub :now, Time.at(1_561_353_581) do
+ assert_fetch_s3 url, "20f974027db2f3cd6193565327a7c73457a138efb1a63ea248d185ce6827d41b"
+ end
+ ensure
+ Gem.configuration[:s3_source] = nil
+ end
+
+ def test_fetch_s3_config_creds_with_region
+ Gem.configuration[:s3_source] = {
+ "my-bucket" => { id: "testuser", secret: "testpass", region: "us-west-2" },
+ }
+ url = "s3://my-bucket/gems/specs.4.8.gz"
+ Time.stub :now, Time.at(1_561_353_581) do
+ assert_fetch_s3 url, "4afc3010757f1fd143e769f1d1dabd406476a4fc7c120e9884fd02acbb8f26c9", nil, "us-west-2"
+ end
+ ensure
+ Gem.configuration[:s3_source] = nil
+ end
+
+ def test_fetch_s3_config_creds_with_token
+ Gem.configuration[:s3_source] = {
+ "my-bucket" => { id: "testuser", secret: "testpass", security_token: "testtoken" },
+ }
+ url = "s3://my-bucket/gems/specs.4.8.gz"
+ Time.stub :now, Time.at(1_561_353_581) do
+ assert_fetch_s3 url, "935160a427ef97e7630f799232b8f208c4a4e49aad07d0540572a2ad5fe9f93c", "testtoken"
+ end
+ ensure
+ Gem.configuration[:s3_source] = nil
+ end
+
+ def test_fetch_s3_env_creds
+ ENV["AWS_ACCESS_KEY_ID"] = "testuser"
+ ENV["AWS_SECRET_ACCESS_KEY"] = "testpass"
+ ENV["AWS_SESSION_TOKEN"] = nil
+ Gem.configuration[:s3_source] = {
+ "my-bucket" => { provider: "env" },
+ }
+ url = "s3://my-bucket/gems/specs.4.8.gz"
+ Time.stub :now, Time.at(1_561_353_581) do
+ assert_fetch_s3 url, "20f974027db2f3cd6193565327a7c73457a138efb1a63ea248d185ce6827d41b"
+ end
+ ensure
+ ENV.each_key {|key| ENV.delete(key) if key.start_with?("AWS") }
+ Gem.configuration[:s3_source] = nil
+ end
+
+ def test_fetch_s3_env_creds_with_region
+ ENV["AWS_ACCESS_KEY_ID"] = "testuser"
+ ENV["AWS_SECRET_ACCESS_KEY"] = "testpass"
+ ENV["AWS_SESSION_TOKEN"] = nil
+ Gem.configuration[:s3_source] = {
+ "my-bucket" => { provider: "env", region: "us-west-2" },
+ }
+ url = "s3://my-bucket/gems/specs.4.8.gz"
+ Time.stub :now, Time.at(1_561_353_581) do
+ assert_fetch_s3 url, "4afc3010757f1fd143e769f1d1dabd406476a4fc7c120e9884fd02acbb8f26c9", nil, "us-west-2"
+ end
+ ensure
+ ENV.each_key {|key| ENV.delete(key) if key.start_with?("AWS") }
+ Gem.configuration[:s3_source] = nil
+ end
+
+ def test_fetch_s3_env_creds_with_token
+ ENV["AWS_ACCESS_KEY_ID"] = "testuser"
+ ENV["AWS_SECRET_ACCESS_KEY"] = "testpass"
+ ENV["AWS_SESSION_TOKEN"] = "testtoken"
+ Gem.configuration[:s3_source] = {
+ "my-bucket" => { provider: "env" },
+ }
+ url = "s3://my-bucket/gems/specs.4.8.gz"
+ Time.stub :now, Time.at(1_561_353_581) do
+ assert_fetch_s3 url, "935160a427ef97e7630f799232b8f208c4a4e49aad07d0540572a2ad5fe9f93c", "testtoken"
+ end
+ ensure
+ ENV.each_key {|key| ENV.delete(key) if key.start_with?("AWS") }
+ Gem.configuration[:s3_source] = nil
+ end
+
+ def test_fetch_s3_url_creds
+ url = "s3://testuser:testpass@my-bucket/gems/specs.4.8.gz"
+ Time.stub :now, Time.at(1_561_353_581) do
+ assert_fetch_s3 url, "20f974027db2f3cd6193565327a7c73457a138efb1a63ea248d185ce6827d41b"
+ end
+ end
+
+ def test_fetch_s3_instance_profile_creds
+ Gem.configuration[:s3_source] = {
+ "my-bucket" => { provider: "instance_profile" },
+ }
+
+ url = "s3://my-bucket/gems/specs.4.8.gz"
+ Time.stub :now, Time.at(1_561_353_581) do
+ assert_fetch_s3 url, "20f974027db2f3cd6193565327a7c73457a138efb1a63ea248d185ce6827d41b", nil, "us-east-1",
+ '{"AccessKeyId": "testuser", "SecretAccessKey": "testpass"}'
+ end
+ ensure
+ Gem.configuration[:s3_source] = nil
+ end
+
+ def test_fetch_s3_instance_profile_creds_with_region
+ Gem.configuration[:s3_source] = {
+ "my-bucket" => { provider: "instance_profile", region: "us-west-2" },
+ }
+
+ url = "s3://my-bucket/gems/specs.4.8.gz"
+ Time.stub :now, Time.at(1_561_353_581) do
+ assert_fetch_s3 url, "4afc3010757f1fd143e769f1d1dabd406476a4fc7c120e9884fd02acbb8f26c9", nil, "us-west-2",
+ '{"AccessKeyId": "testuser", "SecretAccessKey": "testpass"}'
+ end
+ ensure
+ Gem.configuration[:s3_source] = nil
+ end
+
+ def test_fetch_s3_instance_profile_creds_with_token
+ Gem.configuration[:s3_source] = {
+ "my-bucket" => { provider: "instance_profile" },
+ }
+
+ url = "s3://my-bucket/gems/specs.4.8.gz"
+ Time.stub :now, Time.at(1_561_353_581) do
+ assert_fetch_s3 url, "935160a427ef97e7630f799232b8f208c4a4e49aad07d0540572a2ad5fe9f93c", "testtoken", "us-east-1",
+ '{"AccessKeyId": "testuser", "SecretAccessKey": "testpass", "Token": "testtoken"}'
+ end
+ ensure
+ Gem.configuration[:s3_source] = nil
+ end
+
+ def refute_fetch_s3(url, expected_message)
+ fetcher = Gem::RemoteFetcher.new nil
+ @fetcher = fetcher
+
+ e = assert_raise Gem::RemoteFetcher::FetchError do
+ fetcher.fetch_s3 Gem::URI.parse(url)
+ end
+
+ assert_match expected_message, e.message
+ end
+
+ def test_fetch_s3_no_source_key
+ url = "s3://my-bucket/gems/specs.4.8.gz"
+ refute_fetch_s3 url, "no s3_source key exists in .gemrc"
+ end
+
+ def test_fetch_s3_no_host
+ Gem.configuration[:s3_source] = {
+ "my-bucket" => { id: "testuser", secret: "testpass" },
+ }
+
+ url = "s3://other-bucket/gems/specs.4.8.gz"
+ refute_fetch_s3 url, "no key for host other-bucket in s3_source in .gemrc"
+ ensure
+ Gem.configuration[:s3_source] = nil
+ end
+
+ def test_fetch_s3_no_id
+ Gem.configuration[:s3_source] = { "my-bucket" => { secret: "testpass" } }
+
+ url = "s3://my-bucket/gems/specs.4.8.gz"
+ refute_fetch_s3 url, "s3_source for my-bucket missing id or secret"
+ ensure
+ Gem.configuration[:s3_source] = nil
+ end
+
+ def test_fetch_s3_no_secret
+ Gem.configuration[:s3_source] = { "my-bucket" => { id: "testuser" } }
+
+ url = "s3://my-bucket/gems/specs.4.8.gz"
+ refute_fetch_s3 url, "s3_source for my-bucket missing id or secret"
+ ensure
+ Gem.configuration[:s3_source] = nil
+ end
+end
diff --git a/test/rubygems/test_gem_request.rb b/test/rubygems/test_gem_request.rb
index 66477be7bc..5e9b264dac 100644
--- a/test/rubygems/test_gem_request.rb
+++ b/test/rubygems/test_gem_request.rb
@@ -1,25 +1,31 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/request'
-require 'ostruct'
-require 'base64'
+
+require_relative "helper"
+require "rubygems/request"
+require "ostruct"
unless Gem::HAVE_OPENSSL
- warn 'Skipping Gem::Request tests. openssl not found.'
+ warn "Skipping Gem::Request tests. openssl not found."
end
class TestGemRequest < Gem::TestCase
- CA_CERT_FILE = cert_path 'ca'
- CHILD_CERT = load_cert 'child'
- EXPIRED_CERT = load_cert 'expired'
- PUBLIC_CERT = load_cert 'public'
- PUBLIC_CERT_FILE = cert_path 'public'
- SSL_CERT = load_cert 'ssl'
+ CA_CERT_FILE = cert_path "ca"
+ CHILD_CERT = load_cert "child"
+ EXPIRED_CERT = load_cert "expired"
+ PUBLIC_CERT = load_cert "public"
+ PUBLIC_CERT_FILE = cert_path "public"
+ SSL_CERT = load_cert "ssl"
def make_request(uri, request_class, last_modified, proxy)
Gem::Request.create_with_proxy uri, request_class, last_modified, proxy
end
+ # This method is same code as Base64.encode64
+ # We should not use Base64.encode64 because we need to avoid gem activation.
+ def base64_encode64(bin)
+ [bin].pack("m")
+ end
+
def setup
@proxies = %w[http_proxy https_proxy HTTP_PROXY http_proxy_user HTTP_PROXY_USER http_proxy_pass HTTP_PROXY_PASS no_proxy NO_PROXY]
@old_proxies = @proxies.map {|k| ENV[k] }
@@ -28,7 +34,7 @@ class TestGemRequest < Gem::TestCase
super
@proxy_uri = "http://localhost:1234"
- @uri = URI('http://example')
+ @uri = Gem::URI("http://example")
@request = make_request @uri, nil, nil, nil
end
@@ -40,7 +46,7 @@ class TestGemRequest < Gem::TestCase
end
def test_initialize_proxy
- proxy_uri = 'http://proxy.example.com'
+ proxy_uri = "http://proxy.example.com"
request = make_request @uri, nil, nil, proxy_uri
@@ -48,41 +54,41 @@ class TestGemRequest < Gem::TestCase
end
def test_initialize_proxy_URI
- proxy_uri = 'http://proxy.example.com'
+ proxy_uri = "http://proxy.example.com"
- request = make_request @uri, nil, nil, URI(proxy_uri)
+ request = make_request @uri, nil, nil, Gem::URI(proxy_uri)
assert_equal proxy_uri, request.proxy_uri.to_s
end
def test_initialize_proxy_ENV
- ENV['http_proxy'] = @proxy_uri
- ENV['http_proxy_user'] = 'foo'
- ENV['http_proxy_pass'] = 'bar'
+ ENV["http_proxy"] = @proxy_uri
+ ENV["http_proxy_user"] = "foo"
+ ENV["http_proxy_pass"] = "bar"
request = make_request @uri, nil, nil, nil
proxy = request.proxy_uri
- assert_equal 'foo', proxy.user
- assert_equal 'bar', proxy.password
+ assert_equal "foo", proxy.user
+ assert_equal "bar", proxy.password
end
def test_initialize_proxy_ENV_https
- ENV['https_proxy'] = @proxy_uri
+ ENV["https_proxy"] = @proxy_uri
- request = make_request URI('https://example'), nil, nil, nil
+ request = make_request Gem::URI("https://example"), nil, nil, nil
proxy = request.proxy_uri
- assert_equal URI(@proxy_uri), proxy
+ assert_equal Gem::URI(@proxy_uri), proxy
end
def test_proxy_ENV
- ENV['http_proxy'] = "http://proxy"
- ENV['https_proxy'] = ""
+ ENV["http_proxy"] = "http://proxy"
+ ENV["https_proxy"] = ""
- request = make_request URI('https://example'), nil, nil, nil
+ request = make_request Gem::URI("https://example"), nil, nil, nil
proxy = request.proxy_uri
@@ -90,13 +96,13 @@ class TestGemRequest < Gem::TestCase
end
def test_configure_connection_for_https
- connection = Net::HTTP.new 'localhost', 443
+ connection = Gem::Net::HTTP.new "localhost", 443
request = Class.new(Gem::Request) do
def self.get_cert_files
[TestGemRequest::PUBLIC_CERT_FILE]
end
- end.create_with_proxy URI('https://example'), nil, nil, nil
+ end.create_with_proxy Gem::URI("https://example"), nil, nil, nil
Gem::Request.configure_connection_for_https connection, request.cert_files
@@ -106,16 +112,16 @@ class TestGemRequest < Gem::TestCase
end
def test_configure_connection_for_https_ssl_ca_cert
- ssl_ca_cert, Gem.configuration.ssl_ca_cert =
- Gem.configuration.ssl_ca_cert, CA_CERT_FILE
+ ssl_ca_cert = Gem.configuration.ssl_ca_cert
+ Gem.configuration.ssl_ca_cert = CA_CERT_FILE
- connection = Net::HTTP.new 'localhost', 443
+ connection = Gem::Net::HTTP.new "localhost", 443
request = Class.new(Gem::Request) do
def self.get_cert_files
[TestGemRequest::PUBLIC_CERT_FILE]
end
- end.create_with_proxy URI('https://example'), nil, nil, nil
+ end.create_with_proxy Gem::URI("https://example"), nil, nil, nil
Gem::Request.configure_connection_for_https connection, request.cert_files
@@ -128,66 +134,66 @@ class TestGemRequest < Gem::TestCase
end
def test_get_proxy_from_env_fallback
- ENV['http_proxy'] = @proxy_uri
+ ENV["http_proxy"] = @proxy_uri
request = make_request @uri, nil, nil, nil
proxy = request.proxy_uri
- assert_equal URI(@proxy_uri), proxy
+ assert_equal Gem::URI(@proxy_uri), proxy
end
def test_get_proxy_from_env_https
- ENV['https_proxy'] = @proxy_uri
- uri = URI('https://example')
+ ENV["https_proxy"] = @proxy_uri
+ uri = Gem::URI("https://example")
request = make_request uri, nil, nil, nil
proxy = request.proxy_uri
- assert_equal URI(@proxy_uri), proxy
+ assert_equal Gem::URI(@proxy_uri), proxy
end
def test_get_proxy_from_env_domain
- ENV['http_proxy'] = @proxy_uri
- ENV['http_proxy_user'] = 'foo\user'
- ENV['http_proxy_pass'] = 'my bar'
+ ENV["http_proxy"] = @proxy_uri
+ ENV["http_proxy_user"] = 'foo\user'
+ ENV["http_proxy_pass"] = "my bar"
request = make_request @uri, nil, nil, nil
proxy = request.proxy_uri
assert_equal 'foo\user', Gem::UriFormatter.new(proxy.user).unescape
- assert_equal 'my bar', Gem::UriFormatter.new(proxy.password).unescape
+ assert_equal "my bar", Gem::UriFormatter.new(proxy.password).unescape
end
def test_get_proxy_from_env_escape
- ENV['http_proxy'] = @proxy_uri
- ENV['http_proxy_user'] = 'foo@user'
- ENV['http_proxy_pass'] = 'my@bar'
+ ENV["http_proxy"] = @proxy_uri
+ ENV["http_proxy_user"] = "foo@user"
+ ENV["http_proxy_pass"] = "my@bar"
request = make_request @uri, nil, nil, nil
proxy = request.proxy_uri
- assert_equal 'foo%40user', proxy.user
- assert_equal 'my%40bar', proxy.password
+ assert_equal "foo%40user", proxy.user
+ assert_equal "my%40bar", proxy.password
end
def test_get_proxy_from_env_normalize
- ENV['HTTP_PROXY'] = 'fakeurl:12345'
+ ENV["HTTP_PROXY"] = "fakeurl:12345"
request = make_request @uri, nil, nil, nil
- assert_equal 'http://fakeurl:12345', request.proxy_uri.to_s
+ assert_equal "http://fakeurl:12345", request.proxy_uri.to_s
end
def test_get_proxy_from_env_empty
- ENV['HTTP_PROXY'] = ''
- ENV.delete 'http_proxy'
+ ENV["HTTP_PROXY"] = ""
+ ENV.delete "http_proxy"
request = make_request @uri, nil, nil, nil
assert_nil request.proxy_uri
end
def test_fetch
- uri = Gem::Uri.new(URI.parse "#{@gem_repo}/specs.#{Gem.marshal_version}")
- response = util_stub_net_http(:body => :junk, :code => 200) do
- @request = make_request(uri, Net::HTTP::Get, nil, nil)
+ uri = Gem::Uri.new(Gem::URI.parse("#{@gem_repo}/specs.#{Gem.marshal_version}"))
+ response = util_stub_net_http(body: :junk, code: 200) do
+ @request = make_request(uri, Gem::Net::HTTP::Get, nil, nil)
@request.fetch
end
@@ -198,79 +204,79 @@ class TestGemRequest < Gem::TestCase
def test_fetch_basic_auth
Gem.configuration.verbose = :really
- uri = Gem::Uri.new(URI.parse "https://user:pass@example.rubygems/specs.#{Gem.marshal_version}")
- conn = util_stub_net_http(:body => :junk, :code => 200) do |c|
+ uri = Gem::Uri.new(Gem::URI.parse("https://user:pass@example.rubygems/specs.#{Gem.marshal_version}"))
+ conn = util_stub_net_http(body: :junk, code: 200) do |c|
use_ui @ui do
- @request = make_request(uri, Net::HTTP::Get, nil, nil)
+ @request = make_request(uri, Gem::Net::HTTP::Get, nil, nil)
@request.fetch
end
c
end
- auth_header = conn.payload['Authorization']
- assert_equal "Basic #{Base64.encode64('user:pass')}".strip, auth_header
+ auth_header = conn.payload["Authorization"]
+ assert_equal "Basic #{base64_encode64("user:pass")}".strip, auth_header
assert_includes @ui.output, "GET https://user:REDACTED@example.rubygems/specs.#{Gem.marshal_version}"
end
def test_fetch_basic_auth_encoded
Gem.configuration.verbose = :really
- uri = Gem::Uri.new(URI.parse "https://user:%7BDEScede%7Dpass@example.rubygems/specs.#{Gem.marshal_version}")
+ uri = Gem::Uri.new(Gem::URI.parse("https://user:%7BDEScede%7Dpass@example.rubygems/specs.#{Gem.marshal_version}"))
- conn = util_stub_net_http(:body => :junk, :code => 200) do |c|
+ conn = util_stub_net_http(body: :junk, code: 200) do |c|
use_ui @ui do
- @request = make_request(uri, Net::HTTP::Get, nil, nil)
+ @request = make_request(uri, Gem::Net::HTTP::Get, nil, nil)
@request.fetch
end
c
end
- auth_header = conn.payload['Authorization']
- assert_equal "Basic #{Base64.encode64('user:{DEScede}pass')}".strip, auth_header
+ auth_header = conn.payload["Authorization"]
+ assert_equal "Basic #{base64_encode64("user:{DEScede}pass")}".strip, auth_header
assert_includes @ui.output, "GET https://user:REDACTED@example.rubygems/specs.#{Gem.marshal_version}"
end
def test_fetch_basic_oauth_encoded
Gem.configuration.verbose = :really
- uri = Gem::Uri.new(URI.parse "https://%7BDEScede%7Dpass:x-oauth-basic@example.rubygems/specs.#{Gem.marshal_version}")
+ uri = Gem::Uri.new(Gem::URI.parse("https://%7BDEScede%7Dpass:x-oauth-basic@example.rubygems/specs.#{Gem.marshal_version}"))
- conn = util_stub_net_http(:body => :junk, :code => 200) do |c|
+ conn = util_stub_net_http(body: :junk, code: 200) do |c|
use_ui @ui do
- @request = make_request(uri, Net::HTTP::Get, nil, nil)
+ @request = make_request(uri, Gem::Net::HTTP::Get, nil, nil)
@request.fetch
end
c
end
- auth_header = conn.payload['Authorization']
- assert_equal "Basic #{Base64.encode64('{DEScede}pass:x-oauth-basic')}".strip, auth_header
+ auth_header = conn.payload["Authorization"]
+ assert_equal "Basic #{base64_encode64("{DEScede}pass:x-oauth-basic")}".strip, auth_header
assert_includes @ui.output, "GET https://REDACTED:x-oauth-basic@example.rubygems/specs.#{Gem.marshal_version}"
end
def test_fetch_head
- uri = Gem::Uri.new(URI.parse "#{@gem_repo}/specs.#{Gem.marshal_version}")
- response = util_stub_net_http(:body => '', :code => 200) do |conn|
- @request = make_request(uri, Net::HTTP::Get, nil, nil)
+ uri = Gem::Uri.new(Gem::URI.parse("#{@gem_repo}/specs.#{Gem.marshal_version}"))
+ response = util_stub_net_http(body: "", code: 200) do |_conn|
+ @request = make_request(uri, Gem::Net::HTTP::Get, nil, nil)
@request.fetch
end
assert_equal 200, response.code
- assert_equal '', response.body
+ assert_equal "", response.body
end
def test_fetch_unmodified
- uri = Gem::Uri.new(URI.parse "#{@gem_repo}/specs.#{Gem.marshal_version}")
+ uri = Gem::Uri.new(Gem::URI.parse("#{@gem_repo}/specs.#{Gem.marshal_version}"))
t = Time.utc(2013, 1, 2, 3, 4, 5)
- conn, response = util_stub_net_http(:body => '', :code => 304) do |c|
- @request = make_request(uri, Net::HTTP::Get, t, nil)
+ conn, response = util_stub_net_http(body: "", code: 304) do |c|
+ @request = make_request(uri, Gem::Net::HTTP::Get, t, nil)
[c, @request.fetch]
end
assert_equal 304, response.code
- assert_equal '', response.body
+ assert_equal "", response.body
- modified_header = conn.payload['if-modified-since']
+ modified_header = conn.payload["if-modified-since"]
- assert_equal 'Wed, 02 Jan 2013 03:04:05 GMT', modified_header
+ assert_equal "Wed, 02 Jan 2013 03:04:05 GMT", modified_header
end
def test_user_agent
@@ -280,18 +286,18 @@ class TestGemRequest < Gem::TestCase
assert_match %r{RubyGems/#{Regexp.escape Gem::VERSION}}, ua
assert_match %r{ #{Regexp.escape Gem::Platform.local.to_s} }, ua
assert_match %r{Ruby/#{Regexp.escape RUBY_VERSION}}, ua
- assert_match %r{\(#{Regexp.escape RUBY_RELEASE_DATE} }, ua
+ assert_match(/\(#{Regexp.escape RUBY_RELEASE_DATE} /, ua)
end
def test_user_agent_engine
util_save_version
Object.send :remove_const, :RUBY_ENGINE
- Object.send :const_set, :RUBY_ENGINE, 'vroom'
+ Object.send :const_set, :RUBY_ENGINE, "vroom"
ua = make_request(@uri, nil, nil, nil).user_agent
- assert_match %r{\) vroom}, ua
+ assert_match(/\) vroom/, ua)
ensure
util_restore_version
end
@@ -300,11 +306,11 @@ class TestGemRequest < Gem::TestCase
util_save_version
Object.send :remove_const, :RUBY_ENGINE
- Object.send :const_set, :RUBY_ENGINE, 'ruby'
+ Object.send :const_set, :RUBY_ENGINE, "ruby"
ua = make_request(@uri, nil, nil, nil).user_agent
- assert_match %r{\)}, ua
+ assert_match(/\)/, ua)
ensure
util_restore_version
end
@@ -327,7 +333,7 @@ class TestGemRequest < Gem::TestCase
Object.send :remove_const, :RUBY_PATCHLEVEL
Object.send :const_set, :RUBY_PATCHLEVEL, -1
- Object.send :remove_const, :RUBY_REVISION if defined?(RUBY_REVISION)
+ Object.send :remove_const, :RUBY_REVISION
Object.send :const_set, :RUBY_REVISION, 6
ua = make_request(@uri, nil, nil, nil).user_agent
@@ -338,46 +344,38 @@ class TestGemRequest < Gem::TestCase
util_restore_version
end
- def test_user_agent_revision_missing
- util_save_version
-
- Object.send :remove_const, :RUBY_PATCHLEVEL
- Object.send :const_set, :RUBY_PATCHLEVEL, -1
- Object.send :remove_const, :RUBY_REVISION if defined?(RUBY_REVISION)
-
- ua = make_request(@uri, nil, nil, nil).user_agent
-
- assert_match %r{\(#{Regexp.escape RUBY_RELEASE_DATE}\)}, ua
- ensure
- util_restore_version
- end
-
def test_verify_certificate
pend if Gem.java_platform?
+
+ error_number = OpenSSL::X509::V_ERR_OUT_OF_MEM
+
store = OpenSSL::X509::Store.new
context = OpenSSL::X509::StoreContext.new store
- context.error = OpenSSL::X509::V_ERR_OUT_OF_MEM
+ context.error = error_number
use_ui @ui do
Gem::Request.verify_certificate context
end
- assert_equal "ERROR: SSL verification error at depth 0: out of memory (17)\n",
+ assert_equal "ERROR: SSL verification error at depth 0: out of memory (#{error_number})\n",
@ui.error
end
def test_verify_certificate_extra_message
pend if Gem.java_platform?
+
+ error_number = OpenSSL::X509::V_ERR_INVALID_CA
+
store = OpenSSL::X509::Store.new
context = OpenSSL::X509::StoreContext.new store
- context.error = OpenSSL::X509::V_ERR_INVALID_CA
+ context.error = error_number
use_ui @ui do
Gem::Request.verify_certificate context
end
expected = <<-ERROR
-ERROR: SSL verification error at depth 0: invalid CA certificate (24)
+ERROR: SSL verification error at depth 0: invalid CA certificate (#{error_number})
ERROR: Certificate is an invalid CA certificate
ERROR
@@ -486,21 +484,19 @@ ERROR: Certificate is an invalid CA certificate
def util_restore_version
Object.send :remove_const, :RUBY_ENGINE
- Object.send :const_set, :RUBY_ENGINE, @orig_RUBY_ENGINE if
- defined?(@orig_RUBY_ENGINE)
+ Object.send :const_set, :RUBY_ENGINE, @orig_ruby_engine
Object.send :remove_const, :RUBY_PATCHLEVEL
- Object.send :const_set, :RUBY_PATCHLEVEL, @orig_RUBY_PATCHLEVEL
+ Object.send :const_set, :RUBY_PATCHLEVEL, @orig_ruby_patchlevel
- Object.send :remove_const, :RUBY_REVISION if defined?(RUBY_REVISION)
- Object.send :const_set, :RUBY_REVISION, @orig_RUBY_REVISION if
- defined?(@orig_RUBY_REVISION)
+ Object.send :remove_const, :RUBY_REVISION
+ Object.send :const_set, :RUBY_REVISION, @orig_ruby_revision
end
def util_save_version
- @orig_RUBY_ENGINE = RUBY_ENGINE
- @orig_RUBY_PATCHLEVEL = RUBY_PATCHLEVEL
- @orig_RUBY_REVISION = RUBY_REVISION if defined? RUBY_REVISION
+ @orig_ruby_engine = RUBY_ENGINE
+ @orig_ruby_patchlevel = RUBY_PATCHLEVEL
+ @orig_ruby_revision = RUBY_REVISION
end
def util_stub_net_http(hash)
@@ -515,7 +511,10 @@ ERROR: Certificate is an invalid CA certificate
class Conn
attr_accessor :payload
- def new(*args); self; end
+ def new(*args)
+ self
+ end
+
def use_ssl=(bool); end
def verify_callback=(setting); end
def verify_mode=(setting); end
diff --git a/test/rubygems/test_gem_request_connection_pools.rb b/test/rubygems/test_gem_request_connection_pools.rb
index c5e7cf2ed4..966447bff6 100644
--- a/test/rubygems/test_gem_request_connection_pools.rb
+++ b/test/rubygems/test_gem_request_connection_pools.rb
@@ -1,7 +1,8 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/request'
-require 'timeout'
+
+require_relative "helper"
+require "rubygems/request"
+require "rubygems/vendored_timeout"
class TestGemRequestConnectionPool < Gem::TestCase
class FakeHttp
@@ -17,7 +18,7 @@ class TestGemRequestConnectionPool < Gem::TestCase
@old_client = Gem::Request::ConnectionPools.client
Gem::Request::ConnectionPools.client = FakeHttp
- @proxy = URI 'http://proxy.example'
+ @proxy = Gem::URI "http://proxy.example"
end
def teardown
@@ -32,9 +33,9 @@ class TestGemRequestConnectionPool < Gem::TestCase
ems.example
]
- no_proxy = pools.send :no_proxy?, 'rubygems.example', env_no_proxy
+ no_proxy = pools.send :no_proxy?, "rubygems.example", env_no_proxy
- refute no_proxy, 'mismatch'
+ refute no_proxy, "mismatch"
end
def test_to_proxy_empty_string
@@ -42,13 +43,13 @@ class TestGemRequestConnectionPool < Gem::TestCase
env_no_proxy = [""]
- no_proxy = pools.send :no_proxy?, 'ems.example', env_no_proxy
+ no_proxy = pools.send :no_proxy?, "ems.example", env_no_proxy
- refute no_proxy, 'mismatch'
+ refute no_proxy, "mismatch"
end
def test_checkout_same_connection
- uri = URI.parse('http://example/some_endpoint')
+ uri = Gem::URI.parse("http://example/some_endpoint")
pools = Gem::Request::ConnectionPools.new nil, []
pool = pools.pool_for uri
@@ -66,13 +67,13 @@ class TestGemRequestConnectionPool < Gem::TestCase
2.no-proxy.example
]
- no_proxy = pools.send :no_proxy?, '2.no-proxy.example', env_no_proxy
+ no_proxy = pools.send :no_proxy?, "2.no-proxy.example", env_no_proxy
- assert no_proxy, 'match'
+ assert no_proxy, "match"
- no_proxy = pools.send :no_proxy?, 'proxy.example', env_no_proxy
+ no_proxy = pools.send :no_proxy?, "proxy.example", env_no_proxy
- refute no_proxy, 'mismatch'
+ refute no_proxy, "mismatch"
end
def test_to_proxy_eh_wildcard
@@ -82,31 +83,31 @@ class TestGemRequestConnectionPool < Gem::TestCase
.no-proxy.example
]
- no_proxy = pools.send :no_proxy?, '2.no-proxy.example', env_no_proxy
+ no_proxy = pools.send :no_proxy?, "2.no-proxy.example", env_no_proxy
- assert no_proxy, 'wildcard matching subdomain'
+ assert no_proxy, "wildcard matching subdomain"
- no_proxy = pools.send :no_proxy?, 'no-proxy.example', env_no_proxy
+ no_proxy = pools.send :no_proxy?, "no-proxy.example", env_no_proxy
- assert no_proxy, 'wildcard matching dotless domain'
+ assert no_proxy, "wildcard matching dotless domain"
- no_proxy = pools.send :no_proxy?, 'proxy.example', env_no_proxy
+ no_proxy = pools.send :no_proxy?, "proxy.example", env_no_proxy
- refute no_proxy, 'wildcard mismatch'
+ refute no_proxy, "wildcard mismatch"
end
def test_net_http_args
pools = Gem::Request::ConnectionPools.new nil, []
- net_http_args = pools.send :net_http_args, URI('http://example'), nil
+ net_http_args = pools.send :net_http_args, Gem::URI("http://example"), nil
- assert_equal ['example', 80], net_http_args
+ assert_equal ["example", 80], net_http_args
end
def test_net_http_args_ipv6
pools = Gem::Request::ConnectionPools.new nil, []
- net_http_args = pools.send :net_http_args, URI('http://[::1]'), nil
+ net_http_args = pools.send :net_http_args, Gem::URI("http://[::1]"), nil
assert_equal ["::1", 80], net_http_args
end
@@ -114,34 +115,34 @@ class TestGemRequestConnectionPool < Gem::TestCase
def test_net_http_args_proxy
pools = Gem::Request::ConnectionPools.new nil, []
- net_http_args = pools.send :net_http_args, URI('http://example'), @proxy
+ net_http_args = pools.send :net_http_args, Gem::URI("http://example"), @proxy
- assert_equal ['example', 80, 'proxy.example', 80, nil, nil], net_http_args
+ assert_equal ["example", 80, "proxy.example", 80, nil, nil], net_http_args
end
def test_net_http_args_no_proxy
- orig_no_proxy, ENV['no_proxy'] = ENV['no_proxy'], 'example'
+ orig_no_proxy = ENV["no_proxy"]
+ ENV["no_proxy"] = "example"
pools = Gem::Request::ConnectionPools.new nil, []
- net_http_args = pools.send :net_http_args, URI('http://example'), @proxy
-
- assert_equal ['example', 80, nil, nil], net_http_args
+ net_http_args = pools.send :net_http_args, Gem::URI("http://example"), @proxy
+ assert_equal ["example", 80, nil, nil], net_http_args
ensure
- ENV['no_proxy'] = orig_no_proxy
+ ENV["no_proxy"] = orig_no_proxy
end
def test_thread_waits_for_connection
- uri = URI.parse('http://example/some_endpoint')
+ uri = Gem::URI.parse("http://example/some_endpoint")
pools = Gem::Request::ConnectionPools.new nil, []
pool = pools.pool_for uri
pool.checkout
Thread.new do
- assert_raise(Timeout::Error) do
- Timeout.timeout(1) do
+ assert_raise(Gem::Timeout::Error) do
+ Gem::Timeout.timeout(1) do
pool.checkout
end
end
diff --git a/test/rubygems/test_gem_request_set.rb b/test/rubygems/test_gem_request_set.rb
index e2fe98b9bf..9aa244892c 100644
--- a/test/rubygems/test_gem_request_set.rb
+++ b/test/rubygems/test_gem_request_set.rb
@@ -1,14 +1,13 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/request_set'
+
+require_relative "helper"
+require "rubygems/request_set"
class TestGemRequestSet < Gem::TestCase
def setup
super
Gem::RemoteFetcher.fetcher = @fetcher = Gem::FakeFetcher.new
-
- @DR = Gem::Resolver
end
def test_gem
@@ -23,49 +22,49 @@ class TestGemRequestSet < Gem::TestCase
def test_gem_duplicate
rs = Gem::RequestSet.new
- rs.gem 'a', '1'
- rs.gem 'a', '2'
+ rs.gem "a", "1"
+ rs.gem "a", "2"
- assert_equal [dep('a', '= 1', '= 2')], rs.dependencies
+ assert_equal [dep("a", "= 1", "= 2")], rs.dependencies
end
def test_import
rs = Gem::RequestSet.new
- rs.gem 'a'
+ rs.gem "a"
- rs.import [dep('b')]
+ rs.import [dep("b")]
- assert_equal [dep('a'), dep('b')], rs.dependencies
+ assert_equal [dep("a"), dep("b")], rs.dependencies
end
def test_install_from_gemdeps
spec_fetcher do |fetcher|
- fetcher.gem 'a', 2
+ fetcher.gem "a", 2
end
done_installing_ran = false
- Gem.done_installing do |installer, specs|
+ Gem.done_installing do |_installer, _specs|
done_installing_ran = true
end
rs = Gem::RequestSet.new
installed = []
- File.open 'gem.deps.rb', 'w' do |io|
+ File.open "gem.deps.rb", "w" do |io|
io.puts 'gem "a"'
io.flush
- result = rs.install_from_gemdeps :gemdeps => io.path do |req, installer|
+ result = rs.install_from_gemdeps gemdeps: io.path do |req, _installer|
installed << req.full_name
end
assert_kind_of Array, result # what is supposed to be in here?
end
- assert_includes installed, 'a-2'
- assert_path_exist File.join @gemhome, 'gems', 'a-2'
- assert_path_exist 'gem.deps.rb.lock'
+ assert_includes installed, "a-2"
+ assert_path_exist File.join @gemhome, "gems", "a-2"
+ assert_path_exist "gem.deps.rb.lock"
assert rs.remote
refute done_installing_ran
@@ -73,12 +72,12 @@ class TestGemRequestSet < Gem::TestCase
def test_install_from_gemdeps_explain
spec_fetcher do |fetcher|
- fetcher.gem 'a', 2
+ fetcher.gem "a", 2
end
rs = Gem::RequestSet.new
- File.open 'gem.deps.rb', 'w' do |io|
+ File.open "gem.deps.rb", "w" do |io|
io.puts 'gem "a"'
io.flush
@@ -88,7 +87,7 @@ Gems to install:
EXPECTED
actual, _ = capture_output do
- rs.install_from_gemdeps :gemdeps => io.path, :explain => true
+ rs.install_from_gemdeps gemdeps: io.path, explain: true
end
assert_equal(expected, actual)
end
@@ -96,45 +95,45 @@ Gems to install:
def test_install_from_gemdeps_install_dir
spec_fetcher do |fetcher|
- fetcher.gem 'a', 2
+ fetcher.gem "a", 2
end
util_clear_gems
- assert_path_not_exist File.join Gem.dir, 'gems', 'a-2'
+ assert_path_not_exist File.join Gem.dir, "gems", "a-2"
rs = Gem::RequestSet.new
installed = []
- File.open 'gem.deps.rb', 'w' do |io|
+ File.open "gem.deps.rb", "w" do |io|
io.puts 'gem "a"'
end
options = {
- :gemdeps => 'gem.deps.rb',
- :install_dir => "#{@gemhome}2",
+ gemdeps: "gem.deps.rb",
+ install_dir: "#{@gemhome}2",
}
- rs.install_from_gemdeps options do |req, installer|
+ rs.install_from_gemdeps options do |req, _installer|
installed << req.full_name
end
- assert_includes installed, 'a-2'
- assert_path_not_exist File.join Gem.dir, 'gems', 'a-2'
+ assert_includes installed, "a-2"
+ assert_path_not_exist File.join Gem.dir, "gems", "a-2"
end
def test_install_from_gemdeps_local
spec_fetcher do |fetcher|
- fetcher.gem 'a', 2
+ fetcher.gem "a", 2
end
rs = Gem::RequestSet.new
- File.open 'gem.deps.rb', 'w' do |io|
+ File.open "gem.deps.rb", "w" do |io|
io.puts 'gem "a"'
io.flush
assert_raise Gem::UnsatisfiableDependencyError do
- rs.install_from_gemdeps :gemdeps => io.path, :domain => :local
+ rs.install_from_gemdeps gemdeps: io.path, domain: :local
end
end
@@ -143,15 +142,15 @@ Gems to install:
def test_install_from_gemdeps_lockfile
spec_fetcher do |fetcher|
- fetcher.download 'a', 1
- fetcher.download 'a', 2
- fetcher.download 'b', 1, 'a' => '>= 0'
+ fetcher.download "a", 1
+ fetcher.download "a", 2
+ fetcher.download "b", 1, "a" => ">= 0"
end
rs = Gem::RequestSet.new
installed = []
- File.open 'gem.deps.rb.lock', 'w' do |io|
+ File.open "gem.deps.rb.lock", "w" do |io|
io.puts <<-LOCKFILE
GEM
remote: #{@gem_repo}
@@ -168,19 +167,19 @@ DEPENDENCIES
LOCKFILE
end
- File.open 'gem.deps.rb', 'w' do |io|
+ File.open "gem.deps.rb", "w" do |io|
io.puts 'gem "b"'
end
- rs.install_from_gemdeps :gemdeps => 'gem.deps.rb' do |req, installer|
+ rs.install_from_gemdeps gemdeps: "gem.deps.rb" do |req, _installer|
installed << req.full_name
end
- assert_includes installed, 'b-1'
- assert_includes installed, 'a-1'
+ assert_includes installed, "b-1"
+ assert_includes installed, "a-1"
- assert_path_exist File.join @gemhome, 'specifications', 'a-1.gemspec'
- assert_path_exist File.join @gemhome, 'specifications', 'b-1.gemspec'
+ assert_path_exist File.join @gemhome, "specifications", "a-1.gemspec"
+ assert_path_exist File.join @gemhome, "specifications", "b-1.gemspec"
end
def test_install_from_gemdeps_complex_dependencies
@@ -197,7 +196,7 @@ DEPENDENCIES
rs = Gem::RequestSet.new
installed = []
- File.open 'Gemfile.lock', 'w' do |io|
+ File.open "Gemfile.lock", "w" do |io|
io.puts <<-LOCKFILE
GEM
remote: #{@gem_repo}
@@ -212,7 +211,7 @@ DEPENDENCIES
LOCKFILE
end
- File.open 'testo.gemspec', 'w' do |io|
+ File.open "testo.gemspec", "w" do |io|
io.puts <<-LOCKFILE
Gem::Specification.new do |spec|
spec.name = 'testo'
@@ -222,28 +221,28 @@ end
LOCKFILE
end
- File.open 'Gemfile', 'w' do |io|
+ File.open "Gemfile", "w" do |io|
io.puts("gemspec")
end
- rs.install_from_gemdeps :gemdeps => 'Gemfile' do |req, installer|
+ rs.install_from_gemdeps gemdeps: "Gemfile" do |req, _installer|
installed << req.full_name
end
- assert_includes installed, 'z-1.0.3'
+ assert_includes installed, "z-1.0.3"
- assert_path_exist File.join @gemhome, 'specifications', 'z-1.0.3.gemspec'
+ assert_path_exist File.join @gemhome, "specifications", "z-1.0.3.gemspec"
end
def test_install_from_gemdeps_version_mismatch
spec_fetcher do |fetcher|
- fetcher.gem 'a', 2
+ fetcher.gem "a", 2
end
rs = Gem::RequestSet.new
installed = []
- File.open 'gem.deps.rb', 'w' do |io|
+ File.open "gem.deps.rb", "w" do |io|
io.puts <<-GEM_DEPS
gem "a"
ruby "0"
@@ -251,18 +250,18 @@ ruby "0"
io.flush
- rs.install_from_gemdeps :gemdeps => io.path do |req, installer|
+ rs.install_from_gemdeps gemdeps: io.path do |req, _installer|
installed << req.full_name
end
end
- assert_includes installed, 'a-2'
+ assert_includes installed, "a-2"
end
def test_load_gemdeps
rs = Gem::RequestSet.new
- tf = Tempfile.open 'gem.deps.rb' do |io|
+ tf = Tempfile.open "gem.deps.rb" do |io|
io.puts 'gem "a"'
io.flush
@@ -273,7 +272,7 @@ ruby "0"
end
tf.close!
- assert_equal [dep('a')], rs.dependencies
+ assert_equal [dep("a")], rs.dependencies
assert rs.git_set
assert rs.vendor_set
@@ -282,7 +281,7 @@ ruby "0"
def test_load_gemdeps_installing
rs = Gem::RequestSet.new
- tf = Tempfile.open 'gem.deps.rb' do |io|
+ tf = Tempfile.open "gem.deps.rb" do |io|
io.puts 'ruby "0"'
io.puts 'gem "a"'
io.flush
@@ -294,13 +293,13 @@ ruby "0"
end
tf.close!
- assert_equal [dep('a')], rs.dependencies
+ assert_equal [dep("a")], rs.dependencies
end
def test_load_gemdeps_without_groups
rs = Gem::RequestSet.new
- tf = Tempfile.open 'gem.deps.rb' do |io|
+ tf = Tempfile.open "gem.deps.rb" do |io|
io.puts 'gem "a", :group => :test'
io.flush
@@ -324,7 +323,7 @@ ruby "0"
res = rs.resolve StaticSet.new([a, b])
assert_equal 2, res.size
- names = res.map {|s| s.full_name }.sort
+ names = res.map(&:full_name).sort
assert_equal ["a-2", "b-2"], names
@@ -332,28 +331,28 @@ ruby "0"
end
def test_bug_bug_990
- a = util_spec 'a', '1.b', 'b' => '~> 1.a'
- b = util_spec 'b', '1.b', 'c' => '>= 1'
- c = util_spec 'c', '1.1.b'
+ a = util_spec "a", "1.b", "b" => "~> 1.a"
+ b = util_spec "b", "1.b", "c" => ">= 1"
+ c = util_spec "c", "1.1.b"
rs = Gem::RequestSet.new
- rs.gem 'a'
+ rs.gem "a"
rs.prerelease = true
res = rs.resolve StaticSet.new([a, b, c])
assert_equal 3, res.size
- names = res.map {|s| s.full_name }.sort
+ names = res.map(&:full_name).sort
assert_equal %w[a-1.b b-1.b c-1.1.b], names
end
def test_resolve_development
- a = util_spec 'a', 1
+ a = util_spec "a", 1
spec = Gem::Resolver::SpecSpecification.new nil, a
rs = Gem::RequestSet.new
- rs.gem 'a'
+ rs.gem "a"
rs.development = true
res = rs.resolve StaticSet.new [spec]
@@ -364,22 +363,22 @@ ruby "0"
end
def test_resolve_development_shallow
- a = util_spec 'a', 1 do |s|
- s.add_development_dependency 'b'
+ a = util_spec "a", 1 do |s|
+ s.add_development_dependency "b"
end
- b = util_spec 'b', 1 do |s|
- s.add_development_dependency 'c'
+ b = util_spec "b", 1 do |s|
+ s.add_development_dependency "c"
end
- c = util_spec 'c', 1
+ c = util_spec "c", 1
a_spec = Gem::Resolver::SpecSpecification.new nil, a
b_spec = Gem::Resolver::SpecSpecification.new nil, b
c_spec = Gem::Resolver::SpecSpecification.new nil, c
rs = Gem::RequestSet.new
- rs.gem 'a'
+ rs.gem "a"
rs.development = true
rs.development_shallow = true
@@ -395,7 +394,7 @@ ruby "0"
rs = Gem::RequestSet.new
- tf = Tempfile.open 'gem.deps.rb' do |io|
+ tf = Tempfile.open "gem.deps.rb" do |io|
io.puts <<-GEMS_DEPS_RB
gem "#{name}", :git => "#{repository}"
GEMS_DEPS_RB
@@ -410,12 +409,12 @@ ruby "0"
res = rs.resolve
assert_equal 1, res.size
- names = res.map {|s| s.full_name }.sort
+ names = res.map(&:full_name).sort
assert_equal %w[a-1], names
- assert_equal [@DR::BestSet, @DR::GitSet, @DR::VendorSet, @DR::SourceSet],
- rs.sets.map {|set| set.class }
+ assert_equal [Gem::Resolver::BestSet, Gem::Resolver::GitSet, Gem::Resolver::VendorSet, Gem::Resolver::SourceSet],
+ rs.sets.map(&:class)
end
def test_resolve_ignore_dependencies
@@ -429,18 +428,18 @@ ruby "0"
res = rs.resolve StaticSet.new([a, b])
assert_equal 1, res.size
- names = res.map {|s| s.full_name }.sort
+ names = res.map(&:full_name).sort
assert_equal %w[a-2], names
end
def test_resolve_incompatible
- a1 = util_spec 'a', 1
- a2 = util_spec 'a', 2
+ a1 = util_spec "a", 1
+ a2 = util_spec "a", 2
rs = Gem::RequestSet.new
- rs.gem 'a', '= 1'
- rs.gem 'a', '= 2'
+ rs.gem "a", "= 1"
+ rs.gem "a", "= 2"
set = StaticSet.new [a1, a2]
@@ -450,15 +449,15 @@ ruby "0"
end
def test_resolve_vendor
- a_name, _, a_directory = vendor_gem 'a', 1 do |s|
- s.add_dependency 'b', '~> 2.0'
+ a_name, _, a_directory = vendor_gem "a", 1 do |s|
+ s.add_dependency "b", "~> 2.0"
end
- b_name, _, b_directory = vendor_gem 'b', 2
+ b_name, _, b_directory = vendor_gem "b", 2
rs = Gem::RequestSet.new
- tf = Tempfile.open 'gem.deps.rb' do |io|
+ tf = Tempfile.open "gem.deps.rb" do |io|
io.puts <<-GEMS_DEPS_RB
gem "#{a_name}", :path => "#{a_directory}"
gem "#{b_name}", :path => "#{b_directory}"
@@ -474,12 +473,12 @@ ruby "0"
res = rs.resolve
assert_equal 2, res.size
- names = res.map {|s| s.full_name }.sort
+ names = res.map(&:full_name).sort
assert_equal ["a-1", "b-2"], names
- assert_equal [@DR::BestSet, @DR::GitSet, @DR::VendorSet, @DR::SourceSet],
- rs.sets.map {|set| set.class }
+ assert_equal [Gem::Resolver::BestSet, Gem::Resolver::GitSet, Gem::Resolver::VendorSet, Gem::Resolver::SourceSet],
+ rs.sets.map(&:class)
end
def test_sorted_requests
@@ -492,7 +491,7 @@ ruby "0"
rs.resolve StaticSet.new([a, b, c])
- names = rs.sorted_requests.map {|s| s.full_name }
+ names = rs.sorted_requests.map(&:full_name)
assert_equal %w[c-2 b-2 a-2], names
end
@@ -509,7 +508,7 @@ ruby "0"
end
rs = Gem::RequestSet.new
- rs.gem 'a'
+ rs.gem "a"
rs.resolve
@@ -521,14 +520,14 @@ ruby "0"
installers << installer
end
- assert_equal %w[b-1 a-1], reqs.map {|req| req.full_name }
+ assert_equal %w[b-1 a-1], reqs.map(&:full_name)
assert_equal %w[b-1 a-1],
installers.map {|installer| installer.spec.full_name }
- assert_path_exist File.join @gemhome, 'specifications', 'a-1.gemspec'
- assert_path_exist File.join @gemhome, 'specifications', 'b-1.gemspec'
+ assert_path_exist File.join @gemhome, "specifications", "a-1.gemspec"
+ assert_path_exist File.join @gemhome, "specifications", "b-1.gemspec"
- assert_equal %w[b-1 a-1], installed.map {|s| s.full_name }
+ assert_equal %w[b-1 a-1], installed.map(&:full_name)
assert done_installing_ran
end
@@ -545,60 +544,60 @@ ruby "0"
rs.resolve
installed = rs.install_into @tempdir do
- assert_equal @tempdir, ENV['GEM_HOME']
+ assert_equal @tempdir, ENV["GEM_HOME"]
end
- assert_path_exist File.join @tempdir, 'specifications', 'a-1.gemspec'
- assert_path_exist File.join @tempdir, 'specifications', 'b-1.gemspec'
+ assert_path_exist File.join @tempdir, "specifications", "a-1.gemspec"
+ assert_path_exist File.join @tempdir, "specifications", "b-1.gemspec"
- assert_equal %w[b-1 a-1], installed.map {|s| s.full_name }
+ assert_equal %w[b-1 a-1], installed.map(&:full_name)
end
def test_install_into_development_shallow
spec_fetcher do |fetcher|
- fetcher.gem 'a', '1' do |s|
- s.add_development_dependency 'b', '= 1'
+ fetcher.gem "a", "1" do |s|
+ s.add_development_dependency "b", "= 1"
end
- fetcher.gem 'b', '1' do |s|
- s.add_development_dependency 'c', '= 1'
+ fetcher.gem "b", "1" do |s|
+ s.add_development_dependency "c", "= 1"
end
- fetcher.spec 'c', '1'
+ fetcher.spec "c", "1"
end
rs = Gem::RequestSet.new
rs.development = true
rs.development_shallow = true
- rs.gem 'a'
+ rs.gem "a"
rs.resolve
options = {
- :development => true,
- :development_shallow => true,
+ development: true,
+ development_shallow: true,
}
installed = rs.install_into @tempdir, true, options do
- assert_equal @tempdir, ENV['GEM_HOME']
+ assert_equal @tempdir, ENV["GEM_HOME"]
end
- assert_equal %w[a-1 b-1], installed.map {|s| s.full_name }.sort
+ assert_equal %w[a-1 b-1], installed.map(&:full_name).sort
end
def test_sorted_requests_development_shallow
- a = util_spec 'a', 1 do |s|
- s.add_development_dependency 'b'
+ a = util_spec "a", 1 do |s|
+ s.add_development_dependency "b"
end
- b = util_spec 'b', 1 do |s|
- s.add_development_dependency 'c'
+ b = util_spec "b", 1 do |s|
+ s.add_development_dependency "c"
end
- c = util_spec 'c', 1
+ c = util_spec "c", 1
rs = Gem::RequestSet.new
- rs.gem 'a'
+ rs.gem "a"
rs.development = true
rs.development_shallow = true
@@ -608,22 +607,22 @@ ruby "0"
rs.resolve StaticSet.new [a_spec, b_spec, c_spec]
- assert_equal %w[b-1 a-1], rs.sorted_requests.map {|req| req.full_name }
+ assert_equal %w[b-1 a-1], rs.sorted_requests.map(&:full_name)
end
def test_tsort_each_child_development
- a = util_spec 'a', 1 do |s|
- s.add_development_dependency 'b'
+ a = util_spec "a", 1 do |s|
+ s.add_development_dependency "b"
end
- b = util_spec 'b', 1 do |s|
- s.add_development_dependency 'c'
+ b = util_spec "b", 1 do |s|
+ s.add_development_dependency "c"
end
- c = util_spec 'c', 1
+ c = util_spec "c", 1
rs = Gem::RequestSet.new
- rs.gem 'a'
+ rs.gem "a"
rs.development = true
rs.development_shallow = true
@@ -637,22 +636,22 @@ ruby "0"
deps = rs.enum_for(:tsort_each_child, a_req).to_a
- assert_equal %w[b], deps.map {|dep| dep.name }
+ assert_equal %w[b], deps.map(&:name)
end
def test_tsort_each_child_development_shallow
- a = util_spec 'a', 1 do |s|
- s.add_development_dependency 'b'
+ a = util_spec "a", 1 do |s|
+ s.add_development_dependency "b"
end
- b = util_spec 'b', 1 do |s|
- s.add_development_dependency 'c'
+ b = util_spec "b", 1 do |s|
+ s.add_development_dependency "c"
end
- c = util_spec 'c', 1
+ c = util_spec "c", 1
rs = Gem::RequestSet.new
- rs.gem 'a'
+ rs.gem "a"
rs.development = true
rs.development_shallow = true
diff --git a/test/rubygems/test_gem_request_set_gem_dependency_api.rb b/test/rubygems/test_gem_request_set_gem_dependency_api.rb
index cc4f99df91..4b5eaa38ed 100644
--- a/test/rubygems/test_gem_request_set_gem_dependency_api.rb
+++ b/test/rubygems/test_gem_request_set_gem_dependency_api.rb
@@ -1,19 +1,18 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/request_set'
+
+require_relative "helper"
+require "rubygems/request_set"
class TestGemRequestSetGemDependencyAPI < Gem::TestCase
def setup
super
- @GDA = Gem::RequestSet::GemDependencyAPI
-
@set = Gem::RequestSet.new
@git_set = Gem::Resolver::GitSet.new
@vendor_set = Gem::Resolver::VendorSet.new
- @gda = @GDA.new @set, 'gem.deps.rb'
+ @gda = Gem::RequestSet::GemDependencyAPI.new @set, "gem.deps.rb"
@gda.instance_variable_set :@git_set, @git_set
@gda.instance_variable_set :@vendor_set, @vendor_set
end
@@ -44,45 +43,45 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase
end
def test_gempspec_with_multiple_runtime_deps
- save_gemspec 'foo', '1.0' do |s|
- s.add_runtime_dependency 'bar', '>= 1.6.0', '< 1.6.4'
+ save_gemspec "foo", "1.0" do |s|
+ s.add_dependency "bar", ">= 1.6.0", "< 1.6.4"
end
@gda.gemspec
- assert_equal %w[ foo bar ].sort, @set.dependencies.map(&:name).sort
- bar = @set.dependencies.find {|d| d.name == 'bar' }
- assert_equal [["<", Gem::Version.create('1.6.4')],
- [">=", Gem::Version.create('1.6.0')]], bar.requirement.requirements.sort
+ assert_equal %w[foo bar].sort, @set.dependencies.map(&:name).sort
+ bar = @set.dependencies.find {|d| d.name == "bar" }
+ assert_equal [["<", Gem::Version.create("1.6.4")],
+ [">=", Gem::Version.create("1.6.0")]], bar.requirement.requirements.sort
end
def test_gemspec_without_group
- @gda.send :add_dependencies, [:development], [dep('a', '= 1')]
+ @gda.send :add_dependencies, [:development], [dep("a", "= 1")]
- assert_equal [dep('a', '= 1')], @set.dependencies
+ assert_equal [dep("a", "= 1")], @set.dependencies
@gda.without_groups << :development
- @gda.send :add_dependencies, [:development], [dep('b', '= 2')]
+ @gda.send :add_dependencies, [:development], [dep("b", "= 2")]
- assert_equal [dep('a', '= 1')], @set.dependencies
+ assert_equal [dep("a", "= 1")], @set.dependencies
end
def test_gem
- @gda.gem 'a'
+ @gda.gem "a"
- assert_equal [dep('a')], @set.dependencies
+ assert_equal [dep("a")], @set.dependencies
- assert_equal %w[a], @gda.requires['a']
+ assert_equal %w[a], @gda.requires["a"]
- expected = { 'a' => Gem::Requirement.default }
+ expected = { "a" => Gem::Requirement.default }
assert_equal expected, @gda.dependencies
end
def test_gem_duplicate
- @gda.gem 'a'
+ @gda.gem "a"
_, err = capture_output do
- @gda.gem 'a'
+ @gda.gem "a"
end
expected = "Gem dependencies file gem.deps.rb requires a more than once."
@@ -91,147 +90,147 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase
end
def test_gem_git
- @gda.gem 'a', :git => 'git/a'
+ @gda.gem "a", git: "git/a"
- assert_equal [dep('a')], @set.dependencies
+ assert_equal [dep("a")], @set.dependencies
- assert_equal %w[git/a master], @git_set.repositories['a']
+ assert_equal ["git/a", nil], @git_set.repositories["a"]
- expected = { 'a' => Gem::Requirement.create('!') }
+ expected = { "a" => Gem::Requirement.create("!") }
assert_equal expected, @gda.dependencies
end
def test_gem_bitbucket
- @gda.gem 'a', :bitbucket => 'example/repository'
+ @gda.gem "a", bitbucket: "example/repository"
- assert_equal [dep('a')], @set.dependencies
+ assert_equal [dep("a")], @set.dependencies
- assert_equal %w[https://example@bitbucket.org/example/repository.git master],
- @git_set.repositories['a']
+ assert_equal ["https://example@bitbucket.org/example/repository.git", nil],
+ @git_set.repositories["a"]
- expected = { 'a' => Gem::Requirement.create('!') }
+ expected = { "a" => Gem::Requirement.create("!") }
assert_equal expected, @gda.dependencies
end
def test_gem_bitbucket_expand_path
- @gda.gem 'a', :bitbucket => 'example'
+ @gda.gem "a", bitbucket: "example"
- assert_equal [dep('a')], @set.dependencies
+ assert_equal [dep("a")], @set.dependencies
- assert_equal %w[https://example@bitbucket.org/example/example.git master],
- @git_set.repositories['a']
+ assert_equal ["https://example@bitbucket.org/example/example.git", nil],
+ @git_set.repositories["a"]
- expected = { 'a' => Gem::Requirement.create('!') }
+ expected = { "a" => Gem::Requirement.create("!") }
assert_equal expected, @gda.dependencies
end
def test_gem_git_branch
_, err = capture_output do
- @gda.gem 'a', :git => 'git/a', :branch => 'other', :tag => 'v1'
+ @gda.gem "a", git: "git/a", branch: "other", tag: "v1"
end
expected = "Gem dependencies file gem.deps.rb includes git reference for both ref/branch and tag but only ref/branch is used."
assert_match expected, err
- assert_equal [dep('a')], @set.dependencies
+ assert_equal [dep("a")], @set.dependencies
- assert_equal %w[git/a other], @git_set.repositories['a']
+ assert_equal %w[git/a other], @git_set.repositories["a"]
end
def test_gem_git_gist
- @gda.gem 'a', :gist => 'a'
+ @gda.gem "a", gist: "a"
- assert_equal [dep('a')], @set.dependencies
+ assert_equal [dep("a")], @set.dependencies
- assert_equal %w[https://gist.github.com/a.git master],
- @git_set.repositories['a']
+ assert_equal ["https://gist.github.com/a.git", nil],
+ @git_set.repositories["a"]
end
def test_gem_git_ref
_, err = capture_output do
- @gda.gem 'a', :git => 'git/a', :ref => 'abcd123', :branch => 'other'
+ @gda.gem "a", git: "git/a", ref: "abcd123", branch: "other"
end
expected = "Gem dependencies file gem.deps.rb includes git reference for both ref and branch but only ref is used."
assert_match expected, err
- assert_equal [dep('a')], @set.dependencies
+ assert_equal [dep("a")], @set.dependencies
- assert_equal %w[git/a abcd123], @git_set.repositories['a']
+ assert_equal %w[git/a abcd123], @git_set.repositories["a"]
end
def test_gem_git_submodules
- @gda.gem 'a', :git => 'git/a', :submodules => true
+ @gda.gem "a", git: "git/a", submodules: true
- assert_equal [dep('a')], @set.dependencies
+ assert_equal [dep("a")], @set.dependencies
- assert_equal %w[git/a master], @git_set.repositories['a']
+ assert_equal ["git/a", nil], @git_set.repositories["a"]
assert_equal %w[git/a], @git_set.need_submodules.keys
end
def test_gem_git_tag
- @gda.gem 'a', :git => 'git/a', :tag => 'v1'
+ @gda.gem "a", git: "git/a", tag: "v1"
- assert_equal [dep('a')], @set.dependencies
+ assert_equal [dep("a")], @set.dependencies
- assert_equal %w[git/a v1], @git_set.repositories['a']
+ assert_equal %w[git/a v1], @git_set.repositories["a"]
end
def test_gem_github
- @gda.gem 'a', :github => 'example/repository'
+ @gda.gem "a", github: "example/repository"
- assert_equal [dep('a')], @set.dependencies
+ assert_equal [dep("a")], @set.dependencies
- assert_equal %w[git://github.com/example/repository.git master],
- @git_set.repositories['a']
+ assert_equal ["https://github.com/example/repository.git", nil],
+ @git_set.repositories["a"]
- expected = { 'a' => Gem::Requirement.create('!') }
+ expected = { "a" => Gem::Requirement.create("!") }
assert_equal expected, @gda.dependencies
end
def test_gem_github_expand_path
- @gda.gem 'a', :github => 'example'
+ @gda.gem "a", github: "example"
- assert_equal [dep('a')], @set.dependencies
+ assert_equal [dep("a")], @set.dependencies
- assert_equal %w[git://github.com/example/example.git master],
- @git_set.repositories['a']
+ assert_equal ["https://github.com/example/example.git", nil],
+ @git_set.repositories["a"]
- expected = { 'a' => Gem::Requirement.create('!') }
+ expected = { "a" => Gem::Requirement.create("!") }
assert_equal expected, @gda.dependencies
end
def test_gem_group
- @gda.gem 'a', :group => :test
+ @gda.gem "a", group: :test
- assert_equal [dep('a')], @set.dependencies
+ assert_equal [dep("a")], @set.dependencies
end
def test_gem_group_without
@gda.without_groups << :test
- @gda.gem 'a', :group => :test
+ @gda.gem "a", group: :test
assert_empty @set.dependencies
- expected = { 'a' => Gem::Requirement.default }
+ expected = { "a" => Gem::Requirement.default }
assert_equal expected, @gda.dependencies
end
def test_gem_groups
- @gda.gem 'a', :groups => [:test, :development]
+ @gda.gem "a", groups: [:test, :development]
- assert_equal [dep('a')], @set.dependencies
+ assert_equal [dep("a")], @set.dependencies
end
def test_gem_path
name, version, directory = vendor_gem
- @gda.gem name, :path => directory
+ @gda.gem name, path: directory
assert_equal [dep(name)], @set.dependencies
@@ -239,16 +238,17 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase
assert_equal "#{name}-#{version}", loaded.full_name
- expected = { name => Gem::Requirement.create('!') }
+ expected = { name => Gem::Requirement.create("!") }
assert_equal expected, @gda.dependencies
end
def test_gem_platforms
- win_platform, Gem.win_platform = Gem.win_platform?, false
+ win_platform = Gem.win_platform?
+ Gem.win_platform = false
- with_engine_version 'ruby', '2.0.0' do
- @gda.gem 'a', :platforms => :ruby
+ with_engine_version "ruby", "2.0.0" do
+ @gda.gem "a", platforms: :ruby
refute_empty @set.dependencies
end
@@ -257,46 +257,47 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase
end
def test_gem_platforms_bundler_ruby
- win_platform, Gem.win_platform = Gem.win_platform?, false
+ win_platform = Gem.win_platform?
+ Gem.win_platform = false
- with_engine_version 'ruby', '2.0.0' do
+ with_engine_version "ruby", "2.0.0" do
set = Gem::RequestSet.new
- gda = @GDA.new set, 'gem.deps.rb'
- gda.gem 'a', :platforms => :ruby
+ gda = Gem::RequestSet::GemDependencyAPI.new set, "gem.deps.rb"
+ gda.gem "a", platforms: :ruby
refute_empty set.dependencies
end
- with_engine_version 'rbx', '2.0.0' do
+ with_engine_version "rbx", "2.0.0" do
set = Gem::RequestSet.new
- gda = @GDA.new set, 'gem.deps.rb'
- gda.gem 'a', :platforms => :ruby
+ gda = Gem::RequestSet::GemDependencyAPI.new set, "gem.deps.rb"
+ gda.gem "a", platforms: :ruby
refute_empty set.dependencies
end
- with_engine_version 'truffleruby', '2.0.0' do
+ with_engine_version "truffleruby", "2.0.0" do
set = Gem::RequestSet.new
- gda = @GDA.new set, 'gem.deps.rb'
- gda.gem 'a', :platforms => :ruby
+ gda = Gem::RequestSet::GemDependencyAPI.new set, "gem.deps.rb"
+ gda.gem "a", platforms: :ruby
refute_empty set.dependencies
end
- with_engine_version 'jruby', '1.7.6' do
+ with_engine_version "jruby", "1.7.6" do
set = Gem::RequestSet.new
- gda = @GDA.new set, 'gem.deps.rb'
- gda.gem 'a', :platforms => :ruby
+ gda = Gem::RequestSet::GemDependencyAPI.new set, "gem.deps.rb"
+ gda.gem "a", platforms: :ruby
assert_empty set.dependencies
end
Gem.win_platform = true
- with_engine_version 'ruby', '2.0.0' do
+ with_engine_version "ruby", "2.0.0" do
set = Gem::RequestSet.new
- gda = @GDA.new set, 'gem.deps.rb'
- gda.gem 'a', :platforms => :ruby
+ gda = Gem::RequestSet::GemDependencyAPI.new set, "gem.deps.rb"
+ gda.gem "a", platforms: :ruby
assert_empty set.dependencies
end
@@ -305,32 +306,33 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase
end
def test_gem_platforms_engine
- with_engine_version 'jruby', '1.7.6' do
- @gda.gem 'a', :platforms => :mri
+ with_engine_version "jruby", "1.7.6" do
+ @gda.gem "a", platforms: :mri
assert_empty @set.dependencies
end
- with_engine_version 'truffleruby', '1.2.3' do
- @gda.gem 'a', :platforms => :mri
+ with_engine_version "truffleruby", "1.2.3" do
+ @gda.gem "a", platforms: :mri
assert_empty @set.dependencies
end
end
def test_gem_platforms_maglev
- win_platform, Gem.win_platform = Gem.win_platform?, false
+ win_platform = Gem.win_platform?
+ Gem.win_platform = false
- with_engine_version 'maglev', '1.0.0' do
+ with_engine_version "maglev", "1.0.0" do
set = Gem::RequestSet.new
- gda = @GDA.new set, 'gem.deps.rb'
- gda.gem 'a', :platforms => :ruby
+ gda = Gem::RequestSet::GemDependencyAPI.new set, "gem.deps.rb"
+ gda.gem "a", platforms: :ruby
refute_empty set.dependencies
set = Gem::RequestSet.new
- gda = @GDA.new set, 'gem.deps.rb'
- gda.gem 'a', :platforms => :maglev
+ gda = Gem::RequestSet::GemDependencyAPI.new set, "gem.deps.rb"
+ gda.gem "a", platforms: :maglev
refute_empty set.dependencies
end
@@ -339,39 +341,40 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase
end
def test_gem_platforms_truffleruby
- with_engine_version 'truffleruby', '1.0.0' do
+ with_engine_version "truffleruby", "1.0.0" do
set = Gem::RequestSet.new
- gda = @GDA.new set, 'gem.deps.rb'
- gda.gem 'a', :platforms => :truffleruby
+ gda = Gem::RequestSet::GemDependencyAPI.new set, "gem.deps.rb"
+ gda.gem "a", platforms: :truffleruby
refute_empty set.dependencies
set = Gem::RequestSet.new
- gda = @GDA.new set, 'gem.deps.rb'
- gda.gem 'a', :platforms => :maglev
+ gda = Gem::RequestSet::GemDependencyAPI.new set, "gem.deps.rb"
+ gda.gem "a", platforms: :maglev
assert_empty set.dependencies
end
end
def test_gem_platforms_multiple
- win_platform, Gem.win_platform = Gem.win_platform?, false
+ win_platform = Gem.win_platform?
+ Gem.win_platform = false
- with_engine_version 'ruby', '2.0.0' do
- @gda.gem 'a', :platforms => [:mswin, :jruby]
+ with_engine_version "ruby", "2.0.0" do
+ @gda.gem "a", platforms: [:mswin, :jruby]
assert_empty @set.dependencies
end
-
ensure
Gem.win_platform = win_platform
end
def test_gem_platforms_platform
- win_platform, Gem.win_platform = Gem.win_platform?, false
+ win_platform = Gem.win_platform?
+ Gem.win_platform = false
- with_engine_version 'ruby', '2.0.0' do
- @gda.gem 'a', :platforms => :jruby, :platform => :ruby
+ with_engine_version "ruby", "2.0.0" do
+ @gda.gem "a", platforms: :jruby, platform: :ruby
refute_empty @set.dependencies
end
@@ -380,8 +383,8 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase
end
def test_gem_platforms_version
- with_engine_version 'ruby', '2.0.0' do
- @gda.gem 'a', :platforms => :ruby_18
+ with_engine_version "ruby", "2.0.0" do
+ @gda.gem "a", platforms: :ruby_18
assert_empty @set.dependencies
end
@@ -389,26 +392,26 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase
def test_gem_platforms_unknown
e = assert_raise ArgumentError do
- @gda.gem 'a', :platforms => :unknown
+ @gda.gem "a", platforms: :unknown
end
- assert_equal 'unknown platform :unknown', e.message
+ assert_equal "unknown platform :unknown", e.message
end
def test_gem_requires
- @gda.gem 'a', :require => %w[b c]
- @gda.gem 'd', :require => 'e'
+ @gda.gem "a", require: %w[b c]
+ @gda.gem "d", require: "e"
- assert_equal [dep('a'), dep('d')], @set.dependencies
+ assert_equal [dep("a"), dep("d")], @set.dependencies
- assert_equal %w[b c], @gda.requires['a']
- assert_equal %w[e], @gda.requires['d']
+ assert_equal %w[b c], @gda.requires["a"]
+ assert_equal %w[e], @gda.requires["d"]
end
def test_gem_requires_false
- @gda.gem 'a', :require => false
+ @gda.gem "a", require: false
- assert_equal [dep('a')], @set.dependencies
+ assert_equal [dep("a")], @set.dependencies
assert_empty @gda.requires
end
@@ -416,55 +419,55 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase
def test_gem_requires_without_group
@gda.without_groups << :test
- @gda.gem 'a', :group => :test
+ @gda.gem "a", group: :test
assert_empty @set.dependencies
- assert_empty @gda.requires['a']
+ assert_empty @gda.requires["a"]
end
def test_gem_requirement
- @gda.gem 'a', '~> 1.0'
+ @gda.gem "a", "~> 1.0"
- assert_equal [dep('a', '~> 1.0')], @set.dependencies
+ assert_equal [dep("a", "~> 1.0")], @set.dependencies
- expected = { 'a' => Gem::Requirement.create(['~> 1.0']) }
+ expected = { "a" => Gem::Requirement.create(["~> 1.0"]) }
assert_equal expected, @gda.dependencies
end
def test_gem_requirements
- @gda.gem 'b', '~> 1.0', '>= 1.0.2'
+ @gda.gem "b", "~> 1.0", ">= 1.0.2"
- assert_equal [dep('b', '~> 1.0', '>= 1.0.2')], @set.dependencies
+ assert_equal [dep("b", "~> 1.0", ">= 1.0.2")], @set.dependencies
- expected = { 'b' => Gem::Requirement.create(['~> 1.0', '>= 1.0.2']) }
+ expected = { "b" => Gem::Requirement.create(["~> 1.0", ">= 1.0.2"]) }
assert_equal expected, @gda.dependencies
end
def test_gem_requirements_options
- @gda.gem 'c', :git => 'https://example/c.git'
+ @gda.gem "c", git: "https://example/c.git"
- assert_equal [dep('c')], @set.dependencies
+ assert_equal [dep("c")], @set.dependencies
end
def test_gem_source_mismatch
name, _, directory = vendor_gem
- gda = @GDA.new @set, nil
+ gda = Gem::RequestSet::GemDependencyAPI.new @set, nil
gda.gem name
e = assert_raise ArgumentError do
- gda.gem name, :path => directory
+ gda.gem name, path: directory
end
assert_equal "duplicate source path: #{directory} for gem #{name}",
e.message
- gda = @GDA.new @set, nil
+ gda = Gem::RequestSet::GemDependencyAPI.new @set, nil
gda.instance_variable_set :@vendor_set, @vendor_set
- gda.gem name, :path => directory
+ gda.gem name, path: directory
e = assert_raise ArgumentError do
gda.gem name
@@ -475,47 +478,47 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase
end
def test_gem_deps_file
- assert_equal 'gem.deps.rb', @gda.gem_deps_file
+ assert_equal "gem.deps.rb", @gda.gem_deps_file
- gda = @GDA.new @set, 'foo/Gemfile'
+ gda = Gem::RequestSet::GemDependencyAPI.new @set, "foo/Gemfile"
- assert_equal 'Gemfile', gda.gem_deps_file
+ assert_equal "Gemfile", gda.gem_deps_file
end
def test_gem_group_method
groups = []
@gda.group :a do
- groups = @gda.send :gem_group, 'a', :group => :b, :groups => [:c, :d]
+ groups = @gda.send :gem_group, "a", group: :b, groups: [:c, :d]
end
- assert_equal [:a, :b, :c, :d], groups.sort_by {|group| group.to_s }
+ assert_equal [:a, :b, :c, :d], groups.sort_by(&:to_s)
end
def test_gemspec
- save_gemspec 'a', 1 do |s|
- s.add_dependency 'b', 2
- s.add_development_dependency 'c', 3
+ save_gemspec "a", 1 do |s|
+ s.add_dependency "b", 2
+ s.add_development_dependency "c", 3
end
@gda.gemspec
- assert_equal [dep('a', '= 1'), dep('b', '= 2'), dep('c', '=3')],
+ assert_equal [dep("a", "= 1"), dep("b", "= 2"), dep("c", "=3")],
@set.dependencies
- assert_equal %w[a], @gda.requires['a']
+ assert_equal %w[a], @gda.requires["a"]
expected = {
- 'a' => Gem::Requirement.create('!'),
- 'b' => req('= 2'),
- 'c' => req('= 3'),
+ "a" => Gem::Requirement.create("!"),
+ "b" => req("= 2"),
+ "c" => req("= 3"),
}
assert_equal expected, @gda.dependencies
end
def test_gemspec_bad
- FileUtils.touch 'a.gemspec'
+ FileUtils.touch "a.gemspec"
e = assert_raise ArgumentError do
capture_output do
@@ -523,31 +526,31 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase
end
end
- assert_equal 'invalid gemspec ./a.gemspec', e.message
+ assert_equal "invalid gemspec ./a.gemspec", e.message
end
def test_gemspec_development_group
- save_gemspec 'a', 1 do |s|
- s.add_dependency 'b', 2
- s.add_development_dependency 'c', 3
+ save_gemspec "a", 1 do |s|
+ s.add_dependency "b", 2
+ s.add_development_dependency "c", 3
end
@gda.without_groups << :other
- @gda.gemspec :development_group => :other
+ @gda.gemspec development_group: :other
- assert_equal [dep('a', '= 1'), dep('b', '= 2')], @set.dependencies
+ assert_equal [dep("a", "= 1"), dep("b", "= 2")], @set.dependencies
- assert_equal %w[a], @gda.requires['a']
+ assert_equal %w[a], @gda.requires["a"]
end
def test_gemspec_multiple
- save_gemspec 'a', 1 do |s|
- s.add_dependency 'b', 2
+ save_gemspec "a", 1 do |s|
+ s.add_dependency "b", 2
end
- save_gemspec 'b', 2 do |s|
- s.add_dependency 'c', 3
+ save_gemspec "b", 2 do |s|
+ s.add_dependency "c", 3
end
e = assert_raise ArgumentError do
@@ -558,27 +561,27 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase
end
def test_gemspec_name
- save_gemspec 'a', 1 do |s|
- s.add_dependency 'b', 2
+ save_gemspec "a", 1 do |s|
+ s.add_dependency "b", 2
end
- save_gemspec 'b', 2 do |s|
- s.add_dependency 'c', 3
+ save_gemspec "b", 2 do |s|
+ s.add_dependency "c", 3
end
- @gda.gemspec :name => 'b'
+ @gda.gemspec name: "b"
- assert_equal [dep('b', '= 2'), dep('c', '= 3')], @set.dependencies
+ assert_equal [dep("b", "= 2"), dep("c", "= 3")], @set.dependencies
end
def test_gemspec_named
- save_gemspec 'a', 1 do |s|
- s.add_dependency 'b', 2
+ save_gemspec "a", 1 do |s|
+ s.add_dependency "b", 2
end
@gda.gemspec
- assert_equal [dep('a', '= 1'), dep('b', '= 2')], @set.dependencies
+ assert_equal [dep("a", "= 1"), dep("b", "= 2")], @set.dependencies
end
def test_gemspec_none
@@ -590,27 +593,27 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase
end
def test_gemspec_path
- FileUtils.mkdir 'other'
+ FileUtils.mkdir "other"
- save_gemspec 'a', 1, 'other' do |s|
- s.add_dependency 'b', 2
+ save_gemspec "a", 1, "other" do |s|
+ s.add_dependency "b", 2
end
- @gda.gemspec :path => 'other'
+ @gda.gemspec path: "other"
- assert_equal [dep('a', '= 1'), dep('b', '= 2')], @set.dependencies
+ assert_equal [dep("a", "= 1"), dep("b", "= 2")], @set.dependencies
end
def test_git
- @gda.git 'git://example/repo.git' do
- @gda.gem 'a'
- @gda.gem 'b'
+ @gda.git "git://example/repo.git" do
+ @gda.gem "a"
+ @gda.gem "b"
end
- assert_equal [dep('a'), dep('b')], @set.dependencies
+ assert_equal [dep("a"), dep("b")], @set.dependencies
- assert_equal %w[git://example/repo.git master], @git_set.repositories['a']
- assert_equal %w[git://example/repo.git master], @git_set.repositories['b']
+ assert_equal ["git://example/repo.git", nil], @git_set.repositories["a"]
+ assert_equal ["git://example/repo.git", nil], @git_set.repositories["b"]
end
def test_git_source
@@ -618,21 +621,21 @@ class TestGemRequestSetGemDependencyAPI < Gem::TestCase
"git://example/#{repo_name}.git"
end
- @gda.gem 'a', :example => 'repo'
+ @gda.gem "a", example: "repo"
- assert_equal %w[git://example/repo.git master], @git_set.repositories['a']
+ assert_equal ["git://example/repo.git", nil], @git_set.repositories["a"]
end
def test_group
@gda.group :test do
- @gda.gem 'a'
+ @gda.gem "a"
end
- assert_equal [dep('a')], @set.dependencies
+ assert_equal [dep("a")], @set.dependencies
end
def test_load
- tf = Tempfile.open 'gem.deps.rb' do |io|
+ tf = Tempfile.open "gem.deps.rb" do |io|
io.write <<-GEM_DEPS
gem 'a'
@@ -642,31 +645,31 @@ end
GEM_DEPS
io.flush
- gda = @GDA.new @set, io.path
+ gda = Gem::RequestSet::GemDependencyAPI.new @set, io.path
assert_equal gda, gda.load
- assert_equal [dep('a'), dep('b')], @set.dependencies
+ assert_equal [dep("a"), dep("b")], @set.dependencies
io
end
tf.close!
end
def test_pin_gem_source
- gda = @GDA.new @set, nil
+ gda = Gem::RequestSet::GemDependencyAPI.new @set, nil
- gda.send :pin_gem_source, 'a'
- gda.send :pin_gem_source, 'a'
+ gda.send :pin_gem_source, "a"
+ gda.send :pin_gem_source, "a"
e = assert_raise ArgumentError do
- gda.send :pin_gem_source, 'a', :path, 'vendor/a'
+ gda.send :pin_gem_source, "a", :path, "vendor/a"
end
assert_equal "duplicate source path: vendor/a for gem a",
e.message
e = assert_raise ArgumentError do
- gda.send :pin_gem_source, 'a', :git, 'git://example/repo.git'
+ gda.send :pin_gem_source, "a", :git, "git://example/repo.git"
end
assert_equal "duplicate source git: git://example/repo.git for gem a",
@@ -674,19 +677,19 @@ end
end
def test_platform_mswin
- if win_platform?
- util_set_arch 'x86-mswin32-60' do
+ if Gem.win_platform?
+ util_set_arch "x86-mswin32-60" do
@gda.platform :mswin do
- @gda.gem 'a'
+ @gda.gem "a"
end
- assert_equal [dep('a')], @set.dependencies
+ assert_equal [dep("a")], @set.dependencies
refute_empty @set.dependencies
end
else
- util_set_arch 'i686-darwin8.10.1' do
+ util_set_arch "i686-darwin8.10.1" do
@gda.platform :mswin do
- @gda.gem 'a'
+ @gda.gem "a"
end
assert_empty @set.dependencies
@@ -695,23 +698,24 @@ end
end
def test_platform_multiple
- win_platform, Gem.win_platform = Gem.win_platform?, false
+ win_platform = Gem.win_platform?
+ Gem.win_platform = false
- gda = @GDA.new @set, nil
+ gda = Gem::RequestSet::GemDependencyAPI.new @set, nil
- with_engine_version 'ruby', '1.8.7' do
+ with_engine_version "ruby", "1.8.7" do
gda.platform :mri_19, :mri_20 do
- gda.gem 'a'
+ gda.gem "a"
end
end
assert_empty @set.dependencies
- gda = @GDA.new @set, nil
+ gda = Gem::RequestSet::GemDependencyAPI.new @set, nil
- with_engine_version 'ruby', '2.0.0' do
+ with_engine_version "ruby", "2.0.0" do
gda.platform :mri_19, :mri_20 do
- gda.gem 'a'
+ gda.gem "a"
end
end
@@ -721,31 +725,32 @@ end
end
def test_platform_ruby
- win_platform, Gem.win_platform = Gem.win_platform?, false
+ win_platform = Gem.win_platform?
+ Gem.win_platform = false
@gda.platform :ruby do
- @gda.gem 'a'
+ @gda.gem "a"
end
- assert_equal [dep('a')], @set.dependencies
+ assert_equal [dep("a")], @set.dependencies
ensure
Gem.win_platform = win_platform
end
def test_platforms
- unless win_platform?
- util_set_arch 'i686-darwin8.10.1' do
+ unless Gem.win_platform?
+ util_set_arch "i686-darwin8.10.1" do
@gda.platforms :ruby do
- @gda.gem 'a'
+ @gda.gem "a"
end
- assert_equal [dep('a')], @set.dependencies
+ assert_equal [dep("a")], @set.dependencies
@gda.platforms :mswin do
- @gda.gem 'b'
+ @gda.gem "b"
end
- assert_equal [dep('a')], @set.dependencies
+ assert_equal [dep("a")], @set.dependencies
end
end
end
@@ -755,53 +760,51 @@ end
end
def test_ruby_engine
- with_engine_version 'jruby', '1.7.6' do
+ with_engine_version "jruby", "1.7.6" do
assert @gda.ruby RUBY_VERSION,
- :engine => 'jruby', :engine_version => '1.7.6'
-
+ engine: "jruby", engine_version: "1.7.6"
end
- with_engine_version 'truffleruby', '1.0.0-rc11' do
+ with_engine_version "truffleruby", "1.0.0-rc11" do
assert @gda.ruby RUBY_VERSION,
- :engine => 'truffleruby', :engine_version => '1.0.0-rc11'
-
+ engine: "truffleruby", engine_version: "1.0.0-rc11"
end
end
def test_ruby_engine_mismatch_engine
- with_engine_version 'ruby', '2.0.0' do
+ with_engine_version "ruby", "2.0.0" do
e = assert_raise Gem::RubyVersionMismatch do
- @gda.ruby RUBY_VERSION, :engine => 'jruby', :engine_version => '1.7.4'
+ @gda.ruby RUBY_VERSION, engine: "jruby", engine_version: "1.7.4"
end
- assert_equal 'Your Ruby engine is ruby, but your gem.deps.rb requires jruby',
+ assert_equal "Your Ruby engine is ruby, but your gem.deps.rb requires jruby",
e.message
end
end
def test_ruby_engine_mismatch_version
- with_engine_version 'jruby', '1.7.6' do
+ with_engine_version "jruby", "1.7.6" do
e = assert_raise Gem::RubyVersionMismatch do
- @gda.ruby RUBY_VERSION, :engine => 'jruby', :engine_version => '1.7.4'
+ @gda.ruby RUBY_VERSION, engine: "jruby", engine_version: "1.7.4"
end
- assert_equal 'Your Ruby engine version is jruby 1.7.6, but your gem.deps.rb requires jruby 1.7.4',
+ assert_equal "Your Ruby engine version is jruby 1.7.6, but your gem.deps.rb requires jruby 1.7.4",
e.message
end
end
def test_ruby_engine_no_engine_version
e = assert_raise ArgumentError do
- @gda.ruby RUBY_VERSION, :engine => 'jruby'
+ @gda.ruby RUBY_VERSION, engine: "jruby"
end
- assert_equal 'You must specify engine_version along with the Ruby engine',
+ assert_equal "You must specify engine_version along with the Ruby engine",
e.message
end
def test_ruby_mismatch
e = assert_raise Gem::RubyVersionMismatch do
- @gda.ruby '1.8.0'
+ @gda.ruby "1.8.0"
end
assert_equal "Your Ruby version is #{RUBY_VERSION}, but your gem.deps.rb requires 1.8.0", e.message
@@ -810,19 +813,19 @@ end
def test_ruby_mismatch_installing
@gda.installing = true
- assert @gda.ruby '1.8.0'
+ assert @gda.ruby "1.8.0"
end
def test_source
sources = Gem.sources
- @gda.source 'http://first.example'
+ @gda.source "http://first.example"
assert_equal %w[http://first.example], Gem.sources
assert_same sources, Gem.sources
- @gda.source 'http://second.example'
+ @gda.source "http://second.example"
assert_equal %w[http://first.example http://second.example], Gem.sources
end
@@ -832,9 +835,9 @@ end
engine = Gem.ruby_engine
engine_version = RUBY_ENGINE_VERSION
- with_engine_version 'other', '1.2.3' do
- assert_equal 'other', Gem.ruby_engine
- assert_equal '1.2.3', RUBY_ENGINE_VERSION
+ with_engine_version "other", "1.2.3" do
+ assert_equal "other", Gem.ruby_engine
+ assert_equal "1.2.3", RUBY_ENGINE_VERSION
assert_equal version, RUBY_VERSION
end
diff --git a/test/rubygems/test_gem_request_set_lockfile.rb b/test/rubygems/test_gem_request_set_lockfile.rb
index 690b632d9b..83f5002508 100644
--- a/test/rubygems/test_gem_request_set_lockfile.rb
+++ b/test/rubygems/test_gem_request_set_lockfile.rb
@@ -1,7 +1,8 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/request_set'
-require 'rubygems/request_set/lockfile'
+
+require_relative "helper"
+require "rubygems/request_set"
+require "rubygems/request_set/lockfile"
class TestGemRequestSetLockfile < Gem::TestCase
def setup
@@ -9,7 +10,7 @@ class TestGemRequestSetLockfile < Gem::TestCase
Gem::RemoteFetcher.fetcher = @fetcher = Gem::FakeFetcher.new
- util_set_arch 'i686-darwin8.10.1'
+ util_set_arch "i686-darwin8.10.1"
@set = Gem::RequestSet.new
@@ -19,7 +20,7 @@ class TestGemRequestSetLockfile < Gem::TestCase
@set.instance_variable_set :@git_set, @git_set
@set.instance_variable_set :@vendor_set, @vendor_set
- @gem_deps_file = 'gem.deps.rb'
+ @gem_deps_file = "gem.deps.rb"
end
def lockfile
@@ -29,19 +30,19 @@ class TestGemRequestSetLockfile < Gem::TestCase
def write_lockfile(lockfile)
@lock_file = File.expand_path "#{@gem_deps_file}.lock"
- File.open @lock_file, 'w' do |io|
+ File.open @lock_file, "w" do |io|
io.write lockfile
end
end
def test_add_DEPENDENCIES
spec_fetcher do |fetcher|
- fetcher.spec 'a', 2 do |s|
- s.add_development_dependency 'b'
+ fetcher.spec "a", 2 do |s|
+ s.add_development_dependency "b"
end
end
- @set.gem 'a'
+ @set.gem "a"
@set.resolve
out = []
@@ -49,8 +50,8 @@ class TestGemRequestSetLockfile < Gem::TestCase
lockfile.add_DEPENDENCIES out
expected = [
- 'DEPENDENCIES',
- ' a',
+ "DEPENDENCIES",
+ " a",
nil,
]
@@ -59,14 +60,14 @@ class TestGemRequestSetLockfile < Gem::TestCase
def test_add_DEPENDENCIES_from_gem_deps
spec_fetcher do |fetcher|
- fetcher.spec 'a', 2 do |s|
- s.add_development_dependency 'b'
+ fetcher.spec "a", 2 do |s|
+ s.add_development_dependency "b"
end
end
- dependencies = { 'a' => Gem::Requirement.new('~> 2.0') }
+ dependencies = { "a" => Gem::Requirement.new("~> 2.0") }
- @set.gem 'a'
+ @set.gem "a"
@set.resolve
@lockfile =
Gem::RequestSet::Lockfile.new @set, @gem_deps_file, dependencies
@@ -76,8 +77,8 @@ class TestGemRequestSetLockfile < Gem::TestCase
@lockfile.add_DEPENDENCIES out
expected = [
- 'DEPENDENCIES',
- ' a (~> 2.0)',
+ "DEPENDENCIES",
+ " a (~> 2.0)",
nil,
]
@@ -86,18 +87,18 @@ class TestGemRequestSetLockfile < Gem::TestCase
def test_add_GEM
spec_fetcher do |fetcher|
- fetcher.spec 'a', 2 do |s|
- s.add_dependency 'b'
- s.add_development_dependency 'c'
+ fetcher.spec "a", 2 do |s|
+ s.add_dependency "b"
+ s.add_development_dependency "c"
end
- fetcher.spec 'b', 2
+ fetcher.spec "b", 2
- fetcher.spec 'bundler', 1
+ fetcher.spec "bundler", 1
end
- @set.gem 'a'
- @set.gem 'bundler'
+ @set.gem "a"
+ @set.gem "bundler"
@set.resolve
out = []
@@ -105,12 +106,12 @@ class TestGemRequestSetLockfile < Gem::TestCase
lockfile.add_GEM out, lockfile.spec_groups
expected = [
- 'GEM',
- ' remote: http://gems.example.com/',
- ' specs:',
- ' a (2)',
- ' b',
- ' b (2)',
+ "GEM",
+ " remote: http://gems.example.com/",
+ " specs:",
+ " a (2)",
+ " b",
+ " b (2)",
nil,
]
@@ -119,16 +120,16 @@ class TestGemRequestSetLockfile < Gem::TestCase
def test_add_PLATFORMS
spec_fetcher do |fetcher|
- fetcher.spec 'a', 2 do |s|
- s.add_dependency 'b'
+ fetcher.spec "a", 2 do |s|
+ s.add_dependency "b"
end
- fetcher.spec 'b', 2 do |s|
+ fetcher.spec "b", 2 do |s|
s.platform = Gem::Platform::CURRENT
end
end
- @set.gem 'a'
+ @set.gem "a"
@set.resolve
out = []
@@ -136,9 +137,9 @@ class TestGemRequestSetLockfile < Gem::TestCase
lockfile.add_PLATFORMS out
expected = [
- 'PLATFORMS',
- ' ruby',
- ' x86-darwin-8',
+ "PLATFORMS",
+ " ruby",
+ " x86-darwin-8",
nil,
]
@@ -146,21 +147,21 @@ class TestGemRequestSetLockfile < Gem::TestCase
end
def test_relative_path_from
- path = lockfile.relative_path_from '/foo', '/foo/bar'
+ path = lockfile.relative_path_from "/foo", "/foo/bar"
- assert_equal File.expand_path('/foo'), path
+ assert_equal File.expand_path("/foo"), path
- path = lockfile.relative_path_from '/foo', '/foo'
+ path = lockfile.relative_path_from "/foo", "/foo"
- assert_equal '.', path
+ assert_equal ".", path
end
def test_to_s_gem
spec_fetcher do |fetcher|
- fetcher.spec 'a', 2
+ fetcher.spec "a", 2
end
- @set.gem 'a'
+ @set.gem "a"
expected = <<-LOCKFILE
GEM
@@ -180,12 +181,12 @@ DEPENDENCIES
def test_to_s_gem_dependency
spec_fetcher do |fetcher|
- fetcher.spec 'a', 2, 'c' => '>= 0', 'b' => '>= 0'
- fetcher.spec 'b', 2
- fetcher.spec 'c', 2
+ fetcher.spec "a", 2, "c" => ">= 0", "b" => ">= 0"
+ fetcher.spec "b", 2
+ fetcher.spec "c", 2
end
- @set.gem 'a'
+ @set.gem "a"
expected = <<-LOCKFILE
GEM
@@ -211,12 +212,12 @@ DEPENDENCIES
def test_to_s_gem_dependency_non_default
spec_fetcher do |fetcher|
- fetcher.spec 'a', 2, 'b' => '>= 1'
- fetcher.spec 'b', 2
+ fetcher.spec "a", 2, "b" => ">= 1"
+ fetcher.spec "b", 2
end
- @set.gem 'b'
- @set.gem 'a'
+ @set.gem "b"
+ @set.gem "a"
expected = <<-LOCKFILE
GEM
@@ -239,11 +240,11 @@ DEPENDENCIES
def test_to_s_gem_dependency_requirement
spec_fetcher do |fetcher|
- fetcher.spec 'a', 2, 'b' => '>= 0'
- fetcher.spec 'b', 2
+ fetcher.spec "a", 2, "b" => ">= 0"
+ fetcher.spec "b", 2
end
- @set.gem 'a', '>= 1'
+ @set.gem "a", ">= 1"
expected = <<-LOCKFILE
GEM
@@ -269,7 +270,7 @@ DEPENDENCIES
@vendor_set.add_vendor_gem name, directory
- @set.gem 'a'
+ @set.gem "a"
expected = <<-LOCKFILE
PATH
@@ -292,7 +293,7 @@ DEPENDENCIES
@vendor_set.add_vendor_gem name, File.expand_path(directory)
- @set.gem 'a'
+ @set.gem "a"
expected = <<-LOCKFILE
PATH
@@ -312,12 +313,12 @@ DEPENDENCIES
def test_to_s_gem_platform
spec_fetcher do |fetcher|
- fetcher.spec 'a', 2 do |spec|
+ fetcher.spec "a", 2 do |spec|
spec.platform = Gem::Platform.local
end
end
- @set.gem 'a'
+ @set.gem "a"
expected = <<-LOCKFILE
GEM
@@ -337,17 +338,17 @@ DEPENDENCIES
def test_to_s_gem_source
spec_fetcher do |fetcher|
- fetcher.download 'a', 2
+ fetcher.download "a", 2
end
- spec_fetcher 'http://other.example/' do |fetcher|
- fetcher.download 'b', 2
+ spec_fetcher "http://other.example/" do |fetcher|
+ fetcher.download "b", 2
end
- Gem.sources << 'http://other.example/'
+ Gem.sources << "http://other.example/"
- @set.gem 'a'
- @set.gem 'b'
+ @set.gem "a"
+ @set.gem "b"
expected = <<-LOCKFILE
GEM
@@ -377,43 +378,43 @@ DEPENDENCIES
head = nil
Dir.chdir repository do
- FileUtils.mkdir 'b'
+ FileUtils.mkdir "b"
- Dir.chdir 'b' do
- b = Gem::Specification.new 'b', 1 do |s|
- s.add_dependency 'a', '~> 1.0'
- s.add_dependency 'c', '~> 1.0'
+ Dir.chdir "b" do
+ b = Gem::Specification.new "b", 1 do |s|
+ s.add_dependency "a", "~> 1.0"
+ s.add_dependency "c", "~> 1.0"
end
- File.open 'b.gemspec', 'w' do |io|
+ File.open "b.gemspec", "w" do |io|
io.write b.to_ruby
end
- system @git, 'add', 'b.gemspec'
- system @git, 'commit', '--quiet', '-m', 'add b/b.gemspec'
+ system @git, "add", "b.gemspec"
+ system @git, "commit", "--quiet", "-m", "add b/b.gemspec"
end
- FileUtils.mkdir 'c'
+ FileUtils.mkdir "c"
- Dir.chdir 'c' do
- c = Gem::Specification.new 'c', 1
+ Dir.chdir "c" do
+ c = Gem::Specification.new "c", 1
- File.open 'c.gemspec', 'w' do |io|
+ File.open "c.gemspec", "w" do |io|
io.write c.to_ruby
end
- system @git, 'add', 'c.gemspec'
- system @git, 'commit', '--quiet', '-m', 'add c/c.gemspec'
+ system @git, "add", "c.gemspec"
+ system @git, "commit", "--quiet", "-m", "add c/c.gemspec"
end
head = `#{@git} rev-parse HEAD`.strip
end
- @git_set.add_git_gem 'a', repository, 'HEAD', true
- @git_set.add_git_gem 'b', repository, 'HEAD', true
- @git_set.add_git_gem 'c', repository, 'HEAD', true
+ @git_set.add_git_gem "a", repository, "HEAD", true
+ @git_set.add_git_gem "b", repository, "HEAD", true
+ @git_set.add_git_gem "c", repository, "HEAD", true
- @set.gem 'b'
+ @set.gem "b"
expected = <<-LOCKFILE
GIT
@@ -449,12 +450,12 @@ DEPENDENCIES
end
def test_write_error
- @set.gem 'nonexistent'
+ @set.gem "nonexistent"
gem_deps_lock_file = "#{@gem_deps_file}.lock"
- File.open gem_deps_lock_file, 'w' do |io|
- io.write 'hello'
+ File.open gem_deps_lock_file, "w" do |io|
+ io.write "hello"
end
assert_raise Gem::UnsatisfiableDependencyError do
@@ -463,6 +464,6 @@ DEPENDENCIES
assert_path_exist gem_deps_lock_file
- assert_equal 'hello', File.read(gem_deps_lock_file)
+ assert_equal "hello", File.read(gem_deps_lock_file)
end
end
diff --git a/test/rubygems/test_gem_request_set_lockfile_parser.rb b/test/rubygems/test_gem_request_set_lockfile_parser.rb
index 4007c3a69c..253a59b243 100644
--- a/test/rubygems/test_gem_request_set_lockfile_parser.rb
+++ b/test/rubygems/test_gem_request_set_lockfile_parser.rb
@@ -1,14 +1,15 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/request_set'
-require 'rubygems/request_set/lockfile'
-require 'rubygems/request_set/lockfile/tokenizer'
-require 'rubygems/request_set/lockfile/parser'
+
+require_relative "helper"
+require "rubygems/request_set"
+require "rubygems/request_set/lockfile"
+require "rubygems/request_set/lockfile/tokenizer"
+require "rubygems/request_set/lockfile/parser"
class TestGemRequestSetLockfileParser < Gem::TestCase
def setup
super
- @gem_deps_file = 'gem.deps.rb'
+ @gem_deps_file = "gem.deps.rb"
@lock_file = File.expand_path "#{@gem_deps_file}.lock"
@set = Gem::RequestSet.new
end
@@ -53,7 +54,7 @@ class TestGemRequestSetLockfileParser < Gem::TestCase
parser = tokenizer.make_parser nil, nil
e = assert_raise Gem::RequestSet::Lockfile::ParseError do
- parser.get :text, 'y'
+ parser.get :text, "y"
end
expected =
@@ -83,7 +84,7 @@ DEPENDENCIES
platforms = []
parse_lockfile @set, platforms
- assert_equal [dep('a')], @set.dependencies
+ assert_equal [dep("a")], @set.dependencies
assert_equal [Gem::Platform::RUBY], platforms
@@ -91,9 +92,9 @@ DEPENDENCIES
Gem::Resolver::LockSet === set
end
- assert lockfile_set, 'could not find a LockSet'
+ assert lockfile_set, "could not find a LockSet"
- assert_equal %w[a-2], lockfile_set.specs.map {|tuple| tuple.full_name }
+ assert_equal %w[a-2], lockfile_set.specs.map(&:full_name)
end
def test_parse_dependencies
@@ -113,7 +114,7 @@ DEPENDENCIES
platforms = []
parse_lockfile @set, platforms
- assert_equal [dep('a', '>= 1', '<= 2')], @set.dependencies
+ assert_equal [dep("a", ">= 1", "<= 2")], @set.dependencies
assert_equal [Gem::Platform::RUBY], platforms
@@ -121,9 +122,9 @@ DEPENDENCIES
Gem::Resolver::LockSet === set
end
- assert lockfile_set, 'could not find a LockSet'
+ assert lockfile_set, "could not find a LockSet"
- assert_equal %w[a-2], lockfile_set.specs.map {|tuple| tuple.full_name }
+ assert_equal %w[a-2], lockfile_set.specs.map(&:full_name)
end
def test_parse_DEPENDENCIES_git
@@ -159,8 +160,8 @@ DEPENDENCIES
parse_lockfile @set, []
expected = [
- dep('i18n-active_record', '= 0.0.2'),
- dep('rails-footnotes', '= 3.7.9'),
+ dep("i18n-active_record", "= 0.0.2"),
+ dep("rails-footnotes", "= 3.7.9"),
]
assert_equal expected, @set.dependencies
@@ -188,7 +189,7 @@ DEPENDENCIES
parse_lockfile @set, []
expected = [
- dep('jwt', '= 1.1'),
+ dep("jwt", "= 1.1"),
]
assert_equal expected, @set.dependencies
@@ -209,15 +210,15 @@ DEPENDENCIES
parse_lockfile @set, []
- assert_equal [dep('a', '>= 0')], @set.dependencies
+ assert_equal [dep("a", ">= 0")], @set.dependencies
lockfile_set = @set.sets.find do |set|
Gem::Resolver::LockSet === set
end
- assert lockfile_set, 'found a LockSet'
+ assert lockfile_set, "found a LockSet"
- assert_equal %w[a-2], lockfile_set.specs.map {|s| s.full_name }
+ assert_equal %w[a-2], lockfile_set.specs.map(&:full_name)
end
def test_parse_GEM_remote_multiple
@@ -237,27 +238,27 @@ DEPENDENCIES
parse_lockfile @set, []
- assert_equal [dep('a', '>= 0')], @set.dependencies
+ assert_equal [dep("a", ">= 0")], @set.dependencies
lockfile_set = @set.sets.find do |set|
Gem::Resolver::LockSet === set
end
- assert lockfile_set, 'found a LockSet'
+ assert lockfile_set, "found a LockSet"
- assert_equal %w[a-2], lockfile_set.specs.map {|s| s.full_name }
+ assert_equal %w[a-2], lockfile_set.specs.map(&:full_name)
assert_equal %w[https://gems.example/ https://other.example/],
- lockfile_set.specs.flat_map {|s| s.sources.map{|src| src.uri.to_s } }
+ lockfile_set.specs.flat_map {|s| s.sources.map {|src| src.uri.to_s } }
end
def test_parse_GIT
- @set.instance_variable_set :@install_dir, 'install_dir'
+ @set.instance_variable_set :@install_dir, "install_dir"
write_lockfile <<-LOCKFILE
GIT
remote: git://example/a.git
- revision: master
+ revision: abranch
specs:
a (2)
b (>= 3)
@@ -269,31 +270,31 @@ DEPENDENCIES
parse_lockfile @set, []
- assert_equal [dep('a', '= 2')], @set.dependencies
+ assert_equal [dep("a", "= 2")], @set.dependencies
lockfile_set = @set.sets.find do |set|
Gem::Resolver::LockSet === set
end
- refute lockfile_set, 'fount a LockSet'
+ refute lockfile_set, "found a LockSet"
git_set = @set.sets.find do |set|
Gem::Resolver::GitSet === set
end
- assert git_set, 'could not find a GitSet'
+ assert git_set, "could not find a GitSet"
- assert_equal %w[a-2], git_set.specs.values.map {|s| s.full_name }
+ assert_equal %w[a-2], git_set.specs.values.map(&:full_name)
- assert_equal [dep('b', '>= 3'), dep('c')],
+ assert_equal [dep("b", ">= 3"), dep("c")],
git_set.specs.values.first.dependencies
expected = {
- 'a' => %w[git://example/a.git master],
+ "a" => %w[git://example/a.git abranch],
}
assert_equal expected, git_set.repositories
- assert_equal 'install_dir', git_set.root_dir
+ assert_equal "install_dir", git_set.root_dir
end
def test_parse_GIT_branch
@@ -312,22 +313,22 @@ DEPENDENCIES
parse_lockfile @set, []
- assert_equal [dep('a', '= 2')], @set.dependencies
+ assert_equal [dep("a", "= 2")], @set.dependencies
lockfile_set = @set.sets.find do |set|
Gem::Resolver::LockSet === set
end
- refute lockfile_set, 'fount a LockSet'
+ refute lockfile_set, "found a LockSet"
git_set = @set.sets.find do |set|
Gem::Resolver::GitSet === set
end
- assert git_set, 'could not find a GitSet'
+ assert git_set, "could not find a GitSet"
expected = {
- 'a' => %w[git://example/a.git 1234abc],
+ "a" => %w[git://example/a.git 1234abc],
}
assert_equal expected, git_set.repositories
@@ -349,22 +350,22 @@ DEPENDENCIES
parse_lockfile @set, []
- assert_equal [dep('a', '= 2')], @set.dependencies
+ assert_equal [dep("a", "= 2")], @set.dependencies
lockfile_set = @set.sets.find do |set|
Gem::Resolver::LockSet === set
end
- refute lockfile_set, 'fount a LockSet'
+ refute lockfile_set, "found a LockSet"
git_set = @set.sets.find do |set|
Gem::Resolver::GitSet === set
end
- assert git_set, 'could not find a GitSet'
+ assert git_set, "could not find a GitSet"
expected = {
- 'a' => %w[git://example/a.git 1234abc],
+ "a" => %w[git://example/a.git 1234abc],
}
assert_equal expected, git_set.repositories
@@ -386,22 +387,22 @@ DEPENDENCIES
parse_lockfile @set, []
- assert_equal [dep('a', '= 2')], @set.dependencies
+ assert_equal [dep("a", "= 2")], @set.dependencies
lockfile_set = @set.sets.find do |set|
Gem::Resolver::LockSet === set
end
- refute lockfile_set, 'fount a LockSet'
+ refute lockfile_set, "found a LockSet"
git_set = @set.sets.find do |set|
Gem::Resolver::GitSet === set
end
- assert git_set, 'could not find a GitSet'
+ assert git_set, "could not find a GitSet"
expected = {
- 'a' => %w[git://example/a.git 1234abc],
+ "a" => %w[git://example/a.git 1234abc],
}
assert_equal expected, git_set.repositories
@@ -423,45 +424,45 @@ DEPENDENCIES
parse_lockfile @set, []
- assert_equal [dep('a', '= 1')], @set.dependencies
+ assert_equal [dep("a", "= 1")], @set.dependencies
lockfile_set = @set.sets.find do |set|
Gem::Resolver::LockSet === set
end
- refute lockfile_set, 'found a LockSet'
+ refute lockfile_set, "found a LockSet"
vendor_set = @set.sets.find do |set|
Gem::Resolver::VendorSet === set
end
- assert vendor_set, 'could not find a VendorSet'
+ assert vendor_set, "could not find a VendorSet"
- assert_equal %w[a-1], vendor_set.specs.values.map {|s| s.full_name }
+ assert_equal %w[a-1], vendor_set.specs.values.map(&:full_name)
- spec = vendor_set.load_spec 'a', nil, nil, nil
+ spec = vendor_set.load_spec "a", nil, nil, nil
- assert_equal [dep('b', '= 2')], spec.dependencies
+ assert_equal [dep("b", "= 2")], spec.dependencies
end
def test_parse_dependency
- write_lockfile ' 1)'
+ write_lockfile " 1)"
tokenizer = Gem::RequestSet::Lockfile::Tokenizer.from_file @lock_file
parser = tokenizer.make_parser nil, nil
- parsed = parser.parse_dependency 'a', '='
+ parsed = parser.parse_dependency "a", "="
- assert_equal dep('a', '= 1'), parsed
+ assert_equal dep("a", "= 1"), parsed
- write_lockfile ')'
+ write_lockfile ")"
tokenizer = Gem::RequestSet::Lockfile::Tokenizer.from_file @lock_file
parser = tokenizer.make_parser nil, nil
- parsed = parser.parse_dependency 'a', '2'
+ parsed = parser.parse_dependency "a", "2"
- assert_equal dep('a', '= 2'), parsed
+ assert_equal dep("a", "= 2"), parsed
end
def test_parse_gem_specs_dependency
@@ -486,7 +487,7 @@ DEPENDENCIES
platforms = []
parse_lockfile @set, platforms
- assert_equal [dep('a')], @set.dependencies
+ assert_equal [dep("a")], @set.dependencies
assert_equal [Gem::Platform::RUBY], platforms
@@ -494,24 +495,24 @@ DEPENDENCIES
Gem::Resolver::LockSet === set
end
- assert lockfile_set, 'could not find a LockSet'
+ assert lockfile_set, "could not find a LockSet"
- assert_equal %w[a-2 b-3], lockfile_set.specs.map {|tuple| tuple.full_name }
+ assert_equal %w[a-2 b-3], lockfile_set.specs.map(&:full_name)
expected = [
Gem::Platform::RUBY,
- Gem::Platform.new('x86_64-linux'),
+ Gem::Platform.new("x86_64-linux"),
]
- assert_equal expected, lockfile_set.specs.map {|tuple| tuple.platform }
+ assert_equal expected, lockfile_set.specs.map(&:platform)
spec = lockfile_set.specs.first
expected = [
- dep('b', '= 3'),
- dep('c', '~> 4'),
- dep('d'),
- dep('e', '~> 5.0', '>= 5.0.1'),
+ dep("b", "= 3"),
+ dep("c", "~> 4"),
+ dep("d"),
+ dep("e", "~> 5.0", ">= 5.0.1"),
]
assert_equal expected, spec.dependencies
@@ -530,7 +531,7 @@ DEPENDENCIES
end
def write_lockfile(lockfile)
- File.open @lock_file, 'w' do |io|
+ File.open @lock_file, "w" do |io|
io.write lockfile
end
end
diff --git a/test/rubygems/test_gem_request_set_lockfile_tokenizer.rb b/test/rubygems/test_gem_request_set_lockfile_tokenizer.rb
index f779c33012..dce8c9ada5 100644
--- a/test/rubygems/test_gem_request_set_lockfile_tokenizer.rb
+++ b/test/rubygems/test_gem_request_set_lockfile_tokenizer.rb
@@ -1,15 +1,16 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/request_set'
-require 'rubygems/request_set/lockfile'
-require 'rubygems/request_set/lockfile/tokenizer'
-require 'rubygems/request_set/lockfile/parser'
+
+require_relative "helper"
+require "rubygems/request_set"
+require "rubygems/request_set/lockfile"
+require "rubygems/request_set/lockfile/tokenizer"
+require "rubygems/request_set/lockfile/parser"
class TestGemRequestSetLockfileTokenizer < Gem::TestCase
def setup
super
- @gem_deps_file = 'gem.deps.rb'
+ @gem_deps_file = "gem.deps.rb"
@lock_file = File.expand_path "#{@gem_deps_file}.lock"
end
@@ -34,10 +35,10 @@ class TestGemRequestSetLockfileTokenizer < Gem::TestCase
end
def test_token_pos
- tokenizer = Gem::RequestSet::Lockfile::Tokenizer.new ''
+ tokenizer = Gem::RequestSet::Lockfile::Tokenizer.new ""
assert_equal [5, 0], tokenizer.token_pos(5)
- tokenizer = Gem::RequestSet::Lockfile::Tokenizer.new '', nil, 1, 2
+ tokenizer = Gem::RequestSet::Lockfile::Tokenizer.new "", nil, 1, 2
assert_equal [3, 1], tokenizer.token_pos(5)
end
@@ -63,74 +64,74 @@ DEPENDENCIES
LOCKFILE
expected = [
- [:section, 'GEM', 0, 0],
+ [:section, "GEM", 0, 0],
[:newline, nil, 3, 0],
- [:entry, 'remote', 2, 1],
+ [:entry, "remote", 2, 1],
[:text, @gem_repo, 10, 1],
[:newline, nil, 34, 1],
- [:entry, 'specs', 2, 2],
+ [:entry, "specs", 2, 2],
[:newline, nil, 8, 2],
- [:text, 'a', 4, 3],
+ [:text, "a", 4, 3],
[:l_paren, nil, 6, 3],
- [:text, '2', 7, 3],
+ [:text, "2", 7, 3],
[:r_paren, nil, 8, 3],
[:newline, nil, 9, 3],
- [:text, 'b', 6, 4],
+ [:text, "b", 6, 4],
[:l_paren, nil, 8, 4],
- [:requirement, '=', 9, 4],
- [:text, '2', 11, 4],
+ [:requirement, "=", 9, 4],
+ [:text, "2", 11, 4],
[:r_paren, nil, 12, 4],
[:newline, nil, 13, 4],
- [:text, 'c', 6, 5],
+ [:text, "c", 6, 5],
[:l_paren, nil, 8, 5],
- [:requirement, '!=', 9, 5],
- [:text, '3', 12, 5],
+ [:requirement, "!=", 9, 5],
+ [:text, "3", 12, 5],
[:r_paren, nil, 13, 5],
[:newline, nil, 14, 5],
- [:text, 'd', 6, 6],
+ [:text, "d", 6, 6],
[:l_paren, nil, 8, 6],
- [:requirement, '>', 9, 6],
- [:text, '4', 11, 6],
+ [:requirement, ">", 9, 6],
+ [:text, "4", 11, 6],
[:r_paren, nil, 12, 6],
[:newline, nil, 13, 6],
- [:text, 'e', 6, 7],
+ [:text, "e", 6, 7],
[:l_paren, nil, 8, 7],
- [:requirement, '<', 9, 7],
- [:text, '5', 11, 7],
+ [:requirement, "<", 9, 7],
+ [:text, "5", 11, 7],
[:r_paren, nil, 12, 7],
[:newline, nil, 13, 7],
- [:text, 'f', 6, 8],
+ [:text, "f", 6, 8],
[:l_paren, nil, 8, 8],
- [:requirement, '>=', 9, 8],
- [:text, '6', 12, 8],
+ [:requirement, ">=", 9, 8],
+ [:text, "6", 12, 8],
[:r_paren, nil, 13, 8],
[:newline, nil, 14, 8],
- [:text, 'g', 6, 9],
+ [:text, "g", 6, 9],
[:l_paren, nil, 8, 9],
- [:requirement, '<=', 9, 9],
- [:text, '7', 12, 9],
+ [:requirement, "<=", 9, 9],
+ [:text, "7", 12, 9],
[:r_paren, nil, 13, 9],
[:newline, nil, 14, 9],
- [:text, 'h', 6, 10],
+ [:text, "h", 6, 10],
[:l_paren, nil, 8, 10],
- [:requirement, '~>', 9, 10],
- [:text, '8', 12, 10],
+ [:requirement, "~>", 9, 10],
+ [:text, "8", 12, 10],
[:r_paren, nil, 13, 10],
[:newline, nil, 14, 10],
[:newline, nil, 0, 11],
- [:section, 'PLATFORMS', 0, 12],
+ [:section, "PLATFORMS", 0, 12],
[:newline, nil, 9, 12],
[:text, Gem::Platform::RUBY, 2, 13],
@@ -138,10 +139,10 @@ DEPENDENCIES
[:newline, nil, 0, 14],
- [:section, 'DEPENDENCIES', 0, 15],
+ [:section, "DEPENDENCIES", 0, 15],
[:newline, nil, 12, 15],
- [:text, 'a', 2, 16],
+ [:text, "a", 2, 16],
[:newline, nil, 3, 16],
]
@@ -163,27 +164,27 @@ DEPENDENCIES
LOCKFILE
expected = [
- [:section, 'GEM', 0, 0],
+ [:section, "GEM", 0, 0],
[:newline, nil, 3, 0],
- [:entry, 'remote', 2, 1],
+ [:entry, "remote", 2, 1],
[:text, @gem_repo, 10, 1],
[:newline, nil, 34, 1],
- [:entry, 'specs', 2, 2],
+ [:entry, "specs", 2, 2],
[:newline, nil, 8, 2],
- [:text, 'Ab', 4, 3],
+ [:text, "Ab", 4, 3],
[:l_paren, nil, 7, 3],
- [:text, '2', 8, 3],
+ [:text, "2", 8, 3],
[:r_paren, nil, 9, 3],
[:newline, nil, 10, 3],
[:newline, nil, 0, 4],
- [:section, 'PLATFORMS', 0, 5],
+ [:section, "PLATFORMS", 0, 5],
[:newline, nil, 9, 5],
[:text, Gem::Platform::RUBY, 2, 6],
[:newline, nil, 6, 6],
[:newline, nil, 0, 7],
- [:section, 'DEPENDENCIES', 0, 8],
+ [:section, "DEPENDENCIES", 0, 8],
[:newline, nil, 12, 8],
- [:text, 'Ab', 2, 9],
+ [:text, "Ab", 2, 9],
[:newline, nil, 4, 9],
]
@@ -191,7 +192,7 @@ DEPENDENCIES
end
def test_tokenize_conflict_markers
- write_lockfile '<<<<<<<'
+ write_lockfile "<<<<<<<"
e = assert_raise Gem::RequestSet::Lockfile::ParseError do
tokenize_lockfile
@@ -200,7 +201,7 @@ DEPENDENCIES
assert_equal "your #{@lock_file} contains merge conflict markers (at line 0 column 0)",
e.message
- write_lockfile '|||||||'
+ write_lockfile "|||||||"
e = assert_raise Gem::RequestSet::Lockfile::ParseError do
tokenize_lockfile
@@ -209,7 +210,7 @@ DEPENDENCIES
assert_equal "your #{@lock_file} contains merge conflict markers (at line 0 column 0)",
e.message
- write_lockfile '======='
+ write_lockfile "======="
e = assert_raise Gem::RequestSet::Lockfile::ParseError do
tokenize_lockfile
@@ -218,7 +219,7 @@ DEPENDENCIES
assert_equal "your #{@lock_file} contains merge conflict markers (at line 0 column 0)",
e.message
- write_lockfile '>>>>>>>'
+ write_lockfile ">>>>>>>"
e = assert_raise Gem::RequestSet::Lockfile::ParseError do
tokenize_lockfile
@@ -235,10 +236,10 @@ DEPENDENCIES
LOCKFILE
expected = [
- [:section, 'DEPENDENCIES', 0, 0],
+ [:section, "DEPENDENCIES", 0, 0],
[:newline, nil, 12, 0],
- [:text, 'a', 2, 1],
+ [:text, "a", 2, 1],
[:bang, nil, 3, 1],
[:newline, nil, 4, 1],
]
@@ -256,29 +257,29 @@ GEM
LOCKFILE
expected = [
- [:section, 'GEM', 0, 0],
+ [:section, "GEM", 0, 0],
[:newline, nil, 3, 0],
- [:entry, 'remote', 2, 1],
+ [:entry, "remote", 2, 1],
[:text, @gem_repo, 10, 1],
[:newline, nil, 34, 1],
- [:entry, 'specs', 2, 2],
+ [:entry, "specs", 2, 2],
[:newline, nil, 8, 2],
- [:text, 'a', 4, 3],
+ [:text, "a", 4, 3],
[:l_paren, nil, 6, 3],
- [:text, '2', 7, 3],
+ [:text, "2", 7, 3],
[:r_paren, nil, 8, 3],
[:newline, nil, 9, 3],
- [:text, 'b', 6, 4],
+ [:text, "b", 6, 4],
[:l_paren, nil, 8, 4],
- [:requirement, '~>', 9, 4],
- [:text, '3.0', 12, 4],
+ [:requirement, "~>", 9, 4],
+ [:text, "3.0", 12, 4],
[:comma, nil, 15, 4],
- [:requirement, '>=', 17, 4],
- [:text, '3.0.1', 20, 4],
+ [:requirement, ">=", 17, 4],
+ [:text, "3.0.1", 20, 4],
[:r_paren, nil, 25, 4],
[:newline, nil, 26, 4],
]
@@ -295,7 +296,7 @@ GEM
end
def write_lockfile(lockfile)
- File.open @lock_file, 'w' do |io|
+ File.open @lock_file, "w" do |io|
io.write lockfile
end
end
diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb
index b4367681d0..de0d11ec00 100644
--- a/test/rubygems/test_gem_requirement.rb
+++ b/test/rubygems/test_gem_requirement.rb
@@ -1,14 +1,23 @@
# frozen_string_literal: true
-require_relative 'helper'
+
+require_relative "helper"
require "rubygems/requirement"
class TestGemRequirement < Gem::TestCase
def test_concat
- r = req '>= 1'
+ r = req ">= 1"
+
+ r.concat ["< 2"]
+
+ assert_equal [[">=", v(1)], ["<", v(2)]], r.requirements
+ end
- r.concat ['< 2']
+ def test_initialize_copy
+ r = req("= 1.2")
+ r2 = r.dup
- assert_equal [['>=', v(1)], ['<', v(2)]], r.requirements
+ assert_equal r.requirements, r2.requirements
+ refute_same r.requirements, r2.requirements
end
def test_equals2
@@ -60,42 +69,42 @@ class TestGemRequirement < Gem::TestCase
end
def test_for_lockfile
- assert_equal ' (~> 1.0)', req('~> 1.0').for_lockfile
+ assert_equal " (~> 1.0)", req("~> 1.0").for_lockfile
- assert_equal ' (~> 1.0, >= 1.0.1)', req('>= 1.0.1', '~> 1.0').for_lockfile
+ assert_equal " (~> 1.0, >= 1.0.1)", req(">= 1.0.1", "~> 1.0").for_lockfile
- duped = req '= 1.0'
- duped.requirements << ['=', v('1.0')]
+ duped = req "= 1.0"
+ duped.requirements << ["=", v("1.0")]
- assert_equal ' (= 1.0)', duped.for_lockfile
+ assert_equal " (= 1.0)", duped.for_lockfile
assert_nil Gem::Requirement.default.for_lockfile
end
def test_parse
- assert_equal ['=', Gem::Version.new(1)], Gem::Requirement.parse(' 1')
- assert_equal ['=', Gem::Version.new(1)], Gem::Requirement.parse('= 1')
- assert_equal ['>', Gem::Version.new(1)], Gem::Requirement.parse('> 1')
- assert_equal ['=', Gem::Version.new(1)], Gem::Requirement.parse("=\n1")
- assert_equal ['=', Gem::Version.new(1)], Gem::Requirement.parse('1.0')
+ assert_equal ["=", Gem::Version.new(1)], Gem::Requirement.parse(" 1")
+ assert_equal ["=", Gem::Version.new(1)], Gem::Requirement.parse("= 1")
+ assert_equal [">", Gem::Version.new(1)], Gem::Requirement.parse("> 1")
+ assert_equal ["=", Gem::Version.new(1)], Gem::Requirement.parse("=\n1")
+ assert_equal ["=", Gem::Version.new(1)], Gem::Requirement.parse("1.0")
- assert_equal ['=', Gem::Version.new(2)],
- Gem::Requirement.parse(Gem::Version.new('2'))
+ assert_equal ["=", Gem::Version.new(2)],
+ Gem::Requirement.parse(Gem::Version.new("2"))
end
- if RUBY_VERSION >= '2.5' && !(Gem.java_platform? && ENV["JRUBY_OPTS"] =~ /--debug/)
+ unless Gem.java_platform? && ENV["JRUBY_OPTS"].to_s.include?("--debug")
def test_parse_deduplication
- assert_same '~>', Gem::Requirement.parse('~> 1').first
+ assert_same "~>", Gem::Requirement.parse("~> 1").first
end
end
def test_parse_bad
[
nil,
- '',
- '! 1',
- '= junk',
- '1..2',
+ "",
+ "! 1",
+ "= junk",
+ "1..2",
].each do |bad|
e = assert_raise Gem::Requirement::BadRequirementError do
Gem::Requirement.parse bad
@@ -108,28 +117,30 @@ class TestGemRequirement < Gem::TestCase
end
def test_prerelease_eh
- r = req '= 1'
+ r = req "= 1"
refute r.prerelease?
- r = req '= 1.a'
+ r = req "= 1.a"
assert r.prerelease?
- r = req '> 1.a', '< 2'
+ r = req "> 1.a", "< 2"
assert r.prerelease?
end
def test_satisfied_by_eh_bang_equal
- r = req '!= 1.2'
+ r = req "!= 1.2"
assert_satisfied_by "1.1", r
refute_satisfied_by "1.2", r
assert_satisfied_by "1.3", r
assert_raise ArgumentError do
- assert_satisfied_by nil, r
+ Gem::Deprecate.skip_during do
+ assert_satisfied_by nil, r
+ end
end
end
@@ -141,7 +152,9 @@ class TestGemRequirement < Gem::TestCase
refute_satisfied_by "1.3", r
assert_raise ArgumentError do
- assert_satisfied_by nil, r
+ Gem::Deprecate.skip_during do
+ assert_satisfied_by nil, r
+ end
end
end
@@ -153,7 +166,9 @@ class TestGemRequirement < Gem::TestCase
refute_satisfied_by "1.3", r
assert_raise ArgumentError do
- assert_satisfied_by nil, r
+ Gem::Deprecate.skip_during do
+ assert_satisfied_by nil, r
+ end
end
end
@@ -280,7 +295,7 @@ class TestGemRequirement < Gem::TestCase
end
def test_illformed_requirements
- [ ">>> 1.3.5", "> blah" ].each do |rq|
+ [">>> 1.3.5", "> blah"].each do |rq|
assert_raise Gem::Requirement::BadRequirementError, "req [#{rq}] should fail" do
Gem::Requirement.new rq
end
@@ -362,16 +377,16 @@ class TestGemRequirement < Gem::TestCase
end
def test_specific
- refute req('> 1') .specific?
- refute req('>= 1').specific?
+ refute req("> 1") .specific?
+ refute req(">= 1").specific?
- assert req('!= 1').specific?
- assert req('< 1') .specific?
- assert req('<= 1').specific?
- assert req('= 1') .specific?
- assert req('~> 1').specific?
+ assert req("!= 1").specific?
+ assert req("< 1") .specific?
+ assert req("<= 1").specific?
+ assert req("= 1") .specific?
+ assert req("~> 1").specific?
- assert req('> 1', '> 2').specific? # GIGO
+ assert req("> 1", "> 2").specific? # GIGO
end
def test_bad
@@ -392,12 +407,12 @@ class TestGemRequirement < Gem::TestCase
end
def test_hash_with_multiple_versions
- r1 = req('1.0', '2.0')
- r2 = req('2.0', '1.0')
+ r1 = req("1.0", "2.0")
+ r2 = req("2.0", "1.0")
assert_equal r1.hash, r2.hash
- r1 = req('1.0', '2.0').tap {|r| r.concat(['3.0']) }
- r2 = req('3.0', '1.0').tap {|r| r.concat(['2.0']) }
+ r1 = req("1.0", "2.0").tap {|r| r.concat(["3.0"]) }
+ r2 = req("3.0", "1.0").tap {|r| r.concat(["2.0"]) }
assert_equal r1.hash, r2.hash
end
@@ -430,19 +445,19 @@ class TestGemRequirement < Gem::TestCase
end
def test_marshal_load_attack
- wa = Net::WriteAdapter.allocate
+ wa = Gem::Net::WriteAdapter.allocate
wa.instance_variable_set(:@socket, self.class)
wa.instance_variable_set(:@method_id, :exploit)
request_set = Gem::RequestSet.allocate
request_set.instance_variable_set(:@git_set, "id")
request_set.instance_variable_set(:@sets, wa)
- wa = Net::WriteAdapter.allocate
+ wa = Gem::Net::WriteAdapter.allocate
wa.instance_variable_set(:@socket, request_set)
wa.instance_variable_set(:@method_id, :resolve)
ent = Gem::Package::TarReader::Entry.allocate
ent.instance_variable_set(:@read, 0)
ent.instance_variable_set(:@header, "aaa")
- io = Net::BufferedIO.allocate
+ io = Gem::Net::BufferedIO.allocate
io.instance_variable_set(:@io, ent)
io.instance_variable_set(:@debug_output, wa)
reader = Gem::Package::TarReader.allocate
diff --git a/test/rubygems/test_gem_resolver.rb b/test/rubygems/test_gem_resolver.rb
index eb798ad557..4990d5d2dd 100644
--- a/test/rubygems/test_gem_resolver.rb
+++ b/test/rubygems/test_gem_resolver.rb
@@ -1,19 +1,14 @@
# frozen_string_literal: true
-require_relative 'helper'
-class TestGemResolver < Gem::TestCase
- def setup
- super
-
- @DR = Gem::Resolver
- end
+require_relative "helper"
+class TestGemResolver < Gem::TestCase
def make_dep(name, *req)
Gem::Dependency.new(name, *req)
end
def set(*specs)
- source = Gem::Source.new URI @gem_repo
+ source = Gem::Source.new Gem::URI @gem_repo
specs = specs.map do |spec|
Gem::Resolver::SpecSpecification.new nil, spec, source
@@ -25,10 +20,10 @@ class TestGemResolver < Gem::TestCase
def assert_resolves_to(expected, resolver)
actual = resolver.resolve
- exp = expected.sort_by {|s| s.full_name }
- act = actual.map {|a| a.spec.spec }.sort_by {|s| s.full_name }
+ exp = expected.sort_by(&:full_name)
+ act = actual.map {|a| a.spec.spec }.sort_by(&:full_name)
- msg = "Set of gems was not the same: #{exp.map {|x| x.full_name }.inspect} != #{act.map {|x| x.full_name }.inspect}"
+ msg = "Set of gems was not the same: #{exp.map(&:full_name).inspect} != #{act.map(&:full_name).inspect}"
assert_equal exp, act, msg
rescue Gem::DependencyResolutionError => e
@@ -36,18 +31,18 @@ class TestGemResolver < Gem::TestCase
end
def test_self_compose_sets_best_set
- best_set = @DR::BestSet.new
+ best_set = Gem::Resolver::BestSet.new
- composed = @DR.compose_sets best_set
+ composed = Gem::Resolver.compose_sets best_set
assert_equal best_set, composed
end
def test_self_compose_sets_multiple
- index_set = @DR::IndexSet.new
- vendor_set = @DR::VendorSet.new
+ index_set = Gem::Resolver::IndexSet.new
+ vendor_set = Gem::Resolver::VendorSet.new
- composed = @DR.compose_sets index_set, vendor_set
+ composed = Gem::Resolver.compose_sets index_set, vendor_set
assert_kind_of Gem::Resolver::ComposedSet, composed
@@ -55,14 +50,14 @@ class TestGemResolver < Gem::TestCase
end
def test_self_compose_sets_nest
- index_set = @DR::IndexSet.new
- vendor_set = @DR::VendorSet.new
+ index_set = Gem::Resolver::IndexSet.new
+ vendor_set = Gem::Resolver::VendorSet.new
- inner = @DR.compose_sets index_set, vendor_set
+ inner = Gem::Resolver.compose_sets index_set, vendor_set
- current_set = @DR::CurrentSet.new
+ current_set = Gem::Resolver::CurrentSet.new
- composed = @DR.compose_sets inner, current_set
+ composed = Gem::Resolver.compose_sets inner, current_set
assert_kind_of Gem::Resolver::ComposedSet, composed
@@ -70,31 +65,31 @@ class TestGemResolver < Gem::TestCase
end
def test_self_compose_sets_nil
- index_set = @DR::IndexSet.new
+ index_set = Gem::Resolver::IndexSet.new
- composed = @DR.compose_sets index_set, nil
+ composed = Gem::Resolver.compose_sets index_set, nil
assert_same index_set, composed
e = assert_raise ArgumentError do
- @DR.compose_sets nil
+ Gem::Resolver.compose_sets nil
end
- assert_equal 'one set in the composition must be non-nil', e.message
+ assert_equal "one set in the composition must be non-nil", e.message
end
def test_self_compose_sets_single
- index_set = @DR::IndexSet.new
+ index_set = Gem::Resolver::IndexSet.new
- composed = @DR.compose_sets index_set
+ composed = Gem::Resolver.compose_sets index_set
assert_same index_set, composed
end
def test_requests
- a1 = util_spec 'a', 1, 'b' => 2
+ a1 = util_spec "a", 1, "b" => 2
- r1 = Gem::Resolver::DependencyRequest.new dep('a', '= 1'), nil
+ r1 = Gem::Resolver::DependencyRequest.new dep("a", "= 1"), nil
act = Gem::Resolver::ActivationRequest.new a1, r1
@@ -104,18 +99,18 @@ class TestGemResolver < Gem::TestCase
res.requests a1, act, reqs
- assert_equal ['b (= 2)'], reqs.map {|req| req.to_s }
+ assert_equal ["b (= 2)"], reqs.map(&:to_s)
end
def test_requests_development
- a1 = util_spec 'a', 1, 'b' => 2
+ a1 = util_spec "a", 1, "b" => 2
spec = Gem::Resolver::SpecSpecification.new nil, a1
def spec.fetch_development_dependencies
@called = true
end
- r1 = Gem::Resolver::DependencyRequest.new dep('a', '= 1'), nil
+ r1 = Gem::Resolver::DependencyRequest.new dep("a", "= 1"), nil
act = Gem::Resolver::ActivationRequest.new spec, r1
@@ -126,15 +121,15 @@ class TestGemResolver < Gem::TestCase
res.requests spec, act, reqs
- assert_equal ['b (= 2)'], reqs.map {|req| req.to_s }
+ assert_equal ["b (= 2)"], reqs.map(&:to_s)
assert spec.instance_variable_defined? :@called
end
def test_requests_ignore_dependencies
- a1 = util_spec 'a', 1, 'b' => 2
+ a1 = util_spec "a", 1, "b" => 2
- r1 = Gem::Resolver::DependencyRequest.new dep('a', '= 1'), nil
+ r1 = Gem::Resolver::DependencyRequest.new dep("a", "= 1"), nil
act = Gem::Resolver::ActivationRequest.new a1, r1
@@ -149,37 +144,37 @@ class TestGemResolver < Gem::TestCase
end
def test_resolve_conservative
- a1_spec = util_spec 'a', 1
+ a1_spec = util_spec "a", 1
- a2_spec = util_spec 'a', 2 do |s|
- s.add_dependency 'b', 2
- s.add_dependency 'c'
+ a2_spec = util_spec "a", 2 do |s|
+ s.add_dependency "b", 2
+ s.add_dependency "c"
end
- b1_spec = util_spec 'b', 1
- b2_spec = util_spec 'b', 2
+ b1_spec = util_spec "b", 1
+ b2_spec = util_spec "b", 2
- c1_spec = util_spec 'c', 1 do |s|
- s.add_dependency 'd', 2
+ c1_spec = util_spec "c", 1 do |s|
+ s.add_dependency "d", 2
end
- c2_spec = util_spec 'c', 2 do |s|
- s.add_dependency 'd', 2
+ c2_spec = util_spec "c", 2 do |s|
+ s.add_dependency "d", 2
end
- d1_spec = util_spec 'd', 1 do |s|
- s.add_dependency 'e'
+ d1_spec = util_spec "d", 1 do |s|
+ s.add_dependency "e"
end
- d2_spec = util_spec 'd', 2 do |s|
- s.add_dependency 'e'
+ d2_spec = util_spec "d", 2 do |s|
+ s.add_dependency "e"
end
- e1_spec = util_spec 'e', 1
- e2_spec = util_spec 'e', 2
+ e1_spec = util_spec "e", 1
+ e2_spec = util_spec "e", 2
- a_dep = make_dep 'a', '= 2'
- e_dep = make_dep 'e'
+ a_dep = make_dep "a", "= 2"
+ e_dep = make_dep "e"
# When requesting to install:
# a-2, e
@@ -191,7 +186,7 @@ class TestGemResolver < Gem::TestCase
# With the following gems already installed:
# a-1, b-1, c-1, e-1
- res.skip_gems = {'a' => [a1_spec], 'b' => [b1_spec], 'c' => [c1_spec], 'e' => [e1_spec]}
+ res.skip_gems = { "a" => [a1_spec], "b" => [b1_spec], "c" => [c1_spec], "e" => [e1_spec] }
# Make sure the following gems end up getting used/installed/upgraded:
# a-2 (upgraded)
@@ -203,17 +198,17 @@ class TestGemResolver < Gem::TestCase
end
def test_resolve_development
- a_spec = util_spec 'a', 1 do |s|
- s.add_development_dependency 'b'
+ a_spec = util_spec "a", 1 do |s|
+ s.add_development_dependency "b"
end
- b_spec = util_spec 'b', 1 do
- |s| s.add_development_dependency 'c'
+ b_spec = util_spec "b", 1 do |s|
+ s.add_development_dependency "c"
end
- c_spec = util_spec 'c', 1
+ c_spec = util_spec "c", 1
- a_dep = make_dep 'a', '= 1'
+ a_dep = make_dep "a", "= 1"
deps = [a_dep]
@@ -227,24 +222,24 @@ class TestGemResolver < Gem::TestCase
end
def test_resolve_development_shallow
- a_spec = util_spec 'a', 1 do |s|
- s.add_development_dependency 'b'
- s.add_runtime_dependency 'd'
+ a_spec = util_spec "a", 1 do |s|
+ s.add_development_dependency "b"
+ s.add_runtime_dependency "d"
end
- b_spec = util_spec 'b', 1 do |s|
- s.add_development_dependency 'c'
+ b_spec = util_spec "b", 1 do |s|
+ s.add_development_dependency "c"
end
- c_spec = util_spec 'c', 1
+ c_spec = util_spec "c", 1
- d_spec = util_spec 'd', 1 do |s|
- s.add_development_dependency 'e'
+ d_spec = util_spec "d", 1 do |s|
+ s.add_development_dependency "e"
end
- e_spec = util_spec 'e', 1
+ e_spec = util_spec "e", 1
- a_dep = make_dep 'a', '= 1'
+ a_dep = make_dep "a", "= 1"
deps = [a_dep]
@@ -262,19 +257,19 @@ class TestGemResolver < Gem::TestCase
@fetcher = Gem::FakeFetcher.new
Gem::RemoteFetcher.fetcher = @fetcher
- a_dep = make_dep 'a', '= 1'
+ a_dep = make_dep "a", "= 1"
res = Gem::Resolver.new [a_dep], Gem::Resolver::IndexSet.new
- e = assert_raise Gem::UnsatisfiableDepedencyError do
+ e = assert_raise Gem::UnsatisfiableDependencyError do
res.resolve
end
refute_empty e.errors
end
- def test_no_overlap_specificly
- a = util_spec "a", '1'
+ def test_no_overlap_specifically
+ a = util_spec "a", "1"
b = util_spec "b", "1"
ad = make_dep "a", "= 1"
@@ -290,7 +285,7 @@ class TestGemResolver < Gem::TestCase
end
def test_pulls_in_dependencies
- a = util_spec "a", '1'
+ a = util_spec "a", "1"
b = util_spec "b", "1", "c" => "= 1"
c = util_spec "c", "1"
@@ -307,8 +302,8 @@ class TestGemResolver < Gem::TestCase
end
def test_picks_highest_version
- a1 = util_spec "a", '1'
- a2 = util_spec "a", '2'
+ a1 = util_spec "a", "1"
+ a2 = util_spec "a", "2"
s = set(a1, a2)
@@ -321,17 +316,16 @@ class TestGemResolver < Gem::TestCase
def test_picks_best_platform
is = Gem::Resolver::IndexSpecification
- unknown = Gem::Platform.new 'unknown'
- a2_p1 = a3_p2 = nil
+ unknown = Gem::Platform.new "unknown"
spec_fetcher do |fetcher|
- fetcher.spec 'a', 2
+ fetcher.spec "a", 2
- a2_p1 = fetcher.spec 'a', 2 do |s|
+ fetcher.spec "a", 2 do |s|
s.platform = Gem::Platform.local
end
- a3_p2 = fetcher.spec 'a', 3 do |s|
+ fetcher.spec "a", 3 do |s|
s.platform = unknown
end
end
@@ -342,9 +336,9 @@ class TestGemResolver < Gem::TestCase
s = set
- a2 = is.new s, 'a', v2, source, Gem::Platform::RUBY
- a2_p1 = is.new s, 'a', v2, source, Gem::Platform.local.to_s
- a3_p2 = is.new s, 'a', v3, source, unknown
+ a2 = is.new s, "a", v2, source, Gem::Platform::RUBY
+ a2_p1 = is.new s, "a", v2, source, Gem::Platform.local.to_s
+ a3_p2 = is.new s, "a", v3, source, unknown
s.add a3_p2
s.add a2_p1
@@ -357,6 +351,74 @@ class TestGemResolver < Gem::TestCase
assert_resolves_to [a2_p1.spec], res
end
+ def test_does_not_pick_musl_variants_on_non_musl_linux
+ util_set_arch "aarch64-linux" do
+ is = Gem::Resolver::IndexSpecification
+
+ linux_musl = Gem::Platform.new("aarch64-linux-musl")
+
+ spec_fetcher do |fetcher|
+ fetcher.spec "libv8-node", "15.14.0.1" do |s|
+ s.platform = Gem::Platform.local
+ end
+
+ fetcher.spec "libv8-node", "15.14.0.1" do |s|
+ s.platform = linux_musl
+ end
+ end
+
+ v15 = v("15.14.0.1")
+ source = Gem::Source.new @gem_repo
+
+ s = set
+
+ v15_linux = is.new s, "libv8-node", v15, source, Gem::Platform.local.to_s
+ v15_linux_musl = is.new s, "libv8-node", v15, source, linux_musl.to_s
+
+ s.add v15_linux
+ s.add v15_linux_musl
+
+ ad = make_dep "libv8-node", "= 15.14.0.1"
+
+ res = Gem::Resolver.new([ad], s)
+
+ assert_resolves_to [v15_linux.spec], res
+ end
+ end
+
+ def test_pick_generic_linux_variants_on_musl_linux
+ util_set_arch "aarch64-linux-musl" do
+ is = Gem::Resolver::IndexSpecification
+
+ linux = Gem::Platform.new("aarch64-linux")
+
+ spec_fetcher do |fetcher|
+ fetcher.spec "libv8-node", "15.14.0.1" do |s|
+ s.platform = linux
+ end
+
+ fetcher.spec "libv8-node", "15.14.0.1"
+ end
+
+ v15 = v("15.14.0.1")
+ source = Gem::Source.new @gem_repo
+
+ s = set
+
+ v15_ruby = is.new s, "libv8-node", v15, source, Gem::Platform::RUBY
+ v15_linux = is.new s, "libv8-node", v15, source, linux.to_s
+
+ s.add v15_linux
+ s.add v15_ruby
+
+ ad = make_dep "libv8-node", "= 15.14.0.1"
+
+ res = Gem::Resolver.new([ad], s)
+
+ assert_resolves_to [v15_linux.spec], res
+ end
+ end
+
def test_only_returns_spec_once
a1 = util_spec "a", "1", "c" => "= 1"
b1 = util_spec "b", "1", "c" => "= 1"
@@ -469,7 +531,7 @@ class TestGemResolver < Gem::TestCase
r = Gem::Resolver.new([ad], set)
- e = assert_raise Gem::UnsatisfiableDepedencyError do
+ e = assert_raise Gem::UnsatisfiableDependencyError do
r.resolve
end
@@ -486,7 +548,7 @@ class TestGemResolver < Gem::TestCase
r = Gem::Resolver.new([ad], set(a1))
- e = assert_raise Gem::UnsatisfiableDepedencyError do
+ e = assert_raise Gem::UnsatisfiableDependencyError do
r.resolve
end
@@ -499,7 +561,7 @@ class TestGemResolver < Gem::TestCase
r = Gem::Resolver.new([ad], set(a1))
- e = assert_raise Gem::UnsatisfiableDepedencyError do
+ e = assert_raise Gem::UnsatisfiableDependencyError do
r.resolve
end
@@ -509,14 +571,14 @@ class TestGemResolver < Gem::TestCase
def test_raises_and_reports_an_implicit_request_properly
a1 = util_spec "a", "1" do |s|
- s.add_runtime_dependency 'b', '= 2'
+ s.add_dependency "b", "= 2"
end
ad = make_dep "a", "= 1"
r = Gem::Resolver.new([ad], set(a1))
- e = assert_raise Gem::UnsatisfiableDepedencyError do
+ e = assert_raise Gem::UnsatisfiableDependencyError do
r.resolve
end
@@ -546,14 +608,14 @@ class TestGemResolver < Gem::TestCase
dependency = e.conflict.dependency
assert_includes %w[a b], dependency.name
- assert_equal req('>= 0'), dependency.requirement
+ assert_equal req(">= 0"), dependency.requirement
activated = e.conflict.activated
- assert_equal 'c-1', activated.full_name
+ assert_equal "c-1", activated.full_name
- assert_equal dep('c', '= 1'), activated.request.dependency
+ assert_equal dep("c", "= 1"), activated.request.dependency
- assert_equal [dep('c', '>= 2'), dep('c', '= 1')],
+ assert_equal [dep("c", ">= 2"), dep("c", "= 1")],
e.conflict.conflicting_dependencies
end
@@ -617,15 +679,15 @@ class TestGemResolver < Gem::TestCase
end
def test_resolve_conflict
- a1 = util_spec 'a', 1
- a2 = util_spec 'a', 2
+ a1 = util_spec "a", 1
+ a2 = util_spec "a", 2
- b2 = util_spec 'b', 2, 'a' => '~> 2.0'
+ b2 = util_spec "b", 2, "a" => "~> 2.0"
s = set a1, a2, b2
- a_dep = dep 'a', '~> 1.0'
- b_dep = dep 'b'
+ a_dep = dep "a", "~> 1.0"
+ b_dep = dep "b"
r = Gem::Resolver.new [a_dep, b_dep], s
@@ -635,18 +697,18 @@ class TestGemResolver < Gem::TestCase
end
def test_resolve_bug_699
- a1 = util_spec 'a', '1', 'b' => '= 2',
- 'c' => '~> 1.0.3'
+ a1 = util_spec "a", "1", "b" => "= 2",
+ "c" => "~> 1.0.3"
- b1 = util_spec 'b', '2', 'c' => '~> 1.0'
+ b1 = util_spec "b", "2", "c" => "~> 1.0"
- c1 = util_spec 'c', '1.0.9'
- c2 = util_spec 'c', '1.1.0'
- c3 = util_spec 'c', '1.2.0'
+ c1 = util_spec "c", "1.0.9"
+ c2 = util_spec "c", "1.1.0"
+ c3 = util_spec "c", "1.2.0"
s = set a1, b1, c1, c2, c3
- a_dep = dep 'a', '= 1'
+ a_dep = dep "a", "= 1"
r = Gem::Resolver.new [a_dep], s
@@ -654,16 +716,16 @@ class TestGemResolver < Gem::TestCase
end
def test_resolve_rollback
- a1 = util_spec 'a', 1
- a2 = util_spec 'a', 2
+ a1 = util_spec "a", 1
+ a2 = util_spec "a", 2
- b1 = util_spec 'b', 1, 'a' => '~> 1.0'
- b2 = util_spec 'b', 2, 'a' => '~> 2.0'
+ b1 = util_spec "b", 1, "a" => "~> 1.0"
+ b2 = util_spec "b", 2, "a" => "~> 2.0"
s = set a1, a2, b1, b2
- a_dep = dep 'a', '~> 1.0'
- b_dep = dep 'b'
+ a_dep = dep "a", "~> 1.0"
+ b_dep = dep "b"
r = Gem::Resolver.new [a_dep, b_dep], s
@@ -711,42 +773,42 @@ class TestGemResolver < Gem::TestCase
end
def test_sorts_by_source_then_version
- sourceA = Gem::Source.new 'http://example.com/a'
- sourceB = Gem::Source.new 'http://example.com/b'
- sourceC = Gem::Source.new 'http://example.com/c'
+ source_a = Gem::Source.new "http://example.com/a"
+ source_b = Gem::Source.new "http://example.com/b"
+ source_c = Gem::Source.new "http://example.com/c"
- spec_A_1 = util_spec 'some-dep', '0.0.1'
- spec_A_2 = util_spec 'some-dep', '1.0.0'
- spec_B_1 = util_spec 'some-dep', '0.0.1'
- spec_B_2 = util_spec 'some-dep', '0.0.2'
- spec_C_1 = util_spec 'some-dep', '0.1.0'
+ spec_a_1 = util_spec "some-dep", "0.0.1"
+ spec_a_2 = util_spec "some-dep", "1.0.0"
+ spec_b_1 = util_spec "some-dep", "0.0.1"
+ spec_b_2 = util_spec "some-dep", "0.0.2"
+ spec_c_1 = util_spec "some-dep", "0.1.0"
set = StaticSet.new [
- Gem::Resolver::SpecSpecification.new(nil, spec_B_1, sourceB),
- Gem::Resolver::SpecSpecification.new(nil, spec_B_2, sourceB),
- Gem::Resolver::SpecSpecification.new(nil, spec_C_1, sourceC),
- Gem::Resolver::SpecSpecification.new(nil, spec_A_2, sourceA),
- Gem::Resolver::SpecSpecification.new(nil, spec_A_1, sourceA),
+ Gem::Resolver::SpecSpecification.new(nil, spec_b_1, source_b),
+ Gem::Resolver::SpecSpecification.new(nil, spec_b_2, source_b),
+ Gem::Resolver::SpecSpecification.new(nil, spec_c_1, source_c),
+ Gem::Resolver::SpecSpecification.new(nil, spec_a_2, source_a),
+ Gem::Resolver::SpecSpecification.new(nil, spec_a_1, source_a),
]
- dependency = make_dep 'some-dep', '> 0'
+ dependency = make_dep "some-dep", "> 0"
resolver = Gem::Resolver.new [dependency], set
- assert_resolves_to [spec_B_2], resolver
+ assert_resolves_to [spec_b_2], resolver
end
def test_select_local_platforms
r = Gem::Resolver.new nil, nil
- a1 = util_spec 'a', 1
+ a1 = util_spec "a", 1
- a1_p1 = util_spec 'a', 1 do |s|
+ a1_p1 = util_spec "a", 1 do |s|
s.platform = Gem::Platform.local
end
- a1_p2 = util_spec 'a', 1 do |s|
- s.platform = 'unknown'
+ a1_p2 = util_spec "a", 1 do |s|
+ s.platform = "unknown"
end
selected = r.select_local_platforms [a1, a1_p1, a1_p2]
@@ -755,18 +817,18 @@ class TestGemResolver < Gem::TestCase
end
def test_search_for_local_platform_partial_string_match
- a1 = util_spec 'a', 1
+ a1 = util_spec "a", 1
- a1_p1 = util_spec 'a', 1 do |s|
+ a1_p1 = util_spec "a", 1 do |s|
s.platform = Gem::Platform.local.os
end
- a1_p2 = util_spec 'a', 1 do |s|
- s.platform = 'unknown'
+ a1_p2 = util_spec "a", 1 do |s|
+ s.platform = "unknown"
end
s = set(a1_p1, a1_p2, a1)
- d = [make_dep('a')]
+ d = [make_dep("a")]
r = Gem::Resolver.new(d, s)
assert_resolves_to [a1_p1], r
@@ -781,7 +843,7 @@ class TestGemResolver < Gem::TestCase
r = Gem::Resolver.new([ad], set(a1))
- e = assert_raise Gem::UnsatisfiableDepedencyError do
+ e = assert_raise Gem::UnsatisfiableDependencyError do
r.resolve
end
diff --git a/test/rubygems/test_gem_resolver_activation_request.rb b/test/rubygems/test_gem_resolver_activation_request.rb
index c7b726a230..53875b72cb 100644
--- a/test/rubygems/test_gem_resolver_activation_request.rb
+++ b/test/rubygems/test_gem_resolver_activation_request.rb
@@ -1,41 +1,40 @@
# frozen_string_literal: true
-require_relative 'helper'
+
+require_relative "helper"
class TestGemResolverActivationRequest < Gem::TestCase
def setup
super
- @DR = Gem::Resolver
-
- @dep = @DR::DependencyRequest.new dep('a', '>= 0'), nil
+ @dep = Gem::Resolver::DependencyRequest.new dep("a", ">= 0"), nil
source = Gem::Source::Local.new
platform = Gem::Platform::RUBY
- @a3 = @DR::IndexSpecification.new nil, 'a', v(3), source, platform
+ @a3 = Gem::Resolver::IndexSpecification.new nil, "a", v(3), source, platform
- @req = @DR::ActivationRequest.new @a3, @dep
+ @req = Gem::Resolver::ActivationRequest.new @a3, @dep
end
def test_development_eh
refute @req.development?
- dep_req = @DR::DependencyRequest.new dep('a', '>= 0', :development), nil
+ dep_req = Gem::Resolver::DependencyRequest.new dep("a", ">= 0", :development), nil
- act_req = @DR::ActivationRequest.new @a3, dep_req
+ act_req = Gem::Resolver::ActivationRequest.new @a3, dep_req
assert act_req.development?
end
def test_inspect
- assert_match 'a-3', @req.inspect
- assert_match 'from a (>= 0)', @req.inspect
+ assert_match "a-3", @req.inspect
+ assert_match "from a (>= 0)", @req.inspect
end
def test_installed_eh
v_spec = Gem::Resolver::VendorSpecification.new nil, @a3
- @req = @DR::ActivationRequest.new v_spec, @dep
+ @req = Gem::Resolver::ActivationRequest.new v_spec, @dep
assert @req.installed?
end
diff --git a/test/rubygems/test_gem_resolver_api_set.rb b/test/rubygems/test_gem_resolver_api_set.rb
index c3db25d7aa..5781cf37d2 100644
--- a/test/rubygems/test_gem_resolver_api_set.rb
+++ b/test/rubygems/test_gem_resolver_api_set.rb
@@ -1,55 +1,55 @@
# frozen_string_literal: true
-require_relative 'helper'
+
+require_relative "helper"
class TestGemResolverAPISet < Gem::TestCase
def setup
super
- @DR = Gem::Resolver
- @dep_uri = URI "#{@gem_repo}info/"
+ @dep_uri = Gem::URI "#{@gem_repo}info/"
end
def test_initialize
- set = @DR::APISet.new
+ set = Gem::Resolver::APISet.new
- assert_equal URI('https://index.rubygems.org/info/'), set.dep_uri
- assert_equal URI('https://index.rubygems.org/'), set.uri
- assert_equal Gem::Source.new(URI('https://index.rubygems.org')), set.source
+ assert_equal Gem::URI("https://index.rubygems.org/info/"), set.dep_uri
+ assert_equal Gem::URI("https://index.rubygems.org/"), set.uri
+ assert_equal Gem::Source.new(Gem::URI("https://index.rubygems.org")), set.source
end
def test_initialize_deeper_uri
- set = @DR::APISet.new 'https://rubygemsserver.com/mygems/info'
+ set = Gem::Resolver::APISet.new "https://rubygemsserver.com/mygems/info"
- assert_equal URI('https://rubygemsserver.com/mygems/info'), set.dep_uri
- assert_equal URI('https://rubygemsserver.com/'), set.uri
- assert_equal Gem::Source.new(URI('https://rubygemsserver.com/')), set.source
+ assert_equal Gem::URI("https://rubygemsserver.com/mygems/info"), set.dep_uri
+ assert_equal Gem::URI("https://rubygemsserver.com/"), set.uri
+ assert_equal Gem::Source.new(Gem::URI("https://rubygemsserver.com/")), set.source
end
def test_initialize_uri
- set = @DR::APISet.new @dep_uri
+ set = Gem::Resolver::APISet.new @dep_uri
- assert_equal URI("#{@gem_repo}info/"), set.dep_uri
- assert_equal URI("#{@gem_repo}"), set.uri
+ assert_equal Gem::URI("#{@gem_repo}info/"), set.dep_uri
+ assert_equal Gem::URI(@gem_repo.to_s), set.uri
end
def test_find_all
spec_fetcher
data = [
- { :name => 'a',
- :number => '1',
- :platform => 'ruby',
- :dependencies => [] },
+ { name: "a",
+ number: "1",
+ platform: "ruby",
+ dependencies: [] },
]
@fetcher.data["#{@dep_uri}a"] = "---\n1 "
- set = @DR::APISet.new @dep_uri
+ set = Gem::Resolver::APISet.new @dep_uri
- a_dep = @DR::DependencyRequest.new dep('a'), nil
+ a_dep = Gem::Resolver::DependencyRequest.new dep("a"), nil
expected = [
- @DR::APISpecification.new(set, data.first),
+ Gem::Resolver::APISpecification.new(set, data.first),
]
assert_equal expected, set.find_all(a_dep)
@@ -59,26 +59,26 @@ class TestGemResolverAPISet < Gem::TestCase
spec_fetcher
data = [
- { :name => 'a',
- :number => '1',
- :platform => 'ruby',
- :dependencies => [] },
- { :name => 'a',
- :number => '2.a',
- :platform => 'ruby',
- :dependencies => [] },
+ { name: "a",
+ number: "1",
+ platform: "ruby",
+ dependencies: [] },
+ { name: "a",
+ number: "2.a",
+ platform: "ruby",
+ dependencies: [] },
]
@fetcher.data["#{@dep_uri}a"] = "---\n1\n2.a"
- set = @DR::APISet.new @dep_uri
+ set = Gem::Resolver::APISet.new @dep_uri
set.prerelease = true
- a_dep = @DR::DependencyRequest.new dep('a'), nil
+ a_dep = Gem::Resolver::DependencyRequest.new dep("a"), nil
expected = [
- @DR::APISpecification.new(set, data.first),
- @DR::APISpecification.new(set, data.last),
+ Gem::Resolver::APISpecification.new(set, data.first),
+ Gem::Resolver::APISpecification.new(set, data.last),
]
assert_equal expected, set.find_all(a_dep)
@@ -88,22 +88,22 @@ class TestGemResolverAPISet < Gem::TestCase
spec_fetcher
data = [
- { :name => 'a',
- :number => '1',
- :platform => 'ruby',
- :dependencies => [] },
+ { name: "a",
+ number: "1",
+ platform: "ruby",
+ dependencies: [] },
]
@fetcher.data["#{@dep_uri}a"] = "---\n1 "
- set = @DR::APISet.new @dep_uri
+ set = Gem::Resolver::APISet.new @dep_uri
- a_dep = @DR::DependencyRequest.new dep('a'), nil
+ a_dep = Gem::Resolver::DependencyRequest.new dep("a"), nil
set.prefetch [a_dep]
expected = [
- @DR::APISpecification.new(set, data.first),
+ Gem::Resolver::APISpecification.new(set, data.first),
]
assert_equal expected, set.find_all(a_dep)
@@ -112,10 +112,10 @@ class TestGemResolverAPISet < Gem::TestCase
end
def test_find_all_local
- set = @DR::APISet.new @dep_uri
+ set = Gem::Resolver::APISet.new @dep_uri
set.remote = false
- a_dep = @DR::DependencyRequest.new dep('a'), nil
+ a_dep = Gem::Resolver::DependencyRequest.new dep("a"), nil
assert_empty set.find_all(a_dep)
end
@@ -125,9 +125,9 @@ class TestGemResolverAPISet < Gem::TestCase
@fetcher.data["#{@dep_uri}a"] = "---"
- set = @DR::APISet.new @dep_uri
+ set = Gem::Resolver::APISet.new @dep_uri
- a_dep = @DR::DependencyRequest.new dep('a'), nil
+ a_dep = Gem::Resolver::DependencyRequest.new dep("a"), nil
assert_empty set.find_all(a_dep)
@@ -142,14 +142,14 @@ class TestGemResolverAPISet < Gem::TestCase
@fetcher.data["#{@dep_uri}a"] = "---\n1 \n"
@fetcher.data["#{@dep_uri}b"] = "---"
- set = @DR::APISet.new @dep_uri
+ set = Gem::Resolver::APISet.new @dep_uri
- a_dep = @DR::DependencyRequest.new dep('a'), nil
- b_dep = @DR::DependencyRequest.new dep('b'), nil
+ a_dep = Gem::Resolver::DependencyRequest.new dep("a"), nil
+ b_dep = Gem::Resolver::DependencyRequest.new dep("b"), nil
set.prefetch [a_dep, b_dep]
- assert_equal %w[a-1], set.find_all(a_dep).map {|s| s.full_name }
+ assert_equal %w[a-1], set.find_all(a_dep).map(&:full_name)
assert_empty set.find_all(b_dep)
end
@@ -158,10 +158,10 @@ class TestGemResolverAPISet < Gem::TestCase
@fetcher.data["#{@dep_uri}a"] = "---\n1 \n"
- set = @DR::APISet.new @dep_uri
+ set = Gem::Resolver::APISet.new @dep_uri
- a_dep = @DR::DependencyRequest.new dep('a'), nil
- b_dep = @DR::DependencyRequest.new dep('b'), nil
+ a_dep = Gem::Resolver::DependencyRequest.new dep("a"), nil
+ b_dep = Gem::Resolver::DependencyRequest.new dep("b"), nil
set.prefetch [a_dep]
@@ -177,10 +177,10 @@ class TestGemResolverAPISet < Gem::TestCase
@fetcher.data["#{@dep_uri}a"] = "---\n1 \n"
@fetcher.data["#{@dep_uri}b"] = "---"
- set = @DR::APISet.new @dep_uri
+ set = Gem::Resolver::APISet.new @dep_uri
- a_dep = @DR::DependencyRequest.new dep('a'), nil
- b_dep = @DR::DependencyRequest.new dep('b'), nil
+ a_dep = Gem::Resolver::DependencyRequest.new dep("a"), nil
+ b_dep = Gem::Resolver::DependencyRequest.new dep("b"), nil
set.prefetch [a_dep, b_dep]
@@ -196,11 +196,11 @@ class TestGemResolverAPISet < Gem::TestCase
@fetcher.data["#{@dep_uri}a"] = "---\n1 \n"
@fetcher.data["#{@dep_uri}b"] = "---"
- set = @DR::APISet.new @dep_uri
+ set = Gem::Resolver::APISet.new @dep_uri
set.remote = false
- a_dep = @DR::DependencyRequest.new dep('a'), nil
- b_dep = @DR::DependencyRequest.new dep('b'), nil
+ a_dep = Gem::Resolver::DependencyRequest.new dep("a"), nil
+ b_dep = Gem::Resolver::DependencyRequest.new dep("b"), nil
set.prefetch [a_dep, b_dep]
diff --git a/test/rubygems/test_gem_resolver_api_specification.rb b/test/rubygems/test_gem_resolver_api_specification.rb
index 3f9b81868f..2119d73478 100644
--- a/test/rubygems/test_gem_resolver_api_specification.rb
+++ b/test/rubygems/test_gem_resolver_api_specification.rb
@@ -1,28 +1,29 @@
# frozen_string_literal: true
-require_relative 'helper'
+
+require_relative "helper"
class TestGemResolverAPISpecification < Gem::TestCase
def test_initialize
set = Gem::Resolver::APISet.new
data = {
- :name => 'rails',
- :number => '3.0.3',
- :platform => Gem::Platform.local.to_s,
- :dependencies => [
- ['bundler', '~> 1.0'],
- ['railties', '= 3.0.3'],
+ name: "rails",
+ number: "3.0.3",
+ platform: Gem::Platform.local.to_s,
+ dependencies: [
+ ["bundler", "~> 1.0"],
+ ["railties", "= 3.0.3"],
],
}
spec = Gem::Resolver::APISpecification.new set, data
- assert_equal 'rails', spec.name
- assert_equal Gem::Version.new('3.0.3'), spec.version
+ assert_equal "rails", spec.name
+ assert_equal Gem::Version.new("3.0.3"), spec.version
assert_equal Gem::Platform.local, spec.platform
expected = [
- Gem::Dependency.new('bundler', '~> 1.0'),
- Gem::Dependency.new('railties', '= 3.0.3'),
+ Gem::Dependency.new("bundler", "~> 1.0"),
+ Gem::Dependency.new("railties", "= 3.0.3"),
]
assert_equal expected, spec.dependencies
@@ -30,26 +31,26 @@ class TestGemResolverAPISpecification < Gem::TestCase
def test_fetch_development_dependencies
specs = spec_fetcher do |fetcher|
- fetcher.spec 'rails', '3.0.3' do |s|
- s.add_runtime_dependency 'bundler', '~> 1.0'
- s.add_runtime_dependency 'railties', '= 3.0.3'
- s.add_development_dependency 'a', '= 1'
+ fetcher.spec "rails", "3.0.3" do |s|
+ s.add_runtime_dependency "bundler", "~> 1.0"
+ s.add_runtime_dependency "railties", "= 3.0.3"
+ s.add_development_dependency "a", "= 1"
end
end
- rails = specs['rails-3.0.3']
+ rails = specs["rails-3.0.3"]
- repo = @gem_repo + 'info'
+ repo = @gem_repo + "info"
set = Gem::Resolver::APISet.new repo
data = {
- :name => 'rails',
- :number => '3.0.3',
- :platform => 'ruby',
- :dependencies => [
- ['bundler', '~> 1.0'],
- ['railties', '= 3.0.3'],
+ name: "rails",
+ number: "3.0.3",
+ platform: "ruby",
+ dependencies: [
+ ["bundler", "~> 1.0"],
+ ["railties", "= 3.0.3"],
],
}
@@ -60,9 +61,9 @@ class TestGemResolverAPISpecification < Gem::TestCase
spec.fetch_development_dependencies
expected = [
- Gem::Dependency.new('bundler', '~> 1.0'),
- Gem::Dependency.new('railties', '= 3.0.3'),
- Gem::Dependency.new('a', '= 1', :development),
+ Gem::Dependency.new("bundler", "~> 1.0"),
+ Gem::Dependency.new("railties", "= 3.0.3"),
+ Gem::Dependency.new("a", "= 1", :development),
]
assert_equal expected, spec.dependencies
@@ -71,10 +72,10 @@ class TestGemResolverAPISpecification < Gem::TestCase
def test_installable_platform_eh
set = Gem::Resolver::APISet.new
data = {
- :name => 'a',
- :number => '1',
- :platform => 'ruby',
- :dependencies => [],
+ name: "a",
+ number: "1",
+ platform: "ruby",
+ dependencies: [],
}
a_spec = Gem::Resolver::APISpecification.new set, data
@@ -82,10 +83,10 @@ class TestGemResolverAPISpecification < Gem::TestCase
assert a_spec.installable_platform?
data = {
- :name => 'b',
- :number => '1',
- :platform => 'cpu-other_platform-1',
- :dependencies => [],
+ name: "b",
+ number: "1",
+ platform: "cpu-other_platform-1",
+ dependencies: [],
}
b_spec = Gem::Resolver::APISpecification.new set, data
@@ -93,10 +94,10 @@ class TestGemResolverAPISpecification < Gem::TestCase
refute b_spec.installable_platform?
data = {
- :name => 'c',
- :number => '1',
- :platform => Gem::Platform.local.to_s,
- :dependencies => [],
+ name: "c",
+ number: "1",
+ platform: Gem::Platform.local.to_s,
+ dependencies: [],
}
c_spec = Gem::Resolver::APISpecification.new set, data
@@ -107,10 +108,10 @@ class TestGemResolverAPISpecification < Gem::TestCase
def test_source
set = Gem::Resolver::APISet.new
data = {
- :name => 'a',
- :number => '1',
- :platform => 'ruby',
- :dependencies => [],
+ name: "a",
+ number: "1",
+ platform: "ruby",
+ dependencies: [],
}
api_spec = Gem::Resolver::APISpecification.new set, data
@@ -120,16 +121,16 @@ class TestGemResolverAPISpecification < Gem::TestCase
def test_spec
spec_fetcher do |fetcher|
- fetcher.spec 'a', 1
+ fetcher.spec "a", 1
end
- dep_uri = URI(@gem_repo) + 'info'
+ dep_uri = Gem::URI(@gem_repo) + "info"
set = Gem::Resolver::APISet.new dep_uri
data = {
- :name => 'a',
- :number => '1',
- :platform => 'ruby',
- :dependencies => [],
+ name: "a",
+ number: "1",
+ platform: "ruby",
+ dependencies: [],
}
api_spec = Gem::Resolver::APISpecification.new set, data
@@ -137,23 +138,23 @@ class TestGemResolverAPISpecification < Gem::TestCase
spec = api_spec.spec
assert_kind_of Gem::Specification, spec
- assert_equal 'a-1', spec.full_name
+ assert_equal "a-1", spec.full_name
end
def test_spec_jruby_platform
spec_fetcher do |fetcher|
- fetcher.gem 'j', 1 do |spec|
- spec.platform = 'jruby'
+ fetcher.gem "j", 1 do |spec|
+ spec.platform = "jruby"
end
end
- dep_uri = URI(@gem_repo) + 'info'
+ dep_uri = Gem::URI(@gem_repo) + "info"
set = Gem::Resolver::APISet.new dep_uri
data = {
- :name => 'j',
- :number => '1',
- :platform => 'jruby',
- :dependencies => [],
+ name: "j",
+ number: "1",
+ platform: "jruby",
+ dependencies: [],
}
api_spec = Gem::Resolver::APISpecification.new set, data
@@ -161,6 +162,6 @@ class TestGemResolverAPISpecification < Gem::TestCase
spec = api_spec.spec
assert_kind_of Gem::Specification, spec
- assert_equal 'j-1-java', spec.full_name
+ assert_equal "j-1-java", spec.full_name
end
end
diff --git a/test/rubygems/test_gem_resolver_best_set.rb b/test/rubygems/test_gem_resolver_best_set.rb
index 0e279d16a8..02f542efc0 100644
--- a/test/rubygems/test_gem_resolver_best_set.rb
+++ b/test/rubygems/test_gem_resolver_best_set.rb
@@ -1,70 +1,49 @@
# frozen_string_literal: true
-require_relative 'helper'
-class TestGemResolverBestSet < Gem::TestCase
- def setup
- super
-
- @DR = Gem::Resolver
- end
+require_relative "helper"
+class TestGemResolverBestSet < Gem::TestCase
def test_initialize
- set = @DR::BestSet.new
+ set = Gem::Resolver::BestSet.new
assert_empty set.sets
end
- def test_find_all_index
+ def test_find_all
spec_fetcher do |fetcher|
- fetcher.spec 'a', 1
- fetcher.spec 'a', 2
- fetcher.spec 'b', 1
+ fetcher.spec "a", 1
end
- set = @DR::BestSet.new
-
- dependency = dep 'a', '~> 1'
+ api_uri = Gem::URI "#{@gem_repo}info/"
- req = @DR::DependencyRequest.new dependency, nil
+ @fetcher.data["#{api_uri}a"] = "---\n1 "
- found = set.find_all req
-
- assert_equal %w[a-1], found.map {|s| s.full_name }
- end
-
- def test_find_all_fallback
- spec_fetcher do |fetcher|
- fetcher.spec 'a', 1
- end
-
- set = @DR::BestSet.new
-
- api_uri = URI(@gem_repo)
+ set = Gem::Resolver::BestSet.new
set.sets << Gem::Resolver::APISet.new(api_uri)
- dependency = dep 'a', '~> 1'
+ dependency = dep "a", "~> 1"
- req = @DR::DependencyRequest.new dependency, nil
+ req = Gem::Resolver::DependencyRequest.new dependency, nil
found = set.find_all req
- assert_equal %w[a-1], found.map {|s| s.full_name }
+ assert_equal %w[a-1], found.map(&:full_name)
end
def test_find_all_local
spec_fetcher do |fetcher|
- fetcher.spec 'a', 1
- fetcher.spec 'a', 2
- fetcher.spec 'b', 1
+ fetcher.spec "a", 1
+ fetcher.spec "a", 2
+ fetcher.spec "b", 1
end
- set = @DR::BestSet.new
+ set = Gem::Resolver::BestSet.new
set.remote = false
- dependency = dep 'a', '~> 1'
+ dependency = dep "a", "~> 1"
- req = @DR::DependencyRequest.new dependency, nil
+ req = Gem::Resolver::DependencyRequest.new dependency, nil
found = set.find_all req
@@ -73,10 +52,10 @@ class TestGemResolverBestSet < Gem::TestCase
def test_prefetch
spec_fetcher do |fetcher|
- fetcher.spec 'a', 1
+ fetcher.spec "a", 1
end
- set = @DR::BestSet.new
+ set = Gem::Resolver::BestSet.new
set.prefetch []
@@ -85,74 +64,14 @@ class TestGemResolverBestSet < Gem::TestCase
def test_prefetch_local
spec_fetcher do |fetcher|
- fetcher.spec 'a', 1
+ fetcher.spec "a", 1
end
- set = @DR::BestSet.new
+ set = Gem::Resolver::BestSet.new
set.remote = false
set.prefetch []
assert_empty set.sets
end
-
- def test_replace_failed_api_set
- set = @DR::BestSet.new
-
- api_uri = URI(@gem_repo) + './info/'
- api_set = Gem::Resolver::APISet.new api_uri
-
- set.sets << api_set
-
- error_uri = api_uri + 'a'
-
- error = Gem::RemoteFetcher::FetchError.new 'bogus', error_uri
-
- set.replace_failed_api_set error
-
- assert_equal 1, set.sets.size
-
- refute_includes set.sets, api_set
-
- assert_kind_of Gem::Resolver::IndexSet, set.sets.first
- end
-
- def test_replace_failed_api_set_no_api_set
- set = @DR::BestSet.new
-
- index_set = Gem::Resolver::IndexSet.new Gem::Source.new @gem_repo
-
- set.sets << index_set
-
- error = Gem::RemoteFetcher::FetchError.new 'bogus', @gem_repo
-
- e = assert_raise Gem::RemoteFetcher::FetchError do
- set.replace_failed_api_set error
- end
-
- assert_equal error, e
- end
-
- def test_replace_failed_api_set_uri_with_credentials
- set = @DR::BestSet.new
-
- api_uri = URI(@gem_repo) + './info/'
- api_uri.user = 'user'
- api_uri.password = 'pass'
- api_set = Gem::Resolver::APISet.new api_uri
-
- set.sets << api_set
-
- error_uri = api_uri + 'a'
-
- error = Gem::RemoteFetcher::FetchError.new 'bogus', error_uri
-
- set.replace_failed_api_set error
-
- assert_equal 1, set.sets.size
-
- refute_includes set.sets, api_set
-
- assert_kind_of Gem::Resolver::IndexSet, set.sets.first
- end
end
diff --git a/test/rubygems/test_gem_resolver_composed_set.rb b/test/rubygems/test_gem_resolver_composed_set.rb
index 405753a373..5a53000ec7 100644
--- a/test/rubygems/test_gem_resolver_composed_set.rb
+++ b/test/rubygems/test_gem_resolver_composed_set.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
-require_relative 'helper'
+
+require_relative "helper"
class TestGemResolverComposedSet < Gem::TestCase
def test_errors
diff --git a/test/rubygems/test_gem_resolver_conflict.rb b/test/rubygems/test_gem_resolver_conflict.rb
index 1d46e69c3f..5696ff266d 100644
--- a/test/rubygems/test_gem_resolver_conflict.rb
+++ b/test/rubygems/test_gem_resolver_conflict.rb
@@ -1,16 +1,17 @@
# frozen_string_literal: true
-require_relative 'helper'
+
+require_relative "helper"
class TestGemResolverConflict < Gem::TestCase
def test_explanation
root =
- dependency_request dep('net-ssh', '>= 2.0.13'), 'rye', '0.9.8'
+ dependency_request dep("net-ssh", ">= 2.0.13"), "rye", "0.9.8"
child =
- dependency_request dep('net-ssh', '>= 2.6.5'), 'net-ssh', '2.2.2', root
+ dependency_request dep("net-ssh", ">= 2.6.5"), "net-ssh", "2.2.2", root
- dep = Gem::Resolver::DependencyRequest.new dep('net-ssh', '>= 2.0.13'), nil
+ dep = Gem::Resolver::DependencyRequest.new dep("net-ssh", ">= 2.0.13"), nil
- spec = util_spec 'net-ssh', '2.2.2'
+ spec = util_spec "net-ssh", "2.2.2"
active =
Gem::Resolver::ActivationRequest.new spec, dep
@@ -35,16 +36,14 @@ class TestGemResolverConflict < Gem::TestCase
end
def test_explanation_user_request
- @DR = Gem::Resolver
-
- spec = util_spec 'a', 2
+ spec = util_spec "a", 2
- a1_req = @DR::DependencyRequest.new dep('a', '= 1'), nil
- a2_req = @DR::DependencyRequest.new dep('a', '= 2'), nil
+ a1_req = Gem::Resolver::DependencyRequest.new dep("a", "= 1"), nil
+ a2_req = Gem::Resolver::DependencyRequest.new dep("a", "= 2"), nil
- activated = @DR::ActivationRequest.new spec, a2_req
+ activated = Gem::Resolver::ActivationRequest.new spec, a2_req
- conflict = @DR::Conflict.new a1_req, activated
+ conflict = Gem::Resolver::Conflict.new a1_req, activated
expected = <<-EXPECTED
Activated a-2
@@ -63,17 +62,17 @@ class TestGemResolverConflict < Gem::TestCase
def test_request_path
root =
- dependency_request dep('net-ssh', '>= 2.0.13'), 'rye', '0.9.8'
+ dependency_request dep("net-ssh", ">= 2.0.13"), "rye", "0.9.8"
child =
- dependency_request dep('other', '>= 1.0'), 'net-ssh', '2.2.2', root
+ dependency_request dep("other", ">= 1.0"), "net-ssh", "2.2.2", root
conflict =
Gem::Resolver::Conflict.new nil, nil
expected = [
- 'net-ssh (>= 2.0.13), 2.2.2 activated',
- 'rye (= 0.9.8), 0.9.8 activated',
+ "net-ssh (>= 2.0.13), 2.2.2 activated",
+ "rye (= 0.9.8), 0.9.8 activated",
]
assert_equal expected, conflict.request_path(child.requester)
diff --git a/test/rubygems/test_gem_resolver_dependency_request.rb b/test/rubygems/test_gem_resolver_dependency_request.rb
index cea0a7952d..3e14771da8 100644
--- a/test/rubygems/test_gem_resolver_dependency_request.rb
+++ b/test/rubygems/test_gem_resolver_dependency_request.rb
@@ -1,81 +1,76 @@
# frozen_string_literal: true
-require_relative 'helper'
-class TestGemResolverDependencyRequest < Gem::TestCase
- def setup
- super
-
- @DR = Gem::Resolver::DependencyRequest
- end
+require_relative "helper"
+class TestGemResolverDependencyRequest < Gem::TestCase
def test_development_eh
- a_dep = dep 'a', '>= 1'
+ a_dep = dep "a", ">= 1"
- a_dep_req = @DR.new a_dep, nil
+ a_dep_req = Gem::Resolver::DependencyRequest.new a_dep, nil
refute a_dep_req.development?
- b_dep = dep 'b', '>= 1', :development
+ b_dep = dep "b", ">= 1", :development
- b_dep_req = @DR.new b_dep, nil
+ b_dep_req = Gem::Resolver::DependencyRequest.new b_dep, nil
assert b_dep_req.development?
end
def test_match_eh
- spec = util_spec 'a', 1
- dependency = dep 'a', '>= 1'
+ spec = util_spec "a", 1
+ dependency = dep "a", ">= 1"
- dr = @DR.new dependency, nil
+ dr = Gem::Resolver::DependencyRequest.new dependency, nil
assert dr.match? spec
end
def test_match_eh_prerelease
- spec = util_spec 'a', '1.a'
+ spec = util_spec "a", "1.a"
- a_dep = dep 'a', '>= 1'
- a_dr = @DR.new a_dep, nil
+ a_dep = dep "a", ">= 1"
+ a_dr = Gem::Resolver::DependencyRequest.new a_dep, nil
refute a_dr.match? spec
- a_pre_dep = dep 'a', '>= 1.a'
- a_pre_dr = @DR.new a_pre_dep, nil
+ a_pre_dep = dep "a", ">= 1.a"
+ a_pre_dr = Gem::Resolver::DependencyRequest.new a_pre_dep, nil
assert a_pre_dr.match? spec
end
def test_match_eh_prerelease_allow_prerelease
- spec = util_spec 'a', '2.a'
+ spec = util_spec "a", "2.a"
- a_dep = dep 'a', '>= 1'
- a_dr = @DR.new a_dep, nil
+ a_dep = dep "a", ">= 1"
+ a_dr = Gem::Resolver::DependencyRequest.new a_dep, nil
assert a_dr.match? spec, true
end
def test_matches_spec_eh
- spec = util_spec 'a', 1
- dependency = dep 'a', '>= 1'
+ spec = util_spec "a", 1
+ dependency = dep "a", ">= 1"
- dr = @DR.new dependency, nil
+ dr = Gem::Resolver::DependencyRequest.new dependency, nil
assert dr.matches_spec? spec
end
def test_matches_spec_eh_prerelease
- spec = util_spec 'a', '1.a'
+ spec = util_spec "a", "1.a"
- dependency = dep 'a', '>= 0'
- dr = @DR.new dependency, nil
+ dependency = dep "a", ">= 0"
+ dr = Gem::Resolver::DependencyRequest.new dependency, nil
assert dr.matches_spec? spec
end
def test_requirement
- dependency = dep 'a', '>= 1'
+ dependency = dep "a", ">= 1"
- dr = @DR.new dependency, nil
+ dr = Gem::Resolver::DependencyRequest.new dependency, nil
assert_equal dependency, dr.dependency
end
diff --git a/test/rubygems/test_gem_resolver_git_set.rb b/test/rubygems/test_gem_resolver_git_set.rb
index 145cd6c7df..90749d712c 100644
--- a/test/rubygems/test_gem_resolver_git_set.rb
+++ b/test/rubygems/test_gem_resolver_git_set.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
-require_relative 'helper'
+
+require_relative "helper"
class TestGemResolverGitSet < Gem::TestCase
def setup
@@ -13,9 +14,9 @@ class TestGemResolverGitSet < Gem::TestCase
def test_add_git_gem
name, version, repository, = git_gem
- @set.add_git_gem name, repository, 'master', false
+ @set.add_git_gem name, repository, nil, false
- dependency = dep 'a'
+ dependency = dep "a"
specs = @set.find_all dependency
@@ -27,9 +28,9 @@ class TestGemResolverGitSet < Gem::TestCase
def test_add_git_gem_submodules
name, _, repository, = git_gem
- @set.add_git_gem name, repository, 'master', true
+ @set.add_git_gem name, repository, nil, true
- dependency = dep 'a'
+ dependency = dep "a"
refute_empty @set.find_all dependency
@@ -41,7 +42,7 @@ class TestGemResolverGitSet < Gem::TestCase
@set.add_git_spec name, version, repository, revision, true
- dependency = dep 'a'
+ dependency = dep "a"
specs = @set.find_all dependency
@@ -57,9 +58,9 @@ class TestGemResolverGitSet < Gem::TestCase
def test_find_all
name, _, repository, = git_gem
- @set.add_git_gem name, repository, 'master', false
+ @set.add_git_gem name, repository, nil, false
- dependency = dep 'a', '~> 1.0'
+ dependency = dep "a", "~> 1.0"
req = Gem::Resolver::DependencyRequest.new dependency, nil
@reqs.add req
@@ -67,16 +68,16 @@ class TestGemResolverGitSet < Gem::TestCase
found = @set.find_all dependency
- assert_equal [@set.specs['a']], found
+ assert_equal [@set.specs["a"]], found
end
def test_find_all_local
name, _, repository, = git_gem
- @set.add_git_gem name, repository, 'master', false
+ @set.add_git_gem name, repository, nil, false
@set.remote = false
- dependency = dep 'a', '~> 1.0'
+ dependency = dep "a", "~> 1.0"
req = Gem::Resolver::DependencyRequest.new dependency, nil
@reqs.add req
@@ -86,11 +87,11 @@ class TestGemResolverGitSet < Gem::TestCase
end
def test_find_all_prerelease
- name, _, repository, = git_gem 'a', '1.a'
+ name, _, repository, = git_gem "a", "1.a"
- @set.add_git_gem name, repository, 'master', false
+ @set.add_git_gem name, repository, nil, false
- dependency = dep 'a', '>= 0'
+ dependency = dep "a", ">= 0"
req = Gem::Resolver::DependencyRequest.new dependency, nil
@reqs.add req
@@ -100,7 +101,7 @@ class TestGemResolverGitSet < Gem::TestCase
assert_empty found
- dependency = dep 'a', '>= 0.a'
+ dependency = dep "a", ">= 0.a"
req = Gem::Resolver::DependencyRequest.new dependency, nil
@reqs.add req
@@ -122,7 +123,7 @@ class TestGemResolverGitSet < Gem::TestCase
def test_prefetch
name, _, repository, = git_gem
- @set.add_git_gem name, repository, 'master', false
+ @set.add_git_gem name, repository, nil, false
dependency = dep name
req = Gem::Resolver::DependencyRequest.new dependency, nil
@@ -136,7 +137,7 @@ class TestGemResolverGitSet < Gem::TestCase
def test_prefetch_cache
name, _, repository, = git_gem
- @set.add_git_gem name, repository, 'master', false
+ @set.add_git_gem name, repository, nil, false
dependency = dep name
req = Gem::Resolver::DependencyRequest.new dependency, nil
@@ -154,21 +155,21 @@ class TestGemResolverGitSet < Gem::TestCase
def test_prefetch_filter
name, _, repository, = git_gem
- @set.add_git_gem name, repository, 'master', false
+ @set.add_git_gem name, repository, nil, false
- dependency = dep 'b'
+ dependency = dep "b"
req = Gem::Resolver::DependencyRequest.new dependency, nil
@reqs.add req
@set.prefetch @reqs
- refute_empty @set.specs, 'the git source does not filter'
+ refute_empty @set.specs, "the git source does not filter"
end
def test_prefetch_root_dir
name, _, repository, = git_gem
- @set.add_git_gem name, repository, 'master', false
+ @set.add_git_gem name, repository, nil, false
dependency = dep name
req = Gem::Resolver::DependencyRequest.new dependency, nil
diff --git a/test/rubygems/test_gem_resolver_git_specification.rb b/test/rubygems/test_gem_resolver_git_specification.rb
index 857452c159..621333d3bf 100644
--- a/test/rubygems/test_gem_resolver_git_specification.rb
+++ b/test/rubygems/test_gem_resolver_git_specification.rb
@@ -1,13 +1,14 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/installer'
+
+require_relative "helper"
+require "rubygems/installer"
class TestGemResolverGitSpecification < Gem::TestCase
def setup
super
@set = Gem::Resolver::GitSet.new
- @spec = Gem::Specification.new 'a', 1
+ @spec = Gem::Specification.new "a", 1
end
def test_equals2
@@ -15,7 +16,7 @@ class TestGemResolverGitSpecification < Gem::TestCase
assert_equal g_spec_a, g_spec_a
- spec_b = Gem::Specification.new 'b', 1
+ spec_b = Gem::Specification.new "b", 1
g_spec_b = Gem::Resolver::GitSpecification.new @set, spec_b
refute_equal g_spec_a, g_spec_b
@@ -28,17 +29,18 @@ class TestGemResolverGitSpecification < Gem::TestCase
i_set = Gem::Resolver::IndexSet.new
source = Gem::Source.new @gem_repo
i_spec = Gem::Resolver::IndexSpecification.new(
- i_set, 'a', v(1), source, Gem::Platform::RUBY)
+ i_set, "a", v(1), source, Gem::Platform::RUBY
+ )
refute_equal g_spec_a, i_spec
end
def test_add_dependency
- git_gem 'a', 1
+ git_gem "a", 1
git_spec = Gem::Resolver::GitSpecification.new @set, @spec
- b_dep = dep 'b'
+ b_dep = dep "b"
git_spec.add_dependency b_dep
@@ -46,7 +48,7 @@ class TestGemResolverGitSpecification < Gem::TestCase
end
def test_install
- git_gem 'a', 1
+ git_gem "a", 1
git_spec = Gem::Resolver::GitSpecification.new @set, @spec
@@ -63,28 +65,28 @@ class TestGemResolverGitSpecification < Gem::TestCase
def test_install_extension
pend if Gem.java_platform?
- pend if /mswin/ =~ RUBY_PLATFORM && ENV.key?('GITHUB_ACTIONS') # not working from the beginning
- name, _, repository, = git_gem 'a', 1 do |s|
- s.extensions << 'ext/extconf.rb'
+ pend "terminates on mswin" if vc_windows? && ruby_repo?
+ name, _, repository, = git_gem "a", 1 do |s|
+ s.extensions << "ext/extconf.rb"
end
- Dir.chdir 'git/a' do
- FileUtils.mkdir_p 'ext/lib'
+ Dir.chdir "git/a" do
+ FileUtils.mkdir_p "ext/lib"
- File.open 'ext/extconf.rb', 'w' do |io|
+ File.open "ext/extconf.rb", "w" do |io|
io.puts 'require "mkmf"'
io.puts 'create_makefile "a"'
end
- FileUtils.touch 'ext/lib/b.rb'
+ FileUtils.touch "ext/lib/b.rb"
- system @git, 'add', 'ext/extconf.rb'
- system @git, 'add', 'ext/lib/b.rb'
+ system @git, "add", "ext/extconf.rb"
+ system @git, "add", "ext/lib/b.rb"
- system @git, 'commit', '--quiet', '-m', 'Add extension files'
+ system @git, "commit", "--quiet", "-m", "Add extension files"
end
- source = Gem::Source::Git.new name, repository, 'master', true
+ source = Gem::Source::Git.new name, repository, nil, true
spec = source.specs.first
@@ -92,11 +94,11 @@ class TestGemResolverGitSpecification < Gem::TestCase
git_spec.install({})
- assert_path_exist File.join git_spec.spec.extension_dir, 'b.rb'
+ assert_path_exist File.join git_spec.spec.extension_dir, "b.rb"
end
def test_install_installed
- git_gem 'a', 1
+ git_gem "a", 1
git_spec = Gem::Resolver::GitSpecification.new @set, @spec
diff --git a/test/rubygems/test_gem_resolver_index_set.rb b/test/rubygems/test_gem_resolver_index_set.rb
index ddae0c2b82..8ff1acbf1e 100644
--- a/test/rubygems/test_gem_resolver_index_set.rb
+++ b/test/rubygems/test_gem_resolver_index_set.rb
@@ -1,15 +1,10 @@
# frozen_string_literal: true
-require_relative 'helper'
-class TestGemResolverIndexSet < Gem::TestCase
- def setup
- super
-
- @DR = Gem::Resolver
- end
+require_relative "helper"
+class TestGemResolverIndexSet < Gem::TestCase
def test_initialize
- set = @DR::IndexSet.new
+ set = Gem::Resolver::IndexSet.new
fetcher = set.instance_variable_get :@f
@@ -17,7 +12,7 @@ class TestGemResolverIndexSet < Gem::TestCase
end
def test_initialize_source
- set = @DR::IndexSet.new 'http://alternate.example'
+ set = Gem::Resolver::IndexSet.new "http://alternate.example"
fetcher = set.instance_variable_get :@f
@@ -28,49 +23,49 @@ class TestGemResolverIndexSet < Gem::TestCase
def test_find_all
spec_fetcher do |fetcher|
- fetcher.spec 'a', 1
- fetcher.spec 'a', 2
- fetcher.spec 'b', 1
+ fetcher.spec "a", 1
+ fetcher.spec "a", 2
+ fetcher.spec "b", 1
end
- set = @DR::IndexSet.new
+ set = Gem::Resolver::IndexSet.new
- dependency = dep 'a', '~> 1'
+ dependency = dep "a", "~> 1"
- req = @DR::DependencyRequest.new dependency, nil
+ req = Gem::Resolver::DependencyRequest.new dependency, nil
found = set.find_all req
- assert_equal %w[a-1], found.map {|s| s.full_name }
+ assert_equal %w[a-1], found.map(&:full_name)
end
def test_find_all_local
spec_fetcher do |fetcher|
- fetcher.spec 'a', 1
- fetcher.spec 'a', 2
- fetcher.spec 'b', 1
+ fetcher.spec "a", 1
+ fetcher.spec "a", 2
+ fetcher.spec "b", 1
end
- set = @DR::IndexSet.new
+ set = Gem::Resolver::IndexSet.new
set.remote = false
- dependency = dep 'a', '~> 1'
+ dependency = dep "a", "~> 1"
- req = @DR::DependencyRequest.new dependency, nil
+ req = Gem::Resolver::DependencyRequest.new dependency, nil
assert_empty set.find_all req
end
def test_find_all_prerelease
spec_fetcher do |fetcher|
- fetcher.spec 'a', '1.a'
+ fetcher.spec "a", "1.a"
end
- set = @DR::IndexSet.new
+ set = Gem::Resolver::IndexSet.new
- dependency = dep 'a'
+ dependency = dep "a"
- req = @DR::DependencyRequest.new dependency, nil
+ req = Gem::Resolver::DependencyRequest.new dependency, nil
found = set.find_all req
@@ -78,10 +73,10 @@ class TestGemResolverIndexSet < Gem::TestCase
dependency.prerelease = true
- req = @DR::DependencyRequest.new dependency, nil
+ req = Gem::Resolver::DependencyRequest.new dependency, nil
found = set.find_all req
- assert_equal %w[a-1.a], found.map {|s| s.full_name }
+ assert_equal %w[a-1.a], found.map(&:full_name)
end
end
diff --git a/test/rubygems/test_gem_resolver_index_specification.rb b/test/rubygems/test_gem_resolver_index_specification.rb
index ef9c17034e..ed9475f0cf 100644
--- a/test/rubygems/test_gem_resolver_index_specification.rb
+++ b/test/rubygems/test_gem_resolver_index_specification.rb
@@ -1,17 +1,19 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/available_set'
+
+require_relative "helper"
+require "rubygems/available_set"
class TestGemResolverIndexSpecification < Gem::TestCase
def test_initialize
set = Gem::Resolver::IndexSet.new
source = Gem::Source.new @gem_repo
- version = Gem::Version.new '3.0.3'
+ version = Gem::Version.new "3.0.3"
spec = Gem::Resolver::IndexSpecification.new(
- set, 'rails', version, source, Gem::Platform::RUBY)
+ set, "rails", version, source, Gem::Platform::RUBY
+ )
- assert_equal 'rails', spec.name
+ assert_equal "rails", spec.name
assert_equal version, spec.version
assert_equal Gem::Platform::RUBY, spec.platform
@@ -21,24 +23,26 @@ class TestGemResolverIndexSpecification < Gem::TestCase
def test_initialize_platform
set = Gem::Resolver::IndexSet.new
source = Gem::Source::Local.new
- version = Gem::Version.new '3.0.3'
+ version = Gem::Version.new "3.0.3"
spec = Gem::Resolver::IndexSpecification.new(
- set, 'rails', version, source, Gem::Platform.local)
+ set, "rails", version, source, Gem::Platform.local
+ )
- assert_equal Gem::Platform.local.to_s, spec.platform
+ assert_equal Gem::Platform.local, spec.platform
end
def test_install
spec_fetcher do |fetcher|
- fetcher.gem 'a', 2
+ fetcher.gem "a", 2
end
set = Gem::Resolver::IndexSet.new
source = Gem::Source.new @gem_repo
spec = Gem::Resolver::IndexSpecification.new(
- set, 'a', v(2), source, Gem::Platform::RUBY)
+ set, "a", v(2), source, Gem::Platform::RUBY
+ )
called = false
@@ -46,15 +50,15 @@ class TestGemResolverIndexSpecification < Gem::TestCase
called = installer
end
- assert_path_exist File.join @gemhome, 'specifications', 'a-2.gemspec'
+ assert_path_exist File.join @gemhome, "specifications", "a-2.gemspec"
assert_kind_of Gem::Installer, called
end
def test_spec
specs = spec_fetcher do |fetcher|
- fetcher.spec 'a', 2
- fetcher.spec 'a', 2 do |s|
+ fetcher.spec "a", 2
+ fetcher.spec "a", 2 do |s|
s.platform = Gem::Platform.local
end
end
@@ -64,7 +68,7 @@ class TestGemResolverIndexSpecification < Gem::TestCase
set = Gem::Resolver::IndexSet.new
i_spec = Gem::Resolver::IndexSpecification.new \
- set, 'a', version, source, Gem::Platform.local
+ set, "a", version, source, Gem::Platform.local
spec = i_spec.spec
@@ -72,7 +76,7 @@ class TestGemResolverIndexSpecification < Gem::TestCase
end
def test_spec_local
- a_2_p = util_spec 'a', 2 do |s|
+ a_2_p = util_spec "a", 2 do |s|
s.platform = Gem::Platform.local
end
@@ -83,7 +87,7 @@ class TestGemResolverIndexSpecification < Gem::TestCase
set.always_install << a_2_p
i_spec = Gem::Resolver::IndexSpecification.new \
- set, 'a', v(2), source, Gem::Platform.local
+ set, "a", v(2), source, Gem::Platform.local
spec = i_spec.spec
diff --git a/test/rubygems/test_gem_resolver_installed_specification.rb b/test/rubygems/test_gem_resolver_installed_specification.rb
index 0e5ea02fb9..5b10273b13 100644
--- a/test/rubygems/test_gem_resolver_installed_specification.rb
+++ b/test/rubygems/test_gem_resolver_installed_specification.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
-require_relative 'helper'
+
+require_relative "helper"
class TestGemResolverInstalledSpecification < Gem::TestCase
def setup
@@ -9,17 +10,17 @@ class TestGemResolverInstalledSpecification < Gem::TestCase
end
def test_initialize
- source_spec = util_spec 'a'
+ source_spec = util_spec "a"
spec = Gem::Resolver::InstalledSpecification.new @set, source_spec
- assert_equal 'a', spec.name
+ assert_equal "a", spec.name
assert_equal Gem::Version.new(2), spec.version
assert_equal Gem::Platform::RUBY, spec.platform
end
def test_install
- a = util_spec 'a'
+ a = util_spec "a"
spec = Gem::Resolver::InstalledSpecification.new @set, a
@@ -33,7 +34,7 @@ class TestGemResolverInstalledSpecification < Gem::TestCase
end
def test_installable_platform_eh
- b, b_gem = util_gem 'a', 1 do |s|
+ b, b_gem = util_gem "a", 1 do |s|
s.platform = Gem::Platform.new %w[cpu other_platform 1]
end
diff --git a/test/rubygems/test_gem_resolver_installer_set.rb b/test/rubygems/test_gem_resolver_installer_set.rb
index 928a16b9d3..202fe9d653 100644
--- a/test/rubygems/test_gem_resolver_installer_set.rb
+++ b/test/rubygems/test_gem_resolver_installer_set.rb
@@ -1,26 +1,27 @@
# frozen_string_literal: true
-require_relative 'helper'
+
+require_relative "helper"
class TestGemResolverInstallerSet < Gem::TestCase
def test_add_always_install
spec_fetcher do |fetcher|
- fetcher.download 'a', 1
- fetcher.download 'a', 2
+ fetcher.download "a", 1
+ fetcher.download "a", 2
end
- util_gem 'a', 1
+ util_gem "a", 1
set = Gem::Resolver::InstallerSet.new :both
- set.add_always_install dep('a')
+ set.add_always_install dep("a")
- assert_equal %w[a-2], set.always_install.map {|s| s.full_name }
+ assert_equal %w[a-2], set.always_install.map(&:full_name)
e = assert_raise Gem::UnsatisfiableDependencyError do
- set.add_always_install dep('b')
+ set.add_always_install dep("b")
end
- assert_equal dep('b'), e.dependency.dependency
+ assert_equal dep("b"), e.dependency.dependency
end
def test_add_always_install_errors
@@ -30,7 +31,7 @@ class TestGemResolverInstallerSet < Gem::TestCase
set = Gem::Resolver::InstallerSet.new :both
e = assert_raise Gem::UnsatisfiableDependencyError do
- set.add_always_install dep 'a'
+ set.add_always_install dep "a"
end
refute_empty e.errors
@@ -38,64 +39,96 @@ class TestGemResolverInstallerSet < Gem::TestCase
def test_add_always_install_platform
spec_fetcher do |fetcher|
- fetcher.download 'a', 1
- fetcher.download 'a', 2 do |s|
- s.platform = Gem::Platform.new 'x86-freebsd-9'
+ fetcher.download "a", 1
+ fetcher.download "a", 2 do |s|
+ s.platform = Gem::Platform.new "x86-freebsd-9"
end
end
set = Gem::Resolver::InstallerSet.new :both
- set.add_always_install dep('a')
+ set.add_always_install dep("a")
- assert_equal %w[a-1], set.always_install.map {|s| s.full_name }
+ assert_equal %w[a-1], set.always_install.map(&:full_name)
+ end
+
+ def test_add_always_install_platform_if_gem_platforms_modified_by_platform_flag
+ freebsd = Gem::Platform.new "x86-freebsd-9"
+
+ spec_fetcher do |fetcher|
+ fetcher.download "a", 1
+ fetcher.download "a", 1 do |s|
+ s.platform = freebsd
+ end
+ end
+
+ # equivalent to --platform=x86-freebsd-9
+ Gem.platforms << freebsd
+ set = Gem::Resolver::InstallerSet.new :both
+
+ set.add_always_install dep("a")
+
+ assert_equal %w[a-1-x86-freebsd-9], set.always_install.map(&:full_name)
+ end
+
+ def test_add_always_install_index_spec_platform
+ _, a_1_local_gem = util_gem "a", 1 do |s|
+ s.platform = Gem::Platform.local
+ end
+
+ FileUtils.mv a_1_local_gem, @tempdir
+
+ set = Gem::Resolver::InstallerSet.new :both
+ set.add_always_install dep("a")
+
+ assert_equal [Gem::Platform.local], set.always_install.map(&:platform)
end
def test_add_always_install_prerelease
spec_fetcher do |fetcher|
- fetcher.gem 'a', 1
- fetcher.gem 'a', '3.a'
+ fetcher.gem "a", 1
+ fetcher.gem "a", "3.a"
end
set = Gem::Resolver::InstallerSet.new :both
- set.add_always_install dep('a')
+ set.add_always_install dep("a")
- assert_equal %w[a-1], set.always_install.map {|s| s.full_name }
+ assert_equal %w[a-1], set.always_install.map(&:full_name)
end
def test_add_always_install_prerelease_github_problem
spec_fetcher do |fetcher|
- fetcher.gem 'a', 1
+ fetcher.gem "a", 1
end
# Github has an issue in which it will generate a misleading prerelease output in its RubyGems server API and
# returns a 0 version for the gem while it doesn't exist.
@fetcher.data["#{@gem_repo}prerelease_specs.#{Gem.marshal_version}.gz"] = util_gzip(Marshal.dump([
- Gem::NameTuple.new('a', Gem::Version.new(0), 'ruby'),
+ Gem::NameTuple.new("a", Gem::Version.new(0), "ruby"),
]))
set = Gem::Resolver::InstallerSet.new :both
- set.add_always_install dep('a')
+ set.add_always_install dep("a")
- assert_equal %w[a-1], set.always_install.map {|s| s.full_name }
+ assert_equal %w[a-1], set.always_install.map(&:full_name)
end
def test_add_always_install_prerelease_only
spec_fetcher do |fetcher|
- fetcher.gem 'a', '3.a'
+ fetcher.gem "a", "3.a"
end
set = Gem::Resolver::InstallerSet.new :both
assert_raise Gem::UnsatisfiableDependencyError do
- set.add_always_install dep('a')
+ set.add_always_install dep("a")
end
end
def test_add_local
- a_1, a_1_gem = util_gem 'a', 1
+ a_1, a_1_gem = util_gem "a", 1
a_1_source = Gem::Source::SpecificFile.new a_1_gem
@@ -108,9 +141,9 @@ class TestGemResolverInstallerSet < Gem::TestCase
FileUtils.rm a_1_gem
util_clear_gems
- req = Gem::Resolver::DependencyRequest.new dep('a'), nil
+ req = Gem::Resolver::DependencyRequest.new dep("a"), nil
- assert_equal %w[a-1], set.find_all(req).map {|spec| spec.full_name }
+ assert_equal %w[a-1], set.find_all(req).map(&:full_name)
end
def test_consider_local_eh
@@ -146,7 +179,7 @@ class TestGemResolverInstallerSet < Gem::TestCase
set.instance_variable_get(:@errors) << :a
- req = Gem::Resolver::DependencyRequest.new dep('a'), nil
+ req = Gem::Resolver::DependencyRequest.new dep("a"), nil
set.find_all req
@@ -155,42 +188,54 @@ class TestGemResolverInstallerSet < Gem::TestCase
def test_find_all_always_install
spec_fetcher do |fetcher|
- fetcher.download 'a', 2
+ fetcher.download "a", 2
end
- util_gem 'a', 1
+ util_gem "a", 1
set = Gem::Resolver::InstallerSet.new :both
- set.add_always_install dep 'a'
+ set.add_always_install dep "a"
- req = Gem::Resolver::DependencyRequest.new dep('a'), nil
+ req = Gem::Resolver::DependencyRequest.new dep("a"), nil
- assert_equal %w[a-2], set.find_all(req).map {|spec| spec.full_name }
+ assert_equal %w[a-2], set.find_all(req).map(&:full_name)
end
def test_find_all_prerelease
spec_fetcher do |fetcher|
- fetcher.download 'a', '1'
- fetcher.download 'a', '1.a'
+ fetcher.download "a", "1"
+ fetcher.download "a", "1.a"
end
set = Gem::Resolver::InstallerSet.new :both
- req = Gem::Resolver::DependencyRequest.new dep('a'), nil
+ req = Gem::Resolver::DependencyRequest.new dep("a"), nil
- assert_equal %w[a-1], set.find_all(req).map {|spec| spec.full_name }
+ assert_equal %w[a-1], set.find_all(req).map(&:full_name)
- req = Gem::Resolver::DependencyRequest.new dep('a', '>= 0.a'), nil
+ req = Gem::Resolver::DependencyRequest.new dep("a", ">= 0.a"), nil
assert_equal %w[a-1 a-1.a],
- set.find_all(req).map {|spec| spec.full_name }.sort
+ set.find_all(req).map(&:full_name).sort
+ end
+
+ def test_find_all_prerelease_dependencies_with_add_local
+ activesupport_7_1_0_alpha = util_spec "activesupport", "7.1.0.alpha"
+
+ install_gem activesupport_7_1_0_alpha
+
+ set = Gem::Resolver::InstallerSet.new :both
+
+ req = Gem::Resolver::DependencyRequest.new dep("activesupport", ">= 4.2.0"), nil
+
+ assert_equal %w[activesupport-7.1.0.alpha], set.find_all(req).map(&:full_name)
end
def test_load_spec
specs = spec_fetcher do |fetcher|
- fetcher.spec 'a', 2
- fetcher.spec 'a', 2 do |s|
+ fetcher.spec "a", 2
+ fetcher.spec "a", 2 do |s|
s.platform = Gem::Platform.local
end
end
@@ -200,7 +245,7 @@ class TestGemResolverInstallerSet < Gem::TestCase
set = Gem::Resolver::InstallerSet.new :remote
- spec = set.load_spec 'a', version, Gem::Platform.local, source
+ spec = set.load_spec "a", version, Gem::Platform.local, source
assert_equal specs["a-2-#{Gem::Platform.local}"].full_name, spec.full_name
end
@@ -210,7 +255,7 @@ class TestGemResolverInstallerSet < Gem::TestCase
def (set.remote_set).prefetch(_)
raise "called"
end
- assert_raise(RuntimeError){ set.prefetch(nil) }
+ assert_raise(RuntimeError) { set.prefetch(nil) }
set = Gem::Resolver::InstallerSet.new :local
def (set.remote_set).prefetch(_)
diff --git a/test/rubygems/test_gem_resolver_local_specification.rb b/test/rubygems/test_gem_resolver_local_specification.rb
index c11f736128..cefd761520 100644
--- a/test/rubygems/test_gem_resolver_local_specification.rb
+++ b/test/rubygems/test_gem_resolver_local_specification.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/available_set'
+
+require_relative "helper"
+require "rubygems/available_set"
class TestGemResolverLocalSpecification < Gem::TestCase
def setup
@@ -11,12 +12,12 @@ class TestGemResolverLocalSpecification < Gem::TestCase
def test_install
specs = spec_fetcher do |fetcher|
- fetcher.gem 'a', 2
+ fetcher.gem "a", 2
end
- source = Gem::Source::SpecificFile.new 'gems/a-2.gem'
+ source = Gem::Source::SpecificFile.new "gems/a-2.gem"
- spec = Gem::Resolver::LocalSpecification.new @set, specs['a-2'], source
+ spec = Gem::Resolver::LocalSpecification.new @set, specs["a-2"], source
called = false
@@ -24,13 +25,13 @@ class TestGemResolverLocalSpecification < Gem::TestCase
called = installer
end
- assert_path_exist File.join @gemhome, 'specifications', 'a-2.gemspec'
+ assert_path_exist File.join @gemhome, "specifications", "a-2.gemspec"
assert_kind_of Gem::Installer, called
end
def test_installable_platform_eh
- b, b_gem = util_gem 'a', 1 do |s|
+ b, b_gem = util_gem "a", 1 do |s|
s.platform = Gem::Platform.new %w[cpu other_platform 1]
end
diff --git a/test/rubygems/test_gem_resolver_lock_set.rb b/test/rubygems/test_gem_resolver_lock_set.rb
index dc7767a3f8..ebb64ef583 100644
--- a/test/rubygems/test_gem_resolver_lock_set.rb
+++ b/test/rubygems/test_gem_resolver_lock_set.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
-require_relative 'helper'
+
+require_relative "helper"
class TestGemResolverLockSet < Gem::TestCase
def setup
@@ -12,47 +13,47 @@ class TestGemResolverLockSet < Gem::TestCase
end
def test_add
- specs = @set.add 'a', '2', Gem::Platform::RUBY
+ specs = @set.add "a", "2", Gem::Platform::RUBY
spec = specs.first
- assert_equal %w[a-2], @set.specs.map {|t| t.full_name }
+ assert_equal %w[a-2], @set.specs.map(&:full_name)
assert_kind_of Gem::Resolver::LockSpecification, spec
assert_equal @set, spec.set
- assert_equal 'a', spec.name
+ assert_equal "a", spec.name
assert_equal v(2), spec.version
assert_equal Gem::Platform::RUBY, spec.platform
assert_equal @lock_source, spec.source
end
def test_find_all
- @set.add 'a', '1.a', Gem::Platform::RUBY
- @set.add 'a', '2', Gem::Platform::RUBY
- @set.add 'b', '2', Gem::Platform::RUBY
+ @set.add "a", "1.a", Gem::Platform::RUBY
+ @set.add "a", "2", Gem::Platform::RUBY
+ @set.add "b", "2", Gem::Platform::RUBY
- found = @set.find_all dep 'a'
+ found = @set.find_all dep "a"
- assert_equal %w[a-2], found.map {|s| s.full_name }
+ assert_equal %w[a-2], found.map(&:full_name)
- found = @set.find_all dep 'a', '>= 0.a'
+ found = @set.find_all dep "a", ">= 0.a"
- assert_equal %w[a-1.a a-2], found.map {|s| s.full_name }
+ assert_equal %w[a-1.a a-2], found.map(&:full_name)
end
def test_load_spec
spec_fetcher do |fetcher|
- fetcher.spec 'a', 2
+ fetcher.spec "a", 2
end
version = v(2)
- @set.add 'a', version, Gem::Platform::RUBY
+ @set.add "a", version, Gem::Platform::RUBY
- loaded = @set.load_spec 'a', version, Gem::Platform::RUBY, nil
+ loaded = @set.load_spec "a", version, Gem::Platform::RUBY, nil
assert_kind_of Gem::Specification, loaded
- assert_equal 'a-2', loaded.full_name
+ assert_equal "a-2", loaded.full_name
end
def test_prefetch
diff --git a/test/rubygems/test_gem_resolver_lock_specification.rb b/test/rubygems/test_gem_resolver_lock_specification.rb
index 46c8e5edd6..402f5d1509 100644
--- a/test/rubygems/test_gem_resolver_lock_specification.rb
+++ b/test/rubygems/test_gem_resolver_lock_specification.rb
@@ -1,22 +1,21 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/installer'
-require 'rubygems/resolver'
+
+require_relative "helper"
+require "rubygems/installer"
+require "rubygems/resolver"
class TestGemResolverLockSpecification < Gem::TestCase
def setup
super
- @LS = Gem::Resolver::LockSpecification
-
@source = Gem::Source.new @gem_repo
@set = Gem::Resolver::LockSet.new [@source]
end
def test_initialize
- spec = @LS.new @set, 'a', v(2), [@source], Gem::Platform::RUBY
+ spec = Gem::Resolver::LockSpecification.new @set, "a", v(2), [@source], Gem::Platform::RUBY
- assert_equal 'a', spec.name
+ assert_equal "a", spec.name
assert_equal v(2), spec.version
assert_equal Gem::Platform::RUBY, spec.platform
@@ -24,9 +23,9 @@ class TestGemResolverLockSpecification < Gem::TestCase
end
def test_add_dependency
- l_spec = @LS.new @set, 'a', v(2), [@source], Gem::Platform::RUBY
+ l_spec = Gem::Resolver::LockSpecification.new @set, "a", v(2), [@source], Gem::Platform::RUBY
- b_dep = dep('b', '>= 0')
+ b_dep = dep("b", ">= 0")
l_spec.add_dependency b_dep
@@ -35,10 +34,10 @@ class TestGemResolverLockSpecification < Gem::TestCase
def test_install
spec_fetcher do |fetcher|
- fetcher.download 'a', 2
+ fetcher.download "a", 2
end
- spec = @LS.new @set, 'a', v(2), [@source], Gem::Platform::RUBY
+ spec = Gem::Resolver::LockSpecification.new @set, "a", v(2), [@source], Gem::Platform::RUBY
called = false
@@ -50,9 +49,9 @@ class TestGemResolverLockSpecification < Gem::TestCase
end
def test_install_installed
- spec = @LS.new @set, 'a', v(2), [@source], Gem::Platform::RUBY
+ spec = Gem::Resolver::LockSpecification.new @set, "a", v(2), [@source], Gem::Platform::RUBY
- FileUtils.touch File.join(@gemhome, 'specifications', spec.spec.spec_name)
+ FileUtils.touch File.join(@gemhome, "specifications", spec.spec.spec_name)
called = false
@@ -66,17 +65,17 @@ class TestGemResolverLockSpecification < Gem::TestCase
def test_spec
version = v(2)
- l_spec = @LS.new @set, 'a', version, [@source], Gem::Platform::RUBY
+ l_spec = Gem::Resolver::LockSpecification.new @set, "a", version, [@source], Gem::Platform::RUBY
- b_dep = dep 'b', '>= 0'
- c_dep = dep 'c', '~> 1'
+ b_dep = dep "b", ">= 0"
+ c_dep = dep "c", "~> 1"
l_spec.add_dependency b_dep
l_spec.add_dependency c_dep
spec = l_spec.spec
- assert_equal 'a', spec.name
+ assert_equal "a", spec.name
assert_equal version, spec.version
assert_equal Gem::Platform::RUBY, spec.platform
@@ -84,13 +83,13 @@ class TestGemResolverLockSpecification < Gem::TestCase
end
def test_spec_loaded
- real_spec = util_spec 'a', 2
+ real_spec = util_spec "a", 2
install_specs real_spec
real_spec.activate
version = v(2)
- l_spec = @LS.new @set, 'a', version, [@source], Gem::Platform::RUBY
+ l_spec = Gem::Resolver::LockSpecification.new @set, "a", version, [@source], Gem::Platform::RUBY
assert_same real_spec, l_spec.spec
end
diff --git a/test/rubygems/test_gem_resolver_requirement_list.rb b/test/rubygems/test_gem_resolver_requirement_list.rb
index 806c387669..20251805fc 100644
--- a/test/rubygems/test_gem_resolver_requirement_list.rb
+++ b/test/rubygems/test_gem_resolver_requirement_list.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
-require_relative 'helper'
+
+require_relative "helper"
class TestGemResolverRequirementList < Gem::TestCase
def setup
diff --git a/test/rubygems/test_gem_resolver_specification.rb b/test/rubygems/test_gem_resolver_specification.rb
index 9f28c1c0cf..e2bbce0c0c 100644
--- a/test/rubygems/test_gem_resolver_specification.rb
+++ b/test/rubygems/test_gem_resolver_specification.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
-require_relative 'helper'
+
+require_relative "helper"
class TestGemResolverSpecification < Gem::TestCase
class TestSpec < Gem::Resolver::Specification
@@ -16,31 +17,31 @@ class TestGemResolverSpecification < Gem::TestCase
def test_install
gemhome = "#{@gemhome}2"
spec_fetcher do |fetcher|
- fetcher.gem 'a', 1
+ fetcher.gem "a", 1
end
- a = util_spec 'a', 1
+ a = util_spec "a", 1
a_spec = TestSpec.new a
a_spec.source = Gem::Source.new @gem_repo
- a_spec.install :install_dir => gemhome
+ a_spec.install install_dir: gemhome
- assert_path_exist File.join gemhome, 'gems', a.full_name
+ assert_path_exist File.join gemhome, "gems", a.full_name
- expected = File.join gemhome, 'specifications', a.spec_name
+ expected = File.join gemhome, "specifications", a.spec_name
assert_equal expected, a_spec.spec.loaded_from
end
def test_installable_platform_eh
- a = util_spec 'a', 1
+ a = util_spec "a", 1
a_spec = TestSpec.new a
assert a_spec.installable_platform?
- b = util_spec 'a', 1 do |s|
+ b = util_spec "a", 1 do |s|
s.platform = Gem::Platform.new %w[cpu other_platform 1]
end
@@ -50,7 +51,7 @@ class TestGemResolverSpecification < Gem::TestCase
end
def test_source
- a = util_spec 'a', 1
+ a = util_spec "a", 1
source = Gem::Source.new @gem_repo
diff --git a/test/rubygems/test_gem_resolver_vendor_set.rb b/test/rubygems/test_gem_resolver_vendor_set.rb
index e16d43ac1a..25a3c5fc7b 100644
--- a/test/rubygems/test_gem_resolver_vendor_set.rb
+++ b/test/rubygems/test_gem_resolver_vendor_set.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
-require_relative 'helper'
+
+require_relative "helper"
class TestGemResolverVendorSet < Gem::TestCase
def setup
@@ -40,7 +41,7 @@ class TestGemResolverVendorSet < Gem::TestCase
@set.add_vendor_gem name, directory
- dependency = dep 'a', '~> 1'
+ dependency = dep "a", "~> 1"
req = Gem::Resolver::DependencyRequest.new dependency, nil
@@ -58,15 +59,15 @@ class TestGemResolverVendorSet < Gem::TestCase
end
def test_find_all_prerelease
- name, _, directory = vendor_gem 'a', '1.a'
+ name, _, directory = vendor_gem "a", "1.a"
@set.add_vendor_gem name, directory
- req = Gem::Resolver::DependencyRequest.new dep('a'), nil
+ req = Gem::Resolver::DependencyRequest.new dep("a"), nil
assert_empty @set.find_all req
- req = Gem::Resolver::DependencyRequest.new dep('a', '>= 0.a'), nil
+ req = Gem::Resolver::DependencyRequest.new dep("a", ">= 0.a"), nil
refute_empty @set.find_all req
end
@@ -75,7 +76,7 @@ class TestGemResolverVendorSet < Gem::TestCase
error = Object.const_defined?(:KeyError) ? KeyError : IndexError
assert_raise error do
- @set.load_spec 'b', v(1), Gem::Platform::RUBY, nil
+ @set.load_spec "b", v(1), Gem::Platform::RUBY, nil
end
end
end
diff --git a/test/rubygems/test_gem_resolver_vendor_specification.rb b/test/rubygems/test_gem_resolver_vendor_specification.rb
index 93382ccd81..3525a6c14c 100644
--- a/test/rubygems/test_gem_resolver_vendor_specification.rb
+++ b/test/rubygems/test_gem_resolver_vendor_specification.rb
@@ -1,12 +1,13 @@
# frozen_string_literal: true
-require_relative 'helper'
+
+require_relative "helper"
class TestGemResolverVendorSpecification < Gem::TestCase
def setup
super
@set = Gem::Resolver::VendorSet.new
- @spec = Gem::Specification.new 'a', 1
+ @spec = Gem::Specification.new "a", 1
end
def test_equals2
@@ -14,7 +15,7 @@ class TestGemResolverVendorSpecification < Gem::TestCase
assert_equal v_spec_a, v_spec_a
- spec_b = Gem::Specification.new 'b', 1
+ spec_b = Gem::Specification.new "b", 1
v_spec_b = Gem::Resolver::VendorSpecification.new @set, spec_b
refute_equal v_spec_a, v_spec_b
@@ -27,24 +28,25 @@ class TestGemResolverVendorSpecification < Gem::TestCase
i_set = Gem::Resolver::IndexSet.new
source = Gem::Source.new @gem_repo
i_spec = Gem::Resolver::IndexSpecification.new(
- i_set, 'a', v(1), source, Gem::Platform::RUBY)
+ i_set, "a", v(1), source, Gem::Platform::RUBY
+ )
refute_equal v_spec_a, i_spec
end
def test_dependencies
- @spec.add_dependency 'b'
- @spec.add_dependency 'c'
+ @spec.add_dependency "b"
+ @spec.add_dependency "c"
v_spec = Gem::Resolver::VendorSpecification.new @set, @spec
- assert_equal [dep('b'), dep('c')], v_spec.dependencies
+ assert_equal [dep("b"), dep("c")], v_spec.dependencies
end
def test_full_name
v_spec = Gem::Resolver::VendorSpecification.new @set, @spec
- assert_equal 'a-1', v_spec.full_name
+ assert_equal "a-1", v_spec.full_name
end
def test_install
@@ -62,7 +64,7 @@ class TestGemResolverVendorSpecification < Gem::TestCase
def test_name
v_spec = Gem::Resolver::VendorSpecification.new @set, @spec
- assert_equal 'a', v_spec.name
+ assert_equal "a", v_spec.name
end
def test_platform
@@ -72,7 +74,7 @@ class TestGemResolverVendorSpecification < Gem::TestCase
end
def test_version
- spec = Gem::Specification.new 'a', 1
+ spec = Gem::Specification.new "a", 1
v_spec = Gem::Resolver::VendorSpecification.new @set, spec
diff --git a/test/rubygems/test_gem_safe_marshal.rb b/test/rubygems/test_gem_safe_marshal.rb
new file mode 100644
index 0000000000..1085aca9fd
--- /dev/null
+++ b/test/rubygems/test_gem_safe_marshal.rb
@@ -0,0 +1,416 @@
+# frozen_string_literal: true
+
+require_relative "helper"
+
+require "date"
+require "rubygems/safe_marshal"
+
+class TestGemSafeMarshal < Gem::TestCase
+ define_method("test_safe_load_marshal Date #<Date: 1994-12-09 ((2449696j,0s,0n),+0s,2299161j)>") { assert_safe_load_marshal "\x04\bU:\tDate[\vi\x00i\x03 a%i\x00i\x00i\x00f\f2299161" }
+ define_method("test_safe_load_marshal Float 0.0") { assert_safe_load_marshal "\x04\bf\x060" }
+ define_method("test_safe_load_marshal Float -0.0") { assert_safe_load_marshal "\x04\bf\a-0" }
+ define_method("test_safe_load_marshal Float Infinity") { assert_safe_load_marshal "\x04\bf\binf" }
+ define_method("test_safe_load_marshal Float -Infinity") { assert_safe_load_marshal "\x04\bf\t-inf" }
+ define_method("test_safe_load_marshal Float NaN") { assert_safe_load_marshal "\x04\bf\bnan", equality: false }
+ define_method("test_safe_load_marshal Float 1.1") { assert_safe_load_marshal "\x04\bf\b1.1" }
+ define_method("test_safe_load_marshal Float -1.1") { assert_safe_load_marshal "\x04\bf\t-1.1" }
+ define_method("test_safe_load_marshal Float 30000000.0") { assert_safe_load_marshal "\x04\bf\b3e7" }
+ define_method("test_safe_load_marshal Float -30000000.0") { assert_safe_load_marshal "\x04\bf\t-3e7" }
+ define_method("test_safe_load_marshal Gem::Version #<Gem::Version \"1.abc\">") { assert_safe_load_marshal "\x04\bU:\x11Gem::Version[\x06I\"\n1.abc\x06:\x06ET" }
+ define_method("test_safe_load_marshal Hash {} default value") { assert_safe_load_marshal "\x04\b}\x00[\x00", additional_methods: [:default] }
+ define_method("test_safe_load_marshal Hash {}") { assert_safe_load_marshal "\x04\b{\x00" }
+ define_method("test_safe_load_marshal Array {}") { assert_safe_load_marshal "\x04\b[\x00" }
+ define_method("test_safe_load_marshal Hash {:runtime=>:development}") { assert_safe_load_marshal "\x04\bI{\x06:\fruntime:\x10development\x06:\n@type[\x00", permitted_ivars: { "Hash" => %w[@type] } }
+ define_method("test_safe_load_marshal Integer -1") { assert_safe_load_marshal "\x04\bi\xFA" }
+ define_method("test_safe_load_marshal Integer -1048575") { assert_safe_load_marshal "\x04\bi\xFD\x01\x00\xF0" }
+ define_method("test_safe_load_marshal Integer -122") { assert_safe_load_marshal "\x04\bi\x81" }
+ define_method("test_safe_load_marshal Integer -123") { assert_safe_load_marshal "\x04\bi\x80" }
+ define_method("test_safe_load_marshal Integer -124") { assert_safe_load_marshal "\x04\bi\xFF\x84" }
+ define_method("test_safe_load_marshal Integer -127") { assert_safe_load_marshal "\x04\bi\xFF\x81" }
+ define_method("test_safe_load_marshal Integer -128") { assert_safe_load_marshal "\x04\bi\xFF\x80" }
+ define_method("test_safe_load_marshal Integer -2") { assert_safe_load_marshal "\x04\bi\xF9" }
+ define_method("test_safe_load_marshal Integer -255") { assert_safe_load_marshal "\x04\bi\xFF\x01" }
+ define_method("test_safe_load_marshal Integer -256") { assert_safe_load_marshal "\x04\bi\xFF\x00" }
+ define_method("test_safe_load_marshal Integer -257") { assert_safe_load_marshal "\x04\bi\xFE\xFF\xFE" }
+ define_method("test_safe_load_marshal Integer -268435455") { assert_safe_load_marshal "\x04\bi\xFC\x01\x00\x00\xF0" }
+ define_method("test_safe_load_marshal Integer -268435456") { assert_safe_load_marshal "\x04\bi\xFC\x00\x00\x00\xF0" }
+ define_method("test_safe_load_marshal Integer -3") { assert_safe_load_marshal "\x04\bi\xF8" }
+ define_method("test_safe_load_marshal Integer -4") { assert_safe_load_marshal "\x04\bi\xF7" }
+ define_method("test_safe_load_marshal Integer -4294967295") { assert_safe_load_marshal "\x04\bl-\a\xFF\xFF\xFF\xFF" }
+ define_method("test_safe_load_marshal Integer -4294967296") { assert_safe_load_marshal "\x04\bl-\b\x00\x00\x00\x00\x01\x00" }
+ define_method("test_safe_load_marshal Integer -5") { assert_safe_load_marshal "\x04\bi\xF6" }
+ define_method("test_safe_load_marshal Integer -6") { assert_safe_load_marshal "\x04\bi\xF5" }
+ define_method("test_safe_load_marshal Integer -65535") { assert_safe_load_marshal "\x04\bi\xFE\x01\x00" }
+ define_method("test_safe_load_marshal Integer -65536") { assert_safe_load_marshal "\x04\bi\xFE\x00\x00" }
+ define_method("test_safe_load_marshal Integer -9223372036854775807") { assert_safe_load_marshal "\x04\bl-\t\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7F" }
+ define_method("test_safe_load_marshal Integer -9223372036854775808") { assert_safe_load_marshal "\x04\bl-\t\x00\x00\x00\x00\x00\x00\x00\x80" }
+ define_method("test_safe_load_marshal Integer 0") { assert_safe_load_marshal "\x04\bi\x00" }
+ define_method("test_safe_load_marshal Integer 1") { assert_safe_load_marshal "\x04\bi\x06" }
+ define_method("test_safe_load_marshal Integer 1048574") { assert_safe_load_marshal "\x04\bi\x03\xFE\xFF\x0F" }
+ define_method("test_safe_load_marshal Integer 1048575") { assert_safe_load_marshal "\x04\bi\x03\xFF\xFF\x0F" }
+ define_method("test_safe_load_marshal Integer 1048576") { assert_safe_load_marshal "\x04\bi\x03\x00\x00\x10" }
+ define_method("test_safe_load_marshal Integer 121") { assert_safe_load_marshal "\x04\bi~" }
+ define_method("test_safe_load_marshal Integer 122") { assert_safe_load_marshal "\x04\bi\x7F" }
+ define_method("test_safe_load_marshal Integer 123") { assert_safe_load_marshal "\x04\bi\x01{" }
+ define_method("test_safe_load_marshal Integer 124") { assert_safe_load_marshal "\x04\bi\x01|" }
+ define_method("test_safe_load_marshal Integer 125") { assert_safe_load_marshal "\x04\bi\x01}" }
+ define_method("test_safe_load_marshal Integer 126") { assert_safe_load_marshal "\x04\bi\x01~" }
+ define_method("test_safe_load_marshal Integer 127") { assert_safe_load_marshal "\x04\bi\x01\x7F" }
+ define_method("test_safe_load_marshal Integer 128") { assert_safe_load_marshal "\x04\bi\x01\x80" }
+ define_method("test_safe_load_marshal Integer 129") { assert_safe_load_marshal "\x04\bi\x01\x81" }
+ define_method("test_safe_load_marshal Integer 2") { assert_safe_load_marshal "\x04\bi\a" }
+ define_method("test_safe_load_marshal Integer 254") { assert_safe_load_marshal "\x04\bi\x01\xFE" }
+ define_method("test_safe_load_marshal Integer 255") { assert_safe_load_marshal "\x04\bi\x01\xFF" }
+ define_method("test_safe_load_marshal Integer 256") { assert_safe_load_marshal "\x04\bi\x02\x00\x01" }
+ define_method("test_safe_load_marshal Integer 257") { assert_safe_load_marshal "\x04\bi\x02\x01\x01" }
+ define_method("test_safe_load_marshal Integer 258") { assert_safe_load_marshal "\x04\bi\x02\x02\x01" }
+ define_method("test_safe_load_marshal Integer 268435454") { assert_safe_load_marshal "\x04\bi\x04\xFE\xFF\xFF\x0F" }
+ define_method("test_safe_load_marshal Integer 268435455") { assert_safe_load_marshal "\x04\bi\x04\xFF\xFF\xFF\x0F" }
+ define_method("test_safe_load_marshal Integer 268435456") { assert_safe_load_marshal "\x04\bi\x04\x00\x00\x00\x10" }
+ define_method("test_safe_load_marshal Integer 268435457") { assert_safe_load_marshal "\x04\bi\x04\x01\x00\x00\x10" }
+ define_method("test_safe_load_marshal Integer 3") { assert_safe_load_marshal "\x04\bi\b" }
+ define_method("test_safe_load_marshal Integer 4") { assert_safe_load_marshal "\x04\bi\t" }
+ define_method("test_safe_load_marshal Integer 4294967294") { assert_safe_load_marshal "\x04\bl+\a\xFE\xFF\xFF\xFF" }
+ define_method("test_safe_load_marshal Integer 4294967295") { assert_safe_load_marshal "\x04\bl+\a\xFF\xFF\xFF\xFF" }
+ define_method("test_safe_load_marshal Integer 4294967296") { assert_safe_load_marshal "\x04\bl+\b\x00\x00\x00\x00\x01\x00" }
+ define_method("test_safe_load_marshal Integer 4294967297") { assert_safe_load_marshal "\x04\bl+\b\x01\x00\x00\x00\x01\x00" }
+ define_method("test_safe_load_marshal Integer 5") { assert_safe_load_marshal "\x04\bi\n" }
+ define_method("test_safe_load_marshal Integer 6") { assert_safe_load_marshal "\x04\bi\v" }
+ define_method("test_safe_load_marshal Integer 65534") { assert_safe_load_marshal "\x04\bi\x02\xFE\xFF" }
+ define_method("test_safe_load_marshal Integer 65535") { assert_safe_load_marshal "\x04\bi\x02\xFF\xFF" }
+ define_method("test_safe_load_marshal Integer 65536") { assert_safe_load_marshal "\x04\bi\x03\x00\x00\x01" }
+ define_method("test_safe_load_marshal Integer 65537") { assert_safe_load_marshal "\x04\bi\x03\x01\x00\x01" }
+ define_method("test_safe_load_marshal Integer 7") { assert_safe_load_marshal "\x04\bi\f" }
+ define_method("test_safe_load_marshal Integer 9223372036854775806") { assert_safe_load_marshal "\x04\bl+\t\xFE\xFF\xFF\xFF\xFF\xFF\xFF\x7F" }
+ define_method("test_safe_load_marshal Integer 9223372036854775807") { assert_safe_load_marshal "\x04\bl+\t\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x7F" }
+ define_method("test_safe_load_marshal Integer 9223372036854775808") { assert_safe_load_marshal "\x04\bl+\t\x00\x00\x00\x00\x00\x00\x00\x80" }
+ define_method("test_safe_load_marshal Integer 9223372036854775809") { assert_safe_load_marshal "\x04\bl+\t\x01\x00\x00\x00\x00\x00\x00\x80" }
+ define_method("test_safe_load_marshal Rational (1/3)") { assert_safe_load_marshal "\x04\bU:\rRational[\ai\x06i\b" }
+ define_method("test_safe_load_marshal Array [[...]]") { assert_safe_load_marshal "\x04\b[\x06@\x00" }
+ define_method("test_safe_load_marshal String \"hello\" ivar") { assert_safe_load_marshal "\x04\bI\"\nhello\a:\x06ET:\n@type@\x00", additional_methods: [:instance_variables], permitted_ivars: { "String" => %w[@type E] } }
+ define_method("test_safe_load_marshal Array [\"hello\", [\"hello\"], \"hello\", [\"hello\"]]") { assert_safe_load_marshal "\x04\b[\tI\"\nhello\x06:\x06ET[\x06@\x06@\x06@\a" }
+ define_method("test_safe_load_marshal Array [\"hello\", \"hello\"]") { assert_safe_load_marshal "\x04\b[\aI\"\nhello\x06:\x06ET@\x06" }
+ define_method("test_safe_load_marshal Array [:development, :development]") { assert_safe_load_marshal "\x04\b[\a:\x10development;\x00" }
+ define_method("test_safe_load_marshal String \"abc\" ascii") { assert_safe_load_marshal "\x04\bI\"\babc\x06:\x06EF", additional_methods: [:encoding] }
+ define_method("test_safe_load_marshal Array [\"abc\", \"abc\"] ascii") { assert_safe_load_marshal "\x04\b[\aI\"\babc\x06:\x06EF@\x06", additional_methods: [->(x) { x.map(&:encoding) }] }
+ define_method("test_safe_load_marshal String \"abc\" utf8") { assert_safe_load_marshal "\x04\bI\"\babc\x06:\x06ET", additional_methods: [:encoding] }
+ define_method("test_safe_load_marshal Array [\"abc\", \"abc\"] utf8") { assert_safe_load_marshal "\x04\b[\aI\"\babc\x06:\x06ET@\x06", additional_methods: [->(x) { x.map(&:encoding) }] }
+ define_method("test_safe_load_marshal String \"abc\" Windows-1256") { assert_safe_load_marshal "\x04\bI\"\babc\x06:\rencoding\"\x11Windows-1256", additional_methods: [:encoding] }
+ define_method("test_safe_load_marshal Array [\"abc\", \"abc\"] Windows-1256") { assert_safe_load_marshal "\x04\b[\aI\"\babc\x06:\rencoding\"\x11Windows-1256@\x06", additional_methods: [->(x) { x.map(&:encoding) }] }
+ define_method("test_safe_load_marshal String \"abc\" binary") { assert_safe_load_marshal "\x04\b\"\babc", additional_methods: [:encoding] }
+ define_method("test_safe_load_marshal Array [\"abc\", \"abc\"] binary") { assert_safe_load_marshal "\x04\b[\a\"\babc@\x06", additional_methods: [->(x) { x.map(&:encoding) }] }
+ define_method("test_safe_load_marshal String \"\\x61\\x62\\x63\" utf32") { assert_safe_load_marshal "\x04\bI\"\babc\x06:\rencoding\"\vUTF-32", additional_methods: [:encoding] }
+ define_method("test_safe_load_marshal Array [\"\\x61\\x62\\x63\", \"\\x61\\x62\\x63\"] utf32") { assert_safe_load_marshal "\x04\b[\aI\"\babc\x06:\rencoding\"\vUTF-32@\x06", additional_methods: [->(x) { x.map(&:encoding) }] }
+ define_method("test_safe_load_marshal String \"abc\" ivar") { assert_safe_load_marshal "\x04\bI\"\babc\a:\x06ET:\n@typeI\"\ttype\x06;\x00T", permitted_ivars: { "String" => %w[@type E] } }
+ define_method("test_safe_load_marshal String \"\"") { assert_safe_load_marshal "\x04\bI\"\babc\x06:\x06ET" }
+ define_method("test_safe_load_marshal Time 2000-12-31 20:07:59 -1152") { assert_safe_load_marshal "\x04\bIu:\tTime\r'@\x19\x80\x00\x00\xB0\xEF\a:\voffseti\xFE Y:\tzone0", additional_methods: [:ctime, :to_f, :to_r, :to_i, :zone, :subsec, :instance_variables, :dst?, :to_a] }
+ define_method("test_safe_load_marshal Time 2000-12-31 23:59:59 -0800") { assert_safe_load_marshal "\x04\bIu:\tTime\r'@\x19\x80\x00\x00\xB0\xEF\a:\voffseti\xFE\x80\x8F:\tzoneI\"\bPST\x06:\x06EF", additional_methods: [:ctime, :to_f, :to_r, :to_i, :zone, :subsec, :instance_variables, :dst?, :to_a] }
+ define_method("test_safe_load_marshal Time 2000-12-31 23:59:59 2254051613498933/2251799813685248000000000 -0800") { assert_safe_load_marshal "\x04\bIu:\tTime\r'@\x19\x80\x00\x00\xB0\xEF\n:\rnano_numl+\t5^\xBAI\f\x02\b\x00:\rnano_denl+\t\x00\x00\x00\x00\x00\x00\b\x00:\rsubmicro\"\a\x00\x10:\voffseti\xFE\x80\x8F:\tzoneI\"\bPST\x06:\x06EF", additional_methods: [:ctime, :to_f, :to_r, :to_i, :zone, :subsec, :instance_variables, :dst?, :to_a] }
+ define_method("test_safe_load_marshal Time 2000-12-31 23:59:59 2476979795053773/2251799813685248000 -0800") { assert_safe_load_marshal "\x04\bIu:\tTime\r'@\x19\x80L\x04\xB0\xEF\t:\rnano_numi\x025\f:\rnano_denl+\b\x00\x00\x00\x00\x00 :\voffseti\xFE\x80\x8F:\tzoneI\"\bPST\x06:\x06EF", additional_methods: [:ctime, :to_f, :to_r, :to_i, :zone, :subsec, :instance_variables, :dst?, :to_a] }
+ define_method("test_safe_load_marshal Time 2000-12-31 23:59:59 2476979795053773/2251799813685248000000 -0800") { assert_safe_load_marshal "\x04\bIu:\tTime\r'@\x19\x80\x01\x00\xB0\xEF\n:\rnano_numl+\t\x19\x00\x00\x00\x00\x00d\x00:\rnano_denl+\t\x00\x00\x00\x00\x00\x00\x01\x00:\rsubmicro\"\x06\x10:\voffseti\xFE\x80\x8F:\tzoneI\"\bPST\x06:\x06EF", additional_methods: [:ctime, :to_f, :to_r, :to_i, :zone, :subsec, :instance_variables, :dst?, :to_a] }
+ define_method("test_safe_load_marshal Time 2000-12-31 23:59:59 2476979795053773/2251799813685248000000000 -0800") { assert_safe_load_marshal "\x04\bIu:\tTime\r'@\x19\x80\x00\x00\xB0\xEF\n:\rnano_numl+\t\xCD\xCC\xCC\xCC\xCC\xCC\b\x00:\rnano_denl+\t\x00\x00\x00\x00\x00\x00\b\x00:\rsubmicro\"\a\x00\x10:\voffseti\xFE\x80\x8F:\tzoneI\"\bPST\x06:\x06EF", additional_methods: [:ctime, :to_f, :to_r, :to_i, :zone, :subsec, :instance_variables, :dst?, :to_a] }
+ define_method("test_safe_load_marshal Time 2000-12-31 23:59:59 450364466336677/450359962737049600000000 -0800") { assert_safe_load_marshal "\x04\bIu:\tTime\r'@\x19\x80\x00\x00\xB0\xEF\n:\rnano_numl+\t9b->\x05\x00\b\x00:\rnano_denl+\t\x00\x00\x00\x00\x00\x00\b\x00:\rsubmicro\"\a\x00\x10:\voffseti\xFE\x80\x8F:\tzoneI\"\bPST\x06:\x06EF", additional_methods: [:ctime, :to_f, :to_r, :to_i, :zone, :subsec, :instance_variables, :dst?, :to_a] }
+ define_method("test_safe_load_marshal Time 2000-12-31 23:59:59 4548635623644201/4503599627370496000 -0800") { assert_safe_load_marshal "\x04\bIu:\tTime\r'@\x19\x80\xF2\x03\xB0\xEF\t:\rnano_numi\x02q\x02:\rnano_denl+\b\x00\x00\x00\x00\x00@:\voffseti\xFE\x80\x8F:\tzoneI\"\bPST\x06:\x06EF", additional_methods: [:ctime, :to_f, :to_r, :to_i, :zone, :subsec, :instance_variables, :dst?, :to_a] }
+ define_method("test_safe_load_marshal Time 2000-12-31 23:59:59 4548635623644201/4503599627370496000000 -0800") { assert_safe_load_marshal "\x04\bIu:\tTime\r'@\x19\x80\x01\x00\xB0\xEF\n:\rnano_numl+\t\x05\x00\x00\x00\x00\x00\x14\x00:\rnano_denl+\t\x00\x00\x00\x00\x00\x00\x02\x00:\rsubmicro\"\x06\x01:\voffseti\xFE\x80\x8F:\tzoneI\"\bPST\x06:\x06EF", additional_methods: [:ctime, :to_f, :to_r, :to_i, :zone, :subsec, :instance_variables, :dst?, :to_a] }
+ define_method("test_safe_load_marshal Time 2000-12-31 23:59:59 4548635623644201/4503599627370496000000000 -0800") { assert_safe_load_marshal "\x04\bIu:\tTime\r'@\x19\x80\x00\x00\xB0\xEF\n:\rnano_numl+\t)\\\x8F\xC2\xF5(\x10\x00:\rnano_denl+\t\x00\x00\x00\x00\x00\x00\x10\x00:\rsubmicro\"\a\x00\x10:\voffseti\xFE\x80\x8F:\tzoneI\"\bPST\x06:\x06EF", additional_methods: [:ctime, :to_f, :to_r, :to_i, :zone, :subsec, :instance_variables, :dst?, :to_a] }
+ define_method("test_safe_load_marshal Time 2000-12-31 23:59:59.000000001 -0800") { assert_safe_load_marshal "\x04\bIu:\tTime\r'@\x19\x80\x00\x00\xB0\xEF\n:\rnano_numi\x06:\rnano_deni\x06:\rsubmicro\"\a\x00\x10:\voffseti\xFE\x80\x8F:\tzoneI\"\bPST\x06:\x06EF", additional_methods: [:ctime, :to_f, :to_r, :to_i, :zone, :subsec, :instance_variables, :dst?, :to_a] }
+ define_method("test_safe_load_marshal Time 2000-12-31 23:59:59.000001 -0800") { assert_safe_load_marshal "\x04\bIu:\tTime\r'@\x19\x80\x01\x00\xB0\xEF\a:\voffseti\xFE\x80\x8F:\tzoneI\"\bPST\x06:\x06EF", additional_methods: [:ctime, :to_f, :to_r, :to_i, :zone, :subsec, :instance_variables, :dst?, :to_a] }
+ define_method("test_safe_load_marshal Time 2000-12-31 23:59:59.001 -0800") { assert_safe_load_marshal "\x04\bIu:\tTime\r'@\x19\x80\xE8\x03\xB0\xEF\a:\voffseti\xFE\x80\x8F:\tzoneI\"\bPST\x06:\x06EF", additional_methods: [:ctime, :to_f, :to_r, :to_i, :zone, :subsec, :instance_variables, :dst?, :to_a] }
+ define_method("test_safe_load_marshal Time 2001-01-01 07:59:59 +0000") { assert_safe_load_marshal "\x04\bIu:\tTime\r'@\x19\x80\x00\x00\xB0\xEF\a:\voffseti\x00:\tzone0", additional_methods: [:ctime, :to_f, :to_r, :to_i, :zone, :subsec, :instance_variables, :dst?, :to_a] }
+ define_method("test_safe_load_marshal Time 2001-01-01 07:59:59 UTC") { assert_safe_load_marshal "\x04\bIu:\tTime\r'@\x19\xC0\x00\x00\xB0\xEF\x06:\tzoneI\"\bUTC\x06:\x06EF", additional_methods: [:ctime, :to_f, :to_r, :to_i, :zone, :subsec, :instance_variables, :dst?, :to_a] }
+ define_method("test_safe_load_marshal Time 2001-01-01 11:59:59 +0400") { assert_safe_load_marshal "\x04\bIu:\tTime\r'@\x19\x80\x00\x00\xB0\xEF\a:\voffseti\x02@8:\tzone0", additional_methods: [:ctime, :to_f, :to_r, :to_i, :zone, :subsec, :instance_variables, :dst?, :to_a] }
+ define_method("test_safe_load_marshal Time 2023-08-24 10:10:39.09565 -0700") { assert_safe_load_marshal "\x04\bIu:\tTime\r\x11\xDF\x1E\x80\xA2uq*\a:\voffseti\xFE\x90\x9D:\tzoneI\"\bPDT\x06:\x06EF" }
+ define_method("test_safe_load_marshal Time 2023-08-24 10:10:39.098453 -0700") { assert_safe_load_marshal "\x04\bIu:\tTime\r\x11\xDF\x1E\x80\x95\x80q*\b:\n@typeI\"\fruntime\x06:\x06ET:\voffseti\xFE\x90\x9D:\tzoneI\"\bPDT\x06;\aF", permitted_ivars: { "Time" => %w[@type offset zone], "String" => %w[E @debug_created_info] }, marshal_dump_equality: true }
+
+ def test_repeated_symbol
+ assert_safe_load_as [:development, :development]
+ end
+
+ def test_length_one_symbols
+ with_const(Gem::SafeMarshal, :PERMITTED_SYMBOLS, %w[E A b 0] << "") do
+ assert_safe_load_as [:A, :E, :E, :A, "".to_sym, "".to_sym], additional_methods: [:instance_variables]
+ end
+ end
+
+ def test_repeated_string
+ s = "hello"
+ a = [s]
+ assert_safe_load_as [s, a, s, a]
+ assert_safe_load_as [s, s]
+ end
+
+ def test_recursive_string
+ s = String.new("hello")
+ s.instance_variable_set(:@type, s)
+ with_const(Gem::SafeMarshal, :PERMITTED_IVARS, { "String" => %w[@type E] }) do
+ assert_safe_load_as s, additional_methods: [:instance_variables]
+ end
+ end
+
+ def test_recursive_array
+ a = []
+ a << a
+ assert_safe_load_as a
+ end
+
+ def test_time_loads
+ assert_safe_load_as Time.new
+ end
+
+ def test_string_with_encoding
+ [
+ String.new("abc", encoding: "US-ASCII"),
+ String.new("abc", encoding: "UTF-8"),
+ String.new("abc", encoding: "Windows-1256"),
+ String.new("abc", encoding: Encoding::BINARY),
+ String.new("abc", encoding: "UTF-32"),
+
+ String.new("", encoding: "US-ASCII"),
+ String.new("", encoding: "UTF-8"),
+ String.new("", encoding: "Windows-1256"),
+ String.new("", encoding: Encoding::BINARY),
+ String.new("", encoding: "UTF-32"),
+ ].each do |s|
+ assert_safe_load_as s, additional_methods: [:encoding]
+ assert_safe_load_as [s, s], additional_methods: [->(a) { a.map(&:encoding) }]
+ end
+ end
+
+ def test_string_with_ivar
+ str = String.new("abc")
+ str.instance_variable_set :@type, "type"
+ with_const(Gem::SafeMarshal, :PERMITTED_IVARS, { "String" => %w[@type E @debug_created_info] }) do
+ assert_safe_load_as str
+ end
+ end
+
+ def test_time_with_ivar
+ pend "Marshal.load of Time with ivars is broken on jruby, see https://github.com/jruby/jruby/issues/7902" if RUBY_ENGINE == "jruby"
+
+ with_const(Gem::SafeMarshal, :PERMITTED_IVARS, { "Time" => %w[@type offset zone nano_num nano_den submicro], "String" => %w[E @debug_created_info] }) do
+ assert_safe_load_as Time.new.tap {|t| t.instance_variable_set :@type, "runtime" }, marshal_dump_equality: true
+ end
+ end
+
+ secs = Time.new(2000, 12, 31, 23, 59, 59).to_i
+ [
+ Time.at(secs),
+ Time.at(secs, in: "+04:00"),
+ Time.at(secs, in: "-11:52"),
+ Time.at(secs, in: "+00:00"),
+ Time.at(secs, in: "-00:00"),
+ Time.at(secs, 1, :millisecond),
+ Time.at(secs, 1.1, :millisecond),
+ Time.at(secs, 1.01, :millisecond),
+ Time.at(secs, 1, :microsecond),
+ Time.at(secs, 1.1, :microsecond),
+ Time.at(secs, 1.01, :microsecond),
+ Time.at(secs, 1, :nanosecond),
+ Time.at(secs, 1.1, :nanosecond),
+ Time.at(secs, 1.01, :nanosecond),
+ Time.at(secs, 1.001, :nanosecond),
+ Time.at(secs, 1.00001, :nanosecond),
+ Time.at(secs, 1.00001, :nanosecond),
+ Time.at(secs, in: "UTC"),
+ Time.at(secs, in: "Z"),
+ ].each_with_index do |t, i|
+ define_method("test_time_#{i} #{t.inspect}") do
+ additional_methods = [:ctime, :to_f, :to_r, :to_i, :zone, :subsec, :instance_variables, :dst?, :to_a]
+ assert_safe_load_as t, additional_methods: additional_methods
+ end
+ end
+
+ def test_floats
+ [0.0, Float::INFINITY, Float::NAN, 1.1, 3e7].each do |f|
+ assert_safe_load_as f
+ assert_safe_load_as(-f)
+ end
+ end
+
+ def test_hash_with_ivar
+ h = { runtime: :development }
+ h.instance_variable_set :@type, []
+ with_const(Gem::SafeMarshal, :PERMITTED_IVARS, { "Hash" => %w[@type] }) do
+ assert_safe_load_as(h)
+ end
+ end
+
+ def test_hash_with_default_value
+ assert_safe_load_as Hash.new([])
+ end
+
+ def test_hash_with_compare_by_identity
+ with_const(Gem::SafeMarshal, :PERMITTED_CLASSES, %w[Hash]) do
+ assert_safe_load_as Hash.new.compare_by_identity.tap {|h|
+ h[+"a"] = 1
+ h[+"a"] = 2 }, additional_methods: [:compare_by_identity?], equality: false
+ assert_safe_load_as Hash.new.compare_by_identity, additional_methods: [:compare_by_identity?]
+ assert_safe_load_as Hash.new(0).compare_by_identity.tap {|h|
+ h[+"a"] = 1
+ h[+"a"] = 2 }, additional_methods: [:compare_by_identity?, :default], equality: false
+ end
+ end
+
+ class StringSubclass < ::String
+ end
+
+ def test_string_subclass
+ with_const(Gem::SafeMarshal, :PERMITTED_CLASSES, [StringSubclass.name]) do
+ with_const(Gem::SafeMarshal, :PERMITTED_IVARS, { StringSubclass.name => %w[E] }) do
+ e = assert_raise(Gem::SafeMarshal::Visitors::ToRuby::UnsupportedError) do
+ Gem::SafeMarshal.safe_load Marshal.dump StringSubclass.new("abc")
+ end
+ assert_equal "Unsupported user class #{StringSubclass.name} in marshal stream @ root.object", e.message
+ end
+ end
+ end
+
+ class ArraySubclass < ::Array
+ end
+
+ def test_array_subclass
+ with_const(Gem::SafeMarshal, :PERMITTED_CLASSES, [ArraySubclass.name]) do
+ e = assert_raise(Gem::SafeMarshal::Visitors::ToRuby::UnsupportedError) do
+ Gem::SafeMarshal.safe_load(Marshal.dump(ArraySubclass.new << "abc"))
+ end
+ assert_equal "Unsupported user class #{ArraySubclass.name} in marshal stream @ root", e.message
+ end
+ end
+
+ def test_frozen_object
+ assert_safe_load_as Gem::Version.new("1.abc").freeze
+ end
+
+ def test_date
+ assert_safe_load_as Date.new(1994, 12, 9)
+ end
+
+ def test_rational
+ assert_safe_load_as Rational(1, 3)
+ end
+
+ [
+ 0, 1, 2, 3, 4, 5, 6, 122, 123, 124, 127, 128, 255, 256, 257,
+ 2**16, 2**16 - 1, 2**20 - 1,
+ 2**28, 2**28 - 1,
+ 2**32, 2**32 - 1,
+ 2**63, 2**63 - 1
+ ].
+ each do |i|
+ define_method("test_int_ #{i}") do
+ assert_safe_load_as i
+ assert_safe_load_as(-i)
+ assert_safe_load_as(i + 1)
+ assert_safe_load_as(i - 1)
+ end
+ end
+
+ def test_gem_spec_unmarshall_license
+ spec = Gem::Specification.new do |s|
+ s.name = "hi"
+ s.version = "1.2.3"
+ s.license = "MIT"
+ end
+
+ unmarshalled_spec = Gem::SafeMarshal.safe_load(Marshal.dump(spec))
+
+ assert_equal ["MIT"], unmarshalled_spec.license
+ end
+
+ def test_gem_spec_disallowed_symbol
+ e = assert_raise(Gem::SafeMarshal::Visitors::ToRuby::UnpermittedSymbolError) do
+ spec = Gem::Specification.new do |s|
+ s.name = "hi"
+ s.version = "1.2.3"
+
+ s.dependencies << Gem::Dependency.new("rspec", Gem::Requirement.new([">= 1.2.3"]), :runtime).tap {|d| d.instance_variable_set(:@name, :rspec) }
+ end
+ Gem::SafeMarshal.safe_load(Marshal.dump(spec))
+ end
+
+ assert_equal e.message, "Attempting to load unpermitted symbol \"rspec\" @ root.[9].[0].@name"
+ end
+
+ def test_gem_spec_disallowed_ivar
+ e = assert_raise(Gem::SafeMarshal::Visitors::ToRuby::UnpermittedIvarError) do
+ spec = Gem::Specification.new do |s|
+ s.name = "hi"
+ s.version = "1.2.3"
+
+ s.metadata.instance_variable_set(:@foobar, "rspec")
+ end
+ Gem::SafeMarshal.safe_load(Marshal.dump(spec))
+ end
+
+ assert_equal e.message, "Attempting to set unpermitted ivar \"@foobar\" on object of class Hash @ root.[18].ivar_0"
+ end
+
+ def test_unexpected_eof
+ e = assert_raise(Gem::SafeMarshal::Reader::EOFError) do
+ Gem::SafeMarshal.safe_load("\x04\x08")
+ end
+ assert_equal e.message, "Unexpected EOF"
+
+ e = assert_raise(Gem::SafeMarshal::Reader::EOFError) do
+ Gem::SafeMarshal.safe_load("\x04\x08[")
+ end
+ assert_equal e.message, "Unexpected EOF"
+
+ e = assert_raise(Gem::SafeMarshal::Reader::EOFError) do
+ Gem::SafeMarshal.safe_load("\x04\x08[\x06")
+ end
+ assert_equal e.message, "Unexpected EOF"
+ end
+
+ def assert_safe_load_marshal(dumped, additional_methods: [], permitted_ivars: nil, equality: true, marshal_dump_equality: true)
+ loaded = Marshal.load(dumped)
+ safe_loaded =
+ if permitted_ivars
+ with_const(Gem::SafeMarshal, :PERMITTED_IVARS, permitted_ivars) do
+ Gem::SafeMarshal.safe_load(dumped)
+ end
+ else
+ Gem::SafeMarshal.safe_load(dumped)
+ end
+
+ # NaN != NaN, for example
+ if equality
+ assert_equal loaded, safe_loaded, "should equal what Marshal.load returns"
+ end
+
+ assert_equal loaded.to_s, safe_loaded.to_s, "should have equal to_s"
+ assert_equal loaded.inspect, safe_loaded.inspect, "should have equal inspect"
+ additional_methods.each do |m|
+ if m.is_a?(Proc)
+ call = m
+ else
+ call = ->(obj) { obj.__send__(m) }
+ end
+
+ assert_equal call[loaded], call[safe_loaded], "should have equal #{m}"
+ end
+ if marshal_dump_equality
+ assert_equal Marshal.dump(loaded).dump, Marshal.dump(safe_loaded).dump, "should Marshal.dump the same"
+ end
+ end
+
+ def assert_safe_load_as(x, **kwargs)
+ dumped = Marshal.dump(x)
+ equality = x == x # rubocop:disable Lint/BinaryOperatorWithIdenticalOperands
+ assert_safe_load_marshal(dumped, equality: equality, **kwargs)
+ end
+
+ def with_const(mod, name, new_value, &block)
+ orig = mod.const_get(name)
+ mod.send :remove_const, name
+ mod.const_set name, new_value
+
+ begin
+ yield
+ ensure
+ mod.send :remove_const, name
+ mod.const_set name, orig
+ mod.send :private_constant, name
+ end
+ end
+end
diff --git a/test/rubygems/test_gem_safe_yaml.rb b/test/rubygems/test_gem_safe_yaml.rb
new file mode 100644
index 0000000000..02df9f97da
--- /dev/null
+++ b/test/rubygems/test_gem_safe_yaml.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+require_relative "helper"
+
+Gem.load_yaml
+
+class TestGemSafeYAML < Gem::TestCase
+ def test_aliases_enabled_by_default
+ assert_predicate Gem::SafeYAML, :aliases_enabled?
+ assert_equal({ "a" => "a", "b" => "a" }, Gem::SafeYAML.safe_load("a: &a a\nb: *a\n"))
+ end
+
+ def test_aliases_disabled
+ aliases_enabled = Gem::SafeYAML.aliases_enabled?
+ Gem::SafeYAML.aliases_enabled = false
+ refute_predicate Gem::SafeYAML, :aliases_enabled?
+ expected_error = defined?(Psych::AliasesNotEnabled) ? Psych::AliasesNotEnabled : Psych::BadAlias
+ assert_raise expected_error do
+ Gem::SafeYAML.safe_load("a: &a\nb: *a\n")
+ end
+ ensure
+ Gem::SafeYAML.aliases_enabled = aliases_enabled
+ end
+end
diff --git a/test/rubygems/test_gem_security.rb b/test/rubygems/test_gem_security.rb
index 2eabbea3bf..82449a8626 100644
--- a/test/rubygems/test_gem_security.rb
+++ b/test/rubygems/test_gem_security.rb
@@ -1,33 +1,29 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/security'
+
+require_relative "helper"
+require "rubygems/security"
unless Gem::HAVE_OPENSSL
- warn 'Skipping Gem::Security tests. openssl not found.'
+ warn "Skipping Gem::Security tests. openssl not found."
end
if Gem.java_platform?
- warn 'Skipping Gem::Security tests on jruby.'
+ warn "Skipping Gem::Security tests on jruby."
end
class TestGemSecurity < Gem::TestCase
- CHILD_KEY = load_key 'child'
-
- ALTERNATE_CERT = load_cert 'child'
- CHILD_CERT = load_cert 'child'
- EXPIRED_CERT = load_cert 'expired'
+ CHILD_KEY = load_key "child"
+ EC_KEY = load_key "private_ec", "Foo bar"
- def setup
- super
-
- @SEC = Gem::Security
- end
+ ALTERNATE_CERT = load_cert "child"
+ CHILD_CERT = load_cert "child"
+ EXPIRED_CERT = load_cert "expired"
def test_class_create_cert
name = PUBLIC_CERT.subject
key = PRIVATE_KEY
- cert = @SEC.create_cert name, key, 60, Gem::Security::EXTENSIONS, 5
+ cert = Gem::Security.create_cert name, key, 60, Gem::Security::EXTENSIONS, 5
assert_kind_of OpenSSL::X509::Certificate, cert
@@ -41,37 +37,37 @@ class TestGemSecurity < Gem::TestCase
assert_equal 3, cert.extensions.length,
cert.extensions.map {|e| e.to_a.first }
- constraints = cert.extensions.find {|ext| ext.oid == 'basicConstraints' }
- assert_equal 'CA:FALSE', constraints.value
+ constraints = cert.extensions.find {|ext| ext.oid == "basicConstraints" }
+ assert_equal "CA:FALSE", constraints.value
- key_usage = cert.extensions.find {|ext| ext.oid == 'keyUsage' }
- assert_equal 'Digital Signature, Key Encipherment, Data Encipherment',
+ key_usage = cert.extensions.find {|ext| ext.oid == "keyUsage" }
+ assert_equal "Digital Signature, Key Encipherment, Data Encipherment",
key_usage.value
- key_ident = cert.extensions.find {|ext| ext.oid == 'subjectKeyIdentifier' }
+ key_ident = cert.extensions.find {|ext| ext.oid == "subjectKeyIdentifier" }
assert_equal 59, key_ident.value.length
- assert_equal '5F:43:6E:F6:9A:8E:45:25:E9:22:E3:7D:37:5E:A4:D5:36:02:85:1B',
+ assert_equal "B1:1A:54:09:67:45:60:02:02:D7:CE:F4:1D:60:4A:89:DF:E7:58:D9",
key_ident.value
- assert_equal '', cert.issuer.to_s
+ assert_equal "", cert.issuer.to_s
assert_equal name.to_s, cert.subject.to_s
end
def test_class_create_cert_self_signed
subject = PUBLIC_CERT.subject
- cert = @SEC.create_cert_self_signed subject, PRIVATE_KEY, 60
+ cert = Gem::Security.create_cert_self_signed subject, PRIVATE_KEY, 60
- assert_equal '/CN=nobody/DC=example', cert.issuer.to_s
+ assert_equal "/CN=nobody/DC=example", cert.issuer.to_s
assert_equal "sha256WithRSAEncryption", cert.signature_algorithm
end
def test_class_create_cert_email
- email = 'nobody@example'
+ email = "nobody@example"
name = PUBLIC_CERT.subject
key = PRIVATE_KEY
- cert = @SEC.create_cert_email email, key, 60
+ cert = Gem::Security.create_cert_email email, key, 60
assert_kind_of OpenSSL::X509::Certificate, cert
@@ -86,44 +82,71 @@ class TestGemSecurity < Gem::TestCase
assert_equal 5, cert.extensions.length,
cert.extensions.map {|e| e.to_a.first }
- constraints = cert.extensions.find {|ext| ext.oid == 'subjectAltName' }
- assert_equal 'email:nobody@example', constraints.value
+ constraints = cert.extensions.find {|ext| ext.oid == "subjectAltName" }
+ assert_equal "email:nobody@example", constraints.value
- constraints = cert.extensions.find {|ext| ext.oid == 'basicConstraints' }
- assert_equal 'CA:FALSE', constraints.value
+ constraints = cert.extensions.find {|ext| ext.oid == "basicConstraints" }
+ assert_equal "CA:FALSE", constraints.value
- key_usage = cert.extensions.find {|ext| ext.oid == 'keyUsage' }
- assert_equal 'Digital Signature, Key Encipherment, Data Encipherment',
+ key_usage = cert.extensions.find {|ext| ext.oid == "keyUsage" }
+ assert_equal "Digital Signature, Key Encipherment, Data Encipherment",
key_usage.value
- key_ident = cert.extensions.find {|ext| ext.oid == 'subjectKeyIdentifier' }
+ key_ident = cert.extensions.find {|ext| ext.oid == "subjectKeyIdentifier" }
assert_equal 59, key_ident.value.length
- assert_equal '5F:43:6E:F6:9A:8E:45:25:E9:22:E3:7D:37:5E:A4:D5:36:02:85:1B',
+ assert_equal "B1:1A:54:09:67:45:60:02:02:D7:CE:F4:1D:60:4A:89:DF:E7:58:D9",
key_ident.value
end
def test_class_create_key
- key = @SEC.create_key 1024
+ key = Gem::Security.create_key "rsa"
assert_kind_of OpenSSL::PKey::RSA, key
end
+ def test_class_create_key_downcases
+ key = Gem::Security.create_key "DSA"
+
+ assert_kind_of OpenSSL::PKey::DSA, key
+ end
+
+ def test_class_create_key_raises_unknown_algorithm
+ e = assert_raise Gem::Security::Exception do
+ Gem::Security.create_key "NOT_RSA"
+ end
+
+ assert_equal "NOT_RSA algorithm not found. RSA, DSA, and EC algorithms are supported.",
+ e.message
+ end
+
+ def test_class_get_public_key_rsa
+ pkey_pem = PRIVATE_KEY.public_key.to_pem
+
+ assert_equal pkey_pem, Gem::Security.get_public_key(PRIVATE_KEY).to_pem
+ end
+
+ def test_class_get_public_key_ec
+ pkey = Gem::Security.get_public_key(EC_KEY)
+
+ assert_respond_to pkey, :to_pem
+ end
+
def test_class_email_to_name
- assert_equal '/CN=nobody/DC=example',
- @SEC.email_to_name('nobody@example').to_s
+ assert_equal "/CN=nobody/DC=example",
+ Gem::Security.email_to_name("nobody@example").to_s
- assert_equal '/CN=nobody/DC=example/DC=com',
- @SEC.email_to_name('nobody@example.com').to_s
+ assert_equal "/CN=nobody/DC=example/DC=com",
+ Gem::Security.email_to_name("nobody@example.com").to_s
- assert_equal '/CN=no.body/DC=example',
- @SEC.email_to_name('no.body@example').to_s
+ assert_equal "/CN=no.body/DC=example",
+ Gem::Security.email_to_name("no.body@example").to_s
- assert_equal '/CN=no_body/DC=example',
- @SEC.email_to_name('no+body@example').to_s
+ assert_equal "/CN=no_body/DC=example",
+ Gem::Security.email_to_name("no+body@example").to_s
end
def test_class_re_sign
- assert_equal "sha1WithRSAEncryption", EXPIRED_CERT.signature_algorithm
+ assert_equal "sha256WithRSAEncryption", EXPIRED_CERT.signature_algorithm
re_signed = Gem::Security.re_sign EXPIRED_CERT, PRIVATE_KEY, 60
assert_in_delta Time.now, re_signed.not_before, 10
@@ -140,10 +163,10 @@ class TestGemSecurity < Gem::TestCase
end
child_alt_name = CHILD_CERT.extensions.find do |extension|
- extension.oid == 'subjectAltName'
+ extension.oid == "subjectAltName"
end
- assert_equal "#{child_alt_name.value} is not self-signed, contact " +
+ assert_equal "#{child_alt_name.value} is not self-signed, contact " \
"#{ALTERNATE_CERT.issuer} to obtain a valid certificate",
e.message
end
@@ -154,21 +177,21 @@ class TestGemSecurity < Gem::TestCase
end
assert_equal "incorrect signing key for re-signing " +
- "#{ALTERNATE_CERT.subject}",
+ ALTERNATE_CERT.subject.to_s,
e.message
end
def test_class_reset
- trust_dir = @SEC.trust_dir
+ trust_dir = Gem::Security.trust_dir
- @SEC.reset
+ Gem::Security.reset
- refute_equal trust_dir, @SEC.trust_dir
+ refute_equal trust_dir, Gem::Security.trust_dir
end
def test_class_sign
issuer = PUBLIC_CERT.subject
- signee = OpenSSL::X509::Name.parse "/CN=signee/DC=example"
+ signee = OpenSSL::X509::Name.new([["CN", "signee"], ["DC", "example"]])
key = PRIVATE_KEY
cert = OpenSSL::X509::Certificate.new
@@ -177,7 +200,7 @@ class TestGemSecurity < Gem::TestCase
cert.subject = signee
cert.public_key = key.public_key
- signed = @SEC.sign cert, key, PUBLIC_CERT, 60
+ signed = Gem::Security.sign cert, key, PUBLIC_CERT, 60
assert_equal key.public_key.to_pem, signed.public_key.to_pem
assert_equal signee.to_s, signed.subject.to_s
@@ -189,20 +212,20 @@ class TestGemSecurity < Gem::TestCase
assert_equal 4, signed.extensions.length,
signed.extensions.map {|e| e.to_a.first }
- constraints = signed.extensions.find {|ext| ext.oid == 'issuerAltName' }
- assert_equal 'email:nobody@example', constraints.value, 'issuerAltName'
+ constraints = signed.extensions.find {|ext| ext.oid == "issuerAltName" }
+ assert_equal "email:nobody@example", constraints.value, "issuerAltName"
- constraints = signed.extensions.find {|ext| ext.oid == 'basicConstraints' }
- assert_equal 'CA:FALSE', constraints.value
+ constraints = signed.extensions.find {|ext| ext.oid == "basicConstraints" }
+ assert_equal "CA:FALSE", constraints.value
- key_usage = signed.extensions.find {|ext| ext.oid == 'keyUsage' }
- assert_equal 'Digital Signature, Key Encipherment, Data Encipherment',
+ key_usage = signed.extensions.find {|ext| ext.oid == "keyUsage" }
+ assert_equal "Digital Signature, Key Encipherment, Data Encipherment",
key_usage.value
key_ident =
- signed.extensions.find {|ext| ext.oid == 'subjectKeyIdentifier' }
+ signed.extensions.find {|ext| ext.oid == "subjectKeyIdentifier" }
assert_equal 59, key_ident.value.length
- assert_equal '5F:43:6E:F6:9A:8E:45:25:E9:22:E3:7D:37:5E:A4:D5:36:02:85:1B',
+ assert_equal "B1:1A:54:09:67:45:60:02:02:D7:CE:F4:1D:60:4A:89:DF:E7:58:D9",
key_ident.value
assert signed.verify key
@@ -212,9 +235,9 @@ class TestGemSecurity < Gem::TestCase
issuer = PUBLIC_CERT.subject
signee = OpenSSL::X509::Name.parse "/CN=signee/DC=example"
- cert = @SEC.create_cert_email 'signee@example', PRIVATE_KEY
+ cert = Gem::Security.create_cert_email "signee@example", PRIVATE_KEY
- signed = @SEC.sign cert, PRIVATE_KEY, PUBLIC_CERT, 60
+ signed = Gem::Security.sign cert, PRIVATE_KEY, PUBLIC_CERT, 60
assert_equal PUBLIC_KEY.to_pem, signed.public_key.to_pem
assert_equal signee.to_s, signed.subject.to_s
@@ -228,42 +251,42 @@ class TestGemSecurity < Gem::TestCase
assert_equal 5, signed.extensions.length,
signed.extensions.map {|e| e.to_a.first }
- constraints = signed.extensions.find {|ext| ext.oid == 'issuerAltName' }
- assert_equal 'email:nobody@example', constraints.value, 'issuerAltName'
+ constraints = signed.extensions.find {|ext| ext.oid == "issuerAltName" }
+ assert_equal "email:nobody@example", constraints.value, "issuerAltName"
- constraints = signed.extensions.find {|ext| ext.oid == 'subjectAltName' }
- assert_equal 'email:signee@example', constraints.value, 'subjectAltName'
+ constraints = signed.extensions.find {|ext| ext.oid == "subjectAltName" }
+ assert_equal "email:signee@example", constraints.value, "subjectAltName"
- constraints = signed.extensions.find {|ext| ext.oid == 'basicConstraints' }
- assert_equal 'CA:FALSE', constraints.value
+ constraints = signed.extensions.find {|ext| ext.oid == "basicConstraints" }
+ assert_equal "CA:FALSE", constraints.value
- key_usage = signed.extensions.find {|ext| ext.oid == 'keyUsage' }
- assert_equal 'Digital Signature, Key Encipherment, Data Encipherment',
+ key_usage = signed.extensions.find {|ext| ext.oid == "keyUsage" }
+ assert_equal "Digital Signature, Key Encipherment, Data Encipherment",
key_usage.value
key_ident =
- signed.extensions.find {|ext| ext.oid == 'subjectKeyIdentifier' }
+ signed.extensions.find {|ext| ext.oid == "subjectKeyIdentifier" }
assert_equal 59, key_ident.value.length
- assert_equal '5F:43:6E:F6:9A:8E:45:25:E9:22:E3:7D:37:5E:A4:D5:36:02:85:1B',
+ assert_equal "B1:1A:54:09:67:45:60:02:02:D7:CE:F4:1D:60:4A:89:DF:E7:58:D9",
key_ident.value
assert signed.verify PUBLIC_KEY
end
def test_class_trust_dir
- trust_dir = @SEC.trust_dir
+ trust_dir = Gem::Security.trust_dir
- expected = File.join Gem.user_home, '.gem/trust'
+ expected = File.join Gem.user_home, ".gem/trust"
assert_equal expected, trust_dir.dir
end
def test_class_write
- key = @SEC.create_key 1024
+ key = Gem::Security.create_key "rsa"
- path = File.join @tempdir, 'test-private_key.pem'
+ path = File.join @tempdir, "test-private_key.pem"
- @SEC.write key, path
+ Gem::Security.write key, path
assert_path_exist path
@@ -273,13 +296,13 @@ class TestGemSecurity < Gem::TestCase
end
def test_class_write_encrypted
- key = @SEC.create_key 1024
+ key = Gem::Security.create_key "rsa"
- path = File.join @tempdir, 'test-private_encrypted_key.pem'
+ path = File.join @tempdir, "test-private_encrypted_key.pem"
- passphrase = 'It should be long.'
+ passphrase = "It should be long."
- @SEC.write key, path, 0600, passphrase
+ Gem::Security.write key, path, 0o600, passphrase
assert_path_exist path
@@ -289,15 +312,15 @@ class TestGemSecurity < Gem::TestCase
end
def test_class_write_encrypted_cipher
- key = @SEC.create_key 1024
+ key = Gem::Security.create_key "rsa"
- path = File.join @tempdir, 'test-private_encrypted__with_non_default_cipher_key.pem'
+ path = File.join @tempdir, "test-private_encrypted__with_non_default_cipher_key.pem"
- passphrase = 'It should be long.'
+ passphrase = "It should be long."
- cipher = OpenSSL::Cipher.new 'AES-192-CBC'
+ cipher = OpenSSL::Cipher.new "AES-192-CBC"
- @SEC.write key, path, 0600, passphrase, cipher
+ Gem::Security.write key, path, 0o600, passphrase, cipher
assert_path_exist path
diff --git a/test/rubygems/test_gem_security_policy.rb b/test/rubygems/test_gem_security_policy.rb
index 515b8ea00b..2f4fb1ce28 100644
--- a/test/rubygems/test_gem_security_policy.rb
+++ b/test/rubygems/test_gem_security_policy.rb
@@ -1,39 +1,39 @@
# frozen_string_literal: true
-require_relative 'helper'
+require_relative "helper"
unless Gem::HAVE_OPENSSL
- warn 'Skipping Gem::Security::Policy tests. openssl not found.'
+ warn "Skipping Gem::Security::Policy tests. openssl not found."
end
class TestGemSecurityPolicy < Gem::TestCase
- ALTERNATE_KEY = load_key 'alternate'
- INVALID_KEY = load_key 'invalid'
- CHILD_KEY = load_key 'child'
- GRANDCHILD_KEY = load_key 'grandchild'
- INVALIDCHILD_KEY = load_key 'invalidchild'
-
- ALTERNATE_CERT = load_cert 'alternate'
- CA_CERT = load_cert 'ca'
- CHILD_CERT = load_cert 'child'
- EXPIRED_CERT = load_cert 'expired'
- FUTURE_CERT = load_cert 'future'
- GRANDCHILD_CERT = load_cert 'grandchild'
- INVALIDCHILD_CERT = load_cert 'invalidchild'
- INVALID_ISSUER_CERT = load_cert 'invalid_issuer'
- INVALID_SIGNER_CERT = load_cert 'invalid_signer'
- WRONG_KEY_CERT = load_cert 'wrong_key'
+ ALTERNATE_KEY = load_key "alternate"
+ INVALID_KEY = load_key "invalid"
+ CHILD_KEY = load_key "child"
+ GRANDCHILD_KEY = load_key "grandchild"
+ INVALIDCHILD_KEY = load_key "invalidchild"
+
+ ALTERNATE_CERT = load_cert "alternate"
+ CA_CERT = load_cert "ca"
+ CHILD_CERT = load_cert "child"
+ EXPIRED_CERT = load_cert "expired"
+ FUTURE_CERT = load_cert "future"
+ GRANDCHILD_CERT = load_cert "grandchild"
+ INVALIDCHILD_CERT = load_cert "invalidchild"
+ INVALID_ISSUER_CERT = load_cert "invalid_issuer"
+ INVALID_SIGNER_CERT = load_cert "invalid_signer"
+ WRONG_KEY_CERT = load_cert "wrong_key"
def setup
super
- @spec = quick_gem 'a' do |s|
- s.description = 'Ï€'
+ @spec = quick_gem "a" do |s|
+ s.description = "Ï€"
s.files = %w[lib/code.rb]
end
@digest = OpenSSL::Digest.new Gem::Security::DIGEST_NAME
- @trust_dir = Gem::Security.trust_dir.dir # HACK use the object
+ @trust_dir = Gem::Security.trust_dir.dir # HACK: use the object
@no = Gem::Security::NoSecurity
@almost_no = Gem::Security::AlmostNoSecurity
@@ -42,28 +42,28 @@ class TestGemSecurityPolicy < Gem::TestCase
@high = Gem::Security::HighSecurity
@chain = Gem::Security::Policy.new(
- 'Chain',
- :verify_data => true,
- :verify_signer => true,
- :verify_chain => true,
- :verify_root => false,
- :only_trusted => false,
- :only_signed => false
+ "Chain",
+ verify_data: true,
+ verify_signer: true,
+ verify_chain: true,
+ verify_root: false,
+ only_trusted: false,
+ only_signed: false
)
@root = Gem::Security::Policy.new(
- 'Root',
- :verify_data => true,
- :verify_signer => true,
- :verify_chain => true,
- :verify_root => true,
- :only_trusted => false,
- :only_signed => false
+ "Root",
+ verify_data: true,
+ verify_signer: true,
+ verify_chain: true,
+ verify_root: true,
+ only_trusted: false,
+ only_signed: false
)
end
def test_check_data
- data = digest 'hello'
+ data = digest "hello"
signature = sign data
@@ -71,17 +71,17 @@ class TestGemSecurityPolicy < Gem::TestCase
end
def test_check_data_invalid
- data = digest 'hello'
+ data = digest "hello"
signature = sign data
- invalid = digest 'hello!'
+ invalid = digest "hello!"
e = assert_raise Gem::Security::Exception do
@almost_no.check_data PUBLIC_KEY, @digest, signature, invalid
end
- assert_equal 'invalid signature', e.message
+ assert_equal "invalid signature", e.message
end
def test_check_chain
@@ -95,7 +95,7 @@ class TestGemSecurityPolicy < Gem::TestCase
@chain.check_chain [], Time.now
end
- assert_equal 'empty signing chain', e.message
+ assert_equal "empty signing chain", e.message
end
def test_check_chain_invalid
@@ -105,8 +105,8 @@ class TestGemSecurityPolicy < Gem::TestCase
@chain.check_chain chain, Time.now
end
- assert_equal "invalid signing chain: " +
- "certificate #{INVALIDCHILD_CERT.subject} " +
+ assert_equal "invalid signing chain: " \
+ "certificate #{INVALIDCHILD_CERT.subject} " \
"was not issued by #{CHILD_CERT.subject}", e.message
end
@@ -115,7 +115,7 @@ class TestGemSecurityPolicy < Gem::TestCase
@chain.check_chain nil, Time.now
end
- assert_equal 'missing signing chain', e.message
+ assert_equal "missing signing chain", e.message
end
def test_check_cert
@@ -127,7 +127,7 @@ class TestGemSecurityPolicy < Gem::TestCase
@low.check_cert EXPIRED_CERT, nil, Time.now
end
- assert_equal "certificate #{EXPIRED_CERT.subject} " +
+ assert_equal "certificate #{EXPIRED_CERT.subject} " \
"not valid after #{EXPIRED_CERT.not_after}",
e.message
end
@@ -137,7 +137,7 @@ class TestGemSecurityPolicy < Gem::TestCase
@low.check_cert FUTURE_CERT, nil, Time.now
end
- assert_equal "certificate #{FUTURE_CERT.subject} " +
+ assert_equal "certificate #{FUTURE_CERT.subject} " \
"not valid before #{FUTURE_CERT.not_before}",
e.message
end
@@ -147,7 +147,7 @@ class TestGemSecurityPolicy < Gem::TestCase
@low.check_cert INVALID_ISSUER_CERT, PUBLIC_CERT, Time.now
end
- assert_equal "certificate #{INVALID_ISSUER_CERT.subject} " +
+ assert_equal "certificate #{INVALID_ISSUER_CERT.subject} " \
"was not issued by #{PUBLIC_CERT.subject}",
e.message
end
@@ -161,7 +161,7 @@ class TestGemSecurityPolicy < Gem::TestCase
@high.check_cert(nil, nil, Time.now)
end
- assert_equal 'missing signing certificate', e.message
+ assert_equal "missing signing certificate", e.message
end
def test_check_key
@@ -175,7 +175,7 @@ class TestGemSecurityPolicy < Gem::TestCase
@high.check_key(nil, nil)
end
- assert_equal 'missing key or signature', e.message
+ assert_equal "missing key or signature", e.message
end
def test_check_key_wrong_key
@@ -183,7 +183,7 @@ class TestGemSecurityPolicy < Gem::TestCase
@almost_no.check_key(PUBLIC_CERT, ALTERNATE_KEY)
end
- assert_equal "certificate #{PUBLIC_CERT.subject} " +
+ assert_equal "certificate #{PUBLIC_CERT.subject} " \
"does not match the signing key", e.message
end
@@ -198,7 +198,7 @@ class TestGemSecurityPolicy < Gem::TestCase
@chain.check_root [], Time.now
end
- assert_equal 'missing root certificate', e.message
+ assert_equal "missing root certificate", e.message
end
def test_check_root_invalid_signer
@@ -208,7 +208,7 @@ class TestGemSecurityPolicy < Gem::TestCase
@chain.check_root chain, Time.now
end
- assert_equal "certificate #{INVALID_SIGNER_CERT.subject} " +
+ assert_equal "certificate #{INVALID_SIGNER_CERT.subject} " \
"was not issued by #{INVALID_SIGNER_CERT.issuer}",
e.message
end
@@ -220,7 +220,7 @@ class TestGemSecurityPolicy < Gem::TestCase
@chain.check_root chain, Time.now
end
- assert_equal "root certificate #{INVALID_ISSUER_CERT.subject} " +
+ assert_equal "root certificate #{INVALID_ISSUER_CERT.subject} " \
"is not self-signed (issuer #{INVALID_ISSUER_CERT.issuer})",
e.message
end
@@ -230,7 +230,7 @@ class TestGemSecurityPolicy < Gem::TestCase
@chain.check_root nil, Time.now
end
- assert_equal 'missing signing chain', e.message
+ assert_equal "missing signing chain", e.message
end
def test_check_trust
@@ -250,7 +250,7 @@ class TestGemSecurityPolicy < Gem::TestCase
@chain.check_trust [], @digest, @trust_dir
end
- assert_equal 'missing root certificate', e.message
+ assert_equal "missing root certificate", e.message
end
def test_check_trust_mismatch
@@ -260,7 +260,7 @@ class TestGemSecurityPolicy < Gem::TestCase
@high.check_trust [WRONG_KEY_CERT], @digest, @trust_dir
end
- assert_equal "trusted root certificate #{PUBLIC_CERT.subject} checksum " +
+ assert_equal "trusted root certificate #{PUBLIC_CERT.subject} checksum " \
"does not match signing root certificate checksum", e.message
end
@@ -269,7 +269,7 @@ class TestGemSecurityPolicy < Gem::TestCase
@chain.check_trust nil, @digest, @trust_dir
end
- assert_equal 'missing signing chain', e.message
+ assert_equal "missing signing chain", e.message
end
def test_check_trust_no_trust
@@ -285,13 +285,13 @@ class TestGemSecurityPolicy < Gem::TestCase
@high.check_trust [PUBLIC_CERT, CHILD_CERT], @digest, @trust_dir
end
- assert_equal "root cert #{PUBLIC_CERT.subject} is not trusted " +
+ assert_equal "root cert #{PUBLIC_CERT.subject} is not trusted " \
"(root of signing cert #{CHILD_CERT.subject})", e.message
end
def test_subject
- assert_equal 'email:nobody@example', @no.subject(PUBLIC_CERT)
- assert_equal '/C=JP/ST=Tokyo/O=RubyGemsTest/CN=CA', @no.subject(CA_CERT)
+ assert_equal "email:nobody@example", @no.subject(PUBLIC_CERT)
+ assert_equal "/C=JP/ST=Tokyo/O=RubyGemsTest/CN=CA", @no.subject(CA_CERT)
end
def test_verify
@@ -319,7 +319,7 @@ class TestGemSecurityPolicy < Gem::TestCase
@almost_no.verify [PUBLIC_CERT], nil, {}, signatures
end
- assert_equal 'no digests provided (probable bug)', e.message
+ assert_equal "no digests provided (probable bug)", e.message
end
def test_verify_no_digests_no_security
@@ -331,7 +331,7 @@ class TestGemSecurityPolicy < Gem::TestCase
@no.verify [PUBLIC_CERT], nil, {}, signatures
end
- assert_equal 'missing digest for 0', e.message
+ assert_equal "missing digest for 0", e.message
end
def test_verify_no_signatures
@@ -340,7 +340,7 @@ class TestGemSecurityPolicy < Gem::TestCase
digests, = dummy_signatures
use_ui @ui do
- @no.verify [PUBLIC_CERT], nil, digests, {}, 'some_gem'
+ @no.verify [PUBLIC_CERT], nil, digests, {}, "some_gem"
end
assert_match "WARNING: some_gem is not signed\n", @ui.error
@@ -354,7 +354,7 @@ class TestGemSecurityPolicy < Gem::TestCase
Gem::Security.trust_dir.trust_cert PUBLIC_CERT
use_ui @ui do
- @no.verify [PUBLIC_CERT], nil, {}, {}, 'some_gem'
+ @no.verify [PUBLIC_CERT], nil, {}, {}, "some_gem"
end
assert_empty @ui.output
@@ -366,7 +366,7 @@ class TestGemSecurityPolicy < Gem::TestCase
digests, signatures = dummy_signatures
- data = digest 'goodbye'
+ data = digest "goodbye"
signatures[1] = PRIVATE_KEY.sign @digest.new, data.digest
@@ -374,14 +374,14 @@ class TestGemSecurityPolicy < Gem::TestCase
@almost_no.verify [PUBLIC_CERT], nil, digests, signatures
end
- assert_equal 'missing digest for 1', e.message
+ assert_equal "missing digest for 1", e.message
end
def test_verify_no_trust
digests, signatures = dummy_signatures
use_ui @ui do
- @low.verify [PUBLIC_CERT], nil, digests, signatures, 'some_gem'
+ @low.verify [PUBLIC_CERT], nil, digests, signatures, "some_gem"
end
assert_equal "WARNING: email:nobody@example is not trusted for some_gem\n",
@@ -395,18 +395,18 @@ class TestGemSecurityPolicy < Gem::TestCase
def test_verify_wrong_digest_type
Gem::Security.trust_dir.trust_cert PUBLIC_CERT
- data = OpenSSL::Digest.new('SHA512')
- data << 'hello'
+ data = OpenSSL::Digest.new("SHA512")
+ data << "hello"
- digests = { 'SHA512' => { 0 => data } }
- signature = PRIVATE_KEY.sign 'sha512', data.digest
+ digests = { "SHA512" => { 0 => data } }
+ signature = PRIVATE_KEY.sign "sha512", data.digest
signatures = { 0 => signature }
e = assert_raise Gem::Security::Exception do
@almost_no.verify [PUBLIC_CERT], nil, digests, signatures
end
- assert_equal 'no digests provided (probable bug)', e.message
+ assert_equal "no digests provided (probable bug)", e.message
end
def test_verify_signatures_chain
@@ -448,17 +448,19 @@ class TestGemSecurityPolicy < Gem::TestCase
metadata_gz = Gem::Util.gzip @spec.to_yaml
- package = Gem::Package.new 'nonexistent.gem'
+ package = Gem::Package.new "nonexistent.gem"
package.checksums[Gem::Security::DIGEST_NAME] = {}
s = StringIO.new metadata_gz
- def s.full_name() 'metadata.gz' end
+ def s.full_name
+ "metadata.gz"
+ end
digests = package.digest s
- metadata_gz_digest = digests[Gem::Security::DIGEST_NAME]['metadata.gz']
+ metadata_gz_digest = digests[Gem::Security::DIGEST_NAME]["metadata.gz"]
signatures = {}
- signatures['metadata.gz'] =
+ signatures["metadata.gz"] =
PRIVATE_KEY.sign @digest.new, metadata_gz_digest.digest
assert @high.verify_signatures @spec, digests, signatures
@@ -471,26 +473,28 @@ class TestGemSecurityPolicy < Gem::TestCase
metadata_gz = Gem::Util.gzip @spec.to_yaml
- package = Gem::Package.new 'nonexistent.gem'
+ package = Gem::Package.new "nonexistent.gem"
package.checksums[Gem::Security::DIGEST_NAME] = {}
s = StringIO.new metadata_gz
- def s.full_name() 'metadata.gz' end
+ def s.full_name
+ "metadata.gz"
+ end
digests = package.digest s
- digests[Gem::Security::DIGEST_NAME]['data.tar.gz'] = @digest.hexdigest 'hello'
+ digests[Gem::Security::DIGEST_NAME]["data.tar.gz"] = @digest.hexdigest "hello"
- metadata_gz_digest = digests[Gem::Security::DIGEST_NAME]['metadata.gz']
+ metadata_gz_digest = digests[Gem::Security::DIGEST_NAME]["metadata.gz"]
signatures = {}
- signatures['metadata.gz'] =
+ signatures["metadata.gz"] =
PRIVATE_KEY.sign @digest.new, metadata_gz_digest.digest
e = assert_raise Gem::Security::Exception do
@high.verify_signatures @spec, digests, signatures
end
- assert_equal 'missing signature for data.tar.gz', e.message
+ assert_equal "missing signature for data.tar.gz", e.message
end
def test_verify_signatures_none
@@ -500,14 +504,16 @@ class TestGemSecurityPolicy < Gem::TestCase
metadata_gz = Gem::Util.gzip @spec.to_yaml
- package = Gem::Package.new 'nonexistent.gem'
+ package = Gem::Package.new "nonexistent.gem"
package.checksums[Gem::Security::DIGEST_NAME] = {}
s = StringIO.new metadata_gz
- def s.full_name() 'metadata.gz' end
+ def s.full_name
+ "metadata.gz"
+ end
digests = package.digest s
- digests[Gem::Security::DIGEST_NAME]['data.tar.gz'] = @digest.hexdigest 'hello'
+ digests[Gem::Security::DIGEST_NAME]["data.tar.gz"] = @digest.hexdigest "hello"
assert_raise Gem::Security::Exception do
@high.verify_signatures @spec, digests, {}
@@ -525,11 +531,11 @@ class TestGemSecurityPolicy < Gem::TestCase
end
def dummy_signatures(key = PRIVATE_KEY)
- data = digest 'hello'
+ data = digest "hello"
digests = { Gem::Security::DIGEST_NAME => { 0 => data } }
signatures = { 0 => sign(data, key) }
- return digests, signatures
+ [digests, signatures]
end
end if Gem::HAVE_OPENSSL
diff --git a/test/rubygems/test_gem_security_signer.rb b/test/rubygems/test_gem_security_signer.rb
index 7bd6510b50..f4799cbd46 100644
--- a/test/rubygems/test_gem_security_signer.rb
+++ b/test/rubygems/test_gem_security_signer.rb
@@ -1,18 +1,19 @@
# frozen_string_literal: true
-require_relative 'helper'
+
+require_relative "helper"
unless Gem::HAVE_OPENSSL
- warn 'Skipping Gem::Security::Signer tests. openssl not found.'
+ warn "Skipping Gem::Security::Signer tests. openssl not found."
end
class TestGemSecuritySigner < Gem::TestCase
- ALTERNATE_KEY = load_key 'alternate'
- CHILD_KEY = load_key 'child'
- GRANDCHILD_KEY = load_key 'grandchild'
+ ALTERNATE_KEY = load_key "alternate"
+ CHILD_KEY = load_key "child"
+ GRANDCHILD_KEY = load_key "grandchild"
- CHILD_CERT = load_cert 'child'
- GRANDCHILD_CERT = load_cert 'grandchild'
- EXPIRED_CERT = load_cert 'expired'
+ CHILD_CERT = load_cert "child"
+ GRANDCHILD_CERT = load_cert "grandchild"
+ EXPIRED_CERT = load_cert "expired"
def setup
super
@@ -36,36 +37,36 @@ class TestGemSecuritySigner < Gem::TestCase
def test_initialize_cert_chain_mixed
signer = Gem::Security::Signer.new nil, [@cert_file, CHILD_CERT]
- assert_equal [PUBLIC_CERT, CHILD_CERT].map {|c| c.to_pem },
- signer.cert_chain.map {|c| c.to_pem }
+ assert_equal [PUBLIC_CERT, CHILD_CERT].map(&:to_pem),
+ signer.cert_chain.map(&:to_pem)
end
def test_initialize_cert_chain_invalid
assert_raise OpenSSL::X509::CertificateError do
- Gem::Security::Signer.new nil, ['garbage']
+ Gem::Security::Signer.new nil, ["garbage"]
end
end
def test_initialize_cert_chain_path
signer = Gem::Security::Signer.new nil, [@cert_file]
- assert_equal [PUBLIC_CERT].map {|c| c.to_pem },
- signer.cert_chain.map {|c| c.to_pem }
+ assert_equal [PUBLIC_CERT].map(&:to_pem),
+ signer.cert_chain.map(&:to_pem)
end
def test_initialize_default
- FileUtils.mkdir_p File.join(Gem.user_home, '.gem')
+ FileUtils.mkdir_p File.join(Gem.user_home, ".gem")
- private_key_path = File.join Gem.user_home, '.gem', 'gem-private_key.pem'
+ private_key_path = File.join Gem.user_home, ".gem", "gem-private_key.pem"
Gem::Security.write PRIVATE_KEY, private_key_path
- public_cert_path = File.join Gem.user_home, '.gem', 'gem-public_cert.pem'
+ public_cert_path = File.join Gem.user_home, ".gem", "gem-public_cert.pem"
Gem::Security.write PUBLIC_CERT, public_cert_path
signer = Gem::Security::Signer.new nil, nil
assert_equal PRIVATE_KEY.to_pem, signer.key.to_pem
- assert_equal [PUBLIC_CERT.to_pem], signer.cert_chain.map {|c| c.to_pem }
+ assert_equal [PUBLIC_CERT.to_pem], signer.cert_chain.map(&:to_pem)
end
def test_initialize_key_path
@@ -87,7 +88,7 @@ class TestGemSecuritySigner < Gem::TestCase
def test_extract_name
signer = Gem::Security::Signer.new nil, nil
- assert_equal 'child@example', signer.extract_name(CHILD_CERT)
+ assert_equal "child@example", signer.extract_name(CHILD_CERT)
end
def test_load_cert_chain
@@ -99,7 +100,7 @@ class TestGemSecuritySigner < Gem::TestCase
signer.load_cert_chain
assert_equal [PUBLIC_CERT.to_pem, CHILD_CERT.to_pem],
- signer.cert_chain.map {|c| c.to_pem }
+ signer.cert_chain.map(&:to_pem)
end
def test_load_cert_chain_broken
@@ -111,31 +112,31 @@ class TestGemSecuritySigner < Gem::TestCase
signer.load_cert_chain
assert_equal [CHILD_CERT.to_pem, GRANDCHILD_CERT.to_pem],
- signer.cert_chain.map {|c| c.to_pem }
+ signer.cert_chain.map(&:to_pem)
end
def test_sign
signer = Gem::Security::Signer.new PRIVATE_KEY, [PUBLIC_CERT]
- signature = signer.sign 'hello'
+ signature = signer.sign "hello"
expected = <<-EXPECTED
-cHze2sEfRysoUMCfGVAx/7o8jxj5liJJ2ptNxe2jf3l+EZvyjdqpXo9Ndzxx
-6xLp2rxLG4K2//ip4aCH5Sh7hnia+F5u6iuLBETPlklPrmw5dnuKZxolz+vM
-0O1aOZsQHcVzQoESTGjkms3KZk+gn3lg0sSBbAV5/LyDYoHCEjxlcA5D+Olb
-rDmRyBMOnMS+q489OZ5Hr6B2YJJ3QbUwIZNhUeNmOxIBEYTrrKkZ92qkxbRN
-qhlqFP4jR6zXFeyBCOr0KpTiWBNuxBFXDsxmhGyt2BOIjD6qmKn7RSIfYg/U
-toqvglr0kdbknSRRjBVLK6tsgr07aLT9gNP7mTW2PA==
+FmrCYxEXW3dgYYNMxPdS16VrdXT+d5nyXTVlRm64ZHSgMxMAaPtQJsVYv73m
+DWHTzNnLhhINSpgBMLh5a4atM52yxVdkPUTgqIH+LeIPBXn8xaP5JLmfDcmI
+tBpc/9DhS3v9iKCX40igAArFu7Gg3swbgQ61SP+U22LvG5nDQZQz3sudtsw3
+qKPykFVaYjrRwzvBdSdJ1PwlAsanSwcwS/GKPtmE/ykZ6X5XOx7wvCDL/zGy
+B8khkB8hDKC6moCzebmUxCBmTmXD0Wjzon+bf4MOriVE3a0ySGRvpr1mKR2+
+9EaVo7pDJLEM487+xg1CAZHRhwshd6II00XEzG/jBQ==
EXPECTED
- assert_equal expected, [signature].pack('m')
+ assert_equal expected, [signature].pack("m")
end
def test_sign_expired
signer = Gem::Security::Signer.new PRIVATE_KEY, [EXPIRED_CERT]
e = assert_raise Gem::Security::Exception do
- signer.sign 'hello'
+ signer.sign "hello"
end
assert_match "certificate /CN=nobody/DC=example not valid after 1970-01-01 00:00:00 UTC", e.message
@@ -143,17 +144,17 @@ toqvglr0kdbknSRRjBVLK6tsgr07aLT9gNP7mTW2PA==
def test_sign_expired_auto_update
pend if Gem.java_platform?
- FileUtils.mkdir_p File.join(Gem.user_home, '.gem'), :mode => 0700
+ FileUtils.mkdir_p File.join(Gem.user_home, ".gem"), mode: 0o700
- private_key_path = File.join(Gem.user_home, '.gem', 'gem-private_key.pem')
+ private_key_path = File.join(Gem.user_home, ".gem", "gem-private_key.pem")
Gem::Security.write PRIVATE_KEY, private_key_path
- cert_path = File.join Gem.user_home, '.gem', 'gem-public_cert.pem'
+ cert_path = File.join Gem.user_home, ".gem", "gem-public_cert.pem"
Gem::Security.write EXPIRED_CERT, cert_path
signer = Gem::Security::Signer.new PRIVATE_KEY, [EXPIRED_CERT]
- signer.sign 'hello'
+ signer.sign "hello"
cert = OpenSSL::X509::Certificate.new File.read cert_path
@@ -163,14 +164,14 @@ toqvglr0kdbknSRRjBVLK6tsgr07aLT9gNP7mTW2PA==
expiry = EXPIRED_CERT.not_after.strftime "%Y%m%d%H%M%S"
expired_path =
- File.join Gem.user_home, '.gem', "gem-public_cert.pem.expired.#{expiry}"
+ File.join Gem.user_home, ".gem", "gem-public_cert.pem.expired.#{expiry}"
assert_path_exist expired_path
assert_equal EXPIRED_CERT.to_pem, File.read(expired_path)
end
def test_sign_expired_auto_update_exists
- FileUtils.mkdir_p File.join(Gem.user_home, '.gem'), :mode => 0700
+ FileUtils.mkdir_p File.join(Gem.user_home, ".gem"), mode: 0o700
expiry = EXPIRED_CERT.not_after.strftime "%Y%m%d%H%M%S"
expired_path =
@@ -178,16 +179,16 @@ toqvglr0kdbknSRRjBVLK6tsgr07aLT9gNP7mTW2PA==
Gem::Security.write EXPIRED_CERT, expired_path
- private_key_path = File.join(Gem.user_home, 'gem-private_key.pem')
+ private_key_path = File.join(Gem.user_home, "gem-private_key.pem")
Gem::Security.write PRIVATE_KEY, private_key_path
- cert_path = File.join Gem.user_home, 'gem-public_cert.pem'
+ cert_path = File.join Gem.user_home, "gem-public_cert.pem"
Gem::Security.write EXPIRED_CERT, cert_path
signer = Gem::Security::Signer.new PRIVATE_KEY, [EXPIRED_CERT]
e = assert_raise Gem::Security::Exception do
- signer.sign 'hello'
+ signer.sign "hello"
end
assert_match %r{certificate /CN=nobody/DC=example not valid}, e.message
@@ -196,14 +197,14 @@ toqvglr0kdbknSRRjBVLK6tsgr07aLT9gNP7mTW2PA==
def test_sign_no_key
signer = Gem::Security::Signer.new nil, nil
- assert_nil signer.sign 'stuff'
+ assert_nil signer.sign "stuff"
end
def test_sign_wrong_key
signer = Gem::Security::Signer.new ALTERNATE_KEY, [PUBLIC_CERT]
assert_raise Gem::Security::Exception do
- signer.sign 'hello'
+ signer.sign "hello"
end
end
@@ -211,7 +212,7 @@ toqvglr0kdbknSRRjBVLK6tsgr07aLT9gNP7mTW2PA==
signer = Gem::Security::Signer.new ALTERNATE_KEY, []
assert_raise Gem::Security::Exception do
- signer.sign 'hello'
+ signer.sign "hello"
end
end
end if Gem::HAVE_OPENSSL
diff --git a/test/rubygems/test_gem_security_trust_dir.rb b/test/rubygems/test_gem_security_trust_dir.rb
index fc88c84865..cfde8e9d48 100644
--- a/test/rubygems/test_gem_security_trust_dir.rb
+++ b/test/rubygems/test_gem_security_trust_dir.rb
@@ -1,17 +1,18 @@
# frozen_string_literal: true
-require_relative 'helper'
+
+require_relative "helper"
unless Gem::HAVE_OPENSSL
- warn 'Skipping Gem::Security::TrustDir tests. openssl not found.'
+ warn "Skipping Gem::Security::TrustDir tests. openssl not found."
end
class TestGemSecurityTrustDir < Gem::TestCase
- CHILD_CERT = load_cert 'child'
+ CHILD_CERT = load_cert "child"
def setup
super
- @dest_dir = File.join @tempdir, 'trust'
+ @dest_dir = File.join @tempdir, "trust"
@trust_dir = Gem::Security::TrustDir.new @dest_dir
end
@@ -55,9 +56,9 @@ class TestGemSecurityTrustDir < Gem::TestCase
assert_path_exist trusted
- mask = 0100600 & (~File.umask)
+ mask = 0o100600 & (~File.umask)
- assert_equal mask, File.stat(trusted).mode unless win_platform?
+ assert_equal mask, File.stat(trusted).mode unless Gem.win_platform?
assert_equal PUBLIC_CERT.to_pem, File.read(trusted)
end
@@ -69,10 +70,10 @@ class TestGemSecurityTrustDir < Gem::TestCase
assert_path_exist @dest_dir
- mask = 040700 & (~File.umask)
- mask |= 0200000 if /aix/ =~ RUBY_PLATFORM
+ mask = 0o040700 & (~File.umask)
+ mask |= 0o200000 if RUBY_PLATFORM.include?("aix")
- assert_equal mask, File.stat(@dest_dir).mode unless win_platform?
+ assert_equal mask, File.stat(@dest_dir).mode unless Gem.win_platform?
end
def test_verify_file
@@ -86,13 +87,13 @@ class TestGemSecurityTrustDir < Gem::TestCase
end
def test_verify_wrong_permissions
- FileUtils.mkdir_p @dest_dir, :mode => 0777
+ FileUtils.mkdir_p @dest_dir, mode: 0o777
@trust_dir.verify
- mask = 040700 & (~File.umask)
- mask |= 0200000 if /aix/ =~ RUBY_PLATFORM
+ mask = 0o40700 & (~File.umask)
+ mask |= 0o200000 if RUBY_PLATFORM.include?("aix")
- assert_equal mask, File.stat(@dest_dir).mode unless win_platform?
+ assert_equal mask, File.stat(@dest_dir).mode unless Gem.win_platform?
end
end if Gem::HAVE_OPENSSL
diff --git a/test/rubygems/test_gem_server.rb b/test/rubygems/test_gem_server.rb
deleted file mode 100644
index f6aa99fb02..0000000000
--- a/test/rubygems/test_gem_server.rb
+++ /dev/null
@@ -1,608 +0,0 @@
-# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/server'
-require 'stringio'
-
-class Gem::Server
- attr_reader :server
-end
-
-class TestGemServer < Gem::TestCase
- def process_based_port
- 0
- end
-
- def setup
- super
-
- @a1 = quick_gem 'a', '1'
- @a2 = quick_gem 'a', '2'
- @a3_p = quick_gem 'a', '3.a'
-
- @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_doc_root_3
- orig_rdoc_version = Gem::RDoc.rdoc_version
- Gem::RDoc.instance_variable_set :@rdoc_version, Gem::Version.new('3.12')
-
- assert_equal '/doc_root/X-1/rdoc/index.html', @server.doc_root('X-1')
-
- ensure
- Gem::RDoc.instance_variable_set :@rdoc_version, orig_rdoc_version
- end
-
- def test_doc_root_4
- orig_rdoc_version = Gem::RDoc.rdoc_version
- Gem::RDoc.instance_variable_set :@rdoc_version, Gem::Version.new('4.0')
-
- assert_equal '/doc_root/X-1/', @server.doc_root('X-1')
-
- ensure
- Gem::RDoc.instance_variable_set :@rdoc_version, orig_rdoc_version
- end
-
- def test_have_rdoc_4_plus_eh
- orig_rdoc_version = Gem::RDoc.rdoc_version
- Gem::RDoc.instance_variable_set(:@rdoc_version, Gem::Version.new('4.0'))
-
- server = Gem::Server.new Gem.dir, 0, false
- assert server.have_rdoc_4_plus?
-
- Gem::RDoc.instance_variable_set :@rdoc_version, Gem::Version.new('3.12')
-
- server = Gem::Server.new Gem.dir, 0, false
- refute server.have_rdoc_4_plus?
-
- Gem::RDoc.instance_variable_set(:@rdoc_version,
- Gem::Version.new('4.0.0.preview2'))
-
- server = Gem::Server.new Gem.dir, 0, false
- assert server.have_rdoc_4_plus?
- ensure
- Gem::RDoc.instance_variable_set :@rdoc_version, orig_rdoc_version
- end
-
- def test_spec_dirs
- s = Gem::Server.new Gem.dir, process_based_port, false
-
- assert_equal [File.join(Gem.dir, 'specifications')], s.spec_dirs
-
- s = Gem::Server.new [Gem.dir, Gem.dir], process_based_port, false
-
- assert_equal [File.join(Gem.dir, 'specifications'),
- File.join(Gem.dir, 'specifications')], s.spec_dirs
- end
-
- def test_latest_specs
- data = StringIO.new "GET /latest_specs.#{Gem.marshal_version} HTTP/1.0\r\n\r\n"
- @req.parse data
-
- Gem::Deprecate.skip_during do
- @server.latest_specs @req, @res
- end
-
- 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_gemdirs
- data = StringIO.new "GET /latest_specs.#{Gem.marshal_version} HTTP/1.0\r\n\r\n"
- dir = "#{@gemhome}2"
-
- spec = util_spec 'z', 9
-
- specs_dir = File.join dir, 'specifications'
- FileUtils.mkdir_p specs_dir
-
- File.open File.join(specs_dir, spec.spec_name), 'w' do |io|
- io.write spec.to_ruby
- end
-
- server = Gem::Server.new dir, process_based_port, false
-
- @req.parse data
-
- server.latest_specs @req, @res
-
- assert_equal 200, @res.status
-
- assert_equal [['z', v(9), 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
-
- Gem::Deprecate.skip_during do
- @server.latest_specs @req, @res
- end
-
- 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::Util.gunzip(@res.body))
- end
-
- def test_listen
- util_listen
-
- capture_output do
- @server.listen
- end
-
- assert_equal 1, @server.server.listeners.length
- end
-
- def test_listen_addresses
- util_listen
-
- capture_output do
- @server.listen %w[a b]
- end
-
- assert_equal 2, @server.server.listeners.length
- end
-
- def test_prerelease_specs
- data = StringIO.new "GET /prerelease_specs.#{Gem.marshal_version} HTTP/1.0\r\n\r\n"
- @req.parse data
-
- Gem::Deprecate.skip_during do
- @server.prerelease_specs @req, @res
- end
-
- 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', v('3.a'), Gem::Platform::RUBY]],
- Marshal.load(@res.body)
- end
-
- def test_prerelease_specs_gz
- data = StringIO.new "GET /prerelease_specs.#{Gem.marshal_version}.gz HTTP/1.0\r\n\r\n"
- @req.parse data
-
- Gem::Deprecate.skip_during do
- @server.prerelease_specs @req, @res
- end
-
- 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', v('3.a'), Gem::Platform::RUBY]],
- Marshal.load(Gem::Util.gunzip(@res.body))
- end
-
- def test_quick_gemdirs
- data = StringIO.new "GET /quick/Marshal.4.8/z-9.gemspec.rz HTTP/1.0\r\n\r\n"
- dir = "#{@gemhome}2"
-
- server = Gem::Server.new dir, process_based_port, false
-
- @req.parse data
-
- server.quick @req, @res
-
- assert_equal 404, @res.status
-
- spec = util_spec 'z', 9
-
- specs_dir = File.join dir, 'specifications'
-
- FileUtils.mkdir_p specs_dir
-
- File.open File.join(specs_dir, spec.spec_name), 'w' do |io|
- io.write spec.to_ruby
- end
-
- data.rewind
-
- req = WEBrick::HTTPRequest.new :Logger => nil
- res = WEBrick::HTTPResponse.new :HTTPVersion => '1.0'
- req.parse data
-
- server.quick req, res
-
- assert_equal 200, res.status
- end
-
- def test_quick_missing
- data = StringIO.new "GET /quick/Marshal.4.8/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"', @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::Util.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
- 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::Util.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_marshal_a_3_a_gemspec_rz
- data = StringIO.new "GET /quick/Marshal.#{Gem.marshal_version}/a-3.a.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::Util.inflate(@res.body)
- assert_equal 'a', spec.name
- assert_equal v('3.a'), spec.version
- end
-
- def test_quick_marshal_a_b_3_a_gemspec_rz
- quick_gem 'a-b', '3.a'
-
- data = StringIO.new "GET /quick/Marshal.#{Gem.marshal_version}/a-b-3.a.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::Util.inflate(@res.body)
- assert_equal 'a-b', spec.name
- assert_equal v('3.a'), spec.version
- end
-
- def test_quick_marshal_a_b_1_3_a_gemspec_rz
- quick_gem 'a-b-1', '3.a'
-
- data = StringIO.new "GET /quick/Marshal.#{Gem.marshal_version}/a-b-1-3.a.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::Util.inflate(@res.body)
- assert_equal 'a-b-1', spec.name
- assert_equal v('3.a'), spec.version
- end
-
- def test_rdoc
- data = StringIO.new "GET /rdoc?q=a HTTP/1.0\r\n\r\n"
- @req.parse data
-
- @server.rdoc @req, @res
-
- assert_equal 200, @res.status, @res.body
- assert_match %r{No documentation found}, @res.body
- assert_equal 'text/html', @res['content-type']
- 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_root_gemdirs
- data = StringIO.new "GET / HTTP/1.0\r\n\r\n"
- dir = "#{@gemhome}2"
-
- spec = util_spec 'z', 9
-
- specs_dir = File.join dir, 'specifications'
- FileUtils.mkdir_p specs_dir
-
- File.open File.join(specs_dir, spec.spec_name), 'w' do |io|
- io.write spec.to_ruby
- end
-
- server = Gem::Server.new dir, process_based_port, false
-
- @req.parse data
-
- server.root @req, @res
-
- assert_equal 200, @res.status
- assert_match 'z 9', @res.body
- end
-
- def test_xss_homepage_fix_289313
- data = StringIO.new "GET / HTTP/1.0\r\n\r\n"
- dir = "#{@gemhome}2"
-
- spec = util_spec 'xsshomepagegem', 1
- spec.homepage = "javascript:confirm(document.domain)"
-
- specs_dir = File.join dir, 'specifications'
- FileUtils.mkdir_p specs_dir
-
- File.open File.join(specs_dir, spec.spec_name), 'w' do |io|
- io.write spec.to_ruby
- end
-
- server = Gem::Server.new dir, process_based_port, false
-
- @req.parse data
-
- server.root @req, @res
-
- assert_equal 200, @res.status
- assert_match 'xsshomepagegem 1', @res.body
-
- # This verifies that the homepage for this spec is not displayed and is set to ".", because it's not a
- # valid HTTP/HTTPS URL and could be unsafe in an HTML context. We would prefer to throw an exception here,
- # but spec.homepage is currently free form and not currently required to be a URL, this behavior may be
- # validated in future versions of Gem::Specification.
- #
- # There are two variant we're checking here, one where rdoc is not present, and one where rdoc is present in the same regex:
- #
- # Variant #1 - rdoc not installed
- #
- # <b>xsshomepagegem 1</b>
- #
- #
- # <span title="rdoc not installed">[rdoc]</span>
- #
- #
- #
- # <a href="." title=".">[www]</a>
- #
- # Variant #2 - rdoc installed
- #
- # <b>xsshomepagegem 1</b>
- #
- #
- # <a href="\/doc_root\/xsshomepagegem-1\/">\[rdoc\]<\/a>
- #
- #
- #
- # <a href="." title=".">[www]</a>
- regex_match = /xsshomepagegem 1<\/b>\s+(<span title="rdoc not installed">\[rdoc\]<\/span>|<a href="\/doc_root\/xsshomepagegem-1\/">\[rdoc\]<\/a>)\s+<a href="\." title="\.">\[www\]<\/a>/
- assert_match regex_match, @res.body
- end
-
- def test_invalid_homepage
- data = StringIO.new "GET / HTTP/1.0\r\n\r\n"
- dir = "#{@gemhome}2"
-
- spec = util_spec 'invalidhomepagegem', 1
- spec.homepage = "notavalidhomepageurl"
-
- specs_dir = File.join dir, 'specifications'
- FileUtils.mkdir_p specs_dir
-
- File.open File.join(specs_dir, spec.spec_name), 'w' do |io|
- io.write spec.to_ruby
- end
-
- server = Gem::Server.new dir, process_based_port, false
-
- @req.parse data
-
- server.root @req, @res
-
- assert_equal 200, @res.status
- assert_match 'invalidhomepagegem 1', @res.body
-
- # This verifies that the homepage for this spec is not displayed and is set to ".", because it's not a
- # valid HTTP/HTTPS URL and could be unsafe in an HTML context. We would prefer to throw an exception here,
- # but spec.homepage is currently free form and not currently required to be a URL, this behavior may be
- # validated in future versions of Gem::Specification.
- #
- # There are two variant we're checking here, one where rdoc is not present, and one where rdoc is present in the same regex:
- #
- # Variant #1 - rdoc not installed
- #
- # <b>invalidhomepagegem 1</b>
- #
- #
- # <span title="rdoc not installed">[rdoc]</span>
- #
- #
- #
- # <a href="." title=".">[www]</a>
- #
- # Variant #2 - rdoc installed
- #
- # <b>invalidhomepagegem 1</b>
- #
- #
- # <a href="\/doc_root\/invalidhomepagegem-1\/">\[rdoc\]<\/a>
- #
- #
- #
- # <a href="." title=".">[www]</a>
- regex_match = /invalidhomepagegem 1<\/b>\s+(<span title="rdoc not installed">\[rdoc\]<\/span>|<a href="\/doc_root\/invalidhomepagegem-1\/">\[rdoc\]<\/a>)\s+<a href="\." title="\.">\[www\]<\/a>/
- assert_match regex_match, @res.body
- end
-
- def test_valid_homepage_http
- data = StringIO.new "GET / HTTP/1.0\r\n\r\n"
- dir = "#{@gemhome}2"
-
- spec = util_spec 'validhomepagegemhttp', 1
- spec.homepage = "http://rubygems.org"
-
- specs_dir = File.join dir, 'specifications'
- FileUtils.mkdir_p specs_dir
-
- File.open File.join(specs_dir, spec.spec_name), 'w' do |io|
- io.write spec.to_ruby
- end
-
- server = Gem::Server.new dir, process_based_port, false
-
- @req.parse data
-
- server.root @req, @res
-
- assert_equal 200, @res.status
- assert_match 'validhomepagegemhttp 1', @res.body
-
- regex_match = /validhomepagegemhttp 1<\/b>\s+(<span title="rdoc not installed">\[rdoc\]<\/span>|<a href="\/doc_root\/validhomepagegemhttp-1\/">\[rdoc\]<\/a>)\s+<a href="http:\/\/rubygems\.org" title="http:\/\/rubygems\.org">\[www\]<\/a>/
- assert_match regex_match, @res.body
- end
-
- def test_valid_homepage_https
- data = StringIO.new "GET / HTTP/1.0\r\n\r\n"
- dir = "#{@gemhome}2"
-
- spec = util_spec 'validhomepagegemhttps', 1
- spec.homepage = "https://rubygems.org"
-
- specs_dir = File.join dir, 'specifications'
- FileUtils.mkdir_p specs_dir
-
- File.open File.join(specs_dir, spec.spec_name), 'w' do |io|
- io.write spec.to_ruby
- end
-
- server = Gem::Server.new dir, process_based_port, false
-
- @req.parse data
-
- server.root @req, @res
-
- assert_equal 200, @res.status
- assert_match 'validhomepagegemhttps 1', @res.body
-
- regex_match = /validhomepagegemhttps 1<\/b>\s+(<span title="rdoc not installed">\[rdoc\]<\/span>|<a href="\/doc_root\/validhomepagegemhttps-1\/">\[rdoc\]<\/a>)\s+<a href="https:\/\/rubygems\.org" title="https:\/\/rubygems\.org">\[www\]<\/a>/
- assert_match regex_match, @res.body
- 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],
- ['a', v('3.a'), Gem::Platform::RUBY]],
- Marshal.load(@res.body)
- end
-
- def test_specs_gemdirs
- data = StringIO.new "GET /specs.#{Gem.marshal_version} HTTP/1.0\r\n\r\n"
- dir = "#{@gemhome}2"
-
- spec = util_spec 'z', 9
-
- specs_dir = File.join dir, 'specifications'
- FileUtils.mkdir_p specs_dir
-
- File.open File.join(specs_dir, spec.spec_name), 'w' do |io|
- io.write spec.to_ruby
- end
-
- server = Gem::Server.new dir, process_based_port, false
-
- @req.parse data
-
- server.specs @req, @res
-
- assert_equal 200, @res.status
-
- assert_equal [['z', v(9), 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],
- ['a', v('3.a'), Gem::Platform::RUBY]],
- Marshal.load(Gem::Util.gunzip(@res.body))
- end
-
- def test_uri_encode
- url_safe = @server.uri_encode 'http://rubyonrails.org/">malicious_content</a>'
- assert_equal url_safe, 'http://rubyonrails.org/%22%3Emalicious_content%3C/a%3E'
- end
-
- # Regression test for issue #1793: incorrect URL encoding.
- # Checking that no URLs have had '://' incorrectly encoded
- def test_regression_1793
- data = StringIO.new "GET / HTTP/1.0\r\n\r\n"
- @req.parse data
-
- @server.root @req, @res
-
- refute_match %r{%3A%2F%2F}, @res.body
- end
-
- def util_listen
- webrick = Object.new
- webrick.instance_variable_set :@listeners, []
- def webrick.listeners() @listeners end
- def webrick.listen(host, port)
- socket = Object.new
- socket.instance_variable_set :@host, host
- socket.instance_variable_set :@port, port
- def socket.addr() [nil, @port, @host] end
- @listeners << socket
- end
-
- @server.instance_variable_set :@server, webrick
- end
-end
diff --git a/test/rubygems/test_gem_silent_ui.rb b/test/rubygems/test_gem_silent_ui.rb
index 355255fb48..001a73eb51 100644
--- a/test/rubygems/test_gem_silent_ui.rb
+++ b/test/rubygems/test_gem_silent_ui.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/user_interaction'
-require 'timeout'
+
+require_relative "helper"
+require "rubygems/user_interaction"
class TestGemSilentUI < Gem::TestCase
def setup
@@ -18,28 +18,28 @@ class TestGemSilentUI < Gem::TestCase
value = nil
out, err = capture_output do
use_ui @sui do
- value = @sui.ask 'Problem?'
+ value = @sui.ask "Problem?"
end
end
- assert_empty out, 'No output'
- assert_empty err, 'No output'
+ assert_empty out, "No output"
+ assert_empty err, "No output"
- assert_nil value, 'No value'
+ assert_nil value, "No value"
end
def test_ask_for_password
value = nil
out, err = capture_output do
use_ui @sui do
- value = @sui.ask_for_password 'Problem?'
+ value = @sui.ask_for_password "Problem?"
end
end
- assert_empty out, 'No output'
- assert_empty err, 'No output'
+ assert_empty out, "No output"
+ assert_empty err, "No output"
- assert_nil value, 'No value'
+ assert_nil value, "No value"
end
def test_ask_yes_no
@@ -47,70 +47,76 @@ class TestGemSilentUI < Gem::TestCase
out, err = capture_output do
use_ui @sui do
assert_raise(Gem::OperationNotSupportedError) do
- @sui.ask_yes_no 'Problem?'
+ @sui.ask_yes_no "Problem?"
end
end
end
- assert_empty out, 'No output'
- assert_empty err, 'No output'
+ assert_empty out, "No output"
+ assert_empty err, "No output"
out, err = capture_output do
use_ui @sui do
- value = @sui.ask_yes_no 'Problem?', true
+ value = @sui.ask_yes_no "Problem?", true
end
end
- assert_empty out, 'No output'
- assert_empty err, 'No output'
+ assert_empty out, "No output"
+ assert_empty err, "No output"
- assert value, 'Value is true'
+ assert value, "Value is true"
out, err = capture_output do
use_ui @sui do
- value = @sui.ask_yes_no 'Problem?', false
+ value = @sui.ask_yes_no "Problem?", false
end
end
- assert_empty out, 'No output'
- assert_empty err, 'No output'
+ assert_empty out, "No output"
+ assert_empty err, "No output"
- assert_equal value, false, 'Value is false'
+ assert_equal value, false, "Value is false"
end
def test_choose_from_list
value = nil
out, err = capture_output do
use_ui @sui do
- value = @sui.choose_from_list 'Problem?', %w[yes no]
+ value = @sui.choose_from_list "Problem?", %w[yes no]
end
end
- assert_empty out, 'No output'
- assert_empty err, 'No output'
+ assert_empty out, "No output"
+ assert_empty err, "No output"
- assert_equal [nil, nil], value, 'Value is nil!'
+ assert_equal [nil, nil], value, "Value is nil!"
end
def test_progress_reporter
out, err = capture_output do
use_ui @sui do
- @sui.progress_reporter 10, 'hi'
+ @sui.progress_reporter 10, "hi"
end
end
- assert_empty out, 'No output'
- assert_empty err, 'No output'
+ assert_empty out, "No output"
+ assert_empty err, "No output"
end
def test_download_reporter
out, err = capture_output do
use_ui @sui do
- @sui.download_reporter.fetch 'a.gem', 1024
+ @sui.download_reporter.fetch "a.gem", 1024
end
end
- assert_empty out, 'No output'
- assert_empty err, 'No output'
+ assert_empty out, "No output"
+ assert_empty err, "No output"
+ end
+
+ def test_new_without_dev_null
+ File.stub(:open, ->(path, _mode) { raise Errno::ENOTCAPABLE if path == IO::NULL }) do
+ Gem::SilentUI.new
+ end
end
end
diff --git a/test/rubygems/test_gem_source.rb b/test/rubygems/test_gem_source.rb
index 24312626f4..423abd6dd2 100644
--- a/test/rubygems/test_gem_source.rb
+++ b/test/rubygems/test_gem_source.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/source'
-require 'rubygems/indexer'
+
+require_relative "helper"
+require "rubygems/source"
class TestGemSource < Gem::TestCase
def tuple(*args)
@@ -12,41 +12,41 @@ class TestGemSource < Gem::TestCase
super
@specs = spec_fetcher do |fetcher|
- fetcher.spec 'a', '1.a'
- fetcher.gem 'a', 1
- fetcher.spec 'a', 2
- fetcher.spec 'b', 2
+ fetcher.spec "a", "1.a"
+ fetcher.gem "a", 1
+ fetcher.spec "a", 2
+ fetcher.spec "b", 2
end
@source = Gem::Source.new(@gem_repo)
end
def test_initialize_invalid_uri
- assert_raise URI::InvalidURIError do
- Gem::Source.new 'git@example:a.git'
+ assert_raise Gem::URI::InvalidURIError do
+ Gem::Source.new "git@example:a.git"
end
end
def test_initialize_git
- repository = 'git@example:a.git'
+ repository = "git@example:a.git"
- source = Gem::Source::Git.new 'a', repository, 'master', false
+ source = Gem::Source::Git.new "a", repository, nil, false
assert_equal repository, source.uri
end
def test_cache_dir_escapes_windows_paths
- uri = URI.parse("file:///C:/WINDOWS/Temp/gem_repo")
+ uri = Gem::URI.parse("file:///C:/WINDOWS/Temp/gem_repo")
root = Gem.spec_cache_dir
- cache_dir = @source.cache_dir(uri).gsub(root, '')
- assert cache_dir !~ /:/, "#{cache_dir} should not contain a :"
+ cache_dir = @source.cache_dir(uri).gsub(root, "")
+ assert !cache_dir.include?(":"), "#{cache_dir} should not contain a :"
end
def test_dependency_resolver_set_bundler_api
- response = Net::HTTPResponse.new '1.1', 200, 'OK'
- response.uri = URI('http://example')
+ response = Gem::Net::HTTPResponse.new "1.1", 200, "OK"
+ response.uri = Gem::URI("http://example")
- @fetcher.data[@gem_repo] = response
+ @fetcher.data["#{@gem_repo}versions"] = response
set = @source.dependency_resolver_set
@@ -54,7 +54,9 @@ class TestGemSource < Gem::TestCase
end
def test_dependency_resolver_set_file_uri
- Gem::Indexer.new(@tempdir).generate_index
+ empty_dump = Gem::Util.gzip("\x04\x08[\x05".b)
+ File.binwrite(File.join(@tempdir, "prerelease_specs.4.8.gz"), empty_dump)
+ File.binwrite(File.join(@tempdir, "specs.4.8.gz"), empty_dump)
source = Gem::Source.new "file://#{@tempdir}/"
@@ -70,14 +72,14 @@ class TestGemSource < Gem::TestCase
end
def test_fetch_spec
- a1 = @specs['a-1']
+ a1 = @specs["a-1"]
spec_uri = "#{@gem_repo}#{Gem::MARSHAL_SPEC_DIR}#{a1.spec_name}"
- spec = @source.fetch_spec tuple('a', Gem::Version.new(1), 'ruby')
+ spec = @source.fetch_spec tuple("a", Gem::Version.new(1), "ruby")
assert_equal a1.full_name, spec.full_name
- cache_dir = @source.cache_dir URI.parse(spec_uri)
+ cache_dir = @source.cache_dir Gem::URI.parse(spec_uri)
cache_file = File.join cache_dir, a1.spec_name
@@ -85,47 +87,45 @@ class TestGemSource < Gem::TestCase
end
def test_fetch_spec_cached
- a1 = @specs['a-1']
+ a1 = @specs["a-1"]
spec_uri = "#{@gem_repo}/#{Gem::MARSHAL_SPEC_DIR}#{a1.spec_name}"
@fetcher.data["#{spec_uri}.rz"] = nil
- cache_dir = @source.cache_dir URI.parse(spec_uri)
+ cache_dir = @source.cache_dir Gem::URI.parse(spec_uri)
FileUtils.mkdir_p cache_dir
cache_file = File.join cache_dir, a1.spec_name
- File.open cache_file, 'wb' do |io|
+ File.open cache_file, "wb" do |io|
Marshal.dump a1, io
end
- spec = @source.fetch_spec tuple('a', Gem::Version.new(1), 'ruby')
+ spec = @source.fetch_spec tuple("a", Gem::Version.new(1), "ruby")
assert_equal a1.full_name, spec.full_name
end
def test_fetch_spec_platform
- specs = spec_fetcher do |fetcher|
- fetcher.legacy_platform
- end
+ specs = spec_fetcher(&:legacy_platform)
- spec = @source.fetch_spec tuple('pl', Gem::Version.new(1), 'i386-linux')
+ spec = @source.fetch_spec tuple("pl", Gem::Version.new(1), "i386-linux")
- assert_equal specs['pl-1-x86-linux'].full_name, spec.full_name
+ assert_equal specs["pl-1-x86-linux"].full_name, spec.full_name
end
def test_fetch_spec_platform_ruby
- spec = @source.fetch_spec tuple('a', Gem::Version.new(1), nil)
- assert_equal @specs['a-1'].full_name, spec.full_name
+ spec = @source.fetch_spec tuple("a", Gem::Version.new(1), nil)
+ assert_equal @specs["a-1"].full_name, spec.full_name
- spec = @source.fetch_spec tuple('a', Gem::Version.new(1), '')
- assert_equal @specs['a-1'].full_name, spec.full_name
+ spec = @source.fetch_spec tuple("a", Gem::Version.new(1), "")
+ assert_equal @specs["a-1"].full_name, spec.full_name
end
def test_load_specs
- released = @source.load_specs(:released).map {|spec| spec.full_name }
+ released = @source.load_specs(:released).map(&:full_name)
assert_equal %W[a-2 a-1 b-2], released
- cache_dir = File.join Gem.spec_cache_dir, 'gems.example.com%80'
+ cache_dir = File.join Gem.spec_cache_dir, "gems.example.com%80"
assert File.exist?(cache_dir), "#{cache_dir} does not exist"
cache_file = File.join cache_dir, "specs.#{Gem.marshal_version}"
@@ -136,19 +136,19 @@ class TestGemSource < Gem::TestCase
latest_specs = @source.load_specs :latest
# Make sure the cached version is actually different:
- latest_specs << Gem::NameTuple.new('cached', Gem::Version.new('1.0.0'), 'ruby')
+ latest_specs << Gem::NameTuple.new("cached", Gem::Version.new("1.0.0"), "ruby")
@fetcher.data["#{@gem_repo}latest_specs.#{Gem.marshal_version}.gz"] = nil
@fetcher.data["#{@gem_repo}latest_specs.#{Gem.marshal_version}"] =
- ' ' * Marshal.dump(latest_specs).length
+ " " * Marshal.dump(latest_specs).length
- cache_dir = File.join Gem.spec_cache_dir, 'gems.example.com%80'
+ cache_dir = File.join Gem.spec_cache_dir, "gems.example.com%80"
FileUtils.mkdir_p cache_dir
cache_file = File.join cache_dir, "latest_specs.#{Gem.marshal_version}"
- File.open cache_file, 'wb' do |io|
+ File.open cache_file, "wb" do |io|
Marshal.dump latest_specs, io
end
@@ -161,18 +161,18 @@ class TestGemSource < Gem::TestCase
latest_specs = @source.load_specs :latest
# Make sure the cached version is actually different:
- latest_specs << Gem::NameTuple.new('fixed', Gem::Version.new('1.0.0'), 'ruby')
+ latest_specs << Gem::NameTuple.new("fixed", Gem::Version.new("1.0.0"), "ruby")
# Setup valid data on the 'remote'
@fetcher.data["#{@gem_repo}latest_specs.#{Gem.marshal_version}.gz"] =
- util_gzip(Marshal.dump(latest_specs))
+ util_gzip(Marshal.dump(latest_specs))
- cache_dir = File.join Gem.spec_cache_dir, 'gems.example.com%80'
+ cache_dir = File.join Gem.spec_cache_dir, "gems.example.com%80"
FileUtils.mkdir_p cache_dir
cache_file = File.join cache_dir, "latest_specs.#{Gem.marshal_version}"
- File.open cache_file, 'wb' do |io|
+ File.open cache_file, "wb" do |io|
# Setup invalid data in the cache:
io.write Marshal.dump(latest_specs)[0, 10]
end
@@ -192,34 +192,34 @@ class TestGemSource < Gem::TestCase
def test_spaceship
remote = @source
- specific = Gem::Source::SpecificFile.new @specs['a-1'].cache_file
+ specific = Gem::Source::SpecificFile.new @specs["a-1"].cache_file
installed = Gem::Source::Installed.new
local = Gem::Source::Local.new
- assert_equal(0, remote.<=>(remote), 'remote <=> remote')
+ assert_equal(0, remote.<=>(remote), "remote <=> remote") # rubocop:disable Lint/BinaryOperatorWithIdenticalOperands
- assert_equal(-1, remote.<=>(specific), 'remote <=> specific')
- assert_equal(1, specific.<=>(remote), 'specific <=> remote')
+ assert_equal(-1, remote.<=>(specific), "remote <=> specific")
+ assert_equal(1, specific.<=>(remote), "specific <=> remote")
- assert_equal(-1, remote.<=>(local), 'remote <=> local')
- assert_equal(1, local.<=>(remote), 'local <=> remote')
+ assert_equal(-1, remote.<=>(local), "remote <=> local")
+ assert_equal(1, local.<=>(remote), "local <=> remote")
- assert_equal(-1, remote.<=>(installed), 'remote <=> installed')
- assert_equal(1, installed.<=>(remote), 'installed <=> remote')
+ assert_equal(-1, remote.<=>(installed), "remote <=> installed")
+ assert_equal(1, installed.<=>(remote), "installed <=> remote")
no_uri = @source.dup
no_uri.instance_variable_set :@uri, nil
- assert_equal(-1, remote.<=>(no_uri), 'remote <=> no_uri')
+ assert_equal(-1, remote.<=>(no_uri), "remote <=> no_uri")
end
def test_spaceship_order_is_preserved_when_uri_differs
- sourceA = Gem::Source.new "http://example.com/a"
- sourceB = Gem::Source.new "http://example.com/b"
+ source_a = Gem::Source.new "http://example.com/a"
+ source_b = Gem::Source.new "http://example.com/b"
- assert_equal(0, sourceA.<=>(sourceA), 'sourceA <=> sourceA')
- assert_equal(1, sourceA.<=>(sourceB), 'sourceA <=> sourceB')
- assert_equal(1, sourceB.<=>(sourceA), 'sourceB <=> sourceA')
+ assert_equal(0, source_a.<=>(source_a), "source_a <=> source_a") # rubocop:disable Lint/BinaryOperatorWithIdenticalOperands
+ assert_equal(1, source_a.<=>(source_b), "source_a <=> source_b")
+ assert_equal(1, source_b.<=>(source_a), "source_b <=> source_a")
end
def test_update_cache_eh
diff --git a/test/rubygems/test_gem_source_fetch_problem.rb b/test/rubygems/test_gem_source_fetch_problem.rb
index 816407781d..6d8ef360ae 100644
--- a/test/rubygems/test_gem_source_fetch_problem.rb
+++ b/test/rubygems/test_gem_source_fetch_problem.rb
@@ -1,10 +1,11 @@
# frozen_string_literal: true
-require_relative 'helper'
+
+require_relative "helper"
class TestGemSourceFetchProblem < Gem::TestCase
def test_exception
source = Gem::Source.new @gem_repo
- error = RuntimeError.new 'test'
+ error = RuntimeError.new "test"
sf = Gem::SourceFetchProblem.new source, error
@@ -12,25 +13,25 @@ class TestGemSourceFetchProblem < Gem::TestCase
raise sf
end
- assert_equal 'test', e.message
+ assert_equal "test", e.message
end
def test_password_redacted
- source = Gem::Source.new 'https://username:secret@gemsource.com'
- error = RuntimeError.new 'test'
+ source = Gem::Source.new "https://username:secret@gemsource.com"
+ error = RuntimeError.new "test"
sf = Gem::SourceFetchProblem.new source, error
- refute_match sf.wordy, 'secret'
+ refute_match sf.wordy, "secret"
end
def test_source_password_no_redacted
- source = Gem::Source.new 'https://username:secret@gemsource.com'
- error = RuntimeError.new 'test'
+ source = Gem::Source.new "https://username:secret@gemsource.com"
+ error = RuntimeError.new "test"
sf = Gem::SourceFetchProblem.new source, error
sf.wordy
- assert_match 'secret', source.uri.to_s
+ assert_match "secret", source.uri.to_s
end
end
diff --git a/test/rubygems/test_gem_source_git.rb b/test/rubygems/test_gem_source_git.rb
index 73ed8dd2ef..abcd55907e 100644
--- a/test/rubygems/test_gem_source_git.rb
+++ b/test/rubygems/test_gem_source_git.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/source'
+
+require_relative "helper"
+require "rubygems/source"
class TestGemSourceGit < Gem::TestCase
def setup
@@ -8,38 +9,39 @@ class TestGemSourceGit < Gem::TestCase
@name, @version, @repository, @head = git_gem
- @hash = Digest::SHA1.hexdigest @repository
+ @hash = OpenSSL::Digest::SHA1.hexdigest @repository
- @source = Gem::Source::Git.new @name, @repository, 'master', false
+ @source = Gem::Source::Git.new @name, @repository, nil, false
end
def test_base_dir
- assert_equal File.join(Gem.dir, 'bundler'), @source.base_dir
+ assert_equal File.join(Gem.dir, "bundler"), @source.base_dir
@source.root_dir = "#{@gemhome}2"
- assert_equal File.join("#{@gemhome}2", 'bundler'), @source.base_dir
+ assert_equal File.join("#{@gemhome}2", "bundler"), @source.base_dir
end
def test_checkout
@source.checkout
- assert_path_exist File.join @source.install_dir, 'a.gemspec'
+ assert_path_exist File.join @source.install_dir, "a.gemspec"
end
- def test_checkout_master
+ def test_checkout_default
Dir.chdir @repository do
- system @git, 'checkout', '-q', '-b', 'other'
- system @git, 'mv', 'a.gemspec', 'b.gemspec'
- system @git, 'commit', '-q', '-a', '-m', 'rename gemspec'
- system @git, 'checkout', '-q', 'master'
+ default_branch = Gem::Util.popen(@git, "branch", "--show-current").strip
+ system @git, "checkout", "-q", "-b", "other"
+ system @git, "mv", "a.gemspec", "b.gemspec"
+ system @git, "commit", "-q", "-a", "-m", "rename gemspec"
+ system @git, "checkout", "-q", default_branch
end
- @source = Gem::Source::Git.new @name, @repository, 'other', false
+ @source = Gem::Source::Git.new @name, @repository, "other", false
@source.checkout
- assert_path_exist File.join @source.install_dir, 'b.gemspec'
+ assert_path_exist File.join @source.install_dir, "b.gemspec"
end
def test_checkout_local
@@ -47,9 +49,9 @@ class TestGemSourceGit < Gem::TestCase
@source.checkout
- install_dir = File.join Gem.dir, 'bundler', 'gems', "a-#{@head[0..11]}"
+ install_dir = File.join Gem.dir, "bundler", "gems", "a-#{@head[0..11]}"
- assert_path_not_exist File.join install_dir, 'a.gemspec'
+ assert_path_not_exist File.join install_dir, "a.gemspec"
end
def test_checkout_local_cached
@@ -59,25 +61,31 @@ class TestGemSourceGit < Gem::TestCase
@source.checkout
- assert_path_exist File.join @source.install_dir, 'a.gemspec'
+ assert_path_exist File.join @source.install_dir, "a.gemspec"
end
def test_checkout_submodules
- source = Gem::Source::Git.new @name, @repository, 'master', true
+ # We need to allow to checkout submodules with file:// protocol
+ # CVE-2022-39253
+ # https://lore.kernel.org/lkml/xmqq4jw1uku5.fsf@gitster.g/
+ system(@git, *%W[config --global protocol.file.allow always])
+
+ source = Gem::Source::Git.new @name, @repository, nil, true
- git_gem 'b'
+ git_gem "b"
- Dir.chdir 'git/a' do
- output, status = Open3.capture2e(@git, 'submodule', '--quiet', 'add', File.expand_path('../b'), 'b')
+ Dir.chdir "git/a" do
+ require "open3"
+ output, status = Open3.capture2e(@git, "submodule", "--quiet", "add", File.expand_path("../b"), "b")
assert status.success?, output
- system @git, 'commit', '--quiet', '-m', 'add submodule b'
+ system @git, "commit", "--quiet", "-m", "add submodule b"
end
source.checkout
- assert_path_exist File.join source.install_dir, 'a.gemspec'
- assert_path_exist File.join source.install_dir, 'b/b.gemspec'
+ assert_path_exist File.join source.install_dir, "a.gemspec"
+ assert_path_exist File.join source.install_dir, "b/b.gemspec"
end
def test_cache
@@ -86,7 +94,7 @@ class TestGemSourceGit < Gem::TestCase
assert_path_exist @source.repo_cache_dir
Dir.chdir @source.repo_cache_dir do
- assert_equal @head, Gem::Util.popen(@git, 'rev-parse', 'master').strip
+ assert_equal @head, Gem::Util.popen(@git, "rev-parse", "HEAD").strip
end
end
@@ -114,17 +122,17 @@ class TestGemSourceGit < Gem::TestCase
assert_equal @source, @source.dup
source =
- Gem::Source::Git.new @source.name, @source.repository, 'other', false
+ Gem::Source::Git.new @source.name, @source.repository, "other", false
refute_equal @source, source
source =
- Gem::Source::Git.new @source.name, 'repo/other', @source.reference, false
+ Gem::Source::Git.new @source.name, "repo/other", @source.reference, false
refute_equal @source, source
source =
- Gem::Source::Git.new 'b', @source.repository, @source.reference, false
+ Gem::Source::Git.new "b", @source.repository, @source.reference, false
refute_equal @source, source
@@ -138,7 +146,7 @@ class TestGemSourceGit < Gem::TestCase
def test_install_dir
@source.cache
- expected = File.join Gem.dir, 'bundler', 'gems', "a-#{@head[0..11]}"
+ expected = File.join Gem.dir, "bundler", "gems", "a-#{@head[0..11]}"
assert_equal expected, @source.install_dir
end
@@ -151,14 +159,14 @@ class TestGemSourceGit < Gem::TestCase
def test_repo_cache_dir
expected =
- File.join Gem.dir, 'cache', 'bundler', 'git', "a-#{@hash}"
+ File.join Gem.dir, "cache", "bundler", "git", "a-#{@hash}"
assert_equal expected, @source.repo_cache_dir
@source.root_dir = "#{@gemhome}2"
expected =
- File.join "#{@gemhome}2", 'cache', 'bundler', 'git', "a-#{@hash}"
+ File.join "#{@gemhome}2", "cache", "bundler", "git", "a-#{@hash}"
assert_equal expected, @source.repo_cache_dir
end
@@ -169,20 +177,20 @@ class TestGemSourceGit < Gem::TestCase
assert_equal @head, @source.rev_parse
Dir.chdir @repository do
- system @git, 'checkout', '--quiet', '-b', 'other'
+ system @git, "checkout", "--quiet", "-b", "other"
end
- master_head = @head
+ default_head = @head
- git_gem 'a', 2
+ git_gem "a", 2
- source = Gem::Source::Git.new @name, @repository, 'other', false
+ source = Gem::Source::Git.new @name, @repository, "other", false
source.cache
- refute_equal master_head, source.rev_parse
+ refute_equal default_head, source.rev_parse
- source = Gem::Source::Git.new @name, @repository, 'nonexistent', false
+ source = Gem::Source::Git.new @name, @repository, "nonexistent", false
source.cache
@@ -203,38 +211,38 @@ class TestGemSourceGit < Gem::TestCase
end
def test_spaceship
- git = Gem::Source::Git.new 'a', 'git/a', 'master', false
+ git = Gem::Source::Git.new "a", "git/a", nil, false
remote = Gem::Source.new @gem_repo
installed = Gem::Source::Installed.new
- vendor = Gem::Source::Vendor.new 'vendor/foo'
+ vendor = Gem::Source::Vendor.new "vendor/foo"
- assert_equal(0, git.<=>(git), 'git <=> git')
+ assert_equal(0, git.<=>(git), "git <=> git") # rubocop:disable Lint/BinaryOperatorWithIdenticalOperands
- assert_equal(1, git.<=>(remote), 'git <=> remote')
- assert_equal(-1, remote.<=>(git), 'remote <=> git')
+ assert_equal(1, git.<=>(remote), "git <=> remote")
+ assert_equal(-1, remote.<=>(git), "remote <=> git")
- assert_equal(1, git.<=>(installed), 'git <=> installed')
- assert_equal(-1, installed.<=>(git), 'installed <=> git')
+ assert_equal(1, git.<=>(installed), "git <=> installed")
+ assert_equal(-1, installed.<=>(git), "installed <=> git")
- assert_equal(-1, git.<=>(vendor), 'git <=> vendor')
- assert_equal(1, vendor.<=>(git), 'vendor <=> git')
+ assert_equal(-1, git.<=>(vendor), "git <=> vendor")
+ assert_equal(1, vendor.<=>(git), "vendor <=> git")
end
def test_specs
- source = Gem::Source::Git.new @name, @repository, 'master', true
+ source = Gem::Source::Git.new @name, @repository, nil, true
- Dir.chdir 'git/a' do
- FileUtils.mkdir 'b'
+ Dir.chdir "git/a" do
+ FileUtils.mkdir "b"
- Dir.chdir 'b' do
- b = Gem::Specification.new 'b', 1
+ Dir.chdir "b" do
+ b = Gem::Specification.new "b", 1
- File.open 'b.gemspec', 'w' do |io|
+ File.open "b.gemspec", "w" do |io|
io.write b.to_ruby
end
- system @git, 'add', 'b.gemspec'
- system @git, 'commit', '--quiet', '-m', 'add b/b.gemspec'
+ system @git, "add", "b.gemspec"
+ system @git, "commit", "--quiet", "-m", "add b/b.gemspec"
end
end
@@ -244,18 +252,18 @@ class TestGemSourceGit < Gem::TestCase
specs = source.specs
end
- assert_equal %w[a-1 b-1], specs.map {|spec| spec.full_name }
+ assert_equal %w[a-1 b-1], specs.map(&:full_name)
a_spec = specs.shift
base_dir = File.dirname File.dirname source.install_dir
assert_equal source.install_dir, a_spec.full_gem_path
- assert_equal File.join(source.install_dir, 'a.gemspec'), a_spec.loaded_from
+ assert_equal File.join(source.install_dir, "a.gemspec"), a_spec.loaded_from
assert_equal base_dir, a_spec.base_dir
extension_dir =
- File.join Gem.dir, 'bundler', 'extensions',
+ File.join Gem.dir, "bundler", "extensions",
Gem::Platform.local.to_s, Gem.extension_api_version,
"a-#{source.dir_shortref}"
@@ -263,8 +271,8 @@ class TestGemSourceGit < Gem::TestCase
b_spec = specs.shift
- assert_equal File.join(source.install_dir, 'b'), b_spec.full_gem_path
- assert_equal File.join(source.install_dir, 'b', 'b.gemspec'),
+ assert_equal File.join(source.install_dir, "b"), b_spec.full_gem_path
+ assert_equal File.join(source.install_dir, "b", "b.gemspec"),
b_spec.loaded_from
assert_equal base_dir, b_spec.base_dir
@@ -272,7 +280,7 @@ class TestGemSourceGit < Gem::TestCase
end
def test_specs_local
- source = Gem::Source::Git.new @name, @repository, 'master', true
+ source = Gem::Source::Git.new @name, @repository, nil, true
source.remote = false
capture_output do
@@ -281,22 +289,28 @@ class TestGemSourceGit < Gem::TestCase
end
def test_uri
- assert_equal URI(@repository), @source.uri
+ assert_equal Gem::URI(@repository), @source.uri
+ end
+
+ def test_pretty_print
+ assert_equal "#<Gem::Source::Git[Git: \n" \
+ " #{@repository}\n" \
+ " HEAD]>\n", @source.pretty_inspect
end
def test_uri_hash
assert_equal @hash, @source.uri_hash
source =
- Gem::Source::Git.new 'a', 'http://git@example/repo.git', 'master', false
+ Gem::Source::Git.new "a", "http://git@example/repo.git", nil, false
- assert_equal '291c4caac7feba8bb64c297987028acb3dde6cfe',
+ assert_equal "291c4caac7feba8bb64c297987028acb3dde6cfe",
source.uri_hash
source =
- Gem::Source::Git.new 'a', 'HTTP://git@EXAMPLE/repo.git', 'master', false
+ Gem::Source::Git.new "a", "HTTP://git@EXAMPLE/repo.git", nil, false
- assert_equal '291c4caac7feba8bb64c297987028acb3dde6cfe',
+ assert_equal "291c4caac7feba8bb64c297987028acb3dde6cfe",
source.uri_hash
end
end
diff --git a/test/rubygems/test_gem_source_installed.rb b/test/rubygems/test_gem_source_installed.rb
index ef9b63e611..0ef14d7470 100644
--- a/test/rubygems/test_gem_source_installed.rb
+++ b/test/rubygems/test_gem_source_installed.rb
@@ -1,34 +1,40 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/source'
+
+require_relative "helper"
+require "rubygems/source"
class TestGemSourceInstalled < Gem::TestCase
def test_spaceship
- a1 = quick_gem 'a', '1'
+ a1 = quick_gem "a", "1"
util_build_gem a1
remote = Gem::Source.new @gem_repo
specific = Gem::Source::SpecificFile.new a1.cache_file
installed = Gem::Source::Installed.new
local = Gem::Source::Local.new
- git = Gem::Source::Git.new 'a', 'a', 'master'
- vendor = Gem::Source::Vendor.new 'a'
+ git = Gem::Source::Git.new "a", "a", nil
+ vendor = Gem::Source::Vendor.new "a"
+
+ assert_equal(0, installed.<=>(installed), "installed <=> installed") # rubocop:disable Lint/BinaryOperatorWithIdenticalOperands
- assert_equal(0, installed.<=>(installed), 'installed <=> installed')
+ assert_equal(-1, remote.<=>(installed), "remote <=> installed")
+ assert_equal(1, installed.<=>(remote), "installed <=> remote")
- assert_equal(-1, remote.<=>(installed), 'remote <=> installed')
- assert_equal(1, installed.<=>(remote), 'installed <=> remote')
+ assert_equal(1, installed.<=>(local), "installed <=> local")
+ assert_equal(-1, local.<=>(installed), "local <=> installed")
- assert_equal(1, installed.<=>(local), 'installed <=> local')
- assert_equal(-1, local.<=>(installed), 'local <=> installed')
+ assert_equal(-1, specific.<=>(installed), "specific <=> installed")
+ assert_equal(1, installed.<=>(specific), "installed <=> specific")
- assert_equal(-1, specific.<=>(installed), 'specific <=> installed')
- assert_equal(1, installed.<=>(specific), 'installed <=> specific')
+ assert_equal(1, git. <=>(installed), "git <=> installed")
+ assert_equal(-1, installed.<=>(git), "installed <=> git")
- assert_equal(1, git. <=>(installed), 'git <=> installed')
- assert_equal(-1, installed.<=>(git), 'installed <=> git')
+ assert_equal(1, vendor.<=>(installed), "vendor <=> installed")
+ assert_equal(-1, installed.<=>(vendor), "installed <=> vendor")
+ end
- assert_equal(1, vendor.<=>(installed), 'vendor <=> installed')
- assert_equal(-1, installed.<=>(vendor), 'installed <=> vendor')
+ def test_pretty_print
+ local = Gem::Source::Installed.new
+ assert_equal "#<Gem::Source::Installed[Installed]>\n", local.pretty_inspect
end
end
diff --git a/test/rubygems/test_gem_source_list.rb b/test/rubygems/test_gem_source_list.rb
index 6ac5dbb2a6..64353f8f90 100644
--- a/test/rubygems/test_gem_source_list.rb
+++ b/test/rubygems/test_gem_source_list.rb
@@ -1,7 +1,8 @@
# frozen_string_literal: true
-require 'rubygems'
-require 'rubygems/source_list'
-require_relative 'helper'
+
+require "rubygems"
+require "rubygems/source_list"
+require_relative "helper"
class TestGemSourceList < Gem::TestCase
def setup
@@ -36,7 +37,7 @@ class TestGemSourceList < Gem::TestCase
assert_kind_of Gem::Source, source
- assert_kind_of URI, source.uri
+ assert_kind_of Gem::URI, source.uri
assert_equal source.uri.to_s, @uri
assert_equal [source], sl.sources
@@ -45,7 +46,7 @@ class TestGemSourceList < Gem::TestCase
def test_clear
sl = Gem::SourceList.new
- sl << 'http://source.example'
+ sl << "http://source.example"
sl.clear
@@ -76,7 +77,7 @@ class TestGemSourceList < Gem::TestCase
assert_empty sl
- sl << 'http://source.example'
+ sl << "http://source.example"
refute_empty sl
end
@@ -98,7 +99,7 @@ class TestGemSourceList < Gem::TestCase
def test_include_eh
assert @sl.include?(@uri), "string comparison not working"
- assert @sl.include?(URI.parse(@uri)), "uri comparison not working"
+ assert @sl.include?(Gem::URI.parse(@uri)), "uri comparison not working"
end
def test_include_matches_a_source
diff --git a/test/rubygems/test_gem_source_local.rb b/test/rubygems/test_gem_source_local.rb
index 2d4ddbc3a4..ed6aa24f94 100644
--- a/test/rubygems/test_gem_source_local.rb
+++ b/test/rubygems/test_gem_source_local.rb
@@ -1,8 +1,9 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/source'
-require 'fileutils'
+require_relative "helper"
+require "rubygems/source"
+
+require "fileutils"
class TestGemSourceLocal < Gem::TestCase
def setup
@@ -10,9 +11,9 @@ class TestGemSourceLocal < Gem::TestCase
@sl = Gem::Source::Local.new
- @a, @a_gem = util_gem "a", '1'
- @ap, @ap_gem = util_gem "a", '2.a'
- @b, @b_gem = util_gem "b", '1'
+ @a, @a_gem = util_gem "a", "1"
+ @ap, @ap_gem = util_gem "a", "2.a"
+ @b, @b_gem = util_gem "b", "1"
FileUtils.mv @a_gem, @tempdir
FileUtils.mv @ap_gem, @tempdir
@@ -72,7 +73,7 @@ class TestGemSourceLocal < Gem::TestCase
@sl.load_specs :released
- inner = [@a, @ap, @b].map {|t| t.name_tuple }.inspect
+ inner = [@a, @ap, @b].map(&:name_tuple).inspect
assert_equal "#<Gem::Source::Local specs: #{inner}>", @sl.inspect
end
@@ -84,7 +85,7 @@ class TestGemSourceLocal < Gem::TestCase
end
def test_spaceship
- a1 = quick_gem 'a', '1'
+ a1 = quick_gem "a", "1"
util_build_gem a1
remote = Gem::Source.new @gem_repo
@@ -92,15 +93,20 @@ class TestGemSourceLocal < Gem::TestCase
installed = Gem::Source::Installed.new
local = Gem::Source::Local.new
- assert_equal(0, local.<=>(local), 'local <=> local')
+ assert_equal(0, local.<=>(local), "local <=> local") # rubocop:disable Lint/BinaryOperatorWithIdenticalOperands
+
+ assert_equal(-1, remote.<=>(local), "remote <=> local")
+ assert_equal(1, local.<=>(remote), "local <=> remote")
- assert_equal(-1, remote.<=>(local), 'remote <=> local')
- assert_equal(1, local.<=>(remote), 'local <=> remote')
+ assert_equal(1, installed.<=>(local), "installed <=> local")
+ assert_equal(-1, local.<=>(installed), "local <=> installed")
- assert_equal(1, installed.<=>(local), 'installed <=> local')
- assert_equal(-1, local.<=>(installed), 'local <=> installed')
+ assert_equal(-1, specific.<=>(local), "specific <=> local")
+ assert_equal(1, local.<=>(specific), "local <=> specific")
+ end
- assert_equal(-1, specific.<=>(local), 'specific <=> local')
- assert_equal(1, local.<=>(specific), 'local <=> specific')
+ def test_pretty_print
+ local = Gem::Source::Local.new
+ assert_equal "#<Gem::Source::Local[Local gems: ]>\n", local.pretty_inspect
end
end
diff --git a/test/rubygems/test_gem_source_lock.rb b/test/rubygems/test_gem_source_lock.rb
index 5f916cdf7f..91ffee68f2 100644
--- a/test/rubygems/test_gem_source_lock.rb
+++ b/test/rubygems/test_gem_source_lock.rb
@@ -1,24 +1,25 @@
# frozen_string_literal: true
-require_relative 'helper'
+
+require_relative "helper"
class TestGemSourceLock < Gem::TestCase
def test_fetch_spec
spec_fetcher do |fetcher|
- fetcher.spec 'a', 1
+ fetcher.spec "a", 1
end
- name_tuple = Gem::NameTuple.new 'a', v(1), 'ruby'
+ name_tuple = Gem::NameTuple.new "a", v(1), "ruby"
remote = Gem::Source.new @gem_repo
lock = Gem::Source::Lock.new remote
spec = lock.fetch_spec name_tuple
- assert_equal 'a-1', spec.full_name
+ assert_equal "a-1", spec.full_name
end
def test_equals2
- git = Gem::Source::Git.new 'a', 'git/a', 'master', false
+ git = Gem::Source::Git.new "a", "git/a", nil, false
g_lock = Gem::Source::Lock.new git
installed = Gem::Source::Installed.new
@@ -30,83 +31,85 @@ class TestGemSourceLock < Gem::TestCase
end
def test_spaceship
- git = Gem::Source::Git.new 'a', 'git/a', 'master', false
+ git = Gem::Source::Git.new "a", "git/a", nil, false
g_lock = Gem::Source::Lock.new git
installed = Gem::Source::Installed.new
i_lock = Gem::Source::Lock.new installed
- vendor = Gem::Source::Vendor.new 'vendor/a'
+ vendor = Gem::Source::Vendor.new "vendor/a"
v_lock = Gem::Source::Lock.new vendor
- assert_equal(0, g_lock.<=>(g_lock), 'g_lock <=> g_lock')
- assert_equal(0, i_lock.<=>(i_lock), 'i_lock <=> i_lock')
- assert_equal(0, v_lock.<=>(v_lock), 'v_lock <=> v_lock')
+ # rubocop:disable Lint/BinaryOperatorWithIdenticalOperands
+ assert_equal(0, g_lock.<=>(g_lock), "g_lock <=> g_lock")
+ assert_equal(0, i_lock.<=>(i_lock), "i_lock <=> i_lock")
+ assert_equal(0, v_lock.<=>(v_lock), "v_lock <=> v_lock")
+ # rubocop:enable Lint/BinaryOperatorWithIdenticalOperands
- assert_equal(1, g_lock.<=>(i_lock), 'g_lock <=> i_lock')
- assert_equal(-1, i_lock.<=>(g_lock), 'i_lock <=> g_lock')
+ assert_equal(1, g_lock.<=>(i_lock), "g_lock <=> i_lock")
+ assert_equal(-1, i_lock.<=>(g_lock), "i_lock <=> g_lock")
- assert_equal(-1, g_lock.<=>(v_lock), 'g_lock <=> v_lock')
- assert_equal(1, v_lock.<=>(g_lock), 'v_lock <=> g_lock')
+ assert_equal(-1, g_lock.<=>(v_lock), "g_lock <=> v_lock")
+ assert_equal(1, v_lock.<=>(g_lock), "v_lock <=> g_lock")
- assert_equal(-1, i_lock.<=>(v_lock), 'i_lock <=> v_lock')
- assert_equal(1, v_lock.<=>(i_lock), 'i_lock <=> v_lock')
+ assert_equal(-1, i_lock.<=>(v_lock), "i_lock <=> v_lock")
+ assert_equal(1, v_lock.<=>(i_lock), "i_lock <=> v_lock")
end
def test_spaceship_git
- git = Gem::Source::Git.new 'a', 'git/a', 'master', false
+ git = Gem::Source::Git.new "a", "git/a", nil, false
lock = Gem::Source::Lock.new git
- assert_equal(1, lock.<=>(git), 'lock <=> git')
- assert_equal(-1, git.<=>(lock), 'git <=> lock')
+ assert_equal(1, lock.<=>(git), "lock <=> git")
+ assert_equal(-1, git.<=>(lock), "git <=> lock")
end
def test_spaceship_installed
installed = Gem::Source::Installed.new
lock = Gem::Source::Lock.new installed
- assert_equal(1, lock.<=>(installed), 'lock <=> installed')
- assert_equal(-1, installed.<=>(lock), 'installed <=> lock')
+ assert_equal(1, lock.<=>(installed), "lock <=> installed")
+ assert_equal(-1, installed.<=>(lock), "installed <=> lock")
end
def test_spaceship_local
local = Gem::Source::Local.new
lock = Gem::Source::Lock.new local # nonsense
- assert_equal(1, lock.<=>(local), 'lock <=> local')
- assert_equal(-1, local.<=>(lock), 'local <=> lock')
+ assert_equal(1, lock.<=>(local), "lock <=> local")
+ assert_equal(-1, local.<=>(lock), "local <=> lock")
end
def test_spaceship_remote
remote = Gem::Source.new @gem_repo
lock = Gem::Source::Lock.new remote
- assert_equal(1, lock.<=>(remote), 'lock <=> remote')
- assert_equal(-1, remote.<=>(lock), 'remote <=> lock')
+ assert_equal(1, lock.<=>(remote), "lock <=> remote")
+ assert_equal(-1, remote.<=>(lock), "remote <=> lock")
end
def test_spaceship_specific_file
- _, gem = util_gem 'a', 1
+ _, gem = util_gem "a", 1
specific = Gem::Source::SpecificFile.new gem
lock = Gem::Source::Lock.new specific # nonsense
- assert_equal(1, lock.<=>(specific), 'lock <=> specific')
- assert_equal(-1, specific.<=>(lock), 'specific <=> lock')
+ assert_equal(1, lock.<=>(specific), "lock <=> specific")
+ assert_equal(-1, specific.<=>(lock), "specific <=> lock")
end
def test_spaceship_vendor
- vendor = Gem::Source::Vendor.new 'vendor/a'
+ vendor = Gem::Source::Vendor.new "vendor/a"
lock = Gem::Source::Lock.new vendor
- assert_equal(1, lock.<=>(vendor), 'lock <=> vendor')
- assert_equal(-1, vendor.<=>(lock), 'vendor <=> lock')
+ assert_equal(1, lock.<=>(vendor), "lock <=> vendor")
+ assert_equal(-1, vendor.<=>(lock), "vendor <=> lock")
end
def test_uri
remote = Gem::Source.new @gem_repo
lock = Gem::Source::Lock.new remote
- assert_equal URI(@gem_repo), lock.uri
+ assert_equal Gem::URI(@gem_repo), lock.uri
end
end
diff --git a/test/rubygems/test_gem_source_specific_file.rb b/test/rubygems/test_gem_source_specific_file.rb
index 72ed993a88..bcc4168444 100644
--- a/test/rubygems/test_gem_source_specific_file.rb
+++ b/test/rubygems/test_gem_source_specific_file.rb
@@ -1,12 +1,13 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/source'
+
+require_relative "helper"
+require "rubygems/source"
class TestGemSourceSpecificFile < Gem::TestCase
def setup
super
- @a, @a_gem = util_gem "a", '1'
+ @a, @a_gem = util_gem "a", "1"
@sf = Gem::Source::SpecificFile.new(@a_gem)
end
@@ -37,7 +38,7 @@ class TestGemSourceSpecificFile < Gem::TestCase
end
def test_spaceship
- a1 = quick_gem 'a', '1'
+ a1 = quick_gem "a", "1"
util_build_gem a1
remote = Gem::Source.new @gem_repo
@@ -45,31 +46,35 @@ class TestGemSourceSpecificFile < Gem::TestCase
installed = Gem::Source::Installed.new
local = Gem::Source::Local.new
- assert_equal(0, specific.<=>(specific), 'specific <=> specific')
+ assert_equal(0, specific.<=>(specific), "specific <=> specific") # rubocop:disable Lint/BinaryOperatorWithIdenticalOperands
- assert_equal(-1, remote.<=>(specific), 'remote <=> specific')
- assert_equal(1, specific.<=>(remote), 'specific <=> remote')
+ assert_equal(-1, remote.<=>(specific), "remote <=> specific")
+ assert_equal(1, specific.<=>(remote), "specific <=> remote")
- assert_equal(-1, specific.<=>(local), 'specific <=> local')
- assert_equal(1, local. <=>(specific), 'local <=> specific')
+ assert_equal(-1, specific.<=>(local), "specific <=> local")
+ assert_equal(1, local. <=>(specific), "local <=> specific")
- assert_equal(-1, specific. <=>(installed), 'specific <=> installed')
- assert_equal(1, installed.<=>(specific), 'installed <=> specific')
+ assert_equal(-1, specific. <=>(installed), "specific <=> installed")
+ assert_equal(1, installed.<=>(specific), "installed <=> specific")
- a2 = quick_gem 'a', '2'
+ a2 = quick_gem "a", "2"
util_build_gem a2
- b1 = quick_gem 'b', '1'
+ b1 = quick_gem "b", "1"
util_build_gem b1
a1_source = specific
a2_source = Gem::Source::SpecificFile.new a2.cache_file
b1_source = Gem::Source::SpecificFile.new b1.cache_file
- assert_nil a1_source.<=>(b1_source), 'a1_source <=> b1_source'
+ assert_nil a1_source.<=>(b1_source), "a1_source <=> b1_source"
+
+ assert_equal(-1, a1_source.<=>(a2_source), "a1_source <=> a2_source")
+ assert_equal(0, a1_source.<=>(a1_source), "a1_source <=> a1_source") # rubocop:disable Lint/BinaryOperatorWithIdenticalOperands
+ assert_equal(1, a2_source.<=>(a1_source), "a2_source <=> a1_source")
+ end
- assert_equal(-1, a1_source.<=>(a2_source), 'a1_source <=> a2_source')
- assert_equal(0, a1_source.<=>(a1_source), 'a1_source <=> a1_source')
- assert_equal(1, a2_source.<=>(a1_source), 'a2_source <=> a1_source')
+ def test_pretty_print
+ assert_equal "#<Gem::Source::SpecificFile[SpecificFile:\n #{@sf.path}]>\n", @sf.pretty_inspect
end
end
diff --git a/test/rubygems/test_gem_source_subpath_problem.rb b/test/rubygems/test_gem_source_subpath_problem.rb
index c37df39f0c..ad11529f67 100644
--- a/test/rubygems/test_gem_source_subpath_problem.rb
+++ b/test/rubygems/test_gem_source_subpath_problem.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/source'
+
+require_relative "helper"
+require "rubygems/source"
class TestGemSourceSubpathProblem < Gem::TestCase
def tuple(*args)
@@ -20,10 +21,10 @@ class TestGemSourceSubpathProblem < Gem::TestCase
end
def test_dependency_resolver_set
- response = Net::HTTPResponse.new '1.1', 200, 'OK'
- response.uri = URI('http://example')
+ response = Gem::Net::HTTPResponse.new "1.1", 200, "OK"
+ response.uri = Gem::URI("http://example")
- @fetcher.data["#{@gem_repo}/"] = response
+ @fetcher.data["#{@gem_repo}/versions"] = response
set = @source.dependency_resolver_set
@@ -33,17 +34,17 @@ class TestGemSourceSubpathProblem < Gem::TestCase
def test_fetch_spec
@fetcher.data["#{@gem_repo}/#{Gem::MARSHAL_SPEC_DIR}#{@a1.spec_name}.rz"] = Zlib::Deflate.deflate(Marshal.dump(@a1))
- spec = @source.fetch_spec tuple('a', Gem::Version.new(1), 'ruby')
+ spec = @source.fetch_spec tuple("a", Gem::Version.new(1), "ruby")
assert_equal @a1.full_name, spec.full_name
end
def test_load_specs
@fetcher.data["#{@gem_repo}/latest_specs.#{Gem.marshal_version}.gz"] = util_gzip(Marshal.dump([
- Gem::NameTuple.new(@a1.name, @a1.version, 'ruby'),
- Gem::NameTuple.new(@b2.name, @b2.version, 'ruby'),
+ Gem::NameTuple.new(@a1.name, @a1.version, "ruby"),
+ Gem::NameTuple.new(@b2.name, @b2.version, "ruby"),
]))
- released = @source.load_specs(:latest).map {|spec| spec.full_name }
+ released = @source.load_specs(:latest).map(&:full_name)
assert_equal %W[a-1 b-2], released
end
end
diff --git a/test/rubygems/test_gem_source_vendor.rb b/test/rubygems/test_gem_source_vendor.rb
index a5ffb0f223..2543871439 100644
--- a/test/rubygems/test_gem_source_vendor.rb
+++ b/test/rubygems/test_gem_source_vendor.rb
@@ -1,29 +1,30 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/source'
+
+require_relative "helper"
+require "rubygems/source"
class TestGemSourceVendor < Gem::TestCase
def test_initialize
- source = Gem::Source::Vendor.new 'vendor/foo'
+ source = Gem::Source::Vendor.new "vendor/foo"
- assert_equal 'vendor/foo', source.uri
+ assert_equal "vendor/foo", source.uri
end
def test_spaceship
- vendor = Gem::Source::Vendor.new 'vendor/foo'
+ vendor = Gem::Source::Vendor.new "vendor/foo"
remote = Gem::Source.new @gem_repo
- git = Gem::Source::Git.new 'a', 'a', 'master'
+ git = Gem::Source::Git.new "a", "a", nil
installed = Gem::Source::Installed.new
- assert_equal(0, vendor.<=>(vendor), 'vendor <=> vendor')
+ assert_equal(0, vendor.<=>(vendor), "vendor <=> vendor") # rubocop:disable Lint/BinaryOperatorWithIdenticalOperands
- assert_equal(1, vendor.<=>(remote), 'vendor <=> remote')
- assert_equal(-1, remote.<=>(vendor), 'remote <=> vendor')
+ assert_equal(1, vendor.<=>(remote), "vendor <=> remote")
+ assert_equal(-1, remote.<=>(vendor), "remote <=> vendor")
- assert_equal(1, vendor.<=>(git), 'vendor <=> git')
- assert_equal(-1, git.<=>(vendor), 'git <=> vendor')
+ assert_equal(1, vendor.<=>(git), "vendor <=> git")
+ assert_equal(-1, git.<=>(vendor), "git <=> vendor")
- assert_equal(1, vendor.<=>(installed), 'vendor <=> installed')
- assert_equal(-1, installed.<=>(vendor), 'installed <=> vendor')
+ assert_equal(1, vendor.<=>(installed), "vendor <=> installed")
+ assert_equal(-1, installed.<=>(vendor), "installed <=> vendor")
end
end
diff --git a/test/rubygems/test_gem_spec_fetcher.rb b/test/rubygems/test_gem_spec_fetcher.rb
index afae46e120..cb4a4f7204 100644
--- a/test/rubygems/test_gem_spec_fetcher.rb
+++ b/test/rubygems/test_gem_spec_fetcher.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/spec_fetcher'
+
+require_relative "helper"
+require "rubygems/spec_fetcher"
class TestGemSpecFetcher < Gem::TestCase
def tuple(*args)
@@ -10,7 +11,7 @@ class TestGemSpecFetcher < Gem::TestCase
def setup
super
- @uri = URI.parse @gem_repo
+ @uri = Gem::URI.parse @gem_repo
@source = Gem::Source.new(@uri)
@sf = Gem::SpecFetcher.new
@@ -23,7 +24,7 @@ class TestGemSpecFetcher < Gem::TestCase
end
def test_initialize_source
- alternate = 'http://alternate.example'
+ alternate = "http://alternate.example"
fetcher = Gem::SpecFetcher.new alternate
refute_same Gem.sources, fetcher.sources
@@ -38,26 +39,26 @@ class TestGemSpecFetcher < Gem::TestCase
end
def test_initialize_unwritable_home_dir
- pend 'chmod not supported' if Gem.win_platform?
+ pend "chmod not supported" if Gem.win_platform?
- FileUtils.chmod 0000, Gem.user_home
+ FileUtils.chmod 0o000, Gem.user_home
begin
assert Gem::SpecFetcher.new
ensure
- FileUtils.chmod 0755, Gem.user_home
+ FileUtils.chmod 0o755, Gem.user_home
end
end
def test_spec_for_dependency_all
spec_fetcher do |fetcher|
- fetcher.spec 'a', 1
- fetcher.spec 'a', '2.a'
- fetcher.spec 'a', 2
- fetcher.spec 'a', '3.a'
+ fetcher.spec "a", 1
+ fetcher.spec "a", "2.a"
+ fetcher.spec "a", 2
+ fetcher.spec "a", "3.a"
end
- dep = Gem::Dependency.new 'a', ">= 1"
+ dep = Gem::Dependency.new "a", ">= 1"
specs_and_sources, _ = @sf.spec_for_dependency dep
@@ -65,7 +66,7 @@ class TestGemSpecFetcher < Gem::TestCase
[spec.full_name, source_uri]
end
- expected = [['a-1', @source], ['a-2', @source]]
+ expected = [["a-1", @source], ["a-2", @source]]
assert_equal expected, spec_names
@@ -74,63 +75,59 @@ class TestGemSpecFetcher < Gem::TestCase
def test_spec_for_dependency_latest
spec_fetcher do |fetcher|
- fetcher.spec 'a', 1
- fetcher.spec 'a', 2
- fetcher.spec 'a', '3.a'
+ fetcher.spec "a", 1
+ fetcher.spec "a", 2
+ fetcher.spec "a", "3.a"
end
- dep = Gem::Dependency.new 'a'
+ dep = Gem::Dependency.new "a"
specs_and_sources, _ = @sf.spec_for_dependency dep
spec_names = specs_and_sources.map do |spec, source_uri|
[spec.full_name, source_uri]
end
- assert_equal [['a-2', Gem::Source.new(@gem_repo)]],
+ assert_equal [["a-2", Gem::Source.new(@gem_repo)]],
spec_names
end
def test_spec_for_dependency_prerelease
spec_fetcher do |fetcher|
- fetcher.spec 'a', '1.a'
- fetcher.spec 'a', 1
+ fetcher.spec "a", "1.a"
+ fetcher.spec "a", 1
end
- specs_and_sources, _ = @sf.spec_for_dependency dep('a', '1.a')
+ specs_and_sources, _ = @sf.spec_for_dependency dep("a", "1.a")
spec_names = specs_and_sources.map do |spec, source_uri|
[spec.full_name, source_uri]
end
- assert_equal [['a-1.a', Gem::Source.new(@gem_repo)]], spec_names
+ assert_equal [["a-1.a", Gem::Source.new(@gem_repo)]], spec_names
end
def test_spec_for_dependency_platform
- util_set_arch 'i386-linux'
+ util_set_arch "i386-linux"
- spec_fetcher do |fetcher|
- fetcher.legacy_platform
- end
+ spec_fetcher(&:legacy_platform)
- dep = Gem::Dependency.new 'pl', 1
+ dep = Gem::Dependency.new "pl", 1
specs_and_sources, _ = @sf.spec_for_dependency dep
spec_names = specs_and_sources.map do |spec, source_uri|
[spec.full_name, source_uri]
end
- assert_equal [['pl-1-x86-linux', Gem::Source.new(@gem_repo)]],
+ assert_equal [["pl-1-x86-linux", Gem::Source.new(@gem_repo)]],
spec_names
end
def test_spec_for_dependency_mismatched_platform
- util_set_arch 'hrpa-989'
+ util_set_arch "hrpa-989"
- spec_fetcher do |fetcher|
- fetcher.legacy_platform
- end
+ spec_fetcher(&:legacy_platform)
- dep = Gem::Dependency.new 'pl', 1
+ dep = Gem::Dependency.new "pl", 1
specs_and_sources, errors = @sf.spec_for_dependency dep
assert_equal 0, specs_and_sources.size
@@ -150,13 +147,13 @@ class TestGemSpecFetcher < Gem::TestCase
Gem.sources.replace [src]
spec_fetcher do |fetcher|
- fetcher.spec 'a', 1
- fetcher.spec 'a', '2.a'
- fetcher.spec 'a', 2
- fetcher.spec 'a', '3.a'
+ fetcher.spec "a", 1
+ fetcher.spec "a", "2.a"
+ fetcher.spec "a", 2
+ fetcher.spec "a", "3.a"
end
- dep = Gem::Dependency.new 'a', ">= 1"
+ dep = Gem::Dependency.new "a", ">= 1"
specs_and_sources, errors = @sf.spec_for_dependency dep
@@ -170,38 +167,38 @@ class TestGemSpecFetcher < Gem::TestCase
def test_suggest_gems_from_name_latest
spec_fetcher do|fetcher|
- fetcher.spec 'example', 1
- fetcher.spec 'other-example', 1
- fetcher.spec 'examp', 1
+ fetcher.spec "example", 1
+ fetcher.spec "other-example", 1
+ fetcher.spec "examp", 1
end
- suggestions = @sf.suggest_gems_from_name('examplw', :latest, 1)
- assert_equal ['example'], suggestions
+ suggestions = @sf.suggest_gems_from_name("examplw", :latest, 1)
+ assert_equal ["example"], suggestions
- suggestions = @sf.suggest_gems_from_name('other')
- assert_equal ['other-example'], suggestions
+ suggestions = @sf.suggest_gems_from_name("other")
+ assert_equal ["other-example"], suggestions
- suggestions = @sf.suggest_gems_from_name('exam')
- assert suggestions.any? { ['examp'] }
- assert suggestions.any? { ['example'] }
- assert suggestions.any? { ['other-example'] }
+ suggestions = @sf.suggest_gems_from_name("exam")
+ assert suggestions.any? { ["examp"] }
+ assert suggestions.any? { ["example"] }
+ assert suggestions.any? { ["other-example"] }
end
def test_suggest_gems_from_name_prerelease
spec_fetcher do|fetcher|
- fetcher.spec 'example', '1.a'
- fetcher.spec 'other-example', 1
+ fetcher.spec "example", "1.a"
+ fetcher.spec "other-example", 1
end
- suggestions = @sf.suggest_gems_from_name('examplw')
- assert_equal ['example'], suggestions
+ suggestions = @sf.suggest_gems_from_name("examplw")
+ assert_equal ["example"], suggestions
end
def test_available_specs_latest
spec_fetcher do |fetcher|
- fetcher.spec 'a', 1
- fetcher.spec 'a', 2
- fetcher.spec 'a', '3.a'
+ fetcher.spec "a", 1
+ fetcher.spec "a", 2
+ fetcher.spec "a", "3.a"
fetcher.legacy_platform
end
@@ -210,15 +207,15 @@ class TestGemSpecFetcher < Gem::TestCase
assert_equal [@source], specs.keys
expected = Gem::NameTuple.from_list \
- [['a', v(2), Gem::Platform::RUBY],
- ['pl', v(1), 'i386-linux']]
+ [["a", v(2), Gem::Platform::RUBY],
+ ["pl", v(1), "i386-linux"]]
assert_equal expected, specs[@source]
end
def test_available_specs_released
spec_fetcher do |fetcher|
- fetcher.spec 'a', 1
+ fetcher.spec "a", 1
fetcher.legacy_platform
end
@@ -227,17 +224,17 @@ class TestGemSpecFetcher < Gem::TestCase
assert_equal [@source], specs.keys
expected = Gem::NameTuple.from_list \
- [['a', v(1), Gem::Platform::RUBY],
- ['pl', v(1), 'i386-linux']]
+ [["a", v(1), Gem::Platform::RUBY],
+ ["pl", v(1), "i386-linux"]]
assert_equal expected, specs[@source]
end
def test_available_specs_complete
spec_fetcher do |fetcher|
- fetcher.spec 'a', 1
- fetcher.spec 'a', '2.a'
- fetcher.spec 'b', 2
+ fetcher.spec "a", 1
+ fetcher.spec "a", "2.a"
+ fetcher.spec "b", 2
fetcher.legacy_platform
end
@@ -246,19 +243,19 @@ class TestGemSpecFetcher < Gem::TestCase
assert_equal [@source], specs.keys
expected = Gem::NameTuple.from_list \
- [['a', v(1), Gem::Platform::RUBY],
- ['a', v('2.a'), Gem::Platform::RUBY],
- ['b', v(2), Gem::Platform::RUBY],
- ['pl', v(1), 'i386-linux']]
+ [["a", v(1), Gem::Platform::RUBY],
+ ["a", v("2.a"), Gem::Platform::RUBY],
+ ["b", v(2), Gem::Platform::RUBY],
+ ["pl", v(1), "i386-linux"]]
assert_equal expected, specs[@source]
end
def test_available_specs_complete_handles_no_prerelease
spec_fetcher do |fetcher|
- fetcher.spec 'a', 1
- fetcher.spec 'a', '2.a'
- fetcher.spec 'b', 2
+ fetcher.spec "a", 1
+ fetcher.spec "a", "2.a"
+ fetcher.spec "b", 2
fetcher.legacy_platform
end
@@ -270,16 +267,16 @@ class TestGemSpecFetcher < Gem::TestCase
assert_equal [@source], specs.keys
expected = Gem::NameTuple.from_list \
- [['a', v(1), Gem::Platform::RUBY],
- ['b', v(2), Gem::Platform::RUBY],
- ['pl', v(1), 'i386-linux']]
+ [["a", v(1), Gem::Platform::RUBY],
+ ["b", v(2), Gem::Platform::RUBY],
+ ["pl", v(1), "i386-linux"]]
assert_equal expected, specs[@source]
end
def test_available_specs_cache
spec_fetcher do |fetcher|
- fetcher.spec 'a', 1
+ fetcher.spec "a", 1
end
specs, _ = @sf.available_specs(:latest)
@@ -295,9 +292,9 @@ class TestGemSpecFetcher < Gem::TestCase
def test_available_specs_cache_released
spec_fetcher do |fetcher|
- fetcher.spec 'a', 1
- fetcher.spec 'a', '2.a'
- fetcher.spec 'b', 2
+ fetcher.spec "a", 1
+ fetcher.spec "a", "2.a"
+ fetcher.spec "b", 2
fetcher.legacy_platform
end
@@ -314,14 +311,14 @@ class TestGemSpecFetcher < Gem::TestCase
def test_available_specs_prerelease
spec_fetcher do |fetcher|
- fetcher.spec 'a', 1
- fetcher.spec 'a', '2.a'
+ fetcher.spec "a", 1
+ fetcher.spec "a", "2.a"
end
specs, _ = @sf.available_specs(:prerelease)
expected = Gem::NameTuple.from_list \
- [['a', v('2.a'), Gem::Platform::RUBY]]
+ [["a", v("2.a"), Gem::Platform::RUBY]]
assert_equal expected, specs[@source]
end
diff --git a/test/rubygems/test_gem_specification.rb b/test/rubygems/test_gem_specification.rb
index 782ae0380f..0a009cbd7b 100644
--- a/test/rubygems/test_gem_specification.rb
+++ b/test/rubygems/test_gem_specification.rb
@@ -1,16 +1,16 @@
# frozen_string_literal: true
-require 'benchmark'
-require_relative 'helper'
-require 'date'
-require 'pathname'
-require 'stringio'
-require 'rubygems/ext'
-require 'rubygems/specification'
-require 'rubygems/installer'
-require 'rubygems/platform'
+
+require_relative "helper"
+require "date"
+require "pathname"
+require "stringio"
+require "rubygems/ext"
+require "rubygems/specification"
+require "rubygems/installer"
+require "rubygems/platform"
class TestGemSpecification < Gem::TestCase
- LEGACY_YAML_SPEC = <<-EOF.freeze
+ LEGACY_YAML_SPEC = <<-EOF
--- !ruby/object:Gem::Specification
rubygems_version: "1.0"
name: keyedlist
@@ -29,7 +29,7 @@ email: flgr@ccan.de
has_rdoc: true
EOF
- LEGACY_RUBY_SPEC = <<-EOF.freeze
+ LEGACY_RUBY_SPEC = <<-EOF
Gem::Specification.new do |s|
s.name = %q{keyedlist}
s.version = %q{0.4.0}
@@ -44,33 +44,31 @@ end
EOF
def make_spec_c1
- @c1 = util_spec 'a', '1' do |s|
- s.executable = 'exec'
- s.extensions << 'ext/a/extconf.rb'
- s.test_file = 'test/suite.rb'
- s.requirements << 'A working computer'
- s.license = 'MIT'
-
- s.add_dependency 'rake', '> 0.4'
- s.add_dependency 'jabber4r', '> 0.0.0'
- s.add_dependency 'pqa', ['> 0.4', '<= 0.6']
-
- s.mark_version
+ @c1 = util_spec "a", "1" do |s|
+ s.executable = "exec"
+ s.extensions << "ext/a/extconf.rb"
+ s.test_file = "test/suite.rb"
+ s.requirements << "A working computer"
+ s.license = "MIT"
+
+ s.add_dependency "rake", "> 0.4"
+ s.add_dependency "jabber4r", "> 0.0.0"
+ s.add_dependency "pqa", ["> 0.4", "<= 0.6"]
+
s.files = %w[lib/code.rb]
end
end
def ext_spec(platform: Gem::Platform::RUBY)
- @ext = util_spec 'ext', '1' do |s|
- s.executable = 'exec'
- s.test_file = 'test/suite.rb'
+ @ext = util_spec "ext", "1" do |s|
+ s.executable = "exec"
+ s.test_file = "test/suite.rb"
s.extensions = %w[ext/extconf.rb]
- s.license = 'MIT'
+ s.license = "MIT"
s.platform = platform
- s.mark_version
s.files = %w[lib/code.rb]
- s.installed_by_version = v('2.2')
+ s.installed_by_version = v("2.2")
end
end
@@ -88,304 +86,287 @@ end
# is not set.
Gem.instance_variable_set(:'@default_source_date_epoch', nil)
- @a1 = util_spec 'a', '1' do |s|
- s.executable = 'exec'
- s.test_file = 'test/suite.rb'
- s.requirements << 'A working computer'
- s.license = 'MIT'
+ @a1 = util_spec "a", "1" do |s|
+ s.required_ruby_version = ">= 2.3.0"
+ s.executable = "exec"
+ s.test_file = "test/suite.rb"
+ s.requirements << "A working computer"
+ s.license = "MIT"
- s.mark_version
s.files = %w[lib/code.rb]
end
- @a2 = util_spec 'a', '2' do |s|
+ @a2 = util_spec "a", "2" do |s|
s.files = %w[lib/code.rb]
end
- @a3 = util_spec 'a', '3' do |s|
- s.metadata['allowed_push_host'] = "https://privategemserver.com"
+ @a3 = util_spec "a", "3" do |s|
+ s.metadata["allowed_push_host"] = "https://privategemserver.com"
end
@current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
end
def test_self_find_active_stub_by_path
- spec = util_spec('a', '1', nil, 'lib/foo.rb')
+ spec = util_spec("a", "1", nil, "lib/foo.rb")
spec.activated = true
# There used to be a bug (introduced in a9c1aaf) when Gem::Specification
# objects are present in the @stubs collection. This test verifies that
# this scenario works correctly.
Gem::Specification.all = [spec]
- assert_equal spec, Gem::Specification.find_active_stub_by_path('foo')
+ assert_equal spec, Gem::Specification.find_active_stub_by_path("foo")
end
def test_self_activate
- foo = util_spec 'foo', '1'
+ foo = util_spec "foo", "1"
assert_activate %w[foo-1], foo
end
def test_self_activate_ambiguous_direct
- save_loaded_features do
- a1 = util_spec "a", "1", "b" => "> 0"
- b1 = util_spec("b", "1", { "c" => ">= 1" }, "lib/d#{$$}.rb")
- b2 = util_spec("b", "2", { "c" => ">= 2" }, "lib/d#{$$}.rb")
- c1 = util_spec "c", "1"
- c2 = util_spec "c", "2"
+ a1 = util_spec "a", "1", "b" => "> 0"
+ b1 = util_spec("b", "1", { "c" => ">= 1" }, "lib/d#{$$}.rb")
+ b2 = util_spec("b", "2", { "c" => ">= 2" }, "lib/d#{$$}.rb")
+ c1 = util_spec "c", "1"
+ c2 = util_spec "c", "2"
- Gem::Specification.reset
- install_specs c1, c2, b1, b2, a1
+ Gem::Specification.reset
+ install_specs c1, c2, b1, b2, a1
- a1.activate
- assert_equal %w[a-1], loaded_spec_names
- assert_equal ["b (> 0)"], unresolved_names
+ a1.activate
+ assert_equal %w[a-1], loaded_spec_names
+ assert_equal ["b (> 0)"], unresolved_names
- require "d#{$$}"
+ require "d#{$$}"
- assert_equal %w[a-1 b-2 c-2], loaded_spec_names
- assert_equal [], unresolved_names
- end
+ assert_equal %w[a-1 b-2 c-2], loaded_spec_names
+ assert_equal [], unresolved_names
end
def test_find_in_unresolved_tree_is_not_exponentiental
- save_loaded_features do
- num_of_pkg = 7
- num_of_version_per_pkg = 3
- packages = (0..num_of_pkg).map do |pkgi|
- (0..num_of_version_per_pkg).map do |pkg_version|
- deps = Hash[((pkgi + 1)..num_of_pkg).map do |deppkgi|
- ["pkg#{deppkgi}", ">= 0"]
- end]
- util_spec "pkg#{pkgi}", pkg_version.to_s, deps
- end
+ begin
+ require "benchmark"
+ rescue LoadError
+ pend "Benchmark is not available in this environment. Please install it with `gem install benchmark`."
+ end
+
+ pend "currently slower in CI on TruffleRuby" if RUBY_ENGINE == "truffleruby"
+ num_of_pkg = 7
+ num_of_version_per_pkg = 3
+ packages = (0..num_of_pkg).map do |pkgi|
+ (0..num_of_version_per_pkg).map do |pkg_version|
+ deps = Hash[((pkgi + 1)..num_of_pkg).map do |deppkgi|
+ ["pkg#{deppkgi}", ">= 0"]
+ end]
+ util_spec "pkg#{pkgi}", pkg_version.to_s, deps
end
- base = util_spec "pkg_base", "1", {"pkg0" => ">= 0"}
+ end
+ base = util_spec "pkg_base", "1", { "pkg0" => ">= 0" }
- Gem::Specification.reset
- install_specs(*packages.flatten.reverse)
- install_specs base
- base.activate
+ Gem::Specification.reset
+ install_specs(*packages.flatten.reverse)
+ install_specs base
+ base.activate
- tms = Benchmark.measure do
- assert_raise(LoadError) { require 'no_such_file_foo' }
- end
- assert_operator tms.total, :<=, 10
+ tms = Benchmark.measure do
+ assert_raise(LoadError) { require "no_such_file_foo" }
end
+ assert_operator tms.total, :<=, 10
end
def test_self_activate_ambiguous_indirect
- save_loaded_features do
- a1 = util_spec "a", "1", "b" => "> 0"
- b1 = util_spec "b", "1", "c" => ">= 1"
- b2 = util_spec "b", "2", "c" => ">= 2"
- c1 = util_spec "c", "1", nil, "lib/d#{$$}.rb"
- c2 = util_spec "c", "2", nil, "lib/d#{$$}.rb"
+ a1 = util_spec "a", "1", "b" => "> 0"
+ b1 = util_spec "b", "1", "c" => ">= 1"
+ b2 = util_spec "b", "2", "c" => ">= 2"
+ c1 = util_spec "c", "1", nil, "lib/d#{$$}.rb"
+ c2 = util_spec "c", "2", nil, "lib/d#{$$}.rb"
- install_specs c1, c2, b1, b2, a1
+ install_specs c1, c2, b1, b2, a1
- a1.activate
- assert_equal %w[a-1], loaded_spec_names
- assert_equal ["b (> 0)"], unresolved_names
+ a1.activate
+ assert_equal %w[a-1], loaded_spec_names
+ assert_equal ["b (> 0)"], unresolved_names
- require "d#{$$}"
+ require "d#{$$}"
- assert_equal %w[a-1 b-2 c-2], loaded_spec_names
- assert_equal [], unresolved_names
- end
+ assert_equal %w[a-1 b-2 c-2], loaded_spec_names
+ assert_equal [], unresolved_names
end
def test_self_activate_ambiguous_indirect_conflict
- save_loaded_features do
- a1 = util_spec "a", "1", "b" => "> 0"
- a2 = util_spec "a", "2", "b" => "> 0"
- b1 = util_spec "b", "1", "c" => ">= 1"
- b2 = util_spec "b", "2", "c" => ">= 2"
- c1 = util_spec "c", "1", nil, "lib/d#{$$}.rb"
- c2 = util_spec("c", "2", { "a" => "1" }, "lib/d#{$$}.rb") # conflicts with a-2
+ a1 = util_spec "a", "1", "b" => "> 0"
+ a2 = util_spec "a", "2", "b" => "> 0"
+ b1 = util_spec "b", "1", "c" => ">= 1"
+ b2 = util_spec "b", "2", "c" => ">= 2"
+ c1 = util_spec "c", "1", nil, "lib/d#{$$}.rb"
+ c2 = util_spec("c", "2", { "a" => "1" }, "lib/d#{$$}.rb") # conflicts with a-2
- install_specs c1, b1, a1, a2, c2, b2
+ install_specs c1, b1, a1, a2, c2, b2
- a2.activate
- assert_equal %w[a-2], loaded_spec_names
- assert_equal ["b (> 0)"], unresolved_names
+ a2.activate
+ assert_equal %w[a-2], loaded_spec_names
+ assert_equal ["b (> 0)"], unresolved_names
- require "d#{$$}"
+ require "d#{$$}"
- assert_equal %w[a-2 b-1 c-1], loaded_spec_names
- assert_equal [], unresolved_names
- end
+ assert_equal %w[a-2 b-1 c-1], loaded_spec_names
+ assert_equal [], unresolved_names
end
def test_self_activate_ambiguous_unrelated
- save_loaded_features do
- a1 = util_spec "a", "1", "b" => "> 0"
- b1 = util_spec "b", "1", "c" => ">= 1"
- b2 = util_spec "b", "2", "c" => ">= 2"
- c1 = util_spec "c", "1"
- c2 = util_spec "c", "2"
- d1 = util_spec "d", "1", nil, "lib/d#{$$}.rb"
+ a1 = util_spec "a", "1", "b" => "> 0"
+ b1 = util_spec "b", "1", "c" => ">= 1"
+ b2 = util_spec "b", "2", "c" => ">= 2"
+ c1 = util_spec "c", "1"
+ c2 = util_spec "c", "2"
+ d1 = util_spec "d", "1", nil, "lib/d#{$$}.rb"
- install_specs d1, c1, c2, b1, b2, a1
+ install_specs d1, c1, c2, b1, b2, a1
- a1.activate
- assert_equal %w[a-1], loaded_spec_names
- assert_equal ["b (> 0)"], unresolved_names
+ a1.activate
+ assert_equal %w[a-1], loaded_spec_names
+ assert_equal ["b (> 0)"], unresolved_names
- require "d#{$$}"
+ require "d#{$$}"
- assert_equal %w[a-1 d-1], loaded_spec_names
- assert_equal ["b (> 0)"], unresolved_names
- end
+ assert_equal %w[a-1 d-1], loaded_spec_names
+ assert_equal ["b (> 0)"], unresolved_names
end
def test_require_should_prefer_latest_gem_level1
- save_loaded_features do
- a1 = util_spec "a", "1", "b" => "> 0"
- b1 = util_spec "b", "1", "c" => ">= 0" # unresolved
- b2 = util_spec "b", "2", "c" => ">= 0"
- c1 = util_spec "c", "1", nil, "lib/c#{$$}.rb" # 1st level
- c2 = util_spec "c", "2", nil, "lib/c#{$$}.rb"
+ a1 = util_spec "a", "1", "b" => "> 0"
+ b1 = util_spec "b", "1", "c" => ">= 0" # unresolved
+ b2 = util_spec "b", "2", "c" => ">= 0"
+ c1 = util_spec "c", "1", nil, "lib/c#{$$}.rb" # 1st level
+ c2 = util_spec "c", "2", nil, "lib/c#{$$}.rb"
- install_specs c1, c2, b1, b2, a1
+ install_specs c1, c2, b1, b2, a1
- a1.activate
+ a1.activate
- require "c#{$$}"
+ require "c#{$$}"
- assert_equal %w[a-1 b-2 c-2], loaded_spec_names
- end
+ assert_equal %w[a-1 b-2 c-2], loaded_spec_names
end
def test_require_should_prefer_latest_gem_level2
- save_loaded_features do
- a1 = util_spec "a", "1", "b" => "> 0"
- b1 = util_spec "b", "1", "c" => ">= 0" # unresolved
- b2 = util_spec "b", "2", "c" => ">= 0"
- c1 = util_spec "c", "1", "d" => ">= 0" # 1st level
- c2 = util_spec "c", "2", "d" => ">= 0"
- d1 = util_spec "d", "1", nil, "lib/d#{$$}.rb" # 2nd level
- d2 = util_spec "d", "2", nil, "lib/d#{$$}.rb"
+ a1 = util_spec "a", "1", "b" => "> 0"
+ b1 = util_spec "b", "1", "c" => ">= 0" # unresolved
+ b2 = util_spec "b", "2", "c" => ">= 0"
+ c1 = util_spec "c", "1", "d" => ">= 0" # 1st level
+ c2 = util_spec "c", "2", "d" => ">= 0"
+ d1 = util_spec "d", "1", nil, "lib/d#{$$}.rb" # 2nd level
+ d2 = util_spec "d", "2", nil, "lib/d#{$$}.rb"
- install_specs d1, d2, c1, c2, b1, b2, a1
+ install_specs d1, d2, c1, c2, b1, b2, a1
- a1.activate
+ a1.activate
- require "d#{$$}"
+ require "d#{$$}"
- assert_equal %w[a-1 b-2 c-2 d-2], loaded_spec_names
- end
+ assert_equal %w[a-1 b-2 c-2 d-2], loaded_spec_names
end
def test_require_finds_in_2nd_level_indirect
- save_loaded_features do
- a1 = util_spec "a", "1", "b" => "> 0"
- b1 = util_spec "b", "1", "c" => ">= 0" # unresolved
- b2 = util_spec "b", "2", "c" => ">= 0"
- c1 = util_spec "c", "1", "d" => "<= 2" # 1st level
- c2 = util_spec "c", "2", "d" => "<= 2"
- d1 = util_spec "d", "1", nil, "lib/d#{$$}.rb" # 2nd level
- d2 = util_spec "d", "2", nil, "lib/d#{$$}.rb"
- d3 = util_spec "d", "3", nil, "lib/d#{$$}.rb"
+ a1 = util_spec "a", "1", "b" => "> 0"
+ b1 = util_spec "b", "1", "c" => ">= 0" # unresolved
+ b2 = util_spec "b", "2", "c" => ">= 0"
+ c1 = util_spec "c", "1", "d" => "<= 2" # 1st level
+ c2 = util_spec "c", "2", "d" => "<= 2"
+ d1 = util_spec "d", "1", nil, "lib/d#{$$}.rb" # 2nd level
+ d2 = util_spec "d", "2", nil, "lib/d#{$$}.rb"
+ d3 = util_spec "d", "3", nil, "lib/d#{$$}.rb"
- install_specs d1, d2, d3, c1, c2, b1, b2, a1
+ install_specs d1, d2, d3, c1, c2, b1, b2, a1
- a1.activate
+ a1.activate
- require "d#{$$}"
+ require "d#{$$}"
- assert_equal %w[a-1 b-2 c-2 d-2], loaded_spec_names
- end
+ assert_equal %w[a-1 b-2 c-2 d-2], loaded_spec_names
end
def test_require_should_prefer_reachable_gems
- save_loaded_features do
- a1 = util_spec "a", "1", "b" => "> 0"
- b1 = util_spec "b", "1", "c" => ">= 0" # unresolved
- b2 = util_spec "b", "2", "c" => ">= 0"
- c1 = util_spec "c", "1", "d" => "<= 2" # 1st level
- c2 = util_spec "c", "2", "d" => "<= 2"
- d1 = util_spec "d", "1", nil, "lib/d#{$$}.rb" # 2nd level
- d2 = util_spec "d", "2", nil, "lib/d#{$$}.rb"
- d3 = util_spec "d", "3", nil, "lib/d#{$$}.rb"
- e = util_spec "anti_d", "1", nil, "lib/d#{$$}.rb"
+ a1 = util_spec "a", "1", "b" => "> 0"
+ b1 = util_spec "b", "1", "c" => ">= 0" # unresolved
+ b2 = util_spec "b", "2", "c" => ">= 0"
+ c1 = util_spec "c", "1", "d" => "<= 2" # 1st level
+ c2 = util_spec "c", "2", "d" => "<= 2"
+ d1 = util_spec "d", "1", nil, "lib/d#{$$}.rb" # 2nd level
+ d2 = util_spec "d", "2", nil, "lib/d#{$$}.rb"
+ d3 = util_spec "d", "3", nil, "lib/d#{$$}.rb"
+ e = util_spec "anti_d", "1", nil, "lib/d#{$$}.rb"
+
+ install_specs d1, d2, d3, e, c1, c2, b1, b2, a1
- install_specs d1, d2, d3, e, c1, c2, b1, b2, a1
-
- a1.activate
+ a1.activate
- require "d#{$$}"
+ require "d#{$$}"
- assert_equal %w[a-1 b-2 c-2 d-2], loaded_spec_names
- end
+ assert_equal %w[a-1 b-2 c-2 d-2], loaded_spec_names
end
def test_require_should_not_conflict
- save_loaded_features do
- base = util_spec "0", "1", "A" => ">= 1"
- a1 = util_spec "A", "1", {"c" => ">= 2", "b" => "> 0"}, "lib/a.rb"
- a2 = util_spec "A", "2", {"c" => ">= 2", "b" => "> 0"}, "lib/a.rb"
- b1 = util_spec "b", "1", {"c" => "= 1"}, "lib/d#{$$}.rb"
- b2 = util_spec "b", "2", {"c" => "= 2"}, "lib/d#{$$}.rb"
- c1 = util_spec "c", "1", {}, "lib/c.rb"
- c2 = util_spec "c", "2", {}, "lib/c.rb"
- c3 = util_spec "c", "3", {}, "lib/c.rb"
-
- install_specs c1, c2, c3, b1, b2, a1, a2, base
-
- base.activate
- assert_equal %w[0-1], loaded_spec_names
- assert_equal ["A (>= 1)"], unresolved_names
+ base = util_spec "0", "1", "A" => ">= 1"
+ a1 = util_spec "A", "1", { "c" => ">= 2", "b" => "> 0" }, "lib/a.rb"
+ a2 = util_spec "A", "2", { "c" => ">= 2", "b" => "> 0" }, "lib/a.rb"
+ b1 = util_spec "b", "1", { "c" => "= 1" }, "lib/d#{$$}.rb"
+ b2 = util_spec "b", "2", { "c" => "= 2" }, "lib/d#{$$}.rb"
+ c1 = util_spec "c", "1", {}, "lib/c.rb"
+ c2 = util_spec "c", "2", {}, "lib/c.rb"
+ c3 = util_spec "c", "3", {}, "lib/c.rb"
- require "d#{$$}"
+ install_specs c1, c2, c3, b1, b2, a1, a2, base
- assert_equal %w[0-1 A-2 b-2 c-2], loaded_spec_names
- assert_equal [], unresolved_names
- end
+ base.activate
+ assert_equal %w[0-1], loaded_spec_names
+ assert_equal ["A (>= 1)"], unresolved_names
+
+ require "d#{$$}"
+
+ assert_equal %w[0-1 A-2 b-2 c-2], loaded_spec_names
+ assert_equal [], unresolved_names
end
def test_inner_clonflict_in_indirect_gems
- save_loaded_features do
- a1 = util_spec "a", "1", "b" => "> 0"
- b1 = util_spec "b", "1", "c" => ">= 1" # unresolved
- b2 = util_spec "b", "2", "c" => ">= 1", "d" => "< 3"
- c1 = util_spec "c", "1", "d" => "<= 2" # 1st level
- c2 = util_spec "c", "2", "d" => "<= 2"
- c3 = util_spec "c", "3", "d" => "<= 3"
- d1 = util_spec "d", "1", nil, "lib/d#{$$}.rb" # 2nd level
- d2 = util_spec "d", "2", nil, "lib/d#{$$}.rb"
- d3 = util_spec "d", "3", nil, "lib/d#{$$}.rb"
-
- install_specs d1, d2, d3, c1, c2, c3, b1, b2, a1
+ a1 = util_spec "a", "1", "b" => "> 0"
+ b1 = util_spec "b", "1", "c" => ">= 1" # unresolved
+ b2 = util_spec "b", "2", "c" => ">= 1", "d" => "< 3"
+ c1 = util_spec "c", "1", "d" => "<= 2" # 1st level
+ c2 = util_spec "c", "2", "d" => "<= 2"
+ c3 = util_spec "c", "3", "d" => "<= 3"
+ d1 = util_spec "d", "1", nil, "lib/d#{$$}.rb" # 2nd level
+ d2 = util_spec "d", "2", nil, "lib/d#{$$}.rb"
+ d3 = util_spec "d", "3", nil, "lib/d#{$$}.rb"
+
+ install_specs d1, d2, d3, c1, c2, c3, b1, b2, a1
- a1.activate
+ a1.activate
- require "d#{$$}"
+ require "d#{$$}"
- assert_includes [%w[a-1 b-2 c-3 d-2],%w[a-1 b-2 d-2]], loaded_spec_names
- end
+ assert_includes [%w[a-1 b-2 c-3 d-2],%w[a-1 b-2 d-2]], loaded_spec_names
end
def test_inner_clonflict_in_indirect_gems_reversed
- save_loaded_features do
- a1 = util_spec "a", "1", "b" => "> 0"
- b1 = util_spec "b", "1", "xc" => ">= 1" # unresolved
- b2 = util_spec "b", "2", "xc" => ">= 1", "d" => "< 3"
- c1 = util_spec "xc", "1", "d" => "<= 3" # 1st level
- c2 = util_spec "xc", "2", "d" => "<= 2"
- c3 = util_spec "xc", "3", "d" => "<= 3"
- d1 = util_spec "d", "1", nil, "lib/d#{$$}.rb" # 2nd level
- d2 = util_spec "d", "2", nil, "lib/d#{$$}.rb"
- d3 = util_spec "d", "3", nil, "lib/d#{$$}.rb"
-
- install_specs d1, d2, d3, c1, c2, c3, b1, b2, a1
+ a1 = util_spec "a", "1", "b" => "> 0"
+ b1 = util_spec "b", "1", "xc" => ">= 1" # unresolved
+ b2 = util_spec "b", "2", "xc" => ">= 1", "d" => "< 3"
+ c1 = util_spec "xc", "1", "d" => "<= 3" # 1st level
+ c2 = util_spec "xc", "2", "d" => "<= 2"
+ c3 = util_spec "xc", "3", "d" => "<= 3"
+ d1 = util_spec "d", "1", nil, "lib/d#{$$}.rb" # 2nd level
+ d2 = util_spec "d", "2", nil, "lib/d#{$$}.rb"
+ d3 = util_spec "d", "3", nil, "lib/d#{$$}.rb"
+
+ install_specs d1, d2, d3, c1, c2, c3, b1, b2, a1
- a1.activate
+ a1.activate
- require "d#{$$}"
+ require "d#{$$}"
- assert_includes [%w[a-1 b-2 d-2 xc-3], %w[a-1 b-2 d-2]], loaded_spec_names
- end
+ assert_includes [%w[a-1 b-2 d-2 xc-3], %w[a-1 b-2 d-2]], loaded_spec_names
end
##
@@ -395,13 +376,13 @@ end
# [B] ~> 1.0 (satisfied by 1.0)
def test_self_activate_checks_dependencies
- a = util_spec 'a', '1.0'
- a.add_dependency 'c', '= 1.0'
- a.add_dependency 'b', '~> 1.0'
+ a = util_spec "a", "1.0"
+ a.add_dependency "c", "= 1.0"
+ a.add_dependency "b", "~> 1.0"
- b1 = util_spec 'b', '1.0'
- b2 = util_spec 'b', '2.0'
- c = util_spec 'c', '1.0', 'b' => '= 2.0'
+ b1 = util_spec "b", "1.0"
+ b2 = util_spec "b", "2.0"
+ c = util_spec "c", "1.0", "b" => "= 2.0"
install_specs b1, b2, c, a
e = assert_raise Gem::LoadError do
@@ -419,10 +400,10 @@ end
# [B] = 2.0
def test_self_activate_divergent
- a = util_spec 'a', '1.0', 'b' => '~> 1.0', 'c' => '= 1.0'
- b1 = util_spec 'b', '1.0'
- b2 = util_spec 'b', '2.0'
- c = util_spec 'c', '1.0', 'b' => '= 2.0'
+ a = util_spec "a", "1.0", "b" => "~> 1.0", "c" => "= 1.0"
+ b1 = util_spec "b", "1.0"
+ b2 = util_spec "b", "2.0"
+ c = util_spec "c", "1.0", "b" => "= 2.0"
install_specs b1, b2, c, a
@@ -438,9 +419,9 @@ end
# DOC
def test_self_activate_old_required
- e1, = util_spec 'e', '1', 'd' => '= 1'
- @d1 = util_spec 'd', '1'
- @d2 = util_spec 'd', '2'
+ e1, = util_spec "e", "1", "d" => "= 1"
+ @d1 = util_spec "d", "1"
+ @d2 = util_spec "d", "2"
install_specs @d1, @d2, e1
@@ -451,17 +432,17 @@ end
# DOC
def test_self_activate_platform_alternate
- @x1_m = util_spec 'x', '1' do |s|
+ @x1_m = util_spec "x", "1" do |s|
s.platform = Gem::Platform.new %w[cpu my_platform 1]
end
- @x1_o = util_spec 'x', '1' do |s|
+ @x1_o = util_spec "x", "1" do |s|
s.platform = Gem::Platform.new %w[cpu other_platform 1]
end
- @w1 = util_spec 'w', '1', 'x' => nil
+ @w1 = util_spec "w", "1", "x" => nil
- util_set_arch 'cpu-my_platform1'
+ util_set_arch "cpu-my_platform1"
install_specs @x1_m, @x1_o, @w1
assert_activate %w[x-1-cpu-my_platform-1 w-1], @w1, @x1_m
@@ -471,13 +452,13 @@ end
# DOC
def test_self_activate_platform_bump
- @y1 = util_spec 'y', '1'
+ @y1 = util_spec "y", "1"
- @y1_1_p = util_spec 'y', '1.1' do |s|
+ @y1_1_p = util_spec "y", "1.1" do |s|
s.platform = Gem::Platform.new %w[cpu my_platform 1]
end
- @z1 = util_spec 'z', '1', 'y' => nil
+ @z1 = util_spec "z", "1", "y" => nil
install_specs @y1, @y1_1_p, @z1
assert_activate %w[y-1 z-1], @z1, @y1
@@ -490,11 +471,11 @@ end
# [A] >= 0 (satisfied by 1.a)
def test_self_activate_prerelease
- @c1_pre = util_spec 'c', '1.a', "a" => "1.a", "b" => "1"
- @a1_pre = util_spec 'a', '1.a'
- @b1 = util_spec 'b', '1' do |s|
- s.add_dependency 'a'
- s.add_development_dependency 'aa'
+ @c1_pre = util_spec "c", "1.a", "a" => "1.a", "b" => "1"
+ @a1_pre = util_spec "a", "1.a"
+ @b1 = util_spec "b", "1" do |s|
+ s.add_dependency "a"
+ s.add_development_dependency "aa"
end
install_specs @a1_pre, @b1, @c1_pre
@@ -509,41 +490,37 @@ end
install_specs b1, b2, a1
a1.activate
- save_loaded_features do
- require "b/c"
- end
+ require "b/c"
assert_equal %w[a-1 b-1], loaded_spec_names
end
def test_self_activate_via_require_wtf
- save_loaded_features do
- a1 = util_spec "a", "1", "b" => "> 0", "d" => "> 0" # this
- b1 = util_spec "b", "1", { "c" => ">= 1" }, "lib/b#{$$}.rb"
- b2 = util_spec "b", "2", { "c" => ">= 2" }, "lib/b#{$$}.rb" # this
- c1 = util_spec "c", "1"
- c2 = util_spec "c", "2" # this
- d1 = util_spec "d", "1", { "c" => "< 2" }, "lib/d#{$$}.rb"
- d2 = util_spec "d", "2", { "c" => "< 2" }, "lib/d#{$$}.rb" # this
+ a1 = util_spec "a", "1", "b" => "> 0", "d" => "> 0" # this
+ b1 = util_spec "b", "1", { "c" => ">= 1" }, "lib/b#{$$}.rb"
+ b2 = util_spec "b", "2", { "c" => ">= 2" }, "lib/b#{$$}.rb" # this
+ c1 = util_spec "c", "1"
+ c2 = util_spec "c", "2" # this
+ d1 = util_spec "d", "1", { "c" => "< 2" }, "lib/d#{$$}.rb"
+ d2 = util_spec "d", "2", { "c" => "< 2" }, "lib/d#{$$}.rb" # this
- install_specs c1, c2, b1, b2, d1, d2, a1
+ install_specs c1, c2, b1, b2, d1, d2, a1
- a1.activate
+ a1.activate
- assert_equal %w[a-1], loaded_spec_names
- assert_equal ["b (> 0)", "d (> 0)"], unresolved_names
+ assert_equal %w[a-1], loaded_spec_names
+ assert_equal ["b (> 0)", "d (> 0)"], unresolved_names
- require "b#{$$}"
+ require "b#{$$}"
- e = assert_raise Gem::LoadError do
- require "d#{$$}"
- end
+ e = assert_raise Gem::LoadError do
+ require "d#{$$}"
+ end
- assert_equal "unable to find a version of 'd' to activate", e.message
+ assert_equal "unable to find a version of 'd' to activate", e.message
- assert_equal %w[a-1 b-2 c-2], loaded_spec_names
- assert_equal ["d (> 0)"], unresolved_names
- end
+ assert_equal %w[a-1 b-2 c-2], loaded_spec_names
+ assert_equal ["d (> 0)"], unresolved_names
end
def test_self_activate_deep_unambiguous
@@ -560,7 +537,7 @@ end
end
def test_self_activate_loaded
- foo = util_spec 'foo', '1'
+ foo = util_spec "foo", "1"
assert foo.activate
refute foo.activate
@@ -572,9 +549,9 @@ end
# [C] depends on nothing
def test_self_activate_unrelated
- a = util_spec 'a', '1.0', 'b' => '>= 1.0'
- b = util_spec 'b', '1.0'
- c = util_spec 'c', '1.0'
+ a = util_spec "a", "1.0", "b" => ">= 1.0"
+ b = util_spec "b", "1.0"
+ c = util_spec "c", "1.0"
install_specs b, c, a
assert_activate %w[b-1.0 c-1.0 a-1.0], a, c, "b"
@@ -590,11 +567,11 @@ end
# TODO: move these to specification
def test_self_activate_over
- a = util_spec 'a', '1.0', 'b' => '>= 1.0', 'c' => '= 1.0'
- install_specs util_spec 'b', '1.0'
- install_specs util_spec 'b', '1.1'
- install_specs util_spec 'b', '2.0'
- install_specs util_spec 'c', '1.0', 'b' => '~> 1.0'
+ a = util_spec "a", "1.0", "b" => ">= 1.0", "c" => "= 1.0"
+ install_specs util_spec "b", "1.0"
+ install_specs util_spec "b", "1.1"
+ install_specs util_spec "b", "2.0"
+ install_specs util_spec "c", "1.0", "b" => "~> 1.0"
install_specs a
a.activate
@@ -615,10 +592,10 @@ end
# first resolve through a dependency that is later pruned.
def test_self_activate_under
- a = util_spec 'a', '1.0', 'b' => '~> 1.0', 'c' => '= 1.0'
- b1 = util_spec 'b', '1.0'
- b1_1 = util_spec 'b', '1.1'
- c = util_spec 'c', '1.0', 'b' => '= 1.0'
+ a = util_spec "a", "1.0", "b" => "~> 1.0", "c" => "= 1.0"
+ b1 = util_spec "b", "1.0"
+ b1_1 = util_spec "b", "1.1"
+ c = util_spec "c", "1.0", "b" => "= 1.0"
install_specs b1, b1_1, c, a
@@ -634,10 +611,10 @@ end
# [C1] depends on nothing
def test_self_activate_dropped
- a1 = util_spec 'a', '1', 'b' => nil
- b1 = util_spec 'b', '1', 'c' => nil
- b2 = util_spec 'b', '2'
- c1 = util_spec 'c', '1'
+ a1 = util_spec "a", "1", "b" => nil
+ b1 = util_spec "b", "1", "c" => nil
+ b2 = util_spec "b", "2"
+ c1 = util_spec "c", "1"
install_specs c1, b1, b2, a1
assert_activate %w[b-2 a-1], a1, "b"
@@ -654,11 +631,11 @@ end
# resolve.
def test_self_activate_raggi_the_edgecase_generator
- a = util_spec 'a', '1.0', 'b' => '>= 1.0', 'c' => '>= 1.0'
- b1 = util_spec 'b', '1.0'
- b1_0 = util_spec 'b', '1.1', 'z' => '>= 1.0'
- c = util_spec 'c', '1.0', 'b' => '= 1.0'
- z = util_spec 'z', '1'
+ a = util_spec "a", "1.0", "b" => ">= 1.0", "c" => ">= 1.0"
+ b1 = util_spec "b", "1.0"
+ b1_0 = util_spec "b", "1.1", "z" => ">= 1.0"
+ c = util_spec "c", "1.0", "b" => "= 1.0"
+ z = util_spec "z", "1"
install_specs z, b1, b1_0, c, z
@@ -666,8 +643,8 @@ end
end
def test_self_activate_conflict
- install_specs util_spec 'b', '1.0'
- install_specs util_spec 'b', '2.0'
+ install_specs util_spec "b", "1.0"
+ install_specs util_spec "b", "2.0"
gem "b", "= 1.0"
@@ -682,7 +659,7 @@ end
install_specs a
Gem::Specification.all = [a]
- assert_equal a, Gem::Specification.find_inactive_by_path('foo')
+ assert_equal a, Gem::Specification.find_inactive_by_path("foo")
end
def test_self_attribute_names
@@ -718,20 +695,20 @@ end
version
]
- actual_value = Gem::Specification.attribute_names.map {|a| a.to_s }.sort
+ actual_value = Gem::Specification.attribute_names.map(&: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.name = "a"
+ spec.version = "1"
spec.specification_version = @current_version + 1
load_spec = Marshal.load Marshal.dump(spec)
- assert_equal 'a', load_spec.name
+ assert_equal "a", load_spec.name
assert_equal Gem::Version.new(1), load_spec.version
assert_equal @current_version, load_spec.specification_version
end
@@ -810,37 +787,17 @@ dependencies: []
end
def test_self_load_relative
- File.open 'a-2.gemspec', 'w' do |io|
+ File.open "a-2.gemspec", "w" do |io|
io.write @a2.to_ruby_for_cache
end
- spec = Gem::Specification.load 'a-2.gemspec'
+ spec = Gem::Specification.load "a-2.gemspec"
@a2.files.clear
assert_equal @a2, spec
- assert_equal File.join(@tempdir, 'a-2.gemspec'), spec.loaded_from
- end
-
- if RUBY_ENGINE == 'ruby' and RUBY_VERSION < '2.7'
- def test_self_load_tainted
- full_path = @a2.spec_file
- write_file full_path do |io|
- io.write @a2.to_ruby_for_cache
- end
-
- full_path.taint
- loader = Thread.new { $SAFE = 1; Gem::Specification.load full_path }
- spec = loader.value
-
- @a2.files.clear
-
- assert_equal @a2, spec
-
- ensure
- $SAFE = 0
- end
+ assert_equal File.join(@tempdir, "a-2.gemspec"), spec.loaded_from
end
def test_self_load_escape_curly
@@ -901,34 +858,31 @@ dependencies: []
end
def test_self_load_utf8_with_ascii_encoding
- int_enc = Encoding.default_internal
- silence_warnings { Encoding.default_internal = 'US-ASCII' }
-
- spec2 = @a2.dup
- bin = "\u5678".dup
- spec2.authors = [bin]
- full_path = spec2.spec_file
- write_file full_path do |io|
- io.write spec2.to_ruby_for_cache.force_encoding('BINARY').sub("\\u{5678}", bin.force_encoding('BINARY'))
- end
+ with_internal_encoding("US-ASCII") do
+ spec2 = @a2.dup
+ bin = "\u5678".dup
+ spec2.authors = [bin]
+ full_path = spec2.spec_file
+ write_file full_path do |io|
+ io.write spec2.to_ruby_for_cache.force_encoding("BINARY").sub("\\u{5678}", bin.force_encoding("BINARY"))
+ end
- spec = Gem::Specification.load full_path
+ spec = Gem::Specification.load full_path
- spec2.files.clear
+ spec2.files.clear
- assert_equal spec2, spec
- ensure
- silence_warnings { Encoding.default_internal = int_enc }
+ assert_equal spec2, spec
+ end
end
def test_self_load_legacy_ruby
spec = Gem::Deprecate.skip_during do
eval LEGACY_RUBY_SPEC
end
- assert_equal 'keyedlist', spec.name
- assert_equal '0.4.0', spec.version.to_s
+ assert_equal "keyedlist", spec.name
+ assert_equal "0.4.0", spec.version.to_s
assert_kind_of Time, spec.date
- assert spec.required_ruby_version.satisfied_by?(Gem::Version.new('1'))
+ assert spec.required_ruby_version.satisfied_by?(Gem::Version.new("1"))
assert_equal false, spec.has_unit_tests?
end
@@ -963,26 +917,26 @@ dependencies: []
def test_self_outdated
spec_fetcher do |fetcher|
- fetcher.download 'a', 4
+ fetcher.download "a", 4
- fetcher.spec 'a', 3
+ fetcher.spec "a", 3
end
assert_equal %w[a], Gem::Specification.outdated
end
def test_self_outdated_and_latest_remotes
- specs = spec_fetcher do |fetcher|
- fetcher.download 'a', 4
- fetcher.download 'b', 3
+ spec_fetcher do |fetcher|
+ fetcher.download "a", 4
+ fetcher.download "b", 3
- fetcher.spec 'a', '3.a'
- fetcher.spec 'b', 2
+ fetcher.spec "a", "3.a"
+ fetcher.spec "b", 2
end
expected = [
- [specs['a-3.a'], v(4)],
- [specs['b-2'], v(3)],
+ [Gem::Specification.stubs.find {|s| s.full_name == "a-3.a" }, v(4)],
+ [Gem::Specification.stubs.find {|s| s.full_name == "b-2" }, v(3)],
]
assert_equal expected, Gem::Specification.outdated_and_latest_version.to_a
@@ -991,18 +945,18 @@ dependencies: []
def test_self_remove_spec
install_specs @a1
- assert_includes Gem::Specification.all_names, 'a-1'
- assert_includes Gem::Specification.stubs.map {|s| s.full_name }, 'a-1'
+ assert_includes Gem::Specification.all_names, "a-1"
+ assert_includes Gem::Specification.stubs.map(&:full_name), "a-1"
uninstall_gem @a1
Gem::Specification.reset
- refute_includes Gem::Specification.all_names, 'a-1'
- refute_includes Gem::Specification.stubs.map {|s| s.full_name }, 'a-1'
+ refute_includes Gem::Specification.all_names, "a-1"
+ refute_includes Gem::Specification.stubs.map(&:full_name), "a-1"
end
def test_self_remove_spec_removed
- File.open @a1.spec_file, 'w' do |io|
+ File.open @a1.spec_file, "w" do |io|
io.write @a1.to_ruby
end
@@ -1012,40 +966,43 @@ dependencies: []
Gem::Specification.reset
- refute_includes Gem::Specification.all_names, 'a-1'
- refute_includes Gem::Specification.stubs.map {|s| s.full_name }, 'a-1'
+ refute_includes Gem::Specification.all_names, "a-1"
+ refute_includes Gem::Specification.stubs.map(&:full_name), "a-1"
end
def test_self_stubs_for_lazy_loading
Gem.loaded_specs.clear
- Gem::Specification.class_variable_set(:@@stubs, nil)
- dir_standard_specs = File.join Gem.dir, 'specifications'
+ specification_record = Gem::Specification.specification_record
+
+ specification_record.instance_variable_set(:@stubs, nil)
+
+ dir_standard_specs = File.join Gem.dir, "specifications"
- save_gemspec('a-1', '1', dir_standard_specs){|s| s.name = 'a' }
- save_gemspec('b-1', '1', dir_standard_specs){|s| s.name = 'b' }
+ save_gemspec("a-1", "1", dir_standard_specs) {|s| s.name = "a" }
+ save_gemspec("b-1", "1", dir_standard_specs) {|s| s.name = "b" }
- assert_equal ['a-1'], Gem::Specification.stubs_for('a').map {|s| s.full_name }
- assert_equal 1, Gem::Specification.class_variable_get(:@@stubs_by_name).length
- assert_equal ['b-1'], Gem::Specification.stubs_for('b').map {|s| s.full_name }
- assert_equal 2, Gem::Specification.class_variable_get(:@@stubs_by_name).length
+ assert_equal ["a-1"], Gem::Specification.stubs_for("a").map(&:full_name)
+ assert_equal 1, specification_record.instance_variable_get(:@stubs_by_name).length
+ assert_equal ["b-1"], Gem::Specification.stubs_for("b").map(&:full_name)
+ assert_equal 2, specification_record.instance_variable_get(:@stubs_by_name).length
assert_equal(
- Gem::Specification.stubs_for('a').map {|s| s.object_id },
- Gem::Specification.stubs_for('a').map {|s| s.object_id }
+ Gem::Specification.stubs_for("a").map(&:object_id),
+ Gem::Specification.stubs_for("a").map(&:object_id)
)
- Gem.loaded_specs.delete 'a'
- Gem.loaded_specs.delete 'b'
- Gem::Specification.class_variable_set(:@@stubs, nil)
+ Gem.loaded_specs.delete "a"
+ Gem.loaded_specs.delete "b"
+ specification_record.instance_variable_set(:@stubs, nil)
end
def test_self_stubs_for_no_lazy_loading_after_all_specs_setup
- Gem::Specification.all = [util_spec('a', '1')]
+ Gem::Specification.all = [util_spec("a", "1")]
- save_gemspec('b-1', '1', File.join(Gem.dir, 'specifications')){|s| s.name = 'b' }
+ save_gemspec("b-1", "1", File.join(Gem.dir, "specifications")) {|s| s.name = "b" }
- assert_equal [], Gem::Specification.stubs_for('b').map {|s| s.full_name }
+ assert_equal [], Gem::Specification.stubs_for("b").map(&:full_name)
end
def test_self_stubs_for_mult_platforms
@@ -1055,30 +1012,30 @@ dependencies: []
orig_platform = Gem.platforms.dup
# create user spec
- user_spec_dir = File.join Gem.user_dir, 'specifications'
+ user_spec_dir = File.join Gem.user_dir, "specifications"
FileUtils.mkdir_p(user_spec_dir) unless Dir.exist? user_spec_dir
# dirs doesn't include user ?
Gem::Specification.dirs << user_spec_dir
- gem = 'mingw'
- v = '1.1.1'
- platforms = ['x86-mingw32', 'x64-mingw32']
+ gem = "mingw"
+ v = "1.1.1"
+ platforms = ["x86-mingw32", "x64-mingw32"]
- #create specs
+ # create specs
platforms.each do |plat|
spec = Gem::Specification.new(gem, v) {|s| s.platform = plat }
- File.open File.join(user_spec_dir, "#{gem}-#{v}-#{plat}.gemspec"), 'w' do |io|
+ File.open File.join(user_spec_dir, "#{gem}-#{v}-#{plat}.gemspec"), "w" do |io|
io.write spec.to_ruby
end
end
platforms.each do |plat|
cur_plat = Gem::Platform.new plat
- Gem.platforms = ['ruby', cur_plat]
+ Gem.platforms = ["ruby", cur_plat]
Gem::Specification.class_variable_set :@@stubs, nil
Gem::Specification.stubs if plat == platforms.last # test loading via stubs
- t = Gem::Specification.stubs_for 'mingw'
+ t = Gem::Specification.stubs_for "mingw"
assert_equal 1, t.length
assert_equal cur_plat, t.first.platform
@@ -1088,21 +1045,56 @@ dependencies: []
end
def test_self_stubs_returns_only_specified_named_specs
- dir_standard_specs = File.join Gem.dir, 'specifications'
+ dir_standard_specs = File.join Gem.dir, "specifications"
- save_gemspec('a-1', '1', dir_standard_specs){|s| s.name = 'a' }
- save_gemspec('a-2', '2', dir_standard_specs){|s| s.name = 'a' }
- save_gemspec('a-a', '3', dir_standard_specs){|s| s.name = 'a-a' }
+ save_gemspec("a-1", "1", dir_standard_specs) {|s| s.name = "a" }
+ save_gemspec("a-2", "2", dir_standard_specs) {|s| s.name = "a" }
+ save_gemspec("a-a", "3", dir_standard_specs) {|s| s.name = "a-a" }
- assert_equal ['a-1', 'a-2'], Gem::Specification.stubs_for('a').map(&:full_name).sort
+ assert_equal ["a-1", "a-2"], Gem::Specification.stubs_for("a").map(&:full_name).sort
end
def test_handles_private_null_type
- path = File.expand_path "../data/null-type.gemspec.rz", __FILE__
+ yaml_defined = Object.const_defined?("YAML")
+
+ path = File.expand_path "data/pry-0.4.7.gemspec.rz", __dir__
+
+ data = Marshal.load Gem::Util.inflate(Gem.read_binary(path))
+
+ assert_instance_of Gem::Specification, data
+
+ assert_equal(yaml_defined, Object.const_defined?("YAML"))
+ end
+
+ def test_handles_dependencies_with_syck_requirements_bug
+ yaml_defined = Object.const_defined?("YAML")
+
+ path = File.expand_path "data/excon-0.7.7.gemspec.rz", __dir__
data = Marshal.load Gem::Util.inflate(Gem.read_binary(path))
- assert_nil data.signing_key
+ assert_instance_of Gem::Specification, data
+
+ assert_equal(yaml_defined, Object.const_defined?("YAML"))
+ end
+
+ def test_handles_dependencies_with_other_syck_requirements_argument_error
+ yaml_defined = Object.const_defined?("YAML")
+
+ data = Marshal.dump(Gem::Specification.new do |s|
+ v = Gem::Version.allocate
+ v.instance_variable_set :@version, "YAML::Syck::DefaultKey"
+ s.instance_variable_set :@version, v
+ end)
+
+ assert_raise(ArgumentError) { Marshal.load(data) }
+ out, err = capture_output do
+ assert_raise(ArgumentError) { Marshal.load(data) }
+ end
+ assert_empty out
+ assert_empty err
+
+ assert_equal(yaml_defined, Object.const_defined?("YAML"))
end
def test_initialize
@@ -1124,9 +1116,9 @@ dependencies: []
assert_equal [], spec.extensions
assert_equal [], spec.requirements
assert_equal [], spec.dependencies
- assert_equal 'bin', spec.bindir
- assert_equal '>= 0', spec.required_ruby_version.to_s
- assert_equal '>= 0', spec.required_rubygems_version.to_s
+ assert_equal "bin", spec.bindir
+ assert_equal ">= 0", spec.required_ruby_version.to_s
+ assert_equal ">= 0", spec.required_rubygems_version.to_s
end
def test_initialize_future
@@ -1148,18 +1140,18 @@ dependencies: []
spec = Gem::Specification.new do |s|
s.name = "blah"
s.version = "1.3.5"
- s.summary = 'summary'
- s.description = 'description'
- s.authors = 'author a', 'author b'
- s.licenses = 'BSD-2-Clause'
- s.files = 'lib/file.rb'
- s.test_files = 'test/file.rb'
- s.rdoc_options = '--foo'
- s.extra_rdoc_files = 'README.txt'
- s.executables = 'exec'
- s.extensions = 'ext/extconf.rb'
- s.requirements = 'requirement'
- s.add_dependency 'some_gem'
+ s.summary = "summary"
+ s.description = "description"
+ s.authors = "author a", "author b"
+ s.licenses = "BSD-2-Clause"
+ s.files = "lib/file.rb"
+ s.test_files = "test/file.rb"
+ s.rdoc_options = "--foo"
+ s.extra_rdoc_files = "README.txt"
+ s.executables = "exec"
+ s.extensions = "ext/extconf.rb"
+ s.requirements = "requirement"
+ s.add_dependency "some_gem"
end
dup_spec = spec.dup
@@ -1173,84 +1165,96 @@ dependencies: []
assert_equal Gem::Platform::RUBY, spec.platform
assert_same spec.platform, dup_spec.platform
- assert_equal 'summary', spec.summary
+ assert_equal "summary", spec.summary
assert_same spec.summary, dup_spec.summary
assert_equal %w[README.txt bin/exec ext/extconf.rb lib/file.rb
test/file.rb].sort,
spec.files
- refute_same spec.files, dup_spec.files, 'files'
+ refute_same spec.files, dup_spec.files, "files"
assert_equal %w[test/file.rb], spec.test_files
- refute_same spec.test_files, dup_spec.test_files, 'test_files'
+ refute_same spec.test_files, dup_spec.test_files, "test_files"
assert_equal %w[--foo], spec.rdoc_options
- refute_same spec.rdoc_options, dup_spec.rdoc_options, 'rdoc_options'
+ refute_same spec.rdoc_options, dup_spec.rdoc_options, "rdoc_options"
assert_equal %w[README.txt], spec.extra_rdoc_files
refute_same spec.extra_rdoc_files, dup_spec.extra_rdoc_files,
- 'extra_rdoc_files'
+ "extra_rdoc_files"
assert_equal %w[exec], spec.executables
- refute_same spec.executables, dup_spec.executables, 'executables'
+ refute_same spec.executables, dup_spec.executables, "executables"
assert_equal %w[ext/extconf.rb], spec.extensions
- refute_same spec.extensions, dup_spec.extensions, 'extensions'
+ refute_same spec.extensions, dup_spec.extensions, "extensions"
assert_equal %w[requirement], spec.requirements
- refute_same spec.requirements, dup_spec.requirements, 'requirements'
+ refute_same spec.requirements, dup_spec.requirements, "requirements"
- assert_equal [Gem::Dependency.new('some_gem', Gem::Requirement.default)],
+ assert_equal [Gem::Dependency.new("some_gem", Gem::Requirement.default)],
spec.dependencies
- refute_same spec.dependencies, dup_spec.dependencies, 'dependencies'
+ refute_same spec.dependencies, dup_spec.dependencies, "dependencies"
- assert_equal 'bin', spec.bindir
+ assert_equal "bin", spec.bindir
assert_same spec.bindir, dup_spec.bindir
- assert_equal '>= 0', spec.required_ruby_version.to_s
- assert_same spec.required_ruby_version, dup_spec.required_ruby_version
+ assert_equal ">= 0", spec.required_ruby_version.to_s
+ assert_equal spec.required_ruby_version, dup_spec.required_ruby_version
+ refute_same spec.required_ruby_version, dup_spec.required_ruby_version
- assert_equal '>= 0', spec.required_rubygems_version.to_s
- assert_same spec.required_rubygems_version,
+ assert_equal ">= 0", spec.required_rubygems_version.to_s
+ assert_equal spec.required_rubygems_version,
+ dup_spec.required_rubygems_version
+ refute_same spec.required_rubygems_version,
dup_spec.required_rubygems_version
end
def test_initialize_copy_broken
spec = Gem::Specification.new do |s|
- s.name = 'a'
- s.version = '1'
+ s.name = "a"
+ s.version = "1"
end
- spec.instance_variable_set :@licenses, (class << (Object.new);self;end)
- spec.loaded_from = '/path/to/file'
+ spec.instance_variable_set :@licenses, (class << Object.new;self;end)
+ spec.loaded_from = "/path/to/file"
e = assert_raise Gem::FormatException do
spec.dup
end
- assert_equal 'a-1 has an invalid value for @licenses', e.message
- assert_equal '/path/to/file', e.file_path
+ assert_equal "a-1 has an invalid value for @licenses", e.message
+ assert_equal "/path/to/file", e.file_path
end
def test_initialize_prerelease_version_before_name
spec = Gem::Specification.new do |s|
- s.version = '1.0.0.dev'
- s.name = 'a'
+ s.version = "1.0.0.dev"
+ s.name = "a"
end
assert_equal "a", spec.name
assert_equal "1.0.0.dev", spec.version.to_s
end
+ def test_initialize_nil_version
+ expected = "nil versions are discouraged and will be deprecated in Rubygems 4\n"
+ actual_stdout, actual_stderr = capture_output do
+ Gem::Specification.new.version = nil
+ end
+ assert_empty actual_stdout
+ assert_equal(expected, actual_stderr)
+ end
+
def test__dump
@a2.platform = Gem::Platform.local
- @a2.instance_variable_set :@original_platform, 'old_platform'
+ @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
+ assert_equal "old_platform", same_spec.original_platform
end
def test_activate
@@ -1265,11 +1269,11 @@ dependencies: []
awesome.add_dependency :gem_name
end
- assert_equal %w[true gem_name], gem.dependencies.map {|dep| dep.name }
+ assert_equal %w[true gem_name], gem.dependencies.map(&:name)
end
def test_add_dependency_from_existing_dependency
- dep = Gem::Dependency.new("existing_dep", Gem::Requirement.new('> 1'), :runtime)
+ dep = Gem::Dependency.new("existing_dep", Gem::Requirement.new("> 1"), :runtime)
spec = Gem::Specification.new {|s| s.add_dependency dep }
assert_equal dep, spec.dependencies.first
end
@@ -1284,22 +1288,22 @@ dependencies: []
end
def test_author
- assert_equal 'A User', @a1.author
+ assert_equal "A User", @a1.author
end
def test_authors
- assert_equal ['A User'], @a1.authors
+ assert_equal ["A User"], @a1.authors
end
def test_bindir_equals
- @a1.bindir = 'apps'
+ @a1.bindir = "apps"
- assert_equal 'apps', @a1.bindir
+ assert_equal "apps", @a1.bindir
end
def test_bindir_equals_nil
@a2.bindir = nil
- @a2.executable = 'app'
+ @a2.executable = "app"
assert_nil @a2.bindir
assert_equal %w[app lib/code.rb].sort, @a2.files
@@ -1335,14 +1339,12 @@ dependencies: []
assert_empty @ext.build_args
- File.open @ext.build_info_file, 'w' do |io|
- io.puts
- end
+ File.open @ext.build_info_file, "w", &:puts
assert_empty @ext.build_args
- File.open @ext.build_info_file, 'w' do |io|
- io.puts '--with-foo-dir=wherever'
+ File.open @ext.build_info_file, "w" do |io|
+ io.puts "--with-foo-dir=wherever"
end
assert_equal %w[--with-foo-dir=wherever], @ext.build_args
@@ -1352,13 +1354,13 @@ dependencies: []
pend "extensions don't quite work on jruby" if Gem.java_platform?
ext_spec
- assert_path_not_exist @ext.extension_dir, 'sanity check'
- refute_empty @ext.extensions, 'sanity check'
+ assert_path_not_exist @ext.extension_dir, "sanity check"
+ refute_empty @ext.extensions, "sanity check"
extconf_rb = File.join @ext.gem_dir, @ext.extensions.first
FileUtils.mkdir_p File.dirname extconf_rb
- File.open extconf_rb, 'w' do |f|
+ File.open extconf_rb, "w" do |f|
f.write <<-'RUBY'
File.open 'Makefile', 'w' do |f|
f.puts "clean:\n\techo clean"
@@ -1374,13 +1376,13 @@ dependencies: []
end
def test_default_spec_stub_is_marked_default
- default = new_default_spec 'default', 2
+ default = new_default_spec "default", 2
install_default_gems default
- stub = Gem::Specification.stubs.find {|s| s.name == 'default' }
+ stub = Gem::Specification.stubs.find {|s| s.name == "default" }
assert_predicate stub, :default_gem?
- stub = Gem::Specification.find_all_by_name('default').first
+ stub = Gem::Specification.find_all_by_name("default").first
assert_predicate stub, :default_gem?
end
@@ -1388,28 +1390,28 @@ dependencies: []
pend "extensions don't quite work on jruby" if Gem.java_platform?
ext_spec
- refute_empty @ext.extensions, 'sanity check'
+ refute_empty @ext.extensions, "sanity check"
gem_build_complete =
- File.join @ext.extension_dir, 'gem.build_complete'
+ File.join @ext.extension_dir, "gem.build_complete"
FileUtils.mkdir_p @ext.extension_dir
FileUtils.touch gem_build_complete
@ext.build_extensions
- gem_make_out = File.join @ext.extension_dir, 'gem_make.out'
+ gem_make_out = File.join @ext.extension_dir, "gem_make.out"
assert_path_not_exist gem_make_out
end
def test_build_extensions_default_gem
- spec = new_default_spec 'default', 1
- spec.extensions << 'extconf.rb'
+ spec = new_default_spec "default", 1
+ spec.extensions << "extconf.rb"
extconf_rb = File.join spec.gem_dir, spec.extensions.first
FileUtils.mkdir_p File.dirname extconf_rb
- File.open extconf_rb, 'w' do |f|
+ File.open extconf_rb, "w" do |f|
f.write <<-'RUBY'
File.open 'Makefile', 'w' do |f|
f.puts "default:\n\techo built"
@@ -1427,7 +1429,7 @@ dependencies: []
pend "extensions don't quite work on jruby" if Gem.java_platform?
ext_spec
- refute_empty @ext.extensions, 'sanity check'
+ refute_empty @ext.extensions, "sanity check"
assert_raise Gem::Ext::BuildError do
@ext.build_extensions
@@ -1435,18 +1437,18 @@ dependencies: []
end
def test_build_extensions_extensions_dir_unwritable
- pend 'chmod not supported' if Gem.win_platform?
- pend 'skipped in root privilege' if Process.uid.zero?
+ pend "chmod not supported" if Gem.win_platform?
+ pend "skipped in root privilege" if Process.uid.zero?
pend "extensions don't quite work on jruby" if Gem.java_platform?
ext_spec
- refute_empty @ext.extensions, 'sanity check'
+ refute_empty @ext.extensions, "sanity check"
extconf_rb = File.join @ext.gem_dir, @ext.extensions.first
FileUtils.mkdir_p File.dirname extconf_rb
- File.open extconf_rb, 'w' do |f|
+ File.open extconf_rb, "w" do |f|
f.write <<-'RUBY'
File.open 'Makefile', 'w' do |f|
f.puts "clean:\n\techo clean"
@@ -1456,30 +1458,30 @@ dependencies: []
RUBY
end
- FileUtils.mkdir_p File.join @ext.base_dir, 'extensions'
- FileUtils.chmod 0555, @ext.base_dir
- FileUtils.chmod 0555, File.join(@ext.base_dir, 'extensions')
+ FileUtils.mkdir_p File.join @ext.base_dir, "extensions"
+ FileUtils.chmod 0o555, @ext.base_dir
+ FileUtils.chmod 0o555, File.join(@ext.base_dir, "extensions")
@ext.build_extensions
assert_path_not_exist @ext.extension_dir
ensure
- unless ($DEBUG or win_platform? or Process.uid.zero? or Gem.java_platform?)
- FileUtils.chmod 0755, File.join(@ext.base_dir, 'extensions')
- FileUtils.chmod 0755, @ext.base_dir
+ unless $DEBUG || Gem.win_platform? || Process.uid.zero? || Gem.java_platform?
+ FileUtils.chmod 0o755, File.join(@ext.base_dir, "extensions")
+ FileUtils.chmod 0o755, @ext.base_dir
end
end
def test_build_extensions_no_extensions_dir_unwritable
- pend 'chmod not supported' if Gem.win_platform?
+ pend "chmod not supported" if Gem.win_platform?
pend "extensions don't quite work on jruby" if Gem.java_platform?
ext_spec
- refute_empty @ext.extensions, 'sanity check'
+ refute_empty @ext.extensions, "sanity check"
extconf_rb = File.join @ext.gem_dir, @ext.extensions.first
FileUtils.mkdir_p File.dirname extconf_rb
- File.open extconf_rb, 'w' do |f|
+ File.open extconf_rb, "w" do |f|
f.write <<-'RUBY'
File.open 'Makefile', 'w' do |f|
f.puts "clean:\n\techo clean"
@@ -1489,20 +1491,20 @@ dependencies: []
RUBY
end
- FileUtils.rm_r File.join @gemhome, 'extensions'
- FileUtils.chmod 0555, @gemhome
+ FileUtils.rm_r File.join @gemhome, "extensions"
+ FileUtils.chmod 0o555, @gemhome
@ext.build_extensions
- gem_make_out = File.join @ext.extension_dir, 'gem_make.out'
+ gem_make_out = File.join @ext.extension_dir, "gem_make.out"
assert_path_not_exist gem_make_out
ensure
- FileUtils.chmod 0755, @gemhome
+ FileUtils.chmod 0o755, @gemhome
end
def test_build_extensions_none
- assert_path_not_exist @a1.extension_dir, 'sanity check'
- assert_empty @a1.extensions, 'sanity check'
+ assert_path_not_exist @a1.extension_dir, "sanity check"
+ assert_empty @a1.extensions, "sanity check"
@a1.build_extensions
@@ -1516,7 +1518,7 @@ dependencies: []
extconf_rb = File.join @ext.gem_dir, @ext.extensions.first
FileUtils.mkdir_p File.dirname extconf_rb
- File.open extconf_rb, 'w' do |f|
+ File.open extconf_rb, "w" do |f|
f.write <<-'RUBY'
File.open 'Makefile', 'w' do |f|
f.puts "clean:\n\techo clean"
@@ -1526,22 +1528,22 @@ dependencies: []
RUBY
end
- refute_empty @ext.extensions, 'sanity check'
+ refute_empty @ext.extensions, "sanity check"
- @ext.installed_by_version = v('2.2.0.preview.2')
+ @ext.installed_by_version = v("2.2.0.preview.2")
@ext.build_extensions
- gem_make_out = File.join @ext.extension_dir, 'gem_make.out'
+ gem_make_out = File.join @ext.extension_dir, "gem_make.out"
assert_path_exist gem_make_out
end
def test_contains_requirable_file_eh
- code_rb = File.join @a1.gem_dir, 'lib', 'code.rb'
+ code_rb = File.join @a1.gem_dir, "lib", "code.rb"
FileUtils.mkdir_p File.dirname code_rb
FileUtils.touch code_rb
- assert @a1.contains_requirable_file? 'code'
+ assert @a1.contains_requirable_file? "code"
end
def test_contains_requirable_file_eh_extension
@@ -1549,10 +1551,10 @@ dependencies: []
ext_spec
_, err = capture_output do
- refute @ext.contains_requirable_file? 'nonexistent'
+ refute @ext.contains_requirable_file? "nonexistent"
end
- expected = "Ignoring ext-1 because its extensions are not built. " +
+ expected = "Ignoring ext-1 because its extensions are not built. " \
"Try: gem pristine ext --version 1\n"
assert_equal expected, err
@@ -1562,12 +1564,23 @@ dependencies: []
ext_spec(platform: Gem::Platform.new("java"))
_, err = capture_output do
- refute @ext.contains_requirable_file? 'nonexistent'
+ refute @ext.contains_requirable_file? "nonexistent"
end
assert_empty err
end
+ def test_contains_requirable_file_extension_soext
+ ext_spec
+ dlext = RbConfig::CONFIG["DLEXT"]
+ @ext.files += ["lib/ext.#{dlext}"]
+
+ FileUtils.mkdir_p @ext.extension_dir
+ FileUtils.touch File.join(@ext.extension_dir, "ext.#{dlext}")
+ FileUtils.touch File.join(@ext.extension_dir, "gem.build_complete")
+ assert @ext.contains_requirable_file? "ext.so"
+ end
+
def test_date
assert_date @a1.date
end
@@ -1578,13 +1591,13 @@ dependencies: []
end
def test_date_equals_string
- @a1.date = '2003-09-17'
+ @a1.date = "2003-09-17"
assert_equal Time.utc(2003, 9, 17, 0,0,0), @a1.date
end
def test_date_equals_string_bad
assert_raise Gem::InvalidSpecificationException do
- @a1.date = '9/11/2003'
+ @a1.date = "9/11/2003"
end
end
@@ -1605,12 +1618,12 @@ dependencies: []
def test_date_tolerates_hour_sec_zulu
@a1.date = "2012-01-12 11:22:33.4444444 Z"
- assert_equal Time.utc(2012,01,12,0,0,0), @a1.date
+ assert_equal Time.utc(2012,1,12,0,0,0), @a1.date
end
def test_date_tolerates_hour_sec_and_timezone
@a1.date = "2012-01-12 11:22:33.4444444 +02:33"
- assert_equal Time.utc(2012,01,12,0,0,0), @a1.date
+ assert_equal Time.utc(2012,1,12,0,0,0), @a1.date
end
def test_date_use_env_source_date_epoch
@@ -1631,7 +1644,7 @@ dependencies: []
assert_empty @gem.dependent_gems
- bonobo = util_spec 'bonobo', 1
+ bonobo = util_spec "bonobo", 1
install_gem bonobo
install_gem @gem
@@ -1643,11 +1656,11 @@ dependencies: []
end
def test_doc_dir
- assert_equal File.join(@gemhome, 'doc', 'a-1'), @a1.doc_dir
+ assert_equal File.join(@gemhome, "doc", "a-1"), @a1.doc_dir
end
def test_doc_dir_type
- assert_equal File.join(@gemhome, 'doc', 'a-1', 'ri'), @a1.doc_dir('ri')
+ assert_equal File.join(@gemhome, "doc", "a-1", "ri"), @a1.doc_dir("ri")
end
def test_runtime_dependencies
@@ -1661,12 +1674,12 @@ dependencies: []
end
def test_description
- assert_equal 'This is a test description', @a1.description
+ assert_equal "This is a test description", @a1.description
end
def test_eql_eh
- g1 = util_spec 'gem', 1
- g2 = util_spec 'gem', 1
+ g1 = util_spec "gem", 1
+ g2 = util_spec "gem", 1
assert_equal g1, g2
assert_equal g1.hash, g2.hash
@@ -1675,55 +1688,55 @@ dependencies: []
def test_eql_eh_extensions
spec = @a1.dup
- spec.extensions = 'xx'
+ spec.extensions = "xx"
refute_operator @a1, :eql?, spec
refute_operator spec, :eql?, @a1
end
def test_executables
- @a1.executable = 'app'
+ @a1.executable = "app"
assert_equal %w[app], @a1.executables
end
def test_executable_equals
- @a2.executable = 'app'
- assert_equal 'app', @a2.executable
+ @a2.executable = "app"
+ assert_equal "app", @a2.executable
assert_equal %w[bin/app lib/code.rb].sort, @a2.files
end
def test_extensions
- assert_equal ['ext/extconf.rb'], ext_spec.extensions
+ assert_equal ["ext/extconf.rb"], ext_spec.extensions
end
def test_extension_dir
- enable_shared, RbConfig::CONFIG['ENABLE_SHARED'] =
- RbConfig::CONFIG['ENABLE_SHARED'], 'no'
+ enable_shared = RbConfig::CONFIG["ENABLE_SHARED"]
+ RbConfig::CONFIG["ENABLE_SHARED"] = "no"
ext_spec
refute_empty @ext.extensions
expected =
- File.join(@ext.base_dir, 'extensions', Gem::Platform.local.to_s,
+ File.join(@ext.base_dir, "extensions", Gem::Platform.local.to_s,
"#{Gem.ruby_api_version}-static", @ext.full_name)
assert_equal expected, @ext.extension_dir
ensure
- RbConfig::CONFIG['ENABLE_SHARED'] = enable_shared
+ RbConfig::CONFIG["ENABLE_SHARED"] = enable_shared
end
def test_extension_dir_override
- enable_shared, RbConfig::CONFIG['ENABLE_SHARED'] =
- RbConfig::CONFIG['ENABLE_SHARED'], 'no'
+ enable_shared = RbConfig::CONFIG["ENABLE_SHARED"]
+ RbConfig::CONFIG["ENABLE_SHARED"] = "no"
class << Gem
- alias orig_default_ext_dir_for default_ext_dir_for
+ alias_method :orig_default_ext_dir_for, :default_ext_dir_for
remove_method :default_ext_dir_for
def Gem.default_ext_dir_for(base_dir)
- 'elsewhere'
+ "elsewhere"
end
end
@@ -1731,16 +1744,16 @@ dependencies: []
refute_empty @ext.extensions
- expected = File.join @tempdir, 'elsewhere', @ext.full_name
+ expected = File.join @tempdir, "elsewhere", @ext.full_name
assert_equal expected, @ext.extension_dir
ensure
- RbConfig::CONFIG['ENABLE_SHARED'] = enable_shared
+ RbConfig::CONFIG["ENABLE_SHARED"] = enable_shared
class << Gem
remove_method :default_ext_dir_for
- alias default_ext_dir_for orig_default_ext_dir_for
+ alias_method :default_ext_dir_for, :orig_default_ext_dir_for
end
end
@@ -1825,9 +1838,9 @@ dependencies: []
end
def test_for_cache
- @a2.add_runtime_dependency 'b', '1'
+ @a2.add_dependency "b", "1"
@a2.dependencies.first.instance_variable_set :@type, nil
- @a2.required_rubygems_version = Gem::Requirement.new '> 0'
+ @a2.required_rubygems_version = Gem::Requirement.new "> 0"
@a2.test_files = %w[test/test_b.rb]
refute_empty @a2.files
@@ -1843,16 +1856,16 @@ dependencies: []
end
def test_full_gem_path
- assert_equal File.join(@gemhome, 'gems', @a1.full_name), @a1.full_gem_path
+ assert_equal File.join(@gemhome, "gems", @a1.full_name), @a1.full_gem_path
- @a1.original_platform = 'mswin32'
+ @a1.original_platform = "mswin32"
- assert_equal File.join(@gemhome, 'gems', @a1.original_name),
+ assert_equal File.join(@gemhome, "gems", @a1.original_name),
@a1.full_gem_path
end
def test_full_gem_path_double_slash
- gemhome = @gemhome.to_s.sub(/\w\//, '\&/')
+ gemhome = @gemhome.to_s.sub(%r{\w/}, '\&/')
@a1.loaded_from = File.join gemhome, "specifications", @a1.spec_name
expected = File.join @gemhome, "gems", @a1.full_name
@@ -1860,40 +1873,40 @@ dependencies: []
end
def test_full_name
- assert_equal 'a-1', @a1.full_name
+ assert_equal "a-1", @a1.full_name
@a1 = Gem::Specification.new "a", 1
- @a1.platform = Gem::Platform.new ['universal', 'darwin', nil]
- assert_equal 'a-1-universal-darwin', @a1.full_name
+ @a1.platform = Gem::Platform.new ["universal", "darwin", nil]
+ assert_equal "a-1-universal-darwin", @a1.full_name
@a1 = Gem::Specification.new "a", 1
- @a1.instance_variable_set :@new_platform, 'mswin32'
- assert_equal 'a-1-mswin32', @a1.full_name, 'legacy'
+ @a1.instance_variable_set :@new_platform, "mswin32"
+ assert_equal "a-1-mswin32", @a1.full_name, "legacy"
- return if win_platform?
+ return if Gem.win_platform?
@a1 = Gem::Specification.new "a", 1
- @a1.platform = 'current'
- assert_equal 'a-1-x86-darwin-8', @a1.full_name
+ @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',
+ "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|
@a1 = Gem::Specification.new "a", 1
util_set_arch arch
- @a1.platform = 'current'
+ @a1.platform = "current"
assert_equal expected, @a1.full_name
end
end
def test_gem_build_complete_path
- expected = File.join @a1.extension_dir, 'gem.build_complete'
+ expected = File.join @a1.extension_dir, "gem.build_complete"
assert_equal expected, @a1.gem_build_complete_path
end
@@ -1937,23 +1950,23 @@ dependencies: []
end
def test_license
- assert_equal 'MIT', @a1.license
+ assert_equal "MIT", @a1.license
end
def test_licenses
- assert_equal ['MIT'], @a1.licenses
+ assert_equal ["MIT"], @a1.licenses
end
def test_name
- assert_equal 'a', @a1.name
+ assert_equal "a", @a1.name
end
def test_original_name
- assert_equal 'a-1', @a1.full_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
+ @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
@@ -1982,10 +1995,10 @@ dependencies: []
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' ],
+ "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|
@@ -2002,29 +2015,23 @@ dependencies: []
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 = "mswin32"
+ assert_equal Gem::Platform.new("x86-mswin32"), @a1.platform
- @a1.platform = 'powerpc-darwin'
- assert_equal Gem::Platform.new('ppc-darwin'), @a1.platform
- end
+ @a1.platform = "i586-linux"
+ assert_equal Gem::Platform.new("x86-linux"), @a1.platform
- def test_prerelease_spec_adds_required_rubygems_version
- @prerelease = util_spec('tardis', '2.2.0.a')
- refute @prerelease.required_rubygems_version.satisfied_by?(Gem::Version.new('1.3.1'))
- assert @prerelease.required_rubygems_version.satisfied_by?(Gem::Version.new('1.4.0'))
+ @a1.platform = "powerpc-darwin"
+ assert_equal Gem::Platform.new("ppc-darwin"), @a1.platform
end
def test_require_paths
- enable_shared 'no' do
+ enable_shared "no" do
ext_spec
- @ext.require_paths = 'lib'
+ @ext.require_paths = "lib"
- assert_equal [@ext.extension_dir, 'lib'], @ext.require_paths
+ assert_equal [@ext.extension_dir, "lib"], @ext.require_paths
end
end
@@ -2036,15 +2043,15 @@ dependencies: []
end
def Gem.default_ext_dir_for(base_dir)
- '/foo'
+ "/foo"
end
- enable_shared 'no' do
+ enable_shared "no" do
ext_spec
- @ext.require_paths = 'lib'
+ @ext.require_paths = "lib"
- assert_equal [File.expand_path('/foo/ext-1'), 'lib'], @ext.require_paths
+ assert_equal [File.expand_path("/foo/ext-1"), "lib"], @ext.require_paths
end
ensure
class << Gem
@@ -2062,7 +2069,7 @@ dependencies: []
ext_spec
@ext.require_paths = %w[lib ext foo]
- @ext.extensions << 'bar/baz'
+ @ext.extensions << "bar/baz"
expected = %w[
lib
@@ -2077,10 +2084,10 @@ dependencies: []
def test_full_require_paths
ext_spec
- @ext.require_paths = 'lib'
+ @ext.require_paths = "lib"
expected = [
- File.join(@gemhome, 'gems', @ext.original_name, 'lib'),
+ File.join(@gemhome, "gems", @ext.original_name, "lib"),
@ext.extension_dir,
]
@@ -2090,10 +2097,10 @@ dependencies: []
def test_to_fullpath
ext_spec
- @ext.require_paths = 'lib'
+ @ext.require_paths = "lib"
- dir = File.join(@gemhome, 'gems', @ext.original_name, 'lib')
- expected_rb = File.join(dir, 'code.rb')
+ dir = File.join(@gemhome, "gems", @ext.original_name, "lib")
+ expected_rb = File.join(dir, "code.rb")
FileUtils.mkdir_p dir
FileUtils.touch expected_rb
@@ -2127,10 +2134,10 @@ dependencies: []
def test_fullpath_return_rb_extension_file_when_exist_the_same_name_file
ext_spec
- @ext.require_paths = 'lib'
+ @ext.require_paths = "lib"
- dir = File.join(@gemhome, 'gems', @ext.original_name, 'lib')
- expected_rb = File.join(dir, 'code.rb')
+ dir = File.join(@gemhome, "gems", @ext.original_name, "lib")
+ expected_rb = File.join(dir, "code.rb")
FileUtils.mkdir_p dir
FileUtils.touch expected_rb
@@ -2146,52 +2153,48 @@ dependencies: []
end
def test_require_already_activated
- save_loaded_features do
- a1 = util_spec "a", "1", nil, "lib/d#{$$}.rb"
+ a1 = util_spec "a", "1", nil, "lib/d#{$$}.rb"
- install_specs a1 # , a2, b1, b2, c1, c2
+ install_specs a1 # , a2, b1, b2, c1, c2
- a1.activate
- assert_equal %w[a-1], loaded_spec_names
- assert_equal [], unresolved_names
+ a1.activate
+ assert_equal %w[a-1], loaded_spec_names
+ assert_equal [], unresolved_names
- assert require "d#{$$}"
+ assert require "d#{$$}"
- assert_equal %w[a-1], loaded_spec_names
- assert_equal [], unresolved_names
- end
+ assert_equal %w[a-1], loaded_spec_names
+ assert_equal [], unresolved_names
end
def test_require_already_activated_indirect_conflict
- save_loaded_features do
- a1 = util_spec "a", "1", "b" => "> 0"
- a2 = util_spec "a", "2", "b" => "> 0"
- b1 = util_spec "b", "1", "c" => ">= 1"
- b2 = util_spec "b", "2", "c" => ">= 2"
- c1 = util_spec "c", "1", nil, "lib/d#{$$}.rb"
- c2 = util_spec("c", "2", { "a" => "1" }, "lib/d#{$$}.rb") # conflicts with a-2
+ a1 = util_spec "a", "1", "b" => "> 0"
+ a2 = util_spec "a", "2", "b" => "> 0"
+ b1 = util_spec "b", "1", "c" => ">= 1"
+ b2 = util_spec "b", "2", "c" => ">= 2"
+ c1 = util_spec "c", "1", nil, "lib/d#{$$}.rb"
+ c2 = util_spec("c", "2", { "a" => "1" }, "lib/d#{$$}.rb") # conflicts with a-2
- install_specs c1, b1, a1, a2, c2, b2
+ install_specs c1, b1, a1, a2, c2, b2
- a1.activate
- c1.activate
- assert_equal %w[a-1 c-1], loaded_spec_names
- assert_equal ["b (> 0)"], unresolved_names
+ a1.activate
+ c1.activate
+ assert_equal %w[a-1 c-1], loaded_spec_names
+ assert_equal ["b (> 0)"], unresolved_names
- assert require "d#{$$}"
+ assert require "d#{$$}"
- assert_equal %w[a-1 c-1], loaded_spec_names
- assert_equal ["b (> 0)"], unresolved_names
- end
+ assert_equal %w[a-1 c-1], loaded_spec_names
+ assert_equal ["b (> 0)"], unresolved_names
end
def test_requirements
- assert_equal ['A working computer'], @a1.requirements
+ assert_equal ["A working computer"], @a1.requirements
end
def test_allowed_push_host
- assert_nil @a1.metadata['allowed_push_host']
- assert_equal 'https://privategemserver.com', @a3.metadata['allowed_push_host']
+ assert_nil @a1.metadata["allowed_push_host"]
+ assert_equal "https://privategemserver.com", @a3.metadata["allowed_push_host"]
end
def test_runtime_dependencies_legacy
@@ -2203,58 +2206,58 @@ dependencies: []
expected = %w[rake jabber4r pqa]
- assert_equal expected, @c1.runtime_dependencies.map {|d| d.name }
+ assert_equal expected, @c1.runtime_dependencies.map(&:name)
end
def test_spaceship_name
- s1 = util_spec 'a', '1'
- s2 = util_spec 'b', '1'
+ s1 = util_spec "a", "1"
+ s2 = util_spec "b", "1"
assert_equal(-1, (s1 <=> s2))
- assert_equal(0, (s1 <=> s1))
+ assert_equal(0, (s1 <=> s1)) # rubocop:disable Lint/BinaryOperatorWithIdenticalOperands
assert_equal(1, (s2 <=> s1))
end
def test_spaceship_platform
- s1 = util_spec 'a', '1'
- s2 = util_spec 'a', '1' do |s|
- s.platform = Gem::Platform.new 'x86-my_platform1'
+ s1 = util_spec "a", "1"
+ s2 = util_spec "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(0, (s1 <=> s1)) # rubocop:disable Lint/BinaryOperatorWithIdenticalOperands
assert_equal(1, (s2 <=> s1))
end
def test_spaceship_version
- s1 = util_spec 'a', '1'
- s2 = util_spec 'a', '2'
+ s1 = util_spec "a", "1"
+ s2 = util_spec "a", "2"
assert_equal(-1, (s1 <=> s2))
- assert_equal(0, (s1 <=> s1))
+ assert_equal(0, (s1 <=> s1)) # rubocop:disable Lint/BinaryOperatorWithIdenticalOperands
assert_equal(1, (s2 <=> s1))
end
def test_spec_file
- assert_equal File.join(@gemhome, 'specifications', 'a-1.gemspec'),
+ assert_equal File.join(@gemhome, "specifications", "a-1.gemspec"),
@a1.spec_file
end
def test_spec_name
- assert_equal 'a-1.gemspec', @a1.spec_name
+ assert_equal "a-1.gemspec", @a1.spec_name
end
def test_summary
- assert_equal 'this is a summary', @a1.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
+ @a1.test_file = "test/suite.rb"
+ assert_equal ["test/suite.rb"], @a1.test_files
end
def test_runtime_predicate_true
- @a2.add_runtime_dependency 'b', '1'
+ @a2.add_runtime_dependency "b", "1"
assert_predicate @a2.dependencies.first, :runtime?
@a2.dependencies.first.instance_variable_set :@type, nil
@@ -2262,15 +2265,15 @@ dependencies: []
end
def test_runtime_predicate_false
- @a2.add_development_dependency 'b', '1'
+ @a2.add_development_dependency "b", "1"
refute_predicate @a2.dependencies.first, :runtime?
end
def test_to_ruby
- @a2.add_runtime_dependency 'b', '1'
+ @a2.add_dependency "b", "1"
@a2.dependencies.first.instance_variable_set :@type, nil
- @a2.required_rubygems_version = Gem::Requirement.new '> 0'
- @a2.require_paths << 'other'
+ @a2.required_rubygems_version = Gem::Requirement.new "> 0"
+ @a2.require_paths << "other"
ruby_code = @a2.to_ruby
@@ -2280,7 +2283,7 @@ dependencies: []
Gem::Specification.new do |s|
s.name = "a".freeze
- s.version = "2"
+ s.version = "2".freeze
s.required_rubygems_version = Gem::Requirement.new(\"> 0\".freeze) if s.respond_to? :required_rubygems_version=
s.require_paths = ["lib".freeze, "other".freeze]
@@ -2293,15 +2296,9 @@ Gem::Specification.new do |s|
s.rubygems_version = "#{Gem::VERSION}".freeze
s.summary = "this is a summary".freeze
- if s.respond_to? :specification_version then
- s.specification_version = #{Gem::Specification::CURRENT_SPECIFICATION_VERSION}
- end
+ s.specification_version = #{Gem::Specification::CURRENT_SPECIFICATION_VERSION}
- if s.respond_to? :add_runtime_dependency then
- s.add_runtime_dependency(%q<b>.freeze, [\"= 1\"])
- else
- s.add_dependency(%q<b>.freeze, [\"= 1\"])
- end
+ s.add_runtime_dependency(%q<b>.freeze, [\"= 1\".freeze])
end
SPEC
@@ -2313,8 +2310,8 @@ end
end
def test_to_ruby_with_rsa_key
- require 'rubygems/openssl'
- pend 'openssl is missing' unless defined?(OpenSSL::PKey::RSA)
+ require "rubygems/openssl"
+ pend "openssl is missing" unless defined?(OpenSSL::PKey::RSA)
rsa_key = OpenSSL::PKey::RSA.new(2048)
@a2.signing_key = rsa_key
@@ -2326,7 +2323,7 @@ end
Gem::Specification.new do |s|
s.name = "a".freeze
- s.version = "2"
+ s.version = "2".freeze
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
s.require_paths = ["lib".freeze]
@@ -2345,9 +2342,9 @@ end
end
def test_to_ruby_for_cache
- @a2.add_runtime_dependency 'b', '1'
+ @a2.add_dependency "b", "1"
@a2.dependencies.first.instance_variable_set :@type, nil
- @a2.required_rubygems_version = Gem::Requirement.new '> 0'
+ @a2.required_rubygems_version = Gem::Requirement.new "> 0"
@a2.installed_by_version = Gem.rubygems_version
# cached specs do not have spec.files populated:
@@ -2359,7 +2356,7 @@ end
Gem::Specification.new do |s|
s.name = "a".freeze
- s.version = "2"
+ s.version = "2".freeze
s.required_rubygems_version = Gem::Requirement.new(\"> 0\".freeze) if s.respond_to? :required_rubygems_version=
s.require_paths = ["lib".freeze]
@@ -2371,17 +2368,11 @@ Gem::Specification.new do |s|
s.rubygems_version = "#{Gem::VERSION}".freeze
s.summary = "this is a summary".freeze
- s.installed_by_version = "#{Gem::VERSION}" if s.respond_to? :installed_by_version
+ s.installed_by_version = "#{Gem::VERSION}".freeze
- if s.respond_to? :specification_version then
- s.specification_version = #{Gem::Specification::CURRENT_SPECIFICATION_VERSION}
- end
+ s.specification_version = #{Gem::Specification::CURRENT_SPECIFICATION_VERSION}
- if s.respond_to? :add_runtime_dependency then
- s.add_runtime_dependency(%q<b>.freeze, [\"= 1\"])
- else
- s.add_dependency(%q<b>.freeze, [\"= 1\"])
- end
+ s.add_runtime_dependency(%q<b>.freeze, ["= 1".freeze])
end
SPEC
@@ -2401,19 +2392,19 @@ end
ruby_code = @c1.to_ruby
local = Gem::Platform.local
- expected_platform = "[#{local.cpu.inspect}, #{local.os.inspect}, #{local.version.inspect}]"
+ expected_platform = "[#{local.cpu.inspect}.freeze, #{local.os.inspect}.freeze, #{local.version.inspect}.freeze]"
stub_require_paths =
@c1.instance_variable_get(:@require_paths).join "\u0000"
extensions = @c1.extensions.join "\u0000"
expected = <<-SPEC
# -*- encoding: utf-8 -*-
-# stub: a 1 #{win_platform? ? "x86-mswin32-60" : "x86-darwin-8"} #{stub_require_paths}
+# stub: a 1 #{Gem.win_platform? ? "x86-mswin32-60" : "x86-darwin-8"} #{stub_require_paths}
# stub: #{extensions}
Gem::Specification.new do |s|
s.name = "a".freeze
- s.version = "1"
+ s.version = "1".freeze
s.platform = Gem::Platform.new(#{expected_platform})
s.required_rubygems_version = Gem::Requirement.new(\">= 0\".freeze) if s.respond_to? :required_rubygems_version=
@@ -2432,19 +2423,11 @@ Gem::Specification.new do |s|
s.summary = "this is a summary".freeze
s.test_files = ["test/suite.rb".freeze]
- if s.respond_to? :specification_version then
- s.specification_version = 4
- end
+ s.specification_version = 4
- if s.respond_to? :add_runtime_dependency then
- s.add_runtime_dependency(%q<rake>.freeze, [\"> 0.4\"])
- s.add_runtime_dependency(%q<jabber4r>.freeze, [\"> 0.0.0\"])
- s.add_runtime_dependency(%q<pqa>.freeze, [\"> 0.4\", \"<= 0.6\"])
- else
- s.add_dependency(%q<rake>.freeze, [\"> 0.4\"])
- s.add_dependency(%q<jabber4r>.freeze, [\"> 0.0.0\"])
- s.add_dependency(%q<pqa>.freeze, [\"> 0.4\", \"<= 0.6\"])
- end
+ s.add_runtime_dependency(%q<rake>.freeze, [\"> 0.4\".freeze])
+ s.add_runtime_dependency(%q<jabber4r>.freeze, [\"> 0.0.0\".freeze])
+ s.add_runtime_dependency(%q<pqa>.freeze, [\"> 0.4\".freeze, \"<= 0.6\".freeze])
end
SPEC
@@ -2456,11 +2439,11 @@ end
end
def test_to_ruby_keeps_requirements_as_originally_specified
- spec = util_spec 'a', '1' do |s|
- s.add_dependency 'b', ['~> 1.0', '>= 1.0.0']
+ spec = util_spec "a", "1" do |s|
+ s.add_dependency "b", ["~> 1.0", ">= 1.0.0"]
end
- assert_includes spec.to_ruby, '"~> 1.0", ">= 1.0.0"'
+ assert_includes spec.to_ruby, '"~> 1.0".freeze, ">= 1.0.0".freeze'
end
def test_to_ruby_legacy
@@ -2475,30 +2458,30 @@ end
def test_to_ruby_nested_hash
metadata = {}
- metadata[metadata] = metadata
+ metadata[:metadata] = {}
@a2.metadata = metadata
ruby = @a2.to_ruby
- assert_match %r%^ s\.metadata = \{ "%, ruby
+ assert_match(/^ s\.metadata = \{ "/, ruby)
end
def test_to_ruby_platform
@a2.platform = Gem::Platform.local
- @a2.instance_variable_set :@original_platform, 'old_platform'
+ @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
+ assert_equal "old_platform", same_spec.original_platform
end
def test_to_yaml
yaml_str = @a1.to_yaml
- refute_match %r{!!null}, yaml_str
+ refute_match(/!!null/, yaml_str)
same_spec = Gem::Specification.from_yaml(yaml_str)
@@ -2517,27 +2500,47 @@ end
end
def test_to_yaml_platform_empty_string
- @a1.instance_variable_set :@original_platform, ''
+ @a1.instance_variable_set :@original_platform, ""
- assert_match %r{^platform: ruby$}, @a1.to_yaml
+ assert_match(/^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'
+ @a1.platform = "powerpc-darwin7.9.0"
+ @a1.instance_variable_set :@original_platform, "powerpc-darwin7.9.0"
yaml_str = @a1.to_yaml
same_spec = load_yaml yaml_str
- assert_equal Gem::Platform.new('powerpc-darwin7'), same_spec.platform
- assert_equal 'powerpc-darwin7.9.0', same_spec.original_platform
+ 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
+ assert_match(/^platform: ruby$/, @a1.to_yaml)
+ end
+
+ def test_to_yaml_no_autorequire
+ yaml_str = @a1.to_yaml
+
+ refute_match(/^autorequire:/, yaml_str)
+ end
+
+ def test_to_yaml_no_signing_key
+ @a1.signing_key = nil
+ yaml_str = @a1.to_yaml
+
+ refute_match(/^signing_key:/, yaml_str)
+ end
+
+ def test_to_yaml_no_post_install_message
+ @a1.post_install_message = nil
+ yaml_str = @a1.to_yaml
+
+ refute_match(/^post_install_message:/, yaml_str)
end
def test_validate
@@ -2548,10 +2551,21 @@ end
end
end
- def x(s); s.gsub(/xxx/, ''); end
- def w; x "WARxxxNING"; end
- def t; x "TOxxxDO"; end
- def f; x "FxxxIXME"; end
+ def x(s)
+ s.gsub(/xxx/, "")
+ end
+
+ def w
+ x "WARxxxNING"
+ end
+
+ def t
+ x "TOxxxDO"
+ end
+
+ def f
+ x "FxxxIXME"
+ end
def test_validate_authors
util_setup_validate
@@ -2563,7 +2577,7 @@ end
@a1.validate
end
- assert_match "#{w}: no author specified\n", @ui.error, 'error'
+ assert_match "#{w}: no author specified\n", @ui.error, "error"
@a1.authors = [Object.new]
@@ -2597,14 +2611,14 @@ end
util_setup_validate
Dir.chdir @tempdir do
- @a1.autorequire = 'code'
+ @a1.autorequire = "code"
use_ui @ui do
@a1.validate
end
assert_match "#{w}: deprecated autorequire specified\n",
- @ui.error, 'error'
+ @ui.error, "error"
end
end
@@ -2612,19 +2626,19 @@ end
util_setup_validate
Dir.chdir @tempdir do
- @a1.add_runtime_dependency 'b', '>= 1.0.rc1'
- @a1.add_development_dependency 'c', '>= 2.0.rc2'
- @a1.add_runtime_dependency 'd', '~> 1.2.3'
- @a1.add_runtime_dependency 'e', '~> 1.2.3.4'
- @a1.add_runtime_dependency 'g', '~> 1.2.3', '>= 1.2.3.4'
- @a1.add_runtime_dependency 'h', '>= 1.2.3', '<= 2'
- @a1.add_runtime_dependency 'i', '>= 1.2'
- @a1.add_runtime_dependency 'j', '>= 1.2.3'
- @a1.add_runtime_dependency 'k', '> 1.2'
- @a1.add_runtime_dependency 'l', '> 1.2.3'
- @a1.add_runtime_dependency 'm', '~> 2.1.0'
- @a1.add_runtime_dependency 'n', '~> 0.1.0'
- @a1.add_runtime_dependency 'o'
+ @a1.add_runtime_dependency "b", ">= 1.0.rc1"
+ @a1.add_development_dependency "c", ">= 2.0.rc2"
+ @a1.add_runtime_dependency "d", "~> 1.2.3"
+ @a1.add_runtime_dependency "e", "~> 1.2.3.4"
+ @a1.add_runtime_dependency "g", "~> 1.2.3", ">= 1.2.3.4"
+ @a1.add_runtime_dependency "h", ">= 1.2.3", "<= 2"
+ @a1.add_runtime_dependency "i", ">= 1.2"
+ @a1.add_runtime_dependency "j", ">= 1.2.3"
+ @a1.add_runtime_dependency "k", "> 1.2"
+ @a1.add_runtime_dependency "l", "> 1.2.3"
+ @a1.add_runtime_dependency "m", "~> 2.1.0"
+ @a1.add_runtime_dependency "n", "~> 0.1.0"
+ @a1.add_runtime_dependency "o"
use_ui @ui do
@a1.validate
@@ -2635,22 +2649,22 @@ end
#{w}: prerelease dependency on c (>= 2.0.rc2, development) is not recommended
#{w}: open-ended dependency on i (>= 1.2) is not recommended
if i is semantically versioned, use:
- add_runtime_dependency 'i', '~> 1.2'
+ add_runtime_dependency "i", "~> 1.2"
#{w}: open-ended dependency on j (>= 1.2.3) is not recommended
if j is semantically versioned, use:
- add_runtime_dependency 'j', '~> 1.2', '>= 1.2.3'
+ add_runtime_dependency "j", "~> 1.2", ">= 1.2.3"
#{w}: open-ended dependency on k (> 1.2) is not recommended
if k is semantically versioned, use:
- add_runtime_dependency 'k', '~> 1.2', '> 1.2'
+ add_runtime_dependency "k", "~> 1.2", "> 1.2"
#{w}: open-ended dependency on l (> 1.2.3) is not recommended
if l is semantically versioned, use:
- add_runtime_dependency 'l', '~> 1.2', '> 1.2.3'
+ add_runtime_dependency "l", "~> 1.2", "> 1.2.3"
#{w}: open-ended dependency on o (>= 0) is not recommended
- use a bounded requirement, such as '~> x.y'
+ use a bounded requirement, such as "~> x.y"
#{w}: See https://guides.rubygems.org/specification-reference/ for help
EXPECTED
- assert_equal expected, @ui.error, 'warning'
+ assert_equal expected, @ui.error, "warning"
end
end
@@ -2658,10 +2672,10 @@ end
util_setup_validate
Dir.chdir @tempdir do
- @a1.add_runtime_dependency 'b', '~> 1.2'
- @a1.add_runtime_dependency 'b', '>= 1.2.3'
- @a1.add_development_dependency 'c', '~> 1.2'
- @a1.add_development_dependency 'c', '>= 1.2.3'
+ @a1.add_runtime_dependency "b", "~> 1.2"
+ @a1.add_runtime_dependency "b", ">= 1.2.3"
+ @a1.add_development_dependency "c", "~> 1.2"
+ @a1.add_development_dependency "c", ">= 1.2.3"
use_ui @ui do
e = assert_raise Gem::InvalidSpecificationException do
@@ -2670,9 +2684,9 @@ end
expected = <<-EXPECTED
duplicate dependency on b (>= 1.2.3), (~> 1.2) use:
- add_runtime_dependency 'b', '>= 1.2.3', '~> 1.2'
+ add_runtime_dependency "b", ">= 1.2.3", "~> 1.2"
duplicate dependency on c (>= 1.2.3, development), (~> 1.2) use:
- add_development_dependency 'c', '>= 1.2.3', '~> 1.2'
+ add_development_dependency "c", ">= 1.2.3", "~> 1.2"
EXPECTED
assert_equal expected, e.message
@@ -2688,14 +2702,61 @@ duplicate dependency on c (>= 1.2.3, development), (~> 1.2) use:
util_setup_validate
Dir.chdir @tempdir do
- @a1.add_runtime_dependency 'b', '~> 1.2'
- @a1.add_development_dependency 'b', '= 1.2.3'
+ @a1.add_runtime_dependency "b", "~> 1.2"
+ @a1.add_development_dependency "b", "= 1.2.3"
use_ui @ui do
@a1.validate
end
- assert_equal '', @ui.error, 'warning'
+ assert_equal "", @ui.error, "warning"
+ end
+ end
+
+ def test_validate_no_required_ruby_versions
+ util_setup_validate
+
+ Dir.chdir @tempdir do
+ use_ui @ui do
+ @a1.required_ruby_version = nil # reset
+ @a1.validate
+ end
+
+ assert_equal <<-EXPECTED, @ui.error
+#{w}: make sure you specify the oldest ruby version constraint (like \">= 3.0\") that you want your gem to support by setting the `required_ruby_version` gemspec attribute
+#{w}: See https://guides.rubygems.org/specification-reference/ for help
+ EXPECTED
+ end
+ end
+
+ def test_validate_open_required_ruby_versions
+ util_setup_validate
+
+ Dir.chdir @tempdir do
+ @a1.required_ruby_version = ">= 0"
+
+ use_ui @ui do
+ @a1.validate
+ end
+
+ assert_equal <<-EXPECTED, @ui.error
+#{w}: make sure you specify the oldest ruby version constraint (like \">= 3.0\") that you want your gem to support by setting the `required_ruby_version` gemspec attribute
+#{w}: See https://guides.rubygems.org/specification-reference/ for help
+ EXPECTED
+ end
+ end
+
+ def test_validate_valid_required_ruby_versions
+ util_setup_validate
+
+ Dir.chdir @tempdir do
+ @a1.required_ruby_version = ">= 2.3.0"
+
+ use_ui @ui do
+ @a1.validate
+ end
+
+ assert_equal "", @ui.error, "warning"
end
end
@@ -2703,14 +2764,31 @@ duplicate dependency on c (>= 1.2.3, development), (~> 1.2) use:
util_setup_validate
Dir.chdir @tempdir do
- @a1.version = '1.0.0.beta.1'
- @a1.add_runtime_dependency 'b', '~> 1.2.0.beta.1'
+ @a1.version = "1.0.0.beta.1"
+ @a1.add_dependency "b", "~> 1.2.0.beta.1"
+
+ use_ui @ui do
+ @a1.validate
+ end
+
+ assert_equal "", @ui.error, "warning"
+ end
+ end
+
+ def test_validate_self_referencing_dependencies
+ util_setup_validate
+
+ Dir.chdir @tempdir do
+ @a1.add_dependency @a1.name, "1"
use_ui @ui do
@a1.validate
end
- assert_equal '', @ui.error, 'warning'
+ assert_equal <<-EXPECTED, @ui.error
+#{w}: Self referencing dependency is unnecessary and strongly discouraged.
+#{w}: See https://guides.rubygems.org/specification-reference/ for help
+ EXPECTED
end
end
@@ -2718,14 +2796,14 @@ duplicate dependency on c (>= 1.2.3, development), (~> 1.2) use:
util_setup_validate
Dir.chdir @tempdir do
- @a1.extensions = ['Rakefile']
- File.write File.join(@tempdir, 'Rakefile'), ''
+ @a1.extensions = ["Rakefile"]
+ File.write File.join(@tempdir, "Rakefile"), ""
use_ui @ui do
@a1.validate
end
- assert_match(/add rake as a dependency/, @ui.error)
+ assert_match(/add rake as a runtime dependency/, @ui.error)
end
end
@@ -2733,15 +2811,48 @@ duplicate dependency on c (>= 1.2.3, development), (~> 1.2) use:
util_setup_validate
Dir.chdir @tempdir do
- @a1.extensions = ['Rakefile']
- @a1.add_runtime_dependency 'rake'
- File.write File.join(@tempdir, 'Rakefile'), ''
+ @a1.extensions = ["Rakefile"]
+ @a1.add_dependency "rake"
+ File.write File.join(@tempdir, "Rakefile"), ""
use_ui @ui do
@a1.validate
end
- refute_match(/add rake as a dependency/, @ui.error)
+ refute_match(/add rake as a runtime dependency/, @ui.error)
+ end
+ end
+
+ def test_validate_rust_extension_have_missing_cargo_toml_error
+ util_setup_validate
+
+ Dir.chdir @tempdir do
+ @a1.extensions = ["Cargo.toml"]
+ File.write File.join(@tempdir, "Cargo.toml"), ""
+
+ e = assert_raise Gem::InvalidSpecificationException do
+ use_ui @ui do
+ @a1.validate
+ end
+ end
+
+ assert_match(/but Cargo.lock is not part of the gem files/, e.message)
+ end
+ end
+
+ def test_validate_rust_extension_have_no_missing_cargo_toml_error
+ util_setup_validate
+
+ Dir.chdir @tempdir do
+ @a1.extensions = ["Cargo.toml"]
+ @a1.files << "Cargo.toml"
+ @a1.files << "Cargo.lock"
+ File.write File.join(@tempdir, "Cargo.toml"), ""
+ File.write File.join(@tempdir, "Cargo.lock"), ""
+
+ use_ui @ui do
+ @a1.validate
+ end
end
end
@@ -2749,7 +2860,7 @@ duplicate dependency on c (>= 1.2.3, development), (~> 1.2) use:
util_setup_validate
Dir.chdir @tempdir do
- @a1.description = ''
+ @a1.description = ""
use_ui @ui do
@a1.validate
@@ -2795,6 +2906,20 @@ duplicate dependency on c (>= 1.2.3, development), (~> 1.2) use:
assert_nothing_raised do
@a1.validate
end
+
+ # Adding #{f} at the start of the second or later line should be fine.
+ @a1.description = "(some description)\n#{f}"
+
+ assert_nothing_raised do
+ @a1.validate
+ end
+
+ # Adding #{t} at the start of the second or later line should be fine.
+ @a1.description = "(some description)\n#{t}"
+
+ assert_nothing_raised do
+ @a1.validate
+ end
end
end
@@ -2825,7 +2950,7 @@ duplicate dependency on c (>= 1.2.3, development), (~> 1.2) use:
Gem::Specification.new.validate
end
- assert_equal 'missing value for attribute name', e.message
+ assert_equal "missing value for attribute name", e.message
end
def test_validate_error
@@ -2835,15 +2960,15 @@ duplicate dependency on c (>= 1.2.3, development), (~> 1.2) use:
end
end
- assert_match 'See https://guides.rubygems.org/specification-reference/ for help', @ui.error
+ assert_match "See https://guides.rubygems.org/specification-reference/ for help", @ui.error
end
def test_validate_executables
util_setup_validate
- FileUtils.mkdir_p File.join(@tempdir, 'bin')
- File.write File.join(@tempdir, 'bin', 'exec'), ''
- FileUtils.mkdir_p File.join(@tempdir, 'exec')
+ FileUtils.mkdir_p File.join(@tempdir, "bin")
+ File.write File.join(@tempdir, "bin", "exec"), ""
+ FileUtils.mkdir_p File.join(@tempdir, "exec")
use_ui @ui do
Dir.chdir @tempdir do
@@ -2853,41 +2978,49 @@ duplicate dependency on c (>= 1.2.3, development), (~> 1.2) use:
assert_equal %w[exec], @a1.executables
- assert_equal '', @ui.output, 'output'
- assert_match "#{w}: bin/exec is missing #! line\n", @ui.error, 'error'
+ assert_equal "", @ui.output, "output"
+ assert_match "#{w}: bin/exec is missing #! line\n", @ui.error, "error"
end
def test_validate_empty_require_paths
- if win_platform?
- pend 'test_validate_empty_require_paths skipped on MS Windows (symlink)'
- else
- util_setup_validate
+ util_setup_validate
- @a1.require_paths = []
- e = assert_raise Gem::InvalidSpecificationException do
- @a1.validate
- end
+ @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_require_paths_with_invalid_types
+ util_setup_validate
- assert_equal 'specification must have at least one require_path',
- e.message
+ @a1.require_paths = [1, 2]
+ e = assert_raise Gem::InvalidSpecificationException do
+ @a1.validate
end
+
+ assert_equal "require_paths must be an Array of String",
+ e.message
end
def test_validate_files
- pend 'test_validate_files skipped on MS Windows (symlink)' if win_platform?
+ pend "test_validate_files skipped on MS Windows (symlink)" if Gem.win_platform?
util_setup_validate
- @a1.files += ['lib', 'lib2']
- @a1.extensions << 'ext/a/extconf.rb'
+ @a1.files += ["lib", "lib2"]
+ @a1.extensions << "ext/a/extconf.rb"
Dir.chdir @tempdir do
- FileUtils.ln_s 'lib/code.rb', 'lib2' unless vc_windows?
+ FileUtils.ln_s "lib/code.rb", "lib2" unless vc_windows?
use_ui @ui do
@a1.validate
end
- assert_match 'WARNING: lib2 is a symlink, which is not supported on all platforms', @ui.error
+ assert_match "WARNING: lib2 is a symlink, which is not supported on all platforms", @ui.error
end
assert_equal %w[bin/exec ext/a/extconf.rb lib/code.rb lib2 test/suite.rb].sort,
@@ -2903,7 +3036,7 @@ duplicate dependency on c (>= 1.2.3, development), (~> 1.2) use:
{ b: Gem::Dependency.new("x","1") }
end
- specification.define_singleton_method(:find_all_by_name) do |dep_name|
+ specification.define_singleton_method(:find_all_by_name) do |_dep_name|
[]
end
@@ -2930,7 +3063,7 @@ Please report a bug if this causes problems.
{ b: Gem::Dependency.new("x","1") }
end
- specification.define_singleton_method(:find_all_by_name) do |dep_name|
+ specification.define_singleton_method(:find_all_by_name) do |_dep_name|
[
specification.new {|s| s.name = "z", s.version = Gem::Version.new("1") },
specification.new {|s| s.name = "z", s.version = Gem::Version.new("2") },
@@ -2957,7 +3090,7 @@ Please report a bug if this causes problems.
def test_duplicate_runtime_dependency
expected = "WARNING: duplicated b dependency [\"~> 3.0\", \"~> 3.0\"]\n"
out, err = capture_output do
- @a1.add_runtime_dependency "b", "~> 3.0", "~> 3.0"
+ @a1.add_dependency "b", "~> 3.0", "~> 3.0"
end
assert_empty out
assert_equal(expected, err)
@@ -2965,7 +3098,7 @@ Please report a bug if this causes problems.
def set_orig(cls)
s_cls = cls.singleton_class
- s_cls.send :alias_method, :orig_unresolved_deps , :unresolved_deps
+ s_cls.send :alias_method, :orig_unresolved_deps, :unresolved_deps
s_cls.send :alias_method, :orig_find_all_by_name, :find_all_by_name
end
@@ -2993,19 +3126,19 @@ Please report a bug if this causes problems.
@a1.validate
end
- assert_match "#{w}: no homepage specified\n", @ui.error, 'error'
+ assert_match "#{w}: no homepage specified\n", @ui.error, "error"
@ui = Gem::MockGemUi.new
- @a1.homepage = ''
+ @a1.homepage = ""
use_ui @ui do
@a1.validate
end
- assert_match "#{w}: no homepage specified\n", @ui.error, 'error'
+ assert_match "#{w}: no homepage specified\n", @ui.error, "error"
- @a1.homepage = 'over at my cool site'
+ @a1.homepage = "over at my cool site"
e = assert_raise Gem::InvalidSpecificationException do
@a1.validate
@@ -3013,7 +3146,7 @@ Please report a bug if this causes problems.
assert_equal '"over at my cool site" is not a valid HTTP URI', e.message
- @a1.homepage = 'ftp://rubygems.org'
+ @a1.homepage = "ftp://rubygems.org"
e = assert_raise Gem::InvalidSpecificationException do
@a1.validate
@@ -3021,12 +3154,11 @@ Please report a bug if this causes problems.
assert_equal '"ftp://rubygems.org" is not a valid HTTP URI', e.message
- @a1.homepage = 'https://rubygems.org/'
+ @a1.homepage = "https://rubygems.org/"
assert_equal true, @a1.validate
- @a1.homepage = 'https://rubygems.org'
+ @a1.homepage = "https://rubygems.org"
assert_equal true, @a1.validate
-
end
end
@@ -3039,11 +3171,23 @@ Please report a bug if this causes problems.
end
assert_match <<-WARNING, @ui.error
-WARNING: licenses is empty, but is recommended. Use a license identifier from
-http://spdx.org/licenses or 'Nonstandard' for a nonstandard license.
+WARNING: licenses is empty, but is recommended. Use an license identifier from
+https://spdx.org/licenses or 'Nonstandard' for a nonstandard license,
+or set it to nil if you don't want to specify a license.
WARNING
end
+ def test_validate_nil_license
+ util_setup_validate
+
+ use_ui @ui do
+ @a1.license = nil
+ @a1.validate
+ end
+
+ assert_empty @ui.error
+ end
+
def test_validate_license_in_a_non_packaging_context
util_setup_validate
@@ -3056,14 +3200,14 @@ http://spdx.org/licenses or 'Nonstandard' for a nonstandard license.
end
def test_removed_methods
- assert_equal Gem::Specification::REMOVED_METHODS, [:rubyforge_project=]
+ assert_equal Gem::Specification::REMOVED_METHODS, [:rubyforge_project=, :mark_version]
end
def test_validate_removed_rubyforge_project
util_setup_validate
use_ui @ui do
- @a1.rubyforge_project = 'invalid-attribute'
+ @a1.rubyforge_project = "invalid-attribute"
@a1.validate
end
@@ -3074,32 +3218,48 @@ http://spdx.org/licenses or 'Nonstandard' for a nonstandard license.
util_setup_validate
use_ui @ui do
- @a1.licenses = ['BSD']
+ @a1.licenses = ["BSD"]
@a1.validate
end
assert_match <<-WARNING, @ui.error
-WARNING: license value 'BSD' is invalid. Use a license identifier from
-http://spdx.org/licenses or 'Nonstandard' for a nonstandard license.
+WARNING: License identifier 'BSD' is invalid. Use an identifier from
+https://spdx.org/licenses or 'Nonstandard' for a nonstandard license,
+or set it to nil if you don't want to specify a license.
WARNING
end
- def test_validate_license_values_plus
+ def test_validate_license_ref
util_setup_validate
use_ui @ui do
- @a1.licenses = ['GPL-2.0+']
+ @a1.licenses = ["LicenseRef-LICENSE.md"]
@a1.validate
end
assert_empty @ui.error
end
+ def test_validate_deprecated_license_values_plus
+ util_setup_validate
+
+ use_ui @ui do
+ @a1.licenses = ["GPL-2.0+"]
+ @a1.validate
+ end
+
+ assert_match <<-WARNING, @ui.error
+WARNING: License identifier 'GPL-2.0+' is deprecated. Use an identifier from
+https://spdx.org/licenses or 'Nonstandard' for a nonstandard license,
+or set it to nil if you don't want to specify a license.
+ WARNING
+ end
+
def test_validate_license_values_or_later
util_setup_validate
use_ui @ui do
- @a1.licenses = ['GPL-2.0-or-later']
+ @a1.licenses = ["GPL-2.0-or-later"]
@a1.validate
end
@@ -3110,7 +3270,7 @@ http://spdx.org/licenses or 'Nonstandard' for a nonstandard license.
util_setup_validate
use_ui @ui do
- @a1.licenses = ['GPL-2.0+ WITH Autoconf-exception-2.0']
+ @a1.licenses = ["GPL-2.0-or-later WITH Autoconf-exception-2.0"]
@a1.validate
end
@@ -3121,17 +3281,19 @@ http://spdx.org/licenses or 'Nonstandard' for a nonstandard license.
util_setup_validate
use_ui @ui do
- @a1.licenses = ['GPL-2.0+ FOO', 'GPL-2.0 FOO']
+ @a1.licenses = ["GPL-2.0+ FOO", "GPL-2.0 FOO"]
@a1.validate
end
assert_match <<-WARNING, @ui.error
-WARNING: license value 'GPL-2.0+ FOO' is invalid. Use a license identifier from
-http://spdx.org/licenses or 'Nonstandard' for a nonstandard license.
+WARNING: License identifier 'GPL-2.0+ FOO' is invalid. Use an identifier from
+https://spdx.org/licenses or 'Nonstandard' for a nonstandard license,
+or set it to nil if you don't want to specify a license.
WARNING
assert_match <<-WARNING, @ui.error
-WARNING: license value 'GPL-2.0 FOO' is invalid. Use a license identifier from
-http://spdx.org/licenses or 'Nonstandard' for a nonstandard license.
+WARNING: License identifier 'GPL-2.0+ FOO' is invalid. Use an identifier from
+https://spdx.org/licenses or 'Nonstandard' for a nonstandard license,
+or set it to nil if you don't want to specify a license.
WARNING
end
@@ -3139,13 +3301,29 @@ http://spdx.org/licenses or 'Nonstandard' for a nonstandard license.
util_setup_validate
use_ui @ui do
- @a1.licenses = ['GPL-2.0+ WITH Autocofn-exception-2.0']
+ @a1.licenses = ["GPL-2.0-only WITH Autocofn-exception-2.0"]
@a1.validate
end
assert_match <<-WARNING, @ui.error
-WARNING: license value 'GPL-2.0+ WITH Autocofn-exception-2.0' is invalid. Use a license identifier from
-http://spdx.org/licenses or 'Nonstandard' for a nonstandard license.
+WARNING: License identifier 'GPL-2.0-only WITH Autocofn-exception-2.0' is invalid. Use an identifier from
+https://spdx.org/licenses or 'Nonstandard' for a nonstandard license,
+or set it to nil if you don't want to specify a license.
+ WARNING
+ end
+
+ def test_validate_license_with_deprecated_exception
+ util_setup_validate
+
+ use_ui @ui do
+ @a1.licenses = ["GPL-2.0-only WITH Nokia-Qt-exception-1.1"]
+ @a1.validate
+ end
+
+ assert_match <<-WARNING, @ui.error
+WARNING: Exception identifier at 'GPL-2.0-only WITH Nokia-Qt-exception-1.1' is deprecated. Use an identifier from
+https://spdx.org/licenses or 'Nonstandard' for a nonstandard license,
+or set it to nil if you don't want to specify a license.
WARNING
end
@@ -3153,13 +3331,14 @@ http://spdx.org/licenses or 'Nonstandard' for a nonstandard license.
util_setup_validate
use_ui @ui do
- @a1.licenses = ['ruby']
+ @a1.licenses = ["ruby"]
@a1.validate
end
assert_match <<-WARNING, @ui.error
-WARNING: license value 'ruby' is invalid. Use a license identifier from
-http://spdx.org/licenses or 'Nonstandard' for a nonstandard license.
+WARNING: License identifier 'ruby' is invalid. Use an identifier from
+https://spdx.org/licenses or 'Nonstandard' for a nonstandard license,
+or set it to nil if you don't want to specify a license.
Did you mean 'Ruby'?
WARNING
end
@@ -3257,19 +3436,19 @@ Did you mean 'Ruby'?
spec.validate
end
- assert_match %r{^#{name}}, e.message
+ assert_match(/^#{name}/, e.message)
end
end
end
def test_validate_permissions
- pend 'chmod not supported' if Gem.win_platform?
+ pend "chmod not supported" if Gem.win_platform?
util_setup_validate
Dir.chdir @tempdir do
- File.chmod 0640, File.join('lib', 'code.rb')
- File.chmod 0640, File.join('bin', 'exec')
+ File.chmod 0o640, File.join("lib", "code.rb")
+ File.chmod 0o640, File.join("bin", "exec")
use_ui @ui do
@a1.validate
@@ -3282,12 +3461,12 @@ Did you mean 'Ruby'?
end
def test_validate_permissions_of_missing_file_non_packaging
- pend 'chmod not supported' if Gem.win_platform?
+ pend "chmod not supported" if Gem.win_platform?
util_setup_validate
Dir.chdir @tempdir do
- File.delete File.join('lib', 'code.rb')
+ File.delete File.join("lib", "code.rb")
use_ui @ui do
assert @a1.validate(false)
@@ -3299,13 +3478,13 @@ Did you mean 'Ruby'?
util_setup_validate
Dir.chdir @tempdir do
- @a1.platform = 'mswin32'
+ @a1.platform = "mswin32"
assert @a1.validate
- @a1.platform = 'i586-linux'
+ @a1.platform = "i586-linux"
assert @a1.validate
- @a1.platform = 'powerpc-darwin'
+ @a1.platform = "powerpc-darwin"
assert @a1.validate
end
end
@@ -3314,19 +3493,24 @@ Did you mean 'Ruby'?
util_setup_validate
@a1.rubygems_version = "3"
- e = assert_raise Gem::InvalidSpecificationException do
+
+ use_ui @ui do
@a1.validate
end
- assert_equal "expected RubyGems version #{Gem::VERSION}, was 3",
- e.message
+ expected = <<~EXPECTED
+ #{w}: expected RubyGems version #{Gem::VERSION}, was 3
+ #{w}: See https://guides.rubygems.org/specification-reference/ for help
+ EXPECTED
+
+ assert_equal expected, @ui.error
end
def test_validate_specification_version
util_setup_validate
Dir.chdir @tempdir do
- @a1.specification_version = '1.0'
+ @a1.specification_version = "1.0"
e = assert_raise Gem::InvalidSpecificationException do
use_ui @ui do
@@ -3334,7 +3518,7 @@ Did you mean 'Ruby'?
end
end
- err = 'specification_version must be an Integer (did you mean version?)'
+ err = "specification_version must be an Integer (did you mean version?)"
assert_equal err, e.message
end
end
@@ -3343,13 +3527,13 @@ Did you mean 'Ruby'?
util_setup_validate
Dir.chdir @tempdir do
- @a1.summary = ''
+ @a1.summary = ""
use_ui @ui do
@a1.validate
end
- assert_match "#{w}: no summary specified\n", @ui.error, 'error'
+ assert_match "#{w}: no summary specified\n", @ui.error, "error"
@a1.summary = "#{f} (describe your package)"
@@ -3377,11 +3561,11 @@ Did you mean 'Ruby'?
@a1.validate
end
- assert_match 'See https://guides.rubygems.org/specification-reference/ for help', @ui.error
+ assert_match "See https://guides.rubygems.org/specification-reference/ for help", @ui.error
end
def test_version
- assert_equal Gem::Version.new('1'), @a1.version
+ assert_equal Gem::Version.new("1"), @a1.version
end
def test_version_change_reset_full_name
@@ -3417,7 +3601,7 @@ Did you mean 'Ruby'?
capture_output do
Gem::Specification.load(specfile.path)
end
- rescue => e
+ rescue StandardError => e
name_rexp = Regexp.new(Regexp.escape(specfile.path))
assert e.backtrace.grep(name_rexp).any?
end
@@ -3427,22 +3611,22 @@ Did you mean 'Ruby'?
def test_latest_specs
spec_fetcher do |fetcher|
- fetcher.spec 'a', 1 do |s|
- s.platform = Gem::Platform.new 'x86-my_platform1'
+ fetcher.spec "a", 1 do |s|
+ s.platform = Gem::Platform.new "x86-my_platform1"
end
- fetcher.spec 'a', 2
+ fetcher.spec "a", 2
- fetcher.spec 'a', 2 do |s|
- s.platform = Gem::Platform.new 'x86-my_platform1'
+ fetcher.spec "a", 2 do |s|
+ s.platform = Gem::Platform.new "x86-my_platform1"
end
- fetcher.spec 'a', 2 do |s|
- s.platform = Gem::Platform.new 'x86-other_platform1'
+ fetcher.spec "a", 2 do |s|
+ s.platform = Gem::Platform.new "x86-other_platform1"
end
- fetcher.spec 'a', 3 do |s|
- s.platform = Gem::Platform.new 'x86-other_platform1'
+ fetcher.spec "a", 3 do |s|
+ s.platform = Gem::Platform.new "x86-other_platform1"
end
end
@@ -3459,13 +3643,13 @@ Did you mean 'Ruby'?
util_setup_validate
Dir.chdir @tempdir do
- @m1 = quick_gem 'm', '1' do |s|
+ @m1 = quick_gem "m", "1" do |s|
s.files = %w[lib/code.rb]
s.metadata = {
- "one" => "two",
- "home" => "three",
+ "one" => "two",
+ "home" => "three",
"homepage_uri" => "https://example.com/user/repo",
- "funding_uri" => "https://example.com/donate",
+ "funding_uri" => "https://example.com/donate",
}
end
@@ -3479,7 +3663,7 @@ Did you mean 'Ruby'?
util_setup_validate
Dir.chdir @tempdir do
- @m2 = quick_gem 'm', '2' do |s|
+ @m2 = quick_gem "m", "2" do |s|
s.files = %w[lib/code.rb]
s.metadata = { 1 => "fail" }
end
@@ -3496,7 +3680,7 @@ Did you mean 'Ruby'?
util_setup_validate
Dir.chdir @tempdir do
- @m2 = quick_gem 'm', '2' do |s|
+ @m2 = quick_gem "m", "2" do |s|
s.files = %w[lib/code.rb]
s.metadata = { ("x" * 129) => "fail" }
end
@@ -3513,9 +3697,9 @@ Did you mean 'Ruby'?
util_setup_validate
Dir.chdir @tempdir do
- @m2 = quick_gem 'm', '2' do |s|
+ @m2 = quick_gem "m", "2" do |s|
s.files = %w[lib/code.rb]
- s.metadata = { 'fail' => [] }
+ s.metadata = { "fail" => [] }
end
e = assert_raise Gem::InvalidSpecificationException do
@@ -3530,9 +3714,9 @@ Did you mean 'Ruby'?
util_setup_validate
Dir.chdir @tempdir do
- @m2 = quick_gem 'm', '2' do |s|
+ @m2 = quick_gem "m", "2" do |s|
s.files = %w[lib/code.rb]
- s.metadata = { 'fail' => ("x" * 1025) }
+ s.metadata = { "fail" => ("x" * 1025) }
end
e = assert_raise Gem::InvalidSpecificationException do
@@ -3547,9 +3731,9 @@ Did you mean 'Ruby'?
util_setup_validate
Dir.chdir @tempdir do
- @m2 = quick_gem 'm', '2' do |s|
+ @m2 = quick_gem "m", "2" do |s|
s.files = %w[lib/code.rb]
- s.metadata = { 'homepage_uri' => 'http:/example.com' }
+ s.metadata = { "homepage_uri" => "http:/example.com" }
end
e = assert_raise Gem::InvalidSpecificationException do
@@ -3560,10 +3744,43 @@ Did you mean 'Ruby'?
end
end
+ def test_metadata_link_validation_warns_for_duplicates
+ util_setup_validate
+
+ Dir.chdir @tempdir do
+ @m2 = quick_gem "m", "2" do |s|
+ s.required_ruby_version = ">= 2.3.0"
+ s.files = %w[lib/code.rb]
+ s.licenses = "BSD-2-Clause"
+ s.metadata = {
+ "source_code_uri" => "http://example.com",
+ "homepage_uri" => "http://example.com",
+ "changelog_uri" => "http://example.com/changelog",
+ }
+ end
+
+ use_ui @ui do
+ @m2.validate
+ end
+
+ expected = <<~EXPECTED
+ #{w}: You have specified the uri:
+ http://example.com
+ for all of the following keys:
+ homepage_uri
+ source_code_uri
+ Only the first one will be shown on rubygems.org
+ #{w}: See https://guides.rubygems.org/specification-reference/ for help
+ EXPECTED
+
+ assert_equal expected, @ui.error, "warning"
+ end
+ end
+
def test_metadata_specs
- @m1 = quick_gem 'm', '1' do |s|
+ @m1 = quick_gem "m", "1" do |s|
s.files = %w[lib/code.rb]
- s.metadata = { 'one' => "two", 'two' => "three" }
+ s.metadata = { "one" => "two", "two" => "three" }
end
valid_ruby_spec = <<-EOF
@@ -3572,7 +3789,7 @@ Did you mean 'Ruby'?
Gem::Specification.new do |s|
s.name = "m".freeze
- s.version = "1"
+ s.version = "1".freeze
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
s.metadata = { "one" => "two", "two" => "three" } if s.respond_to? :metadata=
@@ -3600,7 +3817,7 @@ end
extconf_rb = File.join @ext.gem_dir, @ext.extensions.first
FileUtils.mkdir_p File.dirname extconf_rb
- File.open extconf_rb, 'w' do |f|
+ File.open extconf_rb, "w" do |f|
f.write <<-'RUBY'
File.open 'Makefile', 'w' do |f|
f.puts "clean:\n\techo clean"
@@ -3616,8 +3833,8 @@ end
end
def test_missing_extensions_eh_default_gem
- spec = new_default_spec 'default', 1
- spec.extensions << 'extconf.rb'
+ spec = new_default_spec "default", 1
+ spec.extensions << "extconf.rb"
refute spec.missing_extensions?
end
@@ -3627,7 +3844,7 @@ end
end
def test_find_all_by_full_name
- pl = Gem::Platform.new 'i386-linux'
+ pl = Gem::Platform.new "i386-linux"
a1 = util_spec "a", "1"
a1_pre = util_spec "a", "1.0.0.pre.1"
@@ -3671,6 +3888,13 @@ end
assert Gem::Specification.find_by_name "q"
end
+ def test_find_by_name_with_only_prereleases_with_requirements
+ q = util_spec "q", "2.a"
+ install_specs q
+
+ assert Gem::Specification.find_by_name "q", ">= 1"
+ end
+
def test_find_by_name_prerelease
b = util_spec "b", "2.a"
@@ -3678,6 +3902,8 @@ end
install_specs b
+ Gem::Specification.reset
+
assert Gem::Specification.find_by_name "b"
assert_raise Gem::MissingSpecVersionError do
@@ -3687,14 +3913,31 @@ end
assert Gem::Specification.find_by_name "b", ">1"
end
+ def test_find_by_full_name
+ pl = Gem::Platform.new "x86_64-linux"
+
+ a = util_spec "a", "1"
+ install_specs a
+
+ a_pl = util_spec("a", "1") {|s| s.platform = pl }
+ install_specs a_pl
+
+ assert_equal a, Gem::Specification.find_by_full_name("a-1")
+ assert_equal a_pl, Gem::Specification.find_by_full_name("a-1-x86_64-linux")
+
+ assert_nil Gem::Specification.find_by_full_name("a-2")
+ assert_nil Gem::Specification.find_by_full_name("b-1")
+ assert_nil Gem::Specification.find_by_full_name("a-1-arm64-linux")
+ end
+
def test_find_by_path
a = util_spec "foo", "1", nil, "lib/foo.rb"
install_specs a
- assert_equal a, Gem::Specification.find_by_path('foo')
+ assert_equal a, Gem::Specification.find_by_path("foo")
a.activate
- assert_equal a, Gem::Specification.find_by_path('foo')
+ assert_equal a, Gem::Specification.find_by_path("foo")
end
def test_find_inactive_by_path
@@ -3702,9 +3945,9 @@ end
install_specs a
- assert_equal a, Gem::Specification.find_inactive_by_path('foo')
+ assert_equal a, Gem::Specification.find_inactive_by_path("foo")
a.activate
- assert_nil Gem::Specification.find_inactive_by_path('foo')
+ assert_nil Gem::Specification.find_inactive_by_path("foo")
end
def test_load_default_gem
@@ -3721,6 +3964,40 @@ end
assert_equal ["default-2.0.0.0"], Gem::Specification.map(&:full_name)
end
+ def test_validate_for_resolution_validates_required_attributes
+ e = assert_raise Gem::InvalidSpecificationException do
+ @a1.name = nil
+ @a1.validate_for_resolution
+ end
+
+ assert_equal "missing value for attribute name", e.message
+ end
+
+ def test_validate_for_resolution_validates_name
+ e = assert_raise Gem::InvalidSpecificationException do
+ @a1.name = 123
+ @a1.validate_for_resolution
+ end
+
+ assert_equal 'invalid value for attribute name: "123" must be a string', e.message
+ end
+
+ def test_validate_for_resolution_validates_duplicate_dependencies
+ e = assert_raise Gem::InvalidSpecificationException do
+ @a1.add_dependency "foo", "1.2.3"
+ @a1.add_dependency "foo", "3.4.5"
+ @a1.validate_for_resolution
+ end
+
+ assert_match "duplicate dependency on foo", e.message
+ end
+
+ def test_validate_for_resolution_ignores_metadata
+ @a1.summary = "TODO: Invalid summary"
+ @a1.metadata["homepage_uri"] = "TODO: Invalid homepage URI"
+ @a1.validate_for_resolution
+ end
+
def util_setup_deps
@gem = util_spec "awesome", "1.0" do |awesome|
awesome.add_runtime_dependency "bonobo", []
@@ -3744,7 +4021,7 @@ end
FileUtils.touch File.join("lib", "code.rb")
FileUtils.touch File.join("test", "suite.rb")
- File.open "bin/exec", "w", 0755 do |fp|
+ File.open "bin/exec", "w", 0o755 do |fp|
fp.puts "#!#{Gem.ruby}"
end
ensure
@@ -3752,11 +4029,4 @@ end
end
end
end
-
- def silence_warnings
- old_verbose, $VERBOSE = $VERBOSE, false
- yield
- ensure
- $VERBOSE = old_verbose
- end
end
diff --git a/test/rubygems/test_gem_stream_ui.rb b/test/rubygems/test_gem_stream_ui.rb
index dc245c342a..b1fcb3bc26 100644
--- a/test/rubygems/test_gem_stream_ui.rb
+++ b/test/rubygems/test_gem_stream_ui.rb
@@ -1,19 +1,20 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/user_interaction'
-require 'timeout'
+
+require_relative "helper"
+require "rubygems/user_interaction"
+require "rubygems/vendored_timeout"
class TestGemStreamUI < Gem::TestCase
- # increase timeout with MJIT for --jit-wait testing
- mjit_enabled = defined?(RubyVM::JIT) ? RubyVM::JIT.enabled? : defined?(RubyVM::MJIT) && RubyVM::MJIT.enabled?
- SHORT_TIMEOUT = (RUBY_ENGINE == "ruby" && !mjit_enabled) ? 0.1 : 1.0
+ # increase timeout with RJIT for --jit-wait testing
+ rjit_enabled = defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled?
+ SHORT_TIMEOUT = RUBY_ENGINE == "ruby" && !rjit_enabled ? 0.1 : 1.0
module IsTty
attr_accessor :tty
def tty?
@tty = true unless defined? @tty
- return @tty
+ @tty
end
alias_method :isatty, :tty?
@@ -39,7 +40,7 @@ class TestGemStreamUI < Gem::TestCase
end
def test_ask
- Timeout.timeout(5) do
+ Gem::Timeout.timeout(5) do
expected_answer = "Arthur, King of the Britons"
@in.string = "#{expected_answer}\n"
actual_answer = @sui.ask("What is your name?")
@@ -50,14 +51,14 @@ class TestGemStreamUI < Gem::TestCase
def test_ask_no_tty
@in.tty = false
- Timeout.timeout(SHORT_TIMEOUT) do
+ Gem::Timeout.timeout(SHORT_TIMEOUT) do
answer = @sui.ask("what is your favorite color?")
assert_nil answer
end
end
def test_ask_for_password
- Timeout.timeout(5) do
+ Gem::Timeout.timeout(5) do
expected_answer = "Arthur, King of the Britons"
@in.string = "#{expected_answer}\n"
actual_answer = @sui.ask_for_password("What is your name?")
@@ -68,7 +69,7 @@ class TestGemStreamUI < Gem::TestCase
def test_ask_for_password_no_tty
@in.tty = false
- Timeout.timeout(SHORT_TIMEOUT) do
+ Gem::Timeout.timeout(SHORT_TIMEOUT) do
answer = @sui.ask_for_password("what is the airspeed velocity of an unladen swallow?")
assert_nil answer
end
@@ -77,7 +78,7 @@ class TestGemStreamUI < Gem::TestCase
def test_ask_yes_no_no_tty_with_default
@in.tty = false
- Timeout.timeout(SHORT_TIMEOUT) do
+ Gem::Timeout.timeout(SHORT_TIMEOUT) do
answer = @sui.ask_yes_no("do coconuts migrate?", false)
assert_equal false, answer
@@ -89,7 +90,7 @@ class TestGemStreamUI < Gem::TestCase
def test_ask_yes_no_no_tty_without_default
@in.tty = false
- Timeout.timeout(SHORT_TIMEOUT) do
+ Gem::Timeout.timeout(SHORT_TIMEOUT) do
assert_raise(Gem::OperationNotSupportedError) do
@sui.ask_yes_no("do coconuts migrate?")
end
@@ -100,14 +101,44 @@ class TestGemStreamUI < Gem::TestCase
@in.puts "1"
@in.rewind
- result = @sui.choose_from_list 'which one?', %w[foo bar]
+ result = @sui.choose_from_list "which one?", %w[foo bar]
- assert_equal ['foo', 0], result
+ 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]
+ 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_choose_from_list_0
+ @in.puts "0"
+ @in.rewind
+
+ 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_choose_from_list_over
+ @in.puts "3"
+ @in.rewind
+
+ 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_choose_from_list_negative
+ @in.puts "-1"
+ @in.rewind
+
+ 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
@@ -115,27 +146,27 @@ class TestGemStreamUI < Gem::TestCase
def test_progress_reporter_silent_nil
@cfg.verbose = nil
- reporter = @sui.progress_reporter 10, 'hi'
+ reporter = @sui.progress_reporter 10, "hi"
assert_kind_of Gem::StreamUI::SilentProgressReporter, reporter
end
def test_progress_reporter_silent_false
@cfg.verbose = false
- reporter = @sui.progress_reporter 10, 'hi'
+ reporter = @sui.progress_reporter 10, "hi"
assert_kind_of Gem::StreamUI::SilentProgressReporter, reporter
assert_equal "", @out.string
end
def test_progress_reporter_simple
@cfg.verbose = true
- reporter = @sui.progress_reporter 10, 'hi'
+ reporter = @sui.progress_reporter 10, "hi"
assert_kind_of Gem::StreamUI::SimpleProgressReporter, reporter
assert_equal "hi\n", @out.string
end
def test_progress_reporter_verbose
@cfg.verbose = 0
- reporter = @sui.progress_reporter 10, 'hi'
+ reporter = @sui.progress_reporter 10, "hi"
assert_kind_of Gem::StreamUI::VerboseProgressReporter, reporter
assert_equal "hi\n", @out.string
end
@@ -143,7 +174,7 @@ class TestGemStreamUI < Gem::TestCase
def test_download_reporter_silent_nil
@cfg.verbose = nil
reporter = @sui.download_reporter
- reporter.fetch 'a.gem', 1024
+ reporter.fetch "a.gem", 1024
assert_kind_of Gem::StreamUI::SilentDownloadReporter, reporter
assert_equal "", @out.string
end
@@ -151,7 +182,7 @@ class TestGemStreamUI < Gem::TestCase
def test_download_reporter_silent_false
@cfg.verbose = false
reporter = @sui.download_reporter
- reporter.fetch 'a.gem', 1024
+ reporter.fetch "a.gem", 1024
assert_kind_of Gem::StreamUI::SilentDownloadReporter, reporter
assert_equal "", @out.string
end
@@ -165,14 +196,14 @@ class TestGemStreamUI < Gem::TestCase
def test_threaded_download_reporter
@cfg.verbose = true
reporter = @sui.download_reporter
- reporter.fetch 'a.gem', 1024
+ reporter.fetch "a.gem", 1024
assert_equal "Fetching a.gem\n", @out.string
end
def test_verbose_download_reporter_progress
@cfg.verbose = true
reporter = @sui.download_reporter
- reporter.fetch 'a.gem', 1024
+ reporter.fetch "a.gem", 1024
reporter.update 512
assert_equal "Fetching a.gem\n", @out.string
end
@@ -180,7 +211,7 @@ class TestGemStreamUI < Gem::TestCase
def test_verbose_download_reporter_progress_once
@cfg.verbose = true
reporter = @sui.download_reporter
- reporter.fetch 'a.gem', 1024
+ reporter.fetch "a.gem", 1024
reporter.update 510
reporter.update 512
assert_equal "Fetching a.gem\n", @out.string
@@ -189,7 +220,7 @@ class TestGemStreamUI < Gem::TestCase
def test_verbose_download_reporter_progress_complete
@cfg.verbose = true
reporter = @sui.download_reporter
- reporter.fetch 'a.gem', 1024
+ reporter.fetch "a.gem", 1024
reporter.update 510
reporter.done
assert_equal "Fetching a.gem\n", @out.string
@@ -198,7 +229,7 @@ class TestGemStreamUI < Gem::TestCase
def test_verbose_download_reporter_progress_nil_length
@cfg.verbose = true
reporter = @sui.download_reporter
- reporter.fetch 'a.gem', nil
+ reporter.fetch "a.gem", nil
reporter.update 1024
reporter.done
assert_equal "Fetching a.gem\n", @out.string
@@ -207,7 +238,7 @@ class TestGemStreamUI < Gem::TestCase
def test_verbose_download_reporter_progress_zero_length
@cfg.verbose = true
reporter = @sui.download_reporter
- reporter.fetch 'a.gem', 0
+ reporter.fetch "a.gem", 0
reporter.update 1024
reporter.done
assert_equal "Fetching a.gem\n", @out.string
@@ -218,7 +249,7 @@ class TestGemStreamUI < Gem::TestCase
@cfg.verbose = true
reporter = @sui.download_reporter
- reporter.fetch 'a.gem', 1024
+ reporter.fetch "a.gem", 1024
assert_equal "", @out.string
end
end
diff --git a/test/rubygems/test_gem_stub_specification.rb b/test/rubygems/test_gem_stub_specification.rb
index e008391ef7..fe30a78c0b 100644
--- a/test/rubygems/test_gem_stub_specification.rb
+++ b/test/rubygems/test_gem_stub_specification.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
require_relative "helper"
require "rubygems/stub_specification"
@@ -10,7 +11,7 @@ class TestStubSpecification < Gem::TestCase
super
@base_dir = __dir__
- @gems_dir = File.join __dir__, 'gem'
+ @gems_dir = File.join __dir__, "gem"
@foo = Gem::StubSpecification.gemspec_stub FOO, @base_dir, @gems_dir
end
@@ -25,24 +26,24 @@ class TestStubSpecification < Gem::TestCase
def test_initialize_extension
stub = stub_with_extension
- assert_equal 'stub_e', stub.name
+ assert_equal "stub_e", stub.name
assert_equal v(2), stub.version
assert_equal Gem::Platform::RUBY, stub.platform
- assert_equal [stub.extension_dir, 'lib'], stub.require_paths
+ assert_equal [stub.extension_dir, "lib"], stub.require_paths
assert_equal %w[ext/stub_e/extconf.rb], stub.extensions
end
def test_initialize_version
stub = stub_with_version
- assert_equal 'stub_v', stub.name
+ assert_equal "stub_v", stub.name
assert_equal v(2), stub.version
end
def test_initialize_with_empty_version
stub = stub_without_version
- assert_equal 'stub_v', stub.name
+ assert_equal "stub_v", stub.name
assert_equal v(0), stub.version
end
@@ -57,21 +58,21 @@ class TestStubSpecification < Gem::TestCase
def test_contains_requirable_file_eh
stub = stub_without_extension
- code_rb = File.join stub.gem_dir, 'lib', 'code.rb'
+ code_rb = File.join stub.gem_dir, "lib", "code.rb"
FileUtils.mkdir_p File.dirname code_rb
FileUtils.touch code_rb
- assert stub.contains_requirable_file? 'code'
+ assert stub.contains_requirable_file? "code"
end
def test_contains_requirable_file_eh_extension
pend "I guess making the stub match the running platform should work" if Gem.java_platform?
stub_with_extension do |stub|
_, err = capture_output do
- refute stub.contains_requirable_file? 'nonexistent'
+ refute stub.contains_requirable_file? "nonexistent"
end
- expected = "Ignoring stub_e-2 because its extensions are not built. " +
+ expected = "Ignoring stub_e-2 because its extensions are not built. " \
"Try: gem pristine stub_e --version 2\n"
assert_equal expected, err
@@ -82,7 +83,7 @@ class TestStubSpecification < Gem::TestCase
stub = stub_with_extension
expected = [
- File.join(stub.full_gem_path, 'lib'),
+ File.join(stub.full_gem_path, "lib"),
stub.extension_dir,
]
@@ -92,32 +93,32 @@ class TestStubSpecification < Gem::TestCase
def test_lib_dirs_glob
stub = stub_without_extension
- assert_equal File.join(stub.full_gem_path, 'lib'), stub.lib_dirs_glob
+ assert_equal File.join(stub.full_gem_path, "lib"), stub.lib_dirs_glob
end
def test_lib_dirs_glob_with_extension
stub = stub_with_extension
- assert_equal File.join(stub.full_gem_path, 'lib'), stub.lib_dirs_glob
+ assert_equal File.join(stub.full_gem_path, "lib"), stub.lib_dirs_glob
end
def test_matches_for_glob
stub = stub_without_extension
- code_rb = File.join stub.gem_dir, 'lib', 'code.rb'
+ code_rb = File.join stub.gem_dir, "lib", "code.rb"
FileUtils.mkdir_p File.dirname code_rb
FileUtils.touch code_rb
- assert_equal code_rb, stub.matches_for_glob('code*').first
+ assert_equal code_rb, stub.matches_for_glob("code*").first
end
def test_matches_for_glob_with_bundler_inline
stub = stub_with_extension
- code_rb = File.join stub.gem_dir, 'lib', 'code.rb'
+ code_rb = File.join stub.gem_dir, "lib", "code.rb"
FileUtils.mkdir_p File.dirname code_rb
FileUtils.touch code_rb
stub.stub(:raw_require_paths, nil) do
- assert_equal code_rb, stub.matches_for_glob('code*').first
+ assert_equal code_rb, stub.matches_for_glob("code*").first
end
end
@@ -127,7 +128,7 @@ class TestStubSpecification < Gem::TestCase
extconf_rb = File.join s.gem_dir, s.extensions.first
FileUtils.mkdir_p File.dirname extconf_rb
- File.open extconf_rb, 'w' do |f|
+ File.open extconf_rb, "w" do |f|
f.write <<-'RUBY'
File.open 'Makefile', 'w' do |f|
f.puts "clean:\n\techo clean"
@@ -146,10 +147,10 @@ class TestStubSpecification < Gem::TestCase
end
def test_missing_extensions_eh_default_gem
- spec = new_default_spec 'default', 1
- spec.extensions << 'extconf.rb'
+ spec = new_default_spec "default", 1
+ spec.extensions << "extconf.rb"
- File.open spec.loaded_from, 'w' do |io|
+ File.open spec.loaded_from, "w" do |io|
io.write spec.to_ruby_for_cache
end
@@ -167,7 +168,7 @@ class TestStubSpecification < Gem::TestCase
real_foo.activate
assert_equal @foo.version, Gem.loaded_specs[@foo.name].version,
- 'sanity check'
+ "sanity check"
assert_same real_foo, @foo.to_spec
end
@@ -180,25 +181,9 @@ class TestStubSpecification < Gem::TestCase
assert bar.to_spec
end
- def test_to_spec_activated
- assert @foo.to_spec.is_a?(Gem::Specification)
- assert_equal "foo", @foo.to_spec.name
- refute @foo.to_spec.instance_variable_get :@ignored
- end
-
- def test_to_spec_missing_extensions
- stub = stub_with_extension
-
- capture_output do
- stub.contains_requirable_file? 'nonexistent'
- end
-
- assert stub.to_spec.instance_variable_get :@ignored
- end
-
def stub_with_version
- spec = File.join @gemhome, 'specifications', 'stub_e-2.gemspec'
- File.open spec, 'w' do |io|
+ spec = File.join @gemhome, "specifications", "stub_e-2.gemspec"
+ File.open spec, "w" do |io|
io.write <<-STUB
# -*- encoding: utf-8 -*-
# stub: stub_v 2 ruby lib
@@ -211,7 +196,7 @@ end
io.flush
- stub = Gem::StubSpecification.gemspec_stub io.path, @gemhome, File.join(@gemhome, 'gems')
+ stub = Gem::StubSpecification.gemspec_stub io.path, @gemhome, File.join(@gemhome, "gems")
yield stub if block_given?
@@ -220,8 +205,8 @@ end
end
def stub_without_version
- spec = File.join @gemhome, 'specifications', 'stub-2.gemspec'
- File.open spec, 'w' do |io|
+ spec = File.join @gemhome, "specifications", "stub-2.gemspec"
+ File.open spec, "w" do |io|
io.write <<-STUB
# -*- encoding: utf-8 -*-
# stub: stub_v ruby lib
@@ -234,7 +219,7 @@ end
io.flush
- stub = Gem::StubSpecification.gemspec_stub io.path, @gemhome, File.join(@gemhome, 'gems')
+ stub = Gem::StubSpecification.gemspec_stub io.path, @gemhome, File.join(@gemhome, "gems")
yield stub if block_given?
@@ -243,8 +228,8 @@ end
end
def stub_with_extension
- spec = File.join @gemhome, 'specifications', 'stub_e-2.gemspec'
- File.open spec, 'w' do |io|
+ spec = File.join @gemhome, "specifications", "stub_e-2.gemspec"
+ File.open spec, "w" do |io|
io.write <<-STUB
# -*- encoding: utf-8 -*-
# stub: stub_e 2 ruby lib
@@ -260,7 +245,7 @@ end
io.flush
- stub = Gem::StubSpecification.gemspec_stub io.path, @gemhome, File.join(@gemhome, 'gems')
+ stub = Gem::StubSpecification.gemspec_stub io.path, @gemhome, File.join(@gemhome, "gems")
yield stub if block_given?
@@ -269,8 +254,8 @@ end
end
def stub_without_extension
- spec = File.join @gemhome, 'specifications', 'stub-2.gemspec'
- File.open spec, 'w' do |io|
+ spec = File.join @gemhome, "specifications", "stub-2.gemspec"
+ File.open spec, "w" do |io|
io.write <<-STUB
# -*- encoding: utf-8 -*-
# stub: stub 2 ruby lib
@@ -283,7 +268,7 @@ end
io.flush
- stub = Gem::StubSpecification.gemspec_stub io.path, @gemhome, File.join(@gemhome, 'gems')
+ stub = Gem::StubSpecification.gemspec_stub io.path, @gemhome, File.join(@gemhome, "gems")
yield stub if block_given?
diff --git a/test/rubygems/test_gem_text.rb b/test/rubygems/test_gem_text.rb
index f170fbf399..8e99610946 100644
--- a/test/rubygems/test_gem_text.rb
+++ b/test/rubygems/test_gem_text.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
-require_relative 'helper'
+
+require_relative "helper"
require "rubygems/text"
class TestGemText < Gem::TestCase
diff --git a/test/rubygems/test_gem_uninstaller.rb b/test/rubygems/test_gem_uninstaller.rb
index 9e18972864..92ea01a3bc 100644
--- a/test/rubygems/test_gem_uninstaller.rb
+++ b/test/rubygems/test_gem_uninstaller.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
-require_relative 'installer_test_case'
-require 'rubygems/uninstaller'
+
+require_relative "installer_test_case"
+require "rubygems/uninstaller"
class TestGemUninstaller < Gem::InstallerTestCase
def setup
@@ -18,19 +19,17 @@ class TestGemUninstaller < Gem::InstallerTestCase
@user_spec = @user_installer.spec
end
end
-
- Gem::Specification.reset
end
def test_initialize_expand_path
- FileUtils.mkdir_p 'foo/bar'
- uninstaller = Gem::Uninstaller.new nil, :install_dir => 'foo//bar'
+ FileUtils.mkdir_p "foo/bar"
+ uninstaller = Gem::Uninstaller.new nil, install_dir: "foo//bar"
assert_match %r{foo/bar$}, uninstaller.instance_variable_get(:@gem_home)
end
def test_ask_if_ok
- c = util_spec 'c'
+ c = util_spec "c"
uninstaller = Gem::Uninstaller.new nil
@@ -58,10 +57,10 @@ class TestGemUninstaller < Gem::InstallerTestCase
end
def test_remove_executables_force_keep
- uninstaller = Gem::Uninstaller.new nil, :executables => false
+ uninstaller = Gem::Uninstaller.new nil, executables: false
- executable = File.join Gem.bindir(@user_spec.base_dir), 'executable'
- assert File.exist?(executable), 'executable not written'
+ executable = File.join Gem.bindir(@user_spec.base_dir), "executable"
+ assert File.exist?(executable), "executable not written"
use_ui @ui do
uninstaller.remove_executables @user_spec
@@ -73,10 +72,10 @@ class TestGemUninstaller < Gem::InstallerTestCase
end
def test_remove_executables_force_remove
- uninstaller = Gem::Uninstaller.new nil, :executables => true
+ uninstaller = Gem::Uninstaller.new nil, executables: true
- executable = File.join Gem.bindir(@user_spec.base_dir), 'executable'
- assert File.exist?(executable), 'executable not written'
+ executable = File.join Gem.bindir(@user_spec.base_dir), "executable"
+ assert File.exist?(executable), "executable not written"
use_ui @ui do
uninstaller.remove_executables @user_spec
@@ -88,29 +87,29 @@ class TestGemUninstaller < Gem::InstallerTestCase
end
def test_remove_executables_user
- uninstaller = Gem::Uninstaller.new nil, :executables => true
+ uninstaller = Gem::Uninstaller.new nil, executables: true
use_ui @ui do
uninstaller.remove_executables @user_spec
end
- exec_path = File.join Gem.user_dir, 'bin', 'executable'
- refute File.exist?(exec_path), 'exec still exists in user bin dir'
+ exec_path = File.join Gem.user_dir, "bin", "executable"
+ refute File.exist?(exec_path), "exec still exists in user bin dir"
assert_equal "Removing executable\n", @ui.output
end
def test_remove_executables_user_format
- Gem::Installer.exec_format = 'foo-%s-bar'
+ Gem::Installer.exec_format = "foo-%s-bar"
- uninstaller = Gem::Uninstaller.new nil, :executables => true, :format_executable => true
+ uninstaller = Gem::Uninstaller.new nil, executables: true, format_executable: true
use_ui @ui do
uninstaller.remove_executables @user_spec
end
- exec_path = File.join Gem.user_dir, 'bin', 'foo-executable-bar'
- assert_equal false, File.exist?(exec_path), 'removed exec from bin dir'
+ exec_path = File.join Gem.user_dir, "bin", "foo-executable-bar"
+ assert_equal false, File.exist?(exec_path), "removed exec from bin dir"
assert_equal "Removing foo-executable-bar\n", @ui.output
ensure
@@ -118,16 +117,16 @@ class TestGemUninstaller < Gem::InstallerTestCase
end
def test_remove_executables_user_format_disabled
- Gem::Installer.exec_format = 'foo-%s-bar'
+ Gem::Installer.exec_format = "foo-%s-bar"
- uninstaller = Gem::Uninstaller.new nil, :executables => true
+ uninstaller = Gem::Uninstaller.new nil, executables: true
use_ui @ui do
uninstaller.remove_executables @user_spec
end
- exec_path = File.join Gem.user_dir, 'bin', 'executable'
- refute File.exist?(exec_path), 'removed exec from bin dir'
+ exec_path = File.join Gem.user_dir, "bin", "executable"
+ refute File.exist?(exec_path), "removed exec from bin dir"
assert_equal "Removing executable\n", @ui.output
ensure
@@ -136,7 +135,7 @@ class TestGemUninstaller < Gem::InstallerTestCase
def test_remove_not_in_home
Dir.mkdir "#{@gemhome}2"
- uninstaller = Gem::Uninstaller.new nil, :install_dir => "#{@gemhome}2"
+ uninstaller = Gem::Uninstaller.new nil, install_dir: "#{@gemhome}2"
e = assert_raise Gem::GemNotInHomeException do
use_ui ui do
@@ -160,7 +159,7 @@ class TestGemUninstaller < Gem::InstallerTestCase
FileUtils.ln_s(@gemhome, dir)
- uninstaller = Gem::Uninstaller.new nil, :install_dir => symlinked_gem_home
+ uninstaller = Gem::Uninstaller.new nil, install_dir: symlinked_gem_home
use_ui ui do
uninstaller.remove @spec
@@ -171,56 +170,115 @@ class TestGemUninstaller < Gem::InstallerTestCase
end
def test_remove_plugins
- write_file File.join(@tempdir, 'lib', 'rubygems_plugin.rb') do |io|
- io.write "puts __FILE__"
+ write_file File.join(@tempdir, "lib", "rubygems_plugin.rb") do |io|
+ io.write "# do nothing"
end
@spec.files += %w[lib/rubygems_plugin.rb]
- Gem::Installer.at(Gem::Package.build(@spec), :force => true).install
+ Gem::Installer.at(Gem::Package.build(@spec), force: true).install
- plugin_path = File.join Gem.plugindir, 'a_plugin.rb'
- assert File.exist?(plugin_path), 'plugin not written'
+ plugin_path = File.join Gem.plugindir, "a_plugin.rb"
+ assert File.exist?(plugin_path), "plugin not written"
Gem::Uninstaller.new(nil).remove_plugins @spec
- refute File.exist?(plugin_path), 'plugin not removed'
+ refute File.exist?(plugin_path), "plugin not removed"
end
- def test_remove_plugins_with_install_dir
- write_file File.join(@tempdir, 'lib', 'rubygems_plugin.rb') do |io|
- io.write "puts __FILE__"
+ def test_uninstall_with_install_dir_removes_plugins
+ write_file File.join(@tempdir, "lib", "rubygems_plugin.rb") do |io|
+ io.write "# do nothing"
end
@spec.files += %w[lib/rubygems_plugin.rb]
- Gem::Installer.at(Gem::Package.build(@spec), :force => true).install
+ package = Gem::Package.build(@spec)
- plugin_path = File.join Gem.plugindir, 'a_plugin.rb'
- assert File.exist?(plugin_path), 'plugin not written'
+ Gem::Installer.at(package, force: true).install
- Dir.mkdir "#{@gemhome}2"
- Gem::Uninstaller.new(nil, :install_dir => "#{@gemhome}2").remove_plugins @spec
+ plugin_path = File.join Gem.plugindir, "a_plugin.rb"
+ assert File.exist?(plugin_path), "plugin not written"
+
+ install_dir = "#{@gemhome}2"
+
+ Gem::Installer.at(package, force: true, install_dir: install_dir).install
- assert File.exist?(plugin_path), 'plugin unintentionally removed'
+ install_dir_plugin_path = File.join install_dir, "plugins/a_plugin.rb"
+ assert File.exist?(install_dir_plugin_path), "plugin not written"
+
+ Gem::Specification.dirs = [install_dir]
+ Gem::Uninstaller.new(@spec.name, executables: true, install_dir: install_dir).uninstall
+
+ assert File.exist?(plugin_path), "plugin unintentionally removed"
+ refute File.exist?(install_dir_plugin_path), "plugin not removed"
+ end
+
+ def test_uninstall_with_install_dir_regenerates_plugins
+ write_file File.join(@tempdir, "lib", "rubygems_plugin.rb") do |io|
+ io.write "# do nothing"
+ end
+
+ @spec.files += %w[lib/rubygems_plugin.rb]
+
+ install_dir = "#{@gemhome}2"
+
+ package = Gem::Package.build(@spec)
+
+ spec_v9 = @spec.dup
+ spec_v9.version = "9"
+ package_v9 = Gem::Package.build(spec_v9)
+
+ Gem::Installer.at(package, force: true, install_dir: install_dir).install
+ Gem::Installer.at(package_v9, force: true, install_dir: install_dir).install
+
+ install_dir_plugin_path = File.join install_dir, "plugins/a_plugin.rb"
+ assert File.exist?(install_dir_plugin_path), "plugin not written"
+
+ Gem::Specification.dirs = [install_dir]
+ Gem::Uninstaller.new(@spec.name, version: "9", executables: true, install_dir: install_dir).uninstall
+ assert File.exist?(install_dir_plugin_path), "plugin unintentionally removed"
+
+ Gem::Specification.dirs = [install_dir]
+ Gem::Uninstaller.new(@spec.name, executables: true, install_dir: install_dir).uninstall
+ refute File.exist?(install_dir_plugin_path), "plugin not removed"
+ end
+
+ def test_remove_plugins_user_installed
+ write_file File.join(@tempdir, "lib", "rubygems_plugin.rb") do |io|
+ io.write "# do nothing"
+ end
+
+ @spec.files += %w[lib/rubygems_plugin.rb]
+
+ Gem::Installer.at(Gem::Package.build(@spec), force: true, user_install: true).install
+
+ plugin_path = File.join Gem.user_dir, "plugins/a_plugin.rb"
+ assert File.exist?(plugin_path), "plugin not written"
+
+ Gem::Specification.dirs = [Gem.dir, Gem.user_dir]
+
+ Gem::Uninstaller.new(@spec.name, executables: true, force: true, user_install: true).uninstall
+
+ refute File.exist?(plugin_path), "plugin not removed"
end
def test_regenerate_plugins_for
- write_file File.join(@tempdir, 'lib', 'rubygems_plugin.rb') do |io|
- io.write "puts __FILE__"
+ write_file File.join(@tempdir, "lib", "rubygems_plugin.rb") do |io|
+ io.write "# do nothing"
end
@spec.files += %w[lib/rubygems_plugin.rb]
- Gem::Installer.at(Gem::Package.build(@spec), :force => true).install
+ Gem::Installer.at(Gem::Package.build(@spec), force: true).install
- plugin_path = File.join Gem.plugindir, 'a_plugin.rb'
- assert File.exist?(plugin_path), 'plugin not written'
+ plugin_path = File.join Gem.plugindir, "a_plugin.rb"
+ assert File.exist?(plugin_path), "plugin not written"
FileUtils.rm plugin_path
Gem::Uninstaller.new(nil).regenerate_plugins_for @spec, Gem.plugindir
- assert File.exist?(plugin_path), 'plugin not regenerated'
+ assert File.exist?(plugin_path), "plugin not regenerated"
end
def test_path_ok_eh
@@ -234,7 +292,7 @@ class TestGemUninstaller < Gem::InstallerTestCase
@spec.loaded_from = @spec.loaded_from.gsub @spec.full_name, '\&-legacy'
@spec.internal_init # blow out cache. but why did ^^ depend on cache?
- @spec.platform = 'legacy'
+ @spec.platform = "legacy"
assert_equal true, uninstaller.path_ok?(@gemhome, @spec)
end
@@ -246,18 +304,18 @@ class TestGemUninstaller < Gem::InstallerTestCase
end
def test_uninstall
- uninstaller = Gem::Uninstaller.new @spec.name, :executables => true
+ uninstaller = Gem::Uninstaller.new @spec.name, executables: true
- gem_dir = File.join @gemhome, 'gems', @spec.full_name
+ gem_dir = File.join @gemhome, "gems", @spec.full_name
Gem.pre_uninstall do
- sleep(0.1) if win_platform?
- assert File.exist?(gem_dir), 'gem_dir should exist'
+ sleep(0.1) if Gem.win_platform?
+ assert File.exist?(gem_dir), "gem_dir should exist"
end
Gem.post_uninstall do
- sleep(0.1) if win_platform?
- refute File.exist?(gem_dir), 'gem_dir should not exist'
+ sleep(0.1) if Gem.win_platform?
+ refute File.exist?(gem_dir), "gem_dir should not exist"
end
uninstaller.uninstall
@@ -269,11 +327,11 @@ class TestGemUninstaller < Gem::InstallerTestCase
end
def test_uninstall_default_gem
- spec = new_default_spec 'default', '2'
+ spec = new_default_spec "default", "2"
install_default_gems spec
- uninstaller = Gem::Uninstaller.new spec.name, :executables => true
+ uninstaller = Gem::Uninstaller.new spec.name, executables: true
use_ui @ui do
uninstaller.uninstall
@@ -281,19 +339,19 @@ class TestGemUninstaller < Gem::InstallerTestCase
lines = @ui.output.split("\n")
- assert_equal 'Gem default-2 cannot be uninstalled because it is a default gem', lines.shift
+ assert_equal "Gem default-2 cannot be uninstalled because it is a default gem", lines.shift
end
def test_uninstall_default_gem_with_same_version
- default_spec = new_default_spec 'default', '2'
+ default_spec = new_default_spec "default", "2"
install_default_gems default_spec
- spec = util_spec 'default', '2'
+ spec = util_spec "default", "2"
install_gem spec
Gem::Specification.reset
- uninstaller = Gem::Uninstaller.new spec.name, :executables => true
+ uninstaller = Gem::Uninstaller.new spec.name, executables: true
ui = Gem::MockGemUi.new "1\ny\n"
use_ui ui do
@@ -308,8 +366,8 @@ class TestGemUninstaller < Gem::InstallerTestCase
end
def test_uninstall_extension
- @spec.extensions << 'extconf.rb'
- write_file File.join(@tempdir, 'extconf.rb') do |io|
+ @spec.extensions << "extconf.rb"
+ write_file File.join(@tempdir, "extconf.rb") do |io|
io.write <<-RUBY
require 'mkmf'
create_makefile '#{@spec.name}'
@@ -321,20 +379,20 @@ create_makefile '#{@spec.name}'
use_ui @ui do
path = Gem::Package.build @spec
- installer = Gem::Installer.at path, :force => true
+ installer = Gem::Installer.at path, force: true
installer.install
end
- assert_path_exist @spec.extension_dir, 'sanity check'
+ assert_path_exist @spec.extension_dir, "sanity check"
- uninstaller = Gem::Uninstaller.new @spec.name, :executables => true
+ uninstaller = Gem::Uninstaller.new @spec.name, executables: true
uninstaller.uninstall
assert_path_not_exist @spec.extension_dir
end
def test_uninstall_nonexistent
- uninstaller = Gem::Uninstaller.new 'bogus', :executables => true
+ uninstaller = Gem::Uninstaller.new "bogus", executables: true
e = assert_raise Gem::InstallError do
uninstaller.uninstall
@@ -344,17 +402,17 @@ create_makefile '#{@spec.name}'
end
def test_uninstall_not_ok
- quick_gem 'z' do |s|
- s.add_runtime_dependency @spec.name
+ quick_gem "z" do |s|
+ s.add_dependency @spec.name
end
uninstaller = Gem::Uninstaller.new @spec.name
- gem_dir = File.join @gemhome, 'gems', @spec.full_name
- executable = File.join @gemhome, 'bin', 'executable'
+ gem_dir = File.join @gemhome, "gems", @spec.full_name
+ executable = File.join @gemhome, "bin", "executable"
- assert File.exist?(gem_dir), 'gem_dir must exist'
- assert File.exist?(executable), 'executable must exist'
+ assert File.exist?(gem_dir), "gem_dir must exist"
+ assert File.exist?(executable), "executable must exist"
ui = Gem::MockGemUi.new "n\n"
@@ -364,16 +422,16 @@ create_makefile '#{@spec.name}'
end
end
- assert File.exist?(gem_dir), 'gem_dir must still exist'
- assert File.exist?(executable), 'executable must still exist'
+ assert File.exist?(gem_dir), "gem_dir must still exist"
+ assert File.exist?(executable), "executable must still exist"
end
def test_uninstall_user_install
- @user_spec = Gem::Specification.find_by_name 'b'
+ Gem::Specification.dirs = [Gem.user_dir]
uninstaller = Gem::Uninstaller.new(@user_spec.name,
- :executables => true,
- :user_install => true)
+ executables: true,
+ user_install: true)
gem_dir = File.join @user_spec.gem_dir
@@ -393,11 +451,37 @@ create_makefile '#{@spec.name}'
assert_same uninstaller, @post_uninstall_hook_arg
end
+ def test_uninstall_user_install_with_symlinked_home
+ pend "Symlinks not supported or not enabled" unless symlink_supported?
+
+ Gem::Specification.dirs = [Gem.user_dir]
+
+ symlinked_home = File.join(@tempdir, "new-home")
+ FileUtils.ln_s(Gem.user_home, symlinked_home)
+
+ ENV["HOME"] = symlinked_home
+ Gem.instance_variable_set(:@user_home, nil)
+ Gem.instance_variable_set(:@data_home, nil)
+
+ uninstaller = Gem::Uninstaller.new(@user_spec.name,
+ executables: true,
+ user_install: true,
+ force: true)
+
+ gem_dir = File.join @user_spec.gem_dir
+
+ assert_path_exist gem_dir
+
+ uninstaller.uninstall
+
+ assert_path_not_exist gem_dir
+ end
+
def test_uninstall_wrong_repo
Dir.mkdir "#{@gemhome}2"
Gem.use_paths "#{@gemhome}2", [@gemhome]
- uninstaller = Gem::Uninstaller.new @spec.name, :executables => true
+ uninstaller = Gem::Uninstaller.new @spec.name, executables: true
e = assert_raise Gem::InstallError do
uninstaller.uninstall
@@ -414,9 +498,9 @@ create_makefile '#{@spec.name}'
def test_uninstall_selection
util_make_gems
- list = Gem::Specification.find_all_by_name 'a'
+ list = Gem::Specification.find_all_by_name "a"
- uninstaller = Gem::Uninstaller.new 'a'
+ uninstaller = Gem::Uninstaller.new "a"
ui = Gem::MockGemUi.new "1\ny\n"
@@ -424,39 +508,39 @@ create_makefile '#{@spec.name}'
uninstaller.uninstall
end
- updated_list = Gem::Specification.find_all_by_name('a')
+ updated_list = Gem::Specification.find_all_by_name("a")
assert_equal list.length - 1, updated_list.length
- assert_match ' 1. a-1', ui.output
- assert_match ' 2. a-2', ui.output
- assert_match ' 3. a-3.a', ui.output
- assert_match ' 4. All versions', ui.output
- assert_match 'uninstalled a-1', ui.output
+ assert_match " 1. a-1", ui.output
+ assert_match " 2. a-2", ui.output
+ assert_match " 3. a-3.a", ui.output
+ assert_match " 4. All versions", ui.output
+ assert_match "uninstalled a-1", ui.output
end
def test_uninstall_selection_greater_than_one
util_make_gems
- list = Gem::Specification.find_all_by_name('a')
+ list = Gem::Specification.find_all_by_name("a")
- uninstaller = Gem::Uninstaller.new('a')
+ uninstaller = Gem::Uninstaller.new("a")
use_ui Gem::MockGemUi.new("2\ny\n") do
uninstaller.uninstall
end
- updated_list = Gem::Specification.find_all_by_name('a')
+ updated_list = Gem::Specification.find_all_by_name("a")
assert_equal list.length - 1, updated_list.length
end
def test_uninstall_prompts_about_broken_deps
- quick_gem 'r', '1' do |s|
- s.add_dependency 'q', '= 1'
+ quick_gem "r", "1" do |s|
+ s.add_dependency "q", "= 1"
end
- quick_gem 'q', '1'
+ quick_gem "q", "1"
- un = Gem::Uninstaller.new('q')
+ un = Gem::Uninstaller.new("q")
ui = Gem::MockGemUi.new("y\n")
use_ui ui do
@@ -466,27 +550,27 @@ create_makefile '#{@spec.name}'
lines = ui.output.split("\n")
lines.shift
- assert_match %r{You have requested to uninstall the gem:}, lines.shift
+ assert_match(/You have requested to uninstall the gem:/, lines.shift)
lines.shift
lines.shift
- assert_match %r{r-1 depends on q \(= 1\)}, lines.shift
- assert_match %r{Successfully uninstalled q-1}, lines.last
+ assert_match(/r-1 depends on q \(= 1\)/, lines.shift)
+ assert_match(/Successfully uninstalled q-1/, lines.last)
end
def test_uninstall_only_lists_unsatisfied_deps
- quick_gem 'r', '1' do |s|
- s.add_dependency 'q', '~> 1.0'
+ quick_gem "r", "1" do |s|
+ s.add_dependency "q", "~> 1.0"
end
- quick_gem 'x', '1' do |s|
- s.add_dependency 'q', '= 1.0'
+ quick_gem "x", "1" do |s|
+ s.add_dependency "q", "= 1.0"
end
- quick_gem 'q', '1.0'
- quick_gem 'q', '1.1'
+ quick_gem "q", "1.0"
+ quick_gem "q", "1.1"
- un = Gem::Uninstaller.new('q', :version => "1.0")
+ un = Gem::Uninstaller.new("q", version: "1.0")
ui = Gem::MockGemUi.new("y\n")
use_ui ui do
@@ -496,23 +580,23 @@ create_makefile '#{@spec.name}'
lines = ui.output.split("\n")
lines.shift
- assert_match %r{You have requested to uninstall the gem:}, lines.shift
+ assert_match(/You have requested to uninstall the gem:/, lines.shift)
lines.shift
lines.shift
- assert_match %r{x-1 depends on q \(= 1.0\)}, lines.shift
- assert_match %r{Successfully uninstalled q-1.0}, lines.last
+ assert_match(/x-1 depends on q \(= 1.0\)/, lines.shift)
+ assert_match(/Successfully uninstalled q-1.0/, lines.last)
end
def test_uninstall_doesnt_prompt_when_other_gem_satisfies_requirement
- quick_gem 'r', '1' do |s|
- s.add_dependency 'q', '~> 1.0'
+ quick_gem "r", "1" do |s|
+ s.add_dependency "q", "~> 1.0"
end
- quick_gem 'q', '1.0'
- quick_gem 'q', '1.1'
+ quick_gem "q", "1.0"
+ quick_gem "q", "1.1"
- un = Gem::Uninstaller.new('q', :version => "1.0")
+ un = Gem::Uninstaller.new("q", version: "1.0")
ui = Gem::MockGemUi.new("y\n")
use_ui ui do
@@ -525,13 +609,13 @@ create_makefile '#{@spec.name}'
end
def test_uninstall_doesnt_prompt_when_removing_a_dev_dep
- quick_gem 'r', '1' do |s|
- s.add_development_dependency 'q', '= 1.0'
+ quick_gem "r", "1" do |s|
+ s.add_development_dependency "q", "= 1.0"
end
- quick_gem 'q', '1.0'
+ quick_gem "q", "1.0"
- un = Gem::Uninstaller.new('q', :version => "1.0")
+ un = Gem::Uninstaller.new("q", version: "1.0")
ui = Gem::MockGemUi.new("y\n")
use_ui ui do
@@ -544,13 +628,13 @@ create_makefile '#{@spec.name}'
end
def test_uninstall_doesnt_prompt_and_raises_when_abort_on_dependent_set
- quick_gem 'r', '1' do |s|
- s.add_dependency 'q', '= 1'
+ quick_gem "r", "1" do |s|
+ s.add_dependency "q", "= 1"
end
- quick_gem 'q', '1'
+ quick_gem "q", "1"
- un = Gem::Uninstaller.new('q', :abort_on_dependent => true)
+ un = Gem::Uninstaller.new("q", abort_on_dependent: true)
ui = Gem::MockGemUi.new("y\n")
assert_raise Gem::DependencyRemovalException do
@@ -561,13 +645,13 @@ create_makefile '#{@spec.name}'
end
def test_uninstall_prompt_includes_dep_type
- quick_gem 'r', '1' do |s|
- s.add_development_dependency 'q', '= 1'
+ quick_gem "r", "1" do |s|
+ s.add_development_dependency "q", "= 1"
end
- quick_gem 'q', '1'
+ quick_gem "q", "1"
- un = Gem::Uninstaller.new('q', :check_dev => true)
+ un = Gem::Uninstaller.new("q", check_dev: true)
ui = Gem::MockGemUi.new("y\n")
use_ui ui do
@@ -577,26 +661,26 @@ create_makefile '#{@spec.name}'
lines = ui.output.split("\n")
lines.shift
- assert_match %r{You have requested to uninstall the gem:}, lines.shift
+ assert_match(/You have requested to uninstall the gem:/, lines.shift)
lines.shift
lines.shift
- assert_match %r{r-1 depends on q \(= 1, development\)}, lines.shift
- assert_match %r{Successfully uninstalled q-1}, lines.last
+ assert_match(/r-1 depends on q \(= 1, development\)/, lines.shift)
+ assert_match(/Successfully uninstalled q-1/, lines.last)
end
def test_uninstall_prompt_only_lists_the_dependents_that_prevented_uninstallation
- quick_gem 'r', '1' do |s|
- s.add_development_dependency 'q', '= 1'
+ quick_gem "r", "1" do |s|
+ s.add_development_dependency "q", "= 1"
end
- quick_gem 's', '1' do |s|
- s.add_dependency 'q', '= 1'
+ quick_gem "s", "1" do |s|
+ s.add_dependency "q", "= 1"
end
- quick_gem 'q', '1'
+ quick_gem "q", "1"
- un = Gem::Uninstaller.new('q', :check_dev => false)
+ un = Gem::Uninstaller.new("q", check_dev: false)
ui = Gem::MockGemUi.new("y\n")
use_ui ui do
@@ -606,16 +690,16 @@ create_makefile '#{@spec.name}'
lines = ui.output.split("\n")
lines.shift
- assert_match %r{You have requested to uninstall the gem:}, lines.shift
+ assert_match(/You have requested to uninstall the gem:/, lines.shift)
lines.shift
lines.shift
- assert_match %r{s-1 depends on q \(= 1\)}, lines.shift
- assert_match %r{Successfully uninstalled q-1}, lines.last
+ assert_match(/s-1 depends on q \(= 1\)/, lines.shift)
+ assert_match(/Successfully uninstalled q-1/, lines.last)
end
def test_uninstall_no_permission
- uninstaller = Gem::Uninstaller.new @spec.name, :executables => true
+ uninstaller = Gem::Uninstaller.new @spec.name, executables: true
stub_rm_r = lambda do |*args|
_path = args.shift
@@ -633,42 +717,42 @@ create_makefile '#{@spec.name}'
end
def test_uninstall_keeps_plugins_up_to_date
- write_file File.join(@tempdir, 'lib', 'rubygems_plugin.rb') do |io|
- io.write "puts __FILE__"
+ write_file File.join(@tempdir, "lib", "rubygems_plugin.rb") do |io|
+ io.write "# do nothing"
end
- plugin_path = File.join Gem.plugindir, 'a_plugin.rb'
+ plugin_path = File.join Gem.plugindir, "a_plugin.rb"
- @spec.version = '1'
- Gem::Installer.at(Gem::Package.build(@spec), :force => true).install
+ @spec.version = "1"
+ Gem::Installer.at(Gem::Package.build(@spec), force: true).install
- refute File.exist?(plugin_path), 'version without plugin installed, but plugin written'
+ refute File.exist?(plugin_path), "version without plugin installed, but plugin written"
@spec.files += %w[lib/rubygems_plugin.rb]
- @spec.version = '2'
- Gem::Installer.at(Gem::Package.build(@spec), :force => true).install
+ @spec.version = "2"
+ Gem::Installer.at(Gem::Package.build(@spec), force: true).install
- assert File.exist?(plugin_path), 'version with plugin installed, but plugin not written'
- assert_match %r{\Arequire.*a-2/lib/rubygems_plugin\.rb}, File.read(plugin_path), 'written plugin has incorrect content'
+ assert File.exist?(plugin_path), "version with plugin installed, but plugin not written"
+ assert_match %r{\Arequire.*a-2/lib/rubygems_plugin\.rb}, File.read(plugin_path), "written plugin has incorrect content"
- @spec.version = '3'
- Gem::Installer.at(Gem::Package.build(@spec), :force => true).install
+ @spec.version = "3"
+ Gem::Installer.at(Gem::Package.build(@spec), force: true).install
- assert File.exist?(plugin_path), 'version with plugin installed, but plugin removed'
- assert_match %r{\Arequire.*a-3/lib/rubygems_plugin\.rb}, File.read(plugin_path), 'old version installed, but plugin updated'
+ assert File.exist?(plugin_path), "version with plugin installed, but plugin removed"
+ assert_match %r{\Arequire.*a-3/lib/rubygems_plugin\.rb}, File.read(plugin_path), "old version installed, but plugin updated"
- Gem::Uninstaller.new('a', :version => '1', :executables => true).uninstall
+ Gem::Uninstaller.new("a", version: "1", executables: true).uninstall
- assert File.exist?(plugin_path), 'plugin removed when old version uninstalled'
- assert_match %r{\Arequire.*a-3/lib/rubygems_plugin\.rb}, File.read(plugin_path), 'old version uninstalled, but plugin updated'
+ assert File.exist?(plugin_path), "plugin removed when old version uninstalled"
+ assert_match %r{\Arequire.*a-3/lib/rubygems_plugin\.rb}, File.read(plugin_path), "old version uninstalled, but plugin updated"
- Gem::Uninstaller.new('a', version: '3', :executables => true).uninstall
+ Gem::Uninstaller.new("a", version: "3", executables: true).uninstall
- assert File.exist?(plugin_path), 'plugin removed when old version uninstalled and another version with plugin still present'
- assert_match %r{\Arequire.*a-2/lib/rubygems_plugin\.rb}, File.read(plugin_path), 'latest version uninstalled, but plugin not updated to previous version'
+ assert File.exist?(plugin_path), "plugin removed when old version uninstalled and another version with plugin still present"
+ assert_match %r{\Arequire.*a-2/lib/rubygems_plugin\.rb}, File.read(plugin_path), "latest version uninstalled, but plugin not updated to previous version"
- Gem::Uninstaller.new('a', version: '2', :executables => true).uninstall
+ Gem::Uninstaller.new("a", version: "2", executables: true).uninstall
- refute File.exist?(plugin_path), 'last version uninstalled, but plugin still present'
+ refute File.exist?(plugin_path), "last version uninstalled, but plugin still present"
end
end
diff --git a/test/rubygems/test_gem_unsatisfiable_dependency_error.rb b/test/rubygems/test_gem_unsatisfiable_dependency_error.rb
index f9d30123f0..5202010dac 100644
--- a/test/rubygems/test_gem_unsatisfiable_dependency_error.rb
+++ b/test/rubygems/test_gem_unsatisfiable_dependency_error.rb
@@ -1,11 +1,12 @@
# frozen_string_literal: true
-require_relative 'helper'
+
+require_relative "helper"
class TestGemUnsatisfiableDependencyError < Gem::TestCase
def setup
super
- @a_dep = dep 'a', '~> 1'
+ @a_dep = dep "a", "~> 1"
@req = Gem::Resolver::DependencyRequest.new @a_dep, nil
@@ -21,7 +22,7 @@ class TestGemUnsatisfiableDependencyError < Gem::TestCase
end
def test_name
- assert_equal 'a', @e.name
+ assert_equal "a", @e.name
end
def test_version
diff --git a/test/rubygems/test_gem_update_suggestion.rb b/test/rubygems/test_gem_update_suggestion.rb
new file mode 100644
index 0000000000..8cb8ee57ff
--- /dev/null
+++ b/test/rubygems/test_gem_update_suggestion.rb
@@ -0,0 +1,209 @@
+# frozen_string_literal: true
+
+require_relative "helper"
+require "rubygems/command"
+require "rubygems/update_suggestion"
+
+class TestUpdateSuggestion < Gem::TestCase
+ def setup
+ super
+
+ @cmd = Gem::Command.new "dummy", "dummy"
+ @cmd.extend Gem::UpdateSuggestion
+ @start_time = 1_000_000
+ @minute = 60 * 60
+ @week = 7 * 24 * @minute
+ end
+
+ def with_eligible_environment(**params)
+ self.class.with_eligible_environment(**params) do
+ yield
+ end
+ end
+
+ def self.with_eligible_environment(
+ tty: true,
+ rubygems_version: Gem::Version.new("1.2.3"),
+ latest_rubygems_version: Gem::Version.new("2.0.0"),
+ ci: false,
+ reset_last_update_check: true,
+ cmd:
+ )
+ original_config = Gem.configuration[:prevent_update_suggestion]
+ Gem.configuration[:prevent_update_suggestion] = nil
+ original_env = ENV["RUBYGEMS_PREVENT_UPDATE_SUGGESTION"]
+ ENV["RUBYGEMS_PREVENT_UPDATE_SUGGESTION"] = nil
+ original_disable = Gem.disable_system_update_message
+ Gem.disable_system_update_message = nil
+ Gem.configuration.last_update_check = 0 if reset_last_update_check
+
+ Gem.ui.stub :tty?, tty do
+ Gem.stub :rubygems_version, rubygems_version do
+ Gem.stub :latest_rubygems_version, latest_rubygems_version do
+ Gem::CIDetector.stub :ci?, ci do
+ yield
+ end
+ end
+ end
+ end
+ ensure
+ Gem.configuration[:prevent_update_suggestion] = original_config
+ ENV["RUBYGEMS_PREVENT_UPDATE_SUGGESTION"] = original_env
+ Gem.disable_system_update_message = original_disable
+ end
+
+ def test_update_suggestion
+ Gem.stub :rubygems_version, Gem::Version.new("1.2.3") do
+ Gem.stub :latest_rubygems_version, Gem::Version.new("2.0.0") do
+ assert_equal @cmd.update_suggestion, <<~SUGGESTION
+
+ A new release of RubyGems is available: 1.2.3 → 2.0.0!
+ Run `gem update --system 2.0.0` to update your installation.
+
+ SUGGESTION
+ end
+ end
+ end
+
+ def test_eligible_for_update
+ with_eligible_environment(cmd: @cmd) do
+ Time.stub :now, 123_456_789 do
+ assert_predicate @cmd, :eligible_for_update?
+ assert_equal 123_456_789, Gem.configuration.last_update_check
+
+ # test last check is written to config file
+ assert_include File.read(Gem.configuration.state_file_name), "123456789"
+ end
+ end
+ end
+
+ def test_eligible_for_update_is_not_annoying_when_new_version_is_released
+ current_version = Gem::Version.new("1.2.0")
+ latest_version = current_version
+
+ # checking for first time, it is not eligible since new version
+ # is not released yet and stored
+ with_eligible_environment(cmd: @cmd, rubygems_version: current_version, latest_rubygems_version: latest_version) do
+ Time.stub :now, @start_time do
+ refute_predicate @cmd, :eligible_for_update?
+ assert_equal @start_time, Gem.configuration.last_update_check
+ end
+ end
+
+ # checking next week, it is not eligible since new version
+ # is not released yet and timestamp is stored
+ with_eligible_environment(
+ cmd: @cmd,
+ rubygems_version: current_version,
+ latest_rubygems_version: latest_version,
+ reset_last_update_check: false
+ ) do
+ Time.stub :now, @start_time + @week do
+ refute_predicate @cmd, :eligible_for_update?
+ assert_equal @start_time + @week, Gem.configuration.last_update_check
+ end
+ end
+
+ # pretend new version is released
+ latest_version = Gem::Version.new("1.3.0")
+
+ # checking later same next week, it is not eligible even new version
+ # is released and timestamp is not stored
+ with_eligible_environment(
+ cmd: @cmd,
+ rubygems_version: current_version,
+ latest_rubygems_version: latest_version,
+ reset_last_update_check: false
+ ) do
+ Time.stub :now, @start_time + @week + @minute do
+ refute_predicate @cmd, :eligible_for_update?
+ assert_equal @start_time + @week, Gem.configuration.last_update_check
+ end
+ end
+ end
+
+ def test_eligible_for_update_is_not_annoying_when_not_upgraded
+ with_eligible_environment(cmd: @cmd) do
+ # checking for first time, it is eligible and stored
+ Time.stub :now, @start_time do
+ assert_predicate @cmd, :eligible_for_update?
+ assert_equal @start_time, Gem.configuration.last_update_check
+ end
+
+ # checking minute later is not eligible and not stored
+ Time.stub :now, @start_time + @minute do
+ refute_predicate @cmd, :eligible_for_update?
+ assert_equal @start_time, Gem.configuration.last_update_check
+ end
+
+ # checking week later is eligible again and stored
+ Time.stub :now, @start_time + @week do
+ assert_predicate @cmd, :eligible_for_update?
+ assert_equal @start_time + @week, Gem.configuration.last_update_check
+ end
+ end
+ end
+
+ def test_eligible_for_update_prevent_config
+ with_eligible_environment(cmd: @cmd) do
+ original_config = Gem.configuration[:prevent_update_suggestion]
+ Gem.configuration[:prevent_update_suggestion] = true
+ refute_predicate @cmd, :eligible_for_update?
+ ensure
+ Gem.configuration[:prevent_update_suggestion] = original_config
+ end
+ end
+
+ def test_eligible_for_update_prevent_env
+ with_eligible_environment(cmd: @cmd) do
+ original_env = ENV["RUBYGEMS_PREVENT_UPDATE_SUGGESTION"]
+ ENV["RUBYGEMS_PREVENT_UPDATE_SUGGESTION"] = "yes"
+ refute_predicate @cmd, :eligible_for_update?
+ ensure
+ ENV["RUBYGEMS_PREVENT_UPDATE_SUGGESTION"] = original_env
+ end
+ end
+
+ def test_eligible_for_update_non_tty
+ with_eligible_environment(tty: false, cmd: @cmd) do
+ refute_predicate @cmd, :eligible_for_update?
+ end
+ end
+
+ def test_eligible_for_update_for_prerelease
+ with_eligible_environment(rubygems_version: Gem::Version.new("1.0.0-rc1"), cmd: @cmd) do
+ refute_predicate @cmd, :eligible_for_update?
+ end
+ end
+
+ def test_eligible_for_update_disabled_update
+ with_eligible_environment(cmd: @cmd) do
+ original_disable = Gem.disable_system_update_message
+ Gem.disable_system_update_message = "disabled"
+ refute_predicate @cmd, :eligible_for_update?
+ ensure
+ Gem.disable_system_update_message = original_disable
+ end
+ end
+
+ def test_eligible_for_update_on_ci
+ with_eligible_environment(ci: true, cmd: @cmd) do
+ refute_predicate @cmd, :eligible_for_update?
+ end
+ end
+
+ def test_eligible_for_update_unwrittable_config
+ with_eligible_environment(cmd: @cmd) do
+ Gem.configuration.stub :state_file_writable?, false do
+ refute_predicate @cmd, :eligible_for_update?
+ end
+ end
+ end
+
+ def test_eligible_for_update_notification_delay
+ with_eligible_environment(cmd: @cmd) do
+ Gem.configuration.last_update_check = Time.now.to_i
+ refute_predicate @cmd, :eligible_for_update?
+ end
+ end
+end
diff --git a/test/rubygems/test_gem_uri.rb b/test/rubygems/test_gem_uri.rb
index 7fe572518b..1253ebc6de 100644
--- a/test/rubygems/test_gem_uri.rb
+++ b/test/rubygems/test_gem_uri.rb
@@ -1,5 +1,7 @@
-require_relative 'helper'
-require 'rubygems/uri'
+# frozen_string_literal: true
+
+require_relative "helper"
+require "rubygems/uri"
class TestUri < Gem::TestCase
def test_to_s_not_string
@@ -31,9 +33,9 @@ class TestUri < Gem::TestCase
end
def test_redacted_does_not_modify_uri
- url = 'https://user:password@example.com'
+ url = "https://user:password@example.com"
uri = Gem::Uri.new(url)
- assert_equal 'https://user:REDACTED@example.com', uri.redacted.to_s
+ assert_equal "https://user:REDACTED@example.com", uri.redacted.to_s
assert_equal url, uri.to_s
end
end
diff --git a/test/rubygems/test_gem_uri_formatter.rb b/test/rubygems/test_gem_uri_formatter.rb
index a41c9238ad..5ab4730d62 100644
--- a/test/rubygems/test_gem_uri_formatter.rb
+++ b/test/rubygems/test_gem_uri_formatter.rb
@@ -1,26 +1,27 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/uri_formatter'
+
+require_relative "helper"
+require "rubygems/uri_formatter"
class TestGemUriFormatter < Gem::TestCase
def test_normalize_uri
- assert_equal 'FILE://example/',
- Gem::UriFormatter.new('FILE://example/').normalize
- assert_equal 'FTP://example/',
- Gem::UriFormatter.new('FTP://example/').normalize
- assert_equal 'HTTP://example/',
- Gem::UriFormatter.new('HTTP://example/').normalize
- assert_equal 'HTTPS://example/',
- Gem::UriFormatter.new('HTTPS://example/').normalize
- assert_equal 'http://example/',
- Gem::UriFormatter.new('example/').normalize
+ assert_equal "FILE://example/",
+ Gem::UriFormatter.new("FILE://example/").normalize
+ assert_equal "FTP://example/",
+ Gem::UriFormatter.new("FTP://example/").normalize
+ assert_equal "HTTP://example/",
+ Gem::UriFormatter.new("HTTP://example/").normalize
+ assert_equal "HTTPS://example/",
+ Gem::UriFormatter.new("HTTPS://example/").normalize
+ assert_equal "http://example/",
+ Gem::UriFormatter.new("example/").normalize
end
def test_escape
- assert_equal 'a%40b%5Cc', Gem::UriFormatter.new('a@b\c').escape
+ assert_equal "a%40b%5Cc", Gem::UriFormatter.new('a@b\c').escape
end
def test_unescape
- assert_equal 'a@b\c', Gem::UriFormatter.new('a%40b%5Cc').unescape
+ assert_equal 'a@b\c', Gem::UriFormatter.new("a%40b%5Cc").unescape
end
end
diff --git a/test/rubygems/test_gem_util.rb b/test/rubygems/test_gem_util.rb
index e0db5c283d..608210a903 100644
--- a/test/rubygems/test_gem_util.rb
+++ b/test/rubygems/test_gem_util.rb
@@ -1,11 +1,12 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/util'
+
+require_relative "helper"
+require "rubygems/util"
class TestGemUtil < Gem::TestCase
def test_class_popen
pend "popen with a block does not behave well on jruby" if Gem.java_platform?
- assert_equal "0\n", Gem::Util.popen(*ruby_with_rubygems_in_load_path, '-e', 'p 0')
+ assert_equal "0\n", Gem::Util.popen(*ruby_with_rubygems_in_load_path, "-e", "p 0")
assert_raise Errno::ECHILD do
Process.wait(-1)
@@ -16,7 +17,7 @@ class TestGemUtil < Gem::TestCase
pend if Gem.java_platform?
Gem::Deprecate.skip_during do
out, err = capture_output do
- Gem::Util.silent_system(*ruby_with_rubygems_in_load_path, '-e', 'puts "hello"; warn "hello"')
+ Gem::Util.silent_system(*ruby_with_rubygems_in_load_path, "-e", 'puts "hello"; warn "hello"')
end
assert_empty out
assert_empty err
@@ -24,59 +25,51 @@ class TestGemUtil < Gem::TestCase
end
def test_traverse_parents
- FileUtils.mkdir_p 'a/b/c'
+ FileUtils.mkdir_p "a/b/c"
- enum = Gem::Util.traverse_parents 'a/b/c'
+ enum = Gem::Util.traverse_parents "a/b/c"
- assert_equal File.join(@tempdir, 'a/b/c'), enum.next
- assert_equal File.join(@tempdir, 'a/b'), enum.next
- assert_equal File.join(@tempdir, 'a'), enum.next
+ assert_equal File.join(@tempdir, "a/b/c"), enum.next
+ assert_equal File.join(@tempdir, "a/b"), enum.next
+ assert_equal File.join(@tempdir, "a"), enum.next
loop { break if enum.next.nil? } # exhaust the enumerator
end
def test_traverse_parents_does_not_crash_on_permissions_error
- pend 'skipped on MS Windows (chmod has no effect)' if win_platform? || java_platform?
+ pend "skipped on MS Windows (chmod has no effect)" if Gem.win_platform? || Gem.java_platform?
- FileUtils.mkdir_p 'd/e/f'
+ FileUtils.mkdir_p "d/e/f"
# remove 'execute' permission from "e" directory and make it
# impossible to cd into it and its children
- FileUtils.chmod(0666, 'd/e')
+ FileUtils.chmod(0o666, "d/e")
- pend 'skipped in root privilege' if Process.uid.zero?
+ pend "skipped in root privilege" if Process.uid.zero?
- paths = Gem::Util.traverse_parents('d/e/f').to_a
+ paths = Gem::Util.traverse_parents("d/e/f").to_a
- assert_equal File.join(@tempdir, 'd'), paths[0]
+ assert_equal File.join(@tempdir, "d"), paths[0]
assert_equal @tempdir, paths[1]
assert_equal File.realpath("..", @tempdir), paths[2]
assert_equal File.realpath("../..", @tempdir), paths[3]
ensure
# restore default permissions, allow the directory to be removed
- FileUtils.chmod(0775, 'd/e') unless win_platform? || java_platform?
- end
-
- def test_linked_list_find
- list = [1,2,3,4,5].inject(Gem::List.new(0)) do |m,o|
- Gem::List.new o, m
- end
- assert_equal 5, list.find {|x| x == 5 }
- assert_equal 4, list.find {|x| x == 4 }
+ FileUtils.chmod(0o775, "d/e") unless Gem.win_platform? || Gem.java_platform?
end
def test_glob_files_in_dir
- FileUtils.mkdir_p 'g'
- FileUtils.touch File.join('g', 'h.rb')
- FileUtils.touch File.join('g', 'i.rb')
+ FileUtils.mkdir_p "g"
+ FileUtils.touch File.join("g", "h.rb")
+ FileUtils.touch File.join("g", "i.rb")
expected_paths = [
- File.join(@tempdir, 'g/h.rb'),
- File.join(@tempdir, 'g/i.rb'),
+ File.join(@tempdir, "g/h.rb"),
+ File.join(@tempdir, "g/i.rb"),
]
- files_with_absolute_base = Gem::Util.glob_files_in_dir('*.rb', File.join(@tempdir, 'g'))
+ files_with_absolute_base = Gem::Util.glob_files_in_dir("*.rb", File.join(@tempdir, "g"))
assert_equal expected_paths.sort, files_with_absolute_base.sort
- files_with_relative_base = Gem::Util.glob_files_in_dir('*.rb', 'g')
+ files_with_relative_base = Gem::Util.glob_files_in_dir("*.rb", "g")
assert_equal expected_paths.sort, files_with_relative_base.sort
end
diff --git a/test/rubygems/test_gem_validator.rb b/test/rubygems/test_gem_validator.rb
index 8090776b4a..80109ab8ba 100644
--- a/test/rubygems/test_gem_validator.rb
+++ b/test/rubygems/test_gem_validator.rb
@@ -11,21 +11,21 @@ class TestGemValidator < Gem::TestCase
end
def test_alien
- @spec = quick_gem 'a' do |s|
+ @spec = quick_gem "a" do |s|
s.files = %w[lib/a.rb lib/b.rb]
end
util_build_gem @spec
- FileUtils.rm File.join(@spec.gem_dir, 'lib/b.rb')
- FileUtils.touch File.join(@spec.gem_dir, 'lib/c.rb')
+ FileUtils.rm File.join(@spec.gem_dir, "lib/b.rb")
+ FileUtils.touch File.join(@spec.gem_dir, "lib/c.rb")
- alien = @validator.alien 'a'
+ alien = @validator.alien "a"
expected = {
@spec.file_name => [
- Gem::Validator::ErrorData.new('lib/b.rb', 'Missing file'),
- Gem::Validator::ErrorData.new('lib/c.rb', 'Extra file'),
+ Gem::Validator::ErrorData.new("lib/b.rb", "Missing file"),
+ Gem::Validator::ErrorData.new("lib/c.rb", "Extra file"),
],
}
@@ -33,9 +33,9 @@ class TestGemValidator < Gem::TestCase
end
def test_alien_default
- new_default_spec 'c', 1, nil, 'lib/c.rb'
+ new_default_spec "c", 1, nil, "lib/c.rb"
- alien = @validator.alien 'c'
+ alien = @validator.alien "c"
assert_empty alien
end
diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb
index 422e1ee86c..cf771bc5a1 100644
--- a/test/rubygems/test_gem_version.rb
+++ b/test/rubygems/test_gem_version.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
-require_relative 'helper'
+
+require_relative "helper"
require "rubygems/version"
class TestGemVersion < Gem::TestCase
@@ -32,12 +33,19 @@ class TestGemVersion < Gem::TestCase
def test_class_create
real = Gem::Version.new(1.0)
- assert_same real, Gem::Version.create(real)
- assert_nil Gem::Version.create(nil)
+ assert_same real, Gem::Version.create(real)
+
+ expected = "nil versions are discouraged and will be deprecated in Rubygems 4\n"
+ actual_stdout, actual_stderr = capture_output do
+ assert_nil Gem::Version.create(nil)
+ end
+ assert_empty actual_stdout
+ assert_equal(expected, actual_stderr)
+
assert_equal v("5.1"), Gem::Version.create("5.1")
- ver = '1.1'.freeze
- assert_equal v('1.1'), Gem::Version.create(ver)
+ ver = "1.1"
+ assert_equal v("1.1"), Gem::Version.create(ver)
end
def test_class_correct
@@ -53,8 +61,8 @@ class TestGemVersion < Gem::TestCase
end
def test_class_new_subclass
- v1 = Gem::Version.new '1'
- v2 = V.new '1'
+ v1 = Gem::Version.new "1"
+ v2 = V.new "1"
refute_same v1, v2
end
@@ -81,7 +89,7 @@ class TestGemVersion < Gem::TestCase
end
def test_initialize
- ["1.0", "1.0 ", " 1.0 ", "1.0\n", "\n1.0\n", "1.0".freeze].each do |good|
+ ["1.0", "1.0 ", " 1.0 ", "1.0\n", "\n1.0\n", "1.0"].each do |good|
assert_version_equal "1.0", good
end
@@ -120,10 +128,10 @@ class TestGemVersion < Gem::TestCase
assert_prerelease "22.1.50.0.d"
assert_prerelease "1.2.d.42"
- assert_prerelease '1.A'
+ assert_prerelease "1.A"
- assert_prerelease '1-1'
- assert_prerelease '1-a'
+ assert_prerelease "1-1"
+ assert_prerelease "1-a"
refute_prerelease "1.2.0"
refute_prerelease "2.9"
@@ -154,6 +162,10 @@ class TestGemVersion < Gem::TestCase
assert_equal(-1, v("5.a") <=> v("5.0.0.rc2"))
assert_equal(1, v("5.x") <=> v("5.0.0.rc2"))
+ assert_equal(0, v("1.9.3") <=> "1.9.3")
+ assert_equal(1, v("1.9.3") <=> "1.9.2.99")
+ assert_equal(-1, v("1.9.3") <=> "1.9.3.1")
+
assert_nil v("1.0") <=> "whatever"
end
@@ -195,7 +207,7 @@ class TestGemVersion < Gem::TestCase
# modifying the segments of a version should not affect the segments of the cached version object
def test_segments
- v('9.8.7').segments[2] += 1
+ v("9.8.7").segments[2] += 1
refute_version_equal "9.8.8", "9.8.7"
assert_equal [9,8,7], v("9.8.7").segments
@@ -208,10 +220,10 @@ class TestGemVersion < Gem::TestCase
end
def test_frozen_version
- v = v('1.freeze.test').freeze
- assert_less_than v, v('1')
- assert_version_equal v('1'), v.release
- assert_version_equal v('2'), v.bump
+ v = v("1.freeze.test").freeze
+ assert_less_than v, v("1")
+ assert_version_equal v("1"), v.release
+ assert_version_equal v("2"), v.bump
end
# Asserts that +version+ is a prerelease.
@@ -257,7 +269,8 @@ class TestGemVersion < Gem::TestCase
# Assert that two versions are eql?. Checks both directions.
def assert_version_eql(first, second)
- first, second = v(first), v(second)
+ first = v(first)
+ second = v(second)
assert first.eql?(second), "#{first} is eql? #{second}"
assert second.eql?(first), "#{second} is eql? #{first}"
end
@@ -278,7 +291,8 @@ class TestGemVersion < Gem::TestCase
# directions.
def refute_version_eql(first, second)
- first, second = v(first), v(second)
+ first = v(first)
+ second = v(second)
refute first.eql?(second), "#{first} is NOT eql? #{second}"
refute second.eql?(first), "#{second} is NOT eql? #{first}"
end
diff --git a/test/rubygems/test_gem_version_option.rb b/test/rubygems/test_gem_version_option.rb
index 74d7979e3a..8b6e14fc42 100644
--- a/test/rubygems/test_gem_version_option.rb
+++ b/test/rubygems/test_gem_version_option.rb
@@ -1,13 +1,14 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems/command'
-require 'rubygems/version_option'
+
+require_relative "helper"
+require "rubygems/command"
+require "rubygems/version_option"
class TestGemVersionOption < Gem::TestCase
def setup
super
- @cmd = Gem::Command.new 'dummy', 'dummy'
+ @cmd = Gem::Command.new "dummy", "dummy"
@cmd.extend Gem::VersionOption
end
@@ -43,8 +44,8 @@ class TestGemVersionOption < Gem::TestCase
expected = [
Gem::Platform::RUBY,
- Gem::Platform.new('x86-freebsd6'),
- Gem::Platform.new('x86-freebsd7'),
+ Gem::Platform.new("x86-freebsd6"),
+ Gem::Platform.new("x86-freebsd7"),
]
assert_equal expected, Gem.platforms
@@ -69,7 +70,7 @@ class TestGemVersionOption < Gem::TestCase
expected = [
Gem::Platform::RUBY,
- Gem::Platform.new('x86-freebsd6'),
+ Gem::Platform.new("x86-freebsd6"),
]
assert_equal expected, Gem.platforms
@@ -81,10 +82,10 @@ class TestGemVersionOption < Gem::TestCase
@cmd.handle_options %w[--version >1]
expected = {
- :args => [],
- :explicit_prerelease => false,
- :prerelease => false,
- :version => Gem::Requirement.new('> 1'),
+ args: [],
+ explicit_prerelease: false,
+ prerelease: false,
+ version: Gem::Requirement.new("> 1"),
}
assert_equal expected, @cmd.options
@@ -93,13 +94,13 @@ class TestGemVersionOption < Gem::TestCase
def test_version_option_compound
@cmd.add_version_option
- @cmd.handle_options ['--version', '< 1, > 0.9']
+ @cmd.handle_options ["--version", "< 1, > 0.9"]
expected = {
- :args => [],
- :explicit_prerelease => false,
- :prerelease => false,
- :version => Gem::Requirement.new('< 1', '> 0.9'),
+ args: [],
+ explicit_prerelease: false,
+ prerelease: false,
+ version: Gem::Requirement.new("< 1", "> 0.9"),
}
assert_equal expected, @cmd.options
@@ -108,13 +109,13 @@ class TestGemVersionOption < Gem::TestCase
def test_multiple_version_operator_option_compound
@cmd.add_version_option
- @cmd.handle_options ['--version', '< 1', '--version', '> 0.9']
+ @cmd.handle_options ["--version", "< 1", "--version", "> 0.9"]
expected = {
- :args => [],
- :explicit_prerelease => false,
- :prerelease => false,
- :version => Gem::Requirement.new('< 1', '> 0.9'),
+ args: [],
+ explicit_prerelease: false,
+ prerelease: false,
+ version: Gem::Requirement.new("< 1", "> 0.9"),
}
assert_equal expected, @cmd.options
@@ -127,10 +128,10 @@ class TestGemVersionOption < Gem::TestCase
@cmd.handle_options %w[--pre --version >1]
expected = {
- :args => [],
- :explicit_prerelease => true,
- :prerelease => true,
- :version => Gem::Requirement.new('> 1'),
+ args: [],
+ explicit_prerelease: true,
+ prerelease: true,
+ version: Gem::Requirement.new("> 1"),
}
assert_equal expected, @cmd.options
@@ -142,10 +143,10 @@ class TestGemVersionOption < Gem::TestCase
@cmd.handle_options %w[--version >1.a]
expected = {
- :args => [],
- :explicit_prerelease => false,
- :prerelease => true,
- :version => Gem::Requirement.new('> 1.a'),
+ args: [],
+ explicit_prerelease: false,
+ prerelease: true,
+ version: Gem::Requirement.new("> 1.a"),
}
assert_equal expected, @cmd.options
@@ -153,10 +154,10 @@ class TestGemVersionOption < Gem::TestCase
@cmd.handle_options %w[--version >1]
expected = {
- :args => [],
- :explicit_prerelease => false,
- :prerelease => false,
- :version => Gem::Requirement.new('> 1'),
+ args: [],
+ explicit_prerelease: false,
+ prerelease: false,
+ version: Gem::Requirement.new("> 1"),
}
assert_equal expected, @cmd.options
diff --git a/test/rubygems/test_kernel.rb b/test/rubygems/test_kernel.rb
index dee36d05ee..d862b26fe9 100644
--- a/test/rubygems/test_kernel.rb
+++ b/test/rubygems/test_kernel.rb
@@ -1,95 +1,98 @@
# frozen_string_literal: true
-require_relative 'helper'
-class TestKernel < Gem::TestCase
+require_relative "helper"
+
+class TestGemKernel < Gem::TestCase
def setup
super
- @old_path = $:.dup
-
util_make_gems
without_any_upwards_gemfiles
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 gem("a", "= 1"), "Should load"
+ assert $:.any? {|p| p.include?("a-1/lib") }
end
def test_gem_default
- assert gem('a', '>= 0')
+ assert gem("a", ">= 0")
- assert_equal @a2, Gem.loaded_specs['a']
+ assert_equal @a2, Gem.loaded_specs["a"]
end
def test_gem_default_re_gem
- assert gem('a', '=1')
+ assert gem("a", "=1")
- refute gem('a', '>= 0')
+ refute gem("a", ">= 0")
- assert_equal @a1, Gem.loaded_specs['a']
+ assert_equal @a1, Gem.loaded_specs["a"]
end
def test_gem_re_gem_mismatch
- assert gem('a', '=1')
+ assert gem("a", "=1")
assert_raise Gem::LoadError do
- gem('a', '= 2')
+ gem("a", "= 2")
end
- assert_equal @a1, Gem.loaded_specs['a']
+ assert_equal @a1, Gem.loaded_specs["a"]
end
def test_gem_redundant
- assert gem('a', '= 1'), "Should load"
- refute gem('a', '= 1'), "Should not load"
- assert_equal 1, $:.select {|p| %r{a-1/lib} =~ p }.size
+ assert gem("a", "= 1"), "Should load"
+ refute gem("a", "= 1"), "Should not load"
+ assert_equal 1, $:.count {|p| p.include?("a-1/lib") }
end
def test_gem_overlapping
- assert gem('a', '= 1'), "Should load"
- refute gem('a', '>= 1'), "Should not load"
- assert_equal 1, $:.select {|p| %r{a-1/lib} =~ p }.size
+ assert gem("a", "= 1"), "Should load"
+ refute gem("a", ">= 1"), "Should not load"
+ assert_equal 1, $:.count {|p| p.include?("a-1/lib") }
end
- def test_gem_prerelease
- quick_gem 'd', '1.1.a'
- refute gem('d', '>= 1'), 'release requirement must not load prerelease'
- assert gem('d', '>= 1.a'), 'prerelease requirement may load prerelease'
+ def test_gem_prerelease_is_the_only_available
+ quick_gem "d", "1.1.a"
+
+ assert gem("d", ">= 1"), "release requirement may load prerelease when sole option"
+ assert $:.one? {|p| p.include?("/d-1.1.a/lib") }
+ end
+
+ def test_release_favored_over_prerelease
+ quick_gem "d", "1.1.a"
+ quick_gem "d", "1.2"
+ gem("d", ">= 1")
+
+ refute $:.any? {|p| p.include?("/d-1.1.a/lib") }
+ assert $:.one? {|p| p.include?("/d-1.2/lib") }
end
def test_gem_env_req
- ENV["GEM_REQUIREMENT_A"] = '~> 2.0'
- assert_raise(Gem::MissingSpecVersionError) { gem('a', '= 1') }
- assert gem('a', '> 1')
- assert_equal @a2, Gem.loaded_specs['a']
+ ENV["GEM_REQUIREMENT_A"] = "~> 2.0"
+ assert_raise(Gem::MissingSpecVersionError) { gem("a", "= 1") }
+ assert gem("a", "> 1")
+ assert_equal @a2, Gem.loaded_specs["a"]
end
def test_gem_conflicting
- assert gem('a', '= 1'), "Should load"
+ assert gem("a", "= 1"), "Should load"
ex = assert_raise Gem::LoadError do
- gem 'a', '= 2'
+ gem "a", "= 2"
end
assert_equal "can't activate a-2, already activated a-1", ex.message
assert_match(/activated a-1/, ex.message)
- assert_equal 'a', ex.name
+ assert_equal "a", ex.name
- assert $:.any? {|p| %r{a-1/lib} =~ p }
- refute $:.any? {|p| %r{a-2/lib} =~ p }
+ assert $:.any? {|p| p.include?("a-1/lib") }
+ refute $:.any? {|p| p.include?("a-2/lib") }
end
def test_gem_not_adding_bin
- assert gem('a', '= 1'), "Should load"
- refute $:.any? {|p| %r{a-1/bin} =~ p }
+ assert gem("a", "= 1"), "Should load"
+ refute $:.any? {|p| p.include?("a-1/bin") }
end
def test_gem_failing_inside_require_doesnt_cause_double_exceptions
@@ -110,32 +113,22 @@ class TestKernel < Gem::TestCase
end
def test_gem_bundler
- quick_gem 'bundler', '1'
- quick_gem 'bundler', '2.a'
+ quick_gem "bundler", "1"
+ quick_gem "bundler", "2.a"
- assert gem('bundler')
- assert $:.any? {|p| %r{bundler-1/lib} =~ p }
- end
-
- def test_gem_bundler_missing_bundler_version
- Gem::BundlerVersionFinder.stub(:bundler_version_with_reason, ["55", "reason"]) do
- quick_gem 'bundler', '1'
- quick_gem 'bundler', '2.a'
-
- e = assert_raise Gem::MissingSpecVersionError do
- gem('bundler')
- end
- assert_match "Could not find 'bundler' (55) required by reason.", e.message
- end
+ assert gem("bundler")
+ assert $:.any? {|p| p.include?("bundler-1/lib") }
end
def test_gem_bundler_inferred_bundler_version
- Gem::BundlerVersionFinder.stub(:bundler_version_with_reason, ["1", "reason"]) do
- quick_gem 'bundler', '1'
- quick_gem 'bundler', '2.a'
+ require "rubygems/bundler_version_finder"
+
+ Gem::BundlerVersionFinder.stub(:bundler_version, Gem::Version.new("1")) do
+ quick_gem "bundler", "1"
+ quick_gem "bundler", "2.a"
- assert gem('bundler', '>= 0.a')
- assert $:.any? {|p| %r{bundler-1/lib} =~ p }
+ assert gem("bundler", ">= 0.a")
+ assert $:.any? {|p| p.include?("bundler-1/lib") }
end
end
end
diff --git a/test/rubygems/test_project_sanity.rb b/test/rubygems/test_project_sanity.rb
index e9e3bfd1ba..7a7b779b08 100644
--- a/test/rubygems/test_project_sanity.rb
+++ b/test/rubygems/test_project_sanity.rb
@@ -3,18 +3,47 @@
require_relative "helper"
require "open3"
-class TestProjectSanity < Gem::TestCase
+class TestGemProjectSanity < Gem::TestCase
+ def setup
+ end
+
+ def teardown
+ end
+
def test_manifest_is_up_to_date
- pend unless File.exist?(File.expand_path("../../../Rakefile", __FILE__))
+ pend unless File.exist?("#{root}/Rakefile")
_, status = Open3.capture2e("rake check_manifest")
- assert status.success?, "Expected Manifest.txt to be up to date, but it's not. Run `rake update_manifest` to sync it."
+ unless status.success?
+ original_contents = File.read("#{root}/Manifest.txt")
+
+ # Update the manifest to see if it fixes the problem
+ Open3.capture2e("rake update_manifest")
+
+ out, status = Open3.capture2e("rake check_manifest")
+
+ # If `rake update_manifest` fixed the problem, that was the original
+ # issue, otherwise it was an unknown error, so print the error output
+ if status.success?
+ File.write("#{root}/Manifest.txt", original_contents)
+
+ raise "Expected Manifest.txt to be up to date, but it's not. Run `rake update_manifest` to sync it."
+ else
+ raise "There was an error running `rake check_manifest`: #{out}"
+ end
+ end
end
def test_require_rubygems_package
- err, status = Open3.capture2e(*ruby_with_rubygems_in_load_path, "--disable-gems", "-e", "'require \"rubygems/package\"'")
+ err, status = Open3.capture2e(*ruby_with_rubygems_in_load_path, "--disable-gems", "-e", "require \"rubygems/package\"")
assert status.success?, err
end
+
+ private
+
+ def root
+ File.expand_path("../..", __dir__)
+ end
end
diff --git a/test/rubygems/test_remote_fetch_error.rb b/test/rubygems/test_remote_fetch_error.rb
index b9e58389d3..5d9028ede7 100644
--- a/test/rubygems/test_remote_fetch_error.rb
+++ b/test/rubygems/test_remote_fetch_error.rb
@@ -1,19 +1,20 @@
# frozen_string_literal: true
-require_relative 'helper'
-class TestRemoteFetchError < Gem::TestCase
+require_relative "helper"
+
+class TestGemRemoteFetchError < Gem::TestCase
def test_password_redacted
- error = Gem::RemoteFetcher::FetchError.new('There was an error fetching', 'https://user:secret@gemsource.org')
- refute_match %r{secret}, error.to_s
+ error = Gem::RemoteFetcher::FetchError.new("There was an error fetching", "https://user:secret@gemsource.org")
+ refute_match(/secret/, error.to_s)
end
def test_invalid_url
- error = Gem::RemoteFetcher::FetchError.new('There was an error fetching', 'https://::gemsource.org')
- assert_equal error.to_s, 'There was an error fetching (https://::gemsource.org)'
+ error = Gem::RemoteFetcher::FetchError.new("There was an error fetching", "https://::gemsource.org")
+ assert_equal error.to_s, "There was an error fetching (https://::gemsource.org)"
end
def test_to_s
- error = Gem::RemoteFetcher::FetchError.new('There was an error fetching', 'https://gemsource.org')
- assert_equal error.to_s, 'There was an error fetching (https://gemsource.org)'
+ error = Gem::RemoteFetcher::FetchError.new("There was an error fetching", "https://gemsource.org")
+ assert_equal error.to_s, "There was an error fetching (https://gemsource.org)"
end
end
diff --git a/test/rubygems/test_require.rb b/test/rubygems/test_require.rb
index 07e412cc76..b915a86197 100644
--- a/test/rubygems/test_require.rb
+++ b/test/rubygems/test_require.rb
@@ -1,6 +1,7 @@
# frozen_string_literal: true
-require_relative 'helper'
-require 'rubygems'
+
+require_relative "helper"
+require "rubygems"
class TestGemRequire < Gem::TestCase
class Latch
@@ -24,16 +25,6 @@ class TestGemRequire < Gem::TestCase
end
end
- def setup
- super
-
- @old_loaded_features = $LOADED_FEATURES.dup
- assert_raise LoadError do
- require 'test_gem_require_a'
- end
- $LOADED_FEATURES.replace @old_loaded_features
- end
-
def assert_require(path)
assert require(path), "'#{path}' was already required"
end
@@ -45,26 +36,26 @@ class TestGemRequire < Gem::TestCase
def test_respect_loaded_features_caching_like_standard_require
dir = Dir.mktmpdir("test_require", @tempdir)
- lp1 = File.join dir, 'foo1'
- foo1 = File.join lp1, 'foo.rb'
+ lp1 = File.join dir, "foo1"
+ foo1 = File.join lp1, "foo.rb"
FileUtils.mkdir_p lp1
- File.open(foo1, 'w') {|f| f.write "class Object; HELLO = 'foo1' end" }
+ File.open(foo1, "w") {|f| f.write "class Object; HELLO = 'foo1' end" }
lp = $LOAD_PATH.dup
$LOAD_PATH.unshift lp1
- assert_require 'foo'
+ assert_require "foo"
assert_equal "foo1", ::Object::HELLO
- lp2 = File.join dir, 'foo2'
- foo2 = File.join lp2, 'foo.rb'
+ lp2 = File.join dir, "foo2"
+ foo2 = File.join lp2, "foo.rb"
FileUtils.mkdir_p lp2
- File.open(foo2, 'w') {|f| f.write "class Object; HELLO = 'foo2' end" }
+ File.open(foo2, "w") {|f| f.write "class Object; HELLO = 'foo2' end" }
$LOAD_PATH.unshift lp2
- refute_require 'foo'
+ refute_require "foo"
assert_equal "foo1", ::Object::HELLO
ensure
$LOAD_PATH.replace lp
@@ -73,76 +64,68 @@ class TestGemRequire < Gem::TestCase
# Providing -I on the commandline should always beat gems
def test_dash_i_beats_gems
- a1 = util_spec "a", "1", {"b" => "= 1"}, "lib/test_gem_require_a.rb"
- b1 = util_spec "b", "1", {"c" => "> 0"}, "lib/b/c.rb"
+ a1 = util_spec "a", "1", { "b" => "= 1" }, "lib/test_gem_require_a.rb"
+ b1 = util_spec "b", "1", { "c" => "> 0" }, "lib/b/c.rb"
c1 = util_spec "c", "1", nil, "lib/c/c.rb"
c2 = util_spec "c", "2", nil, "lib/c/c.rb"
install_specs c1, c2, b1, a1
dir = Dir.mktmpdir("test_require", @tempdir)
- dash_i_arg = File.join dir, 'lib'
+ dash_i_arg = File.join dir, "lib"
- c_rb = File.join dash_i_arg, 'b', 'c.rb'
+ c_rb = File.join dash_i_arg, "b", "c.rb"
FileUtils.mkdir_p File.dirname c_rb
- File.open(c_rb, 'w') {|f| f.write "class Object; HELLO = 'world' end" }
-
- lp = $LOAD_PATH.dup
+ File.open(c_rb, "w") {|f| f.write "class Object; HELLO = 'world' end" }
# Pretend to provide a commandline argument that overrides a file in gem b
$LOAD_PATH.unshift dash_i_arg
- assert_require 'test_gem_require_a'
- assert_require 'b/c' # this should be required from -I
+ assert_require "test_gem_require_a"
+ assert_require "b/c" # this should be required from -I
assert_equal "world", ::Object::HELLO
assert_equal %w[a-1 b-1], loaded_spec_names
ensure
- $LOAD_PATH.replace lp
Object.send :remove_const, :HELLO if Object.const_defined? :HELLO
end
def create_sync_thread
Thread.new do
- begin
- yield
- ensure
- FILE_ENTERED_LATCH.release
- FILE_EXIT_LATCH.await
- end
+ yield
+ ensure
+ FILE_ENTERED_LATCH.release
+ FILE_EXIT_LATCH.await
end
end
# Providing -I on the commandline should always beat gems
def test_dash_i_beats_default_gems
- a1 = new_default_spec "a", "1", {"b" => "= 1"}, "test_gem_require_a.rb"
- b1 = new_default_spec "b", "1", {"c" => "> 0"}, "b/c.rb"
+ a1 = new_default_spec "a", "1", { "b" => "= 1" }, "test_gem_require_a.rb"
+ b1 = new_default_spec "b", "1", { "c" => "> 0" }, "b/c.rb"
c1 = new_default_spec "c", "1", nil, "c/c.rb"
c2 = new_default_spec "c", "2", nil, "c/c.rb"
install_default_gems c1, c2, b1, a1
dir = Dir.mktmpdir("test_require", @tempdir)
- dash_i_arg = File.join dir, 'lib'
+ dash_i_arg = File.join dir, "lib"
- c_rb = File.join dash_i_arg, 'c', 'c.rb'
+ c_rb = File.join dash_i_arg, "c", "c.rb"
FileUtils.mkdir_p File.dirname c_rb
- File.open(c_rb, 'w') {|f| f.write "class Object; HELLO = 'world' end" }
+ File.open(c_rb, "w") {|f| f.write "class Object; HELLO = 'world' end" }
- assert_require 'test_gem_require_a'
-
- lp = $LOAD_PATH.dup
+ assert_require "test_gem_require_a"
# Pretend to provide a commandline argument that overrides a file in gem b
$LOAD_PATH.unshift dash_i_arg
- assert_require 'b/c'
- assert_require 'c/c' # this should be required from -I
+ assert_require "b/c"
+ assert_require "c/c" # this should be required from -I
assert_equal "world", ::Object::HELLO
assert_equal %w[a-1 b-1], loaded_spec_names
ensure
- $LOAD_PATH.replace lp
Object.send :remove_const, :HELLO if Object.const_defined? :HELLO
end
@@ -150,19 +133,13 @@ class TestGemRequire < Gem::TestCase
pend "extensions don't quite work on jruby" if Gem.java_platform?
pend "not installed yet" unless RbConfig::TOPDIR
- dash_i_ext_arg = util_install_extension_file('a')
- dash_i_lib_arg = util_install_ruby_file('a')
-
- lp = $LOAD_PATH.dup
+ dash_i_ext_arg = util_install_extension_file("a")
+ dash_i_lib_arg = util_install_ruby_file("a")
- begin
- $LOAD_PATH.unshift dash_i_lib_arg
- $LOAD_PATH.unshift dash_i_ext_arg
- assert_require 'a'
- assert_match(/a\.rb$/, $LOADED_FEATURES.last)
- ensure
- $LOAD_PATH.replace lp
- end
+ $LOAD_PATH.unshift dash_i_lib_arg
+ $LOAD_PATH.unshift dash_i_ext_arg
+ assert_require "a"
+ assert_match(/a\.rb$/, $LOADED_FEATURES.last)
end
def test_concurrent_require
@@ -174,8 +151,8 @@ class TestGemRequire < Gem::TestCase
install_specs a1, b1
- t1 = create_sync_thread{ assert_require "a#{$$}" }
- t2 = create_sync_thread{ assert_require "b#{$$}" }
+ t1 = create_sync_thread { assert_require "a#{$$}" }
+ t2 = create_sync_thread { assert_require "b#{$$}" }
# wait until both files are waiting on the exit latch
FILE_ENTERED_LATCH.await
@@ -191,13 +168,13 @@ class TestGemRequire < Gem::TestCase
end
def test_require_is_not_lazy_with_exact_req
- a1 = util_spec "a", "1", {"b" => "= 1"}, "lib/test_gem_require_a.rb"
+ a1 = util_spec "a", "1", { "b" => "= 1" }, "lib/test_gem_require_a.rb"
b1 = util_spec "b", "1", nil, "lib/b/c.rb"
b2 = util_spec "b", "2", nil, "lib/b/c.rb"
install_specs b1, b2, a1
- assert_require 'test_gem_require_a'
+ assert_require "test_gem_require_a"
assert_equal %w[a-1 b-1], loaded_spec_names
assert_equal unresolved_names, []
@@ -206,13 +183,13 @@ class TestGemRequire < Gem::TestCase
end
def test_require_is_lazy_with_inexact_req
- a1 = util_spec "a", "1", {"b" => ">= 1"}, "lib/test_gem_require_a.rb"
+ a1 = util_spec "a", "1", { "b" => ">= 1" }, "lib/test_gem_require_a.rb"
b1 = util_spec "b", "1", nil, "lib/b/c.rb"
b2 = util_spec "b", "2", nil, "lib/b/c.rb"
install_specs b1, b2, a1
- assert_require 'test_gem_require_a'
+ assert_require "test_gem_require_a"
assert_equal %w[a-1], loaded_spec_names
assert_equal unresolved_names, ["b (>= 1)"]
@@ -221,12 +198,12 @@ class TestGemRequire < Gem::TestCase
end
def test_require_is_not_lazy_with_one_possible
- a1 = util_spec "a", "1", {"b" => ">= 1"}, "lib/test_gem_require_a.rb"
+ a1 = util_spec "a", "1", { "b" => ">= 1" }, "lib/test_gem_require_a.rb"
b1 = util_spec "b", "1", nil, "lib/b/c.rb"
install_specs b1, a1
- assert_require 'test_gem_require_a'
+ assert_require "test_gem_require_a"
assert_equal %w[a-1 b-1], loaded_spec_names
assert_equal unresolved_names, []
@@ -239,20 +216,20 @@ class TestGemRequire < Gem::TestCase
install_specs a1
- assert_require Pathname.new 'test_gem_require_a'
+ assert_require Pathname.new "test_gem_require_a"
assert_equal %w[a-1], loaded_spec_names
assert_equal unresolved_names, []
end
def test_activate_via_require_respects_loaded_files
pend "Not sure what's going on. If another spec creates a 'a' gem before
- this test, somehow require will load the benchmark in b, and ignore that the
+ this test, somehow require will load the erb in b, and ignore that the
stdlib one is already in $LOADED_FEATURES?. Reproducible by running the
- spaceship_specific_file test before this one" if java_platform?
+ spaceship_specific_file test before this one" if Gem.java_platform?
pend "not installed yet" unless RbConfig::TOPDIR
- lib_dir = File.expand_path("../../lib", File.dirname(__FILE__))
+ lib_dir = File.expand_path("../lib", __dir__)
rubylibdir = File.realdirpath(RbConfig::CONFIG["rubylibdir"])
if rubylibdir == lib_dir
# testing in the ruby repository where RubyGems' lib/ == stdlib lib/
@@ -263,40 +240,40 @@ class TestGemRequire < Gem::TestCase
load_path_changed = true
end
- require 'benchmark' # the stdlib
+ require "erb" # the stdlib
- a1 = util_spec "a", "1", {"b" => ">= 1"}, "lib/test_gem_require_a.rb"
- b1 = util_spec "b", "1", nil, "lib/benchmark.rb"
- b2 = util_spec "b", "2", nil, "lib/benchmark.rb"
+ a1 = util_spec "a", "1", { "b" => ">= 1" }, "lib/test_gem_require_a.rb"
+ b1 = util_spec "b", "1", nil, "lib/erb.rb"
+ b2 = util_spec "b", "2", nil, "lib/erb.rb"
install_specs b1, b2, a1
# Activates a-1, but not b-1 and b-2
- assert_require 'test_gem_require_a'
+ assert_require "test_gem_require_a"
assert_equal %w[a-1], loaded_spec_names
- assert $LOAD_PATH.include? a1.load_paths[0]
- refute $LOAD_PATH.include? b1.load_paths[0]
- refute $LOAD_PATH.include? b2.load_paths[0]
+ assert $LOAD_PATH.include? a1.full_require_paths[0]
+ refute $LOAD_PATH.include? b1.full_require_paths[0]
+ refute $LOAD_PATH.include? b2.full_require_paths[0]
assert_equal unresolved_names, ["b (>= 1)"]
- # The require('benchmark') below will activate b-2. However, its
- # lib/benchmark.rb won't ever be loaded. The reason is MRI sees that even
- # though b-2 is earlier in $LOAD_PATH it already loaded a benchmark.rb file
+ # The require('erb') below will activate b-2. However, its
+ # lib/erb.rb won't ever be loaded. The reason is MRI sees that even
+ # though b-2 is earlier in $LOAD_PATH it already loaded a erb.rb file
# and that still exists in $LOAD_PATH (further down),
# and as a result #gem_original_require returns false.
- refute require('benchmark'), "the benchmark stdlib should be recognized as already loaded"
+ refute require("erb"), "the erb stdlib should be recognized as already loaded"
- assert_includes $LOAD_PATH, b2.load_paths[0]
+ assert_includes $LOAD_PATH, b2.full_require_paths[0]
assert_includes $LOAD_PATH, rubylibdir
message = proc {
"this test relies on the b-2 gem lib/ to be before stdlib to make sense\n" +
- $LOAD_PATH.pretty_inspect
+ $LOAD_PATH.pretty_inspect
}
- assert_operator $LOAD_PATH.index(b2.load_paths[0]), :<, $LOAD_PATH.index(rubylibdir), message
+ assert_operator $LOAD_PATH.index(b2.full_require_paths[0]), :<, $LOAD_PATH.index(rubylibdir), message
# We detected that we should activate b-2, so we did so, but
- # then #gem_original_require decided "I've already got some benchmark.rb" loaded.
+ # then #gem_original_require decided "I've already got some erb.rb" loaded.
# This case is fine because our lazy loading provided exactly
# the same behavior as eager loading would have.
@@ -318,7 +295,7 @@ class TestGemRequire < Gem::TestCase
install_specs a2
- refute_require 'a'
+ refute_require "a"
assert_equal %w[a-1], loaded_spec_names
end
@@ -400,18 +377,18 @@ class TestGemRequire < Gem::TestCase
# Load default ruby gems fresh as if we've just started a ruby script.
Gem::Specification.reset
- require 'rubygems'
+ require "rubygems"
Gem::Specification.stubs
# Remove an old default gem version directly from disk as if someone ran
# gem cleanup.
- FileUtils.rm_rf(File.join @gemhome, "#{b1.full_name}")
- FileUtils.rm_rf(File.join @gemhome, "specifications", "default", "#{b1.full_name}.gemspec")
+ FileUtils.rm_rf(File.join(@gemhome, b1.full_name.to_s))
+ FileUtils.rm_rf(File.join(@gemhome, "specifications", "default", "#{b1.full_name}.gemspec"))
# Require gems that have not been removed.
- assert_require 'a/b'
+ assert_require "a/b"
assert_equal %w[a-1.0], loaded_spec_names
- assert_require 'b/d'
+ assert_require "b/d"
assert_equal %w[a-1.0 b-2.0], loaded_spec_names
end
@@ -447,7 +424,7 @@ class TestGemRequire < Gem::TestCase
times_called = 0
- Kernel.stub(:gem, ->(name, requirement) { times_called += 1 }) do
+ Kernel.stub(:gem, ->(_name, _requirement) { times_called += 1 }) do
refute_require "default/gem"
end
@@ -466,8 +443,7 @@ class TestGemRequire < Gem::TestCase
end
def test_realworld_default_gem
- testing_ruby_repo = !ENV["GEM_COMMAND"].nil?
- pend "this test can't work under ruby-core setup" if testing_ruby_repo || java_platform?
+ omit "this test can't work under ruby-core setup" if ruby_repo?
cmd = <<-RUBY
$stderr = $stdout
@@ -480,8 +456,7 @@ class TestGemRequire < Gem::TestCase
end
def test_realworld_upgraded_default_gem
- testing_ruby_repo = !ENV["GEM_COMMAND"].nil?
- pend "this test can't work under ruby-core setup" if testing_ruby_repo
+ omit "this test can't work under ruby-core setup" if ruby_repo?
newer_json = util_spec("json", "999.99.9", nil, ["lib/json.rb"])
install_gem newer_json
@@ -495,12 +470,12 @@ class TestGemRequire < Gem::TestCase
RUBY
File.write(path, code)
- output = Gem::Util.popen({ 'GEM_HOME' => @gemhome }, *ruby_with_rubygems_in_load_path, path).strip
- assert $?.success?
+ output = Gem::Util.popen({ "GEM_HOME" => @gemhome }, *ruby_with_rubygems_in_load_path, path).strip
refute_empty output
assert_equal "999.99.9", output.lines[0].chomp
# Make sure only files from the newer json gem are loaded, and no files from the default json gem
assert_equal ["#{@gemhome}/gems/json-999.99.9/lib/json.rb"], output.lines.grep(%r{/gems/json-}).map(&:chomp)
+ assert $?.success?
end
def test_default_gem_and_normal_gem
@@ -514,6 +489,33 @@ class TestGemRequire < Gem::TestCase
assert_equal %w[default-3.0], loaded_spec_names
end
+ def test_default_gem_and_normal_gem_same_version
+ default_gem_spec = new_default_spec("default", "3.0",
+ nil, "default/gem.rb")
+ install_default_gems(default_gem_spec)
+ normal_gem_spec = util_spec("default", "3.0", nil,
+ "lib/default/gem.rb")
+ install_specs(normal_gem_spec)
+
+ # Load default ruby gems fresh as if we've just started a ruby script.
+ Gem::Specification.reset
+
+ assert_require "default/gem"
+ assert_equal %w[default-3.0], loaded_spec_names
+ refute Gem.loaded_specs["default"].default_gem?
+ end
+
+ def test_normal_gem_does_not_shadow_default_gem
+ default_gem_spec = new_default_spec("foo", "2.0", nil, "foo.rb")
+ install_default_gems(default_gem_spec)
+
+ normal_gem_spec = util_spec("fake-foo", "3.0", nil, "lib/foo.rb")
+ install_specs(normal_gem_spec)
+
+ assert_require "foo"
+ assert_equal %w[foo-2.0], loaded_spec_names
+ end
+
def test_normal_gems_with_overridden_load_error_message
normal_gem_spec = util_spec("normal", "3.0", nil, "lib/normal/gem.rb")
@@ -554,6 +556,65 @@ class TestGemRequire < Gem::TestCase
assert_equal %w[default-3.0.0.rc2], loaded_spec_names
end
+ def test_default_gem_with_unresolved_gems_depending_on_it
+ my_http_old = util_spec "my-http", "0.1.1", nil, "lib/my/http.rb"
+ install_gem my_http_old
+
+ my_http_default = new_default_spec "my-http", "0.3.0", nil, "my/http.rb"
+ install_default_gems my_http_default
+
+ faraday_1 = util_spec "faraday", "1", { "my-http" => ">= 0" }
+ install_gem faraday_1
+
+ faraday_2 = util_spec "faraday", "2", { "my-http" => ">= 0" }
+ install_gem faraday_2
+
+ chef = util_spec "chef", "1", { "faraday" => [">= 1", "< 3"] }, "lib/chef.rb"
+ install_gem chef
+
+ assert_require "chef"
+ assert_require "my/http"
+ end
+
+ def test_default_gem_required_circulary_with_unresolved_gems_depending_on_it
+ my_http_old = util_spec "my-http", "0.1.1", nil, "lib/my/http.rb"
+ install_gem my_http_old
+
+ my_http_default = new_default_spec "my-http", "0.3.0", nil, "my/http.rb"
+ my_http_default_path = File.join(@tempdir, "default_gems", "lib", "my/http.rb")
+ install_default_gems my_http_default
+ File.write(my_http_default_path, 'require "my/http"')
+
+ faraday_1 = util_spec "faraday", "1", { "my-http" => ">= 0" }
+ install_gem faraday_1
+
+ faraday_2 = util_spec "faraday", "2", { "my-http" => ">= 0" }
+ install_gem faraday_2
+
+ chef = util_spec "chef", "1", { "faraday" => [">= 1", "< 3"] }, "lib/chef.rb"
+ install_gem chef
+
+ assert_require "chef"
+
+ out, err = capture_output do
+ assert_require "my/http"
+ end
+
+ assert_empty out
+
+ circular_require_warning = false
+
+ err_lines = err.split("\n").reject do |line|
+ if line.include?("circular require")
+ circular_require_warning = true
+ elsif circular_require_warning # ignore backtrace lines for circular require warning
+ circular_require_warning = line.start_with?(/[\s]/)
+ end
+ end
+
+ assert_empty err_lines
+ end
+
def loaded_spec_names
Gem.loaded_specs.values.map(&:full_name).sort
end
@@ -565,19 +626,21 @@ class TestGemRequire < Gem::TestCase
def test_try_activate_error_unlocks_require_monitor
silence_warnings do
class << ::Gem
- alias old_try_activate try_activate
- def try_activate(*); raise 'raised from try_activate'; end
+ alias_method :old_try_activate, :try_activate
+ def try_activate(*)
+ raise "raised from try_activate"
+ end
end
end
- require 'does_not_exist_for_try_activate_test'
+ require "does_not_exist_for_try_activate_test"
rescue RuntimeError => e
assert_match(/raised from try_activate/, e.message)
assert Kernel::RUBYGEMS_ACTIVATION_MONITOR.try_enter, "require monitor was not unlocked when try_activate raised"
ensure
silence_warnings do
class << ::Gem
- alias try_activate old_try_activate
+ alias_method :try_activate, :old_try_activate
end
end
Kernel::RUBYGEMS_ACTIVATION_MONITOR.exit
@@ -609,124 +672,106 @@ class TestGemRequire < Gem::TestCase
end
def test_require_bundler
- b1 = util_spec('bundler', '1', nil, "lib/bundler/setup.rb")
- b2a = util_spec('bundler', '2.a', nil, "lib/bundler/setup.rb")
+ b1 = util_spec("bundler", "1", nil, "lib/bundler/setup.rb")
+ b2a = util_spec("bundler", "2.a", nil, "lib/bundler/setup.rb")
install_specs b1, b2a
require "rubygems/bundler_version_finder"
$:.clear
- assert_require 'bundler/setup'
+ assert_require "bundler/setup"
assert_equal %w[bundler-2.a], loaded_spec_names
assert_empty unresolved_names
end
- def test_require_bundler_missing_bundler_version
- Gem::BundlerVersionFinder.stub(:bundler_version_with_reason, ["55", "reason"]) do
- b1 = util_spec('bundler', '1.999999999', nil, "lib/bundler/setup.rb")
- b2a = util_spec('bundler', '2.a', nil, "lib/bundler/setup.rb")
- install_specs b1, b2a
-
- e = assert_raise Gem::MissingSpecVersionError do
- gem('bundler')
- end
- assert_match "Could not find 'bundler' (55) required by reason.", e.message
- end
- end
-
- def test_require_bundler_with_bundler_version
- Gem::BundlerVersionFinder.stub(:bundler_version_with_reason, ["1", "reason"]) do
- b1 = util_spec('bundler', '1.999999999', nil, "lib/bundler/setup.rb")
- b2 = util_spec('bundler', '2', nil, "lib/bundler/setup.rb")
- install_specs b1, b2
-
- $:.clear
- assert_require 'bundler/setup'
- assert_equal %w[bundler-1.999999999], loaded_spec_names
- end
- end
-
- # uplevel is 2.5+ only
- if RUBY_VERSION >= "2.5"
- ["", "Kernel."].each do |prefix|
- define_method "test_no_kernel_require_in_#{prefix.tr(".", "_")}warn_with_uplevel" do
- Dir.mktmpdir("warn_test") do |dir|
- File.write(dir + "/sub.rb", "#{prefix}warn 'uplevel', 'test', uplevel: 1\n")
- File.write(dir + "/main.rb", "require 'sub'\n")
- _, err = capture_subprocess_io do
- system(*ruby_with_rubygems_in_load_path, "-w", "--disable=gems", "-C", dir, "-I", dir, "main.rb")
- end
- assert_match(/main\.rb:1: warning: uplevel\ntest\n$/, err)
- _, err = capture_subprocess_io do
- system(*ruby_with_rubygems_in_load_path, "-w", "--enable=gems", "-C", dir, "-I", dir, "main.rb")
- end
- assert_match(/main\.rb:1: warning: uplevel\ntest\n$/, err)
+ ["", "Kernel."].each do |prefix|
+ define_method "test_no_kernel_require_in_#{prefix.tr(".", "_")}warn_with_uplevel" do
+ Dir.mktmpdir("warn_test") do |dir|
+ File.write(dir + "/sub.rb", "#{prefix}warn 'uplevel', 'test', uplevel: 1\n")
+ File.write(dir + "/main.rb", "require 'sub'\n")
+ _, err = capture_subprocess_io do
+ system(*ruby_with_rubygems_in_load_path, "-w", "--disable=gems", "-C", dir, "-I", dir, "main.rb")
end
- end
-
- define_method "test_no_other_behavioral_changes_with_#{prefix.tr(".", "_")}warn" do
- Dir.mktmpdir("warn_test") do |dir|
- File.write(dir + "/main.rb", "#{prefix}warn({x:1}, {y:2}, [])\n")
- _, err = capture_subprocess_io do
- system(*ruby_with_rubygems_in_load_path, "-w", "--disable=gems", "-C", dir, "main.rb")
- end
- assert_match(/{:x=>1}\n{:y=>2}\n$/, err)
- _, err = capture_subprocess_io do
- system(*ruby_with_rubygems_in_load_path, "-w", "--enable=gems", "-C", dir, "main.rb")
- end
- assert_match(/{:x=>1}\n{:y=>2}\n$/, err)
+ assert_match(/main\.rb:1: warning: uplevel\ntest\n$/, err)
+ _, err = capture_subprocess_io do
+ system(*ruby_with_rubygems_in_load_path, "-w", "--enable=gems", "-C", dir, "-I", dir, "main.rb")
end
+ assert_match(/main\.rb:1: warning: uplevel\ntest\n$/, err)
end
end
- def test_no_crash_when_overriding_warn_with_warning_module
+ define_method "test_no_other_behavioral_changes_with_#{prefix.tr(".", "_")}warn" do
Dir.mktmpdir("warn_test") do |dir|
- File.write(dir + "/main.rb", "module Warning; def warn(str); super; end; end; warn 'Foo Bar'")
+ File.write(dir + "/main.rb", "#{prefix}warn({x:1}, {y:2}, [])\n")
_, err = capture_subprocess_io do
system(*ruby_with_rubygems_in_load_path, "-w", "--disable=gems", "-C", dir, "main.rb")
end
- assert_match(/Foo Bar\n$/, err)
+ assert_match(/{:x=>1}\n{:y=>2}\n$/, err)
_, err = capture_subprocess_io do
system(*ruby_with_rubygems_in_load_path, "-w", "--enable=gems", "-C", dir, "main.rb")
end
- assert_match(/Foo Bar\n$/, err)
+ assert_match(/{:x=>1}\n{:y=>2}\n$/, err)
end
end
+ end
- def test_expected_backtrace_location_when_inheriting_from_basic_object_and_including_kernel
- Dir.mktmpdir("warn_test") do |dir|
- File.write(dir + "/main.rb", "\nrequire 'sub'\n")
- File.write(dir + "/sub.rb", <<-'RUBY')
- require 'rubygems'
- class C < BasicObject
- include ::Kernel
- def deprecated
- warn "This is a deprecated method", uplevel: 2
- end
- end
- C.new.deprecated
- RUBY
+ def test_no_crash_when_overriding_warn_with_warning_module
+ Dir.mktmpdir("warn_test") do |dir|
+ File.write(dir + "/main.rb", "module Warning; def warn(str); super; end; end; warn 'Foo Bar'")
+ _, err = capture_subprocess_io do
+ system(*ruby_with_rubygems_in_load_path, "-w", "--disable=gems", "-C", dir, "main.rb")
+ end
+ assert_match(/Foo Bar\n$/, err)
+ _, err = capture_subprocess_io do
+ system(*ruby_with_rubygems_in_load_path, "-w", "--enable=gems", "-C", dir, "main.rb")
+ end
+ assert_match(/Foo Bar\n$/, err)
+ end
+ end
- _, err = capture_subprocess_io do
- system(*ruby_with_rubygems_in_load_path, "-w", "--disable=gems", "-C", dir, "-I", dir, "main.rb")
- end
- assert_match(/main\.rb:2: warning: This is a deprecated method$/, err)
- _, err = capture_subprocess_io do
- system(*ruby_with_rubygems_in_load_path, "-w", "--enable=gems", "-C", dir, "-I", dir, "main.rb")
+ def test_expected_backtrace_location_when_inheriting_from_basic_object_and_including_kernel
+ Dir.mktmpdir("warn_test") do |dir|
+ File.write(dir + "/main.rb", "\nrequire 'sub'\n")
+ File.write(dir + "/sub.rb", <<-'RUBY')
+ require 'rubygems'
+ class C < BasicObject
+ include ::Kernel
+ def deprecated
+ warn "This is a deprecated method", uplevel: 2
+ end
end
- assert_match(/main\.rb:2: warning: This is a deprecated method$/, err)
+ C.new.deprecated
+ RUBY
+
+ _, err = capture_subprocess_io do
+ system(*ruby_with_rubygems_in_load_path, "-w", "--disable=gems", "-C", dir, "-I", dir, "main.rb")
+ end
+ assert_match(/main\.rb:2: warning: This is a deprecated method$/, err)
+ _, err = capture_subprocess_io do
+ system(*ruby_with_rubygems_in_load_path, "-w", "--enable=gems", "-C", dir, "-I", dir, "main.rb")
end
+ assert_match(/main\.rb:2: warning: This is a deprecated method$/, err)
end
end
- private
+ def test_require_does_not_crash_when_utilizing_bundler_version_finder
+ a1 = util_spec "a", "1.1", { "bundler" => ">= 0" }
+ a2 = util_spec "a", "1.2", { "bundler" => ">= 0" }
+ b1 = util_spec "bundler", "2.3.7"
+ b2 = util_spec "bundler", "2.3.24"
+ c = util_spec "c", "1", { "a" => [">= 1.1", "< 99.0"] }, "lib/test_gem_require_c.rb"
- def silence_warnings
- old_verbose, $VERBOSE = $VERBOSE, false
- yield
- ensure
- $VERBOSE = old_verbose
+ install_specs a1, a2, b1, b2, c
+
+ cmd = <<-RUBY
+ require "test_gem_require_c"
+ require "json"
+ RUBY
+ out = Gem::Util.popen({ "GEM_HOME" => @gemhome }, *ruby_with_rubygems_in_load_path, "-e", cmd)
+ assert_predicate $?, :success?, "Require failed due to #{out}"
end
+ private
+
def util_install_extension_file(name)
spec = quick_gem name
util_build_gem spec
@@ -750,13 +795,13 @@ class TestGemRequire < Gem::TestCase
spec.files += ["extconf.rb", "depend", "#{name}.c"]
- so = File.join(spec.gem_dir, "#{name}.#{RbConfig::CONFIG["DLEXT"]}")
- assert_path_not_exist so
+ extension_file = File.join(spec.extension_dir, "#{name}.#{RbConfig::CONFIG["DLEXT"]}")
+ assert_path_not_exist extension_file
path = Gem::Package.build spec
installer = Gem::Installer.at path
installer.install
- assert_path_exist so
+ assert_path_exist extension_file
spec.gem_dir
end
@@ -768,7 +813,7 @@ class TestGemRequire < Gem::TestCase
a_rb = File.join dash_i_lib_arg, "#{name}.rb"
FileUtils.mkdir_p File.dirname a_rb
- File.open(a_rb, 'w') {|f| f.write "# #{name}.rb" }
+ File.open(a_rb, "w") {|f| f.write "# #{name}.rb" }
dash_i_lib_arg
end
diff --git a/test/rubygems/test_rubygems.rb b/test/rubygems/test_rubygems.rb
index 493b9fdf4a..ec195b65cd 100644
--- a/test/rubygems/test_rubygems.rb
+++ b/test/rubygems/test_rubygems.rb
@@ -1,44 +1,76 @@
-require_relative 'helper'
+# frozen_string_literal: true
+
+require_relative "helper"
class GemTest < Gem::TestCase
def test_rubygems_normal_behaviour
- _ = Gem::Util.popen(*ruby_with_rubygems_in_load_path, '-e', "'require \"rubygems\"'", {:err => [:child, :out]}).strip
+ _ = Gem::Util.popen(*ruby_with_rubygems_in_load_path, "-e", "'require \"rubygems\"'", { err: [:child, :out] }).strip
assert $?.success?
end
def test_operating_system_other_exceptions
- pend "does not apply to truffleruby" if RUBY_ENGINE == 'truffleruby'
+ pend "does not apply to truffleruby" if RUBY_ENGINE == "truffleruby"
path = util_install_operating_system_rb <<-RUBY
intentionally_not_implemented_method
RUBY
- output = Gem::Util.popen(*ruby_with_rubygems_and_fake_operating_system_in_load_path(path), '-e', "'require \"rubygems\"'", {:err => [:child, :out]}).strip
+ output = Gem::Util.popen(*ruby_with_rubygems_and_fake_operating_system_in_load_path(path), "-e", "'require \"rubygems\"'", { err: [:child, :out] }).strip
assert !$?.success?
- assert_includes output, "undefined local variable or method `intentionally_not_implemented_method'"
- assert_includes output, "Loading the rubygems/defaults/operating_system.rb file caused an error. " \
+ assert_match(/undefined local variable or method [`']intentionally_not_implemented_method'/, output)
+ assert_includes output, "Loading the #{operating_system_rb_at(path)} file caused an error. " \
"This file is owned by your OS, not by rubygems upstream. " \
"Please find out which OS package this file belongs to and follow the guidelines from your OS to report " \
"the problem and ask for help."
end
+ def test_operating_system_customizing_default_dir
+ pend "does not apply to truffleruby" if RUBY_ENGINE == "truffleruby"
+ pend "loads a custom defaults/jruby file that gets in the middle" if RUBY_ENGINE == "jruby"
+
+ # On a non existing default dir, there should be no gems
+
+ path = util_install_operating_system_rb <<-RUBY
+ module Gem
+ def self.default_dir
+ File.expand_path("foo")
+ end
+ end
+ RUBY
+
+ output = Gem::Util.popen(
+ *ruby_with_rubygems_and_fake_operating_system_in_load_path(path),
+ "-e",
+ "require \"rubygems\"; puts Gem::Specification.stubs.map(&:full_name)",
+ { err: [:child, :out] }
+ ).strip
+ begin
+ assert_empty output
+ rescue Test::Unit::AssertionFailedError
+ pend "Temporary pending custom default_dir test"
+ end
+ end
+
private
def util_install_operating_system_rb(content)
dir_lib = Dir.mktmpdir("test_operating_system_lib", @tempdir)
- dir_lib_arg = File.join dir_lib
+ dir_lib_arg = File.join dir_lib, "lib"
- dir_lib_rubygems_defaults_arg = File.join dir_lib_arg, "lib", "rubygems", "defaults"
- FileUtils.mkdir_p dir_lib_rubygems_defaults_arg
+ operating_system_rb = operating_system_rb_at(dir_lib_arg)
- operating_system_rb = File.join dir_lib_rubygems_defaults_arg, "operating_system.rb"
+ FileUtils.mkdir_p File.dirname(operating_system_rb)
- File.open(operating_system_rb, 'w') {|f| f.write content }
+ File.open(operating_system_rb, "w") {|f| f.write content }
+
+ dir_lib_arg
+ end
- File.join dir_lib_arg, "lib"
+ def operating_system_rb_at(dir)
+ File.join dir, "rubygems", "defaults", "operating_system.rb"
end
def ruby_with_rubygems_and_fake_operating_system_in_load_path(operating_system_path)
- [Gem.ruby, "-I", operating_system_path, "-I" , $LOAD_PATH.find{|p| p == File.dirname($LOADED_FEATURES.find{|f| f.end_with?("/rubygems.rb") }) }]
+ [Gem.ruby, "-I", operating_system_path, "-I", $LOAD_PATH.find {|p| p == File.dirname($LOADED_FEATURES.find {|f| f.end_with?("/rubygems.rb") }) }]
end
end
diff --git a/test/rubygems/test_webauthn_listener.rb b/test/rubygems/test_webauthn_listener.rb
new file mode 100644
index 0000000000..08edabceb2
--- /dev/null
+++ b/test/rubygems/test_webauthn_listener.rb
@@ -0,0 +1,143 @@
+# frozen_string_literal: true
+
+require_relative "helper"
+require "rubygems/gemcutter_utilities/webauthn_listener"
+require "rubygems/gemcutter_utilities"
+
+class WebauthnListenerTest < Gem::TestCase
+ def setup
+ super
+ @server = TCPServer.new 0
+ @port = @server.addr[1].to_s
+ end
+
+ def teardown
+ @thread.kill.join if @thread
+ @server&.close
+ super
+ end
+
+ def test_listener_thread_retreives_otp_code
+ thread = Gem::GemcutterUtilities::WebauthnListener.listener_thread(Gem.host, @server)
+ Gem::MockBrowser.get Gem::URI("http://localhost:#{@port}?code=xyz")
+
+ thread.join
+ assert_equal "xyz", thread[:otp]
+ end
+
+ def test_listener_thread_sets_error
+ thread = Gem::GemcutterUtilities::WebauthnListener.listener_thread(Gem.host, @server)
+ Gem::MockBrowser.post Gem::URI("http://localhost:#{@port}?code=xyz")
+
+ thread.join
+ assert_equal "Security device verification failed: Invalid HTTP method POST received.", thread[:error].message
+ end
+
+ def test_wait_for_otp_code_get_follows_options
+ wait_for_otp_code
+ assert Gem::MockBrowser.options(Gem::URI("http://localhost:#{@port}?code=xyz")).is_a? Gem::Net::HTTPNoContent
+ assert Gem::MockBrowser.get(Gem::URI("http://localhost:#{@port}?code=xyz")).is_a? Gem::Net::HTTPOK
+ end
+
+ def test_wait_for_otp_code_options_request
+ wait_for_otp_code
+ response = Gem::MockBrowser.options Gem::URI("http://localhost:#{@port}?code=xyz")
+
+ assert response.is_a? Gem::Net::HTTPNoContent
+ assert_equal Gem.host, response["access-control-allow-origin"]
+ assert_equal "POST", response["access-control-allow-methods"]
+ assert_equal "Content-Type, Authorization, x-csrf-token", response["access-control-allow-headers"]
+ assert_equal "close", response["Connection"]
+ end
+
+ def test_wait_for_otp_code_get_request
+ wait_for_otp_code
+ response = Gem::MockBrowser.get Gem::URI("http://localhost:#{@port}?code=xyz")
+
+ assert response.is_a? Gem::Net::HTTPOK
+ assert_equal "text/plain; charset=utf-8", response["Content-Type"]
+ assert_equal "7", response["Content-Length"]
+ assert_equal Gem.host, response["access-control-allow-origin"]
+ assert_equal "POST", response["access-control-allow-methods"]
+ assert_equal "Content-Type, Authorization, x-csrf-token", response["access-control-allow-headers"]
+ assert_equal "close", response["Connection"]
+ assert_equal "success", response.body
+
+ @thread.join
+ assert_equal "xyz", @thread[:otp]
+ end
+
+ def test_wait_for_otp_code_invalid_post_req_method
+ wait_for_otp_code_expect_error_with_message("Security device verification failed: Invalid HTTP method POST received.")
+ response = Gem::MockBrowser.post Gem::URI("http://localhost:#{@port}?code=xyz")
+
+ assert response
+ assert response.is_a? Gem::Net::HTTPMethodNotAllowed
+ assert_equal "GET, OPTIONS", response["allow"]
+ assert_equal "close", response["Connection"]
+
+ @thread.join
+ assert_nil @thread[:otp]
+ end
+
+ def test_wait_for_otp_code_incorrect_path
+ wait_for_otp_code_expect_error_with_message("Security device verification failed: Page at /path not found.")
+ response = Gem::MockBrowser.post Gem::URI("http://localhost:#{@port}/path?code=xyz")
+
+ assert response.is_a? Gem::Net::HTTPNotFound
+ assert_equal "close", response["Connection"]
+
+ @thread.join
+ assert_nil @thread[:otp]
+ end
+
+ def test_wait_for_otp_code_no_params_response
+ wait_for_otp_code_expect_error_with_message("Security device verification failed: Did not receive OTP from https://rubygems.org.")
+ response = Gem::MockBrowser.get Gem::URI("http://localhost:#{@port}")
+
+ assert response.is_a? Gem::Net::HTTPBadRequest
+ assert_equal "text/plain; charset=utf-8", response["Content-Type"]
+ assert_equal "22", response["Content-Length"]
+ assert_equal "close", response["Connection"]
+ assert_equal "missing code parameter", response.body
+
+ @thread.join
+ assert_nil @thread[:otp]
+ end
+
+ def test_wait_for_otp_code_incorrect_params
+ wait_for_otp_code_expect_error_with_message("Security device verification failed: Did not receive OTP from https://rubygems.org.")
+ response = Gem::MockBrowser.get Gem::URI("http://localhost:#{@port}?param=xyz")
+
+ assert response.is_a? Gem::Net::HTTPBadRequest
+ assert_equal "text/plain; charset=utf-8", response["Content-Type"]
+ assert_equal "22", response["Content-Length"]
+ assert_equal "close", response["Connection"]
+ assert_equal "missing code parameter", response.body
+
+ @thread.join
+ assert_nil @thread[:otp]
+ end
+
+ private
+
+ def wait_for_otp_code
+ @thread = Thread.new do
+ Thread.current[:otp] = Gem::GemcutterUtilities::WebauthnListener.new(Gem.host).wait_for_otp_code(@server)
+ end
+ @thread.abort_on_exception = true
+ @thread.report_on_exception = false
+ end
+
+ def wait_for_otp_code_expect_error_with_message(message)
+ @thread = Thread.new do
+ error = assert_raise Gem::WebauthnVerificationError do
+ Thread.current[:otp] = Gem::GemcutterUtilities::WebauthnListener.new(Gem.host).wait_for_otp_code(@server)
+ end
+
+ assert_equal message, error.message
+ end
+ @thread.abort_on_exception = true
+ @thread.report_on_exception = false
+ end
+end
diff --git a/test/rubygems/test_webauthn_listener_response.rb b/test/rubygems/test_webauthn_listener_response.rb
new file mode 100644
index 0000000000..377e5bfe5a
--- /dev/null
+++ b/test/rubygems/test_webauthn_listener_response.rb
@@ -0,0 +1,93 @@
+# frozen_string_literal: true
+
+require_relative "helper"
+require "rubygems/gemcutter_utilities/webauthn_listener/response"
+
+class WebauthnListenerResponseTest < Gem::TestCase
+ def setup
+ super
+ @host = "rubygems.example"
+ end
+
+ def test_ok_response_to_s
+ to_s = Gem::GemcutterUtilities::WebauthnListener::OkResponse.new(@host).to_s
+
+ expected_to_s = <<~RESPONSE
+ HTTP/1.1 200 OK\r
+ connection: close\r
+ access-control-allow-origin: rubygems.example\r
+ access-control-allow-methods: POST\r
+ access-control-allow-headers: Content-Type, Authorization, x-csrf-token\r
+ content-type: text/plain; charset=utf-8\r
+ content-length: 7\r
+ \r
+ success
+ RESPONSE
+
+ assert_equal expected_to_s, to_s
+ end
+
+ def test_no_to_s_response_to_s
+ to_s = Gem::GemcutterUtilities::WebauthnListener::NoContentResponse.new(@host).to_s
+
+ expected_to_s = <<~RESPONSE
+ HTTP/1.1 204 No Content\r
+ connection: close\r
+ access-control-allow-origin: rubygems.example\r
+ access-control-allow-methods: POST\r
+ access-control-allow-headers: Content-Type, Authorization, x-csrf-token\r
+ \r
+ RESPONSE
+
+ assert_equal expected_to_s, to_s
+ end
+
+ def test_method_not_allowed_response_to_s
+ to_s = Gem::GemcutterUtilities::WebauthnListener::MethodNotAllowedResponse.new(@host).to_s
+
+ expected_to_s = <<~RESPONSE
+ HTTP/1.1 405 Method Not Allowed\r
+ connection: close\r
+ access-control-allow-origin: rubygems.example\r
+ access-control-allow-methods: POST\r
+ access-control-allow-headers: Content-Type, Authorization, x-csrf-token\r
+ allow: GET, OPTIONS\r
+ \r
+ RESPONSE
+
+ assert_equal expected_to_s, to_s
+ end
+
+ def test_method_not_found_response_to_s
+ to_s = Gem::GemcutterUtilities::WebauthnListener::NotFoundResponse.new(@host).to_s
+
+ expected_to_s = <<~RESPONSE
+ HTTP/1.1 404 Not Found\r
+ connection: close\r
+ access-control-allow-origin: rubygems.example\r
+ access-control-allow-methods: POST\r
+ access-control-allow-headers: Content-Type, Authorization, x-csrf-token\r
+ \r
+ RESPONSE
+
+ assert_equal expected_to_s, to_s
+ end
+
+ def test_bad_request_response_to_s
+ to_s = Gem::GemcutterUtilities::WebauthnListener::BadRequestResponse.new(@host).to_s
+
+ expected_to_s = <<~RESPONSE
+ HTTP/1.1 400 Bad Request\r
+ connection: close\r
+ access-control-allow-origin: rubygems.example\r
+ access-control-allow-methods: POST\r
+ access-control-allow-headers: Content-Type, Authorization, x-csrf-token\r
+ content-type: text/plain; charset=utf-8\r
+ content-length: 22\r
+ \r
+ missing code parameter
+ RESPONSE
+
+ assert_equal expected_to_s, to_s
+ end
+end
diff --git a/test/rubygems/test_webauthn_poller.rb b/test/rubygems/test_webauthn_poller.rb
new file mode 100644
index 0000000000..fd24081758
--- /dev/null
+++ b/test/rubygems/test_webauthn_poller.rb
@@ -0,0 +1,134 @@
+# frozen_string_literal: true
+
+require_relative "helper"
+require "rubygems/gemcutter_utilities/webauthn_poller"
+require "rubygems/gemcutter_utilities"
+
+class WebauthnPollerTest < Gem::TestCase
+ def setup
+ super
+
+ @host = Gem.host
+ @webauthn_url = "#{@host}/api/v1/webauthn_verification/odow34b93t6aPCdY"
+ @fetcher = Gem::FakeFetcher.new
+ Gem::RemoteFetcher.fetcher = @fetcher
+ @credentials = {
+ identifier: "email@example.com",
+ password: "password",
+ }
+ end
+
+ def test_poll_thread_success
+ @fetcher.data["#{@webauthn_url}/status.json"] = Gem::HTTPResponseFactory.create(
+ body: "{\"status\":\"success\",\"code\":\"Uvh6T57tkWuUnWYo\"}",
+ code: 200,
+ msg: "OK"
+ )
+
+ thread = Gem::GemcutterUtilities::WebauthnPoller.poll_thread({}, @host, @webauthn_url, @credentials)
+ thread.join
+
+ assert_equal thread[:otp], "Uvh6T57tkWuUnWYo"
+ end
+
+ def test_poll_thread_webauthn_verification_error
+ @fetcher.data["#{@webauthn_url}/status.json"] = Gem::HTTPResponseFactory.create(
+ body: "HTTP Basic: Access denied.",
+ code: 401,
+ msg: "Unauthorized"
+ )
+
+ thread = Gem::GemcutterUtilities::WebauthnPoller.poll_thread({}, @host, @webauthn_url, @credentials)
+ thread.join
+
+ assert_equal thread[:error].message, "Security device verification failed: Unauthorized"
+ end
+
+ def test_poll_thread_timeout_error
+ raise_error = ->(*_args) { raise Gem::Timeout::Error, "execution expired" }
+ Gem::Timeout.stub(:timeout, raise_error) do
+ thread = Gem::GemcutterUtilities::WebauthnPoller.poll_thread({}, @host, @webauthn_url, @credentials)
+ thread.join
+ assert_equal thread[:error].message, "execution expired"
+ end
+ end
+
+ def test_poll_for_otp_success
+ @fetcher.data["#{@webauthn_url}/status.json"] = Gem::HTTPResponseFactory.create(
+ body: "{\"status\":\"success\",\"code\":\"Uvh6T57tkWuUnWYo\"}",
+ code: 200,
+ msg: "OK"
+ )
+
+ otp = Gem::GemcutterUtilities::WebauthnPoller.new({}, @host).poll_for_otp(@webauthn_url, @credentials)
+
+ assert_equal otp, "Uvh6T57tkWuUnWYo"
+ end
+
+ def test_poll_for_otp_pending_sleeps
+ @fetcher.data["#{@webauthn_url}/status.json"] = Gem::HTTPResponseFactory.create(
+ body: "{\"status\":\"pending\",\"message\":\"Security device authentication is still pending.\"}",
+ code: 200,
+ msg: "OK"
+ )
+
+ assert_raise Gem::Timeout::Error do
+ Gem::Timeout.timeout(0.1) do
+ Gem::GemcutterUtilities::WebauthnPoller.new({}, @host).poll_for_otp(@webauthn_url, @credentials)
+ end
+ end
+ end
+
+ def test_poll_for_otp_not_http_success
+ @fetcher.data["#{@webauthn_url}/status.json"] = Gem::HTTPResponseFactory.create(
+ body: "HTTP Basic: Access denied.",
+ code: 401,
+ msg: "Unauthorized"
+ )
+
+ error = assert_raise Gem::WebauthnVerificationError do
+ Gem::GemcutterUtilities::WebauthnPoller.new({}, @host).poll_for_otp(@webauthn_url, @credentials)
+ end
+
+ assert_equal error.message, "Security device verification failed: Unauthorized"
+ end
+
+ def test_poll_for_otp_invalid_format
+ @fetcher.data["#{@webauthn_url}/status.json"] = Gem::HTTPResponseFactory.create(
+ body: "{}",
+ code: 200,
+ msg: "OK"
+ )
+
+ error = assert_raise Gem::WebauthnVerificationError do
+ Gem::GemcutterUtilities::WebauthnPoller.new({}, @host).poll_for_otp(@webauthn_url, @credentials)
+ end
+
+ assert_equal error.message, "Security device verification failed: Invalid response from server"
+ end
+
+ def test_poll_for_otp_invalid_status
+ @fetcher.data["#{@webauthn_url}/status.json"] = Gem::HTTPResponseFactory.create(
+ body: "{\"status\":\"expired\",\"message\":\"The token in the link you used has either expired or been used already.\"}",
+ code: 200,
+ msg: "OK"
+ )
+
+ error = assert_raise Gem::WebauthnVerificationError do
+ Gem::GemcutterUtilities::WebauthnPoller.new({}, @host).poll_for_otp(@webauthn_url, @credentials)
+ end
+
+ assert_equal error.message,
+ "Security device verification failed: The token in the link you used has either expired or been used already."
+ end
+
+ def test_poll_for_otp_missing_credentials
+ @credentials = { password: "password" }
+
+ error = assert_raise Gem::WebauthnVerificationError do
+ Gem::GemcutterUtilities::WebauthnPoller.new({}, @host).poll_for_otp(@webauthn_url, @credentials)
+ end
+
+ assert_equal error.message, "Security device verification failed: Provided missing credentials"
+ end
+end
diff --git a/test/rubygems/utilities.rb b/test/rubygems/utilities.rb
index 20416fe70b..357379f88d 100644
--- a/test/rubygems/utilities.rb
+++ b/test/rubygems/utilities.rb
@@ -1,7 +1,8 @@
# frozen_string_literal: true
-require 'tempfile'
-require 'rubygems'
-require 'rubygems/remote_fetcher'
+
+require "tempfile"
+require "rubygems"
+require "rubygems/remote_fetcher"
##
# A fake Gem::RemoteFetcher for use in tests or to avoid real live HTTP
@@ -39,35 +40,43 @@ class Gem::FakeFetcher
end
def find_data(path)
- return Gem.read_binary path.path if URI === path and 'file' == path.scheme
+ return Gem.read_binary path.path if Gem::URI === path && path.scheme == "file"
- if URI === path and "URI::#{path.scheme.upcase}" != path.class.name
+ if Gem::URI === path && "Gem::URI::#{path.scheme.upcase}" != path.class.name
raise ArgumentError,
"mismatch for scheme #{path.scheme} and class #{path.class}"
end
path = path.to_s
@paths << path
- raise ArgumentError, 'need full URI' unless path.start_with?("https://", "http://")
+ raise ArgumentError, "need full Gem::URI" unless path.start_with?("https://", "http://")
unless @data.key? path
raise Gem::RemoteFetcher::FetchError.new("no data for #{path}", path)
end
- if @data[path].kind_of?(Array) && @data[path].first.kind_of?(Array)
+ if @data[path].is_a?(Array)
@data[path].shift
else
@data[path]
end
end
+ def create_response(uri)
+ data = find_data(uri)
+ response = data.respond_to?(:call) ? data.call : data
+ raise TypeError, "#{response.class} is not a type of Gem::Net::HTTPResponse" unless response.is_a?(Gem::Net::HTTPResponse)
+
+ response
+ end
+
def fetch_path(path, mtime = nil, head = false)
data = find_data(path)
if data.respond_to?(:call)
data.call
else
- if path.to_s.end_with?(".gz") and not data.nil? and not data.empty?
+ if path.to_s.end_with?(".gz") && !data.nil? && !data.empty?
data = Gem::Util.gunzip data
end
data
@@ -76,7 +85,7 @@ class Gem::FakeFetcher
def cache_update_path(uri, path = nil, update = true)
if data = fetch_path(uri)
- File.open(path, 'wb') {|io| io.write data } if path and update
+ File.open(path, "wb") {|io| io.write data } if path && update
data
else
Gem.read_binary(path) if path
@@ -85,32 +94,22 @@ class Gem::FakeFetcher
# Thanks, FakeWeb!
def open_uri_or_path(path)
- data = find_data(path)
- body, code, msg = data
+ find_data(path)
- response = Net::HTTPResponse.send(:response_class, code.to_s).new("1.0", code.to_s, msg)
- response.instance_variable_set(:@body, body)
- response.instance_variable_set(:@read, true)
- response
+ create_response(uri)
end
def request(uri, request_class, last_modified = nil)
- data = find_data(uri)
- body, code, msg = (data.respond_to?(:call) ? data.call : data)
-
@last_request = request_class.new uri.request_uri
yield @last_request if block_given?
- response = Net::HTTPResponse.send(:response_class, code.to_s).new("1.0", code.to_s, msg)
- response.instance_variable_set(:@body, body)
- response.instance_variable_set(:@read, true)
- response
+ create_response(uri)
end
def pretty_print(q) # :nodoc:
- q.group 2, '[FakeFetcher', ']' do
+ q.group 2, "[FakeFetcher", "]" do
q.breakable
- q.text 'URIs:'
+ q.text "URIs:"
q.breakable
q.pp @data.keys
@@ -121,7 +120,7 @@ class Gem::FakeFetcher
path = path.to_s
@paths << path
- raise ArgumentError, 'need full URI' unless path =~ %r{^http://}
+ raise ArgumentError, "need full URI" unless %r{^http://}.match?(path)
unless @data.key? path
raise Gem::RemoteFetcher::FetchError.new("no data for #{path}", path)
@@ -135,14 +134,14 @@ class Gem::FakeFetcher
def download(spec, source_uri, install_dir = Gem.dir)
name = File.basename spec.cache_file
path = if Dir.pwd == install_dir # see fetch_command
- install_dir
- else
- File.join install_dir, "cache"
- end
+ install_dir
+ else
+ File.join install_dir, "cache"
+ end
path = File.join path, name
- if source_uri =~ /^http/
+ if /^http/.match?(source_uri)
File.open(path, "wb") do |f|
f.write fetch_path(File.join(source_uri, "gems", name))
end
@@ -164,6 +163,66 @@ class Gem::FakeFetcher
end
end
+##
+# The HTTPResponseFactory allows easy creation of Gem::Net::HTTPResponse instances in RubyGems tests:
+#
+# Example:
+#
+# Gem::HTTPResponseFactory.create(
+# body: "",
+# code: 301,
+# msg: "Moved Permanently",
+# headers: { "location" => "http://example.com" }
+# )
+#
+
+class Gem::HTTPResponseFactory
+ def self.create(body:, code:, msg:, headers: {})
+ response = Gem::Net::HTTPResponse.send(:response_class, code.to_s).new("1.0", code.to_s, msg)
+ response.instance_variable_set(:@body, body)
+ response.instance_variable_set(:@read, true)
+ headers.each {|name, value| response[name] = value }
+
+ response
+ end
+end
+
+##
+# A Gem::MockBrowser is used in tests to mock a browser in that it can
+# send HTTP requests to the defined URI.
+#
+# Example:
+#
+# # Sends a get request to http://localhost:5678
+# Gem::MockBrowser.get Gem::URI("http://localhost:5678")
+#
+# See RubyGems' tests for more examples of MockBrowser.
+#
+
+class Gem::MockBrowser
+ def self.options(uri)
+ options = Gem::Net::HTTP::Options.new(uri)
+ Gem::Net::HTTP.start(uri.hostname, uri.port) do |http|
+ http.request(options)
+ end
+ end
+
+ def self.get(uri)
+ get = Gem::Net::HTTP::Get.new(uri)
+ Gem::Net::HTTP.start(uri.hostname, uri.port) do |http|
+ http.request(get)
+ end
+ end
+
+ def self.post(uri, content_type: "application/x-www-form-urlencoded")
+ headers = { "content-type" => content_type } if content_type
+ post = Gem::Net::HTTP::Post.new(uri, headers)
+ Gem::Net::HTTP.start(uri.hostname, uri.port) do |http|
+ http.request(post)
+ end
+ end
+end
+
# :stopdoc:
class Gem::RemoteFetcher
def self.fetcher=(fetcher)
@@ -288,16 +347,16 @@ class Gem::TestCase::SpecFetcherSetup
# Creates a legacy platform spec with the name 'pl' and version 1
def legacy_platform
- spec 'pl', 1 do |s|
- s.platform = Gem::Platform.new 'i386-linux'
- s.instance_variable_set :@original_platform, 'i386-linux'
+ spec "pl", 1 do |s|
+ s.platform = Gem::Platform.new "i386-linux"
+ s.instance_variable_set :@original_platform, "i386-linux"
end
end
def setup_fetcher # :nodoc:
- require 'zlib'
- require 'socket'
- require 'rubygems/remote_fetcher'
+ require "zlib"
+ require "socket"
+ require "rubygems/remote_fetcher"
unless @test.fetcher
@test.fetcher = Gem::FakeFetcher.new
@@ -307,13 +366,14 @@ class Gem::TestCase::SpecFetcherSetup
Gem::Specification.reset
begin
- gem_repo, @test.gem_repo = @test.gem_repo, @repository
- @test.uri = URI @repository
+ gem_repo = @test.gem_repo
+ @test.gem_repo = @repository
+ @test.uri = Gem::URI @repository
@test.util_setup_spec_fetcher(*@downloaded)
ensure
@test.gem_repo = gem_repo
- @test.uri = URI gem_repo
+ @test.uri = Gem::URI gem_repo
end
@gems.each do |spec, gem|
@@ -338,7 +398,7 @@ class Gem::TestCase::SpecFetcherSetup
end
def write_spec(spec) # :nodoc:
- File.open spec.spec_file, 'w' do |io|
+ File.open spec.spec_file, "w" do |io|
io.write spec.to_ruby_for_cache
end
end
@@ -350,11 +410,11 @@ end
#
# This class was added to flush out problems in Rubinius' IO implementation.
-class TempIO < Tempfile
+class Gem::TempIO < Tempfile
##
# Creates a new TempIO that will be initialized to contain +string+.
- def initialize(string = '')
+ def initialize(string = "")
super "TempIO"
binmode
write string
@@ -369,3 +429,8 @@ class TempIO < Tempfile
Gem.read_binary path
end
end
+
+class Gem::TestCase
+ TempIO = Gem::TempIO
+ HTTPResponseFactory = Gem::HTTPResponseFactory
+end
diff --git a/test/rubygems/wrong_key_cert.pem b/test/rubygems/wrong_key_cert.pem
index 23396d7c81..2f2cffbc61 100644
--- a/test/rubygems/wrong_key_cert.pem
+++ b/test/rubygems/wrong_key_cert.pem
@@ -1,19 +1,19 @@
-----BEGIN CERTIFICATE-----
-MIIDDTCCAfWgAwIBAgIBEjANBgkqhkiG9w0BAQUFADAqMQ8wDQYDVQQDDAZub2Jv
+MIIDDTCCAfWgAwIBAgIBEjANBgkqhkiG9w0BAQsFADAqMQ8wDQYDVQQDDAZub2Jv
ZHkxFzAVBgoJkiaJk/IsZAEZFgdleGFtcGxlMCAXDTEyMDEwMTAwMDAwMFoYDzk5
OTkxMjMxMjM1OTU5WjAqMQ8wDQYDVQQDDAZub2JvZHkxFzAVBgoJkiaJk/IsZAEZ
-FgdleGFtcGxlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvZQipBa1
-xH3M9OonkrUYhGZeX9UHAcJhe6jJbUr/uHXkh1Tu2ERWNnblm85upqBfjyZEnKer
-7uBcwwkkvmisVgC8uBECymsBxuEIw0rfiKYEnLu0B6SiWFYz3dYPS92bBK7Vks2/
-kNyXUmLLGoZ3id2K0eK5C/AJ0j+p84OqPnVhylsjrZmXfIZrh7lkHhgCIrzPefjE
-3pOloi/tz6fh2ktb0FYKQMfweT3Ba2TMeflG13PEOW80AD5w0THxDutGG0zPNCDy
-DEoT7UU1a3B3RMHYuUxEk1GUEYWq9L6a6SMpZISWTSpCp0Ww1QB55PONiCCn+o6v
-cIy46jI71dATAQIDAQABozwwOjAZBgNVHREEEjAQgQ5ub2JvZHlAZXhhbXBsZTAd
-BgNVHQ4EFgQUyvn/FwcZnA7AkzPjmoooB4/tKgcwDQYJKoZIhvcNAQEFBQADggEB
-ABswixv3veo8S0Omyhbch3t19xAd/I4ZAx/lq6a/Ubl+X33hRbZQ7ulXja6Y5ZCs
-iIkezGcpc182e7hZdHuEGGnJ1fJwxz3rbFWvs+MrtRSaCC73HbbxF1x0mQY6Kc7W
-PahB2v+Dx5n3dIN6ah5p+STUHmzhKGr3bsQswtSHrFn74wt6mBu/hyCz+t6UaQ7b
-rpRpzDFO1q3tZB8MeIHg57Lk2bu0LtfaHdkGDghNa3t7oZfV5A6pruiTy/EdQvFL
-ZJpvDgHCyUsDmukMMjz6U4ts+nx7kZ9JoIH9K2lMJo3SGw4iZ8rB+HTfsbUdRfBj
-UlyNcLqCW+FPlUHgHgNugFA=
+FgdleGFtcGxlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApebGm7NO
+nx+DtWG1xQsJBfTfwNlZvfzY61nlZccrhU6vx0AnYNiDZAG3J/gFQmYZ9gJ98rzE
+wfLMCGq9R/TZM+lAEaLhzYZCu3X4QdhKxr1xZ/SFC+1f8KVuH4tLXORW30DwayPh
+NxnrOvup4pWLiYuXUSZpV9CGMvPSUCW2odhMkBMKqaTTPjxoXJIcgacyprkNgIq4
+8cSvqWG/e/HrMRtkqvFbD5ta00uO1mlpajYYw1RRftEwktFo8vQgDBo9NT/EqoE7
+2tffaDnLq6rQrVtw4Kr9fy775DjNAWXyiCBjnJgOQSXCGPsM/AEdFrh/LKQQv2M/
+M7WNevnEUgsEIwIDAQABozwwOjAZBgNVHREEEjAQgQ5ub2JvZHlAZXhhbXBsZTAd
+BgNVHQ4EFgQUYPwS8g98+4Tq/8gcEK1iilkGXH4wDQYJKoZIhvcNAQELBQADggEB
+AJacpAT2GQQn5Rmb/LYaPhguWFHEdjHBO6rU0p7tE8QJW5pwMgim0mFtQlbuXE2L
+mbHrYCyRgVyaPV9gNiFg1sLzQMmmG4Afg1N4cpdg8zLZFZho+eyYGRkH+EtrAN0Q
+l8l603zovMXj8q8Q1eeurxkDHA6mDgwwMGiBQgAiPixQVOjvL+5M5PkwNw/kVzjA
+0EXumGQkeZ1jUAkVjp7uWbyoVatamUcpYvo51NQQQeuqwzdo2oDYLa27axWxaqj2
+m4TKsz2WnnrSnrpq3NnflXfWcOrnXI3odNlhQoPmtZQVt6P8pNbGrx4XD/WTGkGw
+i/6jlkwwjK7A7dSepfnTI4Y=
-----END CERTIFICATE-----
diff --git a/test/rubygems/wrong_key_cert_32.pem b/test/rubygems/wrong_key_cert_32.pem
index 7a3bb9f714..aca829ab44 100644
--- a/test/rubygems/wrong_key_cert_32.pem
+++ b/test/rubygems/wrong_key_cert_32.pem
@@ -1,19 +1,19 @@
-----BEGIN CERTIFICATE-----
-MIIDCzCCAfOgAwIBAgIBEzANBgkqhkiG9w0BAQUFADAqMQ8wDQYDVQQDDAZub2Jv
+MIIDCzCCAfOgAwIBAgIBEzANBgkqhkiG9w0BAQsFADAqMQ8wDQYDVQQDDAZub2Jv
ZHkxFzAVBgoJkiaJk/IsZAEZFgdleGFtcGxlMB4XDTEyMDEwMTAwMDAwMFoXDTM4
MDExOTAzMTQwN1owKjEPMA0GA1UEAwwGbm9ib2R5MRcwFQYKCZImiZPyLGQBGRYH
-ZXhhbXBsZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL2UIqQWtcR9
-zPTqJ5K1GIRmXl/VBwHCYXuoyW1K/7h15IdU7thEVjZ25ZvObqagX48mRJynq+7g
-XMMJJL5orFYAvLgRAsprAcbhCMNK34imBJy7tAekolhWM93WD0vdmwSu1ZLNv5Dc
-l1JiyxqGd4nditHiuQvwCdI/qfODqj51YcpbI62Zl3yGa4e5ZB4YAiK8z3n4xN6T
-paIv7c+n4dpLW9BWCkDH8Hk9wWtkzHn5RtdzxDlvNAA+cNEx8Q7rRhtMzzQg8gxK
-E+1FNWtwd0TB2LlMRJNRlBGFqvS+mukjKWSElk0qQqdFsNUAeeTzjYggp/qOr3CM
-uOoyO9XQEwECAwEAAaM8MDowGQYDVR0RBBIwEIEObm9ib2R5QGV4YW1wbGUwHQYD
-VR0OBBYEFMr5/xcHGZwOwJMz45qKKAeP7SoHMA0GCSqGSIb3DQEBBQUAA4IBAQCU
-VkESWkNeiJ1L3MfkMl2ybP2QPWP5nlhz+NOqwOCJSmEXF86Dq2XTY/GgSu1iPp4s
-pPm1RSpnjujtiV7gjCziNif/XqAxeSjU2deApvq4mknyk958N0IS8c86dUXms1DQ
-Rncmb3pxxvzP1d6Is35Uwoc5KqheJWR3aDwE8ejaFfO8pq/ncUDB25bc7OyslHMJ
-7Ah+2YlFjvHYuPvN8bP44UMYyAPZCCJnjIPn7m7giyQiIo6SA9aiLQ8F7+NN3SU4
-7I9ED0F7RTDxNYISr1sLZ7aNtnXkTAnZclwKohuGfZD3OGAOshLZZXIB2pIRr/Kj
-6zxTef39tli6orheYQXp
+ZXhhbXBsZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKXmxpuzTp8f
+g7VhtcULCQX038DZWb382OtZ5WXHK4VOr8dAJ2DYg2QBtyf4BUJmGfYCffK8xMHy
+zAhqvUf02TPpQBGi4c2GQrt1+EHYSsa9cWf0hQvtX/Clbh+LS1zkVt9A8Gsj4TcZ
+6zr7qeKVi4mLl1EmaVfQhjLz0lAltqHYTJATCqmk0z48aFySHIGnMqa5DYCKuPHE
+r6lhv3vx6zEbZKrxWw+bWtNLjtZpaWo2GMNUUX7RMJLRaPL0IAwaPTU/xKqBO9rX
+32g5y6uq0K1bcOCq/X8u++Q4zQFl8oggY5yYDkElwhj7DPwBHRa4fyykEL9jPzO1
+jXr5xFILBCMCAwEAAaM8MDowGQYDVR0RBBIwEIEObm9ib2R5QGV4YW1wbGUwHQYD
+VR0OBBYEFGD8EvIPfPuE6v/IHBCtYopZBlx+MA0GCSqGSIb3DQEBCwUAA4IBAQBE
+lq/rPaPT+5uui42u4BTFayrQU9EFik9xPG6WJw+IJ/5CprECj6h90FC+GaMNeu2Z
+R0l+iEfgx4xBM4DERiRVLZIlHbZzuPp0YRYH9gyJot/+0piaAcnUEvjz2Z8axoFq
+lE3/q4s6Yw8xdqwxvc5kiwymv2nEm4+v5w6Pb3K/fP/QQLvDUBWrBUMHPgdYXYk2
+zvc58BBwgGDSpFRO0tw+lnqMTM1y+fbpfuvP9TY1m4y13nuw/g7KxVxYolAWVQs3
+TptnJqqzEwdFa2S9BidUIlDRRY8cuhY6R3DM6THNLjR3c1oyf04nhT3sd/ilAJdD
+YjnEtcLlkjxZyLLoWjn2
-----END CERTIFICATE-----
diff --git a/test/runner.rb b/test/runner.rb
index a24cfa31c6..c34517cbf2 100644
--- a/test/runner.rb
+++ b/test/runner.rb
@@ -1,12 +1,5 @@
# frozen_string_literal: true
-# Should be done in rubygems test files?
-ENV["GEM_SKIP"] = ENV["GEM_HOME"] = ENV["GEM_PATH"] = "".freeze
-ENV.delete("RUBY_CODESIGN")
-
-# Get bundled gems on load path
-Dir.glob("#{__dir__}/../.bundle/gems/*/*.gemspec")
- .reject {|f| f =~ /minitest|test-unit|power_assert/ }
- .map {|f| $LOAD_PATH.unshift File.join(File.dirname(f), "lib") }
+# NOTE: Do not add any settings here for test-all. Instead, please add it to ../tool/test/init.rb.
require_relative '../tool/test/runner'
diff --git a/test/fixtures/fake_sorted_set_gem/sorted_set.rb b/test/set/fixtures/fake_sorted_set_gem/sorted_set.rb
index f45a766303..f45a766303 100644
--- a/test/fixtures/fake_sorted_set_gem/sorted_set.rb
+++ b/test/set/fixtures/fake_sorted_set_gem/sorted_set.rb
diff --git a/test/set/test_set.rb b/test/set/test_set.rb
new file mode 100644
index 0000000000..49dc58ef7b
--- /dev/null
+++ b/test/set/test_set.rb
@@ -0,0 +1,892 @@
+# frozen_string_literal: false
+require 'test/unit'
+require 'set'
+
+class TC_Set < Test::Unit::TestCase
+ class Set2 < Set
+ end
+
+ def test_aref
+ assert_nothing_raised {
+ Set[]
+ Set[nil]
+ Set[1,2,3]
+ }
+
+ assert_equal(0, Set[].size)
+ assert_equal(1, Set[nil].size)
+ assert_equal(1, Set[[]].size)
+ assert_equal(1, Set[[nil]].size)
+
+ set = Set[2,4,6,4]
+ assert_equal(Set.new([2,4,6]), set)
+ end
+
+ def test_s_new
+ assert_nothing_raised {
+ Set.new()
+ Set.new(nil)
+ Set.new([])
+ Set.new([1,2])
+ Set.new('a'..'c')
+ }
+ assert_raise(ArgumentError) {
+ Set.new(false)
+ }
+ assert_raise(ArgumentError) {
+ Set.new(1)
+ }
+ assert_raise(ArgumentError) {
+ Set.new(1,2)
+ }
+
+ assert_equal(0, Set.new().size)
+ assert_equal(0, Set.new(nil).size)
+ assert_equal(0, Set.new([]).size)
+ assert_equal(1, Set.new([nil]).size)
+
+ ary = [2,4,6,4]
+ set = Set.new(ary)
+ ary.clear
+ assert_equal(false, set.empty?)
+ assert_equal(3, set.size)
+
+ ary = [1,2,3]
+
+ s = Set.new(ary) { |o| o * 2 }
+ assert_equal([2,4,6], s.sort)
+ end
+
+ def test_clone
+ set1 = Set.new
+ set2 = set1.clone
+ set1 << 'abc'
+ assert_equal(Set.new, set2)
+ end
+
+ def test_dup
+ set1 = Set[1,2]
+ set2 = set1.dup
+
+ assert_not_same(set1, set2)
+
+ assert_equal(set1, set2)
+
+ set1.add(3)
+
+ assert_not_equal(set1, set2)
+ end
+
+ def test_size
+ assert_equal(0, Set[].size)
+ assert_equal(2, Set[1,2].size)
+ assert_equal(2, Set[1,2,1].size)
+ end
+
+ def test_empty?
+ assert_equal(true, Set[].empty?)
+ assert_equal(false, Set[1, 2].empty?)
+ end
+
+ def test_clear
+ set = Set[1,2]
+ ret = set.clear
+
+ assert_same(set, ret)
+ assert_equal(true, set.empty?)
+ end
+
+ def test_replace
+ set = Set[1,2]
+ ret = set.replace('a'..'c')
+
+ assert_same(set, ret)
+ assert_equal(Set['a','b','c'], set)
+
+ set = Set[1,2]
+ assert_raise(ArgumentError) {
+ set.replace(3)
+ }
+ assert_equal(Set[1,2], set)
+ end
+
+ def test_to_a
+ set = Set[1,2,3,2]
+ ary = set.to_a
+
+ assert_equal([1,2,3], ary.sort)
+ end
+
+ def test_flatten
+ # test1
+ set1 = Set[
+ 1,
+ Set[
+ 5,
+ Set[7,
+ Set[0]
+ ],
+ Set[6,2],
+ 1
+ ],
+ 3,
+ Set[3,4]
+ ]
+
+ set2 = set1.flatten
+ set3 = Set.new(0..7)
+
+ assert_not_same(set2, set1)
+ assert_equal(set3, set2)
+
+ # test2; destructive
+ orig_set1 = set1
+ set1.flatten!
+
+ assert_same(orig_set1, set1)
+ assert_equal(set3, set1)
+
+ # test3; multiple occurrences of a set in an set
+ set1 = Set[1, 2]
+ set2 = Set[set1, Set[set1, 4], 3]
+
+ assert_nothing_raised {
+ set2.flatten!
+ }
+
+ assert_equal(Set.new(1..4), set2)
+
+ # test4; recursion
+ set2 = Set[]
+ set1 = Set[1, set2]
+ set2.add(set1)
+
+ assert_raise(ArgumentError) {
+ set1.flatten!
+ }
+
+ # test5; miscellaneous
+ empty = Set[]
+ set = Set[Set[empty, "a"],Set[empty, "b"]]
+
+ assert_nothing_raised {
+ set.flatten
+ }
+
+ set1 = empty.merge(Set["no_more", set])
+
+ assert_nil(Set.new(0..31).flatten!)
+
+ x = Set[Set[],Set[1,2]].flatten!
+ y = Set[1,2]
+
+ assert_equal(x, y)
+ end
+
+ def test_include?
+ set = Set[1,2,3]
+
+ assert_equal(true, set.include?(1))
+ assert_equal(true, set.include?(2))
+ assert_equal(true, set.include?(3))
+ assert_equal(false, set.include?(0))
+ assert_equal(false, set.include?(nil))
+
+ set = Set["1",nil,"2",nil,"0","1",false]
+ assert_equal(true, set.include?(nil))
+ assert_equal(true, set.include?(false))
+ assert_equal(true, set.include?("1"))
+ assert_equal(false, set.include?(0))
+ assert_equal(false, set.include?(true))
+ end
+
+ def test_eqq
+ set = Set[1,2,3]
+
+ assert_equal(true, set === 1)
+ assert_equal(true, set === 2)
+ assert_equal(true, set === 3)
+ assert_equal(false, set === 0)
+ assert_equal(false, set === nil)
+
+ set = Set["1",nil,"2",nil,"0","1",false]
+ assert_equal(true, set === nil)
+ assert_equal(true, set === false)
+ assert_equal(true, set === "1")
+ assert_equal(false, set === 0)
+ assert_equal(false, set === true)
+ end
+
+ def test_superset?
+ set = Set[1,2,3]
+
+ assert_raise(ArgumentError) {
+ set.superset?()
+ }
+
+ assert_raise(ArgumentError) {
+ set.superset?(2)
+ }
+
+ assert_raise(ArgumentError) {
+ set.superset?([2])
+ }
+
+ [Set, Set2].each { |klass|
+ assert_equal(true, set.superset?(klass[]), klass.name)
+ assert_equal(true, set.superset?(klass[1,2]), klass.name)
+ assert_equal(true, set.superset?(klass[1,2,3]), klass.name)
+ assert_equal(false, set.superset?(klass[1,2,3,4]), klass.name)
+ assert_equal(false, set.superset?(klass[1,4]), klass.name)
+
+ assert_equal(true, set >= klass[1,2,3], klass.name)
+ assert_equal(true, set >= klass[1,2], klass.name)
+
+ assert_equal(true, Set[].superset?(klass[]), klass.name)
+ }
+ end
+
+ def test_proper_superset?
+ set = Set[1,2,3]
+
+ assert_raise(ArgumentError) {
+ set.proper_superset?()
+ }
+
+ assert_raise(ArgumentError) {
+ set.proper_superset?(2)
+ }
+
+ assert_raise(ArgumentError) {
+ set.proper_superset?([2])
+ }
+
+ [Set, Set2].each { |klass|
+ assert_equal(true, set.proper_superset?(klass[]), klass.name)
+ assert_equal(true, set.proper_superset?(klass[1,2]), klass.name)
+ assert_equal(false, set.proper_superset?(klass[1,2,3]), klass.name)
+ assert_equal(false, set.proper_superset?(klass[1,2,3,4]), klass.name)
+ assert_equal(false, set.proper_superset?(klass[1,4]), klass.name)
+
+ assert_equal(false, set > klass[1,2,3], klass.name)
+ assert_equal(true, set > klass[1,2], klass.name)
+
+ assert_equal(false, Set[].proper_superset?(klass[]), klass.name)
+ }
+ end
+
+ def test_subset?
+ set = Set[1,2,3]
+
+ assert_raise(ArgumentError) {
+ set.subset?()
+ }
+
+ assert_raise(ArgumentError) {
+ set.subset?(2)
+ }
+
+ assert_raise(ArgumentError) {
+ set.subset?([2])
+ }
+
+ [Set, Set2].each { |klass|
+ assert_equal(true, set.subset?(klass[1,2,3,4]), klass.name)
+ assert_equal(true, set.subset?(klass[1,2,3]), klass.name)
+ assert_equal(false, set.subset?(klass[1,2]), klass.name)
+ assert_equal(false, set.subset?(klass[]), klass.name)
+
+ assert_equal(true, set <= klass[1,2,3], klass.name)
+ assert_equal(true, set <= klass[1,2,3,4], klass.name)
+
+ assert_equal(true, Set[].subset?(klass[1]), klass.name)
+ assert_equal(true, Set[].subset?(klass[]), klass.name)
+ }
+ end
+
+ def test_proper_subset?
+ set = Set[1,2,3]
+
+ assert_raise(ArgumentError) {
+ set.proper_subset?()
+ }
+
+ assert_raise(ArgumentError) {
+ set.proper_subset?(2)
+ }
+
+ assert_raise(ArgumentError) {
+ set.proper_subset?([2])
+ }
+
+ [Set, Set2].each { |klass|
+ assert_equal(true, set.proper_subset?(klass[1,2,3,4]), klass.name)
+ assert_equal(false, set.proper_subset?(klass[1,2,3]), klass.name)
+ assert_equal(false, set.proper_subset?(klass[1,2]), klass.name)
+ assert_equal(false, set.proper_subset?(klass[]), klass.name)
+
+ assert_equal(false, set < klass[1,2,3], klass.name)
+ assert_equal(true, set < klass[1,2,3,4], klass.name)
+
+ assert_equal(false, Set[].proper_subset?(klass[]), klass.name)
+ }
+ end
+
+ def test_spacecraft_operator
+ set = Set[1,2,3]
+
+ assert_nil(set <=> 2)
+
+ assert_nil(set <=> set.to_a)
+
+ [Set, Set2].each { |klass|
+ assert_equal(-1, set <=> klass[1,2,3,4], klass.name)
+ assert_equal( 0, set <=> klass[3,2,1] , klass.name)
+ assert_equal(nil, set <=> klass[1,2,4] , klass.name)
+ assert_equal(+1, set <=> klass[2,3] , klass.name)
+ assert_equal(+1, set <=> klass[] , klass.name)
+
+ assert_equal(0, Set[] <=> klass[], klass.name)
+ }
+ end
+
+ def assert_intersect(expected, set, other)
+ case expected
+ when true
+ assert_send([set, :intersect?, other])
+ assert_send([set, :intersect?, other.to_a])
+ assert_send([other, :intersect?, set])
+ assert_not_send([set, :disjoint?, other])
+ assert_not_send([set, :disjoint?, other.to_a])
+ assert_not_send([other, :disjoint?, set])
+ when false
+ assert_not_send([set, :intersect?, other])
+ assert_not_send([set, :intersect?, other.to_a])
+ assert_not_send([other, :intersect?, set])
+ assert_send([set, :disjoint?, other])
+ assert_send([set, :disjoint?, other.to_a])
+ assert_send([other, :disjoint?, set])
+ when Class
+ assert_raise(expected) {
+ set.intersect?(other)
+ }
+ assert_raise(expected) {
+ set.disjoint?(other)
+ }
+ else
+ raise ArgumentError, "%s: unsupported expected value: %s" % [__method__, expected.inspect]
+ end
+ end
+
+ def test_intersect?
+ set = Set[3,4,5]
+
+ assert_intersect(ArgumentError, set, 3)
+ assert_intersect(true, set, Set[2,4,6])
+
+ assert_intersect(true, set, set)
+ assert_intersect(true, set, Set[2,4])
+ assert_intersect(true, set, Set[5,6,7])
+ assert_intersect(true, set, Set[1,2,6,8,4])
+
+ assert_intersect(false, set, Set[])
+ assert_intersect(false, set, Set[0,2])
+ assert_intersect(false, set, Set[0,2,6])
+ assert_intersect(false, set, Set[0,2,6,8,10])
+
+ # Make sure set hasn't changed
+ assert_equal(Set[3,4,5], set)
+ end
+
+ def test_each
+ ary = [1,3,5,7,10,20]
+ set = Set.new(ary)
+
+ ret = set.each { |o| }
+ assert_same(set, ret)
+
+ e = set.each
+ assert_instance_of(Enumerator, e)
+
+ assert_nothing_raised {
+ set.each { |o|
+ ary.delete(o) or raise "unexpected element: #{o}"
+ }
+
+ ary.empty? or raise "forgotten elements: #{ary.join(', ')}"
+ }
+
+ assert_equal(6, e.size)
+ set << 42
+ assert_equal(7, e.size)
+ end
+
+ def test_add
+ set = Set[1,2,3]
+
+ ret = set.add(2)
+ assert_same(set, ret)
+ assert_equal(Set[1,2,3], set)
+
+ ret = set.add?(2)
+ assert_nil(ret)
+ assert_equal(Set[1,2,3], set)
+
+ ret = set.add(4)
+ assert_same(set, ret)
+ assert_equal(Set[1,2,3,4], set)
+
+ ret = set.add?(5)
+ assert_same(set, ret)
+ assert_equal(Set[1,2,3,4,5], set)
+ end
+
+ def test_delete
+ set = Set[1,2,3]
+
+ ret = set.delete(4)
+ assert_same(set, ret)
+ assert_equal(Set[1,2,3], set)
+
+ ret = set.delete?(4)
+ assert_nil(ret)
+ assert_equal(Set[1,2,3], set)
+
+ ret = set.delete(2)
+ assert_equal(set, ret)
+ assert_equal(Set[1,3], set)
+
+ ret = set.delete?(1)
+ assert_equal(set, ret)
+ assert_equal(Set[3], set)
+ end
+
+ def test_delete_if
+ set = Set.new(1..10)
+ ret = set.delete_if { |i| i > 10 }
+ assert_same(set, ret)
+ assert_equal(Set.new(1..10), set)
+
+ set = Set.new(1..10)
+ ret = set.delete_if { |i| i % 3 == 0 }
+ assert_same(set, ret)
+ assert_equal(Set[1,2,4,5,7,8,10], set)
+
+ set = Set.new(1..10)
+ enum = set.delete_if
+ assert_equal(set.size, enum.size)
+ assert_same(set, enum.each { |i| i % 3 == 0 })
+ assert_equal(Set[1,2,4,5,7,8,10], set)
+ end
+
+ def test_keep_if
+ set = Set.new(1..10)
+ ret = set.keep_if { |i| i <= 10 }
+ assert_same(set, ret)
+ assert_equal(Set.new(1..10), set)
+
+ set = Set.new(1..10)
+ ret = set.keep_if { |i| i % 3 != 0 }
+ assert_same(set, ret)
+ assert_equal(Set[1,2,4,5,7,8,10], set)
+
+ set = Set.new(1..10)
+ enum = set.keep_if
+ assert_equal(set.size, enum.size)
+ assert_same(set, enum.each { |i| i % 3 != 0 })
+ assert_equal(Set[1,2,4,5,7,8,10], set)
+ end
+
+ def test_collect!
+ set = Set[1,2,3,'a','b','c',-1..1,2..4]
+
+ ret = set.collect! { |i|
+ case i
+ when Numeric
+ i * 2
+ when String
+ i.upcase
+ else
+ nil
+ end
+ }
+
+ assert_same(set, ret)
+ assert_equal(Set[2,4,6,'A','B','C',nil], set)
+
+ set = Set[1,2,3,'a','b','c',-1..1,2..4]
+ enum = set.collect!
+
+ assert_equal(set.size, enum.size)
+ assert_same(set, enum.each { |i|
+ case i
+ when Numeric
+ i * 2
+ when String
+ i.upcase
+ else
+ nil
+ end
+ })
+ assert_equal(Set[2,4,6,'A','B','C',nil], set)
+ end
+
+ def test_reject!
+ set = Set.new(1..10)
+
+ ret = set.reject! { |i| i > 10 }
+ assert_nil(ret)
+ assert_equal(Set.new(1..10), set)
+
+ ret = set.reject! { |i| i % 3 == 0 }
+ assert_same(set, ret)
+ assert_equal(Set[1,2,4,5,7,8,10], set)
+
+ set = Set.new(1..10)
+ enum = set.reject!
+ assert_equal(set.size, enum.size)
+ assert_same(set, enum.each { |i| i % 3 == 0 })
+ assert_equal(Set[1,2,4,5,7,8,10], set)
+ end
+
+ def test_select!
+ set = Set.new(1..10)
+ ret = set.select! { |i| i <= 10 }
+ assert_equal(nil, ret)
+ assert_equal(Set.new(1..10), set)
+
+ set = Set.new(1..10)
+ ret = set.select! { |i| i % 3 != 0 }
+ assert_same(set, ret)
+ assert_equal(Set[1,2,4,5,7,8,10], set)
+
+ set = Set.new(1..10)
+ enum = set.select!
+ assert_equal(set.size, enum.size)
+ assert_equal(nil, enum.each { |i| i <= 10 })
+ assert_equal(Set.new(1..10), set)
+ end
+
+ def test_filter!
+ set = Set.new(1..10)
+ ret = set.filter! { |i| i <= 10 }
+ assert_equal(nil, ret)
+ assert_equal(Set.new(1..10), set)
+
+ set = Set.new(1..10)
+ ret = set.filter! { |i| i % 3 != 0 }
+ assert_same(set, ret)
+ assert_equal(Set[1,2,4,5,7,8,10], set)
+
+ set = Set.new(1..10)
+ enum = set.filter!
+ assert_equal(set.size, enum.size)
+ assert_equal(nil, enum.each { |i| i <= 10 })
+ assert_equal(Set.new(1..10), set)
+ end
+
+ def test_merge
+ set = Set[1,2,3]
+ ret = set.merge([2,4,6])
+ assert_same(set, ret)
+ assert_equal(Set[1,2,3,4,6], set)
+
+ set = Set[1,2,3]
+ ret = set.merge()
+ assert_same(set, ret)
+ assert_equal(Set[1,2,3], set)
+
+ set = Set[1,2,3]
+ ret = set.merge([2,4,6], Set[4,5,6])
+ assert_same(set, ret)
+ assert_equal(Set[1,2,3,4,5,6], set)
+
+ assert_raise(ArgumentError) {
+ Set[].merge(a: 1)
+ }
+ end
+
+ def test_subtract
+ set = Set[1,2,3]
+
+ ret = set.subtract([2,4,6])
+ assert_same(set, ret)
+ assert_equal(Set[1,3], set)
+ end
+
+ def test_plus
+ set = Set[1,2,3]
+
+ ret = set + [2,4,6]
+ assert_not_same(set, ret)
+ assert_equal(Set[1,2,3,4,6], ret)
+ end
+
+ def test_minus
+ set = Set[1,2,3]
+
+ ret = set - [2,4,6]
+ assert_not_same(set, ret)
+ assert_equal(Set[1,3], ret)
+ end
+
+ def test_and
+ set = Set[1,2,3,4]
+
+ ret = set & [2,4,6]
+ assert_not_same(set, ret)
+ assert_equal(Set[2,4], ret)
+ end
+
+ def test_xor
+ set = Set[1,2,3,4]
+ ret = set ^ [2,4,5,5]
+ assert_not_same(set, ret)
+ assert_equal(Set[1,3,5], ret)
+ end
+
+ def test_eq
+ set1 = Set[2,3,1]
+ set2 = Set[1,2,3]
+
+ assert_equal(set1, set1)
+ assert_equal(set1, set2)
+ assert_not_equal(Set[1], [1])
+
+ set1 = Class.new(Set)["a", "b"]
+ set1.add(set1).reset # Make recursive
+ set2 = Set["a", "b", Set["a", "b", set1]]
+
+ assert_equal(set1, set2)
+
+ assert_not_equal(Set[Exception.new,nil], Set[Exception.new,Exception.new], "[ruby-dev:26127]")
+ end
+
+ def test_classify
+ set = Set.new(1..10)
+ ret = set.classify { |i| i % 3 }
+
+ assert_equal(3, ret.size)
+ assert_instance_of(Hash, ret)
+ ret.each_value { |value| assert_instance_of(Set, value) }
+ assert_equal(Set[3,6,9], ret[0])
+ assert_equal(Set[1,4,7,10], ret[1])
+ assert_equal(Set[2,5,8], ret[2])
+
+ set = Set.new(1..10)
+ enum = set.classify
+
+ assert_equal(set.size, enum.size)
+ ret = enum.each { |i| i % 3 }
+ assert_equal(3, ret.size)
+ assert_instance_of(Hash, ret)
+ ret.each_value { |value| assert_instance_of(Set, value) }
+ assert_equal(Set[3,6,9], ret[0])
+ assert_equal(Set[1,4,7,10], ret[1])
+ assert_equal(Set[2,5,8], ret[2])
+ end
+
+ def test_divide
+ set = Set.new(1..10)
+ ret = set.divide { |i| i % 3 }
+
+ assert_equal(3, ret.size)
+ n = 0
+ ret.each { |s| n += s.size }
+ assert_equal(set.size, n)
+ assert_equal(set, ret.flatten)
+
+ set = Set[7,10,5,11,1,3,4,9,0]
+ ret = set.divide { |a,b| (a - b).abs == 1 }
+
+ assert_equal(4, ret.size)
+ n = 0
+ ret.each { |s| n += s.size }
+ assert_equal(set.size, n)
+ assert_equal(set, ret.flatten)
+ ret.each { |s|
+ if s.include?(0)
+ assert_equal(Set[0,1], s)
+ elsif s.include?(3)
+ assert_equal(Set[3,4,5], s)
+ elsif s.include?(7)
+ assert_equal(Set[7], s)
+ elsif s.include?(9)
+ assert_equal(Set[9,10,11], s)
+ else
+ raise "unexpected group: #{s.inspect}"
+ end
+ }
+
+ set = Set.new(1..10)
+ enum = set.divide
+ ret = enum.each { |i| i % 3 }
+
+ assert_equal(set.size, enum.size)
+ assert_equal(3, ret.size)
+ n = 0
+ ret.each { |s| n += s.size }
+ assert_equal(set.size, n)
+ assert_equal(set, ret.flatten)
+ end
+
+ def test_freeze
+ orig = set = Set[1,2,3]
+ assert_equal false, set.frozen?
+ set << 4
+ assert_same orig, set.freeze
+ assert_equal true, set.frozen?
+ assert_raise(FrozenError) {
+ set << 5
+ }
+ assert_equal 4, set.size
+ end
+
+ def test_freeze_dup
+ set1 = Set[1,2,3]
+ set1.freeze
+ set2 = set1.dup
+
+ assert_not_predicate set2, :frozen?
+ assert_nothing_raised {
+ set2.add 4
+ }
+ end
+
+ def test_freeze_clone
+ set1 = Set[1,2,3]
+ set1.freeze
+ set2 = set1.clone
+
+ assert_predicate set2, :frozen?
+ assert_raise(FrozenError) {
+ set2.add 5
+ }
+ end
+
+ def test_freeze_clone_false
+ set1 = Set[1,2,3]
+ set1.freeze
+ set2 = set1.clone(freeze: false)
+
+ assert_not_predicate set2, :frozen?
+ set2.add 5
+ assert_equal Set[1,2,3,5], set2
+ assert_equal Set[1,2,3], set1
+ end if Kernel.instance_method(:initialize_clone).arity != 1
+
+ def test_join
+ assert_equal('123', Set[1, 2, 3].join)
+ assert_equal('1 & 2 & 3', Set[1, 2, 3].join(' & '))
+ end
+
+ def test_inspect
+ set1 = Set[1, 2]
+ assert_equal('#<Set: {1, 2}>', set1.inspect)
+
+ set2 = Set[Set[0], 1, 2, set1]
+ assert_equal('#<Set: {#<Set: {0}>, 1, 2, #<Set: {1, 2}>}>', set2.inspect)
+
+ set1.add(set2)
+ assert_equal('#<Set: {#<Set: {0}>, 1, 2, #<Set: {1, 2, #<Set: {...}>}>}>', set2.inspect)
+ end
+
+ def test_to_s
+ set1 = Set[1, 2]
+ assert_equal('#<Set: {1, 2}>', set1.to_s)
+
+ set2 = Set[Set[0], 1, 2, set1]
+ assert_equal('#<Set: {#<Set: {0}>, 1, 2, #<Set: {1, 2}>}>', set2.to_s)
+
+ set1.add(set2)
+ assert_equal('#<Set: {#<Set: {0}>, 1, 2, #<Set: {1, 2, #<Set: {...}>}>}>', set2.to_s)
+ end
+
+ def test_compare_by_identity
+ a1, a2 = "a", "a"
+ b1, b2 = "b", "b"
+ c = "c"
+ array = [a1, b1, c, a2, b2]
+
+ iset = Set.new.compare_by_identity
+ assert_send([iset, :compare_by_identity?])
+ iset.merge(array)
+ assert_equal(5, iset.size)
+ assert_equal(array.map(&:object_id).sort, iset.map(&:object_id).sort)
+
+ set = Set.new
+ assert_not_send([set, :compare_by_identity?])
+ set.merge(array)
+ assert_equal(3, set.size)
+ assert_equal(array.uniq.sort, set.sort)
+ end
+
+ def test_reset
+ [Set, Class.new(Set)].each { |klass|
+ a = [1, 2]
+ b = [1]
+ set = klass.new([a, b])
+
+ b << 2
+ set.reset
+
+ assert_equal(klass.new([a]), set, klass.name)
+ }
+ end
+end
+
+class TC_Enumerable < Test::Unit::TestCase
+ def test_to_set
+ ary = [2,5,4,3,2,1,3]
+
+ set = ary.to_set
+ assert_instance_of(Set, set)
+ assert_equal([1,2,3,4,5], set.sort)
+
+ set = ary.to_set { |o| o * -2 }
+ assert_instance_of(Set, set)
+ assert_equal([-10,-8,-6,-4,-2], set.sort)
+
+ assert_same set, set.to_set
+ assert_not_same set, set.to_set { |o| o }
+ end
+end
+
+class TC_Set_Builtin < Test::Unit::TestCase
+ private def should_omit?
+ (RUBY_VERSION.scan(/\d+/).map(&:to_i) <=> [3, 2]) < 0 ||
+ !File.exist?(File.expand_path('../prelude.rb', __dir__))
+ end
+
+ def test_Set
+ omit "skipping the test for the builtin Set" if should_omit?
+
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ assert_nothing_raised do
+ set = Set.new([1, 2])
+ assert_equal('Set', set.class.name)
+ end
+ end;
+
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ assert_nothing_raised do
+ set = Set[1, 2]
+ assert_equal('Set', set.class.name)
+ end
+ end;
+ end
+
+ def test_to_set
+ omit "skipping the test for the builtin Enumerable#to_set" if should_omit?
+
+ assert_separately([], "#{<<~"begin;"}\n#{<<~'end;'}")
+ begin;
+ assert_nothing_raised do
+ set = [1, 2].to_set
+ assert_equal('Set', set.class.name)
+ end
+ end;
+ end
+end
diff --git a/test/test_sorted_set.rb b/test/set/test_sorted_set.rb
index f7ad7af299..f7ad7af299 100644
--- a/test/test_sorted_set.rb
+++ b/test/set/test_sorted_set.rb
diff --git a/test/socket/test_addrinfo.rb b/test/socket/test_addrinfo.rb
index 5bd34cd5eb..c61764d76d 100644
--- a/test/socket/test_addrinfo.rb
+++ b/test/socket/test_addrinfo.rb
@@ -103,7 +103,7 @@ class TestSocketAddrinfo < Test::Unit::TestCase
end
def test_error_message
- e = assert_raise_with_message(SocketError, /getaddrinfo/) do
+ e = assert_raise_with_message(Socket::ResolutionError, /getaddrinfo/) do
Addrinfo.ip("...")
end
m = e.message
@@ -357,7 +357,7 @@ class TestSocketAddrinfo < Test::Unit::TestCase
ai = Addrinfo.unix("/testdir/sock").family_addrinfo("/testdir/sock2")
assert_equal("/testdir/sock2", ai.unix_path)
assert_equal(Socket::SOCK_STREAM, ai.socktype)
- assert_raise(SocketError) { Addrinfo.tcp("0.0.0.0", 4649).family_addrinfo("::1", 80) }
+ assert_raise(Socket::ResolutionError) { Addrinfo.tcp("0.0.0.0", 4649).family_addrinfo("::1", 80) }
end
def random_port
@@ -373,8 +373,8 @@ class TestSocketAddrinfo < Test::Unit::TestCase
def errors_addrinuse
errs = [Errno::EADDRINUSE]
- # MinGW fails with "Errno::EACCES: Permission denied - bind(2) for 0.0.0.0:49721"
- errs << Errno::EACCES if /mingw/ =~ RUBY_PLATFORM
+ # Windows fails with "Errno::EACCES: Permission denied - bind(2) for 0.0.0.0:49721"
+ errs << Errno::EACCES if /mingw|mswin/ =~ RUBY_PLATFORM
errs
end
@@ -588,7 +588,7 @@ class TestSocketAddrinfo < Test::Unit::TestCase
assert(ai.ipv4? || ai.send(meth), "ai=#{addr_exp}; ai.ipv4? || .#{meth}")
rescue Test::Unit::AssertionFailedError
if /aix/ =~ RUBY_PLATFORM
- skip "Known bug in IN6_IS_ADDR_V4COMPAT and IN6_IS_ADDR_V4MAPPED on AIX"
+ omit "Known bug in IN6_IS_ADDR_V4COMPAT and IN6_IS_ADDR_V4MAPPED on AIX"
end
raise $!
end
diff --git a/test/socket/test_basicsocket.rb b/test/socket/test_basicsocket.rb
index 02e393d4e8..8c1b434a83 100644
--- a/test/socket/test_basicsocket.rb
+++ b/test/socket/test_basicsocket.rb
@@ -35,7 +35,7 @@ class TestSocket_BasicSocket < Test::Unit::TestCase
rescue Test::Unit::AssertionFailedError
s.close
if /aix/ =~ RUBY_PLATFORM
- skip "Known bug in getsockopt(2) on AIX"
+ omit "Known bug in getsockopt(2) on AIX"
end
raise $!
end
diff --git a/test/socket/test_nonblock.rb b/test/socket/test_nonblock.rb
index 5d45593439..5a4688bac3 100644
--- a/test/socket/test_nonblock.rb
+++ b/test/socket/test_nonblock.rb
@@ -279,7 +279,7 @@ class TestSocketNonblock < Test::Unit::TestCase
s1.sendmsg_nonblock("a" * 100000)
}
rescue NotImplementedError, Errno::ENOSYS
- skip "sendmsg not implemented on this platform: #{$!}"
+ omit "sendmsg not implemented on this platform: #{$!}"
rescue Errno::EMSGSIZE
# UDP has 64K limit (if no Jumbograms). No problem.
rescue Errno::EWOULDBLOCK
@@ -307,11 +307,13 @@ class TestSocketNonblock < Test::Unit::TestCase
loop { s1.sendmsg_nonblock(buf) }
end
end
- rescue NotImplementedError, Errno::ENOSYS, Errno::EPROTONOSUPPORT
- skip "UNIXSocket.pair(:SEQPACKET) not implemented on this platform: #{$!}"
+ rescue NotImplementedError, Errno::ENOSYS, Errno::EPROTONOSUPPORT, Errno::EPROTOTYPE
+ omit "UNIXSocket.pair(:SEQPACKET) not implemented on this platform: #{$!}"
end
def test_sendmsg_nonblock_no_exception
+ omit "AF_UNIX + SEQPACKET is not supported on windows" if /mswin|mingw/ =~ RUBY_PLATFORM
+
buf = '*' * 4096
UNIXSocket.pair(:SEQPACKET) do |s1, s2|
n = 0
@@ -329,7 +331,7 @@ class TestSocketNonblock < Test::Unit::TestCase
end
end
rescue NotImplementedError, Errno::ENOSYS, Errno::EPROTONOSUPPORT
- skip "UNIXSocket.pair(:SEQPACKET) not implemented on this platform: #{$!}"
+ omit "UNIXSocket.pair(:SEQPACKET) not implemented on this platform: #{$!}"
end
end
@@ -338,7 +340,7 @@ class TestSocketNonblock < Test::Unit::TestCase
begin
s1.recvmsg_nonblock(4096)
rescue NotImplementedError
- skip "recvmsg not implemented on this platform."
+ omit "recvmsg not implemented on this platform."
rescue Errno::EWOULDBLOCK
assert_kind_of(IO::WaitReadable, $!)
end
diff --git a/test/socket/test_socket.rb b/test/socket/test_socket.rb
index 9807db3674..6a057e866f 100644
--- a/test/socket/test_socket.rb
+++ b/test/socket/test_socket.rb
@@ -1,9 +1,5 @@
# frozen_string_literal: true
-# tentatively disabled due to IPv6 configuration issue on Solaris CI
-# http://rubyci.s3.amazonaws.com/solaris10-gcc/ruby-master/log/20210729T040002Z.fail.html.gz
-return if /solaris/ =~ RUBY_PLATFORM
-
begin
require "socket"
require "tmpdir"
@@ -95,20 +91,20 @@ class TestSocket < Test::Unit::TestCase
def test_getaddrinfo
# This should not send a DNS query because AF_UNIX.
- assert_raise(SocketError) { Socket.getaddrinfo("www.kame.net", 80, "AF_UNIX") }
+ assert_raise(Socket::ResolutionError) { Socket.getaddrinfo("www.kame.net", 80, "AF_UNIX") }
end
def test_getaddrinfo_raises_no_errors_on_port_argument_of_0 # [ruby-core:29427]
assert_nothing_raised('[ruby-core:29427]'){ Socket.getaddrinfo('localhost', 0, Socket::AF_INET, Socket::SOCK_STREAM, nil, Socket::AI_CANONNAME) }
assert_nothing_raised('[ruby-core:29427]'){ Socket.getaddrinfo('localhost', '0', Socket::AF_INET, Socket::SOCK_STREAM, nil, Socket::AI_CANONNAME) }
assert_nothing_raised('[ruby-core:29427]'){ Socket.getaddrinfo('localhost', '00', Socket::AF_INET, Socket::SOCK_STREAM, nil, Socket::AI_CANONNAME) }
- assert_raise(SocketError, '[ruby-core:29427]'){ Socket.getaddrinfo(nil, nil, Socket::AF_INET, Socket::SOCK_STREAM, nil, Socket::AI_CANONNAME) }
+ assert_raise(Socket::ResolutionError, '[ruby-core:29427]'){ Socket.getaddrinfo(nil, nil, Socket::AF_INET, Socket::SOCK_STREAM, nil, Socket::AI_CANONNAME) }
assert_nothing_raised('[ruby-core:29427]'){ TCPServer.open('localhost', 0) {} }
end
def test_getnameinfo
- assert_raise(SocketError) { Socket.getnameinfo(["AF_UNIX", 80, "0.0.0.0"]) }
+ assert_raise(Socket::ResolutionError) { Socket.getnameinfo(["AF_UNIX", 80, "0.0.0.0"]) }
assert_raise(ArgumentError) {Socket.getnameinfo(["AF_INET", "http\0", "example.net"])}
assert_raise(ArgumentError) {Socket.getnameinfo(["AF_INET", "http", "example.net\0"])}
end
@@ -344,10 +340,14 @@ class TestSocket < Test::Unit::TestCase
end
def test_udp_server
+ # http://rubyci.s3.amazonaws.com/rhel_zlinux/ruby-master/log/20230312T023302Z.fail.html.gz
+ # Errno::EHOSTUNREACH: No route to host - recvmsg(2)
+ omit if 'rhel_zlinux' == ENV['RUBYCI_NICKNAME']
+
begin
ifaddrs = Socket.getifaddrs
rescue NotImplementedError
- skip "Socket.getifaddrs not implemented"
+ omit "Socket.getifaddrs not implemented"
end
ifconfig = nil
@@ -441,19 +441,18 @@ class TestSocket < Test::Unit::TestCase
}
rescue NotImplementedError, Errno::ENOSYS
skipped = true
- skip "need sendmsg and recvmsg: #{$!}"
+ omit "need sendmsg and recvmsg: #{$!}"
rescue RuntimeError
skipped = true
- skip "UDP server is no response: #{$!}"
+ omit "UDP server is no response: #{$!}"
ensure
if th
- if skipped
- Thread.kill th unless th.join(10)
- else
+ unless skipped
Addrinfo.udp("127.0.0.1", port).connect {|s| s.sendmsg "exit" }
- unless th.join(10)
- Thread.kill th
- th.join(10)
+ end
+ unless th.join(10)
+ th.kill.join(10)
+ unless skipped
raise "thread killed"
end
end
@@ -490,13 +489,14 @@ class TestSocket < Test::Unit::TestCase
end while IO.select([r], nil, nil, 0.1).nil?
n
end
- timeout = (defined?(RubyVM::JIT) && RubyVM::JIT.enabled? ? 120 : 30) # for --jit-wait
+ timeout = (defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled? ? 120 : 30) # for --jit-wait
assert_equal([[s1],[],[]], IO.select([s1], nil, nil, timeout))
msg, _, _, stamp = s1.recvmsg
assert_equal("a", msg)
assert(stamp.cmsg_is?(:SOCKET, type))
w.close # stop th
n = th.value
+ th = nil
n > 1 and
warn "UDP packet loss for #{type} over loopback, #{n} tries needed"
t2 = Time.now.strftime("%Y-%m-%d")
@@ -505,6 +505,10 @@ class TestSocket < Test::Unit::TestCase
t = stamp.timestamp
assert_match(pat, t.strftime("%Y-%m-%d"))
stamp
+ ensure
+ if th and !th.join(10)
+ th.kill.join(10)
+ end
end
end
@@ -587,7 +591,7 @@ class TestSocket < Test::Unit::TestCase
ensure
serv_thread.value.close
server.close
- end
+ end unless RUBY_PLATFORM.include?("freebsd")
def test_connect_timeout
host = "127.0.0.1"
@@ -766,4 +770,251 @@ class TestSocket < Test::Unit::TestCase
s2.close
end
+ def test_resolurion_error_error_code
+ begin
+ Socket.getaddrinfo("example.com", 80, "AF_UNIX")
+ rescue => e
+ assert_include([Socket::EAI_FAMILY, Socket::EAI_FAIL], e.error_code)
+ end
+ end
+
+ def test_tcp_socket_v6_hostname_resolved_earlier
+ opts = %w[-rsocket -W1]
+ assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}"
+
+ begin;
+ begin
+ server = TCPServer.new("::1", 0)
+ rescue Errno::EADDRNOTAVAIL # IPv6 is not supported
+ exit
+ end
+
+ server_thread = Thread.new { server.accept }
+ port = server.addr[1]
+
+ Addrinfo.define_singleton_method(:getaddrinfo) do |_, _, family, *_|
+ case family
+ when Socket::AF_INET6 then [Addrinfo.tcp("::1", port)]
+ when Socket::AF_INET then sleep(10); [Addrinfo.tcp("127.0.0.1", port)]
+ end
+ end
+
+ socket = Socket.tcp("localhost", port)
+ assert_true(socket.remote_address.ipv6?)
+ server_thread.value.close
+ server.close
+ socket.close if socket && !socket.closed?
+ end;
+ end
+
+ def test_tcp_socket_v4_hostname_resolved_earlier
+ opts = %w[-rsocket -W1]
+ assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}"
+
+ begin;
+ server = TCPServer.new("127.0.0.1", 0)
+ port = server.addr[1]
+
+ Addrinfo.define_singleton_method(:getaddrinfo) do |_, _, family, *_|
+ case family
+ when Socket::AF_INET6 then sleep(10); [Addrinfo.tcp("::1", port)]
+ when Socket::AF_INET then [Addrinfo.tcp("127.0.0.1", port)]
+ end
+ end
+
+ server_thread = Thread.new { server.accept }
+ socket = Socket.tcp("localhost", port)
+ assert_true(socket.remote_address.ipv4?)
+ server_thread.value.close
+ server.close
+ socket.close if socket && !socket.closed?
+ end;
+ end
+
+ def test_tcp_socket_v6_hostname_resolved_in_resolution_delay
+ opts = %w[-rsocket -W1]
+ assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}"
+
+ begin;
+ begin
+ server = TCPServer.new("::1", 0)
+ rescue Errno::EADDRNOTAVAIL # IPv6 is not supported
+ exit
+ end
+
+ port = server.addr[1]
+ delay_time = 0.025 # Socket::RESOLUTION_DELAY (private) is 0.05
+
+ Addrinfo.define_singleton_method(:getaddrinfo) do |_, _, family, *_|
+ case family
+ when Socket::AF_INET6 then sleep(delay_time); [Addrinfo.tcp("::1", port)]
+ when Socket::AF_INET then [Addrinfo.tcp("127.0.0.1", port)]
+ end
+ end
+
+ server_thread = Thread.new { server.accept }
+ socket = Socket.tcp("localhost", port)
+ assert_true(socket.remote_address.ipv6?)
+ server_thread.value.close
+ server.close
+ socket.close if socket && !socket.closed?
+ end;
+ end
+
+ def test_tcp_socket_v6_hostname_resolved_earlier_and_v6_server_is_not_listening
+ opts = %w[-rsocket -W1]
+ assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}"
+
+ begin;
+ ipv4_address = "127.0.0.1"
+ ipv4_server = Socket.new(Socket::AF_INET, :STREAM)
+ ipv4_server.bind(Socket.pack_sockaddr_in(0, ipv4_address))
+ port = ipv4_server.connect_address.ip_port
+
+ Addrinfo.define_singleton_method(:getaddrinfo) do |_, _, family, *_|
+ case family
+ when Socket::AF_INET6 then [Addrinfo.tcp("::1", port)]
+ when Socket::AF_INET then sleep(0.001); [Addrinfo.tcp(ipv4_address, port)]
+ end
+ end
+
+ ipv4_server_thread = Thread.new { ipv4_server.listen(1); ipv4_server.accept }
+ socket = Socket.tcp("localhost", port)
+ assert_equal(ipv4_address, socket.remote_address.ip_address)
+
+ accepted, _ = ipv4_server_thread.value
+ accepted.close
+ ipv4_server.close
+ socket.close if socket && !socket.closed?
+ end;
+ end
+
+ def test_tcp_socket_resolv_timeout
+ opts = %w[-rsocket -W1]
+ assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}"
+
+ begin;
+ Addrinfo.define_singleton_method(:getaddrinfo) { |*_| sleep }
+ port = TCPServer.new("localhost", 0).addr[1]
+
+ assert_raise(Errno::ETIMEDOUT) do
+ Socket.tcp("localhost", port, resolv_timeout: 0.01)
+ end
+ end;
+ end
+
+ def test_tcp_socket_resolv_timeout_with_connection_failure
+ opts = %w[-rsocket -W1]
+ assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}"
+
+ begin;
+ server = TCPServer.new("127.0.0.1", 12345)
+ _, port, = server.addr
+
+ Addrinfo.define_singleton_method(:getaddrinfo) do |_, _, family, *_|
+ if family == Socket::AF_INET6
+ sleep
+ else
+ [Addrinfo.tcp("127.0.0.1", port)]
+ end
+ end
+
+ server.close
+
+ assert_raise(Errno::ETIMEDOUT) do
+ Socket.tcp("localhost", port, resolv_timeout: 0.01)
+ end
+ end;
+ end
+
+ def test_tcp_socket_one_hostname_resolution_succeeded_at_least
+ opts = %w[-rsocket -W1]
+ assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}"
+
+ begin;
+ begin
+ server = TCPServer.new("::1", 0)
+ rescue Errno::EADDRNOTAVAIL # IPv6 is not supported
+ exit
+ end
+
+ port = server.addr[1]
+
+ Addrinfo.define_singleton_method(:getaddrinfo) do |_, _, family, *_|
+ case family
+ when Socket::AF_INET6 then [Addrinfo.tcp("::1", port)]
+ when Socket::AF_INET then sleep(0.001); raise SocketError
+ end
+ end
+
+ server_thread = Thread.new { server.accept }
+ socket = nil
+
+ assert_nothing_raised do
+ socket = Socket.tcp("localhost", port)
+ end
+
+ server_thread.value.close
+ server.close
+ socket.close if socket && !socket.closed?
+ end;
+ end
+
+ def test_tcp_socket_all_hostname_resolution_failed
+ opts = %w[-rsocket -W1]
+ assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}"
+
+ begin;
+ Addrinfo.define_singleton_method(:getaddrinfo) do |_, _, family, *_|
+ case family
+ when Socket::AF_INET6 then raise SocketError
+ when Socket::AF_INET then sleep(0.001); raise SocketError, "Last hostname resolution error"
+ end
+ end
+ port = TCPServer.new("localhost", 0).addr[1]
+
+ assert_raise_with_message(SocketError, "Last hostname resolution error") do
+ Socket.tcp("localhost", port)
+ end
+ end;
+ end
+
+ def test_tcp_socket_v6_address_passed
+ opts = %w[-rsocket -W1]
+ assert_separately opts, "#{<<-"begin;"}\n#{<<-'end;'}"
+
+ begin;
+ begin
+ server = TCPServer.new("::1", 0)
+ rescue Errno::EADDRNOTAVAIL # IPv6 is not supported
+ exit
+ end
+
+ _, port, = server.addr
+
+ Addrinfo.define_singleton_method(:getaddrinfo) do |*_|
+ [Addrinfo.tcp("::1", port)]
+ end
+
+ server_thread = Thread.new { server.accept }
+ socket = Socket.tcp("::1", port)
+
+ assert_true(socket.remote_address.ipv6?)
+ server_thread.value.close
+ server.close
+ socket.close if socket && !socket.closed?
+ end;
+ end
+
+ def test_tcp_socket_fast_fallback_is_false
+ server = TCPServer.new("127.0.0.1", 0)
+ _, port, = server.addr
+ server_thread = Thread.new { server.accept }
+ socket = Socket.tcp("127.0.0.1", port, fast_fallback: false)
+
+ assert_true(socket.remote_address.ipv4?)
+ server_thread.value.close
+ server.close
+ socket.close if socket && !socket.closed?
+ end
end if defined?(Socket)
diff --git a/test/socket/test_sockopt.rb b/test/socket/test_sockopt.rb
index f166027d26..7e343e8c36 100644
--- a/test/socket/test_sockopt.rb
+++ b/test/socket/test_sockopt.rb
@@ -34,7 +34,7 @@ class TestSocketOption < Test::Unit::TestCase
}
rescue TypeError
if /aix/ =~ RUBY_PLATFORM
- skip "Known bug in getsockopt(2) on AIX"
+ omit "Known bug in getsockopt(2) on AIX"
end
raise $!
end
diff --git a/test/socket/test_tcp.rb b/test/socket/test_tcp.rb
index 9aa716f7ec..6a016da71d 100644
--- a/test/socket/test_tcp.rb
+++ b/test/socket/test_tcp.rb
@@ -70,7 +70,7 @@ class TestSocket_TCPSocket < Test::Unit::TestCase
end
def test_initialize_connect_timeout
- assert_raise(Errno::ETIMEDOUT) do
+ assert_raise(IO::TimeoutError, Errno::ENETUNREACH, Errno::EACCES) do
TCPSocket.new("192.0.2.1", 80, connect_timeout: 0)
end
end
diff --git a/test/socket/test_udp.rb b/test/socket/test_udp.rb
index f060b65f2c..4b2b7ab976 100644
--- a/test/socket/test_udp.rb
+++ b/test/socket/test_udp.rb
@@ -25,7 +25,7 @@ class TestSocket_UDPSocket < Test::Unit::TestCase
assert_match(/AF_INET6\b/, sock.inspect)
}
rescue Errno::EAFNOSUPPORT
- skip 'AF_INET6 not supported by kernel'
+ omit 'AF_INET6 not supported by kernel'
end
end
end
diff --git a/test/socket/test_unix.rb b/test/socket/test_unix.rb
index 8c74d0c939..3e7d85befc 100644
--- a/test/socket/test_unix.rb
+++ b/test/socket/test_unix.rb
@@ -60,6 +60,8 @@ class TestSocket_UNIXSocket < Test::Unit::TestCase
assert_not_equal s1.fileno, r.fileno
r.close
end
+ rescue NotImplementedError => error
+ omit error.message
end
def test_fd_passing_n
@@ -150,7 +152,7 @@ class TestSocket_UNIXSocket < Test::Unit::TestCase
lock = Thread::Mutex.new
nr = 0
x = 2
- y = 1000
+ y = 400
begin
s1.send_io(nil)
rescue NotImplementedError
@@ -334,62 +336,70 @@ class TestSocket_UNIXSocket < Test::Unit::TestCase
end
def test_noname_path
- s1, s2 = UNIXSocket.pair
- assert_equal("", s1.path)
- assert_equal("", s2.path)
- ensure
- s1.close
- s2.close
+ if /mswin|mingw/ =~ RUBY_PLATFORM
+ omit "unnamed pipe is emulated on windows"
+ end
+
+ UNIXSocket.pair do |s1, s2|
+ assert_equal("", s1.path)
+ assert_equal("", s2.path)
+ end
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
+ if /mswin|mingw/ =~ RUBY_PLATFORM
+ omit "unnamed pipe is emulated on windows"
+ end
+
+ UNIXSocket.pair do |s1, s2|
+ assert_equal(["AF_UNIX", ""], s1.addr)
+ assert_equal(["AF_UNIX", ""], s2.addr)
+ end
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
+ if /mswin|mingw/ =~ RUBY_PLATFORM
+ omit "unnamed pipe is emulated on windows"
+ end
+
+ UNIXSocket.pair do |s1, s2|
+ assert_equal(["AF_UNIX", ""], s1.peeraddr)
+ assert_equal(["AF_UNIX", ""], s2.peeraddr)
+ end
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
+ if /mswin|mingw/ =~ RUBY_PLATFORM
+ omit "unnamed pipe is emulated on windows"
+ end
+
+ UNIXSocket.pair do |s1, s2|
+ 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) != ""
+ end
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
+ if /mswin|mingw/ =~ RUBY_PLATFORM
+ omit "unnamed pipe is emulated on windows"
+ end
+
+ UNIXSocket.pair do |s1, s2|
+ s2.write("a")
+ assert_equal(["a", ["AF_UNIX", ""]], s1.recvfrom(10))
+ end
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
+ UNIXSocket.pair do |s1, s2|
+ s2.write("a")
+ IO.select [s1]
+ assert_equal("a", s1.recv_nonblock(10))
+ end
end
def test_too_long_path
@@ -410,9 +420,10 @@ class TestSocket_UNIXSocket < Test::Unit::TestCase
s1.recv_nonblock(10)
fail
rescue => e
- assert(IO::EAGAINWaitReadable === e)
- assert(IO::WaitReadable === e)
+ assert_kind_of(IO::EWOULDBLOCKWaitReadable, e)
+ assert_kind_of(IO::WaitReadable, e)
end
+
s2.send("", 0)
s2.send("haha", 0)
s2.send("", 0)
@@ -429,12 +440,79 @@ class TestSocket_UNIXSocket < Test::Unit::TestCase
rv = s1.recv(100, 0, buf)
assert_equal buf.object_id, rv.object_id
assert_equal "BBBBBB", rv
+ rescue Errno::EPROTOTYPE => error
+ omit error.message
+ ensure
+ s1.close if s1
+ s2.close if s2
+ end
+
+ def test_stream_pair
+ s1, s2 = UNIXSocket.pair(Socket::SOCK_STREAM)
+ begin
+ s1.recv_nonblock(10)
+ fail
+ rescue => e
+ assert_kind_of(IO::EWOULDBLOCKWaitReadable, e)
+ assert_kind_of(IO::WaitReadable, e)
+ end
+
+ s2.send("", 0)
+ s2.send("haha", 0)
+ assert_equal("haha", s1.recv(10))
+ assert_raise(IO::EWOULDBLOCKWaitReadable) { s1.recv_nonblock(10) }
+
+ buf = "".dup
+ s2.send("BBBBBB", 0)
+ IO.select([s1])
+ rv = s1.recv(100, 0, buf)
+ assert_equal buf.object_id, rv.object_id
+ assert_equal "BBBBBB", rv
+
+ s2.close
+ assert_nil(s1.recv(10))
+ rescue Errno::EPROTOTYPE => error
+ omit error.message
+ ensure
+ s1.close if s1
+ s2.close if s2
+ end
+
+ def test_seqpacket_pair
+ s1, s2 = UNIXSocket.pair(Socket::SOCK_SEQPACKET)
+ begin
+ s1.recv_nonblock(10)
+ fail
+ rescue => e
+ assert_kind_of(IO::EWOULDBLOCKWaitReadable, e)
+ assert_kind_of(IO::WaitReadable, e)
+ end
+
+ s2.send("haha", 0)
+ assert_equal("haha", s1.recv(10))
+ assert_raise(IO::EWOULDBLOCKWaitReadable) { s1.recv_nonblock(10) }
+
+ buf = "".dup
+ s2.send("BBBBBB", 0)
+ IO.select([s1])
+ rv = s1.recv(100, 0, buf)
+ assert_equal buf.object_id, rv.object_id
+ assert_equal "BBBBBB", rv
+
+ s2.close
+ assert_nil(s1.recv(10))
+ rescue Errno::EPROTOTYPE, Errno::EPROTONOSUPPORT => error
+ omit error.message
ensure
s1.close if s1
s2.close if s2
end
def test_dgram_pair_sendrecvmsg_errno_set
+ if /mswin|mingw/ =~ RUBY_PLATFORM
+ omit("AF_UNIX + SOCK_DGRAM is not supported on windows")
+ end
+
s1, s2 = to_close = UNIXSocket.pair(Socket::SOCK_DGRAM)
pipe = IO.pipe
to_close.concat(pipe)
@@ -457,9 +535,17 @@ class TestSocket_UNIXSocket < Test::Unit::TestCase
end
def test_epipe # [ruby-dev:34619]
+ # This is a good example of why reporting the exact `errno` is a terrible
+ # idea for platform abstractions.
+ if RUBY_PLATFORM =~ /mswin|mingw/
+ error = Errno::ESHUTDOWN
+ else
+ error = Errno::EPIPE
+ end
+
UNIXSocket.pair {|s1, s2|
s1.shutdown(Socket::SHUT_WR)
- assert_raise(Errno::EPIPE) { s1.write "a" }
+ assert_raise(error) { s1.write "a" }
assert_equal(nil, s2.read(1))
s2.write "a"
assert_equal("a", s1.read(1))
@@ -493,6 +579,45 @@ class TestSocket_UNIXSocket < Test::Unit::TestCase
}
end
+ if /mingw|mswin/ =~ RUBY_PLATFORM
+
+ def test_unix_socket_with_encoding
+ Dir.mktmpdir do |tmpdir|
+ path = "#{tmpdir}/sockäöü".encode("cp850")
+ UNIXServer.open(path) do |serv|
+ assert File.socket?(path)
+ assert File.stat(path).socket?
+ assert File.lstat(path).socket?
+ assert_equal path.encode("utf-8"), serv.path
+ UNIXSocket.open(path) do |s1|
+ s2 = serv.accept
+ s2.close
+ end
+ end
+ end
+ end
+
+ def test_windows_unix_socket_pair_with_umlaut
+ otmp = ENV['TMP']
+ ENV['TMP'] = File.join(Dir.tmpdir, "äöü€")
+ FileUtils.mkdir_p ENV['TMP']
+
+ s1, = UNIXSocket.pair
+ assert !s1.path.empty?
+ assert !File.exist?(s1.path)
+ ensure
+ FileUtils.rm_rf ENV['TMP']
+ ENV['TMP'] = otmp
+ end
+
+ def test_windows_unix_socket_pair_paths
+ s1, s2 = UNIXSocket.pair
+ assert !s1.path.empty?
+ assert s2.path.empty?
+ assert !File.exist?(s1.path)
+ end
+ end
+
def test_initialize
Dir.mktmpdir {|d|
Socket.open(Socket::AF_UNIX, Socket::SOCK_STREAM, 0) {|s|
diff --git a/test/stringio/test_ractor.rb b/test/stringio/test_ractor.rb
index 1c334e2c3f..4a2033bc1f 100644
--- a/test/stringio/test_ractor.rb
+++ b/test/stringio/test_ractor.rb
@@ -11,7 +11,7 @@ class TestStringIOInRactor < Test::Unit::TestCase
require "stringio"
$VERBOSE = nil
r = Ractor.new do
- io = StringIO.new("")
+ io = StringIO.new(+"")
io.puts "abc"
io.truncate(0)
io.puts "def"
diff --git a/test/stringio/test_stringio.rb b/test/stringio/test_stringio.rb
index e0b4504b54..aeccac2577 100644
--- a/test/stringio/test_stringio.rb
+++ b/test/stringio/test_stringio.rb
@@ -14,14 +14,19 @@ class TestStringIO < Test::Unit::TestCase
include TestEOF::Seek
+ def test_version
+ assert_kind_of(String, StringIO::VERSION)
+ end
+
def test_initialize
assert_kind_of StringIO, StringIO.new
assert_kind_of StringIO, StringIO.new('str')
assert_kind_of StringIO, StringIO.new('str', 'r+')
+ assert_kind_of StringIO, StringIO.new(nil)
assert_raise(ArgumentError) { StringIO.new('', 'x') }
assert_raise(ArgumentError) { StringIO.new('', 'rx') }
assert_raise(ArgumentError) { StringIO.new('', 'rbt') }
- assert_raise(TypeError) { StringIO.new(nil) }
+ assert_raise(TypeError) { StringIO.new(Object) }
o = Object.new
def o.to_str
@@ -36,14 +41,21 @@ class TestStringIO < Test::Unit::TestCase
assert_kind_of StringIO, StringIO.new(o)
end
+ def test_null
+ io = StringIO.new(nil)
+ assert_nil io.gets
+ io.puts "abc"
+ assert_nil io.string
+ end
+
def test_truncate
io = StringIO.new("")
io.puts "abc"
- io.truncate(0)
+ assert_equal(0, 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, io.truncate(10))
assert_equal("\0\0\0\0def\n\0\0", io.string)
end
@@ -84,6 +96,14 @@ class TestStringIO < Test::Unit::TestCase
assert_string("", Encoding::UTF_8, StringIO.new("foo").gets(0))
end
+ def test_gets_utf_16
+ stringio = StringIO.new("line1\nline2\nline3\n".encode("utf-16le"))
+ assert_equal("line1\n".encode("utf-16le"), stringio.gets)
+ assert_equal("line2\n".encode("utf-16le"), stringio.gets)
+ assert_equal("line3\n".encode("utf-16le"), stringio.gets)
+ assert_nil(stringio.gets)
+ end
+
def test_gets_chomp
assert_equal(nil, StringIO.new("").gets(chomp: true))
assert_equal("", StringIO.new("\n").gets(chomp: true))
@@ -92,13 +112,15 @@ class TestStringIO < Test::Unit::TestCase
assert_equal("a", StringIO.new("a").gets(chomp: true))
assert_equal("a", StringIO.new("a\nb").gets(chomp: true))
assert_equal("abc", StringIO.new("abc\n\ndef\n").gets(chomp: true))
- assert_equal("abc\n\ndef", StringIO.new("abc\n\ndef\n").gets(nil, chomp: true))
- assert_equal("abc\n", StringIO.new("abc\n\ndef\n").gets("", chomp: true))
+ assert_equal("abc\n\ndef\n", StringIO.new("abc\n\ndef\n").gets(nil, chomp: true))
+ assert_equal("abc", StringIO.new("abc\n\ndef\n").gets("", chomp: true))
stringio = StringIO.new("abc\n\ndef\n")
- assert_equal("abc\n", stringio.gets("", chomp: true))
- assert_equal("def", stringio.gets("", chomp: true))
+ assert_equal("abc", stringio.gets("", chomp: true))
+ assert_equal("def\n", stringio.gets("", chomp: true))
assert_string("", Encoding::UTF_8, StringIO.new("\n").gets(chomp: true))
+
+ assert_equal("", StringIO.new("ab").gets("ab", chomp: true))
end
def test_gets_chomp_eol
@@ -109,11 +131,11 @@ class TestStringIO < Test::Unit::TestCase
assert_equal("a", StringIO.new("a").gets(chomp: true))
assert_equal("a", StringIO.new("a\r\nb").gets(chomp: true))
assert_equal("abc", StringIO.new("abc\r\n\r\ndef\r\n").gets(chomp: true))
- assert_equal("abc\r\n\r\ndef", StringIO.new("abc\r\n\r\ndef\r\n").gets(nil, chomp: true))
- assert_equal("abc\r\n", StringIO.new("abc\r\n\r\ndef\r\n").gets("", chomp: true))
+ assert_equal("abc\r\n\r\ndef\r\n", StringIO.new("abc\r\n\r\ndef\r\n").gets(nil, chomp: true))
+ assert_equal("abc", StringIO.new("abc\r\n\r\ndef\r\n").gets("", chomp: true))
stringio = StringIO.new("abc\r\n\r\ndef\r\n")
- assert_equal("abc\r\n", stringio.gets("", chomp: true))
- assert_equal("def", stringio.gets("", chomp: true))
+ assert_equal("abc", stringio.gets("", chomp: true))
+ assert_equal("def\r\n", stringio.gets("", chomp: true))
end
def test_readlines
@@ -223,7 +245,7 @@ class TestStringIO < Test::Unit::TestCase
def test_write_integer_overflow
f = StringIO.new
- f.pos = RbConfig::LIMITS["LONG_MAX"]
+ f.pos = StringIO::MAX_LENGTH
assert_raise(ArgumentError) {
f.write("pos + len overflows")
}
@@ -256,6 +278,12 @@ class TestStringIO < Test::Unit::TestCase
f.set_encoding(Encoding::ASCII_8BIT)
}
assert_equal("foo\x83".b, f.gets)
+
+ f = StringIO.new()
+ f.set_encoding("ISO-8859-16:ISO-8859-1")
+ assert_equal(Encoding::ISO_8859_16, f.external_encoding)
+ assert_equal(Encoding::ISO_8859_16, f.string.encoding)
+ assert_nil(f.internal_encoding)
end
def test_mode_error
@@ -584,20 +612,30 @@ class TestStringIO < Test::Unit::TestCase
end
end
+ def test_each_string_sep
+ f = StringIO.new('a||b||c')
+ assert_equal(["a||", "b||", "c"], f.each("||").to_a)
+ f.rewind
+ assert_equal(["a", "b", "c"], f.each("||", chomp: true).to_a)
+ end
+
def test_each
f = StringIO.new("foo\nbar\nbaz\n")
assert_equal(["foo\n", "bar\n", "baz\n"], f.each.to_a)
f.rewind
assert_equal(["foo", "bar", "baz"], f.each(chomp: true).to_a)
- f = StringIO.new("foo\nbar\n\nbaz\n")
- assert_equal(["foo\nbar\n\n", "baz\n"], f.each("").to_a)
+ f = StringIO.new("foo\nbar\n\n\nbaz\n")
+ assert_equal(["foo\nbar\n\n\n", "baz\n"], f.each("").to_a)
f.rewind
- assert_equal(["foo\nbar\n", "baz"], f.each("", chomp: true).to_a)
+ assert_equal(["foo\nbar", "baz\n"], f.each("", chomp: true).to_a)
- f = StringIO.new("foo\r\nbar\r\n\r\nbaz\r\n")
- assert_equal(["foo\r\nbar\r\n\r\n", "baz\r\n"], f.each("").to_a)
+ f = StringIO.new("foo\r\nbar\r\n\r\n\r\nbaz\r\n")
+ assert_equal(["foo\r\nbar\r\n\r\n\r\n", "baz\r\n"], f.each("").to_a)
f.rewind
- assert_equal(["foo\r\nbar\r\n", "baz"], f.each("", chomp: true).to_a)
+ assert_equal(["foo\r\nbar", "baz\r\n"], f.each("", chomp: true).to_a)
+
+ f = StringIO.new("abc\n\ndef\n")
+ assert_equal(["ab", "c\n", "\nd", "ef", "\n"], f.each(nil, 2, chomp: true).to_a)
end
def test_putc
@@ -662,6 +700,18 @@ class TestStringIO < Test::Unit::TestCase
s.force_encoding(Encoding::US_ASCII)
assert_same(s, f.read(nil, s))
assert_string("", Encoding::UTF_8, s, bug13806)
+
+ bug20418 = '[Bug #20418] ™€®'.b
+ f = StringIO.new(bug20418)
+ s = ""
+ assert_equal(Encoding::UTF_8, s.encoding, bug20418)
+ f.read(4, s)
+ assert_equal(Encoding::UTF_8, s.encoding, bug20418)
+
+ f.rewind
+ s = ""
+ f.read(nil, s)
+ assert_equal(Encoding::ASCII_8BIT, s.encoding, bug20418)
end
def test_readpartial
@@ -673,8 +723,8 @@ class TestStringIO < Test::Unit::TestCase
assert_equal("\u3042\u3044".force_encoding(Encoding::ASCII_8BIT), f.readpartial(f.size))
f.rewind
# not empty buffer
- s = '0123456789'
- assert_equal("\u3042\u3044".force_encoding(Encoding::ASCII_8BIT), f.readpartial(f.size, s))
+ s = '0123456789'.b
+ assert_equal("\u3042\u3044".b, f.readpartial(f.size, s))
end
def test_read_nonblock
@@ -698,8 +748,8 @@ class TestStringIO < Test::Unit::TestCase
assert_equal("\u3042\u3044".force_encoding(Encoding::ASCII_8BIT), f.read_nonblock(f.size))
f.rewind
# not empty buffer
- s = '0123456789'
- assert_equal("\u3042\u3044".force_encoding(Encoding::ASCII_8BIT), f.read_nonblock(f.size, s))
+ s = '0123456789'.b
+ assert_equal("\u3042\u3044".b, f.read_nonblock(f.size, s))
end
def test_sysread
@@ -711,6 +761,32 @@ class TestStringIO < Test::Unit::TestCase
assert_equal Encoding::ASCII_8BIT, f.sysread(3).encoding
end
+ def test_pread
+ f = StringIO.new("pread")
+ f.read
+
+ assert_equal "pre".b, f.pread(3, 0)
+ assert_equal "read".b, f.pread(4, 1)
+ assert_equal Encoding::ASCII_8BIT, f.pread(4, 1).encoding
+
+ buf = "".b
+ f.pread(3, 0, buf)
+ assert_equal "pre".b, buf
+ f.pread(4, 1, buf)
+ assert_equal "read".b, buf
+
+ assert_raise(EOFError) { f.pread(1, 5) }
+ assert_raise(ArgumentError) { f.pread(-1, 0) }
+ assert_raise(Errno::EINVAL) { f.pread(3, -1) }
+
+ assert_equal "".b, StringIO.new("").pread(0, 0)
+ assert_equal "".b, StringIO.new("").pread(0, -10)
+
+ buf = "stale".b
+ assert_equal "stale".b, StringIO.new("").pread(0, 0, buf)
+ assert_equal "stale".b, buf
+ end
+
def test_size
f = StringIO.new("1234")
assert_equal(4, f.size)
@@ -757,6 +833,15 @@ class TestStringIO < Test::Unit::TestCase
assert_equal("b""\0""a", s.string)
end
+ def test_ungetc_fill
+ count = 100
+ s = StringIO.new
+ s.print 'a' * count
+ s.ungetc('b' * (count * 5))
+ assert_equal((count * 5), s.string.size)
+ assert_match(/\Ab+\z/, s.string)
+ end
+
def test_ungetbyte_pos
b = '\\b00010001 \\B00010001 \\b1 \\B1 \\b000100011'
s = StringIO.new( b )
@@ -782,6 +867,15 @@ class TestStringIO < Test::Unit::TestCase
assert_equal("b""\0""a", s.string)
end
+ def test_ungetbyte_fill
+ count = 100
+ s = StringIO.new
+ s.print 'a' * count
+ s.ungetbyte('b' * (count * 5))
+ assert_equal((count * 5), s.string.size)
+ assert_match(/\Ab+\z/, s.string)
+ end
+
def test_frozen
s = StringIO.new
s.freeze
@@ -825,18 +919,18 @@ class TestStringIO < Test::Unit::TestCase
end
def test_overflow
- omit if RbConfig::SIZEOF["void*"] > RbConfig::SIZEOF["long"]
- limit = RbConfig::LIMITS["INTPTR_MAX"] - 0x10
+ intptr_max = RbConfig::LIMITS["INTPTR_MAX"]
+ return if intptr_max > StringIO::MAX_LENGTH
+ limit = intptr_max - 0x10
assert_separately(%w[-rstringio], "#{<<-"begin;"}\n#{<<-"end;"}")
begin;
limit = #{limit}
ary = []
- while true
+ begin
x = "a"*0x100000
break if [x].pack("p").unpack("i!")[0] < 0
ary << x
- omit if ary.size > 100
- end
+ end while ary.size <= 100
s = StringIO.new(x)
s.gets("xxx", limit)
assert_equal(0x100000, s.pos)
@@ -880,6 +974,44 @@ class TestStringIO < Test::Unit::TestCase
$VERBOSE = verbose
end
+ def test_coderange_after_overwrite
+ s = StringIO.new("".b)
+
+ s.write("a=b&c=d")
+ s.rewind
+ assert_predicate(s.string, :ascii_only?)
+ s.write "\u{431 43e 433 443 441}"
+ assert_not_predicate(s.string, :ascii_only?)
+
+ s = StringIO.new("\u{3042}")
+ s.rewind
+ assert_not_predicate(s.string, :ascii_only?)
+ s.write('aaaa')
+ assert_predicate(s.string, :ascii_only?)
+ end
+
+ require "objspace"
+ if ObjectSpace.respond_to?(:dump) && ObjectSpace.dump(eval(%{"test"})).include?('"chilled":true') # Ruby 3.4+ chilled strings
+ def test_chilled_string
+ chilled_string = eval(%{""})
+ io = StringIO.new(chilled_string)
+ assert_warning(/literal string will be frozen/) { io << "test" }
+ assert_equal("test", io.string)
+ assert_same(chilled_string, io.string)
+ end
+
+ def test_chilled_string_string_set
+ io = StringIO.new
+ chilled_string = eval(%{""})
+ io.string = chilled_string
+ assert_warning(/literal string will be frozen/) { io << "test" }
+ assert_equal("test", io.string)
+ assert_same(chilled_string, io.string)
+ end
+ end
+
+ private
+
def assert_string(content, encoding, str, mesg = nil)
assert_equal([content, encoding], [str, str.encoding], mesg)
end
diff --git a/test/strscan/test_ractor.rb b/test/strscan/test_ractor.rb
index 480c1ae8a6..a5de7e56ed 100644
--- a/test/strscan/test_ractor.rb
+++ b/test/strscan/test_ractor.rb
@@ -3,7 +3,7 @@ require 'test/unit'
class TestStringScannerRactor < Test::Unit::TestCase
def setup
- pend unless defined? Ractor
+ omit "Ractor not defined" unless defined? Ractor
end
def test_ractor
diff --git a/test/strscan/test_stringscanner.rb b/test/strscan/test_stringscanner.rb
index 6e30be1f7d..9b7b7910d0 100644
--- a/test/strscan/test_stringscanner.rb
+++ b/test/strscan/test_stringscanner.rb
@@ -7,9 +7,30 @@
require 'strscan'
require 'test/unit'
-class TestStringScanner < Test::Unit::TestCase
- def create_string_scanner(string, *args)
- StringScanner.new(string, *args)
+module StringScannerTests
+ def test_peek_byte
+ omit("not implemented on TruffleRuby") if RUBY_ENGINE == "truffleruby"
+ s = create_string_scanner('ab')
+ assert_equal 97, s.peek_byte
+ assert_equal 97, s.scan_byte
+ assert_equal 98, s.peek_byte
+ assert_equal 98, s.scan_byte
+ assert_nil s.peek_byte
+ assert_nil s.scan_byte
+ end
+
+ def test_scan_byte
+ omit("not implemented on TruffleRuby") if RUBY_ENGINE == "truffleruby"
+ s = create_string_scanner('ab')
+ assert_equal 97, s.scan_byte
+ assert_equal 98, s.scan_byte
+ assert_nil s.scan_byte
+
+ str = "\244\242".dup.force_encoding("euc-jp")
+ s = StringScanner.new(str)
+ assert_equal str.getbyte(s.pos), s.scan_byte
+ assert_equal str.getbyte(s.pos), s.scan_byte
+ assert_nil s.scan_byte
end
def test_s_new
@@ -155,8 +176,10 @@ class TestStringScanner < Test::Unit::TestCase
end
def test_string
- s = create_string_scanner('test')
- assert_equal 'test', s.string
+ s = create_string_scanner('test string')
+ assert_equal 'test string', s.string
+ s.scan(/test/)
+ assert_equal 'test string', s.string
s.string = 'a'
assert_equal 'a', s.string
s.scan(/a/)
@@ -207,6 +230,8 @@ class TestStringScanner < Test::Unit::TestCase
end
def test_charpos_not_use_string_methods
+ omit "not supported on TruffleRuby" if RUBY_ENGINE == "truffleruby"
+
string = +'abcädeföghi'
scanner = create_string_scanner(string)
@@ -237,7 +262,7 @@ class TestStringScanner < Test::Unit::TestCase
end
def test_scan
- s = create_string_scanner('stra strb strc', true)
+ s = create_string_scanner("stra strb\0strc", true)
tmp = s.scan(/\w+/)
assert_equal 'stra', tmp
@@ -245,7 +270,7 @@ class TestStringScanner < Test::Unit::TestCase
assert_equal ' ', tmp
assert_equal 'strb', s.scan(/\w+/)
- assert_equal ' ', s.scan(/\s+/)
+ assert_equal "\u0000", s.scan(/\0/)
tmp = s.scan(/\w+/)
assert_equal 'strc', tmp
@@ -287,11 +312,14 @@ class TestStringScanner < Test::Unit::TestCase
end
def test_scan_string
- s = create_string_scanner('stra strb strc')
+ s = create_string_scanner("stra strb\0strc")
assert_equal 'str', s.scan('str')
assert_equal 'str', s[0]
assert_equal 3, s.pos
assert_equal 'a ', s.scan('a ')
+ assert_equal 'strb', s.scan('strb')
+ assert_equal "\u0000", s.scan("\0")
+ assert_equal 'strc', s.scan('strc')
str = 'stra strb strc'.dup
s = create_string_scanner(str, false)
@@ -465,7 +493,10 @@ class TestStringScanner < Test::Unit::TestCase
assert_equal 'foo', s['a']
assert_equal 'bar', s['b']
assert_raise(IndexError) { s['c'] }
- assert_raise_with_message(IndexError, /\u{30c6 30b9 30c8}/) { s["\u{30c6 30b9 30c8}"] }
+ # see https://github.com/jruby/jruby/issues/7644
+ unless RUBY_ENGINE == "jruby" && RbConfig::CONFIG['host_os'] =~ /mswin|win32|mingw/
+ assert_raise_with_message(IndexError, /\u{30c6 30b9 30c8}/) { s["\u{30c6 30b9 30c8}"] }
+ end
end
def test_pre_match
@@ -555,6 +586,16 @@ class TestStringScanner < Test::Unit::TestCase
assert_nil s.matched_size
end
+ def test_empty_encoding_utf8
+ ss = create_string_scanner('')
+ assert_equal(Encoding::UTF_8, ss.rest.encoding)
+ end
+
+ def test_empty_encoding_ascii_8bit
+ ss = create_string_scanner(''.dup.force_encoding("ASCII-8BIT"))
+ assert_equal(Encoding::ASCII_8BIT, ss.rest.encoding)
+ end
+
def test_encoding
ss = create_string_scanner("\xA1\xA2".dup.force_encoding("euc-jp"))
assert_equal(Encoding::EUC_JP, ss.scan(/./e).encoding)
@@ -567,6 +608,8 @@ class TestStringScanner < Test::Unit::TestCase
end
def test_invalid_encoding_string
+ omit "no encoding check on TruffleRuby for scan(String)" if RUBY_ENGINE == "truffleruby"
+
str = "\xA1\xA2".dup.force_encoding("euc-jp")
ss = create_string_scanner(str)
assert_raise(Encoding::CompatibilityError) do
@@ -628,13 +671,47 @@ class TestStringScanner < Test::Unit::TestCase
assert_equal(nil, s.exist?(/e/))
end
- def test_exist_p_string
+ def test_exist_p_invalid_argument
s = create_string_scanner("test string")
assert_raise(TypeError) do
- s.exist?(" ")
+ s.exist?(1)
end
end
+ def test_exist_p_string
+ omit("not implemented on TruffleRuby") if RUBY_ENGINE == "truffleruby"
+ s = create_string_scanner("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_scan_until
+ s = create_string_scanner("Foo Bar\0Baz")
+ assert_equal("Foo", s.scan_until(/Foo/))
+ assert_equal(3, s.pos)
+ assert_equal(" Bar", s.scan_until(/Bar/))
+ assert_equal(7, s.pos)
+ assert_equal(nil, s.skip_until(/Qux/))
+ assert_equal("\u0000Baz", s.scan_until(/Baz/))
+ assert_equal(11, s.pos)
+ end
+
+ def test_scan_until_string
+ omit("not implemented on TruffleRuby") if RUBY_ENGINE == "truffleruby"
+ s = create_string_scanner("Foo Bar\0Baz")
+ assert_equal("Foo", s.scan_until("Foo"))
+ assert_equal(3, s.pos)
+ assert_equal(" Bar", s.scan_until("Bar"))
+ assert_equal(7, s.pos)
+ assert_equal(nil, s.skip_until("Qux"))
+ assert_equal("\u0000Baz", s.scan_until("Baz"))
+ assert_equal(11, s.pos)
+ end
+
def test_skip_until
s = create_string_scanner("Foo Bar Baz")
assert_equal(3, s.skip_until(/Foo/))
@@ -644,6 +721,16 @@ class TestStringScanner < Test::Unit::TestCase
assert_equal(nil, s.skip_until(/Qux/))
end
+ def test_skip_until_string
+ omit("not implemented on TruffleRuby") if RUBY_ENGINE == "truffleruby"
+ s = create_string_scanner("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 = create_string_scanner("Foo Bar Baz")
assert_equal("Foo", s.check_until(/Foo/))
@@ -653,6 +740,16 @@ class TestStringScanner < Test::Unit::TestCase
assert_equal(nil, s.check_until(/Qux/))
end
+ def test_check_until_string
+ omit("not implemented on TruffleRuby") if RUBY_ENGINE == "truffleruby"
+ s = create_string_scanner("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 = create_string_scanner("Foo Bar Baz")
assert_equal(8, s.search_full(/Bar /, false, false))
@@ -665,6 +762,19 @@ class TestStringScanner < Test::Unit::TestCase
assert_equal(11, s.pos)
end
+ def test_search_full_string
+ omit("not implemented on TruffleRuby") if RUBY_ENGINE == "truffleruby"
+ s = create_string_scanner("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 = create_string_scanner("test string")
assert_equal("test st", s.peek(7))
@@ -712,6 +822,8 @@ class TestStringScanner < Test::Unit::TestCase
end
def test_aref_without_regex
+ omit "#[:missing] always raises on TruffleRuby if matched" if RUBY_ENGINE == "truffleruby"
+
s = create_string_scanner('abc')
s.get_byte
assert_nil(s[:c])
@@ -730,8 +842,8 @@ class TestStringScanner < Test::Unit::TestCase
def test_captures
s = create_string_scanner("Timestamp: Fri Dec 12 1975 14:39")
s.scan("Timestamp: ")
- s.scan(/(\w+) (\w+) (\d+) /)
- assert_equal(["Fri", "Dec", "12"], s.captures)
+ s.scan(/(\w+) (\w+) (\d+) (1980)?/)
+ assert_equal(["Fri", "Dec", "12", nil], s.captures)
s.scan(/(\w+) (\w+) (\d+) /)
assert_nil(s.captures)
end
@@ -745,6 +857,42 @@ class TestStringScanner < Test::Unit::TestCase
assert_nil(s.values_at(0, -1, 5, 2))
end
+ def test_scan_aref_repeatedly
+ s = StringScanner.new('test string')
+ assert_equal "test", s.scan(/\w(\w)(\w*)/)
+ assert_equal "test", s[0]
+ assert_equal "e", s[1]
+ assert_equal "st", s[2]
+ assert_nil s.scan(/\w+/)
+ assert_nil s[0]
+ assert_nil s[1]
+ assert_nil s[2]
+ assert_equal " ", s.scan(/\s+/)
+ assert_equal " ", s[0]
+ assert_nil s[1]
+ assert_nil s[2]
+ assert_equal "string", s.scan(/\w(\w)(\w*)/)
+ assert_equal "string", s[0]
+ assert_equal "t", s[1]
+ assert_equal "ring", s[2]
+ end
+
+ def test_named_captures
+ omit("not implemented on TruffleRuby") if ["truffleruby"].include?(RUBY_ENGINE)
+ scan = StringScanner.new("foobarbaz")
+ assert_equal({}, scan.named_captures)
+ assert_equal(9, scan.match?(/(?<f>foo)(?<r>bar)(?<z>baz)/))
+ assert_equal({"f" => "foo", "r" => "bar", "z" => "baz"}, scan.named_captures)
+ end
+end
+
+class TestStringScanner < Test::Unit::TestCase
+ include StringScannerTests
+
+ def create_string_scanner(string, *args)
+ StringScanner.new(string, *args)
+ end
+
def test_fixed_anchor_true
assert_equal(true, StringScanner.new("a", fixed_anchor: true).fixed_anchor?)
end
@@ -759,7 +907,9 @@ class TestStringScanner < Test::Unit::TestCase
end
end
-class TestStringScannerFixedAnchor < TestStringScanner
+class TestStringScannerFixedAnchor < Test::Unit::TestCase
+ include StringScannerTests
+
def create_string_scanner(string, *args)
StringScanner.new(string, fixed_anchor: true)
end
@@ -786,4 +936,12 @@ class TestStringScannerFixedAnchor < TestStringScanner
assert_equal 1, s.skip(/a/)
assert_nil s.skip(/^b/)
end
+
+ # ruby/strscan#86
+ def test_scan_shared_string
+ s = "hellohello"[5..-1]
+ ss = StringScanner.new(s).scan(/hello/)
+
+ assert_equal "hello", ss
+ end
end
diff --git a/test/syslog/test_syslog_logger.rb b/test/syslog/test_syslog_logger.rb
deleted file mode 100644
index d9ffae3901..0000000000
--- a/test/syslog/test_syslog_logger.rb
+++ /dev/null
@@ -1,588 +0,0 @@
-# coding: US-ASCII
-# frozen_string_literal: false
-require 'test/unit'
-require 'tempfile'
-begin
- require 'syslog/logger'
-rescue LoadError
- # skip. see the bottom of this file.
-end
-
-# These tests ensure Syslog::Logger works like Logger
-
-class TestSyslogRootLogger < Test::Unit::TestCase
-
- module MockSyslog
-
- PRIMASK = Syslog::Level.constants.inject(0) { |mask, name| mask | Syslog::Level.const_get(name) }
-
- LEVEL_LABEL_MAP = {
- Syslog::LOG_ALERT => 'ALERT',
- Syslog::LOG_ERR => 'ERR',
- Syslog::LOG_WARNING => 'WARNING',
- Syslog::LOG_NOTICE => 'NOTICE',
- Syslog::LOG_INFO => 'INFO',
- Syslog::LOG_DEBUG => 'DEBUG'
- }
-
- @facility = Syslog::LOG_USER
-
- class << self
-
- attr_reader :facility
- attr_reader :line
- attr_reader :program_name
-
- def log(priority, format, *args)
- level = priority & PRIMASK
- @line = "<#{priority}> #{LEVEL_LABEL_MAP[level]} - #{format % args}"
- end
-
- def open(program_name)
- @program_name = program_name
- end
-
- def reset
- @line = ''
- end
-
- end
- end
-
- Syslog::Logger.syslog = MockSyslog
-
- LEVEL_LABEL_MAP = {
- Logger::DEBUG => 'DEBUG',
- Logger::INFO => 'INFO',
- Logger::WARN => 'WARN',
- Logger::ERROR => 'ERROR',
- Logger::FATAL => 'FATAL',
- Logger::UNKNOWN => 'ANY',
- }
-
- def setup
- @logger = Logger.new(nil)
- end
-
- class Log
- attr_reader :line, :label, :datetime, :pid, :severity, :progname, :msg
- def initialize(line)
- @line = line
- /\A(\w+), \[([^#]*)#(\d+)\]\s+(\w+) -- (\w*): ([\x0-\xff]*)/ =~ @line
- @label, @datetime, @pid, @severity, @progname, @msg = $1, $2, $3, $4, $5, $6
- end
- end
-
- def log_add(severity, msg, progname = nil, &block)
- log(:add, severity, msg, progname, &block)
- end
-
- def log(msg_id, *arg, &block)
- Log.new(log_raw(msg_id, *arg, &block))
- end
-
- def log_raw(msg_id, *arg, &block)
- Tempfile.create(File.basename(__FILE__) + '.log') {|logdev|
- @logger.instance_eval { @logdev = Logger::LogDevice.new(logdev) }
- assert_equal true, @logger.__send__(msg_id, *arg, &block)
- logdev.rewind
- logdev.read
- }
- end
-
- def test_initialize
- assert_equal Logger::DEBUG, @logger.level
- end
-
- def test_custom_formatter
- @logger.formatter = Class.new {
- def call severity, time, progname, msg
- "hi mom!"
- end
- }.new
-
- assert_match(/hi mom!/, log_raw(:fatal, 'fatal level message'))
- end
-
- def test_add
- msg = log_add nil, 'unknown level message' # nil == unknown
- assert_equal LEVEL_LABEL_MAP[Logger::UNKNOWN], msg.severity
-
- msg = log_add Logger::FATAL, 'fatal level message'
- assert_equal LEVEL_LABEL_MAP[Logger::FATAL], msg.severity
-
- msg = log_add Logger::ERROR, 'error level message'
- assert_equal LEVEL_LABEL_MAP[Logger::ERROR], msg.severity
-
- msg = log_add Logger::WARN, 'warn level message'
- assert_equal LEVEL_LABEL_MAP[Logger::WARN], msg.severity
-
- msg = log_add Logger::INFO, 'info level message'
- assert_equal LEVEL_LABEL_MAP[Logger::INFO], msg.severity
-
- msg = log_add Logger::DEBUG, 'debug level message'
- assert_equal LEVEL_LABEL_MAP[Logger::DEBUG], msg.severity
- end
-
- def test_add_level_unknown
- @logger.level = Logger::UNKNOWN
-
- msg = log_add nil, 'unknown level message' # nil == unknown
- assert_equal LEVEL_LABEL_MAP[Logger::UNKNOWN], msg.severity
-
- msg = log_add Logger::FATAL, 'fatal level message'
- assert_equal '', msg.line
-
- msg = log_add Logger::ERROR, 'error level message'
- assert_equal '', msg.line
-
- msg = log_add Logger::WARN, 'warn level message'
- assert_equal '', msg.line
-
- msg = log_add Logger::INFO, 'info level message'
- assert_equal '', msg.line
-
- msg = log_add Logger::DEBUG, 'debug level message'
- assert_equal '', msg.line
- end
-
- def test_add_level_fatal
- @logger.level = Logger::FATAL
-
- msg = log_add nil, 'unknown level message' # nil == unknown
- assert_equal LEVEL_LABEL_MAP[Logger::UNKNOWN], msg.severity
-
- msg = log_add Logger::FATAL, 'fatal level message'
- assert_equal LEVEL_LABEL_MAP[Logger::FATAL], msg.severity
-
- msg = log_add Logger::ERROR, 'error level message'
- assert_equal '', msg.line
-
- msg = log_add Logger::WARN, 'warn level message'
- assert_equal '', msg.line
-
- msg = log_add Logger::INFO, 'info level message'
- assert_equal '', msg.line
-
- msg = log_add Logger::DEBUG, 'debug level message'
- assert_equal '', msg.line
- end
-
- def test_add_level_error
- @logger.level = Logger::ERROR
-
- msg = log_add nil, 'unknown level message' # nil == unknown
- assert_equal LEVEL_LABEL_MAP[Logger::UNKNOWN], msg.severity
-
- msg = log_add Logger::FATAL, 'fatal level message'
- assert_equal LEVEL_LABEL_MAP[Logger::FATAL], msg.severity
-
- msg = log_add Logger::ERROR, 'error level message'
- assert_equal LEVEL_LABEL_MAP[Logger::ERROR], msg.severity
-
- msg = log_add Logger::WARN, 'warn level message'
- assert_equal '', msg.line
-
- msg = log_add Logger::INFO, 'info level message'
- assert_equal '', msg.line
-
- msg = log_add Logger::DEBUG, 'debug level message'
- assert_equal '', msg.line
- end
-
- def test_add_level_warn
- @logger.level = Logger::WARN
-
- msg = log_add nil, 'unknown level message' # nil == unknown
- assert_equal LEVEL_LABEL_MAP[Logger::UNKNOWN], msg.severity
-
- msg = log_add Logger::FATAL, 'fatal level message'
- assert_equal LEVEL_LABEL_MAP[Logger::FATAL], msg.severity
-
- msg = log_add Logger::ERROR, 'error level message'
- assert_equal LEVEL_LABEL_MAP[Logger::ERROR], msg.severity
-
- msg = log_add Logger::WARN, 'warn level message'
- assert_equal LEVEL_LABEL_MAP[Logger::WARN], msg.severity
-
- msg = log_add Logger::INFO, 'info level message'
- assert_equal '', msg.line
-
- msg = log_add Logger::DEBUG, 'debug level message'
- assert_equal '', msg.line
- end
-
- def test_add_level_info
- @logger.level = Logger::INFO
-
- msg = log_add nil, 'unknown level message' # nil == unknown
- assert_equal LEVEL_LABEL_MAP[Logger::UNKNOWN], msg.severity
-
- msg = log_add Logger::FATAL, 'fatal level message'
- assert_equal LEVEL_LABEL_MAP[Logger::FATAL], msg.severity
-
- msg = log_add Logger::ERROR, 'error level message'
- assert_equal LEVEL_LABEL_MAP[Logger::ERROR], msg.severity
-
- msg = log_add Logger::WARN, 'warn level message'
- assert_equal LEVEL_LABEL_MAP[Logger::WARN], msg.severity
-
- msg = log_add Logger::INFO, 'info level message'
- assert_equal LEVEL_LABEL_MAP[Logger::INFO], msg.severity
-
- msg = log_add Logger::DEBUG, 'debug level message'
- assert_equal '', msg.line
- end
-
- def test_add_level_debug
- @logger.level = Logger::DEBUG
-
- msg = log_add nil, 'unknown level message' # nil == unknown
- assert_equal LEVEL_LABEL_MAP[Logger::UNKNOWN], msg.severity
-
- msg = log_add Logger::FATAL, 'fatal level message'
- assert_equal LEVEL_LABEL_MAP[Logger::FATAL], msg.severity
-
- msg = log_add Logger::ERROR, 'error level message'
- assert_equal LEVEL_LABEL_MAP[Logger::ERROR], msg.severity
-
- msg = log_add Logger::WARN, 'warn level message'
- assert_equal LEVEL_LABEL_MAP[Logger::WARN], msg.severity
-
- msg = log_add Logger::INFO, 'info level message'
- assert_equal LEVEL_LABEL_MAP[Logger::INFO], msg.severity
-
- msg = log_add Logger::DEBUG, 'debug level message'
- assert_equal LEVEL_LABEL_MAP[Logger::DEBUG], msg.severity
- end
-
- def test_unknown
- msg = log :unknown, 'unknown level message'
- assert_equal LEVEL_LABEL_MAP[Logger::UNKNOWN], msg.severity
-
- @logger.level = Logger::UNKNOWN
- msg = log :unknown, 'unknown level message'
- assert_equal LEVEL_LABEL_MAP[Logger::UNKNOWN], msg.severity
-
- @logger.level = Logger::FATAL
- msg = log :unknown, 'unknown level message'
- assert_equal LEVEL_LABEL_MAP[Logger::UNKNOWN], msg.severity
-
- @logger.level = Logger::ERROR
- msg = log :unknown, 'unknown level message'
- assert_equal LEVEL_LABEL_MAP[Logger::UNKNOWN], msg.severity
-
- @logger.level = Logger::WARN
- msg = log :unknown, 'unknown level message'
- assert_equal LEVEL_LABEL_MAP[Logger::UNKNOWN], msg.severity
-
- @logger.level = Logger::INFO
- msg = log :unknown, 'unknown level message'
- assert_equal LEVEL_LABEL_MAP[Logger::UNKNOWN], msg.severity
-
- @logger.level = Logger::DEBUG
- msg = log :unknown, 'unknown level message'
- assert_equal LEVEL_LABEL_MAP[Logger::UNKNOWN], msg.severity
- end
-
- def test_fatal
- msg = log :fatal, 'fatal level message'
- assert_equal LEVEL_LABEL_MAP[Logger::FATAL], msg.severity
-
- @logger.level = Logger::UNKNOWN
- msg = log :fatal, 'fatal level message'
- assert_equal '', msg.line
-
- @logger.level = Logger::FATAL
- msg = log :fatal, 'fatal level message'
- assert_equal LEVEL_LABEL_MAP[Logger::FATAL], msg.severity
-
- @logger.level = Logger::ERROR
- msg = log :fatal, 'fatal level message'
- assert_equal LEVEL_LABEL_MAP[Logger::FATAL], msg.severity
-
- @logger.level = Logger::WARN
- msg = log :fatal, 'fatal level message'
- assert_equal LEVEL_LABEL_MAP[Logger::FATAL], msg.severity
-
- @logger.level = Logger::INFO
- msg = log :fatal, 'fatal level message'
- assert_equal LEVEL_LABEL_MAP[Logger::FATAL], msg.severity
-
- @logger.level = Logger::DEBUG
- msg = log :fatal, 'fatal level message'
- assert_equal LEVEL_LABEL_MAP[Logger::FATAL], msg.severity
- end
-
- def test_fatal_eh
- @logger.level = Logger::FATAL
- assert_equal true, @logger.fatal?
-
- @logger.level = Logger::UNKNOWN
- assert_equal false, @logger.fatal?
- end
-
- def test_error
- msg = log :error, 'error level message'
- assert_equal LEVEL_LABEL_MAP[Logger::ERROR], msg.severity
-
- @logger.level = Logger::UNKNOWN
- msg = log :error, 'error level message'
- assert_equal '', msg.line
-
- @logger.level = Logger::FATAL
- msg = log :error, 'error level message'
- assert_equal '', msg.line
-
- @logger.level = Logger::ERROR
- msg = log :error, 'error level message'
- assert_equal LEVEL_LABEL_MAP[Logger::ERROR], msg.severity
-
- @logger.level = Logger::WARN
- msg = log :error, 'error level message'
- assert_equal LEVEL_LABEL_MAP[Logger::ERROR], msg.severity
-
- @logger.level = Logger::INFO
- msg = log :error, 'error level message'
- assert_equal LEVEL_LABEL_MAP[Logger::ERROR], msg.severity
-
- @logger.level = Logger::DEBUG
- msg = log :error, 'error level message'
- assert_equal LEVEL_LABEL_MAP[Logger::ERROR], msg.severity
- end
-
- def test_error_eh
- @logger.level = Logger::ERROR
- assert_equal true, @logger.error?
-
- @logger.level = Logger::FATAL
- assert_equal false, @logger.error?
- end
-
- def test_warn
- msg = log :warn, 'warn level message'
- assert_equal LEVEL_LABEL_MAP[Logger::WARN], msg.severity
-
- @logger.level = Logger::UNKNOWN
- msg = log :warn, 'warn level message'
- assert_equal '', msg.line
-
- @logger.level = Logger::FATAL
- msg = log :warn, 'warn level message'
- assert_equal '', msg.line
-
- @logger.level = Logger::ERROR
- msg = log :warn, 'warn level message'
- assert_equal '', msg.line
-
- @logger.level = Logger::WARN
- msg = log :warn, 'warn level message'
- assert_equal LEVEL_LABEL_MAP[Logger::WARN], msg.severity
-
- @logger.level = Logger::INFO
- msg = log :warn, 'warn level message'
- assert_equal LEVEL_LABEL_MAP[Logger::WARN], msg.severity
-
- @logger.level = Logger::DEBUG
- msg = log :warn, 'warn level message'
- assert_equal LEVEL_LABEL_MAP[Logger::WARN], msg.severity
- end
-
- def test_warn_eh
- @logger.level = Logger::WARN
- assert_equal true, @logger.warn?
-
- @logger.level = Logger::ERROR
- assert_equal false, @logger.warn?
- end
-
- def test_info
- msg = log :info, 'info level message'
- assert_equal LEVEL_LABEL_MAP[Logger::INFO], msg.severity
-
- @logger.level = Logger::UNKNOWN
- msg = log :info, 'info level message'
- assert_equal '', msg.line
-
- @logger.level = Logger::FATAL
- msg = log :info, 'info level message'
- assert_equal '', msg.line
-
- @logger.level = Logger::ERROR
- msg = log :info, 'info level message'
- assert_equal '', msg.line
-
- @logger.level = Logger::WARN
- msg = log :info, 'info level message'
- assert_equal '', msg.line
-
- @logger.level = Logger::INFO
- msg = log :info, 'info level message'
- assert_equal LEVEL_LABEL_MAP[Logger::INFO], msg.severity
-
- @logger.level = Logger::DEBUG
- msg = log :info, 'info level message'
- assert_equal LEVEL_LABEL_MAP[Logger::INFO], msg.severity
- end
-
- def test_info_eh
- @logger.level = Logger::INFO
- assert_equal true, @logger.info?
-
- @logger.level = Logger::WARN
- assert_equal false, @logger.info?
- end
-
- def test_debug
- msg = log :debug, 'debug level message'
- assert_equal LEVEL_LABEL_MAP[Logger::DEBUG], msg.severity
-
- @logger.level = Logger::UNKNOWN
- msg = log :debug, 'debug level message'
- assert_equal '', msg.line
-
- @logger.level = Logger::FATAL
- msg = log :debug, 'debug level message'
- assert_equal '', msg.line
-
- @logger.level = Logger::ERROR
- msg = log :debug, 'debug level message'
- assert_equal '', msg.line
-
- @logger.level = Logger::WARN
- msg = log :debug, 'debug level message'
- assert_equal '', msg.line
-
- @logger.level = Logger::INFO
- msg = log :debug, 'debug level message'
- assert_equal '', msg.line
-
- @logger.level = Logger::DEBUG
- msg = log :debug, 'debug level message'
- assert_equal LEVEL_LABEL_MAP[Logger::DEBUG], msg.severity
- end
-
- def test_debug_eh
- @logger.level = Logger::DEBUG
- assert_equal true, @logger.debug?
-
- @logger.level = Logger::INFO
- assert_equal false, @logger.debug?
- end
-
-end if defined?(Syslog)
-
-class TestSyslogLogger < TestSyslogRootLogger
-
- @facility = Syslog::LOG_USER
-
- def facility
- self.class.instance_variable_get("@facility")
- end
-
- def setup
- super
- @logger = Syslog::Logger.new
- end
-
- SEVERITY_MAP = {}.tap { |map|
- level2severity = Syslog::Logger::LEVEL_MAP.invert
-
- MockSyslog::LEVEL_LABEL_MAP.each { |level, name|
- map[name] = TestSyslogRootLogger::LEVEL_LABEL_MAP[level2severity[level]]
- }
- }
-
- class Log
- attr_reader :line, :label, :datetime, :pid, :severity, :progname, :msg, :priority
- def initialize(line)
- @line = line
- return unless /\A<(\d+)> (\w+) - (.*)\Z/ =~ @line
- priority, severity, @msg = $1, $2, $3
- @severity = SEVERITY_MAP[severity]
- @priority = priority.to_i
- end
- end
-
- def log_add(severity, msg, progname = nil, &block)
- log(:add, severity, msg, progname, &block)
- end
-
- def log(msg_id, *arg, &block)
- Log.new(log_raw(msg_id, *arg, &block))
- end
-
- def log_raw(msg_id, *arg, &block)
- assert_equal true, @logger.__send__(msg_id, *arg, &block)
- msg = MockSyslog.line
- MockSyslog.reset
- return msg
- end
-
- def test_unknown_eh
- @logger.level = Logger::UNKNOWN
- assert_equal true, @logger.unknown?
-
- @logger.level = Logger::UNKNOWN + 1
- assert_equal false, @logger.unknown?
- end
-
- def test_facility
- assert_equal facility, @logger.facility
- end
-
- def test_priority
- msg = log_add nil, 'unknown level message' # nil == unknown
- assert_equal facility|Syslog::LOG_ALERT, msg.priority
-
- msg = log_add Logger::FATAL, 'fatal level message'
- assert_equal facility|Syslog::LOG_ERR, msg.priority
-
- msg = log_add Logger::ERROR, 'error level message'
- assert_equal facility|Syslog::LOG_WARNING, msg.priority
-
- msg = log_add Logger::WARN, 'warn level message'
- assert_equal facility|Syslog::LOG_NOTICE, msg.priority
-
- msg = log_add Logger::INFO, 'info level message'
- assert_equal facility|Syslog::LOG_INFO, msg.priority
-
- msg = log_add Logger::DEBUG, 'debug level message'
- assert_equal facility|Syslog::LOG_DEBUG, msg.priority
- end
-
- class CustomSyslogLogger < Syslog::Logger
- def level
- Logger::INFO
- end
- end
-
- def test_overriding_level
- @logger = CustomSyslogLogger.new
- log = log_add Logger::INFO, 'msg'
- assert_equal 'msg', log.msg
-
- log = log_add Logger::DEBUG, 'msg'
- assert_nil log.msg
- end
-
-end if defined?(Syslog)
-
-
-# Create test class for each available facility
-
-Syslog::Facility.constants.each do |facility_symb|
-
- test_syslog_class = Class.new(TestSyslogLogger) do
-
- @facility = Syslog.const_get(facility_symb)
-
- def setup
- super
- @logger.facility = facility
- end
-
- end
- Object.const_set("TestSyslogLogger_#{facility_symb}", test_syslog_class)
-
-end if defined?(Syslog)
diff --git a/test/test_abbrev.rb b/test/test_abbrev.rb
deleted file mode 100644
index 67287138aa..0000000000
--- a/test/test_abbrev.rb
+++ /dev/null
@@ -1,55 +0,0 @@
-# frozen_string_literal: true
-require 'test/unit'
-require 'abbrev'
-
-class TestAbbrev < Test::Unit::TestCase
- def test_abbrev
- words = %w[summer winter win ruby rules]
-
- assert_equal({
- "rub" => "ruby",
- "ruby" => "ruby",
- "rul" => "rules",
- "rule" => "rules",
- "rules" => "rules",
- "s" => "summer",
- "su" => "summer",
- "sum" => "summer",
- "summ" => "summer",
- "summe" => "summer",
- "summer" => "summer",
- "win" => "win",
- "wint" => "winter",
- "winte" => "winter",
- "winter" => "winter",
- }, words.abbrev)
-
- assert_equal({
- "rub" => "ruby",
- "ruby" => "ruby",
- "rul" => "rules",
- "rule" => "rules",
- "rules" => "rules",
- }, words.abbrev('ru'))
-
- assert_equal words.abbrev, Abbrev.abbrev(words)
- assert_equal words.abbrev('ru'), Abbrev.abbrev(words, 'ru')
- end
-
- def test_abbrev_lf
- words = ["abc", "abc\nd", "de"]
-
- assert_equal({
- "abc" => "abc",
- "abc\n" => "abc\nd",
- "abc\nd" => "abc\nd",
- "d" => "de",
- "de" => "de",
- }, words.abbrev)
-
- assert_equal({
- "d" => "de",
- "de" => "de",
- }, words.abbrev('d'))
- end
-end
diff --git a/test/test_bundled_gems.rb b/test/test_bundled_gems.rb
new file mode 100644
index 0000000000..36f7324336
--- /dev/null
+++ b/test/test_bundled_gems.rb
@@ -0,0 +1,35 @@
+require_relative "rubygems/helper"
+require "rubygems"
+require "bundled_gems"
+
+class TestBundlerGem < Gem::TestCase
+ def setup
+ Gem::BUNDLED_GEMS::WARNED.clear
+ end
+
+ def teardown
+ Gem::BUNDLED_GEMS::WARNED.clear
+ end
+
+ def test_warning
+ assert Gem::BUNDLED_GEMS.warning?("rss", specs: {})
+ assert_nil Gem::BUNDLED_GEMS.warning?("rss", specs: {})
+ end
+
+ def test_no_warning_warning
+ assert_nil Gem::BUNDLED_GEMS.warning?("some_gem", specs: {})
+ assert_nil Gem::BUNDLED_GEMS.warning?("/path/to/some_gem.rb", specs: {})
+ end
+
+ def test_warning_libdir
+ path = File.join(::RbConfig::CONFIG.fetch("rubylibdir"), "rss.rb")
+ assert Gem::BUNDLED_GEMS.warning?(path, specs: {})
+ assert_nil Gem::BUNDLED_GEMS.warning?(path, specs: {})
+ end
+
+ def test_warning_archdir
+ path = File.join(::RbConfig::CONFIG.fetch("rubyarchdir"), "syslog.so")
+ assert Gem::BUNDLED_GEMS.warning?(path, specs: {})
+ assert_nil Gem::BUNDLED_GEMS.warning?(path, specs: {})
+ end
+end
diff --git a/test/test_delegate.rb b/test/test_delegate.rb
index 57480b18ea..f7bedf37fb 100644
--- a/test/test_delegate.rb
+++ b/test/test_delegate.rb
@@ -3,14 +3,6 @@ require 'test/unit'
require 'delegate'
class TestDelegateClass < Test::Unit::TestCase
- module PP
- def mu_pp(obj)
- str = super
- str = "#<#{obj.class}: #{str}>" if Delegator === obj
- str
- end
- end
-
module M
attr_reader :m
end
@@ -215,7 +207,6 @@ class TestDelegateClass < Test::Unit::TestCase
end
def test_eql?
- extend PP
s0 = SimpleDelegator.new("foo")
s1 = SimpleDelegator.new("bar")
s2 = SimpleDelegator.new("foo")
diff --git a/test/test_extlibs.rb b/test/test_extlibs.rb
index 958c9ff73e..9b6676416c 100644
--- a/test/test_extlibs.rb
+++ b/test/test_extlibs.rb
@@ -34,18 +34,16 @@ class TestExtLibs < Test::Unit::TestCase
end.flatten.compact
excluded << '+' if excluded.empty?
if windows?
- excluded.map! {|i| i == '+' ? ['pty', 'syslog'] : i}
+ excluded.map! {|i| i == '+' ? ['pty'] : i}
excluded.flatten!
else
excluded.map! {|i| i == '+' ? '*win32*' : i}
end
@excluded = excluded
- check_existence "bigdecimal"
check_existence "continuation"
check_existence "coverage"
check_existence "date"
- #check_existence "dbm" # depend on libdbm
check_existence "digest"
check_existence "digest/bubblebabble"
check_existence "digest/md5"
@@ -56,25 +54,20 @@ class TestExtLibs < Test::Unit::TestCase
check_existence "fcntl"
check_existence "fiber"
check_existence "fiddle"
- #check_existence "gdbm" # depend on libgdbm
check_existence "io/console"
check_existence "io/nonblock"
check_existence "io/wait"
check_existence "json"
- check_existence "nkf"
check_existence "objspace"
check_existence "openssl", "this may be false positive, but should assert because rubygems requires this"
check_existence "pathname"
check_existence "psych"
check_existence "pty"
- check_existence "racc/cparse"
check_existence "rbconfig/sizeof"
- #check_existence "readline" # depend on libreadline
check_existence "ripper"
check_existence "socket"
check_existence "stringio"
check_existence "strscan"
- check_existence "syslog"
check_existence "thread"
check_existence "win32ole"
check_existence "zlib", "this may be false positive, but should assert because rubygems requires this"
diff --git a/test/test_find.rb b/test/test_find.rb
index 0e691214c5..f2dad05324 100644
--- a/test/test_find.rb
+++ b/test/test_find.rb
@@ -60,7 +60,7 @@ class TestFind < Test::Unit::TestCase
begin
File.symlink("#{d}/b", "#{d}/c")
rescue NotImplementedError, Errno::EACCES
- skip "symlink is not supported."
+ omit "symlink is not supported."
end
a = []
Find.find(d) {|f| a << f }
@@ -103,8 +103,8 @@ class TestFind < Test::Unit::TestCase
end
def test_unreadable_dir
- skip "no meaning test on Windows" if /mswin|mingw/ =~ RUBY_PLATFORM
- skip "because root can read anything" if Process.uid == 0
+ omit "no meaning test on Windows" if /mswin|mingw/ =~ RUBY_PLATFORM
+ omit "because root can read anything" if Process.uid == 0
Dir.mktmpdir {|d|
Dir.mkdir(dir = "#{d}/dir")
@@ -158,8 +158,8 @@ class TestFind < Test::Unit::TestCase
Find.find(d, ignore_error: true).each {|f| a << f }
assert_equal([d, dir, file], a)
- skip "no meaning test on Windows" if /mswin|mingw/ =~ RUBY_PLATFORM
- skip "skipped because root can read anything" if Process.uid == 0
+ omit "no meaning test on Windows" if /mswin|mingw/ =~ RUBY_PLATFORM
+ omit "skipped because root can read anything" if Process.uid == 0
a = []
assert_raise_with_message(Errno::EACCES, /#{Regexp.quote(file)}/) do
@@ -185,7 +185,7 @@ class TestFind < Test::Unit::TestCase
begin
File.symlink("foo", "#{d}/bar")
rescue NotImplementedError, Errno::EACCES
- skip "symlink is not supported."
+ omit "symlink is not supported."
end
a = []
Find.find(d) {|f| a << f }
@@ -199,7 +199,7 @@ class TestFind < Test::Unit::TestCase
begin
File.symlink("foo", "#{d}/bar")
rescue NotImplementedError, Errno::EACCES
- skip "symlink is not supported."
+ omit "symlink is not supported."
end
assert_raise(Errno::ENOENT) {
Find.find(d) {|f| File.stat(f) }
@@ -245,7 +245,7 @@ class TestFind < Test::Unit::TestCase
begin
File.symlink("d1", dir_1)
rescue NotImplementedError, Errno::EACCES
- skip "symlink is not supported."
+ omit "symlink is not supported."
end
end
}
diff --git a/test/test_forwardable.rb b/test/test_forwardable.rb
index deb0b5d5cf..9ed330058a 100644
--- a/test/test_forwardable.rb
+++ b/test/test_forwardable.rb
@@ -306,7 +306,7 @@ class TestForwardable < Test::Unit::TestCase
def test_basicobject_subclass
bug11616 = '[ruby-core:71176] [Bug #11616]'
- assert_raise_with_message(NameError, /`bar'/, bug11616) {
+ assert_raise_with_message(NameError, /[`']bar'/, bug11616) {
Foo2.new.baz
}
end
diff --git a/test/test_ipaddr.rb b/test/test_ipaddr.rb
index 7b3a199bf3..3e5c3d2aa4 100644
--- a/test/test_ipaddr.rb
+++ b/test/test_ipaddr.rb
@@ -20,18 +20,21 @@ class TC_IPAddr < Test::Unit::TestCase
a = IPAddr.new
assert_equal("::", a.to_s)
assert_equal("0000:0000:0000:0000:0000:0000:0000:0000", a.to_string)
+ assert_equal("::/128", a.cidr)
assert_equal(Socket::AF_INET6, a.family)
assert_equal(128, a.prefix)
a = IPAddr.new("0123:4567:89ab:cdef:0ABC:DEF0:1234:5678")
assert_equal("123:4567:89ab:cdef:abc:def0:1234:5678", a.to_s)
assert_equal("0123:4567:89ab:cdef:0abc:def0:1234:5678", a.to_string)
+ assert_equal("123:4567:89ab:cdef:abc:def0:1234:5678/128", a.cidr)
assert_equal(Socket::AF_INET6, a.family)
assert_equal(128, a.prefix)
a = IPAddr.new("3ffe:505:2::/48")
assert_equal("3ffe:505:2::", a.to_s)
assert_equal("3ffe:0505:0002:0000:0000:0000:0000:0000", a.to_string)
+ assert_equal("3ffe:505:2::/48", a.cidr)
assert_equal(Socket::AF_INET6, a.family)
assert_equal(false, a.ipv4?)
assert_equal(true, a.ipv6?)
@@ -41,18 +44,32 @@ class TC_IPAddr < Test::Unit::TestCase
a = IPAddr.new("3ffe:505:2::/ffff:ffff:ffff::")
assert_equal("3ffe:505:2::", a.to_s)
assert_equal("3ffe:0505:0002:0000:0000:0000:0000:0000", a.to_string)
+ assert_equal("3ffe:505:2::/48", a.cidr)
assert_equal(Socket::AF_INET6, a.family)
assert_equal(48, a.prefix)
+ assert_nil(a.zone_id)
+
+ a = IPAddr.new("fe80::1%ab0")
+ assert_equal("fe80::1%ab0", a.to_s)
+ assert_equal("fe80:0000:0000:0000:0000:0000:0000:0001%ab0", a.to_string)
+ assert_equal(Socket::AF_INET6, a.family)
+ assert_equal(false, a.ipv4?)
+ assert_equal(true, a.ipv6?)
+ assert_equal("#<IPAddr: IPv6:fe80:0000:0000:0000:0000:0000:0000:0001%ab0/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff>", a.inspect)
+ assert_equal(128, a.prefix)
+ assert_equal('%ab0', a.zone_id)
a = IPAddr.new("0.0.0.0")
assert_equal("0.0.0.0", a.to_s)
assert_equal("0.0.0.0", a.to_string)
+ assert_equal("0.0.0.0/32", a.cidr)
assert_equal(Socket::AF_INET, a.family)
assert_equal(32, a.prefix)
a = IPAddr.new("192.168.1.2")
assert_equal("192.168.1.2", a.to_s)
assert_equal("192.168.1.2", a.to_string)
+ assert_equal("192.168.1.2/32", a.cidr)
assert_equal(Socket::AF_INET, a.family)
assert_equal(true, a.ipv4?)
assert_equal(false, a.ipv6?)
@@ -61,6 +78,7 @@ class TC_IPAddr < Test::Unit::TestCase
a = IPAddr.new("192.168.1.2/26")
assert_equal("192.168.1.0", a.to_s)
assert_equal("192.168.1.0", a.to_string)
+ assert_equal("192.168.1.0/26", a.cidr)
assert_equal(Socket::AF_INET, a.family)
assert_equal("#<IPAddr: IPv4:192.168.1.0/255.255.255.192>", a.inspect)
assert_equal(26, a.prefix)
@@ -68,6 +86,7 @@ class TC_IPAddr < Test::Unit::TestCase
a = IPAddr.new("192.168.1.2/255.255.255.0")
assert_equal("192.168.1.0", a.to_s)
assert_equal("192.168.1.0", a.to_string)
+ assert_equal("192.168.1.0/24", a.cidr)
assert_equal(Socket::AF_INET, a.family)
assert_equal(24, a.prefix)
@@ -87,10 +106,14 @@ class TC_IPAddr < Test::Unit::TestCase
assert_raise(IPAddr::InvalidAddressError) { IPAddr.new("192.168.0.256") }
assert_raise(IPAddr::InvalidAddressError) { IPAddr.new("192.168.0.011") }
- assert_raise(IPAddr::InvalidAddressError) { IPAddr.new("fe80::1%fxp0") }
+ assert_raise(IPAddr::InvalidAddressError) { IPAddr.new("fe80::1%") }
+ assert_raise(IPAddr::InvalidAddressError) { IPAddr.new("fe80::1%]") }
assert_raise(IPAddr::InvalidAddressError) { IPAddr.new("[192.168.1.2]/120") }
assert_raise(IPAddr::InvalidAddressError) { IPAddr.new("[2001:200:300::]\nINVALID") }
assert_raise(IPAddr::InvalidAddressError) { IPAddr.new("192.168.0.1/32\nINVALID") }
+ assert_raise(IPAddr::InvalidAddressError) { IPAddr.new("192.168.0.1/32/20") }
+ assert_raise(IPAddr::InvalidPrefixError) { IPAddr.new("192.168.0.1/032") }
+ assert_raise(IPAddr::InvalidPrefixError) { IPAddr.new("::1/0128") }
assert_raise(IPAddr::InvalidPrefixError) { IPAddr.new("::1/255.255.255.0") }
assert_raise(IPAddr::InvalidPrefixError) { IPAddr.new("::1/129") }
assert_raise(IPAddr::InvalidPrefixError) { IPAddr.new("192.168.0.1/33") }
@@ -116,6 +139,42 @@ class TC_IPAddr < Test::Unit::TestCase
assert_equal("192.168.2.1", IPAddr.new_ntoh(a.hton).to_s)
end
+ def test_ntop
+ # IPv4
+ assert_equal("192.168.1.1", IPAddr.ntop("\xC0\xA8\x01\x01".b))
+ assert_equal("10.231.140.171", IPAddr.ntop("\x0A\xE7\x8C\xAB".b))
+ # IPv6
+ assert_equal("0000:0000:0000:0000:0000:0000:0000:0001",
+ IPAddr.ntop("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01".b))
+ assert_equal("fe80:0000:0000:0000:f09f:9985:f09f:9986",
+ IPAddr.ntop("\xFE\x80\x00\x00\x00\x00\x00\x00\xF0\x9F\x99\x85\xF0\x9F\x99\x86".b))
+
+ # Invalid parameters
+ ## wrong length
+ assert_raise(IPAddr::AddressFamilyError) {
+ IPAddr.ntop("192.168.1.1".b)
+ }
+ assert_raise(IPAddr::AddressFamilyError) {
+ IPAddr.ntop("\xC0\xA8\x01\xFF1".b)
+ }
+ ## UTF-8
+ assert_raise(IPAddr::InvalidAddressError) {
+ IPAddr.ntop("192.168.1.1")
+ }
+ assert_raise(IPAddr::InvalidAddressError) {
+ IPAddr.ntop("\x0A\x0A\x0A\x0A")
+ }
+ assert_raise(IPAddr::InvalidAddressError) {
+ IPAddr.ntop("\x0A\xE7\x8C\xAB")
+ }
+ assert_raise(IPAddr::InvalidAddressError) {
+ IPAddr.ntop("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01")
+ }
+ assert_raise(IPAddr::InvalidAddressError) {
+ IPAddr.ntop("\xFE\x80\x00\x00\x00\x00\x00\x00\xF0\x9F\x99\x85\xF0\x9F\x99\x86")
+ }
+ end
+
def test_ipv4_compat
a = IPAddr.new("::192.168.1.2")
assert_equal("::192.168.1.2", a.to_s)
@@ -200,6 +259,74 @@ class TC_IPAddr < Test::Unit::TestCase
assert_equal("3ffe:0505:0002:0000:0000:0000:0000:0001", IPAddr.new("3ffe:505:2::1").to_string)
assert_equal("3ffe:505:2::1", IPAddr.new("3ffe:505:2::1").to_s)
end
+
+ def test_netmask
+ a = IPAddr.new("192.168.1.2/8")
+ assert_equal(a.netmask, "255.0.0.0")
+
+ a = IPAddr.new("192.168.1.2/16")
+ assert_equal(a.netmask, "255.255.0.0")
+
+ a = IPAddr.new("192.168.1.2/24")
+ assert_equal(a.netmask, "255.255.255.0")
+ end
+
+ def test_wildcard_mask
+ a = IPAddr.new("192.168.1.2/1")
+ assert_equal(a.wildcard_mask, "127.255.255.255")
+
+ a = IPAddr.new("192.168.1.2/8")
+ assert_equal(a.wildcard_mask, "0.255.255.255")
+
+ a = IPAddr.new("192.168.1.2/16")
+ assert_equal(a.wildcard_mask, "0.0.255.255")
+
+ a = IPAddr.new("192.168.1.2/24")
+ assert_equal(a.wildcard_mask, "0.0.0.255")
+
+ a = IPAddr.new("192.168.1.2/32")
+ assert_equal(a.wildcard_mask, "0.0.0.0")
+
+ a = IPAddr.new("3ffe:505:2::/48")
+ assert_equal(a.wildcard_mask, "0000:0000:0000:ffff:ffff:ffff:ffff:ffff")
+
+ a = IPAddr.new("3ffe:505:2::/128")
+ assert_equal(a.wildcard_mask, "0000:0000:0000:0000:0000:0000:0000:0000")
+ end
+
+ def test_zone_id
+ a = IPAddr.new("192.168.1.2")
+ assert_raise(IPAddr::InvalidAddressError) { a.zone_id = '%ab0' }
+ assert_raise(IPAddr::InvalidAddressError) { a.zone_id }
+
+ a = IPAddr.new("1:2:3:4:5:6:7:8")
+ a.zone_id = '%ab0'
+ assert_equal('%ab0', a.zone_id)
+ assert_equal("1:2:3:4:5:6:7:8%ab0", a.to_s)
+ assert_raise(IPAddr::InvalidAddressError) { a.zone_id = '%' }
+ end
+
+ def test_to_range
+ a1 = IPAddr.new("127.0.0.1")
+ range = a1..a1
+ assert_equal(range, a1.to_range)
+ assert_equal(range, a1.freeze.to_range)
+
+ a2 = IPAddr.new("192.168.0.1/16")
+ range = IPAddr.new("192.168.0.0")..IPAddr.new("192.168.255.255")
+ assert_equal(range, a2.to_range)
+ assert_equal(range, a2.freeze.to_range)
+
+ a3 = IPAddr.new("3ffe:505:2::1")
+ range = a3..a3
+ assert_equal(range, a3.to_range)
+ assert_equal(range, a3.freeze.to_range)
+
+ a4 = IPAddr.new("::ffff/127")
+ range = IPAddr.new("::fffe")..IPAddr.new("::ffff")
+ assert_equal(range, a4.to_range)
+ assert_equal(range, a4.freeze.to_range)
+ end
end
class TC_Operator < Test::Unit::TestCase
@@ -295,6 +422,8 @@ class TC_Operator < Test::Unit::TestCase
assert_equal(true, net1.include?(IPAddr.new("192.168.2.0")))
assert_equal(true, net1.include?(IPAddr.new("192.168.2.255")))
assert_equal(false, net1.include?(IPAddr.new("192.168.3.0")))
+ assert_equal(true, net1.include?(IPAddr.new("192.168.2.0/28")))
+ assert_equal(false, net1.include?(IPAddr.new("192.168.2.0/16")))
# test with integer parameter
int = (192 << 24) + (168 << 16) + (2 << 8) + 13
@@ -303,6 +432,11 @@ class TC_Operator < Test::Unit::TestCase
end
+ def test_native_coerce_mask_addr
+ assert_equal(IPAddr.new("0.0.0.2/255.255.255.255"), IPAddr.new("::2").native)
+ assert_equal(IPAddr.new("0.0.0.2/255.255.255.255").to_range, IPAddr.new("::2").native.to_range)
+ end
+
def test_loopback?
assert_equal(true, IPAddr.new('127.0.0.1').loopback?)
assert_equal(true, IPAddr.new('127.127.1.1').loopback?)
@@ -312,6 +446,12 @@ class TC_Operator < Test::Unit::TestCase
assert_equal(true, IPAddr.new('::1').loopback?)
assert_equal(false, IPAddr.new('::').loopback?)
assert_equal(false, IPAddr.new('3ffe:505:2::1').loopback?)
+
+ assert_equal(true, IPAddr.new('::ffff:127.0.0.1').loopback?)
+ assert_equal(true, IPAddr.new('::ffff:127.127.1.1').loopback?)
+ assert_equal(false, IPAddr.new('::ffff:0.0.0.0').loopback?)
+ assert_equal(false, IPAddr.new('::ffff:192.168.2.0').loopback?)
+ assert_equal(false, IPAddr.new('::ffff:255.0.0.0').loopback?)
end
def test_private?
@@ -342,6 +482,26 @@ class TC_Operator < Test::Unit::TestCase
assert_equal(true, IPAddr.new('fc84:8bf7:e905::1').private?)
assert_equal(true, IPAddr.new('fd84:8bf7:e905::1').private?)
assert_equal(false, IPAddr.new('fe84:8bf7:e905::1').private?)
+
+ assert_equal(false, IPAddr.new('::ffff:0.0.0.0').private?)
+ assert_equal(false, IPAddr.new('::ffff:127.0.0.1').private?)
+
+ assert_equal(false, IPAddr.new('::ffff:8.8.8.8').private?)
+ assert_equal(true, IPAddr.new('::ffff:10.0.0.0').private?)
+ assert_equal(true, IPAddr.new('::ffff:10.255.255.255').private?)
+ assert_equal(false, IPAddr.new('::ffff:11.255.1.1').private?)
+
+ assert_equal(false, IPAddr.new('::ffff:172.15.255.255').private?)
+ assert_equal(true, IPAddr.new('::ffff:172.16.0.0').private?)
+ assert_equal(true, IPAddr.new('::ffff:172.31.255.255').private?)
+ assert_equal(false, IPAddr.new('::ffff:172.32.0.0').private?)
+
+ assert_equal(false, IPAddr.new('::ffff:190.168.0.0').private?)
+ assert_equal(true, IPAddr.new('::ffff:192.168.0.0').private?)
+ assert_equal(true, IPAddr.new('::ffff:192.168.255.255').private?)
+ assert_equal(false, IPAddr.new('::ffff:192.169.0.0').private?)
+
+ assert_equal(false, IPAddr.new('::ffff:169.254.0.1').private?)
end
def test_link_local?
@@ -359,6 +519,15 @@ class TC_Operator < Test::Unit::TestCase
assert_equal(false, IPAddr.new('fb84:8bf7:e905::1').link_local?)
assert_equal(true, IPAddr.new('fe80::dead:beef:cafe:1234').link_local?)
+
+ assert_equal(false, IPAddr.new('::ffff:0.0.0.0').link_local?)
+ assert_equal(false, IPAddr.new('::ffff:127.0.0.1').link_local?)
+ assert_equal(false, IPAddr.new('::ffff:10.0.0.0').link_local?)
+ assert_equal(false, IPAddr.new('::ffff:172.16.0.0').link_local?)
+ assert_equal(false, IPAddr.new('::ffff:192.168.0.0').link_local?)
+
+ assert_equal(true, IPAddr.new('::ffff:169.254.1.1').link_local?)
+ assert_equal(true, IPAddr.new('::ffff:169.254.254.255').link_local?)
end
def test_hash
diff --git a/test/test_mutex_m.rb b/test/test_mutex_m.rb
deleted file mode 100644
index e5cfbc8b5f..0000000000
--- a/test/test_mutex_m.rb
+++ /dev/null
@@ -1,58 +0,0 @@
-# frozen_string_literal: false
-require 'test/unit'
-require 'mutex_m'
-
-class TestMutexM < Test::Unit::TestCase
- def test_cv_wait
- o = Object.new
- o.instance_variable_set(:@foo, nil)
- o.extend(Mutex_m)
- c = Thread::ConditionVariable.new
- t = Thread.start {
- o.synchronize do
- until foo = o.instance_variable_get(:@foo)
- c.wait(o)
- end
- foo
- end
- }
- sleep(0.0001)
- o.synchronize do
- o.instance_variable_set(:@foo, "abc")
- end
- c.signal
- assert_equal "abc", t.value
- end
-
- class KeywordInitializeParent
- def initialize(x:)
- end
- end
-
- class KeywordInitializeChild < KeywordInitializeParent
- include Mutex_m
- def initialize
- super(x: 1)
- end
- end
-
- def test_initialize_with_keyword_arg
- assert KeywordInitializeChild.new
- end
-
- class NoArgInitializeParent
- def initialize
- end
- end
-
- class NoArgInitializeChild < NoArgInitializeParent
- include Mutex_m
- def initialize
- super()
- end
- end
-
- def test_initialize_no_args
- assert NoArgInitializeChild.new
- end
-end
diff --git a/test/test_observer.rb b/test/test_observer.rb
deleted file mode 100644
index 8f8f24b3c5..0000000000
--- a/test/test_observer.rb
+++ /dev/null
@@ -1,66 +0,0 @@
-# frozen_string_literal: true
-require 'test/unit'
-require 'observer'
-
-class TestObserver < Test::Unit::TestCase
- class TestObservable
- include Observable
-
- def notify(*args)
- changed
- notify_observers(*args)
- end
- end
-
- class TestWatcher
- def initialize(observable)
- @notifications = []
- observable.add_observer(self)
- end
-
- attr_reader :notifications
-
- def update(*args)
- @notifications << args
- end
- end
-
- def test_observers
- observable = TestObservable.new
-
- assert_equal(0, observable.count_observers)
-
- watcher1 = TestWatcher.new(observable)
-
- assert_equal(1, observable.count_observers)
-
- observable.notify("test", 123)
-
- watcher2 = TestWatcher.new(observable)
-
- assert_equal(2, observable.count_observers)
-
- observable.notify(42)
-
- assert_equal([["test", 123], [42]], watcher1.notifications)
- assert_equal([[42]], watcher2.notifications)
-
- observable.delete_observer(watcher1)
-
- assert_equal(1, observable.count_observers)
-
- observable.notify(:cats)
-
- assert_equal([["test", 123], [42]], watcher1.notifications)
- assert_equal([[42], [:cats]], watcher2.notifications)
-
- observable.delete_observers
-
- assert_equal(0, observable.count_observers)
-
- observable.notify("nope")
-
- assert_equal([["test", 123], [42]], watcher1.notifications)
- assert_equal([[42], [:cats]], watcher2.notifications)
- end
-end
diff --git a/test/test_open3.rb b/test/test_open3.rb
index 47d471c031..19277c8a66 100644
--- a/test/test_open3.rb
+++ b/test/test_open3.rb
@@ -2,7 +2,6 @@
require 'test/unit'
require 'open3'
-require_relative 'lib/jit_support'
class TestOpen3 < Test::Unit::TestCase
RUBY = EnvUtil.rubybin
@@ -92,7 +91,7 @@ class TestOpen3 < Test::Unit::TestCase
end
def test_numeric_file_descriptor3
- skip "passing FDs bigger than 2 is not supported on Windows" if /mswin|mingw/ =~ RUBY_PLATFORM
+ omit "passing FDs bigger than 2 is not supported on Windows" if /mswin|mingw/ =~ RbConfig::CONFIG['host_os']
with_pipe {|r, w|
Open3.popen3(RUBY, '-e', 'IO.open(3).puts "foo"', 3 => w) {|i,o,e,t|
assert_equal("foo\n", r.gets, "[GH-808] [ruby-core:67347] [Bug #10699]")
@@ -127,7 +126,7 @@ class TestOpen3 < Test::Unit::TestCase
i.close
STDERR.reopen(old)
assert_equal("zo", o.read)
- assert_equal("ze", JITSupport.remove_mjit_logs(r.read))
+ assert_equal("ze", r.read)
}
}
}
diff --git a/test/test_pp.rb b/test/test_pp.rb
index 4aa3195455..2fdd5df114 100644
--- a/test/test_pp.rb
+++ b/test/test_pp.rb
@@ -3,6 +3,7 @@
require 'pp'
require 'delegate'
require 'test/unit'
+require 'ruby2_keywords'
module PPTestModule
@@ -27,6 +28,13 @@ class PPTest < Test::Unit::TestCase
end
assert_equal(%(""\n), PP.pp(o, "".dup))
end
+
+ def test_range
+ assert_equal("0..1\n", PP.pp(0..1, "".dup))
+ assert_equal("0...1\n", PP.pp(0...1, "".dup))
+ assert_equal("0...\n", PP.pp(0..., "".dup))
+ assert_equal("...1\n", PP.pp(...1, "".dup))
+ end
end
class HasInspect
@@ -139,7 +147,19 @@ class PPCycleTest < Test::Unit::TestCase
a = S.new(1,2)
a.b = a
assert_equal("#<struct Struct::S a=1, b=#<struct Struct::S:...>>\n", PP.pp(a, ''.dup))
- assert_equal("#{a.inspect}\n", PP.pp(a, ''.dup))
+ assert_equal("#{a.inspect}\n", PP.pp(a, ''.dup)) unless RUBY_ENGINE == "truffleruby"
+ end
+
+ if defined?(Data.define)
+ D = Data.define(:aaa, :bbb)
+ def test_data
+ a = D.new("aaa", "bbb")
+ assert_equal("#<data PPTestModule::PPCycleTest::D\n aaa=\"aaa\",\n bbb=\"bbb\">\n", PP.pp(a, ''.dup, 20))
+ assert_equal("#{a.inspect}\n", PP.pp(a, ''.dup))
+
+ b = Data.define(:a).new(42)
+ assert_equal("#{b.inspect}\n", PP.pp(b, ''.dup))
+ end
end
def test_object
@@ -154,6 +174,7 @@ class PPCycleTest < Test::Unit::TestCase
end
def test_withinspect
+ omit if RUBY_ENGINE == "jruby" or RUBY_ENGINE == "truffleruby"
a = []
a << HasInspect.new(a)
assert_equal("[<inspect:[...]>]\n", PP.pp(a, ''.dup))
@@ -178,6 +199,7 @@ class PPSingleLineTest < Test::Unit::TestCase
end
def test_hash_in_array
+ omit if RUBY_ENGINE == "jruby"
assert_equal("[{}]", PP.singleline_pp([->(*a){a.last.clear}.ruby2_keywords.call(a: 1)], ''.dup))
assert_equal("[{}]", PP.singleline_pp([Hash.ruby2_keywords_hash({})], ''.dup))
end
@@ -216,10 +238,36 @@ if defined?(RubyVM)
AST = RubyVM::AbstractSyntaxTree
def test_lasgn_literal
ast = AST.parse("_=1")
- expected = "(SCOPE@1:0-1:3 tbl: [:_] args: nil body: (LASGN@1:0-1:3 :_ (LIT@1:2-1:3 1)))"
+ integer = RUBY_VERSION >= "3.4." ? "INTEGER" : "LIT"
+ expected = "(SCOPE@1:0-1:3 tbl: [:_] args: nil body: (LASGN@1:0-1:3 :_ (#{integer}@1:2-1:3 1)))"
assert_equal(expected, PP.singleline_pp(ast, ''.dup), ast)
end
end
end
+class PPInheritedTest < Test::Unit::TestCase
+ class PPSymbolHash < PP
+ def pp_hash_pair(k, v)
+ case k
+ when Symbol
+ text k.inspect.delete_prefix(":")
+ text ":"
+ group(1) {
+ breakable
+ pp v
+ }
+ else
+ super
+ end
+ end
+ end
+
+ def test_hash_override
+ obj = {k: 1, "": :null, "0": :zero, 100 => :ten}
+ assert_equal <<~EXPECT, PPSymbolHash.pp(obj, "".dup)
+ {k: 1, "": :null, "0": :zero, 100=>:ten}
+ EXPECT
+ end
+end
+
end
diff --git a/test/test_pstore.rb b/test/test_pstore.rb
index fe5f8711a4..7dfbdca367 100644
--- a/test/test_pstore.rb
+++ b/test/test_pstore.rb
@@ -144,6 +144,38 @@ class PStoreTest < Test::Unit::TestCase
assert_equal(bug5311, @pstore.transaction {@pstore["Bug5311"]}, bug5311)
end
+ def test_key_p
+ [:key?, :root?].each do |method|
+ clear_store
+ @pstore.transaction do
+ @pstore[:foo] = 0
+ assert_equal(true, @pstore.send(method, :foo))
+ assert_equal(false, @pstore.send(method, :bar))
+ end
+ end
+ end
+
+ def test_keys
+ [:keys, :roots].each do |method|
+ clear_store
+ @pstore.transaction do
+ assert_equal([], @pstore.send(method))
+ end
+ @pstore.transaction do
+ @pstore[:foo] = 0
+ assert_equal([:foo], @pstore.send(method))
+ end
+ end
+ end
+
+ def clear_store
+ @pstore.transaction do
+ @pstore.keys.each do |key|
+ @pstore.delete(key)
+ end
+ end
+ end
+
def second_file
File.join(Dir.tmpdir, "pstore.tmp2.#{Process.pid}")
end
diff --git a/test/test_pty.rb b/test/test_pty.rb
index 9e40a3d2fb..1c0c6fb3e8 100644
--- a/test/test_pty.rb
+++ b/test/test_pty.rb
@@ -14,7 +14,7 @@ class TestPTY < Test::Unit::TestCase
def test_spawn_without_block
r, w, pid = PTY.spawn(RUBY, '-e', 'puts "a"')
rescue RuntimeError
- skip $!
+ omit $!
else
assert_equal("a\r\n", r.gets)
ensure
@@ -34,7 +34,7 @@ class TestPTY < Test::Unit::TestCase
end
}
rescue RuntimeError
- skip $!
+ omit $!
end
def test_commandline
@@ -49,7 +49,7 @@ class TestPTY < Test::Unit::TestCase
end
}
rescue RuntimeError
- skip $!
+ omit $!
end
def test_argv0
@@ -63,13 +63,13 @@ class TestPTY < Test::Unit::TestCase
end
}
rescue RuntimeError
- skip $!
+ omit $!
end
def test_open_without_block
ret = PTY.open
rescue RuntimeError
- skip $!
+ omit $!
else
assert_kind_of(Array, ret)
assert_equal(2, ret.length)
@@ -100,7 +100,7 @@ class TestPTY < Test::Unit::TestCase
x
}
rescue RuntimeError
- skip $!
+ omit $!
else
assert(r[0].closed?)
assert(r[1].closed?)
@@ -115,7 +115,7 @@ class TestPTY < Test::Unit::TestCase
assert(master.closed?)
}
rescue RuntimeError
- skip $!
+ omit $!
else
assert_nothing_raised {
PTY.open {|master, slave|
@@ -133,7 +133,7 @@ class TestPTY < Test::Unit::TestCase
assert_equal("bar", slave.gets.chomp)
}
rescue RuntimeError
- skip $!
+ omit $!
end
def test_stat_slave
@@ -143,7 +143,7 @@ class TestPTY < Test::Unit::TestCase
assert_equal(0600, s.mode & 0777)
}
rescue RuntimeError
- skip $!
+ omit $!
end
def test_close_master
@@ -152,7 +152,7 @@ class TestPTY < Test::Unit::TestCase
assert_raise(EOFError) { slave.readpartial(10) }
}
rescue RuntimeError
- skip $!
+ omit $!
end
def test_close_slave
@@ -165,7 +165,7 @@ class TestPTY < Test::Unit::TestCase
) { master.readpartial(10) }
}
rescue RuntimeError
- skip $!
+ omit $!
end
def test_getpty_nonexistent
@@ -175,7 +175,7 @@ class TestPTY < Test::Unit::TestCase
begin
PTY.getpty(File.join(tmpdir, "no-such-command"))
rescue RuntimeError
- skip $!
+ omit $!
end
}
end
@@ -194,7 +194,7 @@ class TestPTY < Test::Unit::TestCase
end until st2 = PTY.check(pid)
end
rescue RuntimeError
- skip $!
+ omit $!
else
assert_nil(st1)
assert_equal(pid, st2.pid)
@@ -212,7 +212,7 @@ class TestPTY < Test::Unit::TestCase
st2 = assert_raise(PTY::ChildExited, bug2642) {PTY.check(pid, true)}.status
end
rescue RuntimeError
- skip $!
+ omit $!
else
assert_nil(st1)
assert_equal(pid, st2.pid)
@@ -234,6 +234,6 @@ class TestPTY < Test::Unit::TestCase
end
}
rescue RuntimeError
- skip $!
+ omit $!
end
end if defined? PTY
diff --git a/test/test_rbconfig.rb b/test/test_rbconfig.rb
index fcbbbd8500..1bbf01b9a6 100644
--- a/test/test_rbconfig.rb
+++ b/test/test_rbconfig.rb
@@ -51,13 +51,4 @@ class TestRbConfig < Test::Unit::TestCase
assert_match(/\$\(sitearch|\$\(rubysitearchprefix\)/, val, "#{key} #{bug7823}")
end
end
-
- if /darwin/ =~ RUBY_PLATFORM
- def test_sdkroot
- assert_separately([{"SDKROOT" => "$(prefix)/SDKRoot"}], "#{<<~"begin;"}\n#{<<~'end;'}")
- begin;
- assert_equal RbConfig::CONFIG["prefix"]+"/SDKRoot", RbConfig::CONFIG["SDKROOT"]
- end;
- end
- end
end
diff --git a/test/test_securerandom.rb b/test/test_securerandom.rb
index ab96952e37..e4a0e17365 100644
--- a/test/test_securerandom.rb
+++ b/test/test_securerandom.rb
@@ -1,22 +1,17 @@
# frozen_string_literal: false
require 'test/unit'
require 'securerandom'
-require 'tempfile'
+require_relative 'ruby/test_random_formatter'
# This testcase does NOT aim to test cryptographically strongness and randomness.
class TestSecureRandom < Test::Unit::TestCase
+ include Random::Formatter::FormatterTest
+ include Random::Formatter::NotDefaultTest
+
def setup
@it = SecureRandom
end
- def test_s_random_bytes
- assert_equal(16, @it.random_bytes.size)
- assert_equal(Encoding::ASCII_8BIT, @it.random_bytes.encoding)
- 65.times do |idx|
- assert_equal(idx, @it.random_bytes(idx).size)
- end
- end
-
# This test took 2 minutes on my machine.
# And 65536 times loop could not be enough for forcing PID recycle.
if false
@@ -70,114 +65,6 @@ if false
end
end
- def test_s_hex
- s = @it.hex
- assert_equal(16 * 2, s.size)
- assert_match(/\A\h+\z/, s)
- 33.times do |idx|
- s = @it.hex(idx)
- assert_equal(idx * 2, s.size)
- assert_match(/\A\h*\z/, s)
- end
- end
-
- def test_hex_encoding
- assert_equal(Encoding::US_ASCII, @it.hex.encoding)
- end
-
- def test_s_base64
- assert_equal(16, @it.base64.unpack('m*')[0].size)
- 17.times do |idx|
- assert_equal(idx, @it.base64(idx).unpack('m*')[0].size)
- end
- end
-
- def test_s_urlsafe_base64
- safe = /[\n+\/]/
- 65.times do |idx|
- assert_not_match(safe, @it.urlsafe_base64(idx))
- end
- # base64 can include unsafe byte
- assert((0..10000).any? {|idx| safe =~ @it.base64(idx)}, "None of base64(0..10000) is url-safe")
- end
-
- def test_s_random_number_float
- 101.times do
- v = @it.random_number
- assert_in_range(0.0...1.0, v)
- end
- end
-
- def test_s_random_number_float_by_zero
- 101.times do
- v = @it.random_number(0)
- assert_in_range(0.0...1.0, v)
- end
- end
-
- def test_s_random_number_int
- 101.times do |idx|
- next if idx.zero?
- v = @it.random_number(idx)
- assert_in_range(0...idx, v)
- end
- end
-
- def test_s_random_number_not_default
- msg = "SecureRandom#random_number should not be affected by srand"
- seed = srand(0)
- x = @it.random_number(1000)
- 10.times do|i|
- srand(0)
- return unless @it.random_number(1000) == x
- end
- srand(0)
- assert_not_equal(x, @it.random_number(1000), msg)
- ensure
- srand(seed) if seed
- end
-
- def test_uuid
- uuid = @it.uuid
- assert_equal(36, uuid.size)
-
- # Check time_hi_and_version and clock_seq_hi_res bits (RFC 4122 4.4)
- assert_equal('4', uuid[14])
- assert_include(%w'8 9 a b', uuid[19])
-
- assert_match(/\A\h{8}-\h{4}-\h{4}-\h{4}-\h{12}\z/, uuid)
- end
-
- def test_alphanumeric
- 65.times do |n|
- an = @it.alphanumeric(n)
- assert_match(/\A[0-9a-zA-Z]*\z/, an)
- assert_equal(n, an.length)
- end
- end
-
- def protect
- begin
- yield
- rescue NotImplementedError
- # ignore
- end
- end
-
- def remove_feature(basename)
- $LOADED_FEATURES.delete_if { |path|
- if File.basename(path) == basename
- $LOAD_PATH.any? { |dir|
- File.exist?(File.join(dir, basename))
- }
- end
- }
- end
-
- def assert_in_range(range, result, mesg = nil)
- assert(range.cover?(result), build_message(mesg, "Expected #{result} to be in #{range}"))
- end
-
def test_with_openssl
begin
require 'openssl'
diff --git a/test/test_set.rb b/test/test_set.rb
deleted file mode 100644
index b92930a445..0000000000
--- a/test/test_set.rb
+++ /dev/null
@@ -1,840 +0,0 @@
-# frozen_string_literal: false
-require 'test/unit'
-require 'set'
-
-class TC_Set < Test::Unit::TestCase
- class Set2 < Set
- end
-
- def test_aref
- assert_nothing_raised {
- Set[]
- Set[nil]
- Set[1,2,3]
- }
-
- assert_equal(0, Set[].size)
- assert_equal(1, Set[nil].size)
- assert_equal(1, Set[[]].size)
- assert_equal(1, Set[[nil]].size)
-
- set = Set[2,4,6,4]
- assert_equal(Set.new([2,4,6]), set)
- end
-
- def test_s_new
- assert_nothing_raised {
- Set.new()
- Set.new(nil)
- Set.new([])
- Set.new([1,2])
- Set.new('a'..'c')
- }
- assert_raise(ArgumentError) {
- Set.new(false)
- }
- assert_raise(ArgumentError) {
- Set.new(1)
- }
- assert_raise(ArgumentError) {
- Set.new(1,2)
- }
-
- assert_equal(0, Set.new().size)
- assert_equal(0, Set.new(nil).size)
- assert_equal(0, Set.new([]).size)
- assert_equal(1, Set.new([nil]).size)
-
- ary = [2,4,6,4]
- set = Set.new(ary)
- ary.clear
- assert_equal(false, set.empty?)
- assert_equal(3, set.size)
-
- ary = [1,2,3]
-
- s = Set.new(ary) { |o| o * 2 }
- assert_equal([2,4,6], s.sort)
- end
-
- def test_clone
- set1 = Set.new
- set2 = set1.clone
- set1 << 'abc'
- assert_equal(Set.new, set2)
- end
-
- def test_dup
- set1 = Set[1,2]
- set2 = set1.dup
-
- assert_not_same(set1, set2)
-
- assert_equal(set1, set2)
-
- set1.add(3)
-
- assert_not_equal(set1, set2)
- end
-
- def test_size
- assert_equal(0, Set[].size)
- assert_equal(2, Set[1,2].size)
- assert_equal(2, Set[1,2,1].size)
- end
-
- def test_empty?
- assert_equal(true, Set[].empty?)
- assert_equal(false, Set[1, 2].empty?)
- end
-
- def test_clear
- set = Set[1,2]
- ret = set.clear
-
- assert_same(set, ret)
- assert_equal(true, set.empty?)
- end
-
- def test_replace
- set = Set[1,2]
- ret = set.replace('a'..'c')
-
- assert_same(set, ret)
- assert_equal(Set['a','b','c'], set)
-
- set = Set[1,2]
- assert_raise(ArgumentError) {
- set.replace(3)
- }
- assert_equal(Set[1,2], set)
- end
-
- def test_to_a
- set = Set[1,2,3,2]
- ary = set.to_a
-
- assert_equal([1,2,3], ary.sort)
- end
-
- def test_flatten
- # test1
- set1 = Set[
- 1,
- Set[
- 5,
- Set[7,
- Set[0]
- ],
- Set[6,2],
- 1
- ],
- 3,
- Set[3,4]
- ]
-
- set2 = set1.flatten
- set3 = Set.new(0..7)
-
- assert_not_same(set2, set1)
- assert_equal(set3, set2)
-
- # test2; destructive
- orig_set1 = set1
- set1.flatten!
-
- assert_same(orig_set1, set1)
- assert_equal(set3, set1)
-
- # test3; multiple occurrences of a set in an set
- set1 = Set[1, 2]
- set2 = Set[set1, Set[set1, 4], 3]
-
- assert_nothing_raised {
- set2.flatten!
- }
-
- assert_equal(Set.new(1..4), set2)
-
- # test4; recursion
- set2 = Set[]
- set1 = Set[1, set2]
- set2.add(set1)
-
- assert_raise(ArgumentError) {
- set1.flatten!
- }
-
- # test5; miscellaneous
- empty = Set[]
- set = Set[Set[empty, "a"],Set[empty, "b"]]
-
- assert_nothing_raised {
- set.flatten
- }
-
- set1 = empty.merge(Set["no_more", set])
-
- assert_nil(Set.new(0..31).flatten!)
-
- x = Set[Set[],Set[1,2]].flatten!
- y = Set[1,2]
-
- assert_equal(x, y)
- end
-
- def test_include?
- set = Set[1,2,3]
-
- assert_equal(true, set.include?(1))
- assert_equal(true, set.include?(2))
- assert_equal(true, set.include?(3))
- assert_equal(false, set.include?(0))
- assert_equal(false, set.include?(nil))
-
- set = Set["1",nil,"2",nil,"0","1",false]
- assert_equal(true, set.include?(nil))
- assert_equal(true, set.include?(false))
- assert_equal(true, set.include?("1"))
- assert_equal(false, set.include?(0))
- assert_equal(false, set.include?(true))
- end
-
- def test_eqq
- set = Set[1,2,3]
-
- assert_equal(true, set === 1)
- assert_equal(true, set === 2)
- assert_equal(true, set === 3)
- assert_equal(false, set === 0)
- assert_equal(false, set === nil)
-
- set = Set["1",nil,"2",nil,"0","1",false]
- assert_equal(true, set === nil)
- assert_equal(true, set === false)
- assert_equal(true, set === "1")
- assert_equal(false, set === 0)
- assert_equal(false, set === true)
- end
-
- def test_superset?
- set = Set[1,2,3]
-
- assert_raise(ArgumentError) {
- set.superset?()
- }
-
- assert_raise(ArgumentError) {
- set.superset?(2)
- }
-
- assert_raise(ArgumentError) {
- set.superset?([2])
- }
-
- [Set, Set2].each { |klass|
- assert_equal(true, set.superset?(klass[]), klass.name)
- assert_equal(true, set.superset?(klass[1,2]), klass.name)
- assert_equal(true, set.superset?(klass[1,2,3]), klass.name)
- assert_equal(false, set.superset?(klass[1,2,3,4]), klass.name)
- assert_equal(false, set.superset?(klass[1,4]), klass.name)
-
- assert_equal(true, set >= klass[1,2,3], klass.name)
- assert_equal(true, set >= klass[1,2], klass.name)
-
- assert_equal(true, Set[].superset?(klass[]), klass.name)
- }
- end
-
- def test_proper_superset?
- set = Set[1,2,3]
-
- assert_raise(ArgumentError) {
- set.proper_superset?()
- }
-
- assert_raise(ArgumentError) {
- set.proper_superset?(2)
- }
-
- assert_raise(ArgumentError) {
- set.proper_superset?([2])
- }
-
- [Set, Set2].each { |klass|
- assert_equal(true, set.proper_superset?(klass[]), klass.name)
- assert_equal(true, set.proper_superset?(klass[1,2]), klass.name)
- assert_equal(false, set.proper_superset?(klass[1,2,3]), klass.name)
- assert_equal(false, set.proper_superset?(klass[1,2,3,4]), klass.name)
- assert_equal(false, set.proper_superset?(klass[1,4]), klass.name)
-
- assert_equal(false, set > klass[1,2,3], klass.name)
- assert_equal(true, set > klass[1,2], klass.name)
-
- assert_equal(false, Set[].proper_superset?(klass[]), klass.name)
- }
- end
-
- def test_subset?
- set = Set[1,2,3]
-
- assert_raise(ArgumentError) {
- set.subset?()
- }
-
- assert_raise(ArgumentError) {
- set.subset?(2)
- }
-
- assert_raise(ArgumentError) {
- set.subset?([2])
- }
-
- [Set, Set2].each { |klass|
- assert_equal(true, set.subset?(klass[1,2,3,4]), klass.name)
- assert_equal(true, set.subset?(klass[1,2,3]), klass.name)
- assert_equal(false, set.subset?(klass[1,2]), klass.name)
- assert_equal(false, set.subset?(klass[]), klass.name)
-
- assert_equal(true, set <= klass[1,2,3], klass.name)
- assert_equal(true, set <= klass[1,2,3,4], klass.name)
-
- assert_equal(true, Set[].subset?(klass[1]), klass.name)
- assert_equal(true, Set[].subset?(klass[]), klass.name)
- }
- end
-
- def test_proper_subset?
- set = Set[1,2,3]
-
- assert_raise(ArgumentError) {
- set.proper_subset?()
- }
-
- assert_raise(ArgumentError) {
- set.proper_subset?(2)
- }
-
- assert_raise(ArgumentError) {
- set.proper_subset?([2])
- }
-
- [Set, Set2].each { |klass|
- assert_equal(true, set.proper_subset?(klass[1,2,3,4]), klass.name)
- assert_equal(false, set.proper_subset?(klass[1,2,3]), klass.name)
- assert_equal(false, set.proper_subset?(klass[1,2]), klass.name)
- assert_equal(false, set.proper_subset?(klass[]), klass.name)
-
- assert_equal(false, set < klass[1,2,3], klass.name)
- assert_equal(true, set < klass[1,2,3,4], klass.name)
-
- assert_equal(false, Set[].proper_subset?(klass[]), klass.name)
- }
- end
-
- def test_spacecraft_operator
- set = Set[1,2,3]
-
- assert_nil(set <=> 2)
-
- assert_nil(set <=> set.to_a)
-
- [Set, Set2].each { |klass|
- assert_equal(-1, set <=> klass[1,2,3,4], klass.name)
- assert_equal( 0, set <=> klass[3,2,1] , klass.name)
- assert_equal(nil, set <=> klass[1,2,4] , klass.name)
- assert_equal(+1, set <=> klass[2,3] , klass.name)
- assert_equal(+1, set <=> klass[] , klass.name)
-
- assert_equal(0, Set[] <=> klass[], klass.name)
- }
- end
-
- def assert_intersect(expected, set, other)
- case expected
- when true
- assert_send([set, :intersect?, other])
- assert_send([set, :intersect?, other.to_a])
- assert_send([other, :intersect?, set])
- assert_not_send([set, :disjoint?, other])
- assert_not_send([set, :disjoint?, other.to_a])
- assert_not_send([other, :disjoint?, set])
- when false
- assert_not_send([set, :intersect?, other])
- assert_not_send([set, :intersect?, other.to_a])
- assert_not_send([other, :intersect?, set])
- assert_send([set, :disjoint?, other])
- assert_send([set, :disjoint?, other.to_a])
- assert_send([other, :disjoint?, set])
- when Class
- assert_raise(expected) {
- set.intersect?(other)
- }
- assert_raise(expected) {
- set.disjoint?(other)
- }
- else
- raise ArgumentError, "%s: unsupported expected value: %s" % [__method__, expected.inspect]
- end
- end
-
- def test_intersect?
- set = Set[3,4,5]
-
- assert_intersect(ArgumentError, set, 3)
- assert_intersect(true, set, Set[2,4,6])
-
- assert_intersect(true, set, set)
- assert_intersect(true, set, Set[2,4])
- assert_intersect(true, set, Set[5,6,7])
- assert_intersect(true, set, Set[1,2,6,8,4])
-
- assert_intersect(false, set, Set[])
- assert_intersect(false, set, Set[0,2])
- assert_intersect(false, set, Set[0,2,6])
- assert_intersect(false, set, Set[0,2,6,8,10])
-
- # Make sure set hasn't changed
- assert_equal(Set[3,4,5], set)
- end
-
- def test_each
- ary = [1,3,5,7,10,20]
- set = Set.new(ary)
-
- ret = set.each { |o| }
- assert_same(set, ret)
-
- e = set.each
- assert_instance_of(Enumerator, e)
-
- assert_nothing_raised {
- set.each { |o|
- ary.delete(o) or raise "unexpected element: #{o}"
- }
-
- ary.empty? or raise "forgotten elements: #{ary.join(', ')}"
- }
-
- assert_equal(6, e.size)
- set << 42
- assert_equal(7, e.size)
- end
-
- def test_add
- set = Set[1,2,3]
-
- ret = set.add(2)
- assert_same(set, ret)
- assert_equal(Set[1,2,3], set)
-
- ret = set.add?(2)
- assert_nil(ret)
- assert_equal(Set[1,2,3], set)
-
- ret = set.add(4)
- assert_same(set, ret)
- assert_equal(Set[1,2,3,4], set)
-
- ret = set.add?(5)
- assert_same(set, ret)
- assert_equal(Set[1,2,3,4,5], set)
- end
-
- def test_delete
- set = Set[1,2,3]
-
- ret = set.delete(4)
- assert_same(set, ret)
- assert_equal(Set[1,2,3], set)
-
- ret = set.delete?(4)
- assert_nil(ret)
- assert_equal(Set[1,2,3], set)
-
- ret = set.delete(2)
- assert_equal(set, ret)
- assert_equal(Set[1,3], set)
-
- ret = set.delete?(1)
- assert_equal(set, ret)
- assert_equal(Set[3], set)
- end
-
- def test_delete_if
- set = Set.new(1..10)
- ret = set.delete_if { |i| i > 10 }
- assert_same(set, ret)
- assert_equal(Set.new(1..10), set)
-
- set = Set.new(1..10)
- ret = set.delete_if { |i| i % 3 == 0 }
- assert_same(set, ret)
- assert_equal(Set[1,2,4,5,7,8,10], set)
-
- set = Set.new(1..10)
- enum = set.delete_if
- assert_equal(set.size, enum.size)
- assert_same(set, enum.each { |i| i % 3 == 0 })
- assert_equal(Set[1,2,4,5,7,8,10], set)
- end
-
- def test_keep_if
- set = Set.new(1..10)
- ret = set.keep_if { |i| i <= 10 }
- assert_same(set, ret)
- assert_equal(Set.new(1..10), set)
-
- set = Set.new(1..10)
- ret = set.keep_if { |i| i % 3 != 0 }
- assert_same(set, ret)
- assert_equal(Set[1,2,4,5,7,8,10], set)
-
- set = Set.new(1..10)
- enum = set.keep_if
- assert_equal(set.size, enum.size)
- assert_same(set, enum.each { |i| i % 3 != 0 })
- assert_equal(Set[1,2,4,5,7,8,10], set)
- end
-
- def test_collect!
- set = Set[1,2,3,'a','b','c',-1..1,2..4]
-
- ret = set.collect! { |i|
- case i
- when Numeric
- i * 2
- when String
- i.upcase
- else
- nil
- end
- }
-
- assert_same(set, ret)
- assert_equal(Set[2,4,6,'A','B','C',nil], set)
-
- set = Set[1,2,3,'a','b','c',-1..1,2..4]
- enum = set.collect!
-
- assert_equal(set.size, enum.size)
- assert_same(set, enum.each { |i|
- case i
- when Numeric
- i * 2
- when String
- i.upcase
- else
- nil
- end
- })
- assert_equal(Set[2,4,6,'A','B','C',nil], set)
- end
-
- def test_reject!
- set = Set.new(1..10)
-
- ret = set.reject! { |i| i > 10 }
- assert_nil(ret)
- assert_equal(Set.new(1..10), set)
-
- ret = set.reject! { |i| i % 3 == 0 }
- assert_same(set, ret)
- assert_equal(Set[1,2,4,5,7,8,10], set)
-
- set = Set.new(1..10)
- enum = set.reject!
- assert_equal(set.size, enum.size)
- assert_same(set, enum.each { |i| i % 3 == 0 })
- assert_equal(Set[1,2,4,5,7,8,10], set)
- end
-
- def test_select!
- set = Set.new(1..10)
- ret = set.select! { |i| i <= 10 }
- assert_equal(nil, ret)
- assert_equal(Set.new(1..10), set)
-
- set = Set.new(1..10)
- ret = set.select! { |i| i % 3 != 0 }
- assert_same(set, ret)
- assert_equal(Set[1,2,4,5,7,8,10], set)
-
- set = Set.new(1..10)
- enum = set.select!
- assert_equal(set.size, enum.size)
- assert_equal(nil, enum.each { |i| i <= 10 })
- assert_equal(Set.new(1..10), set)
- end
-
- def test_filter!
- set = Set.new(1..10)
- ret = set.filter! { |i| i <= 10 }
- assert_equal(nil, ret)
- assert_equal(Set.new(1..10), set)
-
- set = Set.new(1..10)
- ret = set.filter! { |i| i % 3 != 0 }
- assert_same(set, ret)
- assert_equal(Set[1,2,4,5,7,8,10], set)
-
- set = Set.new(1..10)
- enum = set.filter!
- assert_equal(set.size, enum.size)
- assert_equal(nil, enum.each { |i| i <= 10 })
- assert_equal(Set.new(1..10), set)
- end
-
- def test_merge
- set = Set[1,2,3]
-
- ret = set.merge([2,4,6])
- assert_same(set, ret)
- assert_equal(Set[1,2,3,4,6], set)
- end
-
- def test_subtract
- set = Set[1,2,3]
-
- ret = set.subtract([2,4,6])
- assert_same(set, ret)
- assert_equal(Set[1,3], set)
- end
-
- def test_plus
- set = Set[1,2,3]
-
- ret = set + [2,4,6]
- assert_not_same(set, ret)
- assert_equal(Set[1,2,3,4,6], ret)
- end
-
- def test_minus
- set = Set[1,2,3]
-
- ret = set - [2,4,6]
- assert_not_same(set, ret)
- assert_equal(Set[1,3], ret)
- end
-
- def test_and
- set = Set[1,2,3,4]
-
- ret = set & [2,4,6]
- assert_not_same(set, ret)
- assert_equal(Set[2,4], ret)
- end
-
- def test_xor
- set = Set[1,2,3,4]
- ret = set ^ [2,4,5,5]
- assert_not_same(set, ret)
- assert_equal(Set[1,3,5], ret)
- end
-
- def test_eq
- set1 = Set[2,3,1]
- set2 = Set[1,2,3]
-
- assert_equal(set1, set1)
- assert_equal(set1, set2)
- assert_not_equal(Set[1], [1])
-
- set1 = Class.new(Set)["a", "b"]
- set1.add(set1).reset # Make recursive
- set2 = Set["a", "b", Set["a", "b", set1]]
-
- assert_equal(set1, set2)
-
- assert_not_equal(Set[Exception.new,nil], Set[Exception.new,Exception.new], "[ruby-dev:26127]")
- end
-
- def test_classify
- set = Set.new(1..10)
- ret = set.classify { |i| i % 3 }
-
- assert_equal(3, ret.size)
- assert_instance_of(Hash, ret)
- ret.each_value { |value| assert_instance_of(Set, value) }
- assert_equal(Set[3,6,9], ret[0])
- assert_equal(Set[1,4,7,10], ret[1])
- assert_equal(Set[2,5,8], ret[2])
-
- set = Set.new(1..10)
- enum = set.classify
-
- assert_equal(set.size, enum.size)
- ret = enum.each { |i| i % 3 }
- assert_equal(3, ret.size)
- assert_instance_of(Hash, ret)
- ret.each_value { |value| assert_instance_of(Set, value) }
- assert_equal(Set[3,6,9], ret[0])
- assert_equal(Set[1,4,7,10], ret[1])
- assert_equal(Set[2,5,8], ret[2])
- end
-
- def test_divide
- set = Set.new(1..10)
- ret = set.divide { |i| i % 3 }
-
- assert_equal(3, ret.size)
- n = 0
- ret.each { |s| n += s.size }
- assert_equal(set.size, n)
- assert_equal(set, ret.flatten)
-
- set = Set[7,10,5,11,1,3,4,9,0]
- ret = set.divide { |a,b| (a - b).abs == 1 }
-
- assert_equal(4, ret.size)
- n = 0
- ret.each { |s| n += s.size }
- assert_equal(set.size, n)
- assert_equal(set, ret.flatten)
- ret.each { |s|
- if s.include?(0)
- assert_equal(Set[0,1], s)
- elsif s.include?(3)
- assert_equal(Set[3,4,5], s)
- elsif s.include?(7)
- assert_equal(Set[7], s)
- elsif s.include?(9)
- assert_equal(Set[9,10,11], s)
- else
- raise "unexpected group: #{s.inspect}"
- end
- }
-
- set = Set.new(1..10)
- enum = set.divide
- ret = enum.each { |i| i % 3 }
-
- assert_equal(set.size, enum.size)
- assert_equal(3, ret.size)
- n = 0
- ret.each { |s| n += s.size }
- assert_equal(set.size, n)
- assert_equal(set, ret.flatten)
- end
-
- def test_freeze
- orig = set = Set[1,2,3]
- assert_equal false, set.frozen?
- set << 4
- assert_same orig, set.freeze
- assert_equal true, set.frozen?
- assert_raise(FrozenError) {
- set << 5
- }
- assert_equal 4, set.size
- end
-
- def test_freeze_dup
- set1 = Set[1,2,3]
- set1.freeze
- set2 = set1.dup
-
- assert_not_predicate set2, :frozen?
- assert_nothing_raised {
- set2.add 4
- }
- end
-
- def test_freeze_clone
- set1 = Set[1,2,3]
- set1.freeze
- set2 = set1.clone
-
- assert_predicate set2, :frozen?
- assert_raise(FrozenError) {
- set2.add 5
- }
- end
-
- def test_freeze_clone_false
- set1 = Set[1,2,3]
- set1.freeze
- set2 = set1.clone(freeze: false)
-
- assert_not_predicate set2, :frozen?
- set2.add 5
- assert_equal Set[1,2,3,5], set2
- assert_equal Set[1,2,3], set1
- end if Kernel.instance_method(:initialize_clone).arity != 1
-
- def test_join
- assert_equal('123', Set[1, 2, 3].join)
- assert_equal('1 & 2 & 3', Set[1, 2, 3].join(' & '))
- end
-
- def test_inspect
- set1 = Set[1, 2]
- assert_equal('#<Set: {1, 2}>', set1.inspect)
-
- set2 = Set[Set[0], 1, 2, set1]
- assert_equal('#<Set: {#<Set: {0}>, 1, 2, #<Set: {1, 2}>}>', set2.inspect)
-
- set1.add(set2)
- assert_equal('#<Set: {#<Set: {0}>, 1, 2, #<Set: {1, 2, #<Set: {...}>}>}>', set2.inspect)
- end
-
- def test_to_s
- set1 = Set[1, 2]
- assert_equal('#<Set: {1, 2}>', set1.to_s)
-
- set2 = Set[Set[0], 1, 2, set1]
- assert_equal('#<Set: {#<Set: {0}>, 1, 2, #<Set: {1, 2}>}>', set2.to_s)
-
- set1.add(set2)
- assert_equal('#<Set: {#<Set: {0}>, 1, 2, #<Set: {1, 2, #<Set: {...}>}>}>', set2.to_s)
- end
-
- def test_compare_by_identity
- a1, a2 = "a", "a"
- b1, b2 = "b", "b"
- c = "c"
- array = [a1, b1, c, a2, b2]
-
- iset = Set.new.compare_by_identity
- assert_send([iset, :compare_by_identity?])
- iset.merge(array)
- assert_equal(5, iset.size)
- assert_equal(array.map(&:object_id).sort, iset.map(&:object_id).sort)
-
- set = Set.new
- assert_not_send([set, :compare_by_identity?])
- set.merge(array)
- assert_equal(3, set.size)
- assert_equal(array.uniq.sort, set.sort)
- end
-
- def test_reset
- [Set, Class.new(Set)].each { |klass|
- a = [1, 2]
- b = [1]
- set = klass.new([a, b])
-
- b << 2
- set.reset
-
- assert_equal(klass.new([a]), set, klass.name)
- }
- end
-end
-
-class TC_Enumerable < Test::Unit::TestCase
- def test_to_set
- ary = [2,5,4,3,2,1,3]
-
- set = ary.to_set
- assert_instance_of(Set, set)
- assert_equal([1,2,3,4,5], set.sort)
-
- set = ary.to_set { |o| o * -2 }
- assert_instance_of(Set, set)
- assert_equal([-10,-8,-6,-4,-2], set.sort)
-
- assert_same set, set.to_set
- assert_not_same set, set.to_set { |o| o }
- end
-end
diff --git a/test/test_singleton.rb b/test/test_singleton.rb
index b3c48bb5f5..e474a0ccc5 100644
--- a/test/test_singleton.rb
+++ b/test/test_singleton.rb
@@ -94,6 +94,23 @@ class TestSingleton < Test::Unit::TestCase
assert_same a, b
end
+ def test_inheritance_creates_separate_singleton
+ a = SingletonTest.instance
+ b = Class.new(SingletonTest).instance
+
+ assert_not_same a, b
+ end
+
+ def test_inheritance_instantiation
+ klass = Class.new do
+ include Singleton
+
+ public_class_method :new
+ end
+
+ assert Class.new(klass).new
+ end
+
def test_class_level_cloning_preserves_singleton_behavior
klass = SingletonTest.clone
@@ -101,4 +118,8 @@ class TestSingleton < Test::Unit::TestCase
b = klass.instance
assert_same a, b
end
+
+ def test_class_level_cloning_creates_separate_singleton
+ assert_not_same SingletonTest.instance, SingletonTest.clone.instance
+ end
end
diff --git a/test/test_syslog.rb b/test/test_syslog.rb
deleted file mode 100644
index 842ae8df49..0000000000
--- a/test/test_syslog.rb
+++ /dev/null
@@ -1,193 +0,0 @@
-# frozen_string_literal: false
-# Please only run this test on machines reasonable for testing.
-# If in doubt, ask your admin.
-
-require 'test/unit'
-
-begin
- require 'syslog'
-rescue LoadError
- # suppress error messages.
-end
-
-class TestSyslog < Test::Unit::TestCase
- def test_new
- assert_raise(NoMethodError) {
- Syslog.new
- }
- end
-
- def test_instance
- sl1 = Syslog.instance
- sl2 = Syslog.open
- sl3 = Syslog.instance
-
- assert_equal(Syslog, sl1)
- assert_equal(Syslog, sl2)
- assert_equal(Syslog, sl3)
- ensure
- Syslog.close if Syslog.opened?
- end
-
- def test_open
- # default parameters
- Syslog.open
-
- assert_equal($0, Syslog.ident)
- assert_equal(Syslog::LOG_PID | Syslog::LOG_CONS, Syslog.options)
- assert_equal(Syslog::LOG_USER, Syslog.facility)
-
- # open without close
- assert_raise(RuntimeError) {
- Syslog.open
- }
-
- Syslog.close
-
- # given parameters
- options = Syslog::LOG_NDELAY | Syslog::LOG_PID
- Syslog.open("foo", options, Syslog::LOG_DAEMON)
-
- assert_equal('foo', Syslog.ident)
- assert_equal(options, Syslog.options)
- assert_equal(Syslog::LOG_DAEMON, Syslog.facility)
-
- Syslog.close
-
- # default parameters again (after close)
- Syslog.open
- Syslog.close
-
- assert_equal(nil, Syslog.ident)
- assert_equal(nil, Syslog.options)
- assert_equal(nil, Syslog.facility)
-
- # block
- param = nil
- Syslog.open { |syslog|
- param = syslog
- }
- assert_equal(Syslog, param)
- ensure
- Syslog.close if Syslog.opened?
- end
-
- def test_opened?
- assert_equal(false, Syslog.opened?)
-
- Syslog.open
- assert_equal(true, Syslog.opened?)
-
- Syslog.close
- assert_equal(false, Syslog.opened?)
-
- Syslog.open {
- assert_equal(true, Syslog.opened?)
- }
-
- assert_equal(false, Syslog.opened?)
- end
-
- def test_close
- assert_raise(RuntimeError) {
- Syslog.close
- }
- end
-
- def test_mask
- assert_equal(nil, Syslog.mask)
-
- Syslog.open
-
- orig = Syslog.mask
-
- Syslog.mask = Syslog.LOG_UPTO(Syslog::LOG_ERR)
- assert_equal(Syslog.LOG_UPTO(Syslog::LOG_ERR), Syslog.mask)
-
- Syslog.mask = Syslog.LOG_MASK(Syslog::LOG_CRIT)
- assert_equal(Syslog.LOG_MASK(Syslog::LOG_CRIT), Syslog.mask)
-
- Syslog.mask = orig
- ensure
- Syslog.close if Syslog.opened?
- end
-
- def syslog_line_regex(ident, message)
- /(?:^| )#{Regexp.quote(ident)}(?:\[([1-9][0-9]*)\])?(?: | ([1-9][0-9]*) - - ||[: ].* )#{Regexp.quote(message)}$/
- end
-
- def test_log
- IO.pipe {|stderr|
- pid = fork {
- stderr[0].close
- STDERR.reopen(stderr[1])
- stderr[1].close
-
- options = Syslog::LOG_PERROR | Syslog::LOG_NDELAY
-
- Syslog.open("syslog_test", options) { |sl|
- sl.log(Syslog::LOG_NOTICE, "test1 - hello, %s!", "world")
- sl.notice("test1 - hello, %s!", "world")
- }
-
- Syslog.open("syslog_test", options | Syslog::LOG_PID) { |sl|
- sl.log(Syslog::LOG_CRIT, "test2 - pid")
- sl.crit("test2 - pid")
- }
- exit!
- }
-
- stderr[1].close
- Process.waitpid(pid)
-
- # LOG_PERROR is not implemented on Cygwin or Solaris. Only test
- # these on systems that define it.
- return unless Syslog.const_defined?(:LOG_PERROR)
- # LOG_PERROR is defined but not supported yet on Android.
- return if RUBY_PLATFORM =~ /android/
-
- 2.times {
- re = syslog_line_regex("syslog_test", "test1 - hello, world!")
- line = stderr[0].gets
- # In AIX, each LOG_PERROR output line has an appended empty line.
- if /aix/ =~ RUBY_PLATFORM && line =~ /^$/
- line = stderr[0].gets
- end
- m = re.match(line)
- assert_not_nil(m)
- if m[1]
- # pid is written regardless of LOG_PID on OS X 10.7+
- assert_equal(pid, m[1].to_i)
- end
- }
-
- 2.times {
- re = syslog_line_regex("syslog_test", "test2 - pid")
- line = stderr[0].gets
- # In AIX, each LOG_PERROR output line has an appended empty line.
- if /aix/ =~ RUBY_PLATFORM && line =~ /^$/
- line = stderr[0].gets
- end
- m = re.match(line)
- assert_not_nil(m)
- output_pid = m[1] || m[2]
- assert_not_nil(output_pid)
- assert_equal(pid, output_pid.to_i)
- }
- }
- end
-
- def test_inspect
- Syslog.open { |sl|
- assert_equal(format('<#%s: opened=true, ident="%s", options=%d, facility=%d, mask=%d>',
- Syslog,
- sl.ident,
- sl.options,
- sl.facility,
- sl.mask),
- sl.inspect)
- }
-
- assert_equal(format('<#%s: opened=false>', Syslog), Syslog.inspect)
- end
-end if defined?(Syslog)
diff --git a/test/test_tempfile.rb b/test/test_tempfile.rb
index 6b087f9207..8077cc3603 100644
--- a/test/test_tempfile.rb
+++ b/test/test_tempfile.rb
@@ -3,6 +3,8 @@ require 'test/unit'
require 'tempfile'
class TestTempfile < Test::Unit::TestCase
+ LIB_TEMPFILE_RB_PATH = File.expand_path(__dir__ + "/../lib/tempfile.rb")
+
def initialize(*)
super
@tempfile = nil
@@ -19,7 +21,7 @@ class TestTempfile < Test::Unit::TestCase
end
end
- def test_leackchecker
+ def test_leakchecker
assert_instance_of(Tempfile, Tempfile.allocate)
end
@@ -63,6 +65,22 @@ class TestTempfile < Test::Unit::TestCase
assert_match(/\.txt$/, File.basename(t.path))
end
+ def test_dup
+ t = tempfile
+ t2 = t.dup
+ t2.close
+ assert_equal true, t2.closed?
+ assert_equal false, t.closed?
+ end
+
+ def test_clone
+ t = tempfile
+ t2 = t.clone
+ t2.close
+ assert_equal true, t2.closed?
+ assert_equal false, t.closed?
+ end
+
def test_unlink
t = tempfile("foo")
path = t.path
@@ -156,8 +174,40 @@ class TestTempfile < Test::Unit::TestCase
end
end unless /mswin|mingw/ =~ RUBY_PLATFORM
+ def test_finalizer_removes_file
+ assert_in_out_err("-r#{LIB_TEMPFILE_RB_PATH}", <<~RUBY) do |(filename,*), (error,*)|
+ file = Tempfile.new("foo")
+ puts file.path
+ RUBY
+ assert_file.not_exist?(filename)
+ assert_nil error
+ end
+ end
+
+ def test_finalizer_removes_file_when_dup
+ assert_in_out_err("-r#{LIB_TEMPFILE_RB_PATH}", <<~RUBY) do |(filename,*), (error,*)|
+ file = Tempfile.new("foo")
+ file.dup
+ puts file.path
+ RUBY
+ assert_file.not_exist?(filename)
+ assert_nil error
+ end
+ end
+
+ def test_finalizer_removes_file_when_clone
+ assert_in_out_err("-r#{LIB_TEMPFILE_RB_PATH}", <<~RUBY) do |(filename,*), (error,*)|
+ file = Tempfile.new("foo")
+ file.clone
+ puts file.path
+ RUBY
+ assert_file.not_exist?(filename)
+ assert_nil error
+ end
+ end
+
def test_finalizer_does_not_unlink_if_already_unlinked
- assert_in_out_err('-rtempfile', <<-'EOS') do |(filename,*), (error,*)|
+ assert_in_out_err("-r#{LIB_TEMPFILE_RB_PATH}", <<-'EOS') do |(filename,*), (error,*)|
file = Tempfile.new('foo')
path = file.path
puts path
@@ -169,7 +219,7 @@ File.open(path, "w").close
assert_nil error
end
- assert_in_out_err('-rtempfile', <<-'EOS') do |(filename,*), (error,*)|
+ assert_in_out_err("-r#{LIB_TEMPFILE_RB_PATH}", <<-'EOS') do |(filename,*), (error,*)|
file = Tempfile.new('foo')
path = file.path
file.unlink
@@ -199,7 +249,7 @@ File.open(path, "w").close
end
def test_tempfile_is_unlinked_when_ruby_exits
- assert_in_out_err('-rtempfile', <<-'EOS') do |(filename), (error)|
+ assert_in_out_err("-r#{LIB_TEMPFILE_RB_PATH}", <<-'EOS') do |(filename), (error)|
puts Tempfile.new('foo').path
EOS
assert_file.for("tempfile must not be exist after GC.").not_exist?(filename)
@@ -209,8 +259,7 @@ puts Tempfile.new('foo').path
def test_tempfile_finalizer_does_not_run_if_unlinked
bug8768 = '[ruby-core:56521] [Bug #8768]'
- args = %w(--disable-gems -rtempfile)
- assert_in_out_err(args, <<-'EOS') do |(filename), (error)|
+ assert_in_out_err("-r#{LIB_TEMPFILE_RB_PATH}", <<-'EOS') do |(filename), (error)|
tmp = Tempfile.new('foo')
puts tmp.path
tmp.close
@@ -363,6 +412,14 @@ puts Tempfile.new('foo').path
assert_file.not_exist?(path)
end
+ def test_open
+ Tempfile.open {|f|
+ file = f.open
+ assert_kind_of File, file
+ assert_equal f.to_i, file.to_i
+ }
+ end
+
def test_open_traversal_dir
assert_mktmpdir_traversal do |traversal_path|
t = Tempfile.open([traversal_path, 'foo'])
@@ -402,4 +459,53 @@ puts Tempfile.new('foo').path
assert_not_send([File.absolute_path(actual), :start_with?, target])
end
end
+
+ def test_create_anonymous_without_block
+ t = Tempfile.create(anonymous: true)
+ assert_equal(File, t.class)
+ assert_equal(0600, t.stat.mode & 0777) unless /mswin|mingw/ =~ RUBY_PLATFORM
+ t.puts "foo"
+ t.rewind
+ assert_equal("foo\n", t.read)
+ t.close
+ ensure
+ t.close if t
+ end
+
+ def test_create_anonymous_with_block
+ result = Tempfile.create(anonymous: true) {|t|
+ assert_equal(File, t.class)
+ assert_equal(0600, t.stat.mode & 0777) unless /mswin|mingw/ =~ RUBY_PLATFORM
+ t.puts "foo"
+ t.rewind
+ assert_equal("foo\n", t.read)
+ :result
+ }
+ assert_equal(:result, result)
+ end
+
+ def test_create_anonymous_removes_file
+ Dir.mktmpdir {|d|
+ t = Tempfile.create("", d, anonymous: true)
+ t.close
+ assert_equal([], Dir.children(d))
+ }
+ end
+
+ def test_create_anonymous_path
+ Dir.mktmpdir {|d|
+ begin
+ t = Tempfile.create("", d, anonymous: true)
+ assert_equal(File.join(d, ""), t.path)
+ ensure
+ t.close if t
+ end
+ }
+ end
+
+ def test_create_anonymous_autoclose
+ Tempfile.create(anonymous: true) {|t|
+ assert_equal(true, t.autoclose?)
+ }
+ end
end
diff --git a/test/test_time.rb b/test/test_time.rb
index b50d8417cf..23e8e104a1 100644
--- a/test/test_time.rb
+++ b/test/test_time.rb
@@ -62,6 +62,15 @@ class TestTimeExtension < Test::Unit::TestCase # :nodoc:
assert_equal(true, t.utc?)
end
+ def test_rfc2822_nonlinear
+ pre = ->(n) {"0 Feb 00 00 :00" + " " * n}
+ assert_linear_performance([100, 500, 5000, 50_000], pre: pre) do |s|
+ assert_raise(ArgumentError) do
+ Time.rfc2822(s)
+ end
+ end
+ end
+
if defined?(Ractor)
def test_rfc2822_ractor
assert_ractor(<<~RUBY, require: 'time')
diff --git a/test/test_timeout.rb b/test/test_timeout.rb
index 71607ed680..34966f92a4 100644
--- a/test/test_timeout.rb
+++ b/test/test_timeout.rb
@@ -3,6 +3,50 @@ require 'test/unit'
require 'timeout'
class TestTimeout < Test::Unit::TestCase
+
+ def test_work_is_done_in_same_thread_as_caller
+ assert_equal Thread.current, Timeout.timeout(10){ Thread.current }
+ end
+
+ def test_work_is_done_in_same_fiber_as_caller
+ require 'fiber' # needed for ruby 3.0 and lower
+ assert_equal Fiber.current, Timeout.timeout(10){ Fiber.current }
+ end
+
+ def test_non_timing_out_code_is_successful
+ assert_nothing_raised do
+ assert_equal :ok, Timeout.timeout(1){ :ok }
+ end
+ end
+
+ def test_allows_zero_seconds
+ assert_nothing_raised do
+ assert_equal :ok, Timeout.timeout(0){:ok}
+ end
+ end
+
+ def test_allows_nil_seconds
+ assert_nothing_raised do
+ assert_equal :ok, Timeout.timeout(nil){:ok}
+ end
+ end
+
+ def test_included
+ c = Class.new do
+ include Timeout
+ def test
+ timeout(1) { :ok }
+ end
+ end
+ assert_nothing_raised do
+ assert_equal :ok, c.new.test
+ end
+ end
+
+ def test_yield_param
+ assert_equal [5, :ok], Timeout.timeout(5){|s| [s, :ok] }
+ end
+
def test_queue
q = Thread::Queue.new
assert_raise(Timeout::Error, "[ruby-dev:32935]") {
@@ -18,24 +62,87 @@ class TestTimeout < Test::Unit::TestCase
end
end
+ def test_nested_timeout
+ a = nil
+ assert_raise(Timeout::Error) do
+ Timeout.timeout(0.1) {
+ Timeout.timeout(30) {
+ nil while true
+ }
+ a = 1
+ }
+ end
+ assert_nil a
+ end
+
+ class MyNewErrorOuter < StandardError; end
+ class MyNewErrorInner < StandardError; end
+
+ # DOES NOT fail with
+ # - raise new(message) if exc.equal?(e)
+ # + raise new(message) if exc.class == e.class
+ def test_nested_timeout_error_identity
+ begin
+ Timeout.timeout(0.1, MyNewErrorOuter) {
+ Timeout.timeout(30, MyNewErrorInner) {
+ nil while true
+ }
+ }
+ rescue => e
+ assert e.class == MyNewErrorOuter
+ end
+ end
+
+ # DOES fail with
+ # - raise new(message) if exc.equal?(e)
+ # + raise new(message) if exc.class == e.class
+ def test_nested_timeout_which_error_bubbles_up
+ raised_exception = nil
+ begin
+ Timeout.timeout(0.1) {
+ Timeout.timeout(1) {
+ raise Timeout::ExitException.new("inner message")
+ }
+ }
+ rescue Exception => e
+ raised_exception = e
+ end
+
+ assert_equal 'inner message', raised_exception.message
+ end
+
def test_cannot_convert_into_time_interval
bug3168 = '[ruby-dev:41010]'
def (n = Object.new).zero?; false; end
assert_raise(TypeError, bug3168) {Timeout.timeout(n) { sleep 0.1 }}
end
- def test_skip_rescue
- bug8730 = '[Bug #8730]'
+ def test_skip_rescue_standarderror
+ e = nil
+ assert_raise_with_message(Timeout::Error, /execution expired/) do
+ Timeout.timeout 0.01 do
+ begin
+ sleep 3
+ rescue => e
+ flunk "should not see any exception but saw #{e.inspect}"
+ end
+ end
+ end
+ end
+
+ def test_raises_exception_internally
e = nil
- assert_raise_with_message(Timeout::Error, /execution expired/, bug8730) do
+ assert_raise_with_message(Timeout::Error, /execution expired/) do
Timeout.timeout 0.01 do
begin
sleep 3
- rescue Exception => e
+ rescue Exception => exc
+ e = exc
+ raise
end
end
end
- assert_nil(e, bug8730)
+ assert_equal Timeout::ExitException, e.class
end
def test_rescue_exit
@@ -103,11 +210,11 @@ class TestTimeout < Test::Unit::TestCase
bug11344 = '[ruby-dev:49179] [Bug #11344]'
ok = false
assert_raise(Timeout::Error) {
- Thread.handle_interrupt(Timeout::Error => :never) {
+ Thread.handle_interrupt(Timeout::ExitException => :never) {
Timeout.timeout(0.01) {
sleep 0.2
ok = true
- Thread.handle_interrupt(Timeout::Error => :on_blocking) {
+ Thread.handle_interrupt(Timeout::ExitException => :on_blocking) {
sleep 0.2
}
}
@@ -115,4 +222,50 @@ class TestTimeout < Test::Unit::TestCase
}
assert(ok, bug11344)
end
+
+ def test_fork
+ omit 'fork not supported' unless Process.respond_to?(:fork)
+ r, w = IO.pipe
+ pid = fork do
+ r.close
+ begin
+ r = Timeout.timeout(0.01) { sleep 5 }
+ w.write r.inspect
+ rescue Timeout::Error
+ w.write 'timeout'
+ ensure
+ w.close
+ end
+ end
+ w.close
+ Process.wait pid
+ assert_equal 'timeout', r.read
+ r.close
+ end
+
+ def test_threadgroup
+ assert_separately(%w[-rtimeout], <<-'end;')
+ tg = ThreadGroup.new
+ thr = Thread.new do
+ tg.add(Thread.current)
+ Timeout.timeout(10){}
+ end
+ thr.join
+ assert_equal [].to_s, tg.list.to_s
+ end;
+ end
+
+ # https://github.com/ruby/timeout/issues/24
+ def test_handling_enclosed_threadgroup
+ assert_separately(%w[-rtimeout], <<-'end;')
+ Thread.new {
+ t = Thread.current
+ group = ThreadGroup.new
+ group.add(t)
+ group.enclose
+
+ assert_equal 42, Timeout.timeout(1) { 42 }
+ }.join
+ end;
+ end
end
diff --git a/test/test_tmpdir.rb b/test/test_tmpdir.rb
index 7ef9f59b54..eae0610c87 100644
--- a/test/test_tmpdir.rb
+++ b/test/test_tmpdir.rb
@@ -12,7 +12,7 @@ class TestTmpdir < Test::Unit::TestCase
end
def test_world_writable
- skip "no meaning on this platform" if /mswin|mingw/ =~ RUBY_PLATFORM
+ omit "no meaning on this platform" if /mswin|mingw/ =~ RUBY_PLATFORM
Dir.mktmpdir do |tmpdir|
# ToDo: fix for parallel test
envs = %w[TMPDIR TMP TEMP]
@@ -23,14 +23,14 @@ class TestTmpdir < Test::Unit::TestCase
ENV[e] = tmpdirx
assert_not_equal(tmpdirx, assert_warn('') {Dir.tmpdir})
File.write(tmpdirx, "")
- assert_not_equal(tmpdirx, assert_warn(/not a directory/) {Dir.tmpdir})
+ assert_not_equal(tmpdirx, assert_warn(/\A#{e} is not a directory/) {Dir.tmpdir})
File.unlink(tmpdirx)
ENV[e] = tmpdir
assert_equal(tmpdir, Dir.tmpdir)
File.chmod(0555, tmpdir)
- assert_not_equal(tmpdir, assert_warn(/not writable/) {Dir.tmpdir})
+ assert_not_equal(tmpdir, assert_warn(/\A#{e} is not writable/) {Dir.tmpdir})
File.chmod(0777, tmpdir)
- assert_not_equal(tmpdir, assert_warn(/world-writable/) {Dir.tmpdir})
+ assert_not_equal(tmpdir, assert_warn(/\A#{e} is world-writable/) {Dir.tmpdir})
newdir = Dir.mktmpdir("d", tmpdir) do |dir|
assert_file.directory? dir
assert_equal(tmpdir, File.dirname(dir))
@@ -47,6 +47,18 @@ class TestTmpdir < Test::Unit::TestCase
end
end
+ def test_tmpdir_not_empty_parent
+ Dir.mktmpdir do |tmpdir|
+ envs = %w[TMPDIR TMP TEMP]
+ oldenv = envs.each_with_object({}) {|v, h| h[v] = ENV.delete(v)}
+ ENV[envs[0]] = ""
+ ENV[envs[1]] = tmpdir
+ assert_equal(tmpdir, Dir.tmpdir)
+ ensure
+ ENV.update(oldenv)
+ end
+ end
+
def test_no_homedir
bug7547 = '[ruby-core:50793]'
home, ENV["HOME"] = ENV["HOME"], nil
@@ -92,6 +104,12 @@ class TestTmpdir < Test::Unit::TestCase
end
end
+ def test_mktmpdir_not_empty_parent
+ assert_raise(ArgumentError) do
+ Dir.mktmpdir("foo", "")
+ end
+ end
+
def assert_mktmpdir_traversal
Dir.mktmpdir do |target|
target = target.chomp('/') + '/'
@@ -103,4 +121,20 @@ class TestTmpdir < Test::Unit::TestCase
end
end
end
+
+ def test_ractor
+ assert_ractor(<<~'end;', require: "tmpdir")
+ r = Ractor.new do
+ Dir.mktmpdir() do |d|
+ Ractor.yield d
+ Ractor.receive
+ end
+ end
+ dir = r.take
+ assert_file.directory? dir
+ r.send true
+ r.take
+ assert_file.not_exist? dir
+ end;
+ end
end
diff --git a/test/test_trick.rb b/test/test_trick.rb
index e37bda2efe..c5c19d079e 100644
--- a/test/test_trick.rb
+++ b/test/test_trick.rb
@@ -1,6 +1,9 @@
+# frozen_string_literal: false
+
require "test/unit"
require "ripper"
require "envutil"
+require "stringio"
# This is a test suite for TRICK entries, joke Ruby program contest.
# The programs are very unusual, and not practical.
@@ -11,24 +14,24 @@ class TestTRICK2013 < Test::Unit::TestCase
def test_kinaba
src = File.join(__dir__, "../sample/trick2013/kinaba/entry.rb")
expected = [*" ".."~"].join("") # all ASCII printables
- assert_in_out_err(["-W0", src], "", [expected])
+ assert_in_out_err(["-W0", "--disable-frozen-string-literal", src], "", [expected])
assert_equal(expected, File.read(src).chomp.chars.sort.join)
end
def test_mame
src = File.join(__dir__, "../sample/trick2013/mame/entry.rb")
ignore_dsp = "def open(_file, _mode); s = ''; def s.flush; self;end; yield s; end;"
- assert_in_out_err(["-W0"], ignore_dsp + File.read(src), File.read(src).lines(chomp: true), timeout: 60)
+ assert_in_out_err(["-W0", "--disable-frozen-string-literal"], ignore_dsp + File.read(src), File.read(src).lines(chomp: true), timeout: 60)
end
def test_shinh
src = File.join(__dir__, "../sample/trick2013/shinh/entry.rb")
- assert_in_out_err(["-W0", src], "", [])
+ assert_in_out_err(["-W0", "--disable-frozen-string-literal", src], "", [])
end
def test_yhara
src = File.join(__dir__, "../sample/trick2013/yhara/entry.rb")
- assert_in_out_err(["-W0", src], "", ["JUST ANOTHER RUBY HACKER"])
+ assert_in_out_err(["-W0", "--disable-frozen-string-literal", src], "", ["JUST ANOTHER RUBY HACKER"])
end
end
@@ -44,7 +47,7 @@ class TestTRICK2015 < Test::Unit::TestCase
end
pi = "3#{ a - b }"
- assert_in_out_err(["-W0", src], "", [pi], timeout: 60)
+ assert_in_out_err(["-W0", "--disable-frozen-string-literal", src], "", [pi], timeout: 60)
assert_equal(pi[0, 242], Ripper.tokenize(File.read(src)).grep(/\S/).map{|t|t.size%10}.join)
end
@@ -59,7 +62,7 @@ class TestTRICK2015 < Test::Unit::TestCase
s << n.to_s
end
- assert_in_out_err(["-W0", src, "27"], "", s)
+ assert_in_out_err(["-W0", "--disable-frozen-string-literal", src, "27"], "", s)
end
def test_monae
@@ -77,13 +80,13 @@ class TestTRICK2015 < Test::Unit::TestCase
end
expected = /\A#{ expected.map {|s| "#{ Regexp.quote(s) }\s*\n" }.join }\z/
- assert_in_out_err(["-W0", src], "", expected)
+ assert_in_out_err(["-W0", "--disable-frozen-string-literal", src], "", expected)
end
def test_eregon
src = File.join(__dir__, "../sample/trick2015/eregon/entry.rb")
- assert_in_out_err(["-W0", src], "", <<END.lines(chomp: true))
+ assert_in_out_err(["-W0", "--disable-frozen-string-literal", src], "", <<END.lines(chomp: true))
1 9 4 2 3 8 7 6 5
3 7 2 6 5 1 4 8 9
8 5 6 7 4 9 2 3 1
@@ -122,7 +125,7 @@ p cnf 3 5
1 3 0
END
- assert_in_out_err(["-W0", src], inp, ["s SATISFIABLE", "v 1 2 -3"])
+ assert_in_out_err(["-W0", "--disable-frozen-string-literal", src], inp, ["s SATISFIABLE", "v 1 2 -3"])
end
end
@@ -130,17 +133,17 @@ class TestTRICK2018 < Test::Unit::TestCase
def test_01_kinaba
src = File.join(__dir__, "../sample/trick2018/01-kinaba/entry.rb")
- assert_in_out_err(["-W0", src], "", [])
+ assert_in_out_err(["-W0", "--disable-frozen-string-literal", src], "", [])
end
def test_02_mame
src = File.join(__dir__, "../sample/trick2018/02-mame/entry.rb")
ignore_sleep = "def sleep(_); end;"
- assert_in_out_err(["-W0"], ignore_sleep + File.read(src)) do |stdout, _stderr, _status|
+ assert_in_out_err(["-W0", "--disable-frozen-string-literal"], ignore_sleep + File.read(src)) do |stdout, _stderr, _status|
code = stdout.join("\n") + "\n"
expected = code.lines(chomp: true)
- assert_in_out_err(["-W0"], ignore_sleep + code, expected)
+ assert_in_out_err(["-W0", "--disable-frozen-string-literal"], ignore_sleep + code, expected)
end
end
@@ -148,7 +151,7 @@ class TestTRICK2018 < Test::Unit::TestCase
src = File.join(__dir__, "../sample/trick2018/03-tompng/entry.rb")
# only syntax check because it requires chunky_png
- assert_in_out_err(["-W0", "-c", src], "", ["Syntax OK"])
+ assert_in_out_err(["-W0", "--disable-frozen-string-literal", "-c", src], "", ["Syntax OK"])
end
def test_04_colin
@@ -171,7 +174,7 @@ class TestTRICK2018 < Test::Unit::TestCase
end
end
END
- assert_in_out_err(["-W0"], code, <<END.lines(chomp: true), encoding: "UTF-8")
+ assert_in_out_err(["-W0", "--disable-frozen-string-literal"], code, <<END.lines(chomp: true), encoding: "UTF-8")
Math
Addition
One plus one equals two.
@@ -186,6 +189,87 @@ END
src = File.join(__dir__, "../sample/trick2018/05-tompng/entry.rb")
# only syntax check because it generates 3D model data
- assert_in_out_err(["-W0", "-c", src], "", ["Syntax OK"])
+ assert_in_out_err(["-W0", "--disable-frozen-string-literal", "-c", src], "", ["Syntax OK"])
+ end
+end
+
+class TestTRICK2022 < Test::Unit::TestCase
+ def test_01_tompng
+ src = File.join(__dir__, "../sample/trick2022/01-tompng/entry.rb")
+
+ # only syntax check because it requires matrix
+ assert_in_out_err(["-W0", "--disable-frozen-string-literal", "-c", src], "", ["Syntax OK"])
+ end
+
+ def test_02_tompng
+ src = File.join(__dir__, "../sample/trick2022/02-tompng/entry.rb")
+
+ # only syntax check because it works as a web server
+ assert_in_out_err(["-W0", "--disable-frozen-string-literal", "-c", src], "", ["Syntax OK"])
+ end
+
+ def test_03_mame
+ src = File.join(__dir__, "../sample/trick2022/03-mame/entry.rb")
+
+ # TODO
+ assert_in_out_err(["-W0", "--disable-frozen-string-literal", "-c", src], "", ["Syntax OK"])
+ end
+end
+
+class TestRubyKaigi2023🥢 < Test::Unit::TestCase
+ CHOPSTICKS = [<<~'0', <<~'1'] # by mame
+ BEGIN{q=:Ruby};p||=:Enjoy;END{puts p,q||2023}
+ 0
+ q=print(q||"/:|}\n")||p&&:@Matsumoto;p=:Kaigi
+ 1
+
+ def test_chopsticks_0
+ assert_in_out_err(%w[-W0], CHOPSTICKS[0], %w[Enjoy Ruby])
+ end
+
+ def test_chopsticks_1
+ assert_in_out_err(%w[-W0], CHOPSTICKS[1], %w[/:|}])
+ end
+
+ def test_chopsticks_0_1
+ assert_in_out_err(%w[-W0], "#{CHOPSTICKS[0]}\n#{CHOPSTICKS[1]}", %w[RubyKaigi @Matsumoto])
+ end
+
+ def test_chopsticks_1_0
+ assert_in_out_err(%w[-W0], "#{CHOPSTICKS[1]}\n#{CHOPSTICKS[0]}", %w[RubyKaigi 2023])
+ end
+end
+
+# https://github.com/mame/all-ruby-quine
+class TestAllRubyQuine < Test::Unit::TestCase
+ def test_all_ruby_quine
+ stdout_bak = $stdout
+ $stdout = StringIO.new
+ verbose_bak = $VERBOSE
+ $VERBOSE = nil
+ src = File.read(File.join(__dir__, "../sample/all-ruby-quine.rb"))
+
+ eval(src)
+
+ out = $stdout.string.lines(chomp: true)
+ $stdout = stdout_bak
+
+ # cheat OCR
+ font = {
+ "-" => 0x7ffffffffffe03fffffffffff, "." => 0x7fffffffffffffffffffc7f8f, "_" => 0x7fffffffffffffffffffff800,
+ "0" => 0x6030e03e07c0f81f03e038603, "1" => 0x70fc1f23fc7f8ff1fe3fc7c01, "2" => 0x4011f1fe3fc7e1f0f87c3f800,
+ "3" => 0x4031e3fe3f8e03fe3fe078c03, "4" => 0x783e0788e318e31c6003f1fe3, "5" => 0x0001fe3fc7f801fe1fe078401,
+ "6" => 0x78083e3fc7f8011e03e038401, "7" => 0x000fe1fc3f0fc3f0fc3f0fc3f, "8" => 0x4011f03e238e038e23e07c401,
+ "9" => 0x4010e03e03c400ff1fe078401, "a" => 0x7fffff00c787f88003e078408, "b" => 0x0ff1fe3fc408701f03e078001,
+ "c" => 0x7fffff8063c0ff1fe3fe3c601, "d" => 0x7f8ff1fe3004781f03e038408,
+ }.invert
+ out = (0...out.first.size / 15).map do |i|
+ font[(3..11).map {|j| out[j][i * 15 + 5, 11] }.join.gsub(/\S/, "#").tr("# ", "10").to_i(2)]
+ end.join
+
+ assert_equal(RUBY_VERSION, out)
+ ensure
+ $stdout = stdout_bak
+ $VERBOSE = verbose_bak
end
end
diff --git a/test/test_unicode_normalize.rb b/test/test_unicode_normalize.rb
index 034d71d808..8789ed92d2 100644
--- a/test/test_unicode_normalize.rb
+++ b/test/test_unicode_normalize.rb
@@ -24,7 +24,7 @@ class TestUnicodeNormalize
NormTest = Struct.new :source, :NFC, :NFD, :NFKC, :NFKD, :line
def self.read_tests
- lines = IO.readlines(expand_filename('NormalizationTest'), encoding: 'utf-8')
+ lines = File.readlines(expand_filename('NormalizationTest'), encoding: 'utf-8')
firstline = lines.shift
define_method "test_0_normalizationtest_firstline" do
assert_include(firstline, "NormalizationTest-#{UNICODE_VERSION}.txt")
diff --git a/test/uri/test_common.rb b/test/uri/test_common.rb
index 5e30cda41d..bccdeafeaf 100644
--- a/test/uri/test_common.rb
+++ b/test/uri/test_common.rb
@@ -3,16 +3,43 @@ require 'test/unit'
require 'envutil'
require 'uri'
-module URI
-
-
-class TestCommon < Test::Unit::TestCase
+class URI::TestCommon < Test::Unit::TestCase
def setup
end
def teardown
end
+ def test_fallback_constants
+ orig_verbose = $VERBOSE
+ $VERBOSE = nil
+ assert URI::ABS_URI
+ assert_raise(NameError) { URI::FOO }
+ ensure
+ $VERBOSE = orig_verbose
+ end
+
+ def test_parser_switch
+ assert_equal(URI::Parser, URI::RFC3986_Parser)
+ refute defined?(URI::REGEXP)
+ refute defined?(URI::PATTERN)
+
+ URI.parser = URI::RFC2396_PARSER
+
+ assert_equal(URI::Parser, URI::RFC2396_Parser)
+ assert defined?(URI::REGEXP)
+ assert defined?(URI::PATTERN)
+ assert defined?(URI::PATTERN::ESCAPED)
+
+ URI.parser = URI::RFC3986_PARSER
+
+ assert_equal(URI::Parser, URI::RFC3986_Parser)
+ refute defined?(URI::REGEXP)
+ refute defined?(URI::PATTERN)
+ ensure
+ URI.parser = URI::RFC3986_PARSER
+ end
+
def test_extract
EnvUtil.suppress_warning do
assert_equal(['http://example.com'],
@@ -41,18 +68,52 @@ class TestCommon < Test::Unit::TestCase
RUBY
end
+ DEFAULT_SCHEMES = ["FILE", "FTP", "HTTP", "HTTPS", "LDAP", "LDAPS", "MAILTO", "WS", "WSS"].sort.freeze
+
def test_register_scheme
- assert_equal(["FILE", "FTP", "HTTP", "HTTPS", "LDAP", "LDAPS", "MAILTO", "WS"].sort, URI.scheme_list.keys.sort)
+ assert_equal(DEFAULT_SCHEMES, URI.scheme_list.keys.sort)
foobar = Class.new(URI::Generic)
URI.register_scheme 'FOOBAR', foobar
begin
- assert_equal(["FILE", "FTP", "HTTP", "HTTPS", "LDAP", "LDAPS", "MAILTO", "WS", "FOOBAR"].sort, URI.scheme_list.keys.sort)
+ assert_include(URI.scheme_list.keys, "FOOBAR")
+ assert_equal foobar, URI.parse('foobar://localhost').class
ensure
URI.const_get(:Schemes).send(:remove_const, :FOOBAR)
end
- assert_equal(["FILE", "FTP", "HTTP", "HTTPS", "LDAP", "LDAPS", "MAILTO", "WS"].sort, URI.scheme_list.keys.sort)
+ assert_equal(DEFAULT_SCHEMES, URI.scheme_list.keys.sort)
+ end
+
+ def test_register_scheme_lowercase
+ assert_equal(DEFAULT_SCHEMES, URI.scheme_list.keys.sort)
+
+ foobar = Class.new(URI::Generic)
+ URI.register_scheme 'foobarlower', foobar
+ begin
+ assert_include(URI.scheme_list.keys, "FOOBARLOWER")
+ assert_equal foobar, URI.parse('foobarlower://localhost').class
+ ensure
+ URI.const_get(:Schemes).send(:remove_const, :FOOBARLOWER)
+ end
+
+ assert_equal(DEFAULT_SCHEMES, URI.scheme_list.keys.sort)
+ end
+
+ def test_register_scheme_with_symbols
+ # Valid schemes from https://www.iana.org/assignments/uri-schemes/uri-schemes.xhtml
+ some_uri_class = Class.new(URI::Generic)
+ assert_raise(NameError) { URI.register_scheme 'ms-search', some_uri_class }
+ assert_raise(NameError) { URI.register_scheme 'microsoft.windows.camera', some_uri_class }
+ assert_raise(NameError) { URI.register_scheme 'coaps+ws', some_uri_class }
+
+ ms_search_class = Class.new(URI::Generic)
+ URI.register_scheme 'MS_SEARCH', ms_search_class
+ begin
+ assert_equal URI::Generic, URI.parse('ms-search://localhost').class
+ ensure
+ URI.const_get(:Schemes).send(:remove_const, :MS_SEARCH)
+ end
end
def test_regexp
@@ -78,6 +139,17 @@ class TestCommon < Test::Unit::TestCase
assert_raise(NoMethodError) { Object.new.URI("http://www.ruby-lang.org/") }
end
+ def test_parse_timeout
+ pre = ->(n) {
+ 'https://example.com/dir/' + 'a' * (n * 100) + '/##.jpg'
+ }
+ assert_linear_performance((1..3).map {|i| 10**i}, rehearsal: 1000, pre: pre) do |uri|
+ assert_raise(URI::InvalidURIError) do
+ URI.parse(uri)
+ end
+ end
+ end
+
def test_encode_www_form_component
assert_equal("%00+%21%22%23%24%25%26%27%28%29*%2B%2C-.%2F09%3A%3B%3C%3D%3E%3F%40" \
"AZ%5B%5C%5D%5E_%60az%7B%7C%7D%7E",
@@ -130,6 +202,58 @@ class TestCommon < Test::Unit::TestCase
assert_nothing_raised(ArgumentError){URI.decode_www_form_component("x"*(1024*1024))}
end
+ def test_encode_uri_component
+ assert_equal("%00%20%21%22%23%24%25%26%27%28%29*%2B%2C-.%2F09%3A%3B%3C%3D%3E%3F%40" \
+ "AZ%5B%5C%5D%5E_%60az%7B%7C%7D%7E",
+ URI.encode_uri_component("\x00 !\"\#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~"))
+ assert_equal("%95A", URI.encode_uri_component(
+ "\x95\x41".force_encoding(Encoding::Shift_JIS)))
+ assert_equal("0B", URI.encode_uri_component(
+ "\x30\x42".force_encoding(Encoding::UTF_16BE)))
+ assert_equal("%1B%24B%24%22%1B%28B", URI.encode_uri_component(
+ "\e$B$\"\e(B".force_encoding(Encoding::ISO_2022_JP)))
+
+ assert_equal("%E3%81%82", URI.encode_uri_component(
+ "\u3042", Encoding::ASCII_8BIT))
+ assert_equal("%82%A0", URI.encode_uri_component(
+ "\u3042", Encoding::Windows_31J))
+ assert_equal("%E3%81%82", URI.encode_uri_component(
+ "\u3042", Encoding::UTF_8))
+
+ assert_equal("%82%A0", URI.encode_uri_component(
+ "\u3042".encode("sjis"), Encoding::ASCII_8BIT))
+ assert_equal("%A4%A2", URI.encode_uri_component(
+ "\u3042".encode("sjis"), Encoding::EUC_JP))
+ assert_equal("%E3%81%82", URI.encode_uri_component(
+ "\u3042".encode("sjis"), Encoding::UTF_8))
+ assert_equal("B0", URI.encode_uri_component(
+ "\u3042".encode("sjis"), Encoding::UTF_16LE))
+ assert_equal("%26%23730%3B", URI.encode_uri_component(
+ "\u02DA", Encoding::WINDOWS_1252))
+
+ # invalid
+ assert_equal("%EF%BF%BD%EF%BF%BD", URI.encode_uri_component(
+ "\xE3\x81\xFF", "utf-8"))
+ assert_equal("%E6%9F%8A%EF%BF%BD%EF%BF%BD", URI.encode_uri_component(
+ "\x95\x41\xff\xff".force_encoding(Encoding::Shift_JIS), "utf-8"))
+ end
+
+ def test_decode_uri_component
+ assert_equal(" +!\"\#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~",
+ URI.decode_uri_component(
+ "%20+%21%22%23%24%25%26%27%28%29*%2B%2C-.%2F09%3A%3B%3C%3D%3E%3F%40" \
+ "AZ%5B%5C%5D%5E_%60az%7B%7C%7D%7E"))
+ assert_equal("\xA1\xA2".force_encoding(Encoding::EUC_JP),
+ URI.decode_uri_component("%A1%A2", "EUC-JP"))
+ assert_equal("\xE3\x81\x82\xE3\x81\x82".force_encoding("UTF-8"),
+ URI.decode_uri_component("\xE3\x81\x82%E3%81%82".force_encoding("UTF-8")))
+
+ assert_raise(ArgumentError){URI.decode_uri_component("%")}
+ assert_raise(ArgumentError){URI.decode_uri_component("%a")}
+ assert_raise(ArgumentError){URI.decode_uri_component("x%a_")}
+ assert_nothing_raised(ArgumentError){URI.decode_uri_component("x"*(1024*1024))}
+ end
+
def test_encode_www_form
assert_equal("a=1", URI.encode_www_form("a" => "1"))
assert_equal("a=1", URI.encode_www_form(a: 1))
@@ -195,6 +319,3 @@ class TestCommon < Test::Unit::TestCase
private
def s(str) str.force_encoding(Encoding::Windows_31J); end
end
-
-
-end
diff --git a/test/uri/test_ftp.rb b/test/uri/test_ftp.rb
index 0eec984db8..f45bb0667c 100644
--- a/test/uri/test_ftp.rb
+++ b/test/uri/test_ftp.rb
@@ -2,10 +2,7 @@
require 'test/unit'
require 'uri/ftp'
-module URI
-
-
-class TestFTP < Test::Unit::TestCase
+class URI::TestFTP < Test::Unit::TestCase
def setup
end
@@ -29,7 +26,7 @@ class TestFTP < Test::Unit::TestCase
end
def test_parse_invalid
- assert_raise(InvalidURIError){URI.parse('ftp:example')}
+ assert_raise(URI::InvalidURIError) {URI.parse('ftp:example')}
end
def test_paths
@@ -62,6 +59,3 @@ class TestFTP < Test::Unit::TestCase
end
end
end
-
-
-end
diff --git a/test/uri/test_generic.rb b/test/uri/test_generic.rb
index fdb405e396..8209363b82 100644
--- a/test/uri/test_generic.rb
+++ b/test/uri/test_generic.rb
@@ -24,7 +24,19 @@ class URI::TestGeneric < Test::Unit::TestCase
assert_equal "file:///foo", URI("file:///foo").to_s
assert_equal "postgres:///foo", URI("postgres:///foo").to_s
- assert_equal "http:/foo", URI("http:///foo").to_s
+ assert_equal "http:///foo", URI("http:///foo").to_s
+ assert_equal "http:/foo", URI("http:/foo").to_s
+
+ uri = URI('rel_path')
+ assert_equal "rel_path", uri.to_s
+ uri.scheme = 'http'
+ assert_equal "http:rel_path", uri.to_s
+ uri.host = 'h'
+ assert_equal "http://h/rel_path", uri.to_s
+ uri.port = 8080
+ assert_equal "http://h:8080/rel_path", uri.to_s
+ uri.host = nil
+ assert_equal "http::8080/rel_path", uri.to_s
end
def test_parse
@@ -157,6 +169,12 @@ class URI::TestGeneric < Test::Unit::TestCase
assert_equal(nil, url.user)
assert_equal(nil, url.password)
assert_equal(nil, url.userinfo)
+
+ # sec-156615
+ url = URI.parse('http:////example.com')
+ # must be empty string to identify as path-abempty, not path-absolute
+ assert_equal('', url.host)
+ assert_equal('http:////example.com', url.to_s)
end
def test_parse_scheme_with_symbols
@@ -970,6 +988,10 @@ class URI::TestGeneric < Test::Unit::TestCase
end
end
+ def test_split
+ assert_equal [nil, nil, nil, nil, nil, "", nil, nil, nil], URI.split("//")
+ end
+
class CaseInsensitiveEnv
def initialize(h={})
@h = {}
diff --git a/test/uri/test_http.rb b/test/uri/test_http.rb
index cc19046c8f..e937b1a26b 100644
--- a/test/uri/test_http.rb
+++ b/test/uri/test_http.rb
@@ -1,11 +1,9 @@
# frozen_string_literal: false
require 'test/unit'
require 'uri/http'
+require 'uri/https'
-module URI
-
-
-class TestHTTP < Test::Unit::TestCase
+class URI::TestHTTP < Test::Unit::TestCase
def setup
end
@@ -24,14 +22,16 @@ class TestHTTP < Test::Unit::TestCase
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))
+ 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')
+ 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)
@@ -49,11 +49,11 @@ class TestHTTP < Test::Unit::TestCase
end
def test_request_uri
- assert_equal('/', URI.parse('http://a.b.c/').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('/', URI.parse('http://a.b.c').request_uri)
assert_equal('/?abc=def', URI.parse('http://a.b.c?abc=def').request_uri)
- assert_equal(nil, URI.parse('http:foo').request_uri)
+ assert_equal(nil, URI.parse('http:foo').request_uri)
end
def test_select
@@ -64,7 +64,18 @@ class TestHTTP < Test::Unit::TestCase
u.select(:scheme, :host, :not_exist, :port)
end
end
-end
+
+ def test_authority
+ assert_equal('a.b.c', URI.parse('http://a.b.c/').authority)
+ assert_equal('a.b.c:8081', URI.parse('http://a.b.c:8081/').authority)
+ assert_equal('a.b.c', URI.parse('http://a.b.c:80/').authority)
+ end
+ def test_origin
+ assert_equal('http://a.b.c', URI.parse('http://a.b.c/').origin)
+ assert_equal('http://a.b.c:8081', URI.parse('http://a.b.c:8081/').origin)
+ assert_equal('http://a.b.c', URI.parse('http://a.b.c:80/').origin)
+ assert_equal('https://a.b.c', URI.parse('https://a.b.c/').origin)
+ end
end
diff --git a/test/uri/test_ldap.rb b/test/uri/test_ldap.rb
index 64845e487a..9c4506a357 100644
--- a/test/uri/test_ldap.rb
+++ b/test/uri/test_ldap.rb
@@ -2,10 +2,7 @@
require 'test/unit'
require 'uri/ldap'
-module URI
-
-
-class TestLDAP < Test::Unit::TestCase
+class URI::TestLDAP < Test::Unit::TestCase
def setup
end
@@ -39,7 +36,7 @@ class TestLDAP < Test::Unit::TestCase
# from RFC2255, section 6.
{
'ldap:///o=University%20of%20Michigan,c=US' =>
- ['ldap', nil, URI::LDAP::DEFAULT_PORT,
+ ['ldap', '', URI::LDAP::DEFAULT_PORT,
'o=University%20of%20Michigan,c=US',
nil, nil, nil, nil],
@@ -74,12 +71,12 @@ class TestLDAP < Test::Unit::TestCase
nil, '(int=%5c00%5c00%5c00%5c04)', nil, nil],
'ldap:///??sub??bindname=cn=Manager%2co=Foo' =>
- ['ldap', nil, URI::LDAP::DEFAULT_PORT,
+ ['ldap', '', 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,
+ ['ldap', '', URI::LDAP::DEFAULT_PORT,
'',
nil, 'sub', nil, '!bindname=cn=Manager%2co=Foo'],
}.each do |url2, ary|
@@ -100,6 +97,3 @@ class TestLDAP < Test::Unit::TestCase
assert_raise(URI::InvalidURIError) {URI.parse("ldap:https://example.com")}
end
end
-
-
-end
diff --git a/test/uri/test_parser.rb b/test/uri/test_parser.rb
index 03de137788..f455a5cc9b 100644
--- a/test/uri/test_parser.rb
+++ b/test/uri/test_parser.rb
@@ -8,8 +8,8 @@ class URI::TestParser < Test::Unit::TestCase
end
def test_inspect
- assert_match(/URI::RFC2396_Parser/, URI::Parser.new.inspect)
- assert_match(/URI::RFC3986_Parser/, URI::RFC3986_Parser.new.inspect)
+ assert_match(/URI::RFC2396_Parser/, URI::RFC2396_Parser.new.inspect)
+ assert_match(/URI::RFC3986_Parser/, URI::Parser.new.inspect)
end
def test_compare
@@ -33,7 +33,9 @@ class URI::TestParser < Test::Unit::TestCase
assert(!u2.equal?(u3))
end
- def test_parse
+ def test_parse_rfc2396_parser
+ URI.parser = URI::RFC2396_PARSER
+
escaped = URI::REGEXP::PATTERN::ESCAPED
hex = URI::REGEXP::PATTERN::HEX
p1 = URI::Parser.new(:ESCAPED => "(?:#{escaped}|%u[#{hex}]{4})")
@@ -43,6 +45,8 @@ class URI::TestParser < Test::Unit::TestCase
u1.path = '/%uDCBA'
assert_equal(['http', nil, 'a', URI::HTTP.default_port, '/%uDCBA', nil, nil],
uri_to_ary(u1))
+ ensure
+ URI.parser = URI::DEFAULT_PARSER
end
def test_parse_query_pct_encoded
@@ -50,17 +54,63 @@ class URI::TestParser < Test::Unit::TestCase
assert_raise(URI::InvalidURIError) { URI.parse('https://www.example.com/search?q=%XX') }
end
+ def test_parse_auth
+ str = "http://al%40ice:p%40s%25sword@example.com/dir%2Fname/subdir?foo=bar%40example.com"
+ uri = URI.parse(str)
+ assert_equal "al%40ice", uri.user
+ assert_equal "p%40s%25sword", uri.password
+ assert_equal "al@ice", uri.decoded_user
+ assert_equal "p@s%sword", uri.decoded_password
+ end
+
def test_raise_bad_uri_for_integer
assert_raise(URI::InvalidURIError) do
URI.parse(1)
end
end
- def test_unescape
- p1 = URI::Parser.new
+ def test_rfc2822_unescape
+ p1 = URI::RFC2396_Parser.new
assert_equal("\xe3\x83\x90", p1.unescape("\xe3\x83\x90"))
assert_equal("\xe3\x83\x90", p1.unescape('%e3%83%90'))
assert_equal("\u3042", p1.unescape('%e3%81%82'.force_encoding(Encoding::US_ASCII)))
assert_equal("\xe3\x83\x90\xe3\x83\x90", p1.unescape("\xe3\x83\x90%e3%83%90"))
end
+
+ def test_split
+ assert_equal(["http", nil, "example.com", nil, nil, "", nil, nil, nil], URI.split("http://example.com"))
+ assert_equal(["http", nil, "[0::0]", nil, nil, "", nil, nil, nil], URI.split("http://[0::0]"))
+ assert_equal([nil, nil, "example.com", nil, nil, "", nil, nil, nil], URI.split("//example.com"))
+ assert_equal([nil, nil, "[0::0]", nil, nil, "", nil, nil, nil], URI.split("//[0::0]"))
+
+ assert_equal(["a", nil, nil, nil, nil, "", nil, nil, nil], URI.split("a:"))
+ assert_raise(URI::InvalidURIError) do
+ URI.parse("::")
+ end
+ assert_raise(URI::InvalidURIError) do
+ URI.parse("foo@example:foo")
+ end
+ end
+
+ def test_rfc2822_parse_relative_uri
+ pre = ->(length) {
+ " " * length + "\0"
+ }
+ parser = URI::RFC2396_Parser.new
+ assert_linear_performance((1..5).map {|i| 10**i}, pre: pre) do |uri|
+ assert_raise(URI::InvalidURIError) do
+ parser.split(uri)
+ end
+ end
+ end
+
+ def test_rfc3986_port_check
+ pre = ->(length) {"\t" * length + "a"}
+ uri = URI.parse("http://my.example.com")
+ assert_linear_performance((1..5).map {|i| 10**i}, pre: pre) do |port|
+ assert_raise(URI::InvalidComponentError) do
+ uri.port = port
+ end
+ end
+ end
end
diff --git a/test/uri/test_ws.rb b/test/uri/test_ws.rb
index 17acb0d9f2..f3918f617c 100644
--- a/test/uri/test_ws.rb
+++ b/test/uri/test_ws.rb
@@ -3,10 +3,7 @@ require 'test/unit'
require 'uri/http'
require 'uri/ws'
-module URI
-
-
-class TestWS < Test::Unit::TestCase
+class URI::TestWS < Test::Unit::TestCase
def setup
end
@@ -66,6 +63,3 @@ class TestWS < Test::Unit::TestCase
end
end
end
-
-
-end
diff --git a/test/uri/test_wss.rb b/test/uri/test_wss.rb
new file mode 100644
index 0000000000..13a2583059
--- /dev/null
+++ b/test/uri/test_wss.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: false
+require 'test/unit'
+require 'uri/https'
+require 'uri/wss'
+
+class URI::TestWSS < 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_build
+ u = URI::WSS.build(host: 'www.example.com', path: '/foo/bar')
+ assert_kind_of(URI::WSS, u)
+ end
+
+ def test_parse
+ u = URI.parse('wss://a')
+ assert_kind_of(URI::WSS, u)
+ assert_equal(['wss',
+ nil, 'a', URI::HTTPS.default_port,
+ '', nil], uri_to_ary(u))
+ end
+
+ def test_normalize
+ host = 'aBcD'
+ u1 = URI.parse('wss://' + host + '/eFg?HiJ')
+ u2 = URI.parse('wss://' + 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('wss://abc/', URI.parse('wss://abc').normalize.to_s)
+ end
+
+ def test_equal
+ assert(URI.parse('wss://abc') == URI.parse('wss://ABC'))
+ assert(URI.parse('wss://abc/def') == URI.parse('wss://ABC/def'))
+ assert(URI.parse('wss://abc/def') != URI.parse('wss://ABC/DEF'))
+ end
+
+ def test_request_uri
+ assert_equal('/', URI.parse('wss://a.b.c/').request_uri)
+ assert_equal('/?abc=def', URI.parse('wss://a.b.c/?abc=def').request_uri)
+ assert_equal('/', URI.parse('wss://a.b.c').request_uri)
+ assert_equal('/?abc=def', URI.parse('wss://a.b.c?abc=def').request_uri)
+ assert_equal(nil, URI.parse('wss:foo').request_uri)
+ end
+
+ def test_select
+ assert_equal(['wss', 'a.b.c', 443], URI.parse('wss://a.b.c/').select(:scheme, :host, :port))
+ u = URI.parse('wss://a.b.c/')
+ assert_equal(uri_to_ary(u), u.select(*u.component))
+ assert_raise(ArgumentError) do
+ u.select(:scheme, :host, :not_exist, :port)
+ end
+ end
+end
diff --git a/test/win32/test_registry.rb b/test/win32/test_registry.rb
new file mode 100644
index 0000000000..02cafc09b0
--- /dev/null
+++ b/test/win32/test_registry.rb
@@ -0,0 +1,97 @@
+if /mswin|mingw|cygwin/ =~ RUBY_PLATFORM
+ begin
+ require 'win32/registry'
+ rescue LoadError
+ else
+ require 'test/unit'
+ end
+end
+
+if defined?(Win32::Registry)
+ class TestWin32Registry < Test::Unit::TestCase
+ COMPUTERNAME = 'SYSTEM\\CurrentControlSet\\Control\\ComputerName\\ComputerName'
+ VOLATILE_ENVIRONMENT = 'Volatile Environment'
+
+ def test_predefined
+ assert_predefined_key Win32::Registry::HKEY_CLASSES_ROOT
+ assert_predefined_key Win32::Registry::HKEY_CURRENT_USER
+ assert_predefined_key Win32::Registry::HKEY_LOCAL_MACHINE
+ assert_predefined_key Win32::Registry::HKEY_USERS
+ assert_predefined_key Win32::Registry::HKEY_PERFORMANCE_DATA
+ assert_predefined_key Win32::Registry::HKEY_PERFORMANCE_TEXT
+ assert_predefined_key Win32::Registry::HKEY_PERFORMANCE_NLSTEXT
+ assert_predefined_key Win32::Registry::HKEY_CURRENT_CONFIG
+ assert_predefined_key Win32::Registry::HKEY_DYN_DATA
+ end
+
+ def test_class_open
+ name1, keys1 = Win32::Registry.open(Win32::Registry::HKEY_LOCAL_MACHINE, "SYSTEM") do |reg|
+ assert_predicate reg, :open?
+ [reg.name, reg.keys]
+ end
+ name2, keys2 = Win32::Registry::HKEY_LOCAL_MACHINE.open("SYSTEM") do |reg|
+ assert_predicate reg, :open?
+ [reg.name, reg.keys]
+ end
+ assert_equal name1, name2
+ assert_equal keys1, keys2
+ end
+
+ def test_read
+ computername = ENV['COMPUTERNAME']
+ Win32::Registry::HKEY_LOCAL_MACHINE.open(COMPUTERNAME) do |reg|
+ assert_equal computername, reg['ComputerName']
+ assert_equal [Win32::Registry::REG_SZ, computername], reg.read('ComputerName')
+ assert_raise(TypeError) {reg.read('ComputerName', Win32::Registry::REG_DWORD)}
+ end
+ end
+
+ def test_create
+ desired = Win32::Registry::KEY_ALL_ACCESS
+ option = Win32::Registry::REG_OPTION_VOLATILE
+ Win32::Registry::HKEY_CURRENT_USER.open(VOLATILE_ENVIRONMENT, desired) do |reg|
+ v = self.class.unused_value(reg)
+ begin
+ reg.create(v, desired, option) {}
+ ensure
+ reg.delete_key(v, true)
+ end
+ end
+ end
+
+ def test_write
+ desired = Win32::Registry::KEY_ALL_ACCESS
+ Win32::Registry::HKEY_CURRENT_USER.open(VOLATILE_ENVIRONMENT, desired) do |reg|
+ v = self.class.unused_value(reg)
+ begin
+ reg.write_s(v, "data")
+ assert_equal [Win32::Registry::REG_SZ, "data"], reg.read(v)
+ reg.write_i(v, 0x5fe79027)
+ assert_equal [Win32::Registry::REG_DWORD, 0x5fe79027], reg.read(v)
+ ensure
+ reg.delete(v)
+ end
+ end
+ end
+
+ private
+
+ def assert_predefined_key(key)
+ assert_kind_of Win32::Registry, key
+ assert_predicate key, :open?
+ assert_not_predicate key, :created?
+ end
+
+ class << self
+ def unused_value(reg, prefix = "Test_", limit = 100, fail: true)
+ limit.times do
+ v = + rand(0x100000).to_s(36)
+ reg.read(v)
+ rescue
+ return v
+ end
+ omit "Unused value not found in #{reg}" if fail
+ end
+ end
+ end
+end
diff --git a/test/win32ole/available_ole.rb b/test/win32ole/available_ole.rb
index ebc9baae66..af397e00b5 100644
--- a/test/win32ole/available_ole.rb
+++ b/test/win32ole/available_ole.rb
@@ -8,7 +8,7 @@ if defined?(WIN32OLE)
module_function
def sysmon_available?
- WIN32OLE_TYPE.new('System Monitor Control', 'SystemMonitor')
+ WIN32OLE::Type.new('System Monitor Control', 'SystemMonitor')
true
rescue
false
@@ -22,18 +22,18 @@ if defined?(WIN32OLE)
end
def msxml_available?
- !WIN32OLE_TYPELIB.typelibs.find { |t| t.name.start_with?('Microsoft XML') }.nil?
+ !WIN32OLE::TypeLib.typelibs.find { |t| t.name.start_with?('Microsoft XML') }.nil?
end
def event_param
method = if msxml_available?
- typelib = WIN32OLE_TYPELIB.typelibs.find { |t| t.name.start_with?('Microsoft XML') }
- ole_type = WIN32OLE_TYPE.new(typelib.name, 'IVBSAXContentHandler')
- WIN32OLE_METHOD.new(ole_type, 'startElement')
+ typelib = WIN32OLE::TypeLib.typelibs.find { |t| t.name.start_with?('Microsoft XML') }
+ ole_type = WIN32OLE::Type.new(typelib.name, 'IVBSAXContentHandler')
+ WIN32OLE::Method.new(ole_type, 'startElement')
elsif ado_available?
typelib = WIN32OLE.new('ADODB.Connection').ole_typelib
- ole_type = WIN32OLE_TYPE.new(typelib.name, 'Connection')
- WIN32OLE_METHOD.new(ole_type, 'WillConnect')
+ ole_type = WIN32OLE::Type.new(typelib.name, 'Connection')
+ WIN32OLE::Method.new(ole_type, 'WillConnect')
end
method && method.params[0]
end
diff --git a/test/win32ole/err_in_callback.rb b/test/win32ole/err_in_callback.rb
index aa6c9c7e3a..baecf780b6 100644
--- a/test/win32ole/err_in_callback.rb
+++ b/test/win32ole/err_in_callback.rb
@@ -2,9 +2,9 @@
require 'win32ole'
db = WIN32OLE.new('ADODB.Connection')
db.connectionString = "Driver={Microsoft Text Driver (*.txt; *.csv)};DefaultDir=.;"
-ev = WIN32OLE_EVENT.new(db)
+ev = WIN32OLE::Event.new(db)
ev.on_event('WillConnect') {|*args|
foo
}
db.open
-WIN32OLE_EVENT.message_loop
+WIN32OLE::Event.message_loop
diff --git a/test/win32ole/test_err_in_callback.rb b/test/win32ole/test_err_in_callback.rb
index 2c2b4a61a1..bea5781bc9 100644
--- a/test/win32ole/test_err_in_callback.rb
+++ b/test/win32ole/test_err_in_callback.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: false
#
# test Win32OLE avoids cfp consistency error when the exception raised
-# in WIN32OLE_EVENT handler block. [ruby-dev:35450]
+# in WIN32OLE::Event handler block. [ruby-dev:35450]
#
begin
@@ -31,14 +31,14 @@ if defined?(WIN32OLE)
def available_adodb?
begin
WIN32OLE.new('ADODB.Connection')
- rescue WIN32OLERuntimeError
+ rescue WIN32OLE::RuntimeError
return false
end
return true
end
def test_err_in_callback
- skip "'ADODB.Connection' is not available" unless available_adodb?
+ omit "'ADODB.Connection' is not available" unless available_adodb?
if @ruby
Dir.mktmpdir do |tmpdir|
logfile = File.join(tmpdir, "test_err_in_callback.log")
diff --git a/test/win32ole/test_folderitem2_invokeverb.rb b/test/win32ole/test_folderitem2_invokeverb.rb
index e11503ca2a..a1c2b2f472 100644
--- a/test/win32ole/test_folderitem2_invokeverb.rb
+++ b/test/win32ole/test_folderitem2_invokeverb.rb
@@ -44,7 +44,7 @@ if defined?(WIN32OLE)
assert_equal(0, links.size)
# Now create shortcut to @dummy_path
- arg = WIN32OLE_VARIANT.new("Link")
+ arg = WIN32OLE::Variant.new("Link")
@fi2.InvokeVerb(arg)
# Now search shortcut to @dummy_path
diff --git a/test/win32ole/test_nil2vtempty.rb b/test/win32ole/test_nil2vtempty.rb
index 49757d61b3..bd86403676 100644
--- a/test/win32ole/test_nil2vtempty.rb
+++ b/test/win32ole/test_nil2vtempty.rb
@@ -28,7 +28,7 @@ if defined?(WIN32OLE)
assert(rs)
assert_equal("_Recordset", rs.ole_type.name)
- rs = con.openSchema(4, [WIN32OLE_VARIANT::Empty, WIN32OLE_VARIANT::Empty, "DUMMY", "TABLE"])
+ rs = con.openSchema(4, [WIN32OLE::Variant::Empty, WIN32OLE::Variant::Empty, "DUMMY", "TABLE"])
assert(rs)
assert_equal("_Recordset", rs.ole_type.name)
end
diff --git a/test/win32ole/test_propertyputref.rb b/test/win32ole/test_propertyputref.rb
index 93edb50835..83418140c2 100644
--- a/test/win32ole/test_propertyputref.rb
+++ b/test/win32ole/test_propertyputref.rb
@@ -11,7 +11,7 @@ if defined?(WIN32OLE)
begin
@sapi = WIN32OLE.new('SAPI.SpVoice')
@sv = @sapi.voice
- rescue WIN32OLERuntimeError
+ rescue WIN32OLE::RuntimeError
@sapi = nil
end
end
diff --git a/test/win32ole/test_thread.rb b/test/win32ole/test_thread.rb
index cb34693064..b30b2349c5 100644
--- a/test/win32ole/test_thread.rb
+++ b/test/win32ole/test_thread.rb
@@ -14,7 +14,7 @@ if defined?(WIN32OLE)
t = Thread.__send__(meth) {
WIN32OLE.new('Scripting.Dictionary')
}
- assert_nothing_raised(WIN32OLERuntimeError, "[Bug #2618] Thread.#{meth}") {
+ assert_nothing_raised(WIN32OLE::RuntimeError, "[Bug #2618] Thread.#{meth}") {
t.join
}
end
diff --git a/test/win32ole/test_win32ole.rb b/test/win32ole/test_win32ole.rb
index 3941780528..e6347e89b4 100644
--- a/test/win32ole/test_win32ole.rb
+++ b/test/win32ole/test_win32ole.rb
@@ -34,23 +34,23 @@ if defined?(WIN32OLE)
assert_equal(1, @dict2.item("one"))
end
def test_non_exist_property
- assert_raise(WIN32OLERuntimeError) {
+ assert_raise(WIN32OLE::RuntimeError) {
@dict1.unknown_property = 1
}
end
def test_raise_message
- exc = assert_raise(WIN32OLERuntimeError) {
+ exc = assert_raise(WIN32OLE::RuntimeError) {
@dict1.add
}
assert_match(/^\(in OLE method `add': \)/, exc.message) #`
- exc = assert_raise(WIN32OLERuntimeError) {
+ exc = assert_raise(WIN32OLE::RuntimeError) {
@dict1._invoke(1, [], [])
}
assert_match(/^\(in OLE method `<dispatch id:1>': \)/, exc.message) #`
- exc = assert_raise(WIN32OLERuntimeError) {
+ exc = assert_raise(WIN32OLE::RuntimeError) {
@dict1.compareMode = -1
}
assert_match(/^\(in setting property `compareMode': \)/, exc.message) #`
@@ -101,7 +101,7 @@ if defined?(WIN32OLE)
assert_include(mnames, 'Count')
end
- def test_ole_mehtod_help
+ def test_ole_method_help
minfo = @dict1.ole_method_help("Add")
assert_equal(2, minfo.size_params)
end
@@ -167,6 +167,11 @@ if defined?(WIN32OLE)
assert_instance_of(WIN32OLE, @dict2)
end
+ def test_toplevel_constants_backward_compatibility
+ assert_equal(WIN32OLE::RuntimeError, ::WIN32OLERuntimeError)
+ assert_equal(WIN32OLE::QueryInterfaceError, ::WIN32OLEQueryInterfaceError)
+ end
+
def test_s_new_exc
assert_raise(TypeError) {
WIN32OLE.new(1)
@@ -184,7 +189,7 @@ if defined?(WIN32OLE)
def test_s_new_from_clsid
shell = WIN32OLE.new("{13709620-C279-11CE-A49E-444553540000}")
assert_instance_of(WIN32OLE, shell)
- exc = assert_raise(WIN32OLERuntimeError) {
+ exc = assert_raise(WIN32OLE::RuntimeError) {
WIN32OLE.new("{000}")
}
assert_match(/unknown OLE server: `\{000\}'/, exc.message) #`
@@ -335,17 +340,19 @@ if defined?(WIN32OLE)
end
def test_s_codepage_changed
+ omit if RUBY_PLATFORM.match("mswin")
+
cp = WIN32OLE.codepage
fso = WIN32OLE.new("Scripting.FileSystemObject")
fname = fso.getTempName
begin
- obj = WIN32OLE_VARIANT.new([0x3042].pack("U*").force_encoding("UTF-8"))
+ 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
+ rescue WIN32OLE::RuntimeError
end
if (WIN32OLE.codepage == 932)
assert_equal("\x82\xA0".force_encoding("CP932"), obj.value)
@@ -353,7 +360,7 @@ if defined?(WIN32OLE)
begin
WIN32OLE.codepage = 20932 # MS EUC-JP
- rescue WIN32OLERuntimeError
+ rescue WIN32OLE::RuntimeError
end
if (WIN32OLE.codepage == 20932)
assert_equal("\xA4\xA2".force_encoding("CP20932"), obj.value)
@@ -376,7 +383,7 @@ if defined?(WIN32OLE)
# This test fail if codepage 20932 (euc) is not installed.
begin
WIN32OLE.codepage = 20932
- rescue WIN32OLERuntimeError
+ rescue WIN32OLE::RuntimeError
end
if (WIN32OLE.codepage == 20932)
WIN32OLE.codepage = cp
@@ -403,7 +410,7 @@ if defined?(WIN32OLE)
def test_cp51932
cp = WIN32OLE.codepage
begin
- obj = WIN32OLE_VARIANT.new([0x3042].pack("U*").force_encoding("UTF-8"))
+ obj = WIN32OLE::Variant.new([0x3042].pack("U*").force_encoding("UTF-8"))
begin
WIN32OLE.codepage = 51932
rescue
@@ -424,13 +431,13 @@ if defined?(WIN32OLE)
begin
begin
WIN32OLE.locale = 1041
- rescue WIN32OLERuntimeError
+ rescue WIN32OLE::RuntimeError
STDERR.puts("\n#{__FILE__}:#{__LINE__}:#{self.class.name}.test_s_locale_set is skipped(Japanese locale is not installed)")
return
end
assert_equal(1041, WIN32OLE.locale)
WIN32OLE.locale = WIN32OLE::LOCALE_SYSTEM_DEFAULT
- assert_raise(WIN32OLERuntimeError) {
+ assert_raise(WIN32OLE::RuntimeError) {
WIN32OLE.locale = 111
}
assert_equal(WIN32OLE::LOCALE_SYSTEM_DEFAULT, WIN32OLE.locale)
@@ -443,13 +450,13 @@ if defined?(WIN32OLE)
begin
begin
WIN32OLE.locale = 0x0411
- rescue WIN32OLERuntimeError
+ rescue WIN32OLE::RuntimeError
end
if WIN32OLE.locale == 0x0411
- obj = WIN32OLE_VARIANT.new("\\100,000", WIN32OLE::VARIANT::VT_CY)
+ 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)
+ assert_raise(WIN32OLE::RuntimeError) {
+ obj = WIN32OLE::Variant.new("$100.000", WIN32OLE::VARIANT::VT_CY)
}
else
STDERR.puts("\n#{__FILE__}:#{__LINE__}:#{self.class.name}.test_s_locale_change is skipped(Japanese locale is not installed)")
@@ -457,10 +464,10 @@ if defined?(WIN32OLE)
begin
WIN32OLE.locale = 1033
- rescue WIN32OLERuntimeError
+ rescue WIN32OLE::RuntimeError
end
if WIN32OLE.locale == 1033
- obj = WIN32OLE_VARIANT.new("$100,000", WIN32OLE::VARIANT::VT_CY)
+ obj = WIN32OLE::Variant.new("$100,000", WIN32OLE::VARIANT::VT_CY)
assert_equal("100000", obj.value)
else
STDERR.puts("\n#{__FILE__}:#{__LINE__}:#{self.class.name}.test_s_locale_change is skipped(US English locale is not installed)")
diff --git a/test/win32ole/test_win32ole_event.rb b/test/win32ole/test_win32ole_event.rb
index 742bff4f7a..d52f8cf9b3 100644
--- a/test/win32ole/test_win32ole_event.rb
+++ b/test/win32ole/test_win32ole_event.rb
@@ -28,17 +28,21 @@ swbemsink_available =
end
end
-if defined?(WIN32OLE_EVENT)
+if defined?(WIN32OLE::Event)
class TestWIN32OLE_EVENT < Test::Unit::TestCase
+ def test_toplevel_constants_backward_compatibility
+ assert_equal(WIN32OLE::Event, ::WIN32OLE_EVENT)
+ end
+
def test_s_new_exception
assert_raise(TypeError) {
- WIN32OLE_EVENT.new("A")
+ WIN32OLE::Event.new("A")
}
end
def test_s_new_non_exist_event
dict = WIN32OLE.new('Scripting.Dictionary')
assert_raise(RuntimeError) {
- WIN32OLE_EVENT.new(dict)
+ WIN32OLE::Event.new(dict)
}
end
end
@@ -58,19 +62,20 @@ if defined?(WIN32OLE_EVENT)
end
2.times do
- WIN32OLE_EVENT.message_loop
+ WIN32OLE::Event.message_loop
sleep 1
end
if watch_ivar
# wait until event is proceeded
tries = 0
+ seconds = EnvUtil.apply_timeout_scale(1)
while tries < 5 && instance_variable_get(watch_ivar) == orig_ivar
- seconds = 2 ** tries # sleep at most 31s in total
$stderr.puts "test_win32ole_event.rb: retrying and sleeping #{seconds}s until #{watch_ivar} is changed from #{orig_ivar.inspect}..."
- WIN32OLE_EVENT.message_loop
+ WIN32OLE::Event.message_loop
sleep(seconds)
tries += 1
+ seconds *= 2 # sleep at most 31s in total
end
end
end
@@ -85,24 +90,24 @@ if defined?(WIN32OLE_EVENT)
def test_s_new_non_exist_event
assert_raise(RuntimeError) {
- WIN32OLE_EVENT.new(@sws, 'XXXXX')
+ WIN32OLE::Event.new(@sws, 'XXXXX')
}
end
def test_s_new
- obj = WIN32OLE_EVENT.new(@sws, 'ISWbemSinkEvents')
- assert_instance_of(WIN32OLE_EVENT, obj)
- obj = WIN32OLE_EVENT.new(@sws)
- assert_instance_of(WIN32OLE_EVENT, obj)
+ obj = WIN32OLE::Event.new(@sws, 'ISWbemSinkEvents')
+ assert_instance_of(WIN32OLE::Event, obj)
+ obj = WIN32OLE::Event.new(@sws)
+ assert_instance_of(WIN32OLE::Event, obj)
end
def test_s_new_loop
exec_notification_query_async
- ev = WIN32OLE_EVENT.new(@sws)
+ ev = WIN32OLE::Event.new(@sws)
ev.on_event {|*args| default_handler(*args)}
message_loop
10.times do |i|
- WIN32OLE_EVENT.new(@sws)
+ WIN32OLE::Event.new(@sws)
message_loop
GC.start
end
@@ -114,7 +119,7 @@ if defined?(WIN32OLE_EVENT)
def test_on_event
exec_notification_query_async
- ev = WIN32OLE_EVENT.new(@sws, 'ISWbemSinkEvents')
+ ev = WIN32OLE::Event.new(@sws, 'ISWbemSinkEvents')
ev.on_event {|*args| default_handler(*args)}
message_loop(:@event)
assert_match(/OnObjectReady/, @event)
@@ -122,7 +127,7 @@ if defined?(WIN32OLE_EVENT)
def test_on_event_symbol
exec_notification_query_async
- ev = WIN32OLE_EVENT.new(@sws)
+ ev = WIN32OLE::Event.new(@sws)
ev.on_event(:OnObjectReady) {|*args|
handler1
}
@@ -135,7 +140,7 @@ if defined?(WIN32OLE_EVENT)
@wmi.ExecNotificationQueryAsync(@sws, @sql)
rescue => e
if /OLE error code:80041008 in SWbemServicesEx/ =~ e.message
- skip "No administrator privilege?"
+ omit "No administrator privilege?"
end
raise
end
@@ -162,7 +167,7 @@ if defined?(WIN32OLE_EVENT)
module ADO
end
def message_loop
- WIN32OLE_EVENT.message_loop
+ WIN32OLE::Event.message_loop
end
def default_handler(event, *args)
@@ -181,7 +186,7 @@ if defined?(WIN32OLE_EVENT)
end
def test_on_event2
- ev = WIN32OLE_EVENT.new(@db, 'ConnectionEvents')
+ ev = WIN32OLE::Event.new(@db, 'ConnectionEvents')
ev.on_event('WillConnect') {|*args| handler1}
ev.on_event('WillConnect') {|*args| handler2}
@db.open
@@ -190,7 +195,7 @@ if defined?(WIN32OLE_EVENT)
end
def test_on_event4
- ev = WIN32OLE_EVENT.new(@db, 'ConnectionEvents')
+ ev = WIN32OLE::Event.new(@db, 'ConnectionEvents')
ev.on_event{|*args| handler1}
ev.on_event{|*args| handler2}
ev.on_event('WillConnect'){|*args| handler3(*args)}
@@ -201,7 +206,7 @@ if defined?(WIN32OLE_EVENT)
end
def test_on_event5
- ev = WIN32OLE_EVENT.new(@db, 'ConnectionEvents')
+ ev = WIN32OLE::Event.new(@db, 'ConnectionEvents')
ev.on_event {|*args| default_handler(*args)}
ev.on_event('WillConnect'){|*args| handler3(*args)}
@db.open
@@ -212,7 +217,7 @@ if defined?(WIN32OLE_EVENT)
end
def test_unadvise
- ev = WIN32OLE_EVENT.new(@db, 'ConnectionEvents')
+ ev = WIN32OLE::Event.new(@db, 'ConnectionEvents')
ev.on_event {|*args| default_handler(*args)}
@db.open
message_loop
@@ -223,16 +228,16 @@ if defined?(WIN32OLE_EVENT)
@db.open
message_loop
assert_equal("", @event);
- assert_raise(WIN32OLERuntimeError) {
+ assert_raise(WIN32OLE::RuntimeError) {
ev.on_event {|*args| default_handler(*args)}
}
end
def test_on_event_with_outargs
- ev = WIN32OLE_EVENT.new(@db)
+ ev = WIN32OLE::Event.new(@db)
@db.connectionString = 'XXX' # set illegal connection string
- assert_raise(WIN32OLERuntimeError) {
+ assert_raise(WIN32OLE::RuntimeError) {
@db.open
}
ev.on_event_with_outargs('WillConnect'){|*args|
@@ -244,7 +249,7 @@ if defined?(WIN32OLE_EVENT)
end
def test_on_event_hash_return
- ev = WIN32OLE_EVENT.new(@db)
+ ev = WIN32OLE::Event.new(@db)
ev.on_event('WillConnect'){|*args|
{:return => 1, :ConnectionString => CONNSTR}
}
@@ -254,7 +259,7 @@ if defined?(WIN32OLE_EVENT)
end
def test_on_event_hash_return2
- ev = WIN32OLE_EVENT.new(@db)
+ ev = WIN32OLE::Event.new(@db)
ev.on_event('WillConnect'){|*args|
{:ConnectionString => CONNSTR}
}
@@ -264,7 +269,7 @@ if defined?(WIN32OLE_EVENT)
end
def test_on_event_hash_return3
- ev = WIN32OLE_EVENT.new(@db)
+ ev = WIN32OLE::Event.new(@db)
ev.on_event('WillConnect'){|*args|
{'ConnectionString' => CONNSTR}
}
@@ -274,7 +279,7 @@ if defined?(WIN32OLE_EVENT)
end
def test_on_event_hash_return4
- ev = WIN32OLE_EVENT.new(@db)
+ ev = WIN32OLE::Event.new(@db)
ev.on_event('WillConnect'){|*args|
{'return' => 1, 'ConnectionString' => CONNSTR}
}
@@ -284,7 +289,7 @@ if defined?(WIN32OLE_EVENT)
end
def test_on_event_hash_return5
- ev = WIN32OLE_EVENT.new(@db)
+ ev = WIN32OLE::Event.new(@db)
ev.on_event('WillConnect'){|*args|
{0 => CONNSTR}
}
@@ -294,7 +299,7 @@ if defined?(WIN32OLE_EVENT)
end
def test_off_event
- ev = WIN32OLE_EVENT.new(@db)
+ ev = WIN32OLE::Event.new(@db)
ev.on_event{handler1}
ev.off_event
@db.open
@@ -303,7 +308,7 @@ if defined?(WIN32OLE_EVENT)
end
def test_off_event_arg
- ev = WIN32OLE_EVENT.new(@db)
+ ev = WIN32OLE::Event.new(@db)
ev.on_event('WillConnect'){handler1}
ev.off_event('WillConnect')
@db.open
@@ -312,7 +317,7 @@ if defined?(WIN32OLE_EVENT)
end
def test_off_event_arg2
- ev = WIN32OLE_EVENT.new(@db)
+ ev = WIN32OLE::Event.new(@db)
ev.on_event('WillConnect'){handler1}
ev.on_event('ConnectComplete'){handler1}
ev.off_event('WillConnect')
@@ -322,7 +327,7 @@ if defined?(WIN32OLE_EVENT)
end
def test_off_event_sym_arg
- ev = WIN32OLE_EVENT.new(@db)
+ ev = WIN32OLE::Event.new(@db)
ev.on_event('WillConnect'){handler1}
ev.off_event(:WillConnect)
@db.open
@@ -381,7 +386,7 @@ if defined?(WIN32OLE_EVENT)
end
def test_handler1
- ev = WIN32OLE_EVENT.new(@db)
+ ev = WIN32OLE::Event.new(@db)
h1 = Handler1.new
ev.handler = h1
@db.open
@@ -394,7 +399,7 @@ if defined?(WIN32OLE_EVENT)
end
def test_handler2
- ev = WIN32OLE_EVENT.new(@db)
+ ev = WIN32OLE::Event.new(@db)
h2 = Handler2.new
ev.handler = h2
@db.open
diff --git a/test/win32ole/test_win32ole_method.rb b/test/win32ole/test_win32ole_method.rb
index a0e113e7f0..c84c4027ff 100644
--- a/test/win32ole/test_win32ole_method.rb
+++ b/test/win32ole/test_win32ole_method.rb
@@ -5,42 +5,46 @@ rescue LoadError
end
require "test/unit"
-if defined?(WIN32OLE_METHOD)
+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 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 Scripting Runtime", "File")
+ @m_file_name = WIN32OLE::Method.new(ole_type, "name")
+ end
+
+ def test_toplevel_constants_backward_compatibility
+ assert_equal(WIN32OLE::Method, ::WIN32OLE_METHOD)
end
def test_initialize
- ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ ole_type = WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "Shell")
assert_raise(TypeError) {
- WIN32OLE_METHOD.new(1, 2)
+ WIN32OLE::Method.new(1, 2)
}
assert_raise(ArgumentError) {
- WIN32OLE_METHOD.new("foo")
+ WIN32OLE::Method.new("foo")
}
assert_raise(ArgumentError) {
- WIN32OLE_METHOD.new(ole_type)
+ WIN32OLE::Method.new(ole_type)
}
- assert_raise(WIN32OLERuntimeError) {
- WIN32OLE_METHOD.new(ole_type, "NonExistMethod")
+ assert_raise(WIN32OLE::RuntimeError) {
+ WIN32OLE::Method.new(ole_type, "NonExistMethod")
}
assert_raise(TypeError) {
- WIN32OLE_METHOD.new(ole_type, 1)
+ 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)
+ 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
@@ -119,7 +123,7 @@ if defined?(WIN32OLE_METHOD)
params = @m_browse_for_folder.params
assert_instance_of(Array, params)
assert_equal(4, params.size)
- assert_instance_of(WIN32OLE_PARAM, params[0])
+ assert_instance_of(WIN32OLE::Param, params[0])
end
def test_to_s
@@ -127,7 +131,7 @@ if defined?(WIN32OLE_METHOD)
end
def test_inspect
- assert_equal("#<WIN32OLE_METHOD:NameSpace>", @m_namespace.inspect)
+ assert_equal("#<WIN32OLE::Method:NameSpace>", @m_namespace.inspect)
end
end
diff --git a/test/win32ole/test_win32ole_method_event.rb b/test/win32ole/test_win32ole_method_event.rb
index 6dad6ff2b4..ab409a1f2d 100644
--- a/test/win32ole/test_win32ole_method_event.rb
+++ b/test/win32ole/test_win32ole_method_event.rb
@@ -5,19 +5,19 @@ end
require 'test/unit'
-if defined?(WIN32OLE_METHOD)
+if defined?(WIN32OLE::Method)
require_relative 'available_ole'
class TestWIN32OLE_METHOD_EVENT < Test::Unit::TestCase
unless AvailableOLE.sysmon_available?
def test_dummy_for_skip_message
- skip 'System Monitor Control is not available'
+ omit 'System Monitor Control is not available'
end
else
def setup
- ole_type = WIN32OLE_TYPE.new('System Monitor Control', 'SystemMonitor')
- @on_dbl_click = WIN32OLE_METHOD.new(ole_type, 'OnDblClick')
- ole_type = WIN32OLE_TYPE.new('Microsoft Shell Controls And Automation', 'Shell')
- @namespace = WIN32OLE_METHOD.new(ole_type, 'namespace')
+ ole_type = WIN32OLE::Type.new('System Monitor Control', 'SystemMonitor')
+ @on_dbl_click = WIN32OLE::Method.new(ole_type, 'OnDblClick')
+ ole_type = WIN32OLE::Type.new('Microsoft Shell Controls And Automation', 'Shell')
+ @namespace = WIN32OLE::Method.new(ole_type, 'namespace')
end
def test_event?
diff --git a/test/win32ole/test_win32ole_param.rb b/test/win32ole/test_win32ole_param.rb
index 09452d1927..13ca9d0cfb 100644
--- a/test/win32ole/test_win32ole_param.rb
+++ b/test/win32ole/test_win32ole_param.rb
@@ -5,45 +5,49 @@ rescue LoadError
end
require "test/unit"
-if defined?(WIN32OLE_PARAM)
+if defined?(WIN32OLE::Param)
class TestWIN32OLE_PARAM < Test::Unit::TestCase
def setup
- ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "ShellLinkObject")
- m_geticonlocation = WIN32OLE_METHOD.new(ole_type, "GetIconLocation")
+ 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")
+ 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")
+ ole_type = WIN32OLE::Type.new("Microsoft Scripting Runtime", "FileSystemObject")
+ m_copyfile = WIN32OLE::Method.new(ole_type, "CopyFile")
@param_source = m_copyfile.params[0]
@param_overwritefiles = m_copyfile.params[2]
- ole_type = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "Dictionary")
- m_add = WIN32OLE_METHOD.new(ole_type, "Add")
+ ole_type = WIN32OLE::Type.new("Microsoft Scripting Runtime", "Dictionary")
+ m_add = WIN32OLE::Method.new(ole_type, "Add")
@param_key = m_add.params[0]
end
+ def test_constants_backward_compatibility
+ assert_equal(WIN32OLE::Param, ::WIN32OLE_PARAM)
+ end
+
def test_s_new
assert_raise(ArgumentError) {
- WIN32OLE_PARAM.new("hoge")
+ WIN32OLE::Param.new("hoge")
}
- ole_type = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "FileSystemObject")
- m_copyfile = WIN32OLE_METHOD.new(ole_type, "CopyFile")
+ ole_type = WIN32OLE::Type.new("Microsoft Scripting Runtime", "FileSystemObject")
+ m_copyfile = WIN32OLE::Method.new(ole_type, "CopyFile")
assert_raise(IndexError) {
- WIN32OLE_PARAM.new(m_copyfile, 4);
+ WIN32OLE::Param.new(m_copyfile, 4);
}
assert_raise(IndexError) {
- WIN32OLE_PARAM.new(m_copyfile, 0);
+ WIN32OLE::Param.new(m_copyfile, 0);
}
- param = WIN32OLE_PARAM.new(m_copyfile, 3)
+ param = WIN32OLE::Param.new(m_copyfile, 3)
assert_equal("OverWriteFiles", param.name)
- assert_equal(WIN32OLE_PARAM, param.class)
+ assert_equal(WIN32OLE::Param, param.class)
assert_equal(true, param.default)
- assert_equal("#<WIN32OLE_PARAM:OverWriteFiles=true>", param.inspect)
+ assert_equal("#<WIN32OLE::Param:OverWriteFiles=true>", param.inspect)
end
def test_name
@@ -91,8 +95,8 @@ if defined?(WIN32OLE_PARAM)
end
def test_inspect
- assert_equal("#<WIN32OLE_PARAM:Source>", @param_source.inspect)
- assert_equal("#<WIN32OLE_PARAM:OverWriteFiles=true>", @param_overwritefiles.inspect)
+ assert_equal("#<WIN32OLE::Param:Source>", @param_source.inspect)
+ assert_equal("#<WIN32OLE::Param:OverWriteFiles=true>", @param_overwritefiles.inspect)
end
end
end
diff --git a/test/win32ole/test_win32ole_param_event.rb b/test/win32ole/test_win32ole_param_event.rb
index 64812e567d..f5a16ead76 100644
--- a/test/win32ole/test_win32ole_param_event.rb
+++ b/test/win32ole/test_win32ole_param_event.rb
@@ -5,7 +5,7 @@ end
require 'test/unit'
-if defined?(WIN32OLE_PARAM)
+if defined?(WIN32OLE::Param)
require_relative 'available_ole'
class TestWIN32OLE_PARAM_EVENT < Test::Unit::TestCase
@@ -23,7 +23,7 @@ if defined?(WIN32OLE_PARAM)
end
else
def test_dummy_for_skip_message
- skip 'ActiveX Data Object Library and MS XML not found'
+ omit 'ActiveX Data Object Library and MS XML not found'
end
end
end
diff --git a/test/win32ole/test_win32ole_record.rb b/test/win32ole/test_win32ole_record.rb
index 7d6c3fb4af..49205ce53d 100644
--- a/test/win32ole/test_win32ole_record.rb
+++ b/test/win32ole/test_win32ole_record.rb
@@ -65,18 +65,24 @@ End Class
=end
-if defined?(WIN32OLE_RECORD)
+if defined?(WIN32OLE::Record)
+ class TestWIN32OLE_RECORD < Test::Unit::TestCase
+ def test_toplevel_constants_backward_compatibility
+ assert_equal(WIN32OLE::Record, ::WIN32OLE_RECORD)
+ end
+ end
+
def rbcomtest_exist?
WIN32OLE.new(PROGID_RBCOMTEST)
true
- rescue WIN32OLERuntimeError
+ rescue WIN32OLE::RuntimeError
false
end
class TestWIN32OLE_RECORD_BY_RBCOMTEST < Test::Unit::TestCase
unless rbcomtest_exist?
def test_dummy_for_skip_message
- skip "#{PROGID_RBCOMTEST} for WIN32OLE_RECORD test is not installed"
+ omit "#{PROGID_RBCOMTEST} for WIN32OLE::Record test is not installed"
end
else
def setup
@@ -84,42 +90,42 @@ if defined?(WIN32OLE_RECORD)
end
def test_s_new_from_win32ole
- rec = WIN32OLE_RECORD.new('Book', @obj)
+ rec = WIN32OLE::Record.new('Book', @obj)
assert(rec)
- assert_instance_of(WIN32OLE_RECORD, rec)
+ assert_instance_of(WIN32OLE::Record, rec)
end
def test_s_new_from_win32ole_typelib
tlib = @obj.ole_typelib
- rec = WIN32OLE_RECORD.new('Book', tlib)
+ rec = WIN32OLE::Record.new('Book', tlib)
assert(rec)
- assert_instance_of(WIN32OLE_RECORD, rec)
+ assert_instance_of(WIN32OLE::Record, rec)
end
def test_s_new_raise
- assert_raise(WIN32OLERuntimeError) {
- WIN32OLE_RECORD.new('NonExistRecordName', @obj)
+ assert_raise(WIN32OLE::RuntimeError) {
+ WIN32OLE::Record.new('NonExistRecordName', @obj)
}
assert_raise(ArgumentError) {
- WIN32OLE_RECORD.new
+ WIN32OLE::Record.new
}
assert_raise(ArgumentError) {
- WIN32OLE_RECORD.new('NonExistRecordName')
+ WIN32OLE::Record.new('NonExistRecordName')
}
end
def test_to_h
- rec = WIN32OLE_RECORD.new('Book', @obj)
+ rec = WIN32OLE::Record.new('Book', @obj)
assert_equal({'title'=>nil, 'cost'=>nil}, rec.to_h)
end
def test_typename
- rec = WIN32OLE_RECORD.new('Book', @obj)
+ rec = WIN32OLE::Record.new('Book', @obj)
assert_equal('Book', rec.typename)
end
def test_method_missing_getter
- rec = WIN32OLE_RECORD.new('Book', @obj)
+ rec = WIN32OLE::Record.new('Book', @obj)
assert_equal(nil, rec.title)
assert_raise(KeyError) {
rec.non_exist_name
@@ -127,14 +133,14 @@ if defined?(WIN32OLE_RECORD)
end
def test_method_missing_setter
- rec = WIN32OLE_RECORD.new('Book', @obj)
+ rec = WIN32OLE::Record.new('Book', @obj)
rec.title = "Ruby Book"
assert_equal("Ruby Book", rec.title)
end
def test_get_record_from_comserver
rec = @obj.getBook
- assert_instance_of(WIN32OLE_RECORD, rec)
+ assert_instance_of(WIN32OLE::Record, rec)
assert_equal("The Ruby Book", rec.title)
assert_equal(20, rec.cost)
end
@@ -143,16 +149,16 @@ if defined?(WIN32OLE_RECORD)
rec = @obj.getBooks
assert_instance_of(Array, rec)
assert_equal(2, rec.size)
- assert_instance_of(WIN32OLE_RECORD, rec[0])
+ assert_instance_of(WIN32OLE::Record, rec[0])
assert_equal("The CRuby Book", rec[0].title)
assert_equal(30, rec[0].cost)
- assert_instance_of(WIN32OLE_RECORD, rec[1])
+ assert_instance_of(WIN32OLE::Record, rec[1])
assert_equal("The JRuby Book", rec[1].title)
assert_equal(40, rec[1].cost)
end
def test_pass_record_parameter
- rec = WIN32OLE_RECORD.new('Book', @obj)
+ rec = WIN32OLE::Record.new('Book', @obj)
rec.title = "Ruby Book"
rec.cost = 60
book = @obj.getVer2BookByValBook(rec)
@@ -161,23 +167,23 @@ if defined?(WIN32OLE_RECORD)
end
def test_pass_variant_parameter_byref
- obj = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_VARIANT|WIN32OLE::VARIANT::VT_BYREF)
+ obj = WIN32OLE::Variant.new(nil, WIN32OLE::VARIANT::VT_VARIANT|WIN32OLE::VARIANT::VT_BYREF)
@obj.getBookByRefBook(obj)
- assert_instance_of(WIN32OLE_RECORD, obj.value)
+ assert_instance_of(WIN32OLE::Record, obj.value)
book = obj.value
assert_equal("The Ruby Reference Book2", book.title)
assert_equal(44, book.cost)
end
def test_pass_record_parameter_byref
- book = WIN32OLE_RECORD.new('Book', @obj)
+ book = WIN32OLE::Record.new('Book', @obj)
@obj.getBookByRefBook(book)
assert_equal("The Ruby Reference Book2", book.title)
assert_equal(44, book.cost)
end
def test_pass_and_get_record_parameter_byref
- book = WIN32OLE_RECORD.new('Book', @obj)
+ book = WIN32OLE::Record.new('Book', @obj)
book.title = "Ruby Book"
book.cost = 60
@obj.getVer3BookByRefBook(book)
@@ -186,13 +192,13 @@ if defined?(WIN32OLE_RECORD)
end
def test_ole_instance_variable_get
- obj = WIN32OLE_RECORD.new('Book', @obj)
+ obj = WIN32OLE::Record.new('Book', @obj)
assert_equal(nil, obj.ole_instance_variable_get(:title))
assert_equal(nil, obj.ole_instance_variable_get('title'))
end
def test_ole_instance_variable_set
- book = WIN32OLE_RECORD.new('Book', @obj)
+ book = WIN32OLE::Record.new('Book', @obj)
book.ole_instance_variable_set(:title, "Ruby Book")
assert_equal("Ruby Book", book.title)
book.ole_instance_variable_set('title', "Ruby Book2")
@@ -200,8 +206,8 @@ if defined?(WIN32OLE_RECORD)
end
def test_inspect
- book = WIN32OLE_RECORD.new('Book', @obj)
- assert_equal(%q[#<WIN32OLE_RECORD(Book) {"title"=>nil, "cost"=>nil}>], book.inspect)
+ book = WIN32OLE::Record.new('Book', @obj)
+ assert_equal(%q[#<WIN32OLE::Record(Book) {"title"=>nil, "cost"=>nil}>], book.inspect)
end
end
end
diff --git a/test/win32ole/test_win32ole_type.rb b/test/win32ole/test_win32ole_type.rb
index 485b390d5c..9abcd68c9b 100644
--- a/test/win32ole/test_win32ole_type.rb
+++ b/test/win32ole/test_win32ole_type.rb
@@ -5,11 +5,14 @@ rescue LoadError
end
require "test/unit"
-if defined?(WIN32OLE_TYPE)
+if defined?(WIN32OLE::Type)
class TestWIN32OLE_TYPE < Test::Unit::TestCase
+ def test_toplevel_constants_backward_compatibility
+ assert_equal(WIN32OLE::Type, ::WIN32OLE_TYPE)
+ end
def test_s_progids
- progids = WIN32OLE_TYPE.progids
+ progids = WIN32OLE::Type.progids
assert_instance_of(Array, progids)
assert(progids.size > 0)
assert_instance_of(String, progids[0])
@@ -18,25 +21,25 @@ if defined?(WIN32OLE_TYPE)
def test_initialize
assert_raise(ArgumentError) {
- WIN32OLE_TYPE.new
+ WIN32OLE::Type.new
}
assert_raise(ArgumentError) {
- WIN32OLE_TYPE.new("foo")
+ WIN32OLE::Type.new("foo")
}
assert_raise(TypeError) {
- WIN32OLE_TYPE.new(1, 2)
+ WIN32OLE::Type.new(1, 2)
}
assert_raise(TypeError) {
- WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", 1)
+ WIN32OLE::Type.new("Microsoft Shell Controls And Automation", 1)
}
- assert_raise(WIN32OLERuntimeError) {
- WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "foo")
+ assert_raise(WIN32OLE::RuntimeError) {
+ WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "foo")
}
- assert_raise(WIN32OLERuntimeError) {
- WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Application")
+ assert_raise(WIN32OLE::RuntimeError) {
+ 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)
+ 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)
@@ -53,8 +56,8 @@ if defined?(WIN32OLE_TYPE)
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)
+ 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)
@@ -76,7 +79,7 @@ if defined?(WIN32OLE_TYPE)
end
def setup
- @ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "Shell")
+ @ole_type = WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "Shell")
end
def test_name
@@ -97,7 +100,7 @@ if defined?(WIN32OLE_TYPE)
def test_visible?
assert(@ole_type.visible?)
- ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "IShellDispatch")
+ ole_type = WIN32OLE::Type.new("Microsoft Shell Controls And Automation", "IShellDispatch")
assert(!ole_type.visible?)
end
@@ -107,13 +110,13 @@ if defined?(WIN32OLE_TYPE)
def test_major_version
assert_equal(0, @ole_type.major_version)
- # ole_type = WIN32OLE_TYPE.new("Microsoft Word 11.0 Object Library", "Documents")
+ # 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")
+ # ole_type = WIN32OLE::Type.new("Microsoft Word 11.0 Object Library", "Documents")
# assert_equal(3, ole_type.minor_version)
end
@@ -126,20 +129,20 @@ if defined?(WIN32OLE_TYPE)
end
def test_src_type
- ole_type = WIN32OLE_TYPE.new("Microsoft Scripting Runtime", "DriveTypeConst")
+ 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")
+ 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")
+ ole_type = WIN32OLE::Type.new("Microsoft Scripting Runtime", "Folders")
assert_equal(2181929, ole_type.helpcontext)
end
@@ -148,25 +151,25 @@ if defined?(WIN32OLE_TYPE)
assert_instance_of(Array, variables)
assert(variables.size == 0)
- ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "ShellSpecialFolderConstants")
+ 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])
+ 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_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_instance_of(WIN32OLE::TypeLib, tlib)
assert_equal("Microsoft Shell Controls And Automation", tlib.name)
end
@@ -178,20 +181,20 @@ if defined?(WIN32OLE_TYPE)
end
def test_inspect
- assert_equal("#<WIN32OLE_TYPE:Shell>", @ole_type.inspect)
+ assert_equal("#<WIN32OLE::Type:Shell>", @ole_type.inspect)
end
- # WIN32OLE_TYPE.typelibs will be obsoleted.
+ # WIN32OLE::Type.typelibs will be obsoleted.
def test_s_typelibs
- tlibs = WIN32OLE_TYPE.typelibs.sort
- tlibs2 = WIN32OLE_TYPELIB.typelibs.collect{|t|t.name}.sort
+ 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.
+ # 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
+ 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)
diff --git a/test/win32ole/test_win32ole_type_event.rb b/test/win32ole/test_win32ole_type_event.rb
index ad2de54e59..5d1c9fc44c 100644
--- a/test/win32ole/test_win32ole_type_event.rb
+++ b/test/win32ole/test_win32ole_type_event.rb
@@ -6,18 +6,18 @@ end
require 'test/unit'
-if defined?(WIN32OLE_TYPE)
+if defined?(WIN32OLE::Type)
require_relative 'available_ole'
class TestWIN32OLE_TYPE_EVENT < Test::Unit::TestCase
unless AvailableOLE.sysmon_available?
def test_dummy_for_skip_message
- skip 'System Monitor Control is not available'
+ omit 'System Monitor Control is not available'
end
else
def setup
- @ole_type = WIN32OLE_TYPE.new('System Monitor Control', 'SystemMonitor')
+ @ole_type = WIN32OLE::Type.new('System Monitor Control', 'SystemMonitor')
end
def test_implemented_ole_types
diff --git a/test/win32ole/test_win32ole_typelib.rb b/test/win32ole/test_win32ole_typelib.rb
index 321c019e53..31d6122756 100644
--- a/test/win32ole/test_win32ole_typelib.rb
+++ b/test/win32ole/test_win32ole_typelib.rb
@@ -5,10 +5,14 @@ rescue LoadError
end
require "test/unit"
-if defined?(WIN32OLE_TYPELIB)
+if defined?(WIN32OLE::TypeLib)
class TestWIN32OLE_TYPELIB < Test::Unit::TestCase
+ def test_toplevel_constants_backward_compatibility
+ assert_equal(WIN32OLE::TypeLib, ::WIN32OLE_TYPELIB)
+ end
+
def test_s_typelibs
- tlibs = WIN32OLE_TYPELIB.typelibs
+ tlibs = WIN32OLE::TypeLib.typelibs
assert_instance_of(Array, tlibs)
assert(tlibs.size > 0)
tlib = tlibs.find {|t| t.name == "Microsoft Shell Controls And Automation"}
@@ -17,100 +21,100 @@ if defined?(WIN32OLE_TYPELIB)
def test_initialize
assert_raise(ArgumentError) {
- WIN32OLE_TYPELIB.new(1,2,3,4)
+ WIN32OLE::TypeLib.new(1,2,3,4)
}
assert_raise(TypeError) {
- WIN32OLE_TYPELIB.new(100)
+ 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")
+ 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)
- 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)
+ 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)
+ 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")
+ assert_raise(WIN32OLE::RuntimeError) {
+ WIN32OLE::TypeLib.new("Non Exist Type Library")
}
end
# #Bug:3907 [ruby-dev:42338]
def test_initialize_with_REG_EXPAND_SZ
- tlib = WIN32OLE_TYPELIB.new("Disk Management Snap-In Object Library")
- assert_instance_of(WIN32OLE_TYPELIB, tlib)
+ tlib = WIN32OLE::TypeLib.new("Disk Management Snap-In Object Library")
+ assert_instance_of(WIN32OLE::TypeLib, tlib)
end
def test_guid
- tlib = WIN32OLE_TYPELIB.new("Microsoft Shell Controls And Automation")
+ 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")
+ 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}")
+ 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")
+ 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")
+ 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")
+ 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")
+ 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")
+ 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")
+ 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")
+ 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")
+ 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])
+ 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)
+ tlib = WIN32OLE::TypeLib.new("Microsoft Shell Controls And Automation")
+ assert_equal("#<WIN32OLE::TypeLib:Microsoft Shell Controls And Automation>", tlib.inspect)
end
end
diff --git a/test/win32ole/test_win32ole_variable.rb b/test/win32ole/test_win32ole_variable.rb
index 826029e0a8..646cf68915 100644
--- a/test/win32ole/test_win32ole_variable.rb
+++ b/test/win32ole/test_win32ole_variable.rb
@@ -5,17 +5,25 @@ rescue LoadError
end
require "test/unit"
-if defined?(WIN32OLE_VARIABLE)
+if defined?(WIN32OLE::Variable)
class TestWIN32OLE_VARIABLE < Test::Unit::TestCase
def setup
- ole_type = WIN32OLE_TYPE.new("Microsoft Shell Controls And Automation", "ShellSpecialFolderConstants")
+ 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
+ variables = WIN32OLE::Type.new("Microsoft Windows Installer Object Library", "Installer").variables
@var2 = variables.find {|v| v.name == 'UILevel'}
end
+ def test_toplevel_constants_backward_compatibility
+ assert_equal(WIN32OLE::Variable, ::WIN32OLE_VARIABLE)
+ end
+
+ def test_initialize
+ assert_raise(TypeError) {WIN32OLE::Variable.new}
+ end
+
def test_name
assert_equal('ssfDESKTOP', @var1.name)
end
@@ -54,8 +62,8 @@ if defined?(WIN32OLE_VARIABLE)
end
def test_inspect
- assert_equal("#<WIN32OLE_VARIABLE:ssfDESKTOP=0>", @var1.inspect)
- assert_equal("#<WIN32OLE_VARIABLE:UILevel=nil>", @var2.inspect)
+ assert_equal("#<WIN32OLE::Variable:ssfDESKTOP=0>", @var1.inspect)
+ assert_equal("#<WIN32OLE::Variable:UILevel=nil>", @var2.inspect)
end
end
diff --git a/test/win32ole/test_win32ole_variant.rb b/test/win32ole/test_win32ole_variant.rb
index 390534b5e1..13b9a229a5 100644
--- a/test/win32ole/test_win32ole_variant.rb
+++ b/test/win32ole/test_win32ole_variant.rb
@@ -5,7 +5,7 @@ rescue LoadError
end
require "test/unit"
-if defined?(WIN32OLE_VARIANT)
+if defined?(WIN32OLE::Variant)
class TestWIN32OLE_VARIANT < Test::Unit::TestCase
def setup
@@ -17,36 +17,40 @@ if defined?(WIN32OLE_VARIANT)
WIN32OLE.locale = @orglocale
end
+ def test_toplevel_constants_backward_compatibility
+ assert_equal(WIN32OLE::Variant, ::WIN32OLE_VARIANT)
+ end
+
def test_s_new
- obj = WIN32OLE_VARIANT.new('foo')
- assert_instance_of(WIN32OLE_VARIANT, obj)
+ obj = WIN32OLE::Variant.new('foo')
+ assert_instance_of(WIN32OLE::Variant, obj)
end
def test_s_new_exc
assert_raise(TypeError) {
- WIN32OLE_VARIANT.new(/foo/)
+ WIN32OLE::Variant.new(/foo/)
}
end
def test_s_new_ary
- obj = WIN32OLE_VARIANT.new([1])
- assert_instance_of(WIN32OLE_VARIANT, obj)
+ obj = WIN32OLE::Variant.new([1])
+ assert_instance_of(WIN32OLE::Variant, obj)
assert_raise(TypeError) {
- WIN32OLE_VARIANT.new([/foo/])
+ WIN32OLE::Variant.new([/foo/])
}
end
def test_s_new_no_argument
pat = /wrong number of arguments \(.*\b0\b.* 1\.\.3\)/
assert_raise_with_message(ArgumentError, pat) do
- WIN32OLE_VARIANT.new
+ WIN32OLE::Variant.new
end
end
def test_s_new_one_argument
ex = nil
begin
- WIN32OLE_VARIANT.new('foo')
+ WIN32OLE::Variant.new('foo')
rescue
ex = $!
end
@@ -54,247 +58,247 @@ if defined?(WIN32OLE_VARIANT)
end
def test_s_new_with_nil
- obj = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_I2)
+ 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)
+ 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)
+ 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)
+ 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)
+ 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)
+ obj = WIN32OLE::Variant.new(nil, WIN32OLE::VARIANT::VT_DATE)
assert_equal(Time.new(1899,12,30), obj.value)
assert_equal(WIN32OLE::VARIANT::VT_DATE, obj.vartype)
- obj = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_BSTR)
+ 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)
+ 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)
+ 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)
+ 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)
+ 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)
+ 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)
+ 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)
+ 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)
+ 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)
+ 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)
+ 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)
+ 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)
+ 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)
+ 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)
+ 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)
+ 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)
+ 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)
+ obj = WIN32OLE::Variant.new("2001-06-15 12:17:34", WIN32OLE::VARIANT::VT_DATE)
assert_equal(Time.new(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)
+ 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)
+ 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)
+ 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)
+ 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)
+ 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)
+ 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)
+ 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)
+ 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)
+ 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)
+ 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)
+ 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)
+ 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)
+ 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)
+ 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)
+ 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)
+ obj = WIN32OLE::Variant.new("2001-06-15 12:17:34", WIN32OLE::VARIANT::VT_DATE|WIN32OLE::VARIANT::VT_BYREF)
assert_equal(Time.new(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)
+ 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)
+ 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)
+ 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)
+ 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)
+ 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)
+ 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)
+ 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)
+ 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
def test_s_new_with_i8_byref
- obj = WIN32OLE_VARIANT.new(-123456789012345, WIN32OLE::VARIANT::VT_I8|WIN32OLE::VARIANT::VT_BYREF)
+ 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)
end
def test_s_new_with_ui8_byref
- obj = WIN32OLE_VARIANT.new(123456789012345, WIN32OLE::VARIANT::VT_UI8|WIN32OLE::VARIANT::VT_BYREF)
+ 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)
end
def test_value
- obj = WIN32OLE_VARIANT.new('foo')
+ 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)
+ 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)
+ 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)
+ 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)
+ obj = WIN32OLE::Variant.new(nil, vt)
assert_equal(vt, obj.vartype)
assert_nil(obj.value)
end
@@ -302,29 +306,29 @@ if defined?(WIN32OLE_VARIANT)
def test_s_new_array
# should not occur stack over flow
ar = (1..500000).to_a.map{|i| [i]}
- ar2 = WIN32OLE_VARIANT.new(ar)
+ ar2 = WIN32OLE::Variant.new(ar)
assert_equal(ar, ar2.value)
end
def test_s_new_vt_record_exc
- # VT_RECORD (= 36) should not be allowed in WIN32OLE_VARIANT#new
+ # VT_RECORD (= 36) should not be allowed in WIN32OLE::Variant#new
assert_raise(ArgumentError) {
- WIN32OLE_VARIANT.new(nil, 36)
+ WIN32OLE::Variant.new(nil, 36)
}
end
def test_s_array
- obj = WIN32OLE_VARIANT.array([2,3], WIN32OLE::VARIANT::VT_I4)
- assert_instance_of(WIN32OLE_VARIANT, obj)
+ 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)
+ 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)
+ 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)
@@ -334,60 +338,60 @@ if defined?(WIN32OLE_VARIANT)
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 = 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)
+ 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) {
- WIN32OLE_VARIANT.array(2, WIN32OLE::VARIANT::VT_I4)
+ WIN32OLE::Variant.array(2, WIN32OLE::VARIANT::VT_I4)
}
end
def test_conversion_num2str
- obj = WIN32OLE_VARIANT.new(124, WIN32OLE::VARIANT::VT_BSTR)
+ 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)
+ 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)
+ 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)
+ 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)
+ 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)
+ obj = WIN32OLE::Variant.new("2004-12-24 12:24:45", WIN32OLE::VARIANT::VT_DATE)
assert_equal(Time.new(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)
+ obj = WIN32OLE::Variant.new(dt, WIN32OLE::VARIANT::VT_DATE)
assert_equal(dt, obj.value)
end
def test_conversion_dbl2date_with_msec
# Date is "2014/8/27 12:34:56.789"
- obj = WIN32OLE_VARIANT.new(41878.524268391200167, WIN32OLE::VARIANT::VT_DATE)
+ obj = WIN32OLE::Variant.new(41878.524268391200167, WIN32OLE::VARIANT::VT_DATE)
t = obj.value
assert_equal("2014-08-27 12:34:56", t.strftime('%Y-%m-%d %H:%M:%S'))
assert_in_delta(0.789, t.nsec / 1000000000.0, 0.001)
@@ -396,7 +400,7 @@ if defined?(WIN32OLE_VARIANT)
def test_conversion_time2date_with_msec
t0 = Time.new(2014, 8, 27, 12, 34, 56)
t0 += 0.789
- t1 = WIN32OLE_VARIANT.new(t0).value
+ t1 = WIN32OLE::Variant.new(t0).value
# The t0.nsec is 789000000 and t1.nsec is 789000465
# because of error range by conversion Time between VT_DATE Variant.
@@ -406,7 +410,7 @@ if defined?(WIN32OLE_VARIANT)
t0 = Time.new(2014, 8, 27, 12, 34, 56)
t0 += 0.999999999
- t1 = WIN32OLE_VARIANT.new(t0).value
+ t1 = WIN32OLE::Variant.new(t0).value
msg = "Expected:#{t0.strftime('%Y-%m-%dT%H:%M:%S.%N')} but was:#{t1.strftime('%Y-%m-%dT%H:%M:%S.%N')}"
# The t0 is "2014/08/27 12:34.56.999999999" and
@@ -414,7 +418,7 @@ if defined?(WIN32OLE_VARIANT)
assert_in_delta(t0, t1, 0.001, msg)
t0 = Time.now
- t1 = WIN32OLE_VARIANT.new(t0).value
+ t1 = WIN32OLE::Variant.new(t0).value
msg = "Expected:#{t0.strftime('%Y-%m-%dT%H:%M:%S.%N')} but was:#{t1.strftime('%Y-%m-%dT%H:%M:%S.%N')}"
assert_in_delta(t0, t1, 0.001, msg)
end
@@ -426,110 +430,110 @@ if defined?(WIN32OLE_VARIANT)
# def test_conversion_time_nsec2date
# dt = Time.new(2004, 12,24, 12, 24, 45)
# dt += 0.1
- # obj = WIN32OLE_VARIANT.new(dt, WIN32OLE::VARIANT::VT_DATE)
+ # obj = WIN32OLE::Variant.new(dt, WIN32OLE::VARIANT::VT_DATE)
# assert_equal(dt, obj.value)
# end
def test_conversion_str2cy
begin
WIN32OLE.locale = 0x0411 # set locale Japanese
- rescue WIN32OLERuntimeError
- skip("Japanese locale is not installed")
+ rescue WIN32OLE::RuntimeError
+ omit("Japanese locale is not installed")
end
if WIN32OLE.locale == 0x0411
- obj = WIN32OLE_VARIANT.new("\\10,000", WIN32OLE::VARIANT::VT_CY)
+ obj = WIN32OLE::Variant.new("\\10,000", WIN32OLE::VARIANT::VT_CY)
assert_equal("10000", obj.value)
end
end
def test_create_vt_array
- obj = WIN32OLE_VARIANT.new([1.2, 2.3], WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_R8)
+ 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)
+ 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)
+ 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"])
+ 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)
+ 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"]])
+ 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"]])
+ 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]]])
+ 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([])
+ obj = WIN32OLE::Variant.new([])
assert_equal([], obj.value)
- obj = WIN32OLE_VARIANT.new([[]])
+ obj = WIN32OLE::Variant.new([[]])
assert_equal([[]], obj.value)
- obj = WIN32OLE_VARIANT.new([[],[]])
+ obj = WIN32OLE::Variant.new([[],[]])
assert_equal([[],[]], obj.value)
- obj = WIN32OLE_VARIANT.new([], WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_BYREF)
+ 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)
+ 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)
+ 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)
+ 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)
+ 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)
+ 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)
+ 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) {
- WIN32OLE_VARIANT.new("", WIN32OLE::VARIANT::VT_ARRAY)
+ WIN32OLE::Variant.new("", WIN32OLE::VARIANT::VT_ARRAY)
}
assert_match(/wrong argument type String \(expected Array\)/, exc.message)
end
def test_create_vt_array_str2ui1array
- obj = WIN32OLE_VARIANT.new("ABC", WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_UI1)
+ obj = WIN32OLE::Variant.new("ABC", WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_UI1)
assert_equal("ABC", obj.value)
obj.value = "DEF"
@@ -537,10 +541,10 @@ if defined?(WIN32OLE_VARIANT)
obj[0] = 71
assert_equal("GEF", obj.value)
- obj = WIN32OLE_VARIANT.new([65, 0].pack("C*"), WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_UI1)
+ 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)
+ 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)
@@ -551,19 +555,19 @@ if defined?(WIN32OLE_VARIANT)
end
def test_create_vt_array_int
- obj = WIN32OLE_VARIANT.new([65, 0], WIN32OLE::VARIANT::VT_ARRAY|WIN32OLE::VARIANT::VT_UI1)
+ 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])
+ 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)
+ 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]])
+ 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])
@@ -571,10 +575,10 @@ if defined?(WIN32OLE_VARIANT)
assert_equal(5, obj[1,1])
assert_equal(6, obj[1,2])
- assert_raise(WIN32OLERuntimeError) {
+ assert_raise(WIN32OLE::RuntimeError) {
obj[0,4]
}
- assert_raise(WIN32OLERuntimeError) {
+ assert_raise(WIN32OLE::RuntimeError) {
obj[0,-1]
}
assert_raise(ArgumentError) {
@@ -585,10 +589,10 @@ if defined?(WIN32OLE_VARIANT)
obj[1,2] = 8
assert_equal([[7,2,3], [4,5,8]], obj.value)
- assert_raise(WIN32OLERuntimeError) {
+ assert_raise(WIN32OLE::RuntimeError) {
obj[0,4] = 9
}
- assert_raise(WIN32OLERuntimeError) {
+ assert_raise(WIN32OLE::RuntimeError) {
obj[0,-1] = 10
}
assert_raise(ArgumentError) {
@@ -597,60 +601,60 @@ if defined?(WIN32OLE_VARIANT)
end
def test_conversion_vt_date
- obj = WIN32OLE_VARIANT.new(-657434, WIN32OLE::VARIANT::VT_DATE)
+ obj = WIN32OLE::Variant.new(-657434, WIN32OLE::VARIANT::VT_DATE)
assert_equal(Time.new(100,1,1), obj.value)
- obj = WIN32OLE_VARIANT.new("1500/12/29 23:59:59", WIN32OLE::VARIANT::VT_DATE)
+ obj = WIN32OLE::Variant.new("1500/12/29 23:59:59", WIN32OLE::VARIANT::VT_DATE)
assert_equal(Time.new(1500,12,29,23,59,59), obj.value)
- obj = WIN32OLE_VARIANT.new("1500/12/30 00:00:00", WIN32OLE::VARIANT::VT_DATE)
+ obj = WIN32OLE::Variant.new("1500/12/30 00:00:00", WIN32OLE::VARIANT::VT_DATE)
assert_equal(Time.new(1500,12,30), obj.value)
- obj = WIN32OLE_VARIANT.new("1500/12/30 00:00:01", WIN32OLE::VARIANT::VT_DATE)
+ obj = WIN32OLE::Variant.new("1500/12/30 00:00:01", WIN32OLE::VARIANT::VT_DATE)
assert_equal(Time.new(1500,12,30,0,0,1), obj.value)
- obj = WIN32OLE_VARIANT.new("1899/12/29 23:59:59", WIN32OLE::VARIANT::VT_DATE)
+ obj = WIN32OLE::Variant.new("1899/12/29 23:59:59", WIN32OLE::VARIANT::VT_DATE)
assert_equal(Time.new(1899,12,29,23,59,59), obj.value)
- obj = WIN32OLE_VARIANT.new("1899/12/30 00:00:00", WIN32OLE::VARIANT::VT_DATE)
+ obj = WIN32OLE::Variant.new("1899/12/30 00:00:00", WIN32OLE::VARIANT::VT_DATE)
assert_equal(Time.new(1899,12,30), obj.value)
- obj = WIN32OLE_VARIANT.new("1899/12/30 00:00:01", WIN32OLE::VARIANT::VT_DATE)
+ obj = WIN32OLE::Variant.new("1899/12/30 00:00:01", WIN32OLE::VARIANT::VT_DATE)
assert_equal(Time.new(1899,12,30,0,0,1), obj.value)
- obj = WIN32OLE_VARIANT.new(0, WIN32OLE::VARIANT::VT_DATE)
+ obj = WIN32OLE::Variant.new(0, WIN32OLE::VARIANT::VT_DATE)
assert_equal(Time.new(1899,12,30), obj.value)
- obj = WIN32OLE_VARIANT.new("2008/12/29 23:59:59", WIN32OLE::VARIANT::VT_DATE)
+ obj = WIN32OLE::Variant.new("2008/12/29 23:59:59", WIN32OLE::VARIANT::VT_DATE)
assert_equal(Time.new(2008,12,29,23,59,59), obj.value)
- obj = WIN32OLE_VARIANT.new("2008/12/30 00:00:00", WIN32OLE::VARIANT::VT_DATE)
+ obj = WIN32OLE::Variant.new("2008/12/30 00:00:00", WIN32OLE::VARIANT::VT_DATE)
assert_equal(Time.new(2008,12,30,0,0,0), obj.value)
- obj = WIN32OLE_VARIANT.new("2008/12/30 00:00:01", WIN32OLE::VARIANT::VT_DATE)
+ obj = WIN32OLE::Variant.new("2008/12/30 00:00:01", WIN32OLE::VARIANT::VT_DATE)
assert_equal(Time.new(2008,12,30,0,0,1), obj.value)
- obj = WIN32OLE_VARIANT.new("9999/12/31 23:59:59", WIN32OLE::VARIANT::VT_DATE)
+ obj = WIN32OLE::Variant.new("9999/12/31 23:59:59", WIN32OLE::VARIANT::VT_DATE)
assert_equal(Time.new(9999,12,31,23,59,59), obj.value)
end
def test_create_nil_dispatch
- var = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_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);
+ 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")
+ obj = WIN32OLE::Variant.new("Str")
assert_equal(WIN32OLE::VARIANT::VT_BSTR, obj.vartype)
end
def test_set_value
- obj = WIN32OLE_VARIANT.new(10)
+ obj = WIN32OLE::Variant.new(10)
obj.value = 12
assert_equal(12, obj.value)
assert_equal(WIN32OLE::VARIANT::VT_I4, obj.vartype)
@@ -661,57 +665,57 @@ if defined?(WIN32OLE_VARIANT)
assert_equal(11, obj.value)
assert_equal(WIN32OLE::VARIANT::VT_I4, obj.vartype)
- obj = WIN32OLE_VARIANT.new([1,2])
- assert_raise(WIN32OLERuntimeError) {
+ obj = WIN32OLE::Variant.new([1,2])
+ assert_raise(WIN32OLE::RuntimeError) {
obj.value = [3,4]
}
- obj = WIN32OLE_VARIANT.new("2007/01/01", WIN32OLE::VARIANT::VT_DATE)
- assert_raise(WIN32OLERuntimeError) {
+ obj = WIN32OLE::Variant.new("2007/01/01", WIN32OLE::VARIANT::VT_DATE)
+ assert_raise(WIN32OLE::RuntimeError) {
obj.value = "hogehoge"
}
assert_equal(Time.new(2007,1,1), obj.value)
- obj2 = WIN32OLE_VARIANT.new("2006/01/01", WIN32OLE::VARIANT::VT_DATE)
+ obj2 = WIN32OLE::Variant.new("2006/01/01", WIN32OLE::VARIANT::VT_DATE)
obj.value = obj2
assert_equal(Time.new(2006,01,01), obj.value)
end
def test_c_nothing
- assert_nil(WIN32OLE_VARIANT::Nothing.value)
+ assert_nil(WIN32OLE::Variant::Nothing.value)
end
def test_c_empty
- assert_nil(WIN32OLE_VARIANT::Empty.value)
+ assert_nil(WIN32OLE::Variant::Empty.value)
end
def test_c_null
- assert_nil(WIN32OLE_VARIANT::Null.value)
+ assert_nil(WIN32OLE::Variant::Null.value)
end
def test_c_noparam
# DISP_E_PARAMNOTFOUND
- assert_equal(-2147352572, WIN32OLE_VARIANT::NoParam.value)
+ assert_equal(-2147352572, WIN32OLE::Variant::NoParam.value)
end
def test_vt_error_noparam
- v = WIN32OLE_VARIANT.new(-1, WIN32OLE::VARIANT::VT_ERROR)
+ v = WIN32OLE::Variant.new(-1, WIN32OLE::VARIANT::VT_ERROR)
assert_equal(-1, v.value)
fso = WIN32OLE.new("Scripting.FileSystemObject")
- exc = assert_raise(WIN32OLERuntimeError) {
+ exc = assert_raise(WIN32OLE::RuntimeError) {
fso.openTextFile("NonExistingFile", v, false)
}
assert_match(/Type mismatch/i, exc.message)
- exc = assert_raise(WIN32OLERuntimeError) {
- fso.openTextFile("NonExistingFile", WIN32OLE_VARIANT::NoParam, false)
+ exc = assert_raise(WIN32OLE::RuntimeError) {
+ fso.openTextFile("NonExistingFile", WIN32OLE::Variant::NoParam, false)
}
# 800A0035 is 'file not found' error.
assert_match(/800A0035/, exc.message)
# -2147352572 is DISP_E_PARAMNOTFOUND
- v = WIN32OLE_VARIANT.new(-2147352572, WIN32OLE::VARIANT::VT_ERROR)
- exc = assert_raise(WIN32OLERuntimeError) {
- fso.openTextFile("NonExistingFile", WIN32OLE_VARIANT::NoParam, false)
+ v = WIN32OLE::Variant.new(-2147352572, WIN32OLE::VARIANT::VT_ERROR)
+ exc = assert_raise(WIN32OLE::RuntimeError) {
+ fso.openTextFile("NonExistingFile", WIN32OLE::Variant::NoParam, false)
}
# 800A0035 is 'file not found' error code.
assert_match(/800A0035/, exc.message)
diff --git a/test/win32ole/test_win32ole_variant_m.rb b/test/win32ole/test_win32ole_variant_m.rb
index 25ad56cc21..3c2884644c 100644
--- a/test/win32ole/test_win32ole_variant_m.rb
+++ b/test/win32ole/test_win32ole_variant_m.rb
@@ -8,6 +8,11 @@ require "test/unit"
if defined?(WIN32OLE::VARIANT)
class TestWin32OLE_VARIANT_MODULE < Test::Unit::TestCase
include WIN32OLE::VARIANT
+
+ def test_toplevel_constants_backward_compatibility
+ assert_equal(WIN32OLE::VariantType, WIN32OLE::VARIANT)
+ end
+
def test_variant
assert_equal(0, VT_EMPTY)
assert_equal(1, VT_NULL)
diff --git a/test/win32ole/test_win32ole_variant_outarg.rb b/test/win32ole/test_win32ole_variant_outarg.rb
index aa5793b84c..9301a76aaa 100644
--- a/test/win32ole/test_win32ole_variant_outarg.rb
+++ b/test/win32ole/test_win32ole_variant_outarg.rb
@@ -23,7 +23,7 @@ def ado_csv_installed?
installed
end
-if defined?(WIN32OLE_VARIANT)
+if defined?(WIN32OLE::Variant)
class TestWIN32OLE_VARIANT_OUTARG < Test::Unit::TestCase
module ADO
end
@@ -42,17 +42,17 @@ if defined?(WIN32OLE_VARIANT)
def test_variant_ref_and_argv
if !ado_csv_installed?
- skip("ActiveX Data Object Library not found")
+ omit("ActiveX Data Object Library not found")
end
sql = "INSERT INTO data.csv VALUES (5, 'E')"
@db.execute(sql, -1)
c = WIN32OLE::ARGV[1]
assert_equal(1, c)
- obj = WIN32OLE_VARIANT.new(nil, WIN32OLE::VARIANT::VT_VARIANT|WIN32OLE::VARIANT::VT_BYREF)
+ obj = WIN32OLE::Variant.new(nil, WIN32OLE::VARIANT::VT_VARIANT|WIN32OLE::VARIANT::VT_BYREF)
assert_equal(nil, obj.value)
@db.execute(sql , obj)
assert_equal(1, obj.value)
- obj = WIN32OLE_VARIANT.new(-100, WIN32OLE::VARIANT::VT_VARIANT|WIN32OLE::VARIANT::VT_BYREF)
+ obj = WIN32OLE::Variant.new(-100, WIN32OLE::VARIANT::VT_VARIANT|WIN32OLE::VARIANT::VT_BYREF)
assert_equal(-100, obj.value)
@db.execute(sql, obj)
assert_equal(1, obj.value)
diff --git a/test/win32ole/test_word.rb b/test/win32ole/test_word.rb
index b1cdb273cc..34cfbbc2a4 100644
--- a/test/win32ole/test_word.rb
+++ b/test/win32ole/test_word.rb
@@ -35,13 +35,13 @@ if defined?(WIN32OLE)
class TestWIN32OLE_WITH_WORD < Test::Unit::TestCase
unless word_installed?
def test_dummy_for_skip_message
- skip "Microsoft Word is not installed"
+ omit "Microsoft Word is not installed"
end
else
def setup
begin
@obj = WIN32OLE.new('Word.Application')
- rescue WIN32OLERuntimeError
+ rescue WIN32OLE::RuntimeError
@obj = nil
end
end
diff --git a/test/yaml/test_store.rb b/test/yaml/test_store.rb
index ef8d3229c1..d389530271 100644
--- a/test/yaml/test_store.rb
+++ b/test/yaml/test_store.rb
@@ -133,7 +133,7 @@ class YAMLStoreTest < Test::Unit::TestCase
def test_yaml_store_files_are_accessed_as_binary_files
bug5311 = '[ruby-core:39503]'
n = 128
- assert_in_out_err(["-Eutf-8:utf-8", "-ryaml/store", "-", @yaml_store_file], <<-SRC, [bug5311], [], bug5311, timeout: 15)
+ assert_in_out_err(["-Eutf-8:utf-8", "-ryaml/store", "-", @yaml_store_file], <<-SRC, [bug5311], [], bug5311, timeout: 60)
@yaml_store = YAML::Store.new(ARGV[0])
(1..#{n}).each do |i|
@yaml_store.transaction {@yaml_store["Key\#{i}"] = "value \#{i}"}
@@ -177,4 +177,4 @@ class YAMLStoreTest < Test::Unit::TestCase
end
assert_equal(indentation_3_yaml, File.read(@yaml_store_file), bug12800)
end
-end
+end if defined?(::YAML::Store)
diff --git a/test/zlib/test_zlib.rb b/test/zlib/test_zlib.rb
index a629c0c902..15e5bd852f 100644
--- a/test/zlib/test_zlib.rb
+++ b/test/zlib/test_zlib.rb
@@ -506,6 +506,7 @@ if defined? Zlib
end
def test_multithread_deflate
+ pend 'hangs' if RUBY_ENGINE == 'truffleruby'
zd = Zlib::Deflate.new
s = "x" * 10000
@@ -522,6 +523,7 @@ if defined? Zlib
end
def test_multithread_inflate
+ pend 'hangs' if RUBY_ENGINE == 'truffleruby'
zi = Zlib::Inflate.new
s = Zlib.deflate("x" * 10000)
@@ -538,30 +540,36 @@ if defined? Zlib
end
def test_recursive_deflate
+ original_gc_stress = GC.stress
+ GC.stress = true
zd = Zlib::Deflate.new
s = SecureRandom.random_bytes(1024**2)
- assert_raise(Zlib::BufError) do
+ assert_raise(Zlib::InProgressError) do
zd.deflate(s) do
zd.deflate(s)
end
end
ensure
+ GC.stress = original_gc_stress
zd&.finish
zd&.close
end
def test_recursive_inflate
+ original_gc_stress = GC.stress
+ GC.stress = true
zi = Zlib::Inflate.new
s = Zlib.deflate(SecureRandom.random_bytes(1024**2))
- assert_raise(Zlib::DataError) do
+ assert_raise(Zlib::InProgressError) do
zi.inflate(s) do
zi.inflate(s)
end
end
ensure
+ GC.stress = original_gc_stress
zi&.close
end
end
@@ -786,31 +794,40 @@ if defined? Zlib
}
end
- if defined? File::TMPFILE
+ if defined?(File::TMPFILE) and RUBY_ENGINE != 'truffleruby'
def test_path_tmpfile
sio = StringIO.new("".dup, 'w')
gz = Zlib::GzipWriter.new(sio)
gz.write "hi"
gz.close
- File.open(Dir.mktmpdir, File::RDWR | File::TMPFILE) do |io|
+ tmpdir = Dir.mktmpdir("zlib_file_tmpfile")
+ File.open(tmpdir, File::RDWR | File::TMPFILE) do |io|
io.write sio.string
io.rewind
gz0 = Zlib::GzipWriter.new(io)
- assert_raise(NoMethodError) { gz0.path }
-
gz1 = Zlib::GzipReader.new(io)
- assert_raise(NoMethodError) { gz1.path }
+
+ if IO.method_defined?(:path)
+ assert_nil gz0.path
+ assert_nil gz1.path
+ else
+ assert_raise(NoMethodError) { gz0.path }
+ assert_raise(NoMethodError) { gz1.path }
+ end
+
gz0.close
gz1.close
end
rescue Errno::EINVAL
- skip 'O_TMPFILE not supported (EINVAL)'
+ omit 'O_TMPFILE not supported (EINVAL)'
rescue Errno::EISDIR
- skip 'O_TMPFILE not supported (EISDIR)'
+ omit 'O_TMPFILE not supported (EISDIR)'
rescue Errno::EOPNOTSUPP
- skip 'O_TMPFILE not supported (EOPNOTSUPP)'
+ omit 'O_TMPFILE not supported (EOPNOTSUPP)'
+ ensure
+ Dir.rmdir(tmpdir) if tmpdir
end
end
end
@@ -974,6 +991,25 @@ if defined? Zlib
assert_raise(ArgumentError) { f.read(-1) }
assert_equal(str, f.read)
end
+
+ Zlib::GzipReader.open(t.path) do |f|
+ s = "".b
+
+ assert_raise(ArgumentError) { f.read(-1, s) }
+
+ assert_same s, f.read(1, s)
+ assert_equal "\xE3".b, s
+
+ assert_same s, f.read(2, s)
+ assert_equal "\x81\x82".b, s
+
+ assert_same s, f.read(6, s)
+ assert_equal "\u3044\u3046".b, s
+
+ assert_nil f.read(1, s)
+ assert_equal "".b, s
+ assert_predicate f, :eof?
+ end
}
end
@@ -988,10 +1024,14 @@ if defined? Zlib
Zlib::GzipReader.open(t.path) do |f|
s = "".dup
- f.readpartial(3, s)
+ assert_same s, f.readpartial(3, s)
assert("foo".start_with?(s))
assert_raise(ArgumentError) { f.readpartial(-1) }
+
+ assert_same s, f.readpartial(3, s)
+
+ assert_predicate f, :eof?
end
}
end
@@ -1191,6 +1231,38 @@ if defined? Zlib
}
end
+ # Various methods of Zlib::GzipReader failed when to reading files
+ # just a few bytes larger than GZFILE_READ_SIZE.
+ def test_gzfile_read_size_boundary
+ Tempfile.create("test_zlib_gzip_read_size_boundary") {|t|
+ t.close
+ # NO_COMPRESSION helps with recreating the error condition.
+ # The error happens on compressed files too, but it's harder to reproduce.
+ # For example, ~12750 bytes are needed to trigger the error using __FILE__.
+ # We avoid this because the test file will change over time.
+ Zlib::GzipWriter.open(t.path, Zlib::NO_COMPRESSION) do |gz|
+ gz.print("\n" * 2024) # range from 2024 to 2033 triggers the error
+ gz.flush
+ end
+
+ Zlib::GzipReader.open(t.path) do |f|
+ f.readpartial(1024) until f.eof?
+ assert_raise(EOFError) { f.readpartial(1) }
+ end
+
+ Zlib::GzipReader.open(t.path) do |f|
+ f.readline until f.eof?
+ assert_raise(EOFError) { f.readline }
+ end
+
+ Zlib::GzipReader.open(t.path) do |f|
+ b = f.readbyte until f.eof?
+ f.ungetbyte(b)
+ f.readbyte
+ assert_raise(EOFError) { f.readbyte }
+ end
+ }
+ end
end
class TestZlibGzipWriter < Test::Unit::TestCase
@@ -1297,6 +1369,7 @@ if defined? Zlib
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))
+ assert_equal(0x97d1a9f7, Zlib.adler32("p", -305419897))
Tempfile.create("test_zlib_gzip_file_to_io") {|t|
File.binwrite(t.path, "foo")
t.rewind
@@ -1318,10 +1391,10 @@ if defined? Zlib
begin
assert_equal(0x02820145, Zlib.adler32_combine(one, two, 1))
rescue NotImplementedError
- skip "adler32_combine is not implemented"
+ omit "adler32_combine is not implemented"
rescue Test::Unit::AssertionFailedError
if /aix/ =~ RUBY_PLATFORM
- skip "zconf.h in zlib does not handle _LARGE_FILES in AIX. Skip until it is fixed"
+ omit "zconf.h in zlib does not handle _LARGE_FILES in AIX. Skip until it is fixed"
end
raise $!
end
@@ -1332,6 +1405,7 @@ if defined? Zlib
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))
+ assert_equal(0xf136439b, Zlib.crc32("p", -305419897))
Tempfile.create("test_zlib_gzip_file_to_io") {|t|
File.binwrite(t.path, "foo")
t.rewind
@@ -1353,10 +1427,10 @@ if defined? Zlib
begin
assert_equal(0x8c736521, Zlib.crc32_combine(one, two, 1))
rescue NotImplementedError
- skip "crc32_combine is not implemented"
+ omit "crc32_combine is not implemented"
rescue Test::Unit::AssertionFailedError
if /aix/ =~ RUBY_PLATFORM
- skip "zconf.h in zlib does not handle _LARGE_FILES in AIX. Skip until it is fixed"
+ omit "zconf.h in zlib does not handle _LARGE_FILES in AIX. Skip until it is fixed"
end
raise $!
end
@@ -1443,6 +1517,13 @@ if defined? Zlib
assert_raise(Zlib::GzipFile::Error){ Zlib.gunzip(src) }
end
+ # Zlib.gunzip input is always considered a binary string, regardless of its String#encoding.
+ def test_gunzip_encoding
+ # vvvvvvvv = mtime, but valid UTF-8 string of U+0080
+ src = %w[1f8b0800c28000000003cb48cdc9c9070086a6103605000000].pack("H*").force_encoding('UTF-8')
+ assert_equal 'hello', Zlib.gunzip(src.freeze)
+ end
+
def test_gunzip_no_memory_leak
assert_no_memory_leak(%[-rzlib], "#{<<~"{#"}", "#{<<~'};'}")
d = Zlib.gzip("data")